diff --git a/.github/scripts/build-compiler-docs.sh b/.github/scripts/build-compiler-docs.sh deleted file mode 100755 index 81e0e9b..0000000 --- a/.github/scripts/build-compiler-docs.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash -# -# Build the edgcpp/compiler documentation at a tag or branch and copy it into -# this site, so Jekyll publishes it with everything else. -# -# Usage: build-compiler-docs.sh -# -# is relative to the site root and is also the URL path the docs are -# served under; for example, "doc" is published at https://edgcpp.org/doc/. - -set -euo pipefail - -ref="$1" -dest="$2" -clone="$(mktemp -d)" - -# Fetch only doc/; a full checkout of the compiler tree is over 3 GB. -git -c advice.detachedHead=false clone --quiet --depth 1 --branch "$ref" \ - --filter=blob:none --sparse https://github.com/edgcpp/compiler.git "$clone" -git -C "$clone" sparse-checkout set doc -echo "Building compiler documentation at $ref" \ - "($(git -C "$clone" rev-parse --short HEAD)) into $dest/" - -docker run --rm \ - -v "$clone:/work" \ - -w /work/doc \ - edgcpp/sphinx-env:latest \ - make dirhtml SPHINXOPTS="-D html_baseurl=https://edgcpp.org/$dest/" - -mkdir -p "$dest" -cp -a "$clone/doc/build/dirhtml/." "$dest/" diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml deleted file mode 100644 index 872c58a..0000000 --- a/.github/workflows/build_and_deploy.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: build_and_deploy - -on: - push: - branches-ignore: - - master - # edgcpp/compiler triggers this (on develop) when doc/ changes on its main - # branch, to republish https://edgcpp.org/dev/doc/. - workflow_dispatch: - -# Serialize runs (replaces the CircleCI eddiewebb/queue orb). -concurrency: - group: build_and_deploy - cancel-in-progress: false - -env: - # Tag of edgcpp/compiler whose documentation is published at - # https://edgcpp.org/doc/. Bump this to publish a newer release's docs. - # The documentation for its main branch is published at - # https://edgcpp.org/dev/doc/. - COMPILER_DOC_REF: '7.0' - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - name: Build compiler documentation - run: | - .github/scripts/build-compiler-docs.sh "$COMPILER_DOC_REF" doc - .github/scripts/build-compiler-docs.sh main dev/doc - - uses: ruby/setup-ruby@v1 - with: - ruby-version: '4.0' - bundler-cache: true - - run: bundle exec jekyll build - - deploy: - needs: test - if: github.ref == 'refs/heads/develop' - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@v5 - - name: Build compiler documentation - run: | - .github/scripts/build-compiler-docs.sh "$COMPILER_DOC_REF" doc - .github/scripts/build-compiler-docs.sh main dev/doc - - uses: ruby/setup-ruby@v1 - with: - ruby-version: '4.0' - bundler-cache: true - - run: bundle exec jekyll build - - name: Deploy to master - run: | - COMMIT_MESSAGE="$(git log -1 --pretty=%B)" - # Unlike the old CircleCI deploy (which preserved .circleci/ so CI - # config stayed on master), .github/ is intentionally NOT kept: - # GITHUB_TOKEN is not allowed to push workflow files, and the - # workflow ignores master anyway. - find . -maxdepth 1 ! -name '_site' ! -name '.git' -exec rm -rf {} \; - mv _site/* . - rm -r _site/ - # Serve master as-is. Without this, GitHub Pages runs Jekyll over it - # again, which drops the documentation's _static/ and _sources/ - # directories. - touch .nojekyll - git config --global user.name "GitHub Actions" - git config --global user.email "actions@edgcpp.org" - git add . - git commit --allow-empty -m "$COMMIT_MESSAGE" - git push -f origin HEAD:master diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 9e1828a..0000000 --- a/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -_drafts/ -_site/ -/tmp -.DS_Store -*.swp -Gemfile.lock -.sass-cache/ -.ruby-version - -# Ruby Bundler configuration -.bundle/ - -# JetBrains IDE project files -.idea/ - -# Ruby gems installed locally via Bundler -vendor/ - -# Local working directory for temporary project-related data. -local/ - -# Claude Code and agent instructions (per-user, not shared) -AGENTS.md -CLAUDE.md diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 1f7f21a..0000000 --- a/Gemfile +++ /dev/null @@ -1,14 +0,0 @@ -source "https://rubygems.org" - -# Run Jekyll with `bundle exec`, like so: -# -# bundle exec jekyll serve -# -gem "jekyll", "~> 4.4" - -# Ruby 4.0 removed `logger` from the default gems, but Jekyll 4.4 still -# requires it at load time (https://github.com/jekyll/jekyll/issues/9915). -gem "logger" - -# Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] diff --git a/README.md b/README.md deleted file mode 100644 index 82f1bfa..0000000 --- a/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# edgcpp.org Website - -Source code for [edgcpp.org](https://edgcpp.org), the website for EDG's -transition to open source under a fiscal sponsorship agreement with -[The C++ Alliance](https://cppalliance.org). It is a Jekyll 4 project -published as a fully static site through GitHub Pages. - -The site has two pages: the main page in `index.html`, and John Spicer's -announcement note with testimonials and the transition FAQ in -`announcement.html` (served at `/announcement/`). Both are built on a small Jekyll scaffold: - -- `_layouts/default.html` – page shell -- `_includes/head.html`, `header.html`, `footer.html` – shared chrome -- `_includes/banner.html` – announcement banner, shown on pages that set - `banner: true` in their front matter (currently only `index.html`) -- `assets/css/main.css` – plain CSS, no Sass -- `assets/img/logo.gif` – site logo, also used as the favicon - -Site-wide links (the GitHub organization, the compiler repository, this -repository, and The C++ Alliance) are set in `_config.yml`. The history section of the page is a -marked placeholder until that content is collected. - -The project was bootstrapped from -[cppalliance.github.io](https://github.com/cppalliance/cppalliance.github.io). - -## Local Development - -```bash -bundle install -bundle exec jekyll serve -``` - -## Deployment - -Deployments are handled by GitHub Actions -(`.github/workflows/build_and_deploy.yml`): - -1. Commit source changes to the `develop` branch and push to GitHub. -2. CI builds the site with `bundle exec jekyll build`. -3. On `develop`, the deploy job removes everything from the working tree - except `_site` and `.git`, moves the built `_site` output to the - repository root, and force-pushes the result to `master`. - -The `master` branch is therefore generated build output; never edit it -directly. GitHub Pages serves the site from `master`, and `CNAME` binds -the deployment to `edgcpp.org`. diff --git a/_config.yml b/_config.yml deleted file mode 100644 index 7978415..0000000 --- a/_config.yml +++ /dev/null @@ -1,34 +0,0 @@ -# Jekyll configuration - -title: EDGCPP -url: https://edgcpp.org # the base hostname & protocol for the site -description: >- - The edgcpp.org open-source project website. - -# Project links used throughout the site. -github_url: https://github.com/edgcpp -compiler_url: https://github.com/edgcpp/compiler -repo_url: https://github.com/edgcpp/edgcpp.github.io -alliance_url: https://cppalliance.org -slack_url: https://cppalliance.org/slack/ - -# Build settings -markdown: kramdown - -# Exclude from processing. -exclude: - - Gemfile - - Gemfile.lock - - node_modules - - vendor - - local - - README.md - - CLAUDE.md - - AGENTS.md - -# Keep the Sphinx output directories that the compiler documentation build -# copies into doc/ (Jekyll skips names that start with an underscore). -include: - - _static - - _sources - - _images diff --git a/_includes/banner.html b/_includes/banner.html deleted file mode 100644 index d5df39e..0000000 --- a/_includes/banner.html +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/_includes/footer.html b/_includes/footer.html deleted file mode 100644 index 02cfc73..0000000 --- a/_includes/footer.html +++ /dev/null @@ -1,11 +0,0 @@ - diff --git a/_includes/head.html b/_includes/head.html deleted file mode 100644 index ef4c0d7..0000000 --- a/_includes/head.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - {%- assign meta_description = page.description | default: site.description | strip_newlines | strip -%} - {%- if page.title -%} - {{ page.title }} · {{ site.title }} - {%- else -%} - {{ site.title }} - {%- endif -%} - - - - - - - - - - - - - - - diff --git a/_includes/header.html b/_includes/header.html deleted file mode 100644 index a2f7839..0000000 --- a/_includes/header.html +++ /dev/null @@ -1,25 +0,0 @@ - diff --git a/_layouts/default.html b/_layouts/default.html deleted file mode 100644 index 550d0cb..0000000 --- a/_layouts/default.html +++ /dev/null @@ -1,13 +0,0 @@ - - -{% include head.html %} - - - {% if page.banner %}{% include banner.html %}{% endif %} - {% include header.html %} -
-{{ content }} -
- {% include footer.html %} - - diff --git a/announcement.html b/announcement/index.html similarity index 77% rename from announcement.html rename to announcement/index.html index 7e02701..85077bc 100644 --- a/announcement.html +++ b/announcement/index.html @@ -1,12 +1,53 @@ ---- -layout: default -title: What's Next for EDG -permalink: /announcement/ -description: >- - A note from John Spicer on EDG's C++ front end becoming open source, - testimonials from the C++ community, and answers to frequently asked - questions about the transition. ---- + + + + + What's Next for EDG · EDGCPP + + + + + + + + + + + + + + + + + + + + +

The EDG open source transition

@@ -28,7 +69,7 @@

A note from John Spicer

Hello members of the C++ community,

I wanted to share some news about EDG and where we’re headed next.

-

After many years of developing and supporting EDG’s C++ front end, we’ve decided to make it open source. On September 30, 2026, the source code will be publicly available at github.com/edgcpp. The C++ Alliance, a nonprofit, will be the open-source home of the open-source project. The project will work under a fiscal sponsorship agreement, similar to how Boost operates. In addition, the C++ Alliance will explore ways in which it can facilitate EDG development going forward.

+

After many years of developing and supporting EDG’s C++ front end, we’ve decided to make it open source. On September 30, 2026, the source code will be publicly available at github.com/edgcpp. The C++ Alliance, a nonprofit, will be the open-source home of the open-source project. The project will work under a fiscal sponsorship agreement, similar to how Boost operates. In addition, the C++ Alliance will explore ways in which it can facilitate EDG development going forward.

This is a significant change for EDG, and I believe it’s the right path forward. A lot has gone into this technology over the years, and it has found its way into more compilers, tools and products than I could have imagined when we started. Open source means more people in the C++ community can use it, contribute to it and help shape what comes next.

I’ll stay closely involved. I’ll chair the Fiscal Sponsorship Committee, which will oversee the project’s development alongside volunteers from the EDG user community.

For those of you who use EDG today, the first questions are likely to be practical ones: what changes, what stays the same, how the project will be maintained and what this means for you. Our FAQ answers those questions, and we’ll share more as the transition moves forward.

@@ -177,7 +218,7 @@

What does this mean for current EDG users?

When did the source code become available?

-

The code became available at github.com/edgcpp/compiler on September 30, 2026, under the LLVM license. Details on how to contribute will follow.

+

The code became available at github.com/edgcpp/compiler on September 30, 2026, under the LLVM license. Details on how to contribute will follow.

  • @@ -218,3 +259,19 @@

    Who should users contact with questions about the transition?

  • + +
    + + + + diff --git a/dev/doc/_sources/admin.rst.txt b/dev/doc/_sources/admin.rst.txt new file mode 100644 index 0000000..cf56bcf --- /dev/null +++ b/dev/doc/_sources/admin.rst.txt @@ -0,0 +1,1654 @@ +======================== +Administrative Functions +======================== + + + + +The source file ``cfe.c`` contains the main program. It calls +``proc_command_line`` (in ``cmd_line.c``) to parse the command line; +``fe_init`` (in ``fe_init.c``) to do global initialization; +``translation_unit`` (in ``decls.c``) to compile or ``cpp_driver`` (in +``preproc.c``) to do preprocessing; and ``fe_wrapup`` (in ``fe_wrapup.c``) +to do global termination. If a back end should be called, and there were no +errors, it also calls ``back_end``. Then, it calls ``fe_wrapup_part_2`` +(also in ``fe_wrapup.c``) to do post-back-end wrapup. Finally, it calls +``exit_compilation`` to exit with the exit status appropriate to the +severity of the errors detected. + +If multiple source files can be compiled, the main program includes a loop +around the steps from ``fe_init`` to ``back_end``. It calls +``get_next_source_file`` to see if there are any more source file names in +the command line. + +Usually, the front end has its own main program, but it can instead be used +as part of some other main program. This is done by setting the +``MAKE_FRONT_END_CALLABLE`` configuration macro. The name of the main entry +point into the front end is specified by the ``EDG_MAIN`` macro, and is +``edg_main`` by default. When the front end is callable, +``exit_compilation`` does not actually exit the program, but instead +returns control to the routine that called the front end. + +Initialization and Wrapup +========================= + +``fe_init.c`` contains one-time initialization. Declarations of external +variables in ``.h`` files, which must begin with ``EXTERN``, are compiled +here with ``EXTERN`` defined as an empty string, so storage is actually +allocated. Likewise, ``VAR_INITIALIZERS`` is defined as 1, so that +initializers on those variables are put out. The main routine is +``fe_init``; it calls other routines to initialize predefined macros, +keywords, and assorted state variables. In particular, it calls some +initialization routines in other files (e.g., ``lexical_init``, +``sym_tbl_init``). There are several different kinds of initialization +routines: + +* | "early" initialization routines (e.g., ``cmd_line_early_init``), which + are called before command-line processing is done. + +* | "one time" initialization routines (e.g., ``lexical_one_time_init``), + which are called only once per invocation of the front end, even if + multiple source files have been specified on the command-line (when + ``COMPILE_MULTIPLE_SOURCE_FILES`` is enabled). + +* | "per-compilation" initialization routines (e.g., ``lexical_init``), + which are called for each source file specified on the command-line + (when ``COMPILE_MULTIPLE_SOURCE_FILES`` is enabled). + +* | "trans-unit" initialization routines (e.g., + ``lexical_trans_unit_init``), which are called once for each + translation unit processed when processing exported template definition + files or when ``COMPILE_MULTIPLE_TRANSLATION_UNITS`` is enabled. + +Because the front end can be reinitialized (when +``MAKE_FRONT_END_CALLABLE`` is used), most variables must be initialized +dynamically, not statically. Variables that are modified by command-line +processing must be initialized in early initialization routines. + +Command-line ``-D`` and ``-U`` options are also handled here (see +``preproc_init``). + +If multiple source files are accepted, ``fe_init`` is called at the start +of compilation of each file. + +``fe_wrapup.c`` contains one-time wrapup code. This involves popping the +file name scope, checking for errors on files written, and dumping debug +statistics, such as information on symbol table efficiency and on total +memory used. ``fe_wrapup`` is called after the front end is done but before +the back end (if any) is executed, and ``fe_wrapup_part_2`` is called after +the back end (if any) is executed. + +.. _cppcli-init: + +C++/CLI Initialization +---------------------- + +The C++/CLI language depends in some essential ways on its core library, +which is loaded from assembly metadata (usually a file called +``mscorlib.dll``). The initialization process therefore preloads that +library and any others specified via the ``--preusing`` command-line option +with a call to ``process_preusings``. + +Immediately after loading the top-level declarations of the core library, +``process_preusings`` also initializes a number of global variables (and +global array elements) to point to the symbols for special entities from +the core library (for example, the ref class ``System::Object``). This is +done in ``init_cli_symbols``. + +``init_cli_symbols`` also creates templates for ``cli::array``, +``cli::interior_ptr``, and ``cli::pin_ptr``. This is achieved by running +ordinary front end processing on string literals (via calls to +``scan_top_level_metadata_declarations``) containing the declarations for +those templates. The symbols representing these templates are recorded at +this time (for ease of reference in later contexts). + +The symbol for namespace ``::cli`` itself is created even earlier by a call +to ``make_symbol_for_namespace_cli``. + +Debug Routines +============== + +The source file ``debug.c`` contains the routine that processes the +command-line debug request option (``-d``), and also the routines +``debug_enter`` and ``debug_exit`` which are called for flow tracing. When +the command-line debug request includes routine names, ``debug_enter`` +checks the name of the routine entered against the names on the request +list. If the name is found, the associated modification of ``debug_level`` +is done. An internal stack is used to preserve information from +``debug_enter`` time to ``debug_exit`` time for a function. One trick: A +checksum of the stop tokens set is computed and stored on entry, and +recomputed and checked on exit. This helps catch mismatched +``add_stop_token`` and ``remove_stop_token`` calls in recursive descent +scanning routines. + +``debug_enter`` and ``debug_exit`` are not called if there is no +command-line debug request (i.e., if ``db_active`` is FALSE). + +Generating Strings from IL Types and Constants +============================================== + +``il_to_str.c`` contains code that converts IL types and constants into +C/C++-form strings. Associated declarations are in ``il_to_str.h``. + +To use these routines, one needs to declare a control block of type +``an_il_to_str_output_control_block``, call +``clear_il_to_str_output_control_block`` to initialize it, and then set +applicable fields to describe how the string output should be done. The +control block includes, among other things, a pointer to a routine to +output a string, so one can establish a control block that provides an +output routine that writes to a file, or a control block that provides a +routine that puts the output string into a buffer, etc. Other fields in the +control block control the style of output and provide other (optional) +callback routines to do specialized output (instead of the default version) +for certain constructs. + +``form_type`` produces a string for a type. It does this by calling + +* | ``form_type_first_part``, which outputs the type specifiers and the + part of the declarator that precedes the name, and then + +* | ``form_type_second_part``, which outputs the part of the declarator + following the name. + +So, for example, for the type + + | *array* ``[10]`` *of pointer to* ``const int`` + +the "first part" would be + +.. code:: c++ + + const int * + +and the second part would be + +.. code:: c++ + + [10] + +If one wants to put out a declaration of an identifier, one can do so by + +#. calling ``form_type_first_part``, then + +#. outputting the identifier, then + +#. calling ``form_type_second_part``. + + +producing an overall output string like "``const int *a[10]``". + +``form_type_first_part`` descends through any derived types that are at the +top of the type by calling itself recursively. When it reaches a +non-derived type, it calls ``form_type_specifier`` to output the specifiers +part of the type (e.g., "``const int``" for the above example). Then, while +reascending, it puts out the parts of the declarator that appear on the +left-hand side of the declarator (pointers, references, +pointers-to-members, and any required parentheses). + +``form_type_second_part`` also descends through any derived types by +calling itself recursively. While descending, it puts out the parts of the +declarator that appear on the right-hand side of the declarator (arrays, +functions, and any required parentheses). ``form_array_declarator`` puts +out array declarators. ``form_function_declarator`` puts out function +declarators; it can be replaced by a user-provided routine if desired. One +reason to replace it: It does not handle putting out function declarators +for function definitions. + +``form_type_specifier`` puts out non-derived types. Most cases are simple +(see, for example, ``form_int_kind_name`` and +``form_float_kind_name``). Typedef names are put out as such. ``class``, +``struct``, ``union``, and ``enum`` types are always put out as references +to those types, i.e., a definition is never put out. + +``form_name`` puts out names; it can be replaced by a user-provided routine +if desired. It handles qualified names (see +``form_class_or_namespace_qualifier``), unnamed entities, and template +argument lists on classes (see ``form_template_args``). + +``form_constant`` produces a string for a constant. It does some processing +itself, and has several important helper routines: + +* | ``form_integer_constant`` puts out integer constants, including sign, + suffix, and implicit casts. It also handles integer constants cast to + pointer types (e.g., null pointers). + +* | ``form_address_constant`` puts out address constants, including the + "``&``" and optimizations for arrays and for adding a byte offset to + the base address. + +* | ``form_pm_constant`` puts out pointer-to-member constants, including + null constants and any required implicit casts. + +* | ``form_char`` puts out a single character of a string or character + constant, dealing with unprintable characters and the like. + +.. _error-reporting: + +Error Reporting +=============== + +``error.c`` contains code that handles reporting of errors. ``error.h`` +contains the declarations needed to use the error +routines. ``error_msg.txt`` defines the error codes and associated error +message text for all of the error messages, and, along with +``error_tag.h``, is used by ``mk_errinfo`` to generate the ``err_codes.h`` +and ``err_data.h`` files. It is the generated files that are actually used +by the front end to define the ``an_error_code`` enumeration and the array +of error message text. See :ref:`mk-errinfo` for a description. + +``an_error_code`` defines enumeration constants that represent each error +message (for example, ``ec_unclosed_string`` represents the error message +"missing closing quote"). ``ec_no_error`` is the first member of the +enumeration, and therefore has the value ``0``, which has the effect of +allowing flags with the value ``0`` for no error, and a non-zero value to +indicate a specific error. + +Within the error message texts, fill-in codes beginning with "``%``" +indicate points at which information is to be inserted: + +.. list-table:: + + * - | ``%%`` + - | A "``%``" is inserted into the message. + * - | ``%d`` + - | A number is inserted into the message. + * - | ``%s`` + - | A character string is inserted into the message. ``%sq`` indicates + that the inserted string should be placed in quotes, e.g., + + ``could not open source file "abc.h"`` + + * - | ``%t`` + - | A description of a type is inserted into the message. It is always + placed in quotes, e.g., + + ``cast to array type is nonstandard (treated as cast to + "int *")`` + + * - | ``%n`` + - | A description of an entity in the program (identified by a symbol) + is inserted into the message. The default ``%n`` ("name") can be + modified by appending an "``o``" (``%no``, "name only") to get just + the name of the entity, a "``p``" (``%np``, "name with function + parameters") to force parameter information on a function, an + "``f``" (``%nf``, "name full") to get full type information on the + name, an "``a``" (``%na``, "name with template arguments") to get + arguments on a template, "``t``" to force the "``A with T=int``" + form of template name to be used, or a "T" to get the translation + unit in which the symbol was declared. + + .. list-table:: + + * - | ``%n`` + - | ``function "A::f"`` + * - | ``%no`` + - | ``"A::f"`` + * - | ``%np`` + - | ``"A::f(int, float)"`` + * - | ``%na`` + - | ``"A"`` + * - | ``%nt`` + - | ``"A with T=int"`` + * - | ``%nT`` + - | ``function "f(int)" (from translation unit "x.c")`` + +.. list-table:: + + * - | ``%p`` + - | A source position is inserted into the message. + * - | ``%[``\ *label*\ ``]`` + - | The specified label is looked up in the ``label_fill_ins`` array + and one of two error messages is substituted depending on the + value of a boolean variable associated with the label. The + substituted error messages cannot themselves have fill-ins. See + the definition of ``label_fill_ins`` to determine the list of + valid label fill-ins (or to add a new one). + * - | ``%T`` + - | A template argument list is inserted into the message. + +In the default mode, the entity description is preceded by a keyword that +identifies the type of the entity (e.g., ``function`` above). That is also +done in the "full" mode for entities that are not variable-like or +function-like. The normal "``%n``" displays function parameter types only +for overloaded functions. Any of the ``%n`` codes can be modified by +appending a "``d``" to request information on the point of declaration of +the symbol: + +.. code:: text + + declaration is incompatible with "int f(char)" (declared at line 17) + +Following the optional "``d``" modifier, the "``T``" modifier may be used +to display the translation unit associated with the symbol ("``from +translation unit "x.c"``"). When compiling a primary translation unit, this +will cause the translation unit to be displayed for symbols from secondary +translation units. When compiling a secondary translation unit, this will +cause the translation unit to be displayed for all symbols. + +There can be more than one fill-in code in a message. When there is, each +fill-in code can be numbered (e.g., ``%t1``, ``%t2``) to tie it to a +corresponding fill-in argument. Note that this technique allows one to +reorder the fill-ins in a message (say, when changing the error messages to +a language other than English) without changing the order of the fill-in +arguments on error calls throughout the front end. + +Each normal diagnostic includes four kinds of information: + +* | the error code, which is a value from the enumeration just mentioned, + and indicates the error message text; + +* | a severity (remark, warning, discretionary error, error, or + catastrophic error); + +* | the error position (a sequence number and column); and + +* | optionally, some information that goes into fill-in spots in the error + message text. + +The severity is usually indicated by the routine called (e.g., ``warning`` +instead of ``error``). There are also routines that accept the severity as +an argument. A given message can be (and is, in many cases) output with +different severities in different modes or different places. + +The severity of a given error code may be overridden through the use of a +command line option or pragma. For example, the option +``--diag_error=extra_semicolon`` may be used to cause the extra semicolon +diagnostic to be issued as an error, even if the ``warning`` function was +actually called to report the error. Only diagnostics that would by default +be issued as remarks, warnings, or discretionary errors may have their +severities overridden (i.e., nondiscretionary errors and catastrophic +errors may not have their severities overridden). When a severity is +overridden by a pragma, the default severity can be restored by use of the +``diag_default`` pragma. The default severity is the severity as would +normally be used for the message as adjusted by any command-line options. + +The error severity may be overridden by specifying either an error "tag" or +an error number. The error tag is a name assigned to each error code. The +error number is the numeric value of the error code enumerator that +represents the message. By default, the error tag is the same as the error +code enumerator name with the ``ec_`` prefix removed. The error tag may be +changed by specifying an alternate tag in the ``error_msg.txt`` +file. Additional tags may be provided by creating entries in the +``error_tag.txt`` file. ``set_severity_for_error_tag`` and +``set_severity_for_error_number`` are used to override the severity for a +given diagnostic. These routines are called to process the error severity +options during command line processing. + +The error position is usually given by the global variable +``error_position``, but it can also be explicitly +supplied. ``error_position`` is set to the start of each token as it is +scanned, and is set on exit from recursive descent routines to the start of +the entity just scanned, unless that entity is extremely large (like +several lines). This usually results in the correct position in +``error_position``, at least for syntax errors. + +When the sequence number of ``a_source_position`` is ``0``, the column has +special meaning (for example, it can indicate that the error occurred in +the command line). See ``basics.h``. + +The error routines themselves have names that encode the severity (one of +``remark``, ``warning``, ``error``, ``catastrophe`` or the generic +``diagnostic``), and the particular combination of fill-ins and a source +position that they accept. That is, an error routine name may be as simple +as ``error`` or as complicated as ``pos_ty2_warning``. ``pos`` indicates +that a source position is provided; ``str`` or ``st`` indicates that a +string fill-in is provided; ``sym`` or ``sy`` indicates that a symbol +fill-in is provided; ``type`` or ``ty`` indicates that a type fill-in is +provided. These can be followed by a number if more than one fill-in is +needed, e.g., ``ty2`` for two types. So, for example, ``pos_ty2_warning`` +issues a warning, and the caller is expected to provide the error code, the +source position, and two fill-in types. See ``error.c`` for the full list +of routines. Not all combinations exist, but it is easy to add any routine +that does not exist. + +For a syntax error, one can instead call + +.. code:: c++ + + syntax_error(error_code); + +which will call ``error`` and then ``flush_tokens`` (see ``lexical.c``). + +For complicated errors that may have to list an arbitrary number of items, +for example diagnostics for overloading ambiguity, one can make an initial +call to issue the initial line of the error (calling ``start_error`` or one +of its variants such as ``type_start_error``), then any number of calls to +add individual lines of additional information (calling ``add_diag_info`` +or one of its variants such as ``sym_add_diag_info``), and then a call to +``end_error`` to finish the error processing (including writing the source +line in error). The end result is illustrated by + +.. code:: text + + "test.C", line 7: more than one constructor applies to convert from + "double" to "A": + function "A::A(int)" + function "A::A(float)" + f(2.0); + ^ + +The usual fill-in processing is available on both the initial line and any +lines of additional information. The additional lines are described by an +error code, so they can also contain arbitrary text. + +The error formatting and processing is done by ``construct_message``. It +fetches the error message text, builds a linked list of message segments +describing the message and its fill-in codes, expands each fill-in +appropriately, and writes the full message. + +If an error is detected while processing a template instantiation or during +implicit generation of a routine (e.g., a constructor), it is helpful to +provide additional information on the context in which the error was +detected: + +.. code:: text + + "test.c", line 7: error: "A::A()" is inaccessible + B x; + ^ + detected during implicit generation of "B::B()" at line 7 + +The context is deduced from the entries in the scope +stack. ``include_in_context_output`` identifies the scope stack entries +that merit extra context information. If there are any such entries, +``diag_message`` outputs an extra context line for each, in order from +innermost context to outermost. + +``format_output_line`` is the routine that actually prints the diagnostic +messages; it is the routine to change to modify the error output. To output +the source line associated with the diagnostic, ``write_source_line`` is +called. If the error is in the current line, ``write_orig_source_line`` +reconstructs and writes out the original source line, with a caret under +the column position of the error. If the error is not in the current line, +``write_error_source_line`` reads the line from the source file, if +possible, and writes out the source line. Long diagnostic messages are +wrapped across multiple lines. If raw listing information is requested, +similar information is written to ``f_raw_listing`` (in encoded form). The +diagnostic routines count the number of diagnostics of each severity so +that the compilation can be ended with an appropriate exit status. They +suppress diagnostics that are below the error display threshold. If an +error is catastrophic or if the error limit is reached, the compilation is +terminated. + +The severity of diagnostics for strict ANSI violations and C++ anachronisms +can be specified by command line options. To simplify handling of these +diagnostics the global variables ``strict_ansi_error_severity`` and +``strict_ansi_discretionary_severity`` contain the error severity to be +used for strict ANSI violations. The former is either ``es_warning`` or +``es_error``, while the latter is either ``es_warning`` or +``es_discretionary_error``, depending on which strict mode was selected on +the command line. ``anachronism_error_severity`` contains the error +severity to be used when anachronistic features are used. These global +variables can be used as arguments to the ``diagnostic`` reporting +routines. + +``command_line_error`` and ``str_command_line_error`` are the routines +called for command-line errors (without or with fill-in text, +respectively). They do not return. + +The routine ``internal_error`` should be called for internal errors, such +as failures of consistency checks. It should not be called for anything +that is due to a source program error or some environmental error (like a +missing file). The call should look like + + ``internal_error("``\ *routine-name*: *problem found*\ ``");`` + +Several routines are provided as convenient ways to do consistency +checking. Calls of these routines need not be surrounded by ``#if +CHECKING``/``#endif``; they are defined as macros that expand to nothing +when ``CHECKING`` is disabled. ``check_assertion`` can be used to check an +expression to make sure it is true; ``check_assertion_str`` is similar, but +includes a string to be printed on error +termination. ``unexpected_condition`` is used when a piece of code is not +expected to be reached (for example, the default clause of a switch); +``unexpected_condition_str`` is similar, but includes a string to be +printed on error termination. + +Memory Management +================= + +``mem_manage.c`` contains memory management routines. ``mem_manage.h`` +contains the associated declarations. + +Memory is allocated in *memory regions*. File-scope intermediate language +information is put in memory region 1, and the functions in the source +program will each have one of the memory regions 2, 3, and so forth. Memory +region 0 is used for storage that need not survive the front end, like the +symbol table. + +Before using a memory region, one calls either ``init_memory_region`` (for +regions 0 and 1) or ``new_memory_region`` (for regions for functions) to +initialize the new region. + +``alloc_in_region`` is then called when needed to allocate space in a given +region. (``alloc_fe`` can be called for the special case of allocation in +region 0, the front-end-only region.) ``alloc_in_region`` allocates a large +block of memory for each memory region by calling ``malloc``, then parcels +out that storage as it is needed. When the block is exhausted, a new block +is allocated and put on a linked list of blocks for that memory region. + +When one is done with an IL memory region, +``check_for_done_with_memory_region`` is called; it will either write the +information to a file and free the block, or trim the end of the memory +region to reclaim any unused space (depending on whether an IL file is +being generated), or defer this processing until later if the memory is +potentially needed for operations such as inlining or generic lambda +instantiation. "Trimming" means making a separate available block from the +remaining space at the end of the last block in the region. Since the +blocks are large (typically, 64K) and a typical function will use less than +10K of the block, this is an important feature. The combination of using a +large block size and reusing the remaining space improves efficiency (in +reducing the number of calls to ``malloc``) and avoids the need to guess at +the amount of storage a particular memory region is likely to +need. Eventually, when the partial blocks created in this way are released, +they are recombined into the original large blocks allocated via +``malloc``, and freed using the system ``free``. Thus storage used is +freed, but only on a large-block basis, so fragmentation is not a problem. + +``alloc_general`` is a more-or-less direct interface to ``malloc`` to be +used in the infrequent cases where storage must be allocated that will +survive into the back end if the back end is called in the same program. An +example of such storage is the debug option control list, which holds +information about the command-line debug option. + +``alloc_resizable_buffer`` and ``realloc_buffer`` are used to allocate +tables that can be enlarged (e.g., ``input_stack``). + +When ``MAKE_FRONT_END_CALLABLE`` is used, the front end keeps a record of +all memory allocations so that all of the memory allocated can be freed +before returning control to the caller. + +When precompiled headers are used, the memory management routines work to +allocate the IL memory region blocks at reproducible addresses, so that the +information in a precompiled header file can be read back in without the +need to walk the IL and remap pointer references. See +:ref:`memory-management-issues`. + +File Variables +============== + +Normally, any open files are closed when the front end exits, but when +``MAKE_FRONT_END_CALLABLE`` is used, any open files must be closed if the +front-end were to terminate abnormally. This is accomplished by having a +special cleanup routine (e.g., ``templates_cleanup``) in any file that +opens and closes files. The cleanup routine is present only when +``MAKE_FRONT_END_CALLABLE`` is used. File variables must be set to ``NULL`` +when they do not refer to an open file. The cleanup routine generally calls +``close_file_if_open``, to close any files that may be open. The cleanup +routines are called by ``fe_cleanup`` (in ``fe_wrapup.c``). + +Command-line Parsing +==================== + +``cmd_line.c`` contains code to parse the command line; ``cmd_line.h`` +contains the associated declarations. The main routine is +``proc_command_line``. Aside from setting switches, ``proc_command_line`` +establishes the primary source file, the preprocessing output file if there +is one, the raw listing output file if there is one, the cross-reference +output file if there is one, and the include file search list. + +If multiple source files can be compiled, ``get_next_source_file`` is +called after each source file is compiled to see if there is another file +name on the command line. It also does some minor initialization. + +``proc_command_line`` is called only once, even if multiple source files +are specified on the command line. Since the IL memory for each source file +is separate and self-contained, ``proc_command_line`` cannot allocate +anything in the IL memory: For one thing, it does not exist yet, and for +another, there will be a distinct copy for each source file +compiled. Therefore, file names and other information saved by +``proc_command_line`` must be saved in general memory, and copied into IL +memory later (e.g., in ``fe_init``) for each source file. + +Host-dependent Routines +======================= + +``host_envir.c`` contains host-dependent routines; ``host_envir.h`` +contains the associated declarations. + +The following routines are used to maintain the list of directory names to +be searched for include files: + +* | ``add_default_include_search_path`` +* | ``add_to_include_search_path`` +* | ``add_to_front_of_include_search_path`` +* | ``push_primary_include_search_dir`` +* | ``pop_primary_include_search_dir`` +* | ``change_primary_include_search_dir`` + +The following routines are used to tear apart and build up file names: + +* | ``directory_of`` +* | ``gs_directory_of`` +* | ``derived_name`` +* | ``replace_file_name_suffix`` +* | ``combine_dir_and_file_name`` + +The following routines are used to open files in various ways: + +* | ``open_source_file`` +* | ``reopen_source_file`` +* | ``okay_as_output_file`` +* | ``open_output_file`` +* | ``reopen_error_output_file`` + +``delete_file`` is used to delete files (specifically, files that were +partially generated and are to be canceled because of detection of an +error). + +``open_temp_file`` and ``close_temp_file`` provide support for creating +temporary files. (Note: At the present time, the front end only uses +temporary files when generating an intermediate language file for immediate +use by a back end called in the same program, and in the C-generating back +end.) + +``normal_termination`` and ``term_compilation`` are used for termination of +the compilation. The low-level functions of ``term_compilation`` are +available individually through ``write_signoff`` and ``exit_compilation``. + +``identify_source_file`` is called from ``fe_init`` at the start of +compilation of each source file when there are multiple source files on the +command line. It outputs a message identifying the start of the compilation +of the file. + +``set_signal_handlers`` is called during initialization to set up handling +for signals that should abort the compilation. + +This file is likely to be modified for different hosts. See the section on +host configuration for more information. + +Intermediate Language Traversal +=============================== + +``il_walk.c`` contains the routines that walk the intermediate language +tree, and ``il_walk.h`` contains the associated +declarations. ``walk_entry.h`` contains the detailed code to process the +fields of each IL entry kind. + +"Walking" the tree means traversing the in-memory form of the IL and +calling a supplied routine for each node in the tree. This is used in +displaying the IL in human-readable form, in writing the IL to a file, and +in reading the IL from a file. + +The walking is done on a memory region basis, i.e., for the file-scope +memory region or the memory region for a function. The routines for those +cases are ``walk_file_scope_il`` and ``walk_routine_scope_il``. They call +``walk_entry_and_subtree`` or ``walk_string_entry`` for each entry, and +those in turn call the user-supplied entry processing functions. There are +two separate entry processing functions supplied for each traversal: one +for strings, and one for non-strings. The main reason for the difference is +that string entries do not have fixed sizes, so the string routine has an +extra parameter for the size. + +Since the tree is actually a graph and has cycles, there needs to be a way +to tell when the traversal returns to an entry that has already been +visited. This is provided by the ``il_walk_flag`` in the prefix that +precedes each IL entry. This flag starts out as 0 in all entries. On the +first traversal, it is changed to 1 in all entries, and it keeps +alternating between 0 and 1 on each subsequent traversal. Therefore, on a +given traversal, the entries already seen have one value, and those not yet +seen have the other value. + +While the tree is traversed, one can also request that all the pointers in +the tree be remapped in some way. For example, when writing to an IL file +in the alternate form, each pointer is replaced by an entry number. Such +remapping can be requested by providing a pointer remap function for the IL +walk, or explicitly by calling ``remap_pointers_in_il_entry`` or +``remap_il_header_pointers``. + +Special handling is required for "orphan" entries. These are entries +allocated in the file scope memory region that are referenced only from +function scope memory regions. When the parents of such entries are written +out and then removed from memory, the entries are orphaned because they are +not attached to the rest of the file-scope IL tree. + +The orphan mechanism makes lists of such entries so that they can be found +during traversal of the file-scope IL. + +The array ``orphaned_file_scope_il_entries`` heads lists of orphaned +entries linked together by a hidden orphan-list pointer that precedes the +storage for each file-scope IL entry. (It also precedes the +``an_il_entry_prefix`` structure.) + +The orphan lists are built up while the function scope memory regions are +walked. Each time an entry in a function scope memory region contains a +pointer into the file scope memory region, the entry pointed to is recorded +as a potential orphan. Later, at the end of the walk of the file scope IL, +the entries on the orphan lists are visited. If the entries are not in fact +orphans, they will have been previously visited, and the IL walk flag will +indicate that fact. + +A separate mechanism exists for orphaned lists, specifically the lists of +local types and local static variables in function and block scopes. Those +are unusual in that the list is completely in the file scope memory region +but the pointer to the list is in a function scope memory region +entry. Each of the entries on those lists is placed on the orphaned entries +list, but there needs in addition to be a way to remember the head-of-list +pointers so that the ``next`` pointers in the entries can be +remapped. That's done with a list of entries of type +``a_scope_orphaned_list_header`` pointed to by the +``scope_orphaned_list_headers`` field of ``il_header``. Each entry on the +list points to a list of types and a list of static variables preserved +from a function or block scope. + +Obviously, the code in ``walk_entry.h`` must be kept up-to-date whenever +the IL definition in ``il_def.h`` is changed. + +``il_walk.c`` also contains some special-purpose walking routines: +``walk_declarative_entities_in_scope`` can be used to walk entities like +variables in a given scope; ``traverse_expr`` can be used to walk an +expression tree; and ``traverse_statement`` can be used to walk a statement +tree. In each case, user-provided callback routines can be called for each +node of the tree. + +.. _needed-flags: + +Needed Flags +============ + +When the configuration switch ``MAINTAIN_NEEDED_FLAGS`` is TRUE, the front +end will maintain the ``needed`` flag in the source-correspondence entry, +and the ``definition_needed`` flag in class types and routines. The code to +do this is in ``il_walk.c``, ``walk_entry.h``, ``il.c``, and +``scope_stk.c``. The needed flags are a more sophisticated version of the +``referenced`` flag. They are set by beginning with all externally-defined +variables, static data members, and functions in the compilation unit, and +marking those as needed. Then the entities referenced by those are marked +as needed, and so on. The resulting ``needed`` flag setting indicates +whether something is "really" needed, as opposed to referenced from +something that is itself unneeded. For example: + +.. code:: c++ + + static int i; // i is referenced, not needed + static void f() { // f is not referenced, not needed + i = 1; + } + int main () {} // main is needed, not referenced + +The ``definition_needed`` flag indicates whether the definition of a class +is needed, as opposed to merely a declaration. For example: + +.. code:: c++ + + struct A { }; + struct B { }; + A *p; // forces needed on A, but not definition_needed + B b; // forces needed and definition_needed on B + +There is a similar flag for functions as well. + +If ``DEFAULT_REMOVE_UNNEEDED_ENTITIES`` is TRUE, and that setting is not +overridden via a command-line option, unneeded entities are removed from +the IL. Classes that have ``needed`` TRUE and ``definition_needed`` FALSE +are modified to eliminate their definitions. Function-local entities are +never affected by this process (they are not removed, and local classes are +never turned into declarations). The IL tree after alteration is +self-consistent, in that a back end that does not use the "needed" flags +will find all the IL entries it expects. A back end that does use the +"needed" flags should be sure to use both of them, i.e., +``definition_needed`` as well as ``needed``. + +The "needed" flags processing and removal of unneeded entries works with +and without IL lowering, and for both C and C++. When IL lowering is used, +the "needed" flag information is determined on the basis of the lowered +code. When the C++-generating back end is used, and the source program has +templates, elimination of unneeded entities is disabled, because the +template bodies may contain references to apparently unneeded +entities. This can be changed, carefully, if one has a situation where all +template instantiation will be done by the EDG front end rather than by +some compiler operating on the source code generated by the C++-generating +back end. + +The setting of the "needed" flags is done as follows: + +* | At the end of scanning a function definition, if the function is + externally defined, ``pop_scope`` calls ``mark_as_needed`` on the + routine, which in turn calls ``set_routine_definition_needed``. These + use a specialized version of the ``walk_entry.h`` IL-walking code to + sweep through the IL tree and set the ``needed`` flag on all + transitively-referenced entities. If the type of reference requires a + complete type, and the type is a class, ``set_class_definition_needed`` + is called to set the ``definition_needed`` flag on the class. If a + reference to a routine requires that the routine have a definition, + ``set_routine_definition_needed`` is called for the routine. + | + | When a routine's definition is needed, the definition is also walked, + and then the memory region for the function can be disposed + of. (``mark_to_keep_in_il`` is also called for the function memory + region; more on this below.) That means the memory region can be + written to a file and then freed, if an IL file is being + used. Conversely, as long as a function is not known to be needed, its + body must be retained. If the function is still marked as unneeded at + the end of the compilation, it is then clear that the function truly is + unneeded. It is deleted and its memory region is freed (without writing + it to the IL file, if there is one). +* | When the file scope is being + popped from the scope stack, several things are done. First, + ``set_needed_flags_at_end_of_file_scope`` is called. It visits all + variables (including static data members), and calls ``mark_as_needed`` + for those that are externally-defined. This causes the variables and + everything they reference to be marked as "needed." +* | Then, + ``mark_to_keep_in_il`` is called for the file scope. This uses another + variant of the ``walk_entry.h`` IL-walking code to sweep through the IL + tree and set the ``keep_in_il`` flags in the IL entry prefix and the + ``keep_definition_in_il`` flag in classes and routines. These flags + have meanings similar to the ``needed`` and ``definition_needed`` + flags, but they are set in more cases, to deal with the fact that some + entities in the IL tree must be retained (for consistency) even if they + are "unneeded." In this sweep, entities that can and will be removed + (based on the ``needed`` and ``definition_needed`` flags and the + context where the entities appear) will not be visited. The + ``keep_in_il`` sweep also notes whether complete class types are + needed, and calls ``set_class_keep_definition_in_il`` when appropriate, + and whether routine definitions are needed, and calls + ``set_routine_keep_definition_in_il``. + | + | All decisions about + removing IL entries from the IL tree are based on the ``keep_in_il`` + and ``keep_definition_in_il`` flags, rather than on ``needed`` and + ``definition_needed``. +* | Then, + ``eliminate_bodies_of_unneeded_functions`` is called. It eliminate the + bodies (but not the declarations) of functions that are not needed. +* | Then, ``eliminate_unneeded_il_entries`` is called. It removes types, + variables, and routines in the file scope that are unneeded, and + reduces classes to declarations where appropriate (by calling + ``turn_class_definition_into_declaration``). Auxiliary parts of the IL + data structure, such as source sequence entries and the hidden-name + table, are updated as necessary. + +The IL-walk process used to set these "needed" flags stops when it +encounters an entry with the flag already set. This is desirable for +compilation speed reasons, and necessary to avoid loops for parts of the IL +structure that are graphs instead of trees, but it also makes certain kinds +of problems possible. Variables, routines, and types that are not +function-local have the potential to be redeclared after the "needed" flag +is initially set. For example, a class ``A`` might be declared, then marked +as needed, then defined. Or, a function might be defined, then declared to +add an additional default argument. In all such cases, The ``needed`` or +``keep_in_il`` flag would be set already on the entry, and therefore an +attempt to set it again would result in an immediate return, rather than a +sweep through the updated subtree. To avoid this problem, the subtrees of +these redeclarable entities are not swept ordinarily; the appropriate flag +is set on the entry itself, but its subtree is not visited. At the end of +the file scope, when no more redeclarations are possible, the global flag +``end_of_file_scope_needed_flags_phase`` is set to TRUE, and that enables +the subtree walks. ``set_needed_flags_at_end_of_file_scope`` and +``mark_to_keep_in_il``, as they are doing the ``needed`` and ``keep_in_il`` +walks respectively, look for these delayed-subtree-processing entries, and +handle them by clearing the ``needed`` or ``keep_in_il`` flag and then +calling the subroutine to set them again, which this time will visit the +subtree. For the ``needed`` flag walk, ``remark_as_needed`` provides a +convenient way of doing this. + +When ``ONE_INSTANTIATION_PER_OBJECT`` is TRUE, a more complicated set of +"needed" flags is maintained. In that mode, each instantiation is put out +as a separate object file. There is still only one IL tree, but it is +marked so that a back end can sweep through it several times and put out a +different "slice" each time, each slice containing one instantiated entity +(function, variable, or static data member) plus exactly the set of other +entities needed by that entity. This is done via a set of per-instantiation +"needed" flags, represented as a bit vector implemented as a linked list of +entries of type ``a_per_instantiation_needed_flags_entry`` attached to the +``per_instantiation_needed_flags`` field of the source correspondence. Each +slice is assigned one bit in that bit vector, and if the bit is 1 the +associated entity is needed in the slice. + +The per-instantiation "needed" flags are tested and set by the macros +``needed_flag_is_set`` and ``set_needed_flag``. The global variable +``needed_flag_bit_number`` indicates the bit number to be tested or set. +If it is zero, the ``needed`` flag is tested or set instead of the bit +vector. + +Each instantiation is actually assigned two bits in the bit vector, the +second one used for the per-instantiation versions of the class and +function ``definition_needed`` flags. These are tested and set by +``class_definition_needed_flag_is_set``, +``set_class_definition_needed_flag``, +``routine_definition_needed_flag_is_set``, and +``set_routine_definition_needed_flag``. As with the needed-flag macros, +these macros depend on the value of ``needed_flag_bit_number`` and use the +``definition_needed`` flags if that variable is zero. + +The bit number assigned to a given instantiation entity is recorded in the +``instantiation_needed_bit_number`` field in the variable or routine. When +``mark_as_needed`` is called for the entity, after the standard "needed" +flag processing has been done, another sweep is done to set the proper bit +in the per-instantiation "needed" flag bit vectors of all entities +referenced from the instantiation. The class and function per-instantiation +definition-needed bits are also set in this sweep. + +All externally-defined entities that are not instantiations are assigned to +the slice numbered 1 (though their ``instantiation_needed_bit_number`` +fields are left as zero), and a similar sweep is done for them. By the end +of the compilation, therefore, every externally-defined entity has been +assigned to a slice, and the per-instantiation bits show what must be +included in each slice. The "1" slice includes everything that isn't in an +instantiation slice. + +Some entities are present in multiple slices. Constants, types, and class +definitions appear in each slice as needed. Inline functions are also +present in a slice if they are referenced in that slice. In general, +however, functions and variables can only appear in one slice, or more +precisely, their definitions can only appear in one slice. If other slices +reference them, they appear only as declarations in those slices. This +causes a problem for static functions and variables, which by definition +cannot be referenced from other object files. This is handled by making +those entities external with generated names. The sweeping routines will +set the ``static_used_by_instantiation`` flag in static entities that are +used by an instantiation, and IL lowering will turn such routines and +variables into external entities. + +The simple ``needed`` and ``definition_needed`` flags end up being in +effect the unions of the corresponding per-instantiation sets. That is, if +any per-instantiation "needed" flag is set on an entity, then the +``needed`` flag will be set, and likewise for the definition-needed +flags. Therefore, when the normal processing to remove unneeded entities is +done, it will remove only entities that are unneeded in all slices. + +Intermediate Language Display +============================= + +``il_display.c`` contains routines to display the IL in human-readable +form. ``il_display.h`` contains the associated declarations. The code is +currently set up to be compiled as a standalone utility program: It reads +the IL from a file (by calling the IL read routines), then traverses the +in-memory form using the IL walk routines, producing output on +``stdout``. ``il_display`` could be set up as a subroutine to be called +from within the front end. + +The processing is very simple: Using the IL walk routines, it walks the +file scope and displays it, then walks each routine scope and displays +that. The IL walk routines are told to call ``disp_entry`` for each +non-string entry, and to call nothing for string entries (string entries +are displayed when pointers pointing to them are displayed). Most of the +display routines are very straightforward. When pointers are displayed, an +attempt is made to show what is pointed to. That is, if the entity pointed +to is named, or if it is a string, a constant, or a type, a brief summary +of the entity is given so one does not have to look at, say, a type entry +to find out that it is the entry for ``int``. + +If there are errors in the IL, they are highlighted (e.g., +"**BAD-TYPE-SPECIFIER-KIND**") and the display continues as well as it +can. An internal error is not generated. + +Obviously, the code in ``il_display.c`` must be kept up-to-date whenever +the IL definition in ``il_def.h`` is changed. + +Writing the Intermediate Language to a File +=========================================== + +``il_write.c`` contains routines that write the intermediate language to a +file, and ``il_write.h`` contains associated declarations. + +IL writing takes the in-memory IL and writes it to a file for later +reading. + +``start_il_file`` is called to open the IL file, and ``finish_il_file`` to +close it. Alternatively, ``cancel_il_file`` can be called to delete the IL +file and suppress further IL file generation if an error is detected during +the compilation. + +``write_memory_region`` is called to write out each memory region, i.e., +the file-scope memory region or a memory region for a function. It writes +the memory region at the end of the intermediate language file. + +There are two IL file formats. The switch ``ALTERNATE_IL_FILE_FORMAT`` in +``host_envir.h`` indicates which is to be used. The file header is the same +in both formats: + +* | A special string identifying the file as an IL file, and including the + version number of the IL (see ``il_file.h``). + +* | The number of memory regions. +* | The number of function definitions. +* | The file position of the file index (at the end of the file). +* | The file position of the file-scope memory region. +* | The ``il_header`` struct, which is the root of the IL tree. +* | The array of orphan-list pointers. + +In terms of processing, the space for the header information is reserved at +``start_il_file`` time, but the full information is not known until all +regions have been written. At ``finish_il_file`` time, the file pointer is +repositioned and the final information is overwritten on the reserved +space. + +The file index is also the same in both formats: It is an array of file +positions, such that file-index[*i*] gives the file position of the start of +the information for memory region *i*. The index is the last thing written in +the file. No entry 0 is written; the first entry is entry 1 (i.e., for the +file scope), which is at the position indicated by the file index position +in the header. The other entries follow. There are as many entries as the +"number of memory regions" given in the header. + +Between the header and the file index is a sequence of one or more memory +regions. Since the file-scope region is not complete until the end of the +compilation, the file contains all the function regions first, in order of +definition, and then the file-scope region at the end. + +In both formats, the information for a memory region begins with the memory +region number, and the overall sequence of regions is followed by a zero +which serves as an end marker if the regions are read sequentially. + +Beyond that, the information for a memory region is quite different in the +two file formats. + +The default file format involves writing out the memory blocks for each +region exactly as they appear in memory -- i.e., large blocks, in memory image +form. On the reading side, these blocks are read back in, and since they +are probably not read in at the same address they had when written out, the +IL tree is walked to find and remap all the pointers. A tree walk is also +required on the writing side, at least for function scope memory regions, +to get the data structure for orphaned entries built. The process is fairly +fast on both the writing side and the reading side; although the tree walk +takes time, at least the I/O for reading the blocks can be done +efficiently, in large blocks. + +The information for a region in the default format is as follows: + +* | The memory region number. +* | The original memory address for the first block header. +* | The original memory address for the primary scope entry for the region. + +* | The total size in bytes of the information following (i.e., the total + size of all blocks and their associated headers). + +* | For each memory block, the block header and block data. The header + contains pointers that point to the next block and to the data (all as + original memory addresses). + +In the alternate file format, each entry is assigned an entry number (which +is recorded in the prefix preceding the entry), all pointers are changed to +the corresponding entry numbers, and each entry is written individually to +the file, preceded by an indication of the entry kind and by the entry +number. On the reading side, the entries are read individually and the +pointers in them are changed to the proper new pointer values. This format +is less efficient than the default format, because the actual I/O is done +one entry at a time for both writing and reading (there is of course +buffering under this, but it is still less efficient to make thousands of +calls to ``fwrite`` and ``fread`` than to make dozens of calls). The +advantage of the alternate file format is that it allows resizing or other +alteration of the entries on the reading side. If one wants to add +back-end-specific information, for example, one can do so. + +The information for a region in the alternate file format is as follows: + +* | The memory region number. + +* | An array giving, for all the IL entry kinds (see ``il_walk.h``), the + number of entries of each kind in this memory region. + +* | A sequence of entries, giving for each entry the entry kind, the entry + number, the entry length (only for string entries), the orphan-list + pointer (only for non-string file-scope memory region entries), and the + entry itself. After the last entry, a zero entry kind marks the end of + the sequence. + +Entry numbers are assigned from 1 for each kind of table; there can be, for +example, a type entry 27 and a constant entry 27. 0 is used to represent a +NULL pointer. The entry numbers in each function scope start again from 1, +but in addition they have the top bit on, i.e., they effectively start with +``LONG_MAX+2``. Thus there can be identical entry numbers in two function +scopes (and that is not a problem), but a file-scope entry number can +always be distinguished from a function-scope number. + +For string entries, the "entry number" used is an offset into a conceptual +block formed by concatenating all the strings of that kind, including the +terminating null if any, and with space reserved between the strings for +the entry prefix and for any required alignment. The offsets start from 1 +to preserve 0 as a NULL pointer. In the array of entry counts, the values +for string entries indicate the total size of the conceptual block, in +bytes, rather than an entry count. Thus, if there were three strings "``abc``", +"``de``", and "``fghi``" in a region, the prefix takes 4 bytes, and the host +machine requires 4-byte alignment, the strings' entry numbers would be 5, +13, and 21, respectively, and the entry in the count array would be 25. + +Reading the Intermediate Language from a File +============================================= + +``il_read.c`` contains routines that read the intermediate language from a +file, and ``il_read.h`` contains associated declarations. + +File reading takes the IL in file form and reads it in to re-create the +in-memory form. + +The routine ``il_read`` reads the file header and the file index, then +calls ``read_memory_region`` to read the file-scope memory region. Other +(function-scope) regions must be read explicitly by calling +``read_memory_region`` directly. This allows the back end to read each +function, process it, and then free its IL by calling +``free_memory_region``, to reduce overall memory requirements. + +With the default file format, the information for each memory region is +read with one large read, and the pointers in the region are then remapped +to the proper values by calling ``walk_file_scope_il`` or +``walk_routine_scope_il`` with a pointer remap function. If all the memory +blocks are read back in at their original addresses (an attempt is made to +do this), the IL walk is not needed. + +With the alternate file format, the array of entry counts is read at the +beginning of processing the region. For each entry kind, an area is +allocated that is large enough to contain all the entries of that kind (its +size is the number of entries times the size of each entry). This area is +then considered an array of entries of that kind, and the entry number is +an index into the area. (For string entries, the "entry count" is the +actual total size, and the "entry number" is still an index -- with the area +treated as an array of characters.) Each entry is then read, placed at the +right place in the allocated space, and its pointers changed from entry +numbers back to real pointers. Note that no overall tree walk is done, and +no special orphan processing is required: Since each entry is read +individually, one can do all the processing for each entry when it is read, +and be sure no entries were missed. + +As each region is read, the associated entry of ``region_scope_entry`` in +``il_header`` is set to point to the primary scope entry for the region. + +Precompiled Headers +=================== + +The precompiled headers ("PCH") facility is intended to speed up +compilations that include relatively stable header files. It does this by +writing a precompiled header file that is a snapshot of the front end's +internal state at a point in the compilation process immediately following +the initial sequence of ``#include``\ s. On a recompilation of that file +(or another that begins with the same sequence of ``#includes``), the front +end checks to see if all the header files are unchanged since the +precompiled header file was generated, and if so reads in the precompiled +header file to re-establish the front end state as it would be after +reading and compiling the header files. Reading in the PCH file takes less +time than compiling the header files from source, so there is a net savings +in compilation time. + +Since the point of this feature is saving time, it is important that the +process of writing and reading the PCH files be as fast as possible. One +would like to see savings of 80% or the like (comparing the time to restore +a PCH file to the time to compile the original source code); an improvement +of only 30% or so would barely be worth the extra complexity. In addition, +one should not have to pay a large price to write out the precompiled +header file; it's okay to slow compilations a little to get the benefits of +precompiled headers on later compilations, but if it takes too long to +write the file, the net gain is marginal or negative. + +These speed issues suggest some basic design decisions: + +* | The information written to the precompiled header file must not require + a tree walk, because visiting every entry takes a lot of time. (It also + requires code or data structures that describe how to do the tree walk, + which exist for IL entries but not for the front-end-only data + structures.) Therefore, the information must be written out and read + back in as large chunks (rather than one entry at a time), and it must + not be necessary to remap all pointers in the information to new values + (i.e., it must be possible to bring the information back in at the same + address). These requirements also make it possible to exploit memory + mapping on systems that support it. + +* | Precompiled header files should contain snapshots of compilation + states, and not information about individual header files. While it's + tempting to imagine writing precompiled header files for individual + header files, the work required in carving out the right information + and the description of dependencies so that the information can be + written to a file, and the work to bring it back in and merge it with + the front end state, will make substantial time savings unlikely. + +An unfortunate consequence of this latter design decision is that users are +probably forced to change their source code to get any meaningful benefit +from the PCH facility. In average source code, the order of inclusion of +header files is essentially random. The net effect of the various orders of +inclusion is often the same, because of the way header files tend to be +written, but it is difficult to deduce that fact, and time-consuming. So we +have a dilemma: If we strive for maximum save/restore speed, we will find +few "natural" common sequences, and therefore generate many PCH files for +little benefit. On the other hand, if we try for maximum ability to reuse +precompiled headers from unaltered source files, we lose something +significant on save/restore speed. + +We've chosen to go in the direction of maximum save/restore speed. We +believe that users are willing to make small changes in their source code +to get large reductions in compilation time, and that given a choice +between + +#. | You don't have to change your source, and precompiled headers will + give you a 15% savings, or + +#. | You may have to reorder your initial ``#include``\ s or add the + equivalent of + + ``#include `` + + | to the beginning of your source files, and precompiled headers will + give you a 50% savings, + +users will choose option 2. This, of course, is a matter of opinion, and +the percentages are fictitious. But for better or worse, this is what we +decided. + +Because PCH processing is not likely to be helpful on arbitrary files, it +is disabled by default. + +The code for precompiled header processing is mostly in ``pch.c``, with +associated declarations in ``pch.h``. + +Prefix and Header Stop Point +---------------------------- + +The initial sequence of the source code of the primary source file that is +subject to the PCH optimization is referred to as the *prefix*. It consists +of the preprocessing directives preceding the *header stop point*. The header +stop point is determined as follows: + +* | Start at the first token of the primary source file that is not part of + a preprocessing directive (or the end of the file if there is no such + token). + +* | If there is a ``#pragma hdrstop`` preceding that token, back up to the + pragma position. + +* | If the position determined by the first two steps is inside a + preprocessing directive like an ``#if``, back up to (just after) the + previous top-level preprocessing directive. + +For example: + +.. code:: c++ + + /* Comments. */ + #define flag 1 + #if flag + #include "abc.h" + #else + #include "def.h" + #endif + #include + /* header-stop point. */ + int i = 1; + #include "abc.h" + /* header-stop point. */ + #if xyz + #include "def.h" + #pragma hdrstop + #endif + +Note that, while determining the prefix, ``#if``\ s and the like are not +evaluated, so code that will be skipped in the actual compilation can +nevertheless serve as a header stop point. This is particularly important +with ``#pragma hdrstop``. + +At the beginning of compilation, if precompiled headers are enabled, the +prefix for the primary source file is accumulated. This is done by opening +the primary source file, reading the beginning of it in a special mode +while building an in-memory representation of the preprocessing directives +read, and closing the source file. This is a separate process from the +normal compilation of the file, and is a necessary first step whether the +front end ends up using an existing PCH file or creating a new one. See +``build_prefix_information``. + +The prefix scan is done by setting ``building_pch_prefix`` and calling +``get_token`` once. That causes the scanning of all of the preprocessing +directives preceding the first "real" token of the primary source file. The +preprocessing directives are not evaluated in the usual way; they are just +placed on the prefix event list. (In particular, ``#include`` directives +are just accumulated like the others; the included files are not read.) +Each such event contains an enumeration code for the preprocessing +directive and a null-terminated string giving the text of the directive +following the directive keyword. + +After the initial prefix list is built up, the list is trimmed down by +discarding anything after a ``#pragma hdrstop`` and then, if the end is +inside an ``#if`` or the like, discarding preprocessing directives back to +the last top-level directive. + +If the primary source for the compilation is coming from ``stdin`` instead +of a file, the prefix construction cannot be done (and therefore PCH files +cannot be created or used). + +A list of the command-line options for the current compilation is also +built. It is also a linked list, and each entry on the list indicates one +command-line option. Options that have no effect on the state preserved by +PCH processing are not put on the list, but the rest (most of them) +are. The option code is represented by an enumeration, so the difference +between the single-letter form of the option and the keyword form is +erased, but in all other respects the list built up will have to match the +corresponding list for a PCH file exactly -- same options, same order. + +Using a PCH file +---------------- + +Once the prefix has been created, the front end will look to see if any of +the existing PCH files can be used to avoid some part of the compilation +for the current file. A host-dependent routine is used to fetch the names +of all PCH files in the appropriate directory (the directory can be +specified via the ``--pch_dir`` command-line option). Each file is checked +to make sure it is a regular file (not, say, a directory), that it has the +right header string identifying it as a PCH file, that the compiler version +number and generation date/time are the same, and that the flag indicating +that the file is completely written has been set. If any of those checks +fails, the file is closed and not considered further; in effect, it's +considered not to be a PCH file. + +The next round of checks seeks to determine whether the PCH file is +applicable to the current compilation. The front end checks that the +current directory and the one recorded in the PCH file are the same; that +the command-line event lists are the same; and that the preprocessing +directive event lists are the same (or the current file's prefix list is +longer than the prefix list in the PCH file). If those are okay, the front +end checks that the header files included in the PCH file have not changed +since the PCH file was built (this is done by checking the timestamps of +the files against the timestamps recorded in the PCH file). If the +timestamps indicate that the PCH file is out of date, it is deleted. + +A PCH file that makes it this far can be used, but it might not be the best +choice: There might be another PCH file that also matches but includes more +of the prefix preprocessing directives. Therefore, if the match is not +perfect, other PCH files are considered and the best-matching PCH file is +chosen. Each PCH file is closed after it is considered and must be reopened +later if selected as the best file. + +If the user has used the ``--use_pch`` command-line option, the indicated +PCH file is chosen directly. No other PCH files are considered, and the +applicability test is not done (at this point; see below). + +Once the best-matching PCH file is selected for a file called (say) +``x.C``, if the PCH file selected is not ``x.pch``, and there exists an +``x.pch``, ``x.pch`` is deleted. This is a simple way of getting rid of PCH +files that are no longer needed. + +Once a PCH file is selected, the front end state is restored from the +file. The PCH file is opened again and the prefix check is done again to +make sure the file has not changed since the first check. For a PCH file +specified via a ``--use_pch`` command-line option, this is the only +applicability test done (and if the file fails, a warning is issued and the +compilation continues without using the PCH file); for other cases, this is +a repetition of the applicability test already done. Next, the global +variables registered via ``register_pch_saved_variables`` are read and +restored. Finally, the contents of the various memory regions (IL and front +end) are restored. These are restored at the original addresses, so it is +not necessary to walk through the restored data to adjust pointers. (See +the section on memory management issues below for more information on this +aspect.) + +The restoration process occurs after most initialization of the front end, +so some variables are initialized then overwritten by the restoration from +the PCH file. + +Once the front end state has been restored from the PCH file, the lexical +routines are reset and the primary source file is opened again. The prefix +is skipped by doing a ``get_token`` in a special lexical mode. This is very +similar to the scan done to accumulate the prefix, in that initial +preprocessing directives are passed over uninterpreted. However, once the +preprocessing directive that marks the end of the matched part of the +prefix is processed, normal processing of preprocessing directives is +re-enabled. Shortly thereafter, the initial ``get_token`` finishes, and +normal compilation continues from that point (we know we are between +top-level declarations, so we can continue simply by entering the main +compilation-unit loop). + +The PCH restoration process restores the front end state after compilation +of the precompiled headers, but it doesn't duplicate the output that would +have been done on auxiliary files during the skipped part of the +compilation. Diagnostics that would have been written, and output lines on +the raw listing and cross-reference output files that would have been +generated, are not put out when a PCH file is used. If the front end is +configured to use an IL file, that file also is not generated as this +point. However, the IL file does get generated by a catch-up process done +after the point where a PCH file is generated or a decision is made not to +generate one; see below. + +Because the source sequence numbers of the original compilation may not +exactly match the sequence numbers in the current compilation (e.g., +because of whitespace differences), the source file mapping information in +the IL in the PCH file is restored as, in effect, the first include file on +the list under the primary source file of the current compilation. + +Creating a PCH File +------------------- + +After the front end has read in a PCH file or chosen not to use one, the +"normal" compilation process begins. When the compilation reaches the +header stop point, we have the option of creating a PCH file that +encapsulates the front end's state at that point for later restoration. + +Note that it is possible to both use and create a PCH file in the same +compilation, because the best-matching PCH file might contain only the head +of the full prefix. In that case, the internal state is restored from the +PCH file, then the rest of the prefix is compiled in the normal way, and at +the header stop point the compiled form of the full prefix is saved to a +new PCH file. + +The position of the header stop point was determined by the prefix scan at +the very beginning of the compilation. Its position is defined in terms of +a preprocessing directive, more specifically as the end of the processing +for that directive. Compilation starts up or continues in a mostly normal +way, with the header stop position set as a sort of breakpoint. When the +end of the indicated preprocessing directive is reached, the front end will +check to see whether a PCH file can be generated. + +On the way to the header stop point, some things may happen to preclude +generation of a PCH file: + +* | A reference to one of the macros ``__DATE__`` or ``__TIME__``. Since + these would change from compilation to compilation, there is no point + to saving the state of a compilation that uses them. + +* | A ``#pragma no_pch``. This is an explicit request not to generate a PCH + file. + +* | A ``#line`` directive. (Such directives could probably be allowed but + are not accommodated at present.) + +When the header stop point is reached, ``generate_precompiled_header`` is +called. It starts by making several checks that the current position is +acceptable: + +* | The current position is not inside a declaration, i.e., it is between + two file-scope declarations, or before the first such declaration, or + after the last. ``next_token_is_top_level_decl_start``, maintained by + the declaration-scanning routines, gives this information. + +* | The preprocessing ``#if`` stack is empty, i.e., the current position is + not inside a conditionally-compiled section. + +* | There have been no errors. + +* | The global variable ``cannot_create_pch_file`` is not set. It is set + for things that preclude generation of a PCH file (e.g., referencing + ``__DATE__``). + +If the current position is acceptable, a precompiled header file can be +written, and the front end will write out a file *xxx*\ ``.pch``, where "*xxx*" +is the base file name of the file being compiled. The user can specify a +different file name via the ``--create_pch`` command-line option. If a file +with the chosen name already exists, it is deleted. Precompiled header +files are written in the current directory by default, but another +directory can be specified via the ``--pch_dir`` command-line option. + +The following information is written to the PCH file, in the order given: + +* | An string that identifies the file as a PCH file, and gives the front + end version number and generation date/time. + +* | The current directory name (this may affect the include file search + order, etc.). + +* | The list of command-line events, i.e., all the command-line options + that could have an effect on PCH files. + +* | The list of preprocessing directive events, i.e., the sequence of + preprocessing directives whose compiled form is encapsulated in the PCH + file. + +* | Timestamps for all the header files referenced by the compilation (this + includes all files, not just those included directly from the primary + source file). + +* | The values of all front end variables registered with + ``register_pch_saved_variables``. + +* | The contents of all memory regions, i.e., the front end memory region + and all IL memory regions. + +* | Once the rest of the information has been written, the front end goes + back to the header and writes a flag indicating that the PCH file is + complete. This flag prevents other compilations from using a PCH file + that is not yet completely written. + +After writing out the PCH file, the front end continues with +compilation. Because the header-stop point has been passed, no further +precompiled-header checking or processing is done in the rest of the +compilation. + +If an IL file is being generated, function scope memory regions that are +completed before the header stop point are held in memory and neither +written to the IL file nor freed. Once the header stop point has been +reached, and a PCH file has been written or a decision made not to write +one, those memory regions are written to the IL file and freed. + +.. _memory-management-issues: + +Memory Management Issues +------------------------ + +As was mentioned earlier, one of the prerequisites for fast PCH processing +is the ability to bring memory regions back into memory at the same +addresses they had when written out. Clearly, that requires that (a) +nothing else happens to have been allocated at the desired addresses, and +(b) there is some way to request allocation or assignment of those +addresses so that no later allocation uses them. + +The front end provides two schemes that accomplish this goal. The first and +better scheme requires memory mapping support from the underlying operating +system (UNIX and Windows NT versions are provided). A fixed set of +addresses is chosen for all memory regions (the exact addresses are either +left to the discretion of the operating system or chosen in the +configuration of the front end; see +``USE_FIXED_ADDRESS_FOR_MMAP``). Initially, these memory addresses are +mapped onto a temporary file. When a PCH file is created, the memory is +written to the PCH file (using normal file I/O). On restoration of a PCH +file, the default mapping to the temporary file is released, and the +reserved memory addresses are mapped onto the PCH file being restored. This +brings the saved information into the front end's address space without any +immediate I/O. (In the actual implementation, the memory addresses are +tentatively mapped once to verify that the mapping can be done, and then, +once it is known that all the mappings will be successful, they are done +again with the official mappings.) All dynamically allocated memory that is +not part of a memory region is just allocated in the normal way through +``malloc``, since it need not be at any particular addresses. This means, +in effect, that there are two completely separate pools of memory -- memory +region allocations are done at the fixed mappable addresses, and everything +else is done more casually in the traditional way. + +The other implementation does not require memory mapping, but it is +slightly less friendly to users. Very early in the execution of the front +end a large amount of memory is preallocated in large blocks and saved off +to the side for use exclusively for memory regions. This is done early so +that the allocated addresses are reproducible (i.e., one can get the same +addresses on all compilations). If the allocations were done later, their +addresses would be affected by minor variations in the amount of memory +used during the command-line processing, and perhaps by memory allocated by +runtime routines of the host C compiler (e.g., ``printf`` formatting). As +the compilation proceeds, requests for memory for memory region blocks are +satisfied by taking blocks from this preallocated list. All other +allocations (for things not in memory regions) are done directly through +``malloc``. When a PCH file is created, the memory addresses of blocks are +written to the PCH file along with the block contents. Also written is an +array of the preallocated memory block addresses used, serving as a sort of +allocation history (this array is written to the file also in the +memory-mapped mode). Once the header stop point is passed, and either a PCH +file was written or a decision was made not to write one, the remaining +preallocated memory is freed, and subsequent allocation for all purposes is +done directly through ``malloc``. + +If the preallocated space is too small to hold the memory regions created +up to the header stop point, the precompiled header cannot be created +(since the remaining required space cannot be allocated at predictable +addresses). A warning is issued, telling the programmer that the +``--pch_mem`` option can be used (on a subsequent invocation of the front +end) to request a larger preallocation to avoid the problem. The +compilation continues normally -- the PCH file cannot be created, but the +compilation can be completed regardless. + +Since the preallocated blocks have a fixed (though large) size, any +requirement to allocate a single entity larger than that fixed size cannot +be satisfied from the preallocated pool, and therefore precludes generation +of a PCH file. This could happen, for example, if a user program contains a +single literal string containing 200,000 characters. Again, the compilation +continues without difficulty, but a warning is issued that a PCH file could +not be generated. + +When a PCH file is read back in the non-memory-mapped mode, the allocation +history information history is read in from the PCH file and used to check that +the preallocated blocks are indeed at the same addresses (on some systems, in +spite of the care taken to allocate the blocks early, the addresses still +change; for example, under MS-DOS, the addresses can be affected by placing a +new TSR program in memory). If the addresses are not right, it is still +possible to give up on using the PCH file and continue with normal compilation. +If the history information matches, the memory regions are read in: The address +for each block is read from the file, the preallocated block at the right +address is assigned, and the memory region contents are read from the PCH file +into the proper addresses. + +It should be noted that if a given environment provides a (nonstandard) way +of allocating memory from a pool distinct from the normal ``malloc`` +allocation pool, the non-memory-mapped approach can be made to work without +preallocation and without the ``--pch_mem`` command-line option. + +When multiple source files are specified in one invocation of the front +end, the preallocation scheme breaks down: The first file can be processed +okay, but on subsequent files the preallocated memory has been used and +reclaimed and is no longer in quite the right predictable state. This can +probably be solved in some way, but the current implementation takes the +easy way out and disallows PCH file use on compilations where more than one +source file is specified on the command line. + +.. _predefined-macro-defs: + +Predefined Macro Definition File +================================ + +Macros may be predefined either by explicit calls of +``enter_predef_macro``, and/or through use of a predefined macro definition +file. Whether or not the front end reads a predefined macro definition file +is controlled by the ``DEFAULT_USE_PREDEFINED_MACRO_FILE`` macro. The file +``EDG_BASE/EDG_AUXILIARY_INFO_DIR_NAME/PREDEFINED_MACRO_FILE_NAME`` is read +to provide the macro definitions. The ``EDG_BASE`` directory can be +specified by an environment variable (``EDG_BASE``), build-time macro +(``DEFAULT_EDG_BASE``), or command-line option +(``--edg_base_dir``). ``EDG_AUXILIARY_INFO_DIR_NAME`` and +``PREDEFINED_MACRO_FILE_NAME`` are configuration macros with default values +of "``lib``" and "``predefined_macros.txt``". If +``EDG_AUXILIARY_INFO_DIR_NAME`` is null, the ``EDG_BASE`` directory is used +directly. The format of the entries in the file is: + +.. code:: text + + mode,!mode,mode cannot_redefine macro_name macro_value + +* | ``mode`` is a label from the predefined macro modes table. The macro is + defined if the mode is set, or if the mode is not set when ``!mode`` is + used. The macro is defined if any of the mode tests is TRUE. The set of + mode values is specified in ``host_envir.h``. + +* | ``cannot_redefine`` indicates whether the predefined macro may later be + redefined. The value must be "yes" or "no". + +* | ``macro_name`` is the name of the macro to be defined. + +* | ``macro_value`` is the value to which the macro should be defined. All + of the characters until the end of the line are used as the macro + value. + +For example: + +.. code:: text + + gcc no __HAVE_BUILTIN_SETJMP__ 1 + gpp no __CHAR_BIT__ 8 + gnu no __GNUC_PATCHLEVEL__ 0 + gnu no __WINT_TYPE__ unsigned int + gnu,microsoft __IS_GNU_OR_MICROSOFT_MODE 1 + +A script (``make_predefined_macro_file``) is provided that automatically +generates the ``predefined_macros.txt`` file for a given version of gcc/g++ +or clang. It does this by invoking gcc and g++ or clang and capturing the +predefined macro information. diff --git a/dev/doc/_sources/build.rst.txt b/dev/doc/_sources/build.rst.txt new file mode 100644 index 0000000..c7ca954 --- /dev/null +++ b/dev/doc/_sources/build.rst.txt @@ -0,0 +1,949 @@ +========================================== +Configuring and Building the C++ Front End +========================================== + + + +This chapter is an introduction to configuring and building the front end and +the various tools that come with it. Bringing up the front end on a new +platform typically can be done in a few hours, and if the platform is close +enough to a system for which sample configurations are available (e.g., Linux, +Windows, etc.) that initial process can be reduced to a matter of minutes. + +The front end can be configured for a variety of uses. For example, it could +be part of a compiler with a custom code generator, or a compiler with a +portable C-generating back end (the latter is provided). Alternatively, it +could be part of a source analysis tool (without a code generator) or of a +source transformation/translation tool (using the supplied C/C++-generating +back end). Some of the tools supplied with the front end will not be needed +for some of these applications. For example, a source analysis tool is +unlikely to need the supplied prelinker tool to perform automatic +instantiations. The details of the build process are therefore likely going to +depend on the application. However, the overall structure of the source code +is simple enough that customizing the build process should be straightforward. + +The source code implementing the front end and associated tools is written in +C++11 (i.e., ISO/IEC 14882:2011) and can be compiled using relatively current +C++ compilers. The front end has been compiled with g++ 4.8.1, clang 3.3, and +Microsoft Visual Studio 2015 (build 19.00.24215.1). The front end does not +explicitly throw or catch exceptions and does not use C++ features that would +requite runtime type information (RTTI), so those features can be disabled when +compiling the front end (for compilers that support that). (The sample +run-time support library is written in C++ and (if needed) is normally compiled +using the front end itself. When building on Microsoft Windows, a component is +also available to read metadata in C++/CLI mode: This is written in C++ for the +Microsoft C++ compiler.) + +Directories and Files in a Release +================================== + +After unpacking a release, its top-level directory should contain the following +directories and files: + +.. list-table:: + + * - | ``Makefile`` + - | In a Unix-like environment (including Windows-hosted environments like + Cygwin or MinGW), the ``make`` utility can be used to build the front + end and its supporting tools and components. This top-level + ``Makefile`` runs the ``make`` tool in the various subdirectories as + needed. It is geared primarily toward building a compiler using the + C-generating back end along with the sample run-time support library. + A ``make`` process using this top-level ``Makefile`` may therefore + terminate with errors for other situations; in that case, the + ``Makefile``\ s in the appropriate subdirectories (especially + ``misc/`` and ``src/``) are still likely to be useful. + * - | ``src/`` + - | The directory containing the source files of the C++ front end and + its optional components (such as the C- and C++-generating back + ends). In addition to source code, the ``src/`` directory also + holds the ``Changes`` file, which describes the various changes + made to the front end in the current and previous releases. Note + that most of the source files have the ``.c`` suffix that would + normally indicate a C source file. Starting with the 6.0 release, + these files contain C++ source code and must be compiled using a + C++ compiler (with the C++14 dialect). The original filenames + have been maintained to make patching files easier. If desired, + symbolic links can be added to accommodate build environments as + necessary. + * - | ``bin/`` + - | Initially, this directory contains a script ``eccp`` that can be used + to run the front end much like typical C++ compilers in Unix-like + environments (such as ``CC`` and ``g++``). See + ":ref:`the-eccp-script`" for details. Once the front end is built (in + the ``src/`` directory), it can be moved here for invocation by + ``eccp`` (this is done automatically if the top-level ``Makefile`` is + used). + * - | ``sample_edg_eccp_config/`` + - | The ``eccp`` script can be configured in various ways. This directory + contains sample configuration files for some popular Unix-like + operating systems (Linux, MacOS X, and Solaris). It also includes a + script ``make_g++_incl_paths`` (to be run from the ``lib/`` directory) + to establish the location of ``g++``\ 's header files (in cases where + ``eccp`` should rely on a native ``g++`` installation for system and + standard header files). + * - | ``include/`` + - | This directory contains prototype implementations for a few standard + C++ header files that are closely tied to the compiler's internals. + (For example, the contents of the ```` header must match the + compiler's understanding of the ``std::type_info`` type.) + * - | ``lib_src/`` + - | This directory contains C++ source code implementing a minimal C++ + run-time support library (in support of C++ features like exception + handling, the ``dynamic_cast`` operator, and ``operator new``). The + library also includes support for certain extensions to the C89 + language (like operations on complex floating-point types and support + for variable-length arrays). All of this code is primarily meant for + demonstration purposes, and is probably not suitable for end-user + products: It is very portable, but not very efficient. It is usually + not needed for non-compiler applications such as source analysis or + source-to-source translation. This directory also contains a + ``Changes`` file describing the history of the run-time support + library. + * - | ``lib/`` + - | Initially, this directory only contains a file + ``predefined_macros.txt``. This file is read by the front end to + predefine certain macros. It is typically used to define macros + that are defined by compilers being emulated (see + ``make_predef_macro_table`` and ``make_win_predef_macro_table.c`` + for utilities that automatically generate a set of predefined + macros for GNU and clang and Microsoft compilers, respectively). + Once the run-time support library is built (in the ``lib_src/`` + directory), it can be moved here so the ``eccp`` script can find + it (this is done automatically if the top-level ``Makefile`` is + used). Note that this directory is only used when an unnamed + "legacy" target configuration is specified -- see ``lib_``\ + *target*\ ``/`` below for cases where a named target configuration + is used. + * - | ``lib_``\ *target*\ ``/`` + - | Target-specific version of the ``lib/`` directory described above + used when the "``--target`` *target*" command-line option is + specified. This directory can have the same + ``predefined_macros.txt`` and ``libC.a`` files as ``lib/``, or can + be different as required by the specific target. If a + target-specific version of ``libC.a`` is required, it must be + built manually (see ``lib_src/Makefile``). + * - | ``misc/`` + - This directory contains sources for four utility programs (and a + ``Makefile`` to build them) to build and configure the front end: + + * ``make_predef_macro_table``: A script to generate a predefined + macros file (like ``lib/predefined_macros.txt``) to match given + versions of ``gcc/g++`` and ``clang``. + * ``make_win_predef_macro_table.c``: A program to generate a + predefined macros file (like ``lib/predefined_macros.txt``) to match + a given version of Microsoft Visual Studio. Note that this program + is not built by the ``Makefile`` (and must be built manually if + required). + * ``mk_errinfo.c``: A program to translate the files describing the + diagnostics emitted by the front end to plain C++ code. + * ``dettarg.c``: A utility to determine basic configuration settings for + a target platform (e.g., the size and alignment of various integer + types). See ":ref:`the-detarg-utility`" below. + * - | ``util/`` + - This directory contains sources for three utility programs (and a + ``Makefile`` to build them) that can be used in conjunction with the + front end (e.g., by the ``eccp`` script): + + * ``edg_prelink.c``: A program that implements automatic template + instantiation by re-running the front end to generate missing + instantiations. + * ``edg_decode.c``: A name demangler (which can, for example, be used on + the output of a linker to make that output more readable). It is + an interface for the actual demangling logic, which is contained + in ``decode.c`` to allow its use in other programs as well. + * ``edg_munch.c``: A utility that generates a C program that will call + all required start-up initialization routines. This is needed only + if your linker does not provide a way to invoke code automatically at + program start-up time. + * - | ``doc/`` + - | This directory contains a PDF version of this document (``plm.pdf``). + * - | ``README`` + - | A plain text file summarizing some of the information in this chapter. + +Configuring the Front End +========================= + +A large number of behaviors of the front end can be configured by appropriately +defining various configuration macros. These macros can affect which +components of the front end are enabled, which dialects are supported, what +host and target platform characteristics are assumed, and so forth. See +:ref:`macro-defaults` below for information about where all the macros are +documented. + +Beginning with version 4.10.1 of the front end, a facility to provide for +run-time selection of a target configuration (through the use of the +``--target`` command-line option) is provided. To support this run-time +target-configuration feature, a number of the configuration macros have +been designated as "target-specific". See +:ref:`target-specific-configuration` for more information. + +The ``defines.h`` File +---------------------- + +It is highly recommended that the front end be configured by defining the +appropriate macros in the ``src/defines.h`` file. Occasionally, it may be +expedient to set the macros directly through ``src/Makefile`` or a similar +build-system mechanism (e.g., to enable debugging facilities), but modifying +other front end sources to set the configuration macros is not a recommended +option. + +Sample configuration files are provided in the ``src/`` directory for Linux, +MacOS X, Solaris, and Windows (``defines.h.linux``, ``defines.h.macosx``, +``defines.h.solaris``, and ``defines.h.win32``, respectively). These are +recommended starting points when building the front end on these platforms: For +example, to build the front end on MacOS X, one can start by copying +``src/defines.h.macosx`` to ``src/defines.h``. + +A partial configuration file ``src/defines.h.proto`` is also provided: It +contains the macros needed to enable the modern IA-64 ABI (also called the +Itanium ABI), but it must be complemented by additional target characteristics +(which can be obtained by running the ``dettarg`` utility described next). + +.. _the-detarg-utility: + +The ``dettarg`` Utility +----------------------- + +File ``misc/dettarg.c`` is a simple C++ program that can be compiled, linked, +and run on a system for which the compiler is targeted to determine some basic +characteristics (like endianness, size and alignment of fundamental types, and +so forth) of that target platform. The output produced by ``dettarg`` is in a +form suitable for addition to the ``src/defines.h`` file. + +.. _macro-defaults: + +``lang_feat.h``, ``host_envir.h``, ``targ_def.h``, and ``target.h`` +------------------------------------------------------------------- + +A typical ``src/defines.h`` file will not explicitly set all the configuration +macros available in the front end. Instead, most macros are just left to their +default values. These defaults are specified in four header files. Perhaps +more importantly, these header files are also the place where all the +configuration macros are documented (in comments preceding the directives +determining the default values). The header files are as follows: + +.. list-table:: + + * - | ``src/lang_feat.h`` + - | Configuration macros controlling language features. Some macros + control a single language feature detail, whereas others control whole + dialects. + * - | ``src/host_envir.h`` + - | Configuration macros that determine characteristics of the host + platform (the platform on which the front end runs). + * - | ``src/targ_def.h`` + | ``src/target.h`` + - | Configuration macros describing characteristics of the target platform + (the platform for which code must be generated). Many of these macros + have names that begin with ``TARG_``. Characteristics that are + entirely fixed at the time the front end is built are normally + documented in ``targ_def.h``, whereas ``target.h`` describes target + characteristics that can be overridden for every invocation of the + front end. + +These descriptions are generally correct, but occasionally a configuration +macro may need to be placed in a header that doesn't quite match that macro's +function. For example, ``targ_def.h`` contains some macros that would more +naturally belong to ``lang_feat.h``, but the default value of the macro depends +on a target platform characteristic. + +Note that these files should not be modified to set configuration options. +Instead, the appropriate macros should be defined in ``src/defines.h`` or +perhaps in a ``Makefile`` or similar build system tool. + +``basics.h`` and Build Environment Configuration +------------------------------------------------ + +The front end is written in portable C++11 (except for one file in the +Microsoft dialect if the capability of reading Microsoft metadata for +C++/CLI is needed). The ``basics.h`` header adds abstractions to allow +most of the remainder of the front end source code to be written without +concern for variations in system headers. The build environment type can +often be determined by the preprocessor tests in ``basics.h``, but when +that is not the case, one should define one of the following build +environment macros (on the command-line or in ``src/defines.h``): +``__ANSIC__`` (for ANSI C; also used for Borland and Microsoft C under +MS-DOS and Windows), ``__SYSV__`` (for System V), ``__BSD__`` (for Berkeley +4.n), ``__VMS__`` (for VAX/VMS C; this will cause ``__SYSV__`` to be +defined, but the ``__VMS__`` flag will control some minor variations from +System V). + +Some ANSI library functions do not exist in all system libraries. This problem +is handled by remapping such function calls (via macros) to functions that do +exist. For example, traditional Berkeley UNIX does not have ``memcpy``, but +does have ``bcopy``; the front end source is written using calls to ``memcpy``, +but when it is compiled with the ``__BSD__`` flag set, a macro ``memcpy`` +transforms those calls into calls to ``bcopy``. Another function of the build +environment macros is controlling inclusion of appropriate header files. Even +when identical functions exist on different host systems, they are sometimes +defined by different header files (e.g., Berkeley systems use ```` +instead of the ANSI/System V ````). ``basics.h`` includes the +appropriate definitions for the most common functions (standard I/O, string and +block operations, and character typing); any other required headers are +included only in those source files that need them, with appropriate +conditional compilation surrounding the ``#include``\ s. + +Very occasionally, the macro definitions in ``basics.h`` must be modified +directly (i.e., by editing ``basics.h``). Specifically, when ``__ANSIC__`` is +not set, some ``#define``\ s in ``basics.h`` must establish values for about a +dozen of the most useful values (specifically, ``CHAR_BIT``, ``CHAR_MIN``, +``CHAR_MAX``, ``UCHAR_MAX``, ``SHRT_MAX``, ``INT_MAX``, ``LONG_MAX``, +``LONG_MIN``, and ``ULONG_MAX``). These should be set to proper values for the +host. ``sizeof_t`` should also be defined as the integral type to be used for +sizes of things. Usually this is the same as ``size_t``, but it might be +different if ``size_t`` is too small (e.g., 16 bits). These values cannot be +set in ``defines.h`` or on the compilation command line. + +Finally, ``basics.h`` also determines the default values of some macros that +control the presence of code aiding in the development of the front end (e.g., +``DEBUG`` for debugging aids and ``CHECKING`` for internal consistency checks). + +The front end requires a minimal C++ standard library. Prior to release 6.0, +the front end was written in C and used various host C standard library +functions (e.g., for file I/O). When switching to C++, it was decided not to +use the additional portions of the C++ standard library that became available +(e.g., ``std::string``) as this would add a burden to our customers and would +require testing against many versions of the C++ standard library. Instead, a +small subset of library-like utility functions was developed for the front end +(in ``util.h``). As a result, the portion of a C++ standard library that the +front end requires is about the same as that provided by a C standard library. + +Commonly-used Configuration Macros +---------------------------------- + +The following subsections describe a selection of macros that commonly appear +in ``src/defines.h``. This list is not meant to be exhaustive. Many (but not +all) configuration macros are used to initialize global variables with a +similar name, and it is the value of the variable that controls a particular +behavior. For example, ``GCC_IS_GENERATED_CODE_TARGET`` (described below) +initializes the global variable ``gcc_is_generated_code_target``. This allows +particular behaviors to be controlled at run time (via the command line or via +custom code additions). + +Note that none of the configuration macros described below are +"target-specific" (so, for example, there can't be one target configuration +where ``DO_IL_LOWERING`` is TRUE and another where it is FALSE). + +Optional Components +^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + + * - | ``BACK_END_SHOULD_BE_CALLED`` + - | TRUE if a back end should be called (the call is to a function + ``back_end``). + * - | ``DO_IL_LOWERING`` + - | TRUE if IL lowering (rewriting C++-specific constructs in the + intermediate language in C form) should be done. + * - | ``BACK_END_IS_C_GEN_BE`` + - | TRUE if the C-generating back end should be used. If FALSE, some + other back end must be supplied or ``BACK_END_SHOULD_BE_CALLED`` must + be FALSE. The C-generating back end takes the lowered IL for a + translation unit and generates a C source file suitable for + compilation to binary code by a native C compiler. + * - | ``BACK_END_IS_CP_GEN_BE`` + - | TRUE if the C++/C-generating back end should be used. If FALSE, some + other back end must be supplied or ``BACK_END_SHOULD_BE_CALLED`` must + be FALSE. The C++/C-generating back end is intended for + source-to-source transformation applications. It takes the unlowered + IL for a translation unit and generates a source file that is similar + to the original C or C++ input. + * - | ``MINIMAL_INLINING`` + - | TRUE if minimal inlining of function calls should be done during IL + lowering. This option is intended mostly for use with the + C-generating back end, and is limited to inlining calls to very simple + functions that are defined inline in the source. + +Support for Source Language Dialects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + + * - | ``GNU_EXTENSIONS_ALLOWED`` + | ``DEFAULT_GNU_COMPATIBILITY`` + | + - | Control whether compatibility with GNU's ``gcc`` and ``g++`` compilers + should be enabled, either by default or only when the ``--gcc`` or + ``--g++`` command-line options are specified. + * - | ``MICROSOFT_EXTENSIONS_ALLOWED`` + | ``DEFAULT_MICROSOFT_COMPATIBILITY`` + | + - | Control whether compatibility with Microsoft's C and C++ compilers + should be enabled, either by default or only when the ``--microsoft`` + command-line option is specified. + * - | ``SUN_EXTENSIONS_ALLOWED`` + | ``DEFAULT_SUN_COMPATIBILITY`` + | + - | Control whether compatibility with Sun CC should be enabled, either by + default or only when the ``--sun`` command-line option is specified. + * - | ``DEFAULT_CLANG_COMPATIBILITY`` + | + - | Controls whether compatibility with clang C and C++ should be + enabled by default or only when the ``--clang`` command-line + option is specified. (Clang extensions are mostly identical to GNU + extensions and are controlled by ``GNU_EXTENSIONS_ALLOWED``.) + +Setting an ...\ ``_ALLOWED`` macro to TRUE makes the corresponding +``DEFAULT_``\ ... macro TRUE by default. If the front end is configured to +support multiple dialects, the ``DEFAULT_``\ ... macros must be set explicitly +to avoid selecting more than one dialect as the default. + +.. list-table:: + + * - | ``CPPCLI_ENABLING_POSSIBLE`` + | ``CPPCX_ENABLING_POSSIBLE`` + | + - | Control whether a mode compatible with Microsoft's C++/CLI or + C++/CX extensions should be available through the command-line + options ``--cppcli``/``--cppcx``. Setting either of these options + to TRUE requires that ``MICROSOFT_EXTENSIONS_ALLOWED`` also be + TRUE. + * - | ``DEFAULT_CPPCLI_ENABLED`` + | ``DEFAULT_CPPCX_ENABLED`` + | + - | TRUE if C++/CLI or C++/CX extensions should be enabled by default + when Microsoft extensions are enabled. + +IL Features +^^^^^^^^^^^ + +.. list-table:: + + * - | ``EXTRA_SOURCE_POSITIONS_IN_IL`` + | + - | TRUE if certain additional IL entries, besides those that already have + ``a_source_correspondence`` fields, should contain source position + information. For example, expression nodes will record the starting + and ending position of the corresponding expression, as well as the + position of that expression's top-level operator. Note that this can + increase the size of the IL substantially. + * - | ``EXPR_RANGE_MODIFIERS_IN_IL`` + | + - | TRUE to extend the tracking of source ranges for expressions by + including position information for operators that generally do not + appear in the IL, such as ``*``, ``&``, and ``()``. + * - | ``RECORD_MACROS_IN_IL`` + | ``RECORD_MACRO_INVOCATIONS`` + | ``RECORD_MACRO_ARGS`` + | ``FULLY_RESOLVED_MACRO_POSITIONS`` + | ``MACRO_INVOCATION_TREE_IN_IL`` + | + - | Indicate whether extra information should be recorded in the IL + describing macros and their expansions. Setting + ``RECORD_MACRO_ARGS`` to TRUE requires that + ``RECORD_MACRO_INVOCATIONS`` be set to TRUE. Setting either of + the latter two configuration macros to TRUE can increase the size + of the IL substantially. + * - | ``ALL_TEMPLATE_INFO_IN_IL`` + | + - | TRUE if prototype template instantiations (i.e., the parsed generic + form of templates) should be recorded in the main IL tree. + +Target Platform Options +^^^^^^^^^^^^^^^^^^^^^^^ + +Note that although these configuration macros deal with issues related to the +target, they are not considered "target-specific" (because these values cannot +differ between target configurations). + +.. list-table:: + + * - | ``IA64_ABI`` + - | Controls whether the IA-64 ABI standard is used for code + generation and object layout. This is a "modern" C++ object + layout (unlike the cfront layout), and is a good starting point + even on architectures other than IA-64 (Itanium). This ABI is + used by many versions of g++ (3.2 and later) and clang. For a + complete specification, see + https://itanium-cxx-abi.github.io/cxx-abi/. See also other macro + names beginning with ``IA64_ABI``, some of which enable compatibility + with the ARM EABI variant of the ``IA64_ABI``. If ``IA64_ABI`` is + set to FALSE (or 0), a cfront-like ABI is used instead. + * - | ``DEFAULT_GNU_ABI_VERSION`` + | ``DEFAULT_EMULATE_GNU_ABI_BUGS`` + | + - | Control the emulation of the GNU variant of the IA-64 ABI. + * - | ``GCC_IS_GENERATED_CODE_TARGET`` + | ``GNU_TARGET_VERSION_NUMBER`` + | ``MSVC_IS_GENERATED_CODE_TARGET`` + | ``MSVC_TARGET_VERSION_NUMBER`` + | ``SUN_IS_GENERATED_CODE_TARGET`` + | ``SUN_TARGET_VERSION_NUMBER`` + | ``CLANG_IS_GENERATED_CODE_TARGET`` + | ``CLANG_TARGET_VERSION_NUMBER`` + | + - | Control whether the code generated by the C- or C++-generating + back end should target a specific GNU, Microsoft, Sun, or clang + compiler. This is information is used to avoid limitations of + those compilers and to exploit extensions they provide. + * - | ``CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT`` + | + - | TRUE if the C++-generating back end should generate code that matches + the dialect selected for the front end. (E.g., if the front end is + set to parse GNU code, the back end can generate GNU ``__attribute`` + constructs, whereas if the front end is set to accept Microsoft + extensions, the back end might generate ``__declspec`` specifiers.) + +Front End Behaviors +^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + + * - | ``MAKE_FRONT_END_CALLABLE`` + | + - | TRUE if, instead of having its own main program, the front end is to + be linked as part of some other main program. When this flag is set, + the ``EDG_MAIN`` macro provides the name of the main entry point into + the front end.The front end can then be called repeatedly by the same + process (each call reinitializes the front end's internal state). + * - | ``COMPILE_MULTIPLE_SOURCE_FILES`` + | + - | Indicates that the front end should be capable of compiling a list of + source files in a single invocation. + * - | ``IL_SHOULD_BE_WRITTEN_TO_FILE`` + | + - | TRUE if the intermediate language should be written to a file; FALSE + if the intermediate language is passed in memory to the back end + (assuming ``BACK_END_SHOULD_BE_CALLED`` is TRUE). + * - | ``USING_DRIVER`` + - | Indicates that the front end is being run from a driver program. + Setting this flag suppresses termination messages (like + "``Compilation terminated.``") written to the error output file + because it is expected that the driver will write those. + * - | ``MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED`` + | + - | TRUE if multibyte character sequences (e.g., like Unicode UTF-8 or + those in the Japanese SJIS encoding) are supported in comments, + string literals, identifiers, and character constants. + * - | ``USE_OWN_SJIS_MULTIBYTE_CHAR_PROCESSING`` + | + - | TRUE if, instead of the routines in the standard C library (e.g., + ``mblen``), custom routines in ``host_envir.c`` should be used to deal + with Japanese SJIS multibyte characters in source code. + * - | ``LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED`` + | + - | Indicates the locale to be established by a call to ``setlocale`` to + get the desired processing of multibyte characters from the C library + while reading the source code. + * - | ``UNICODE_SOURCE_SUPPORTED`` + | + - | TRUE if the character set to be supported is Unicode. When + ``MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED`` is TRUE, source files + encoded as UTF-8 and UTF-16 are accepted, depending on the + ``--unicode_source_kind`` command-line option, + ``DEFAULT_UNICODE_SOURCE_KIND`` configuration macro, or Byte Order + Mark (BOM), and UTF-16 is translated to UTF-8 immediately on + input. When ``MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED`` is FALSE, the + source file is assumed to be encoded as ISO/IEC 8859-1 (Latin-1). + +Development Aids +^^^^^^^^^^^^^^^^ + +.. list-table:: + + * - | ``DEBUG`` + - | Enables additional code in the front end to simplify debugging. This + includes flow/event tracing options, routines that can be called from + a debugger to examine the IL, and an option to output the settings of + the configuration macros. + * - | ``CHECKING`` + - | Enables inexpensive internal consistency checking. Recommended even + in production builds. + * - | ``EXPENSIVE_CHECKING`` + - | Enables more expensive internal consistency checking. (Not generally + recommended for production builds.) + * - | ``WRITE_CPPCLI_PORTABLE_ASSEMBLIES`` + | + - | When TRUE, this enables an internal command-line option + "``--set_flag generate_portable_assemblies``" that causes a front + end built with support for C++/CLI (for Microsoft Windows) to + write out all assemblies used in the compilation (likely including + ``mscorlib.dll``) in the current directory in a format that is + readable on non-Windows platforms (i.e., with a front end not + built with ``EDG_WIN32`` set to TRUE). Since the assemblies are + written in the current directory with their original file name + (e.g., "``mscorlib.dll``"), care should be taken that no required + assemblies are in the current directory when the front end is + invoked in this way. + +.. _target-specific-configuration: + +Target-Specific Configuration +----------------------------- + +A target configuration is defined by giving appropriate values to a set of +configuration macros (dubbed the target-specific configuration macros). +Multiple target configurations can be specified when the front end is built; +the ``--target`` command-line option is used to select a non-default target +configuration when the front end is invoked. The ``--dump_legacy_as_target`` +command-line option can be used to display the set of target-configuration +macros. + +Each target-specific configuration macro has a "legacy" version, i.e., one +without any target-specific suffix, as well as a version for each target +configuration that is specified when the front end is built. Non-legacy +configuration macro names are formed by appending an underscore and the target +configuration name to the legacy configuration macro name. For example, the +legacy macro ``TARG_LITTLE_ENDIAN`` would have a corresponding +``TARG_LITTLE_ENDIAN_win32`` configuration macro for the ``win32`` target +configuration. + +By default, the legacy configuration has no name, but one may be specified by +setting ``LEGACY_TARGET_CONFIGUATION_NAME`` to the desired name. The default +target configuration can be specified by giving its name as the definition of +the ``DEFAULT_TARGET_CONFIGURATION_NAME`` configuration macro; otherwise, the +legacy target configuration will be used as the default. + +Note that specifying a named target configuration (either explicitly or through +defaults) requires that an ``$EDG_BASE/lib_``\ *target*\ ``/`` directory be +present at run time. Having target-specific ``$EDG_BASE/lib_``\ *target*\ +``/`` directories allows each target configuration to have different predefined +macros (e.g., to define ``_M_IX86`` in one and ``_M_X64`` in another). + +A legacy configuration can be configured manually (by specifying values for +each target-specific macro), or automatically (by using the ``dettarg`` tool +and defaults that many configuration macros have). The +``--dump_configuration`` command-line option provides a convenient display of +all configuration macros and their settings. + +By default, the ``--version`` and ``--dump_configuration`` output (and the +string that identifies precompiled header files) includes the date and time the +front end was built, so no two builds produce identical executables. Defining +the configuration macro ``BUILD_IDENTIFIER`` as a string literal (with CMake, +``-DEDG_BUILD_IDENTIFIER=``\ *string*) replaces the date and time with that +string, making the build reproducible. Builds of different sources should use +different identifiers so their precompiled headers aren't mistaken for each +other. + +A non-legacy target configuration is most easily generated as a derivative from +an existing legacy target configuration using the ``--dump_legacy_as_target`` +command-line option. This option takes a target configuration name and +generates a list of the target-specific macro names for the given target +configuration name along with the values of the legacy configuration. This +file (after verifying that ``TARGET_CONFIGURATION_``\ *number* is unique) can +then be included in ``defines.h`` as the basis for a new target configuration. +Additional target configurations can be generated from different legacy +configurations in the same manner, or by using an existing target configuration +as a template (and changing the target configuration name in each macro, along +with the ``TARGET_CONFIGURATION_``\ *number*). Note that all target-specific +configurations must share the same non-target-specific configuration, so for +instance, it's not possible to have an IA-64 ABI target configuration and a +Cfront target configuration in the same front end configuration (because +``IA64_ABI`` is not a target-specific configuration macro and must have the +same value across all target configurations). + +Note that it is inadvisable to use a target-specific global variable as the +value for a target-specific configuration macro. For example: + + ``#define TARG_IA64_VTABLE_ENTRY_INT_KIND targ_ptrdiff_t_int_kind`` + +is subject to race conditions (because ``targ_ptrdiff_t_int_kind`` may or may +not have been initialized before its value is used to set +``targ_ia64_vtable_entry_int_kind``). The following will work as expected: + + ``#define TARG_IA64_VTABLE_ENTRY_INT_KIND TARG_PTRDIFF_T_INT_KIND`` + +An important aspect of this architecture is that each legacy configuration +macro has an associated global variable whose value is set at initialization +time to the value of the (legacy or per-target) configuration macro for the +selected target. Because of this, it is imperative that user modifications to +the front end use the run-time value of global variables rather than the +compile-time values of legacy configuration macros. + +Replaceable Code +---------------- + +Occasionally, some customizations are needed that cannot simply be expressed +through configuration macros. Those may require instead that various routines +be replaced with custom code. The following files in ``src/`` are written with +such modifications in mind: + +.. list-table:: + + * - | ``fixed_pt.c`` + - | Routines implementing operations on fixed-point values (only supported + in some configurations). + * - | ``float_pt.c`` + - | Routines implementing operations on floating-point values. + * - | ``host_envir.c`` + - | Includes routines dealing with operations on files and directories. + Signal handlers can also be set up there. + * - | ``sys_predef.c`` + - | Routines to predefine platform-specific entities (macros, types, + routines, etc.) + +Building the Front End +====================== + +Using the Top-Level Makefile +---------------------------- + +Assuming a Unix-like environment, a complete demonstration compiler can be +configured and built using a sequence of shell commands like the one shown +below (for a typical Linux platform, but other Unix-like environments are +similar). The sequence assumes that the current directory is the top-level +directory of a freshly unpacked release. + +.. code:: bash + + cp sample_edg_eccp_config/edg_eccp_config.linux edg_eccp_config + cp src/defines.h.linux src/defines.h + cd lib + ../sample_edg_eccp_config/make_g++_incl_paths + ../misc/make_predef_macro_table + cd .. + export EDG_BASE=`pwd` # or setenv EDG_BASE `pwd` + make + +This builds a front end with a C-generating back end, along with a run-time +support library and helper tools such as the prelinker and demangler. The +entire toolset can be driven with the ``eccp`` script (see +":ref:`the-eccp-script`"). + +Building the Front End Only +--------------------------- + +In an environment with a Unix-like ``make`` utility, the front end can be +compiled and linked by running + +.. code:: bash + + make edgcpfe + +in the ``src/`` directory (after constructing an appropriate ``defines.h`` file +and editing ``src/Makefile`` to select the desired compiler and compiler +options for building the front end). This can be useful to update the front +end for modifications after building the complete tool set, or when only the +front end program itself is desired. If ``make`` is not available, the front +end can be built using the following manual steps. + +* | Configure the ``defines.h`` file. For example, under Windows the following + is a useful starting point: + + .. code:: powershell + + copy src\defines.h.win32 src\defines.h + +* | In the ``misc/`` directory, compile and link the ``mk_errinfo`` program + into a ``mk_errinfo`` executable file. For example, using a Windows + command line and the Microsoft C++ compiler: + + .. code:: powershell + + cd misc + cl /TP /I..\src mk_errinfo.c + cd .. + + | See :ref:`mk-errinfo` for additional information about ``mk_errinfo`` and + the format of its input files. +* | In the ``src/`` directory, translate the diagnostic messages using the + ``mk_errinfo`` program that was built in the previous step. For example, + using a Windows command line + + .. code:: powershell + + cd src + ..\misc\mk_errinfo error_msg.txt error_tag.txt err_codes.h err_data.h + +* | Still in the ``src/`` directory, compile and link all the ``.c`` and + ``.cpp`` files. For example: + + .. code:: powershell + + cl /TP /EHsc /Feedgcpfe.exe *.c *.cpp /link mscoree.lib oleaut32.lib + +Building Support for C++/CLI and C++/CX Modes +--------------------------------------------- + +C++/CLI is a Microsoft extension to C++ that simplifies writing C++-like +programs for Microsoft's ".NET" environment. It is formally specified by the +ECMA standard ECMA-372. The front end can support this extension, provided it +is built on a sufficiently recent Microsoft Windows platform with a compiler +that is sufficiently compatible with Microsoft's "Visual C++" compiler. This +support is currently limited to producing high-level IL. The C++-generating +back end can consume this IL (and render the C++/CLI constructs it describes), +but lowering and the C-generating back end are not available in C++/CLI mode. + +C++/CX is a Microsoft extension to C++ similar to C++/CLI, but it targets the +"Windows Runtime" (WinRT) platform instead of the ".NET" environment. Unlike +C++/CLI, there is no formal document specifying this extension. The front end +can also support C++/CX, with the same caveats as those mentioned for C++/CLI +support (in particular, IL lowering is not available for C++/CX mode). + +To include support for C++/CLI and/or C++/CX the configuration macros +``CPPCLI_ENABLING_POSSIBLE`` and/or ``CPPCX_ENABLING_POSSIBLE`` +(respectively) must be set to TRUE. (The macros +``MICROSOFT_EXTENSIONS_ALLOWED`` and ``EDG_WIN32`` must also be TRUE when +building such configurations.) In addition to compiling the C++ files +constituting the front end proper (as explained above), support for C++/CLI +and/or C++/CX requires that the C++ source file ``ms_metadata.cpp`` be +compiled and the resulting object file must be added to the set of files +linked into the final front end executable (or library). The system +libraries ``mscoree.lib`` and ``oleaut32.lib`` are then also required in +the final executable. + +Compiling ``ms_metadata.cpp`` requires Visual C++ 2012 or later (or a C++ +compiler and libraries that are sufficiently compatible with that). The free +"Express" version of Visual C++ is not sufficient because it doesn't include +the ATLMFC library, which ``ms_metadata.cpp`` depends on. + +Building and Using the IL Display Program +----------------------------------------- + +For educational and debugging purposes, the front end comes with a utility +named ``edgcpdisp`` that reads a file containing the IL produced when the front +end compiles one or more source files and displays it in a human-readable form. +(In order to use this facility, of course, the front end must be configured to +write an IL file, i.e., ``IL_SHOULD_BE_WRITTEN_TO_FILE`` must be set to TRUE in +``defines.h`` or in ``src/Makefile``.) + +Because the IL file written by the front end is essentially a binary dump of +the IL data structures, it is necessary for the front end and ``edgcpdisp`` to +be built on the same platform and using the same configuration options. (Many +of the IL data structures contain fields that are present only in certain +configurations.) + +In an environment with a Unix-like ``make`` utility, ``edgcpdisp`` is +automatically built (with a configuration that correctly matches that of +the front end) when ``make`` is run for the default target in either the +top-level or ``src/``\ directory. It can also be built separately in the +``src/`` directory by specifying ``edgcpdisp`` as the target. + +If ``make`` is not available, ``edgcpdisp`` can be built after the front end is +built (as described in the preceding section) in the ``src/``\ directory by +compiling a subset of the source files with ``STANDALONE_IL_DISPLAY`` set to +TRUE. For example, on a Windows platform using the Microsoft C++ compiler, the +command would be (all on one line): + +.. code:: powershell + + cl /TP /Feedgcpdisp.exe -DSTANDALONE_IL_DISPLAY const_ints.c debug.c \ + error.c fixed_pt.c float_pt.c host_envir.c il.c il_display.c il_read.c \ + il_to_str.c il_walk.c mem_manage.c target.c types.c fe_init.c + +Displaying the IL for a source file ``x.cpp`` can be accomplished with the +following commands: + +.. code:: bash + + edgcpfe --output x.cil x.cpp + edgcpdisp x.cil + +(In configurations that do IL lowering, ``x.cil`` will contain the lowered IL. +To view the unlowered IL, see the ``--no_il_lowering`` front-end command-line +option described in the next chapter.) + +The format of the output is partially controlled by the configuration macro +``ALTERNATIVE_IL_FILE_FORMAT``. When that macro is set to TRUE, each entry +is given a unique numeric identifier, resulting in output like the +following: + +.. code:: text + + ... + file-scope type#6 + source_corresp: + name: file-scope id-name#17: "type_info" + ... + +When ``ALTERNATIVE_IL_FILE_FORMAT`` is FALSE, the entries are +distinguished by a hexadecimal representation of the entry's address: + +.. code:: text + + ... + file-scope type@a0013ee68 + source_corresp: + name: file-scope id-name@a0013f050: "type_info" + ... + +It is not necessary to use the ``edgcpdisp`` to get a human-readable +display of the IL. When it is built with the configuration macro +``NEED_IL_DISPLAY`` set to TRUE, the front end will put out the IL display +on ``stdout`` (using the hexadecimal-address format) when the +``--il_display`` command-line option is specified. (The IL need not be +written to a file in this case.) + +Driving the Front End +===================== + +For many applications, it is useful to invoke the front end through another +"driver" program. One such driver is the ``bin/eccp`` script that is part of +every release. Another is the ``edgcc`` program that can be downloaded +separately from the EDG download site. + +.. _the-eccp-script: + +The ``eccp`` script +------------------- + +The ``bin/`` directory contains a (Bourne) shell script ``eccp`` that +allows the front end to be used much like most Unix-hosted compilers. It +invokes the front end -- which must be configured with the C-generating back +end -- with various default options, and then compiles any generated C files +through a "native" C compiler (e.g., the GNU ``gcc`` compiler) and a native +linker. The script accepts Unix-like compiler options (such as ``-c``, +``-o``, ``-O``, ``-g``, ``-I``, ``-L``, and ``-l``) and also passes through +most of the options handled by the front end proper (see :ref:`cli`). + +The script can be moved anywhere, but it normally looks for various components +(the front end, the prelinker, etc.) under a directory designated by the +environment variable ``EDG_BASE``. The ``eccp`` script can be edited to set a +default substitute value for the ``EDG_BASE`` variable. Normally, the value of +``EDG_BASE`` is the top level directory of a fully-built release tree (although +the ``src/`` and ``lib_src/`` directories are not used by ``eccp``). ``eccp`` +will start by setting various environment variables by executing a script +``$EDG_BASE/edg_eccp_config``. Sample scripts for various platforms are +provided in the ``sample_edg_eccp_config/`` directory. Two environment +variables commonly customized in the ``edg_eccp_config`` script are +``EDG_DEFAULT_DEFINES`` (to add options like ``-D__unix__``) and +``EDG_C_TO_OBJ_COMPILER`` (to establish which "native" compiler to use; e.g., +``gcc``). + +``eccp`` may also invoke the prelinker (``util/edg_prelink``) to automatically +instantiate templates (and, with some front end configurations, inline +functions that need an out-of-line copy). See +:ref:`template-auto-instantiation` for notes on this process. The script will +also run ``util/edg_munch`` if needed, and filter linker errors through +``util/edg_decode``. + +See ":ref:`utility-programs`" for more information on the utility programs +``edg_prelink``, ``edg_munch``, and ``edg_decode`` used by the ``eccp`` script. + +The ``edgcc`` Driver for Windows +-------------------------------- + +A Windows program implementing a subset of ``eccp``\ 's functionality can be +downloaded from the EDG download site. The file to download is +``nt_util.zip``. In addition to source code for the driver program ``edgcc``, +it also contains source code for a Windows-hosted prelinker (``pl_nm``) and +munch-like program (``munch_nm``). + +The plain text file ``src/msinfo.txt`` contains additional notes for +running the front end in the Windows environment. + +Configuring and Building the Run-Time Support Library +===================================================== + +Source code for a sample run-time support library is provided in the +``lib_src/`` directory. This library is meant to be built using the front end +(i.e., a compiler incorporating the EDG front end). The library is useful for +demonstration and debugging purposes. However, it is normally not suitable for +production compilers because it is written in portable C++ that cannot take +advantage of more efficient platform-specific mechanisms (e.g., to implement +exception handling). + +Similarly to the front end, the library can be configured through macro +definitions placed in ``lib_src/defines.h``. Typically, however, few or no +macros need to be defined because the ``--building_runtime`` option to the +front end (used to build this library) causes most or all required macros +to be predeclared. + +The macros that might need manual configuration are documented in +``lib_src/config.h``. + +When using multiple target configurations, a version of the run-time support +library must be built for each target configuration and installed in the +appropriate ``lib_``\ *target*\ ``/`` directory. See ``lib_src/Makefile`` for +directions to build target-specific versions of the library. diff --git a/dev/doc/_sources/c_gen_be.rst.txt b/dev/doc/_sources/c_gen_be.rst.txt new file mode 100644 index 0000000..ded1396 --- /dev/null +++ b/dev/doc/_sources/c_gen_be.rst.txt @@ -0,0 +1,395 @@ +===================== +C-Generating Back End +===================== + +``c_gen_be.c`` contains code to translate the intermediate language to C; +``c_gen_be.h`` contains the associated declarations. This is a fake "back end" +that is useful as a way of testing the front end in the absence of a real back +end, as a portability aid, and as an example of how to traverse the +intermediate code (which may be helpful to those writing back ends). + +Function +======== + +Generated C Code +---------------- + +The C code generated can be either ANSI C or old-style K&R C, depending on the +setting of the configuration flag ``C_GEN_BE_GENERATES_ANSI_C``. + +The output contains ``#line`` directives that relate the generated code back to +the original source lines that generated it. The ``#line`` directives do not +ascend monotonically through the line numbers of the source file; they jump +around as the code generation jumps around. However, since the C-generating +back end tends to process all declarations of entities of one kind in a sweep +through those entities in source order, the output tends to have all the types +in source order, then all the variables in source order, etc. + +Long output lines are broken (between tokens) to avoid unduly stressing C +compilers that must process the generated code. + +Since the generated code is intended to be fed into a C compiler, rather than +read by a human, it is not very readable. The readability can be improved +(slightly) by turning on debugging (e.g., ``-d0`` on the command line); that +will cause the C-generating back end to generate annotation comments and +indentation. Unreferenced entities, which ordinarily are not put out at all, +are generated inside ``#if 0``/``#endif`` delimiters in this mode. + +Transformations +--------------- + +For the most part, what the C-generating back end does is just writing out the +C code that corresponds directly to the IL. Since the IL has the same concepts +and constructs as the C language, the processing is pretty straightforward. +However, there are a few complicating transformations. + +The following transformations on names are done: + +* | Names that match C reserved words, or words that are likely to mean + something to the underlying C compiler (e.g., ``unix``), are given a prefix + of "``__x``". +* | Names with no linkage (e.g., local variables) are given a prefix that is + the source sequence (line) number and column number of the name's + declaration, to make sure they do not conflict with similar names from + elsewhere in the program (e.g., "``i``" is output as "``__28_7_i``"). +* | Unnamed entities are given generated names of the form "``__T``\ *nnnnnn*", + with *nnnnnn* generated from the IL entry address. +* | The "``this``" parameter, passed through from C++, is given the name + "``this``". +* | Function-local and prototype-scope types are given names formed by + concatenating the original name, "``__``", the (mangled) function name, + "``__``", and "``L``\ *nn*", where *nn* is a number identifying the + function, prototype, or block scope scope of which the type is a + member. (Renaming is needed because such types are promoted out of + functions; more on this below.) +* | When generating K&R C, file-scope static variables are given a suffix + formed from the name of the module and the date and time of compilation. + This suffix is needed because initialized file-scope static variables must + be made external to avoid some pcc limitations on declaring static + variables more than once. The suffix helps to ensure that the now-external + name does not conflict with like-named static and external variables from + other compilation units. + +Another set of transformations is necessitated by the fact that IL lowering +generates "C" IL that actually contains some minor extensions. These +"extensions" are things that a real back end would probably take in its stride +(i.e., it wouldn't see these cases as being different than normal cases), but +which must be rewritten if standard C code must be generated: + +* | Dynamic initializations for declarations can appear in mid-block, after + executable statements have appeared. (These are generated as executable + code. Because of this, "``const``" type qualifiers are suppressed on + variables initialized dynamically and on all struct members.) +* | Structs and unions can have no members at all, and aggregate constants used + in initializers can contain empty lists of constants ("``{}``"). (The + struct/union definition will include a dummy field, and the initialization + puts a zero into that field.) +* | Enumerations having no enumerator constants are put out as the + corresponding integral type. +* | The ``eok_bassign`` operator is used to do assignment of arrays (e.g., in + generated copy constructors). (A ``memcpy`` is generated.) +* | Prototyped parameter variables may be unnamed. (A name is generated.) +* | Variables can be indicated to be initialized to zero (the ``initk_zero`` + initialization kind). This is used to differentiate real definitions of + external variables from tentative definitions (a distinction that is hazy + in C), and for local aggregate variables that are partially initialized. + (For static variables, the initialization to zero is preserved in the + generated C; for automatic variables, a ``memset`` is generated.) +* | String literals in C++ are ``const``. IL lowering leaves them ``const``, + even though string literals in C are not ``const``. (This does not require + a transformation in the generated C code: the string literals are put out + as such, and the C compiler sees them as non-``const``, which works out + okay.) + +When generating K&R C, some transformations are needed to erase ANSI C features +that do not exist in K&R C: + +* | Prototyped functions are put out as old-style unprototyped functions. +* | Type qualifiers ("``const``" and "``volatile``") are not put out. +* | Enumerations are put out as integral types, and enumeration constants are + put out as integral constants. +* | "``signed``" is never put out. "``signed char``" is put out as "``char``", + and "``signed int``" is not used for the base type of a bit field. +* | "``long double``" is put out as "``double``". +* | The suffixes "``U``" on integral constants and "``F``" and "``L``" on + floating constants are not put out; a cast is used instead. +* | Union initializations are rendered as executable code. +* | Initializations of automatic aggregates are rendered as executable code. +* | Bit fields in unions are put out as normal fields. +* | Signed bit fields are simulated by adding code to sign-extend and truncate + the bit fields on each access. +* | Second and third operands of "``?``" of type ``void`` are rewritten. +* | ``extern void`` variables are put out with type ``char``. +* | Labels are given a prefix of "``__L_``" to accommodate the fact that pcc + does not maintain a separate name space for labels. + +The following transformations also deal with features missing in K&R C, but +these transformations are done even when generating ANSI C to avoid some +features that might not be implemented (well) in C compilers: + +* | Rvalue field selections (e.g., "``f(x).i``") are rewritten as lvalue field + selections by using a temporary. + + .. code:: c++ + + struct A { int i; }; + extern struct A f(); + void m() { + j = f().i; /* Rewritten as "j = (Tnnnn = f(), Tnnnn.i)" */ + } + +* | Wide string constants are stored in generated static variables and the + variables are used in place of the constants at each reference. +* | Character arrays initialized with string constants not containing a + trailing null character are rendered in "exploded" form, e.g., something + like + + .. code:: c++ + + int a[4] = "abcd"; + + | is rendered as + + .. code:: c++ + + int a[4] = {'a', 'b', 'c', 'd'}; + +The following transformations are necessary to deal with ordering problems +(i.e., they're necessary because of the order in which the C-generating back +end outputs entities): + +* | Local types of functions are generated at file scope. This avoids problems + with extern declarations written inside functions (the extern entity is on + the file-scope list, but it may refer to local types of the function). + + .. code:: c++ + + void f() { + struct A { int i; }; + extern void g(struct A); + } + + | is rewritten as + + .. code:: c++ + + struct A { int i; }; + extern void g(struct A); + void f() {} + +* | Types in the prototype scope of a function are promoted out of the + prototype scope. This is because each function and variable is put out + twice, once as a declaration and once as a definition. Without this + promotion, the declaration and definition would be incompatible because the + two copies of the prototype scope types would be considered to be distinct + types. + + .. code:: c++ + + void f(struct A { int i; } p) {} + + | is rewritten as + + .. code:: c++ + + struct A { int i; }; + void f(struct A); + void f(struct A p) {} + + | Prototype scopes that are not part of a function or variable definition are + not processed in this way. When generating K&R C, such unprocessed + function types are put out unprototyped, which eliminates the types defined + in the prototype scope. When generating ANSI C, such unprocessed function + types are put out prototyped, and if any structs, unions, or enums are + defined in the prototype scope they are put out inline. + | + | When a pointer type containing a prototype scope needs to be put out (i.e., + as the type of a constant or in a cast), the type (and cast) is suppressed, + because the conversion must have been implicit in the source program -- + it's not possible to name the types defined in a prototype scope outside of + that scope. + +When virtual functions with covariant return types appear in the source +program, IL lowering rewrites them in a way that uses wrapper functions. That +is, when an overriding virtual function returns a pointer to a derived class, +and the overridden virtual function returns a pointer to a base, a wrapper +function is generated that calls the overriding function but returns a pointer +appropriate for the overridden function. Such functions have a body that is +simply a return of an ``enk_result_of_overriding_function`` node cast to the +proper pointer-to-base-class type. The C-generating back end expands these +wrapper functions by generating the body of the overriding function again, with +the added cast inserted over the expression at each return statement. Note +that the "obvious" implementation technique of replacing the +``enk_result_of_overriding_function`` node by a call of the overriding function +(i.e., implementing these as actual wrapper functions) will not work if the +functions have variable-length argument lists. The same technique is used for +alternate entry points for constructors in the IA64-ABI, but only if the +routine has a variable-length argument list. + +Configuration +------------- + +Although the generated C code is generally portable, there are some +configuration issues that must be attended to. + +The most obvious is to make sure that the sizes and alignments of basic types +defined in ``targ_def.h`` match those assumed by the target C compiler. + +Block operations (e.g., ``memcpy``) are generated in either the BSD form or the +System V/ANSI form under control of the ``__BSD__`` configuration option, so +make sure its setting matches the library of the target C compiler. + +If the target C compiler has some way of indicating that a function is inline, +the code in ``dump_routine_decl`` should probably be changed to output that +construct. + +Long output lines are wrapped to avoid overly long lines. You can alter the +maximum size by adjusting ``MAX_OUTPUT_LINE_SIZE``. The default is fairly +modest (a few hundred characters). + +If the target C compiler has particular bugs or shortcomings, you may want to +add code to work around them. There is existing code for the Sun, Microsoft, +and gcc C compilers. + +The C-generating back end can emit ``#pragma`` directives for IL pragma +entries, but only in a somewhat limited way. For pragmas bound to an entity, +the pragma is emitted right before the declaration of the entity. However, +pragmas not bound to an entity are emitted at the beginning of the scope +containing them, and therefore they may not be where expected. That makes that +kind of pragma suitable only in cases where the exact position of the pragma is +not very significant, e.g., for global-effect pragmas and those that associate +attributes with entities by naming the entities. + +Operation +========= + +The code can be compiled either as a subroutine ``back_end`` that is called in +the same program as the front end, or as a main program. In either case, +``c_gen_be`` is called to do the C generation. It begins at ``il_header`` and +walks through the intermediate language tree, generating C and writing it to a +file with a ``.int.c`` suffix. First, it dumps the source correspondence +information (``dump_source_file_correspondence_info``) and some other header +code (``dump_header_code``). Then, for the file scope level, it + +* | calls ``dump_scope_constants`` to dump code for constants on the file-scope + list. This has marginal utility, but dumps class member constants (an + extension) promoted to the file scope by IL lowering. They are put out as + ``enum`` declarations. +* | calls ``dump_scope_types`` to dump declarations for all named types -- + i.e., ``typedef``\ s and tags. The tags are output twice: as incomplete + declarations on a first pass, and as complete declarations on the second, + to avoid forward-reference problems. Local and prototype-scope types are + also output here (at the file scope) to avoid some ordering problems. +* | calls ``dump_scope_routines`` to dump routine headers (no bodies). +* | calls ``dump_scope_variables`` twice. The first time dumps variables + without initializers, and tentative declarations for those with + initializers. The second time dumps only the initialized variables, this + time with initializers. This is to avoid forward-reference problems. +* | calls ``dump_scope_routines`` to dump routines with bodies. + +When ``ONE_INSTANTIATION_PER_OBJECT`` is enabled, each instantiation is put +out as a separate object file. There is still only one IL tree, but it is +marked so that the C-generating back end can sweep through it several times +and put out a different C file (a "slice") each time, each C file +containing one instantiated entity (function or static data member) plus +exactly the set of other entities needed by that entity. The information +on which entities to include on each sweep is provided by the +per-instantiation "needed" flags, which are a bit vector attached to the +source correspondence entry (see :ref:`needed-flags`). Each slice is +assigned one bit in that bit vector, and if the bit is 1 the associated +entity is needed in the slice. On beginning the generation of the C file +for a slice, the C-generating back end sets the global variable +``needed_flag_bit_number`` to the bit number for the slice, and then goes +through the normal processing to generate C for everything in the IL tree. +The normal test of the "needed" flag, used to exclude things that aren't +needed, in this mode tests the proper bit in the bit vector, and therefore +excludes all entities that are not in the slice. In addition, when a +variable or function with a definition is encountered, if the variable or +function is not assigned to the current slice (as indicated by the +``instantiation_needed_bit_number`` field in the variable or routine +entry), the variable or function is put out as a declaration instead of a +definition. + +The lower-level routines are as follows: + +``dump_type_decl`` generates a type declaration. It calls + +* | ``dump_enum_definition``, +* | ``dump_struct_union_definition``, or +* | ``dump_typedef_decl``. + +Types are written out by ``dump_type`` and +``dump_general_declaration_using_type``. They use routines from +``il_to_str.c`` to produce the output for the type. ``dump_enum_definition`` +puts out enum definitions, and ``dump_struct_union_definition`` puts out +struct/union definitions. + +``dump_variable_decl`` generates a variable declaration. For a variable with +an initializer, it calls ``dump_initializer``. There's some fairly complicated +processing under that routine to turn constant aggregate initialization into +executable code. Among other things, it involves writing initialization +assignments to an auxiliary file while processing declarations, then copying +the initialization code to the right place after all the declarations have been +processed. Because initialized static variables are put out twice (on two +calls of ``dump_variable_decl``), they are made external when generating K&R C, +so their names are modified (by ``dump_variable_name``) to avoid name conflicts +with like-named static and external variables in other compilation units. + +Code generated for file-scope initializations (of unions when generating K&R C) +is placed in a separate routine (with a name beginning with "``__cgi__``") that +needs to be called at program start-up time. If the compilation contains a +main program, or an initialization routine generated by IL lowering (with a +prefix of "``__sti__``"), a call to the C-generating back end initialization +routine is inserted there. Otherwise, if the compilation is of C++ source, the +C-generating back end generates an initialization routine of the same form as +that generated by IL lowering ("``__sti__``" prefix), along with the variables +needed to alert the link phase to the presence of the initialization routine. +If the compilation is of C source, a message is issued to ask the user to +include an appropriate "``-i``" option elsewhere to request invocation of the +initialization code. + +``dump_routine_decl`` generates a routine declaration. For a routine with a +definition, it calls ``dump_routine_definition``. That in turn calls +``dump_func_definition_type`` to dump the parameters (prototyped or old-style). + +``dump_statement`` is called to generate code for statements. + +The statements and expressions of functions are pre-scanned before code for the +routine is generated, to generate declarations for any temporaries that will be +needed in the generated code. Specifically, temporaries are generated for +rvalue field selections and wide string constants. + +Expressions are dumped by calling ``dump_expr``. It outputs the expression by +walking the tree. It puts in explicit parentheses where necessary to guarantee +the grouping of operators. Taking the address of a function or array must also +be handled carefully, and is done by ``dump_ampersand``. + +Since ``pcc`` doesn't allow signed bit fields, operations on such fields are +surrounded by references to macros to sign-extend them or truncate them for +storing. + +``dump_constant`` dumps out a literal constant or address constant using the +IL-to-string routines in ``il_to_str.c``. + +Actual output of generated code is handled by the following routines: + +* | ``m_write_ch``, +* | ``write_ch``, +* | ``m_write_str``, +* | ``write_str``, +* | ``m_write_tok_ch``, +* | ``write_tok_ch``, +* | ``m_write_tok_str``, +* | ``write_tok_str``, +* | ``write_unsigned_num``, and +* | ``write_num``. + +The "``m_``" versions are macros; the others are not. One can choose between +them based on the need for speed and/or a single evaluation of the argument. +The "``tok_``" routines always write a full token (or several); that allows the +output line to be broken before or after the output if the line is too long. + +``set_output_position`` is called to establish the source position of an entity +about to be generated. If necessary, it generates a ``#line`` directive or the +right number of empty lines to adjust the output position (see +``write_line_directive``). diff --git a/dev/doc/_sources/class_decl.rst.txt b/dev/doc/_sources/class_decl.rst.txt new file mode 100644 index 0000000..282a720 --- /dev/null +++ b/dev/doc/_sources/class_decl.rst.txt @@ -0,0 +1,1865 @@ +================== +Class Declarations +================== + +All class, struct, and union declarations are scanned in ``decl_spec.c``, and +their definitions, including the declarations of class members, are handled +through a set of routines, most of which are found in ``class_decl.c``. The +layout of classes is handled in ``layout.c``. Associated declarations are in +``class_decl.h`` and ``layout.h``. + +Declarations of structs and unions in C mode are, for the most part, precisely +compatible with C++ declarations; they just make use of a small subset of the +syntactic options. + +C++/CLI managed class add both a number of variant class kinds (collectively +called "managed classes") and a number of variant member kinds (e.g., events). +These are also mostly implemented in ``class_decl.c``. + +C++11 lambda expressions implicitly define a closure class type. While the +top-level class declaration parsing routines (``class_specifier`` and +``scan_class_definition``) are not applicable for parsing lambdas, some other +important routines in this area are reused (see :ref:`lambdas`). + +Similarly, C++/CLI delegate definitions implicitly define a ref class type, +which reuses some important routines supporting the ordinary definitions of +class types, but not the routines that parse such definitions. + +Overview +======== + +Class Declarations +------------------ + +``class_specifier`` (in ``decl_spec.c``) is called from ``decl_specifiers`` +when a ``class``, ``struct``, or ``union`` keyword is encountered. [#f1]_ In +Microsoft mode, this is also done with the ``__interface`` keyword, and in +C++/CLI mode with the "keywords" ``ref class``, ``ref struct``, ``value +class``, ``value struct``, ``interface class``, and ``interface struct``. A +tag name may be present, and if it is ``declares_something`` is returned +TRUE. A definition may be present, and if it is ``defines_something`` is +returned TRUE. In every case, even when there is an error, a pointer to a +``tk_class``, ``tk_struct``, or ``tk_union`` type entry is returned in +``type_ptr``. + +The processing of class declarations consists of several steps. The tag name +(if present) is scanned and looked up in the symbol table (see +``scan_tag_name``). A declaration may be the declaration of a new class, a +reference to an existing class, or the completion of a declaration whereby an +incomplete class is fully defined; it may also be a specialization of a class +template. If this is a brand new class, the type entry is allocated for it; +otherwise, the old one is fetched from the symbol entry. + +If the declaration does not actually *define* a class, that's about all that +needs to be done. The type is returned to the caller and declaration +processing continues. + +Class Definitions +----------------- + +If a class declaration is a class definition -- that is, if the class body is +present -- then ``scan_class_definition`` is called from ``class_specifier`` +(it is also called from other places like ``f_instantiate_template_class`` to +create an instance of a template class and ``instantiate_class_template`` to do +prototype instantiation of the class template). The creation of a class +definition is tracked using type ``a_class_def_state``; this is true for +ordinary definitions appearing in the source, but also for definitions +generated for, e.g., lambda expressions (i.e., closure types). This structure +records all kinds properties of the definition (e.g., the current accessibility +or whether a member has been seen that requires a nontrivial constructor) and +is passed around to many routines that implement class member declarations. + +Most of the tasks performed by ``scan_class_definition`` are done in C++ mode +only: + +* | The base class specifiers (if any) are scanned and recorded. +* | The scope stack is pushed for the class (and the scope stack entry is made + to point to the ``a_class_def_state`` structure for the definition). +* | A loop is entered to scan class members. In ordinary C this means scanning + the declarations of fields. In C++ it means scanning all kinds of member + declarations. +* | At the top of the loop (in C++ only) an optional access control specifier + is scanned. +* | When ``using`` appears (or there is only a qualified name and no + declaration specifiers), a using declaration (or access declaration) is + scanned. +* | When ``template`` appears ``template_declaration_or_directive`` is called + to process a member template. +* | Otherwise, ``class_member_declaration`` is called: + + * | A structure of type ``a_member_decl_info`` tracks properties of the + declaration. This structure includes a field ``decl_state`` of type + ``a_decl_parse_state`` (which is the kind of structure used for general + declaration processing). + * | ``decl_specifiers`` (in ``decl_spec.c``) is called to scan the + declaration specifiers. + * | When there is no declarator following, + + * | if it is a friend class declaration, ``decl_friend_class`` is called + and declarator processing is skipped. + * | if it is a nested ``class``, ``struct``, ``union``, or ``enum`` + declaration, declarator processing is skipped. + * | if it is a nested anonymous union declaration, declarator processing is + entered (even though the call to ``declarator`` itself is skipped) + since the rest of the processing is done in + ``decl_nonstatic_data_member``. + * | A loop is entered to scan a declarator list. In cases where only a + single declarator is permitted, the loop will be exited at the + appropriate point. + * | ``declarator`` (in ``declarator.c``) is called to scan a single + declarator. If default arguments are encountered when a parameter list + for a member function is scanned, they will be cached away to be + rescanned later. + * | Based on the combined information returned from ``decl_specifiers`` and + ``declarator``, one of the following is done: + + * | ``decl_member_function`` is called to process a member function + declaration (static or nonstatic, virtual or nonvirtual). If the + function body is present, the tokens are cached so that they can + scanned later (see ``prescan_function_definition``). If there is no + function body, a pure specifier ("``= 0``") is checked for (see + ``scan_pure_specifier``). + * | ``decl_friend_function`` is called to process a friend function (member + or nonmember). If the function body is present, the tokens are cached + so that they can scanned later (see ``prescan_function_definition``). + * | ``decl_member_function_template`` is called to process a member + function template. + * | ``decl_typedef`` is called to process a ``typedef`` declaration. + * | ``decl_nonstd_member_constant`` is called to process a member constant + declaration (an extension). + * | ``decl_static_data_member`` is called if the keyword ``static`` was + used in a non-function declaration. + * | ``decl_nonstatic_data_member`` is called to do processing for ordinary + fields. + * | At the bottom of the declarator loop, continue looking for declarators if + the next token is a comma. +* | At the bottom of the loop, continue looking for member declarations unless + a right brace (or end of file) is encountered. +* | Once the member declarations have been processed, further error checking is + done, and in addition: + + * | In case the class was declared before the current definition, + ``move_to_end_of_types_list`` is called to move the type entry for the + class to the end of the scope types list. (It will have been initially + put onto the list in ``class_specifier``.) + * | ``set_virtual_function_numbers`` is called to do the remaining processing + for virtual functions -- in typical implementations, the virtual function + number in a routine entry corresponds to its position in the virtual + function table. + * | ``check_special_member_functions`` is called to determine whether a + compiler-generated default constructor, copy constructor, and assignment + operator is needed and, if so, to generate the declarations. (The bodies + are generated if and when the function is referenced.) + * | ``do_class_layout`` is called to allocate space for base classes and + nonstatic data members, as well as for whatever information is needed + (e.g., pointers) to support accessing virtual base classes and calling + virtual functions. + * | ``project_base_class_conversion_functions`` is called to add projection + symbols for inherited conversion functions to the class symbol + supplement's ``conversion_list``. + * | ``report_virtual_function_ambiguities`` is called to issue diagnostics on + unresolved ambiguities in virtual function declarations. + * | ``check_abstract_class`` is called to mark a class with pure virtual + functions as "abstract." +* | The scope stack is popped, and the closing right brace of the class + definition is bypassed. +* | For non-nested classes ``delayed_scan_fixup_for_class`` is called to rescan + member function default argument declarations and inline member function + definitions. + +Many of these "class definition completion" tasks are initiated from the +``complete_class_definition`` function. This function is also called for class +types that don't appear using ordinary class definition syntax in the source +code (for example, closure types for lambda expressions; see :ref:`lambdas`). + +Ideally, all properties of a class should be known once the definition has been +seen. Unfortunately, that is not always the case. In particular, the C++11 +notion of whether a class type is a "literal type" cannot always be determined +until it is known whether it has a constexpr constructor, which in turn +sometimes requires waiting until all the field initializers have been scanned +(and for template classes that can be arbitrarily delayed). Whether a class +type is a literal type is therefore tracked by two flags in the class symbol +supplement [#f2]_ (``known_to_be_a_literal_type`` and +``known_not_to_be_a_literal_type``), which can be determined "on demand" by a +call to ``set_literal_type_flag`` or, more generally, ``is_literal_type``. + +.. _cppcli-managed-types: + +C++/CLI Managed Class Definitions +--------------------------------- + +Managed class definitions are parsed using the same framework as standard class +definitions. However, C++/CLI adds many new kinds of members, several of which +are implemented with new top-level mechanisms. + +Several "field-like" managed member kinds rely on "context-sensitive +keywords", i.e., specific identifiers (``event``, ``initonly``, +``literal``, and ``property``) that are keywords only if the rest of the +declaration would not otherwise be valid. The function +``check_for_cli_modifier`` looks ahead through the token stream for such +keywords, and records their presence in the ``a_decl_parse_state`` +structure for the current declaration. If the keywords ``event`` or +``property`` were found, the member declaration is handled using the +special-purpose function ``scan_cli_property_or_event_head``, after which +the front end proceeds with the next declaration. The other two keywords +(``initonly`` and ``literal``) are consumed by the regular call of +``decl_specifiers`` (which is passed the ``a_decl_parse_state`` structure +indicating that these identifiers should be treated as keywords). + +Delegate definitions appearing as member declarations also rely on a +context-sensitive keyword ``delegate``. That case is identified by the +function ``check_for_cli_delegate_definition``, and is then handled by +``scan_and_record_cli_delegate_definition``. + +Properties and events are represented as fields (``a_field``) if they are +nonstatic or as static data members (``a_variable``) if they are static. These +representations are created by calls to ``decl_nonstatic_data_member`` or +``decl_static_data_member`` respectively, which is done by the function +``decl_property_or_event_member``. + +Property and event definitions may include a brace-enclosed list of accessor +declarations (such properties/events are called *nontrivial*). Accessors are a +special kind of member function (i.e., their ``a_routine`` entry has a +special_kind field that is not ``sfk_none``) of the parent class of the +property or event: The braces are for grouping purposes only and do not +introduce a new scope. Accessors declarations are handled as separate member +declarations in the main loop of ``scan_class_definition``; not as part of the +call to ``scan_cli_property_or_event_head``. However, a copy of the +``a_member_decl_info`` structure recorded for the property/event declaration +itself is kept around while scanning the accessors (accessible via the +``pe_info`` field of the current ``a_class_def_state`` structure). This is +needed because the exact nature of the property/event may depend on the storage +class specified on the first accessor: If no storage class was specified on the +property/event declaration itself, but the first accessor is declared static, +then the property/event should be treated as static. Hence for a nontrivial +property or events, the call to ``decl_property_or_event_member`` is delayed +until parsing of the subsequent accessor has started: At that point a lookahead +for a ``static`` specifier (using function ``static_member_next``) is performed +if needed to determine the static/nonstatic nature of the property or event. + +Literal fields (i.e., fields declared with the context-sensitive keyword +``literal``) are recorded in ``decl_literal_field``: The result is an IL entry +of type ``a_constant``, not a_field (i.e., "literal field" is somewhat of a +misnomer). ``initonly`` members, on the other hand, are just treated as +slightly special cases in ``decl_nonstatic_data_member`` and +``decl_static_data_member``. + +Conversion functions and other operators can be static members of managed +classes; such members must have one more explicit parameter than their +nonstatic counterparts. The constraints on those parameters are checked in the +function ``check_operator_function_params``. + +Names +===== + +Name Scope +---------- + +When a class is declared with a tag name, an ``sk_class_or_struct`` or +``sk_union`` symbol is created to represent the use of the name. Since an +elaborated class specifier appearing in the source may refer to an existing +class, its name must be looked up in the symbol table. Finding a tag name in +the current or a containing scope is handled by ``scan_tag_name``. + +This is not a simple lookup, however. An interesting case occurs when a tag +name has already been declared in an outer scope: a reference to the same name +in an inner scope may or may not be a reference to the same entity. For +instance, + +.. code:: c++ + + struct S { int i; }; + void f() { struct S s; } + void g() { struct S { /* ... */ } s; } + +In this example, the ``S`` in function ``f`` refers to the ``S`` defined in the +file scope, whereas the one in function ``g`` refers to another ``S``, one +local to the function scope. The difference is that the declaration in ``g`` +is a definition and so eclipses the name from the file scope, whereas in ``f`` +there no redefinition of ``S``. For this reason ``scan_tag_name`` must take +into account whether the class is being defined in the current declaration in +deciding whether to reuse a class defined in a containing scope. A further +complexity is revealed by another example: + +.. code:: c++ + + struct S { int i; }; + void f() { struct S; struct S *p; struct S { } s; } + +Here the first declaration of ``S`` in function ``f``, referred to as a +"vacuous declaration" of ``S`` because it does not define a class and is not +used in the definition of any other object, has the effect of introducing an +incomplete class ``S`` into the routine scope and thereby eclipsing the file +scope ``S``. [#f3]_ ``scan_tag_name`` also deals with this kind of case. + +When no tag symbol is found, there is still the question of what scope a new +symbol is to be declared in. This too is determined in ``scan_tag_name``; the +answer is returned to the caller by ``effective_decl_level``. In most cases it +is simply the current scope (given in ``decl_scope_level`` [#f4]_). However, +in C++ a non-defining initial use of a class name in a function prototype scope +or a class scope is treated as declaring that name in the innermost containing +scope that is not the scope of a function prototype or a class. For example, + +.. code:: c++ + + int f(struct S *p) { return (p == 0); } + struct S { /* ... */ } s; + +Here (and contrary to the interpretation in ordinary C mode) there is only one +``S``; the second reference defines the ``struct`` to which the first is a kind +of forward reference. Thus ``scan_tag_name`` would return the file scope as +the ``effective_decl_level`` for ``S`` in its initial declaration. Similar +treatment is accorded declarations in classes: + +.. code:: c++ + + class A { + class B; + class C *pc; + class D { + class E *pe; + }; + }; + +Here ``class B`` is a vacuous declaration (it anticipates a definition of a +nested ``class B`` later in the definition of ``A``), whereas ``class C`` is a +forward reference to a file scope declaration of ``C``. Similarly, ``class E`` +anticipates a file scope declaration as well, even though the file scope is not +the immediately containing scope of ``class D``. + +The tag name can be a qualified name, not only in a reference (e.g., a +``friend`` declaration or the declaration of another entity using an elaborated +type specifier) but also in a definition. + +* | It can be a class-qualified name for a "delayed definition" of a nested + class. For example, + + .. code:: c++ + + class A { + struct S; + /* ... */ + }; + struct A::S { /* ... */ } + + | Here ``scan_tag_name`` returns a symbol locator specifying the qualified + name; the parent class scope is then reactivated in + ``scan_class_definition`` before the body of the class definition is + scanned. +* | It can also be a namespace-qualified name -- most interestingly when a + class declared in a namespace is then defined outside the namespace. (It + is a requirement that the scope in which the definition occurs enclose the + scope in which original declaration occurs.) For example, + + .. code:: c++ + + namespace N { + struct S; + /* ... */ + }; + struct N::S { /* ... */ } + + | ``scan_tag_name`` returns a symbol locator specifying the qualified name, + and ``class_specifier`` pushes a namespace-extension scope before calling + ``scan_class_definition``. + +Tagless Classes +--------------- + +When classes are declared with no tag name, though obviously no symbol is +needed for lookup on a subsequent reference, one *is* needed to store +information about the class (see below). Creating such a symbol, which is +not actually added to the symbol table, is done by +``make_unnamed_tag_symbol``. + +There is a way by which a tagless class can acquire a name retroactively -- +when its definition appears within a ``typedef`` declaration. Here is an +example, + +.. code:: c++ + + typedef struct { /* ... */ } S; + +in which case the tagless ``struct`` comes to acquire the name ``S``. This +cannot be anticipated during the processing done by ``scan_class_definition``. +Rather, the situation is detected only after the class definition has been +scanned, in ``decl_typedef``. In general, this means the name is assigned "for +linkage purposes", which means the ``name`` field in the type's +source-correspondence is updated. Additionally in cfront mode, +``relink_unnamed_tag_symbol`` is called to add the symbol for the unnamed class +to the symbol table after turning it into a symbol of the specified name. + +C++/CLI Accessor Names +---------------------- + +The names of accessor functions of properties and events (``get``, ``set``, +``add``, ``remove``, and ``raise``) are not directly visible in the class of +which they are members (although accessors are members of that class in all +other ways; e.g., they have a ``this`` handle). Instead, referring to them +directly requires qualification with the name of the property or event. For +example + +.. code:: c++ + + ref struct RS { + int get(); // (1) + property int p[int] { + int get(int); // (2) Use p::get + } + property int p[double] { + int get(double); // (3) Use p::get + } + property int q { + int get(int); // (4) Use q::get + } + }; + +The accessors marked (2) and (3) form an overload set. The accessors marked +(1) and (4) are not part of overload sets. (See also :ref:`cppcli-delegates`.) + +The symbol for an CLI accessor is not linked under the symbol header used for +normal lookups of the accessor's name. For example, a ``get`` accessor for a +property is not linked on the list of the symbol header normally associated +with the identifier ``get``, and hence looking up the identifier ``get`` in the +usual way will never find an accessor. Instead, a special symbol header is +synthesized by combining the accessor name and its parent event or property; +see ``get_property_or_event_accessor_symbol_header`` for details. (See also +:ref:`cppcli-member-funcs` for additional notes on accessor functions and their +representation, as well as :ref:`cppcli-props` for related remarks about +properties and events.) + +.. _type-scope-and-symbol: + +Type, Scope, and Symbol +======================= + +Processing a class declaration involves forming a potentially extensive and +complex description of the class. There are three principal data structures +that serve as repositories for this information: a symbol entry, a type entry, +and an IL scope entry. The information that must be passed on to the back end +(including the IL lowering phase, if applicable) is stored in the type and +scope entries; information that is only of use in front end processing (e.g., +for error detection) is recorded in the symbol. + +Detailed descriptions of these data structures are provided in the files +``il_def.h`` and ``symbol_tbl.h``; introductions painted with a broader brush +may be found in the Intermediate Language and Symbol Table chapters. + +One thing that might be a bit confusing is that both the symbols and type +entries for classes have supplements, entities of type +``a_class_symbol_supplement`` and ``a_class_type_supplement``, respectively. + +Moving among the symbol, type, and scope entries that represent a class is +fairly straightforward: + +* | The ``assoc_type`` field of the IL scope entries points to the associated + class type. +* | The ``assoc_scope`` field of the class type supplement points to the + corresponding IL scope entry. +* | In the type entry the ``source_corresp.assoc_info`` field is a pointer to + the class's symbol entry. [#f5]_ +* | The symbol points to the type entry by means of the ``type`` field. + +To make it a bit easier to get from source language categories to the data +structures that represent them, here (from a slightly different slant) is yet +another description of how the symbol, type, and scope divide up the task of +summarizing a class declaration: + +* | Nonstatic data members ("fields") are recorded on a linked list of + ``a_field`` that is accessed from the type entry. +* | Static data members are represented by ``a_variable`` entries; a list of + them appears on the scope entry. +* | Member functions appear on a linked list of ``a_routine`` entries which is + also accessed from the scope entry. Static and nonstatic member functions + are intermingled on this list; they can be distinguished by the presence or + absence of an implicit ``this`` parameter type in the associated routine + type. +* | Member function templates are represented by ``sk_function_template`` + symbols. (They also appear in the IL, but only very limited information is + available there: see the linked list of ``a_template`` pointed to from the + scope entry for the class.) Instances of member function templates, like + ordinary member functions, appear on the ``routines`` list of the class + scope entry. +* | As far as the IL is concerned, constructors, destructors, overloaded + operator routines, and user-defined conversion routines are just like any + other member function. They can be identified by the + ``special_function_kind`` value in the routine entry (e.g., for generating + their names). To facilitate front-end processing, however, the symbol's + class supplement contains pointers to the symbols for the constructor(s), + the destructor, and the assignment operator routine(s). +* | Member types (including type entries for nested classes) and member + constants also appear on lists hanging off the scope entry. +* | Member class templates are represented by ``sk_class_template`` symbols. + (They also appear in the IL, but only very limited information is available + there: see the linked list of ``a_template`` pointed to from the scope + entry for the class.) Instances of member class templates, like ordinary + nested classes, appear on the ``types`` list of the class scope entry. +* | Friendship is represented by a reference to the befriending class in the + routine entry for the friend function (or in the type entry when friendship + is conferred on an entire class). +* | Derivation is represented by a list of ``a_base_class`` entries that is + pointed to from the class type supplement of the derived class. All base + classes (direct, indirect, virtual) appear on this list. The specific ways + the class is derived are given by the ``a_base_class_derivation`` entry + associated with each base class; and there may be more than one such entry + for a given base class if it is virtual. +* | Inherited names are represented by ``sk_projection`` symbols. The + projection symbol identifies both the fundamental symbol and the base class + entry with which that instance of the symbol is associated. +* | Names brought into a derived class from a base class by a + *using-declaration* (or an access declaration) appear in the symbol table + as projection symbols for which ``is_using_decl`` is TRUE. Such + declarations are also recorded in the IL by entries of type + ``a_using_decl``, pointed to from the scope entry. +* | Accessibility is recorded in IL entries (for front-end use and symbolic + debug purposes only), in projection symbols (which can end up marked + "inaccessible"), and in base class derivation entries. But since + accessibility is generally dynamic, it must usually be computed (e.g., see + ``access_to_end_of_path`` and ``have_access_to_symbol`` in + ``symbol_tbl.c``). + +Base Classes +============ + +Once the tag symbol and type entry have been created for a class definition, +``scan_class_definition`` calls ``scan_base_specifier_list`` to scan any base +classes that may have been specified. It goes through the comma-separated list +of base classes one by one, creating for each (and for each of the indirect +base classes derived through it) an entry of type ``a_base_class`` that is +added to the ``base_classes`` list of the class type supplement. When all base +classes have been added, ``wrapup_base_classes`` is called to establish certain +properties (like the preferred derivation path of virtual bases) that cannot in +general be determined by looking at a single derivation. + +Base Class List +--------------- + +The list of base classes associated with any derived class contains a base +class entry for each of its base classes -- not just for those from which it is +directly derived. The order of the list is significant: depth-first +left-to-right, following the source code order of declarations. Base classes +contain a ``direct`` flag to distinguish direct from indirect base classes; +there is also an ``is_virtual`` flag. Consider this example: + +.. code:: c++ + + class V { /* ... */ }; + class A : virtual V { /* ... */ }; + class B : virtual V { /* ... */ }; + class C : public B { /* ... */ }; + class D : public C, public A { /* ... */ }; + +Here the base classes list for class ``D`` will contain the following entries; +note that the virtual base class appears only once in the list: + +* | Indirect virtual base class ``V`` +* | Indirect base class ``B`` +* | Direct base class ``C`` +* | Direct base class ``A`` + +Base class entries are not shared between classes because they contain +information uniquely identifying the relation of a base class to its derived +class. Thus, in the previous example, class ``C`` also has its own base +classes list, namely: + +* | Indirect virtual base class ``V`` +* | Direct base class ``B`` + +Despite some overlap of information, new copies of the base class entries of +``C`` are made for the base classes list of ``D``. + +In ``scan_base_specifier_list``, for each base specifier in the source the +optional access-specifier and optional ``virtual`` keyword are scanned, the +base class name is scanned, and error checking is performed. If the same base +class name appears twice in the base specifier list, an error is issued. +However, if the name of a direct base class is identical to that of an indirect +base class already on the list, no error is reported at this time; rather, both +base classes are marked as ambiguous. This is an example of such a case: + +.. code:: c++ + + class A { /* ... */ }; + class B : public A { /* ... */ }; + class C : public B, public A { /* ... */ }; + +The base classes list for ``C`` will contain: + +* | Indirect base class ``A`` (marked ambiguous) +* | Direct base class ``B`` +* | Direct base class ``A`` (marked ambiguous) + +Only later, if, say, a qualified name using ``A`` appeared within a member +function of ``C``, would the base class ambiguity be reported. + +Creating the base classes list is done by ``scan_base_specifier_list``, which +adds direct base classes, and ``add_indirect_base_classes``, which in recording +indirect base classes calls itself recursively as required. Both routines call +``fixup_virtual_base_class`` when a virtual base class is encountered more than +once among the direct and indirect base classes. + +Derivation Path +--------------- + +Each base class entry contains a ``derivation`` field, which points to one +or more entries of type ``a_base_class_derivation``. (Nonvirtual base +classes will have only one such entry, but virtual bases may have more.) +Each base class derivation entry points to a linked list of one or more +entities of type ``a_derivation_step``. Such a list is referred to as a +"derivation path" because it records the derivation of the derived class +from the base class: it is the path *from* a derived class back up its base +class tree *to* the required base class. Here is a simple example: + +.. code:: c++ + + class A { /* ... */ }; + class B : public A { /* ... */ }; + class C : public B { /* ... */ }; + +The derivation path from derived class ``C`` to direct base class ``B`` is +=>B, whereas the path to indirect base class ``A`` is =>B=>A. (The notation => +can be thought of as a cast from a derived to a direct base class.) + +The first step on a derivation path is either a direct base class, as in the +examples above, or a virtual base class. In the latter case, the paths to the +virtual base class (there may be more than one) are elided and may be found by +examining its base class derivation entries. For example: + +.. code:: c++ + + class X { /* ... */ }; + class A : public X { /* ... */ }; + class B : virtual public A { /* ... */ }; + class C : virtual public A { /* ... */ }; + class D : private B, public C { /* ... */ }; + +Here the derivation path for ``X`` in ``D`` is represented as =>A=>X, whereas +``A`` itself has two derivation paths, =>B=>A and =>C=>A, which are in effect +implicit in the derivation for ``X``. + +Base class ambiguity can be seen as a case in which there are two distinct +paths to nonvirtual base class entries that refer to the same class. Returning +to a previous example, + +.. code:: c++ + + class A { /* ... */ }; + class B : public A { /* ... */ }; + class C : public B, public A { /* ... */ }; + +there are two base class entries for ``A`` in class ``C``, with derivation +paths of =>B=>A and =>A. + +``add_indirect_base_class`` takes an existing base class entry and creates a +new one based on it, but to do this it needs a new derivation path as well. +``copy_and_extend_path`` creates a new path based on the derivation path of the +original base class entry. + +For cases in which it is necessary to compare two derivation paths, +``congruent_paths`` returns TRUE if two paths refer, step for step, to the same +classes. + +Virtual Base Class +------------------ + +When two or more base classes of the same type are specified ``virtual``, they +share the same base class entry. Its position in the base classes list will be +that of first appearance in the depth-first left-to-right traversal of the base +classes. However, each appearance in the derivation graph is recorded with a +separate derivation entry, and each derivation entry gives a unique derivation +path. + +``set_preferred_base_class_derivation`` is called to identify the "preferred" +path of a virtual base class -- tantamount to the sequence of casts that +affords the greatest "normal" accessibility (i.e., without special treatment +for casts in the context of member or friend functions). For example, + +.. code:: c++ + + class A { /* ... */ }; + class B : virtual public A { /* ... */ }; + class C : virtual public A { /* ... */ }; + class D : private B, public C { /* ... */ }; + +Class ``D`` is derived from virtual base class ``A`` via two paths, BA and CA. +Therefore ``A``\ 's base class entry points to a list of two base class +derivation entries, one for each path. Since the path through ``C`` gives +greater accessibility, the base class derivation entry that points to CA is the +one marked "preferred". (When several entries afford equally good access, a +direct base class is preferred over an indirect, and an indirect base class +with no virtual base classes in its derivation is preferred over one that has +virtual base classes in its derivation.) + +Virtual Functions +----------------- + +A final task performed by ``scan_base_specifier_list`` and its subroutines is +to accumulate virtual function information for its base classes. + +When a function in a derived class "overrides" a virtual function from one of +its base classes, that information is recorded for later use: [#f6]_ A list of +entries of type ``an_overriding_virtual_function`` is pointed to from the base +class entry to identify the virtual functions that are members of that class +and that are overridden in some other class derived from it. This information +must be propagated as base classes are copied. Here is an example to make this +a bit clearer: + +.. code:: c++ + + class A { virtual void f(); }; + class B : public A { void f(); }; + class C : public B { }; + +``A::f()`` is a virtual function of the base class ``A`` that is overridden +by ``B::f()`` in the derived class ``B``. The +``overriding_virtual_functions`` field of the base class entry for ``A`` in +``B`` points to an entry that identifies ``A::f()`` as the *primary +function* and ``B::f()`` as the *overriding function*. When ``C`` is +derived from ``B``, this information is passed along. At the time the base +class entry for ``A`` is created in ``C``, the virtual function override +information is copied from the base class entry for ``A`` in ``B``, with an +additional piece of information -- a pointer to the base class entry for +``B`` in ``C``. [#f7]_ + +The virtual function override list is sorted on the basis of the virtual +function number in the routine entry of the primary function. It can be that +more than one overriding virtual function entry for a given primary function +ends up on the overriding virtual function list -- and it needn't be illegal. +Consider the following example: + +.. code:: c++ + + class A { virtual void f(); }; + class B : virtual public A { void f(); }; + class C : virtual public B { void f(); }; + class D : public B, public C { }; + +Within both ``B`` and ``C`` there are an overriding virtual function entries +for base class ``A`` specifying that primary function ``A::f()`` is overridden, +in the one instance by ``B::f()`` and in the other by ``C::f()``. Within ``D`` +there is also a base class entry for ``A``, and both the overriding by +``B::f()`` and the overriding by ``C::f()`` are recorded in its list; both +overriding function entries will refer to the same primary function, +``A::f()``. As written above, this example is illegal. But the diagnostic +cannot be issued until the definition of ``D`` is complete (see +``report_virtual_function_ambiguities``), since a declaration ``D::f()`` would +override both ``B::f()`` and ``C::f()``, making the ambiguity moot and the +program legal. + +``copy_virtual_function_override_list`` copies the overriding virtual function +for a base class from one class to another derived from it, calling +``insert_in_virtual_function_override_list`` to place the copy in the proper +sorted location in the new list. + +C++/CLI Derivations +------------------- + +C++/CLI managed classes can derive from base classes in two different ways: +They can "inherit" from one ref class and they can "implement" any number of +interface classes. If the definition of a managed class (other than +``System::Object``) does not specify a base class explicitly, it inherits +``System::ValueType`` if it is a value class, or it derives virtually from +``System::Object`` otherwise (hence, all managed classes ultimately derive from +a virtual base class ``System::Object``). See ``add_implicit_cli_bases``. + +"Implementing an interface" is modeled as virtual derivation. Inheriting from +a ref class other than ``System::Object`` corresponds to regular (i.e., +nonvirtual) derivation. + +Some ref classes must implicitly directly derive from (i.e., "implement") the +``System::IDisposable`` interface according to a set of rules known as the "CLI +dispose pattern" (see ``implement_dispose_pattern_if_needed``). However, this +cannot be determined until after the complete class definition has been seen: +This is therefore a unique situation where a (virtual) base class is added +after members have been seen. When this is done, ``wrapup_base_classes`` must +be called a second time. + +Some generated managed classes implicitly inherit specific ref classes (by +calling ``add_cli_system_base_class``): delegate classes inherit +``System::MulticastDelegate`` and boxed enum types inherit ``System::Enum``. + +Generic parameters are modeled using proxy (managed) class types called +"constraint types". A type constraint specifying a type C on a parameter +modeled by a constraint type P is modeled by adding C as a base class of P. +Note that Microsoft compilers permit "sealed" classes [#f8]_ to be specified as +type constraints, which means that in this context a sealed class can be +derived from (and in that case, the deriving constraint type is marked as +sealed also). + +Fields +====== + +Declarations +------------ + +``scan_nonstatic_data_member`` is called from ``class_member_declaration`` to +process the declarations of what in ordinary C are called "fields" and in C++ +are "nonstatic data members". It handles parsing of bit field widths and +C++11-style initializers (see below), and calls ``decl_nonstatic_data_member`` +to create the actual IL entry (type ``a_field``) and associated symbol (if any) +as well as to do some error checking and set various flags. [#f9]_ + +Field symbols point to their corresponding IL entry and also to a field symbol +supplement that carries some additional (mostly C++-specific) information. + +Processing is straightforward for ordinary fields. There are several special +cases that warrant a little more explanation, however. + +* | For bit-fields ``scan_fs_constant_expression`` is called to scan the size + specified after the colon. It scans the constant value. This constant is + then used by decl_nonstatic_data_member to perform error checking, and, in + a few unusual cases, to modify the field's type to accommodate the + bit-field (e.g., when a signed integer kind was specified but the bit-field + is too small for a sign bit). +* | For unnamed fields a field entry is created and added to the IL tree (the + field entry is needed when ``set_field_size_and_offset`` is called), and a + symbol is created for it (see ``unnamed_field_symbol`` in + ``symbol_tbl.c``). The space allocated by the unnamed field is represented + as a gap left in the layout of the class. +* | Anonymous union "parent fields" have no names, but they do have an + associated symbol and a field entry in the IL. In addition, + ``check_anonymous_union_symbols`` is called both to do error checking and + to promote the symbols for the fields of the anonymous union into the name + scope of the class of which the anonymous union is a member field. This + produces an inconsistency between the IL representation, which is that of + any nested union, and the symbol table representation, where the names of + the fields of the anonymous union are treated as though they were declared + in the containing class -- for example, the parent class of the promoted + ``sk_field`` symbol is the containing class, but the IL field entries to + which it points continues to be represented as a member of the nested + anonymous union. + +In addition to actually doing error checking, ``decl_nonstatic_data_member`` +also sets some flags in the symbol to facilitate error checking and other +processing at a later time. For instance, if the field's type is a reference +type, ``any_ref_member`` is set in the class symbol supplement; the setting can +then be checked to determine whether the compiler can generate a default +constructor. + +Offset and Alignment +-------------------- + +The front end is configurable to use either of two models for assigning offsets +to fields. Either a class is laid out so that the fields are allocated exactly +in the order in which they are declared, or else they are grouped by access, +with first the ``public`` fields allocated in order of declaration, then the +``protected`` and finally the ``private`` fields. + +Processing for both models is done by ``set_offsets_for_fields``, called from +``do_class_layout`` in ``layout.c``. For each field it calls +``set_field_size_and_offset``, which takes as input offset values left over +from the previous allocation and uses them to allocate the current field. The +maximum alignment required for the structure as a whole is also tracked. The +computations are done in ``increment_field_offsets``, which does overflow +checking on all calculations. + +By default, fields are assigned offsets in declaration order; the other +model is activated by setting +``TARG_FIELD_ALLOC_SEQUENCE_EQUALS_DECL_SEQUENCE`` to ``0``. *However, at +this time only the default allocation model is supported by the IL lowering +pass.* + +.. _field-inits: + +Field Initializers +------------------ + +C++11 allows a field initializer (also known as a DMI -- default member +initializer -- or, previously, an NSDMI -- non-static data member +initializer) to be specified on a field declaration. For example: + +.. code:: c++ + + struct S { + int i = init_val; + static int init_val; + }; + +The initializer must be parsed in the context of the completed class (which, +e.g., means a field initializer can make use of a member that is declared at a +point that is lexically after the initializer). To achieve this, +``scan_nonstatic_data_member`` caches the initializer for later parsing. In +the case of nontemplate classes, this later parsing is handled by recording a +fixup entry (by calling ``record_inclass_initializer_fixup``) which is later +processed by a call to ``inclass_initializer_fixup`` (when the class is +completed), and that in turn calls ``field_initializer`` (in ``decl_inits.c``) +to actually parse and record the initializer. For template classes, the +initializers are not parsed until they're needed. If a field initializer of a +template class must be accessed by the front end, it must call +``instantiate_field_initializer_if_needed`` prior to examining the IL for that +initializer (recorded in ``a_field::initializer``). In the template case also +``field_initializer`` is the routine that performs the actual parsing of the +initializer. + +Field initializers are subject to various error checks. One of the more subtle +checks in this context is for circular dependencies: The initializer for a +field may depend on that field's value in various indirect ways. The front end +will diagnose this if the circularity affects compile-time evaluation +(particularly, when dealing with constexpr constructors). + +Static Data Members +=================== + +``decl_static_data_member`` is called to process declarations of static data +members. It creates a variable entry (typically with ``sc_extern`` storage +class -- it will later be changed to ``sc_unspecified`` if it is defined in the +current translation unit) and appends it to the ``variables`` list of the IL +scope entry for the current class. It also creates a symbol entry of kind +``sk_static_data_member`` and enters it into the symbol table. + +When a static data member of integral type is declared as ``const``-qualified +and an initializer appears in the in-class declaration, it is usable as a +member constant. The initializer expression is scanned by +``scan_member_constant_initializer_expression``, and the variable is flagged +with ``is_member_constant`` set to TRUE. + +Definitions of static data members, with optional initializer, are handled as +part of normal declaration processing, where ``define_static_data_member`` is +called from ``function_definition``. Aside from setting a few flags, little +needs to be done except some error checking. + +C++/CLI Static Data Members +--------------------------- + +Static data members of C++/CLI managed classes can have an initializer when +they're first declared in the class, and that declaration is then considered to +be a definition. Unlike standard static data members, there are no type +restrictions for this in-class initialization to be permitted and any +initializer that would be allowed in namespace scope can be specified. + +Furthermore, such initializers are by default not processed until the complete +class definition has been seen [#f10]_. This parallels the standard treatment +of in-class function definitions and in-class default arguments. However, if +the value of the static data member is needed to evaluate a +constant-expression, the initializer is processed at that point (i.e., early; +see ``ensure_inclass_static_member_constant_initializer_is_scanned``). + +Member Functions +================ + +``decl_member_function`` is called to complete processing a member function +declaration, but the work has already been started by ``function_declarator``, +which needs to recognize member function declarations for two reasons: + +* | Default arguments in parameter declarations are not passed to + expression-scanning routines immediately; rather, the tokens are cached and + scanned only once the entire class declaration has been completed. +* | After the parameters have been scanned, an optional ``const`` or + ``volatile`` qualifier may be present on nonstatic member functions. And + whether the qualifier is there or not, the type of the implicit ``this`` + parameter is determined in ``function_declarator`` and the routine type + supplement for the member function's routine type entry is updated + accordingly. + +Consequently, even before ``decl_member_function`` is called, quite a bit of +processing has been done on member functions. What remains is to create a +symbol entry and a routine entry for the member function, add the symbol to the +symbol table, and append the routine entry to the ``routines`` list of the IL +scope entry for the current class. Some special processing is required for +overloaded functions, for virtual functions, for constructors and destructors, +for user-defined conversions, and for operator functions. The field +``special_kind`` of ``a_routine`` entries identifies special member functions +(like constructors, destructors, operators, C++/CLI accessors, etc.); it is set +to ``sfk_none`` for ordinary member functions (and non-member functions). + +Static *vs.* Nonstatic +---------------------- + +As noted above, a nonstatic member function receives special treatment in +``function_declarator``: the ``implicit_this_param_type`` field of the routine +type supplement is updated with a pointer to the (optionally qualified) class +of which the function is a member. In a static member function this pointer +remains NULL. This is the only way static and nonstatic member functions are +distinguished in the IL. ``routine_type_is_nonstatic_member_function`` is a +macro that is available to test the field. + +Overloading +----------- + +Function overloading is a matter for name lookup only -- that a function is +overloaded is not explicitly represented in the IL. The general technique for +supporting function name overloading with ``sk_overloaded_function`` symbols is +discussed in detail in the chapter on the Symbol Table. + +Entering a new member function symbol in a way that takes overloading into +account is handled by ``symbol_for_member_function``. One of the subroutines +it calls is ``member_function_redecl_sym``, which checks for type +compatibility, recognizing when the type of the implicit ``this`` parameter +should be ignored and when it must be taken into account. + +In addition to ``sk_member_function`` symbols, the overload set may include +``sk_projection`` symbols representing ``using``-declarations and +``sk_function_template`` symbols representing member function templates. + +Virtual Functions +----------------- + +A member function may be explicitly declared ``virtual``, or it may be a +virtual function implicitly, because of having the same name and type as a +virtual function from a base class. In either case, for every member function +it is necessary to go through all the base classes and look for functions with +the same name and type. Then, if the original function is virtual for either +reason, not only must it be so marked, but it is also necessary to record the +fact that a virtual function from a base class is overridden by a function from +a derived class. This, as already described in another context, is done with +entries of type ``an_overriding_virtual_function``. + +``decl_member_function`` calls ``check_for_virtual_override`` to accomplish all +this. The latter does the search through the base classes for overridden +virtual functions, and when it finds one it calls +``record_virtual_function_override`` to add an entry to the +``overriding_virtual_functions`` list in the base class. When an entry that +refers to the same primary function is already there (as a result of an +override by an inherited function), that entry is updated to record the +override by the current class's member. When more than one such entry is on +the list, the extras are removed, since the ambiguity is resolved by the +current declaration. + +After all declarations of the current class have been processed, +``scan_class_definition`` calls ``set_virtual_function_numbers`` to assign +sequential numbers to nonoverriding virtual functions declared in the current +class. (Overriding virtual functions will have already been assigned the +number of the associated base class function.) + +Then it calls ``report_virtual_function_ambiguities``, which makes another pass +over the base classes to look for ambiguous virtual function overriding -- it +issues errors when such ambiguities, caused by merging overriding virtual +function lists from several base classes, are not resolved by a member function +declaration in the current class. + +Default Arguments +----------------- + +Default arguments specified for parameter declarations in member function +declarations require special handling, because the expressions must not be +scanned until all the member declarations in the class have been scanned. +Parameter declarations are scanned in ``function_declaration``. When a default +argument is encountered in a member function declaration that is part of a +class definition, ``prescan_default_arg_expr`` is called to cache the tokens +that make up the expression; the cache resides in an entry of type +``a_def_arg_expr_fixup``, which is kept on a list pointed to by an entry of +type ``a_routine_fixup`` that is accessed from the class symbol supplement. +When the class's member declarations are complete, that list is revisited and +the default argument expression is rescanned (see +``delayed_scan_of_default_arg_expr``, which is called from +``delayed_scan_fixup_for_class``). + +Inline Definitions +------------------ + +When a member function body appears within a class definition, it is handled +somewhat like default argument expressions: ``prescan_function_definition`` is +called to cache the tokens that comprise the function body (the cache resides +in an entry of type ``a_routine_fixup``), and when the class definition is +complete, ``delayed_scan_fixup_for_class`` calls ``scan_function_body`` (in +``func_def.c``) to process the function body retroactively. (For constructors +that are defined inline, the constructor initializer list is included among the +cached tokens, and ``ctor_initializer`` (in ``decl_inits.c``) is later called +to scan it.) + +A somewhat special case occurs when inline definitions and default argument +expressions appear within a nested class: the language definition requires that +a reference to a name in the enclosing class be found even if that name is +declared after the nested class definition is complete. For instance, + +.. code:: c++ + + struct Outer { + struct Inner { + static int f() { return i; } + }; + static int i; + }; + +Since a call to ``Inner::f()`` should return the current value of ``Outer::i``, +the body of ``Inner::f()`` cannot be processed until all the members of +``Outer`` have been seen. Therefore the delayed scan fixup list for a nested +class is not rescanned until its outermost containing class has been completely +scanned. Only then does ``scan_class_definition`` call +``delayed_scan_fixup_for_class``, which in turn calls itself recursively for +nested classes before processing the tokens cached for the members of the class +passed to it. + +User-Defined Conversions +------------------------ + +When ``decl_member_function`` is called for a user-defined conversion, it +creates an entry of type ``a_conversion_list_entry`` to record the existence of +the conversion routine in the class symbol supplement for the current class. +The entry simply points to the symbol for the user-defined conversion; all such +routines for a given class are accumulated on a linked list. + +Since conversion functions are functions that convert an object of the current +class to a specified result type, the list that is created can serve as a list, +for a given source type, of all the target types for which a user-defined +conversion exists. This kind of list can be useful in selecting the +appropriate implicit cast during expression processing. + +User-defined conversion functions are inherited, so after all member +declarations have been seen, the list is augmented by projection symbols for +inherited conversion functions that result in types that are not already +present in the list (see ``project_base_class_conversion_functions`` which goes +through the conversion lists for each of the direct base classes of the current +class looking for unrepresented result types). + +Compiler-Generated Functions +---------------------------- + +A default constructor or a copy constructor is created by the compiler when it +is required in a class but was not explicitly declared by the user. Likewise a +compiler-generated destructor may be needed, or an assignment operator which +effectively copies an object of a given class onto another object of the same +class. Even if one of these functions is needed, only a declaration is +generated at first, not a function body. The body is generated only when there +is an actual invocation of the function. The functions will be declared as +extern inline member functions, just as if they had been explicitly defined in +the class definition. + +After all member declarations have been scanned, +``check_special_member_functions`` is called. For each compiler-generated +function determined to be needed, it calls ``generate_special_function``, which +creates a routine type entry and calls ``decl_member_function`` to create the +symbol and the routine entry. + +``reference_to_implicitly_invoked_function`` is called when a +compiler-generated function is implicitly invoked. If the function has no +body, ``define_special_member_function`` (in ``func_def.c``) is called, which +in turn calls ``make_default_constructor_body``, +``make_default_destructor_body``, or ``make_default_assignment_body``. The +compiler-generated assignment function is created only when a simple ``struct`` +copy is insufficient, i.e., when memberwise copying must be done explicitly. + +Trivial default constructors present a special problem. They are "trivial" +because calling them has no actual effect, so an obvious optimization is to +eliminate them. When the symbol supplement for a class has a NULL +``constructor`` pointer, that means the implicitly declared default constructor +for the class (always present in principle) is trivial and can generally be +ignored. There is an exception, however, when the definition of a trivial +default constructor would be ill-formed: then, even though no call is put out +in the IL, a diagnostic must still be issued. Here's an example: + +.. code:: c++ + + class A { + const int i; + }; + A var; + +Since class ``A`` is not a "POD-struct", ``var`` is default-initialized, which +means the default constructor ``A::A()`` is supposed to be called, and calling +an implicitly-declared constructor normally triggers its definition. The call +can be optimized away since it has no effect, but the definition would be +ill-formed (because ``A::i`` is ``const``-qualified). So to preserve the +behavior *as if* ``A::A()`` were called, its declaration is saved in the symbol +(see ``trivial_default_constructor`` in the class symbol supplement) and its +definition is generated at the point of implicit reference by a call to +``reference_to_trivial_default_constructor`` in ``symbol_ref.c``. + +.. _cppcli-member-funcs: + +C++/CLI Member Functions +------------------------ + +C++/CLI adds several variations for member function declarations in managed +classes. + +Syntactically, a static constructor is like a default constructor (i.e., with +no parameters) declared with the storage class ``static``. The two can +coexist, but they don't create an overload set. In expression contexts, +default construction always refers to the nonstatic constructor kind. In +declaration contexts, the static constructor is only found if the declaration +includes ``static`` (which is communicated to the lookup functions with the +flag ``IDL_IS_STATIC_DECL``). Static constructors are the only members that +can be defined outside their parent class with an explicit storage class +specifier (and such definitions must include that ``static`` specifier). + +Managed classes can contain finalizers: Their handling is completely parallel +to that of destructors. The syntax uses "``!X``" instead of "``~X``". + +User-declared accessor functions for properties and events are explained in +:ref:`cppcli-managed-types`. For trivial properties and events (which don't +include user-declared accessors), accessors are generated by calls to +``generate_trivial_accessor``. Whether generated or user-declared, the +``a_routine`` for an accessor function points to the +``a_property_or_event_descr`` entry associated with the corresponding event or +property. + +The member function modifiers ``sealed``, ``abstract``, and ``override`` are +accepted in both ordinary Microsoft mode and in C++/CLI mode. They can appear +after the optional const and/or volatile at the end of a nonstatic member +function declarator (see ``scan_microsoft_function_modifiers``), but in C++/CLI +``override`` is not optional for derived class members that override a member +in a base ref class. The modifier ``new`` is also accepted at this grammatical +location to indicated that a function does not implicitly override a virtual +base member with the same name and type. + +A virtual member function can also specify specific base members it overrides +using a specifier like "``= B::m, C::n``" where ``B`` and ``C`` are the base +classes or interfaces whose respective members ``m`` and ``n`` are +overridden/implemented. This is called "named overriding" (in contrast to +"implicit overriding"). + +Named overriding and the requirements of the ``override`` and ``new`` modifiers +are mostly handled in ``check_for_virtual_override`` and its helper functions. +These features add considerable complexity to that function. + +Member Function Templates +========================= + +``scan_class_definition`` calls ``template_declaration_or_directive`` (in +``templates.c``) when a member declaration begins with the keyword +``template``. When the declaration designates a function template, this +results in a call to ``class_member_template_declaration``, which in turn calls +``class_member_declaration``. Once processing by ``decl_specifiers`` and +``declarator`` has been done, ``decl_member_function_template`` is called to +create the ``sk_function_template`` symbol. A routine entry is also created, +but (as with nonmember template functions) it is not added to the IL. Rather, +it is attached to the template symbol supplement and is for front-end use only. + +Member Constant Extension +========================= + +As an extension to C++ the EDG front end allows "member constant" declarations. +[#f11]_ Member constants may be of any scalar type. For integers such a +declaration is similar to declaring a constant name in an ``enum`` declaration. +For example, instead of this: + +.. code:: c++ + + class A { + enum { MAX = 100 }; + int array[MAX]; + }; + +the program may declare and use a member constant: + +.. code:: c++ + + class A { + const int MAX = 100; + int array[MAX]; + }; + +Qualified-name references to member constants (e.g., to ``A::MAX``) are also +permitted, subject to the same access and ambiguity constraints imposed on any +class member. + +``class_member_declaration`` calls ``decl_nonstd_member_constant`` to process +such a declaration. It adds to the IL an entry of type ``a_constant`` (it is +appended to the ``constants`` list of the IL scope associated with the current +class), and it enters an ``sk_constant`` symbol that points to it. Note that a +member constant is not equivalent to an initialized ``const`` static data +member, which is represented as a variable in the IL. + +Friend Declarations +=================== + +A ``friend`` declaration involves (1) a class which gives ``friend`` access to +nonmembers and (2) the routine or class to which that access is given; and so +one may refer to the former as the *befriending* class and the latter as the +*befriended* routine or class. + +The class type supplement of the befriending class contains pointers +(``friend_routines`` and ``friend_classes``) to linked lists of entries +identifying the routines and classes to which friendship is given. This +corresponds to the way in which a friend declaration actually appears in the +source. + +In addition, the befriending-befriended relationship is represented the other +way around as well, with the befriending class also recorded in the befriended +routine or class. Specifically, routine entries have a pointer to a list of +entries that point to classes; the linked list identifies the befriending +classes, those that afford ``friend`` access to the specified routine. A +similar ``befriending_classes`` field can be found in the type supplement for a +befriended class. + +``decl_friend_function`` is called by ``class_member_declaration`` to process a +``friend`` function declaration. For a member function +``member_function_redecl_sym`` is called to get the symbol; otherwise, +``decl_routine`` in ``decls.c`` is called (where, if this is the first +declaration of the function, the symbol will be created in the appropriate +non-class scope). Once the symbol is retrieved, the current class is recorded +as a befriending class in the routine entry. + +``decl_friend_class`` is called to process a ``friend`` class declaration. +This is just a matter of recording the current class as a befriending class in +the type supplement of the befriended class. + +A class- or namespace-qualified ``friend`` declaration must refer to a +previously declared entity, but it may be that the first declaration of an +entity is an *un*\ qualified ``friend`` declaration. The lookup for an +unqualified ``friend`` declaration begins in the innermost enclosing +nonclass scope and continues to (but no farther than) the innermost +enclosing namespace scope, and if it is not found a declaration is +"injected" into the innermost enclosing nonclass scope. [#f12]_ For +instance: + +.. code:: c++ + + namespace N { + class S { + friend void f(); + /* ... */ + }; + void f() { /* ... */ } // Same "f" as declared a friend by N::S + } + +This approach is taken even when the specified name is visible in a scope +enclosing the innermost namespace scope -- in the above example, ``f`` would be +injected into namespace ``N`` even if a ``::f`` were visible. + +Using Declarations and Access Declarations +========================================== + +A ``using``-declaration inside a class definition is processed by +``member_using_declaration``, which is also called when +``scan_class_definition`` encounters a declaration that is a class-qualified +name followed by a semicolon, interpreted to be an old-style access declaration +of an inherited member. ``member_using_declaration`` performs error checking +and causes a projection symbol to be created to reserve the name in the current +class. The flag ``is_using_decl`` is set in the projection symbol, since this +is not an ordinary kind of projection and is subject to somewhat different +rules for computing accessibility; [#f13]_ it can also be added to an overload +set if it refers to an inherited member function. In addition, the declaration +is recorded in the IL by adding an entry of type ``a_using_decl`` to the scope +associated with this class, in case a symbolic debugger would need the +information (see ``make_using_decl`` in\ ``decls.c``). + +.. _cppcli-delegates: + +Delegates (C++/CLI mode) +======================== + +A C++/CLI delegate is a managed function object (i.e., a "callable" object) +that encapsulates an invocation list. A delegate type is introduced by a +delegate definition, which looks like a typedef for a function type where the +keyword ``typedef`` is replaced by a context-sensitive keyword ``delegate``. +The front end represents a delegate type as a mostly ordinary ref class type +synthesized from the signature provided in the definition. For example, a +definition like + +.. code:: c++ + + delegate void D(System::Object^); + +causes the front end to synthesize (in ``create_cli_delegate_definition``) +a ref class called ``D``, implementing the interface +``System::MulticastDelegate`` with (among others) a member function called +``Invoke`` with the signature of the delegate definition (to which "calls" +of delegate objects are dispatched), a constructor, and static member +operators ``+`` and ``-`` (to add or remove targets from the encapsulated +invocation list). + +.. _cppcli-props: + +Properties and Events (Microsoft and C++/CLI modes) +=================================================== + +Microsoft C++ includes a notion of "property" members for (otherwise +standard) class types. Syntactically, this is a field declared with an +attribute of the form ``__declspec(property(get=``\ *func_name1*\ ``, +put=``\ *func_name2*\ ``))``. The result is not really a field: No storage +is allocated for it, but every "read" operation on the pseudo-field is +mapped to a call of *func_name1* and every "write" operation is mapped to a +call of *func_name2* (either operation name may be omitted from the +attribute to create a read-only or write-only property). The IL +representation of this kind of property members uses ``a_field`` entries, +which point to entries of type ``a_property_or_event_descr``, and those +entries in turn record the name of the specified get and/or put functions. +*func_name1* and *func_name2* are looked up at every point that requires +their use, which may not always yield consistent results. Therefore, the +rewriting of property-field accesses is done right away in the front end +proper (and not, for example, in a later lowering pass since the symbol +table might have changed by then). + +C++/CLI provides a similar notion of properties for managed class types, but +instead of indicating the "accessor functions" (named ``get`` and ``set`` in +this case) by name in an attribute, they are part of the property definition +syntax. For example: + +.. code:: c++ + + ref struct RS { + property int p { int get(); void set(int); } + }; + +The IL representation is similar to that of the first kind of property (i.e., +the non-C++/CLI variant described above), but since the accessor functions are +independent from the point of use in this case, the corresponding ``a_routine`` +entries are pointed to directly from the ``a_property_or_event_descr`` entry +and vice versa. Also, since C++/CLI properties can be static or nonstatic, +their representation can be entries of type ``a_field`` and ``a_variable`` (the +latter corresponding to a pseudo-static-data-member). + +C++/CLI properties can be "indexed" to model a sort of "array field" (but +unlike regular fields, indexed properties can be truly multidimensional). +Furthermore, such indexed properties can be overloaded: + +.. code:: c++ + + ref class RC { + property double ip[double, int] { + double get(double, int); + set(double, int, double); + } + property float ip[float, int] { + float get(float, int); + } + }; + +Because of this possibility, the symbol representing a property in a class has +a kind ``sk_property_set``, which reflects that it potentially represents a set +of properties (unlike function symbols, there is no separate symbol kind for +single properties and overloaded sets). ``sk_property_set`` symbols point to a +structure of type ``a_property_set_symbol_supplement``, which in turn points +both to the associated pseudo-data-members (``sk_field`` or +``sk_static_data_member``) and to the overload sets formed by their ``get`` and +``set`` accessors respectively. + +Indexed properties can have the name ``default``: Applying a subscript to such +a property's parent object amounts to a use of such a property (this has some +similarity to the more traditional ``operator[]``). If any such +default-indexed properties are present in a class, the corresponding +``sk_property_symbol`` is pointed to from the class' symbol supplement. + +C++/CLI has a notion of "event" members. These are similar to C++/CLI +properties, but they cannot be indexed, must have handle-to-delegate type, and +they allow only three operations: ``+=``, ``-=``, and "call". An event +definition can declare up to three accessors (matching the aforementioned three +operations) called ``add``, ``remove``, and ``raise``, or it can be "trivial" +(in which case those accessors are generated by the front end). Since events +cannot be indexed, they cannot be overloaded, and no separate symbol kind is +needed for them: They're simply associated with the ``sk_field`` or +``sk_static_data_member`` symbol for their pseudo-data-member. + +Class Object Layout +=================== + +Laying out the storage for a class means computing the overall size of an +object of that type and assigning to each of its components an offset +representing its position in the object. Nonstatic data members are +represented by entries of type ``a_field``, each of which has an ``offset`` +value that represents the byte offset from the beginning of the object and a +``offset_bit_remainder`` value (nonzero for bit fields only) that represents +the additional bits that must be taken into consideration if the field is not +aligned on a byte boundary. Base classes have an ``offset`` field that +contains the byte offset from the beginning of storage for the class as a whole +to the beginning of storage for the base class's data section; for virtual base +classes there is also a ``pointer_offset`` field, which is the offset of the +pointer to the data section. The class type supplement also has a +``virtual_function_info_offset`` field. All these offset values together make +up the abstraction we refer to as the class's layout. + +Object Layout Models +-------------------- + +The front end provides by default two distinct object models: a "classic" model +based on the original cfront implementation and a more modern "IA-64" model +based on specifications drafted by a group of vendors for the 64-bit Itanium +Architecture of Intel. At the time of this writing, the latter specifications +can be found at: + + ``_ + +The implementation of both models can be found in ``layout.c``. Where +convenient, the same routines are used to implement the two models (e.g., there +is only one ``do_class_layout`` function). + +The front end can also be configured to implement small variations of both the +cfront-like and IA-64 models. For the cfront-like model, increased +compatibility with the original cfront implementation can be achieved by +setting ``CFRONT_OBJECT_CODE_COMPATIBILITY`` to TRUE (this involves routines +whose names start with ``cfc_``). Similarly, by setting +``DEFAULT_EMULATE_GNU_ABI_BUGS`` to TRUE, improved compatibility is achieved +with the default IA-64-based ABI implemented by GNU C++ 3.2 (and this involves +routines in ``layout.c`` whose names start with the ``gnu_`` prefix). + +General Layout Steps +--------------------- + +All classes are laid out in the same general way, following this pattern (in +the sequence indicated): + +* | First, in the IA-64 model, storage is reserved for the so-called *primary + base class* (if it exists) or for a pointer to a virtual table (if the + class is polymorphic without having a primary base): + + * | There is no primary base class concept in the cfront-like object model. + * | The primary base class shares a "virtual pointer" at offset zero with the + complete class. Usually, the primary base class is a nonvirtual direct + base class, but it can also be indirect and/or virtual in less common + situations. If none of the base classes are polymorphic, the derived + class has no primary base class. The primary base class is also pointed + to from the class type supplement (by the field ``primary_base_class``). + * | No storage is allocated for non-primary virtual bases of the primary base + class at this point. +* | Next, storage is allocated for all the remaining *direct* base classes + (which implicitly includes storage for nonvirtual *indirect* base + classes as well): + + * | In the cfront-like model, when the direct base class is also virtual, + only enough space is set aside for a pointer to the actual storage, + which appears later. In the IA-64 model, no such pointer is used and + -- unless it is also the primary base -- the direct virtual base is + allocated later on. + * | In the case of a nonvirtual direct base class, enough storage is set + aside for its own primary base class (if any), its nonvirtual base + classes, its virtual base class pointers (in the cfront-like model), its + own fields, and its virtual function information, but no space is + allocated for its virtual base classes. + * | In the cfront-like model, nonvirtual direct base classes that are *empty* + (no own or inherited nonstatic data members and no virtual functions or + direct or indirect virtual base classes) are allocated in a separate pass + when ``targ_optimize_empty_base_class_layout`` is TRUE. In the IA-64 + model, direct empty bases are allocated in the same pass as nonempty + bases. (See :ref:`empty-base-class-optimization`). +* | Next, storage is reserved for the class's own fields. +* | Next, in the cfront-like model, storage for virtual function information + (typically, a pointer to a virtual function table). +* | Finally, storage for its virtual base classes, with space enough in each + case for its own primary and nonvirtual base classes, virtual base class + pointers (cfront-like model only), fields, and virtual function + information. + +The storage and alignment for all the items but the last are recorded in the +class's type supplement as ``size_without_virtual_base_classes`` and +``alignment_without_virtual_base_classes``; the ``size`` and ``alignment`` +fields of the type entry itself record the values for the entire object. +Except in an incomplete type, both size values will be at least 1. + +This general sequence is implemented by ``do_class_layout``, which is called by +``scan_class_definition`` once all the members have been scanned. +``do_class_layout`` calls several subroutines: + +* | ``set_offsets_for_nonvirtual_base_classes`` to assign the offsets for + nonvirtual base classes; +* | ``set_offsets_for_fields`` to set the ``offset`` and + ``offset_bit_remainder`` values of each field; +* | ``set_offset_for_virtual_function_info`` to record the position at which + (typically) the virtual function table pointer will be found; +* | ``set_offsets_for_virtual_base_classes`` to lay out the part of the class + object where the data sections of virtual bases classes are kept; and +* | ``set_offsets_for_indirect_base_classes`` to record the offsets of indirect + nonvirtual base classes (this phase is really just a fixup pass -- no new + storage is reserved). + +.. _empty-base-class-optimization: + +The Empty Base Class Layout Optimization +---------------------------------------- + +The C++ language specifications allow an implementation to allocate an empty +base subobject at the same location as another subobject provided this does not +cause two objects or subobjects of the same type to be allocated at the same +address. For example: + +.. code:: c++ + + struct E {}; + struct A: E { char c; }; + struct B: E { E e; }; + +In ``A``, the base class ``E`` can be allocated at the same offset as the field +``c``, but in ``B`` the optimization cannot be applied because two subobjects +of the same type (the field and the base) would occupy the same address. + +In the cfront-like model, the front end implements this optimization when +``targ_optimize_empty_base_class_layout`` is TRUE and most of the required work +is performed in ``set_offsets_for_empty_nonvirtual_base_classes``. The +cfront-like optimization heuristic uses a two-pass algorithm: + +* | First the direct nonvirtual nonempty direct base classes are allocated as + usual; i.e. empty base classes are skipped. +* | Next, an additional pass is made in + ``set_offsets_for_empty_nonvirtual_base_classes`` to place the direct + nonvirtual empty base classes. The first offset to be attempted is the + origin of the object (i.e., zero). If a situation is detected that + would cause two subobjects with the same type to be allocated at the + same offset, a new offset is sought after the next allocated base (if + one is available). This is repeated for every empty base -- without + backtracking the offset -- until there are no more empty bases. + | Another example illustrates how the second pass is a single pass (i.e., + the offset if not backtracked): + + .. code:: c++ + + struct E1 {}; // Empty + struct E2: E1 {}; // Empty + struct E3 {}; + struct B { E1 e; } // Not empty + struct D: E1, E2, E3, B { char c; }; + // Layout: + // B : this+0. (a nonempty base is allocated in the first pass) + // E1: after B because at this+0 it conflicts with B::e. + // E2: at least one byte farther than direct base E1 because else + // E2::E1 conflicts with base E1. + // E3: same offset as E2 since there is no type conflict; there is, + // however, no backing up to the offset of direct base E1. + // c : same offset as E2 and E3. + + | The optimization can only be applied to empty base classes and not to empty + (nonstatic) data members. Hence, ``B`` cannot be considered empty in this + last example. + +In the IA-64 model, empty base classes are allocated in the same pass as other +direct nonvirtual base classes. In this case the heuristic is different: If +the base can be allocated at offset zero without causing a conflict with a +subobject that has already been allocated there, then that is where the empty +base class is allocated. Otherwise, it is allocated at the next available +offset. Every time a base class is allocated (whether empty or not), +``base_subobject_conflict`` is called: If a conflict is detected, the +allocation is retried at the next alignment boundary. This process is repeated +until there is no conflict. A similar process is needed for the first field +(to avoid having an empty base of a field end up at the same offset as an empty +base of the complete class). + +The IA-64 model also handles the concept of a *nearly-empty base class*: This +is a virtual base class whose storage requirement is limited to a virtual table +pointer and (optionally) its own virtual base classes. Such a class can be +selected as a primary base class, in which case it is allocated at offset zero. + +Deferred Class Fixup +==================== + +As mentioned above, default arguments, inline member function bodies, and field +initializers are not processed until the entire class definition has been seen; +and when the class is a nested class, the processing is deferred until the +definition of the outermost containing class has been completed. + +However, it gets even more complicated when templates are involved. Consider +this example: + +.. code:: c++ + + template class A { + void f(T* = new T) { ... } + }; + class B { + A x; + } b; + +Here, the instantiation of ``A`` is kicked off before the definition of +``B`` has finished, but the default argument expression for ``A::f(B*)`` +requires that ``B`` be complete. + +To accommodate cases like this, the default argument and inline function body +processing is deferred until all pending class definitions have completed. +(The definition of ``B`` is pending when the definition of ``A`` is +finished, so the fixup for the latter is deferred.) + +``scan_class_definition`` calls +``process_deferred_class_fixups_and_instantiations``, and if global variable +``pending_class_definitions`` is zero, +``process_deferred_instantiation_requests`` (in ``templates.c``) and +``process_deferred_class_fixups`` are called. + +The latter calls ``delayed_scan_fixup_for_class``, which scans the token caches +saved for default arguments and function bodies. First it pushes a class +reactivation scope. Then, for default arguments it pushes a function prototype +scope and calls ``delayed_scan_of_default_arg_expr`` (or, for class template +instances, ``delayed_scan_for_function_template_default_args``). For function +bodies it calls ``scan_function_body`` -- except that the scanning of inline +member function bodies inside a class template instance is further deferred +until the member function has actually been referenced. + +A similar mechanism is also used to delay processing of in-class initializers +for nonstatic data members in C++11 mode and of static data members of C++/CLI +managed classes; see ``record_inclass_initializer_fixup`` and +``inclass_initializer_fixup_for_class``. + +Class Linkage +============= + +Like functions and variables, a class has linkage recorded in the +``source_corresp.name_linkage`` field of its type entry. Ordinarily (i.e., +except in cfront-compatibility mode), when a class is first created, it is +given external linkage by default, except for local classes (which have no +linkage) and classes declared inside an unnamed namespace (which have internal +linkage). This setting in turn determines the linkage and storage class +applied to class members. + +In cfront mode, however, when a class is first created, it is given internal +linkage by default, and, since the class and its members are supposed to have +the same linkage, its members also have internal linkage (and correspondingly a +storage class of ``static``). These are provisional settings, however, since +the presence of a non-inline member function or a static data member requires a +class to become externally linked. Moreover, if a class is referenced in a +declaration of an externally linked entity, it needs to have external linkage. +Thus, at the end of translation unit processing ``check_class_linkage`` is +called (in cfront-compatibility mode only) to make a pass over all the classes +defined in the translation unit and, where appropriate, to fix up the linkage +and storage class of classes and their members. + +.. _lambdas: + +Lambdas +======= + +A C++11 lambda expression is essentially a shortcut to define a "function +object" class and initialize a temporary object of that class. For example: + +.. code:: c++ + + int f(int x) { + auto f_impl = [x]()->int { return x*2; }; + return f_impl(); + } + +is largely equivalent to: + +.. code:: c++ + + int f(int x) { + class _Closure { + int x; + public: + int operator()() const { return x*2; }; + }; + _Closure f_impl = (_Closure){ x }; + return f_impl(); + } + +The implementation of lambdas in the front end exploits this equivalence: When +expression processing encounters the beginning of a lambda expression, it hands +over the task of parsing the construct to ``scan_lambda`` (see +:ref:`scanning-operations`). This routine calls ``make_closure_class``, pushes +an associated class scope on the stack (after captures have been scanned -- see +below), and records a synthetic ``a_class_def_state`` structure to go along +with the class definition scope. This allows the lambda to be parsed much as +if it were an in-class definition of a member function. + +``scan_lambda`` also creates the ``a_lambda`` entry and records it in the scope +stack entry for the closure class. That allows, e.g., expression and statement +processing to be aware of the lambda context. The convenience function +``get_current_lambda`` is also useful for this purpose. The type entry for the +closure class does not itself directly point to the associated lambda (due to +memory region constraints), but its class type supplement has a flag indicating +that it is a lambda closure class type (rather than a user-defined class type). + +Explicit and Implicit Captures +------------------------------ + +The C++11 lambda syntax allows for the optional specification of an implicit +capture mode and explicitly captured local variables and expressions (the +latter are often referred to as "init-captures"). ``scan_lambda_capture_list`` +parses this construct and records it in the ``a_lambda`` entry. Explicitly +captured variables are recorded with a call to ``add_lambda_capture`` and +explicitly captured expressions are handled by a call to ``scan_init_capture``. +The fields associated with these explicit captures are added by a call to +``decl_lambda_capture_fields`` (after the closure class definition scope has +been pushed and after the optional lambda declarator has been processed). + +If an implicit capture mode has been specified (using the "``[=`` ... ``]``" +or "``[&`` ... ``]``" forms of the lambda capture list), +``add_lambda_capture`` is also the routine that records the capture (it also +creates the associated field in the implicit capture case). However, in such +cases we get there via ``lambda_capture_for_variable``, which is called from +the expression scanning routines while parsing the lambda body (ultimately, via +``scan_identifier``\ --see :ref:`scanning-idents`). + +The "Lambda Declarator" +----------------------- + +The syntax to describe lambda parameters, return type, and mutability is +optional and, when present, it differs from the ordinary member function +declaration syntax. Still, the function ``scan_lambda_declarator`` is much +simplified by reusing ``function_declarator``. (``function_declarator`` is +also used when parsing ordinary functions/operators, and is aware of the +enclosing class definition environment.) Similarly, +``decl_call_operator_for_lambda`` -- which creates the ``operator()`` member of +the closure class -- mostly relies on ``decl_member_function`` and +``decl_member_function_template``. + +For generic lambdas (a C++14 feature), the lambda declarator corresponds to the +declarator of a function template, where the template parameters are created +implicitly from the use of ``auto`` as a parameter type. For example: + +.. code:: c++ + + [](auto p) { return p*2; } + +creates a closure class with an ``operator()`` that is a member template +corresponding to: + +.. code:: c++ + + template auto operator()(_T p) { return p*2; } + +The front end implements this by prescanning the lambda declarator to record +information about ``auto`` parameters. If there are any such parameters, +``set_up_generic_lambda_declarator_scan`` then proceeds to set up a member +function template declaration environment. ``decl_specifiers`` also uses the +information gathered during the ``prescan`` to map occurrences of ``auto`` in +the parameter list to the appropriate template parameter type (see +``process_generic_lambda_param_type``). + +``a_func_info_block`` has been augmented with a pointer to the associated +``a_lambda`` when applicable, and some lambda-specific behaviors of +``function_declarator`` (e.g., ``mutable`` as a function qualifier instead of +cv-qualifiers) make use of it. + +If no return type is specified explicitly for the lambda, the return type is +temporarily set to the unknown type (``tk_unknown``). +``scan_return_expression`` is aware of this arrangement, and it will update the +return type if appropriate. After the lambda body has been scanned +``scan_lambda`` sets the return type to ``void`` if no return statement was +seen (through ``check_implicit_lambda_return_type``, which also performs other +language-mandated checks if the return type was implicitly determined by a +return statement). + +Scanning the Lambda Body +------------------------ + +The lambda body is parsed by ``scan_function_body`` as would the body of a +member function of a user-defined class type (or via +``function_prototype_instantiation``, in the case of a generic lambda). There +are however a few subtle differences involved for the lambda case. + +First, ``scan_function_body`` is called while the class scope is still active. +This is needed so that closure fields associated with implicit captures can be +generated. So the option ``SFB_NO_CLASS_REACTIVATION`` is passed to +``scan_function_body`` to avoid reactivating the scope of the not-yet-completed +closure class. + +Second, if IL lowering is enabled, the function body is not lowered when the +associated function scope is popped. Instead, that lowering is triggered by a +call from ``scan_lambda`` to ``finish_function_processing_for_memory_region``. +This is a consequence of the previous observation: Lowering of the member +function cannot happen when the associated member function is popped because +the parent (closure) class hasn't been completed yet. + +.. [#f1] For the most part the term "class" will be used generically in this + chapter to include structs and unions as well as types declared with + the ``class`` keyword. +.. [#f2] See :ref:`type-scope-and-symbol`. +.. [#f3] This rule does not apply in ``pcc`` mode, only in ANSI C and C++. +.. [#f4] In C mode a ``struct`` does not cause a new name scope to be + established, and so ``decl_scope_level`` for a nested ``struct`` + will be the scope in which the parent ``struct`` is contained. On + the other hand, in C++ where a new name scope *is* established for + classes, ``decl_scope_level`` is the scope of the class itself. +.. [#f5] This field is used in this manner during front end processing only. +.. [#f6] For instance, to create a virtual function table. (This would be the + typical use of this information, but the front end tries to avoid + introducing any constraints that would imply a particular + implementation of virtual functions.) +.. [#f7] To take this example a step further, if there were a declaration of + ``C::f()``, the overriding virtual function entry for ``A::f()`` (the + one that is associated with the base class for ``A`` in ``C``) would + have to be modified, since it now would be overridden by ``C::f()``. + This is discussed later. +.. [#f8] "Sealed" is called "final" in other dialects; the IL uses flags named + ``final`` to indicate this property. +.. [#f9] Computing the field's storage properties (alignment and offset within + an object of the class to which it belongs) is done as the class is + being laid out; see ``set_field_size_and_offset`` in ``layout.c``. +.. [#f10] As a consequence, the C++11 ``auto`` type specifier cannot be used + for these members since the type of the member could not be deduced + from the initializer. +.. [#f11] This functionality is based on an extension offered by the GNU C++ + compiler and was added before a similar feature was proposed for the + official language -- namely, ``const`` static data members with + in-class initializers. +.. [#f12] For nonlocal classes, of course, the "innermost enclosing nonclass + scope" and the "innermost enclosing namespace scope" will be one and + the same. +.. [#f13] See ``have_proj_access_to_symbol`` in ``symbol_tbl.c``. diff --git a/dev/doc/_sources/code_style.rst.txt b/dev/doc/_sources/code_style.rst.txt new file mode 100644 index 0000000..43cc164 --- /dev/null +++ b/dev/doc/_sources/code_style.rst.txt @@ -0,0 +1,722 @@ +================== +Coding Style Guide +================== + + +General Whitespace Rules +======================== + +* Maximum line length is 79 characters. +* Indentation is by 2 spaces. +* Editors should be set to use an 8 space tab width. + +General Line Wrapping +===================== + +General Condition Rules +----------------------- + +Conditions that cause the line length to exceed 79 characters are wrapped via a +line break following an operator. The continuation is left aligned with the +opening paren: + +.. code:: cpp + + if (/* something very long */ && + /* something else */) { + /* etc... */ + } /* if */ + + if ((a || b) && + (/* something very long */ || + /* something else */)) { + /* etc... */ + } /* if */ + + if ((a || b) && (/* something very long */ || + /* something else */)) { + /* etc... */ + } /* if */ + +General Statement Rules +----------------------- + +Expressions that cause the line length to exceed 79 characters are wrapped via +a line break following an operator. The continuation is right-aligned: + +.. code:: cpp + + int x = /* something very long */ && + /* something else (right-aligned to column 79) */; + +General Line Breaks +=================== + +Line breaks are prioritized as follows: + +* 1 line for a conditional preprocessor directives (e.g., #if, #ifdef, etc.) + unless adding whitespace would break a visual "grouping" (e.g., conditional + inclusion of a header in a list of headers, conditionally enabling a single + statement in a function, etc.). +* 1 line for a namespace declaration and its associated closing comments. +* 2 lines for a function definition. +* 1 line for a function, variable, or type declaration. + +Naming Convention +================= + +The EDG naming convention can be broadly described as "snake case" (with an +exception for templates). In snake case, names are composed of lower case +letters and underscores. + +For types, the naming convention additionally adds a "``a_``/``an_``" +prefixed to the typename. For instance, what (in many projects) would be +spelled ``struct thing`` is called ``struct a_thing``. + +Writing a Variable +================== + +Variables appearing in "global" (these technically shouldn't exist as +there's a conditional "``edg``" namespace around all file contents) or +namespace scope are indented using tabs in older files which make use of +tabs and the equivalent +(8) spaces in newer files. The type is not indented, the name is indented by +2 tabs, and a comment should be added at 3 tabs: + +.. code:: cpp + + a_variable_type_name + my_variable; + /* A descriptive comment. */ + +If a variable type or name ends before the next tab stop, the lines should be +collapsed: + +.. code:: cpp + + a_variable_type_name + x; /* A descriptive comment. */ + int my_variable; + /* A descriptive comment. */ + int x; /* A descriptive comment. */ + +.. _writing-a-function: + +Writing a Function +================== + +Parameter Alignment +------------------- + +Functions declarations that fit within a single line should do so: + +.. code:: cpp + + void foo(int a, int b, int c); + +If a function declaration does not fit on a single line, it should be broken up +with the parameters broken up into two left-aligned columns, one column of +parameter types, and one column of parameter names: + +.. code:: cpp + + void foo(a_variable_type thing, + an_other_variable_type other_thing, + a_thingy thingy); + +Wrapping Function Declarations +------------------------------ + +Particularly for function definitions with lots of qualifiers and long names +(member functions are particularly guilty), simply wrapping the parameters can +be insufficient. In these cases, there are two accepted techniques for keeping +the function within the required line length. + +If the function has qualifiers like ``static`` and ``inline`` these can be +moved to the preceding line along with the return type: + +.. code:: cpp + + static inline void + very_long_long_long_long_foo(a_variable_type thing, + a_nother_variable_type other_thing, + a_thingy thingy); + +If this is still insufficient, the parameters can be moved to a new line and +right-aligned: + +.. code:: cpp + + void very_long_long_long_long_long_foo( + a_variable_type thing, + a_nother_variable_type other_thing, + a_thingy thingy); + +Documentation +------------- + +In a function definition, a comment should be added after the closing paren but +before the opening curly brace. This comment should describe all of the +parameters, the return value, and any actions it takes, and the closing +``}`` of the function should be followed by a comment giving the name +of the function, separated from the ``}`` by two spaces: + +.. code:: cpp + + a_boolean foo(int num_l_parens, int num_r_parens) + /* + Given the number of left parens (num_l_parens) and the number of right + parens (num_r_parens), display the values and return TRUE if the + numbers are equivalent; otherwise, return FALSE. + */ + { + printf("lparens=%d, rparens= %d\n", num_l_parens, num_r_parens); + return num_l_parens == num_r_parens; + } /* foo */ + +This also applies to void functions that use output parameters: + +.. code:: cpp + + void foo(a_boolean *result, int num_l_parens, int num_r_parens) + /* + Given the number of left parens (num_l_parens) and the number of right + parens (num_r_parens), assign *result to TRUE if the numbers are equivalent; + otherwise, assign *result to FALSE. + */ + { + *result = (num_l_parens == num_r_parens); + } /* foo */ + +Return Value +------------ + +If a function requires a variable to hold the result, it should be the first +variable in the function, and it should be named "``result``": + +.. code:: cpp + + int foo() + /* + A descriptive comment. + */ + { + int result; + + /* etc... */ + return result; + } /* foo */ + +Variable Grouping +----------------- + +Variables should be grouped into blocks with their types and names aligned. +The first block of variables should have a trailing newline, and any following +blocks should use a preceding newline: + +.. code:: cpp + + int foo() + /* + A descriptive comment. + */ + { + int result; + a_boolean temp_state; + + /* etc... */ + + a_state_catcher secondary_state; + a_boolean state_catcher_used = FALSE; + /* etc... */ + return result; + } /* foo */ + +Writing a Lambda +================ + +Lambdas are a case that's a mix of variable and function rules. Lambda +parameters -- similar to function parameters -- should be broken up into two +left-aligned columns, one column of parameter types, and one column of +parameter names: + +.. code:: cpp + + auto x = [](int num_l_parens, + int num_r_parens) -> a_boolean { + return num_l_parens == num_r_parens; + }; + +Unlike functions, lambdas do not require a documentation comment, or a closing +comment. For this reason, lambdas should be reserved for fairly trivial +operations. + +If a lambda appears in a block of other variables, the lambda should follow the +name alignment of the variables in the same block, e.g., + +.. code:: cpp + + a_long_type_name y = /* etc... */; + auto x = [](int num_l_parens, + int num_r_parens) -> a_boolean { + return num_l_parens == num_r_parens; + }; + +Writing a Class +=============== + +Classes should be preceded by a descriptive comment, and terminated by a +closing comment giving the class name and separated from the ``;`` by two +spaces: + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + /* etc... */ + }; /* foo */ + +Data Members +------------ + +Data members should be written at the end of the class. In terms of +indentation, data members are indented similarly to variables in global & +namespace scope, with the exception that the type is always indented by two +spaces: + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + /* etc... */ + private: + a_variable_type_name + my_var_a; + /* A descriptive comment. */ + a_variable_type_name + b; /* A descriptive comment. */ + int my_var_c; + /* A descriptive comment. */ + int d; /* A descriptive comment. */ + }; /* foo */ + +Member Functions +---------------- + +Member functions (including special member functions like constructors and +destructors) that do not exceed 1 line can be written inline: + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + void bar() + { this->x += 1; } + private: + int x; /* A descriptive comment. */ + }; /* foo */ + +If the member function is empty it should be spelled "``{}``" (no space): + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + void foo() + {} + }; /* foo */ + +Member functions that exceed 1 line should be written out-of-line: + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + void complex_bar(); + private: + int x; /* A descriptive comment. */ + }; /* foo */ + + + void foo::complex_bar() + /* + A descriptive comment about complex_bar. + */ + { + /* etc... */ + }; /* foo::complex_bar */ + +Additionally see :ref:`writing-a-function` as those rules also apply to member +functions. + +Member Initializer +------------------ + +If initializing using a passed value, the data members and parameters +should have names that differ (e.g., for a data member ``x``, ``x_val`` can +be an appropriate parameter name). + +Additionally, the introducing colon and all member initializers should be +indented two spaces, e.g., + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + void foo() + : x(1), y(2), z(3) + {} + inline void foo(int x_val, int y_val, int z_val); + int x; /* A descriptive comment. */ + int y; /* A descriptive comment. */ + int z; /* A descriptive comment. */ + }; /* foo */ + + + void foo::foo(int x_val, int y_val, int z_val) + /* + A descriptive comment about foo::foo. + */ + : x(x_val + 100), y(y_val + 1000), + z(z_val + 10000) + { + /* etc... */ + }; /* foo::foo */ + +Statements +========== + +``for`` Statements +------------------ + +C-style +^^^^^^^ + +"C-style" ``for`` loops should be formatted with their contents indented by 2 +spaces, and a closing comment (with two preceding spaces): + +.. code:: cpp + + for (int x = 0; x < 10; ++x) { + /* etc... */ + } /* for */ + +If the condition of the ``for`` loop causes the line length to exceed 79 +characters, it should be broken up at the semicolons: + +.. code:: cpp + + for (int long_variable = 0; + long_variable < another_long_variable; + ++long_variable) { + /* etc... */ + } /* for */ + +Range-based +^^^^^^^^^^^ + +Range-based ``for`` loops should be formatted as "C-style" ``for`` loops +are, with the exception that, if the condition cause the line length to +exceed 79 characters, it should be broken at the colon and right aligned: + +.. code:: cpp + + for (a_long_type &&x : + some_container) { + /* etc... */ + } /* for */ + +``if`` Statements +----------------- + +``if`` statements should be formatted with their contents indented by 2 +spaces. ``else`` and ``else if`` clauses should be preceded and followed by +braces, aligned with the ``if``, and the closing brace aligned with the +``if`` and followed by an ``if`` comment (with two preceding spaces): + +.. code:: cpp + + if (argument) { + /* something */ + } else if (other_argument) { + /* something else */ + } else { + /* default action */ + } /* if */ + +``switch`` Statements +--------------------- + +``switch`` statements should be formatted with their case labels indented +by 2 spaces, the contents further indented by two spaces, and the closing +brace annotated with a comment (with two preceding spaces). The opening +brace of a scoping block within a case can be immediately followed on the +same line by the first statement of the block, and its closing brace should +have no comment. If one case intentionally omits the usual closing +``break`` statement and flows into the next, the intent should be +documented by use of the ``FALLTHROUGH`` macro. When the cases of a +``switch`` statement are intended to cover all the enumerators of an +enumeration, the ``default_is_unexpected`` macro should be used to trigger +compiler diagnostics if an enumerator is added and not explicitly handled +by the ``switch``: + +.. code:: cpp + + switch (argument) { + case a: + { int y = 10; + + x += y; + } + FALLTHROUGH + case b: + x += 1; + break; + case c: + /* no-op */ + break; + default_is_unexpected(); + } /* switch */ + +``while`` Statements +-------------------- + +Pre-condition +^^^^^^^^^^^^^ + +"Pre-condition" ``while`` statements should be formatted with their contents +indented by 2 spaces, and a closing comment (with two preceding spaces): + +.. code:: cpp + + while (argument) { + /* etc... */ + } /* while */ + +Post-condition +^^^^^^^^^^^^^^ + +"Post-condition" (i.e., ``do``) while statements should similarly be +formatted with their contents indented by 2 spaces. However, unlike +"pre-condition" ``while`` statements, no closing comment is required: + +.. code:: cpp + + do { + /* etc... */ + } while (argument); + +Preprocessor Directives +======================= + +``#if`` and ``#endif`` +---------------------- + +``#if`` should have its closing #endif commented with the condition used +(preceded by a single space): + +.. code:: cpp + + #if MACRO_IS_ENABLED + /* etc... */ + #endif /* MACRO_IS_ENABLED */ + +If the condition is complicated, the closing comment can be abbreviated: + +.. code:: cpp + + #if MACRO_IS_ENABLED && (OTHER_MACRO_IS_ENABLED || \ + OTHER_OTHER_MACRO_IS_ENABLED) + /* etc... */ + #endif /* MACRO_IS_ENABLED && (OTHER_MACRO...) */ + +``#else`` +--------- + +If an ``#if`` makes use of an ``#else`` a comment should express the negated +condition (preceded by a single space): + +.. code:: cpp + + #if MACRO_IS_ENABLED + /* etc... */ + #else /* !MACRO_IS_ENABLED */ + /* etc... */ + #endif /* MACRO_IS_ENABLED */ + +``#elif`` +--------- + +If an ``#if`` makes use of an ``#elif``, no change to comments is performed: + +.. code:: cpp + + #if MACRO_IS_ENABLED + /* etc... */ + #elif OTHER_MACRO_IS_ENABLED + /* etc... */ + #endif /* MACRO_IS_ENABLED */ + +Templates +========= + +Templates follow the rules of the respective thing being templated, with +the exception that the name for templates declaring a type should not +follow the normal naming convention. For class and alias templates, no +``a_`` or ``an_`` qualifier is used, instead an uppercase letter starts the +name (e.g., ``Dyn_array``). + +Template Parameters +------------------- + +Template parameters, like template declarations, have their own naming +convention. They should be named ``a_``/``an_`` followed by a capital +letter, and then a descriptive name, e.g., + +.. code:: cpp + + template + struct My_template; + +If multiple template parameters need to be denoted as the "1st, 2nd, 3rd, +etc." version of a parameter, capital letters can be used to denote this, +e.g., + +.. code:: cpp + + template + struct Thingy_helper; + +Special Cases +============= + +Pointer & Reference Types +------------------------- + +The rule for pointer and reference types is that the pointer or ref qualifier +accompanies the name being typed (for purposes of a function, consider the +return type the "type" of the function) e.g., + +.. code:: cpp + + void foo(int *result, const thingy &a) + /* + A descriptive comment. + */ + { + int &c = a.value; + + *result = c; + } /* foo */ + + + a_thingy *alloc_thingy(); + +Empty Loop Bodies +----------------- + +Empty compound statements (e.g., function bodies and loop bodies) should be +spelled "``{}``" (no space) and follow the looping statement on the same line, +e.g., + +.. code:: cpp + + for (x = 0; x < y; x *= 2) {} + + while (try_op(x)) {} + +Annotating Function Arguments +----------------------------- + +When a function is called with an argument of a fixed value (e.g., a +``TRUE`` or ``FALSE`` value for a "flag" argument) the argument should be +annotated with a comment naming the associated parameter, e.g., + +.. code:: cpp + + int chars = count_characters(str, /*include_whitespace=*/FALSE); + +When ``NULL`` is passed, it should either follow the same convention or +be cast to the parameter's type, e.g., + +.. code:: cpp + + some_func(one_thing, /*associated_thing=*/NULL); + other_func(something_else, (a_foo*)NULL); + +Wrapping Function Calls +----------------------- + +Function calls that cause the line length to exceed 79 characters can be +handled one of two ways. + +If the function call is initializing a variable, and would otherwise fit on the +line, it can be moved down a line and right aligned: + +.. code:: cpp + + int x = + my_very_long_function(a, b, c, d, e, f, g, h); + +Otherwise, the function call should be wrapped on the arguments, aligning +continuation lines with the "``(``" of the function call; if there is a +single argument that cannot fit between the "``(``" column and the right +margin, the call should be broken after the "``(``" and all continuation lines +aligned with the position resulting from right-justifying the longest +argument. The exact style for wrapping the arguments is not specified, but +in general developers should, in the interest of compact code, flow as many +arguments together as will fit on each line: + +.. code:: cpp + + int x = my_very_long_function(a, b, c, d, e, f, + g, h); + +If arguments have some logical relation, e.g., for an area function, these +arguments can be grouped to emphasize the relation instead of flowing for +maximal compactness: + +.. code:: cpp + + compute_area_of_points(x1, y1, z1, + x2, y2, z2); + +In cases where the arguments are annotated with embedded comments, it may be +desirable to distribute them across multiple lines for clarity and neatness, +e.g., + +.. code:: cpp + + f(a, b, c, d, /*is_foo_bar=*/FALSE, + /*needs_more_squirrels=*/VERY_FALSE); + +instead of: + +.. code:: cpp + + f(a, b, c, d, /*is_foo_bar=*/FALSE, /*needs_more_squirrels=*/VERY_FALSE); + +Wrapping Array Subscripts +------------------------- + +Array subscripts that cause the line length to exceed 79 characters are +wrapped like a function call whose argument cannot fit: the line is broken +after the "``[``" and the continuation is right-aligned to column 79, including +the closing "``]``" and any punctuation that follows it: + +.. code:: cpp + + pkdp = pragma_description_for_pragma_kind[ + /* something very long (right-aligned to column 79) */]; diff --git a/dev/doc/_sources/cp_gen_be.rst.txt b/dev/doc/_sources/cp_gen_be.rst.txt new file mode 100644 index 0000000..b809f87 --- /dev/null +++ b/dev/doc/_sources/cp_gen_be.rst.txt @@ -0,0 +1,300 @@ +======================= +C++-Generating Back End +======================= + +The C++-generating back end is a "back end" that turns C or C++ intermediate +language back into source text in C or C++. It is designed for +source-to-source-transformation applications, i.e., processors that read in +source code, make some modifications to its meaning (e.g., adding profiling +code), and then write it out as modified. + +The C++-generating back end handles C++, ANSI/ISO C, and K&R C [#f1]_. The +output is in the same language as the input, and means the same thing, but +is not expected to be identical. At the very least, comments are +eliminated and preprocessing is done, which means ``#include`` files are +merged in, macros are expanded, and ``#if``\ s and the like are processed. +The output *will* match the input exactly with regard to entity names and +source line numbers (the latter by use of ``#line`` directives, if +necessary), and in the order of declarations and statements in the source. +In short, it should be possible to compile the output file with a C or C++ +compiler, execute it to get the same results as the original program, and +debug it using the original source text. + +The source code for the C++-generating back end is in ``cp_gen_be.c``; +``cp_gen_be.h`` contains the associated declarations. + +Source Sequence Lists +===================== + +The C++-generating back end requires the source sequence list, which is a +construct that lists all declarations and statements of the source program in +the order of their appearance. It is optional, and must be enabled by the +configuration flag ``GENERATE_SOURCE_SEQUENCE_LISTS``. The source sequence +list stands alongside the "normal" tree-structured intermediate language, as a +sort of table of contents for the IL tree. That is, for a program fragment +that declares variable ``i``, function ``f``, and variable ``j``, the source +sequence list would be a list of three entries, pointing to the IL entries for +``i``, ``f``, and ``j``, and the tree-structured information under those +entries would provide full information on the entities. + +The list is conceptually a single list that runs through the whole compilation +unit, though in actuality it is implemented by a somewhat more complicated data +structure that snakes between the file scope memory region and the function +scope memory regions. That is, however, merely the low-level representation +dictated by the restrictions on pointers between memory regions, and is hidden +by access functions, e.g., ``adv_to_signif_source_sequence_entry``. + +Some entities in the source program may be declared or defined more than once. +For example, a function can be declared and then later defined. For such +cases, one of the occurrences (the definition if there is one) is selected as +the primary declaration, and the source sequence entry for that declaration +points directly at the IL entry for the entity. For all the other +declarations, the source sequence entry on the list points to a source sequence +secondary declaration entry, which points to the IL entry for the entity and +also gives information about that particular declaration, e.g., the source +position and the specific type used (which may differ from that of the +definition by use of typedefs, array bounds, etc.). + +The C++-generating back end operates by traversing the list and generating code +for each construct it encounters. A program is considered to be made up of an +alternation of declarative regions and executable regions. + +In declarative regions, the C++-generating back end steps through the +entries on the source sequence list, each of which points to a declared +entity, and generates declarations. Source sequence entries for class, +struct, union, and enum types that are declared as part of some other +declaration (e.g., "``struct A {int i;} x;``"), called *non-*\ autonomous +declarations, are skipped over without generating a declaration for the +type, but the type is marked to be put out when encountered while putting +out the type of the containing entity (e.g., "``x``" above). All other +declarative source sequence entries are processed immediately. + +In executable regions, the C++-generating back end steps through the source +sequence entries (a flat list) and the IL statement entries (a tree) in tandem, +and generates code for the statements. + +Declarations +============ + +The top-level routine for declaration processing is ``gen_declaration``. It +calls routines like + +* | ``gen_variable_decl``, +* | ``gen_routine_decl``, +* | ``gen_namespace``, +* | ``gen_type_decl``, +* | ``gen_template``, +* | ``gen_using_directive_or_declaration``, and +* | ``gen_instantiation_directive``. + +``gen_type_decl`` breaks the various type-declaration cases down as calls to + +* | ``gen_class_definition``, +* | ``gen_enum_definition``, or +* | ``gen_typedef_decl``. + +``gen_declaration_using_type`` and ``gen_type`` output types in general, by +calling routines in ``il_to_str.c``. + +``gen_secondary_decl`` handles secondary declaration source sequence entries. + +``gen_initializer`` handles initializers on variables. It calls +``gen_dynamic_init`` to handle dynamic initialization. + +``gen_class_definition`` uses normal declaration routines like +``gen_routine_decl`` to put out code for the class members, and also the +following, which handle special kinds of members: + +* | ``gen_field_decl``, +* | ``gen_member_constant_decl``, and +* | ``gen_using_declaration.`` + +``gen_type_decl``, ``gen_variable_decl`` and ``gen_routine_decl`` include +special code to deal with declarations within class definitions. In +particular, they deal with friend declarations. + +Executable Code +=============== + +The top-level routine for executable code processing is ``gen_statement``. +Most statements are straightforward, but the following routines handle the more +complicated cases: + +* | ``gen_block_statement``, +* | ``gen_try_block_statement``, +* | ``gen_switch_statement``, and +* | ``gen_for_statement``. + +Expressions are handled by ``gen_expr``, with some more complicated cases +handled by: + +* | ``gen_new_delete`` and +* | ``gen_temp_init`` + +The expression routines always add parentheses around expressions if there is +any chance of precedence confusion. + +Constants +========= + +Constants are put out by ``gen_constant``, which calls routines in +``il_to_str.c`` to do the actual output. + +``gen_initializer_constant`` handles initializer constants, which include +aggregate constants, ``ck_dynamic_init`` constants, and cases where a reference +is initialized from a constant, as well as the usual kinds of constants. + +Templates and Macros +==================== + +Templates and macros are strange cases in the IL. Both are macro-like, in +that the source provides a prototype that is expanded by the front end on +each use of the construct. That means that template and macro references +are largely invisible in the IL -- one sees only the expanded form and +little evidence that it came from a template or macro reference. + +It is nevertheless desirable to be able to put out the template and macro +definitions in some way so that template instantiation and symbolic debugging +can be done on the generated code. To accommodate this need, the IL optionally +contains entries for templates and macros. These contain normalized textual +representations of the template or macro (e.g., a string like "``#define x(a) +a+1``"). The C++-generating back just puts those out verbatim. (The macro +entries are all put out at the end of the output file, so they won't affect the +already-macro-expanded code that is put out, but they will still be available +for symbolic debuggers.) Note that macro entries are also used for ``#undef`` +directives. See ``gen_template`` and ``gen_macro``. + +Source Output +============= + +The effective position for source output is set by calling +``set_output_position``. That will result in generation of ``#line`` +directives as necessary, but not until some text is actually output, at which +point ``adjust_output_position`` is called. Note that while line number +correspondence is maintained in the output, there is no attempt to maintain +column number correspondence, or even to do appropriate indentation. + +Actual text output is done through + +* | ``write_ch``, +* | ``m_write_ch``, +* | ``write_space``, +* | ``m_write_space``, +* | ``write_tok_ch``, +* | ``m_write_tok_ch``, +* | ``write_tok_str``, +* | ``m_write_tok_str``, +* | ``write_unsigned_num``, and +* | ``write_num``, + +The names that begin with "``m_``" are macros and are intended for those cases +where speed is important. The others are functions. The names that include +"``_tok_``" are used to write complete tokens or sequences of tokens; the +low-level routines are given permission to break long output lines before or +after such text to avoid overly-long lines. + +Troublesome Cases +================= + +Names +----- + +Names are, in general, put out exactly as they appear in the IL. In some +cases, unnamed entities are given generated names. Members of classes are in +general put out as qualified names (e.g., ``A::x``), but sometimes special care +is required: + +* | The declaration of a member within its class must not use a qualified name. + To handle this, a name context stack is maintained (see + ``push_name_context`` and ``pop_name_context``), tracking the current + scope. When immediately within a class definition, the class qualifier for + that class is suppressed. The same thing is done for namespaces. +* | A call of a virtual function with a qualified name suppresses the + virtual-ness of the function, so a qualified name must be used only if that + behavior is desired. +* | In references to nonstatic members of classes (data or function), the + choice of name can have an effect on access control (e.g., for protected + members) and can disambiguate an otherwise ambiguous member name. + ``gen_simple_field_selection`` and ``gen_bound_function`` handle such + references for data and function cases, and call + ``optimized_expr_for_selection`` to determine the class to be used in + naming the member (that's done by examining any implicit casts used in the + member selection). +* | Sometimes, a prefix "``::``" or an elaborated type specifier (e.g., ``class + X``) must be used to distinguish one name from another. One would think + that always generating those would be the appropriate (and easy) thing to + do. It turns out, however, that various compilers have bugs in that area, + and won't accept some valid code generated in that mechanical way. As a + consequence, the C++-generating back end uses the hidden-name information + developed by the front end to generate prefix "``::``", qualified names in + general, and elaborated type specifiers only when they are required. See + ``alloc_hidden_name_fixup`` et al. This processing has an additional + benefit: it handles external variables and functions that are declared + ``extern`` within a function. References to such entities must not use a + "``::``" prefix, because although the entity named is external, and thus in + some sense in the global scope, the name used for it is declared local to + the function. + +See + +* | ``gen_name``, +* | ``gen_unqualified_name``, +* | ``gen_decl_name``, +* | ``gen_class_qualifier``, and +* | ``gen_namespace_qualifier``. + +References +---------- + +Reference types, or rather uses of entities with such types, require some +special attention. In expressions, ``eok_reference_to`` and +``eok_ref_indirect`` occur in order to make explicit the indirection implicit +in the uses of the reference types; these operators are simply ignored when +generating the expressions. + +More subtle is the fact that certain kinds of constants implicitly contain an +"address-of" operation. The ordinary processing of these by ``form_constant`` +adds an ``&`` to the output before writing the constant's value; this ``&`` +must be suppressed when the constant has a reference type (or, more generally, +is used in an lvalue context). This special processing is provided by +``handle_lvalue_constant_node``. + +Prototype Scopes +---------------- + +Prototype scopes (scopes associated with a prototyped function declarator, in +C) cause a particular set of headaches, because while such types cannot be +named outside of the prototype scope, they do nevertheless show up in the types +of objects outside those scopes. For example: + +.. code:: c++ + + void f(struct A {int i;} *p); + void g(enum E {e1}); + main() { + f(0); /* Really f((struct A *)0) */ + g(1); /* Really g((enum E)1) */ + return 0; + } + +The C++-generating back end deals with these by noting such cases and +suppressing the explicit casts in those cases. The conversion is then once +again implicit in the output program. + +See ``is_implicitly_cast_integral_constant``. + +Rewritten Property References +----------------------------- + +References to Microsoft properties are rewritten by the front end. Something +like "``p+1``", referring to a property ``p``, might have been rewritten as +"call the get accessor function for ``p``, add ``1``\ to it, and store the +resulting value by calling the set accessor for ``p``." The C++-generating back +end recovers the original source form. This is based on a field in expression +nodes called ``rewritten_property_reference_kind``, which is set by the front +end to special values to identify certain key nodes in the expansion. See +``gen_prop_event_or_op_synth_call``. Event references are similarly +reconstituted. + +.. [#f1] It cannot be used, however, to generate C from the output of IL + lowering. diff --git a/dev/doc/_sources/decls.rst.txt b/dev/doc/_sources/decls.rst.txt new file mode 100644 index 0000000..f87d801 --- /dev/null +++ b/dev/doc/_sources/decls.rst.txt @@ -0,0 +1,1081 @@ +============ +Declarations +============ + +Declaration scanning is shared among a number of files. What is specific to +class member declarations is found in ``class_decl.c`` and is discussed in the +next chapter. The remainder of declaration processing is found in ``decls.c``, +which contains the top level routines and a number of utility functions; +``decl_spec.c``, which handles declaration specifiers; ``declarator.c``, which +scans declarators; ``func_def.c``, which contains the code to process function +definitions; and ``decl_inits.c``, which contains the code to scan +initializers. ``decls.h``, ``decl_spec.h``, ``declarator.h``, ``func_def.h``, +and ``decl_inits.h`` contain associated declarations. In addition, code for +disambiguating C++ declarations and expressions is found in ``disambig.c``, +with associated declarations in ``disambig.h``. + +Overview +======== + +The top level routine in declaration scanning, and in fact in the overall +compilation process, is ``translation_unit``, which scans a series of +declarations and stops at end of file. The routine it calls is +``scan_nonmember_declaration`` (via the older ``declaration`` interface), which +is also called for local declarations that appear within functions or blocks +(including old-style parameter declarations). (The only declarations that do +not pass through ``declaration`` are class member declarations and new-style +parameter declarations.) + +Since a typical declaration looks like this: + + | *decl-specifiers* *declarator-list* ``;`` + +two principal elements in the structure of ``scan_nonmember_declaration`` are + +* | a call to ``decl_specifiers``, which scans the type specifier, storage + class keyword, and so forth; and +* | a loop to handle a comma-separated list of declarators with successive + calls to ``declarator``. + +There are many details, including a lot of error checking and some special +cases. But in general, after the return from ``declarator``, one of several +routines is called (though not called directly from ``declaration``) to do +additional processing: + +* | When a function body is present ``function_definition`` is called and the + loop is exited. +* | ``decl_variable`` is called for declarations of variables. +* | ``decl_routine`` is called for declarations of non-member functions without + bodies (it is also called via ``function_definition`` when a body is + present). +* | ``decl_typedef`` is called for ``typedef`` declarations. +* | ``decl_parameter`` is called for old-style parameter list declarations. +* | ``define_static_data_member`` is called for C++ static data member + definitions. + +Finally, if an initializer is present in a variable or static data member +declaration, it is scanned by a call to ``initializer``; in cases where default +initialization may be required, ``def_initializer`` is called. + +Other sorts of declarations are handled by the following (via +``check_special_declaration_form``): + +* | ``template_directive_or_declaration`` is called for template declarations, + template instantiation directives, and template specializations (in other + words, declarations that begin with the keyword ``template``). +* | ``namespace_declaration`` is called for namespace and namespace alias + declarations. +* | ``nonmember_using_declaration`` is called for all ``using``-declarations + except those appearing in a class definition. +* | ``using_directive`` is called for ``using``-directives. +* | ``asm_declaration`` is called for declarations that begin with the keyword + ``asm``. +* | ``alias_declaration`` is called for C++11-style alias declarations. +* | ``scan_and_record_cli_delegate_definition`` is called for C++/CLI delegate + definitions. + +Declaration Parse State +----------------------- + +The outline above just lists a few of the many functions involved in parsing +declarations, and many of those functions need to share various bits of state. +The principal structure tracking this state through this process have type +``a_decl_parse_state``. This keeps track of types (declared type, effective +type, etc.), positions (start of declaration, declarator, certain specifier +keywords, etc.), additional declarative attributes (GNU, Microsoft, etc.), and +so forth. + +For declarations involving a declarator, the declared entity's symbol, once +available, is pointed to by ``dps->sym`` where ``dps`` is a pointer to the +declaration parse state for that declaration. + +In most cases the declaration parse state is initialized using the +``init_decl_parse_state`` macro, but when multiple comma-separated declarators +are handled, the state is recycled for each secondary declarator by calling +``start_secondary_declarator`` (which preserves and even restores state +associated with the common declaration specifiers). + +``a_decl_parse_state`` includes a field of type ``an_init_state`` to describe +the processing of any initializer associated with the declaration (although +``an_init_state`` variables can also exist independent of a specific +declaration; see also :ref:`init-components-and-state`). + +The ``a_decl_parse_state`` stucture also maintains a list of "actions" +(pointers to functions accepting a pointer to that state) that should be run at +the end of a declaration; this can be useful when a local declaration element +is encountered that cannot be checked until the declaration has been more or +less completely processed. New actions can be registered by calls to +``add_end_of_parse_action`` (they are eventually run by a call to +``run_end_of_parse_actions``). + +The ``a_decl_parse_state`` structure is not only used by declarations handled +by ``scan_nonmember_declaration``, but also for class member declarations, +parameter declarations, and even when parsing type names in contexts such as +casts and template arguments (through function ``type_name_full``), which isn't +really declaration parsing at all. + +.. _cppcli-assembly-decls: + +Declarations from C++/CLI Assembly Metadata +------------------------------------------- + +In C++/CLI mode, the front end is able to import assembly metadata files. This +is achieved by first transforming the metadata into equivalent C++/CLI source +code, and then parsing that code. Whether metadata is imported implicitly +(because it is the core library file), explicitly through a "preusing" +command-line toption, or explicitly through a ``#using`` directive, the root +function doing the importing is ``import_metadata`` (in ``preproc.c``). This +function sequences the following operations: + +* | It prepares a file for importing by calling ``make_cli_metadata_file`` and + ``import_metadata_file``. +* | If all went well, it calls ``generate_top_level_metadata_code``, which + creates a string containing C++/CLI source representing the + declarations -- but not the definitions -- of the top-level entities + (which are managed class types) in the metadata file. The actual work + for this is done by the "metadata reader" implemented in + ``ms_metadata.cpp`` (a C++ file meant to be compiled only in a + Microsoft environment). +* | Finally, the generated string is passed to + ``scan_top_level_metadata_declarations``, which (much like + ``translation_unit``) repeatedly calls ``declaration`` to internalize the + generated code. + +The definitions of the generated entities [#f1]_ aren't imported until (and +unless) they are needed. When that happens, a process somewhat similar to that +of ``import_metadata`` is performed by ``get_definition_of_class``, but this +time routines to process definitions are called instead of ``declaration``: +``scan_cli_generic_class_definition_from_assembly_import`` for generic entities +(including generic delegates), +``scan_cli_delegate_definition_from_assembly_import`` for non-generic delegate +definitions, and ``scan_class_definition`` for other non-generic class type +definition. +An imported assembly is assigned a number (the "assembly index") and that +number is recorded in the IL representation of class and enum types loaded from +the assembly. +While processing code generated from metadata (top-level or needed +definitions), the global variable ``scanning_generated_code_from_metadata`` is +TRUE. This is used, for example, to suppress certain diagnostics that do not +apply to code generated from metadata. + +Linkage Specifications +====================== + +In C++ the first thing ``declaration`` must check for is the token ``extern`` +followed by a string literal (e.g., ``extern "C"``). This introduces a linkage +specification, which may control a single declaration or a brace-enclosed block +of declarations. In either case ``linkage_specification`` is called. It sets +global variable ``def_external_linkage`` to describe the kind of linkage that +is to be the default for subsequent declarations, and then it calls +``declaration`` again. + +Declarations *vs.* Expressions +============================== + +Inside a function body it is sometimes difficult to determine whether something +is a declaration or an executable statement. In C the presence of a +declaration specifier keyword or a type name is sufficient to disambiguate the +cases, but in C++ it can be more complicated. Similar disambiguation problems +appear in other contexts as well. Here are some examples. + +* | a statement *vs.* a declaration: + + .. code:: c++ + + typedef int I; + I(i); // declaration (= I i); + I(i)++; // cast i to I, then increment +* | with ``operator new``, a parenthesized type *vs.* a placement expression: + + .. code:: c++ + + new (int(1.5)) A // placement + new (int(* )) // type +* | a parenthesized initializer *vs.* a parameter declaration + + .. code:: c++ + + struct A { /* ... */ }; + A a(int(1)); // declare variable a (initialized by + // calling A::A() with arg 1) + A f(int(i)); // declare function f to take an integer + // argument and return an A + +The function ``is_decl_not_expr`` is called in cases where disambiguation is +required. This may in turn use the routines ``prescan_declaration``, +``prescan_decl_specifiers``, ``prescan_declarator``, and +``prescan_function_declarator``. In general, if a sequence of tokens looks +like a declaration, then it is a declaration, even if it could also be an +expression. The technique requires looking ahead as many tokens as necessary +to confirm or disprove the assumption that the token sequence is a declaration; +tokens are cached so that they can be rescanned by the caller. + +Thus, in statement processing, when ``is_decl_not_expr`` returns TRUE the +tokens are scanned as a declaration (``declaration`` is called); otherwise, the +tokens are scanned assuming that they constitute a statement. + +Declaration Scanning +==================== + +Declaration Specifiers +---------------------- + +The principal part of the code for processing declaration specifiers appears in +``decl_spec.c``. + +``decl_specifiers`` scans a list of type specifiers, type qualifiers, and/or +storage class specifiers, and returns (through a ``a_decl_parse_state`` object) +a pointer to a type tree. It is passed a vector of input flags (telling it +that a storage class specifier is allowed, that the declaration is of a class +member, etc.) and it returns additional information about the results of the +scan (reporting that ``inline`` was scanned, that an explicit type specifier +was present, etc.) via the ``a_decl_parse_state`` object that was passed in. + +The specifiers are scanned in a loop. The simple ones are handled directly. +When ``enum`` is seen, ``enum_specifier`` is called. When ``class``, +``struct``, or ``union`` is scanned, ``class_specifier`` is called; the +processing entailed in scanning a class definition (see +``scan_class_definition`` in ``class_decl.c``) is described in the chapter on +Class Declarations. + +A ``typedef`` name may appear as a type specifier, as may a class name in C++. +Therefore, to tell whether an identifier (including a qualified name) is a type +name or a declarator, a call is made to ``curr_type_symbol``; it returns a +symbol pointer when the identifier is a type name and NULL otherwise. Since +class name can also be a constructor name under some conditions, that case is +also checked for by ``is_constructor_decl``. + +The loop continues until it reaches something it does not recognize as a +declaration specifier. Then the accumulated information is combined to create +a type entry (see ``combine_type_specifiers`` and ``add_type_qualifiers``, and +the output flags are set. When no type is explicitly specified, a default type +is returned; ordinarily it is ``int``, but when the declarator is recognized to +be a constructor, the default is a reference to the class type, and for +destructors it is ``void``. + +``decl_specifiers`` is also called to scan a set of type qualifiers only, e.g., +as part of scanning a pointer-declarator. For such cases +``a_type_qualifier_set`` is always returned independently of the type (even +though in the usual case it is also part of the returned type). (See also +``collect_type_qualifiers`` in ``declarator.c``.) + +The details of an ``enum`` declaration are handled by ``enum_specifier``. +First it calls ``scan_tag_name`` (which is also called from +``class_specifier``) to look up the (optional) tag name and return a symbol. +When a brace-enclosed declaration follows the tag name, ``enum_specifier`` +scans the list of enumeration constant declarations, calling +``scan_integral_constant_expression`` when a value is specified. Each +declaration is turned into a constant entry with the proper value, and all of +the constant entries are linked together under the type entry for the +enumerated type. The size of the enumerated type is also determined from the +value. [#f2]_ Note that in C++, unlike C, the types of the enumeration and its +constants are always the same. + +Declarators +----------- + +Most of the code for scanning declarators is found in ``declarator.c``. + +``declarator`` scans a declarator. It can scan either a real declarator or an +abstract declarator. It receives as input (via the ``a_decl_parse_state`` +object tracking that declaration) the type from an associated specifiers list, +and combines that type with the type information in the declarator. It also +returns a symbol locator for the name declared in the middle of the declarator. +For an abstract declarator, it returns an error locator. It takes as input a +vector of flags to direct its processing, and it returns a vector of output +flags to report results to the caller (again via the ``a_decl_parse_state`` +object). + +``declarator`` is the top-level interface and calls ``r_declarator``, which is +recursive. Declarator processing has three parts: + +* | ``pointer_declarator`` is called to handle pointer modifiers (``*``) and in + C++ references (``&``) and pointer-to-member syntax. There can be more + than one such modifier, and each can be accompanied by one or more type + qualifiers. These are combined with the type returned by + ``decl_specifiers``; the routines invoked to construct the new types are + ``make_pointer_type``, ``make_reference_type``, + ``make_rvalue_reference_type``, and ``pointer_to_member_type``. +* | The middle section is either an identifier (or the place where one would + be, for an abstract declarator) or a nested declarator enclosed in + parentheses. The left parenthesis is ambiguous in an abstract declarator, + so the routine looks one token past it to disambiguate the function + declarator case from the nested declarator case. The declarator + identifier, scanned by ``scan_real_declarator_id``, may be a simple + identifier, a qualified name, [#f3]_ a destructor name, or a token sequence + representing an overloaded operator or a user-defined conversion (such as + ``operator+`` or ``operator int``). +* | The third section consists of zero or more function or array declarators, + for which calls are made to ``function_declarator`` or + ``array_declarator``. + + * | ``function_declarator`` scans the parameter list (an old-style id list, a + prototype parameter list, or ``void``) and builds a function type. For a + top-level function type some additional information is returned in a + block called ``func_info``, which is returned to the caller to assist + with later function processing; most notably, this includes a list of the + identifier names in an old-style id list. If the function declarator is + a prototype, and if any tags are declared in the prototype, a prototype + scope is created. + * | ``array_declarator`` scans constant and nonconstant array dimensions (the + latter for variable length arrays in C mode and type names in ``new`` + expressions in C++). + + | The processing for VLA declarations has several twists. In the ordinary + case in which a VLA declaration appears at function or block scope, a VLA + dimension entry is created and an ``stmk_set_vla_size`` statment is put + out. If the VLA declaration appears in a function prototype, then the + dimension expression may be unspecified (i.e., the\ ``[*]`` syntax is + accepted); this is not permitted, however, when the function prototype + belongs to a function definition, but this check is delayed till + ``scan_function_body``. If the dimension expression *is* specified in a + function prototype scope, a fixup entry is created and processing is + completed in ``scan_function_body``: once the routine's IL scope has been + created, the VLA dimension entry can be allocated and any references to + parameter variables can be properly incorporated into the VLA dimension + expression. + +The type information from the three sections is combined into a single type +tree. The routine that combines derived types is ``add_to_derived_type_list``; +aside from the purely mechanical task of joining types, it also does error +checking, and calls ``set_type_size`` once all the parts of a derived type have +come together. + +Information about the *declarator-id* is returned from ``declarator`` in a +symbol locator. + +C++/CLI Type Constructs +----------------------- + +C++/CLI adds several type composition mechanisms: handles, tracking references, +interior pointers, pin pointers, CLI arrays, and delegates. It also adds new +class type and enum type variations. + +The C++/CLI core library (which is always imported, and is usually +``mscorlib.dll``) defines a number of special "value class types" (e.g., +``System::Int32``) that map onto fundamental types (like ``int``). When the +type scanned by ``decl_specifiers`` is such a special class type, it is +immediately replaced by the corresponding fundamental type (by a call to +``fundamental_type_from_system_type``). However, if a handle to a fundamental +type with a corresponding value class type is formed, the fundamental type is +replaced by the class type (through a call to ``boxed_type_for``, which in turn +calls ``system_type_from_fundamental_type``). Handles to enumeration type are +handled similarly: A C++/CLI value class type is created that "boxes" the +enumeration (see ``make_boxed_enum_type``), and the handle is to that class +type. + +Syntactically, handles and tracking references are like pointers and references +that use different declarator operators ("``^``" and "``%``" respectively). +They have different semantics and constraints, however. Many of the basic +constraints on their underlying types are checked in +``f_check_cli_type_pointed_to``. + +Like handles and tracking references, C++/CLI interior pointers and pin +pointers are represented using ``tk_pointer`` entries. However, the syntax to +express interior pointers and pin pointers uses template-like angle brackets +(e.g., ``cli::pin_ptr``) instead of declarator operators. The front end +implements support for that syntax by predefining special alias templates +``cli::pin_ptr`` and ``cli::interior_ptr`` (see +``make_symbol_for_cli_interior_ptr`` and ``make_symbol_for_cli_pin_ptr``) that +rely on internal ``__declspec`` attributes to form the aliased ``tk_pointer`` +type. + +CLI arrays are instances of a ref class template ``cli::array`` +(see ``make_symbol_for_cli_array``). Instances of this template have the flag +``is_cli_array`` set (in their class type supplement); this simplifies, among +other things, the implementation of the function ``is_cli_array_type``). CLI +arrays can mostly only be used via handles-to-CLI-arrays (see +``check_invalid_use_of_special_cli_class_type``). + +A delegate is a special kind of generated reference class type that +encapsulates an "invocation list" (see :ref:`cppcli-delegates` for details). +Like CLI arrays, they can mostly only be used via handles-to-delegates. + +C++/CLI function declarators can include a trailing "parameter array" (with +syntax like "``void f(double, ...cli::array ^p)``", where the type must +be a handle to a one-dimensional CLI array). They are akin to traditional C +variadic function arguments ("varargs"), but they are type-safe and limited to +accepting a variadic list of arguments that are all of the same type. A +parameter array is represented with a single ``a_param_type`` entry whose +``is_cli_param_array`` flag is TRUE. + +Completing the Declaration +-------------------------- + +Once the declaration specifiers and the declarator have been scanned, it +remains to put the type and other declarative information together and generate +IL and symbol representations for the objects declared. + +If ``typedef`` was seen among the declaration specifiers, ``decl_typedef`` is +called. It enters a ``tk_typeref`` type entry into the IL and an ``sk_type`` +symbol in the symbol table. In C++ it has some extra processing when the type +passed in to it is that of a tagless class or enum: the ``typedef`` name is +transferred to the class or enum type entry, and in cfront-compatibility mode +the symbol for the class is modified accordingly. + +``define_static_data_member`` is called to process the definition of a static +data member. The IL entry and symbol were created at the original point of +declaration. + +Variables and routines are entered by calling ``decl_variable`` or +``decl_routine``, which are similarly organized functions made fairly +complicated by the need to check the declaration's compatibility with previous +declarations of the same entity. + +* | ``id_linkage`` is used to determine whether the declared name has linkage, + and if so, to what (see ``find_linked_symbol``, which returns a symbol if + there is a previous use in scope). +* | ``qualified_name_redecl_sym`` is called instead of ``id_linkage`` if the + declarator is a namespace-qualified name (e.g., a friend declaration or a + namespace member definition that appears outside the scope of the namespace + to which it belongs); it also calls ``find_linked_symbol``. +* | ``find_linked_symbol`` not only calls the appropriate lookup routine; it + also deals with function overloading and function template specializations + (see ``matching_template_function`` in ``templates.c``). +* | ``create_external_symbol_for_linked_entity`` is called to find any previous + external variable or routine of the same name, even if the previous name + has since gone out of scope; it also checks that the old and new types are + compatible. ``decl_variable`` and ``decl_routine`` use this information to + decide whether to create a new variable or routine entry or instead to + reuse or complete a previous declaration. + +"Block-extern" variables and routines have linkage and are always entered at +the file scope or namespace scope in the intermediate language, but their +symbols belong to the current scope in the symbol table (except in ``pcc`` +mode, where they are entered at the file scope in the symbol table too). When +a ``friend`` declaration introduces a new routine, its symbol is entered in the +innermost enclosing nonclass scope, and the associated routine entry is entered +in the innermost enclosing namespace scope. + +In addition to deciding whether an existing symbol and IL entry can be reused +or new ones need to be created, ``decl_variable`` and ``decl_routine`` are also +responsible for checking type compatibility, storage class, and name-linkage, +and they call the routines that record cross-reference and source-sequence +information. + +Functions with bodies need additional processing. ``function_definition`` +finishes the scanning of a function definition started by ``declaration``. If +there is an old-style parameter list, the declarations are scanned through a +series of calls to ``declaration``. Next, it calls ``decl_routine`` (for +normal functions) or ``define_member_function`` (for member functions) to +retrieve or create the function's symbol and routine entry. + +Then, ``scan_function_body`` is called. First, the scope stack is fixed up -- +if the routine is a member function defined outside the class body, the scope +of the class of which it is a member is reactivated, or, if it is a namespace +member appearing outside the scope of the namespace, a namespace extension +scope is pushed -- after which the routine's own function scope is pushed. + +Function parameter processing is completed within the function scope, so that +parameter variables will be entered into the symbol table correctly. A pass is +made over the linked list of ``a_param_type`` entries recorded in the function +type and the linked list of ``a_param_id`` entries created from scanning the +parameter declarations (the two lists should be in sync; the latter knows the +name of the parameter, the former only the type), and ``decl_parameter`` is +called to create the parameter variable entries. + +When support for variable length arrays is enabled, a fixup is performed on any +VLA declarations that appeared in the function prototype. If the VLA dimension +expression referred to a parameter, a dummy variable is replaced with the +"real" parameter variable that has just been created. Then, the dimension +expression is copied from the file-scope memory region to the function-scope +memory region, and an entry of type ``a_vla_dimension`` is created to record it +in the IL. + +If it is a constructor that is being defined, ``ctor_intializer`` is called to +scan the constructor initializer list and to enter implicit ctor-initializers; +similar processing is done for a destructor with a call to +``dtor_initializer``. If this definition appears in the midst of statement +processing (either because it is an inline member function of a local class or +a template instantiation), it is necessary to save the structured statement +stack and start a brand new one (see ``new_struct_stmt_stack``). Then +``compound_statement`` can finally be called to scan the body of the function; +the resulting statement tree is recorded in the ``assoc_block`` field of the +function's scope entry. Before returning, ``scan_function_body`` restores the +structured statement stack and pops the various scopes off the scope stack. + +Initialization +============== + +Initialization is a broad topic in C and C++. It includes: + +* | Setting the initial value of a variable as part of its declaration (the + traditional C notion of initialization) +* | Initializing members and bases of a class as part of the execution of a + constructor +* | Initializing a temporary variable as part of a cast or C99-style compound + literal +* | Passing arguments in a function call (parameter variables are initialized + with argument values) + +Furthermore, "default" initialization actions may be required even in the +absence of an explicit source construct, and the binding of references, while +treated as a form of initialization, involves a number of rules of its own. +Also, C++17 structured bindings are sometimes "aliases" for expressions and +those are represented as variables with a special kind of "initializer" +(although arguably those do not correspond to actual initialization). + +Source file ``decl_inits.c`` is primarily concerned with declaration contexts: +Initializing variables and initializing members of classes as part of +constructor definitions (i.e., the first two bullets). It also includes the +structural handling of aggregate initialization (the traditional brace-enclosed +initializers), and that handling is also used in non-declaration contexts; +particularly, in C99-style compound literals and in various C++11-style list +initialization contexts. + +IL Representation +----------------- + +The special case of a variable with static storage duration initialized with a +true constant is represented by associating the ``a_constant`` entry directly +with the ``a_variable`` entry (via the ``an_initializer`` entry embedded in the +variable entry). C++17 structured bindings for array elements and structure +fields are represented as variables with a special kind of "binding" +initializer pointing to the aliased expression (also via the ``an_initializer`` +entry). In all other cases, initialization involves a dynamic element and an +entry of type ``a_dynamic_init`` is used to represent it (see +:ref:`il-dynamic-init`). + +In addition, even for entities that are not initialized (or whose +initialization is "trivial"), a dynamic init entry may nonetheless be generated +to represent the eventual destruction of that entity (assuming that entity has +a nontrivial destructor). + +.. _init-components-and-state: + +Init Components and Init States +------------------------------- + +It is frequently convenient in the front end to separate the parsing of an +initializer from its actual binding to a target entity. When this is done, the +parsing phase produces an "init component" (type ``an_init_component``, defined +in ``expr.h``). Such a component can represent either + +* | an expression, or +* | a C99-style aggregate member designator, or +* | a brace-enclosed list of init components. + +(A fourth kind of "placeholder" init component exists. It represents a +point at which the parsing of a large aggregate initializer has been +suspended for later continuation. This is transparent to the routines +processing initializers because they don't access the ``next`` pointer of +init components directly and instead use macros -- like ``next_elem`` -- that +automatically resume parsing when reaching one of these placeholder +entries.) + +An init component that represents an expression ultimately points to an object +of type ``an_operand`` (see :ref:`expr-operands`), as well as other information +needed for the second ("binding") phase of initializer processing. + +``decl_inits.c`` relies on two functions from ``expr.c`` to scan init +components: ``scan_braced_init_list`` for list initializers (which in +general will return the top component of a tree representing the braced +structure), and ``scan_full_initializer_expr_as_component`` (which will +return a simple expression component). Sometimes, initializers must be +"prescanned" (to deduce the type of a C++11-style ``auto`` declaration): +The two aforementioned functions will retrieve the prescanned init +components from a cache if needed. Eventually, +``free_init_component_list`` must be called on the top-level component +produced for every initializer. + +The binding of an initializer as represented by an init component to its target +entity is generally handled by a call to ``convert_initializer``, except for +aggregate initialization where the structure of the initializer is mapped to +that of the target type using a variety of functions (see +:ref:`decl-aggregate-init`) which eventually call the ``expr.c`` function +``convert_initializer`` for the non-aggregate "leaf" elements of the aggregate +initializer. + +Initializer processing shares a fair amount of information across calls to a +large number of functions. To facilitate this, the information is recorded in +a structure of type ``an_init_state``. This is both an "input" and an "output" +device: Some fields are used to pass information down the initializer +processing functions, while others are used to return results. In particular, +some input fields inhibit the generation of IL entries +(``check_validity_only``) and/or the emission of diagnostics +(``no_diagnostics``): This is needed to handle overload resolution and template +deduction (which requires "tentative" initialization in C++11). + +A declaration parse state block (``a_decl_parse_state``) embeds an init state +for initialization directly associated with a declaration (variable +initializers, particularly), and in that case, the embedded init state also +contains a pointer back to the associated declaration parse state block. + +Variable Initializers +--------------------- + +Variable initializers (including initializers for static data members) are +scanned and processed by calling ``initializer`` in ``decl_inits.c``. After +checking for errors independently of the initializer itself, and if necessary +deducing the type of the variable from the type of the initializer +(``prescan_initializer_for_auto_type_deduction``), the function distinguishes +four syntactic cases: + +#. | parenthesized initializers (a C++ feature; e.g., "``T x(3);``"), +#. | direct list initializers (a C++11 feature; e.g., "``T x{3};``"), +#. | traditional list initializers (e.g., "``T x = {3};``"), and +#. | simple initializers (e.g., "``T x = 3;``"). + +Parenthesized initializers for class types and for template-dependent types are +the only variations that do not use init components as an intermediate +representation of the initializer: Instead, these cases are handled by calls to +``scan_class_parenthesized_initializer`` and +``scan_dependent_type_parenthesized_initializer``, respectively. The remaining +parenthesized cases (i.e., those that cannot involve a constructor and +therefore must allow for only a single parenthesized expression) are handled by +``expr_direct_init_object``. + +Both the C++11-style direct list initialization syntax and the more traditional +list initialization syntax are handled by calls to ``brace_init_variable``, +except that the initialization of a C++/CLI array using traditional list +initialization syntax uses a dedicated routine +``aggr_init_cli_array_with_alloc``. brace_init_variable calls +braced_initializer + +Finally, initializations of the form "``T x =`` *expr*" are handled by +``expr_init_aggr_variable`` (for variables of class or array types) and +``expr_init_scalar_variable`` (for scalar variables). + +Structured bindings to array elements and to fields are technically not +variables (they are aliased to components of the unnamed "container" variable +for the binding), but they are represented though ``a_variable`` entries in the +front end. These entries have an ``initk_binding`` initializer kind and point +to the aliased expression. The routines +``record_struct_binding_expr_for_array_element`` and +``record_struct_binding_expr_for_field`` (both in ``expr.c``) handle this +pseudo-initializers. + +Auto type deduction +^^^^^^^^^^^^^^^^^^^ + +Some modes allow the keyword ``auto`` to be used as a type specifier. In such +cases, the actual type must be deduced from the initializer using rules similar +to those for function template argument deduction. This presents an ordering +challenge: The expression handling routines called by ``initializer`` must know +the type of the entity being initialized (e.g., to determine appropriate +conversions), but that type is not known until the initializer has been +determined. To address this, the initializer for entities declared with the +``auto`` type specifier is prescanned (routine +``prescan_initializer_for_auto_type_deduction`` in ``expr.c``): That process +deduces the actual type of ``auto`` (using the same machinery as that used for +calls of function templates) and records the prescanned init component in the +``a_decl_parse_state`` entity for the current declaration. The routines called +by ``initializer`` to scan init components are aware of this record and will +use it instead of actually scanning tokens when appropriate. + +The same mechanism is also used to support the ``auto`` type specifier in +*new-expression*\ s (``scan_new_operator`` in ``expr.c``) and in +declarations of ``static const`` data members with in-class initializers +(``decl_static_data_member`` in ``class_decl.c``). + +Default Initialization +^^^^^^^^^^^^^^^^^^^^^^ + +C++ entities of class type that are declared without an explicit initializer +are "default-initialized" -- which means calling the class's default +constructor (or, for an array, calling the default constructor for each +element): + +.. code:: c++ + + struct A { A(); /* ... */ } a; // a is default-initialized by A::A() + +The routine ``def_initializer`` is called for declarations without +initializers, and it generates the default initialization if appropriate. +Default initialization is done only for variables and static data members that +are defined in the current translation unit, and not all classes are subject to +default initialization in the same way: + +#. | "POD" structs and unions (roughly, C-style structs: no non-public + members, no user-defined constructor, destructor, or assignment operator, + no base classes, no virtual functions, etc.) are *never* + default-initialized: + + .. code:: c++ + + struct A { int i; }; // POD + A a1; // a1 goes uninitialized + const A a2; // error -- no explicit initializer + +#. | Non-POD classes with an implicitly-declared trivial default constructor + (i.e., classes for which each base class or nonstatic data member of + class type, if any, will in turn be initialized with its own trivial + default constructor) are default-initialized only when the object is + non-``const``: + + .. code:: c++ + + struct B { private: int i; }; // implicit trivial B::B() + B b1; // b1 is default-initialized + const B b2; // error -- no explicit initializer + +#. | Classes with an implicitly-declared nontrivial default constructor are + likewise default-initialized only when the object is non-``const``: + + .. code:: c++ + + struct C { int i; virtual void f(); }; // implicit nontrivial C::C() + C c1; // c1 is default-initialized + const C c2; // error -- no explicit initializer + +#. | Classes with at least one user-declared constructor are default + initialized whether or not the object is ``const``: + + .. code:: c++ + + struct D { int i; D(); }; // user-declared D::D() + D d1; // d1 is default-initialized + const D d2; // d2 is default-initialized + +A further distinction is made between the second and third groups (classes with +trivial vs. nontrivial implicitly declared default constructor): ``b1`` and +``c1`` differ in how their default initialization is implemented. A call to +the nontrivial default constructor ``C::C()`` is actually added to the IL (it +needs to deal with the virtual function info for class ``C``), but the trivial +default constructor ``B::B()`` need not actually be called, since calling it +would have no effect. Its definition is generated in case there might be +compile-time side-effects (see ``reference_to_trivial_default_constructor`` in +``symbol_ref.c``), but the IL for a trivial default constructor does not appear +in the IL. + +.. _decl-aggregate-init: + +Aggregate Initializers +---------------------- + +An aggregate type is an array type or a class type that has no user-provided +constructors. When an entity of such a type is initialized with a +braced-enclosed construct, the front end traverses the initializer structure +and the destination type's structure mapping one onto the other. The result is +an aggregate constant (``ck_aggregate``), which may contain elements that are +not actually constants (i.e., ``ck_dynamic_init`` "constants"). Four cases are +distinguished: + +* | aggregate class types: handled by ``aggr_init_class``, with help from + ``aggr_init_field_designator`` to handle C99- and GNU-style designators, + and from ``aggr_init_class_remainder_if_needed`` to represent nontrivial + initializations (in C++) of fields that have no explicit initializer. +* | array types: handled by ``aggr_init_array``, with help from + ``aggr_init_array_designator`` to handle designators, and from + ``aggr_init_array_remainder_if_needed`` to represent nontrivial + initializations (in C++) of array elements that have no explicit + initializer. +* | template-dependent types: handled by ``aggr_init_generic_element``; since + the structure of the destination type is not known in that case, the + structure of the resulting constant is entirely determined by the + brace-structure of the initializer. +* | C++/CLI array types: handled by ``aggr_init_cli_array`` with help from + ``aggr_init_cli_array_level`` (which deals with the special rules for + deducing CLI array dimensions from the initializer when applicable). + +The cases can be composed (e.g., an aggregate struct can contain an array of +aggregate structs), which is handled through recursion: ``aggr_init_element`` +handles the dispatching of the recursion based on the subaggregate object's +type. Leaf entities (i.e., entities whose initialization doesn't fall into one +of the cases above) are handled by ``aggr_init_simple_element``. Cleanup +actions needed in case of an exception occurring during the initialization of a +leaf entity -- including default initialization -- is handled by calls to +``record_partial_aggregate_cleanup_destruction``. + +The complete handling of a top-level aggregate initialization is initiated +either by a call to ``braced_initializer`` (for the initialization of variables +and static data members, compound literals, and constructor-initializers), or +by a call to ``prep_aggr_initializer`` (for all other expression contexts). + +While "aggregate initializer" mainly deals with the initialization of an entity +of aggregate type with a brace-enclosed construct, it also includes the +initialization of a character array with a string literal. This can happen at +the top-level (e.g., "``char str[] = "text``";") or at a subaggregate level +(e.g., "``X x = { 1, 2, "three" };``"). A central routine for this aspect of +initialization is ``try_string_literal_init``. + +Constructor Initializers +------------------------ + +Constructor initializers can be written explicitly in the source: + +.. code:: c++ + + struct A { + int i, j; + A() : i(1), j{2} // Constructor initializers with parenthesized + {} // and braced syntax, respectively. + }; + +They can also be generated implicitly by the front end for class members and +base classes that must be initialized and are not explicitly initialized in the +source. (This includes, as an extreme case, constructor routines that are +front-end-generated; any needed constructor-initializers would have to be +implicit). + +``ctor_initializer`` builds the proper list of constructor-initializer entries +and attaches it to a constructor routine entry. It is called with a flag that +indicates whether or not it should attempt to scan the source construct (if +not, it just generates a default list without looking at the source). + +The list generated is in the "right" order, that is, the order in which +initialization should be done, which is not necessarily the order in which the +explicit constructor-initializer clauses were written. The list contains three +parts, tracked by the ``a_ctor_init_block`` data structure: direct base +entries, virtual base entries, and field entries. Each initialization is +represented in the IL with an entry of type ``a_constructor_init`` (which in +turn points to a dynamic init entry). + +The explicit clauses are scanned by calling ``scan_mem_initializer``, which +ultimately calls + +* | ``scan_parenthesized_mem_init_args`` for parenthesized initializers (often + in turn calling ``scan_dependent_type_parenthesized_initializer`` for + template-dependent entities, ``scan_class_parenthesized_initializer`` for + class type entities initialized through a constructor call, or + ``expr_direct_init_object`` for other initializations not involving a + constructor). +* | ``braced_initializer`` for C++11-style braced initializers. + +Once any explicit clauses have been scanned, default initializers are generated +for any base classes and members that require them. In addition, in C++11 +mode, implicit constructor initializer entries may be generated for fields with +"field initializers" (see also :ref:`field-inits`): Such entries do not decribe +the initialization directly, but defer to the initializer recorded in the +``a_field`` entry by setting the ``use_field_initializer`` flag to TRUE. + +Destructor-initializers +----------------------- + +The destructor-initializers list attached to a destructor indicates any +destructions required for base classes and members of the destructor's class. +The list is in the order in which the destructions should be done, i.e., the +reverse of the order of the list on the corresponding constructor. + +Unlike in the constructor case, there is no source form for the +destructor-initializers, and therefore all the entries on the list are +front-end generated. + +Type Names in Expressions +========================= + +When a type name appears in an expression, routines that are used in +declaration processing are invoked to scan the type name. + +``type_name`` is called to scan a type that appears in a cast expression or as +an argument to ``sizeof``. It calls [#f4]_ ``decl_specifiers`` and, for +abstractor declarators only, ``declarator``. It returns a pointer to a type. + +``new_type_name`` is called to scan a C++ *new-type-name* or a parenthesized +*type-name* that may appear in a ``new`` expression. Only abstract declarators +are allowed, but a nonconstant bound expression is permitted for the first +array dimension. + +``asm`` Declarations +==================== + +``asm_declaration`` is called when an ``asm`` keyword is encountered. A +parenthesized string literal is scanned and recorded in an entity of kind +``an_asm_entry``. The ``asm``-string is not parsed or validated by the front +end -- it is simply passed as-is to the back end. + +In Microsoft and GNU modes, some syntax variations are accepted, and in GNU +modes, this can involve some limited validation checks. + +Namespaces +========== + +Namespace Declarations +---------------------- + +``namespace_declaration`` is called to process original namespace definitions, +namespace extensions, and declarations of namespace aliases. + +When a namespace is originally declared, an entry of type ``a_namespace`` is +created and an ``sk_namespace`` symbol is entered in the symbol table. Then, +an ``sck_namespace`` scope is pushed, and declarations inside the namespace are +represented by symbols that are entered on the active symbol list of a given +symbol header; when the scope is popped the symbols are moved from the active +list to the inactive list. However, that namespace can be reopened again, in +which case it is an ``sck_namespace_extension`` scope that is pushed onto the +scope stack. It points to the same IL scope as the original ``sck_namespace`` +scope, but symbols that are entered within this scope are added directly to the +inactive list. This affects how name lookup is done inside a namespace +extension definition -- see the :ref:`symbol-table` chapter. + +For both original and extending namespace definitions, once the appropriate +scope has been pushed, a loop is executed to make a series of calls to +``declaration`` until the closing ``}`` of the namespace definition is +encountered. Then the ``sck_namespace`` or ``sck_namespace_extension`` scope +is popped off the scope stack. + +Unnamed namespace definitions are a special case. For an original unnamed +namespace definition, an ``sck_namespace`` scope is immediately pushed and then +popped, a ``using``-directive is simulated, and then an +``sck_namespace_extension`` scope is opened. [#f5]_ In other words, an +original unnamed namespace definition that is written like this + +.. code:: c++ + + namespace { + int i; + } + +is represented internally as if it were + + | ``namespace`` ** ``{ }`` + | ``using namespace`` **\ ``;`` + | ``namespace`` ** ``{`` + | ``int i;`` + | ``}`` + +``namespace_declaration`` also handles declarations of namespace aliases, for +which a namespace IL entry and a namespace symbol are also created. However, +in this case the namespace IL entry has its ``is_namespace_alias`` flag set to +TRUE and points not to an associated IL scope but to the namespace entry it +stands for. + +Using-Directives +---------------- + +A *using-directive* is processed by ``using_directive``, which looks up the +namespace name and calls ``make_using_directive`` to create and enter an entry +of type ``a_using_decl`` and to "activate" the using directive in the current +scope (see ``add_active_using_directive`` in ``scope_stk.c``). The effect of a +*using-directive* on the lookup algorithm is discussed in the Symbol Table +chapter. + +Using-Declarations +------------------ + +A *using-declaration* that appears in a scope other than that of a class +definition is processed by ``nonmember_using_declaration``. [#f6]_ First it +looks up and validates the namespace-qualified or globally qualified name. +Then it enters an ``sk_namespace_projection`` symbol to represent the name +pulled into the current scope by the using-declaration. + +When a *using-declaration* specifies the name of an overloaded function, each +member of the overload set will have its own projection symbol. An overload +set in the current scope may end up with a mix of ``sk_routine`` symbols +(declarations from the current scope) and ``sk_namespace_projection`` symbols +(referring to declarations from another scope). +``conflicts_with_previous_function_decl`` is called to determine if a function +specified by a *using-declaration* is not distinguishable, for purposes of +overloading, from functions actually declared in the current scope. + +An IL entry is created to represent the *using-declaration* (see +``make_using_decl``); it is available to back ends from the ``using_decls`` +list pointed to from the current scope. + +Standard Attributes, GNU Attributes, and ``__declspec`` Attributes +================================================================== + +In declarative contexts, the processing for standard attributes (delimited by +double square brackets) is very similar to that for GNU attributes +("``__attribute((...))``") and Microsoft ``__declspec(...)`` attributes. The +main difference (other than the delimiting tokens) is that standard attributes +have strict "appertaining rules" whereas nonstandard (GNU and Microsoft +``__declspec``) attributes can be placed more loosely. The standard rules are +basically that an attribute applies to the construct immediately preceding it, +except for "prefix attributes" which apply to all the entities denoted by the +declarators of the prefixed declaration. With nonstandard attributes, the +entity modified by an attribute depends on the attribute. For example: + +.. code:: c++ + + [[noreturn]] int [[X]] f [[ nothrow ]] () [[Y]], g(); // (1) + #define A __attribute + A((noreturn)) int A((nothrow)) f() A((pure)), g(); // (2) + +In (1), the ``noreturn`` attribute applies to the functions ``f`` and ``g``, +and any attribute in that location would apply to those entities. The unknown +attribute ``X`` (in (1)) applies to ``int``, ``nothrow`` applies to ``f``, and +``Y`` applies to the function type associated with the function declarator that +precedes it. (There are currently no standard attributes that could appear in +the locations indicated by X and Y, but the language specification does +anticipate their appertainance.) + +While in (2) the ``noreturn`` attribute applies as in (1), the ``nothrow`` +attribute applies to the type of ``f`` (a function type) and the ``pure`` +attribute applies to ``f`` itself. Furthermore, the locations of the +``nothrow`` and ``pure`` attributes can be interchanged with no change of +meaning. + +The principal routines for parsing and applying attributes are described in +detail :ref:`pragmas-and-attributes`. For attributes that apply to +declarations, the attribute application "callback" functions can rely on the +``assoc_info`` field of the attribute entry pointing to the +``a_decl_parse_state`` structure for that declaration. + +.. _ms-attributes: + +Microsoft Attributes +==================== + +In Microsoft mode, Microsoft attributes delimited by single brackets are +accepted. Attributes may, in general, be specified where a declaration is +accepted. In particular, they are accepted in namespace scopes, class scopes, +and in function parameter lists. Attributes have the form: + +.. code:: c++ + + [attribute_name] + [attribute_name(args)] + +When the bracket that begins an attribute is encountered, +``scan_microsoft_attributes`` is used to scan the attributes and create the IL +entries used to represent them. A list of attributes is returned. This list +is later passed to one of the following routines that either add the attributes +to the IL or issue the appropriate diagnostics if the attributes appear in +invalid locations: + +.. code:: c++ + + apply_microsoft_attributes + verify_standalone_attributes + dispose_of_unapplied_attributes + +The attribute scanning routines use an attribute description data structure to +describe the attributes that should be recognized and to describe the argument +lists expected by those attributes. When the +``RECOGNIZE_MICROSOFT_ATTRIBUTES`` macro is TRUE, the front end supplies +attribute descriptions for the documented Microsoft attributes. When +``SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING`` is TRUE, the Microsoft attributes +are recognized in the sense that no "unrecognized attribute" warning is issued, +but they are otherwise treated as unrecognized attributes (see below). + +Each attribute is represented by an entry of type ``an_ms_attribute``. The +entry contains a string representation of the attribute. In addition, a +structured representation is also created for recognized attributes. In the +structured representation, each attribute has a list of associated argument +values. The argument values are checked to verify that they match the kind of +value expected for a given argument (e.g., for a boolean parameter the value +must be true or false). When processing an unrecognized attribute, no semantic +checking of argument values is performed and no checking is done to verify that +a given attribute is used in an acceptable location. + +Attribute processing results in a list of attribute IL entries, and a flag +in the source correspondence that indicates that attributes apply to a +given entity (see the :ref:`intermediate-language` chapter for more +information). The source correspondence flag is only available when the +structured attribute representation is being used. Beyond the error +checking described above, no additional semantic processing of attributes +is performed. For example, no code insertion is performed for the COM +attributes. + +C++/CLI makes use of the same attribute syntax. Currently, however, no +C++/CLI-specific attributes are recognized (and as a consequence no associated +semantics are implemented). + +.. [#f1] The top-level entities imported from assemblies are generic and + nongeneric managed classes, including some expressed using delegate + definition syntax. A delegate whose definition has not yet been + loaded is treated like a ref class without a definition. +.. [#f2] See ``enum_types_can_be_smaller_than_int`` in the configuration + section of this document. +.. [#f3] As an extension it is permitted to use a qualified name as the + declarator in a class member declaration (see + ``simplify_curr_class_qualified_name``). For instance, +.. [#f4] The indirect call is via the more general function ``type_name_full``. +.. [#f5] The reason for this is to correctly handle globally qualified + references to unnamed namespace members within the original namespace + definition the same way as within a subsequent namespace extension. + For example: +.. [#f6] Using-declarations that appear inside a class definition are handled + by ``member_using_declaration`` in ``class_decl.c``, which is + described in the Class Declarations chapter. diff --git a/dev/doc/_sources/err_msgs.rst.txt b/dev/doc/_sources/err_msgs.rst.txt new file mode 100644 index 0000000..72147cb --- /dev/null +++ b/dev/doc/_sources/err_msgs.rst.txt @@ -0,0 +1,10453 @@ +.. _error-messages: + +============== +Error Messages +============== + +.. list-table:: + + * - ``0001``\ + - | ``last_line_incomplete``\ : + | last line of file ends without a newline + * - ``0002``\ + - | ``last_line_backslash``\ : + | last line of file ends with a backslash + * - ``0003``\ + - | ``include_recursion``\ : + | #include file *"xxxx"*\ includes itself + * - ``0004``\ + - | ``out_of_memory``\ : + | out of memory + * - ``0006``\ + - | ``comment_unclosed_at_eof``\ : + | comment unclosed at end of file + * - ``0007``\ + - | ``bad_token``\ : + | unrecognized token + * - ``0008``\ + - | ``unclosed_string``\ : + | missing closing quote + * - ``0009``\ + - | ``nested_comment``\ : + | nested comment is not allowed + * - ``0010``\ + - | ``bad_use_of_sharp``\ : + | "#" not expected here + * - ``0011``\ + - | ``bad_pp_directive_keyword``\ : + | unrecognized preprocessing directive + * - ``0012``\ + - | ``end_of_flush``\ : + | parsing restarts here after previous syntax error + * - ``0013``\ + - | ``exp_file_name``\ : + | expected a file name + * - ``0014``\ + - | ``extra_text_in_pp_directive``\ : + | extra text after expected end of preprocessing directive + * - ``0017``\ + - | ``exp_rbracket``\ : + | expected a "]" + * - ``0018``\ + - | ``exp_rparen``\ : + | expected a ")" + * - ``0019``\ + - | ``extra_chars_on_number``\ : + | extra text after expected end of number + * - ``0020``\ + - | ``undefined_identifier``\ : + | identifier *"xxxx"*\ is undefined + * - ``0021``\ + - | ``useless_type_qualifiers``\ : + | type qualifiers are meaningless in this declaration + * - ``0022``\ + - | ``bad_hex_digit``\ : + | invalid hexadecimal number + * - ``0023``\ + - | ``integer_too_large``\ : + | integer constant is too large + * - ``0024``\ + - | ``bad_octal_digit``\ : + | invalid octal digit + * - ``0025``\ + - | ``zero_length_string``\ : + | quoted string should contain at least one character + * - ``0026``\ + - | ``too_many_characters``\ : + | too many characters in character constant + * - ``0027``\ + - | ``bad_character_value``\ : + | character value is out of range + * - ``0028``\ + - | ``expr_not_constant``\ : + | expression must have a constant value + * - ``0029``\ + - | ``exp_primary_expr``\ : + | expected an expression + * - ``0030``\ + - | ``bad_float_value``\ : + | floating constant is out of range + * - ``0031``\ + - | ``expr_not_integral``\ : + | expression must have integral type + * - ``0032``\ + - | ``expr_not_arithmetic``\ : + | expression must have arithmetic type + * - ``0033``\ + - | ``exp_line_number``\ : + | expected a line number + * - ``0034``\ + - | ``bad_line_number``\ : + | invalid line number + * - ``0035``\ + - | ``error_directive``\ : + | #error directive: *xxxx*\ + * - ``0036``\ + - | ``missing_pp_if``\ : + | the #if for this directive is missing + * - ``0037``\ + - | ``missing_endif``\ : + | the #endif for this directive is missing + * - ``0038``\ + - | ``pp_else_already_appeared``\ : + | directive is not allowed -- an #else has already appeared + * - ``0039``\ + - | ``divide_by_zero``\ : + | division by zero + * - ``0040``\ + - | ``exp_identifier``\ : + | expected an identifier + * - ``0041``\ + - | ``expr_not_scalar``\ : + | expression must have arithmetic or pointer type + * - ``0042``\ + - | ``incompatible_operands``\ : + | operand types are incompatible (*"type"*\ and *"type"*\ ) + * - ``0044``\ + - | ``expr_not_pointer``\ : + | expression must have pointer type + * - ``0045``\ + - | ``cannot_undef_predef_macro``\ : + | #undef may not be used on this predefined name + * - ``0046``\ + - | ``cannot_redef_predef_macro``\ : + | *"entity"*\ is predefined; attempted redefinition ignored + * - ``0047``\ + - | ``bad_macro_redef``\ : + | incompatible redefinition of macro *"entity"*\ (declared at line + *xxxx*\ ) + * - ``0049``\ + - | ``duplicate_macro_param_name``\ : + | duplicate macro parameter name + * - ``0050``\ + - | ``paste_cannot_be_first``\ : + | "##" may not be first in a macro definition + * - ``0051``\ + - | ``paste_cannot_be_last``\ : + | "##" may not be last in a macro definition + * - ``0052``\ + - | ``exp_macro_param``\ : + | expected a macro parameter name + * - ``0053``\ + - | ``exp_colon``\ : + | expected a ":" + * - ``0054``\ + - | ``too_few_macro_args``\ : + | too few arguments in invocation of *entity-kind "entity"*\ + * - ``0055``\ + - | ``too_many_macro_args``\ : + | too many arguments in invocation of *entity-kind "entity"*\ + * - ``0056``\ + - | ``sizeof_function``\ : + | operand of sizeof may not be a function + * - ``0057``\ + - | ``bad_constant_operator``\ : + | this operator is not allowed in a constant expression + * - ``0058``\ + - | ``bad_pp_operator``\ : + | this operator is not allowed in a preprocessing expression + * - ``0059``\ + - | ``bad_constant_function_call``\ : + | function call is not allowed in a constant expression + * - ``0060``\ + - | ``bad_integral_operator``\ : + | this operator is not allowed in an integral constant expression + * - ``0061``\ + - | ``integer_overflow``\ : + | integer operation result is out of range + * - ``0062``\ + - | ``negative_shift_count``\ : + | shift count is negative + * - ``0063``\ + - | ``shift_count_too_large``\ : + | shift count is too large + * - ``0064``\ + - | ``useless_decl``\ : + | declaration does not declare anything + * - ``0065``\ + - | ``exp_semicolon``\ : + | expected a ";" + * - ``0066``\ + - | ``enum_value_out_of_int_range``\ : + | enumeration value is out of "int" range + * - ``0067``\ + - | ``exp_rbrace``\ : + | expected a "}" + * - ``0068``\ + - | ``integer_sign_change``\ : + | integer conversion resulted in a change of sign + * - ``0069``\ + - | ``integer_truncated``\ : + | integer conversion resulted in truncation + * - ``0070``\ + - | ``incomplete_type_not_allowed``\ : + | incomplete type *"type"*\ is not allowed + * - ``0071``\ + - | ``sizeof_bit_field``\ : + | operand of sizeof may not be a bit field + * - ``0075``\ + - | ``bad_indirection_operand``\ : + | operand of "\*" must be a pointer but has type *"type"*\ + * - ``0076``\ + - | ``empty_macro_argument``\ : + | argument to macro is empty + * - ``0077``\ + - | ``missing_decl_specifiers``\ : + | this declaration has no storage class or type specifier + * - ``0078``\ + - | ``initializer_in_param``\ : + | a parameter declaration may not have an initializer + * - ``0079``\ + - | ``exp_type_specifier``\ : + | expected a type specifier + * - ``0080``\ + - | ``storage_class_not_allowed``\ : + | a storage class may not be specified here + * - ``0081``\ + - | ``mult_storage_classes``\ : + | more than one storage class may not be specified + * - ``0082``\ + - | ``storage_class_not_first``\ : + | storage class is not first + * - ``0083``\ + - | ``dupl_type_qualifier``\ : + | type qualifier specified more than once + * - ``0084``\ + - | ``bad_combination_of_type_specifiers``\ : + | invalid combination of type specifiers + * - ``0085``\ + - | ``bad_param_storage_class``\ : + | invalid storage class for a parameter + * - ``0086``\ + - | ``bad_function_storage_class``\ : + | invalid storage class for a function + * - ``0087``\ + - | ``type_specifier_not_allowed``\ : + | a type specifier may not be used here + * - ``0088``\ + - | ``array_of_function``\ : + | array of functions is not allowed + * - ``0089``\ + - | ``array_of_void``\ : + | array of void is not allowed + * - ``0090``\ + - | ``function_returning_function``\ : + | function returning function is not allowed + * - ``0091``\ + - | ``function_returning_array``\ : + | function returning array is not allowed + * - ``0092``\ + - | ``param_id_list_needs_function_def``\ : + | identifier-list parameters may only be used in a function definition + * - ``0093``\ + - | ``function_type_must_come_from_declarator``\ : + | function type may not come from a typedef + * - ``0094``\ + - | ``array_size_must_be_positive``\ : + | the size of an array must be greater than zero + * - ``0095``\ + - | ``array_size_too_large``\ : + | array is too large + * - ``0096``\ + - | ``empty_translation_unit``\ : + | a translation unit must contain at least one declaration + * - ``0097``\ + - | ``bad_function_return_type``\ : + | a function may not return a value of this type + * - ``0098``\ + - | ``bad_array_element_type``\ : + | an array may not have elements of this type + * - ``0099``\ + - | ``decl_should_be_of_param``\ : + | a declaration here must declare a parameter + * - ``0100``\ + - | ``dupl_param_name``\ : + | duplicate parameter name + * - ``0101``\ + - | ``id_already_declared``\ : + | *"xxxx"*\ has already been declared in the current scope + * - ``0102``\ + - | ``nonstd_forward_decl_enum``\ : + | forward declaration of enum type is nonstandard + * - ``0103``\ + - | ``class_too_large``\ : + | class is too large + * - ``0104``\ + - | ``struct_too_large``\ : + | struct or union is too large + * - ``0105``\ + - | ``bad_bit_field_size``\ : + | invalid size for bit field + * - ``0106``\ + - | ``bad_bit_field_type``\ : + | invalid type for a bit field + * - ``0107``\ + - | ``zero_length_bit_field_must_be_unnamed``\ : + | zero-length bit field must be unnamed + * - ``0108``\ + - | ``signed_one_bit_field``\ : + | signed bit field of length 1 + * - ``0109``\ + - | ``expr_not_ptr_to_function``\ : + | expression preceding parentheses of apparent call must have + (pointer-to-) function type + * - ``0110``\ + - | ``exp_definition_of_tag``\ : + | expected either a definition or a tag name + * - ``0111``\ + - | ``code_is_unreachable``\ : + | statement is unreachable + * - ``0112``\ + - | ``exp_while``\ : + | expected "while" + * - ``0114``\ + - | ``never_defined``\ : + | *entity-kind "entity"*\ was referenced but not defined + * - ``0115``\ + - | ``continue_must_be_in_loop``\ : + | a continue statement may only be used within a loop + * - ``0116``\ + - | ``break_must_be_in_loop_or_switch``\ : + | a break statement may only be used within a loop or switch + * - ``0117``\ + - | ``no_value_returned_in_non_void_function``\ : + | non-void *entity-kind "entity"*\ should return a value + * - ``0118``\ + - | ``value_returned_in_void_function``\ : + | a void function may not return a value + * - ``0119``\ + - | ``cast_to_bad_type``\ : + | cast to type *"type"*\ is not allowed + * - ``0120``\ + - | ``bad_return_value_type``\ : + | return value type does not match the function type + * - ``0121``\ + - | ``case_label_must_be_in_switch``\ : + | a case label may only be used within a switch + * - ``0122``\ + - | ``default_label_must_be_in_switch``\ : + | a default label may only be used within a switch + * - ``0124``\ + - | ``default_label_appears_more_than_once``\ : + | default label has already appeared in this switch + * - ``0125``\ + - | ``exp_lparen``\ : + | expected a "(" + * - ``0126``\ + - | ``expr_not_an_lvalue``\ : + | expression must be an lvalue + * - ``0127``\ + - | ``exp_statement``\ : + | expected a statement + * - ``0128``\ + - | ``loop_not_reachable``\ : + | loop is not reachable + * - ``0129``\ + - | ``block_scope_function_must_be_extern``\ : + | a block-scope function may only have extern storage class + * - ``0130``\ + - | ``exp_lbrace``\ : + | expected a "{" + * - ``0131``\ + - | ``expr_not_ptr_to_class``\ : + | expression must have pointer-to-class type but it has type *"type"*\ + * - ``0132``\ + - | ``expr_not_ptr_to_struct_or_union``\ : + | expression must have pointer-to-struct-or-union type but it has type + *"type"*\ + * - ``0133``\ + - | ``exp_member_name``\ : + | expected a member name + * - ``0134``\ + - | ``exp_field_name``\ : + | expected a field name + * - ``0135``\ + - | ``not_a_member``\ : + | *entity-kind "entity"*\ has no member *"xxxx"*\ + * - ``0136``\ + - | ``not_a_field``\ : + | *entity-kind "entity"*\ has no field *"xxxx"*\ + * - ``0137``\ + - | ``expr_not_a_modifiable_lvalue``\ : + | expression must be a modifiable lvalue + * - ``0138``\ + - | ``address_of_register_variable``\ : + | taking the address of a register variable is not allowed + * - ``0139``\ + - | ``address_of_bit_field``\ : + | taking the address of a bit field is not allowed + * - ``0140``\ + - | ``too_many_arguments``\ : + | too many arguments in function call + * - ``0141``\ + - | ``all_proto_params_must_be_named``\ : + | unnamed prototyped parameters not allowed when body is present + * - ``0142``\ + - | ``expr_not_pointer_to_object``\ : + | expression must have pointer-to-object type but it has type *"type"*\ + * - ``0143``\ + - | ``program_too_large``\ : + | program too large or complicated to compile + * - ``0144``\ + - | ``bad_initializer_type``\ : + | a value of type *"type"*\ cannot be used to initialize an entity of + type *"type"*\ + * - ``0145``\ + - | ``cannot_initialize``\ : + | *entity-kind "entity"*\ may not be initialized + * - ``0146``\ + - | ``too_many_initializer_values``\ : + | too many initializer values + * - ``0147``\ + - | ``not_compatible_with_previous_decl``\ : + | declaration is incompatible with *entity-kind "entity"*\ (declared + at line *xxxx*\ ) + * - ``0148``\ + - | ``already_initialized``\ : + | *entity-kind "entity"*\ has already been initialized + * - ``0149``\ + - | ``bad_file_scope_storage_class``\ : + | a global-scope declaration may not have this storage class + * - ``0150``\ + - | ``type_cannot_be_param_name``\ : + | a type name may not be redeclared as a parameter + * - ``0151``\ + - | ``typedef_cannot_be_param_name``\ : + | a typedef name may not be redeclared as a parameter + * - ``0152``\ + - | ``non_zero_int_conv_to_pointer``\ : + | conversion of nonzero integer to pointer + * - ``0153``\ + - | ``expr_not_class``\ : + | expression must have class type but it has type *"type"*\ + * - ``0154``\ + - | ``expr_not_struct_or_union``\ : + | expression must have struct or union type but it has type *"type"*\ + * - ``0155``\ + - | ``old_fashioned_assignment_operator``\ : + | old-fashioned assignment operator + * - ``0156``\ + - | ``old_fashioned_initializer``\ : + | old-fashioned initializer + * - ``0157``\ + - | ``expr_not_integral_constant``\ : + | expression must be an integral constant expression + * - ``0158``\ + - | ``expr_not_an_lvalue_or_function_designator``\ : + | expression must be an lvalue or a function designator + * - ``0159``\ + - | ``decl_incompatible_with_previous_use``\ : + | declaration is incompatible with previous *"entity"*\ (declared at + line *xxxx*\ ) + * - ``0160``\ + - | ``external_name_clash``\ : + | external name conflicts with external name of *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``0161``\ + - | ``unrecognized_pragma``\ : + | unrecognized #pragma + * - ``0163``\ + - | ``cannot_open_temp_file_reason``\ : + | could not open temporary file *"xxxx"*\ : *xxxx*\ + * - ``0165``\ + - | ``too_few_arguments``\ : + | too few arguments in function call + * - ``0166``\ + - | ``bad_float_constant``\ : + | invalid floating constant + * - ``0167``\ + - | ``incompatible_param``\ : + | argument of type *"type"*\ is incompatible with parameter of type + *"type"*\ + * - ``0168``\ + - | ``function_type_not_allowed``\ : + | a function type is not allowed here + * - ``0169``\ + - | ``exp_declaration``\ : + | expected a declaration + * - ``0170``\ + - | ``pointer_outside_base_object``\ : + | pointer points outside of underlying object + * - ``0171``\ + - | ``bad_cast``\ : + | invalid type conversion + * - ``0172``\ + - | ``linkage_conflict``\ : + | external/internal linkage conflict with previous declaration at line + *xxxx*\ + * - ``0173``\ + - | ``float_to_integer_conversion``\ : + | floating-point value does not fit in required integral type + * - ``0174``\ + - | ``expr_has_no_effect``\ : + | expression has no effect + * - ``0175``\ + - | ``subscript_out_of_range``\ : + | subscript out of range + * - ``0177``\ + - | ``declared_but_not_referenced``\ : + | *entity-kind "entity"*\ was declared but never referenced + * - ``0178``\ + - | ``pcc_address_of_array``\ : + | "&" applied to an array has no effect + * - ``0179``\ + - | ``mod_by_zero``\ : + | right operand of "%" is zero + * - ``0180``\ + - | ``old_style_incompatible_param``\ : + | argument is incompatible with formal parameter + * - ``0181``\ + - | ``printf_arg_mismatch``\ : + | argument is incompatible with corresponding format string conversion + (expected type *"type"*\ but argument has type *"type"*\ ) + * - ``0182``\ + - | ``empty_include_search_path``\ : + | could not open source file *"xxxx"*\ (no directories in search list) + * - ``0183``\ + - | ``cast_not_integral``\ : + | type of cast must be integral + * - ``0184``\ + - | ``cast_not_scalar``\ : + | type of cast must be arithmetic or pointer + * - ``0185``\ + - | ``initialization_not_reachable``\ : + | dynamic initialization in unreachable code + * - ``0186``\ + - | ``unsigned_compare_with_zero``\ : + | pointless comparison of unsigned integer with zero + * - ``0187``\ + - | ``assign_where_compare_meant``\ : + | use of "=" where "==" may have been intended + * - ``0188``\ + - | ``mixed_enum_type``\ : + | enumerated type mixed with another type + * - ``0189``\ + - | ``file_write_error``\ : + | error while writing *xxxx*\ file + * - ``0190``\ + - | ``bad_il_file``\ : + | invalid intermediate language file + * - ``0191``\ + - | ``cast_to_qualified_type``\ : + | type qualifier is meaningless on cast type + * - ``0192``\ + - | ``unrecognized_char_escape``\ : + | unrecognized character escape sequence + * - ``0193``\ + - | ``undefined_preproc_id``\ : + | zero used for undefined preprocessing identifier *"xxxx"*\ + * - ``0194``\ + - | ``exp_asm_string``\ : + | expected an asm string + * - ``0195``\ + - | ``asm_func_must_be_prototyped``\ : + | an asm function must be prototyped + * - ``0196``\ + - | ``bad_asm_func_ellipsis``\ : + | an asm function may not have an ellipsis + * - ``0219``\ + - | ``file_delete_error_reason``\ : + | error while deleting file *"xxxx"*\ : *xxxx*\ + * - ``0220``\ + - | ``integer_to_float_conversion``\ : + | integral value does not fit in required floating-point type + * - ``0221``\ + - | ``float_to_float_conversion``\ : + | floating-point value does not fit in required floating-point type + * - ``0222``\ + - | ``bad_float_operation_result``\ : + | floating-point operation result is out of range + * - ``0223``\ + - | ``implicit_func_decl``\ : + | function *"xxxx"*\ declared implicitly + * - ``0224``\ + - | ``too_few_printf_args``\ : + | the format string requires additional arguments + * - ``0225``\ + - | ``too_many_printf_args``\ : + | the format string ends before this argument + * - ``0226``\ + - | ``bad_printf_format_string``\ : + | invalid format string conversion + * - ``0227``\ + - | ``macro_recursion``\ : + | macro recursion + * - ``0228``\ + - | ``nonstd_extra_comma``\ : + | trailing comma is nonstandard + * - ``0229``\ + - | ``enum_bit_field_too_small``\ : + | bit field cannot contain all values of the enumerated type + * - ``0230``\ + - | ``nonstd_bit_field_type``\ : + | nonstandard type for a bit field + * - ``0231``\ + - | ``decl_in_prototype_scope``\ : + | declaration is not visible outside of function + * - ``0232``\ + - | ``decl_of_void_ignored``\ : + | old-fashioned typedef of "void" ignored + * - ``0233``\ + - | ``old_fashioned_field_selection``\ : + | left operand is not a struct or union containing this field + * - ``0234``\ + - | ``old_fashioned_ptr_field_selection``\ : + | pointer does not point to struct or union containing this field + * - ``0235``\ + - | ``var_retained_incomp_type``\ : + | variable *"xxxx"*\ was declared with a never-completed type + * - ``0236``\ + - | ``boolean_controlling_expr_is_constant``\ : + | controlling expression is constant + * - ``0237``\ + - | ``switch_selector_expr_is_constant``\ : + | selector expression is constant + * - ``0238``\ + - | ``bad_param_specifier``\ : + | invalid specifier on a parameter + * - ``0239``\ + - | ``bad_specifier_outside_class_decl``\ : + | invalid specifier outside a class declaration + * - ``0240``\ + - | ``dupl_decl_specifier``\ : + | duplicate specifier in declaration + * - ``0241``\ + - | ``base_class_not_allowed_for_union``\ : + | a union is not allowed to have a base class + * - ``0242``\ + - | ``access_already_specified``\ : + | multiple access control specifiers are not allowed + * - ``0243``\ + - | ``missing_class_definition``\ : + | class or struct definition is missing + * - ``0244``\ + - | ``name_not_member_of_class_or_base_classes``\ : + | qualified name is not a member of class *"type"*\ or its base classes + * - ``0245``\ + - | ``member_ref_requires_object``\ : + | a nonstatic member reference must be relative to a specific object + * - ``0246``\ + - | ``nonstatic_member_def_not_allowed``\ : + | a nonstatic data member may not be defined outside its class + * - ``0247``\ + - | ``already_defined``\ : + | *entity-kind "entity"*\ has already been defined + * - ``0248``\ + - | ``pointer_to_reference``\ : + | pointer to reference is not allowed + * - ``0249``\ + - | ``reference_to_reference``\ : + | reference to reference is not allowed + * - ``0250``\ + - | ``reference_to_void``\ : + | reference to void is not allowed + * - ``0251``\ + - | ``array_of_reference``\ : + | array of reference is not allowed + * - ``0252``\ + - | ``missing_initializer_on_reference``\ : + | reference *entity-kind "entity"*\ requires an initializer + * - ``0253``\ + - | ``exp_comma``\ : + | expected a "," + * - ``0254``\ + - | ``type_identifier_not_allowed``\ : + | type name is not allowed + * - ``0255``\ + - | ``type_definition_not_allowed``\ : + | type definition is not allowed + * - ``0256``\ + - | ``bad_type_name_redeclaration``\ : + | invalid redeclaration of type name *"entity"*\ (declared at line + *xxxx*\ ) + * - ``0257``\ + - | ``missing_initializer_on_const``\ : + | const *entity-kind "entity"*\ requires an initializer + * - ``0258``\ + - | ``this_used_incorrectly``\ : + | "this" may only be used inside a nonstatic member function + * - ``0259``\ + - | ``constant_value_not_known``\ : + | constant value is not known + * - ``0260``\ + - | ``missing_type_specifier``\ : + | explicit type is missing ("int" assumed) + * - ``0261``\ + - | ``missing_access_specifier``\ : + | access control not specified (*"xxxx"*\ by default) + * - ``0262``\ + - | ``not_a_class_or_struct_name``\ : + | not a class or struct name + * - ``0263``\ + - | ``dupl_base_class_name``\ : + | duplicate base class name + * - ``0264``\ + - | ``bad_base_class``\ : + | invalid base class + * - ``0265``\ + - | ``no_access_to_name``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) is inaccessible + * - ``0266``\ + - | ``ambiguous_name``\ : + | *"entity"*\ is ambiguous + * - ``0267``\ + - | ``old_style_parameter_list``\ : + | old-style parameter list (anachronism) + * - ``0268``\ + - | ``declaration_after_statements``\ : + | declaration may not appear after executable statement in block + * - ``0269``\ + - | ``inaccessible_base_class``\ : + | conversion to inaccessible base class *"type"*\ is not allowed + * - ``0274``\ + - | ``improperly_terminated_macro_call``\ : + | improperly terminated macro invocation + * - ``0276``\ + - | ``id_must_be_class_or_namespace_name``\ : + | name followed by "::" must be a class or namespace name + * - ``0277``\ + - | ``bad_friend_decl``\ : + | invalid friend declaration + * - ``0278``\ + - | ``value_returned_in_constructor``\ : + | a constructor or destructor may not return a value + * - ``0279``\ + - | ``bad_destructor_decl``\ : + | invalid destructor declaration + * - ``0280``\ + - | ``class_and_member_name_conflict``\ : + | declaration of a member with the same name as its class + * - ``0281``\ + - | ``global_qualifier_not_allowed``\ : + | global-scope qualifier (leading "::") is not allowed + * - ``0282``\ + - | ``name_not_found_in_file_scope``\ : + | the global scope has no *"xxxx"*\ + * - ``0283``\ + - | ``qualified_name_not_allowed``\ : + | qualified name is not allowed + * - ``0284``\ + - | ``null_reference``\ : + | NULL reference is not allowed + * - ``0285``\ + - | ``brace_initialization_not_allowed``\ : + | initialization with "{...}" is not allowed for object of type + *"type"*\ + * - ``0286``\ + - | ``ambiguous_base_class``\ : + | base class *"type"*\ is ambiguous + * - ``0287``\ + - | ``ambiguous_derived_class``\ : + | derived class *"type"*\ contains more than one instance of class + *"type"*\ + * - ``0288``\ + - | ``derived_class_from_virtual_base``\ : + | cannot convert pointer to base class *"type"*\ to pointer to derived + class *"type"*\ -- base class is virtual + * - ``0289``\ + - | ``no_matching_constructor``\ : + | no instance of constructor *"entity"*\ matches the argument list + * - ``0290``\ + - | ``ambiguous_copy_constructor``\ : + | copy constructor for class *"type"*\ is ambiguous + * - ``0291``\ + - | ``no_default_constructor``\ : + | no default constructor exists for class *"type"*\ + * - ``0292``\ + - | ``not_a_field_or_base_class``\ : + | *"xxxx"*\ is not a nonstatic data member or base class of class + *"type"*\ + * - ``0293``\ + - | ``indirect_nonvirtual_base_class_not_allowed``\ : + | indirect nonvirtual base class is not allowed + * - ``0294``\ + - | ``bad_union_field``\ : + | invalid union member -- class *"type"*\ has a disallowed member + function + * - ``0296``\ + - | ``bad_rvalue_array``\ : + | invalid use of non-lvalue array + * - ``0297``\ + - | ``exp_operator``\ : + | expected an operator + * - ``0298``\ + - | ``inherited_member_not_allowed``\ : + | inherited member is not allowed + * - ``0299``\ + - | ``indeterminate_overloaded_function``\ : + | cannot determine which instance of *entity-kind "entity"*\ is + intended + * - ``0300``\ + - | ``bound_function_must_be_called``\ : + | a pointer to a bound function may only be used to call the function + * - ``0301``\ + - | ``duplicate_typedef``\ : + | typedef name has already been declared (with same type) + * - ``0304``\ + - | ``no_matching_function``\ : + | no instance of *entity-kind "entity"*\ matches the argument list + * - ``0305``\ + - | ``type_def_not_allowed_in_func_type_decl``\ : + | type definition is not allowed in function return type declaration + * - ``0306``\ + - | ``default_arg_not_at_end``\ : + | default argument not at end of parameter list + * - ``0307``\ + - | ``default_arg_already_defined``\ : + | redefinition of default argument + * - ``0308``\ + - | ``ambiguous_overloaded_function``\ : + | more than one instance of *entity-kind "entity"*\ matches the + argument list: + * - ``0309``\ + - | ``ambiguous_constructor``\ : + | more than one instance of constructor *"entity"*\ matches the + argument list: + * - ``0310``\ + - | ``bad_default_arg_type``\ : + | default argument of type *"type"*\ is incompatible with parameter of + type *"type"*\ + * - ``0311``\ + - | ``return_type_cannot_distinguish_functions``\ : + | cannot overload functions distinguished by return type alone + * - ``0312``\ + - | ``no_user_defined_conversion``\ : + | no suitable user-defined conversion from *"type"*\ to *"type"*\ + exists + * - ``0314``\ + - | ``virtual_static_not_allowed``\ : + | only nonstatic member functions may be virtual + * - ``0315``\ + - | ``unqual_function_with_qual_object``\ : + | the object has type qualifiers that are not compatible with the + member function + * - ``0316``\ + - | ``too_many_virtual_functions``\ : + | program too large to compile (too many virtual functions) + * - ``0317``\ + - | ``bad_return_type_on_virtual_function_override``\ : + | return type is not identical to nor covariant with return type + *"type"*\ of overridden virtual function *"entity"*\ + * - ``0318``\ + - | ``ambiguous_virtual_function_override``\ : + | override of virtual *entity-kind "entity"*\ is ambiguous + * - ``0319``\ + - | ``pure_specifier_on_nonvirtual_function``\ : + | pure specifier ("= 0") allowed only on virtual functions + * - ``0320``\ + - | ``bad_pure_specifier``\ : + | badly-formed pure specifier (only "= 0" is allowed) + * - ``0321``\ + - | ``bad_data_member_initialization``\ : + | data member initializer is not allowed + * - ``0322``\ + - | ``abstract_class_object_not_allowed``\ : + | object of abstract class type *"type"*\ is not allowed: + * - ``0323``\ + - | ``function_returning_abstract_class``\ : + | function returning abstract class *"type"*\ is not allowed: + * - ``0324``\ + - | ``duplicate_friend_decl``\ : + | duplicate friend declaration + * - ``0325``\ + - | ``inline_and_nonfunction``\ : + | inline specifier allowed on function declarations only + * - ``0326``\ + - | ``inline_not_allowed``\ : + | "inline" is not allowed + * - ``0327``\ + - | ``bad_storage_class_with_inline``\ : + | invalid storage class for an inline function + * - ``0328``\ + - | ``bad_member_storage_class``\ : + | invalid storage class for a class member + * - ``0329``\ + - | ``local_class_function_def_missing``\ : + | local class member *entity-kind "entity"*\ requires a definition + * - ``0330``\ + - | ``inaccessible_special_function``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) is inaccessible + * - ``0332``\ + - | ``missing_const_copy_constructor``\ : + | class *"type"*\ has no copy constructor to copy a const object + * - ``0333``\ + - | ``definition_of_implicitly_declared_function``\ : + | defining an implicitly declared member function is not allowed + * - ``0334``\ + - | ``no_suitable_copy_constructor``\ : + | class *"type"*\ has no suitable copy constructor + * - ``0335``\ + - | ``linkage_specifier_not_allowed``\ : + | linkage specification is not allowed + * - ``0336``\ + - | ``bad_linkage_specifier``\ : + | unknown external linkage specification + * - ``0337``\ + - | ``incompatible_linkage_specifier``\ : + | linkage specification is incompatible with previous *"entity"*\ + (declared at line *xxxx*\ ) + * - ``0338``\ + - | ``overloaded_function_linkage``\ : + | more than one instance of overloaded function *"entity"*\ has "C" + linkage + * - ``0339``\ + - | ``ambiguous_default_constructor``\ : + | class *"type"*\ has more than one default constructor + * - ``0340``\ + - | ``temp_used_for_ref_init``\ : + | value copied to temporary, reference to temporary used + * - ``0341``\ + - | ``nonmember_operator_not_allowed``\ : + | "operator*xxxx*\ " must be a member function + * - ``0342``\ + - | ``static_member_operator_not_allowed``\ : + | operator may not be a static member function + * - ``0343``\ + - | ``too_many_args_for_conversion``\ : + | no arguments allowed on user-defined conversion + * - ``0344``\ + - | ``too_many_args_for_operator``\ : + | too many parameters for this operator function + * - ``0345``\ + - | ``too_few_args_for_operator``\ : + | too few parameters for this operator function + * - ``0346``\ + - | ``no_params_with_class_type``\ : + | nonmember operator requires a parameter with class type + * - ``0347``\ + - | ``default_arg_expr_not_allowed``\ : + | default argument is not allowed + * - ``0348``\ + - | ``ambiguous_user_defined_conversion``\ : + | more than one user-defined conversion from *"type"*\ to *"type"*\ + applies: + * - ``0349``\ + - | ``no_matching_operator_function``\ : + | no operator *"xxxx"*\ matches these operands + * - ``0350``\ + - | ``ambiguous_operator_function``\ : + | more than one operator *"xxxx"*\ matches these operands: + * - ``0351``\ + - | ``bad_arg_type_for_operator_new``\ : + | first parameter of allocation function must be of type "size_t" + * - ``0352``\ + - | ``bad_return_type_for_op_new``\ : + | allocation function requires "void \*" return type + * - ``0353``\ + - | ``bad_return_type_for_op_delete``\ : + | deallocation function requires "void" return type + * - ``0354``\ + - | ``bad_first_arg_type_for_operator_delete``\ : + | first parameter of deallocation function must be of type "void \*" + * - ``0356``\ + - | ``type_must_be_object_type``\ : + | type must be an object type + * - ``0357``\ + - | ``base_class_already_initialized``\ : + | base class *"type"*\ has already been initialized + * - ``0358``\ + - | ``base_class_init_anachronism``\ : + | base class name required -- *"type"*\ assumed (anachronism) + * - ``0359``\ + - | ``member_already_initialized``\ : + | *entity-kind "entity"*\ has already been initialized + * - ``0360``\ + - | ``missing_base_class_or_member_name``\ : + | name of member or base class is missing + * - ``0361``\ + - | ``assignment_to_this``\ : + | assignment to "this" (anachronism) + * - ``0362``\ + - | ``overload_anachronism``\ : + | "overload" keyword used (anachronism) + * - ``0363``\ + - | ``anon_union_member_access``\ : + | invalid anonymous union -- nonpublic member is not allowed + * - ``0364``\ + - | ``anon_union_member_function``\ : + | invalid anonymous union -- member function is not allowed + * - ``0365``\ + - | ``anon_union_storage_class``\ : + | anonymous union at global or namespace scope must be declared static + * - ``0366``\ + - | ``missing_initializer_on_fields``\ : + | *entity-kind "entity"*\ provides no initializer for: + * - ``0367``\ + - | ``cannot_initialize_fields``\ : + | implicitly generated constructor for class *"type"*\ cannot + initialize: + * - ``0368``\ + - | ``no_ctor_but_const_or_ref_member``\ : + | *entity-kind "entity"*\ defines no constructor to initialize the + following: + * - ``0369``\ + - | ``var_with_uninitialized_member``\ : + | *entity-kind "entity"*\ has an uninitialized const or reference + member + * - ``0370``\ + - | ``var_with_uninitialized_field``\ : + | *entity-kind "entity"*\ has an uninitialized const field + * - ``0371``\ + - | ``missing_const_assignment_operator``\ : + | class *"type"*\ has no assignment operator to copy a const object + * - ``0372``\ + - | ``no_suitable_assignment_operator``\ : + | class *"type"*\ has no suitable assignment operator + * - ``0373``\ + - | ``ambiguous_assignment_operator``\ : + | ambiguous assignment operator for class *"type"*\ + * - ``0375``\ + - | ``missing_typedef_name``\ : + | declaration requires a typedef name + * - ``0377``\ + - | ``virtual_not_allowed``\ : + | "virtual" is not allowed + * - ``0378``\ + - | ``static_not_allowed``\ : + | "static" is not allowed + * - ``0379``\ + - | ``bound_function_cast_anachronism``\ : + | cast of bound function to normal function pointer (anachronism) + * - ``0380``\ + - | ``expr_not_ptr_to_member``\ : + | expression must have pointer-to-member type + * - ``0381``\ + - | ``extra_semicolon``\ : + | extra ";" ignored + * - ``0382``\ + - | ``nonstd_const_member``\ : + | in-class initializer for nonstatic member is nonstandard + * - ``0384``\ + - | ``no_matching_new_function``\ : + | no instance of overloaded *"entity"*\ matches the argument list + * - ``0386``\ + - | ``no_match_for_addr_of_overloaded_function``\ : + | no instance of *entity-kind "entity"*\ matches the required type + * - ``0387``\ + - | ``delete_count_anachronism``\ : + | delete array size expression used (anachronism) + * - ``0389``\ + - | ``cast_to_abstract_class``\ : + | a cast to abstract class *"type"*\ is not allowed: + * - ``0390``\ + - | ``bad_use_of_main``\ : + | function "main" may not be called or have its address taken + * - ``0391``\ + - | ``initializer_not_allowed_on_array_new``\ : + | a new-initializer may not be specified for an array + * - ``0392``\ + - | ``member_function_redecl_outside_class``\ : + | member function *"entity"*\ may not be redeclared outside its class + * - ``0394``\ + - | ``ref_to_nested_function_var``\ : + | reference to local variable of enclosing function is not allowed + * - ``0395``\ + - | ``single_arg_postfix_incr_decr_anachronism``\ : + | single-argument function used for postfix *"xxxx"*\ (anachronism) + * - ``0397``\ + - | ``bad_default_assignment``\ : + | implicitly generated assignment operator cannot copy: + * - ``0398``\ + - | ``nonstd_array_cast``\ : + | cast to array type is nonstandard (treated as cast to *"type"*\ ) + * - ``0399``\ + - | ``class_with_op_new_but_no_op_delete``\ : + | *entity-kind "entity"*\ has an operator new*xxxx*\ () but no default + operator delete*xxxx*\ () + * - ``0400``\ + - | ``class_with_op_delete_but_no_op_new``\ : + | *entity-kind "entity"*\ has a default operator delete*xxxx*\ () but + no operator new*xxxx*\ () + * - ``0401``\ + - | ``base_class_with_nonvirtual_dtor``\ : + | destructor for base class *"entity"*\ (declared at line *xxxx*\ ) is + not virtual + * - ``0403``\ + - | ``member_function_redeclaration``\ : + | invalid redeclaration of member *entity-kind "entity"*\ (declared at + line *xxxx*\ ) + * - ``0404``\ + - | ``inline_main``\ : + | function "main" may not be declared inline + * - ``0405``\ + - | ``class_and_member_function_name_conflict``\ : + | member function with the same name as its class must be a constructor + * - ``0406``\ + - | ``nested_class_anachronism``\ : + | using nested *entity-kind "entity"*\ (anachronism) + * - ``0407``\ + - | ``too_many_params_for_destructor``\ : + | a destructor may not have parameters + * - ``0408``\ + - | ``bad_constructor_param``\ : + | copy constructor for class *"type"*\ may not have a parameter of + type *"type"*\ + * - ``0409``\ + - | ``incomplete_function_return_type``\ : + | *entity-kind "entity"*\ returns incomplete type *"type"*\ + * - ``0410``\ + - | ``protected_access_problem``\ : + | protected *entity-kind "entity"*\ (declared at line *xxxx*\ ) is not + accessible through a *"type"*\ pointer or object + * - ``0411``\ + - | ``param_not_allowed``\ : + | a parameter is not allowed + * - ``0412``\ + - | ``asm_decl_not_allowed``\ : + | an "asm" declaration is not allowed here + * - ``0413``\ + - | ``no_conversion_function``\ : + | no suitable conversion function from *"type"*\ to *"type"*\ exists + * - ``0414``\ + - | ``delete_of_incomplete_class``\ : + | delete of pointer to incomplete class + * - ``0415``\ + - | ``no_constructor_for_conversion``\ : + | no suitable constructor exists to convert from *"type"*\ to + *"type"*\ + * - ``0416``\ + - | ``ambiguous_constructor_for_conversion``\ : + | more than one constructor applies to convert from *"type"*\ to + *"type"*\ : + * - ``0417``\ + - | ``ambiguous_conversion_function``\ : + | more than one conversion function from *"type"*\ to *"type"*\ + applies: + * - ``0418``\ + - | ``ambiguous_conversion_to_builtin``\ : + | more than one conversion function from *"type"*\ to a built-in type + applies: + * - ``0424``\ + - | ``addr_of_constructor_or_destructor``\ : + | a constructor or destructor may not have its address taken + * - ``0426``\ + - | ``nonconst_ref_init_anachronism``\ : + | temporary used for initial value of reference to non-const + (anachronism) + * - ``0427``\ + - | ``qualifier_in_member_declaration``\ : + | qualified name is not allowed in member declaration + * - ``0428``\ + - | ``mixed_enum_type_anachronism``\ : + | enumerated type mixed with another type (anachronism) + * - ``0429``\ + - | ``new_array_size_must_be_nonnegative``\ : + | the size of an array in "new" must be non-negative + * - ``0430``\ + - | ``return_ref_init_requires_temp``\ : + | returning reference to local temporary + * - ``0432``\ + - | ``enum_not_allowed``\ : + | "enum" declaration is not allowed + * - ``0433``\ + - | ``qualifier_dropped_in_ref_init``\ : + | qualifiers dropped in binding reference of type *"type"*\ to + initializer of type *"type"*\ + * - ``0434``\ + - | ``bad_nonconst_ref_init``\ : + | a reference of type *"type"*\ (not const-qualified) cannot be + initialized with a value of type *"type"*\ + * - ``0435``\ + - | ``delete_of_function_pointer``\ : + | a pointer to function may not be deleted + * - ``0436``\ + - | ``bad_conversion_function_decl``\ : + | conversion function must be a nonstatic member function + * - ``0437``\ + - | ``bad_template_declaration_scope``\ : + | a template declaration is not allowed here + * - ``0438``\ + - | ``exp_lt``\ : + | expected a "<" + * - ``0439``\ + - | ``exp_gt``\ : + | expected a ">" + * - ``0440``\ + - | ``missing_template_param``\ : + | template parameter declaration is missing + * - ``0441``\ + - | ``missing_template_arg_list``\ : + | argument list for *entity-kind "entity"*\ is missing + * - ``0442``\ + - | ``too_few_template_args``\ : + | too few arguments for *entity-kind "entity"*\ + * - ``0443``\ + - | ``too_many_template_args``\ : + | too many arguments for *entity-kind "entity"*\ + * - ``0445``\ + - | ``not_used_in_template_function_params``\ : + | *entity-kind "entity"*\ is not used in declaring the parameter types + of *entity-kind "entity"*\ + * - ``0446``\ + - | ``cfront_multiple_nested_types``\ : + | two nested types have the same name: *"entity"*\ and *"entity"*\ + (declared at line *xxxx*\ ) (cfront compatibility) + * - ``0447``\ + - | ``cfront_global_defined_after_nested_type``\ : + | global *"entity"*\ was declared after nested *"entity"*\ (declared + at line *xxxx*\ ) (cfront compatibility) + * - ``0449``\ + - | ``ambiguous_ptr_to_overloaded_function``\ : + | more than one instance of *entity-kind "entity"*\ matches the + required type + * - ``0450``\ + - | ``nonstd_long_long``\ : + | the type "long long" is nonstandard + * - ``0451``\ + - | ``nonstd_friend_decl``\ : + | omission of *"xxxx"*\ is nonstandard + * - ``0452``\ + - | ``return_type_on_conversion_function``\ : + | return type may not be specified on a conversion function + * - ``0456``\ + - | ``runaway_recursive_instantiation``\ : + | excessive recursion at instantiation of *entity-kind "entity"*\ + * - ``0457``\ + - | ``bad_template_declaration``\ : + | *"xxxx"*\ is not a function or static data member + * - ``0458``\ + - | ``bad_nontype_template_arg``\ : + | argument of type *"type"*\ is incompatible with template parameter + of type *"type"*\ + * - ``0459``\ + - | ``init_needing_temp_not_allowed``\ : + | initialization requiring a temporary or conversion is not allowed + * - ``0460``\ + - | ``decl_hides_function_parameter``\ : + | declaration of *"xxxx"*\ hides function parameter + * - ``0461``\ + - | ``nonconst_ref_init_from_rvalue``\ : + | initial value of reference to non-const must be an lvalue + * - ``0463``\ + - | ``template_not_allowed``\ : + | "template" is not allowed + * - ``0464``\ + - | ``not_a_class_template``\ : + | *"type"*\ is not a class template + * - ``0466``\ + - | ``function_template_named_main``\ : + | "main" is not a valid name for a function template + * - ``0467``\ + - | ``union_nonunion_mismatch``\ : + | invalid reference to *entity-kind "entity"*\ (union/nonunion + mismatch) + * - ``0468``\ + - | ``local_type_in_template_arg``\ : + | a template argument may not reference a local type + * - ``0469``\ + - | ``tag_kind_incompatible_with_declaration``\ : + | tag kind of *xxxx*\ is incompatible with declaration of *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``0470``\ + - | ``name_not_tag_in_file_scope``\ : + | the global scope has no tag named *"xxxx"*\ + * - ``0471``\ + - | ``not_a_tag_member``\ : + | *entity-kind "entity"*\ has no tag member named *"xxxx"*\ + * - ``0472``\ + - | ``ptr_to_member_typedef``\ : + | member function typedef (allowed for cfront compatibility) + * - ``0473``\ + - | ``bad_use_of_member_function_typedef``\ : + | *entity-kind "entity"*\ may be used only in pointer-to-member + declaration + * - ``0475``\ + - | ``nonexternal_entity_in_template_arg``\ : + | a template argument may not reference a non-external entity + * - ``0476``\ + - | ``id_must_be_class_or_type_name``\ : + | name followed by "::~" must be a class name or a type name + * - ``0478``\ + - | ``destructor_type_mismatch``\ : + | type used as destructor name does not match type *"type"*\ + * - ``0479``\ + - | ``called_function_redeclared_inline``\ : + | *entity-kind "entity"*\ redeclared "inline" after being called + * - ``0481``\ + - | ``bad_storage_class_on_template_decl``\ : + | invalid storage class for a template declaration + * - ``0482``\ + - | ``no_access_to_type_cfront_mode``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) is an + inaccessible type (allowed for cfront compatibility) + * - ``0484``\ + - | ``invalid_instantiation_argument``\ : + | invalid explicit instantiation declaration + * - ``0485``\ + - | ``not_instantiatable_entity``\ : + | *entity-kind "entity"*\ is not an entity that can be instantiated + * - ``0486``\ + - | ``compiler_generated_function_cannot_be_instantiated``\ : + | compiler generated *entity-kind "entity"*\ cannot be explicitly + instantiated + * - ``0487``\ + - | ``inline_function_cannot_be_instantiated``\ : + | inline *entity-kind "entity"*\ cannot be explicitly instantiated + * - ``0489``\ + - | ``instantiation_requested_no_definition_supplied``\ : + | *entity-kind "entity"*\ cannot be instantiated -- no template + definition was supplied + * - ``0490``\ + - | ``instantiation_requested_and_specialized``\ : + | *entity-kind "entity"*\ cannot be instantiated -- it has been + explicitly specialized + * - ``0493``\ + - | ``no_match_for_type_of_overloaded_function``\ : + | no instance of *entity-kind "entity"*\ matches the specified type + * - ``0494``\ + - | ``nonstd_void_param_list``\ : + | declaring a void parameter list with a typedef is nonstandard + * - ``0495``\ + - | ``cfront_name_lookup_bug``\ : + | global *entity-kind "entity"*\ used instead of *entity-kind + "entity"*\ (cfront compatibility) + * - ``0496``\ + - | ``redeclaration_of_template_param_name``\ : + | template parameter *"xxxx"*\ may not be redeclared in this scope + * - ``0497``\ + - | ``decl_hides_template_parameter``\ : + | declaration of *"xxxx"*\ hides template parameter + * - ``0498``\ + - | ``must_be_prototype_instantiation``\ : + | template argument list must match the parameter list + * - ``0500``\ + - | ``bad_extra_arg_for_postfix_operator``\ : + | extra parameter of postfix "operator*xxxx*\ " must be of type "int" + * - ``0501``\ + - | ``function_type_required``\ : + | an operator name must be declared as a function + * - ``0502``\ + - | ``operator_name_not_allowed``\ : + | operator name is not allowed + * - ``0503``\ + - | ``bad_scope_for_specialization``\ : + | *entity-kind "entity"*\ cannot be specialized in the current scope + * - ``0504``\ + - | ``nonstd_member_function_address``\ : + | nonstandard form for taking the address of a member function + * - ``0505``\ + - | ``too_few_template_params``\ : + | too few template parameters -- does not match previous declaration + (declared at line *xxxx*\ ) + * - ``0506``\ + - | ``too_many_template_params``\ : + | too many template parameters -- does not match previous declaration + (declared at line *xxxx*\ ) + * - ``0507``\ + - | ``template_operator_delete``\ : + | function template for operator delete(void \*) is not allowed + * - ``0508``\ + - | ``class_template_same_name_as_templ_param``\ : + | class template and template parameter may not have the same name + * - ``0510``\ + - | ``unnamed_type_in_template_arg``\ : + | a template argument may not reference an unnamed type + * - ``0511``\ + - | ``enum_type_not_allowed``\ : + | this operation on an enumerated type requires an applicable + user-defined operator function + * - ``0512``\ + - | ``qualified_reference_type``\ : + | type qualifier on a reference type is not allowed + * - ``0513``\ + - | ``incompatible_assignment_operands``\ : + | a value of type *"type"*\ cannot be assigned to an entity of type + *"type"*\ + * - ``0514``\ + - | ``unsigned_compare_with_negative``\ : + | pointless comparison of unsigned integer with a negative constant + * - ``0515``\ + - | ``converting_to_incomplete_class``\ : + | cannot convert to incomplete class *"type"*\ + * - ``0516``\ + - | ``missing_initializer_on_unnamed_const``\ : + | const object requires an initializer + * - ``0517``\ + - | ``unnamed_object_with_uninitialized_field``\ : + | object has an uninitialized const or reference member + * - ``0518``\ + - | ``nonstd_pp_directive``\ : + | nonstandard preprocessing directive + * - ``0519``\ + - | ``unexpected_template_arg_list``\ : + | *entity-kind "entity"*\ may not have a template argument list + * - ``0520``\ + - | ``missing_initializer_list``\ : + | initialization with "{...}" expected for aggregate object + * - ``0521``\ + - | ``incompatible_ptr_to_member_selection_operands``\ : + | pointer-to-member selection class types are incompatible (*"type"*\ + and *"type"*\ ) + * - ``0522``\ + - | ``self_friendship``\ : + | pointless friend declaration + * - ``0523``\ + - | ``period_used_as_qualifier``\ : + | "." used in place of "::" to form a qualified name + * - ``0524``\ + - | ``const_function_anachronism``\ : + | non-const function called for const object (anachronism) + * - ``0525``\ + - | ``dependent_stmt_is_declaration``\ : + | a dependent statement may not be a declaration + * - ``0526``\ + - | ``void_param_not_allowed``\ : + | a parameter may not have void type + * - ``0529``\ + - | ``bad_templ_arg_expr_operator``\ : + | this operator is not allowed in a template argument expression + * - ``0530``\ + - | ``missing_handler``\ : + | try block requires at least one handler + * - ``0531``\ + - | ``missing_exception_declaration``\ : + | handler requires an exception declaration + * - ``0532``\ + - | ``masked_by_default_handler``\ : + | handler is masked by default handler + * - ``0533``\ + - | ``masked_by_handler``\ : + | handler is potentially masked by previous handler for type *"type"*\ + * - ``0534``\ + - | ``local_type_used_in_exception``\ : + | use of a local type to specify an exception + * - ``0535``\ + - | ``redundant_exception_specification_type``\ : + | redundant type in exception specification + * - ``0536``\ + - | ``incompatible_exception_specification``\ : + | exception specification is incompatible with that of previous + *entity-kind "entity"*\ (declared at line *xxxx*\ ): + * - ``0540``\ + - | ``no_exception_support``\ : + | support for exception handling is disabled + * - ``0541``\ + - | ``omitted_exception_specification``\ : + | allowing all exceptions is incompatible with previous *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``0542``\ + - | ``cannot_create_instantiation_request_file``\ : + | could not create instantiation request file *"xxxx"*\ + * - ``0543``\ + - | ``non_arith_operation_in_templ_arg``\ : + | non-arithmetic operation not allowed in nontype template argument + * - ``0544``\ + - | ``local_type_in_nonlocal_var``\ : + | use of a local type to declare a nonlocal variable + * - ``0545``\ + - | ``local_type_in_function``\ : + | use of a local type to declare a function + * - ``0546``\ + - | ``branch_past_initialization``\ : + | transfer of control bypasses initialization of: + * - ``0548``\ + - | ``branch_into_handler``\ : + | transfer of control into an exception handler + * - ``0549``\ + - | ``used_before_set``\ : + | *entity-kind "entity"*\ is used before its value is set + * - ``0550``\ + - | ``set_but_not_used``\ : + | *entity-kind "entity"*\ was set but never used + * - ``0551``\ + - | ``bad_scope_for_definition``\ : + | *entity-kind "entity"*\ cannot be defined in the current scope + * - ``0552``\ + - | ``exception_specification_not_allowed``\ : + | exception specification is not allowed + * - ``0553``\ + - | ``template_and_instance_linkage_conflict``\ : + | external/internal linkage conflict for *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``0554``\ + - | ``conversion_function_not_usable``\ : + | *entity-kind "entity"*\ will not be called for implicit or explicit + conversions + * - ``0555``\ + - | ``tag_kind_incompatible_with_template_parameter``\ : + | tag kind of *xxxx*\ is incompatible with template parameter of type + *"type"*\ + * - ``0556``\ + - | ``template_operator_new``\ : + | function template for operator new(size_t) is not allowed + * - ``0558``\ + - | ``bad_member_type_in_ptr_to_member``\ : + | pointer to member of type *"type"*\ is not allowed + * - ``0559``\ + - | ``ellipsis_on_operator_function``\ : + | ellipsis is not allowed in operator function parameter list + * - ``0560``\ + - | ``unimplemented_keyword``\ : + | *"entity"*\ is reserved for future use as a keyword + * - ``0561``\ + - | ``cl_invalid_macro_definition``\ : + | invalid macro definition: *xxxx*\ + * - ``0562``\ + - | ``cl_invalid_macro_undefinition``\ : + | invalid macro undefinition: *xxxx*\ + * - ``0565``\ + - | ``cl_il_file_must_be_specified``\ : + | IL file name must be specified if input is + * - ``0570``\ + - | ``cl_error_in_debug_option_argument``\ : + | error in debug option argument + * - ``0571``\ + - | ``cl_invalid_option``\ : + | invalid option: *xxxx*\ + * - ``0572``\ + - | ``cl_back_end_requires_il_file``\ : + | back end requires name of IL file + * - ``0573``\ + - | ``cl_could_not_open_il_file``\ : + | could not open IL file *xxxx*\ + * - ``0574``\ + - | ``cl_invalid_number``\ : + | invalid number: *xxxx*\ + * - ``0575``\ + - | ``cl_incorrect_host_id``\ : + | incorrect host CPU id + * - ``0576``\ + - | ``cl_invalid_instantiation_mode``\ : + | invalid instantiation mode: *xxxx*\ + * - ``0578``\ + - | ``cl_invalid_error_limit``\ : + | invalid error limit: *xxxx*\ + * - ``0585``\ + - | ``cl_vtbl_option_only_in_cplusplus``\ : + | virtual function tables can only be suppressed when compiling C++ + * - ``0586``\ + - | ``cl_anachronism_option_only_in_cplusplus``\ : + | anachronism option can be used only when compiling C++ + * - ``0587``\ + - | ``cl_instantiation_option_only_in_cplusplus``\ : + | instantiation mode option can be used only when compiling C++ + * - ``0588``\ + - | ``cl_auto_instantiation_option_only_in_cplusplus``\ : + | automatic instantiation mode can be used only when compiling C++ + * - ``0589``\ + - | ``cl_implicit_inclusion_option_only_in_cplusplus``\ : + | implicit template inclusion mode can be used only when compiling C++ + * - ``0590``\ + - | ``cl_exceptions_option_only_in_cplusplus``\ : + | exception handling option can be used only when compiling C++ + * - ``0591``\ + - | ``cl_strict_mode_incompatible_with_pcc``\ : + | strict mode is incompatible with K&R mode + * - ``0592``\ + - | ``cl_strict_mode_incompatible_with_cfront``\ : + | strict mode is incompatible with cfront mode + * - ``0593``\ + - | ``cl_missing_source_file_name``\ : + | missing source file name + * - ``0594``\ + - | ``cl_output_file_incompatible_with_multiple_inputs``\ : + | output files may not be specified when compiling several input files + * - ``0595``\ + - | ``cl_too_many_arguments``\ : + | too many arguments on command line + * - ``0596``\ + - | ``cl_no_output_file_needed``\ : + | an output file was specified, but none is needed + * - ``0597``\ + - | ``cl_il_display_requires_il_file_name``\ : + | IL display requires name of IL file + * - ``0598``\ + - | ``void_template_parameter``\ : + | a template parameter may not have void type + * - ``0599``\ + - | ``too_many_unused_instantiations``\ : + | excessive recursive instantiation of *entity-kind "entity"*\ due to + instantiate-all mode + * - ``0600``\ + - | ``cl_strict_mode_incompatible_with_anachronisms``\ : + | strict mode is incompatible with allowing anachronisms + * - ``0601``\ + - | ``void_throw``\ : + | a throw expression may not have void type + * - ``0602``\ + - | ``cl_tim_local_conflicts_with_auto_instantiation``\ : + | local instantiation mode is incompatible with automatic instantiation + * - ``0603``\ + - | ``abstract_class_param_type``\ : + | parameter of abstract class type *"type"*\ is not allowed: + * - ``0604``\ + - | ``array_of_abstract_class``\ : + | array of abstract class *"type"*\ is not allowed: + * - ``0605``\ + - | ``float_template_parameter``\ : + | floating-point template parameter is nonstandard + * - ``0606``\ + - | ``pragma_must_precede_declaration``\ : + | this pragma must immediately precede a declaration + * - ``0607``\ + - | ``pragma_must_precede_statement``\ : + | this pragma must immediately precede a statement + * - ``0608``\ + - | ``pragma_must_precede_decl_or_stmt``\ : + | this pragma must immediately precede a declaration or statement + * - ``0609``\ + - | ``pragma_may_not_be_used_here``\ : + | this kind of pragma may not be used here + * - ``0611``\ + - | ``partial_override``\ : + | overloaded virtual function *"entity"*\ is only partially overridden + in *entity-kind "entity"*\ + * - ``0612``\ + - | ``specialization_of_called_inline_template_function``\ : + | specific definition of inline template function must precede its + first use + * - ``0613``\ + - | ``cl_invalid_error_tag``\ : + | invalid error tag in diagnostic control option: *xxxx*\ + * - ``0614``\ + - | ``cl_invalid_error_number``\ : + | invalid error number in diagnostic control option: *xxxx*\ + * - ``0617``\ + - | ``ptr_to_member_cast_to_ptr_to_function``\ : + | pointer-to-member-function cast to pointer to function + * - ``0618``\ + - | ``no_named_fields``\ : + | struct or union declares no named members + * - ``0619``\ + - | ``nonstd_unnamed_field``\ : + | nonstandard unnamed field + * - ``0620``\ + - | ``nonstd_unnamed_member``\ : + | nonstandard unnamed member + * - ``0624``\ + - | ``not_a_type_name``\ : + | *"xxxx"*\ is not a type name + * - ``0625``\ + - | ``cannot_open_pch_input_file_reason``\ : + | cannot open precompiled header input file *"xxxx"*\ : *xxxx*\ + * - ``0626``\ + - | ``invalid_pch_file``\ : + | precompiled header file *"xxxx"*\ is either invalid or not generated + by this version of the compiler + * - ``0627``\ + - | ``pch_curr_directory_changed``\ : + | precompiled header file *"xxxx"*\ was not generated in this directory + * - ``0628``\ + - | ``pch_header_files_have_changed``\ : + | header files used to generate precompiled header file *"xxxx"*\ have + changed + * - ``0629``\ + - | ``pch_cmd_line_option_mismatch``\ : + | the command line options do not match those used when precompiled + header file *"xxxx"*\ was created + * - ``0630``\ + - | ``pch_file_prefix_mismatch``\ : + | the initial sequence of preprocessing directives is not compatible + with those of precompiled header file *"xxxx"*\ + * - ``0631``\ + - | ``unable_to_get_mapped_memory``\ : + | unable to obtain mapped memory + * - ``0632``\ + - | ``using_pch``\ : + | "*xxxx*\ ": using precompiled header file "*xxxx*\ " + * - ``0633``\ + - | ``creating_pch``\ : + | "*xxxx*\ ": creating precompiled header file "*xxxx*\ " + * - ``0634``\ + - | ``memory_mismatch``\ : + | memory usage conflict with precompiled header file *"xxxx"*\ + * - ``0635``\ + - | ``cl_invalid_pch_size``\ : + | invalid PCH memory size: *xxxx*\ + * - ``0636``\ + - | ``cl_pch_must_be_first``\ : + | PCH options must appear first in the command line + * - ``0637``\ + - | ``out_of_memory_during_pch_allocation``\ : + | insufficient memory for PCH memory allocation + * - ``0638``\ + - | ``cl_pch_incompatible_with_multiple_inputs``\ : + | precompiled header files may not be used when compiling several input + files + * - ``0639``\ + - | ``not_enough_preallocated_memory``\ : + | insufficient preallocated memory for generation of precompiled header + file (*xxxx*\ bytes required) + * - ``0640``\ + - | ``program_entity_too_large_for_pch``\ : + | very large entity in program prevents generation of precompiled + header file + * - ``0641``\ + - | ``cannot_chdir``\ : + | *"xxxx"*\ is not a valid directory + * - ``0642``\ + - | ``cannot_build_temp_file_name``\ : + | cannot build temporary file name + * - ``0643``\ + - | ``restrict_not_allowed``\ : + | "restrict" is not allowed + * - ``0644``\ + - | ``restrict_pointer_to_function``\ : + | a pointer or reference to function type may not be qualified by + "restrict" + * - ``0646``\ + - | ``calling_convention_not_allowed``\ : + | a calling convention modifier may not be specified here + * - ``0647``\ + - | ``conflicting_calling_conventions``\ : + | conflicting calling convention modifiers + * - ``0648``\ + - | ``cl_strict_mode_incompatible_with_microsoft``\ : + | strict mode is incompatible with Microsoft mode + * - ``0649``\ + - | ``cl_cfront_incompatible_with_microsoft``\ : + | cfront mode is incompatible with Microsoft mode + * - ``0650``\ + - | ``calling_convention_ignored``\ : + | calling convention specified here is ignored + * - ``0651``\ + - | ``calling_convention_may_not_precede_nested_declarator``\ : + | a calling convention may not be followed by a nested declarator + * - ``0652``\ + - | ``calling_convention_ignored_for_type``\ : + | calling convention is ignored for this type + * - ``0654``\ + - | ``decl_modifiers_incompatible_with_previous_decl``\ : + | declaration modifiers are incompatible with previous declaration + * - ``0655``\ + - | ``decl_modifiers_invalid_for_this_decl``\ : + | the modifier *"xxxx"*\ is not allowed on this declaration + * - ``0656``\ + - | ``branch_into_try_block``\ : + | transfer of control into a try block + * - ``0657``\ + - | ``incompatible_inline_specifier_on_specific_decl``\ : + | inline specification is incompatible with previous *"entity"*\ + (declared at line *xxxx*\ ) + * - ``0658``\ + - | ``template_missing_closing_brace``\ : + | closing brace of template definition not found + * - ``0659``\ + - | ``cl_wchar_t_option_only_in_cplusplus``\ : + | wchar_t keyword option can be used only when compiling C++ + * - ``0660``\ + - | ``bad_pack_alignment``\ : + | invalid packing alignment value + * - ``0661``\ + - | ``exp_int_constant``\ : + | expected an integer constant + * - ``0662``\ + - | ``call_of_pure_virtual``\ : + | call of pure virtual function + * - ``0663``\ + - | ``bad_ident_string``\ : + | invalid source file identifier string + * - ``0664``\ + - | ``template_friend_definition_not_allowed``\ : + | a class template cannot be defined in a friend declaration + * - ``0665``\ + - | ``asm_not_allowed``\ : + | "asm" is not allowed + * - ``0666``\ + - | ``bad_asm_function_def``\ : + | "asm" must be used with a function definition + * - ``0667``\ + - | ``nonstd_asm_function``\ : + | "asm" function is nonstandard + * - ``0668``\ + - | ``nonstd_ellipsis_only_param``\ : + | ellipsis with no explicit parameters is nonstandard + * - ``0669``\ + - | ``nonstd_address_of_ellipsis``\ : + | "&..." is nonstandard + * - ``0670``\ + - | ``bad_address_of_ellipsis``\ : + | invalid use of "&..." + * - ``0672``\ + - | ``const_volatile_ref_init_anachronism``\ : + | temporary used for initial value of reference to const volatile + (anachronism) + * - ``0673``\ + - | ``bad_const_volatile_ref_init``\ : + | a reference of type *"type"*\ cannot be initialized with a value of + type *"type"*\ + * - ``0674``\ + - | ``const_volatile_ref_init_from_rvalue``\ : + | initial value of reference to const volatile must be an lvalue + * - ``0675``\ + - | ``cl_SVR4_C_option_only_in_ansi_C``\ : + | SVR4 C compatibility option can be used only when compiling ANSI C + * - ``0676``\ + - | ``using_out_of_scope_declaration``\ : + | using out-of-scope declaration of *entity-kind "entity"*\ (declared + at line *xxxx*\ ) + * - ``0677``\ + - | ``cl_strict_mode_incompatible_with_SVR4``\ : + | strict mode is incompatible with SVR4 C mode + * - ``0678``\ + - | ``cannot_inline_call``\ : + | call of *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot + be inlined + * - ``0679``\ + - | ``cannot_inline``\ : + | *entity-kind "entity"*\ cannot be inlined + * - ``0680``\ + - | ``cl_invalid_pch_directory``\ : + | invalid PCH directory: *xxxx*\ + * - ``0681``\ + - | ``exp_except_or_finally``\ : + | expected \__except or \__finally + * - ``0682``\ + - | ``leave_must_be_in_try``\ : + | a \__leave statement may only be used within a \__try + * - ``0688``\ + - | ``not_found_on_pack_alignment_stack``\ : + | *"xxxx"*\ not found on pack alignment stack + * - ``0689``\ + - | ``empty_pack_alignment_stack``\ : + | empty pack alignment stack + * - ``0690``\ + - | ``cl_rtti_option_only_in_cplusplus``\ : + | RTTI option can be used only when compiling C++ + * - ``0691``\ + - | ``inaccessible_elided_cctor``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ), required for + copy that was eliminated, is inaccessible + * - ``0692``\ + - | ``uncallable_elided_cctor``\ : + | *entity-kind "entity"*\ , required for copy that was eliminated, is + not callable because reference parameter cannot be bound to rvalue + * - ``0693``\ + - | ``typeid_needs_typeinfo``\ : + | must be included before typeid is used + * - ``0694``\ + - | ``cannot_cast_away_const``\ : + | *xxxx*\ cannot cast away const or other type qualifiers + * - ``0695``\ + - | ``bad_dynamic_cast_type``\ : + | the type in a dynamic_cast must be a pointer or reference to a + complete class type, or void \* + * - ``0696``\ + - | ``bad_ptr_dynamic_cast_operand``\ : + | the operand of a pointer dynamic_cast must be a pointer to a complete + class type + * - ``0697``\ + - | ``bad_ref_dynamic_cast_operand``\ : + | the operand of a reference dynamic_cast must be an lvalue of a + complete class type + * - ``0698``\ + - | ``dynamic_cast_operand_must_be_polymorphic``\ : + | the operand of a runtime dynamic_cast must have a polymorphic class + type + * - ``0699``\ + - | ``cl_bool_option_only_in_cplusplus``\ : + | bool option can be used only when compiling C++ + * - ``0701``\ + - | ``array_type_not_allowed``\ : + | an array type is not allowed here + * - ``0702``\ + - | ``exp_assign``\ : + | expected an "=" + * - ``0704``\ + - | ``redeclaration_of_condition_decl_name``\ : + | *"xxxx"*\ , declared in condition, may not be redeclared in this scope + * - ``0705``\ + - | ``default_template_arg_not_allowed``\ : + | default template arguments are not allowed for function templates + * - ``0706``\ + - | ``exp_comma_or_gt``\ : + | expected a "," or ">" + * - ``0707``\ + - | ``missing_template_param_list``\ : + | expected a template parameter list + * - ``0708``\ + - | ``incr_of_bool_deprecated``\ : + | incrementing a bool value is deprecated + * - ``0709``\ + - | ``bool_type_not_allowed``\ : + | bool type is not allowed + * - ``0710``\ + - | ``base_class_offset_too_large``\ : + | offset of base class *"entity"*\ within class *"entity"*\ is too + large + * - ``0711``\ + - | ``expr_not_bool``\ : + | expression must have bool type (or be convertible to bool) + * - ``0712``\ + - | ``cl_array_new_and_delete_option_only_in_cplusplus``\ : + | array new and delete option can be used only when compiling C++ + * - ``0713``\ + - | ``based_requires_variable_name``\ : + | *entity-kind "entity"*\ is not a variable name + * - ``0714``\ + - | ``based_not_allowed_here``\ : + | __based modifier is not allowed here + * - ``0715``\ + - | ``based_not_followed_by_star``\ : + | __based does not precede a pointer operator, \__based ignored + * - ``0716``\ + - | ``based_var_must_be_ptr``\ : + | variable in \__based modifier must have pointer type + * - ``0717``\ + - | ``bad_const_cast_type``\ : + | the type in a const_cast must be a pointer, reference, or pointer to + member to an object type + * - ``0718``\ + - | ``bad_const_cast``\ : + | a const_cast can only adjust type qualifiers; it cannot change the + underlying type + * - ``0719``\ + - | ``mutable_not_allowed``\ : + | mutable is not allowed + * - ``0720``\ + - | ``cannot_change_access``\ : + | redeclaration of *entity-kind "entity"*\ is not allowed to alter its + access + * - ``0722``\ + - | ``probable_inadvertent_lbracket_digraph``\ : + | use of alternative token "<:" appears to be unintended + * - ``0723``\ + - | ``probable_inadvertent_sharp_digraph``\ : + | use of alternative token "%:" appears to be unintended + * - ``0724``\ + - | ``namespace_def_not_allowed``\ : + | namespace definition is not allowed + * - ``0725``\ + - | ``missing_namespace_name``\ : + | name must be a namespace name + * - ``0726``\ + - | ``namespace_alias_def_not_allowed``\ : + | namespace alias definition is not allowed + * - ``0727``\ + - | ``namespace_qualified_name_required``\ : + | namespace-qualified name is required + * - ``0728``\ + - | ``namespace_name_not_allowed``\ : + | a namespace name is not allowed + * - ``0729``\ + - | ``bad_combination_of_dll_attributes``\ : + | invalid combination of DLL attributes + * - ``0730``\ + - | ``sym_not_a_class_template``\ : + | *entity-kind "entity"*\ is not a class template + * - ``0731``\ + - | ``array_of_incomplete_type``\ : + | array with incomplete element type is nonstandard + * - ``0732``\ + - | ``allocation_operator_in_namespace``\ : + | allocation operator may not be declared in a namespace + * - ``0733``\ + - | ``deallocation_operator_in_namespace``\ : + | deallocation operator may not be declared in a namespace + * - ``0734``\ + - | ``conflicts_with_using_decl``\ : + | *entity-kind "entity"*\ conflicts with using-declaration of + *entity-kind "entity"*\ + * - ``0735``\ + - | ``using_decl_conflicts_with_prev_decl``\ : + | using-declaration of *entity-kind "entity"*\ conflicts with + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``0736``\ + - | ``cl_namespaces_option_only_in_cplusplus``\ : + | namespaces option can be used only when compiling C++ + * - ``0737``\ + - | ``useless_using_declaration``\ : + | using-declaration ignored -- it refers to the current namespace + * - ``0738``\ + - | ``class_qualified_name_required``\ : + | a class-qualified name is required + * - ``0742``\ + - | ``not_an_actual_member``\ : + | *entity-kind "entity"*\ has no actual member *"xxxx"*\ + * - ``0744``\ + - | ``mem_attrib_incompatible``\ : + | incompatible memory attributes specified + * - ``0745``\ + - | ``mem_attrib_ignored``\ : + | memory attribute ignored + * - ``0746``\ + - | ``mem_attrib_may_not_precede_nested_declarator``\ : + | memory attribute may not be followed by a nested declarator + * - ``0747``\ + - | ``dupl_mem_attrib``\ : + | memory attribute specified more than once + * - ``0748``\ + - | ``dupl_calling_convention``\ : + | calling convention specified more than once + * - ``0749``\ + - | ``type_qualifier_not_allowed``\ : + | a type qualifier is not allowed + * - ``0750``\ + - | ``template_instance_already_used``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was used before + its template was declared + * - ``0751``\ + - | ``static_nonstatic_with_same_param_types``\ : + | static and nonstatic member functions with same parameter types + cannot be overloaded + * - ``0752``\ + - | ``no_prior_declaration``\ : + | no prior declaration of *entity-kind "entity"*\ + * - ``0753``\ + - | ``template_id_not_allowed``\ : + | a template-id is not allowed + * - ``0754``\ + - | ``class_qualified_name_not_allowed``\ : + | a class-qualified name is not allowed + * - ``0755``\ + - | ``bad_scope_for_redeclaration``\ : + | *entity-kind "entity"*\ may not be redeclared in the current scope + * - ``0756``\ + - | ``qualifier_in_namespace_member_decl``\ : + | qualified name is not allowed in namespace member declaration + * - ``0757``\ + - | ``sym_not_a_type_name``\ : + | *entity-kind "entity"*\ is not a type name + * - ``0758``\ + - | ``explicit_instantiation_not_in_namespace_scope``\ : + | explicit instantiation is not allowed in the current scope + * - ``0759``\ + - | ``bad_scope_for_explicit_instantiation``\ : + | *entity-kind "entity"*\ cannot be explicitly instantiated in the + current scope + * - ``0760``\ + - | ``multiple_explicit_instantiations``\ : + | *entity-kind "entity"*\ explicitly instantiated more than once + * - ``0761``\ + - | ``typename_not_in_template``\ : + | typename may only be used within a template + * - ``0762``\ + - | ``cl_special_subscript_cost_option_only_in_cplusplus``\ : + | special_subscript_cost option can be used only when compiling C++ + * - ``0763``\ + - | ``cl_typename_option_only_in_cplusplus``\ : + | typename option can be used only when compiling C++ + * - ``0764``\ + - | ``cl_implicit_typename_option_only_in_cplusplus``\ : + | implicit typename option can be used only when compiling C++ + * - ``0765``\ + - | ``nonstd_character_at_start_of_macro_def``\ : + | nonstandard character at start of object-like macro definition + * - ``0766``\ + - | ``exception_spec_override_incompat``\ : + | exception specification for virtual *entity-kind "entity"*\ is + incompatible with that of overridden *entity-kind "entity"*\ + * - ``0767``\ + - | ``pointer_conversion_loses_bits``\ : + | conversion from pointer to smaller integer + * - ``0768``\ + - | ``generated_exception_spec_override_incompat``\ : + | exception specification for implicitly declared virtual *entity-kind + "entity"*\ is incompatible with that of overridden *entity-kind + "entity"*\ + * - ``0769``\ + - | ``implicit_call_of_ambiguous_name``\ : + | *"entity"*\ , implicitly called from *entity-kind "entity"*\ , is + ambiguous + * - ``0770``\ + - | ``cl_explicit_option_only_in_cplusplus``\ : + | option "explicit" can be used only when compiling C++ + * - ``0771``\ + - | ``explicit_not_allowed``\ : + | "explicit" is not allowed + * - ``0772``\ + - | ``conflicts_with_predeclared_type_info``\ : + | declaration conflicts with *"xxxx"*\ (reserved class name) + * - ``0773``\ + - | ``array_member_initialization``\ : + | only "()" is allowed as initializer for array *entity-kind "entity"*\ + * - ``0774``\ + - | ``virtual_function_template``\ : + | "virtual" is not allowed in a function template declaration + * - ``0775``\ + - | ``anon_union_class_member_template``\ : + | invalid anonymous union -- class member template is not allowed + * - ``0776``\ + - | ``template_depth_mismatch``\ : + | template nesting depth does not match the previous declaration of + *entity-kind "entity"*\ + * - ``0777``\ + - | ``multiple_template_decls_not_allowed``\ : + | this declaration cannot have multiple "template <...>" clauses + * - ``0778``\ + - | ``cl_old_for_init_option_only_in_cplusplus``\ : + | option to control the for-init scope can be used only when compiling + C++ + * - ``0779``\ + - | ``redeclaration_of_for_init_decl_name``\ : + | *"xxxx"*\ , declared in for-loop initialization, may not be + redeclared in this scope + * - ``0780``\ + - | ``hidden_by_old_for_init``\ : + | reference is to *entity-kind "entity"*\ (declared at line *xxxx*\ ) + -- under old for-init scoping rules it would have been *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``0781``\ + - | ``cl_for_init_diff_warning_option_only_in_cplusplus``\ : + | option to control warnings on for-init differences can be used only + when compiling C++ + * - ``0782``\ + - | ``unnamed_class_virtual_function_def_missing``\ : + | definition of virtual *entity-kind "entity"*\ is required here + * - ``0783``\ + - | ``svr4_token_pasting_comment``\ : + | empty comment interpreted as token-pasting operator "##" + * - ``0784``\ + - | ``storage_class_in_friend_decl``\ : + | a storage class is not allowed in a friend declaration + * - ``0785``\ + - | ``templ_param_list_not_allowed``\ : + | template parameter list for *"entity"*\ is not allowed in this + declaration + * - ``0786``\ + - | ``bad_member_template_sym``\ : + | *entity-kind "entity"*\ is not a valid class member template + * - ``0787``\ + - | ``bad_member_template_decl``\ : + | not a valid member class or function template declaration + * - ``0788``\ + - | ``specialization_follows_param_list``\ : + | a template declaration containing a template parameter list may not + be followed by an explicit specialization declaration + * - ``0789``\ + - | ``specialization_of_referenced_template``\ : + | explicit specialization of *entity-kind "entity"*\ must precede the + first use of *entity-kind "entity"*\ + * - ``0790``\ + - | ``explicit_specialization_not_in_namespace_scope``\ : + | explicit specialization is not allowed in the current scope + * - ``0791``\ + - | ``partial_specialization_not_allowed``\ : + | partial specialization of *entity-kind "entity"*\ is not allowed + * - ``0792``\ + - | ``entity_cannot_be_specialized``\ : + | *entity-kind "entity"*\ is not an entity that can be explicitly + specialized + * - ``0793``\ + - | ``specialization_of_referenced_entity``\ : + | explicit specialization of *entity-kind "entity"*\ must precede its + first use + * - ``0794``\ + - | ``template_param_in_elab_type``\ : + | template parameter *"xxxx"*\ may not be used in an elaborated type + specifier + * - ``0795``\ + - | ``old_specialization_not_allowed``\ : + | specializing *entity-kind "entity"*\ requires "template<>" syntax + * - ``0798``\ + - | ``cl_old_specializations_option_only_in_cplusplus``\ : + | option "old_specializations" can be used only when compiling C++ + * - ``0799``\ + - | ``nonstd_old_specialization``\ : + | specializing *entity-kind "entity"*\ without "template<>" syntax is + nonstandard + * - ``0800``\ + - | ``bad_linkage_for_decl``\ : + | this declaration may not have extern "C" linkage + * - ``0801``\ + - | ``not_a_template_name``\ : + | *"xxxx"*\ is not a class or function template name in the current + scope + * - ``0802``\ + - | ``nonstd_default_arg_on_function_template_redecl``\ : + | specifying a default argument when redeclaring an unreferenced + function template is nonstandard + * - ``0803``\ + - | ``default_arg_on_function_template_not_allowed``\ : + | specifying a default argument when redeclaring an already referenced + function template is not allowed + * - ``0804``\ + - | ``pm_derived_class_from_virtual_base``\ : + | cannot convert pointer to member of base class *"type"*\ to pointer + to member of derived class *"type"*\ -- base class is virtual + * - ``0805``\ + - | ``bad_exception_specification_for_specialization``\ : + | exception specification is incompatible with that of *entity-kind + "entity"*\ (declared at line *xxxx*\ ): + * - ``0806``\ + - | ``omitted_exception_specification_on_specialization``\ : + | allowing all exceptions is incompatible with *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``0807``\ + - | ``unexpected_end_of_default_arg``\ : + | unexpected end of default argument expression + * - ``0808``\ + - | ``default_init_of_reference``\ : + | default-initialization of reference is not allowed + * - ``0809``\ + - | ``uninitialized_field_with_const_member``\ : + | uninitialized *entity-kind "entity"*\ has a const member + * - ``0810``\ + - | ``uninitialized_base_class_with_const_member``\ : + | uninitialized base class *"type"*\ has a const member + * - ``0811``\ + - | ``missing_default_constructor_on_const``\ : + | const *entity-kind "entity"*\ requires an initializer -- class + *"type"*\ has no user-provided default constructor + * - ``0812``\ + - | ``missing_default_constructor_on_unnamed_const``\ : + | const object requires an initializer -- class *"type"*\ has no + user-provided default constructor + * - ``0813``\ + - | ``cl_impl_extern_c_conv_option_only_in_cplusplus``\ : + | option "implicit_extern_c_type_conversion" can be used only when + compiling C++ + * - ``0814``\ + - | ``cl_strict_mode_incompatible_with_long_preserving``\ : + | strict mode is incompatible with long preserving rules + * - ``0815``\ + - | ``useless_type_qualifier_on_return_type``\ : + | type qualifier on return type is meaningless + * - ``0816``\ + - | ``type_qualifier_on_void_return_type``\ : + | in a function definition a type qualifier on a "void" return type is + not allowed + * - ``0817``\ + - | ``static_data_member_not_allowed``\ : + | static data member declaration is not allowed in this class + * - ``0818``\ + - | ``invalid_declaration``\ : + | template instantiation resulted in an invalid function declaration + * - ``0819``\ + - | ``ellipsis_not_allowed``\ : + | "..." is not allowed + * - ``0820``\ + - | ``cl_extern_inline_option_only_in_cplusplus``\ : + | option "extern_inline" can be used only when compiling C++ + * - ``0821``\ + - | ``extern_inline_never_defined``\ : + | extern inline *entity-kind "entity"*\ was referenced but not defined + * - ``0822``\ + - | ``invalid_destructor_name``\ : + | invalid destructor name for type *"type"*\ + * - ``0824``\ + - | ``ambiguous_destructor``\ : + | destructor reference is ambiguous -- both *entity-kind "entity"*\ + and *entity-kind "entity"*\ could be used + * - ``0825``\ + - | ``virtual_inline_never_defined``\ : + | virtual inline *entity-kind "entity"*\ was never defined + * - ``0826``\ + - | ``unreferenced_function_param``\ : + | *entity-kind "entity"*\ was never referenced + * - ``0827``\ + - | ``union_already_initialized``\ : + | only one member of a union may be specified in a constructor + initializer list + * - ``0828``\ + - | ``no_array_new_and_delete_support``\ : + | support for "new[]" and "delete[]" is disabled + * - ``0829``\ + - | ``double_for_long_double``\ : + | "double" used for "long double" in generated C code + * - ``0830``\ + - | ``no_corresponding_delete``\ : + | *entity-kind "entity"*\ has no corresponding operator delete*xxxx*\ + (to be called if an exception is thrown during initialization of an + allocated object) + * - ``0831``\ + - | ``useless_placement_delete``\ : + | support for placement delete is disabled + * - ``0832``\ + - | ``no_appropriate_delete``\ : + | no appropriate operator delete is visible + * - ``0833``\ + - | ``ptr_or_ref_to_incomplete_type``\ : + | pointer or reference to incomplete type *"type"*\ is not allowed + * - ``0834``\ + - | ``bad_partial_specialization``\ : + | invalid partial specialization -- *entity-kind "entity"*\ is already + fully specialized + * - ``0835``\ + - | ``incompatible_exception_specs``\ : + | incompatible exception specifications + * - ``0836``\ + - | ``returning_ref_to_local_variable``\ : + | returning reference to local variable + * - ``0837``\ + - | ``nonstd_implicit_int``\ : + | omission of explicit type is nonstandard ("int" assumed) + * - ``0838``\ + - | ``ambiguous_partial_spec``\ : + | more than one partial specialization matches the template argument + list of *entity-kind "entity"*\ + * - ``0840``\ + - | ``partial_spec_is_primary_template``\ : + | a template argument list is not allowed in a declaration of a primary + template + * - ``0841``\ + - | ``default_not_allowed_on_partial_spec``\ : + | partial specializations may not have default template arguments + * - ``0842``\ + - | ``not_used_in_partial_spec_arg_list``\ : + | *entity-kind "entity"*\ is not used in or cannot be deduced from the + template argument list of *entity-kind "entity"*\ + * - ``0844``\ + - | ``partial_spec_arg_depends_on_templ_param``\ : + | the template argument list of the partial specialization includes a + nontype argument whose type depends on a template parameter + * - ``0845``\ + - | ``partial_spec_after_instantiation``\ : + | this partial specialization would have been used to instantiate + *entity-kind "entity"*\ + * - ``0846``\ + - | ``partial_spec_after_instantiation_ambiguous``\ : + | this partial specialization would have made the instantiation of + *entity-kind "entity"*\ ambiguous + * - ``0847``\ + - | ``expr_not_integral_or_enum``\ : + | expression must have integral or enum type + * - ``0848``\ + - | ``expr_not_arithmetic_or_enum``\ : + | expression must have arithmetic or enum type + * - ``0849``\ + - | ``expr_not_arithmetic_or_enum_or_pointer``\ : + | expression must have arithmetic, enum, or pointer type + * - ``0850``\ + - | ``cast_not_integral_or_enum``\ : + | type of cast must be integral or enum + * - ``0851``\ + - | ``cast_not_arithmetic_or_enum_or_pointer``\ : + | type of cast must be arithmetic, enum, or pointer + * - ``0852``\ + - | ``expr_not_object_pointer``\ : + | expression must be a pointer to a complete object type + * - ``0855``\ + - | ``different_return_type_on_virtual_function_override``\ : + | return type is not identical to return type *"type"*\ of overridden + virtual function *"entity"*\ + * - ``0856``\ + - | ``cl_guiding_decls_option_only_in_cplusplus``\ : + | option "guiding_decls" can be used only when compiling C++ + * - ``0857``\ + - | ``member_partial_spec_not_in_namespace``\ : + | a partial specialization of a class template must be declared in the + namespace of which it is a member + * - ``0858``\ + - | ``pure_virtual_function``\ : + | *entity-kind "entity"*\ is a pure virtual function + * - ``0859``\ + - | ``no_overrider_for_pure_virtual_function``\ : + | pure virtual *entity-kind "entity"*\ has no overrider + * - ``0860``\ + - | ``decl_modifiers_ignored``\ : + | __declspec attributes ignored + * - ``0861``\ + - | ``invalid_char``\ : + | invalid character in input line + * - ``0862``\ + - | ``incomplete_return_type``\ : + | function returns incomplete type *"type"*\ + * - ``0863``\ + - | ``local_pragma_pack``\ : + | effect of this "#pragma pack" directive is local to *entity-kind + "entity"*\ + * - ``0864``\ + - | ``not_a_template``\ : + | *xxxx*\ is not a template + * - ``0865``\ + - | ``friend_partial_specialization``\ : + | a friend declaration may not declare a partial specialization + * - ``0866``\ + - | ``exception_specification_ignored``\ : + | exception specification ignored + * - ``0867``\ + - | ``unexpected_type_for_size_t``\ : + | declaration of "size_t" does not match the expected type *"type"*\ + * - ``0868``\ + - | ``exp_gt_not_shift_right``\ : + | space required between adjacent ">" delimiters of nested template + argument lists (">>" is the right shift operator) + * - ``0869``\ + - | ``bad_multibyte_char_locale``\ : + | could not set locale *"xxxx"*\ to allow processing of multibyte + characters + * - ``0870``\ + - | ``bad_multibyte_char``\ : + | invalid multibyte character sequence + * - ``0871``\ + - | ``bad_type_from_instantiation``\ : + | template instantiation resulted in unexpected function type of + *"type"*\ (the meaning of a name may have changed since the template + declaration -- the type of the template is *"type"*\ ) + * - ``0872``\ + - | ``ambiguous_guiding_decl``\ : + | ambiguous guiding declaration -- more than one function template + *"entity"*\ matches type *"type"*\ + * - ``0873``\ + - | ``non_integral_operation_in_templ_arg``\ : + | non-integral operation not allowed in nontype template argument + * - ``0874``\ + - | ``cl_embedded_cplusplus_option_only_in_cplusplus``\ : + | option "embedded_c++" can be used only when compiling C++ + * - ``0875``\ + - | ``templates_in_embedded_cplusplus``\ : + | Embedded C++ does not support templates + * - ``0876``\ + - | ``exceptions_in_embedded_cplusplus``\ : + | Embedded C++ does not support exception handling + * - ``0877``\ + - | ``namespaces_in_embedded_cplusplus``\ : + | Embedded C++ does not support namespaces + * - ``0878``\ + - | ``rtti_in_embedded_cplusplus``\ : + | Embedded C++ does not support run-time type information + * - ``0879``\ + - | ``new_cast_in_embedded_cplusplus``\ : + | Embedded C++ does not support the new cast syntax + * - ``0880``\ + - | ``using_decl_in_embedded_cplusplus``\ : + | Embedded C++ does not support using-declarations + * - ``0881``\ + - | ``mutable_in_embedded_cplusplus``\ : + | Embedded C++ does not support "mutable" + * - ``0882``\ + - | ``multiple_inheritance_in_embedded_cplusplus``\ : + | Embedded C++ does not support multiple or virtual inheritance + * - ``0883``\ + - | ``cl_invalid_microsoft_version``\ : + | invalid Microsoft version number: *xxxx*\ + * - ``0884``\ + - | ``inheritance_kind_already_set``\ : + | pointer-to-member representation *"xxxx"*\ has already been set for + *entity-kind "entity"*\ + * - ``0885``\ + - | ``bad_constructor_type``\ : + | *"type"*\ cannot be used to designate constructor for *"type"*\ + * - ``0886``\ + - | ``bad_suffix``\ : + | invalid suffix on integral constant + * - ``0887``\ + - | ``uuidof_requires_uuid_class_type``\ : + | operand of \__uuidof must have a class or enum type for which + \__declspec(uuid("...")) has been specified + * - ``0888``\ + - | ``bad_uuid_string``\ : + | invalid GUID string in \__declspec(uuid("...")) + * - ``0889``\ + - | ``cl_vla_option_only_in_C``\ : + | option "vla" can be used only when compiling C + * - ``0890``\ + - | ``vla_with_unspecified_bound_not_allowed``\ : + | variable length array with unspecified bound is not allowed + * - ``0891``\ + - | ``explicit_template_args_not_allowed``\ : + | an explicit template argument list is not allowed on this declaration + * - ``0892``\ + - | ``variably_modified_type_not_allowed``\ : + | an entity with linkage cannot have a type involving a variable length + array + * - ``0893``\ + - | ``vla_is_not_auto``\ : + | a variable length array cannot have static storage duration + * - ``0894``\ + - | ``sym_not_a_template``\ : + | *entity-kind "entity"*\ is not a template + * - ``0896``\ + - | ``expected_template_arg``\ : + | expected a template argument + * - ``0898``\ + - | ``no_params_with_class_or_enum_type``\ : + | nonmember operator requires a parameter with class or enum type + * - ``0899``\ + - | ``cl_enum_overloading_option_only_in_cplusplus``\ : + | option "enum_overloading" can be used only when compiling C++ + * - ``0901``\ + - | ``destructor_qualifier_type_mismatch``\ : + | qualifier of destructor name *"type"*\ does not match type *"type"*\ + * - ``0902``\ + - | ``type_qualifier_ignored``\ : + | type qualifier ignored + * - ``0903``\ + - | ``cl_nonstandard_qualifier_deduction_option_only_in_cplusplus``\ : + | option "nonstd_qualifier_deduction" can be used only when compiling + C++ + * - ``0904``\ + - | ``cannot_define_dllimport_function``\ : + | a function declared "dllimport" may not be defined + * - ``0905``\ + - | ``bad_declspec_property``\ : + | incorrect property specification; correct form is + \__declspec(property(get=name1,put=name2)) + * - ``0906``\ + - | ``dupl_get_or_put``\ : + | property has already been specified + * - ``0907``\ + - | ``declspec_property_not_allowed``\ : + | __declspec(property) is not allowed on this declaration + * - ``0908``\ + - | ``no_get_property``\ : + | member is declared with \__declspec(property), but no "get" function + was specified + * - ``0909``\ + - | ``get_property_function_missing``\ : + | the \__declspec(property) "get" function *"xxxx"*\ is missing + * - ``0910``\ + - | ``no_put_property``\ : + | member is declared with \__declspec(property), but no "put" function + was specified + * - ``0911``\ + - | ``put_property_function_missing``\ : + | the \__declspec(property) "put" function *"xxxx"*\ is missing + * - ``0912``\ + - | ``dual_lookup_ambiguous_name``\ : + | ambiguous class member reference -- *entity-kind "entity"*\ + (declared at line *xxxx*\ ) used in preference to *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``0916``\ + - | ``pm_virtual_base_from_derived_class``\ : + | cannot convert pointer to member of derived class *"type"*\ to + pointer to member of base class *"type"*\ -- base class is virtual + * - ``0917``\ + - | ``cl_invalid_instantiation_directory``\ : + | invalid directory for instantiation files: *xxxx*\ + * - ``0918``\ + - | ``cl_one_instantiation_per_object_option_only_in_cplusplus``\ : + | option "one_instantiation_per_object" can be used only when compiling + C++ + * - ``0921``\ + - | ``cl_ii_file_name_incompatible_with_multiple_inputs``\ : + | an instantiation information file name may not be specified when + compiling several input files + * - ``0922``\ + - | ``cl_one_instantiation_per_object_incompatible_with_multiple_inputs``\ + : + | option "one_instantiation_per_object" may not be used when compiling + several input files + * - ``0923``\ + - | ``cl_ambiguous_option``\ : + | more than one command line option matches the abbreviation + "--*xxxx*\ ": + * - ``0925``\ + - | ``cv_qualified_function_type``\ : + | type qualifiers on function types are ignored + * - ``0927``\ + - | ``cl_late_tiebreaker_option_only_in_cplusplus``\ : + | late/early tiebreaker option can be used only when compiling C++ + * - ``0928``\ + - | ``bad_va_start``\ : + | incorrect use of va_start + * - ``0929``\ + - | ``bad_va_arg``\ : + | incorrect use of va_arg + * - ``0930``\ + - | ``bad_va_end``\ : + | incorrect use of va_end + * - ``0931``\ + - | ``cl_pending_instantiations_option_only_in_cplusplus``\ : + | pending instantiations option can be used only when compiling C++ + * - ``0932``\ + - | ``cl_invalid_import_directory``\ : + | invalid directory for #import files: *xxxx*\ + * - ``0933``\ + - | ``cl_import_only_in_microsoft``\ : + | an import directory can be specified only in Microsoft mode + * - ``0934``\ + - | ``ref_not_allowed_in_union``\ : + | a member with reference type is not allowed in a union + * - ``0935``\ + - | ``typedef_not_allowed``\ : + | "typedef" may not be specified here + * - ``0936``\ + - | ``redecl_changes_access``\ : + | redeclaration of *entity-kind "entity"*\ alters its access + * - ``0937``\ + - | ``qualified_name_required``\ : + | a class or namespace qualified name is required + * - ``0938``\ + - | ``implicit_int_on_main``\ : + | return type "int" omitted in declaration of function "main" + * - ``0939``\ + - | ``invalid_inheritance_kind_for_class``\ : + | pointer-to-member representation *"xxxx"*\ is too restrictive for + *entity-kind "entity"*\ + * - ``0940``\ + - | ``implicit_return_from_non_void_function``\ : + | missing return statement at end of non-void *entity-kind "entity"*\ + * - ``0941``\ + - | ``duplicate_using_decl``\ : + | duplicate using-declaration of *"entity"*\ ignored + * - ``0942``\ + - | ``unsigned_enum_bit_field_with_signed_enumerator``\ : + | enum bit fields are always unsigned, but enum *"type"*\ includes + negative enumerator + * - ``0943``\ + - | ``cl_class_name_injection_option_only_in_cplusplus``\ : + | option "class_name_injection" can be used only when compiling C++ + * - ``0944``\ + - | ``cl_arg_dependent_lookup_option_only_in_cplusplus``\ : + | option "arg_dep_lookup" can be used only when compiling C++ + * - ``0945``\ + - | ``cl_friend_injection_option_only_in_cplusplus``\ : + | option "friend_injection" can be used only when compiling C++ + * - ``0946``\ + - | ``invalid_name_after_template``\ : + | name following "template" must be a template + * - ``0948``\ + - | ``local_class_friend_requires_prior_decl``\ : + | nonstandard local-class friend declaration -- no prior declaration in + the enclosing scope + * - ``0949``\ + - | ``nonstd_default_arg``\ : + | specifying a default argument on this declaration is nonstandard + * - ``0950``\ + - | ``cl_nonstd_using_decl_option_only_in_cplusplus``\ : + | option "nonstd_using_decl" can be used only when compiling C++ + * - ``0951``\ + - | ``bad_return_type_on_main``\ : + | return type of function "main" must be "int" + * - ``0952``\ + - | ``template_parameter_has_class_type``\ : + | a nontype template parameter may not have class type + * - ``0953``\ + - | ``default_arg_on_member_decl``\ : + | a default template argument cannot be specified on the definition of + a member of a class template outside the template + * - ``0954``\ + - | ``return_from_ctor_function_try_block_handler``\ : + | a return statement is not allowed in a handler of a function try + block of a constructor + * - ``0955``\ + - | ``no_ordinary_and_extended_designators``\ : + | ordinary and extended designators cannot be combined in an + initializer designation + * - ``0956``\ + - | ``no_negative_designator_range``\ : + | the second subscript must not be smaller than the first + * - ``0958``\ + - | ``cl_extended_designators_option_only_in_C``\ : + | option "extended_designators" can be used only when compiling C + * - ``0959``\ + - | ``extra_bits_ignored``\ : + | declared size for bit field is larger than the size of the bit field + type; truncated to *xxxx*\ bits + * - ``0960``\ + - | ``constructor_type_mismatch``\ : + | type used as constructor name does not match type *"type"*\ + * - ``0961``\ + - | ``type_with_no_linkage_in_var_with_linkage``\ : + | use of a type with no linkage to declare a variable with linkage + * - ``0962``\ + - | ``type_with_no_linkage_in_function``\ : + | use of a type with no linkage to declare a function + * - ``0963``\ + - | ``return_type_on_constructor``\ : + | return type may not be specified on a constructor + * - ``0964``\ + - | ``return_type_on_destructor``\ : + | return type may not be specified on a destructor + * - ``0965``\ + - | ``malformed_universal_character``\ : + | incorrectly formed universal character name + * - ``0966``\ + - | ``invalid_UCN``\ : + | universal character name specifies an invalid character + * - ``0967``\ + - | ``UCN_names_basic_char``\ : + | a universal character name cannot designate a character in the basic + character set + * - ``0968``\ + - | ``invalid_identifier_UCN``\ : + | this universal character is not allowed in an identifier + * - ``0969``\ + - | ``VA_ARGS_not_allowed``\ : + | the identifier \__VA_ARGS\__ can only appear in the replacement lists + of variadic macros + * - ``0970``\ + - | ``friend_qualification_ignored``\ : + | the qualifier on this friend declaration is ignored + * - ``0971``\ + - | ``no_range_designator_with_dynamic_init``\ : + | array range designators cannot be applied to dynamic initializers + * - ``0972``\ + - | ``property_name_not_allowed``\ : + | property name cannot appear here + * - ``0973``\ + - | ``inline_qualifier_ignored``\ : + | "inline" used as a function qualifier is ignored + * - ``0974``\ + - | ``cl_compound_literals_option_only_in_C``\ : + | option "compound_literals" can be used only when compiling C + * - ``0975``\ + - | ``vla_not_allowed``\ : + | a variable-length array type is not allowed + * - ``0976``\ + - | ``bad_integral_compound_literal``\ : + | a compound literal is not allowed in an integral constant expression + * - ``0977``\ + - | ``bad_compound_literal_type``\ : + | a compound literal of type *"type"*\ is not allowed + * - ``0978``\ + - | ``friend_template_in_local_class``\ : + | a template friend declaration cannot be declared in a local class + * - ``0979``\ + - | ``ambiguous_question_operator``\ : + | ambiguous "?" operation: second operand of type *"type"*\ can be + converted to third operand type *"type"*\ , and vice versa + * - ``0980``\ + - | ``bad_call_of_class_object``\ : + | call of an object of a class type without appropriate operator() or + conversion functions to pointer-to-function type + * - ``0982``\ + - | ``ambiguous_class_call``\ : + | there is more than one way an object of type *"type"*\ can be called + for the argument list: + * - ``0983``\ + - | ``similar_typedef``\ : + | typedef name has already been declared (with similar type) + * - ``0984``\ + - | ``no_internal_linkage_for_new_or_delete``\ : + | operator new and operator delete cannot be given internal linkage + * - ``0985``\ + - | ``no_mutable_allowed_on_anonymous_union``\ : + | storage class "mutable" is not allowed for anonymous unions + * - ``0986``\ + - | ``bad_pch_file``\ : + | invalid precompiled header file + * - ``0987``\ + - | ``abstract_class_catch_type``\ : + | abstract class type *"type"*\ is not allowed as catch type: + * - ``0988``\ + - | ``bad_qualified_function_type``\ : + | a qualified function type cannot be used to declare a nonmember + function or a static member function + * - ``0989``\ + - | ``bad_qualified_function_type_parameter``\ : + | a qualified function type cannot be used to declare a parameter + * - ``0990``\ + - | ``ptr_or_ref_to_qualified_function_type``\ : + | cannot create a pointer or reference to qualified function type + * - ``0991``\ + - | ``nonstd_braces``\ : + | extra braces are nonstandard + * - ``0992``\ + - | ``bad_cmd_line_macro``\ : + | invalid macro definition: *xxxx*\ + * - ``0993``\ + - | ``nonstandard_ptr_minus_ptr``\ : + | subtraction of pointer types *"type"*\ and *"type"*\ is nonstandard + * - ``0994``\ + - | ``empty_template_param_list``\ : + | an empty template parameter list is not allowed in a template + template parameter declaration + * - ``0995``\ + - | ``exp_class``\ : + | expected "class" + * - ``0996``\ + - | ``struct_not_allowed``\ : + | the "struct" keyword may not be used when declaring a template + template parameter + * - ``0997``\ + - | ``virtual_function_decl_hidden``\ : + | *entity-kind "entity"*\ is hidden by *"entity"*\ -- virtual + function override intended? + * - ``0998``\ + - | ``no_qualified_friend_definition``\ : + | a qualified name is not allowed for a friend declaration that is a + function definition + * - ``0999``\ + - | ``not_compatible_with_templ_templ_param``\ : + | *entity-kind "entity"*\ is not compatible with *entity-kind + "entity"*\ + * - ``1000``\ + - | ``storage_class_requires_function_or_variable``\ : + | a storage class may not be specified here + * - ``1001``\ + - | ``member_using_must_be_visible_in_direct_base``\ : + | class member designated by a using-declaration must be visible in a + direct base class + * - ``1003``\ + - | ``cl_sun_incompatible_with_cfront``\ : + | Sun mode is incompatible with cfront mode + * - ``1004``\ + - | ``cl_strict_mode_incompatible_with_sun``\ : + | strict mode is incompatible with Sun mode + * - ``1005``\ + - | ``cl_sun_mode_only_in_cplusplus``\ : + | Sun mode is only allowed when compiling C++ + * - ``1006``\ + - | ``template_template_param_same_name_as_templ_param``\ : + | a template template parameter cannot have the same name as one of its + template parameters + * - ``1007``\ + - | ``recursive_def_arg_instantiation``\ : + | recursive instantiation of default argument + * - ``1009``\ + - | ``bad_template_name``\ : + | *entity-kind "entity"*\ is not an entity that can be defined + * - ``1010``\ + - | ``destructor_name_must_be_qualified``\ : + | destructor name must be qualified + * - ``1011``\ + - | ``no_typename_in_friend_class_decl``\ : + | friend class name may not be introduced with "typename" + * - ``1012``\ + - | ``no_ctor_or_dtor_using_declaration``\ : + | a using-declaration may not name a constructor or destructor + * - ``1013``\ + - | ``friend_is_nonreal_template``\ : + | a qualified friend template declaration must refer to a specific + previously declared template + * - ``1014``\ + - | ``bad_class_template_decl``\ : + | invalid specifier in class template declaration + * - ``1015``\ + - | ``simple_incompatible_param``\ : + | argument is incompatible with formal parameter + * - ``1016``\ + - | ``cl_dep_name_option_only_in_cplusplus``\ : + | option "dep_name" can be used only when compiling C++ + * - ``1017``\ + - | ``op_arrow_loop``\ : + | loop in sequence of "operator->" functions starting at class + *"type"*\ + * - ``1018``\ + - | ``not_a_member_class``\ : + | *entity-kind "entity"*\ has no member class *"xxxx"*\ + * - ``1019``\ + - | ``name_not_class_in_file_scope``\ : + | the global scope has no class named *"xxxx"*\ + * - ``1020``\ + - | ``recursive_inst_of_templ_default_arg``\ : + | recursive instantiation of template default argument + * - ``1021``\ + - | ``no_access_or_using_decl_in_union``\ : + | access declarations and using-declarations cannot appear in unions + * - ``1022``\ + - | ``not_class_member``\ : + | *"entity"*\ is not a class member + * - ``1023``\ + - | ``nonstd_const_member_decl_not_allowed``\ : + | nonstandard member constant declaration is not allowed + * - ``1024``\ + - | ``cl_ignore_std_option_only_in_cplusplus``\ : + | option "ignore_std" can be used only when compiling C++ + * - ``1025``\ + - | ``cl_parse_nonclass_templates_option_only_in_cplusplus``\ : + | option "parse_templates" can be used only when compiling C++ + * - ``1026``\ + - | ``cl_dep_name_requires_parse_nonclass_templates``\ : + | option "dep_name" cannot be used with "no_parse_templates" + * - ``1027``\ + - | ``cl_incompatible_language_modes``\ : + | language modes specified are incompatible + * - ``1028``\ + - | ``invalid_nested_class_redecl``\ : + | invalid redeclaration of nested class + * - ``1029``\ + - | ``flexible_array_member_not_allowed``\ : + | type containing an unknown-size array is not allowed + * - ``1030``\ + - | ``static_variable_in_inline_function``\ : + | a variable with static storage duration cannot be defined within an + inline function + * - ``1031``\ + - | ``bad_linkage_of_ref_within_inline_function``\ : + | an entity with internal linkage cannot be referenced within an inline + function with external linkage + * - ``1032``\ + - | ``type_generic_function_mismatch``\ : + | argument type *"type"*\ does not match this type-generic function + macro + * - ``1034``\ + - | ``friend_cannot_add_default_arguments``\ : + | friend declaration cannot add default arguments to previous + declaration + * - ``1035``\ + - | ``cannot_be_declared_in_scope``\ : + | *entity-kind "entity"*\ cannot be declared in this scope + * - ``1036``\ + - | ``id_can_only_appear_in_function``\ : + | the reserved identifier *"xxxx"*\ may only be used inside a function + * - ``1037``\ + - | ``invalid_identifier_start_UCN``\ : + | this universal character cannot begin an identifier + * - ``1038``\ + - | ``exp_string_literal``\ : + | expected a string literal + * - ``1039``\ + - | ``unrecognized_stdc_pragma``\ : + | unrecognized STDC pragma + * - ``1040``\ + - | ``bad_stdc_pragma_arg``\ : + | expected "ON", "OFF", or "DEFAULT" + * - ``1041``\ + - | ``stdc_pragma_not_allowed_here``\ : + | a STDC pragma may only appear between declarations in the global + scope or before any statements or declarations in a block scope + * - ``1042``\ + - | ``bad_va_copy``\ : + | incorrect use of va_copy + * - ``1043``\ + - | ``only_applies_to_float_types``\ : + | *xxxx*\ can only be used with floating-point types + * - ``1044``\ + - | ``complex_type_not_allowed``\ : + | complex type is not allowed + * - ``1045``\ + - | ``invalid_designator_kind``\ : + | invalid designator kind + * - ``1046``\ + - | ``inexact_fp_conversion``\ : + | floating-point value cannot be represented exactly + * - ``1047``\ + - | ``bad_complex_operation_result``\ : + | complex floating-point operation result is out of range + * - ``1048``\ + - | ``real_imaginary_conversion``\ : + | conversion between real and imaginary yields zero + * - ``1049``\ + - | ``cannot_initialize_flexible_array_member``\ : + | an initializer cannot be specified for a flexible array member + * - ``1050``\ + - | ``imaginary_times_assign``\ : + | imaginary \*= imaginary sets the left-hand operand to zero + * - ``1051``\ + - | ``undeclared_parameter``\ : + | standard requires that *entity-kind "entity"*\ be given a type by a + subsequent declaration ("int" assumed) + * - ``1052``\ + - | ``inline_never_defined``\ : + | a definition is required for inline *entity-kind "entity"*\ + * - ``1053``\ + - | ``conversion_to_pointer_loses_bits``\ : + | conversion from integer to smaller pointer + * - ``1054``\ + - | ``missing_floating_point_type``\ : + | a floating-point type must be included in the type specifier for a + _Complex or _Imaginary type + * - ``1055``\ + - | ``type_decl_in_anon_union``\ : + | types cannot be declared in anonymous unions + * - ``1056``\ + - | ``returning_ptr_to_local_variable``\ : + | returning pointer to local variable + * - ``1057``\ + - | ``returning_ptr_to_local_temp``\ : + | returning pointer to local temporary + * - ``1058``\ + - | ``cl_export_template_option_only_in_cplusplus``\ : + | option "export" can be used only when compiling C++ + * - ``1059``\ + - | ``cl_export_template_requires_dep_name``\ : + | option "export" cannot be used with "no_dep_name" + * - ``1060``\ + - | ``cl_export_template_requires_no_implicit_include``\ : + | option "export" cannot be used with "implicit_include" + * - ``1061``\ + - | ``corresp_decl_incompatible``\ : + | declaration of *entity-kind "entity"*\ is incompatible with a + declaration in another translation unit + * - ``1062``\ + - | ``corresp_decl_at``\ : + | the other declaration is at line *xxxx*\ + * - ``1065``\ + - | ``field_cannot_involve_vla_type``\ : + | a field declaration cannot have a type involving a variable length + array + * - ``1066``\ + - | ``entity_differs_in_other_trans_unit``\ : + | declaration of *entity-kind "entity"*\ had a different meaning + during compilation of *"xxxx"*\ + * - ``1067``\ + - | ``exp_template``\ : + | expected "template" + * - ``1068``\ + - | ``export_on_instantiation``\ : + | "export" cannot be used on an explicit instantiation + * - ``1069``\ + - | ``bad_decl_for_export``\ : + | "export" cannot be used on this declaration + * - ``1070``\ + - | ``exported_in_unnamed_namespace``\ : + | a member of an unnamed namespace cannot be declared "export" + * - ``1071``\ + - | ``export_after_definition``\ : + | a template cannot be declared "export" after it has been defined + * - ``1072``\ + - | ``labeled_declaration``\ : + | a declaration cannot have a label + * - ``1073``\ + - | ``no_export_support``\ : + | support for exported templates is disabled + * - ``1075``\ + - | ``entity_defined_in_other_trans_unit``\ : + | *entity-kind "entity"*\ already defined during compilation of + *"xxxx"*\ + * - ``1076``\ + - | ``entity_defined_twice``\ : + | *entity-kind "entity"*\ already defined in another translation unit + * - ``1077``\ + - | ``based_var_cannot_be_local``\ : + | a nonstatic local variable may not be used in a \__based specification + * - ``1078``\ + - | ``cl_list_make_dependencies_incompatible_with_multiple_trans_units``\ + : + | the option to list makefile dependencies may not be specified when + compiling more than one translation unit + * - ``1080``\ + - | ``cl_pp_output_incompatible_with_multiple_trans_units``\ : + | the option to generate preprocessed output may not be specified when + compiling more than one translation unit + * - ``1081``\ + - | ``field_name_conflicts_with_class``\ : + | a field with the same name as its class cannot be declared in a class + with a user-declared constructor + * - ``1082``\ + - | ``cl_implicit_include_incompatible_with_multiple_trans_units``\ : + | "implicit_include" cannot be used when compiling more than one + translation unit + * - ``1083``\ + - | ``corrupted_export_template_file``\ : + | exported template file *"xxxx"*\ is corrupted + * - ``1084``\ + - | ``exported_instantiation_and_specialized``\ : + | *entity-kind "entity"*\ cannot be instantiated -- it has been + explicitly specialized in the translation unit containing the + exported definition + * - ``1086``\ + - | ``unqual_named_function_with_qual_object``\ : + | the object has type qualifiers that are not compatible with the + member *entity-kind "entity"*\ + * - ``1087``\ + - | ``no_matching_function_due_to_selector``\ : + | no instance of *entity-kind "entity"*\ matches the argument list and + object (the object has type qualifiers that prevent a match) + * - ``1088``\ + - | ``mode_incompatible_with_type``\ : + | an attribute specifies a mode incompatible with *"type"*\ + * - ``1089``\ + - | ``no_type_of_specified_width``\ : + | there is no type with the width specified + * - ``1090``\ + - | ``bad_attribute_alignment``\ : + | invalid alignment value specified by attribute + * - ``1091``\ + - | ``attribute_does_not_apply_to_type``\ : + | invalid attribute for *"type"*\ + * - ``1094``\ + - | ``arguments_provided_for_attribute``\ : + | attribute *"xxxx"*\ does not take arguments + * - ``1096``\ + - | ``exp_attribute_name``\ : + | expected an attribute name + * - ``1097``\ + - | ``unrecognized_attribute``\ : + | unknown attribute *"xxxx"*\ + * - ``1098``\ + - | ``attribute_not_allowed``\ : + | attributes may not appear here + * - ``1099``\ + - | ``invalid_argument_to_attribute``\ : + | invalid argument to attribute *"xxxx"*\ + * - ``1101``\ + - | ``assigned_goto_requires_void_ptr``\ : + | in "goto \*expr", expr must have type "void \*" + * - ``1102``\ + - | ``nonstd_assigned_goto``\ : + | "goto \*expr" is nonstandard + * - ``1103``\ + - | ``nonstd_address_of_label``\ : + | taking the address of a label is nonstandard + * - ``1104``\ + - | ``cl_duplicate_file_name``\ : + | file name specified more than once: *xxxx*\ + * - ``1105``\ + - | ``warning_directive``\ : + | #warning directive: *xxxx*\ + * - ``1107``\ + - | ``transparent_type_is_not_union``\ : + | the "transparent_union" attribute only applies to unions, and + *"type"*\ is not a union + * - ``1108``\ + - | ``transparent_attribute_ignored``\ : + | the "transparent_union" attribute is ignored on incomplete types + * - ``1109``\ + - | ``union_cannot_be_transparent_sym``\ : + | *"type"*\ cannot be transparent because *entity-kind "entity"*\ + does not have the same size as the first field + * - ``1110``\ + - | ``union_cannot_be_transparent``\ : + | *"type"*\ cannot be transparent because it has a field of type + *"type"*\ which is not the same size as the first field + * - ``1112``\ + - | ``attribute_does_not_apply_to_local_variable``\ : + | attribute *"xxxx"*\ does not apply to local variables + * - ``1113``\ + - | ``attributes_in_rout_defn``\ : + | attributes are not permitted in a function definition + * - ``1115``\ + - | ``invalid_case_range``\ : + | the second constant in a case range must be larger than the first + * - ``1116``\ + - | ``asm_name_in_rout_defn``\ : + | an asm name is not permitted in a function definition + * - ``1117``\ + - | ``asm_name_in_typedef``\ : + | an asm name is ignored in a typedef + * - ``1118``\ + - | ``bad_reg_name``\ : + | unknown register name "*xxxx*\ " + * - ``1120``\ + - | ``bad_asm_constraint_modifier``\ : + | unknown asm constraint modifier '*xxxx*\ ' + * - ``1121``\ + - | ``bad_asm_constraint_letter``\ : + | unknown asm constraint letter '*xxxx*\ ' + * - ``1122``\ + - | ``missing_constraint_letter``\ : + | asm operand has no constraint letter + * - ``1123``\ + - | ``asm_output_must_have_output_mod``\ : + | an asm output operand must have one of the '=' or '+' modifiers + * - ``1124``\ + - | ``asm_input_must_not_have_output_mod``\ : + | an asm input operand may not have the '=' or '+' modifiers + * - ``1127``\ + - | ``register_used_twice``\ : + | register "*xxxx*\ " used more than once + * - ``1128``\ + - | ``register_used_and_clobbered``\ : + | register "*xxxx*\ " is both used and clobbered + * - ``1129``\ + - | ``register_clobbered_twice``\ : + | register "*xxxx*\ " clobbered more than once + * - ``1130``\ + - | ``fixed_register_used``\ : + | register "*xxxx*\ " has a fixed purpose and may not be used in an asm + statement + * - ``1131``\ + - | ``fixed_register_clobbered``\ : + | register "*xxxx*\ " has a fixed purpose and may not be clobbered in + an asm statement + * - ``1132``\ + - | ``empty_clobbers_list``\ : + | an empty clobbers list must be omitted entirely + * - ``1133``\ + - | ``exp_asm_operand``\ : + | expected an asm operand + * - ``1134``\ + - | ``exp_asm_clobber``\ : + | expected a register to clobber + * - ``1135``\ + - | ``format_rout_not_varargs``\ : + | "format" attribute requires an ellipsis parameter or parameter pack + * - ``1136``\ + - | ``subst_arg_is_not_variable``\ : + | first substitution argument is not the first variable argument + * - ``1137``\ + - | ``fmt_arg_does_not_exist``\ : + | format argument index is greater than number of parameters + * - ``1138``\ + - | ``fmt_arg_is_not_string``\ : + | format argument does not have string type + * - ``1139``\ + - | ``template_not_in_template``\ : + | the "template" keyword used for syntactic disambiguation may only be + used within a template + * - ``1142``\ + - | ``attr_requires_func_type``\ : + | attribute *"xxxx"*\ does not apply to non-function type *"type"*\ + * - ``1143``\ + - | ``nonobject_pointer_arithmetic``\ : + | arithmetic on pointer to void or function type + * - ``1144``\ + - | ``invalid_storage_class_in_for_init``\ : + | storage class must be auto or register + * - ``1145``\ + - | ``va_arg_would_have_been_promoted``\ : + | *"type"*\ would have been promoted to *"type"*\ when passed through + the ellipsis parameter; use the latter type instead + * - ``1146``\ + - | ``not_a_base_class_member``\ : + | *"xxxx"*\ is not a base class member + * - ``1147``\ + - | ``super_after_scope``\ : + | __super cannot appear after "::" + * - ``1148``\ + - | ``super_not_in_class``\ : + | __super may only be used in a class scope + * - ``1149``\ + - | ``unqualified_super``\ : + | __super must be followed by "::" + * - ``1151``\ + - | ``mangled_name_too_long``\ : + | mangled name is too long + * - ``1152``\ + - | ``aliased_name_undeclared``\ : + | declaration aliased to undefined entity *"xxxx"*\ + * - ``1153``\ + - | ``aliased_name_bad_kind``\ : + | declaration does not match its alias *entity-kind "entity"*\ + * - ``1154``\ + - | ``alias_cannot_have_definition``\ : + | entity declared as alias cannot have definition + * - ``1155``\ + - | ``vla_size_ignored``\ : + | variable-length array field type will be treated as zero-length array + field type + * - ``1156``\ + - | ``gcc_lvalue_cast_ignored``\ : + | nonstandard cast on lvalue ignored + * - ``1157``\ + - | ``cl_invalid_flag_name``\ : + | unrecognized flag name: *xxxx*\ + * - ``1158``\ + - | ``qualified_void_return_type``\ : + | void return type cannot be qualified + * - ``1159``\ + - | ``auto_ignored``\ : + | the auto specifier is ignored here (invalid in standard C/C++) + * - ``1160``\ + - | ``alignment_reduction_ignored``\ : + | a reduction in alignment without the "packed" attribute is ignored + * - ``1161``\ + - | ``corresp_member_template_is_different_kind``\ : + | a member template corresponding to *"entity"*\ is declared as a + template of a different kind in another translation unit + * - ``1162``\ + - | ``excess_initializers_ignored``\ : + | excess initializers are ignored + * - ``1163``\ + - | ``va_start_requires_ellipsis_function``\ : + | va_start can appear only in a function with an ellipsis parameter + * - ``1164``\ + - | ``cl_short_enums_requires_gcc_mode``\ : + | the "short_enums" option is only valid in GNU C and GNU C++ modes + * - ``1165``\ + - | ``bad_export_info_file``\ : + | invalid export information file *"xxxx"*\ at line number *xxxx*\ + * - ``1166``\ + - | ``statement_expression_in_function_only``\ : + | statement expressions are only allowed in block scope + * - ``1168``\ + - | ``asm_name_on_auto_variable``\ : + | an asm name is ignored on a non-register automatic variable + * - ``1170``\ + - | ``unrecognized_upc_pragma``\ : + | unrecognized UPC pragma + * - ``1171``\ + - | ``mismatched_shared_block_size``\ : + | shared block size does not match one previously specified + * - ``1172``\ + - | ``ambiguous_block_size_spec``\ : + | bracketed expression is assumed to be a block size specification + rather than an array dimension + * - ``1173``\ + - | ``shared_block_size_must_be_positive``\ : + | the block size of a shared array must be greater than zero + * - ``1174``\ + - | ``multiple_block_sizes``\ : + | multiple block sizes not allowed + * - ``1175``\ + - | ``nonshared_strict_relaxed``\ : + | strict or relaxed requires shared + * - ``1176``\ + - | ``threads_constant_not_allowed``\ : + | THREADS not allowed in this context + * - ``1177``\ + - | ``shared_block_size_too_large``\ : + | block size specified exceeds the maximum value of *xxxx*\ + * - ``1178``\ + - | ``function_returning_shared``\ : + | function returning shared is not allowed + * - ``1180``\ + - | ``shared_nonthreads_dim``\ : + | one dimension of an array of a shared type must be a multiple of + THREADS when the number of threads is nonconstant + * - ``1181``\ + - | ``shared_inside_struct``\ : + | shared type inside a struct or union is not allowed + * - ``1182``\ + - | ``shared_parameter``\ : + | parameters may not have shared types + * - ``1183``\ + - | ``threads_dimension_requires_definite_block_size``\ : + | a dynamic THREADS dimension requires a definite block size + * - ``1184``\ + - | ``bad_shared_storage_class``\ : + | shared variables must be static or extern + * - ``1185``\ + - | ``nonshared_blocksizeof``\ : + | argument of upc_blocksizeof is a pointer to a shared type (not shared + type itself) + * - ``1186``\ + - | ``nested_upc_forall``\ : + | affinity expression ignored in nested upc_forall + * - ``1187``\ + - | ``exit_forall``\ : + | branching into or out of a upc_forall loop is not allowed + * - ``1188``\ + - | ``bad_affinity``\ : + | affinity expression must have a shared type or point to a shared type + * - ``1189``\ + - | ``shared_affinity_type``\ : + | affinity has shared type (not pointer to shared) + * - ``1190``\ + - | ``upc_shared_void_comparison``\ : + | shared void\* types can only be compared for equality + * - ``1191``\ + - | ``cl_upc_requires_ansi_c_dialect``\ : + | UPC mode is incompatible with C++ and K&R modes + * - ``1192``\ + - | ``null_char_ignored``\ : + | null (zero) character in input line ignored + * - ``1193``\ + - | ``null_char_in_string``\ : + | null (zero) character in string or character constant + * - ``1194``\ + - | ``null_char_in_header_name``\ : + | null (zero) character in header name + * - ``1195``\ + - | ``for_init_hides_declaration``\ : + | declaration in for-initializer hides a declaration in the surrounding + scope + * - ``1196``\ + - | ``for_init_hidden_declaration``\ : + | the hidden declaration is at line *xxxx*\ + * - ``1197``\ + - | ``prototype_lost``\ : + | the prototype declaration of *entity-kind "entity"*\ (declared at + line *xxxx*\ ) is ignored after this unprototyped redeclaration + * - ``1199``\ + - | ``bad_linkage_for_redefine_extname``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) must have + external C linkage + * - ``1200``\ + - | ``declaration_hides_for_init``\ : + | variable declaration hides declaration in for-initializer + * - ``1201``\ + - | ``typedef_in_elab_type``\ : + | typedef *"xxxx"*\ may not be used in an elaborated type specifier + * - ``1202``\ + - | ``call_of_zero``\ : + | call of zero constant ignored + * - ``1203``\ + - | ``handler_redeclares_parameter``\ : + | parameter *"xxxx"*\ may not be redeclared in a catch clause of + function try block + * - ``1204``\ + - | ``specialization_out_of_namespace``\ : + | the initial explicit specialization of *entity-kind "entity"*\ must + be declared in the namespace containing the template + * - ``1205``\ + - | ``cc_clobber_ignored``\ : + | "cc" clobber ignored + * - ``1206``\ + - | ``invalid_token_after_template``\ : + | "template" must be followed by an identifier + * - ``1207``\ + - | ``mythread_constant_not_allowed``\ : + | MYTHREAD not allowed in this context + * - ``1208``\ + - | ``bad_upc_shared_pointer_layout_qualifier``\ : + | layout qualifier cannot qualify pointer to shared + * - ``1209``\ + - | ``bad_upc_shared_array_layout_qualifier``\ : + | layout qualifier cannot qualify an incomplete array + * - ``1210``\ + - | ``decl_hides_catch_parameter``\ : + | declaration of *"xxxx"*\ hides handler parameter + * - ``1211``\ + - | ``nonstd_ignored_array_cast``\ : + | nonstandard cast to array type ignored + * - ``1212``\ + - | ``invalid_pragma_operator``\ : + | this pragma cannot be used in a _Pragma operator (a #pragma directive + must be used) + * - ``1213``\ + - | ``field_uses_tail_padding``\ : + | field uses tail padding of a base class + * - ``1214``\ + - | ``gnu_may_use_bit_padding``\ : + | GNU C++ compilers may use bit field padding + * - ``1215``\ + - | ``deprecated_entity``\ : + | *entity-kind "entity"*\ was declared deprecated + * - ``1216``\ + - | ``field_with_asm_name_not_allowed``\ : + | an asm name is not allowed on a nonstatic member declaration + * - ``1217``\ + - | ``unrecognized_format_function_type``\ : + | unrecognized format function type *"xxxx"*\ ignored + * - ``1218``\ + - | ``base_uses_tail_padding``\ : + | base class *"entity"*\ uses tail padding of base class *"entity"*\ + * - ``1219``\ + - | ``bad_variable_for_init_priority``\ : + | the "init_priority" attribute can only be used for definitions of + static data members and namespace scope variables of class types + * - ``1220``\ + - | ``init_priority_reserved``\ : + | requested initialization priority is reserved for internal use + * - ``1221``\ + - | ``hidden_anonymous_union_field``\ : + | this anonymous union/struct field is hidden by *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``1222``\ + - | ``invalid_error_number``\ : + | invalid error number + * - ``1223``\ + - | ``invalid_error_tag``\ : + | invalid error tag + * - ``1224``\ + - | ``exp_error_argument``\ : + | expected an error number or error tag + * - ``1225``\ + - | ``size_affected_by_tail_padding``\ : + | size of class is affected by tail padding + * - ``1226``\ + - | ``nonlocal_label_reference``\ : + | labels can be referenced only in function definitions + * - ``1227``\ + - | ``branch_into_statement_expr``\ : + | transfer of control into a statement expression is not allowed + * - ``1229``\ + - | ``bad_statement_in_statement_expr``\ : + | this statement is not allowed inside of a statement expression + * - ``1230``\ + - | ``class_def_in_statement_expr``\ : + | a class that is not trivially copyable cannot be defined inside a + statement expression + * - ``1232``\ + - | ``dyn_local_static_in_statement_expr``\ : + | a dynamically-initialized local static variable is not allowed inside + of a statement expression + * - ``1233``\ + - | ``vla_in_statement_expr``\ : + | a variable-length array is not allowed inside of a statement + expression + * - ``1234``\ + - | ``statement_expr_in_default_arg``\ : + | a statement expression is not allowed inside of a default argument + * - ``1235``\ + - | ``ptr_func_ptr_data_conv``\ : + | nonstandard conversion between pointer to function and pointer to data + * - ``1236``\ + - | ``interface_cannot_have_virtual_base``\ : + | interface types cannot have virtual base classes + * - ``1237``\ + - | ``interface_cannot_have_private_or_protected``\ : + | interface types cannot specify "private" or "protected" + * - ``1238``\ + - | ``interface_must_derive_from_interface``\ : + | interface types can only derive from other interface types + * - ``1239``\ + - | ``type_is_interface``\ : + | *"type"*\ is an interface type + * - ``1240``\ + - | ``interface_cannot_have_typedef``\ : + | interface types cannot have typedef members + * - ``1241``\ + - | ``interface_cannot_have_ctor_or_dtor``\ : + | interface types cannot have user-declared constructors or destructors + * - ``1242``\ + - | ``interface_cannot_have_operator``\ : + | interface types cannot have user-declared member operators + * - ``1243``\ + - | ``interface_cannot_be_local``\ : + | interface types cannot be declared in functions + * - ``1245``\ + - | ``interface_cannot_have_data_member``\ : + | interface types cannot have data members + * - ``1246``\ + - | ``interface_cannot_have_friend``\ : + | interface types cannot contain friend declarations + * - ``1248``\ + - | ``interface_cannot_be_nested_class``\ : + | interface types cannot be nested class types + * - ``1249``\ + - | ``interface_cannot_have_member_templates``\ : + | interface types cannot have member templates + * - ``1250``\ + - | ``interface_cannot_have_static_members``\ : + | interface types cannot have static member functions + * - ``1251``\ + - | ``invalid_microsoft_pragma_operator``\ : + | this pragma cannot be used in a \__pragma operator (a #pragma + directive must be used) + * - ``1252``\ + - | ``qualifier_must_be_base_class``\ : + | qualifier must be base class of *"type"*\ + * - ``1253``\ + - | ``invalid_selective_overrider_declaration``\ : + | declaration must correspond to a pure virtual member function in the + indicated base class + * - ``1254``\ + - | ``integer_overflow_class_internal``\ : + | integer overflow in internal computation due to size or complexity of + *"type"*\ + * - ``1255``\ + - | ``integer_overflow_internal``\ : + | integer overflow in internal computation + * - ``1256``\ + - | ``invalid_type_for_w64``\ : + | __w64 can only be specified on int, long, and pointer types + * - ``1257``\ + - | ``ilp64_will_narrow``\ : + | potentially narrowing conversion when compiled in an environment + where int, long, or pointer types are 64 bits wide + * - ``1258``\ + - | ``value_of_pragma_pack_show``\ : + | current value of pragma pack is *xxxx*\ + * - ``1259``\ + - | ``pragma_pack_show_args_ignored``\ : + | arguments for pragma pack(show) are ignored + * - ``1262``\ + - | ``multiple_declspec_align``\ : + | earlier \__declspec(align(...)) ignored + * - ``1263``\ + - | ``exp_ms_attr_enum_value``\ : + | expected an argument value for the *"xxxx"*\ attribute parameter + * - ``1264``\ + - | ``invalid_ms_attr_enum_value``\ : + | invalid argument value for the *"xxxx"*\ attribute parameter + * - ``1265``\ + - | ``exp_ms_attr_bool_value``\ : + | expected a boolean value for the *"xxxx"*\ attribute parameter + * - ``1266``\ + - | ``positional_after_named``\ : + | a positional argument cannot follow a named argument in an attribute + * - ``1267``\ + - | ``invalid_ms_attr_name``\ : + | attribute *"xxxx"*\ has no parameter named *"xxxx"*\ + * - ``1268``\ + - | ``exp_ms_attr_arg_list``\ : + | expected an argument list for the *"xxxx"*\ attribute + * - ``1269``\ + - | ``exp_comma_or_rbracket``\ : + | expected a "," or "]" + * - ``1270``\ + - | ``duplicate_ms_attr_arg``\ : + | attribute argument *"xxxx"*\ has already been given a value + * - ``1271``\ + - | ``cannot_assign_to_ms_attr``\ : + | a value cannot be assigned to the *"xxxx"*\ attribute + * - ``1272``\ + - | ``ptr_incomplete_throw``\ : + | a throw expression may not have pointer-to-incomplete type + * - ``1273``\ + - | ``alignof_incomplete_type``\ : + | alignment-of operator applied to incomplete type + * - ``1274``\ + - | ``invalid_use_of_standalone_ms_attr``\ : + | *"xxxx"*\ may only be used as a standalone attribute + * - ``1275``\ + - | ``invalid_use_of_ms_attr``\ : + | *"xxxx"*\ attribute cannot be used here + * - ``1277``\ + - | ``ms_attr_not_allowed``\ : + | attributes are not allowed here + * - ``1278``\ + - | ``invalid_ms_attr_uuid_value``\ : + | invalid argument value for the *"xxxx"*\ attribute parameter + * - ``1279``\ + - | ``too_many_ms_attr_args``\ : + | too many attribute arguments + * - ``1280``\ + - | ``conv_from_inaccessible_base_class``\ : + | conversion from inaccessible base class *"type"*\ is not allowed + * - ``1281``\ + - | ``cl_export_template_requires_distinct_templ_sigs``\ : + | option "export" requires distinct template signatures + * - ``1282``\ + - | ``mixed_string_concatenation``\ : + | string literals with different character kinds cannot be concatenated + * - ``1283``\ + - | ``no_gnu_virtual_base_gap``\ : + | GNU layout bug not emulated because it places virtual base + *"entity"*\ outside *"entity"*\ object boundaries + * - ``1284``\ + - | ``gnu_virtual_base_gap``\ : + | virtual base *"entity"*\ placed outside *"entity"*\ object + boundaries + * - ``1285``\ + - | ``nonstd_qualifier_in_namespace_member_decl``\ : + | nonstandard qualified name in namespace member declaration + * - ``1286``\ + - | ``declspec_align_reduction_ignored``\ : + | reduction in alignment ignored + * - ``1287``\ + - | ``const_ignored``\ : + | const qualifier ignored + * - ``1289``\ + - | ``invalid_asm_qualifiers``\ : + | invalid GNU asm qualifiers + * - ``1290``\ + - | ``non_pod_passed_to_ellipsis``\ : + | a class type that is not trivially copyable passed through ellipsis + * - ``1291``\ + - | ``non_pod_va_arg``\ : + | a class type that cannot be trivially copied cannot be fetched by + va_arg + * - ``1292``\ + - | ``nonstd_fixed_point_suffix``\ : + | the 'u' or 'U' suffix must appear before the 'l' or 'L' suffix in a + fixed-point literal + * - ``1293``\ + - | ``cl_fixed_point_option_only_in_C``\ : + | option "fixed_point" can be used only when compiling C + * - ``1294``\ + - | ``integer_may_not_fit_in_fixed_point_result``\ : + | integer operand may cause fixed-point overflow + * - ``1295``\ + - | ``bad_fixed_point_value``\ : + | fixed-point constant is out of range + * - ``1296``\ + - | ``inexact_fxp_conversion``\ : + | fixed-point value cannot be represented exactly + * - ``1297``\ + - | ``c99_constant_in_unsigned_long_long_range``\ : + | constant is too large for long long; given unsigned long long type + (nonstandard) + * - ``1298``\ + - | ``bad_upc_shared_void_pointer_layout_qualifier``\ : + | layout qualifier cannot qualify pointer to shared void + * - ``1299``\ + - | ``duplicate_threads_dim``\ : + | duplicate THREADS in multidimensional array type + * - ``1300``\ + - | ``bad_strong_using_scope``\ : + | a strong using-directive may only appear in a namespace scope + * - ``1301``\ + - | ``probable_guiding_friend``\ : + | *entity-kind "entity"*\ declares a non-template function -- add <> + to refer to a template instance + * - ``1302``\ + - | ``operation_may_not_fit_in_fixed_point_result``\ : + | operation may cause fixed-point overflow + * - ``1303``\ + - | ``expr_not_integral_or_enum_or_fixed_point``\ : + | expression must have integral, enum, or fixed-point type + * - ``1304``\ + - | ``expr_not_integral_or_fixed_point``\ : + | expression must have integral or fixed-point type + * - ``1305``\ + - | ``noreturn_function_does_return``\ : + | function declared with "noreturn" does return + * - ``1306``\ + - | ``asm_name_conflict``\ : + | asm name ignored because it conflicts with a previous declaration + * - ``1307``\ + - | ``duplicate_typedef_in_class``\ : + | class member typedef may not be redeclared + * - ``1308``\ + - | ``taking_address_of_temporary``\ : + | taking the address of a temporary + * - ``1309``\ + - | ``attribute_ignored_on_incomplete_class_decl``\ : + | attributes are ignored on a class declaration that is not also a + definition + * - ``1310``\ + - | ``implicit_fixed_point_to_floating_point_conversion``\ : + | fixed-point value implicitly converted to floating-point type + * - ``1311``\ + - | ``no_classification_for_fixed_point_type``\ : + | fixed-point types have no classification + * - ``1312``\ + - | ``fixed_template_parameter``\ : + | a template parameter may not have fixed-point type + * - ``1313``\ + - | ``hex_fp_constant``\ : + | hexadecimal floating-point constants are not allowed + * - ``1314``\ + - | ``cl_named_address_spaces_option_only_in_C``\ : + | option "named_address_spaces" can be used only when compiling C + * - ``1315``\ + - | ``float_to_fixed_conversion``\ : + | floating-point value does not fit in required fixed-point type + * - ``1316``\ + - | ``inexact_fixed_conversion``\ : + | value cannot be converted to fixed-point value exactly + * - ``1317``\ + - | ``fixed_sign_change``\ : + | fixed-point conversion resulted in a change of sign + * - ``1318``\ + - | ``integer_to_fixed_conversion``\ : + | integer value does not fit in required fixed-point type + * - ``1319``\ + - | ``bad_fixed_operation_result``\ : + | fixed-point operation result is out of range + * - ``1320``\ + - | ``multiple_named_address_spaces``\ : + | multiple named address spaces + * - ``1321``\ + - | ``bad_storage_class_for_named_address_space_variable``\ : + | variable with automatic storage duration cannot be stored in a named + address space + * - ``1322``\ + - | ``type_with_named_address_space_not_allowed``\ : + | type cannot be qualified with named address space + * - ``1323``\ + - | ``named_address_space_on_function_type``\ : + | function type cannot be qualified with named address space + * - ``1324``\ + - | ``field_type_cannot_be_qualified_with_named_address_space``\ : + | field type cannot be qualified with named address space + * - ``1325``\ + - | ``fixed_to_float_conversion``\ : + | fixed-point value does not fit in required floating-point type + * - ``1326``\ + - | ``fixed_to_integer_conversion``\ : + | fixed-point value does not fit in required integer type + * - ``1327``\ + - | ``fixed_to_fixed_conversion``\ : + | value does not fit in required fixed-point type + * - ``1328``\ + - | ``cl_named_registers_option_only_in_C``\ : + | option "named_registers" can be used only when compiling C + * - ``1329``\ + - | ``named_register_not_allowed``\ : + | a named-register storage class is not allowed here + * - ``1330``\ + - | ``register_storage_class_conflict``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) redeclared with + incompatible named-register storage class + * - ``1331``\ + - | ``aliased_variable_cannot_have_register_storage_class``\ : + | named-register storage class cannot be specified for aliased variable + * - ``1332``\ + - | ``register_in_use``\ : + | named-register storage specifier is already in use + * - ``1333``\ + - | ``embedded_c_option_incompatible_with_individual_feature_options``\ : + | option "embedded_c" cannot be combined with options to control + individual Embedded C features + * - ``1334``\ + - | ``cl_invalid_edg_base_directory``\ : + | invalid EDG_BASE directory: *xxxx*\ + * - ``1336``\ + - | ``bad_predef_macro_line``\ : + | invalid predefined macro entry at line *xxxx*\ : *xxxx*\ + * - ``1337``\ + - | ``bad_macro_mode_name``\ : + | invalid macro mode name *"xxxx"*\ + * - ``1338``\ + - | ``bad_predef_macro_redef``\ : + | incompatible redefinition of predefined macro *"xxxx"*\ + * - ``1339``\ + - | ``missing_named_register_storage_class``\ : + | redeclaration of *entity-kind "entity"*\ (declared at line *xxxx*\ ) + is missing a named-register storage class + * - ``1340``\ + - | ``register_too_small``\ : + | named register is too small for the type of the variable + * - ``1341``\ + - | ``no_named_register_for_array``\ : + | arrays cannot be declared with named-register storage class + * - ``1342``\ + - | ``enum_const_cast``\ : + | const_cast to enum type is nonstandard + * - ``1343``\ + - | ``cl_embedded_c_option_only_in_C``\ : + | option "embedded_c" can be used only when compiling C + * - ``1344``\ + - | ``named_address_space_not_allowed``\ : + | a named address space qualifier is not allowed here + * - ``1345``\ + - | ``bad_initializer_for_array_with_unspecified_bound``\ : + | an empty initializer is invalid for an array with unspecified bound + * - ``1346``\ + - | ``incomplete_class_return_type``\ : + | function returns incomplete class type *"type"*\ + * - ``1347``\ + - | ``out_of_class_initializer_ignored``\ : + | *entity-kind "entity"*\ has already been initialized; the + out-of-class initializer will be ignored + * - ``1348``\ + - | ``local_variable_hidden``\ : + | declaration hides *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``1349``\ + - | ``named_address_space_for_parameter``\ : + | a parameter cannot be allocated in a named address space + * - ``1350``\ + - | ``bad_float_or_fixed_suffix``\ : + | invalid suffix on fixed-point or floating-point constant + * - ``1351``\ + - | ``register_in_address_space``\ : + | a register variable cannot be allocated in a named address space + * - ``1352``\ + - | ``bad_stdc_fx_overflow_pragma_arg``\ : + | expected "SAT" or "DEFAULT" + * - ``1353``\ + - | ``no_corresponding_member_delete``\ : + | *entity-kind "entity"*\ has no corresponding member operator + delete*xxxx*\ (to be called if an exception is thrown during + initialization of an allocated object) + * - ``1354``\ + - | ``dll_thread_conflict``\ : + | a thread-local variable cannot be declared with "dllimport" or + "dllexport" + * - ``1355``\ + - | ``function_returning_named_address_space``\ : + | a function return type cannot be qualified with a named address space + * - ``1356``\ + - | ``cannot_initialize_destructible_flexible_array``\ : + | an initializer cannot be specified for a flexible array member whose + elements have a nontrivial destructor + * - ``1357``\ + - | ``cannot_initialize_indirect_flexible_array``\ : + | an initializer cannot be specified for an indirect flexible array + member + * - ``1358``\ + - | ``cl_invalid_gnu_version``\ : + | invalid GNU version number: *xxxx*\ + * - ``1359``\ + - | ``attribute_after_parenthesized_initializer``\ : + | variable attributes appearing after a parenthesized initializer are + ignored + * - ``1360``\ + - | ``gcc_use_of_cast_as_lvalue``\ : + | the result of this cast cannot be used as an lvalue + * - ``1361``\ + - | ``unsigned_fixed_point_negation``\ : + | negation of an unsigned fixed-point value + * - ``1364``\ + - | ``register_name_on_nonregister``\ : + | register names can only be used for register variables + * - ``1365``\ + - | ``void_named_register``\ : + | named-register variables cannot have void type + * - ``1367``\ + - | ``parameter_with_link_scope_specifier``\ : + | parameters cannot have link scope specifiers + * - ``1368``\ + - | ``multiple_link_scope_specifiers``\ : + | multiple link scope specifiers + * - ``1369``\ + - | ``link_scope_requires_external_linkage``\ : + | link scope specifiers can only appear on functions and variables with + external linkage + * - ``1370``\ + - | ``link_scope_relaxation``\ : + | a redeclaration cannot weaken a link scope + * - ``1371``\ + - | ``invalid_link_scope``\ : + | link scope specifier not allowed on this declaration + * - ``1372``\ + - | ``nonstd_qualifier_in_global_scope_decl``\ : + | nonstandard qualified name in global scope declaration + * - ``1373``\ + - | ``impl_narrowing_64_bit_int``\ : + | implicit conversion of a 64-bit integral type to a smaller integral + type (potential portability problem) + * - ``1374``\ + - | ``expl_narrowing_64_bit_int``\ : + | explicit conversion of a 64-bit integral type to a smaller integral + type (potential portability problem) + * - ``1375``\ + - | ``pointer_conversion_to_same_size_int``\ : + | conversion from pointer to same-sized integral type (potential + portability problem) + * - ``1377``\ + - | ``friend_specifier_ignored``\ : + | friend specifier is not allowed in a class definition; friend + specifier is ignored + * - ``1378``\ + - | ``cannot_use_thread_local_storage``\ : + | only static and extern variables can use thread-local storage + * - ``1379``\ + - | ``multiple_thread_local_storage_specifiers``\ : + | multiple thread-local storage specifiers + * - ``1380``\ + - | ``virtual_function_never_defined``\ : + | virtual *entity-kind "entity"*\ was not defined (and cannot be + defined elsewhere because it is a member of an unnamed namespace) + * - ``1381``\ + - | ``stray_carriage_return``\ : + | carriage return character in source line outside of comment or + character/string literal + * - ``1382``\ + - | ``expr_not_fixed_point``\ : + | expression must have fixed-point type + * - ``1383``\ + - | ``invalid_access_specifier``\ : + | invalid use of access specifier is ignored + * - ``1384``\ + - | ``ptr_conv_to_bool``\ : + | pointer converted to bool + * - ``1385``\ + - | ``ptr_to_member_conv_to_bool``\ : + | pointer-to-member converted to bool + * - ``1386``\ + - | ``storage_specifier_ignored``\ : + | storage specifier ignored + * - ``1387``\ + - | ``dll_interface_ignored_on_class_template``\ : + | dllexport and dllimport are ignored on class templates + * - ``1388``\ + - | ``base_class_has_different_dll_interface``\ : + | base class dllexport/dllimport specification differs from that of the + derived class + * - ``1389``\ + - | ``redeclaration_adds_dll_interface``\ : + | redeclaration cannot add dllexport/dllimport to *"entity"*\ + (declared at line *xxxx*\ ) + * - ``1390``\ + - | ``dll_interface_conflict_dllexport_assumed``\ : + | dllexport/dllimport conflict with *"entity"*\ (declared at line + *xxxx*\ ); dllexport assumed + * - ``1391``\ + - | ``dllimport_defined``\ : + | cannot define dllimport entity + * - ``1392``\ + - | ``dll_interface_requires_external_linkage``\ : + | dllexport/dllimport requires external linkage + * - ``1393``\ + - | ``class_and_member_have_dll_interface``\ : + | a member of a class declared with dllexport/dllimport cannot itself + be declared with such a specifier + * - ``1394``\ + - | ``field_without_dll_interface``\ : + | field of class type without a DLL interface used in a class with a + DLL interface + * - ``1395``\ + - | ``microsoft_parenthesized_member``\ : + | parenthesized member declaration is nonstandard + * - ``1396``\ + - | ``white_space_inside_splice``\ : + | white space between backslash and newline in line splice ignored + * - ``1397``\ + - | ``dll_interface_conflict_none_assumed``\ : + | dllexport/dllimport conflict with *"entity"*\ (declared at line + *xxxx*\ ); dllimport/dllexport dropped + * - ``1398``\ + - | ``bad_nonstd_anonymous_union_field``\ : + | invalid member for anonymous member class -- class *"type"*\ has a + disallowed member function + * - ``1399``\ + - | ``nonstd_reinterpret_cast``\ : + | nonstandard reinterpret_cast + * - ``1400``\ + - | ``positional_format_specifier_zero``\ : + | positional format specifier cannot be zero + * - ``1401``\ + - | ``nonlocal_vla_not_allowed``\ : + | a local class cannot reference a variable-length array type from an + enclosing function + * - ``1402``\ + - | ``class_and_inherited_member_instance_have_dll_interface``\ : + | member *entity-kind "entity"*\ (declared at line *xxxx*\ ) already + has an explicit dllexport/dllimport specifier + * - ``1403``\ + - | ``vla_in_return_type``\ : + | a variable-length array is not allowed in a function return type + * - ``1404``\ + - | ``ptr_to_member_of_vla_type``\ : + | variable-length array type is not allowed in pointer to member of + type *"type"*\ + * - ``1405``\ + - | ``statement_expr_with_vla_type``\ : + | the result of a statement expression cannot have a type involving a + variable-length array + * - ``1406``\ + - | ``trigraph_ignored``\ : + | support for trigraphs is disabled + * - ``1407``\ + - | ``attribute_requires_external_linkage``\ : + | the *"xxxx"*\ attribute can only appear on functions and variables + with external linkage + * - ``1408``\ + - | ``cl_strict_mode_incompatible_with_ignore_std``\ : + | strict mode is incompatible with treating namespace std as an alias + for the global namespace + * - ``1414``\ + - | ``invalid_symbolic_asm_operand_name``\ : + | invalid symbolic operand name *"xxxx"*\ + * - ``1415``\ + - | ``match_limit_for_symbolic_asm_operand``\ : + | a symbolic match constraint must refer to one of the first ten + operands + * - ``1416``\ + - | ``if_exists_not_allowed``\ : + | use of \__if_exists is not supported in this context + * - ``1417``\ + - | ``if_exists_not_closed``\ : + | __if_exists block not closed in the same scope in which it was opened + * - ``1418``\ + - | ``bad_init_for_thread_local``\ : + | thread-local variable cannot be dynamically initialized + * - ``1419``\ + - | ``unaligned_qualifier_dropped``\ : + | conversion drops "\__unaligned" qualifier + * - ``1420``\ + - | ``insufficient_enum_range``\ : + | some enumerator values cannot be represented by the integral type + underlying the enum type + * - ``1421``\ + - | ``friend_class_template_default_arg_not_allowed``\ : + | default argument is not allowed on a friend class template declaration + * - ``1422``\ + - | ``multi_char_literal``\ : + | multicharacter character literal (potential portability problem) + * - ``1423``\ + - | ``exp_class_type``\ : + | expected a class, struct, or union type + * - ``1424``\ + - | ``offsetof_nonfield``\ : + | second operand of offsetof must be a field + * - ``1425``\ + - | ``offsetof_bit_field``\ : + | second operand of offsetof may not be a bit field + * - ``1426``\ + - | ``offsetof_virtual_base_member``\ : + | cannot apply offsetof to a member of a virtual base + * - ``1427``\ + - | ``offset_in_non_POD_nonstandard``\ : + | offsetof applied to a type other than a standard-layout class + * - ``1428``\ + - | ``default_arg_on_member_friend``\ : + | default arguments are not allowed on a friend declaration of a member + function + * - ``1429``\ + - | ``default_arg_requires_friend_to_be_definition``\ : + | default arguments are not allowed on friend declarations that are not + definitions + * - ``1430``\ + - | ``redeclaration_of_friend_with_default_args``\ : + | redeclaration of *entity-kind "entity"*\ (declared at line *xxxx*\ ) + previously declared as a friend with default arguments is not allowed + * - ``1431``\ + - | ``bad_qualifier_for_nested_class_decl``\ : + | invalid qualifier for *"type"*\ (a derived class is not allowed here) + * - ``1432``\ + - | ``bad_qualifier_for_delayed_class_definition``\ : + | invalid qualifier for definition of class *"type"*\ + * - ``1433``\ + - | ``no_prior_push_macro``\ : + | no prior push_macro for *"xxxx"*\ + * - ``1434``\ + - | ``wide_string_not_allowed``\ : + | wide string literal not allowed + * - ``1436``\ + - | ``feature_requires_c``\ : + | *"xxxx"*\ is only allowed in C + * - ``1437``\ + - | ``microsoft_ptr_width_must_follow_star``\ : + | __ptr32 and \__ptr64 must follow a "\*" + * - ``1438``\ + - | ``microsoft_ptr_width_conflict``\ : + | __ptr32 and \__ptr64 cannot both apply + * - ``1439``\ + - | ``name_must_be_prototype_instantiation``\ : + | template argument list of *"xxxx"*\ must match the parameter list + * - ``1440``\ + - | ``incomplete_class_type``\ : + | an incomplete class type is not allowed + * - ``1441``\ + - | ``complex_integral_type``\ : + | complex integral types are not supported + * - ``1442``\ + - | ``real_and_imag_require_complex_argument``\ : + | __real and \__imag can only be applied to complex values + * - ``1443``\ + - | ``real_and_imag_applied_to_real_value``\ : + | __real/\__imag applied to real value + * - ``1444``\ + - | ``deprecated_entity_with_custom_message``\ : + | *entity-kind "entity"*\ was declared deprecated (*"xxxx"*\ ) + * - ``1446``\ + - | ``dll_interface_in_unnamed_namespace``\ : + | dllimport/dllexport applied to a member of an unnamed namespace + * - ``1447``\ + - | ``thiscall_requires_nonstatic_member``\ : + | __thiscall can only appear on nonstatic member function declarations + * - ``1448``\ + - | ``vararg_thiscall``\ : + | __thiscall not allowed on function with ellipsis parameter + * - ``1449``\ + - | ``specialization_of_referenced_entity_pos``\ : + | explicit specialization of *entity-kind "entity"*\ must precede its + first use (at line *xxxx*\ ) + * - ``1450``\ + - | ``sealed_base_class``\ : + | a sealed class type cannot be used as a base class + * - ``1451``\ + - | ``duplicate_class_modifier``\ : + | duplicate class modifier + * - ``1452``\ + - | ``function_modifiers_abstract_and_sealed``\ : + | a member function cannot have both the "abstract" and "sealed" + modifiers + * - ``1453``\ + - | ``pure_specifier_on_sealed_member``\ : + | a sealed member cannot be pure virtual + * - ``1454``\ + - | ``function_modifier_requires_virtual_function``\ : + | nonvirtual function cannot be declared with "abstract" or "sealed" + modifier + * - ``1455``\ + - | ``override_member_does_not_override``\ : + | member function declared with "override" does not override a base + class member + * - ``1456``\ + - | ``override_of_sealed_function``\ : + | cannot override sealed *entity-kind "entity"*\ (declared at line + *xxxx*\ ) + * - ``1457``\ + - | ``type_is_declared_abstract``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was declared + with the class modifier "abstract" + * - ``1534``\ + - | ``duplicate_function_modifier``\ : + | duplicate function modifier + * - ``1535``\ + - | ``no_char16_t_representation``\ : + | invalid character for char16_t literal + * - ``1537``\ + - | ``cl_unrecognized_calling_convention``\ : + | unrecognized calling convention *xxxx*\ , must be one of: + * - ``1541``\ + - | ``enum_base_type_must_be_integral``\ : + | underlying type of enum type must be an integral type + * - ``1542``\ + - | ``enum_base_type_too_limited``\ : + | some enumerator constants cannot be represented by *"type"*\ + * - ``1543``\ + - | ``feature_not_allowed_in_current_mode``\ : + | *"xxxx"*\ not allowed in current mode + * - ``1544``\ + - | ``cl_type_traits_helpers_option_only_in_cplusplus``\ : + | type traits helpers option can be used only when compiling C++ + * - ``1545``\ + - | ``gnu_sentinel_attribute_requires_ellipsis``\ : + | attribute "sentinel" requires an ellipsis parameter + * - ``1546``\ + - | ``invalid_gnu_sentinel_argument``\ : + | argument must be a constant null pointer value + * - ``1547``\ + - | ``no_gnu_sentinel_argument``\ : + | insufficient number of arguments for sentinel value + * - ``1548``\ + - | ``gnu_sentinel_must_be_ellipsis_argument``\ : + | sentinel argument must correspond to an ellipsis parameter + * - ``1549``\ + - | ``implementation_key_outside_mapping_region``\ : + | __declspec(implementation_key(...) can appear only between #pragma + start_map_region and #pragma stop_map_region + * - ``1550``\ + - | ``start_map_region_ignored``\ : + | #pragma start_map_region already active: pragma ignored + * - ``1551``\ + - | ``stop_map_region_ignored``\ : + | no #pragma start_map_region is currently active: pragma ignored + * - ``1552``\ + - | ``var_used_as_destructor``\ : + | *entity-kind "entity"*\ cannot be used to name a destructor (a type + name is required) + * - ``1553``\ + - | ``empty_wide_character``\ : + | nonstandard empty wide character literal treated as L'\0' + * - ``1554``\ + - | ``invalid_typename_specifier``\ : + | "typename" may not be specified here + * - ``1555``\ + - | ``no_default_delete_in_virtual_dtor``\ : + | a non-placement operator delete must be visible in a class with a + virtual destructor + * - ``1556``\ + - | ``name_linkage_mismatch_for_variable``\ : + | name linkage conflicts with previous declaration of *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``1557``\ + - | ``alias_loop``\ : + | alias creates cycle of aliased entities + * - ``1559``\ + - | ``register_mapped_variable_cannot_have_initializer``\ : + | a variable with static storage duration allocated in a specific + register cannot be declared with an initializer + * - ``1560``\ + - | ``register_mapped_variable_must_be_POD``\ : + | a variable allocated in a specific register must be trivially copyable + * - ``1561``\ + - | ``predef_macro_redefined``\ : + | predefined meaning of *"entity"*\ discarded + * - ``1563``\ + - | ``designator_for_non_POD``\ : + | class type not suitable for use with designators + * - ``1565``\ + - | ``nonstandard_anonymous_union_qualifier``\ : + | anonymous union qualifier is nonstandard + * - ``1566``\ + - | ``anonymous_union_qualifier_ignored``\ : + | anonymous union qualifier is ignored + * - ``1568``\ + - | ``struct_declspec_ignored_in_C_mode``\ : + | __declspec(*xxxx*\ ) ignored (it has no meaning for a C struct) + * - ``1569``\ + - | ``nonstandard_secondary_decl_specifiers``\ : + | specifiers after comma between declarations are nonstandard + * - ``1570``\ + - | ``secondary_specifier_ignored``\ : + | nonstandard specifier ignored + * - ``1571``\ + - | ``enum_attribute_ignored``\ : + | attributes are ignored on an enum declaration that is not also a + definition + * - ``1572``\ + - | ``reference_declared_mutable``\ : + | declaring a reference with "mutable" is nonstandard + * - ``1573``\ + - | ``array_condition_always_true``\ : + | a condition declaration for an array is always true + * - ``1574``\ + - | ``static_assert``\ : + | static assertion failed with *"xxxx"*\ + * - ``1575``\ + - | ``gnu_visibility_conflict``\ : + | visibility attribute ignored because it conflicts with a previous + declaration + * - ``1576``\ + - | ``pcc_field_ambiguity``\ : + | field name resolves to more than one offset -- see *"entity"*\ + (declared at line *xxxx*\ ) and *"entity"*\ (declared at line + *xxxx*\ ) + * - ``1577``\ + - | ``not_a_field_name``\ : + | *"xxxx"*\ is not a field name + * - ``1578``\ + - | ``case_label_conflict``\ : + | case label value has already appeared in this switch at line *xxxx*\ + * - ``1579``\ + - | ``member_cannot_have_internal_linkage``\ : + | a member function cannot have internal linkage + * - ``1580``\ + - | ``builtin_function_hidden``\ : + | declaration hides built-in *entity-kind "entity"*\ + * - ``1581``\ + - | ``builtin_function_overloaded``\ : + | declaration overloads built-in *entity-kind "entity"*\ + * - ``1582``\ + - | ``cl_list_macros_incompatible_with_multiple_trans_units``\ : + | the option to list macro definitions may not be specified when + compiling more than one translation unit + * - ``1583``\ + - | ``lparen_after_function``\ : + | unexpected parenthesis after declaration of *entity-kind "entity"*\ + (malformed parameter list or invalid initializer?) + * - ``1584``\ + - | ``nonstandard_parenthesized_string_initializer``\ : + | parentheses around a string initializer are nonstandard + * - ``1586``\ + - | ``auto_variable_in_own_initializer``\ : + | a variable declared with an auto type specifier cannot appear in its + own initializer + * - ``1587``\ + - | ``cannot_deduce_auto_type``\ : + | cannot deduce "auto" type + * - ``1588``\ + - | ``auto_brace_initialization_not_allowed``\ : + | initialization with "{...}" is not allowed for "auto" type + * - ``1589``\ + - | ``auto_type_in_array_type``\ : + | "auto" type cannot appear in top-level array type + * - ``1590``\ + - | ``auto_type_in_function_type``\ : + | "auto" type cannot appear in top-level function type + * - ``1591``\ + - | ``invalid_member_constant_type``\ : + | a member of type *"type"*\ cannot have an in-class initializer + * - ``1592``\ + - | ``member_constant_not_const``\ : + | a member with an in-class initializer must be const + * - ``1593``\ + - | ``auto_type_requires_initializer``\ : + | cannot deduce "auto" type (initializer required) + * - ``1594``\ + - | ``inconsistent_deduction_of_auto``\ : + | "auto" type is *"type"*\ for this entity, but was previously implied + to be *"type"*\ + * - ``1595``\ + - | ``bad_constructor_decl``\ : + | invalid constructor declaration + * - ``1596``\ + - | ``bad_type_qualifier``\ : + | invalid use of a type qualifier + * - ``1597``\ + - | ``abstract_or_sealed_on_union``\ : + | a union cannot be abstract or sealed + * - ``1598``\ + - | ``auto_not_allowed_here``\ : + | "auto" is not allowed here + * - ``1599``\ + - | ``unfinished_base_class``\ : + | definition of base class type not completed yet + * - ``1600``\ + - | ``static_extern_template``\ : + | "extern template" cannot refer to a specialization of static + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``1601``\ + - | ``extern_template_follows_instantiation``\ : + | "extern template" cannot follow explicit instantiation of + *entity-kind "entity"*\ + * - ``1602``\ + - | ``bad_declspec_restrict_return``\ : + | __declspec(restrict) requires a function returning a pointer type + * - ``1603``\ + - | ``cl_report_gnu_extensions_requires_gnu_mode``\ : + | the "report_gnu_extensions" option is only valid in GNU C and GNU C++ + modes + * - ``1604``\ + - | ``vla_is_nonstandard``\ : + | variable-length array types are nonstandard + * - ``1605``\ + - | ``designator_is_nonstandard``\ : + | designators are nonstandard + * - ``1606``\ + - | ``extended_designator_is_gnu_extension``\ : + | this designator syntax is a GNU extension + * - ``1607``\ + - | ``compound_literal_is_nonstandard``\ : + | compound literals are nonstandard + * - ``1608``\ + - | ``statement_expression_is_gnu_extension``\ : + | statement expressions are a GNU extension + * - ``1609``\ + - | ``asm_name_after_definition``\ : + | asm name ignored for previously defined entity + * - ``1610``\ + - | ``attribute_is_gnu_extension``\ : + | attributes are a GNU extension + * - ``1611``\ + - | ``asm_operand_spec_is_gnu_extension``\ : + | extended asm syntax is a GNU feature + * - ``1612``\ + - | ``volatile_asm_is_gnu_extension``\ : + | volatile asm declarations are a GNU extension + * - ``1613``\ + - | ``asm_name_is_gnu_extension``\ : + | asm name specifiers are a GNU extension + * - ``1614``\ + - | ``gnu_restrict_is_nonstandard``\ : + | the "\__restrict" qualifier is nonstandard + * - ``1615``\ + - | ``typeof_is_gnu_extension``\ : + | "typeof" is a GNU extension + * - ``1616``\ + - | ``typedef_modification_is_nonstandard``\ : + | modifying the size or signedness of a typedef is nonstandard + * - ``1617``\ + - | ``zero_length_array_is_gnu_extension``\ : + | zero-length arrays are a GNU extension + * - ``1618``\ + - | ``flexible_array_is_nonstandard``\ : + | flexible array members are nonstandard + * - ``1619``\ + - | ``nonnull_on_nonpointer``\ : + | attribute "nonnull" references nonpointer parameter + * - ``1620``\ + - | ``nonnull_parameter_number_too_large``\ : + | argument for attribute "nonnull" is larger than number of parameters + * - ``1621``\ + - | ``no_pointer_parameters``\ : + | no parameter has pointer type + * - ``1622``\ + - | ``null_argument_for_nonnull_parameter``\ : + | null argument provided for parameter marked with attribute "nonnull" + * - ``1623``\ + - | ``access_prevents_dtor_generation``\ : + | the destructor for *"type"*\ has been suppressed because the + destructor for *"type"*\ is inaccessible + * - ``1624``\ + - | ``suppressed_dtor_needed``\ : + | the suppressed destructor for *"type"*\ is needed + * - ``1625``\ + - | ``inline_gnu_noinline_conflict``\ : + | routine is both "inline" and "noinline" + * - ``1626``\ + - | ``invalid_cleanup_routine``\ : + | invalid cleanup routine + * - ``1627``\ + - | ``attribute_cleanup_requires_automatic_storage``\ : + | attribute "cleanup" requires automatic storage duration + * - ``1628``\ + - | ``attribute_cleanup_for_parameter``\ : + | attribute "cleanup" does not apply to parameters + * - ``1629``\ + - | ``bad_type_for_cleanup_routine``\ : + | cleanup routine has invalid type + * - ``1630``\ + - | ``nonstandard_conversion_for_cleanup``\ : + | call of cleanup routine requires suspect conversion + * - ``1631``\ + - | ``microsoft_ptr_signedness_must_follow_star``\ : + | __sptr and \__uptr must follow a "\*" + * - ``1632``\ + - | ``microsoft_ptr_signedness_conflict``\ : + | __sptr and \__uptr cannot both be specified + * - ``1633``\ + - | ``microsoft_ptr_sign_extension``\ : + | widening pointer conversion from *"type"*\ to *"type"*\ extends + sign bit + * - ``1634``\ + - | ``microsoft_ptr_signedness_on_ptr_to_member``\ : + | __sptr and \__uptr don't apply to pointer-to-member types + * - ``1635``\ + - | ``const_mbr_suppresses_copy_asgn_decl``\ : + | the declaration of the copy assignment operator for *"type"*\ has + been suppressed because *entity-kind "entity"*\ is const + * - ``1636``\ + - | ``ref_mbr_suppresses_copy_asgn_decl``\ : + | the declaration of the copy assignment operator for *"type"*\ has + been suppressed because *entity-kind "entity"*\ has reference type + * - ``1637``\ + - | ``subobj_copy_asgn_decl_suppressed``\ : + | the declaration of the copy assignment operator for *"type"*\ has + been suppressed because that of *"type"*\ was suppressed + * - ``1638``\ + - | ``ambig_suppresses_copy_asgn_decl``\ : + | the declaration of the copy assignment operator for *"type"*\ has + been suppressed because that of *"type"*\ is ambiguous + * - ``1639``\ + - | ``access_suppresses_copy_asgn_decl``\ : + | the declaration of the copy assignment operator for *"type"*\ has + been suppressed because that of *"type"*\ is inaccessible + * - ``1640``\ + - | ``subobj_copy_ctor_decl_suppressed``\ : + | the declaration of the copy constructor for *"type"*\ has been + suppressed because that of *"type"*\ was suppressed + * - ``1641``\ + - | ``ambig_suppresses_copy_ctor_decl``\ : + | the declaration of the copy constructor for *"type"*\ has been + suppressed because that of *"type"*\ is ambiguous + * - ``1642``\ + - | ``access_suppresses_copy_ctor_decl``\ : + | the declaration of the copy constructor for *"type"*\ has been + suppressed because that of *"type"*\ is inaccessible + * - ``1643``\ + - | ``inaccessible_dtor_not_invoked``\ : + | the destructor for *"type"*\ will not be called because it is + inaccessible and the destructor for *"type"*\ was suppressed + * - ``1644``\ + - | ``file_ends_with_unterminated_type_definition``\ : + | definition at end of file not followed by a semicolon or a declarator + * - ``1645``\ + - | ``bad_type_for_gnu_sync_function``\ : + | first argument must be a pointer to integer or enum type + * - ``1646``\ + - | ``invalid_gnu_sync_size``\ : + | synchronized operations are valid only on objects of size 1, 2, 4, or + 8 + * - ``1647``\ + - | ``extra_arguments_ignored``\ : + | extra arguments ignored + * - ``1648``\ + - | ``equals_assumed_in_cmd_line_macro_def``\ : + | '=' assumed following macro name *"xxxx"*\ in command-line definition + * - ``1649``\ + - | ``white_space_required_after_macro_name``\ : + | white space is required between the macro name *"xxxx"*\ and its + replacement text + * - ``1650``\ + - | ``call_result_should_be_used``\ : + | result of call is not used + * - ``1651``\ + - | ``warn_unused_result_with_void_return``\ : + | attribute "warn_unused_result" is ignored for void return type + * - ``1653``\ + - | ``dll_interface_ignored_on_qualified_declaration``\ : + | dllimport/dllexport is ignored on redeclaration using a qualified name + * - ``1654``\ + - | ``leading_character_ignored_in_char_literal``\ : + | too many characters in character literal -- extra leading characters + ignored + * - ``1655``\ + - | ``first_inline_after_definition``\ : + | *entity-kind "entity"*\ cannot be declared inline after its + definition at line *xxxx*\ + * - ``1658``\ + - | ``type_with_no_linkage_in_template_arg``\ : + | a template argument may not reference a type with no name linkage + * - ``1659``\ + - | ``virtual_ignored``\ : + | "virtual" is ignored here + * - ``1660``\ + - | ``vla_type_in_template_arg``\ : + | a template argument may not reference a variable-length array type + * - ``1661``\ + - | ``UCN_names_surrogate_code_point``\ : + | a universal character name cannot designate a surrogate code point + * - ``1662``\ + - | ``include_next_in_primary_source_file``\ : + | #include_next cannot be used in the primary source file + * - ``1663``\ + - | ``bad_template_member_definition``\ : + | *"entity"*\ cannot be specified in a template member definition -- + *"entity"*\ assumed instead + * - ``1664``\ + - | ``local_function_attribute_ignored``\ : + | attribute *"xxxx"*\ is ignored on local function declaration + * - ``1665``\ + - | ``concat_yields_invalid_token``\ : + | concatenation with *"xxxx"*\ in *entity-kind "entity"*\ does not + create a valid token + * - ``1666``\ + - | ``ambiguous_injected_template_name``\ : + | *"entity"*\ is ambiguous (*entity-kind "entity"*\ assumed) + * - ``1667``\ + - | ``function_qualifier_on_static_member``\ : + | a type qualifier is not allowed on a static member function + * - ``1668``\ + - | ``function_qualifier_on_ctor_or_dtor``\ : + | a type qualifier is not allowed on a constructor or destructor + * - ``1669``\ + - | ``function_qualifier_on_new_or_delete``\ : + | a type qualifier is not allowed on operator new or operator delete + * - ``1670``\ + - | ``function_qualifier_on_nonmember``\ : + | a type qualifier is not allowed on a nonmember function + * - ``1671``\ + - | ``assume_expression_discarded``\ : + | argument to *xxxx*\ has side-effects but is unevaluated + * - ``1672``\ + - | ``cl_unrecognized_unicode_source_kind``\ : + | unrecognized Unicode source kind (must be one of UTF-8, UTF-16, + UTF-16LE, UTF-16BE): *xxxx*\ + * - ``1673``\ + - | ``bad_unicode_char_in_pp_output``\ : + | Unicode character with hex value *xxxx*\ not representable in + preprocessing output + * - ``1674``\ + - | ``ctor_dtor_priority_reserved``\ : + | requested constructor/destructor priority is reserved for internal use + * - ``1675``\ + - | ``unrecognized_gcc_pragma``\ : + | unrecognized GCC pragma + * - ``1676``\ + - | ``unrecognized_gcc_visibility_pragma``\ : + | unrecognized GCC visibility pragma directive + * - ``1677``\ + - | ``unrecognized_visibility``\ : + | unrecognized visibility kind + * - ``1678``\ + - | ``ELF_visibility_pop_mismatch``\ : + | visibility pragma was still active + * - ``1679``\ + - | ``ELF_visibility_stack_empty``\ : + | no matching visibility push + * - ``1680``\ + - | ``typeid_of_incomplete_type``\ : + | typeid of incomplete type + * - ``1682``\ + - | ``array_size_one_assumed``\ : + | array *entity-kind "entity"*\ assumed to have one element + * - ``1683``\ + - | ``vector_size_attribute_requires_integral_floating_or_enum_type``\ : + | vector_size attribute requires an arithmetic or enum type + * - ``1684``\ + - | ``vector_size_too_large``\ : + | vector size is too large + * - ``1685``\ + - | ``vector_size_must_be_power_of_two``\ : + | the number of elements in a vector must be a power of two + * - ``1686``\ + - | ``vector_size_must_be_multiple_of_element_size``\ : + | vector size must be a multiple of the element size + * - ``1687``\ + - | ``mixed_vector_scalar_operation``\ : + | mixed vector-scalar operation not allowed + * - ``1688``\ + - | ``vectors_must_have_same_size``\ : + | operation requires two vectors of the same size + * - ``1689``\ + - | ``dependent_vector_size``\ : + | template-dependent vector size is not allowed + * - ``1692``\ + - | ``vector_size_attribute_on_complex_type``\ : + | vector_size attribute is not allowed with a complex element type + * - ``1694``\ + - | ``vector_element_type_mismatch``\ : + | vector operation requires identical element types + * - ``1695``\ + - | ``vector_operation_requires_integer_vector``\ : + | vector operation does not apply to vector with non-integral type + * - ``1696``\ + - | ``cannot_open_file``\ : + | cannot open *xxxx*\ file *"xxxx"*\ + * - ``1697``\ + - | ``cannot_open_file_reason``\ : + | cannot open *xxxx*\ file *"xxxx"*\ : *xxxx*\ + * - ``1703``\ + - | ``file_write_error_errno``\ : + | error while writing *xxxx*\ file: *xxxx*\ + * - ``1712``\ + - | ``il_output``\ : + | IL output + * - ``1713``\ + - | ``restrict_qualifier_dropped``\ : + | conversion drops "\__restrict" qualifier + * - ``1714``\ + - | ``unable_to_get_mapped_memory_reason``\ : + | unable to obtain mapped memory for *"xxxx"*\ : *xxxx*\ + * - ``1715``\ + - | ``restrict_qualifier_ignored``\ : + | restrict qualifier is ignored + * - ``1717``\ + - | ``nonstandard_array_with_flexible_array_element``\ : + | array of elements containing a flexible array member is nonstandard + * - ``1718``\ + - | ``vector_template_parameter``\ : + | a template parameter may not have a vector type + * - ``1719``\ + - | ``out_of_order_ctor_init``\ : + | the initialization of *entity-kind "entity"*\ will be done before + that of *entity-kind "entity"*\ + * - ``1721``\ + - | ``inheritance_kind_ignored_on_enum``\ : + | inheritance kind is ignored on an enum specifier + * - ``1723``\ + - | ``extended_modifier_ignored_on_enum``\ : + | modifier is ignored on an enum specifier + * - ``1724``\ + - | ``non_unicode_char_in_ident``\ : + | identifier character cannot be represented in Unicode + * - ``1725``\ + - | ``non_unicode_char_in_header``\ : + | header name contains characters that cannot be represented in Unicode + * - ``1726``\ + - | ``invalid_locale``\ : + | *"xxxx"*\ is not a valid locale name + * - ``1727``\ + - | ``nonstd_template_void_param_list``\ : + | declaring a void parameter list with a template parameter is + nonstandard + * - ``1728``\ + - | ``cl_lambdas_option_only_in_cplusplus``\ : + | lambdas option can be used only when compiling C++ + * - ``1729``\ + - | ``capture_mode_matches_default``\ : + | explicit capture matches default + * - ``1730``\ + - | ``not_a_variable``\ : + | *entity-kind "entity"*\ is not a variable + * - ``1731``\ + - | ``capture_of_static_duration_variable``\ : + | a variable with static storage duration cannot be captured in a lambda + * - ``1732``\ + - | ``cannot_capture_this_by_reference``\ : + | "this" cannot be captured by reference + * - ``1733``\ + - | ``this_in_lambda``\ : + | "this" cannot be used inside the body of this lambda + * - ``1734``\ + - | ``anon_union_ref_in_lambda``\ : + | a member of an outer-scope anonymous union cannot be referenced + inside the body of a lambda + * - ``1735``\ + - | ``not_captured_local_var_in_lambda``\ : + | an enclosing-function local variable cannot be referenced in a lambda + body unless it is in the capture list + * - ``1736``\ + - | ``bad_local_var_in_lambda``\ : + | invalid reference to an outer-scope local variable in a lambda body + * - ``1737``\ + - | ``captured_local_var_not_in_innermost_function``\ : + | a local variable outside the current function scope cannot be captured + * - ``1738``\ + - | ``not_captured_this_in_lambda``\ : + | the enclosing-function "this" cannot be referenced in a lambda body + unless it is in the capture list + * - ``1740``\ + - | ``captured_var_type_not_copyable``\ : + | lambda captured variable of type *"type"*\ cannot be copied to + closure class field of type *"type"*\ + * - ``1741``\ + - | ``cl_invalid_template_directory``\ : + | invalid template directory: *xxxx*\ + * - ``1749``\ + - | ``enum_value_out_of_underlying_range``\ : + | enumeration value is outside the range of its underlying type + (*"type"*\ ) + * - ``1750``\ + - | ``not_a_line_splice``\ : + | "\" followed by white space is not a line splice + * - ``1751``\ + - | ``dynamic_cast_without_rtti``\ : + | this dynamic_cast cannot be done without runtime type information, + which is disabled + * - ``1752``\ + - | ``ambiguous_cast_selects_direct_base``\ : + | conversion to *"type"*\ is ambiguous; direct base selected + * - ``1753``\ + - | ``requested_size_too_large``\ : + | an internal buffer would be too large + * - ``1754``\ + - | ``exception_handler_used``\ : + | C++ exception handler used, but exception handling semantics have not + been specified + * - ``1755``\ + - | ``type_qualifier_ignored_on_constructor``\ : + | type qualifier ignored on constructor + * - ``1756``\ + - | ``lambda_capture_involves_variable_length_array``\ : + | a variable captured by a lambda cannot have a type involving a + variable-length array + * - ``1757``\ + - | ``incompatible_vectors_conversion``\ : + | conversion between incompatible vector types + * - ``1758``\ + - | ``missing_lambda_body``\ : + | expected a "{" introducing a lambda body + * - ``1759``\ + - | ``cl_rvalue_references_option_only_in_cplusplus``\ : + | rvalue references option can be used only when compiling C++ + * - ``1760``\ + - | ``type_qualifier_on_lambda``\ : + | a type qualifier is not allowed on a lambda + * - ``1761``\ + - | ``more_than_one_capture``\ : + | a name cannot appear more than once in a capture-list + * - ``1762``\ + - | ``explicit_template_args_ignored``\ : + | explicit template arguments ignored + * - ``1763``\ + - | ``bad_constant_lambda``\ : + | a lambda is not allowed in a constant expression + * - ``1764``\ + - | ``class_type_required``\ : + | *"type"*\ is not a class type + * - ``1765``\ + - | ``delete_of_array_type``\ : + | "delete" applied to a pointer-to-array type treated as delete[] + * - ``1766``\ + - | ``delete_of_array_type_nonstandard``\ : + | "delete" applied to a pointer-to-array type is nonstandard; treated + as delete[] + * - ``1767``\ + - | ``function_does_not_match_arguments``\ : + | *entity-kind "entity"*\ cannot be called with the given argument list + * - ``1768``\ + - | ``rvalue_reference_bound_to_lvalue``\ : + | an rvalue reference cannot be bound to an lvalue + * - ``1769``\ + - | ``rvalue_ref_template_parameter``\ : + | a nontype template parameter cannot have rvalue reference type + * - ``1770``\ + - | ``type_qualifiers_ignored_on_reference``\ : + | type qualifiers are ignored (underlying type is a reference) + * - ``1771``\ + - | ``decl_with_local_type_but_not_defined``\ : + | *entity-kind "entity"*\ , declared using a local type, must be + defined in this translation unit + * - ``1772``\ + - | ``decl_with_no_linkage_type_but_not_defined``\ : + | *entity-kind "entity"*\ , declared using a type with no linkage, must + be defined in this translation unit + * - ``1773``\ + - | ``bad_rvalue_ref_dynamic_cast_operand``\ : + | the operand of an rvalue reference dynamic_cast must have a complete + class type + * - ``1774``\ + - | ``invalid_function_to_be_defaulted``\ : + | "= default" can only appear on default constructors, copy/move + constructors, copy/move assignment operators, and destructors + * - ``1775``\ + - | ``deleted_function_definition_must_be_first_declaration``\ : + | "= delete" can only appear on the first declaration of a function + * - ``1776``\ + - | ``deleted_function``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot be + referenced -- it is a deleted function + * - ``1777``\ + - | ``bad_unevaluated_lambda``\ : + | a lambda is not allowed in an unevaluated expression + * - ``1778``\ + - | ``bad_function_for_gnu_va_arg_pack``\ : + | __builtin_va_arg_pack/\__builtin_va_arg_pack_len can appear only in + an inline function with an ellipsis parameter + * - ``1779``\ + - | ``function_defaulted_in_friend_decl``\ : + | "= default" cannot be specified on a friend declaration + * - ``1780``\ + - | ``exp_cpp_keyword``\ : + | expected a C++ keyword + * - ``1782``\ + - | ``nonconstant_offsetof``\ : + | offset is not constant + * - ``1783``\ + - | ``unrecognized_microsoft_comment_pragma_type``\ : + | unrecognized #pragma comment type *"xxxx"*\ + * - ``1784``\ + - | ``cl_auto_type_option_only_in_cplusplus``\ : + | option to control whether "auto" is a type specifier can be used only + when compiling C++ + * - ``1785``\ + - | ``cl_auto_storage_option_only_in_cplusplus``\ : + | option to control whether "auto" is a storage class can be used only + when compiling C++ + * - ``1786``\ + - | ``cl_auto_cannot_be_disabled``\ : + | the type specifier and storage class specifier meanings of "auto" + cannot both be disabled + * - ``1787``\ + - | ``bad_pragma_comment_string``\ : + | invalid string in #pragma comment + * - ``1788``\ + - | ``deleted_function_overrides_nondeleted_function``\ : + | deleted function overrides nondeleted *entity-kind "entity"*\ + * - ``1789``\ + - | ``nondeleted_function_overrides_deleted_function``\ : + | nondeleted function overrides deleted *entity-kind "entity"*\ + * - ``1790``\ + - | ``deleted_default_constructor``\ : + | the default constructor of *"type"*\ cannot be referenced -- it is a + deleted function + * - ``1791``\ + - | ``rvalue_reference_catch_type``\ : + | an rvalue reference is not allowed as a catch type + * - ``1792``\ + - | ``default_args_incompatible``\ : + | default arguments of *entity-kind "entity"*\ is incompatible with a + declaration in another translation unit + * - ``1793``\ + - | ``default_arg_differs_in_other_trans_unit``\ : + | default arguments of *entity-kind "entity"*\ were different during + compilation of *"xxxx"*\ + * - ``1795``\ + - | ``initializers_incompatible``\ : + | initializer for *entity-kind "entity"*\ is different in another + translation unit + * - ``1796``\ + - | ``initializer_differs_in_other_trans_unit``\ : + | initializer for *entity-kind "entity"*\ was different during + compilation of *"xxxx"*\ + * - ``1797``\ + - | ``designator_for_template_dependent_type``\ : + | a designator into a template-dependent type is not allowed + * - ``1798``\ + - | ``invalid_pragma_conform_kind``\ : + | unrecognized conformance kind + * - ``1799``\ + - | ``exp_on_or_off``\ : + | expected "on" or "off" + * - ``1800``\ + - | ``forScope_stack_empty``\ : + | #pragma conform(forScope) stack is empty + * - ``1801``\ + - | ``no_matching_forScope_stack_entry``\ : + | no previous #pragma conform(forScope) entry matches *"xxxx"*\ + * - ``1802``\ + - | ``show_pragma_conform_forScope_is_nonstandard``\ : + | forScope behavior is nonstandard + * - ``1803``\ + - | ``show_pragma_conform_forScope_is_standard``\ : + | forScope behavior is standard + * - ``1804``\ + - | ``deleted_main``\ : + | function "main" cannot be deleted + * - ``1805``\ + - | ``useless_type_qualifiers_in_type_name``\ : + | type qualifiers are meaningless here + * - ``1806``\ + - | ``invalid_assignment_operator_to_be_defaulted``\ : + | invalid type for defaulted assignment operator + * - ``1807``\ + - | ``function_template_cannot_be_defaulted``\ : + | function templates cannot be defaulted + * - ``1808``\ + - | ``invalid_constructor_to_be_defaulted``\ : + | invalid type for defaulted constructor + * - ``1809``\ + - | ``call_requires_one_argument``\ : + | function call requires one argument + * - ``1810``\ + - | ``call_requires_floating_point_argument``\ : + | function call requires a real floating-point argument + * - ``1811``\ + - | ``copy_ctor_with_default_arg_cannot_be_defaulted``\ : + | a copy constructor with a default argument cannot be defaulted + * - ``1812``\ + - | ``predeclared_function_cannot_be_deleted``\ : + | a predeclared function cannot be deleted + * - ``1813``\ + - | ``empty_then_statement``\ : + | empty dependent statement in if-statement + * - ``1814``\ + - | ``empty_else_statement``\ : + | empty dependent statement in "else" clause of if-statement + * - ``1815``\ + - | ``deleted_elided_cctor``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ), required for + copy that was eliminated, cannot be referenced -- it is a deleted + function + * - ``1816``\ + - | ``main_first_param_not_int``\ : + | nonstandard first parameter *"type"*\ of "main", expected "int" + * - ``1817``\ + - | ``main_wrong_num_params``\ : + | nonstandard number of parameters for "main", expected zero or two + parameters + * - ``1818``\ + - | ``main_second_param_wrong_type``\ : + | nonstandard second parameter *"type"*\ of "main", expected "char + \*[]" or "char \*\*" + * - ``1819``\ + - | ``incl_dir_both_sys_and_nonsys``\ : + | *"xxxx"*\ was specified as both a system and non-system include + directory -- the non-system entry will be ignored + * - ``1820``\ + - | ``cl_rvalue_ctor_is_copy_ctor_option_only_in_cplusplus``\ : + | option to control move constructors and move assignment operators can + be used only when compiling C++ + * - ``1823``\ + - | ``trailing_return_type_requires_auto``\ : + | a trailing return type requires the "auto" type specifier + * - ``1824``\ + - | ``trailing_return_type_in_nested_declarator``\ : + | a trailing return type cannot appear in a nested declarator + * - ``1825``\ + - | ``trailing_return_type_function_without_simple_auto``\ : + | a function declarator with a trailing return type must be preceded by + a simple "auto" type specifier + * - ``1826``\ + - | ``missing_trailing_return_type``\ : + | "auto" function requires a trailing return type + * - ``1827``\ + - | ``pure_virtual_member_template``\ : + | a member template cannot have a pure specifier + * - ``1828``\ + - | ``excess_characters_in_literal_ignored``\ : + | string literal too long -- excess characters ignored + * - ``1830``\ + - | ``nullptr_conv_to_bool``\ : + | std::nullptr_t converted to bool + * - ``1833``\ + - | ``invalid_empty_attribute_arg_list``\ : + | attribute *"xxxx"*\ does not allow an empty argument list + * - ``1834``\ + - | ``attr_twice_in_group``\ : + | attribute appears more than once + * - ``1835``\ + - | ``wrong_entity_for_attribute``\ : + | attribute *"xxxx"*\ does not apply here + * - ``1836``\ + - | ``attr_disallows_bit_field``\ : + | attribute *"xxxx"*\ does not apply to bit fields + * - ``1837``\ + - | ``attr_requires_bit_field``\ : + | attribute *"xxxx"*\ requires a bit field + * - ``1838``\ + - | ``attr_disallows_member_function``\ : + | attribute *"xxxx"*\ does not apply to member functions + * - ``1839``\ + - | ``attr_requires_member_function``\ : + | attribute *"xxxx"*\ requires a member function + * - ``1840``\ + - | ``attr_disallows_virtual_function``\ : + | attribute *"xxxx"*\ does not apply to virtual functions + * - ``1841``\ + - | ``attr_requires_virtual_function``\ : + | attribute *"xxxx"*\ requires a virtual function + * - ``1842``\ + - | ``attr_disallows_pure_virtual_function``\ : + | attribute *"xxxx"*\ does not apply to pure virtual functions + * - ``1843``\ + - | ``attr_requires_pure_virtual_function``\ : + | attribute *"xxxx"*\ requires a pure virtual function + * - ``1844``\ + - | ``attr_disallows_register_storage``\ : + | attribute *"xxxx"*\ does not apply to register variables + * - ``1845``\ + - | ``attr_requires_register_storage``\ : + | attribute *"xxxx"*\ requires a register variable + * - ``1846``\ + - | ``attr_must_also_appear_in_first_declaration``\ : + | attribute *"xxxx"*\ did not appear on original declaration + * - ``1847``\ + - | ``invalid_attribute_location``\ : + | attributes are not allowed here + * - ``1848``\ + - | ``attr_must_appear_in_class_definition``\ : + | attribute *"xxxx"*\ must appear in a class definition + * - ``1849``\ + - | ``pure_final_virtual``\ : + | "final" applied to a pure virtual function + * - ``1850``\ + - | ``override_of_final_function``\ : + | cannot override "final" *entity-kind "entity"*\ (declared at line + *xxxx*\ ) + * - ``1851``\ + - | ``undefined_static_function_treated_as_extern``\ : + | static *entity-kind "entity"*\ treated as extern because it was + referenced but not defined + * - ``1852``\ + - | ``cl_gnu_c89_inlining_option_only_in_C``\ : + | option to enable GNU-C89-style inlining can be used only when + compiling C + * - ``1853``\ + - | ``first_decl_not_gnu_inline``\ : + | function was previously declared without the "gnu_inline" attribute + * - ``1854``\ + - | ``gnu_inline_requires_inline``\ : + | the "gnu_inline" attribute is ignored on non-inline functions + * - ``1855``\ + - | ``carries_dependency_not_on_first_decl``\ : + | *entity-kind "entity"*\ previously declared without the + carries_dependency attribute + * - ``1856``\ + - | ``bad_array_member_initialization``\ : + | invalid initializer for array *entity-kind "entity"*\ + * - ``1857``\ + - | ``cl_must_specify_cpp11_mode``\ : + | must specify C++11 or C++14 mode when building runtime library + * - ``1858``\ + - | ``attr_disallows_function_type``\ : + | attribute *"xxxx"*\ does not apply to function types + * - ``1859``\ + - | ``attr_requires_function_type``\ : + | attribute *"xxxx"*\ requires a function type + * - ``1860``\ + - | ``attribute_ignored_on_nonstatic_member_function``\ : + | attribute *"xxxx"*\ does not apply to nonstatic member functions + * - ``1861``\ + - | ``attr_disallows_automatic_storage``\ : + | attribute *"xxxx"*\ does not apply to automatic variables + * - ``1862``\ + - | ``attr_requires_automatic_storage``\ : + | attribute *"xxxx"*\ requires an automatic variable + * - ``1863``\ + - | ``attr_disallows_external_linkage``\ : + | attribute *"xxxx"*\ does not apply to a variable or function with + external linkage + * - ``1864``\ + - | ``attr_requires_local_variable``\ : + | attribute *"xxxx"*\ requires a local variable + * - ``1865``\ + - | ``attributes_ignored``\ : + | attributes ignored here + * - ``1866``\ + - | ``unattached_attribute``\ : + | attribute does not apply to any entity + * - ``1867``\ + - | ``bad_attribute_template_substitution``\ : + | bad attribute argument substitution + * - ``1868``\ + - | ``bad_tls_model_attr_arg``\ : + | the argument of the "tls_model" attribute must be "global-dynamic", + "local-dynamic", "initial-exec", or "local-exec" + * - ``1869``\ + - | ``inconsistent_tls_model_attr_arg``\ : + | the declaration at line *xxxx*\ specified a different "tls_model" + argument + * - ``1870``\ + - | ``attr_disallows_inline``\ : + | attribute *"xxxx"*\ does not apply to inline functions + * - ``1871``\ + - | ``attr_requires_inline``\ : + | attribute *"xxxx"*\ requires a inline function + * - ``1872``\ + - | ``include_kind_mismatch``\ : + | both file names in an include_alias pragma must use the same + delimiter characters + * - ``1873``\ + - | ``signed_unsigned_comparison``\ : + | comparison between signed and unsigned operands + * - ``1874``\ + - | ``attribute_ignored_on_unnamed_type``\ : + | attribute *"xxxx"*\ ignored on unnamed type + * - ``1875``\ + - | ``attribute_ignored_on_nondefinition``\ : + | attribute *"xxxx"*\ ignored because no definition follows + * - ``1876``\ + - | ``incompatible_thread_locality``\ : + | thread locality is incompatible with a previous declaration of + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``1877``\ + - | ``no_implicit_capture_on_enclosing_lambda``\ : + | this enclosing-function local variable cannot be referenced in this + lambda body because an enclosing lambda does not allow implicit + captures + * - ``1878``\ + - | ``unbalanced_attribute_argument``\ : + | this attribute argument contains unmatched parentheses, brackets, or + braces + * - ``1879``\ + - | ``invalid_builtin_fpclassify_args``\ : + | a call to \__builtin_fpclassify requires five integral arguments + followed by one floating-point argument + * - ``1880``\ + - | ``bad_final_builtin_fpclassify_arg``\ : + | the last argument in a call to \__builtin_fpclassify must have a real + floating-point type + * - ``1881``\ + - | ``invalid_alignment_reducing_attr``\ : + | alignment cannot be set to less than the default alignment + * - ``1882``\ + - | ``attribute_on_explicit_instantiation``\ : + | attributes are not allowed on explicit instantiations + * - ``1883``\ + - | ``attr_disallows_definition``\ : + | attribute *"xxxx"*\ does not apply to a definition + * - ``1884``\ + - | ``attr_requires_definition``\ : + | attribute *"xxxx"*\ requires a definition + * - ``1885``\ + - | ``friend_attribute_requires_definition``\ : + | standard attributes cannot appear on friend declarations that are not + definitions + * - ``1886``\ + - | ``inconsistent_alignment``\ : + | specified alignment (*xxxx*\ ) is different from alignment (*xxxx*\ ) + specified on a previous declaration + * - ``1887``\ + - | ``variable_align_attr_not_on_definition``\ : + | alignment attribute must also appear on definition at line *xxxx*\ + * - ``1888``\ + - | ``alias_used_in_type``\ : + | *entity-kind "entity"*\ may not be used in the type-id of the + alias-declaration + * - ``1890``\ + - | ``transparent_union_cannot_have_floating_first_field``\ : + | *"type"*\ cannot be transparent because its first field has a + floating-point type + * - ``1891``\ + - | ``transparent_union_cannot_have_bit_field_first``\ : + | *"type"*\ cannot be transparent because its first field is a bit + field + * - ``1892``\ + - | ``missing_override_attr_in_base_check_class``\ : + | virtual function of a "base_check" class overrides a base class + member but lacks the "override" attribute + * - ``1893``\ + - | ``hiding_attr_on_nonhiding_member``\ : + | "hiding" attribute specified on a declaration that does not hide a + base class declaration + * - ``1894``\ + - | ``hiding_attr_on_unhidden_member``\ : + | "hiding" attribute specified on a declaration referred to by the + using-declaration at line *xxxx*\ + * - ``1895``\ + - | ``hiding_attr_required``\ : + | attribute "hiding" is required on a declaration (in a "base_check" + class) that hides *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``1896``\ + - | ``undefined_decl_using_local_type``\ : + | *entity-kind "entity"*\ is not defined in this translation unit but + depends on a local type + * - ``1897``\ + - | ``undefined_decl_using_no_linkage_type``\ : + | *entity-kind "entity"*\ is not defined in this translation unit but + depends on a type with no linkage + * - ``1898``\ + - | ``missing_attribute_in_other_translation_unit``\ : + | attribute *"xxxx"*\ is missing in another translation unit + * - ``1899``\ + - | ``conflicting_attribute_in_other_translation_unit``\ : + | attribute *"xxxx"*\ conflicts with another translation unit + * - ``1900``\ + - | ``cl_nonstd_gnu_keywords_requires_gnu_mode``\ : + | the "nonstd_gnu_keywords" option is only valid in GNU C and GNU C++ + modes + * - ``1901``\ + - | ``const_var_in_C_const_expr``\ : + | use of a const variable in a constant expression is nonstandard in C + * - ``1902``\ + - | ``cannot_init_auto_flexible_array_member``\ : + | an initializer cannot be specified for a flexible array member with + automatic storage duration + * - ``1904``\ + - | ``final_base_class``\ : + | a "final" class type cannot be used as a base class + * - ``1905``\ + - | ``export_removed``\ : + | exported templates are no longer in the standard C++ language + * - ``1906``\ + - | ``template_dependent_designator``\ : + | a template-dependent designator is not allowed + * - ``1907``\ + - | ``offsetof_ref_field``\ : + | second operand of offsetof may not be a field with reference type + * - ``1908``\ + - | ``cl_long_lifetime_temps_incompat_with_newer_features``\ : + | long lifetime temporaries are incompatible with other requested newer + language features + * - ``1909``\ + - | ``wide_deprecation_string``\ : + | wide character string literal will not be quoted in diagnostics + * - ``1910``\ + - | ``missing_attribute_arguments``\ : + | missing arguments for attribute *"xxxx"*\ + * - ``1911``\ + - | ``sfinae_requires_newer_abi_version``\ : + | options "c++11" and "c++11_sfinae" require a different compiler + configuration + * - ``1912``\ + - | ``template_param_pack_not_at_end``\ : + | template parameter pack not at end of parameter list + * - ``1913``\ + - | ``parameter_pack_decl_not_allowed``\ : + | a parameter pack declaration is not allowed here + * - ``1914``\ + - | ``param_pack_cannot_have_default``\ : + | a parameter pack cannot have a default + * - ``1915``\ + - | ``cl_cppcli_only_in_microsoft_cplusplus``\ : + | C++/CLI can be enabled only in Microsoft C++ mode + * - ``1916``\ + - | ``reserved_enumerator_name``\ : + | "value\__" cannot be used as the name of an enumerator constant (it + is a reserved name in this context) + * - ``1917``\ + - | ``cppcli_enumerator_requires_explicit_value``\ : + | an explicit enumerator value is required in an enum type with boolean + underlying type + * - ``1919``\ + - | ``pack_not_expanded``\ : + | parameter pack *"xxxx"*\ was referenced but not expanded + * - ``1920``\ + - | ``expansion_contains_no_packs``\ : + | pack expansion does not make use of any argument packs + * - ``1921``\ + - | ``pack_length_mismatch``\ : + | pack *"xxxx"*\ does not have the same number of elements as + *"xxxx"*\ + * - ``1923``\ + - | ``vector_size_attribute_on_enum_type``\ : + | vector_size attribute is not allowed with an enum type + * - ``1924``\ + - | ``virtual_static_property``\ : + | a property cannot be both static and virtual + * - ``1925``\ + - | ``trivial_indexed_property``\ : + | an indexed property cannot be trivial + * - ``1926``\ + - | ``invalid_property_accessor_decl``\ : + | this declaration cannot appear in a property definition + * - ``1927``\ + - | ``qualified_cli_accessor``\ : + | a qualified function type cannot be used to declare an accessor + function + * - ``1928``\ + - | ``ellipsis_cli_accessor``\ : + | an accessor function cannot have an ellipsis parameter + * - ``1929``\ + - | ``property_get_already_declared``\ : + | a "get" accessor was already declared for this property at line + *xxxx*\ + * - ``1930``\ + - | ``property_set_already_declared``\ : + | a "set" accessor was already declared for this property at line + *xxxx*\ + * - ``1931``\ + - | ``property_get_cannot_have_parameter``\ : + | a "get" accessor cannot have a parameter + * - ``1932``\ + - | ``bad_property_get_return``\ : + | return type of "get" accessor does not match property type + * - ``1933``\ + - | ``bad_property_set_return``\ : + | return type of "set" accessor must be void + * - ``1934``\ + - | ``empty_property_indices``\ : + | a property cannot declare an empty list of indices + * - ``1935``\ + - | ``void_property_index_type``\ : + | a property index cannot have type void + * - ``1936``\ + - | ``property_set_index_type_mismatch``\ : + | index type does not match the corresponding parameter in the "set" + accessor + * - ``1937``\ + - | ``property_get_index_type_mismatch``\ : + | index type does not match the corresponding parameter in the "get" + accessor + * - ``1938``\ + - | ``property_set_index_type_missing``\ : + | index type is missing in the "set" accessor + * - ``1939``\ + - | ``property_get_index_type_missing``\ : + | index type is missing in the "get" accessor + * - ``1940``\ + - | ``property_set_missing_value_parameter``\ : + | "set" accessor is missing its value parameter + * - ``1941``\ + - | ``extra_property_accessor_parameters``\ : + | accessor function has too many parameters + * - ``1942``\ + - | ``property_set_value_parameter_mismatch``\ : + | the last parameter of the "set" accessor does not match the property + type + * - ``1943``\ + - | ``cppcli_not_enabled``\ : + | *"xxxx"*\ requires C++/CLI mode + * - ``1944``\ + - | ``win32_api_error``\ : + | error in Win32 API "*xxxx*\ ": *xxxx*\ + * - ``1945``\ + - | ``using_not_at_file_scope``\ : + | #using may only be used at global scope + * - ``1947``\ + - | ``member_name_reserved_by_property``\ : + | member name *"xxxx"*\ is reserved by *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``1948``\ + - | ``exp_lbracket``\ : + | expected a "[" + * - ``1949``\ + - | ``cl_microsoft_version_insufficient_for_cppcli``\ : + | C++/CLI mode requires microsoft_version >= 1600 + * - ``1950``\ + - | ``static_default_indexed_property``\ : + | a default-indexed property cannot be static + * - ``1951``\ + - | ``virtual_static_property_accessor``\ : + | a property accessor cannot be both static and virtual + * - ``1952``\ + - | ``visibility_specifier_on_nested_type``\ : + | a top-level visibility specifier cannot appear on a nested type + declaration + * - ``1953``\ + - | ``visibility_specifier_requires_definition``\ : + | a top-level visibility specifier requires a type definition + * - ``1954``\ + - | ``trivial_reference_property``\ : + | a trivial property cannot have a reference type + * - ``1955``\ + - | ``trivial_const_or_volatile_property``\ : + | a trivial property cannot have a const or volatile type + * - ``1956``\ + - | ``incompatible_enum_kinds``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared as a different kind of enum type + * - ``1957``\ + - | ``lambda_captures_managed_class_type``\ : + | a variable captured by a lambda cannot have a managed class type + * - ``1958``\ + - | ``covariant_override_in_managed_class``\ : + | virtual function overriding with a covariant return type is not + allowed in a managed class + * - ``1959``\ + - | ``array_of_handle``\ : + | array of handles is not allowed + * - ``1960``\ + - | ``handle_to_array``\ : + | handle to array is not allowed + * - ``1961``\ + - | ``handle_to_function``\ : + | handle to function is not allowed + * - ``1962``\ + - | ``handle_to_void``\ : + | handle to void is not allowed + * - ``1963``\ + - | ``handle_to_address_type``\ : + | handle to handle, pointer, or reference is not allowed + * - ``1964``\ + - | ``tracking_reference_to_function``\ : + | tracking reference to function is not allowed + * - ``1966``\ + - | ``field_cannot_be_tracking_reference``\ : + | a field cannot be a tracking reference + * - ``1967``\ + - | ``invalid_ref_tracking_ref_combination``\ : + | a tracking reference cannot be combined with an ordinary reference in + this way + * - ``1968``\ + - | ``static_storage_variable_with_ref_class_type``\ : + | a variable with static storage duration cannot have a ref class type + * - ``1969``\ + - | ``unnamed_cli_managed_class_type``\ : + | a managed class cannot be unnamed + * - ``1970``\ + - | ``local_cli_managed_class_type``\ : + | a managed class cannot be local + * - ``1971``\ + - | ``conflicting_cli_class_type_kinds``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared as a different kind of class + * - ``1972``\ + - | ``conflicting_cli_class_template_kinds``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared as a different kind of class template + * - ``1973``\ + - | ``literal_requires_managed_class``\ : + | literal data members can only be members of managed classes + * - ``1974``\ + - | ``literal_without_initializer``\ : + | a literal data member must be initialized + * - ``1975``\ + - | ``invalid_literal_type``\ : + | a literal data member of type *"type"*\ is not allowed + * - ``1976``\ + - | ``literal_const_has_no_effect``\ : + | const has no effect on a literal data member + * - ``1977``\ + - | ``initonly_requires_managed_class``\ : + | initonly data members can only be members of managed classes + * - ``1978``\ + - | ``initonly_const_has_no_effect``\ : + | const has no effect on an initonly data member + * - ``1979``\ + - | ``cli_get_accessor_missing``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) has no "get" + accessor + * - ``1980``\ + - | ``cli_set_accessor_missing``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) has no "set" + accessor + * - ``1981``\ + - | ``static_constructor_with_params``\ : + | a static constructor cannot have parameters + * - ``1982``\ + - | ``static_constructor_member_template``\ : + | a static constructor cannot be a member template + * - ``1983``\ + - | ``compound_lvalue_as_asm_operand``\ : + | a compound lvalue is not allowed as an asm output operand + * - ``1984``\ + - | ``property_requires_managed_class``\ : + | properties can only be members of managed classes + * - ``1985``\ + - | ``qualifier_not_allowed_on_managed_member_function``\ : + | a type qualifier is not allowed on a member function of a managed + class + * - ``1986``\ + - | ``pointer_to_ref_or_interface_class``\ : + | an ordinary pointer to a C++/CLI ref class or interface class is not + allowed + * - ``1987``\ + - | ``reference_to_ref_or_interface_class``\ : + | an ordinary reference to a C++/CLI ref class or interface class is + not allowed + * - ``1988``\ + - | ``override_name_must_be_a_base_class_member_function``\ : + | override specifier does not name a base class member function + * - ``1989``\ + - | ``override_name_nonvirtual``\ : + | override specifier designates a nonvirtual member *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``1990``\ + - | ``multiple_overrides``\ : + | member function overrides *entity-kind "entity"*\ (declared at line + *xxxx*\ ) which is already overridden by *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``1991``\ + - | ``multiple_visibility_specifiers``\ : + | at most one visibility specifier is allowed + * - ``1992``\ + - | ``invalid_delegate_type``\ : + | type *"type"*\ used for delegate definition is not a function type + * - ``1993``\ + - | ``delegate_requires_managed_class``\ : + | delegate member types can only be members of managed classes + * - ``1994``\ + - | ``tracking_reference_to_delegate``\ : + | a tracking reference to a delegate type is not allowed + * - ``1995``\ + - | ``bad_use_of_delegate_type``\ : + | a delegate type is not allowed here + * - ``1996``\ + - | ``empty_pack_expansion``\ : + | this pack expansion produced an empty list of expressions, and an + expression is needed here + * - ``1997``\ + - | ``virtual_static_event``\ : + | an event cannot be both static and virtual + * - ``1998``\ + - | ``event_requires_managed_class``\ : + | events can only be members of managed classes + * - ``1999``\ + - | ``invalid_event_accessor_decl``\ : + | this declaration cannot appear in an event definition + * - ``2000``\ + - | ``invalid_event_type``\ : + | event type must be a handle-to-delegate type + * - ``2001``\ + - | ``event_add_already_declared``\ : + | an "add" accessor was already declared for this event at line *xxxx*\ + * - ``2002``\ + - | ``event_remove_already_declared``\ : + | a "remove" accessor was already declared for this event at line + *xxxx*\ + * - ``2003``\ + - | ``event_raise_already_declared``\ : + | a "raise" accessor was already declared for this event at line + *xxxx*\ + * - ``2004``\ + - | ``virtual_static_event_accessor``\ : + | an event accessor cannot be both static and virtual + * - ``2005``\ + - | ``bad_event_add_or_remove_return``\ : + | return type of "add" and "remove" accessors must be void + * - ``2006``\ + - | ``event_accessor_missing_value_parameter``\ : + | event accessor is missing its value parameter + * - ``2007``\ + - | ``extra_event_accessor_parameters``\ : + | accessor function has too many parameters + * - ``2008``\ + - | ``event_accessor_value_parameter_mismatch``\ : + | the type *"type"*\ of the parameter of the event accessor does not + match the event type (*"type"*\ ) + * - ``2009``\ + - | ``event_raise_type_mismatch``\ : + | the type of the "raise" accessor does not match the event's delegate + invocation type + * - ``2010``\ + - | ``missing_add_or_remove_accessor``\ : + | an event definition must include both "add" and "remove" accessors + * - ``2011``\ + - | ``static_conversion_function_must_have_one_parameter``\ : + | a static conversion function must accept exactly one argument + * - ``2012``\ + - | ``bad_parameter_type_for_static_member_operator``\ : + | static operator must have a parameter type T, T&, T%, or T^ with T = + *"type"*\ + * - ``2013``\ + - | ``sizeof_operand_not_parameter_pack``\ : + | the operand of sizeof... must be a parameter pack name + * - ``2014``\ + - | ``sizeof_pack_in_non_variadic_context``\ : + | the sizeof... operator can be used only in a variadic template + * - ``2015``\ + - | ``event_name_not_allowed``\ : + | event name cannot appear here + * - ``2016``\ + - | ``handle_to_standard_class_type``\ : + | a handle to a non-managed class is not allowed + * - ``2017``\ + - | ``handle_to_unscoped_enum_type``\ : + | a handle to an unscoped enum type is not allowed + * - ``2018``\ + - | ``property_attribute_in_managed_class``\ : + | "property" attribute not allowed in managed class + * - ``2019``\ + - | ``pure_virtual_definition``\ : + | a pure specifier ("= 0") followed by a definition is nonstandard + * - ``2020``\ + - | ``managed_nullptr_not_allowed``\ : + | the managed nullptr type cannot be used here + * - ``2021``\ + - | ``addr_of_ref_class``\ : + | the "&" operator cannot be used to take the address of an object with + a ref class type + * - ``2022``\ + - | ``array_of_managed_class``\ : + | array of managed class is not allowed + * - ``2023``\ + - | ``static_storage_variable_with_handle_or_tracking_ref_type``\ : + | a variable with static storage duration cannot have a handle or + tracking reference type + * - ``2024``\ + - | ``lambda_captures_handle_or_tracking_ref``\ : + | a variable captured by a lambda cannot be a handle or tracking + reference + * - ``2025``\ + - | ``invalid_param_array_type``\ : + | a C++/CLI parameter array requires a handle to a one-dimensional + cli::array type + * - ``2026``\ + - | ``cannot_import_metadata``\ : + | could not import metadata from file *"xxxx"*\ + * - ``2027``\ + - | ``namespace_cli_cannot_be_extended``\ : + | the cli namespace cannot be extended + * - ``2028``\ + - | ``cli_array_invalid_element_type``\ : + | the element type of a cli::array must be a handle or value type + * - ``2029``\ + - | ``cli_array_invalid_number_of_dimensions``\ : + | invalid number of dimensions for cli::array type + * - ``2030``\ + - | ``invalid_type_pointed_to_for_interior_ptr_or_pin_ptr``\ : + | a cli::interior_ptr/cli::pin_ptr must point to a standard class, a + value class, an integer, a handle, or a standard pointer + * - ``2031``\ + - | ``type_cannot_be_class_member``\ : + | *"type"*\ cannot be a class member + * - ``2032``\ + - | ``pin_ptr_param_not_allowed``\ : + | a parameter of type cli::pin_ptr is not allowed + * - ``2033``\ + - | ``bad_finalizer_decl``\ : + | invalid finalizer declaration + * - ``2034``\ + - | ``too_many_params_for_finalizer``\ : + | a finalizer may not have parameters + * - ``2035``\ + - | ``function_qualifier_on_finalizer``\ : + | a type qualifier is not allowed on a finalizer + * - ``2036``\ + - | ``return_type_on_finalizer``\ : + | a return type may not be specified on a finalizer + * - ``2037``\ + - | ``no_finalizer_using_declaration``\ : + | a using-declaration may not name a finalizer + * - ``2038``\ + - | ``finalizer_name_must_be_qualified``\ : + | a finalizer name must be qualified + * - ``2039``\ + - | ``finalizer_qualifier_type_mismatch``\ : + | qualifier of finalizer name *"type"*\ does not match type *"type"*\ + * - ``2040``\ + - | ``var_used_as_finalizer``\ : + | *entity-kind "entity"*\ cannot be used to name a finalizer (a type + name is required) + * - ``2041``\ + - | ``invalid_finalizer_name``\ : + | invalid finalizer name for type *"type"*\ + * - ``2042``\ + - | ``ambiguous_finalizer``\ : + | finalizer reference is ambiguous -- both *entity-kind "entity"*\ and + *entity-kind "entity"*\ could be used + * - ``2043``\ + - | ``finalizer_requires_reference_type``\ : + | a finalizer can only be a member of a ref class + * - ``2045``\ + - | ``finalizer_type_mismatch``\ : + | type used as finalizer name does not match type *"type"*\ + * - ``2046``\ + - | ``finalizer_does_not_exist``\ : + | a finalizer does not exist for this type + * - ``2047``\ + - | ``handle_of_non_managed``\ : + | the "%" operator can be used only on an object with a managed class + type + * - ``2048``\ + - | ``ptr_handle_or_ref_to_interior_ptr``\ : + | a pointer, handle, or reference to a cli::interior_ptr is not allowed + * - ``2049``\ + - | ``ptr_handle_or_ref_to_pin_ptr``\ : + | a pointer, handle, or reference to a cli::pin_ptr is not allowed + * - ``2050``\ + - | ``ptr_or_ref_to_cli_array``\ : + | a pointer or reference to a C++/CLI array is not allowed + * - ``2051``\ + - | ``bad_use_of_cli_array_type``\ : + | a C++/CLI array type is not allowed here + * - ``2052``\ + - | ``invalid_ref_class_base``\ : + | a C++/CLI ref class can only derive from another ref class or from + interface classes + * - ``2053``\ + - | ``invalid_value_class_base``\ : + | a C++/CLI value class can only derive from interface classes + * - ``2054``\ + - | ``invalid_interface_class_base``\ : + | a C++/CLI interface class can only derive from interface classes + * - ``2055``\ + - | ``ref_class_has_multiple_ref_bases``\ : + | a ref class can have at most one direct ref base class (*"type"*\ is + already such a base) + * - ``2056``\ + - | ``managed_base_for_standard_class``\ : + | a standard class cannot derive from a managed class + * - ``2057``\ + - | ``virtual_base_for_managed_class``\ : + | a managed class cannot have a virtual base + * - ``2058``\ + - | ``managed_class_type_cannot_have_private_or_protected_base``\ : + | a managed class cannot have a "private" or "protected" base + * - ``2059``\ + - | ``override_requires_virtual``\ : + | the "override" modifier requires a virtual function declaration with + an explicit "virtual" keyword + * - ``2060``\ + - | ``abstract_requires_virtual``\ : + | the "abstract" modifier requires a virtual function declaration with + an explicit "virtual" keyword + * - ``2061``\ + - | ``sealed_requires_virtual``\ : + | the "sealed" modifier requires a virtual function declaration with an + explicit "virtual" keyword + * - ``2062``\ + - | ``named_override_requires_virtual``\ : + | a named override specifier requires a virtual function declaration + with an explicit "virtual" keyword + * - ``2063``\ + - | ``pin_ptr_return_type_not_allowed``\ : + | a cli::pin_ptr return type is not allowed + * - ``2064``\ + - | ``cppcli_attribute_only``\ : + | attribute *"xxxx"*\ applies in C++/CLI mode only + * - ``2065``\ + - | ``normal_ref_bound_to_gc_lvalue``\ : + | a simple (non-tracking) reference cannot be bound to an entity on the + managed heap + * - ``2067``\ + - | ``cli_entity_not_loaded``\ : + | "*xxxx*\ " not loaded from default assemblies + * - ``2068``\ + - | ``list_initializer_nonstandard_in_current_mode``\ : + | list initialization syntax is a C++11 feature + * - ``2069``\ + - | ``sizeof_ref_or_interface_class``\ : + | operand of sizeof may not be a ref class type or interface class type + * - ``2070``\ + - | ``cli_array_invalid_number_of_subscripts``\ : + | invalid number of subscripts for this cli::array type + * - ``2071``\ + - | ``ptr_to_member_of_managed_class``\ : + | a pointer-to-member is not valid for a managed class + * - ``2072``\ + - | ``private_virtual_member_function_not_sealed``\ : + | private virtual member function of managed class is not "sealed" + * - ``2073``\ + - | ``modifier_not_allowed_on_destructor``\ : + | modifier is not allowed on a destructor + * - ``2074``\ + - | ``modifier_not_allowed_on_finalizer``\ : + | modifier is not allowed on a finalizer + * - ``2075``\ + - | ``virtual_has_no_effect``\ : + | "virtual" has no effect on a destructor of a managed class + * - ``2076``\ + - | ``new_or_override_required``\ : + | "new" or "override" is required because this declaration matches + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``2077``\ + - | ``new_or_virtual_required``\ : + | "new" or "virtual" is required because this declaration matches + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``2078``\ + - | ``override_for_interface_member``\ : + | "new" or "override" are not valid here because the matching + *entity-kind "entity"*\ (declared at line *xxxx*\ ) is a member of + an interface + * - ``2079``\ + - | ``new_requires_matching_base_member``\ : + | "new" modifier without a matching base ref class member + * - ``2080``\ + - | ``overriding_reduces_accessibility_in_managed_type``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) overridden with + reduced access + * - ``2081``\ + - | ``bad_tracking_ref_init``\ : + | a reference of type *"type"*\ cannot be initialized with a value of + type *"type"*\ + * - ``2082``\ + - | ``copy_constructor_in_value_class_type``\ : + | a copy constructor cannot be declared in a value class + * - ``2083``\ + - | ``default_constructor_in_value_class_type``\ : + | a default constructor cannot be declared in a value class + * - ``2084``\ + - | ``destructor_in_value_class_type``\ : + | a destructor cannot be declared in a value class + * - ``2085``\ + - | ``assignment_in_value_class_type``\ : + | an assignment operator cannot be declared in a value class + * - ``2086``\ + - | ``nonvalue_class_type_cannot_be_value_class_member``\ : + | non-value class *"type"*\ cannot be the type of a member of a value + class + * - ``2087``\ + - | ``cppcli_requires_newer_abi_version``\ : + | option "cppcli" requires a different compiler configuration + * - ``2088``\ + - | ``managed_member_exception_spec``\ : + | exception specifications are not allowed on member functions of + managed classes + * - ``2089``\ + - | ``managed_class_cannot_have_friend``\ : + | a managed class cannot declare a friend + * - ``2092``\ + - | ``local_class_in_managed_member_function``\ : + | a local class definition is not allowed in a member function of a + managed class + * - ``2093``\ + - | ``local_lambda_in_managed_member_function``\ : + | a local lambda is not allowed in a member function of a managed class + * - ``2094``\ + - | ``cli_interface_member_function_definition``\ : + | a member function of a C++/CLI interface class type cannot have a + definition + * - ``2095``\ + - | ``missing_get_and_set_accessors``\ : + | a property definition must include at least one accessor ("get" or + "set") + * - ``2096``\ + - | ``subscript_mechanism_conflict``\ : + | default-indexed property conflicts with *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``2097``\ + - | ``unusable_pack``\ : + | *entity-kind "entity"*\ cannot be used because it follows a + parameter pack and cannot be deduced from the parameters of + *entity-kind "entity"*\ + * - ``2098``\ + - | ``excess_pack_expansion``\ : + | this pack expansion produced more than one expression, and a single + expression is needed here + * - ``2099``\ + - | ``cli_enum_base_has_no_system_counterpart``\ : + | type must correspond to System::Boolean, System::Byte, System::SByte, + System::Int16, System::UInt16, System::Int32, System::UInt32, + System::Int64, or System::UInt64 + * - ``2100``\ + - | ``bad_call_of_handle``\ : + | call of an object of a handle type without appropriate operator() or + conversion functions to pointer-to-function type + * - ``2101``\ + - | ``abstract_declarator_pack_is_nested``\ : + | an unnamed parameter pack declaration cannot be parenthesized + * - ``2102``\ + - | ``cl_variadic_templates_only_in_cplusplus``\ : + | variadic templates can be enabled only when compiling C++ + * - ``2103``\ + - | ``conflicting_properties``\ : + | property definition conflicts with *entity-kind "entity"*\ (declared + at line *xxxx*\ ) + * - ``2106``\ + - | ``generic_param_cannot_have_default``\ : + | a generic parameter cannot have a default + * - ``2107``\ + - | ``bad_param_kind_for_generic``\ : + | a generic can only have type parameters + * - ``2108``\ + - | ``for_each_missing_function``\ : + | to be used with "for each" statements, type *"type"*\ must provide + nonstatic member function *"xxxx"*\ + * - ``2109``\ + - | ``for_each_static_function``\ : + | "for each" cannot use member *entity-kind "entity"*\ because it is + static + * - ``2110``\ + - | ``for_each_no_matching_overload``\ : + | in this "for each" statement, no instance of *"entity"*\ is callable + with an empty argument list + * - ``2111``\ + - | ``for_each_invalid_return_type_for_move_next``\ : + | "for each" cannot use member function "MoveNext" because the return + type is invalid + * - ``2112``\ + - | ``for_each_incompatible_type``\ : + | a "for each" statement cannot operate on an expression of type + *"type"*\ + * - ``2113``\ + - | ``for_each_missing_field``\ : + | to be used with "for each" statements, type *"type"*\ must provide a + non-indexed property *"xxxx"*\ + * - ``2115``\ + - | ``for_each_getenumerator_return_type_invalid``\ : + | in this "for each" statement, *"type"*\ is not a valid enumerator + (returned by "GetEnumerator" of *"type"*\ ) + * - ``2116``\ + - | ``exp_in``\ : + | expected "in" + * - ``2117``\ + - | ``no_suitable_synthesis_assignment_operator``\ : + | class *"type"*\ has no suitable assignment operator (after operator + synthesis) + * - ``2118``\ + - | ``not_a_generic_param``\ : + | *"xxxx"*\ is not a generic parameter + * - ``2119``\ + - | ``not_generic_param_of_curr_decl``\ : + | *"xxxx"*\ is not a generic parameter of the innermost generic + parameter list + * - ``2120``\ + - | ``invalid_constraint``\ : + | invalid generic constraint + * - ``2121``\ + - | ``invalid_event_use``\ : + | invalid use of event member (only subscription, unsubscription, and + invocation are allowed) + * - ``2122``\ + - | ``event_without_raise_invoked``\ : + | invoking an event with no "raise" accessor is invalid + * - ``2123``\ + - | ``bad_event_compound_assignment``\ : + | only "+=" and "-=" are valid for events + * - ``2124``\ + - | ``typeid_of_managed_type``\ : + | typeid of a managed type is not allowed + * - ``2125``\ + - | ``cli_typeid_of_managed_pointer``\ : + | typeid of a managed pointer type is not allowed + * - ``2126``\ + - | ``name_before_typeid_not_type``\ : + | name followed by "::typeid" must be a type name + * - ``2127``\ + - | ``reserved_dispose``\ : + | a member *"xxxx"*\ of this type is reserved within a managed class + -- destructor intended? + * - ``2128``\ + - | ``reserved_finalize``\ : + | a member *"xxxx"*\ of this type is reserved within a managed class + -- finalizer intended? + * - ``2129``\ + - | ``invalid_idisposable_dispose``\ : + | System::IDisposable::Dispose is missing or invalid + * - ``2130``\ + - | ``invalid_object_finalize``\ : + | System::Object::Finalize is missing or invalid + * - ``2131``\ + - | ``finalize_does_not_override_object_finalize``\ : + | *entity-kind "entity"*\ does not override System::Object::Finalize + * - ``2132``\ + - | ``bad_handle_dynamic_cast_operand``\ : + | the operand of a handle dynamic_cast must be a handle to a complete + class type + * - ``2133``\ + - | ``bad_tracking_ref_dynamic_cast_operand``\ : + | the operand of a tracking-reference dynamic_cast must be an lvalue of + a complete class type + * - ``2134``\ + - | ``bad_cli_dynamic_cast_type``\ : + | the type in a dynamic_cast to a handle or tracking reference type + must refer to a complete class + * - ``2135``\ + - | ``cast_interior_ptr_to_ptr``\ : + | an interior pointer cannot be cast to a native pointer + * - ``2136``\ + - | ``cppcli_explicit_conversion_only_in_ref_and_value_classes``\ : + | explicit conversion operators can only be declared in ref and value + class types + * - ``2137``\ + - | ``cppcli_explicit_conversion_is_virtual``\ : + | explicit conversion operator cannot be virtual + * - ``2138``\ + - | ``expr_not_arithmetic_or_unscoped_enum``\ : + | expression must have arithmetic or unscoped enum type + * - ``2139``\ + - | ``expr_not_arithmetic_or_unscoped_enum_or_pointer``\ : + | expression must have arithmetic, unscoped enum, or pointer type + * - ``2140``\ + - | ``expr_not_integral_or_unscoped_enum``\ : + | expression must have integral or unscoped enum type + * - ``2141``\ + - | ``expr_not_integral_or_unscoped_enum_or_fixed_point``\ : + | expression must have integral, unscoped enum, or fixed-point type + * - ``2142``\ + - | ``scoped_enum_operation_type_mismatch``\ : + | a built-in binary operator applied to a scoped enumeration requires + two operands of the same type + * - ``2143``\ + - | ``invalid_gcnew_type``\ : + | gcnew cannot allocate an entity of type *"type"*\ + * - ``2144``\ + - | ``gcnew_used_with_placement_syntax``\ : + | placement syntax cannot be used with gcnew + * - ``2145``\ + - | ``new_used_on_unsuitable_value_type``\ : + | new can only be used with simple value types + * - ``2146``\ + - | ``new_used_on_managed_class_type``\ : + | new cannot be used on a managed class (gcnew should be used instead) + * - ``2147``\ + - | ``new_used_on_handle_or_tracking_reference_type``\ : + | new cannot be used on a handle type + * - ``2148``\ + - | ``cli_array_must_have_new_or_array_init``\ : + | gcnew for a C++/CLI array must have a new initializer or an array + initializer + * - ``2149``\ + - | ``gcnew_bad_type_used_with_array_init``\ : + | an array initializer can only be used to initialize a C++/CLI array + type + * - ``2150``\ + - | ``gcnew_used_with_auto_syntax``\ : + | gcnew does not allow auto + * - ``2151``\ + - | ``too_many_array_bounds``\ : + | too many array bounds + * - ``2152``\ + - | ``too_few_array_bounds``\ : + | too few array bounds + * - ``2153``\ + - | ``too_few_generic_args``\ : + | too few arguments for *entity-kind "entity"*\ + * - ``2154``\ + - | ``too_many_generic_args``\ : + | too many arguments for *entity-kind "entity"*\ + * - ``2156``\ + - | ``no_matching_arity``\ : + | no declaration of *entity-kind "entity"*\ accepts the number of + generic arguments supplied + * - ``2157``\ + - | ``bad_function_for_delegate``\ : + | invalid delegate initializer -- must be a function + * - ``2158``\ + - | ``ambiguous_function_for_delegate``\ : + | invalid delegate initializer -- more than one function matches the + delegate type + * - ``2159``\ + - | ``mismatched_function_for_delegate``\ : + | invalid delegate initializer -- function does not match the delegate + type + * - ``2160``\ + - | ``missing_delegate_object``\ : + | invalid delegate initializer -- an object is needed in addition to a + function + * - ``2161``\ + - | ``nonmanaged_function_for_delegate``\ : + | invalid delegate initializer -- function is not a member of a managed + class + * - ``2162``\ + - | ``superfluous_delegate_object``\ : + | invalid delegate initializer -- object is not needed for the + specified function + * - ``2163``\ + - | ``incompatible_delegate_object``\ : + | invalid delegate initializer -- object has type *"type"*\ but type + *"type"*\ is expected + * - ``2164``\ + - | ``address_of_managed_member_function``\ : + | taking the address of a member function of a managed class is not + allowed + * - ``2165``\ + - | ``bad_delegate_init_list``\ : + | invalid delegate initializer -- expected either + "()" or "(, )" + * - ``2166``\ + - | ``interface_not_implemented``\ : + | class fails to implement interface member *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``2167``\ + - | ``gcnew_of_native_array``\ : + | gcnew cannot be used to allocate a native array + * - ``2168``\ + - | ``cli_interface_cannot_have_assignment``\ : + | a C++/CLI interface class cannot declare an assignment operator + * - ``2169``\ + - | ``sealed_cli_interface``\ : + | a C++/CLI interface class cannot be sealed + * - ``2171``\ + - | ``destructor_or_finalizer_with_named_override``\ : + | a destructor or finalizer declaration cannot include a named override + specifier + * - ``2172``\ + - | ``override_name_is_destructor_or_finalizer``\ : + | an override specifier cannot designate a destructor or finalizer + * - ``2173``\ + - | ``named_override_requires_managed_type``\ : + | a named override specifier is allowed only in a managed class + * - ``2174``\ + - | ``named_override_type_mismatch``\ : + | no member designated by the named override specifier matches the type + of this member + * - ``2175``\ + - | ``static_constructor_with_named_override``\ : + | a static constructor declaration cannot include a named override + specifier + * - ``2176``\ + - | ``unnamed_scoped_enum``\ : + | a scoped enum type must have a name + * - ``2177``\ + - | ``branch_into_finally``\ : + | transfer of control into a finally block is not allowed + * - ``2178``\ + - | ``return_from_finally``\ : + | return statement inside a finally block is not allowed + * - ``2179``\ + - | ``missing_finally``\ : + | try block requires at least one handler or finally clause + * - ``2180``\ + - | ``managed_object_not_thrown_by_handle``\ : + | a managed object must be thrown by handle + * - ``2181``\ + - | ``managed_object_not_caught_by_handle``\ : + | a managed object must be caught by handle + * - ``2182``\ + - | ``break_cannot_be_in_finally_block``\ : + | a break statement cannot be used in a finally block + * - ``2183``\ + - | ``continue_cannot_be_in_finally_block``\ : + | a continue statement cannot be used in a finally block + * - ``2184``\ + - | ``no_overloaded_subscript_with_offsetof``\ : + | builtin offsetof cannot be used when subscripting is overloaded + * - ``2185``\ + - | ``duplicate_constraint``\ : + | duplicate constraint + * - ``2186``\ + - | ``multiple_class_constraints``\ : + | more than one class constraint: *"type"*\ and *"type"*\ + * - ``2187``\ + - | ``multiple_constraint_clauses``\ : + | more than one constraint clause for *entity-kind "entity"*\ + * - ``2188``\ + - | ``initonly_static_data_member_not_initialized``\ : + | initonly static data members must have an initializer or be + initialized in a static constructor + * - ``2189``\ + - | ``gnu_attr_on_template_redecl``\ : + | GNU attributes on a template redeclaration have no effect + * - ``2190``\ + - | ``gnu_attr_on_template_redecl_but_original_kept``\ : + | GNU attributes on a template redeclaration have no effect (the + attributes of the original declaration at line *xxxx*\ apply instead) + * - ``2191``\ + - | ``cli_param_array_must_be_last_parameter``\ : + | a C++/CLI parameter array must be the last parameter + * - ``2192``\ + - | ``default_arg_used_in_param_array_function``\ : + | a function with a C++/CLI parameter array cannot have default + arguments + * - ``2193``\ + - | ``ellipsis_after_param_array``\ : + | a C++/CLI parameter array cannot be followed by an ellipsis parameter + * - ``2194``\ + - | ``parameter_array_on_operator_function``\ : + | a C++/CLI parameter array is not allowed in an operator function + parameter list + * - ``2195``\ + - | ``microsoft_inline_not_allowed_here``\ : + | __inline and \__forceinline are not allowed here + * - ``2196``\ + - | ``data_member_with_interface_type``\ : + | a data member cannot have a C++/CLI interface class type + * - ``2197``\ + - | ``variable_with_interface_type``\ : + | a variable cannot have a C++/CLI interface class type + * - ``2198``\ + - | ``parameter_with_interface_type``\ : + | a parameter cannot have a C++/CLI interface class type + * - ``2199``\ + - | ``return_type_is_interface``\ : + | a function return type cannot be a C++/CLI interface class type + * - ``2200``\ + - | ``array_of_generic_param``\ : + | an array of generic parameter type is not allowed + * - ``2201``\ + - | ``ptr_handle_or_ref_to_generic_param``\ : + | a pointer, handle, or reference to a generic parameter type is not + allowed + * - ``2202``\ + - | ``ref_class_initonly_field``\ : + | an initonly field cannot have a ref class type + * - ``2203``\ + - | ``ref_bound_to_initonly_field``\ : + | a reference cannot be bound to an initonly field + * - ``2204``\ + - | ``address_of_initonly_field``\ : + | taking the address of an initonly field is not allowed + * - ``2205``\ + - | ``modification_of_initonly_field``\ : + | an initonly field can only be modified by the instance constructor of + its containing class + * - ``2206``\ + - | ``modification_of_static_initonly_field``\ : + | a static initonly field can only be modified by the static + constructor of its containing class + * - ``2207``\ + - | ``member_function_call_on_initonly_field``\ : + | member function will be invoked on a copy of the initonly field + * - ``2208``\ + - | ``expr_not_pointer_nor_handle``\ : + | expression must have pointer or handle type but it has type *"type"*\ + * - ``2209``\ + - | ``move_ctor_or_assign_copy_of_lvalue``\ : + | a move constructor or move assignment operator is used to copy an + lvalue here, which may destroy the source object + * - ``2210``\ + - | ``generic_selection_with_points_to``\ : + | member selection on a C++/CLI generic entity must use the "->" + syntax, not "." + * - ``2211``\ + - | ``invalid_specific_ref_class_base``\ : + | a ref class type cannot derive from *"type"*\ + * - ``2212``\ + - | ``generic_class_must_be_managed``\ : + | a generic class must be managed (i.e., a ref class, a value class, or + an interface class) + * - ``2213``\ + - | ``sealed_constraint``\ : + | a sealed class cannot be used as a constraint + * - ``2214``\ + - | ``dynamic_cast_to_value_generic``\ : + | the type in a dynamic_cast cannot be a generic type that might be a + value type + * - ``2215``\ + - | ``UCN_names_invalid_code_point``\ : + | a universal character name must designate a valid code point + * - ``2216``\ + - | ``override_with_constraint_mismatch``\ : + | generic constraints do not match those of *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``2217``\ + - | ``bad_argument_for_underlying_type``\ : + | __underlying_type only applies to enum types + * - ``2218``\ + - | ``too_many_cast_operands``\ : + | expected only one operand expression for this cast + * - ``2219``\ + - | ``bad_unicode_char_in_string``\ : + | Unicode character with hex value *xxxx*\ not representable in the + system default code page + * - ``2220``\ + - | ``conv_of_pm_to_func_ptr``\ : + | nonstandard conversion of bound pointer-to-member to a function + pointer + * - ``2221``\ + - | ``deprecated_access_specifier``\ : + | access specifier *xxxx*\ is deprecated -- use *xxxx*\ instead + * - ``2222``\ + - | ``static_accessor_in_nonstatic_property_or_event``\ : + | a static accessor function is not permitted in a nonstatic property + or event definition + * - ``2223``\ + - | ``both_ref_and_value_constraints``\ : + | *"type"*\ has both a value class and ref class constraint + * - ``2224``\ + - | ``circular_constraints``\ : + | *"type"*\ and *"type"*\ involve circular naked type constraints + * - ``2225``\ + - | ``invalid_type_constraint``\ : + | *"type"*\ is not a valid type constraint + * - ``2226``\ + - | ``pch_file_incomplete``\ : + | precompiled header file *"xxxx"*\ not used (because it is incomplete) + * - ``2227``\ + - | ``invalid_generic_arg``\ : + | *"type"*\ is not a valid generic argument + * - ``2228``\ + - | ``bad_assembly_info_attribute``\ : + | assembly_info attribute applied to an invalid type + * - ``2229``\ + - | ``ref_class_not_satisfied``\ : + | *"type"*\ does not satisfy the ref class constraint of generic + parameter *"type"*\ + * - ``2230``\ + - | ``value_class_not_satisfied``\ : + | *"type"*\ does not satisfy the value class constraint of generic + parameter *"type"*\ + * - ``2231``\ + - | ``gcnew_and_abstract``\ : + | *"type"*\ does not satisfy the gcnew constraint of generic parameter + *"type"*\ because it is abstract + * - ``2232``\ + - | ``gcnew_and_no_ctor``\ : + | *"type"*\ does not satisfy the gcnew constraint of generic parameter + *"type"*\ because it does not have a public default constructor + * - ``2233``\ + - | ``gcnew_and_no_gcnew``\ : + | generic parameter *"type"*\ does not satisfy the gcnew constraint of + generic parameter *"type"*\ because it does not have the gcnew + constraint + * - ``2234``\ + - | ``type_not_satisfied``\ : + | *"type"*\ does not satisfy the *"type"*\ type constraint of generic + parameter *"type"*\ + * - ``2235``\ + - | ``constraint_mismatch``\ : + | constraint on generic parameter *"type"*\ differs from previous + declaration (at line *xxxx*\ ) + * - ``2236``\ + - | ``standard_array_member_in_managed_class``\ : + | a member of a managed class cannot be a standard array + * - ``2237``\ + - | ``handle_member_in_standard_class``\ : + | a member of a non-managed class cannot be a handle + * - ``2238``\ + - | ``tracking_reference_member_in_standard_class``\ : + | a member of a non-managed class cannot be a tracking reference + * - ``2239``\ + - | ``reinterpret_cast_of_handle``\ : + | unsafe reinterpret_cast of handle + * - ``2240``\ + - | ``generic_type_in_template_arg``\ : + | a template argument may not reference a generic type parameter + * - ``2241``\ + - | ``comma_operator_in_cli_subscript``\ : + | an expression list is not allowed in this subscript operation (use + parentheses around a top-level comma operator) + * - ``2242``\ + - | ``expr_not_pointer_or_array_handle``\ : + | expression must have pointer-to-object or handle-to-C++/CLI-array + type but it has type *"type"*\ + * - ``2243``\ + - | ``unrecognized_ms_attr``\ : + | unrecognized attribute + * - ``2244``\ + - | ``standard_class_member_in_managed_class``\ : + | a member of a managed class cannot be of a non-managed class type + * - ``2245``\ + - | ``ref_or_interface_class_member_in_standard_class``\ : + | a member of a non-managed class cannot have a ref class type or + interface class type + * - ``2247``\ + - | ``template_delegate``\ : + | a delegate may not be declared as a template + * - ``2248``\ + - | ``invalid_generic_specialization``\ : + | a generic cannot be explicitly specialized + * - ``2249``\ + - | ``generic_in_template``\ : + | a generic cannot be declared in a class template + * - ``2250``\ + - | ``template_in_generic``\ : + | a template cannot be declared in a generic class + * - ``2251``\ + - | ``static_literal_field``\ : + | a literal field cannot be declared "static" + * - ``2252``\ + - | ``nonstandard_long_float``\ : + | "long float" is a nonstandard extension -- use "double" instead + * - ``2253``\ + - | ``standard_class_nested_in_managed_class``\ : + | a standard class cannot be nested in a managed class + * - ``2254``\ + - | ``clrcall_requires_cppcli``\ : + | __clrcall is valid only in C++/CLI mode + * - ``2255``\ + - | ``vararg_clrcall``\ : + | __clrcall not allowed on function with ellipsis parameter + * - ``2256``\ + - | ``bad_use_of_function_modifier``\ : + | *"xxxx"*\ is not allowed here + * - ``2257``\ + - | ``override_with_trivial_property_or_event``\ : + | a trivial property or event cannot be used to override *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``2258``\ + - | ``exp_id_in_for_each_decl``\ : + | expected an iterator variable name + * - ``2259``\ + - | ``missing_notequal_on_for_each_type``\ : + | the iterator type in this "for each" statement is *"type"*\ , which + is not a pointer type or an iterator-like class type + * - ``2260``\ + - | ``missing_incr_on_for_each_type``\ : + | the iterator type in this "for each" statement is *"type"*\ , which + is not a pointer type or an iterator-like class type + * - ``2261``\ + - | ``missing_indirect_on_for_each_type``\ : + | the iterator type in this "for each" statement is *"type"*\ , which + is not a pointer type or an iterator-like class type + * - ``2262``\ + - | ``no_packing_of_non_POD_field``\ : + | packing attribute on the parent type is ignored for this field of + class type *"type"*\ that is not standard-layout + * - ``2263``\ + - | ``nonpublic_implicit_interface_match``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) not implemented + because this declaration is not public and has no named override + specifier + * - ``2264``\ + - | ``missing_gnu_inline_attr_on_redeclaration``\ : + | this declaration is missing the gnu_inline attribute specified in the + previous declaration at line *xxxx*\ + * - ``2265``\ + - | ``managed_member_function_cannot_have_ellipsis_parameter``\ : + | a member function of a managed class cannot have an ellipsis parameter + * - ``2266``\ + - | ``invalid_prev_decl_iterator``\ : + | previously-declared *entity-kind "entity"*\ invalid as iterator of + "for each" statement + * - ``2267``\ + - | ``generic_parameter_requires_clrcall``\ : + | calling convention ignored because the function type involves a + generic parameter; \__clrcall used instead + * - ``2268``\ + - | ``generic_parameter_does_not_permit_varargs``\ : + | a function type involving a generic parameter cannot have an ellipsis + parameter + * - ``2269``\ + - | ``virtual_required_for_base_override``\ : + | "virtual" is required to override the matching *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``2270``\ + - | ``virtual_required_for_interface_implementation``\ : + | "virtual" is required to implement the matching *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``2271``\ + - | ``initonly_volatile_not_allowed``\ : + | an initonly data member cannot be volatile + * - ``2272``\ + - | ``member_name_reserved_by_cli_operator``\ : + | a member *"xxxx"*\ of this type is reserved within a managed class + -- C++/CLI operators must be declared using the keyword "operator" + * - ``2273``\ + - | ``tracking_ref_to_constant``\ : + | a tracking reference to non-const cannot be bound to a constant + * - ``2274``\ + - | ``attributes_with_no_decl``\ : + | attributes ignored here because they do not apply to a declared entity + * - ``2275``\ + - | ``tracking_reference_to_system_string``\ : + | a tracking reference to System::String is not allowed + * - ``2276``\ + - | ``use_of_generic_class_with_pending_constraint``\ : + | invalid use of a generic class *"type"*\ with pending constraints + (probably caused by an invalid metadata file) + * - ``2277``\ + - | ``invalid_entity_for_pending_constraint``\ : + | a pending constraint clause is only allowed for generic class + declarations (but not generic class definitions) + * - ``2278``\ + - | ``invalid_empty_initializer_list``\ : + | empty initializer list not allowed here + * - ``2279``\ + - | ``template_in_managed_class``\ : + | a template cannot be declared in a managed class + * - ``2280``\ + - | ``bad_generic_declaration_scope``\ : + | a generic declaration is not allowed here + * - ``2281``\ + - | ``interface_cannot_have_member_generics``\ : + | interface types cannot have member generics + * - ``2282``\ + - | ``character_not_latin_1``\ : + | Unicode character not Latin-1, truncated to low-order byte + * - ``2283``\ + - | ``range_based_for_missing_function``\ : + | to be used with range-based "for" statements, type *"type"*\ must + provide function *"xxxx"*\ + * - ``2284``\ + - | ``missing_notequal_on_range_based_for_type``\ : + | the iterator type in this range-based "for" statement is *"type"*\ , + which is not a pointer type or an iterator-like class type + * - ``2285``\ + - | ``missing_incr_on_range_based_for_type``\ : + | the iterator type in this range-based "for" statement is *"type"*\ , + which is not a pointer type or an iterator-like class type + * - ``2286``\ + - | ``missing_indirect_on_range_based_for_type``\ : + | the iterator type in this range-based "for" statement is *"type"*\ , + which is not a pointer type or an iterator-like class type + * - ``2287``\ + - | ``range_based_for_incomplete_array_type``\ : + | a range-based "for" statement cannot operate on an array of unknown + size or incomplete type *"type"*\ + * - ``2288``\ + - | ``begin_end_type_mismatch_in_range_based_for``\ : + | return types for "begin" and "end" functions used in a range-based + "for" statement must be the same ("begin" return type is *"type"*\ , + "end" return type is *"type"*\ ) + * - ``2289``\ + - | ``inaccessible_elided_dtor``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ), required to + destroy temporary that was eliminated, is inaccessible + * - ``2290``\ + - | ``range_based_for_no_matching_overload``\ : + | in this range-based "for" statement, no instance of *"entity"*\ + matches the argument list + * - ``2291``\ + - | ``range_based_for_undefined_identifier``\ : + | this range-based "for" statement requires a suitable *"xxxx"*\ + function and none was found + * - ``2292``\ + - | ``for_each_undefined_identifier``\ : + | this "for each" statement requires a suitable *"xxxx"*\ function and + none was found + * - ``2293``\ + - | ``class_metadata_not_representable``\ : + | *"type"*\ has a metadata representation not representable using + C++/CLI + * - ``2294``\ + - | ``exp_ellipsis``\ : + | expected "..." + * - ``2295``\ + - | ``implements_requires_interface``\ : + | *"type"*\ in \__implements list is not an interface + * - ``2296``\ + - | ``implements_must_precede_virtual_functions``\ : + | an \__implements list must precede virtual function declarations + * - ``2297``\ + - | ``missing_implements_list``\ : + | *"type"*\ specified "\__implements ..." in its list of bases, but is + missing a matching \__implements list + * - ``2298``\ + - | ``unused_dereference_of_ref_class``\ : + | the result of dereferencing a handle to a ref or interface class type + must be used + * - ``2300``\ + - | ``exp_rparen_and_pragma_ignored``\ : + | expected a ")"; pragma ignored + * - ``2301``\ + - | ``using_or_access_declaration_in_managed_class``\ : + | a using-declaration or access declaration cannot appear in a managed + class + * - ``2302``\ + - | ``skipped_inaccessible_function``\ : + | Note: *entity-kind "entity"*\ (declared at line *xxxx*\ ) could have + been called but was not considered because it is inaccessible + * - ``2303``\ + - | ``cli_abstract_member_function_definition``\ : + | an abstract member function of a C++/CLI managed class cannot have a + definition + * - ``2304``\ + - | ``nonstatic_addressof_operator_in_managed_class``\ : + | declaring this unary "operator\*" can change the meaning of + dereferencing a handle (use static member operators to explicitly + indicate applicable types) + * - ``2319``\ + - | ``interface_nonstatic_data_member``\ : + | an interface class cannot contain a nonstatic data member + * - ``2320``\ + - | ``pragma_gcc_system_header_in_primary_file``\ : + | #pragma GCC system_header cannot be used in the primary source file + * - ``2321``\ + - | ``too_large_to_inline``\ : + | *entity-kind "entity"*\ is too large to be inlined + * - ``2323``\ + - | ``cl_gen_move_operations_option_only_in_cplusplus``\ : + | option to control move operations can be used only when compiling C++ + * - ``2324``\ + - | ``cl_gen_move_operations_and_rvalue_ctor_is_copy_ctor``\ : + | move operations cannot be generated when rvalue constructors are copy + constructors + * - ``2325``\ + - | ``cl_move_operations_require_rvalue_references``\ : + | option to control move operations cannot be used when rvalue + references are disabled + * - ``2326``\ + - | ``final_managed_class``\ : + | "final" cannot be used for managed classes (use "sealed" instead) + * - ``2327``\ + - | ``cast_to_cli_interface_class``\ : + | a cast to CLI interface class *"type"*\ is not allowed -- cast to + handle intended? + * - ``2328``\ + - | ``new_of_cli_interface_class``\ : + | cannot create an object of a CLI interface class + * - ``2329``\ + - | ``enum_type_replacement``\ : + | this declaration hides the nonstandard declaration of *entity-kind + "entity"*\ (declared at line *xxxx*\ ) because the underlying types + are incompatible + * - ``2330``\ + - | ``known_comparison_with_null``\ : + | pointer comparison result is constant, because operand can never be + null + * - ``2331``\ + - | ``value_init_of_incomplete``\ : + | an object of the incomplete type *"type"*\ cannot be + value-initialized + * - ``2332``\ + - | ``value_init_of_reference``\ : + | a reference cannot be value-initialized + * - ``2333``\ + - | ``exp_lparen_or_brace``\ : + | expected a "(" or a "{" + * - ``2334``\ + - | ``explicit_ctor_in_copy_list_init``\ : + | copy-list-initialization cannot use a constructor marked "explicit" + * - ``2335``\ + - | ``ptr_to_member_of_type_void``\ : + | pointer to member of type void is not allowed + * - ``2336``\ + - | ``ptr_to_member_of_reference_type``\ : + | pointer to member of reference type is not allowed + * - ``2337``\ + - | ``ptr_to_member_of_handle_type``\ : + | pointer to member of handle type is not allowed + * - ``2338``\ + - | ``braced_init_list_not_allowed``\ : + | a brace-enclosed list is not allowed here + * - ``2339``\ + - | ``arrow_star_operator_in_managed_class``\ : + | an operator->\* member is not allowed in a managed class + * - ``2340``\ + - | ``bad_assembly_index``\ : + | assembly metadata refers to non-existent assembly + * - ``2341``\ + - | ``attribute_conflict``\ : + | attribute *"xxxx"*\ conflicts with earlier attribute *"xxxx"*\ + * - ``2342``\ + - | ``incompatible_enum_base_types``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared with a different base type + * - ``2343``\ + - | ``invalid_scoped_enum_elaboration``\ : + | "enum class" and "enum struct" cannot be used here (use plain "enum" + instead) + * - ``2344``\ + - | ``extra_braces_on_simple_init``\ : + | only one level of braces is allowed on an initializer for an object + of type *"type"*\ + * - ``2345``\ + - | ``not_an_enum_type_name``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot be used + as an enum type name + * - ``2347``\ + - | ``auto_new_with_braced_init``\ : + | a braced-initializer cannot be used with "new auto" + * - ``2348``\ + - | ``missing_initializer_list_ctor``\ : + | the definition of std::initializer_list does not contain the expected + constructor + * - ``2349``\ + - | ``variable_hides_entity``\ : + | declaration hides *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``2350``\ + - | ``invalid_std_initializer_list_parameter_list``\ : + | invalid template parameter list for std::initializer_list (it should + be one ordinary type parameter with no default) + * - ``2351``\ + - | ``braced_list_passed_to_ellipsis``\ : + | a brace-enclosed list cannot be passed for an ellipsis parameter + * - ``2352``\ + - | ``initializer_list_not_included``\ : + | an #include is needed prior to a use of + std::initializer_list, including an implicit use + * - ``2353``\ + - | ``inline_on_alias``\ : + | the "inline" keyword cannot be used on a namespace alias declaration + * - ``2354``\ + - | ``prev_ns_not_inline``\ : + | the previous declaration of *entity-kind "entity"*\ was not declared + inline + * - ``2355``\ + - | ``prev_ns_inline``\ : + | *entity-kind "entity"*\ was previously declared inline + * - ``2356``\ + - | ``first_arg_must_be_integer_constant``\ : + | the first argument must be an integer constant + * - ``2357``\ + - | ``designator_requires_aggregate_type``\ : + | a designator cannot be used with a non-aggregate type *"type"*\ + * - ``2358``\ + - | ``indirect_anon_union_designator``\ : + | a designator for an anonymous union member can only appear within + braces corresponding to that anonymous union + * - ``2359``\ + - | ``cl_func_prototype_tags_option_only_in_C``\ : + | function prototype tags can only be enabled when compiling C + * - ``2360``\ + - | ``cannot_elide_braces``\ : + | braces cannot be omitted for this subobject initializer + * - ``2361``\ + - | ``narrowing_conversion``\ : + | invalid narrowing conversion from *"type"*\ to *"type"*\ + * - ``2362``\ + - | ``constant_narrowing_conversion``\ : + | invalid narrowing conversion from *"type"*\ to *"type"*\ : constant + value does not fit in destination type + * - ``2363``\ + - | ``cast_to_incomplete_array_type``\ : + | cast to incomplete array type *"type"*\ is not allowed + * - ``2364``\ + - | ``constant_narrowing_conversion_to_float``\ : + | invalid narrowing conversion from *"type"*\ to *"type"*\ : constant + value cannot be represented exactly in destination type + * - ``2365``\ + - | ``braced_init_in_paren_init``\ : + | a parenthesized initializer for a non-class entity must be an + expression, not a brace-enclosed list + * - ``2366``\ + - | ``braced_list_for_implicit_lambda_type``\ : + | a brace-enclosed list does not provide a return type for this lambda + * - ``2367``\ + - | ``invalid_explicit_exception_specification``\ : + | the declared exception specification is incompatible with the + generated one + * - ``2368``\ + - | ``scoped_enum_nonstandard_in_current_mode``\ : + | scoped enum types are a C++11 feature + * - ``2369``\ + - | ``value_init_of_function``\ : + | a function type cannot be value-initialized + * - ``2370``\ + - | ``list_init_of_incomplete``\ : + | list-initialization of an object type *"type"*\ is not allowed + because the type is incomplete + * - ``2371``\ + - | ``std_initializer_list_has_dtor``\ : + | std::initializer_list has a destructor, and is not supposed to -- + library is misconfigured + * - ``2372``\ + - | ``explicit_enum_base_nonstandard_in_current_mode``\ : + | explicit enum base types are a C++11 feature + * - ``2373``\ + - | ``unconvertible_con_expr``\ : + | this constant expression has type *"type"*\ instead of the required + *"type"*\ type + * - ``2374``\ + - | ``new_of_initializer_list``\ : + | a "new" of an std::initializer_list object is unlikely to work as + expected because the underlying array will be destroyed at the end of + the full expression + * - ``2377``\ + - | ``defined_always_false``\ : + | "defined" is always false in a macro expansion in Microsoft mode + * - ``2378``\ + - | ``init_list_element_type_not_complete_object``\ : + | *"type"*\ cannot be the element type of an initializer list because + it is not a complete object type + * - ``2379``\ + - | ``invalid_default_arg``\ : + | mismatched delimiters in default argument expression + * - ``2380``\ + - | ``conv_of_unbound_pm_to_func_ptr``\ : + | nonstandard conversion of pointer-to-member to a function pointer + * - ``2381``\ + - | ``dynamic_exception_specifications_deprecated``\ : + | dynamic exception specifications are deprecated + * - ``2382``\ + - | ``bad_scope_for_partial_spec``\ : + | *entity-kind "entity"*\ cannot be partially specialized in the + current scope + * - ``2383``\ + - | ``previous_constexpr_decl_conflict``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared constexpr + * - ``2384``\ + - | ``previous_nonconstexpr_decl_conflict``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + not declared constexpr + * - ``2385``\ + - | ``constexpr_variable_decl_must_be_definition``\ : + | missing initializer for constexpr variable + * - ``2386``\ + - | ``invalid_constexpr``\ : + | "constexpr" is not valid here + * - ``2387``\ + - | ``invalid_constexpr_body``\ : + | a constexpr function must contain exactly one return statement + * - ``2388``\ + - | ``invalid_statement_in_constexpr_function``\ : + | statement may not appear in a constexpr function + * - ``2389``\ + - | ``invalid_statement_in_constexpr_constructor``\ : + | statement may not appear in a constexpr constructor + * - ``2390``\ + - | ``constexpr_virtual_combination``\ : + | a function cannot be both constexpr and virtual in this mode + * - ``2391``\ + - | ``nonliteral_return_type_in_constexpr_function``\ : + | a constexpr function cannot have a nonliteral return type *"type"*\ + * - ``2392``\ + - | ``nonliteral_param_type_in_constexpr_function``\ : + | a constexpr function cannot have a parameter of nonliteral type + *"type"*\ + * - ``2393``\ + - | ``unsequenced_use_of_variable``\ : + | unsequenced uses of *entity-kind "entity"*\ in expression may + produce undefined results + * - ``2394``\ + - | ``3rd_arg_of_assume_aligned_must_be_integral``\ : + | the optional third argument of a call to \__builtin_assumed_aligned + must have integral type + * - ``2395``\ + - | ``constexpr_destructor``\ : + | a destructor cannot be constexpr + * - ``2396``\ + - | ``invalid_mmap_address``\ : + | address supplied for mmap must be aligned on a page boundary: *xxxx*\ + * - ``2397``\ + - | ``constexpr_constructor_with_function_try_block``\ : + | the body of a constexpr constructor cannot be a function try block + * - ``2398``\ + - | ``missing_initializer_on_fields_with_constexpr_ctor``\ : + | constexpr *entity-kind "entity"*\ provides no initializer for: + * - ``2400``\ + - | ``default_ctor_call_not_constant``\ : + | calling the default constructor for *"type"*\ does not produce a + constant value + * - ``2401``\ + - | ``default_ctor_not_constexpr``\ : + | the default constructor for *"type"*\ is not constexpr + * - ``2402``\ + - | ``constexpr_variable_must_have_literal_type``\ : + | a constexpr variable must have a literal type or a reference type + * - ``2403``\ + - | ``constexpr_ctor_with_virtual_base``\ : + | a constructor for a class with virtual bases cannot be constexpr + * - ``2404``\ + - | ``bad_cpp11_constant_function_call``\ : + | function call must have a constant value in a constant expression + * - ``2405``\ + - | ``constexpr_main``\ : + | function "main" may not be declared constexpr + * - ``2407``\ + - | ``tag_defined_in_constexpr_body``\ : + | a class or enum type definition cannot appear in a constexpr function + or constructor body + * - ``2408``\ + - | ``only_gnu_attributes_here``\ : + | only GNU-style attributes are permitted here + * - ``2409``\ + - | ``auto_used_two_ways``\ : + | nonstandard use of "auto" to both deduce the type from an initializer + and to announce a trailing return type + * - ``2410``\ + - | ``nonstd_qualified_void_param_list``\ : + | declaring a void parameter list with a qualified void type is + nonstandard + * - ``2411``\ + - | ``qualifier_ignored_on_local_declaration``\ : + | the qualifier on this local declaration is ignored + * - ``2412``\ + - | ``bad_conv_constant_expr_type``\ : + | this constant expression has type *"type"*\ instead of the required + *xxxx*\ type + * - ``2413``\ + - | ``bad_argument_for_bases``\ : + | an instantiation of \__bases or \__direct_bases requires a class type + * - ``2414``\ + - | ``bad_prototype_argument_for_bases``\ : + | the argument of \__bases and \__direct_bases must be a type template + parameter + * - ``2415``\ + - | ``bases_not_in_template``\ : + | *xxxx*\ can only be used in template contexts + * - ``2416``\ + - | ``constexpr_return_not_constant``\ : + | constexpr function return is non-constant + * - ``2417``\ + - | ``nonconstexpr_call_in_mem_initializer``\ : + | constexpr constructor calls non-constexpr *entity-kind "entity"*\ + * - ``2418``\ + - | ``nonconstant_field_initializer_in_mem_initializer``\ : + | constructor cannot be constexpr because the initializer of + *entity-kind "entity"*\ is not a constant expression + * - ``2419``\ + - | ``nonconstant_mem_init_for_constexpr_ctor``\ : + | non-constant initializer for constexpr constructor + * - ``2420``\ + - | ``generated_default_constructor_used_in_field_initializer``\ : + | the generated default constructor for *"type"*\ cannot be used in an + initializer for its own data member + * - ``2421``\ + - | ``recursive_initializer_instantiation``\ : + | instantiation of initializer of *entity-kind "entity"*\ depends on + its own value + * - ``2422``\ + - | ``defaulted_default_ctor_cannot_be_constexpr``\ : + | defaulted default constructor cannot be constexpr because the + corresponding implicitly declared default constructor would not be + constexpr + * - ``2424``\ + - | ``bad_binary_digit``\ : + | invalid binary number + * - ``2425``\ + - | ``multiple_union_field_initializers``\ : + | a union can have at most one field initializer -- *entity-kind + "entity"*\ (declared at line *xxxx*\ ) also has an initializer + * - ``2427``\ + - | ``union_constexpr_constructor_initializes_no_field``\ : + | constexpr constructor of a union must initialize one of its fields + * - ``2428``\ + - | ``constexpr_constructor_initializes_no_variant_field``\ : + | constexpr constructor fails to initialize an anonymous union (defined + at line *xxxx*\ ) + * - ``2429``\ + - | ``constexpr_static_data_member_without_initializer``\ : + | a constexpr static data member declaration requires an in-class + initializer + * - ``2430``\ + - | ``cl_max_constexpr_option_only_in_cplusplus``\ : + | maximum constexpr depth/count options can be used only when compiling + C++ + * - ``2431``\ + - | ``excessive_constexpr_complexity``\ : + | expression not folded to a constant due to excessive constexpr + function call complexity + * - ``2432``\ + - | ``cl_unrestricted_unions_option_only_in_cplusplus``\ : + | unrestricted union options can be used only when compiling C++ + * - ``2433``\ + - | ``constexpr_ctor_does_not_initialize_base``\ : + | constexpr constructor must initialize direct base class *"type"*\ + * - ``2434``\ + - | ``field_initializer_list``\ : + | creation of an std::initializer_list object in a field initializer is + unlikely to work as expected because the underlying array will be + destroyed at the end of the full expression + * - ``2435``\ + - | ``this_not_constant``\ : + | "this" cannot be used in a constant expression + * - ``2437``\ + - | ``constexpr_explicit_instantiation``\ : + | "constexpr" is not allowed on an explicit instantiation directive + * - ``2438``\ + - | ``generated_default_ctor_exception_spec_circularity``\ : + | cannot determine the exception specification of the default + constructor due to a circular dependency + * - ``2439``\ + - | ``anon_union_at_decl_position``\ : + | anonymous union defined at line *xxxx*\ + * - ``2440``\ + - | ``unbounded_constexpr_ctor_init_recursion``\ : + | this constructor uses the initializer of *entity-kind "entity"*\ + (declared at line *xxxx*\ ), which would result in unbounded recursion + * - ``2442``\ + - | ``block_extern_initializer_not_allowed``\ : + | an initializer is not allowed on a local declaration of an extern + variable + * - ``2443``\ + - | ``local_named_register_initializer_not_allowed``\ : + | an initializer is not allowed on a local declaration of a named + register variable + * - ``2445``\ + - | ``cl_unrestricted_unions_in_microsoft_mode``\ : + | unrestricted unions cannot be enabled in Microsoft mode + * - ``2446``\ + - | ``delegation_loop``\ : + | constructor delegates directly or indirectly to itself + * - ``2447``\ + - | ``delegation_init_and_mem_init``\ : + | a delegating constructor cannot have other mem-initializers + * - ``2448``\ + - | ``ref_qualifier_not_allowed``\ : + | a ref-qualifier is not allowed here + * - ``2449``\ + - | ``same_param_types_with_and_without_ref_qualifiers``\ : + | overloading two member functions with the same parameter types + requires that they both have ref-qualifiers or both lack + ref-qualifiers + * - ``2450``\ + - | ``bad_raw_string_delim_char``\ : + | invalid character in raw string delimiter + * - ``2451``\ + - | ``missing_raw_string_delim_lparen``\ : + | parenthesis terminating raw string delimiter not found within 16 + characters -- raw string indicator ignored + * - ``2452``\ + - | ``missing_raw_string_delimiter``\ : + | ending delimiter for raw string not found + * - ``2453``\ + - | ``pack_not_last_arg``\ : + | a parameter pack must be the final template argument in a partial + specialization + * - ``2454``\ + - | ``pm_call_obj_not_lvalue``\ : + | a pointer-to-member function with type *"type"*\ can only be used + with an lvalue object + * - ``2455``\ + - | ``pm_call_obj_not_rvalue``\ : + | a pointer-to-member function with type *"type"*\ can only be used + with an rvalue object + * - ``2456``\ + - | ``defaulted_copy_ctor_cannot_have_const_parameter``\ : + | the parameter of this defaulted copy-constructor cannot be const + because a base or member copy constructor parameter is non-const + * - ``2457``\ + - | ``defaulted_assignment_cannot_have_const_parameter``\ : + | the parameter of this defaulted assignment operator cannot be const + because a base or member copy assignment parameter is non-const + * - ``2458``\ + - | ``empty_anonymous_union``\ : + | an anonymous union must contain at least one nonstatic data member + * - ``2459``\ + - | ``delegating_constructor_requires_newer_abi_version``\ : + | option "delegating_constructors" requires a different compiler + configuration + * - ``2460``\ + - | ``alignment_reduction_unconditionally_ignored``\ : + | a reduction in alignment is ignored + * - ``2461``\ + - | ``bad_rvalue_ref_const_cast_operand``\ : + | the operand of a const_cast to an rvalue reference type cannot be a + non-class prvalue + * - ``2462``\ + - | ``expr_not_a_glvalue``\ : + | expression must be an lvalue or xvalue + * - ``2463``\ + - | ``lossy_conversion``\ : + | conversion may change the value + * - ``2464``\ + - | ``deprecated_string_conv``\ : + | conversion from a string literal to "char \*" is deprecated + * - ``2465``\ + - | ``deprecated_string_conv_gen``\ : + | conversion from a string literal to pointer-to-character (non-const) + is deprecated + * - ``2466``\ + - | ``override_and_final_is_cpp11``\ : + | "override" and "final" are C++11 features + * - ``2467``\ + - | ``rvalue_reference_in_exception_specification``\ : + | rvalue references are not allowed as exception specification types + * - ``2468``\ + - | ``attr_disallows_handler_param``\ : + | attribute *"xxxx"*\ does not apply to handler parameters + * - ``2469``\ + - | ``attr_requires_handler_param``\ : + | attribute *"xxxx"*\ requires a handler parameter + * - ``2470``\ + - | ``wrong_entity_for_alignas``\ : + | alignas does not apply here + * - ``2471``\ + - | ``std_alignof_with_expr_arg``\ : + | the standard "alignof" operator does not accept an expression + argument (use a type instead) + * - ``2472``\ + - | ``bad_qualifier_for_member_enum_decl``\ : + | invalid qualifier for *"type"*\ (a derived class is not allowed here) + * - ``2473``\ + - | ``always_inline_requires_inline``\ : + | the "always_inline" attribute is ignored on non-inline functions + * - ``2474``\ + - | ``inheriting_ctor_not_from_direct_base``\ : + | inheriting constructors must be inherited from a direct base class + * - ``2476``\ + - | ``exp_asm_label``\ : + | expected a label + * - ``2477``\ + - | ``missing_label_operand_number``\ : + | expected an operand number after "%" + * - ``2478``\ + - | ``label_operand_number_out_of_range``\ : + | operand number for "%" does not refer to a valid label argument + * - ``2479``\ + - | ``wide_string_invalid_in_asm``\ : + | a wide string is invalid in an "asm" statement + * - ``2480``\ + - | ``attribute_is_nonstandard``\ : + | attribute is nonstandard + * - ``2481``\ + - | ``decltype_is_not_base_class``\ : + | not a base class of class *"type"*\ + * - ``2482``\ + - | ``bad_user_defined_suffix``\ : + | non-identifier character in user-defined literal suffix + * - ``2483``\ + - | ``multichar_ud_lit``\ : + | a multicharacter literal cannot be part of a user-defined literal + * - ``2484``\ + - | ``ud_string_suffix_mismatch``\ : + | user-defined literal suffix does not match the earlier *"xxxx"*\ + * - ``2485``\ + - | ``invalid_literal_operator_id``\ : + | invalid literal operator name + * - ``2486``\ + - | ``literal_operator_not_found``\ : + | user-defined literal operator not found + * - ``2487``\ + - | ``ambig_literal_operator``\ : + | ambiguous literal operators and/or literal operator template: + * - ``2488``\ + - | ``udl_cannot_be_class_member``\ : + | a literal operator cannot be a member of a class + * - ``2489``\ + - | ``extern_c_literal_operator``\ : + | a literal operator cannot have extern "C" name linkage + * - ``2490``\ + - | ``no_parameter_for_literal_operator``\ : + | at least one parameter expected for a literal operator + * - ``2491``\ + - | ``too_many_parameters_for_literal_operator``\ : + | too many parameters for this literal operator + * - ``2492``\ + - | ``invalid_parameter_type_for_literal_operator``\ : + | invalid parameter type *"type"*\ for literal operator + * - ``2493``\ + - | ``invalid_integer_parameter_for_literal_operator``\ : + | invalid integer parameter type (*"type"*\ ) for literal operator; + expected a character type or unsigned long long + * - ``2494``\ + - | ``invalid_float_parameter_for_literal_operator``\ : + | invalid floating-point parameter type (*"type"*\ ) for literal + operator; expected long double + * - ``2495``\ + - | ``pointer_to_nonconst_for_literal_operator``\ : + | invalid first parameter type (*"type"*\ ) for literal operator; + pointer to non-const type is not allowed + * - ``2496``\ + - | ``invalid_second_parameter_type_for_literal_operator``\ : + | invalid second parameter type (*"type"*\ ) for literal operator; must + be size_t + * - ``2497``\ + - | ``invalid_pointer_parameter_for_literal_operator``\ : + | invalid pointer parameter type (*"type"*\ ) for literal operator; + expected a pointer to a character type + * - ``2498``\ + - | ``ellipsis_parameter_for_literal_operator``\ : + | a literal operator cannot have an ellipsis parameter + * - ``2499``\ + - | ``invalid_parameter_for_literal_operator_template``\ : + | a literal operator template cannot have any parameters + * - ``2500``\ + - | ``invalid_template_parameter_for_literal_operator_template``\ : + | a literal operator template must have a template parameter list + equivalent to "" + * - ``2501``\ + - | ``thread_local_not_allowed``\ : + | thread-local storage class is not valid here + * - ``2502``\ + - | ``thread_local_follows_non_thread_local``\ : + | thread-local declaration follows non-thread-local declaration + (declared at line *xxxx*\ ) + * - ``2503``\ + - | ``non_thread_local_follows_thread_local``\ : + | non-thread-local declaration follows thread-local declaration + (declared at line *xxxx*\ ) + * - ``2504``\ + - | ``default_arg_for_literal_operator``\ : + | a literal operator cannot have default arguments + * - ``2505``\ + - | ``attribute_ignored_for_thread_local``\ : + | attribute is ignored for thread-local variables + * - ``2506``\ + - | ``lit_suffix_no_underscore``\ : + | a user-provided literal suffix must begin with "_" + * - ``2507``\ + - | ``rvalue_references_is_cpp11``\ : + | rvalue references are a C++11 feature + * - ``2508``\ + - | ``lambdas_is_cpp11``\ : + | lambda expressions are a C++11 feature + * - ``2509``\ + - | ``std_attributes_is_cpp11``\ : + | standard attribute syntax is a C++11 feature + * - ``2510``\ + - | ``delegating_constructor_is_cpp11``\ : + | delegating constructors are a C++11 feature + * - ``2511``\ + - | ``inheriting_constructor_is_cpp11``\ : + | inheriting constructors are a C++11 feature + * - ``2512``\ + - | ``field_initializers_is_cpp11``\ : + | field initializers are a C++11 feature + * - ``2513``\ + - | ``deleted_functions_is_cpp11``\ : + | deleted functions are a C++11 feature + * - ``2514``\ + - | ``defaulted_functions_is_cpp11``\ : + | defaulted functions are a C++11 feature + * - ``2515``\ + - | ``storage_class_not_allowed_in_specialization``\ : + | a storage class is not allowed in an explicit specialization + * - ``2517``\ + - | ``specialization_of_unscoped_enum``\ : + | an unscoped enumeration must be opaque in order to be specialized + * - ``2518``\ + - | ``nonmember_enum_template``\ : + | an enumeration template declaration must refer to a previously + declared member of a class template + * - ``2519``\ + - | ``operand_must_be_vector``\ : + | expected a vector operand + * - ``2520``\ + - | ``incompatible_shuffle_source_operands``\ : + | shuffle source operands have incompatible types *"type"*\ and + *"type"*\ + * - ``2521``\ + - | ``nonintegral_shuffle_mask``\ : + | shuffle mask (type *"type"*\ ) is not a vector of integers + * - ``2522``\ + - | ``incompatible_shuffle_mask``\ : + | shuffle mask (type *"type"*\ ) has a length different from the source + operand (type *"type"*\ ) + * - ``2523``\ + - | ``bad_size_for_static_address_init``\ : + | static initialization with an address value requires a destination of + the same size as the address + * - ``2524``\ + - | ``feature_test_macro_req_id``\ : + | the argument to a feature-test macro must be a simple identifier + * - ``2525``\ + - | ``has_include_next_in_primary_source_file``\ : + | __has_include_next cannot be used in the primary source file + * - ``2526``\ + - | ``absolute_file_name_in_has_include_next``\ : + | absolute file name used in \__has_include_next + * - ``2527``\ + - | ``attr_not_applied_to_function_type``\ : + | attribute *"xxxx"*\ must be applied to a function type + * - ``2529``\ + - | ``bad_c11_noreturn``\ : + | _Noreturn is not allowed here + * - ``2530``\ + - | ``operand_must_be_real_floating_value``\ : + | expected an operand of real floating-point type (not *"type"*\ ) + * - ``2531``\ + - | ``incompatible_builtin_complex_types``\ : + | __builtin_complex requires operands of compatible types (unlike + *"type"*\ and *"type"*\ ) + * - ``2532``\ + - | ``default_association_appears_more_than_once``\ : + | a default association already appeared in this _Generic selection + * - ``2533``\ + - | ``variably_modified_type_not_allowed_here``\ : + | a type involving a variable length array is not allowed here + * - ``2534``\ + - | ``duplicate_type_in_c11_generic``\ : + | duplicate association type (*"type"*\ ) in _Generic selection + * - ``2535``\ + - | ``no_match_in_c11_generic``\ : + | no association matches the selector type *"type"*\ + * - ``2536``\ + - | ``incompatible_ifunc_resolver_type``\ : + | the type of *entity-kind "entity"*\ (*"type"*\ ) is incompatible + with an ifunc resolver type + * - ``2537``\ + - | ``ifunc_cant_be_alias``\ : + | a function cannot have both ifunc and alias attributes + * - ``2538``\ + - | ``ifunc_cant_be_weak``\ : + | a function cannot have both ifunc and weak attributes + * - ``2539``\ + - | ``call_requires_string_literal``\ : + | call requires a string literal operand + * - ``2540``\ + - | ``duplicate_inheriting_constructor``\ : + | duplicate inheriting constructor declaration (previous at line + *xxxx*\ ) + * - ``2541``\ + - | ``modified_decltype_auto_type``\ : + | "decltype(auto)" must be a placeholder for the complete type of the + variable (not for a component of that type) + * - ``2542``\ + - | ``decltype_auto_not_allowed_here``\ : + | decltype(auto) is not allowed here + * - ``2543``\ + - | ``decltype_auto_type_requires_initializer``\ : + | cannot deduce "decltype(auto)" (initializer required) + * - ``2544``\ + - | ``cannot_deduce_decltype_auto_type``\ : + | cannot deduce "decltype(auto)" type + * - ``2545``\ + - | ``thread_local_must_include_static_or_extern``\ : + | a block-scope thread-local declaration must include static or extern + * - ``2546``\ + - | ``deduced_return_type_conflict``\ : + | deduced return type *"type"*\ conflicts with previously deduced type + *"type"*\ + * - ``2547``\ + - | ``use_of_undefined_function_with_deduced_return_type``\ : + | cannot deduce the return type of *entity-kind "entity"*\ (declared + at line *xxxx*\ ); it has not been defined + * - ``2548``\ + - | ``virtual_function_cannot_have_deduced_return_type``\ : + | a virtual function cannot have a deduced return type + * - ``2549``\ + - | ``keyword_dropped``\ : + | *entity-kind "entity"*\ will be treated as a context-sensitive + keyword from this point + * - ``2550``\ + - | ``global_ns_has_no_actual_member``\ : + | the global namespace has no actual member *"xxxx"*\ + * - ``2551``\ + - | ``different_enum_comparison``\ : + | comparison between two different enum types (*"type"*\ and + *"type"*\ ) + * - ``2552``\ + - | ``unrecognized_target_attribute``\ : + | target attribute not recognized + * - ``2553``\ + - | ``gnu_mv_default_missing``\ : + | missing "default" target function + * - ``2554``\ + - | ``gnu_mv_only_one_arch``\ : + | only one arch= target may be specified + * - ``2555``\ + - | ``generic_class_cannot_be_custom_attribute``\ : + | a generic class cannot be a custom attribute + * - ``2556``\ + - | ``invalid_ms_attribute_target``\ : + | invalid attribute target *"xxxx"*\ + * - ``2557``\ + - | ``ambiguous_ms_attribute``\ : + | ambiguous attribute -- both *"type"*\ and *"type"*\ could be used + * - ``2558``\ + - | ``cli_attribute_inaccessible_field``\ : + | a named attribute argument can only reference a public nonstatic + read/write field or scalar property + * - ``2559``\ + - | ``cli_attribute_invalid_field``\ : + | a named attribute argument can only reference a nonstatic field or + scalar property of an attribute parameter type + * - ``2560``\ + - | ``cli_attribute_invalid_argument``\ : + | invalid attribute argument -- expression must be a constant of an + attribute parameter type + * - ``2561``\ + - | ``cli_typeid_of_generic_param_in_attribute``\ : + | an attribute argument cannot use generic type parameters + * - ``2562``\ + - | ``invalid_use_of_standalone_custom_ms_attr``\ : + | *"type"*\ may only be used as a standalone attribute + * - ``2563``\ + - | ``field_target_on_nontrivial_property_or_event``\ : + | the 'field' attribute target cannot be used on a non-trivial + property/event + * - ``2564``\ + - | ``invalid_attribute_target_for_standalone_ms_attr``\ : + | invalid attribute target for a standalone attribute + * - ``2565``\ + - | ``invalid_attribute_target_for_ms_attr``\ : + | invalid attribute target for this context + * - ``2566``\ + - | ``invalid_use_of_custom_ms_attr``\ : + | *"type"*\ attribute cannot be used here + * - ``2567``\ + - | ``cli_param_array_attribute_deprecated``\ : + | *"type"*\ is deprecated; use '...' to specify a parameter array + * - ``2568``\ + - | ``namespace_default_cannot_be_extended``\ : + | the default namespace cannot be extended + * - ``2569``\ + - | ``cppcx_box_invalid_type``\ : + | the boxed type must be a value class or enum + * - ``2570``\ + - | ``tracking_reference_to_value_class``\ : + | tracking reference to value class is not allowed + * - ``2571``\ + - | ``handle_to_value_class``\ : + | handle to value class is not allowed + * - ``2572``\ + - | ``tracking_reference_to_enum``\ : + | tracking reference to enum is not allowed + * - ``2573``\ + - | ``handle_to_enum``\ : + | handle to enum is not allowed + * - ``2574``\ + - | ``cppcx_public_native_type``\ : + | a public native type is not allowed + * - ``2575``\ + - | ``public_nested_type_in_cppcx_type``\ : + | a public nested type is not allowed + * - ``2576``\ + - | ``cppcx_generic_type_not_allowed``\ : + | generic types are not permitted in C++/CX + * - ``2577``\ + - | ``cppcx_generic_method_not_allowed``\ : + | generic methods are not permitted in C++/CX + * - ``2578``\ + - | ``cppcx_generic_constraints_not_allowed``\ : + | generic constraints are not allowed + * - ``2579``\ + - | ``nonpublic_data_member_in_public_cppcx_value_type``\ : + | non-public data members are not allowed in public C++/CX value types + * - ``2580``\ + - | ``public_nondata_member_in_public_cppcx_value_type``\ : + | public non-data members are not allowed in public C++/CX value types + * - ``2581``\ + - | ``cppcx_public_value_class_constructor``\ : + | constructors are not allowed in public C++/CX value types + * - ``2582``\ + - | ``bad_cppcx_event_add_return``\ : + | the return type of the "add" accessor must be + Windows::Foundation::EventRegistrationToken + * - ``2583``\ + - | ``bad_cppcx_event_remove_return``\ : + | the return type of the "remove" accessor must be void + * - ``2584``\ + - | ``bad_cppcx_event_remove_parameter``\ : + | the parameter type of the "remove" accessor must be + Windows::Foundation::EventRegistrationToken + * - ``2585``\ + - | ``cppcx_handle_or_ref_to_generic_param``\ : + | a handle or reference to a generic parameter type is not allowed + * - ``2586``\ + - | ``public_data_member_in_public_non_value_type``\ : + | public data members are not allowed in non-value types + * - ``2587``\ + - | ``cl_cppcx_only_in_microsoft_cplusplus``\ : + | C++/CX can be enabled only in Microsoft C++ mode + * - ``2588``\ + - | ``cl_cppcx_and_cppcli``\ : + | C++/CLI and C++/CX modes cannot be combined + * - ``2589``\ + - | ``cppcx_not_enabled``\ : + | *"xxxx"*\ requires C++/CX mode + * - ``2590``\ + - | ``cl_microsoft_version_insufficient_for_cppcx``\ : + | C++/CX mode requires microsoft_version >= 1600 + * - ``2591``\ + - | ``literal_fields_disallowed_in_cppcx_mode``\ : + | Literal fields are not allowed in C++/CX + * - ``2592``\ + - | ``normal_ref_bound_to_cppcx_lvalue``\ : + | a standard reference cannot be bound to a C++/CX type + * - ``2593``\ + - | ``cppcx_enum_base_has_no_platform_counterpart``\ : + | type must correspond to Platform::Boolean, default::uint8, + default::int8, default::int16, default::uint16, default::int32, + default::uint32, default::int64, or default::uint64 + * - ``2594``\ + - | ``event_in_cppcx_value_type``\ : + | a C++/CX value type cannot have events + * - ``2595``\ + - | ``bad_cppcx_dynamic_cast_type``\ : + | a dynamic_cast to a handle type must refer to a complete class type + * - ``2596``\ + - | ``cppcx_array_only_one_dimension_allowed``\ : + | Platform::Array can only be one-dimensional + * - ``2597``\ + - | ``cppcx_tracking_reference_on_standard_class_type``\ : + | tracking reference to standard class type is not allowed + * - ``2598``\ + - | ``cppcx_value_type_deriving_from_interface``\ : + | a C++/CX value type cannot inherit from an interface + * - ``2599``\ + - | ``cppcx_value_type_contains_virtual_function``\ : + | a C++/CX value type cannot contain virtual functions + * - ``2600``\ + - | ``partial_class_incorrect_type_or_location``\ : + | "partial" can only be applied to "ref class" or "ref struct" at + global scope or namespace scope + * - ``2601``\ + - | ``cppcx_invalid_array_property_set_value_parameter``\ : + | the parameter of the "set" accessor must be of type "const + Platform::Array^" + * - ``2602``\ + - | ``cppcx_public_global_type``\ : + | the definition of a public C++/CX type is not allowed at global scope + * - ``2603``\ + - | ``cppcx_public_indexed_property``\ : + | an indexed property with a public "get" or "set" accessor is not + allowed + * - ``2604``\ + - | ``cppcx_public_nested_delegate``\ : + | a public nested delegate type is not allowed + * - ``2605``\ + - | ``cppcx_bad_delegate_init_list``\ : + | invalid delegate initializer -- expected either "( [, Platform::CallbackContext])" or "(, [, Platform::CallbackContext [, bool]])" + * - ``2606``\ + - | ``cppcx_invalid_delegate_object``\ : + | invalid delegate initializer -- object must be a handle to a managed + class + * - ``2607``\ + - | ``cppcx_non_const_array_parameter``\ : + | C++/CX does not support 'in/out' arrays -- use "const + Platform::Array^" for 'in' and "Platform::WriteOnlyArray^" or + "Platform::Array^\*" for 'out' on public APIs + * - ``2608``\ + - | ``missing_target_attribute``\ : + | missing "target" attribute for *entity-kind "entity"*\ (declared at + line *xxxx*\ ) + * - ``2609``\ + - | ``no_matching_target_attribute``\ : + | no declared member function matches "target" attributes for + *entity-kind "entity"*\ + * - ``2610``\ + - | ``invalid_base_for_ms_attributes``\ : + | Microsoft attributes in this location are only permitted for + interface types + * - ``2611``\ + - | ``resolver_routine_required``\ : + | GNU function multiversion resolver routine required + * - ``2612``\ + - | ``enum_in_managed_class_missing_definition``\ : + | an enum type declared in a managed class must include a definition + * - ``2613``\ + - | ``decltype_qualified_declared_name``\ : + | a decltype-qualified name is nonstandard in this declaration context + * - ``2614``\ + - | ``final_modifier_requires_virtual_function``\ : + | nonvirtual function cannot be declared with "final" modifier + * - ``2615``\ + - | ``target_on_special_function``\ : + | "target" attribute on special function is not supported + * - ``2616``\ + - | ``target_string_must_be_narrow``\ : + | must be a narrow string literal + * - ``2617``\ + - | ``target_unmatched_parens``\ : + | unmatched parentheses + * - ``2618``\ + - | ``gcc_pragma_nothing_to_pop``\ : + | no corresponding "push_options" + * - ``2619``\ + - | ``pragma_inside_function``\ : + | this pragma is not allowed inside a function + * - ``2620``\ + - | ``inline_new_or_delete_operator``\ : + | declaring a new or delete operator "inline" is nonstandard + * - ``2621``\ + - | ``pack_expansion_for_field_mem_init``\ : + | a mem-initializer for a data member cannot be a pack expansion + * - ``2622``\ + - | ``generic_lambda_cannot_capture``\ : + | generic lambda expressions cannot have capture defaults in this mode + * - ``2623``\ + - | ``friend_with_def_arg_must_be_definition``\ : + | a default template argument in a friend declaration may only be + specified in a definition + * - ``2624``\ + - | ``friend_with_def_arg_must_be_only_decl``\ : + | a friend template declaration with a default template argument must + be the only declaration (first declared at line *xxxx*\ ) + * - ``2625``\ + - | ``non_autonomous_opaque_enum_decl``\ : + | an opaque enum declaration cannot be part of another declaration + * - ``2626``\ + - | ``nonstd_opaque_enum_decl_in_type_id``\ : + | an opaque enum declaration is nonstandard in this context + * - ``2627``\ + - | ``extended_friends_is_cpp11``\ : + | extended friend syntax is a C++11 feature + * - ``2628``\ + - | ``digit_separators_not_enabled``\ : + | digit separators not enabled, apostrophe begins a character literal + * - ``2629``\ + - | ``bad_digit_separator_pos``\ : + | digit separator cannot appear here + * - ``2630``\ + - | ``constexpr_ignored_on_microsoft_nonstatic_member``\ : + | "constexpr" is ignored here in Microsoft mode + * - ``2631``\ + - | ``bad_gnu_stmt_return``\ : + | invalid expression for statement expression result + * - ``2632``\ + - | ``macro_not_udl_suffix``\ : + | identifier is a macro and not a literal suffix + * - ``2633``\ + - | ``cannot_call_named_member_on_lvalue``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot be called + on an lvalue + * - ``2634``\ + - | ``cannot_call_named_member_on_rvalue``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot be called + on an rvalue + * - ``2635``\ + - | ``cannot_call_member_on_lvalue``\ : + | member function cannot be called on an lvalue + * - ``2636``\ + - | ``cannot_call_member_on_rvalue``\ : + | member function cannot be called on an rvalue + * - ``2637``\ + - | ``templ_param_list_too_long``\ : + | the template parameter list is too long + * - ``2638``\ + - | ``bad_alias_templ_redecl``\ : + | alias template type *"type"*\ is incompatible with the previous type + of *"type"*\ in the redeclaration of *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``2639``\ + - | ``field_initializer_is_not_constant``\ : + | the field initializer for *entity-kind "entity"*\ (declared at line + *xxxx*\ ) is not a constant expression + * - ``2640``\ + - | ``constraint_number_mismatch``\ : + | the number of operand constraints must be the same in each constraint + string + * - ``2641``\ + - | ``too_many_constraints``\ : + | the constraint string contains too many alternative constraints; not + all constraints were checked + * - ``2643``\ + - | ``decltype_auto_cannot_be_qualified``\ : + | decltype(auto) cannot have added type qualifiers + * - ``2644``\ + - | ``bad_init_capture_capture``\ : + | init-capture *"entity"*\ (declared at line *xxxx*\ ) cannot be + captured here + * - ``2645``\ + - | ``invalid_nontype_template_argument``\ : + | invalid nontype template argument of type *"type"*\ + * - ``2646``\ + - | ``abi_tag_ignored_in_C_mode``\ : + | the abi_tag attribute is ignored (it has no meaning in C mode) + * - ``2647``\ + - | ``abi_tag_redefinition``\ : + | redeclaration adds abi_tag attribute "*xxxx*\ " + * - ``2648``\ + - | ``abi_tag_ignored``\ : + | abi_tag attribute is ignored (superseded by later abi_tag attribute) + * - ``2649``\ + - | ``no_abi_tag_on_declaration``\ : + | previous declaration of *entity-kind "entity"*\ (declared at line + *xxxx*\ ) had no abi_tag attribute + * - ``2651``\ + - | ``abi_tag_ignored_on_specialization``\ : + | abi_tag attribute is ignored on specialization + * - ``2652``\ + - | ``decltype_auto_return_must_be_standalone``\ : + | decltype(auto) cannot appear under a pointer, reference, or + pointer-to-member construct + * - ``2653``\ + - | ``exp_class_or_typename``\ : + | expected "class" or "typename" + * - ``2654``\ + - | ``placement_new_refers_to_non_placement_delete``\ : + | placement "new" expression refers to non-placement *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``2655``\ + - | ``cl_must_specify_cpp14_mode``\ : + | must specify C++14 mode when building runtime library + * - ``2659``\ + - | ``constexpr_not_const``\ : + | constexpr non-static member function will not be implicitly 'const' + in C++14 + * - ``2660``\ + - | ``nonliteral_var_in_constexpr_function``\ : + | variable type *"type"*\ in constexpr function is not a literal type + * - ``2661``\ + - | ``nonautomatic_var_in_constexpr_function``\ : + | variable in constexpr function does not have automatic storage + duration + * - ``2662``\ + - | ``uninitialized_var_in_constexpr_function``\ : + | variable in constexpr function is uninitialized + * - ``2663``\ + - | ``auto_direct_list_init_requires_singleton``\ : + | braced initialization of a variable declared with a placeholder type + but without "=" requires exactly one element inside the braces + * - ``2664``\ + - | ``cl_invalid_target``\ : + | no "*xxxx*\ " --target configuration exists + * - ``2665``\ + - | ``attribute_not_supported_in_x86_64``\ : + | attribute is supported only in 32-bit x86 configurations + * - ``2666``\ + - | ``cl_missing_argument``\ : + | "*xxxx*\ " requires an argument + * - ``2667``\ + - | ``special_member_coroutine``\ : + | a constructor or destructor cannot be a coroutine + * - ``2668``\ + - | ``main_coroutine``\ : + | *entity-kind "entity"*\ cannot be a coroutine + * - ``2669``\ + - | ``yield_in_catch``\ : + | co_yield expressions are not permitted in a catch clause + * - ``2674``\ + - | ``special_class_template_not_found``\ : + | class template *"xxxx"*\ not found + * - ``2675``\ + - | ``typename_needed``\ : + | use the "typename" keyword to treat *entity-kind "entity"*\ as a + type in a dependent context + * - ``2676``\ + - | ``shufflevector_index_out_of_range``\ : + | argument value must be less than the sum of the vector elements + * - ``2677``\ + - | ``not_a_type_member``\ : + | *"type"*\ has no member *"xxxx"*\ + * - ``2678``\ + - | ``braced_list_for_implicit_return_type``\ : + | a brace-enclosed list does not provide a return type + * - ``2679``\ + - | ``await_not_allowed_outside_function_scope``\ : + | a co_await expression must appear in a function scope + * - ``2680``\ + - | ``await_not_allowed_in_catch_clause``\ : + | a co_await expression is not allowed inside a catch clause + * - ``2681``\ + - | ``coroutine_with_ellipsis_parameter``\ : + | a coroutine cannot have an ellipsis parameter + * - ``2682``\ + - | ``cl_relaxed_constexpr_requires_bool``\ : + | enabling C++14-style constexpr requires support for "bool" + * - ``2683``\ + - | ``constexpr_function_undefined``\ : + | constexpr *entity-kind "entity"*\ (declared at line *xxxx*\ ) is not + defined + * - ``2684``\ + - | ``constexpr_call_not_interpretable``\ : + | this call cannot be evaluated because the target function + *entity-kind "entity"*\ (declared at line *xxxx*\ ) is not constexpr + or not completely defined yet + * - ``2687``\ + - | ``anon_union_alias_member_template``\ : + | invalid anonymous union -- alias member template is not allowed + * - ``2688``\ + - | ``utf8_char_lit_too_long``\ : + | a UTF-8 character literal value cannot occupy more than one code unit + * - ``2689``\ + - | ``variable_not_constant_valued``\ : + | the value of *entity-kind "entity"*\ (declared at line *xxxx*\ ) + cannot be used as a constant + * - ``2690``\ + - | ``variable_not_constant_addressed``\ : + | a pointer or reference to *entity-kind "entity"*\ (declared at line + *xxxx*\ ) cannot be used as a constant + * - ``2691``\ + - | ``constexpr_non_array_subscript``\ : + | nonzero subscript for non-array object + * - ``2692``\ + - | ``constexpr_out_of_bounds_array_access``\ : + | cannot access position *n*\ in array of *n*\ elements + * - ``2693``\ + - | ``constexpr_called_from``\ : + | called from: + * - ``2694``\ + - | ``constexpr_union_field_inactive``\ : + | invalid access to inactive *entity-kind "entity"*\ of union + (*entity-kind "entity"*\ is active) + * - ``2695``\ + - | ``constexpr_goto``\ : + | 'goto' cannot be executed in constexpr contexts + * - ``2696``\ + - | ``constexpr_missing_return_value``\ : + | missing return value + * - ``2697``\ + - | ``constexpr_null_callee``\ : + | callee is null + * - ``2698``\ + - | ``constexpr_null_dereference``\ : + | attempt to dereference a null pointer + * - ``2699``\ + - | ``constexpr_access_one_past_array_end``\ : + | attempt to access storage one position past the end of an array of + *n*\ elements + * - ``2700``\ + - | ``constexpr_access_to_expired_storage``\ : + | attempt to access expired storage + * - ``2701``\ + - | ``constexpr_access_to_runtime_storage``\ : + | attempt to access run-time storage + * - ``2703``\ + - | ``constexpr_call_to_nonconstexpr_function``\ : + | cannot call non-constexpr *entity-kind "entity"*\ (declared at line + *xxxx*\ ) + * - ``2704``\ + - | ``constexpr_vla``\ : + | cannot use variable-length array during constexpr evaluation + * - ``2705``\ + - | ``constexpr_negative_shift``\ : + | cannot perform a negative shift + * - ``2706``\ + - | ``constexpr_shift_excess``\ : + | shift amount (*n*\ ) too large + * - ``2707``\ + - | ``constexpr_integer_overflow``\ : + | value exceeds range of *"type"*\ + * - ``2708``\ + - | ``constexpr_fp_error``\ : + | floating-point error + * - ``2709``\ + - | ``constexpr_null_ptr_to_member_data``\ : + | attempt to dereference a null pointer-to-member (data member) + * - ``2710``\ + - | ``comparison_of_pointers_to_void_and_function``\ : + | comparing a pointer to void and a pointer to a function is nonstandard + * - ``2711``\ + - | ``ms_metadata_init_failed``\ : + | metadata initialization failed + * - ``2712``\ + - | ``constexpr_bad_derived_class_cast``\ : + | invalid base-to-derived cast (actual derived class type is *"type"*\ ) + * - ``2713``\ + - | ``constexpr_invalid_pm_access``\ : + | invalid access to *entity-kind "entity"*\ in object of complete type + *"type"*\ + * - ``2714``\ + - | ``bad_gnu_auto_type``\ : + | *"xxxx"*\ not allowed here + * - ``2715``\ + - | ``gnu_auto_type_with_secondary_declarator``\ : + | *"xxxx"*\ does not permit multiple declarators + * - ``2716``\ + - | ``auto_type_brace_initialization_not_allowed``\ : + | initialization with "{...}" is not allowed for *"xxxx"*\ + * - ``2717``\ + - | ``modified_auto_type``\ : + | *"xxxx"*\ must be a placeholder for the complete type of the + variable (not for a component of that type) + * - ``2718``\ + - | ``gnu_auto_type_without_initializer``\ : + | a variable declared with *"xxxx"*\ requires an initializer + * - ``2719``\ + - | ``constant_must_be_positive``\ : + | integer constant must be greater than or equal to zero + * - ``2720``\ + - | ``type_must_be_integral``\ : + | type must be an integral type + * - ``2721``\ + - | ``constexpr_expression_cannot_be_interpreted``\ : + | expression cannot be interpreted + * - ``2722``\ + - | ``constexpr_statement_cannot_be_interpreted``\ : + | statement cannot be interpreted + * - ``2723``\ + - | ``constexpr_interpreter_address``\ : + | invalid use of address of interpreter storage + * - ``2724``\ + - | ``constexpr_invalid_constant_kind``\ : + | invalid constant kind for constant-expression + * - ``2725``\ + - | ``constexpr_type_too_large``\ : + | type *"type"*\ too large for constant-expression evaluation + * - ``2726``\ + - | ``constexpr_type_invalid``\ : + | invalid type *"type"*\ for constant-expression evaluation + * - ``2727``\ + - | ``constexpr_invalid_type_conversion``\ : + | conversion from *"type"*\ to *"type"*\ is invalid in + constant-expression evaluation + * - ``2728``\ + - | ``constexpr_fp_conversion_failed``\ : + | floating-point conversion failed + * - ``2730``\ + - | ``deduced_return_types_is_cpp14``\ : + | deduced return types are a C++14 feature + * - ``2731``\ + - | ``constexpr_ctor_with_dtor``\ : + | cannot evaluate a constructor with an associated destructor + * - ``2732``\ + - | ``constexpr_missing_initializer_for_field``\ : + | *entity-kind "entity"*\ not initialized during constexpr evaluation + * - ``2733``\ + - | ``constexpr_invalid_pdiff``\ : + | invalid pointer difference in constexpr evaluation + * - ``2734``\ + - | ``constexpr_non_array_pointer_arithmetic``\ : + | invalid arithmetic on non-array pointer + * - ``2735``\ + - | ``constexpr_pointer_ahead_of_array``\ : + | cannot set pointer before the first array element + * - ``2736``\ + - | ``coroutine_with_deduced_return_type``\ : + | a coroutine with a deduced return type is invalid + * - ``2737``\ + - | ``await_in_unevaluated_operand``\ : + | expression not allowed in unevaluated context + * - ``2740``\ + - | ``return_in_coroutine``\ : + | "return" is not permitted in a coroutine (use "co_return" instead) + * - ``2741``\ + - | ``invalid_co_return``\ : + | "co_return" is only allowed in coroutines + * - ``2742``\ + - | ``constexpr_fp_values_not_comparable``\ : + | floating-point values cannot be compared + * - ``2743``\ + - | ``constexpr_pointers_not_comparable``\ : + | pointer values cannot be compared because they do not point into the + same complete object or they point to subobjects with different + accessibility + * - ``2744``\ + - | ``ignoring_attribute_on_non_inline_namespace``\ : + | ignoring abi_tag attribute on non-inline namespace + * - ``2745``\ + - | ``ignoring_attribute_on_anonymous_namespace``\ : + | ignoring abi_tag attribute on anonymous namespace + * - ``2746``\ + - | ``complex_template_parameter``\ : + | complex or imaginary template parameter type is nonstandard + * - ``2747``\ + - | ``yield_outside_of_function``\ : + | co_yield expression is not permitted outside a function scope + * - ``2748``\ + - | ``thread_local_ignored``\ : + | ignoring thread-local indication on anonymous union + * - ``2751``\ + - | ``object_not_initialized``\ : + | access to uninitialized object + * - ``2752``\ + - | ``constexpr_volatile_fetch``\ : + | attempt to read from volatile storage + * - ``2753``\ + - | ``constexpr_no_active_union_field``\ : + | invalid access to inactive *entity-kind "entity"*\ of union (no + field is active) + * - ``2754``\ + - | ``label_in_constexpr_function``\ : + | label definitions cannot appear in constexpr functions + * - ``2755``\ + - | ``constexpr_equality_past_the_end_address``\ : + | cannot compare a pointer past the end of an array with a pointer to + another complete object + * - ``2756``\ + - | ``variable_templ_function_type``\ : + | function type *"type"*\ is an invalid type for a variable template + instantiation + * - ``2757``\ + - | ``incomplete_var_type``\ : + | variable cannot have incomplete type *"type"*\ + * - ``2758``\ + - | ``field_subobject_not_initialized``\ : + | access to uninitialized subobject (*entity-kind "entity"*\ ) + * - ``2759``\ + - | ``base_subobject_not_initialized``\ : + | access to uninitialized subobject (base class *"type"*\ ) + * - ``2760``\ + - | ``constexpr_vacuous_dtor_call``\ : + | a pseudo-destructor call is not permitted in a constant-expression + * - ``2761``\ + - | ``constexpr_modifying_const_storage``\ : + | attempt to modify const storage + * - ``2764``\ + - | ``constexpr_access_past_object``\ : + | attempt to access storage one position past an object treated as an + array of one element + * - ``2765``\ + - | ``constexpr_reinterpret_cast``\ : + | cannot use reinterpret_cast in constant-expression evaluation + * - ``2766``\ + - | ``constexpr_invalid_null_ptr_operation``\ : + | operation not allowed on null pointer + * - ``2767``\ + - | ``star_this_not_constant_valued``\ : + | the value of \*this cannot be used as a constant + * - ``2768``\ + - | ``inline_on_nested_namespace``\ : + | the "inline" keyword cannot be used on a nested namespace declaration + * - ``2769``\ + - | ``carries_dependency_ignored``\ : + | the "carries_dependency" attribute is ignored + * - ``2770``\ + - | ``event_interface_cannot_have_definition``\ : + | an "\__event \__interface" cannot have a definition here + * - ``2771``\ + - | ``invalid_event_handler_type``\ : + | an event handler must have a void or integral return type + * - ``2772``\ + - | ``event_interface_must_be_previously_defined``\ : + | an "\__event \__interface" must have been previously defined + * - ``2773``\ + - | ``too_many_template_arguments``\ : + | too many template arguments for *entity-kind "entity"*\ + * - ``2774``\ + - | ``enumerator_already_declared``\ : + | enumerator already declared (see *entity-kind "entity"*\ (declared + at line *xxxx*\ )) + * - ``2775``\ + - | ``microsoft_version_doesnt_support_cpp14_mode``\ : + | the version of Microsoft being emulated must be at least 1903 to use + "--ms_c++14" + * - ``2776``\ + - | ``microsoft_version_doesnt_support_cpplatest_mode``\ : + | the version of Microsoft being emulated must be at least 1903 to use + "--ms_c++latest" + * - ``2777``\ + - | ``c11_atomic_array_or_function_type``\ : + | type *"type"*\ cannot be _Atomic because it is an array or function + type + * - ``2778``\ + - | ``c11_atomic_specifier_with_qualified_type``\ : + | the _Atomic(...) specifier cannot be applied to qualified type + *"type"*\ + * - ``2779``\ + - | ``access_to_member_of_c11_atomic_object``\ : + | access to member of _Atomic object + * - ``2780``\ + - | ``c11_atomic_bit_field``\ : + | a bit field cannot have an _Atomic type + * - ``2782``\ + - | ``nonconstexpr_mem_init_ctor_for_constexpr_ctor``\ : + | constexpr constructor calls non-constexpr constructor for subobject + initialization + * - ``2783``\ + - | ``terse_static_assert_not_enabled``\ : + | expected a comma (the one-argument version of static_assert is not + enabled in this mode) + * - ``2784``\ + - | ``terse_static_assert``\ : + | static assertion failed + * - ``2785``\ + - | ``conflicting_nullability``\ : + | at most one of the qualifiers _Nullable, _Nonnull, and + _Null_unspecified can modify a type + * - ``2786``\ + - | ``invalid_type_for_nullability``\ : + | nullability qualifiers are only permitted on pointer and + pointer-to-member types + * - ``2787``\ + - | ``vector_length_too_large``\ : + | vector length is too large + * - ``2788``\ + - | ``invalid_vector_element_type``\ : + | vector element type must be integral, enum, or real floating-point + type + * - ``2789``\ + - | ``builtin_needs_128_bit_integers``\ : + | builtin function is not available because 128-bit integers are not + supported + * - ``2790``\ + - | ``builtin_needs_vector_types``\ : + | builtin function is not available because vector types are not + supported + * - ``2791``\ + - | ``must_introduce_attribute``\ : + | two consecutive left square brackets always introduce an attribute + list but an attribute list cannot appear here + * - ``2792``\ + - | ``invalid_target_attribute``\ : + | unrecognized "target" attribute disqualifies this routine from being + used by resolver routine + * - ``2793``\ + - | ``vector_type_required``\ : + | *"type"*\ is not a vector type + * - ``2794``\ + - | ``vector_types_differ_in_length``\ : + | vector types *"type"*\ and *"type"*\ must have the same length + * - ``2795``\ + - | ``member_special_after_class_definition``\ : + | added default arguments cannot result in declaring a default or copy + constructor + * - ``2796``\ + - | ``template_arg_cannot_point_to_subobject``\ : + | a nontype template argument of reference type must bind to a function + or to a complete object + * - ``2797``\ + - | ``type_not_allowed_here``\ : + | *"type"*\ not allowed here + * - ``2798``\ + - | ``register_keyword_disallowed``\ : + | use of the "register" storage class specifier is not allowed + * - ``2799``\ + - | ``register_keyword_deprecated``\ : + | use of the "register" storage class specifier is deprecated + * - ``2800``\ + - | ``incr_of_bool_not_allowed``\ : + | incrementing a bool value is not allowed + * - ``2801``\ + - | ``redeclaration_of_range_iterator``\ : + | *"xxxx"*\ , declared as iterator of range-based "for" statement, may + not be redeclared in this scope + * - ``2802``\ + - | ``namespace_not_allowed``\ : + | an attribute namespace may not be used here (because a "using" prefix + was specified) + * - ``2803``\ + - | ``attribute_namespace_unrecognized``\ : + | attribute namespace *"xxxx"*\ is unrecognized + * - ``2804``\ + - | ``default_member_init_for_value_class``\ : + | a default member initializer is not permitted in a value class + * - ``2805``\ + - | ``cl_implicit_noexcept_requires_noexcept_support``\ : + | "--implicit_noexcept" requires a mode that enables noexcept + * - ``2806``\ + - | ``constexpr_virtual_base``\ : + | cannot fold operation involving virtual base class (*"type"*\ ) + * - ``2807``\ + - | ``initializer_not_constant``\ : + | initialization is not constant + * - ``2808``\ + - | ``constexpr_incomplete_type``\ : + | cannot evaluate value of incomplete *"type"*\ + * - ``2809``\ + - | ``nodiscard_routine``\ : + | ignoring return value from routine declared with "nodiscard" attribute + * - ``2810``\ + - | ``nodiscard_return_type``\ : + | ignoring return value type with "nodiscard" attribute + * - ``2811``\ + - | ``nodiscard_doesnt_apply``\ : + | the "nodiscard" attribute does not apply to destructors or routines + with void return type + * - ``2812``\ + - | ``fallthrough_applies_to_null_statement``\ : + | the "fallthrough" attribute only applies to null statements + * - ``2813``\ + - | ``fallthrough_not_in_switch``\ : + | the "fallthrough" attribute may only appear in an enclosing switch + statement + * - ``2814``\ + - | ``fallthrough_must_precede_switch_case``\ : + | fallthrough statement must precede switch case label or default + * - ``2815``\ + - | ``constexpr_expiring_temporary``\ : + | reference or pointer to temporary with limited lifetime + * - ``2816``\ + - | ``address_of_nontrue_enable_if_function``\ : + | cannot take the address of a function with an "enable_if" attribute + whose condition is not unconditionally true + * - ``2817``\ + - | ``nonconstant_enable_if_attr``\ : + | "enable_if" attributes with conditions that are not constant values + are not currently supported + * - ``2818``\ + - | ``attribute_declared_here``\ : + | attribute was declared here + * - ``2819``\ + - | ``has_include_not_in_if``\ : + | __has_include cannot appear outside #if + * - ``2820``\ + - | ``coclass_base_requirements_not_met``\ : + | could not add CComCoClass base class + * - ``2821``\ + - | ``constexpr_string_not_null_terminated``\ : + | not a null-terminated string + * - ``2822``\ + - | ``non_scalar_vacuous_dtor_call``\ : + | non-scalar type *"type"*\ cannot be used in a pseudo-destructor call + * - ``2823``\ + - | ``constexpr_weak_address``\ : + | address of "weak" *entity-kind "entity"*\ is not constant + * - ``2824``\ + - | ``excessive_rescan_depth``\ : + | too many recursive substitutions of function template signatures + * - ``2825``\ + - | ``invalid_struct_binding_specifier``\ : + | invalid specifier for structured binding declaration + * - ``2826``\ + - | ``invalid_struct_binding_syntax``\ : + | invalid structured binding syntax + * - ``2827``\ + - | ``missing_initializer``\ : + | missing initializer + * - ``2828``\ + - | ``invalid_struct_binding_type``\ : + | type *"type"*\ has no components to bind to + * - ``2829``\ + - | ``too_many_struct_bindings``\ : + | too many identifiers + * - ``2830``\ + - | ``missing_bindings``\ : + | there are more elements than there are binding names + * - ``2831``\ + - | ``missing_std_tuple_element``\ : + | "std::tuple_element" not defined + * - ``2832``\ + - | ``missing_std_tuple_element_instance``\ : + | cannot instantiate "std::tuple_element" for <*xxxx*\ , *"type"*\ > + * - ``2833``\ + - | ``failed_tuple_container_member_get``\ : + | cannot call member function "get<*xxxx*\ >()" for type *"type"*\ + * - ``2834``\ + - | ``tuple_get_no_matching_overload``\ : + | no instance of *"entity"*\ matches the argument list + * - ``2835``\ + - | ``struct_binding_undefined_identifier``\ : + | this structured binding requires a suitable *"xxxx"*\ function and + none was found + * - ``2836``\ + - | ``struct_binding_inline``\ : + | a structured binding cannot be declared "inline" + * - ``2837``\ + - | ``struct_binding_constexpr``\ : + | a structured binding cannot be declared "constexpr" + * - ``2838``\ + - | ``struct_binding_storage_class``\ : + | a structured binding cannot declare an explicit storage class + * - ``2839``\ + - | ``invalid_tuple_size``\ : + | std::tuple_size<*"type"*\ >::value is not a valid integral + constant-expression + * - ``2840``\ + - | ``condition_does_not_declare_a_variable``\ : + | a condition declaration must declare a variable + * - ``2841``\ + - | ``condition_decl_must_have_initializer``\ : + | a condition declaration must include an initializer + * - ``2842``\ + - | ``parenthesized_init_not_allowed``\ : + | a parenthesized initializer is not permitted for a condition + declaration + * - ``2843``\ + - | ``condition_with_multiple_declarators``\ : + | a condition declaration can only declare one variable + * - ``2844``\ + - | ``struct_binding_lambda``\ : + | structured binding cannot bind to closure type + * - ``2845``\ + - | ``struct_binding_private_member``\ : + | cannot bind to non-public *entity-kind "entity"*\ + * - ``2846``\ + - | ``struct_binding_incomplete_type``\ : + | cannot bind to incomplete type *"type"*\ + * - ``2847``\ + - | ``invalid_init_statement``\ : + | this declaration is not valid here + * - ``2848``\ + - | ``constexpr_function_with_function_try_block``\ : + | the body of a constexpr function cannot be a function try block + * - ``2849``\ + - | ``branch_into_constexpr_if``\ : + | transfer of control into a constexpr if block is not allowed + * - ``2850``\ + - | ``lambda_capture_structured_binding``\ : + | structured binding cannot be captured + * - ``2851``\ + - | ``microsoft_version_doesnt_support_cpp17_mode``\ : + | the version of Microsoft being emulated must be at least 1911 to use + "--ms_c++17" + * - ``2852``\ + - | ``attempt_to_read_past_end_of_object``\ : + | attempt to read past the end of the object + * - ``2853``\ + - | ``constexpr_lambdas_not_enabled``\ : + | constexpr lambdas are not enabled in this mode + * - ``2854``\ + - | ``lambda_not_constant_expr``\ : + | a constant expression cannot contain a lambda expression + * - ``2855``\ + - | ``template_argument_index_out_of_bounds``\ : + | value exceeds number of template arguments + * - ``2856``\ + - | ``fold_expression_operator_mismatch``\ : + | second operator in binary fold expression does not match first + * - ``2857``\ + - | ``invalid_fold_expression_operator``\ : + | invalid fold expression operator + * - ``2858``\ + - | ``two_packs_in_fold_expression``\ : + | a binary fold expression cannot apply to two parameter packs + * - ``2859``\ + - | ``invalid_empty_fold_expression``\ : + | empty expansion not valid for this fold expression + * - ``2860``\ + - | ``inline_nonstatic_data_mem``\ : + | a nonstatic data member cannot be declared as inline + * - ``2861``\ + - | ``no_pack_in_fold_expression``\ : + | fold expression does not refer to a parameter pack + * - ``2862``\ + - | ``same_param_types_with_different_exception_specifications``\ : + | two functions with the same parameter types but different exception + specifications cannot be overloaded + * - ``2863``\ + - | ``dynamic_exc_spec_not_permitted``\ : + | dynamic exception specifications are not permitted in this mode + * - ``2865``\ + - | ``invalid_noexcept_specifier_operand``\ : + | invalid operand for noexcept specifier + * - ``2866``\ + - | ``lambda_in_noexcept_specifier``\ : + | lambda expression cannot appear in noexcept specifier of a template + * - ``2867``\ + - | ``inaccessible_rvalue_dtor``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) is inaccessible + * - ``2868``\ + - | ``bad_enum_template_decl``\ : + | invalid specifier in enum template declaration + * - ``2869``\ + - | ``no_float80``\ : + | 80-bit floating-point types are not supported in this configuration + * - ``2870``\ + - | ``no_float128``\ : + | 128-bit floating-point types are not supported in this configuration + * - ``2871``\ + - | ``invalid_enumerator_value``\ : + | invalid enumerator value + * - ``2872``\ + - | ``must_be_atomic_qualified_type``\ : + | must be an _Atomic qualified type + * - ``2873``\ + - | ``element_type_incomplete``\ : + | type of array element must be complete + * - ``2874``\ + - | ``always_inline_suppressed``\ : + | the always_inline attribute has been suppressed for this function + * - ``2875``\ + - | ``negative_value``\ : + | a negative value is not permitted here + * - ``2876``\ + - | ``integer_pack_element_for_type``\ : + | an integer pack element cannot match *entity-kind "entity"*\ + * - ``2877``\ + - | ``integer_pack_element_for_template``\ : + | an integer pack element cannot match *entity-kind "entity"*\ + * - ``2878``\ + - | ``unexpected_designator``\ : + | unexpected designator + * - ``2879``\ + - | ``cannot_evaluate_builtin_offsetof``\ : + | cannot evaluate \__builtin_offsetof + * - ``2880``\ + - | ``deduction_guide_def``\ : + | deduction guide *"type"*\ cannot be defined + * - ``2881``\ + - | ``bad_deduction_guide_scope``\ : + | deduction guide must be declared in the same scope as *entity-kind + "entity"*\ + * - ``2882``\ + - | ``invalid_specifier_for_deduction_guide``\ : + | invalid specifier for deduction guide declaration (only "explicit" is + permitted) + * - ``2883``\ + - | ``constexpr_mutable_field_load``\ : + | mutable *entity-kind "entity"*\ of a constant cannot be accessed in + a constant expression + * - ``2884``\ + - | ``member_function_modifier_on_static_member``\ : + | function modifier does not apply to static member declaration + * - ``2885``\ + - | ``overloadable_attribute_requires_prototype``\ : + | the "overloadable" attribute requires a prototyped function + declaration + * - ``2886``\ + - | ``cannot_deduce_auto_templ_param``\ : + | cannot deduce "auto" template parameter type *"type"*\ from + *"type"*\ + * - ``2887``\ + - | ``modified_class_template_placeholder``\ : + | class template name must be a placeholder for the complete type being + initialized (not for a component of that type) + * - ``2888``\ + - | ``alias_declaration_is_cpp11``\ : + | alias declarations are a C++11 feature + * - ``2889``\ + - | ``alias_template_is_cpp11``\ : + | alias templates are a C++11 feature + * - ``2890``\ + - | ``bad_deduction_guide_return_type``\ : + | the return type must directly designate a specialization of the + associated class template + * - ``2891``\ + - | ``explicit_deduction_guide_in_copy_list_init``\ : + | copy-list-initialization cannot use "explicit" *entity-kind + "entity"*\ + * - ``2893``\ + - | ``invalid_udl_value``\ : + | Invalid value for user-defined literal operator + * - ``2894``\ + - | ``has_cpp_attrib_not_in_if``\ : + | *xxxx*\ cannot appear outside of preprocessor directives + * - ``2895``\ + - | ``bad_deduction_guide_access``\ : + | deduction guide must be declared with the same accessibility as + *entity-kind "entity"*\ + * - ``2896``\ + - | ``lambda_not_allowed_here``\ : + | a lambda is not permitted in this context + * - ``2897``\ + - | ``align_not_equivalent``\ : + | specified alignment is not equivalent to previous declaration + * - ``2898``\ + - | ``no_alignment_on_definition``\ : + | no alignment specified on definition; previous declaration had + specified an alignment + * - ``2899``\ + - | ``builtin_needs_128_bit_floats``\ : + | builtin function is not available because 128-bit floating-point + types are not supported + * - ``2900``\ + - | ``constexpr_shift_negative_value``\ : + | left-shifting a negative value has undefined behavior + * - ``2901``\ + - | ``no_array_designators_in_cpp_mode``\ : + | array designators are nonstandard in C++ + * - ``2902``\ + - | ``no_chained_designators_in_cpp_mode``\ : + | chained designators are nonstandard in C++ + * - ``2903``\ + - | ``no_mixed_init_in_cpp_mode``\ : + | mixing designated and non-designated initializers is nonstandard in + C++ + * - ``2904``\ + - | ``no_out_of_order_init_in_cpp_mode``\ : + | out-of-order initializers are nonstandard in C++ + * - ``2905``\ + - | ``invalid_string_literal_operator_template``\ : + | a string literal operator template must have a template parameter + list equivalent to "" + * - ``2906``\ + - | ``duplicate_designator``\ : + | duplicate designator is not allowed + * - ``2907``\ + - | ``likely_unlikely_conflict``\ : + | attribute conflicts with previous likely/unlikely attribute + * - ``2908``\ + - | ``implicit_copy_this_capture_deprecated``\ : + | the implicit by-copy capture of "this" is deprecated + * - ``2909``\ + - | ``empty_lambda_template_param_list``\ : + | an empty template parameter list is not allowed in a lambda expression + * - ``2910``\ + - | ``microsoft_version_doesnt_support_cpp20_mode``\ : + | the version of Microsoft being emulated must be at least 1920 to use + "--ms_c++20" + * - ``2911``\ + - | ``bad_stdc_pragma_arg_for_mode``\ : + | STDC pragma argument not accepted in this mode + * - ``2912``\ + - | ``if_constexpr_is_cpp17``\ : + | constexpr if statements are a C++17 feature + * - ``2913``\ + - | ``no_pack_expansion_in_designator``\ : + | pack expansion is not allowed in a designated initializer list + * - ``2914``\ + - | ``no_designator_value``\ : + | field designator has no value + * - ``2915``\ + - | ``multiple_union_field_initializers_empty``\ : + | a union can have at most one field initializer + * - ``2916``\ + - | ``bad_ordering_type``\ : + | no valid std::*xxxx*\ type found ( must be included) + * - ``2917``\ + - | ``invalid_spaceship_types``\ : + | invalid types (*"type"*\ and *"type"*\ ) for built-in operator<=> + * - ``2918``\ + - | ``fold_expressions_nonstandard``\ : + | fold expressions are nonstandard in this mode + * - ``2919``\ + - | ``selection_initializer_nonstandard``\ : + | C++17-style initializer is nonstandard in this mode + * - ``2920``\ + - | ``star_this_capture_nonstandard``\ : + | capturing \*this is nonstandard in this mode + * - ``2921``\ + - | ``using_attribute_nonstandard``\ : + | C++17-style "using" attribute prefix is nonstandard in this mode + * - ``2922``\ + - | ``nested_namespace_nonstandard``\ : + | C++17-style nested namespaces are nonstandard in this mode + * - ``2923``\ + - | ``constexpr_and_consteval_specifiers``\ : + | only one of "constexpr", "consteval", and "constinit" can appear on a + declaration + * - ``2924``\ + - | ``consteval_virtual_combination``\ : + | a function cannot be both consteval and virtual in this mode + * - ``2925``\ + - | ``consteval_explicit_instantiation``\ : + | "consteval" is not allowed on an explicit instantiation directive + * - ``2926``\ + - | ``invalid_consteval``\ : + | "consteval" is not valid here + * - ``2927``\ + - | ``consteval_destructor``\ : + | a destructor cannot be consteval + * - ``2928``\ + - | ``consteval_ctor_with_virtual_base``\ : + | a constructor for a class with virtual bases cannot be consteval + * - ``2929``\ + - | ``consteval_variable``\ : + | "consteval" is not permitted on the declaration of a variable or + static data member + * - ``2930``\ + - | ``previous_consteval_decl_conflict``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared consteval + * - ``2931``\ + - | ``previous_nonconsteval_decl_conflict``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + not declared consteval + * - ``2932``\ + - | ``consteval_main``\ : + | function "main" may not be declared consteval + * - ``2933``\ + - | ``consteval_call_nonconstant``\ : + | call to consteval *entity-kind "entity"*\ did not produce a valid + constant expression + * - ``2934``\ + - | ``address_of_consteval_function``\ : + | address of consteval *entity-kind "entity"*\ in constant expression + result + * - ``2935``\ + - | ``consteval_overrides_nonconsteval``\ : + | consteval member cannot override non-consteval *entity-kind + "entity"*\ + * - ``2936``\ + - | ``nonconsteval_overrides_consteval``\ : + | non-consteval member cannot override consteval *entity-kind + "entity"*\ + * - ``2938``\ + - | ``constexpr_invalid_dynamic_cast``\ : + | dynamic_cast to subobject of type *"type"*\ is invalid (most-derived + type is *"type"*\ ) + * - ``2939``\ + - | ``VA_OPT_not_allowed``\ : + | the identifier \__VA_OPT\__ can only appear in the replacement lists + of variadic macros + * - ``2940``\ + - | ``nested_VA_OPT``\ : + | __VA_OPT\__ cannot appear in a \__VA_OPT\__ operand + * - ``2941``\ + - | ``unclosed_VA_OPT``\ : + | missing closing parenthesis for \__VA_OPT\__ + * - ``2942``\ + - | ``missing_VA_OPT_paren``\ : + | __VA_OPT\__ must be followed by "(" + * - ``2943``\ + - | ``paste_cannot_be_first_in_VA_OPT``\ : + | "##" may not be first in a \__VA_OPT\__ operand + * - ``2944``\ + - | ``paste_cannot_be_last_in_VA_OPT``\ : + | "##" may not be last in a \__VA_OPT\__ operand + * - ``2945``\ + - | ``nested_inline_namespace_nonstandard``\ : + | C++20-style nested inline namespaces are nonstandard in this mode + * - ``2946``\ + - | ``derived_class_too_far``\ : + | cannot convert pointer to base class *"type"*\ to pointer to derived + class *"type"*\ -- attempt to point beyond the most-derived object + * - ``2948``\ + - | ``invalid_variable_main``\ : + | "main" cannot be used as a global variable name or given C language + linkage + * - ``2949``\ + - | ``linkage_main``\ : + | function "main" cannot be declared in a linkage-specification + * - ``2950``\ + - | ``struct_binding_in_condition``\ : + | structured binding is not allowed in a condition + * - ``2951``\ + - | ``missing_attr_namespace``\ : + | an attribute namespace identifier is required before "::" + * - ``2952``\ + - | ``multiple_attr_namespaces``\ : + | only one attribute namespace is allowed + * - ``2953``\ + - | ``bad_return``\ : + | "return" not allowed here + * - ``2954``\ + - | ``struct_binding_with_multiple_declarators``\ : + | a structured binding cannot be combined with other declarators + * - ``2955``\ + - | ``branch_out_of_constant``\ : + | cannot branch out of a constant-evaluation context + * - ``2956``\ + - | ``struct_binding_template``\ : + | structured binding templates are not permitted + * - ``2957``\ + - | ``braced_init_in_parens``\ : + | a parenthesized initializer must be an expression, not a + brace-enclosed list + * - ``2958``\ + - | ``cannot_deduce_class_template_arguments``\ : + | cannot deduce class template arguments + * - ``2959``\ + - | ``consteval_new_or_delete_operator``\ : + | a new or delete operator cannot be declared "consteval" + * - ``2960``\ + - | ``address_of_consteval_function_leaked``\ : + | the address of a consteval function cannot be used here + * - ``2961``\ + - | ``alignof_function_type``\ : + | the alignment of a function type (*"type"*\ ) is nonstandard + * - ``2962``\ + - | ``alignof_incomplete_array``\ : + | the alignment of an array of unspecified bound is nonstandard in C + * - ``2963``\ + - | ``cannot_be_common_internal_linkage``\ : + | a variable cannot have both "common" and "internal_linkage" attributes + * - ``2964``\ + - | ``internal_linkage_not_on_prior_declaration``\ : + | the "internal_linkage" attribute did not appear on a prior declaration + * - ``2965``\ + - | ``no_class_template_guide``\ : + | no viable template argument deduction candidate found for + *entity-kind "entity"*\ + * - ``2966``\ + - | ``fully_qualified_constructor_call``\ : + | a fully qualified constructor call is not allowed + * - ``2967``\ + - | ``bad_scope_for_defaulted_comparison``\ : + | a defaulted comparison operator must be a member or a friend of the + class it applies to + * - ``2968``\ + - | ``bad_param_type_for_defaulted_comparison``\ : + | bad type *"type"*\ for parameter of defaulted comparison operator + (must be "reference to const X" where X is the enclosing class type) + * - ``2969``\ + - | ``return_type_of_default_comparison_must_be_bool``\ : + | return type of defaulted comparison operator must be "bool" + * - ``2970``\ + - | ``nonconst_defaulted_member_comparison``\ : + | a defaulted member comparison operator must be "const" + * - ``2972``\ + - | ``no_return_value_and_return_void``\ : + | a coroutine's promise type *"type"*\ cannot have both "return_void" + and "return_value" set + * - ``2973``\ + - | ``return_value_at``\ : + | "return_value" declared at line *xxxx*\ + * - ``2974``\ + - | ``return_void_at``\ : + | "return_void" declared at line *xxxx*\ + * - ``2975``\ + - | ``implicit_co_return_with_no_return_void``\ : + | missing co_return statement while *"type"*\ has no "return_void" at + end of *entity-kind "entity"*\ + * - ``2976``\ + - | ``no_nothrow_global_new_for_coroutine``\ : + | no nothrow variant of the global "operator new" found for coroutine + state allocation + * - ``2977``\ + - | ``no_viable_delete_for_coroutine``\ : + | no viable "operator delete" found for coroutine state deallocation + * - ``2978``\ + - | ``no_constexpr_coroutine``\ : + | a constexpr function cannot be a coroutine + * - ``2979``\ + - | ``await_operand_not_a_class``\ : + | the operand to this *xxxx*\ expression resolves to non-class + *"type"*\ + * - ``2980``\ + - | ``await_not_allowed_in_static_initializer``\ : + | a co_await expression is not allowed in a static initializer + * - ``2981``\ + - | ``final_suspend_cannot_throw``\ : + | the co_await expression calling *entity-kind "entity"*\ must be + non-throwing + * - ``2982``\ + - | ``excessive_comparison_rewrites``\ : + | too many recursive comparison rewrite operations + * - ``2983``\ + - | ``invalid_placeholder_for_defaulted_spaceship_return``\ : + | a deducible return type for a default operator<=> must be "auto" + * - ``2984``\ + - | ``constexpr_implied_source_nonconstant``\ : + | implicit copy of non-constant source + * - ``2985``\ + - | ``struct_binding_restricted_storage_class``\ : + | a structured binding cannot declare an explicit storage class other + than static or thread_local + * - ``2986``\ + - | ``defaulted_comparison_for_property``\ : + | defaulted comparison operators are not supported for nontrivial + Microsoft property fields + * - ``2987``\ + - | ``invalid_std_comparison_type``\ : + | standard comparison type (*"type"*\ ) must be a class type with a + single nonstatic data member of integral type + * - ``2988``\ + - | ``invalid_std_comparison_value``\ : + | no constexpr static data member *"xxxx"*\ found in *"type"*\ + * - ``2989``\ + - | ``constexpr_alloc_too_large``\ : + | number of elements (*n*\ ) too large for dynamic allocation + * - ``2990``\ + - | ``constexpr_allocation_too_large``\ : + | constexpr dynamic allocation request too large + * - ``2991``\ + - | ``constexpr_bad_deallocation``\ : + | deallocation of storage that was not dynamically allocated + * - ``2992``\ + - | ``constexpr_bad_deallocation_size``\ : + | deallocation size (*n*\ ) does not correspond to size allocated + (*n*\ ) + * - ``2993``\ + - | ``constexpr_allocation_pos``\ : + | allocation occurred here + * - ``2994``\ + - | ``constexpr_bad_deallocation_type``\ : + | deallocation type (*"type"*\ ) does not correspond to allocation type + (*"type"*\ ) + * - ``2995``\ + - | ``constexpr_leftover_allocations``\ : + | some dynamic allocations (total number = *n*\ ) were not deallocated + * - ``2996``\ + - | ``constexpr_invalid_intrinsic_signature``\ : + | intrinsic *entity-kind "entity"*\ declared with unexpected signature + (type *"type"*\ ) + * - ``2997``\ + - | ``constexpr_begin_report``\ : + | >> output from std::\__report_constexpr_value + * - ``2998``\ + - | ``constexpr_end_report``\ : + | >> end output from std::\__report_constexpr_value + * - ``2999``\ + - | ``constexpr_dependent_array_size``\ : + | cannot use array with dependent array size in constexpr evaluation + * - ``3000``\ + - | ``nodiscard_routine_with_reason``\ : + | ignoring return value from routine declared with "nodiscard" + attribute (*"xxxx"*\ ) + * - ``3001``\ + - | ``nodiscard_return_type_with_reason``\ : + | ignoring return value type with "nodiscard" attribute (*"xxxx"*\ ) + * - ``3002``\ + - | ``nodiscard_constructor``\ : + | constructor used to create discarded object has "nodiscard" attribute + * - ``3003``\ + - | ``nodiscard_constructor_with_reason``\ : + | constructor used to create discarded object has "nodiscard" attribute + (*"xxxx"*\ ) + * - ``3004``\ + - | ``nodiscard_object_type``\ : + | type of discarded object has "nodiscard" attribute + * - ``3005``\ + - | ``nodiscard_object_type_with_reason``\ : + | type of discarded object has "nodiscard" attribute (*"xxxx"*\ ) + * - ``3006``\ + - | ``vacuous_destructor_not_called``\ : + | a pseudo-destructor reference can only be used for a + pseudo-destructor call + * - ``3007``\ + - | ``constexpr_explicit_dtor_call``\ : + | an explicit destructor call is not permitted in a constant-expression + * - ``3008``\ + - | ``comma_operator_in_array_subscript_deprecated``\ : + | an unparenthesized comma operator in an array subscript expression is + deprecated + * - ``3009``\ + - | ``constexpr_alloc_too_small``\ : + | number of dynamically-allocated elements (*n*\ ) too small for + initializer + * - ``3011``\ + - | ``volatile_ass_deprecated``\ : + | use of the result of an assignment to a volatile scalar object is + deprecated + * - ``3012``\ + - | ``volatile_op_ass_deprecated``\ : + | a volatile destination type for a compound assignment expression is + deprecated + * - ``3013``\ + - | ``volatile_func_param_deprecated``\ : + | a volatile function parameter is deprecated + * - ``3014``\ + - | ``volatile_return_type_deprecated``\ : + | a volatile return type is deprecated + * - ``3015``\ + - | ``volatile_str_bind_deprecated``\ : + | use of a volatile qualifier on a structured binding is deprecated + * - ``3016``\ + - | ``ext_vector_type_invalid_size``\ : + | the "ext_vector_type" argument must be between 1 and 2047 + * - ``3017``\ + - | ``ext_vector_type_not_in_typedef``\ : + | the "ext_vector_type" attribute may appear only in a typedef + * - ``3018``\ + - | ``ext_vector_type_requires_integral_floating_type``\ : + | the "ext_vector_type" attribute applies only to integer or + floating-point types + * - ``3019``\ + - | ``feature_test_macro_ignored``\ : + | this feature-test macro is ignored (and returns 0) in the current + compilation mode + * - ``3020``\ + - | ``constexpr_multiple_union_initializers``\ : + | cannot evaluate an aggregate initializer with multiple elements for a + union + * - ``3021``\ + - | ``cmp_operator_does_not_return_bool``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) selected for + operator rewrite does not return type bool + * - ``3022``\ + - | ``constexpr_class_specific_new``\ : + | a new-expression calling a class-specific allocation function cannot + be constant-evaluated + * - ``3023``\ + - | ``constexpr_placement_new``\ : + | a placement new-expression cannot be constant-evaluated + * - ``3024``\ + - | ``constexpr_nonvirtual_subobject_delete``\ : + | deleting through a subobject pointer requires a virtual destructor + * - ``3026``\ + - | ``invalid_intaddr_address``\ : + | operand of \__INTADDR\__ must be offset from null pointer + * - ``3027``\ + - | ``ambiguous_c11_generic``\ : + | _Generic construct matches multiple types + * - ``3028``\ + - | ``ambiguous_c11_generic_previous_match``\ : + | the other match is *"type"*\ + * - ``3029``\ + - | ``availability_attribute_ignored``\ : + | the "availability" attribute used here is ignored + * - ``3030``\ + - | ``init_stmt_in_range_for_nonstandard``\ : + | C++20-style initializer statement in a range-based "for" statement is + nonstandard in this mode + * - ``3031``\ + - | ``co_await_on_non_range_based_for``\ : + | co_await can only apply to a range-based "for" statement + * - ``3032``\ + - | ``cannot_deduce_type_in_range_based_for``\ : + | cannot deduce type of range in range-based "for" statement + * - ``3033``\ + - | ``inline_variables_nonstandard``\ : + | inline variables are a C++17 feature + * - ``3034``\ + - | ``destroying_delete_wrong_type``\ : + | destroying operator delete requires *"type"*\ as first parameter + * - ``3035``\ + - | ``destroying_delete_with_extra_params``\ : + | a destroying operator delete cannot have parameters other than + std::size_t and std::align_val_t + * - ``3036``\ + - | ``cl_relaxed_abstract_checking_only_in_cplusplus``\ : + | relaxed abstract class options can be used only when compiling C++ + * - ``3037``\ + - | ``invalid_start_of_requires_clause_expr``\ : + | invalid start of expression in requires clause + * - ``3038``\ + - | ``cast_in_requires_clause``\ : + | a cast expression in a requires-clause must be parenthesized + * - ``3039``\ + - | ``invalid_operator_in_requires_clause``\ : + | this operator cannot appear at the top level (without parentheses) in + a requires-clause + * - ``3040``\ + - | ``nonbool_atomic_constraint``\ : + | atomic constraint must have type bool + * - ``3041``\ + - | ``atomic_constraint_substitution_failed``\ : + | atomic constraint failed substitution + * - ``3042``\ + - | ``atomic_constraint_evaluation_failed``\ : + | atomic constraint not constant + * - ``3043``\ + - | ``atomic_constraint_false``\ : + | atomic constraint evaluates to false + * - ``3044``\ + - | ``template_constraint_not_satisfied``\ : + | template constraint not satisfied + * - ``3045``\ + - | ``bad_scope_for_concept``\ : + | concept definition cannot appear in this scope + * - ``3046``\ + - | ``invalid_concept_redecl``\ : + | invalid redeclaration of *entity-kind "entity"*\ (declared at line + *xxxx*\ ) + * - ``3047``\ + - | ``concept_arg_list_substitution_failed``\ : + | substitution of arguments *""*\ for concept-id failed + * - ``3048``\ + - | ``concept_failed``\ : + | concept is false for arguments *""*\ + * - ``3049``\ + - | ``trailing_requires_clause_not_on_template``\ : + | a requires-clause is not allowed here (not a templated function) + * - ``3051``\ + - | ``requires_incompatible_with_previous_decl``\ : + | requires-clause incompatible with *entity-kind "entity"*\ (declared + at line *xxxx*\ ) + * - ``3052``\ + - | ``expected_an_attribute``\ : + | expected an attribute + * - ``3054``\ + - | ``exp_type_name``\ : + | expected a type name + * - ``3055``\ + - | ``requires_expr_ellipsis_param``\ : + | an ellipsis parameter is not permitted in a requires-expression + * - ``3056``\ + - | ``unnamed_require_expr_param``\ : + | unnamed parameter in requires-expression has no effect + * - ``3057``\ + - | ``exp_concept_name``\ : + | expected a concept name + * - ``3058``\ + - | ``is_constant_evaluated_in_constant_expression``\ : + | call to *xxxx*\ appearing in a constant expression always produces + "true" + * - ``3059``\ + - | ``is_constant_evaluated_in_consteval_context``\ : + | call to *xxxx*\ appearing in a consteval context always produces + "true" + * - ``3060``\ + - | ``is_constant_evaluated_in_nonconstexpr_context``\ : + | call to *xxxx*\ appearing in a non-constexpr function always + produces "false" + * - ``3061``\ + - | ``type_constraint_failed``\ : + | type constraint failed for *"type"*\ + * - ``3062``\ + - | ``cl_export_template_option_incompatible_with_modules``\ : + | option "export" cannot be used in modes where C++ modules are enabled + * - ``3063``\ + - | ``glb_mod_fgmt_decl_must_come_first``\ : + | a global module fragment declaration must precede any other + declaration + * - ``3064``\ + - | ``module_decl_only_after_glb_mod``\ : + | a module declaration can only be preceded by a global module fragment + * - ``3065``\ + - | ``pvt_mod_fgmt_only_after_module``\ : + | a private module fragment must be preceded by a module declaration + * - ``3066``\ + - | ``cannot_export_fgmt``\ : + | a *xxxx*\ module fragment cannot be exported + * - ``3067``\ + - | ``more_than_one_module_decl``\ : + | cannot declare more than one module + * - ``3068``\ + - | ``more_than_one_fgmt_decl``\ : + | cannot declare more than one *xxxx*\ module fragment + * - ``3069``\ + - | ``module_req_primary_name``\ : + | a module must be declared with a non-empty name + * - ``3070``\ + - | ``header_not_importable``\ : + | *"xxxx"*\ is not an importable header + * - ``3071``\ + - | ``cannot_import_module_with_no_name``\ : + | cannot import a module with no name + * - ``3072``\ + - | ``module_cannot_depend_on_itself``\ : + | a module cannot have an interface dependency on itself + * - ``3073``\ + - | ``module_already_imported``\ : + | *module "module name"*\ has already been imported + * - ``3075``\ + - | ``module_file_not_found``\ : + | could not find module file for module *"xxxx"*\ + * - ``3076``\ + - | ``cannot_import_module``\ : + | could not import module file *"xxxx"*\ + * - ``3079``\ + - | ``unknown_ifc_partition``\ : + | unknown partition name *"xxxx"*\ + * - ``3085``\ + - | ``types_must_have_same_size``\ : + | the type of the second operand *"type"*\ must have the same size as + *"type"*\ + * - ``3086``\ + - | ``type_must_be_trivially_copyable``\ : + | type must be trivially copyable + * - ``3087``\ + - | ``unsupported_type_for_bit_cast``\ : + | type *"type"*\ is currently not supported for constexpr evaluation + of \__builtin_bit_cast + * - ``3088``\ + - | ``bitfields_not_allowed``\ : + | class types with bitfields *"type"*\ are not currently supported for + constexpr evaluation of \__builtin_bit_cast + * - ``3089``\ + - | ``reference_type_not_allowed``\ : + | non-static data member of reference type *"type"*\ prevents + constexpr evaluation of \__builtin_bit_cast + * - ``3090``\ + - | ``volatile_type_not_allowed``\ : + | a volatile type *"type"*\ prevents constexpr evaluation of + \__builtin_bit_cast + * - ``3091``\ + - | ``invalid_bit_cast_type``\ : + | a union, pointer, or pointer-to-member type *"type"*\ prevents + constexpr evaluation of \__builtin_bit_cast + * - ``3093``\ + - | ``deleted_inh_def_constructor``\ : + | the sub-object construction of *"type"*\ for inheriting constructors + cannot be performed -- the associated constructor is deleted + * - ``3094``\ + - | ``promise_type_returns_return_void``\ : + | *entity-kind "entity"*\ must return void + * - ``3095``\ + - | ``invalid_start_of_member_declaration``\ : + | invalid start of member declaration + * - ``3096``\ + - | ``exp_auto``\ : + | expected "auto" + * - ``3097``\ + - | ``operator_not_allowed_after_new``\ : + | this operator is not allowed at this point; parenthesize the + preceding new-expression + * - ``3098``\ + - | ``invalid_use_of_concept``\ : + | invalid use of concept + * - ``3099``\ + - | ``rvalue_defaulted_member_comparison``\ : + | a defaulted member comparison operator cannot be "&&"-qualified + * - ``3100``\ + - | ``constexpr_comparison_calls_nonconstexpr_function``\ : + | default constexpr comparison function calls non-constexpr function + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``3101``\ + - | ``invalid_constexpr_memcmp``\ : + | constexpr memory comparison is only supported for integer or + array-of-integer objects + * - ``3102``\ + - | ``constraint_concept_template``\ : + | a concept template cannot have associated constraints + * - ``3103``\ + - | ``export_not_allowed``\ : + | "export" is not allowed + * - ``3104``\ + - | ``export_class_members``\ : + | exporting individual class members is not allowed + * - ``3105``\ + - | ``export_must_introduce_name``\ : + | an exported declaration must introduce a name + * - ``3106``\ + - | ``export_cannot_contain_export``\ : + | an export declaration cannot contain an export declaration (previous + declaration at line *xxxx*\ ) + * - ``3107``\ + - | ``export_cannot_contain_import``\ : + | an export declaration cannot contain a module import declaration + * - ``3108``\ + - | ``export_only_in_modules``\ : + | an export declaration can only appear in a module interface unit + * - ``3109``\ + - | ``export_internal_linkage``\ : + | an export declaration cannot export a name with internal linkage + * - ``3112``\ + - | ``empty_requires_expression``\ : + | a requires-expression must specify at least one requirement + * - ``3113``\ + - | ``invalid_constinit``\ : + | "constinit" is not valid here + * - ``3114``\ + - | ``constinit_variable_storage``\ : + | "constinit" is only valid for declarations of variables with static + or thread storage duration + * - ``3115``\ + - | ``constinit_variable_has_dynamic_init``\ : + | constinit variable requires dynamic initialization + * - ``3116``\ + - | ``missing_constinit``\ : + | variable was previously declared with "constinit" at line *xxxx*\ + * - ``3117``\ + - | ``use_of_non_prototype_func_declarator``\ : + | use of non-prototype function declarator + * - ``3118``\ + - | ``cannot_be_const_qualified``\ : + | argument cannot have a const-qualified type + * - ``3119``\ + - | ``ptr_to_mem_of_incomplete_class``\ : + | a pointer-to-member of an incomplete type *"type"*\ is not allowed + * - ``3120``\ + - | ``pack_init_capture_not_enabled``\ : + | pack expansion in init-capture not enabled in this mode + * - ``3121``\ + - | ``pack_init_capture_is_cpp20``\ : + | pack expansion in init-capture is a C++20 feature + * - ``3122``\ + - | ``comparison_defaulted_in_class_must_be_first_decl``\ : + | a comparison operator defaulted in a class definition must be the + first declaration of that comparison operator (*entity-kind + "entity"*\ (declared at line *xxxx*\ )) + * - ``3123``\ + - | ``pack_init_capture_in_non_variadic_context``\ : + | a pack expansion in an init-capture can be used only in a variadic + template + * - ``3124``\ + - | ``type_constraint_requires_type_concept``\ : + | type constraint uses *entity-kind "entity"*\ (declared at line + *xxxx*\ ) that is not a type concept (i.e., a concept template whose + first parameter is a type parameter) + * - ``3125``\ + - | ``placeholder_type_failed_constraint``\ : + | the deduced placeholder type *"type"*\ failed the type constraint + * - ``3126``\ + - | ``ineligible_default_constructor``\ : + | default constructor for *"type"*\ is not eligible + * - ``3127``\ + - | ``ambiguous_destructor_constraints``\ : + | destructor for *"type"*\ is ambiguous because of unordered + constraints + * - ``3128``\ + - | ``failed_destructor_constraints``\ : + | destructor for *"type"*\ is ineligible because of failed constraints + * - ``3129``\ + - | ``destructor_position``\ : + | ambiguous destructor candidate + * - ``3130``\ + - | ``trailing_requires_on_virtual_func``\ : + | a virtual function cannot have a trailing requires clause + * - ``3131``\ + - | ``function_ineligible``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) does not satisfy + its constraints + * - ``3132``\ + - | ``bad_decltype_qualifier``\ : + | result of decltype qualifier *"type"*\ is not a class or enumeration + * - ``3133``\ + - | ``cpp20_reversed_comparison_ambiguity``\ : + | comparison is ambiguous in standard C++20 because the implied + comparison operator with reversed parameters is an equally good match + -- this is usually caused by a missing "const" qualifier on the + comparison operator; see *"entity"*\ (declared at line *xxxx*\ ) + * - ``3134``\ + - | ``invalid_concept_id``\ : + | invalid concept-id + * - ``3135``\ + - | ``requires_clause_arg_list_substitution_failed``\ : + | substitution of arguments *""*\ for requires-clause + failed + * - ``3136``\ + - | ``ineligible_member_function``\ : + | constraints for *entity-kind "entity"*\ (declared at line *xxxx*\ ) + are not satisfied + * - ``3137``\ + - | ``var_with_virtual_bases_in_constexpr_function``\ : + | variable type *"type"*\ in constexpr function has virtual base + classes + * - ``3138``\ + - | ``constexpr_object_with_virtual_base``\ : + | a constant expression cannot allocate a virtual base subobject (for + type *"type"*\ ) + * - ``3139``\ + - | ``template_parameter_has_nonstructural_class_type``\ : + | a template parameter of class type must be of structural class type + * - ``3140``\ + - | ``utf8_lit_no_ulit``\ : + | support for UTF-8 literals requires u-literal support. + * - ``3141``\ + - | ``duplicate_module_map``\ : + | module file mapping for "*xxxx*\ " specified more than once + * - ``3142``\ + - | ``duplicate_header_unit_map``\ : + | header unit mapping for "*xxxx*\ " specified more than once + * - ``3143``\ + - | ``missing_header_unit_map``\ : + | no mapping specified for "*xxxx*\ " + * - ``3145``\ + - | ``cannot_find_header_for_import``\ : + | cannot find header "*xxxx*\ " to import + * - ``3146``\ + - | ``multiple_module_matches``\ : + | more than one file in the module file list matches "*xxxx*\ " + * - ``3147``\ + - | ``module_file_mismatch``\ : + | module file found for "*xxxx*\ " is for a different module + * - ``3149``\ + - | ``module_read_error``\ : + | unable to read module file + * - ``3150``\ + - | ``builtin_needs_char8_t``\ : + | builtin function is not available because the char8_t type is not + supported with the current options + * - ``3152``\ + - | ``nonstandard_use_of_explicit_default_constructor``\ : + | nonstandard use of explicit constructor *"entity"*\ (declared at + line *xxxx*\ ) for default aggregate element initialization + * - ``3153``\ + - | ``constexpr_memcpy_operand_not_object``\ : + | source or destination of memcpy-like intrinsic does not point to an + object + * - ``3154``\ + - | ``constexpr_memcpy_distinct_types``\ : + | memcpy-like intrinsic attempts to copy representationally-distinct + types *"type"*\ and *"type"*\ + * - ``3155``\ + - | ``constexpr_memcpy_nontrivial_type``\ : + | memcpy-like intrinsic attempts to copy nontrivially-copyable type + *"type"*\ + * - ``3156``\ + - | ``constexpr_memcpy_partial_object``\ : + | memcpy-like intrinsic attempts to copy partial object + * - ``3157``\ + - | ``constexpr_memcpy_overflow``\ : + | memcpy-like intrinsic attempts to copy past array boundary + * - ``3158``\ + - | ``constexpr_memcpy_overlap``\ : + | memcpy-like intrinsic attempts to copy overlapping byte ranges (using + corresponding memmove operation instead) + * - ``3159``\ + - | ``nondefining_friend_requires_clause``\ : + | a friend declaration with a trailing-requires-clause must be a + definition + * - ``3160``\ + - | ``type_not_scalar``\ : + | expression must have arithmetic or pointer type but has type + *"type"*\ + * - ``3161``\ + - | ``type_not_arithmetic_or_enum_or_pointer``\ : + | expression must have arithmetic, enum, or pointer type but has type + *"type"*\ + * - ``3162``\ + - | ``type_not_arithmetic_or_unscoped_enum_or_pointer``\ : + | expression must have arithmetic, unscoped enum, or pointer type but + has type *"type"*\ + * - ``3163``\ + - | ``type_not_pointer``\ : + | expression must have pointer type but it has type *"type"*\ + * - ``3164``\ + - | ``member_access_requires_pointer``\ : + | operator -> or ->\* applied to *"type"*\ instead of to a pointer type + * - ``3166``\ + - | ``cannot_interpret_target_bits``\ : + | cannot interpret bit layout for this compilation target + * - ``3167``\ + - | ``ifc_no_corresponding_operator``\ : + | no corresponding operator for IFC operator *"xxxx"*\ + * - ``3168``\ + - | ``ifc_no_corresponding_calling_conv``\ : + | no corresponding calling convention for IFC calling convention + *"xxxx"*\ + * - ``3169``\ + - | ``module_file_contains_unsupported_constructs``\ : + | *module "module name"*\ contains unsupported constructs + * - ``3170``\ + - | ``unhandled_ifc_construct``\ : + | unsupported IFC construct: *"xxxx"*\ + * - ``3171``\ + - | ``is_signed_no_longer_a_keyword``\ : + | __is_signed is no longer a keyword from this point + * - ``3172``\ + - | ``dim_not_const_unsigned_int``\ : + | an array dimension must have a constant unsigned integer value + * - ``3174``\ + - | ``modules_not_enabled``\ : + | modules are not enabled in this mode + * - ``3175``\ + - | ``import_name_not_allowed``\ : + | "import" is not allowed in a module name + * - ``3176``\ + - | ``module_name_not_allowed``\ : + | "module" is not allowed in a module name + * - ``3179``\ + - | ``not_an_enum_type``\ : + | *entity-kind "entity"*\ is not an enum type + * - ``3180``\ + - | ``using_enum_conflicts``\ : + | enumerator *"entity"*\ conflicts with *entity-kind "entity"*\ + * - ``3181``\ + - | ``using_enum_redecl``\ : + | enumerator *"entity"*\ has already been declared in this scope at + line *xxxx*\ + * - ``3182``\ + - | ``empty_throw_specification_not_cpp20``\ : + | the "throw()" specification is not part of C++20 and later + * - ``3183``\ + - | ``multiple_header_map_matches``\ : + | more than entry in the header unit map matches "*xxxx*\ " + * - ``3184``\ + - | ``exp_push_pop``\ : + | #pragma diagnostic must have either 'push' or 'pop' argument + * - ``3185``\ + - | ``no_corresponding_push``\ : + | no '#pragma diagnostic push' was found to match this 'diagnostic pop' + * - ``3186``\ + - | ``macro_in_pp_directive``\ : + | *"xxxx"*\ cannot be a macro when used in an import or module + directive + * - ``3187``\ + - | ``not_global_namespace``\ : + | this directive can only appear in the global namespace scope + * - ``3188``\ + - | ``export_not_at_namespace_scope``\ : + | an "export" declaration can appear only at global or namespace scope + * - ``3189``\ + - | ``identifier_not_keyword``\ : + | *"xxxx"*\ is parsed as an identifier rather than a keyword because + the tokens that follow it do not match those of a preprocessor + directive + * - ``3190``\ + - | ``apparent_module_pp_directive``\ : + | this appears to be the start of a preprocessor directive, but the + lack of a ';' followed immediately by a newline prevents that + * - ``3191``\ + - | ``module_directive_in_macro``\ : + | this appears to be a modules preprocessing directive, but such + directives cannot appear within a macro expansion + * - ``3192``\ + - | ``module_directive_in_if``\ : + | a "module" directive cannot appear within the scope of conditional + inclusion (e.g., #if, #else, #elseif, etc.) + * - ``3193``\ + - | ``import_skipped``\ : + | the import of *"xxxx"*\ has been skipped + * - ``3194``\ + - | ``bad_gro_on_alloc_fail``\ : + | promise type *"type"*\ must declare + get_return_object_on_allocation_failure as a static member function + requiring no arguments + * - ``3195``\ + - | ``expl_spec_alias_template``\ : + | an alias template cannot be explicitly specialized + * - ``3196``\ + - | ``matching_lbrace``\ : + | to match this "{" + * - ``3197``\ + - | ``macro_invocation``\ : + | in this macro invocation + * - ``3198``\ + - | ``call_with_unusable_argument_conversion``\ : + | call requires an ambiguous argument conversion + * - ``3199``\ + - | ``named_module_source_conflict``\ : + | declaration owned by module *xxxx*\ conflicts with *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``3200``\ + - | ``global_module_source_conflict``\ : + | declaration owned by global module conflicts with *entity-kind + "entity"*\ (declared at line *xxxx*\ ) owned by a named module + * - ``3201``\ + - | ``bad_malloc_attribute``\ : + | the first argument to a "malloc" attribute must be a function + * - ``3202``\ + - | ``cannot_capture_var``\ : + | cannot capture *"entity"*\ (declared at line *xxxx*\ ) + * - ``3203``\ + - | ``cannot_capture_this``\ : + | cannot capture "this" + * - ``3204``\ + - | ``already_in_consteval_context``\ : + | already in consteval context + * - ``3205``\ + - | ``if_consteval_requires_braced_dependent_statement``\ : + | "if consteval" and "if not consteval" require braced dependent + statements + * - ``3206``\ + - | ``if_consteval_in_nonconstexpr_function``\ : + | "if consteval" and "if not consteval" are meaningless in a + non-constexpr function + * - ``3207``\ + - | ``branch_into_if_consteval``\ : + | transfer of control into an "if consteval" or "if not consteval" + statement is not allowed + * - ``3208``\ + - | ``constexpr_local_static``\ : + | constant-evaluation cannot go through the declaration of a variable + with static or thread storage duration + * - ``3209``\ + - | ``mutable_qualifier_on_explicit_this_lambda``\ : + | the mutable qualifier is not allowed on a lambda with an explicit + "this" parameter + * - ``3210``\ + - | ``static_with_explicit_this``\ : + | a member function declared with "static" cannot have an explicit + "this" parameter + * - ``3211``\ + - | ``explicit_this_param_must_be_first``\ : + | an explicit "this" parameter must be the first declared parameter + * - ``3212``\ + - | ``bad_this``\ : + | "this" is not allowed here + * - ``3214``\ + - | ``explicit_this_needs_this``\ : + | an explicit "this" function requires a selector operand + * - ``3215``\ + - | ``if_consteval_nonstandard``\ : + | "if consteval" and "if not consteval" are not standard in this mode + * - ``3216``\ + - | ``lambda_without_parameters_nonstandard``\ : + | omitting "()" in a lambda declarator is nonstandard in this mode + * - ``3217``\ + - | ``lambda_without_parameters_requires_clause``\ : + | a trailing-requires-clause is not permitted when the lambda parameter + list is omitted + * - ``3218``\ + - | ``invalid_ifc_partition``\ : + | *module "module name"*\ invalid partition requested + * - ``3219``\ + - | ``undefined_ifc_partition``\ : + | *module "module name"*\ undefined partition (believed to be + *"xxxx"*\ ) requested + * - ``3222``\ + - | ``invalid_overflowing_ifc_position``\ : + | *module "module name"*\ file position *n*\ (relative position + *n*\ ) requested for partition *"xxxx"*\ - which overflows the end + of its partition + * - ``3223``\ + - | ``invalid_misaligned_ifc_position``\ : + | *module "module name"*\ file position *n*\ (relative position + *n*\ ) requested for partition *"xxxx"*\ - which is misaligned with + its partitions elements + * - ``3224``\ + - | ``invalid_ifc_position_backtrace_field``\ : + | from subfield *"xxxx"*\ (relative position to node *n*\ ) + * - ``3225``\ + - | ``invalid_ifc_position_backtrace_pos``\ : + | from partition *"xxxx"*\ element *n*\ (file position *n*\ , + relative position *n*\ ) + * - ``3226``\ + - | ``nonstandard_lambda_attributes``\ : + | attributes on lambdas are a C++23 feature + * - ``3227``\ + - | ``confusable_identifier``\ : + | identifier *"xxxx"*\ could be confused with a visually-similar one + appearing at line *xxxx*\ + * - ``3228``\ + - | ``suspicious_comment_formatting``\ : + | this comment contains suspicious Unicode formatting control characters + * - ``3229``\ + - | ``suspicious_string_formatting``\ : + | this string contains Unicode formatting control characters that could + result in unexpected runtime behavior + * - ``3230``\ + - | ``suppressed_module_warning_diag``\ : + | *n*\ suppressed warning was encountered while processing *module + "module name"*\ + * - ``3231``\ + - | ``suppressed_module_warnings_diag``\ : + | *n*\ suppressed warnings were encountered while processing *module + "module name"*\ + * - ``3232``\ + - | ``suppressed_module_error_diag``\ : + | *n*\ suppressed error was encountered while processing *module + "module name"*\ + * - ``3233``\ + - | ``suppressed_module_errors_diag``\ : + | *n*\ suppressed errors were encountered while processing *module + "module name"*\ + * - ``3236``\ + - | ``virtual_with_explicit_this``\ : + | a virtual member function cannot have an explicit "this" parameter + * - ``3237``\ + - | ``address_of_unqualified_explicit_this_function``\ : + | taking the address of an explicit "this" function requires a + qualified name + * - ``3238``\ + - | ``implicit_address_of_explicit_this_function``\ : + | forming the address of an explicit "this" function requires the "&" + operator + * - ``3239``\ + - | ``string_literal_cannot_initialize_flexible_array_member``\ : + | a string literal cannot be used to initialize a flexible array member + * - ``3246``\ + - | ``ifc_missing_function_definition``\ : + | the IFC representation of the definition of function *"xxxx"*\ is + missing + * - ``3247``\ + - | ``member_function_modifier_on_template``\ : + | function modifier does not apply to member template declaration + * - ``3248``\ + - | ``constexpr_too_many_nested_anonymous_types``\ : + | member selection involves too many nested anonymous types + * - ``3249``\ + - | ``no_common_type``\ : + | there is no common type between the operands + * - ``3250``\ + - | ``exp_pointer_to_member``\ : + | expected a pointer-to-member + * - ``3251``\ + - | ``lone_flexible_array_member``\ : + | a flexible array member cannot be declared in an otherwise-empty type + * - ``3252``\ + - | ``missing_gnu_srcloc_type``\ : + | expected "std::source_location::\__impl" to be defined to a class + with only the data members "_M_function_name", "_M_file_name", + "_M_column", "_M_line" + * - ``3253``\ + - | ``srcloc_column_bounds``\ : + | given column number is too large for "std::source_location" + implementation + * - ``3254``\ + - | ``srcloc_line_bounds``\ : + | given line number is too large for "std::source_location" + implementation + * - ``3255``\ + - | ``utf16_char_lit_too_long``\ : + | a UTF-16 character constant cannot occupy more than one code unit; + value truncated + * - ``3256``\ + - | ``both_arguments_must_have_same_type``\ : + | both arguments must have the same type + * - ``3257``\ + - | ``invalid_type_for_builtin``\ : + | type *"type"*\ is invalid as an argument for this builtin + * - ``3258``\ + - | ``constexpr_called_from_rout``\ : + | called from *entity-kind "entity"*\ (declared at line *xxxx*\ ): + * - ``3259``\ + - | ``qualified_unnamed_bit_field_type``\ : + | a qualified type is nonstandard for anonymous bit fields + * - ``3260``\ + - | ``bad_vector_conditional_size``\ : + | the element type of the vector condition (*"type"*\ ) must have the + same size as the element type of the result (*"type"*\ ) + * - ``3261``\ + - | ``bad_vector_float_operand_size``\ : + | the floating-point vector operand type (*"type"*\ ) has no matching + integer vector type + * - ``3262``\ + - | ``mangling_for_requires``\ : + | mangling for "requires" expressions is not yet implemented + * - ``3263``\ + - | ``unavailable_attr``\ : + | because of an "unavailable" attribute + * - ``3264``\ + - | ``duplicate_asm_qualifier``\ : + | duplicate 'asm' qualifier + * - ``3265``\ + - | ``incomplete_enum_bit_field_or_bad_opaque_enum``\ : + | either a bit field with an incomplete enum type or an opaque + enumeration with an invalid base type + * - ``3266``\ + - | ``ifc_partition_mismatch``\ : + | attempted to construct an element from IFC partition *"xxxx"*\ using + an index into IFC partition *"xxxx"*\ + * - ``3267``\ + - | ``ifc_partition_bad_entry_size``\ : + | the partition *"xxxx"*\ specified its entry size as *n*\ when *n*\ + was expected + * - ``3268``\ + - | ``ifc_requirement_failure``\ : + | an unexpected IFC requirement was encountered while processing + *module "module name"*\ + * - ``3269``\ + - | ``ifc_requirement_failure_fill_in``\ : + | condition failed at line *n*\ in *xxxx*\ : *"xxxx"*\ + * - ``3270``\ + - | ``circular_constraint``\ : + | atomic constraint depends on itself + * - ``3271``\ + - | ``noreturn_with_return_type``\ : + | "noreturn" function has non-void return type + * - ``3272``\ + - | ``ifc_bad_function_param_name``\ : + | a correction has been made by dropping the parameter *"xxxx"*\ (at + relative index *n*\ ) + * - ``3273``\ + - | ``default_arg_on_member_template_def``\ : + | a default template argument cannot be specified on the definition of + a member template outside its class + * - ``3274``\ + - | ``ifc_bad_identifier``\ : + | invalid IFC identifier name *"xxxx"*\ encountered during entity + reconstruction + * - ``3276``\ + - | ``invalid_ifc_sort_value``\ : + | *module "module name"*\ invalid sort value + * - ``3277``\ + - | ``ifc_function_template_parse_failure``\ : + | a function template loaded from an IFC module was incorrectly parsed + as *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``3278``\ + - | ``ifc_entity_ref_failure``\ : + | failed to load an IFC entity reference in *module "module name"*\ + * - ``3279``\ + - | ``ifc_entity_ref_failure_info``\ : + | from partition *"xxxx"*\ element *n*\ (file position *n*\ , + relative position *n*\ ) + * - ``3280``\ + - | ``no_chained_designators_with_destructor``\ : + | chained designators are not permitted for a class type with a + nontrivial destructor + * - ``3281``\ + - | ``explicit_specialization_friend``\ : + | an explicit specialization declaration may not be a friend declaration + * - ``3282``\ + - | ``std_float128_not_supported``\ : + | the std::float128_t type is not supported; std::float64_t will be + used instead + * - ``3284``\ + - | ``alias_template_deduction_guide``\ : + | a deduction guide may not be declared for alias template *"entity"*\ + * - ``3285``\ + - | ``unavailable_entity``\ : + | *entity-kind "entity"*\ was declared declared unavailable + * - ``3286``\ + - | ``unavailable_entity_with_custom_message``\ : + | *entity-kind "entity"*\ was declared unavailable (*"xxxx"*\ ) + * - ``3287``\ + - | ``deprecated_attr``\ : + | because of a "deprecated" attribute + * - ``3288``\ + - | ``explicit_lambda_template_parameters_is_cpp20``\ : + | explicit lambda template parameters are a C++20 feature + * - ``3289``\ + - | ``c23_noreturn_deprecated``\ : + | the use of "_Noreturn" has been obsoleted in C23; use "[[noreturn]]" + instead + * - ``3290``\ + - | ``c23_alignof_deprecated``\ : + | the use of "_Alignof" has been obsoleted in C23; use "alignof" instead + * - ``3291``\ + - | ``c23_alignas_deprecated``\ : + | the use of "_Alignas" has been obsoleted in C23; use "alignas" instead + * - ``3292``\ + - | ``c23_bool_deprecated``\ : + | the use of "_Bool" has been obsoleted in C23; use "bool" instead + * - ``3293``\ + - | ``c23_static_assert_deprecated``\ : + | the use of "_Static_assert" has been obsoleted in C23; use + "static_assert" instead + * - ``3294``\ + - | ``c23_thread_local_deprecated``\ : + | the use of "_Thread_local" has been obsoleted in C23; use + "thread_local" instead + * - ``3295``\ + - | ``ms_ifc_unavailable``\ : + | Microsoft mode must be enabled to use the module file *"xxxx"*\ (a + Microsoft Visual Studio IFC module) + * - ``3296``\ + - | ``file_for_module_not_found``\ : + | could not open module file *"xxxx"*\ + * - ``3297``\ + - | ``found_from_module_map``\ : + | found in the module map for module *"xxxx"*\ + * - ``3298``\ + - | ``found_from_header_unit_map``\ : + | found in the header unit map for *"xxxx"*\ + * - ``3299``\ + - | ``cl_invalid_output_mode``\ : + | unrecognized output mode (must be one of text, sarif): *xxxx*\ + * - ``3300``\ + - | ``cl_c23_typeof_option_only_in_C``\ : + | option "c23_typeof" can be used only when compiling C + * - ``3301``\ + - | ``cl_invalid_clang_version``\ : + | invalid clang version number: *xxxx*\ + * - ``3305``\ + - | ``constexpr_flexible_array_initializer``\ : + | cannot evaluate an initializer for a flexible array member + * - ``3306``\ + - | ``nonstandard_bit_field_initializer``\ : + | a default bit-field initializer is a C++20 feature + * - ``3307``\ + - | ``ifc_too_many_template_args``\ : + | too many arguments in template argument list in *module "module + name"*\ + * - ``3308``\ + - | ``ifc_too_many_template_args_info``\ : + | detected for the template argument represented by *"xxxx"*\ element + *n*\ (file position *n*\ , relative position *n*\ ) + * - ``3309``\ + - | ``ifc_too_few_template_args``\ : + | too few arguments in template argument list in *module "module + name"*\ + * - ``3310``\ + - | ``ifc_too_few_template_args_info``\ : + | detected while processing the template argument list represented by + *"xxxx"*\ element *n*\ (file position *n*\ , relative position + *n*\ ) + * - ``3311``\ + - | ``nonstandard_conversion_from_scoped_enum``\ : + | conversion from scoped enumeration type *"type"*\ is nonstandard + * - ``3312``\ + - | ``constexpr_allocation_mismatch``\ : + | deallocation does not match allocation kind (one is for an array and + the other not) + * - ``3313``\ + - | ``constexpr_address_unknown``\ : + | comparison involves unknown address (e.g., the address of a weak + variable) + * - ``3314``\ + - | ``bad_argument_to_make_signed``\ : + | __make_signed is only compatible with non-bool integer and enum types + * - ``3315``\ + - | ``bad_argument_to_make_unsigned``\ : + | __make_unsigned is only compatible with non-bool integer and enum + types + * - ``3316``\ + - | ``intrinsic_name_released``\ : + | the intrinsic name *"xxxx"*\ will be treated as an ordinary + identifier from here + * - ``3317``\ + - | ``array_subobject_not_initialized``\ : + | access to uninitialized subobject at index *n*\ + * - ``3318``\ + - | ``ifc_line_number_overflow``\ : + | IFC line number (*n*\ ) overflows maximum allowed value (*n*\ ) + *module "module name"*\ + * - ``3319``\ + - | ``invalid_unrepresentable_ifc_position``\ : + | *module "module name"*\ requested element *n*\ of partition + *"xxxx"*\ , this file position exceeds the maximum representable value + * - ``3320``\ + - | ``wrong_number_of_arguments``\ : + | wrong number of arguments + * - ``3321``\ + - | ``candidate_failed_constraint``\ : + | constraint on candidate *entity-kind "entity"*\ not satisfied + * - ``3322``\ + - | ``candidate_wrong_param_count``\ : + | number of parameters of *entity-kind "entity"*\ does not match the + call + * - ``3323``\ + - | ``candidate_expl_templ_arg_subst_failed``\ : + | substituting explicit template arguments *""*\ for + *entity-kind "entity"*\ failed + * - ``3324``\ + - | ``impl_deleted_move_candidate_ignored``\ : + | *entity-kind "entity"*\ is an implicitly "= delete" move function + and thus ignored during overload resolution + * - ``3325``\ + - | ``arg_for_empty_param_pack``\ : + | *entity-kind "entity"*\ does not match because argument #*n*\ is + provided for an empty parameter pack + * - ``3326``\ + - | ``nonviable_because_arg_mismatch``\ : + | *entity-kind "entity"*\ does not match because argument #*n*\ does + not match parameter + * - ``3327``\ + - | ``deduction_failed``\ : + | candidate *entity-kind "entity"*\ failed deduction + * - ``3328``\ + - | ``builtin_operator_nonviable_because_arg_mismatch``\ : + | built-in operator*xxxx*\ does not match because argument #*n*\ does + not match parameter + * - ``3329``\ + - | ``integral_operand``\ : + | + * - ``3330``\ + - | ``promoted_integral_operand``\ : + | + * - ``3331``\ + - | ``ptrdiff_t_operand``\ : + | + * - ``3332``\ + - | ``enum_operand``\ : + | + * - ``3333``\ + - | ``scoped_enum_operand``\ : + | + * - ``3334``\ + - | ``arith_operand``\ : + | + * - ``3335``\ + - | ``promoted_arith_operand``\ : + | + * - ``3336``\ + - | ``nonbool_arith_operand``\ : + | + * - ``3337``\ + - | ``pointer_operand``\ : + | + * - ``3338``\ + - | ``nullptr_operand``\ : + | + * - ``3339``\ + - | ``handle_operand``\ : + | + * - ``3340``\ + - | ``handle_to_cli_array_operand``\ : + | + * - ``3341``\ + - | ``pointer_to_object_operand``\ : + | + * - ``3342``\ + - | ``pointer_to_function_operand``\ : + | + * - ``3343``\ + - | ``ptr_to_member_operand``\ : + | + * - ``3344``\ + - | ``bool_operand``\ : + | + * - ``3345``\ + - | ``bool_equivalent_operand``\ : + | + * - ``3346``\ + - | ``class_operand``\ : + | + * - ``3347``\ + - | ``auto_cast_is_cpp23``\ : + | auto() and auto{} are a C++23 feature + * - ``3348``\ + - | ``anon_union_using_declaration``\ : + | invalid anonymous union -- using declaration is not allowed + * - ``3349``\ + - | ``ifc_file_incompatibility``\ : + | IFC file *"xxxx"*\ cannot be processed + * - ``3350``\ + - | ``unsupported_ifc_file_version_info``\ : + | IFC version *n*\ .*n*\ is not supported + * - ``3351``\ + - | ``unsupported_ifc_file_arch_info``\ : + | IFC architecture *"xxxx"*\ is incompatible with the current target + architecture + * - ``3352``\ + - | ``unknown_ifc_partition_conversion``\ : + | *module "module name"*\ requests index *n*\ of an unsupported + partition corresponding to *"xxxx"*\ + * - ``3353``\ + - | ``param_cannot_be_completed``\ : + | parameter number *n*\ of *entity-kind "entity"*\ has type + *"type"*\ which cannot be completed + * - ``3354``\ + - | ``param_is_incomplete``\ : + | parameter number *n*\ of *entity-kind "entity"*\ has incomplete + type *"type"*\ + * - ``3355``\ + - | ``param_is_abstract``\ : + | parameter number *n*\ of *entity-kind "entity"*\ has abstract type + *"type"*\ + * - ``3356``\ + - | ``struct_bindings_is_cpp17``\ : + | structured bindings are a C++17 feature + * - ``3357``\ + - | ``capturing_struct_bindings_is_cpp20``\ : + | capturing structured bindings is a C++20 feature + * - ``3358``\ + - | ``bad_splicer_operand``\ : + | operand of splicer has type *"type"*\ instead of std::meta::info + * - ``3359``\ + - | ``not_a_type_reflection``\ : + | operand (reflection for *reflection-description*\ ) is not the + reflection of a type + * - ``3360``\ + - | ``nonconstant_splicer_operand``\ : + | nonconstant operand of splicer + * - ``3361``\ + - | ``bad_std_string_view``\ : + | use of *"type"*\ instead of std::string_view (= + std::basic_string_view) + * - ``3362``\ + - | ``inconsistent_std_string_view``\ : + | std::string_view used here is inconsistent with use in other + intrinsics + * - ``3363``\ + - | ``invalid_std_string_view_for_reflection``\ : + | definition of std::string_view does not match assumptions of + reflection (no base classes and data members for pointer and length) + * - ``3364``\ + - | ``constexpr_reflection_not_of_constant``\ : + | reflection is not that of a constant value + * - ``3368``\ + - | ``bad_reflection_kind_for_expression_splice``\ : + | bad reflection (*reflection-description*\ ) for expression splice + * - ``3369``\ + - | ``already_defined_with_pos``\ : + | *entity-kind "entity"*\ has already been defined (previous + definition at line *xxxx*\ ) + * - ``3371``\ + - | ``incompatible_std_meta_value_of_type``\ : + | extract of type *"type"*\ is not compatible with the given + reflection (entity with type *"type"*\ ) + * - ``3372``\ + - | ``reflection_of_overloaded_set``\ : + | reflecting an overload set is not currently permitted + * - ``3373``\ + - | ``intrinsic_requires_template_instance``\ : + | this intrinsic requires a reflection for a template instance + * - ``3374``\ + - | ``invalid_reflection_equality``\ : + | incompatible types *"type"*\ and *"type"*\ for operator + * - ``3375``\ + - | ``invalid_reflection_for_intrinsic``\ : + | invalid reflection for intrinsic metafunction + * - ``3376``\ + - | ``nonmember_reflection_for_intrinsic``\ : + | intrinsic metafunction requires a reflection for a class member + * - ``3377``\ + - | ``union_base``\ : + | a class cannot not derive from a union + * - ``3378``\ + - | ``base_with_flexible_array``\ : + | cannot derive from a class with a flexible array member + * - ``3379``\ + - | ``null_reflection``\ : + | null reflection + * - ``3380``\ + - | ``namespace_alias``\ : + | namespace alias + * - ``3381``\ + - | ``unspecified_reflection``\ : + | reflection (details unavailable) + * - ``3382``\ + - | ``std_meta_substitute_bad_arg_reflection``\ : + | bad reflection (*reflection-description*\ ) for template argument in + std::meta::substitute + * - ``3383``\ + - | ``std_meta_substitute_failed``\ : + | call to std::meta::substitute (for *reflection-description*\ ) failed + * - ``3384``\ + - | ``expired_reflection_value``\ : + | reflection value refers to inactive entity + * - ``3385``\ + - | ``cannot_splice_general_expression``\ : + | an expression splice must splice a constant value, a variable, or a + function + * - ``3386``\ + - | ``cannot_splice_member_access``\ : + | a member access splice must splice a data member or a member function + * - ``3387``\ + - | ``splice_is_not_a_member_of_class``\ : + | member *entity-kind "entity"*\ (declared at line *xxxx*\ ) is not a + direct or indirect member of *"type"*\ + * - ``3388``\ + - | ``unicode_name_not_found``\ : + | the name *"xxxx"*\ does not designate a known Unicode character + * - ``3389``\ + - | ``unterminated_unicode_name``\ : + | unterminated named Unicode character escape + * - ``3390``\ + - | ``invalid_char_in_unicode_name``\ : + | character cannot appear in a Unicode name + * - ``3391``\ + - | ``empty_unicode_name``\ : + | empty named Unicode character escape + * - ``3392``\ + - | ``exp_lsplice``\ : + | expected a "[:" + * - ``3393``\ + - | ``exp_rsplice``\ : + | expected a ":]" + * - ``3394``\ + - | ``lambda_mutable_and_static``\ : + | a lambda expression cannot be both "mutable" and "static" + * - ``3395``\ + - | ``static_lambda_nonstandard``\ : + | a "static" lambda expression is nonstandard + * - ``3396``\ + - | ``static_lambda_with_capture``\ : + | a "static" lambda expression must have an empty capture specification + * - ``3399``\ + - | ``ifc_creation_failure``\ : + | an IFC file could not be produced for the current translation unit + * - ``3400``\ + - | ``unsupported_il_to_ifc``\ : + | one or more entities cannot currently be written to an IFC file + * - ``3401``\ + - | ``nonstandard_explicit_bool``\ : + | 'explicit(bool)' is a C++20 feature + * - ``3402``\ + - | ``bad_type_for_atomic_fetch``\ : + | first argument must be a pointer to integer, enum, or supported + floating-point type + * - ``3403``\ + - | ``module_use_in_multi_tu_mode``\ : + | C++ modules cannot be used when compiling multiple translation units + * - ``3404``\ + - | ``module_use_with_export_template``\ : + | C++ modules cannot be used with the pre-C++11 "export" feature + * - ``3405``\ + - | ``ifc_unsupported_token``\ : + | the IFC token *"xxxx"*\ is not supported + * - ``3406``\ + - | ``pass_object_size_not_in_function_decl``\ : + | the "pass_object_size" attribute is only valid on parameters of + function declarations + * - ``3407``\ + - | ``attr_arg_out_of_small_integer_range``\ : + | the argument of the *"xxxx"*\ attribute *n*\ must be a value + between 0 and *n*\ + * - ``3408``\ + - | ``ref_qualifier_ignored``\ : + | a ref-qualifier here is ignored + * - ``3409``\ + - | ``invalid_neon_vector_element_type``\ : + | invalid NEON vector element type *"type"*\ + * - ``3410``\ + - | ``invalid_neon_polyvector_element_type``\ : + | invalid NEON polyvector element type *"type"*\ + * - ``3411``\ + - | ``invalid_scalable_vector_element_type``\ : + | invalid scalable vector element type *"type"*\ + * - ``3412``\ + - | ``invalid_scalable_vector_tuple_elements``\ : + | invalid number of tuple elements for scalable vector type + * - ``3413``\ + - | ``invalid_neon_vector_size``\ : + | a NEON vector or polyvector must be either 64 or 128 bits wide + * - ``3414``\ + - | ``sizeless_type_not_allowed``\ : + | sizeless type *"type"*\ is not allowed + * - ``3415``\ + - | ``value_init_of_sizeless_type``\ : + | an object of the sizeless type *"type"*\ cannot be value-initialized + * - ``3416``\ + - | ``ifc_unexpected_null_scope_member``\ : + | unexpected null declaration index found as part of scope *n*\ + * - ``3417``\ + - | ``cl_unnamed_module_map``\ : + | a module name must be specified for the module file map referencing + the file *"xxxx"*\ + * - ``3418``\ + - | ``ifc_partition_missing_element``\ : + | a null index value was received where a node in the IFC partition + *"xxxx"*\ was expected + * - ``3419``\ + - | ``void_template_variable``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot have type + *"type"*\ + * - ``3420``\ + - | ``ref_qualifier_nonstandard``\ : + | a ref-qualifier is nonstandard in this mode + * - ``3421``\ + - | ``range_based_for_nonstandard``\ : + | a range-based "for" statement is nonstandard in this mode + * - ``3422``\ + - | ``auto_type_nonstandard``\ : + | "auto" as a type specifier is nonstandard in this mode + * - ``3423``\ + - | ``cannot_import_module_bad_checksum``\ : + | could not import module file *"xxxx"*\ due to file corruption + * - ``3425``\ + - | ``extraneous_injected_member_tokens``\ : + | extraneous tokens injected after member declaration + * - ``3426``\ + - | ``bad_injection_scope``\ : + | bad injection scope (*reflection-description*\ ) + * - ``3427``\ + - | ``expected_string_view_value``\ : + | expected a value of type std::string_view but got *"type"*\ + * - ``3428``\ + - | ``extraneous_injected_statement_tokens``\ : + | extraneous tokens injected after statement + * - ``3429``\ + - | ``extraneous_injected_declaration_tokens``\ : + | extraneous tokens injected after declaration + * - ``3430``\ + - | ``tuple_index_overflow``\ : + | tuple index value (*n*\ ) overflow + * - ``3431``\ + - | ``constexpr_begin_report_tokens``\ : + | >> output from std::meta::\__report_tokens + * - ``3432``\ + - | ``constexpr_end_report_tokens``\ : + | >> end output from std::meta::\__report_tokens + * - ``3433``\ + - | ``constexpr_no_current_parameters``\ : + | not in a context with parameter variables + * - ``3434``\ + - | ``empty_delimited_escape``\ : + | a delimited escape sequence must have at least one character + * - ``3435``\ + - | ``unterminated_delimited_escape``\ : + | unterminated delimited escape sequence + * - ``3436``\ + - | ``constant_addresses_local_variable``\ : + | constant contains address of a local variable + * - ``3437``\ + - | ``struct_binding_consteval``\ : + | a structured binding cannot be declared "consteval" + * - ``3438``\ + - | ``module_import_conflict``\ : + | *"entity"*\ conflicts with the imported declaration *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``3439``\ + - | ``char_too_wide_for_rep``\ : + | character cannot be represented in the specified character type + * - ``3440``\ + - | ``annotation_after_using``\ : + | an annotation cannot appear in the context of a "using" attribute + prefix + * - ``3441``\ + - | ``annotation_must_have_literal_type``\ : + | type *"type"*\ of annotation is not a literal type + * - ``3442``\ + - | ``ext_vector_type_requires_bool_integral_floating_type``\ : + | the "ext_vector_type" attribute applies only to bool, integer, or + floating-point types + * - ``3443``\ + - | ``multiple_union_designators``\ : + | multiple designators into the same union are not permitted + * - ``3444``\ + - | ``debug_show_location``\ : + | test message + * - ``3445``\ + - | ``microsoft_version_doesnt_support_cpp23_mode``\ : + | the version of Microsoft being emulated must be at least 1943 to use + "--ms_c++23" + * - ``3446``\ + - | ``cl_invalid_cwd``\ : + | invalid current working directory: *xxxx*\ + * - ``3447``\ + - | ``cleanup_attribute_in_constexpr_function``\ : + | "cleanup" attribute within a constexpr function is not currently + supported + * - ``3448``\ + - | ``assume_statement_applies_to_null_statements``\ : + | the "assume" attribute can only apply to a null statement + * - ``3449``\ + - | ``assumption_failed``\ : + | assumption failed + * - ``3450``\ + - | ``variable_templates_is_cpp14``\ : + | variable templates are a C++14 feature + * - ``3451``\ + - | ``address_of_function_with_pass_object_size_attr``\ : + | cannot take the address of a function with a parameter declared with + the "pass_object_size" attribute + * - ``3452``\ + - | ``all_arguments_must_have_same_type``\ : + | all arguments must have the same type + * - ``3453``\ + - | ``comparison_details``\ : + | the final comparison was *xxxx*\ *xxxx*\ *xxxx*\ + * - ``3454``\ + - | ``too_many_arguments_provided_for_attribute``\ : + | too many arguments for attribute *"xxxx"*\ + * - ``3455``\ + - | ``constexpr_bad_mantissa_string``\ : + | mantissa string does not contain a valid number + * - ``3456``\ + - | ``constexpr_float_error``\ : + | floating-point error during constant evaluation + * - ``3457``\ + - | ``inheriting_ctor_ignored_for_copy``\ : + | inheriting constructor *entity-kind "entity"*\ ignored for + copy/move-like operation + * - ``3458``\ + - | ``cannot_get_file_size``\ : + | cannot determine size of file *xxxx*\ + * - ``3459``\ + - | ``cannot_read_file``\ : + | cannot read *xxxx*\ + * - ``3461``\ + - | ``unrec_embed_param``\ : + | unrecognized parameter name + * - ``3462``\ + - | ``dupl_embed_param``\ : + | parameter specified more than once + * - ``3463``\ + - | ``has_embed_not_in_if``\ : + | __has_embed cannot appear outside #if + * - ``3464``\ + - | ``setlocale_lc_numeric_failed``\ : + | could not set LC_NUMERIC locale to C + * - ``3465``\ + - | ``elifdef_not_enabled``\ : + | elifdef and elifndef are not enabled in this mode and are ignored in + text being skipped + * - ``3466``\ + - | ``nonstandard_alias_declaration_context``\ : + | an alias declaration is nonstandard in this context + * - ``3467``\ + - | ``out_of_order_field_allocation_nonstandard``\ : + | the target ABI may allocate nonstatic members in an order not + matching their declaration order, which is nonstandard in C++23 and + later + * - ``3470``\ + - | ``module_unit_export_unexpected``\ : + | the module declaration cannot be exported from this translation unit + unless creating a module interface file + * - ``3471``\ + - | ``module_unit_export_expected``\ : + | the module declaration must be exported from this translation unit to + create a module interface file + * - ``3472``\ + - | ``cannot_write_module_none_declared``\ : + | module file generation was requested but no module was declared in + the translation unit + * - ``3473``\ + - | ``candidate_constraints_failed``\ : + | substituting *""*\ for *entity-kind "entity"*\ failed + constraints + * - ``3474``\ + - | ``concept_not_satisfied``\ : + | *entity-kind "entity"*\ not satisfied for *""*\ + * - ``3475``\ + - | ``bad_embed_initializer``\ : + | the #embed expansion is too long to initialize an entity of type + *"type"*\ + * - ``3476``\ + - | ``bad_defined_pp_op``\ : + | the "defined" operator is not permitted here + * - ``3477``\ + - | ``ptr_to_mem_to_non_member``\ : + | *entity-kind "entity"*\ is not a member of *"type"*\ + * - ``3478``\ + - | ``embed_narrowing``\ : + | narrowing conversion to signed character in #embed data + * - ``3479``\ + - | ``invalid_vector_of_bool_operator``\ : + | operator is not permitted for "vector of bool" types + * - ``3480``\ + - | ``constexpr_object_too_large``\ : + | object too large for constant-evaluation + * - ``3481``\ + - | ``self_referencing_temporary_object``\ : + | self-referencing temporary object + * - ``3482``\ + - | ``lambda_cannot_refer_to_local_entity_here``\ : + | a lambda cannot refer to a local variable or init-capture in this + context + * - ``3483``\ + - | ``parameter_capture_conflict``\ : + | a lambda parameter cannot hide an explicit capture + * - ``3484``\ + - | ``template_parameter_capture_conflict``\ : + | a lambda template parameter cannot hide an explicit capture + * - ``3485``\ + - | ``insufficient_address_space``\ : + | insufficient address space exists to process this translation unit + * - ``3486``\ + - | ``undetermined_type``\ : + | + * - ``3487``\ + - | ``undetermined_constant``\ : + | + * - ``3488``\ + - | ``undetermined_template``\ : + | + * - ``3489``\ + - | ``bad_flt_config``\ : + | the configured size of *xxxx*\ is too small for the specified number + of mantissa + exponent bits + * - ``3490``\ + - | ``expression``\ : + | expression + * - ``3491``\ + - | ``quoted_expression``\ : + | + * - ``3492``\ + - | ``unnamed``\ : + | unnamed + * - ``3493``\ + - | ``quoted_unnamed``\ : + | + * - ``3494``\ + - | ``error_type``\ : + | + * - ``3495``\ + - | ``unknown_type``\ : + | + * - ``3496``\ + - | ``something``\ : + | + * - ``3497``\ + - | ``null_type``\ : + | + * - ``3498``\ + - | ``no_init``\ : + | + * - ``3499``\ + - | ``zero_init``\ : + | + * - ``3500``\ + - | ``bitwise_copy_of``\ : + | bitwise copy of: + * - ``3501``\ + - | ``bitwise_copy``\ : + | + * - ``3502``\ + - | ``class_result_via_ctor``\ : + | class result via ctor: + * - ``3503``\ + - | ``constructor_call``\ : + | + * - ``3504``\ + - | ``null_expression``\ : + | + * - ``3505``\ + - | ``quoted_error``\ : + | + * - ``3506``\ + - | ``null_routine``\ : + | + * - ``3507``\ + - | ``quoted_default``\ : + | + * - ``3508``\ + - | ``parameter_number``\ : + | parameter # + * - ``3509``\ + - | ``one_level_up``\ : + | (one level up) + * - ``3510``\ + - | ``levels_up``\ : + | levels up + * - ``3511``\ + - | ``dynamic_init``\ : + | dynamic-init: + * - ``3512``\ + - | ``error_constant``\ : + | + * - ``3513``\ + - | ``stack_offset_of``\ : + | stack-offset-of: + * - ``3514``\ + - | ``implicit_element``\ : + | + * - ``3515``\ + - | ``repetitions_of``\ : + | repetitions of + * - ``3516``\ + - | ``type_code_integer``\ : + | integer + * - ``3517``\ + - | ``type_code_enum``\ : + | enum + * - ``3518``\ + - | ``type_code_scoped_enum``\ : + | scoped enum + * - ``3519``\ + - | ``type_code_arithmetic``\ : + | arithmetic + * - ``3520``\ + - | ``type_code_non_bool_arithmetic``\ : + | non-bool arithmetic + * - ``3521``\ + - | ``type_code_pointer``\ : + | pointer + * - ``3522``\ + - | ``type_code_nullptr_type``\ : + | nullptr type + * - ``3523``\ + - | ``type_code_handle``\ : + | handle + * - ``3524``\ + - | ``type_code_handle_to_CLI_array``\ : + | handle-to-CLI-array + * - ``3525``\ + - | ``type_code_pointer_to_object``\ : + | pointer-to-object + * - ``3526``\ + - | ``type_code_pointer_to_function``\ : + | pointer-to-function + * - ``3527``\ + - | ``type_code_pointer_to_member``\ : + | pointer-to-member + * - ``3528``\ + - | ``type_code_bool``\ : + | bool + * - ``3529``\ + - | ``type_code_bool_equivalent``\ : + | bool-equivalent + * - ``3530``\ + - | ``type_code_class``\ : + | class + * - ``3531``\ + - | ``volatile_inc_deprecated``\ : + | a volatile operand to an increment expression is deprecated + * - ``3532``\ + - | ``volatile_dec_deprecated``\ : + | a volatile operand to a decrement expression is deprecated + * - ``3533``\ + - | ``indeterminate_not_on_first_decl``\ : + | *entity-kind "entity"*\ previously declared without the + "indeterminate" attribute + * - ``3534``\ + - | ``default_constructor_is_explicit``\ : + | the default constructor for *"type"*\ is explicit + * - ``3535``\ + - | ``ifc_definition_load_failure``\ : + | failed to load the definition of *entity-kind "entity"*\ in *module + "module name"*\ + * - ``3536``\ + - | ``ifc_initializer_load_failure``\ : + | failed to load the initializer for *entity-kind "entity"*\ in + *module "module name"*\ + * - ``3537``\ + - | ``base_class_of_class_type_with_typedef_name``\ : + | a class with a typedef name for linkage purposes cannot have a base + class + * - ``3538``\ + - | ``member_function_of_class_type_with_typedef_name``\ : + | a class with a typedef name for linkage purposes cannot have a member + function + * - ``3539``\ + - | ``member_type_of_class_type_with_typedef_name``\ : + | a class with a typedef name for linkage purposes cannot have a nested + type, other than an enumeration type or a non-closure class type + * - ``3540``\ + - | ``lambda_in_class_type_with_typedef_name``\ : + | a class with a typedef name for linkage purposes cannot contain a + lambda expression + * - ``3541``\ + - | ``field_init_in_class_type_with_typedef_name``\ : + | a class with a typedef name for linkage purposes cannot have a + nonstatic data member with a default member initializer + * - ``3542``\ + - | ``static_data_member_not_allowed_in_unnamed_class``\ : + | a static data member declaration is not allowed in an unnamed class + * - ``3543``\ + - | ``initializer_addresses_dllimport_variable``\ : + | initializer result addresses a dllimport variable + * - ``3544``\ + - | ``cannot_be_specialized``\ : + | template with "no_specializations" attribute cannot be specialized + * - ``3545``\ + - | ``static_dimension_nonstandard``\ : + | "static" is nonstandard here + * - ``3546``\ + - | ``enum_previously_declared_without_explicit_base``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared without an explicit enum base + * - ``3547``\ + - | ``missing_typename``\ : + | missing "typename" is nonstandard here + * - ``3548``\ + - | ``abbreviated_deduction_guide``\ : + | abbreviated function template syntax is nonstandard for deduction + guides + * - ``3549``\ + - | ``explicit_this_is_cpp23``\ : + | explicit "this" parameters are a C++23 feature + * - ``3550``\ + - | ``array_designator_for_deduced_context``\ : + | array designators are not supported in template deduction contexts + * - ``3551``\ + - | ``second_argument_wrong_shape``\ : + | the second argument must be an integer type with the same shape (a + scalar or vector type) as the first argument + * - ``3552``\ + - | ``vector_of_boolean_required``\ : + | argument must be a vector of boolean types + * - ``3553``\ + - | ``pointer_to_scalar_required``\ : + | argument must be a pointer to a scalar type + * - ``3554``\ + - | ``incorrect_masked_type``\ : + | incorrect argument type (should be *"type"*\ ) + * - ``3555``\ + - | ``vector_type_with_size_is_required``\ : + | a vector type (with the same number of elements as the first + argument) is required + * - ``3556``\ + - | ``struct_binding_packs_is_cpp26``\ : + | structured binding packs are a C++26 feature + * - ``3557``\ + - | ``non_template_structured_binding_pack``\ : + | a structured binding pack can only be declared inside a template + * - ``3558``\ + - | ``multiple_structured_binding_packs``\ : + | cannot declare multiple packs in a structured binding declaration + * - ``3559``\ + - | ``cl_cpp26_requires_parse_nonclass_templates``\ : + | The "--no_parse_templates" option cannot be used in C++26 mode + * - ``3560``\ + - | ``type_pack_element_cannot_match``\ : + | a type pack element cannot match *entity-kind "entity"*\ + * - ``3561``\ + - | ``c23_old_style_param_id``\ : + | identifier-only parameters can only be used in old-style function + definitions, which are nonstandard since C23 + * - ``3562``\ + - | ``cl_require_func_prototypes_option_only_in_C``\ : + | option "no_require_func_prototypes" can be used only when compiling C + * - ``3563``\ + - | ``address_of_overload_set_implicit_obj_member_selected``\ : + | overload resolution for an address-of-overload-set call may not + select implicit-object member *entity-kind "entity"*\ (declared at + line *xxxx*\ ) + * - ``3564``\ + - | ``pack_indexing_is_cpp26``\ : + | pack indexing is a C++26 feature + * - ``3565``\ + - | ``pack_index_out_of_bounds``\ : + | pack index exceeds number of pack elements + * - ``3566``\ + - | ``alias_ctad_is_cpp20``\ : + | class template argument deduction for alias templates is a C++20 + feature + * - ``3567``\ + - | ``bitint_width_too_large``\ : + | _BitInt(*n*\ ) is invalid; the maximum integer width is *n*\ + * - ``3568``\ + - | ``signed_bitint_width_too_small``\ : + | _BitInt(*n*\ ) is invalid; the minimum signed _BitInt width is *n*\ + * - ``3569``\ + - | ``unsigned_bitint_width_too_small``\ : + | unsigned _BitInt(*n*\ ) is invalid; the minimum unsigned _BitInt + width is *n*\ + * - ``3570``\ + - | ``bitint_enum_base_not_allowed``\ : + | _BitInt types cannot be the underlying type of an enumeration type + * - ``3571``\ + - | ``deduction_guide_redeclaration``\ : + | redeclaration of deduction guide *"type"*\ (previous declaration at + line *xxxx*\ ) + * - ``3572``\ + - | ``create_pch_file_not_created``\ : + | precompiled header file *"xxxx"*\ was not created + * - ``3576``\ + - | ``non_c_like_typedef_for_linkage``\ : + | anonymous non-C-like type given name for linkage purposes by typedef + or alias declaration + * - ``3577``\ + - | ``non_c_like_because_of_base_class``\ : + | type is not C-like because of this base class + * - ``3578``\ + - | ``non_c_like_because_of_default_member_init``\ : + | type is not C-like because of this default member initializer + * - ``3579``\ + - | ``non_c_like_because_of_friend``\ : + | type is not C-like because of this friend declaration + * - ``3580``\ + - | ``non_c_like_because_of_member``\ : + | type is not C-like because of this member declaration + * - ``3581``\ + - | ``non_c_like_because_of_lambda``\ : + | type is not C-like because of this lambda expression + * - ``3582``\ + - | ``enum_qualifier_is_cpp11``\ : + | an enum-type name qualifier is a C++11 feature + * - ``3583``\ + - | ``unrestricted_unions_is_cpp11``\ : + | unrestricted unions are a C++11 feature + * - ``3584``\ + - | ``pack_expansion_for_non_pack_alias_param``\ : + | a pack expansion cannot be used as an argument for non-pack + *entity-kind "entity"*\ of *entity-kind "entity"*\ + * - ``3585``\ + - | ``uniterable_reflection_range``\ : + | the range passed to the metafunction cannot be iterated + * - ``3587``\ + - | ``interpreter_message_remark``\ : + | *xxxx*\ *xxxx*\ + * - ``3588``\ + - | ``interpreter_message_warning``\ : + | *xxxx*\ *xxxx*\ + * - ``3589``\ + - | ``interpreter_message_error``\ : + | *xxxx*\ *xxxx*\ + * - ``3590``\ + - | ``constexpr_diag_arg_count``\ : + | a call to "\__builtin_constexpr_diag" requires three arguments + * - ``3591``\ + - | ``constexpr_diag_bad_level``\ : + | the first argument in a call to "\__builtin_constexpr_diag" must be 0 + (remark), 1 (warning), 2 (error), 16 (remark at caller), 17 (warning + at caller), or 18 (error at caller) + * - ``3592``\ + - | ``constexpr_diag_bad_string``\ : + | a string literal or an object with the representation of + std::string_view is required for the tag and the message in a call to + "\__builtin_constexpr_diag" + * - ``3593``\ + - | ``constexpr_diag_bad_tag``\ : + | the tag in a call to "\__builtin_constexpr_diag" may contain only + letters, digits, and underscores + * - ``3594``\ + - | ``cl_invalid_constexpr_diag_tag``\ : + | invalid tag in constexpr diagnostic control option: *xxxx*\ + * - ``3595``\ + - | ``token_sequence_needs_double_caret``\ : + | a token sequence must be introduced by "^^" + * - ``3596``\ + - | ``exp_interpolator``\ : + | expected an interpolator ("\[", "\[:", "\{", "\val", or "\str") + * - ``3597``\ + - | ``interpolated_id_is_not_identifier``\ : + | *"xxxx"*\ does not spell an identifier + * - ``3598``\ + - | ``interpolated_operand_is_not_token_sequence``\ : + | the operand of a "\{...}" interpolator is not a token sequence + * - ``3599``\ + - | ``tag_redefined_differently``\ : + | this declaration of *entity-kind "entity"*\ does not declare the + same type as the declaration at line *xxxx*\ + * - ``3600``\ + - | ``bad_gcc_unroll_pragma_value``\ : + | the argument of "#pragma GCC unroll" must be a non-negative integral + constant less than 65535 diff --git a/dev/doc/_sources/exceptions.rst.txt b/dev/doc/_sources/exceptions.rst.txt new file mode 100644 index 0000000..5178d16 --- /dev/null +++ b/dev/doc/_sources/exceptions.rst.txt @@ -0,0 +1,566 @@ +================== +Exception Handling +================== + +The high-level representation of exception handling in the IL closely follows +the C++ language specification. The data structures involved are defined in +``il_def.h``, and the routines to manage declarations and other support are in +``decls.c``, ``statements.c``, and ``expr.c``. + +A global variable, ``exceptions_enabled``, controls whether exception +processing is done. An error is issued if the flag is FALSE and the source +program attempts to use a syntactic feature that pertains to exception +handling. The default value of the ``exceptions_enabled`` flag is configurable +(see ``DEFAULT_EXCEPTIONS_ENABLED`` in ``lang_feat.h``). The value may be +toggled by a command-line option (``-x``), except that its value may be TRUE +only in C++ mode and only when cfront-compatibility mode has not been selected. + +Any actual implementation of exception handling will require a tradeoff between +portability and efficiency. The high-level representation of exception +handling (that is, the representation of the "unlowered" IL) is not explicit +about a number of details that an actual implementation will have to deal with, +notably finding the right handler, copying the ``throw`` object to the right +handler parameter, and calling the right set of destructors at the right time. +Therefore, though a portable implementation of exception handling is provided +(see ``lower_eh.c`` and routines provided for run-time support), back ends may +choose to replace it with an implementation adapted to the specific support +available on the target platform. IL lowering can instead be configured to do +partial lowering or no lowering of exception handling features. + +This chapter describes the high-level support for exceptions and then +summarizes the main features of the portable implementation. + +Exception Specifications +======================== + +An exception specification that appears on a function declaration is +represented by an entry of type ``an_exception_specification``. The +function refers to it by means of the ``exception_specification`` field of +its routine type supplement. When the function is declared with no +exception specification (meaning that *any* exception might be thrown), the +``exception_specification`` pointer will be NULL. A dynamic ``throw`` +specification entry itself has a pointer to a linked list of entries of +type ``a_throw_spec_type_entry``, each of which indicates a type of +exception that will be thrown from the given routine; that pointer is NULL +to indicate that *no* exceptions will be thrown. A ``noexcept`` specifier +points to a constant representing its operand or NULL if there is no such +operand. + +``scan_exception_specification``, which is called from ``function_declarator``, +scans an exception specification and allocates a ``throw`` specification entry +and its associated list of types, if any. Subsequently (i.e., after the +routine entry has been identified) the exception specification is either added +to the routine type supplement or checked against a prior declaration (see +``check_exception_specification``). + +The ``used_in_exception`` flag is set for any type that appears in an exception +specification (as well as for any type that is the type of a ``throw`` +expression or appears in the exception declaration of a handler). Some +implementations of exception handling may use this flag in generating special +code for run-time type identification. In addition, if such a type is (or +"contains") a class or enumeration type, that class or enumeration type must be +externally linked. See ``set_used_in_exception_or_rtti_flag`` (in +``types.c``). + +``try`` Blocks +============== + +A ``try`` block is represented in the IL by a statement of kind +``stmk_try_block``, which points to a compound statement block and a linked +list of handlers. The latter are entries of type ``a_handler``; each points to +a (possibly unnamed) parameter (the local variable to which the ``throw`` +object will be copied when the handler is invoked) and to an ``stmk_block`` +statement, the body of the handler; for a default handler (i.e., the +``catch(...)`` case) the parameter pointer in the handler entry is NULL. + +A ``try`` block is scanned by ``try_block_statement`` (in ``statements.c``). +First ``compound_statement`` is called to scan the part of the ``try`` block +that precedes the first handler declaration. Then ``handler_declaration`` (in +``decls.c``) is called for each ``catch`` clause. + +``handler_declaration`` scans the exception declaration (calling +``decl_specifiers`` and, if a named parameter is present, ``declarator``). +Except for the default handler case, it creates a ``variable`` entry to +represent the parameter, whether it is explicitly declared or not. It also +does various checks to assure that the parameter's type is valid (e.g., that it +is not an incomplete type) and calls ``set_used_in_exception_or_rtti_flag``; +then it calls ``type_masks_handler_param_type`` (in ``types.c``), to assure +that it is not masked by a previous handler declaration in the same ``try`` +block. + +Finally, ``compound_statement`` is called to scan the handler's body. Special +checking is done to assure that no label defined within the handler is +referenced by a ``goto`` from outside the handler. + +in C++/CLI mode, there may be a "``finally``" block at the end, either in +addition to or in place of the catch clauses. It provides code that is +always executed when the try block is exited, whether normally, via a +``goto`` or ``return``, or via a thrown exception. + +``throw`` Expressions +===================== + +A ``throw`` expression is scanned by ``scan_throw_operator`` (in ``expr.c``). +An ``enk_throw`` expression node is produced, which points to a dynamic +initialization entry that describes the object to be thrown (or rather, how to +copy it to the space for the object allocated by the run-time). +``set_used_in_exception_or_rtti_flag`` is called for the type. A "rethrow", +where no ``throw`` object is specified (i.e., ``throw;``), is represented by an +``enk_throw`` expression with a NULL pointer. + +Portable Implementation +======================= + +One exception handling implementation provided in this release is a portable +implementation that provides complete EH support while requiring few changes to +existing back ends. Because this is a portable implementation there is a +significant impact on the performance of the generated code when exception +handling is enabled. + +A walk-through of an EH example +------------------------------- + +What follows is a rather contrived example that provides an overview of how the +compiled code and the run-time system cooperate in throwing and handling +exceptions. It is intended as an introduction, with a more detailed discussion +of some of its features in subsequent sections. + +Here is the example (with the numbers to the right corresponding to the text +that follows): + +.. code:: c++ + + #include + struct A { ~A() { } }; + struct B : public A { }; + struct C { }; + void f(int i) throw(A) { // 2, 3, 4 + A a1; // 5 + if (i==0) throw a1; // 6 + B b1; + if (i==1) throw b1; + C c1; + if (i==2) throw c1; + } + int main() { + for (int i = 0; i < 3; ++i) { + printf("i=%0d\n", i); + try { // 1 + f(i); + } + catch (A a) { printf("Caught an A\n"); } // 7, 8 + catch (...) { printf("Caught something else\n"); } + } /* for */ // 9 + } + +#. Each time the ``for`` loop in ``main`` is executed and control enters + the ``try`` block, prologue code is executed, which includes pushing an + entry onto the "EH stack" to record that a ``try`` block has been + entered. (The EH stack is the principal data structure used to track the + dynamic context in which exception handling events occur.) + +#. Each time ``f`` is called, prologue code for the function pushes another + entry onto the EH stack to record that a function with exception + specifications has been entered. This entry provides the run-time system + with a list of the types that may be thrown from ``f``. + +#. Moreover, since ``f`` contains objects (namely, automatic variables with + destructors) that may need to be cleaned up if an exception is thrown + during its execution, an additional entry is pushed onto the EH stack + for object cleanup. [#f1]_ The array it points to is updated each time + an object that is eligible for clean-up is constructed. + +#. The first clean-up region of ``f`` is entered, and global variable + ``__eh_curr_region`` is updated accordingly. This routine has three such + regions -- the region in which no objects require clean-up, the region in + which ``a1`` requires clean-up, and the region in which both ``a1`` and + ``b1`` require clean-up. [#f2]_ + +#. When ``a1`` is constructed, the second clean-up region is entered. The + address of ``a1`` is entered in the "object address table". + +#. The processing for the original source expression "``throw a1``" + involves three steps: + + * | ``__throw_setup`` is called to record information about ``a1`` (most + importantly, its type) and to return a pointer to a piece of storage + into which it may be copied. [#f3]_ + + * | The compiled code makes a copy of ``a1`` to pass to + ``__throw``. Note that if class ``A`` had a copy constructor, the + generated code would include a call of ``__exception_started`` prior + to making the copy of ``a1``. + + * | ``__throw`` is called. First it walks the EH stack to identify the + action that is required -- in this case, it locates a handler that + can catch an ``A`` object. It then makes a second pass through the + EH stack to do the appropriate clean-up, which in this case involves + calling the destructor for ``a1`` and popping a couple of entries + off the EH stack. The actions performed by ``__throw`` may entail a + good deal more complexity, as described in greater detail later. + +#. After the clean-up is complete, control transfers back to the ``try`` + block in ``main``, and specifically to the first handler (since it is + the one that catches an ``A`` object), and then "``Caught an A``" is + printed out. + +#. The epilogue code of the handler involves a call to + ``__free_thrown_object``, to deallocate the storage into which ``a1`` + was copied. + +#. As the ``try`` block is exited, the EH stack entry for the current + ``try`` block is popped, restoring the state to what it was originally, + before the try block was entered. + +On the second iteration of the ``for`` loop in ``main``, the same sequence of +events takes place, except for two things. First, in function ``f``\ ``b1`` is +also constructed, so that the third clean-up region is entered and the address +of ``b1`` is recorded in the object address table (along with that of ``a1``); +that means that two objects are eligible for clean-up when an exception occurs. +Second, ``__throw`` must take into account that ``A`` is an accessible base +class of ``B`` in locating the handler that can catch ``b1``. + +Finally, on the third iteration of the loop, ``__throw`` detects a violation of +the exception specification for function ``f`` -- ``c1`` is the thrown object +this time, but ``C`` is not on the list of types that the function is allowed +to throw. As a result, ``unexpected`` is called, which results in a call to +``terminate``. + +Run-Time Support +---------------- + +The EH Stack +^^^^^^^^^^^^ + +A principal data structure used in coordinating the compiled code and the +run-time is the "EH stack". It maintains information about the dynamic context +in which exception handling events occur. The EH stack is a linked list of +structures, and a new entry is pushed onto the stack each time a ``try`` block +is entered, each time a function with an exception specification is entered, +and each time a function is entered for which some kind of object clean-up must +be done if an exception is thrown. + +Code generated for a ``try`` block +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a ``try`` block is entered, a ``try`` block entry is pushed onto the EH +stack. The ``try`` block entry contains + +* | a ``setjmp`` buffer that will be used for transfer of control back to the + ``try`` block when an exception is thrown; +* | a list of the ``catch`` clauses associated with the ``try`` block; +* | other status information used to record the current state of the ``try`` + block. + +The state information in the ``try`` block is initialized so that the run-time +knows that the ``try`` section of the block (as opposed to one of the handlers) +is currently being executed. When generating code for exception cleanup it is +sometimes necessary for the front end to generate ``try`` blocks that do not +appear in the original program. These are known as "internal" ``try`` blocks +and are distinguished from normal ``try`` blocks by the fact that the pointer +to the list of ``catch`` clauses is null. + +Prologue code for a function with an exception specification +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a function with an exception specification is entered, a ``throw`` +specification entry is pushed onto the EH stack. This entry provides a list of +the types that may be thrown (directly or indirectly) by the function. It is +removed from the EH stack when the function returns. + +Prologue code for a function that may need clean-up if an exception is thrown +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a function constructs objects that may need to be cleaned up in the event +of an exception, its prologue code pushes a function clean-up entry onto the EH +stack. Note that a given function may push both a ``throw`` specification +entry and a function clean-up entry. + +A function clean-up entry will be pushed on the stack if the function creates +any automatic objects (including temporaries) of classes with destructors; one +is also generated when an object may be dynamically allocated using ``operator +new`` and the front end is configured to generate the ``operator new`` call +outside the constructor. + +The function clean-up entry contains + +* | a pointer to an array of region entries that are used to describe the + clean-up regions within the function +* | a pointer to an array table that provides additional information for + certain region entries +* | a pointer to an object address table used to determine the address of + objects referenced by the region and array tables + +A region is associated with a specific sequence of clean-up actions that would +be required should an exception occur. A new region is typically started +whenever a destructable object comes into or goes out of scope. + +The global variable ``__eh_curr_region`` records the region number currently +being executed. It is saved each time a new function entry or ``try`` block is +pushed on the stack and restored when the entry is popped. + +The region entries contain the information needed to identify the object to be +cleaned up and the kind of clean-up action required. The run-time must be able +to determine the address of each object for which some kind of clean-up must be +done. Ideally this would be done by putting stack offsets in the region +entries. This can't be done in the portable implementation, and so instead the +region entries contain an index into the object address table. The object +address table is allocated on the stack because its contents vary with each +invocation of the function. As each region is entered, the appropriate entry +in the object address table is filled in with the address of the object to be +cleaned up. The address of the object address table is recorded in the +function entry on the EH stack. + +The region entries have been designed to be as compact as possible. Some +unusual circumstances require additional information not normally available in +the region entry. The additional information is needed when the region entry +describes an array or when the region entry describes a new allocation of a +class object whose ``operator delete`` function is of the two-operand variety. +In these cases the region entry contains an index into an array supplement and +the array supplement pointer is stored in the function entry on the EH stack. + +Throwing an exception (generated code) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When an exception is thrown, the run-time routine ``__throw_setup`` is called +to provide information to the run-time system about the object being thrown and +to allocate space into which the thrown object may be copied. A pointer to +this space is returned to the caller (i.e., the compiled code), which is +responsible for actually making the copy of the object. If copying the object +requires calling a copy constructor, ``__exception_started`` is called after +the evaluation of the object to be thrown, but before the copy constructor is +called. Once the object has been copied the run-time routine ``__throw`` is +called to complete the throw processing. If the thrown object requires +destruction, ``__throw_setup_dtor`` is called instead of ``__throw_setup``. If +the thrown object is a multi-level pointer, ``__throw_setup_ptr`` is called +instead of ``__throw_setup``. + +Throwing an exception (``__throw_setup``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When ``__throw_setup`` is called, an entry is pushed onto the throw stack +(which is distinct from the EH stack). The throw stack contains information +about each of the thrown objects and is needed because throws may be nested +(i.e., a throw may occur while in a handler reached as the result of an earlier +throw). ``__throw_setup`` records the information provided by the caller in +the throw stack entry. This includes information about the type of the thrown +object. + +The run-time system requires information about the types of objects that are +thrown and caught and also for types used in exception specifications. The +term "``typeinfo``" is used to refer to this type description information. +[#f4]_ It is not necessarily possible to generate only one ``typeinfo`` record +for a given type. [#f5]_ Consequently it must be possible to determine that +two ``typeinfo`` records refer to the same type. This is done by having each +``typeinfo`` point to a "unique ID object". The unique ID objects are +generated as tentative definitions to avoid potential multiple definition +problems. Two ``typeinfo`` records refer to the same type if they point to the +same unique ID object. The ``typeinfo`` information includes a list of the +base classes of the type. The base class list includes all direct base classes +as well as all virtual base classes, whether direct or indirect. + +When checking exception specifications and looking for a ``catch`` clause that +can catch the thrown object, it is necessary to determine whether a given type +is a base class (and an accessible one) of the thrown type. This is done by +traversing the ``typeinfo`` base class list. The base class list includes +information about accessibility and ambiguity, which allows the runtime to +ignore non-public and ambiguous base classes. + +In front end versions preceding 2.29, the runtime routine ``__throw_alloc`` was +called instead of ``__throw_setup``. It had a similar function and a similar +interface, with one additional parameter, which (when non-NULL) was a string +indicating the accessibility for each base class, computed by the front end at +the point of the throw. This changed because the C++ language changed: As of +March 1995, the rules for ``throw`` were changed to allow catching only public +base classes, which eliminates the need for determining any special +accessibility at the point of throw. + +Marking the initiation of the exception (``__exception_started``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An exception is considered "uncaught" after the expression in the throw +statement has been evaluated. If a copy constructor must be called to copy the +thrown object into the temporary copy used by the EH runtime, the copy +constructor must be called while the exception is considered uncaught. In +other words, if an exception is thrown during the evaluation of the expression +in the throw, that exception is handled normally. If, however, an exception is +thrown from a copy constructor called to copy an object to the temporary used +by the EH runtime (and control is transferred out of the copy constructor +because of the exception) ``terminate()`` must be called instead. + +``__exception_started`` is called to mark the point at which an exception is +considered uncaught. When the copy of the thrown object can be made without +calling a copy constructor ``__exception_started`` is not called, and the +exception is considered uncaught at the point at which ``__throw`` is called. + +Throwing an exception (``__throw``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +After the compiled code copies the thrown object into the space designated by +``__throw_setup``, it issues a call to ``__throw`` to complete the processing. + +``__throw`` makes two passes through the ``try`` stack. The first pass +determines what should occur as a result of the throw -- transferring to a +specific handler, calling ``unexpected`` because an exception specification was +violated, or calling ``terminate`` (for any of several reasons). Once the end +result of the throw has been determined, a second pass is made through the EH +stack entries to perform any clean-up actions that are required. + +During the first pass through the EH stack +``check_exception_type_specifications`` is called for each ``try`` block entry +and each ``throw`` specification entry. Only ``try`` blocks that are executing +the ``try`` portion of the block (as opposed to a handler) are eligible to be +the destination of a ``throw``. ``try`` blocks that are currently in handlers +are simply ignored. The search is terminated when a matching ``catch`` clause +is found or a violated exception specification is detected. When it is a +matching ``catch`` clause that is found, a pointer to the thrown object is +passed to the routine so that it may be adjusted for any derived-to-base-class +conversions that may be needed. If the matching ``catch`` clause is associated +with an internal ``try`` block, the search of the EH stack continues to +determine if a normal ``try`` block can be found. The search for a normal +``try`` block that with a matching handler is used to determine whether +``terminate()`` should be called. + +According to the standard it is implementation-defined whether the stack is +unwound before ``terminate()`` is called. The runtime can be configured to +select either of the possible behaviors by setting the +``UNWIND_STACK_BEFORE_CALLING_TERMINATE`` configuration flag. If this flag is +not set, ``terminate()`` would be called now if no matching handler was found. + +In the second pass only the function clean-up entries are processed. The +function ``cleanup`` is called for each such entry. ``cleanup`` processes the +region entries associated with the function starting with the region number +specified by the caller. Each region entry contains a "flags" field that +controls how the region information is interpreted. + +* | If the "conditional flag" bit is set, the region entry describes an object + that is conditionally constructed and must only be destroyed if a variable, + whose address is determined from the next element in the region array, + indicates the object was actually constructed. +* | If the "new allocation" bit is set, the region entry describes an object + allocated by ``new`` that must be deleted during clean-up. In this case + the function pointer in the region entry that normally points to the + destructor instead points to the delete routine to be called. +* | If the "VLA" bit is set, the region entry describes a variable length + array, whose size is determined from the next element in the region array. + +One of the fields in the region entry is the region number of the next entry to +be processed. The end of the region list is designated by a reserved value in +the next entry field. + +If an exception occurs while constructing or destructing an array, the clean-up +operation must destroy the remaining portion of the partially constructed (or +destructed) array. To accomplish this there is a special kind of EH stack +entry that is only used by ``vec_new`` and ``vec_delete``. When this entry is +encountered during the clean-up pass, ``__cleanup_vec_new_or_delete`` is called +to the required clean-up. + +After all of the function clean-up entries have been processed, ``__throw`` +determines whether there are any clean-up actions required by the ``try`` block +associated with the handler to which control is to be transferred. If so, +``cleanup`` is called to do the required clean-up operations. + +Only after all the clean-up operations have been completed is the action +performed that was determined by the first pass through the EH stack: + +* | If an exception specification was violated, ``unexpected`` is called. +* | If no handler was found, ``terminate()`` is called (when the + ``UNWIND_STACK_BEFORE_CALLING_TERMINATE`` configuration flag is set). +* | Otherwise, control is transferred to the handler. Global variable + ``__catch_clause_number`` is set to the sequence number of the ``catch`` + clause to which control is to be transferred, and another global variable, + ``__caught_object_address``, is set to the address of the object to be used + to initialize the handler parameter. The state information in the ``try`` + block entry is updated to indicate that a handler is now being executed. + Finally, ``longjmp`` is used to branch back to the appropriate ``try`` + block. + +In the handler +^^^^^^^^^^^^^^ + +The ``try`` block code uses ``__catch_clause_number`` to select the appropriate +handler, and then the handler parameter is initialized using +``__caught_object_address``: If the handler parameter is a reference, it is +initialized by setting a pointer to the global variable; otherwise, the object +pointed to by ``__caught_object_address`` is used to initialize the handler +parameter. ``__exception_caught`` is called after the handler parameter has +been initialized. This marks the end of the period during which an exception +is considered uncaught. ``__exception_caught`` is not called by the catch +clause associated with an internal try block. Instead, an internal try block +exits by calling ``__internal_rethrow``, which calls ``__exception_caught`` +before performing the rethrow. + +A rethrow from the handler +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A rethrow (a ``throw`` with no operand) may be executed anywhere within the +dynamic context of a handler. This has the effect of doing a nested throw of +the object on top of the throw stack. Note that it rethrows the thrown object +and not the caught object (the two can be different if a derived-to-base +conversion occurred or if the object was caught using ellipsis). + +The handling of rethrow is almost identical to the handling of a normal throw. +The only difference is that the thrown object is not copied. The throw stack +entry for the rethrow points to the copy of the thrown object made when the +original throw was done. + +At the end of a handler +^^^^^^^^^^^^^^^^^^^^^^^ + +At the end of each handler ``__free_throw_object`` is called to pop entries off +of the throw stack, call the destructor for the thrown object, and to free the +space used for copies of the thrown objects associated with the throw stack +entries being cleared. + +Run-Time storage management +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The exception handling run-time dynamically allocates information used for book +keeping (e.g., throw stack entries) and for making copies of thrown objects. +The memory is allocated and freed using a stack discipline. The run-time +includes a static buffer that is used for this dynamically allocated memory. +If the static buffer is exhausted, additional memory is allocated using +``malloc``. If the run-time is unable to allocate the memory needed to handle +an exception, ``terminate`` is called. + +Non-Portable Implementation +=========================== + +The non-portable implementation would be more properly described as "turning +off parts of the portable implementation so that a back end can do something +better." EDG does not provide a complete non-portable implementation (in IL +lowering and the runtime), but our customers should be able to write one using +the information provided by the front end. + +The portable implementation is also known as the full-lowering implementation, +because it lowers everything related to exception handling to C, leaving +nothing related to exception handling in the IL. It is enabled by setting +``DO_FULL_PORTABLE_EH_LOWERING`` to TRUE. + +The next step down from that is the partial-lowering implementation, which is +enabled by setting ``GENERATE_EH_TABLES`` to TRUE. In that mode, the data +tables of the portable scheme are still generated, but the executable code is +rendered as exception-handling operations, so that a back end can choose a +different approach (e.g., not using ``setjmp``, not maintaining a separate EH +stack). + +The final step down is the no-lowering implementation, which is enabled by +having both ``DO_FULL_PORTABLE_EH_LOWERING`` and ``GENERATE_EH_TABLES`` FALSE. +In that mode, the data tables are not generated either, but the object lifetime +information is preserved so that the back end can use it to generate its own +version of the cleanup tables. + +See the :ref:`il-lowering` chapter for details on the constructs +preserved and lowered under each alternative. + +.. [#f1] Note that the prologue code for ``f`` pushes two entries onto the EH + stack, one for its exception specifications and one for object + clean-up. +.. [#f2] ``c1`` requires no clean-up since ``C`` has no destructor. +.. [#f3] In versions before 2.29, the runtime routine was called + ``__throw_alloc``. +.. [#f4] This is not the structure called "``type_info``" that is visible to + the programmer via ``typeid``. +.. [#f5] Unique ``typeinfo`` records can only be generated for classes with at + least one noninline virtual function (i.e., the same algorithm that is + used to generate virtual function tables). diff --git a/dev/doc/_sources/expr.rst.txt b/dev/doc/_sources/expr.rst.txt new file mode 100644 index 0000000..36ef517 --- /dev/null +++ b/dev/doc/_sources/expr.rst.txt @@ -0,0 +1,2262 @@ +=================== +Expression Scanning +=================== + + + + +``expr.c`` and ``expr.h`` contain the code and associated declarations to scan +expressions. ``exprutil.c`` and ``exprutil.h`` contain utilities related to +expression scanning, for processing other than the actual syntax analysis. +``overload.c`` and ``overload.h`` contain code to do overload resolution and +conversions. + +The expression routines function as an expression-scanning utility for the rest +of the front end. They provide a set of simple interface routines that are +called to scan various kinds of expressions: + +* | ``scan_integer_expression`` scans an integral expression, e.g., the + selector expression for a ``switch`` statement. +* | ``scan_void_expression`` scans a "void" expression, one whose value is + thrown away, e.g., an expression statement or the incrementing expression + in a ``for`` statement. +* | ``scan_default_arg_expr`` scans a default argument expression. +* | ``scan_template_argument_constant_expression`` scans a nontype argument of + a template reference. +* | ``scan_return_expression`` scans the expression in a ``return`` statement. +* | ``scan_case_label_constant`` scans a constant expression for a switch case. +* | ``scan_constant_dimension_expression`` scans a constant array bound. +* | ``scan_pp_expression`` scans a preprocessing expression, e.g., an + expression in an ``#if``. +* | ``scan_integral_constant_expression`` scans an integral constant + expression. +* | ``scan_constant_initializer_expression`` scans an initializer that is + required to be a constant. +* | ``scan_member_constant_initializer_expression`` scans an initializer for a + member constant (integral or enum) in C++. +* | ``scan_full_initializer_expr_as_component``\ scans an initializer that need + not be a constant. +* | ``scan_class_initializer_expression`` scans an initializer for a class. +* | ``scan_class_parenthesized_initializer`` scans a parenthesized initializer + for a class. +* | ``scan_boolean_controlling_expression`` scans a scalar expression that + controls a conditional statement (``if``, ``while``, ``do while``, and + ``for``). + +Each of these routines has roughly the same structure. ``scan_expr_full`` is +called to do the actual expression scanning. This produces a result of type +``an_operand``, which is checked for kind, converted to a required type (if +there is one), and then converted to the form required on return from the +interface routine, usually an expression node or a constant. + +Some other utility expression routines with a different type of interface: + +* | ``scan_ctor_arguments`` is called to scan a parenthesized list of + expressions that acts as the argument list for a constructor call, for + example + + .. code:: c++ + + struct A { + A(int, int); + }; + A aa(1, j+1); // scan_ctor_arguments is called + +* | ``try_to_convert_class_operand_to_builtin_type`` is called to convert an + expression of a class type to a builtin type, as when such an expression + appears as the conditional expression in an ``if`` statement or the like. +* | ``scan_braced_init_list`` scans a complete braced-enclosed initializer as + in the C++11 "initializer lists" feature. ``convert_initializer`` is used + to convert initializers, in particular brace-enclosed initializers, to the + type of the entity being initialized. +* | ``find_default_constructor`` finds a default constructor capable of + initializing an object of a given class type. +* | ``find_copy_constructor`` finds a copy constructor capable of copying an + object of a given class type with a given cv-qualification. +* | ``find_copy_assignment_operator`` is similar for an ``operator=`` function. + +``scan_expr_full`` +------------------ + +``scan_expr_full`` actually handles all expression scanning. It is called with +a set of option flags that configure its processing for various types of +expressions. It scans through the tokens of an expression, builds an +expression tree for the expression scanned, and returns an argument of type +``an_operand`` to describe the expression scanned. + +Its arguments are as follows: + +.. list-table:: + + * - | ``result`` + - | The result (of type ``an_operand``) of this level of expression + scanning. + * - | ``prec_level`` + - | The operator precedence level at which to terminate the scanning. + Expression scanning continues while the next operator precedence is + higher than this (or equal, with right-associative operators). + * - | ``expression_kind`` + - | The kind of expression that is expected: ``ek_pp`` for a preprocessing + expression, ``ek_integral_constant`` for an integral constant + expression, ``ek_init_constant`` for a constant initializer expression + (not used in C++, except for nontype template arguments and some C++11 + expressions), ``ek_normal`` for a normal expression, or ``ek_sizeof`` + for the operand of ``sizeof``. For the three constant expression + cases, some operators are restricted, some operand types are + restricted, and values of variables (etc.) may not be loaded. (See + the section on constant expressions.) + * - | ``local_options`` + - | A bit-set of option switches that apply to just this level of + expression scanning (i.e., they do not apply to subexpressions scanned + within this expression scan). The switches control whether the comma + operator is allowed, whether the expression is being scanned as the + immediate operand of a cast, etc. + +Note that typically ``scan_expr_full`` is called through the macro +``scan_expr``. + +Parsing Technique +----------------- + +``scan_expr_full`` scans an expression using a modified version of recursive +descent. The technique is "modified" in that it includes an operator +precedence level (higher precedences, numerically, bind more tightly). This +modification avoids the many levels of subroutine calls inherent in the +traditional recursive descent method. In the modified method, there is +approximately one subroutine call per leaf operand. Basically, +``scan_expr_full`` will scan an expression up to either something it does not +understand (presumably something that follows the end of the expression), or up +to an operator that has lower precedence than the level being scanned (or equal +precedence when left-associative). + +The precedence check is done by the routine ``token_ends_expr``. One special +case: when inside a template argument list, "``>``" is treated as the closing +bracket for the argument list rather than the "greater than" operator. + +For example, the expression ``1+2*3-4`` is parsed as follows: + +#. ``scan_expr_full`` is called with level 0. It takes the ``1``, then + looks at the operator ``+``. The current level (0) is less than the + level of ``+`` (12), so ``scan_expr_full`` takes the ``+`` and calls + itself with level 12. + +#. ``scan_expr_full`` (called with level 12) takes the ``2``, then looks at + the operator ``*``. The current level (12) is less than the level of + ``*`` (13), so ``scan_expr_full`` takes the ``*`` and calls itself + with level 13. + +#. ``scan_expr_full`` (called with level 13) takes the ``3``, then looks at + the operator ``-``. The current level (13) is greater than the level of + ``-`` (12), so ``scan_expr_full`` returns the constant expression for + ``3``. + +#. Back in ``scan_expr_full`` (level 12, step 2 above), ``2*3`` is + assembled (by computing the constant result). ``scan_expr_full`` then + looks at the operator ``-``. The current level (12) is equal to the + level of ``-``, and ``-`` is left-associative, so ``scan_expr_full`` + returns the constant expression for ``2*3`` (i.e., 6). + +#. Back in ``scan_expr_full`` (level 0, step 1), ``1+(2*3)`` is assembled + (by computing the constant result). ``scan_ \expr_full`` then looks at + the operator ``-``. The current level (0) is less than the level of + ``-`` (12), so ``scan_expr_full`` takes the ``-`` and calls itself with + level 12. + +#. ``scan_expr_full`` (called with level 12) takes the ``4``, then looks at + the next token of input, which is something unrecognized, and returns + the constant expression for ``4``. + +#. Back in ``scan_expr_full`` (level 0, step 5), ``(1+(2*3))-4`` is + assembled (by computing the constant result). ``scan_expr_full`` then + looks at the next token of input, which is something unrecognized, and + returns the constant expression for ``(1+(2*3))-4`` (i.e., 3). + +``scan_expr_full`` Processing +----------------------------- + +The processing within ``scan_expr_full`` is only slightly more complicated than +the description above. There are two major sections: In the first, a leaf +operand (identifier or constant), a prefix operator followed by an expression, +or an expression in parentheses (or a cast) is scanned. In the second section, +there is a loop with the above-described precedence level test at the top. So +long as the next thing in the input (whether it is a postfix operator, +subscript, function argument list, or binary operator) has an appropriate +precedence, it will be taken and added to the current expression. The loop +stops on the first thing that is not recognized or has a lower precedence. A +loop is required for expressions containing equal-precedence left-associative +operators, like ``1+2*3*4+5``: the ``*3`` and ``*4`` would be accumulated on +successive iterations of the loop in one call of ``scan_expr_full``. + +.. _scanning-idents: + +Scanning Identifiers +-------------------- + +When ``scan_expr_full`` scans an identifier, it calls ``scan_identifier``, +which builds an operand for identifiers for enumeration constants, variables, +functions, etc. Odd C++ "names" like ``operator+`` are also handled by +``scan_identifier``. The appropriate routines are called to turn them into +pseudo-identifier tokens, and thereafter the handling is the same as for other +names. + +In constant expressions, variables are only allowed if they can legitimately be +part of a constant expression. + +For undefined identifiers in C mode, ``scan_identifier`` enters the identifier +as an undefined identifier; shortly, the identifier will turn out to be either +truly undefined (in which case an error is generated) or will turn out to be +the name of an implicitly-declared function (in which case +``decl_default_function`` in ``decls.c`` will be called to declare it as such). + +In C++, nonstatic data members and nonstatic member functions are processed as +if preceded by "``this->``" (see ``make_this_pointer_operand``). If the +identifier is a type identifier and it is followed by a left parenthesis, +``scan_functional_notation_type_conversion`` is called to scan a type cast. + +Also in C++, special considerations are made for uses of identifiers in local +classes (which can only use entities from the enclosing function in very +limited ways) and in local lambdas (which have similarities to local classes, +with the added wrinkle that references to enclosing local variables must be +interpreted as uses of fields of the associated closure class, and these fields +may have to be created as a result of these references). See +``bad_nested_function_variable_ref`` and +``make_selection_for_captured_variable``. + +Scanning Constants +------------------ + +When ``scan_expr_full`` scans a constant, it calls ``make_constant_operand`` to +build the appropriate operand. Floating constants are allowed in integral +constant expressions only as the immediate operand of a cast (see +``local_options``, above). For string literals, +``make_string_constant_operand`` is called instead. It produces an lvalue for +the array of characters; except in unusual cases (e.g., when the string is used +to initialize a character array), this is changed to a pointer to the string +(by ``conv_array_operand_to_pointer_operand``). + +.. _scanning-operations: + +Scanning Operations +------------------- + +Processing for operators is done by lower-level routines. The routines are +called when the operator token has been scanned, so for non-unary operators, +this means after the left operand expression has been scanned. Most of these +routines have a structure similar to the following, which describes a generic +binary operation routine: + +* | A check is made to see if the operator is allowed in the present type of + expression (some operators, for example, are disallowed in some kinds of + constant expressions). +* | The right operand is scanned by calling ``scan_expr_full`` with appropriate + switches. +* | In C++ mode if either of the operands has a class type, + ``check_for_operator_overloading`` is called to see if operator overloading + applies. If it does, an appropriate operator function call is generated. + If not, the remaining steps are done. +* | The left operand (passed in) is converted from a glvalue to a prvalue. In + cases where the left operand is supposed to be an lvalue, that is checked, + and ``using_lvalue`` or ``modifying_lvalue`` (depending on how the lvalue + is used) is called. +* | The type of the left operand is checked. +* | The right operand is converted from a glvalue to a prvalue. +* | The type of the right operand is checked. +* | The types of the operands are checked to see if they are compatible with + one another and with the operation. This sometimes selects a subcase of + the operation (e.g., pointer addition instead of integer addition). + + * | For arithmetic operations, ``determine_arithmetic_conversions`` is called + to determine the usual arithmetic conversions and + ``change_binary_operand_types`` is called to promote the operand types as + necessary. + * | For pointer operands, ``check_compatibility_of_pointer_operands`` is + called to check the operand types and do implicit type changes. + * | For pointers to members, + ``check_ptr_to_member_operands_for_compatibility`` is called to do a + similar check. +* | ``which_binary_operator`` is called to select the proper intermediate + language operator for the operation on this type of operands. +* | ``do_binary_operation`` is called to produce the result operand, either by + folding an operation on constants (by calling ``binary_operation`` in + ``folding.c``, but not when not-evaluated), or by building an expression + tree. +* | The start position of the expression is recorded in the result operand. + +The prefix ``++`` and ``--`` operators are scanned by +``scan_prefix_incr_decr``. + +The unary operator ``&`` is scanned by ``scan_ampersand_operator``. It usually +calls ``take_address_of_lvalue`` to produce the prvalue address result. In +``pcc`` mode, it issues a warning for taking the address of an array, and calls +``conv_array_operand_to_pointer_operand`` to produce address-of-array-element +instead of the ANSI address-of-array. If the operand is the qualified name of +a class member, a pointer-to-member constant is created. In C++/CLI, ``&`` +applied to an lvalue that might be on the CLR heap (as determined by +``is_gc_lvalue_expr``) produces an ``interior_ptr`` result. + +The C++/CLI unary operator ``%`` is scanned by +``scan_handle_address_operator``. It produces an ``eok_handle_to`` or +``eok_box`` operator. The result is a handle. + +The unary operator ``*`` is scanned by ``scan_indirection_operator``, producing +an lvalue or function designator as a result. + +``scan_arith_prefix_operator`` is called to scan the prefix operators ``+``, +``-``, ``~``, and ``!``. The unary version of the code in +``do_binary_operation`` (fold if constant by calling ``unary_operation`` in +``folding.c``, else build expression node) is included directly here, since +these are all of the normal unary operators. + +The ``sizeof`` operator is scanned by ``scan_sizeof_operator``, which calls +``is_decl_not_expr`` to decide whether or not the argument is a type name. If +it is, ``type_name`` is called to scan the type. If the argument is not a +type, it is scanned as a not-evaluated expression. The size of the type is +taken from the type entry in either case. + +``scan_alignof_operator`` is used to scan the ``__ALIGNOF__`` construct (an +extension; similar to ``sizeof``, but returns the alignment for a type instead +of its size). + +``scan_intaddr_operator`` is used to scan the ``__INTADDR__`` construct (used +in the ``offsetof`` macro to scan an address expression and cast it to integral +type). + +``scan_noexcept_operator`` scans the C++11 ``noexcept`` operator. + +``scan_typeid`` scans the ``typeid`` operator. It produces an expression node +of kind ``enk_typeid``. + +``scan_dynamic_cast_operator`` scans the ``dynamic_cast`` operator. Cases that +require runtime type determination are rendered as ``eok_dynamic_cast`` +expression nodes (or ``eok_ref_dynamic_cast``, for casts to reference types); +the other cases are turned into ordinary casts. + +``scan_static_cast_operator`` scans ``static_cast``. + +``scan_safe_cast_operator`` scans the C++/CLI ``safe_cast``. It's essentially +the same as ``static_cast`` except that it allows additional runtime-checked +cases, which are found by ``process_runtime_checked_safe_cast``. + +``scan_reinterpret_cast_operator`` scans ``reinterpret_cast``. + +``scan_const_cast_operator`` scans ``const_cast``. + +``scan_new_operator`` is used to scan the ``new`` operator. The ``new`` +operation is rendered as an ``enk_new_delete`` operator tagged as a "new", +whose supplement describes the operator ``new`` function to call plus +(optionally) some kind of initialization of the space allocated (for example, a +constructor call). For the C++/CLI ``gcnew``, an ``enk_gcnew`` is used, and +the supplement for that includes additional information, including an +initializer. For a ``gcnew`` of a C++/CLI array, the supplement contains both +information about the array bounds (either as explicitly provided, or deduced +from the number of elements in the initializer), and an aggregate initializer +for the array elements (the latter is scanned by ``scan_cli_array_init``). For +delegate initializers, ``scan_delegate_initializer`` scans the initializer, +which requires hand-coded checking because the delegate class doesn't have +constructors that accurately cover the allowed initializers. + +``scan_delete_operator`` is used to scan the ``delete`` operator. The +``delete`` operation is rendered as an ``enk_new_delete`` operator tagged as a +"delete", whose supplement describes the operator ``delete`` function to call +plus (optionally) a destructor to call on the space being deallocated. + +A left parenthesis can indicate a cast, a nested expression, or a C++17 fold +expression. ``scan_cast_or_expr`` is called for all cases. It uses +``is_decl_not_expr`` to decide whether or not the thing following the left +parenthesis is a type name. If it is, ``type_name`` is called to scan the +type, ``cast_type_pre_check`` to check the legality of the type, and +``do_cast`` to check and process the cast. For casts to void, an explicit +cast-to-void expression node is placed on top of the expression, as a special +marker for ``simplify_void_operand``, but no simplification is done at this +point. In ``pcc`` mode, certain casts of lvalues leave an lvalue as the result +(see ``still_an_lvalue``). If what is inside the parentheses is not a type, +``scan_expr_full`` is called to scan a nested expression or the first term of a +fold expression. If it turns out to be a fold expression (or the left +parenthesis was followed by an ellipsis, which also implies a fold expression), +``scan_fold_expression`` is called to scan the fold expression in either +generic form (during the prototype instantiation of the enclosing template) or +expanded form (during real instantiations). + +The postfix ``++`` and ``--`` operators are scanned by +``scan_postfix_incr_decr``. + +Subscripting is scanned by ``scan_subscript_operator``. The subscript is +represented by an ``eok_subscript`` operator. Constant subscripts are checked +for legality by ``valid_node_if_subscript`` or by the constant-folding +routines. When the first operand is a C++/CLI array, the contents of the ``[`` +... ``]`` are scanned as an expression list (no top-level comma operator is +allowed), and an ``eok_cli_subscript`` operator is used. Default indexed +properties, indexed properties, and ``operator[]`` functions can all be used to +implement the subscripting operation. Property rewrites are considered both +for the entire subscripted operation and for the first operand if it can be +converted to something subscriptable. + +Function calls are scanned by ``scan_function_call``. The function name is +entered as a default function if it is undefined (in C89 mode). The argument +list is scanned, and each argument is cast or default-promoted (see +``prep_argument_operand`` and ``arg_default_promote_operand``) appropriately. +The arguments are checked against the applicable function prototype or, if the +called function has an old-style declaration with a body, against the declared +old-style parameters. If the called function was declared with the pragma +``__printf_args`` or the pragma ``__scanf_args``, and the format string is a +constant, ``check_printf_scanf_arg`` is called for each argument following the +format string. It checks that the type of the argument matches the type of the +corresponding formatting specifier, and issues a warning if not. +``assemble_function_call`` and ``make_function_call`` are called to put +together the actual function call. If the function is a virtual function, a +different expression operator is used; the virtual call is suppressed if the +function was named with a qualified name or if the proper function to call can +be determined statically. If the function is an overloaded function, +``scan_call_arguments`` just builds a list of entries of type +``an_arg_list_elem`` that describe the arguments scanned. No checking can be +done on them until the specific function to be called is identified in overload +resolution. + +The operators ``->`` and ``.`` are scanned by +``scan_field_selection_operator``. After the right operand (a member name) is +scanned, the processing breaks apart into several cases: + +* | For nonstatic data members (C fields), ``do_field_selection_operation`` is + called; it in turn calls ``fold_field_selection`` to fold field selection + relative to a constant address to produce another constant address. The + expression operator generated is ``eok_dot_field`` or + ``eok_points_to_field``. +* | For nonstatic member functions, ``do_member_function_selection`` is called. + It produces an operand for a bound function, i.e., a function bound to a + selector object. +* | For static data members and static member functions, + ``combine_unneeded_selector_with_operand`` is called, and it generates an + ``eok_dot_static`` or ``eok_points_to_static`` operation. + +For nonstatic members, ``cast_pointer_for_field_selection`` is called to cast +the left operand pointer to a base class if necessary. + +The operators ``->*`` and ``.*`` are scanned by +``scan_ptr_to_member_operator``. For member function cases, the result is a +bound member function. For data member cases, an ``eok_pm_field or +eok_pm_points_to_field`` operation is generated. + +The operators ``*``, ``/``, and ``%`` are scanned by ``scan_mult_operator``. + +The operators ``+`` and ``-`` are scanned by ``scan_add_operator``. + +The operators ``>>`` and ``<<`` are scanned by ``scan_shift_operator``. + +The operators ``>``, ``<``, ``<=``, and ``>=`` are scanned by +``scan_rel_operator``, and the operators ``==`` and ``!=`` are scanned by +``scan_eq_operator``. + +The operators ``&``, ``^``, and ``|`` are scanned by ``scan_bit_operator``. + +The operators ``&&`` and ``||`` are scanned by ``scan_logical_operator``, and +the operator ``?`` (and the associated ``:``) is scanned by +``scan_conditional_operator``. When these operators have constant operands for +the boolean controlling expressions, some operands will be scanned as +not-evaluated expressions, and the result tree is (conditionally) simplified +accordingly. + +The operator "``,``" is scanned by ``scan_comma_operator``. Note that the +comma operator is not allowed at the top level in initializer expressions and +in argument lists, because it means something else in those contexts; see the +``local_options`` parameter of ``scan_expr_full``. + +``scan_simple_assignment_operator`` scans the operator ``=``. It calls +``prep_assignment_operand`` to check and convert the right operand in most +cases. Assignment to "``this``" is recognized as a special case and +allowed with a warning. + +``scan_compound_assignment_operator`` scans compound assignment operators +(``+=``, ``-=``, et al.). + +Lambda expressions are scanned by ``scan_lambda_expression``. The actual +parsing is handed to ``scan_lambda`` in ``class_decl.c``, and +``scan_lambda_expression`` constructs the required temporary initialization +from the resulting ``a_lambda`` entry. (See also :ref:`scanning-idents` for +special measures needed when parsing identifiers in a lambda body.) + +.. _expr-operands: + +Operand Data Structure +---------------------- + +Throughout the expression routines (and nowhere else), all the information +about an operand is maintained in an entry called ``an_operand``. The operand +contains the type of the operand, its "kind" (indicating the way in which the +operand is represented, i.e., as a constant or an expression tree), its "state" +(none, glvalue, prvalue, or function designator), and its source position. +Variables of type ``an_operand`` are typically stack-based variables within the +expression routines. They are never allocated in the intermediate language +memory region. + +An *lvalue* is an object in memory; an *rvalue* is a value, with no associated +memory location. The distinction between lvalues and rvalues is very important +in the C language. [#f1]_ Names of variables start out as lvalues, and if +their values are used, they are implicitly converted to rvalues. C++11 adds +*xvalues*, which are eXpiring values produced by certain rvalue reference +operations. They share an operand state with lvalues, since the two are very +similar (they have addresses, possibly cv-qualified types, dynamic type, object +identity). They can be distinguished with the ``is_an_lvalue()`` and +``is_an_xvalue()`` tests. Lvalues and xvalues are collectively known as +*glvalues*. The things formerly known as rvalues in C and in pre-C++11 C++ are +now known in C++11 as *prvalues*, and prvalues and xvalues collectively are now +known as rvalues. + +The expression scanning routines attempt to model the C++11 concept of "value +categories" exactly, and the ``an_operand`` entry plays a part in that. [#f2]_ +It is always clear from the operand whether an expression is currently an +lvalue, xvalue, or prvalue, and the transformation from glvalue to prvalue is +done deliberately and when appropriate (see ``conv_glvalue_to_prvalue``). + +For functions, the equivalent of an lvalue is a *function designator*, and +there is a representation for those in ``an_operand``. + +In the C++ language definition, the term "lvalue" includes C's function +designator as well as C's lvalue, but in this implementation and this +documentation we use the term with the narrower C meaning. + +When the operand representation is an expression, the operand points to an +expression tree in an intermediate language memory region. When the operand +representation is a constant, however, the constant is contained directly in +the operand (it is not allocated). This allows the expression routines to scan +constant expressions and fold them to constant results without allocating and +throwing away useless intermediate constant entries. + +When an operand represents a bound function, that is, a C++ member function +with an associated object, the operand has the ``bound_function`` flag set. A +second operand is used to describe the associated object. There's no direct +link between the two; the expression routines must carry around two operand +entries. + +When expressions appear in a comma-separated list, such as an argument list, +the operands on the list are often represented as entries of type +``an_arg_list_elem``. Such entries can represent either an expression (in +``an_operand`` form), or a brace-enclosed list, the latter being needed for the +C++11 "initializer lists" feature. + +The C++/CLI ECMA standard mentions the concept of a "gc-lvalue," and defines +conversions between normal lvalues and gc-lvalues. It turns out those concepts +are not needed, at least not in the suggested way, and no added kind of lvalue +is needed in ``an_operand`` entries. The important principle is that the +language must never allow the address of something that might be on the CLR +heap to be placed in a normal pointer where the garbage collector cannot find +it. So, whenever the address of something that might be in the CLR heap is +taken, the address must be placed in an ``interior_ptr`` or a ``pin_ptr``, both +which are visible to the garbage collector. The functions +``is_gc_lvalue_expr`` and ``is_gc_lvalue_operand`` test for lvalues that might +be in the CLR heap; if they return TRUE, the address of such an entity is made +an ``interior_ptr``. + +Primitive Operations on Operands +-------------------------------- + +Many routines exist to do primitive operations on operands. Routines that +perform initialization are + +* | ``set_operand_kind`` and +* | ``clear_operand``. + +Constructors for the various kinds of operands are + +* | ``make_constant_operand``, +* | ``make_string_constant_operand``, +* | ``make_integer_constant_operand``, +* | ``make_expression_operand``, +* | ``make_glvalue_expression_operand``, +* | ``make_indefinite_function_operand``, +* | ``make_sym_for_ptr_to_member_operand``, +* | ``make_lvalue_variable_operand``, +* | ``make_ptr_to_member_constant_operand``, +* | ``make_function_designator_operand``, and +* | ``make_field_operand``. + +Routines that create operands for one- and two-operand expressions are + +* | ``build_unary_result_operand`` and +* | ``build_binary_result_operand``. + +Error operands are created for parts of expressions containing errors by + +* | ``make_error_operand``, +* | ``conv_to_error_operand``, +* | ``error_in_operand``, and +* | ``error_and_make_error_operand``, + +which differ in whether or not they issue errors, and where. +``make_node_from_operand`` converts an operand to an equivalent expression +tree. + +Checking Operands +----------------- + +``op_is_zero_constant`` tests for a zero operand. There is also a set of +``check_...`` routines, which are called to verify that an operand has certain +attributes, and if not, issue an error and change the operand to an error +operand: + +* | ``check_modifiable_lvalue_operand``, +* | ``check_integral_operand``, +* | ``check_integral_or_enum_operand``, +* | ``check_integral_or_enum_or_fixed_point_operand``, +* | ``check_arithmetic_operand``, +* | ``check_pointer_operand``, +* | ``check_object_pointer_operand``, +* | ``check_function_pointer_operand``, +* | ``check_scalar_operand``. + +``check_boolean_controlling_expression`` checks that an expression controlling +a conditional is a scalar expression, and in C++ modes that don't disable the +``bool`` keyword, it converts the expression to ``bool``. + +Transformations on Operands +--------------------------- + +Several routines handle transformations on expressions defined by the standard: + +* | ``conv_glvalue_to_prvalue`` changes a glvalue to a prvalue. Several + special cases are handled. Type qualifiers on the glvalue type are removed + to make the prvalue type. Most of the work for expression cases is handled + by ``conv_glvalue_expr_to_prvalue``. ``conv_glvalue_to_prvalue`` calls + ``using_lvalue`` to do the error check for using the element just past the + end of an array; it also generates an error if it is called to convert a + glvalue in a constant expression. +* | ``conv_array_operand_to_pointer_operand`` changes an array to a pointer to + the first element of the array. +* | ``conv_function_designator_to_ptr_to_function`` changes a function + designator to a pointer to the function. + +``do_operand_transformations`` is a convenient way to request the preceding +three transformations. It can do any or all of them. + +Note that in C++ operand transformations often cannot be done until one knows +the way in which an expression will be used. In an expression like ``arr + +xx``, for example, with ``arr`` an array, one cannot convert the array to a +pointer until one has ruled out the possibility that this operation is an +overloaded use of operator "``+``" with a function for which the first +parameter is a reference to an array. In C, the transformations can often be +done earlier, but for ease of handling they are delayed as in C++. + +* | ``promote_operand`` handles the integral promotions (C standard, 6.3.1.1); + these are done only where explicitly called for. +* | ``determine_arithmetic_conversions`` handles the usual arithmetic + conversions (C standard, 6.3.1.8). In ``pcc`` mode, the promotions are + unsigned preserving (e.g., ``unsigned char`` is promoted to ``unsigned + int``), and all ``float`` operations are forced to ``double``. To + determine integral promotion types ``type_after_integral_promotions`` (in + ``types.c``) is called; a special case involving bit-fields is handled by + ``type_after_bit_field_integral_promotion``. +* | ``arg_default_promote_operand`` does the default argument promotions on an + operand (C standard, 6.5.2.2). +* | ``take_address_of_lvalue`` converts an lvalue to a prvalue pointer to the + object. This is the ``&`` operator for objects. It checks for taking the + address of a bit field or a register variable. + ``take_reference_to_operand`` does the similar operation for a reference + binding. + +When fixed-point types (an Embedded C extension described in ISO/IEC TR 18037) +are enabled, transformations of fixed-point operands are also performed as +needed. For example, in arithmetic operations involving both a fixed-point and +a floating-point operand the fixed-point operand is converted to a +floating-point type. However, unlike most other mixed-type operations, +operations involving a mix of fixed-point and integer operands do not cause the +conversion of the operands to a common type. + +The Expression Stack +-------------------- + +While expressions are being scanned, the expression routines maintain an +expression stack. This stack snakes through local stack frames (i.e., it is +not allocated via ``malloc``). The expression stack contains information on +the kind of expression being scanned, whether or not the expression is being +evaluated (e.g., the operand of a ``sizeof`` is not evaluated), and some other +minor information. + +There is a new stack entry for each major kind of expression scanned, but not +for each level in the expression. That is, if one started on a normal +expression, an entry would be placed on the stack; no new entries would be +added for parentheses or grouped operators in the expression; but if a sizeof +expression, or an integral constant expression in an array size in a type in a +cast, is reached, a new entry would be placed on the top of the stack. + +See ``push_expr_stack`` and ``pop_expr_stack``. + +Expression Lists and Initializer Lists +-------------------------------------- + +The C++ language, as of the C++11 revision, uses lists of expressions in two +contexts: + +* | argument lists of function calls (syntax term *expression-list*), for + example "``f(x, 2)``", and +* | initializer lists (syntax term *initializer-list*), for example + initializers of variables as in "``A a{x, 2};``". + +Those contexts at first glance might seem to have little in common other than +the fact that they involve lists of expressions. However, the standard ties +the use of variadic template pack expansions and the use of brace-enclosed +initializer lists to those expression-list contexts, and in some cases +initializer lists become argument lists for constructor calls. So, in the end, +it becomes appropriate and desirable to represent both kinds of expression +lists with the same data structure and to process them with many of the same +routines. + +The data structure used is ``an_init_component``, which can represent + +* | an expression, e.g., "``x``", in ``an_operand`` form, or +* | a braced-enclosed list, e.g., "``{1, 2, 3}``", as a pointer to a list of + init-component entries, or +* | a designator, e.g., an array element designation like "``[1]=``" in an + aggregate initializer, or +* | a continuation state to resume parsing when parsing of an initializer list + was suspended (see below). + +In initializer processing, e.g., in ``decl_inits.c`` and expression routines +that interface with that, the name ``an_init_component`` is used. In routines +that are more related to argument lists and overload resolution, on the other +hand, the name ``an_arg_list_elem`` is used instead. It's a typedef to the +same type, but it reflects a slightly different view of what the structure +represents. In practice, the line between the two is a bit fuzzy, and +especially with some lower-level routines the naming has to choose one or the +other name and is therefore somewhat arbitrary. Probably the main thing to +remember is that both names are used for the same data structure, with the +expression routines using the ``an_arg_list_elem`` name somewhat more often, +and the initializer routines using ``an_init_component`` exclusively. About +the only real difference that can be pointed out is that an argument list +referred to via ``an_arg_list_elem`` will never have a designator on the list. + +Init-component entries are linked together into lists and trees. Something +like "``{1, {2, 3, 4}}``", for example, creates a braced-init-list component +pointing to a list of two entries, the second of which is a braced-init-list +component pointing to a list of three expression components. + +The essence of the initializer lists feature in the language is that the same +notation can be used for initializations that are ultimately interpreted in +many different ways. Therefore, the handling of initializer lists inherently +involves a two-step process: first, parsing the source into a tree of +init-component entries, and then interpreting those entries by context as +describing calls and initializations of various kinds. At the simplest level, +the initializer processing calls ``scan_braced_init_list`` first to scan an +entire braced-init-list, and then ``convert_initializer`` to convert it to the +type of the entity being initialized. The real work in scanning +braced-init-lists is done by ``parse_braced_init_list_full`` and its +subroutines. + +In some cases the front end will process a very long braced initializer list in +parts to avoid tying up too much memory in init-component entries (which are +transient front end structures). It does this by suspending and resuming the +parsing of the initializer (repeatedly if needed) and using placeholder +init-component entries (of kind ``ick_continued``) that point to some state +information sufficient to resume parsing later on. This is fairly transparent +to the routines processing init-component entries, but requires that those +routines use macros like ``next_elem`` and ``is_last_elem`` rather than +directly access the ``next`` pointers of init-component entries. This is only +possible for traditional aggregate initializers, but it is a worthwhile +optimization because occasionally programs contain initializers with thousands +or even millions of elements. + +So some expression routines deal with an init-component (or list or tree of +them) as the "source" for an initialization. And some routines will scan an +expression or braced-init-list in init-component form to do lookahead, and then +place the init-component entry in an *initializer cache*, later to be fetched +out of there as if it had been freshly scanned from source. That's used, for +example, for declarations with "``auto``" type; an expression is scanned so its +type can be used for the ``auto`` type deduction, and the expression is then +put into the initializer cache so it will be picked up at the appropriate time +later. + +Because expression components are scanned at one point and then revisited later +for processing, some of the context information for them must be saved along +with the init-component entries. In particular, because it's not known at the +time of scan where the full-expression boundaries will fall, each expression is +scanned in its own invented lifetime, and is "bundled" with that lifetime in +the init-component. When the expression is removed from the list later for +additional processing, the lifetime is reactivated or subsumed into an existing +lifetime. Likewise, the cross reference entries associated with an expression +are detached from the current expression and saved in the init-component, and +then reactivated when the expression is processed further. This allows things +like tracking of whether a variable is ultimately used as an lvalue or rvalue. +(See ``scan_expr_as_init_component`` for the bundling code, and +``extract_operand_from_expression_component`` and +``unbundle_init_component_expressions`` for the unbundling.) + +The processing when a braced-init-list meets a destination type is handled by +``convert_initializer`` (callable from outside the expression routines) and +``prep_list_initializer`` (callable only from within the expression routines). +The latter does the real work. It has some significant subroutines: + +* | ``make_initializer_list_object`` makes an object of type + ``std::initializer_list`` from a braced-init-list, which involves a call + to a constructor of ``initializer_list`` passing an array containing the + element values. +* | ``value_initialization`` handles value-initialization, which is usually the + result when the braced-init-list is an empty list, "``{}``". +* | ``check_narrowing_conversion`` checks for the "narrowing" conversions, + issuing appropriate diagnostics. + +``prep_list_initializer`` operates in one of three modes: + +#. Producing ``an_operand result``. This is the usual mode for internal calls + in the expression routines. + +#. Guided by ``an_init_state``, producing either a dynamic init entry or a + constant as a result. This is the usual mode for calls that come from + initializer processing by way of ``convert_initializer``. This mode can + be modified to produce no diagnostics or generate no IL, which is used + for SFINAE analysis. + +#. Doing overload resolution analysis, producing a result in an entry of + type ``an_arg_match_summary``. That is used when evaluating arguments in + overload resolution, and in that mode no errors are issued, no IL is + generated, and the source init-components are not modified (in other + words, it's purely exploratory). + +All processing for aggregates, i.e., arrays and aggregate classes, is done by +code in ``decl_inits.c``. ``prep_list_initializer`` calls +``prep_aggr_initializer`` to handle aggregate initialization from a +braced-init-list, and the initializer processing routines will call back into +the expression routines as necessary. In certain cases, processing will hop +back and forth between the two areas repeatedly. In those cases, the +``an_init_state`` structure is used to convey information across the +transitions, e.g., to record something that expression processing knows so that +as the transfer or control goes to the ``decl_inits.c`` routines and back into +expression processing that information is still known. + +The expression routines have to be quite careful about whether they are dealing +with a single expression or (a member of) an expression list, and that is made +easier by using different structures to represent those, i.e., ``an_operand`` +for a single expression, and ``an_arg_list_elem`` for (a member of) an +expression list. There are some rare cases in the C++11 language where a +brace-enclosed list is allowed in a context where a single expression is +allowed, and in those cases ``an_operand`` of kind ``ok_braced_init_list`` is +constructed, which points to an init-component list. That allows a lot of the +existing routines to accept a braced-init-list in some limited cases. To give +one example, the assignment operators allow a braced-init-list as their second +operand, even though that's not an expression list context. So, if a +braced-init-list is present, it is scanned as an operand (see +``scan_braced_init_list_as_operand``) and passed around in that form to the +usual routines. When it gets to the operator-overloading routine +``check_for_operator_overloading``, that routine is prepared to unpack that +operand and use the braced-init-list in overload resolution. There are also +some cases when rescanning expressions (see below) where a braced-init-list +operand is constructed so that a braced-init-list can be returned through an +interface that is designed for single operand expressions. + +The ``an_arg_operand`` data structure, which in the past was used for operands +in argument lists, is now reserved for a few cases where a single +non-expression-list expression needs to be returned to a caller outside the +expression routines, specifically for nontype template arguments values. + +In most cases, there is no direct IL representation for initializer lists, +because when a braced-init-list meets a destination type it is converted to +some expression form that is no longer a braced-init-list. (For example, it +might become a dynamic init for a constructor call, or a nonconstant aggregate +dynamic init.) However, in prototype instantiations of templates there may be +braced-init-lists that have not met a real destination type and therefore +cannot be interpreted yet, and those must remain in braced-init-list form. For +those, the ``enk_braced_init_list`` expression node kind is used. It points to +a list of expressions, some of which may themselves be ``enk_braced_init_list`` +nodes. + +Constant Expressions +-------------------- + +Constant expression processing has two fairly different modes: + +#. In C mode, and in C++ mode prior to C++11, each constituent of an + expression is checked immediately to see whether it is allowed in a + constant expression. An error is issued if not. So, for example, the + appearance of a ``throw`` operator in a constant expression draws an + immediate error. Class-typed values are never allowed, and neither are + user-defined conversions. This mode is referred to as the "traditional + constant expression" mode (see, for example, + ``curr_expr_kind_is_traditional_const``). + +#. In C++11 (roughly, when ``constexpr_enabled`` is TRUE), what matters is + whether the expression overall folds to a constant, regardless of the + constituents of the expression. So, for example, "``1 ? 2 : i``" is a + valid C++11 constant expression: the reference to "``i``" is not + evaluated and does not rule out a constant expression. Class-typed + constant values (of "literal" type) are allowed, and so are user-defined + conversions using ``constexpr`` functions. This mode is referred to as + the constexpr mode. (A variation of that mode, known as "relaxed + ``constexpr`` mode", is enabled in C++14 mode. See also + :ref:`constexpr-and-expr-folding`.) + +In both modes, references to constant-valued variables and operations on +constant operands are folded as soon as they can be, [#f3]_ and a constant +value is passed up to the next level, so the basic processing is very much the +same. The main differences are: + +* | In traditional constant expressions, many operator-scan routines check + immediately on entry whether the operator they handle is valid, and issue + an error if not. In C++11 constant expressions, the check is done by + calling ``operator_not_allowed_in_cpp11_constant_expr`` (or + ``construct_not_allowed_in_cpp11_constant_expr``), which issues no error in + unevaluated parts of expressions. +* | Various routines that handle looking for user-defined conversions (e.g., + ``check_user_defined_conversions_for_cast``) allow user-defined conversions + when ``constexpr_enabled`` is TRUE. +* | Calls, including constructor calls, can be folded to constants. This is + done by first building the normal IL for the call and then, if the function + or constructor involved is ``constexpr``, seeing whether the call can be + folded to a constant. This is done by ``expr_fold_constexpr_call`` and + ``expr_fold_constexpr_ctor``. Implicit calls, like conversion function + calls, can also be folded to constants. If backing expressions are being + recorded, the original IL for the call is recorded as the backing + expression for the result constant. +* | Both modes require tracking, in non-constant expressions, of whether the + expression makes use of anything not allowed in a constant expression. + [#f4]_ In traditional constant expressions, the kinds of expressions ruled + out are tracked at the ``an_operand`` level (see the + ``ruled_out_expr_kinds`` set and the ``rule_out_expr_kinds`` routine), and + for specific kinds of constant expressions (e.g., integral constant + expressions). In C++11 constant expressions, a single boolean flag called + ``constant_expr_ruled_out`` is maintained in the expression stack, and + there's effectively only one kind of constant expression. (Note, however, + that in C++11 mode some kinds of expressions are scanned as traditional + constant expressions, e.g., preprocessor expressions and nontype template + argument address expressions, because the C++11 language rules still impose + many restrictions on the kinds of operators that can be used in them.) + | In certain contexts, the rules about what is ruled out are relaxed + slightly. Specifically, in contexts that will later be subject to + parameter substitution in ``constexpr`` call evaluation, a use of the value + of a parameter variable does not rule the expression out as a potential + constant expression (because in a real evaluation, the parameter might have + a constant value). Those contexts (the return expression of a + ``constexpr`` function, the mem-initializers of a ``constexpr`` + constructor, and the field initializers of a literal class) are identified + by ``in_potential_constant_constexpr_context``. + | When init-components are used, expression processing is often done in two + steps: first, the expression is scanned into an init-component, and then + the init-component is converted to the final required type. In those + cases, the ``constant_expr_ruled_out`` flag is copied from the expression + stack into the init-component, and then back from the init-component to the + expression stack when the conversion processing is started. +* | In several contexts, the C++11 standard calls for a "converted constant + expression" of a given type (for example, an array bound is a converted + constant expression of type ``size_t``). This is implemented by + ``process_converted_constant_expression``. The required type can be a + specific type, like ``size_t``, or a general category of types, like + integral types. In traditional constant expressions, that routine just + scans a constant expression and converts it as necessary, not allowing + user-defined conversions. In C++11 mode, it allows user-defined + conversions but imposes a restriction on the types of implicit conversions + allowed at the end (e.g., not "narrowing" conversions). The C++11 rules + are therefore broader overall but more restrictive in certain cases. The + set of allowed implicit conversions is defined by + ``impl_converted_constant_expr_conversion_possible``. +* | ``constexpr`` calls and constructions in constant expressions produce a + constant result directly, i.e., not a temporary initialized by a constant, + but other temporaries (e.g., a temporary needed to bind "``const int &``" + to an integer constant ``2``) are created as usual. Processing within + folding fetches the value out of the temporary if appropriate, or creates a + special compile-time temporary using a ``ck_address/abk_temporary`` + constant that holds the necessary constant value. Operations that cannot + be converted to those forms are left as initialization of a temporary, + which is considered non-constant. + +.. _rescanning-exprs: + +Rescanning Expressions +---------------------- + +The C++11 standard introduced some new rules for template deduction (see +`WG21 paper N2634 +`__). +When a function template is considered in overload resolution, part of the +process is "template deduction," which is an attempt to find values for the +template parameters of that template that will specify a template instance +that is a viable function for the call. The deduction rules require that +any expressions that appear in the template type be valid after +substitution of the deduced template arguments for the template parameters. +Whereas in older versions of the standard "valid" was defined by a specific +list of requirements, and only relatively simple expressions were allowed, +the C++11 rules now allow arbitrarily complex expressions inside +unevaluated contexts (e.g., ``sizeof`` and ``decltype``), and "valid" is +defined by the normal semantic rules of the language, except that access +checking is not done. So, for example: + +.. code:: c++ + + template auto f(T p1, T p2) -> decltype(p1 + p2) { + return p1 + p2; + }; + struct A { + const A & operator +(const A&); + }; + A a1, a2; + int main() { + f(a1, a2); + } + +Here, the call is valid only if the expression "``p1+p2``" is valid, which is +true only if there is a valid meaning for the "``+``" operator, possibly found +by doing overload resolution as in this case. Any error detected during this +process should cause only a failure of deduction for that template, and not a +hard error. (This idea is summarized in the acronym that is often used to +refer to this non-error-producing deduction process, SFINAE, which stands for +Substitution Failure Is Not An Error.) + +To implement this, the Front End is capable of "rescanning" expressions to redo +the semantic checking on them. An expression saved during the initial scan of +a template is copied, with substitution of template argument values for +template parameters, and is then passed through the normal +expression-processing routines in order to do everything that would have been +done to that expression after scanning it from source tokens. A key part of +the infrastructure for performing that is that almost all operator-scanning +routines have an ``rcblock`` parameter, which can be used to pass in a rescan +control block. When that parameter is non-NULL, it gives information about the +expression to be rescanned, the template arguments and template parameters, and +some options. The operator scan function tests ``rcblock`` each time it is +about to get something from source tokens, and when ``rcblock`` is non-null it +instead uses the previously-scanned IL expression to produce the same +information in the same form. That information then passes through the parts +of the operator routine that handle semantic checking, implicit conversions and +transformations, etc., undergoing exactly the processing it would have received +if scanned from source. + +Because IL expressions don't contain all the information that was available +when the expression was originally scanned, additional information (in the form +of ``an_expr_rescan_info_entry``) is saved whenever an expression is scanned in +a context that might later be subject to a rescan (essentially, in function +template headers). That rescan information includes a copy of the +``an_operand`` entry that represented the IL expression, and a bit of +additional information like the operator source position. + +When deduction is being done, if ``expr_is_rescannable`` is true for an +expression, it is passed to ``rescan_expr_with_substitution_internal``, which +determines the operator-scanning function that corresponds to the top operator +of the expression (see ``operator_token_for_expr_rescan``) and then calls that +operator-scanning function. The scanning function will then do substitution +and rescanning on its operands (see ``make_rescan_operands``), followed by the +semantic checking and processing it usually does, before returning an operand +back to its caller, which will continue through the rescan process. If an +error occurs, the error flag in the rescan control block is set, and once the +processing returns to the top level the deduction fails. + +The expression rescanning code co-exists with the older code that handled +SFINAE processing for many years before this change, e.g., routines like +``copy_template_param_expr``. Those routines are still used when new-style +SFINAE is turned off (see ``cpp0x_sfinae_enabled``), and also for parts of +expressions that aren't rescannable. + +For braced-init-lists, a copy of the original list in init-component form is +saved in the rescan info operand (see +``save_rescan_info_for_braced_init_list``). On the rescan, that list is +rescanned. As with all rescans, the source of the rescan is mined for +source-like information, and a lot of other information is ignored. That +means, for rescanned braced-init-lists, that the original list is not modified +or really "used" -- it's a guide for the rescan as opposed to a source of +expression operands to be used directly. + +Making rescanning work requires some special coding conventions in +expression-processing routines: + +#. The error-reporting routines cannot be called directly. Instead the + corresponding routines beginning with "``expr_``" must called. So, for + example, instead of "``pos_error``" one must call + "``expr_pos_error``". This allows the interception of error calls so + that they set a flag in the expression stack instead of issuing an + error. + +#. Code that checks access must be conditional on + ``expr_access_checking_should_be_done()``. Note that it's usually + necessary to avoid the access checks altogether rather than doing them + and getting to the point where an error would be issued, in order that + complete and correct IL is generated. + +#. Calls out to utility routines in other parts of the front end must not + generate errors (unless those errors come from handling something + outside of the expression; for example, it's okay to issue an error out + of a template instantiation that is kicked off by the expression + processing). If those utility routines might generate errors, they must + have parameters that can be used to get an error return instead of + having an error issued. For an example, see ``binary_operation`` in + ``folding.c`` and its ``error_detected`` parameter. + +#. Scanning routines for added operators must have an ``rcblock`` + parameter, to indicate the rescan. Within such routines, all processing + that deals with source tokens must have a rescan alternative that pick + up the information from the expression being rescanned. As a general + guideline, beware of using ``curr_token``, ``pos_curr_token``, + ``end_pos_curr_token``, ``locator_for_curr_id``, + ``const_for_curr_token``, ``curr_construct_ end_position``, + ``error_position``, and the error-reporting routines that use an implied + position. + + Near the end of the scanning routine, call + ``record_operator_position_in_rescan_info`` to record the operator + position in the rescan information for the expression. + + The scanning routine should be added to + ``operator_token_for_expr_rescan`` and + ``rescan_expr_with_substitution_internal`` so it will be rescannable. If + an operator scanning routine is not added to those routines, it will not + be rescannable, and if it comes up in a deduction context the deduction + will simply fail. That may be acceptable for certain kinds of + operators. + +#. Note that none of these restrictions are necessary for features used + only in C mode, but may be desirable anyway to allow the option of using + that feature in C++ mode at some later date. + +Void Expressions +---------------- + +When a void expression has been scanned, either by ``scan_void_expression`` or +as the first operand in ``scan_comma_operator``, ``simplify_void_operand`` is +called to trim off any parts of the expression that have no effect. This +trimming is done very conservatively, however. Top-level casts to ``void`` are +removed. Other kinds of trimming could be done, but they are not in the +interest of preserving the source expression. ``simplify_void_operand`` issues +a warning for expressions that have no overall effect. (See +``node_has_side_effects``.) + +Expressions that are explicitly cast to void are not processed as void +expressions at the time of the cast; a cast-to-void node is placed on top of +the expression, and the expression is handed up. If the node makes it up to +the top level, it is simplified and the cast-to-void node is removed. Casts to +void can remain in the final intermediate language, but only in rare cases +(such as + +.. code:: c++ + + i>0 ? (void)f(1) : (void)g(2) + +as a statement). + +Type Conversions +---------------- + +Type conversions happen implicitly (in assignments and initializations) and +explicitly (in casts). Either way, they are done under control of the +expression routines. And they must be: in C++, conversions involve not just +the type of an expression, but whether it is and stays an lvalue or an rvalue, +and whether or not other implicit transformations may be done. The data +structure that can express these concepts is ``an_operand``, and it exists only +within ``expr.c``, ``exprutil.c``, and ``overload.c``. + +To scan and process an expression correctly, one needs to know what will +ultimately be done with it, specifically what type it will be converted to. +Therefore, in all cases involving conversion, all necessary information about +the destination is passed into the expression routines, and they take care of +the conversion. By the time the expression is returned to the caller, it has +the correct type. + +The routines that control these conversions have names beginning with +"``prep_``": + +* | ``prep_conversion_operand`` deals with the general assignment or + initialization case. +* | ``prep_initializer_operand`` deals with initialization. Its interesting + special case is initialization of references. +* | ``prep_elision_initializer_operand`` deals with initialization of entities + with class types that have constructors, where it may be possible to avoid + a copy constructor call. +* | ``prep_argument_operand`` deals with initialization when it applies to + arguments. Its interesting special case is generating copy constructor + calls for class values passed by value. +* | ``prep_return_by_cctor_operand`` deals with expressions in ``return`` + statements (also considered an initialization case), specifically in + routines that return class values by calling a copy constructor. A dynamic + initialization entry describing the initializing operation is built and + returned to the caller. +* | ``prep_assignment_operand`` deals with the right-side expressions in + assignments. + +In general, these routines do their work in two parts: + +* | They determine whether or not the source operand can be converted to the + destination type, and if so, how. This is done by calling + ``conversion_possible``. +* | If the conversion is valid, they do it, by calling ``convert_operand``. + +``conversion_possible`` uses ``impl_conversion_possible`` (from ``types.c``) to +see if a standard conversion if available to do the conversion); if not, it +calls ``user_defined_conversion_possible`` to see if a user-defined conversion +can be done. + +``user_defined_conversion_possible`` calls ``conversion_to_class_possible`` to +check for constructors and ``conversion_from_class_possible`` to check for +conversion functions that might be applicable. + +``convert_operand`` calls ``cast_operand`` for simple conversions, and +``user_convert_operand`` for user-defined conversions. + +``cast_operand`` and ``cast_node`` are called to change the type of an +operand or expression node. (``cast_operand`` is actually just a wrapper +on top of ``cast_operand_full``, which does the real work.) The caller of +those routines must have already determined that the conversion is valid. +If the cast is implicit and if it does not change the type of an operand, +that operand is usually left alone. (An exception are casts on bit fields, +because a bit-field access that has no cast on it has slightly different +properties -- especially with respect to promotion -- from the same access +with a cast on top.) + +If the operand is a constant, ``type_change_constant`` is called to fold the +conversion. + +If the operand is an expression, ``add_cast_to_node`` is called to add a cast +to the expression tree. For casting a pointer-to-class to a +pointer-to-related-class it calls ``add_base_class_casts`` or +``add_derived_class_casts``, and for the similar cases involving pointers to +members, it calls ``add_pm_base_class_casts`` or +``add_pm_derived_class_casts``. + +The routines that scan explicit casts use several lower-level routines: + +* | ``check_user_defined_conversions_for_cast`` looks to see if a cast performs + any user-defined conversions, and if so applies them. +* | ``set_up_for_cast_to_reference`` does some checking and setup in the cases + where the cast is to a reference type. +* | ``cast_operand_for_reference_cast`` is like ``cast_operand``, but for cases + where the operand is being cast to a reference type (including an rvalue + reference type). +* | ``generic_cast_operand`` performs a cast when either the source operand or + the destination type involves something template-dependent in a prototype + instantiation. In such cases, it's not generally possible to know what the + cast does, and we just want to put a generic representation of it in the + IL. + +In C++/CLI, string literals start out as standard C++ string constants, and are +converted to C++/CLI strings if the context requires it. So, for example, if a +standard string literal is passed as an argument to a function that takes a +parameter of type "``System::String``\ ``^``", the string will be converted to +a C++/CLI string. This is done by setting the constant type to "handle to +``System::String``" without setting the ``implicit_cast`` flag. There is no +conversion of the characters in the string to Unicode (or in any other way), in +spite of what the ECMA standard seems to require. Wide string literals can +also be converted to C++/CLI strings in this way, and in that case the string +contents are treated as Unicode (as they always are in Microsoft mode, and +therefore in C++/CLI mode; but still no conversion is done). Having C++/CLI +strings represented as constants is a little strange, since ultimately they +have to result in creation of a class object on the heap, and use of its -- +non-constant -- address. However, MSVC treats such strings as constants, so +representing them that way makes it easier to emulate MSVC's behavior. See +``literal_type_convertible_to_cli_string``, +``is_literal_convertible_to_cli_string``, and +``convert_operand_to_handle_to_cli_string``. + +C++/CLI also allows boxing and unboxing conversions, i.e., between a value of a +value type and (a handle to) a boxed value in the CLR heap. Boxing can be +either an implicit conversion or a cast; unboxing is always done explicitly by +a cast. Operands having fundamental types will be implicitly converted to a +boxed value in cases where a class is required, e.g., in an example like +"``(3).toString()``", or when they are implicitly converted to an appropriate +handle type. Significant routines for boxing and unboxing are +``is_boxable_type``, ``add_box_to_expression``, ``add_unbox_to_expression``, +``box_value_type_operand``, and ``unbox_after_indirection_if_required``. + +Temporaries +----------- + +``create_expr_temporary`` creates an ``enk_temp_init`` node that defines a +expression temporary. It hangs a dynamic initialization entry under that node +and, if the temporary will require a destructor call, puts the destructor +information in the dynamic initialization entry. + +``alloc_dtor_dynamic_init`` is the routine that actually allocates the dynamic +initialization entry for the temporary. If the temporary is within the +expression in a return statement in a routine that returns its value via a copy +constructor, the destructor routine is recorded in the dynamic initialization +entry, but the destructor routine is not marked as referenced. This is because +the topmost initialization in the return expression should not indicate a +destructor (the caller does the destruction), but one cannot know at the time +the dynamic initialization entry is created whether or not it will end up being +the topmost one. Therefore, all entries are given destructors, but the +destructor routines are not marked as referenced. Each such dynamic +initialization is placed on a fixup list. After the entire expression is +processed, the destructor indication is cleared in the topmost initialization, +and ``fix_up_dynamic_init_dtors`` is called to revisit the dynamic +initialization entries and mark the (remaining) destructors as referenced. + +``temp_init_from_operand`` creates a temporary variable and initializes it from +a given operand value. + +``convert_operand_into_temp`` creates a temporary variable and initializes it +from a given operand value where there might be type conversion involved. + +Note that the temporary closure object resulting from a lambda expression is +not represented with an ``enk_temp_init`` node; the ``enk_lambda`` node itself +represents the temporary (it points to an associated dynamic initialization +entry). + +Copy Constructor Elision +------------------------ + +In cases where a class entity is being initialized, it is often possible to +avoid calling a copy constructor: + +.. code:: c++ + + struct A { A(int) {...}}; + A xx = 1; // A::A(int) + +The constructor in that case can be used to directly initialize the variable +``xx``. It's not necessary to initialize a temporary with that constructor and +then copy the temporary to ``xx`` using a copy constructor. The process of +avoiding the unnecessary copy constructor call is called *copy constructor +elision*. + +``determine_dynamic_init_for_class_init`` is the routine that checks for the +possibility of copy constructor elision. It attempts to find a constructor or +other routine that can do the initialization directly. Failing that, it +returns a copy constructor. + +If a copy constructor call is elided, the copy constructor must still exist. +To confirm its existence and accessibility ``handle_elided_copy_constructor`` +is called. + +Selector Operands +----------------- + +A function call like + +.. code:: c++ + + p->f(xx); + +is processed by (1) scanning ``p->f`` and generating a pair of operands (one +for the object, one for the function) bound together, then (2) processing the +call. Between the first step and the second, the selector operand for the +object is carried around alongside of the (primary) operand for the function. + +If the function being called is a nonstatic member function (which would be the +usual case), the selector must sometimes become a pointer to an object rather +than an lvalue or rvalue for the object. ``conv_operand_to_object_pointer`` +does that transformation. + +``conv_selector_to_object_pointer`` also does that transformation but has a +flag indicating whether or not the object has been turned into a pointer, so +that the transformation is not done more than once. + +``conv_object_pointer_to_lvalue`` does the transformation in the other +direction. + +It is noteworthy that the addresses of class prvalues can be taken. The +language does not allow the addresses of other kinds of prvalues to be taken. +However, the addresses of class objects are needed in order to do copy +constructor calls, member function calls, and base/derived class casts. The +language hints that all class prvalues might really be temporary variables of +class type, and that therefore it is possible to take their addresses. +Accordingly, the front end generates temporaries for class prvalues, including +cases when functions return class values. The routine +``conv_class_prvalue_operand_to_object_pointer`` can turn an expression for a +class prvalue back into a pointer to the class object, usually by finding the +``enk_temp_init`` node that defines the temporary and flipping the +address/value flag in that node back to "address." + +Overloaded Function Calls +------------------------- + +Overloaded function calls can be explicit calls or they can be implicit in +contexts that involve user-defined conversions (constructors or conversion +functions). In either case, the process of overload resolution must be done. +It involves considering an argument list and a set of overloaded functions, +selecting the function that best matches the argument list, then adjusting the +types of the arguments so that they are appropriate arguments for the function +selected. + +The argument list is represented as a list of entries of type +``an_arg_list_elem``, with each entry containing either an expression in +``an_operand`` form or a brace-enclosed list. + +Each function in the overload set is considered in turn to see how well it +matches the argument list. If all of the arguments can be made to match the +function parameters, the function is added to a candidate functions list (see +type ``a_candidate_function``). Under that entry is a list of entries that +describes how well each argument matches the function's corresponding formal +parameter. + +After all the functions are considered, ``select_best_candidate_functions`` is +called to select the function(s) with the best argument matches. For each +argument, it forms the set of functions that match best on that argument; then +the intersection of those best-match sets is formed. If the intersection has +just one function, it is the best-matching function. However, it must still be +compared to all the other functions to verify that the chosen function is +better in some argument position than each of the other functions (though not +necessarily on the same argument position for each function). After the +candidate functions list has been trimmed to a list of best-matching functions, + +* | If there are no functions on the list, an error is issued: no function is + appropriate. +* | If there is more than one function on the list, an error is issued: several + functions are appropriate, so the call is ambiguous. +* | If there is exactly one function on the list, that is the function to call. + The arguments are converted to the proper parameter types and the call is + generated. + +``compare_arg_match_levels`` compares two argument match summaries and +determines which of the two is a better match. Often, this is just a matter of +comparing the match levels. However, one of the overload resolution rules says +that if one match is a subsequence of the other (for certain cases), the +shorter sequence is the better match; this is the routine that implements that +rule. When comparing two matches at the same level, it looks to see if either +one is a subsequence of the other, and if so, the shorter sequence is called a +better match. The functions ``compare_argument_tiebreakers`` and +``compare_standard_conversions`` are called to do most of the work. + +There are several tie-breakers that will select one function over another when +the argument matches are equally good for the two functions. See +``compare_candidate_functions``. + +If function templates are involved in the overload resolution, the candidate +functions set is built more or less as described above. After an initial check +that the number of arguments matches the number of parameters, +``function_template_call_argument_deduction`` is called to do template +parameter deduction for the call. If deduction is possible, it returns a list +of template argument values and a routine type with the template argument +values substituted for the corresponding template parameters. This routine +type (which is a normal routine type containing no template parameters) is then +used for the rest of the overload resolution process. If the function name was +accompanied by a set of explicit template arguments (e.g., ``f(1)``), the +explicit template argument list is passed to the deduction routines and those +template parameters are not deduced. +``function_template_call_argument_deduction`` calls ``matches_template_type`` +to do the actual deduction. After the list of candidate functions has been +built, ``select_best_candidate_functions`` considers the template candidates +alongside the non-template functions. If a template function is chosen as the +best function, ``find_template_function`` is called to build the instance of +the function, and the template function routine is then used as the result of +the overload resolution. + +When template-dependent name lookup is enabled, some special processing is +done. If, in a prototype instantiation, the argument list contains an +expression of template-dependent type, overload resolution cannot be done. A +special "unknown dependent function" indication is returned to the caller. If, +in a prototype instantiation, the argument list contains no dependent +expressions, the call is a "non-dependent call" according to the standard. +Overload resolution is done, and the function selected is recorded (in +association with the token sequence number of the position of the call or +overloaded operator) by calling ``record_nondependent_call``. Then, in a real +instantiation of the template, ``get_nondependent_call_info`` is called to +retrieve the information, if any, recorded for a given call. If there is +information associated with the call, the call is non-dependent and the +function previously determined by overload resolution is used again (overload +resolution is not done). + +There are several things that are done during the processing of a +non-overloaded call that cannot be done at that point during the processing of +an overloaded function call, because it's not known which specific function +will be called. Once overload resolution has been done, those things are done +by ``overloaded_function_catch_up``: + +* | Check access to the function if it is a class member. +* | Record reference information for the function called. +* | Check that the return type of the function is not incomplete. + +The casting of the arguments to the proper types is also a "catch-up" function. + +``select_overloaded_function`` is the top-level routine for overload +resolution. To find the best match it calls ``try_overloaded_function_match``, +which first calls ``determine_arg_match_level`` to see how well the arguments +match (for the selector object, it uses ``selector_match_with_this_param`` +instead) and then calls ``select_best_candidate_functions`` to pick the best +function from the list of viable functions. + +``set_up_overload_set_traversal``, ``next_symbol_in_overload_set``, +``set_up_overload_symbol_list_traversal``, and +``next_symbol_in_overload_symbol_list`` are used to set up and traverse +overload sets (the first two for normal sets, and the second two for sets +introduced by symbol lists, e.g., argument-dependent lookup or conversion +functions). + +``determine_arg_match_level`` implements the argument matching rules of the +language. An argument can match at any of the following levels: + +.. list-table:: + + * - | ``aml_exact`` + - | Exact match or trivial conversions. + * - | ``aml_promotion`` + - | Match with promotions. + * - | ``aml_std_conversion`` + - | Match with standard conversions. + * - | ``aml_boxing_conversion`` + - | Match with boxing conversion (C++/CLI only) + * - | ``aml_user_conversion`` + - | Match with user-defined conversions. + * - | ``aml_ellipsis`` + - | Match with ellipsis. + * - | ``aml_error`` + - | Match with error type (not in ARM). + * - | ``aml_none`` + - | No match. + +C++/CLI adds a few additional complexities: + +* | Parameter arrays, where zero of more arguments at the end of the argument + list can be bundled together into a CLI array of values passed to a final + parameter with a parameter array type. Such a match is worse than other + matches except for an ellipsis match. Parameter arrays are also handled + when template type deduction is done. +* | Overload sets are formed using hide-by-sig lookup. + ``use_hide_by_sig_lookup`` is called on a function symbol to see whether + hide-by-sig lookup applies (it only applies to members of managed classes), + and to build a list, attached to the symbol, of the symbols that should be + in the overload set for that symbol. The overload set traversal routines + ``set_up_overload_set_traversal`` and ``next_symbol_in_overload_set`` + determine whether the symbol requires hide-by-sig lookup, and traverse the + hide-by-sig list if so, skipping any inaccessible functions. Since + hide-by-sig applies only to member functions, it never has to co-exist with + argument-dependent lookup. + +User-defined Conversions +------------------------ + +``conversion_to_class_possible`` looks for a constructor or conversion function +that will convert an expression to a particular class type, and +``conversion_from_class_possible`` looks for a conversion function that will +convert an expression from a class type to a specific other type or to a +built-in type from a given set. These use ``try_overloaded_function_match`` +for the constructor cases, and ``try_conversion_function_match_full`` for the +conversion function cases. + +Conversion functions that return reference types are a little tricky in that +their results are lvalues or xvalues, but that falls out more or less naturally +from the fact that operand transformations (like glvalue to prvalue) are put +off as long as possible. When the result of a conversion is to be bound to a +reference, the kind of reference (lvalue reference or rvalue reference) +constrains the choice of suitable conversion functions. + +C++/CLI adds static conversion functions. Those can convert to a class in +addition to from a class, and can also convert to/from a handle to a class or +tracking reference to a class. Therefore, places that look for conversion +functions must also look in the destination class for conversion functions, and +in the base classes of the source type, and must also consider handles to be +class-like as both source and destination types of a conversion, because the +classes underlying those handle types may have static conversion functions. +See ``try_static_conversion_function_match`` and +``cli_handle_user_defined_conversion_possible``. + +Operator Overloading +-------------------- + +``check_for_operator_overloading`` looks for operator overloading +possibilities. It is called only when one or more of the operands of an +operator has a class or enum type [#f5]_. It considers three ways of +processing the operands: + +#. As arguments of an operator member function. + +#. As arguments of an operator function that is not a member function. + +#. As operands of the built-in version of the operator, with the operands + converted from the class types to acceptable built-in types by use of + conversion functions. This is not tried for operators that have a + built-in meaning for classes ("``,``", "``->``", "``=``", and unary + "``&``"). + +As with overload resolution for function calls, the overloaded operator +resolution process considers each of the alternatives (functions and built-in +operator) in turn and builds a list of candidate functions. After all the +alternatives have been examined, the best one is selected (or an error is +issued). The operands are then adjusted to match the function or built-in +operator that was selected. + +``try_overloaded_function_match`` is called (possibly several times) to +determine how well the operator functions match the operands. +``opname_member_function_symbol`` is used to find the applicable member +functions (if any), and ``nonmember_operator_function_lookup`` is used to find +the applicable nonmember functions (if any); special processing is done for +those if the operand types come from namespaces. + +``try_conversions_for_builtin_operator`` is called to try to find conversions +that will allow use of the built-in version of the operator. Its subroutines +-- ``operand_type_pattern_for_operator``, ``try_builtin_operands_match``, and +``try_pointer_builtin_operands_match`` -- do the necessary investigation. + +C++/CLI adds some additional issues: + +* | When the first operand is a handle, it is overloadable much as if it had + the underlying class type. An expression like "``h+x``" can be treated as + "``h->operator+(x)``". +* | When either operand is a handle, it may be possible to use a static + conversion function to convert the operand to a fundamental type for which + there is a builtin version of the operator, much as is done for class + operands. +* | Static operator functions can apply. They don't have a "``this``" + parameter, so the first operand matches the first parameter, and the + second operand (if there is one) the second parameter. "``a+b``" could + become "``X::operator+(a,b)``". These are also searched for in the + class of the second operand, if there is one and it has class type. +* | Operator synthesis can be done. If a class does not have an + "``operator+=``", for example, the combination of an "``operator+``" and an + "``operator=``" can be used. +* | In certain cases, string literals can act as if they are handles to + ``System::String``, which then makes them overloadable. + +Address of Overloaded Function +------------------------------ + +When an overloaded function appears in an expression, it is represented an as +indefinite function operand, which is basically just an operand that points to +the overloaded function symbol. + +When such an operand is subjected to the function-to-pointer transformation, +the operand stays an indefinite function, but changes from a function +designator to a prvalue pointer. + +When such an operand shows up in a conversion where the destination type is a +function pointer, ``find_addr_of_overloaded_function_match`` is called to find +out which (if any) of the specific functions matches the required function +pointer. The operand is then converted to the specific function pointer in +``cast_operand_full``; ``overloaded_function_catch_up`` is called to do +whatever would have been done had it been known all along which specific +function was intended. + +If the overload set includes one or more template functions, the resolution +algorithm is as follows: + +#. If there is an exact match in the set of non-function-templates, it is + selected (if there is more than one, the pointer use is ambiguous); + otherwise, + +#. If there is a template function from which a function can be generated + that will match exactly, it is selected (if there is more than one, the + pointer use is ambiguous); otherwise, + +#. If there is a non-exact match in the set of non-function-templates, it is + selected (this can only happen with pointers to member functions, where + an implicit conversion from base to derived is allowed). + +``matching_template_function`` is called to attempt to find a match under rule +(2). + +Range-based ``for`` statement +----------------------------- + +The C++11 range-based ``for`` statement is checked and assembled by +``check_range_based_for_statement``. It determines which of the three +"patterns" is applicable for the statement and calls +``check_range_based_for_array_case``, ``check_range_based_for_member_case``, or +``check_range_based_for_default_case`` as necessary to perform the necessary +semantic checks and generate the IL. + +The range-based-for statement takes the form: + + | ``for (`` *for-range-declaration* ``:`` *expression* ``)`` *statement* + +and is defined to be equivalent to: + + | ``{`` + | ``auto && __range = (``\ *expression*\ ``);`` + | ``for ( auto __begin =`` *begin-expr*\ ``,`` + | ``__end =`` *end-expr*\ ``;`` + | ``__begin != __end;`` + | ``++__begin ) {`` + | *for-range-declaration* ``= *__begin;`` + | *statement* + | ``}`` + | ``}`` + +Lower level routines for handling variable initializer expressions, member +lookup, overload resolution, etc. are shared (where applicable) with the +for-each statement handling described below (together the range-based ``for`` +and for-each statements are referred internally as "enhanced ``for``" +statements). + +For-each Statement +------------------ + +The C++/CLI for-each statement is checked and assembled by +``check_for_each_statement``. There are four "patterns" for the for-each +statement (the STL pattern, the CLI collection pattern, the CLI array pattern, +and the native array pattern). ``check_for_each_statement`` determines the +pattern matched by a given loop, and calls the right one of four routines, each +charged with checking one of the patterns and building the IL. + +The for-each statement is defined in terms of a rewrite for each of the +patterns. For example, a for-each loop that matches the native array pattern +is rewritten from + + | ``for each (``\ *T t* ``in`` *c*\ ``)`` *statement* + +to + + | ``{ C &cref =`` *c*\ ``;`` + | ``I *cend = &cref[0]+``\ *c_num_elements*\ `;`` + | ``I *i = cref;`` + | ``for (; i != cend; ++i) {`` + | *T t* ``= static_cast<``\ *T*\ ``>(*i);`` + | *statement* + | ``}`` + | ``}`` + +The IL for this case contains variables and associated scopes for the iterator +variable and the added temporary variables, initializer expressions for each of +those, and additional expressions for the loop ``!= and ++`` expressions. +Those are relatively simple in this case, but in other cases and other patterns +the generated expressions can be complex, and developing them may involve +member lookup, overload resolution, operator overloading, or user-defined +conversions. The front end's goal is to provide IL that completely describes +the actions needed to implement the loop, while at the same time retaining the +parts in a high-enough-level form that source-analysis programs can discern the +original loop variables and expressions. + +Properties +---------- + +Microsoft mode has properties, which are data members of classes that are +implemented by accessor functions, e.g., one to get the current value of the +property, and one to set the current value of the property. Properties come in +two kinds: + +* | Old-style properties, indicated by the ``__declspec(property(``... )) + attribute. The accessor functions are only loosely associated with the + property, by being named in the attribute. +* | New-style properties in C++/CLI, which begin with the "``property``" + context-dependent keyword. The accessor functions are declared as part of + the property declaration, in a form that looks vaguely like a nested class. + +In both cases, the IL has a description of the property declaration, in +something close to the source form (that information is held in +``an_property_or_event_descr`` entry). However, also in both cases, references +to the properties are expanded by expression processing, so they are not +retained in source form. A bit of source code like "``p``\ ``+=``\ ``1``" +might be expanded into a series of calls something like "call the get accessor +for ``p``, call ``operator+`` on the fetched value and 1, and call the put +accessor to store the computed value." The generated IL contains some tags on +various nodes in the expansion that help source-analysis code recover the +original meaning, though in a cumbersome way. + +Property references cannot be rewritten immediately. They have to be carried +around for a short while in expression processing until it becomes clear from +the context how the property is being used, i.e., a "get" or a "set". Before +they are rewritten, property references are carried around as ``an_operand`` +entries of kind ``ok_property_ref``. The operand can include a list of +subscripts that is part of the property reference. Once the context is +established, the property reference is rewritten; that's handled by +``rewrite_property_reference``. As hinted at above, some rewrites are more +complicated than a simple "get" or "set", and might involve a "get", some +operation on the fetched value, possibly surrounded by conversions, and finally +a "set". That happens for compound assignment operators and for pre- and +post-increment and -decrement operators. In such cases, the operand is cloned +(see ``clone_operand``), so that it will only be evaluated once, and +``rewrite_property_reference`` is called twice, once for the "get" and once for +the "set". + +C++/CLI events are very similar to the new-style properties, in representation +and in the fact that references are expanded by the front end. + +C++/CLI Generics +---------------- + +Expression processing for C++/CLI generics, meaning handling of expressions +during the scanning of a generic definition, mostly falls out of normal +expression processing. During the generic definition, the parameters of the +generic (represented as template parameters) are given values that are +generated class types that reflect the constraints on the generic parameters. +So, for example, if a generic parameter is constrained to derive from an +interface I, the generated class type will be such that it will be possible to +look up members of I in the class and find them in a base class that is I. +That makes most operations work without special handling. Also, for many +cases, the template parameter's value is a handle to the constraint class type, +so that operations like assignment work because they become handle assignments +instead of class assignments (where it might not be possible to know whether +the class will have an appropriate ``operator=`` at runtime). There are a few +special cases with casting, where a generic parameter might or might not be a +value class type, or might or might not effectively be a handle at runtime. +Casts are rejected if they might be invalid because they treat a value type as +a handle, or vice-versa. Also, casts are rejected if it can be shown at +compile time that the source value type can never satisfy the constraints of +the destination type. + +Reference Information +--------------------- + +To track references to identifiers, ``ref_entry`` is called for each identifier +reference in an expression. The information provided is used to write +cross-reference information (when requested) and to set the referenced, used, +modified, and address-taken flags in variable and routine entries. For some +identifiers, the kind of reference is known immediately, so +``record_symbol_reference`` is called to record the information. For others, +the kind of reference is dependent on the expression context, and therefore it +is not known immediately. For such cases, an entry called ``a_ref_entry`` is +allocated and placed on a list of such entries for the current expression. +When the reference kind becomes known, the kind in the entry is updated (see +``change_ref_kinds``). At the end of the expression, +``flush_ref_entries_list`` is called. It scans the entries on the list, calls +``record_symbol_reference`` to record the (now fully determined) reference, and +then frees the entries. + +Diagnostic output +----------------- + +Diagnostic output in the expression-processing routines must be handled +specially in order that it be possible to suppress diagnostics when rescanning +an expression during template deduction. For that reason, what would normally +be simply a call of a diagnostic-output routine must be slightly more +complicated in the expression-processing source files. For the simpler +diagnostics, there are direct ``expr_`` equivalents: + +* | For ``pos_error``, use ``expr_pos_error``. +* | For ``pos_warning``, use ``expr_pos_warning``. +* | For ``pos_diagnostic``, use ``expr_pos_diagnostic``. +* | For ``syntax_error``, use ``expr_syntax_error``. + +Other diagnostic calls should be enclosed in a test of +``expr_error_should_be_issued`` or ``expr_diagnostic_should_be_issued``, as +appropriate. + +Any access-checking code must be conditioned on +``expr_access_checking_should_be_done``. It's not enough to simply surround +access-error diagnostic calls with a suppression test; when template deduction +is being done, it must be as if no access checking is even attempted, and the +flow of control must continue as if the error were not present. + +Folding of Constant Operations +============================== + +There are four main files involved in folding constant operations: + +* | ``const_ints.c`` contains the code for low-level integer operations, with + ``const_ints.h`` containing associated declarations. +* | ``fixed_pt.c`` contains the code for low-level fixed-point operations, with + ``fixed_pt.h`` containing associated declarations. +* | ``float_pt.c`` contains the code for low-level floating-point operations, + with ``float_pt.h`` containing associated declarations. +* | ``folding.c`` contains the higher-level code that handles folding of + constant operations and of type conversions on constants. ``folding.h`` + contains associated declarations. Code for folding of ``constexpr`` calls + and operations is also here. + +Low-level Integer Routines +-------------------------- + +``const_ints.c`` contains the routines that manipulate low-level integers. Any +integer literal constant in the source program and any operation on constant +integers implied by the source program are ultimately handled by the routines +here. For the most part, the low-level integer form can be viewed as a +representation for target machine integers on the host machine, although it is +also used for some things (like array dimensions) that are only arguably target +machine constants. + +The point of these routines is to collect all the code that operates on target +integers in one place, so that it can be modified if necessary, and so that the +rest of the front end does not need to deal with the subtleties of signed and +unsigned representations, overflow, etc. + +There are two different possible representations for integer values (type +``an_integer_value``): + +* | If there is some host integer type that is big enough to hold any target + integer (the usual case), an integer value is simply represented as a host + integer. Operations on that representation are done using the host C + operators, with extra overflow checking. If the host C compiler supports + ``long long``, that type can be used as the representation type. +* | Otherwise (for example, in a cross-compiler for a 64-bit target running on + a 32-bit host), an integer value is represented as a ``struct`` containing + an array of small integers (of type ``an_int_value_part``). Operations on + that representation are simulated in software. + +(See configuration constant ``INTEGER_VALUE_REPR_IS_A_HOST_INTEGER``.) + +The ``an_integer_value`` representation may be used to represent signed or +unsigned quantities. It is not self-identifying in that regard, i.e., the +representation does not contain an indication of the signedness of the value. +Therefore, in cases where signedness is significant, (e.g., multiplication), +the caller must pass in a separate argument indicating the signedness to be +used for the integer value. For values that can be represented in both the +signed and unsigned forms, the representation in the two forms is the same. +That allows small constants to be used as either signed or unsigned quantities +as the need arises. + +The ``const_ints.c`` routines deal with integer values as single-sized +entities, the size being large enough to hold any of the target integer types. +The routines check for overflow relative to that representation, but they know +nothing of different integer types and their sizes. + +Most routines in ``const_ints.c`` operate on values in the ``an_integer_value`` +form. For convenience, some routines are provided that operate on the IL +``a_constant`` form, but it's a circumspect use of that form: as far as the +routines are concerned, ``a_constant`` is a structure that only contains +``an_integer_value`` (in the variant ``integer_value`` field) and a type (in +the ``type`` field) that can be passed to ``int_constant_is_signed`` to +determine the signedness of the value. No other fields of the constant need be +defined. + +The routines that are used to translate between ``a_host_large_integer`` (some +large built-in host integral type) and the ``an_integer_value`` form are + +* | ``set_integer_value``, +* | ``set_unsigned_integer_value``, +* | ``value_of_integer_constant``, and +* | ``unsigned_value_of_integer_constant``. + +Routines used to get attributes of integer values are + +* | ``get_integer_size_and_alignment`` and +* | ``int_constant_is_signed``. + +Utility routines used to determine the magnitude of an integer value, create a +bit mask, and sign-extend a value are + +* | ``bits_required_to_represent_integer_constant``, +* | ``make_integer_value_mask``, and +* | ``sign_extend_integer_value``. + +Routines used to format integer values in decimal string form are + +* | ``str_for_integer_constant``. + +Routines used to compare integer values (including some comparisons against the +limits of integers of given kinds) are + +* | ``cmp_integer_values``, +* | ``cmp_integer_constants``, +* | ``cmplit_integer_value``, +* | ``cmpulit_integer_value``, +* | ``in_range_for_integer_kind``, +* | ``le_max_value_for_integer_kind``, and +* | ``is_max_value_for_integer_kind``. + +On these, the two values being compared may have independent signedness. The +``lit`` routines do comparison against ``a_host_large_integer`` or +``a_host_large_unsigned`` value, typically a small constant. + +Routines used to perform arithmetic and logical operations are + +* | ``add_integer_values``, +* | ``subtract_integer_values``, +* | ``multiply_integer_values``, +* | ``divide_integer_values``, +* | ``remainder_integer_values``, +* | ``and_integer_values``, +* | ``or_integer_values``, +* | ``xor_integer_values``, +* | ``shift_left_integer_values``, +* | ``shift_right_integer_values``, and +* | ``complement_integer_values``. + +On these, the two operands must have the same signedness (except that there are +versions of the add and subtract routines for the independent-signedness +cases). The result of the operation overwrites the first operand. + +For some kinds of values, it's just too much of a nuisance to use the integer +value routines, so the front end converts such values to +``a_host_large_integer`` or ``a_host_large_unsigned`` (which are typically +signed and unsigned ``long``, or signed and unsigned ``long long``) and +operates on them in that form. The values handled that way are: + +* | Sizes of objects, including arrays (conceptually of type ``size_t`` on the + target). +* | Offsets relative to objects (conceptually of type ``ptrdiff_t`` on the + target). +* | Single characters (but not a character constant containing one or more + characters). +* | Single ``wchar_t`` values. + +Note that the target ``size_t`` and ``ptrdiff_t`` are allowed to be bigger than +the host ``a_host_large_integer``; the use of ``a_host_large_integer`` +representation just restricts the possible constant values of that type that +the front end can deal with. The conversions into the host types are done with +overflow checking, so the front end will issue errors for values larger than +those it can accommodate. + +Low-level Fixed-point Routines +------------------------------ + +The routines in ``fixed_pt.c`` manipulate the internal repreentation of +fixed-point constants on the host machine. As with the integer routines, they +are collected in one place so that they can be changed more easily and so that +the front end at large need know nothing about the fixed-point representation. + +They implement very low-level operations on the internal form of fixed-point +constants. Some of the standard product versions of these routines (e.g., for +conversion of a decimal text form of a fixed-point constant to internal form) +are not always accurate to the last significant bit: They are best viewed as +prototype routines for testing purposes, to be replaced by real routines for +the production version. + +The main routines (or macros) in ``fixed_pt.c`` are the following: + +* | ``cmp_fixed_point_constants`` +* | ``fxp_init_value`` +* | ``fxp_value_is_zero`` +* | ``fxp_string_to_fixed_point`` +* | ``fxp_hex_string_to_fixed_point`` +* | ``conv_fixed_point_to_fixed_point`` +* | ``conv_integer_to_fixed_point`` +* | ``conv_fixed_point_to_integer`` +* | ``conv_float_to_fixed_point`` +* | ``conv_fixed_point_to_float`` +* | ``fxp_to_string`` +* | ``fxp_add`` +* | ``fxp_subtract`` +* | ``fxp_multiply`` +* | ``fxp_divide`` +* | ``fxp_compare`` +* | ``fxp_hash`` + +Low-level Floating-point Routines +--------------------------------- + +The routines in ``float_pt.c`` manipulate target floating-point constants on +the host machine. As with the integer routines, they are collected in one +place so that they can be changed more easily and so that the front end at +large need know nothing about the floating-point representation. + +They implement very low-level operations on the internal form of floating-point +constants. When ``USE_HOST_FP_CONVERSION_ROUTINES`` is TRUE (the default), +binary to decimal conversions are performed using standard UNIX conversion +routines provided by the host. When ``USE_HOST_FP_CONVERSION_ROUTINES`` is +FALSE, internal routines (in ``floating.c``) are used to perform these +conversions. Arithmetic operations are performed without range checking; +therefore, they are best viewed as prototype routines for testing purposes, to +be replaced by real routines for the production version. + +In cases where the target configuration supports floating-point types that are +not supported by the host compiler (e.g., ``__float128`` and ``__float80`` on +Windows), the `Berkeley SoftFloat library +`__ can be used to perform +arithmetic operations on the host. This configuration can be selected by +setting the ``USE_SOFTFLOAT`` configuration macro to TRUE. In such +configurations, the ``USE_HOST_FP_CONVERSION`` routines is automatically set to +FALSE to enable a software-only floating-point configuration. Note that +such configurations are inherently slower than those that use floating-point +hardware. See the SoftFloat web site for licensing information. + +The main routines in ``float_pt.c`` are the following: + +* | ``fp_change_kind`` +* | ``fp_string_to_float`` +* | ``fp_hex_string_to_float`` +* | ``fp_to_string`` +* | ``fp_long_to_float`` +* | ``fp_unsigned_long_to_float`` +* | ``fp_to_host_large_integer`` +* | ``fp_to_host_large_unsigned`` +* | ``fp_is_zero_constant`` +* | ``fp_add`` +* | ``fp_subtract`` +* | ``fp_multiply`` +* | ``fp_divide`` +* | ``fp_compare`` +* | ``fp_hash`` + +Constant Folding +---------------- + +The routines in ``folding.c`` do folding of constant operations and type +conversions on constants. + +This folding is done in target machine arithmetic. For integers, routines in +``const_ints.c`` do the actual operations on the generic integer value, but the +routines here add a layer that understands specific integer types, and does +overflow checking, masking, and sign extension according to the size and +signedness of the integer type. For fixed-point and floating operations, +target-specific code in ``fixed_pt.c`` and ``float_pt.c`` does the actual +operations. For pointer operations, the constants are either address constants +(a base symbol plus a byte offset) or integer constants cast to a pointer type +(the most common of these is ``NULL``/0). The routines ``get_pointer_offset`` +and ``set_pointer_offset`` are used to extract and set the offsets in both +those cases. + +The folding routines detect errors and warnings and call the error routines to +report them. When they are called in nonconstant contexts (like executable +statements), errors are downgraded to warnings, and the operation is left +unfolded, to be tried at runtime. + +If the folding routines are unable to fold an operation to a constant (because +of some attribute of the operands, not because of an error), they return a flag +``did_not_fold`` set to TRUE, which tells the caller to leave the operation +unfolded. For example, the pointer difference of pointers to different static +objects is a constant, but one that is unknowable until link time. +``did_not_fold`` would be returned TRUE for that case (and no error or warning +would be indicated). The folding routines also record the unfolded expression +in constants resulting from the folding. + +``unary_operation`` and ``binary_operation`` are the top-level routines for +operations on constants. They take as input an operator and one or two +constants, and produce a constant (or an error indication) as output. The +operations are done with all necessary checking for overflows, etc. The +routines called by ``unary_operation`` to do the actual folding are + +* | ``do_inegate``, +* | ``do_fxnegate``, +* | ``do_fnegate``, +* | ``do_xnegate``, +* | ``do_complement``, and +* | ``do_not``, + +and those called by ``binary_operation`` are: + +* | ``do_iadd``, +* | ``do_isubtract``, +* | ``do_imultiply``, +* | ``do_idivide``, +* | ``do_remainder``, +* | ``do_shiftr``, +* | ``do_shiftl``, +* | ``do_icompare``, +* | ``do_and``, +* | ``do_or``, and +* | ``do_xor`` + +for integers; + +* | ``do_land`` and +* | ``do_lor`` + +for scalars; + +* | ``do_fxadd``, +* | ``do_fxsubtract``, +* | ``do_fxmultiply``, +* | ``do_fxdivide``, and +* | ``do_fxcompare`` + +for fixed-point; + +* | ``do_fadd``, +* | ``do_fsubtract``, +* | ``do_fmultiply``, +* | ``do_fdivide``, and +* | ``do_fcompare`` + +for floating-point; + +* | ``do_xadd``, +* | ``do_xsubtract``, +* | ``do_xmultiply``, +* | ``do_xdivide``, +* | ``do_jmultiply``, +* | ``do_jdivide``, and +* | ``do_xcompare`` + +for complex and imaginary; + +* | ``do_padd``, +* | ``do_pdiff``, and +* | ``do_pcompare`` + +for pointers; and + +* | ``do_pmcompare`` + +for pointers to members. + +Actual shifting is performed by ``do_shift``, which calls ``check_shift_count`` +for error checking. The shifting is implemented with the integer size and +sign-extension appropriate for the target. + +When pointer addition or subtraction is folded, the resulting constant, if an +address constant, is checked to see if the offset lies within the base object. +Offsets beyond the end of the object and negative offsets are flagged with a +warning (most often, this is due to a constant subscript out of bounds). This +is checked by ``valid_address_constant``. + +In ordinary constant folding, ``valid_address_constant`` will allow the +position just past the end of an object without a warning, since it does not +know whether the address of that position is required (which is allowed by ANSI +C) or the value (which is an error). The routine ``using_lvalue`` calls +``valid_address_constant`` again to check for the error once it is known that +it is the value that is being accessed. + +``type_change_constant_full`` changes the type of a constant to something else. +It's usually called through the simpler interface ``type_change_constant``. It +has subroutines + +* | ``conv_integer_to_integer``, +* | ``conv_integer_to_float``, +* | ``conv_float_to_integer``, +* | ``conv_float_to_float``, +* | ``conv_pointer_to_whatever``, +* | ``conv_integer_to_pointer``, +* | ``conv_ptr_to_member_to_ptr_to_member``, and +* | ``conv_integer_to_ptr_to_member``. + +with the obvious functions. Warnings about truncation and hidden changes of +sign are issued (the latter are suppressed if the type change was the result of +an explicit cast or if the operand was a non-decimal constant). + +Casts of pointers to classes to pointers to base or derived classes are handled +by + +* | ``fold_base_class_cast`` and +* | ``fold_derived_class_cast``. + +The similar cases for pointers to members are handled by + +* | ``fold_pm_base_class_cast`` and +* | ``fold_pm_derived_class_cast``. + +``fold_field_selection`` is called to fold a field selection relative to a +constant address. Because of the unusual second operand (a field rather than a +constant), ``binary_operation`` could not be used for this case. If the field +is a bit field, ``fold_field_selection`` returns a ``did_not_fold`` flag. + +``constant_glvalue_address`` and its companion routine +``constant_prvalue_pointer`` examine expression trees to determine if they +represent constant addresses, computing and returning the appropriate constant +value on the fly. + +.. _constexpr-and-expr-folding: + +Folding and ``constexpr`` +------------------------- + +C++11 and C++14 permit calls to ``constexpr`` functions and constructors in +constant-expressions. To implement this, the front end includes an IL +interpreter implemented in the source file ``interpret.c``. The start of that +file contains extensive comments describing the overall structure of the +interpreter. The global variable ``relaxed_constexpr_enabled`` is TRUE +when the C++14 version of the ``constexpr`` feature is enabled. This enables +the interpretation of expressions, like assignments, with side-effects (valid +in C++14, but not C++11). It also removes C++11 structural constraints for +``constexpr`` functions and constructors (e.g., it allows multiple statements +in definitions). + +To avoid burdening the IL or the rest of the front end, the interpreter does +not record state information in the IL or other front end structures. Instead, +it maintains its own data structures linked to the IL through efficient hash +tables. It does, however, use front end types to represent integral and +floating-point values. Other kinds of values (e.g., addresses) are represented +using interpreter-specific structures. + +The interpreter can fold calls to ``constexpr`` functions and constructors, but +it can also more generally fold expressions and dynamic initializations. + +The entry points into the interpreter are ``interpret_expr,``\ +``interpret_dynamic_init,``\ ``interpret_constexpr_call,`` and +``interpret_constexpr_ctor``. These functions return a boolean value +indicating whether interpretation succeeded (TRUE) or failed (FALSE). +Interpretation can fail because it encountered an operation not permitted +during ``constexpr`` evaluation (e.g., a virtual function call), including +operations with undefined behavior (e.g., attempting to fetch a value from +uninitialized storage). It can also fail when the cost of interpretation +becomes too high. The parameters limiting that cost can be set through the +command-line options ``--max_depth_constexpr_call`` and +``--max_cost_constexpr_call``. If interpretation fails, the interpreter also +returns a diagnostic description indicating the reason for the failure (that +description can be emitted as part of the diagnostic if a constant was +required). + +.. [#f1] Note that the C standard does not actually have an rvalue concept, + though it has lvalues. This is a difference from K&R. However, the + distinction between an rvalue and a non-lvalue is almost nonexistent. + It has to do with some strange cases (like ``sizeof``) that allow + unevaluated non-lvalues. For simplicity, the term "rvalue" is used, + but what is actually implemented by the front end is the ANSI C + non-lvalue. +.. [#f2] Following the implementation of C++11 value categories in version + 4.8, the front end has tried to use the C++11 terms in general + internally. That caused a lot of renaming of routines and fields; for + example, ``conv_lvalue_to_rvalue`` became ``conv_glvalue_to_prvalue``. + Ugly until you get used to it, but very helpful in reminding you to + consider xvalues when you write code that deals with expressions. +.. [#f3] Meaning, more or less, when the glvalue-to-prvalue conversion is done + on the operand. Constant-valued variables are replaced by their + values at that point, and member access and subscripting operations, + and pointer dereferences, produce constant values only when the + glvalue addressing expression is converted to a prvalue. +.. [#f4] This is used, for example, for the initializer expression on a + const-typed variable; the initializer is not required to be a constant + expression, but if it is, the variable is usable as a constant. So + the expression is scanned as a normal (non-constant) expression, and + if it produces a constant value and does not violate the rules for a + well-formed constant expression, the variable is a constant. +.. [#f5] Actually, it is also called -- during prototype instantiations -- when + at least one operand has a template-dependent type. In that case, it + generates a generic expression and returns without doing overload + resolution. diff --git a/dev/doc/_sources/ext_intf.rst.txt b/dev/doc/_sources/ext_intf.rst.txt new file mode 100644 index 0000000..77754c4 --- /dev/null +++ b/dev/doc/_sources/ext_intf.rst.txt @@ -0,0 +1,5681 @@ +================== +External Interface +================== + +Bear in mind that this information applies to the standard product. If any +local modifications are made, the documentation given to users must be adjusted +accordingly. + +.. _cli: + +Command Line +============ + +The front end is invoked by a command of the form + + ``edgcpfe [``\ *options*\ ``]`` *ifile* + +to compile the single input file *ifile*. If ``-`` (hyphen) is specified +for *ifile*, the front end reads from ``stdin``. [#f1]_ No particular +file name suffix is required on input files. + +Command line options may be specified using either single character option +codes (e.g., ``-o``) or keyword options (e.g., ``--output``). A single +character option specification consists of a hyphen followed by one or more +option characters (e.g., ``-Ab``). If an option requires an argument, the +argument may immediately follow the option letter, or may be separated from the +option letter by white space. A keyword option specification consists of two +hyphens followed by the option keyword (e.g., ``--strict``). Keyword options +may be abbreviated by specifying as many of the leading characters of the +option name as are needed to uniquely identify an option name (for example, the +``--wchar_t_keyword`` option may be abbreviated as ``--wc``). If an option +requires an argument, the argument may be separated from the keyword by white +space, or the keyword may be immediately followed by ``=``\ *argument*. When +the second form is used there may not be any white space on either side of the +equals sign. + +If the configuration flag ``COMPILE_MULTIPLE_SOURCE_FILES`` is defined as TRUE, +a list of files may appear for *ifile*. If a list of files is specified, +options that specify a compilation output file (``--output``, ``--list``, and +``--xref``) may not be used, and the name of each source file is written to the +error output file as the compilation of that file begins. + +When one of the preprocessing-only modes is specified (see below), the +``--output`` option can be used to specify the preprocessing output file. If +``--output`` is not specified, preprocessing output is written to ``stdout``. +Preprocessing output has trigraphs and line splices processed (and thus they do +not appear in their original form). + +When compilation (rather than just preprocessing) is done, the output (if any) +from the compilation is written to a file selected by the back end; see the +documentation of the back end for further information. For versions of the +front end that generate an intermediate language file, the ``--output`` option +can be used to specify the IL output file. + +The *options* are described in the following subsections (organized by +category). + +Language Dialect Options +------------------------ + +The following options select among various C and C++ dialects. + +.. list-table:: + + * - | ``--anachronisms`` + | ``--no_anachronisms`` + - | Enable or disable anachronisms in C++ mode. The default for this + option is specified by ``DEFAULT_ALLOW_ANACHRONISMS``. This option is + valid only in C++ mode. + * - | ``--c`` + | ``-m`` + - | Enable compilation of C rather than C++. + * - | ``--c89`` + - | Enable the compilation of the C89 version of C. + * - | ``--c99`` + | ``--no_c99`` + - | Enable or disable compilation of the C99 version of C. In either + case, C rather than C++ is compiled. + * - | ``--c11`` + - | Enable language features added in the C11 standard. This option + cannot be combined with options enabling or requiring a C++ mode. + * - | ``--c18`` + | ``--c17`` + - | Enable support for C18 (which is only a minor "bug fix" change from + C11). This option cannot be combined with options enabling or + requiring a C++ mode. + * - | ``--c23`` + - | Enable language features added in drafts of the anticipated C23 + standard. This option cannot be combined with options enabling or + requiring a C++ mode. + * - | ``--old_c`` + | ``-K`` + - | Enable K&R/pcc mode, which approximates the behavior of the standard + UNIX ``pcc``. ANSI/ISO C features that do not conflict with K&R/pcc + features are still supported in this mode. + * - | ``--c++`` + | ``-p`` + - | Enable compilation of C++. This is the default. + * - | ``--c++03`` + - | Enable compilation of C++ as specified by the ISO/IEC 14882:2003 + standard by explicitly disabling all C++11 features, regardless of + their configured default values (but individual C++11 features can be + enabled on the command line). This option implicitly enables C++ mode + and can be combined with the options enabling strict ANSI/ISO + conformance, as well as other emulation modes (e.g., ``--microsoft``, + ``--g++``). + * - | ``--c++11`` + | ``--no_c++11`` + | ``--c++0x`` + | ``--no_c++0x`` + - | Enable or disable extensions added in the C++11 standard. This option + is only valid in C++ mode and can be combined with the options + enabling strict ANSI/ISO conformance. + * - | ``--c++14`` + - | Enable language features added in the C++14 standard. This option + cannot be combined with options enabling or requiring a C mode. + * - | ``--c++17`` + - | Enable language features added in the C++17 standard. This option + cannot be combined with options enabling or requiring a C mode. + * - | ``--c++20`` + - | Enable language features added in the C++20 standard. This option + cannot be combined with options enabling or requiring a C mode. + * - | ``--c++23`` + - | Enable language features added in the C++23 standard. This option + cannot be combined with options enabling or requiring a C mode. + * - | ``--c++26`` + - | Enable language features added in drafts of the anticipated C++26 + standard. This option cannot be combined with options enabling or + requiring a C mode. + * - | ``--cfront_2.1`` + | ``-b`` + - | Enable compilation of C++ with compatibility with cfront version 2.1. + This causes the compiler to accept language constructs that, while not + part of the C++ language definition, are accepted by the AT&T C++ + Language System (cfront) release 2.1. This option also enables + acceptance of anachronisms. + * - | ``--cfront_3.0`` + - | Enable compilation of C++ with compatibility with cfront version 3.0. + This causes the compiler to accept language constructs that, while not + part of the C++ language definition, are accepted by the AT&T C++ + Language System (cfront) release 3.0. This option also enables + acceptance of anachronisms. + * - | ``--c++cli`` + | ``--no_c++cli`` + | ``--cppcli`` + | ``--no_cppcli`` + | ``--clr`` + - | Enable or disable compilation of C++/CLI source. This option implies + Microsoft C++ mode; it cannot be combined with options that are + contrary to such a mode (e.g., forcing strict mode) or with the option + ``--microsoft_version`` with a value less than 1600. + * - | ``--c++cx`` + | ``--no_c++cx`` + | ``--cppcx`` + | ``--no_cppcx`` + - | Enable or disable compilation of C++/CX source. This option implies + Microsoft C++ mode; it cannot be combined with options that are + contrary to such a mode (e.g., forcing strict mode) or with the option + ``--microsoft_version`` with a value less than 1600. Support for this + mode is preliminary and will be improved in future versions of the + front end. + * - | ``--clang`` + | ``--no_clang`` + - | Enable or disable clang C or C++ language compatibility features. + This option also enables the GNU C or C++ language compatibility + features. It is only recognized when ``GNU_EXTENSIONS_ALLOWED`` is + TRUE. As of this writing, the only effect of clang mode apart from + enabling GNU emulation is to enable the feature-test macros like + ``__has_feature``. + * - | ``--clang_version`` *version-number* + | + - | The version of the clang compiler that should be emulated. Version + x.y.z of the clang compiler is encoded as x*10000+y*100+z (e.g., + version 3.4.1 is emulated with the option "``--clang_version + 30401``"). + * - | ``--embedded_c`` + | ``--no_embedded_c`` + - | Enable or disable support for all Embedded C language extensions + (fixed-point types, named address space qualifiers, and named-register + storage class specifiers). These options are not available with C++ + modes. + * - | ``--embedded_c++`` + - | Enable the diagnosis of noncompliance with the "Embedded C++" subset + (from which templates, exceptions, namespaces, new-style casts, RTTI, + multiple inheritance, virtual base classes, and ``mutable`` are + excluded). + * - | ``--g++`` + | ``--no_g++`` + - | Enable or disable GNU C++ language compatibility features. This + option also specifies that the source language being compiled is C++. + It is only recognized when ``GNU_EXTENSIONS_ALLOWED`` is TRUE. + * - | ``--gcc`` + | ``--no_gcc`` + - | Enable or disable GNU C language compatibility features. This option + also specifies that the source language being compiled is C. It is + only recognized when ``GNU_EXTENSIONS_ALLOWED`` is TRUE. + * - | ``--gnu_version`` *version-number* + | + - | The version of the GNU compiler that should be emulated in any of the + GNU (C or C++) modes. Version x.y.z of the GNU compiler is encoded as + x*10000+y*100+z (e.g., version 3.4.1 is emulated with the option + "``--gnu_version 30401``"). + * - | ``--microsoft`` + | ``--microsoft_16`` + | ``--no_microsoft`` + - | Enable or disable Microsoft emulation mode. These options may only be + used if ``MICROSOFT_EXTENSIONS_ALLOWED`` is TRUE. ``--microsoft`` + enables 32-bit mode. ``--microsoft_16`` enables 16-bit mode (i.e., + support for ``near`` and ``far``; the option is accepted only if + ``NEAR_AND_FAR_ALLOWED`` is TRUE). The default values are supplied by + ``DEFAULT_MICROSOFT_MODE`` and ``DEFAULT_NEAR_AND_FAR_ENABLED``. In + Microsoft emulation mode, language features that are not recognized by + the Microsoft compiler are disabled by default. In most cases these + features can then be enabled through use of other command line options + (for example, ``--bool``). Microsoft bugs mode is also enabled when + ``DEFAULT_MICROSOFT_BUGS`` is TRUE. + * - | ``--microsoft_version`` *version-number* + - | The version of the Microsoft compiler that should be emulated in + Microsoft mode. This enables or disables particular Microsoft mode + features when the acceptance of those features varies between versions + of the Microsoft compiler. The value specified is the value of the + predefined macro ``_MSC_VER`` supplied by the version of the Microsoft + compiler to be emulated. For example, 1100 is the value that + corresponds to Visual C++ version 5.0. This option also enables + Microsoft mode, but it does not imply either 16-bit or 32-bit mode + (i.e., it uses whatever value has already been specified, or the + default value if none has been explicitly specified). + * - | ``--microsoft_build_number`` *build-number* + - | The "build number" of the Microsoft compiler that should be emulated + in Microsoft mode (this option also enables Microsoft mode). This + value is used to set the value of the predeclared macro + ``_MSC_FULL_VER`` (which is a concatenation of the microsoft version + number and the build number; e.g., with "``--microsoft_version 1600 + --microsoft_build_number 30507``" ``_MSC_FULL_VER`` is defined to + expand to ``160030507``). The default build number is 99999. + * - | ``--microsoft_bugs`` + | ``--no_microsoft_bugs`` + - | Enable or disable recognition of certain Microsoft bugs. These + options also enable Microsoft mode. Microsoft bugs mode is + automatically enabled when Microsoft mode is used and + ``DEFAULT_MICROSOFT_BUGS`` is TRUE. + * - | ``--ms_await`` + - | Emulate the Microsoft Visual Studio ``/await`` command-line switch + that enables a pre-C++20 version of coroutines. + * - | ``--ms_await_strict`` + - | Emulate the Microsoft Visual Studio ``/await:strict`` command-line + switch that enables a pre-C++20 version of coroutines. + * - | ``--ms_c11`` + - | Emulate the Microsoft Visual Studio ``/std:c11`` command-line switch + by enabling the same set of C11 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1927 for this + option to have an effect. + * - | ``--ms_c17`` + - | Emulate the Microsoft Visual Studio ``/std:c17`` command-line switch + by enabling the same set of C17 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1928 for this + option to have an effect. + * - | ``--ms_c23`` + - | Emulate the Microsoft Visual Studio ``/std:c23`` command-line switch + by enabling the same set of C23 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1935 for this + option to have an effect. + * - | ``--ms_c++14`` + - | Emulate the Microsoft Visual Studio ``/std:c++14`` command-line switch + by enabling the same set of C++14 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1903 to use this + option. + * - | ``--ms_c++17`` + - | Emulate the Microsoft Visual Studio ``/std:c++17`` command-line switch + by enabling the same set of C++17 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1911 to use this + option. + * - | ``--ms_c++20`` + - | Emulate the Microsoft Visual Studio ``/std:c++20`` command-line switch + by enabling the same set of C++20 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1920 to use this + option. + * - | ``--ms_c++23`` + - | Emulate the Microsoft Visual Studio ``/std:c++23`` command-line switch + by enabling the same set of C++23 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1943 to use this + option. + * - | ``--ms_c++latest`` + - | Emulate the Microsoft Visual Studio ``/std:c++latest`` command-line + switch by enabling the same set of C++ options as are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + * - | ``--ms_compatibility`` + | ``--no_ms_compatibility`` + - | Enable or disable certain Microsoft compatibility options (as defined + by the ``clang``\ ``-fms-compatibility`` option). Unlike the + ``--microsoft`` option (i.e., Microsoft emulation mode), this + command-line option can be combined with other emulation modes (e.g., + ``--clang``). Specifying ``--ms_compatibility`` implies + ``--ms_extensions``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + * - | ``--ms_std_preprocessor`` + | ``--no_ms_std_preprocessor`` + - | Enable or disable a mode in which the behavior of the preprocessor in + Microsoft emulation mode conforms with the C and C++ Standards; when + disabled, the preprocessor emulates the behavior of the traditional + Microsoft preprocessor. + * - | ``--ms_stdc`` + | ``--no_ms_stdc`` + - | Emulate the ``/Zc:__STDC__`` option of Microsoft's Visual Studio by + setting the value of the ``__STDC__`` macro to the value ``1`` or + leaving the macro undefined respectively. Implicitly enables + Microsoft emulation mode. + * - | ``--ms_cplusplus_std_value`` + | ``--no_ms_cplusplus_std_value`` + | + - | Emulate the ``/Zc:__cplusplus[-]`` option of Microsoft's Visual Studio + by either setting the value of the ``__cplusplus`` macro to the value + implied by the C++ standard currently being implemented or leaving it + as the default value of ``199711L`` used by Visual Studio. Implicitly + enables Microsoft emulation mode. + * - | ``--ms_extensions`` + | ``--no_ms_extensions`` + - | Enable or disable certain Microsoft extensions (as defined by the + ``clang``\ ``-fms-extensions`` option). Unlike the ``--microsoft`` + option (i.e., Microsoft emulation mode), this command-line option can + be combined with other emulation modes (e.g., ``--clang``). If not + specified explicitly with the ``--microsoft_version`` command-line + option, ``microsoft_version`` is set to the value of the + ``DEFAULT_MICROSOFT_VERSION`` macro. + * - | ``--ms_permissive`` + | ``--no_ms_permissive`` + - | Enable or disable "permissive" mode during Microsoft emulation. These + command-line options control emulation of the Visual Studio + ``/permissive[-]`` command-line options and can be used in C, C++, + C++/CLI, or C++/CX modes. The default value is controlled by the + ``DEFAULT_MS_PERMISSIVE`` configuration macro. Specifying one of + these command-line options also implicitly enables Microsoft emulation + mode. + * - | ``--nonstd_gnu_keywords`` + | ``--no_nonstd_gnu_keywords`` + | + - | In GNU modes, ``--no_nonstd_gnu_keywords`` disables GNU-specific + keywords that do not start with underscores (notably: ``typeof``); the + option has no effect in other modes. ``--nonstd_gnu_keywords`` is + only accepted in GNU modes and enables any keywords that were disabled + by a prior occurrence of ``--no_nonstd_gnu_keywords``. + * - | ``--no_strict_gnu`` + | ``--strict_gnu`` + - | For every version of the C and C++ ISO standards, the GNU and Clang + compilers support both the language as defined by ISO (with + ``-std=c*`` command-line options) as well as the language with certain + incompatible compiler-specific extensions (with ``-std=gnu*``). + Specifying ``--strict_gnu`` on the command-line causes the front end + to emulate the ``-std=c*`` behavior of the selected GNU/Clang + compiler, while specifying ``--no_strict_gnu`` emulates the + ``-std=gnu*`` behavior. When these options are not specified, the + front end implicitly emulates the ``-std=c*`` behavior whenever any + ``--c*`` or ``--c++*`` command-line options are specified (e.g., + ``--c++11`` mimics ``-std=c++11``); otherwise the ``-std=gnu*`` + behavior is emulated. + * - | ``--strict_warnings`` or ``-a`` + | ``--strict`` or ``-A`` + - | Enable strict ANSI/ISO mode, which provides diagnostic messages when + nonstandard features are used, and disables features that conflict + with ANSI/ISO C or C++. This is compatible with both C and C++ mode. + It is not compatible with pcc mode. ANSI/ISO violations can be issued + as either warnings or errors depending on which command line option is + used. The ``-A`` and ``--strict`` options cause errors to be issued + whereas the ``-a`` and ``--strict_warnings`` options produce warnings. + (Note that nonstandard types, functions, etc., that might be + predeclared by various compilers will not be declared by the front end + in this mode, so any references to these names will be diagnosed as + errors, regardless of which of these options is specified.) The error + threshold is set so that the requested diagnostics will be listed. + * - | ``--stricter_template_checking`` + - | If a selected dialect weakens the type checking performed in a + template, adding this option makes it stricter again (although not + always as strict as what is done in strict ANSI/ISO mode). + * - | ``--sun`` + | ``--no_sun`` + - | Enable or disable Sun CC (version 5.x) language compatibility + features. This option can only be used in C++ mode, and cannot be + combined with options to enable strict ANSI mode, or compatibility + with cfront, Microsoft, or GNU. It is only recognized when + ``SUN_EXTENSIONS_ALLOWED`` is TRUE. + * - | ``--svr4`` + | ``--no_svr4`` + - | Enable or disable recognition of SVR4 C compatibility features. The + default value is supplied by ``DEFAULT_SVR4_C_MODE``. This option + also specifies that the source language being compiled is ANSI C. + * - | ``--upc`` + | ``--no_upc`` + - | Enable or disable UPC (Unified Parallel C) extensions. + * - | ``--upc_threads`` *n* + - | Specify a fixed number of UPC threads (this is the value of the + THREADS identifier). + * - | ``--upc_strict`` + | ``--upc_relaxed`` + - | Specify the default UPC access method for objects of shared types. + +Input/output Options +-------------------- + +The following options control the kind of input read or output produced or the +location of such input or output. + +.. list-table:: + + * - | ``--unicode_source_kind`` *kind* + | + - | Source input files that do not begin with a byte order mark indicating + the kind of Unicode encoding are assumed to use the Unicode encoding + indicated by *kind*. Possible values of *kind* are ``UTF-8``, + ``UTF-16``, ``UTF-16LE`` (little-endian), ``UTF-16BE`` (big-endian), + and ``none`` (to indicate that the source file is not Unicode). + * - | ``--gen_c_file_name`` *file-name* + | + - | When using the C-generating back end or the C++-generating back end, + this option specifies the file name to be used for the generated + output. + * - | ``--dependencies`` + | ``-M`` + - | Do preprocessing only. Instead of the normal preprocessing output, + generate on the preprocessing output file a list of dependency lines + suitable for input to the UNIX ``make`` program. Note that when + implicit inclusion of templates is enabled, the output may indicate + false (but safe) dependencies unless ``--no_preproc_only`` is also + used. + * - | ``--error_output`` *efile* + - | Redirect the output that would normally go to the error output + file (i.e., diagnostic messages) to the file *efile*. This option + is useful on systems where output redirection of files is not well + supported. If used, this option should probably be specified + first in the command line, since otherwise any command-line errors + for options preceding the ``--error_output`` would be written to + ``stderr`` before redirection. + * - | ``--list`` *lfile* + | ``-L``\ *lfile* + - | Generate raw listing information in the file *lfile*. This + information is likely to be used to generate a formatted listing. + The raw listing file contains raw source lines, information on + transitions into and out of include files, and diagnostics + generated by the front end. Each line of the listing file begins + with a key character that identifies the type of line, as follows: + + ``N``: + a normal line of source; the rest of the line is the text of the + line. + + ``X``: + the expanded form of a normal line of source; the rest of the + line is the text of the line. This line appears following the N + line, and only if the line contains non-trivial modifications + (comments are considered trivial modifications; macro expansions, + line splices, and trigraphs are considered non-trivial + modifications). Comments are replaced by a single space in the + expanded-form line. + + ``S``: + a line of source skipped by an #if or the like; the rest of the + line is text. Note that the #else, #elif, or #endif that ends a + skip is marked with an N. + + ``L``: + an indication of a change in source position. The line has a + format similar to the # line-identifying directive output by cpp, + that is to say + + ``L`` *line-number* ``"``\ *file-name*\ ``"`` *key* + + where *key* is 1 for entry into an include file, 2 for exit from an + include file, and omitted otherwise. The first line in the raw + listing file is always an L line identifying the primary input + file. L lines are also output for #line directives (*key* is + omitted). L lines indicate the source position of the following + source line in the raw listing file. + + ``R``, ``W``, ``E``, or ``C``: + an indication of a diagnostic (``R`` for remark, ``W`` for + warning, ``E`` for error, and ``C`` for catastrophic error). The + line has the form + + *S* ``"``\ *file-name*\ ``"`` *line-number column-number + message-text* + + where *S* is ``R``, ``W``, ``E``, or ``C``, as explained + above. Errors at the end of file indicate the last line of the + primary source file and a column number of zero. Command-line + errors are catastrophes with an empty file name (``""``) and a + line and column number of zero. Internal errors are catastrophes + with position information as usual, and message-text beginning + with (internal error). When a diagnostic displays a list (e.g., + all the contending routines when there is ambiguity on an + overloaded call), the initial diagnostic line is followed by one + or more lines with the same overall format (code letter, file + name, line number, column number, and message text), but in which + the code letter is the lower case version of the code letter in + the initial line. The source position in such lines is the same + as that in the corresponding initial line. + + * - | ``--list_macros`` + - | Do preprocessing only. Instead of the normal preprocessing output, + generate on the preprocessing output file a list of all the macros in + effect after processing the source file, including predefined and + command-line macros along with their definitions. + * - | ``--no_line_commands`` + | ``-P`` + - | Do preprocessing only. Write preprocessed text to the preprocessing + output file, with comments removed and without line control + information. + * - | ``--old_line_commands`` + - | When generating source output (e.g., with the C-generating back end), + put out ``#line`` directives in the form used by the Reiser cpp, i.e., + "``#`` *nnn*" instead of "``#line`` *nnn*". + * - | ``--output`` *ofile* + | ``-o`` *ofile* + - | Specify the output file of the compilation, i.e., the preprocessing or + intermediate language output file. + * - | ``--xref`` *xfile* + | ``-X``\ *xfile* + - | Generate cross-reference information in the file *xfile*. For each + reference to an identifier in the source program, a line of the form + + *symbol-id name ref-code file-name line-number column-number* + + | is written, where *ref-code* is ``D`` for definition, ``d`` for + declaration (that is, a declaration that is not a definition), ``T`` + for a full template instantiation, ``t`` for a partial template + instantiation (i.e., an instantiation of the template declaration, but + not of its definition), ``M`` for modification, ``A`` for address + taken, ``U`` for used, ``C`` for changed (but actually meaning "used + and modified in a single operation," such as an increment), ``R`` for + any other kind of reference, or ``E`` for an error in which the kind + of reference is indeterminate. *symbol-id* is a unique decimal number + for the symbol. The fields of the above line are separated by tab + characters. + * - | ``--create_header_unit`` *file* + - | Write an EDG IFC header unit file + representing the current translation unit to *file*. + * - | ``--create_module_interface`` *file* + | + - | Write an EDG IFC module file for a module interface unit to *file*. + * - | ``--create_module_internal_partition`` *file* + | + - | Write an EDG IFC module file for a module implementation unit to + *file*. + * - | ``--module_interface`` + - | Write an EDG IFC module file for a module interface unit in the + current working directory. The filename is derived from the parsed + module declaration. + * - | ``--module_internal_partition`` + | + - | Write an EDG IFC module file for a module implementation unit in the + current working directory. The filename is derived from the parsed + module declaration. + +Preprocessor Options +-------------------- + +The following options control the behavior of the preprocessor. + +.. list-table:: + + * - | ``--comments`` + | ``-C`` + - | Keep comments in the preprocessed output. This should be specified + after either ``--preprocess`` or ``--no_line_commands``; it does not + of itself request preprocessing output. + * - | ``--define_macro`` *name* [ ``(`` *parm-list* ``)`` ] [ = *def* ] + | ``-D`` *name* [ ``(`` *parm-list* ``)`` ] [ ``=`` *def* ] + | + - | Define macro *name* as *def*. If "``=`` *def* " is omitted, + define *name* as ``1``. Function-style macros can be defined by + appending a macro parameter list to *name*. + * - | ``--embed_directory`` *dir* + - | Add *dir* to the list of directories searched for ``#embed``\ s. The + process by which files named in #embed directives are found is similar + to that used for ``#include``. See :ref:`finding-includes`. + * - | ``--import_dir`` *dir-name* + - | Specify the directory in which the files to be included by ``#import`` + directives are to be found. These files must have been generated + previously by the Microsoft compiler. This option is valid only in + Microsoft mode. + * - | ``--incl_suffixes`` *str* + - | Specifies the list of suffixes to be used when searching for an + include file whose name was specified without a suffix. The + argument is a colon-separated list of suffixes (e.g., + ``"h:hpp::"``). If a null suffix is to be allowed, it must be + included in the suffix list. The default is specified by the + configuation flag ``DEFAULT_INCLUDE_FILE_SUFFIX_LIST``. + * - | ``--include_directory`` *dir* + | ``--sys_include`` *dir* + | ``-I``\ *dir* + - | Add *dir* to the list of directories searched for ``#include``\ s. + See :ref:`finding-includes`. + * - | ``--modules_directory`` *dir* + | + - | Add *dir* to the list of directories searched for module files when + processing an ``import`` directive. The current working directory is + automatically added to the start of this list. If the + ``EDG_MODULES_PATH`` environment variable is set, that path is added + to the end of the list. See :ref:`finding-modules`. + * - | ``--ms_header_unit`` *header_path*\ ``=``\ *module_file* + | ``--header_unit`` *header_path*\ ``=``\ *module_file* + | + - | Add *module_file* to the header unit map, corresponding to + *header_path*. When importing a header unit, if the resolved path + to the header matches *header_path*, then *module_file* is used as + the match. See :ref:`finding-modules`. + * - | ``--ms_header_unit_angle`` *header_path*\ ``=``\ *module_file* + | ``--ms_header_unit_quote`` *header_path*\ ``=``\ *module_file* + | + - | Add *module_file*, corresponding to *header_path*, to a header + unit map selected by the form in which *header_path* is written, + ``<...>`` and ``"..."``, respectively. Unlike --ms_header_unit, + *header_path* is not resolved immediately but will be resolved on + demand. (See :ref:`finding-includes`.) If the resolved path to + the header for the header unit matches the resolved *header_path*, + *module_file* is used as the match. See :ref:`finding-modules`. + * - | ``--ms_mod_file_map`` [ *module_name*\ ``=`` ] *file* + | + - | If *module_name* is omitted, *file* will be examined to determine + if the module it represents matches the module named in the + ``import`` directive. Otherwise, an import of *module_name* will + resolve to *file* without examining its contents. See + :ref:`finding-modules`. + * - | ``--ms_translate_include`` + | ``--no_ms_translate_include`` + | + - | Enable or disable the automatic translation of ``#include`` + directives into ``import`` directives when a header has a mapping + to a module file in a header unit map (see ``--ms_header_unit``, + ``--ms_header_unit_angle``, and ``--ms_header_unit_quote`` + regarding how such mappings are specified.) + * - | ``--old_style_preprocessing`` + | + - | Forces pcc style preprocessing when compiling in ANSI C or C++ mode. + This may be used when compiling an ANSI C or C++ program on a system + in which the system header files require pcc style preprocessing. + * - | ``--preinclude_macros`` *filename* + | ``--preinclude`` *filename* + - | Include the source code of the indicated file at the beginning of the + compilation. This can be used to establish standard macro + definitions, etc. The file name is searched for in the directories on + the include search list. When the ``preinclude_macros`` variant is + used, only the preprocessing directives from the file are evaluated. + All of the actual code is discarded. The effect of this option is + that any macro definitions from the specified file will be in effect + when the primary source file is compiled. All of the macro-only files + are processed before any of the normal preincludes. Within each + group, the files are processed in the order in which they were + specified. + * - | ``--preprocess`` + | ``-E`` + - | Do preprocessing only. Write preprocessed text to the preprocessing + output file, with comments removed and with line control information. + * - | ``--no_preproc_only`` + - | May be used in conjunction with the options that normally cause the + front end to do preprocessing only (e.g., ``--preprocess``, etc.) to + specify that a full compilation should be done (not just + preprocessing). When used with the implicit inclusion option, this + makes it possible to generate a preprocessed output file that includes + any implicitly included files. + * - | ``--stdc_zero_in_system_headers`` + | ``--no_stdc_zero_in_system_headers`` + | + - | Enable or disable special processing of the ``__STDC__`` macro + when referenced from system headers. When this feature is + enabled, ``__STDC__`` has the value zero in system header files + (files found in directories specified using the ``--sys_include`` + option) and one otherwise. This feature is provided to emulate + the behavior of ``gcc`` in certain configurations. The default is + specified by ``DEFAULT_STDC_ZERO_IN_SYSTEM_HEADERS``. If the flag + is not TRUE by default, the GNU mode default is specified by the + ``DEFAULT_GNU_STDC_ZERO_IN_SYSTEM_HEADERS`` macro. + * - | ``--trace_includes`` + | ``-H`` + - | Output a list of the names of files ``#include``\ d to the error + output file. The source file is compiled normally (i.e., it is not + just preprocessed) unless another option that causes preprocessing + only is specified. + * - | ``--undefine_macro`` *name* + | ``-U``\ *name* + - | Remove any initial definition of the macro *name*. + ``--undefine_macro`` options are processed after all + ``--define_macro`` options in the command line have been + processed. + * - | ``--check_concatenations`` + | ``--no_check_concatenations`` + | + - | Specifies whether or not the front end will issue a diagnostic if a + concatenation operator ``##`` in a macro expansion fails to produce a + valid preprocessor token as required by the C and C++ Standards. + * - | ``--no_token_separators_in_pp_output`` + | + - | Used in connection with options that generate preprocessing output, + suppresses the extra spaces the front end inserts in the text of macro + expansions to ensure that tokens that should not be combined remain + separate tokens. This can be used to prevent the insertion of + extraneous spaces when the front end is used as a preprocessor for + text that is not C or C++. + +Diagnostic Options +------------------ + +The following options control when or how diagnostics are emitted. + +.. list-table:: + + * - | ``--add_match_notes`` + | ``--no_add_match_notes`` + - | Enable or disable diagnostic notes that + provide further details for a failure to match candidates in an + overload set. + * - | ``--brief_diagnostics`` + | ``--no_brief_diagnostics`` + | + - | Enable or disable a mode in which a shorter form of the diagnostic + output is used. When enabled, the original source line is not + displayed and the error message text is not wrapped when too long to + fit on a single line. + * - | ``--colors`` + | ``--no_colors`` + - | Enable or disable colorization of diagnostic messages. The default + behavior is controlled by the ``DEFAULT_ENABLE_COLORIZED_DIAGNOSTICS`` + configuration macro (which defaults to TRUE). Colorized + diagnostics are disabled when not writing to a terminal, and are also + disabled when the ``NOCOLOR`` environment variable is set, the + ``TERM`` environment variable is unset, or the ``EDG_COLORS`` + environment variable is set to an empty string. + * - | ``--constexpr_diag_suppress`` *tag, tag,...* + | ``--constexpr_diag_remark`` *tag, tag,...* + | ``--constexpr_diag_warning`` *tag, tag,...* + | ``--constexpr_diag_error`` *tag, tag,...* + - | Override the severity of the diagnostics that calls of + ``__builtin_constexpr_diag`` request with any of the specified tags. + A tag is shown in brackets at the end of the diagnostic it names, and + may contain only letters, digits, and underscores. When more than + one of these options names a given tag, the last one on the command + line takes effect. + * - | ``--context_limit`` *number* + | + - | Set the context limit to *number*. The context limit is the maximum + number of template instantiation context entries to be displayed as + part of a diagnostic message. The default is specified by the + ``DEFAULT_CONTEXT_LIMIT`` macro. If the number of context entries + exceeds the limit, the first and last N context entries are displayed, + where N is half of the context limit. A value of zero is used to + indicate that there is no limit. + * - | ``--diag_suppress`` *tag, tag,...* + | ``--diag_remark`` *tag, tag,...* + | ``--diag_warning`` *tag, tag,...* + | ``--diag_error`` *tag, tag,...* + - | Override the normal error severity of the specified diagnostic + messages. The message(s) may be specified using a mnemonic error tag + or using an error number. The error tag names and error numbers are + listed in the Error Messages appendix. + * - | ``--diag_once`` *tag, tag,...* + - | Causes the specified diagnostic to be issued only once as a warning or + remark. The message(s) may be specified using a mnemonic error tag or + using an error number. The error tag names and error numbers are + listed in the Error Messages appendix. + * - | ``--display_error_number`` + | ``--no_display_error_number`` + | + - | Enable or disable the display of an error message number in any + diagnostic messages that are generated. The option may be used to + determine the error number to be used when overriding the severity of + a diagnostic message. The configuration macro + ``DEFAULT_DISPLAY_ERROR_NUMBER`` specifies the default behavior. + * - | ``--error_limit`` *number* + | ``-e`` *number* + - | Set the error limit to *number*. The front end will abandon + compilation after this number of errors (remarks and warnings are + not counted toward the limit). By default, the limit is 100. + * - | ``--for_init_diff_warning`` + | ``--no_for_init_diff_warning`` + | + - | Enable or disable a warning that is issued when programs compiled + under the new for-init scoping rules would have had different behavior + under the old rules. The diagnostic is only put out when the new + rules are used. ``DEFAULT_WARNING_ON_FOR_INIT_DIFFERENCE`` specifies + the default behavior. This option is valid only in C++ mode. + * - | ``--lossy_conversion_warning`` + | ``--no_lossy_conversion_warning`` + | + - | Enable or disable a warning that is issued when conversion of an + arithmetic value to a different type might result in lost data because + the target type cannot represent all the values of the source type. + * - | ``--macro_positions_in_diagnostics`` + | ``--no_macro_positions_in_diagnostics`` + | + - | Enable or disable display of extra information for diagnostics that + refer to text in macro expansions. These options may only be used if + ``FULLY_RESOLVED_MACRO_POSITIONS`` is TRUE. The additional + information includes the original source line from which the text + identified by the message was copied into the macro expansion (i.e., a + macro definition or an argument in the top-level macro invocation), as + well as the chain of macro invocations that led to the expanded text + designated by the diagnostic (if ``MACRO_INVOCATION_TREE_IN_IL`` is + TRUE). The default value is given by + ``DEFAULT_MACRO_POSITIONS_IN_DIAGNOSTICS``. + * - | ``--module_import_diagnostics`` + | ``--no_module_import_diagnostics`` + | + - | Enable or disable the issuing of diagnostics while importing entities + from module files. + * - | ``--output_mode`` *mode* + - | Set the front end diagnostic output mode to *mode*. Valid modes + are ``text`` for traditional command line diagnostic output and + ``sarif`` for SARIF (Static Analysis Results Interchange Format) + output (see `www.sarif.info `__). + * - | ``--promote_warnings`` + | ``-W`` + - | Issue all warnings as if they were discretionary errors.`` + * - | ``--remarks`` + | ``-r`` + - | Issue remarks, which are diagnostic messages even milder than + warnings. + * - | ``--report_gnu_extensions`` + | + - | Warn about the use of certain GNU extensions outside system header + files. Only valid in GNU C or C++ mode. + * - | ``--template_typedefs_in_diagnostics`` + | ``--no_template_typedefs_in_diagnostics`` + | + - | Disable or enable, respectively, the replacement of typedefs + declared in template classes with their underlying type. + Diagnostic messages are often more useful when such typedefs are + replaced. The default behavior is specified by the + ``DEFAULT_TEMPLATE_TYPEDEFS_IN_DIAGNOSTICS`` macro. + * - | ``--timing`` + | ``-#`` + - | Generate compilation timing information. This option causes the + compiler to display the amount of CPU time and elapsed time used by + each phase of the compilation and a total for the entire compilation. + * - | ``--top_templates`` *number* + - | At the end of the compilation, write to the error output file a report + of the templates that were substituted the most. *number* specifies + how many templates to report; if it is zero, every template that has a + nonzero number of substitutions is reported. + * - | ``--no_use_before_set_warnings`` + | ``-j`` + - | Suppress warnings on local automatic variables that are used before + their values are set. The front end's algorithm for detecting such + uses is conservative and is likely to miss some cases that an + optimizer with sophisticated flow analysis could detect; thus, an + implementation might choose to suppress the warnings from the front + end when optimization has been requested but to permit them when the + optimizer is not being run. + * - | ``--no_warnings`` + | ``-w`` + - | Suppress warnings. Errors are still issued. + * - | ``--wrap_diagnostics`` + | ``--no_wrap_diagnostics`` + - | Enable or disable a mode in which the error message text is not + wrapped when too long to fit on a single line. + +Individual Language Features +---------------------------- + +The following options enable or disable specific language syntax. (Options +that affect the meaning of existing constructs are listed in +:ref:`cli-alt-lang-behaviors`.) + +.. list-table:: + + * - | ``--alternative_tokens`` + | ``--no_alternative_tokens`` + | + - | Enable or disable recognition of alternative tokens. This controls + recognition of the digraph tokens in C and C++, and controls + recognition of the operator keywords (e.g., ``and``, ``bitand``, etc.) + in C++. The default behavior is specified by the + ``DEFAULT_ALTERNATIVE_TOKENS_ALLOWED`` configuration constant. + * - | ``--array_new_and_delete`` + | ``--no_array_new_and_delete`` + | + - | Enable or disable support for array new and delete. The default + behavior is specified by the configuration constant + ``DEFAULT_ARRAY_NEW_AND_DELETE_ENABLED``. This option is valid only + in C++ mode. The front end can be configured to define a + preprocessing variable when array new and delete are enabled. This + preprocessing variable may then be used by the standard header files + to decide whether to include the declarations for the array new/delete + functions. + * - | ``--auto_storage`` + | ``--no_auto_storage`` + - | Enable or disable the traditional meaning of ``auto`` as a storage + class specifier (only valid in C++ mode). (If disabled, then ``auto`` + must be a type specifier.). The default behavior is specified by the + ``DEFAULT_AUTO_STORAGE_CLASS_SPECIFIER_ENABLED`` configuration + constant. + * - | ``--auto_type`` + | ``--no_auto_type`` + - | Enable or disable ``auto`` as a type specifier where the actual type + is deduced from an initializer (only valid in C++ mode). This is a + C++11 feature. If enabled, the traditional meaning of ``auto`` as a + storage class specifier is disabled (which matches C++11), unless the + option ``--auto_storage`` is also supplied. The default behavior is + specified by the ``DEFAULT_AUTO_TYPE_SPECIFIER_ENABLED`` configuration + constant. + * - | ``--bit_precise_integers`` + | ``--no_bit_precise_integers`` + - | Enable or disable support for C23-style ``_BitInt`` types. + * - | ``--bool`` + | ``--no_bool`` + - | Enable or disable recognition of ``bool``. The default value is + supplied by ``DEFAULT_BOOL_IS_KEYWORD``. This option is valid only in + C++ mode. The front end can be configured to define a preprocessing + variable when ``bool`` is recognized. This preprocessing variable may + then be used by header files to determine whether a typedef should be + supplied to define ``bool``. + * - | ``--c23_typeof`` + | ``--no_c23_typeof`` + - | Enable or disable support for the C23 ``typeof`` and + ``typeof_unqual`` operators, regardless of the current C language + level. This option is valid only in C mode. + * - | ``--c++11_sfinae`` + | ``--no_c++11_sfinae`` + - | Enable or disable template deduction in the style dictated by the + C++11 standard, i.e., where general expressions are allowed in + deduction contexts and they undergo the full usual semantic + checking. This type of deduction is necessary to get the full + power of the ``decltype`` feature in return types. ("SFINAE" is + an acronym for "Substitution Failure Is Not An Error", which is + the guiding principle for template deduction, and by extension a + name for the process of deduction.) + * - | ``--c++11_sfinae_ignore_access`` + | ``--no_c++11_sfinae_ignore_access`` + | + - | When new-style SFINAE is enabled, these options control whether or not + access errors cause deduction failures. The positive option indicates + that access checking should not be done during template deduction, and + therefore that access errors cannot cause a deduction failure; this + was the status quo ante when the new-style SFINAE rules were proposed. + The "``no``" version of the option indicates that access checking + should be done during template deduction, and therefore that access + errors cause a deduction failure; this is the revised direction chosen + by the standards committee. + * - | ``--char8_t`` + | ``--no_char8_t`` + | + - | Enable or disable support for the ``char8_t`` keyword and type (a + C++20 feature). Enabled by default in C++20 mode. + * - | ``--compound_literals`` + | ``--no_compound_literals`` + - | Enable or disable support for "compound literals" (a C99 feature). + * - | ``--concepts`` + | ``--no_concepts`` + | + - | Enable or disable support for concepts (a C++20 feature). + * - | ``--delegating_constructors`` + | ``--no_delegating_constructors`` + | + - | Enable or disable delegating constructors (a C++11 feature). + * - | ``--deprecated_string_conv`` + | ``--no_deprecated_string_conv`` + | + - | Enable or disable the deprecated conversion from a string literal to + ``char *``. Meaningful only when string literals are const. + * - | ``--designators`` + | ``--no_designators`` + - | Enable or disable support for designators (a C99 feature). These + options are not available in C++ mode. + * - | ``--digit_separators`` + | ``--no_digit_separators`` + - | Enable or disable support for digit separators (a C++14 feature). + When this feature is enabled, an apostrophe can appear between the + digits of a numeric literal and is ignored, e.g., ``123'456'789``. + * - | ``--extended_designators`` + | ``--no_extended_designators`` + | + - | Enable or disable support for "extended designators," an extension + accepted only in C mode to emulate the behavior of certain other C + compilers when it comes to designators in aggregate initializers. + * - | ``--dollar`` + | ``-$`` + - | Accept dollar signs in identifiers. The default value of this option + is specified in a configuration file. + * - | ``--exceptions--no_exceptions`` + | ``-x`` + - | Enable or disable support for exception handling. ``-x`` is + equivalent to ``--exceptions``. The default behavior is specified by + the configuration constant ``DEFAULT_EXCEPTIONS_ENABLED``. This + option is valid only in C++ mode. + * - | ``--exc_spec_in_func_type`` + | ``--no_exc_spec_in_func_type`` + - | Enable or disable exceptions being part of a function type (enabled by + default in C++17 modes and disabled by default otherwise). + * - | ``--explicit`` + | ``--no_explicit`` + - | Enable or disable support for the ``explicit`` specifier on + constructor declarations. The default behavior is specified by the + configuration constant ``DEFAULT_EXPLICIT_KEYWORD_ENABLED``. This + option is valid only in C++ mode. + * - | ``--export`` + | ``--no_export`` + - | Enable or disable recognition of exported templates. The default + value is supplied by ``DEFAULT_EXPORT_TEMPLATE_ALLOWED``. This option + is valid only in C++ mode. This option requires that dependent name + processing be done, and cannot be used with implicit inclusion of + template definitions. + * - | ``--extern_inline`` + | ``--no_extern_inline`` + - | Enable or disable support for ``inline`` functions with external + linkage in C++. When ``inline`` functions are allowed to have + external linkage (as required by the standard), then ``extern`` and + ``inline`` are compatible specifiers on a nonmember function + declaration; the default linkage when ``inline`` appears alone is + external (that is, ``inline`` means ``extern inline`` on nonmember + functions); and an ``inline`` member function takes on the linkage of + its class (which is usually external). However, when ``inline`` + functions have only internal linkage (as specified in the ARM), then + ``extern`` and ``inline`` are incompatible; the default linkage when + ``inline`` appears alone is internal (that is, ``inline`` means + ``static inline`` on nonmember functions); and ``inline`` member + functions have internal linkage no matter what the linkage of their + class. + * - | ``--fixed_point`` + | ``--no_fixed_point`` + - | Enable or disable support for Embedded C fixed-point types. (Not + available in C++ modes.) + * - | ``--lambdas`` + | ``--no_lambdas`` + - | Enable or disable support for C++11 lambdas. (Only available in C++ + modes.) + * - | ``--long_long`` + - | Permit the use of ``long long`` in strict mode in dialects in which it + is non-standard. + * - | ``--modules`` + | ``--no_modules`` + - | Enable or disable support for modules. Modules are currently + experimental and will be enabled by default in future releases in the + applicable modes. The front end does not currently generate modules + files of its own and can only consume module files produced by + Microsoft Visual Studio version 16.8. This support is incomplete and + compatibility will change in future releases. + | + * - | ``--multibyte_chars`` + | ``--no_multibyte_chars`` + - | Enable or disable processing for multibyte character sequences in + comments, string literals, and character constants. The default + behavior is specified by + ``DEFAULT_MULTIBYTE_CHARS_IN_SOURCE_ALLOWED``. Multibyte encodings + are used for character sets like the Japanese SJIS. + * - | ``--named_address_spaces`` + | ``--no_named_address_spaces`` + | + - | Enable or disable support for Embedded C named address space + qualifiers. (Not available in C++ modes.) + * - | ``--named_registers`` + | ``--no_named_registers`` + - | Enable or disable support for Embedded C named-register storage class + specifiers. (Not available in C++ modes.) + * - | ``--namespaces`` + | ``--no_namespaces`` + - | Enable or disable support for namespaces. The default behavior is + specified by the configuration constant + ``DEFAULT_NAMESPACES_ENABLED``. This option is valid only in C++ + mode. + * - | ``--nonstd_using_decl`` + | ``--no_nonstd_using_decl`` + | + - | In C++, controls whether a nonmember using-declaration that specifies + an unqualified name is allowed. + * - | ``--nullptr`` + | ``--no_nullptr`` + - | Enable or disable support for the C++11/C23 ``nullptr`` keyword. + * - | ``--old_specializations`` + | ``--no_old_specializations`` + | + - | Enable or disable acceptance of old-style template specializations + (i.e., specializations that do not use the ``template<>`` syntax). + Default behavior is specified by + ``DEFAULT_OLD_SPECIALIZATIONS_ALLOWED``. This option is valid only in + C++ mode. + * - | ``--relaxed_abstract_checking`` + | ``--no_relaxed_abstract_checking`` + | + - | Enable or disable a mode in which checking for the use abstract class + types as function parameter or return types is performed only when the + function is defined or called. Traditionally this checking has been + performed on non-defining function declarations as well, and this + behavior can be preserved via the second option. + * - | ``--restrict`` + | ``--no_restrict`` + - | Enable or disable recognition of the ``restrict`` keyword. + * - | ``--rtti`` + | ``--no_rtti`` + - | Enable or disable support for RTTI (runtime type information) + features: ``dynamic_cast``, ``typeid``. The default behavior is + specified by the configuration constant ``DEFAULT_RTTI_ENABLED``. + This option is valid only in C++ mode. + * - | ``--rvalue_ctor_is_copy_ctor`` + | ``--rvalue_ctor_is_not_copy_ctor`` + | + - | Determines whether an rvalue (or "move") constructor is treated as a + copy constructor (the default) or not. If rvalue constructors are + treated as copy constructors, a user-declared rvalue constructor will + inhibit the implicit generation of a traditional copy constructor. + * - | ``--rvalue_refs`` + | ``--no_rvalue_refs`` + - | Enable or disable support for rvalue references. (Only valid in C++ + mode.) + * - | ``--sun_linker_scope`` + | ``--no_sun_linker_scope`` + | + - | Enable or disable support for Sun CC 5.5 link scope specifiers + (``__global``, ``__symbolic``, and ``__hidden``). The default setting + is supplied by ``DEFAULT_SUN_LINKER_SCOPE_ALLOWED``. + * - | ``--thread_local_storage`` + | ``--no_thread_local_storage`` + | + - | Enable or disable the C++11 ``thread_local`` specifier (and, if so + configured, the ``__thread`` specifier) to indicate that variables + should be stored in thread-local storage. By default, the + ``__thread`` specifier is enabled in Sun mode and in GNU mode when + ``gnu_version`` >= 30400. + * - | ``--trigraphs`` + | ``--no_trigraphs`` + | + - | Enable or disable recognition of trigraphs. The default behavior is + specified by the ``DEFAULT_TRIGRAPHS_ALLOWED`` configuration constant. + * - | ``--typename`` + | ``--no_typename`` + - | Enable or disable recognition of ``typename``. The default value is + supplied by ``DEFAULT_TYPENAME_ENABLED``. This option is valid only + in C++ mode. + * - | ``--type_traits_helpers`` + | ``--no_type_traits_helpers`` + | + - | Enable or disable support for type traits helpers (like ``__is_union`` + and ``__has_virtual_destructor``; intended to ease the implementation + of ISO/IEC TR 19768). Only valid in C++. Type traits helpers are + enabled in all C++ modes by default, except in GNU and Sun C++ modes. + * - | ``--uliterals`` + | ``--no_uliterals`` + - | Enable or disable recognition of U-literals (string literals of the + forms ``U"..."`` and ``u"..."``, and character literals of the forms + ``U'...'`` and ``u'...'``). In C++ mode, this also enables or + disables the C++11 ``char16_t`` and ``char32_t`` keywords. + * - | ``--unrestricted_unions`` + | ``--no_unrestricted_unions`` + | + - | Enable or disable C++11-style "unrestricted unions" (i.e., unions with + data members that have nontrivial initialization and/or destruction + semantics). This option can currently not be enabled in Microsoft + mode. + * - | ``--user_defined_literals`` + | ``--no_user_defined_literals`` + | + - | Enable or disable C++11-style "user-defined literals," i.e., + literals with a suffix designating an operator function that is to + be called to produce the value of the literal, e.g., ``12.34_km``, + which calls ``operator ""_km(12.34)``. + * - | ``--utf8_char_literals`` + | ``--no_utf8_char_literals`` + | + - | Enable or disable C++17-style ``UTF-8`` character literals (e.g., + ``u8'a'``). Enabled by default in C++17 mode as well as when + ``microsoft_version`` >= 1900. + * - | ``--variadic_macros`` + | ``--no_variadic_macros`` + - | Enable or disable support for variadic macros (a C99 feature that is + also available in C++ mode). + * - | ``--extended_variadic_macros`` + | ``--no_extended_variadic_macros`` + | + - | Enable or disable support for "extended variadic macros," an extension + that emulates the behavior of certain other C compilers when it comes + to variadic macros. + * - | ``--variadic_templates`` + | ``--no_variadic_templates`` + | + - | Enable or disable support for "variadic templates," a C++11 feature + that allows declaration of templates with a variable number of + arguments. The default value is dependent on the major language mode + and on ``DEFAULT_VARIADIC_TEMPLATES_ENABLED``. This option is valid + only in C++ modes. + * - | ``--vla`` + | ``--no_vla`` + - | Enable or disable support for "variable length arrays," a C99 feature + and an extension in some other modes that allows the declaration and + use of arrays of automatic storage duration with dimensions that are + fixed at run time. These options are available only if + ``VLA_ALLOWED`` is configured to TRUE. + * - | ``--wchar_t_keyword`` + | ``--no_wchar_t_keyword`` + - | Enable or disable recognition of ``wchar_t`` as a keyword. The + default value is supplied by ``DEFAULT_WCHAR_T_IS_KEYWORD``. This + option is valid only in C++ mode. The front end can be configured to + define a preprocessing variable when ``wchar_t`` is recognized as a + keyword. This preprocessing variable may then be used by the standard + header files to determine whether a typedef should be supplied to + define ``wchar_t``. + +.. _cli-alt-lang-behaviors: + +Alternative Language Behaviors +------------------------------ + +The following options affect the meaning of various language constructs. + +.. list-table:: + + * - | ``--aligned_new`` + | ``--no_aligned_new`` + | + - | Enable or disable calling special allocation and deallocation + functions for types with more stringent alignment requirements than + the fundamental types (enabled by default in C++17 modes and disabled + otherwise). + * - | ``--arg_dep_lookup`` + | ``--no_arg_dep_lookup`` + | + - | In C++, controls whether argument dependent lookup of unqualified + function names is performed + * - | ``--base_assign_op_is_default`` + | ``--no_base_assign_op_is_default`` + | + - | Enable or disable the anachronism of accepting a copy assignment + operator that has an input parameter that is a reference to a base + class as a default copy assignment operator for the derived class. + This option is enabled by default in cfront compatibility mode. + * - | ``--class_name_injection`` + | ``--no_class_name_injection`` + | + - | In C++, controls whether the name of a class is injected into the + scope of the class (as required by the standard) or is not injected + (as was true in earlier versions of the C++ language). + * - | ``--const_string_literals`` + | ``--no_const_string_literals`` + | + - | Control whether C++ string literals and wide string literals are const + (as required by the standard) or non-const (as was true in earlier + versions of the C++ language). + * - | ``--default_calling_convention`` *calling-convention* + | + - | The calling convention that should be assumed for functions that are + declared without an explicit calling convention. This option may only + be used if ``MICROSOFT_EXTENSIONS_ALLOWED`` is TRUE. + *calling-convention* must be one of ``__cdecl``, ``__fastcall``, + ``__stdcall``, and ``__thiscall``. + * - | ``--default_nocommon_tentative_definitions`` + | ``--default_common_tentative_definitions`` + | + - | Control whether tentative definitions are placed in "common" storage. + These options are only available in configurations with + ``GNU_EXTENSIONS_ALLOWED`` set to TRUE. The default can be overridden + for specific variables with the GNU attributes ``common`` and + ``nocommon``. + * - | ``--defer_parse_function_templates`` + | ``--no_defer_parse_function_templates`` + | + - | Enable or disable deferral of prototype instantiations until the + first actual instantiation of a function. This is used to permit + the compilation of programs that contain definitions of unusable + function templates. It is enabled by default in g++ mode when + ``gnu_version`` is >= 30400 (but not when using the C++-generating + back end). + * - | ``--dep_name`` + | ``--no_dep_name`` + - | Enable or disable dependent name processing; i.e., the special lookup + of names used in templates as required by the C++ standard. The + default value is supplied by ``DEFAULT_DEPENDENT_NAME_PROCESSING``. + This option is valid only in C++ mode and ``--dep_name`` cannot be + combined with ``--no_parse_templates``. + * - | ``--distinct_template_signatures`` + | ``--no_distinct_template_signatures`` + | + - | Control whether the signatures for template functions can match those + for non-template functions when the functions appear in different + compilation units. (This option is available only on versions that do + name mangling on the names of external entities.) The default is + ``--distinct_template_signatures``, under which a normal function + cannot be used to satisfy the need for a template instance; e.g., a + function "``void f(int)``" could not be used to satisfy the need for + an instantiation of a template "``void f(T)``" with ``T`` set to + ``int``. ``--no_distinct_template_signatures`` provides the older + language behavior, under which a non-template function can match a + template function. Also controls whether function templates may have + template parameters that are not used in the function signature of the + function template. + * - | ``--enum_overloading`` + | ``--no_enum_overloading`` + - | Enable or disable support for using operator functions to overload + builtin operations on enum-typed operands. + * - | ``--far_data_pointers`` + | ``--near_data_pointers`` + | ``--far_code_pointers`` + | ``--near_code_pointers`` + - | Set the default size for pointers when support for ``near`` and + ``far`` is enabled (e.g., in Microsoft 16-bit mode). Ignored in other + modes. + * - | ``--friend_injection`` + | ``--no_friend_injection`` + | + - | In C++, controls whether the name of a class or function that is + declared only in friend declarations is visible when using the normal + lookup mechanisms. When friend names are injected, they are visible + to such lookups. When friend names are not injected (as required by + the standard), function names are visible only when using + argument-dependent lookup, and class names are never visible. + * - | ``--func_prototype_tags`` + | ``--no_func_prototype_tags`` + - | in C, controls whether tag types first + declared in a function prototype belong to the function prototype + scope (standard C behavior) or to a surrounding scope (default + Microsoft C behavior). + * - | ``--gcc89_inlining`` + - | Use the GNU C89 semantics of ``inline`` in C99 mode. (Not valid in + C++ modes.) + * - | ``--gen_move_operations`` + | ``--no_gen_move_operations`` + | + - | Enable or disable the generation of move constructors and move + assignment operators according to standard C++11 rules. + * - | ``--guiding_decls`` + | ``--no_guiding_decls`` + - | Enable or disable recognition of "guiding declarations" of template + functions. A guiding declaration is a function declaration that + matches an instance of a function template but has no explicit + definition (since its definition derives from the function template). + For example: + + .. code:: c++ + + template void f(T) { ... } + void f(int); + + | When regarded as a guiding declaration, ``f(int)`` is an instance of + the template; otherwise, it is an independent function for which a + definition must be supplied. If ``--no_guiding_decls`` is combined + with ``--old_specializations``, a specialization of a non-member + template function is not recognized -- it is treated as a definition + of an independent function. Default behavior is specified by + ``DEFAULT_GUIDING_DECLS_ALLOWED``. This option is valid only in C++ + mode. + * - | ``--ignore_std`` + - | Enable a ``g++`` compatibility feature that makes the ``std`` + namespace a synonym for the global namespace. + * - | ``--implicit_extern_c_type_conversion`` + | ``--no_implicit_extern_c_type_conversion`` + | + - | Enable or disable an extension to permit implicit type conversion in + C++ between a pointer to an ``extern "C"`` function and a pointer to + an ``extern "C++"`` function. This extension is allowed in + environments where C and C++ functions share the same calling + conventions: ``IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE`` + must be set for it to be available. (It is useful for cfront + compatibility when ``DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT`` + is TRUE -- in standard C++ the linkage specification is part of the + function type, with the consequence that otherwise identical function + types, one declared ``extern "C"`` and the other declared ``extern + "C++"``, are viewed as distinct.) + * - | ``--implicit_noexcept`` + | ``--no_implicit_noexcept`` + | + - | Enable or disable the implicit generation of exception specifications + for user-declared destructors and deallocation functions in C++11 + mode. (In strict C++11 mode, it is enabled by default, whereas in + other C++11 modes it is disabled by default.) + * - | ``--implicit_typename`` + | ``--no_implicit_typename`` + | + - | Enable or disable implicit determination, from context, whether a + template parameter dependent name is a type or nontype. The default + value is supplied by ``DEFAULT_IMPLICIT_TYPENAME_ENABLED``. This + option is valid only in C++ mode. + * - | ``--late_tiebreaker`` + | ``--early_tiebreaker`` + - | Select the way that tie-breakers (e.g., cv-qualifier differences) + apply in overload resolution. In "early" tie-breaker processing, the + tie-breakers are considered at the same time as other measures of the + goodness of the match of an argument value and the corresponding + parameter type (this is the standard approach). In "late" tiebreaker + processing, tie-breakers are ignored during the initial comparison, + and considered only if two functions are otherwise equally good on all + arguments; the tie-breakers can then be used to choose one function + over another. + * - | ``--long_lifetime_temps`` + | ``--short_lifetime_temps`` + | + - | Select the lifetime for temporaries: "short" means to end of full + expression; "long" means to the earliest of end of scope, end of + switch clause, or the next label. "short" is standard C++, and "long" + is what cfront uses (the cfront compatibility modes select "long" by + default). + * - | ``--long_preserving_rules`` + | ``--no_long_preserving_rules`` + | + - | Enable or disable the K&R usual arithmetic conversion rules with + respect to ``long``. This means the rules of K&R I, Appendix A, 6.6, + not the rules used by the pcc compiler. The significant difference is + in the handling of "``long`` *op* ``unsigned int``" when ``int`` and + ``long`` are the same size. The ANSI/ISO/pcc rules say the result is + ``unsigned long``, but K&R I says the result is ``long`` (``unsigned + long`` did not exist in K&R I). + * - | ``--max_depth_constexpr_call=`` *n* + | ``--max_cost_constexpr_call=`` *n* + | + - | Specify the maximum depth of recursion or the maximum "cost" for + folding a top-level ``constexpr`` call (function or constructor). In + C++11 modes, the "cost" is the number of calls expanded from a single + top-level call. In C++14 modes, the "cost" is a combination of the + number of calls interpreted and the number of loop iterations + performed during the interpretation of a top-level call. + * - | ``--ms_rvalue_cast`` + | ``--no_ms_rvalue_cast`` + | + - | Explicitly disable or enable treating a cast of an lvalue to its own + type as that same lvalue. (``--ms_rvalue_cast`` corresponds to + standard behavior, but Microsoft compilers traditionally behaved + otherwise.) Implies Microsoft mode. + * - | ``--ms_strict_ternary`` + | ``--no_ms_strict_ternary`` + | + - | Enable or disable strict standard-conforming behavior of the + conditional ternary operator (?:) in Microsoft mode. It is disabled + by default in Microsoft mode, unless Microsoft permissive mode is + disabled (see ``--no_ms_permissive``). Implies Microsoft mode. + * - | ``--nonconst_ref_anachronism`` + | ``--no_nonconst_ref_anachronism`` + | + - | Enable or disable the anachronism of allowing a reference to nonconst + to bind to a class rvalue of the right type. This anachronism is also + enabled by the ``--anachronisms`` option and the cfront-compatibility + options. + * - | ``--nonstd_anonymous_unions`` + | ``--no_nonstd_anonymous_unions`` + | + - | Enable or disable extensions to the C++ anonymous union feature + (including of anonymous "structs" or "classes"). This option can also + be used in C modes. Enabled by default in GNU and Microsoft modes, + and disabled by default in strict modes. + * - | ``--nonstd_default_arg_deduction`` + | ``--no_nonstd_default_arg_deduction`` + | + - | Controls whether default arguments are retained as part of deduced + function types. The C++ standard requires that default arguments not + be part of deduced function types. + * - | ``--nonstd_instantiation_lookup`` + | ``--no_nonstd_instantiation_lookup`` + | + - | Controls whether the lookup of names during template instantiation + should, instead of the normal lookup rules, use rules that were part + of the C++98 working paper for some time during the development of the + standard. In this mode, names are looked up in both the namespace of + the template definition and in the namespace in which a template + entity was first referenced in a way that would require an + instantiation. + * - | ``--nonstd_qualifier_deduction`` + | ``--no_nonstd_qualifier_deduction`` + | + - | Controls whether nonstandard template argument deduction should be + performed in the qualifier portion of a qualified name. With this + feature enabled, a template argument for the template parameter ``T`` + can de deduced in contexts like ``A::B`` or ``T::B``. The standard + deduction mechanism treats these as nondeduced contexts that use the + values of template parameters that were either explicitly specified or + deduced elsewhere. + * - | ``--old_id_chars`` + | ``--no_old_id_chars`` + - | Controls whether the set of extended characters accepted in C++ + identifiers should be those specified by pre-C++23 C++ standards or by + Unicode Standard Annex #44. The latter is the default in all C++ + modes, because the C++ Standard Committee adopted the Unicode + specification of identifier characters both for C++23 and + retroactively for earlier standards. + * - | ``--old_for_init`` + | ``--new_for_init`` + - | Control the scope of a declaration in a ``for-init-statement``. The + old (cfront-compatible) scoping rules mean the declaration is in the + scope to which the ``for`` statement itself belongs; the new + (standard-conforming) rules in effect wrap the entire ``for`` + statement in its own implicitly generated scope. The default behavior + is specified by configuration constant + ``DEFAULT_USE_NONSTANDARD_FOR_INIT_SCOPE``. This option is valid only + in C++ mode. + * - | ``--pack_alignment`` *n* + - | Set the default alignment for packing classes and structs to *n*, a + power-of-2 value within the range defined by + ``TARG_MINIMUM_PACK_ALIGNMENT`` and ``TARG_MAXIMUM_PACK_ALIGNMENT``. + The argument *n* is the default maximum alignment for nonstatic data + members; it can be overridden by a ``#pragma pack`` directive. This + option is allowed only when ``USER_CONTROL_OF_STRUCT_PACKING`` is + TRUE. + * - | ``--parse_templates`` + | ``--no_parse_templates`` + | + - | Enable or disable the parsing of nonclass templates in their generic + form (i.e., even if they are not really instantiated). It is done by + default if dependent name processing is enabled. This option is valid + only in C++ mode. + * - | ``--preserve_lvalues_with_same_type_casts`` + | ``--no_preserve_lvalues_with_same_type_casts`` + | + - | Explicitly enable or disable treating a cast of an lvalue to its own + type as that same lvalue (whereas both C and C++ specify that such + casts result in rvalues). Enabled by default in Microsoft and Sun + modes. + * - | ``--require_func_prototypes`` + | ``--no_require_func_prototypes`` + - | In C, controls whether old-style non-prototype function declarators + are recognized. If not, something like "``int f();``" is equivalent + to "``int f(void);``". The default is that non-prototype function + declarators are not recognized in C23 mode, while they are recognized + in earlier C modes. + * - | ``--short_enums`` + | ``--no_short_enums`` + - | Enable or disable a mode in which all enumeration types are "packed" + (meaning that the underlying type of the enumeration is chosen to be + the smallest integer that will accommodate the enumerator constants). + Only valid in GNU C compatibility mode. + * - | ``--signed_bit_fields`` + | + - | Make bit fields declared with a plain integer type (e.g., ``short`` or + ``int``, but not ``signed short`` or ``unsigned int``) signed. + * - | ``--signed_chars`` + | ``-s`` + - | Make plain ``char`` signed. The default signedness for ``char`` is + selected at the time of installation of the front end (information on + this appears in a later section of this document). When plain + ``char`` is signed, the macro ``__SIGNED_CHARS__`` is defined by the + front end. + * - | ``--special_subscript_cost`` + | ``--no_special_subscript_cost`` + | + - | Enable or disable a special nonstandard weighting of the conversion to + the integral operand of the ``[]`` operator in overload resolution. + This is a compatibility feature that may be useful with some existing + code. The special cost is enabled by default in cfront 3.0 mode. + With this feature enabled, the following code compiles without error: + + .. code:: c++ + + struct A { + A(); + operator int *(); + int operator[](unsigned); + }; + void main() { + A a; + a[0]; // Ambiguous, but allowed with + // this option operator[] + // is chosen + } + + | As of July 1996, the above is again acceptable, if ``ptrdiff_t`` is + configured as ``long``. Using a parameter of type ``ptrdiff_t`` + (instead of ``unsigned``\ ``int``) is recommended for portability. + * - | ``--no_stdarg_builtin`` + - | Disable special treatment of the ```` header. When enabled, + the ```` header is treated as a built-in, and references to + its macros (``va_start`` et al) are passed through as such in + generated C or C++ code. The default value is supplied by + ``DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE``. This option + cannot be used when the feature is disabled by default. + * - | ``--unsigned_bit_fields`` + | + - | Make bit fields declared with a plain integer type (e.g., ``short`` or + ``int``, but not ``signed short`` or ``unsigned int``) unsigned. + * - | ``--unsigned_chars`` + | ``-u`` + - | Make plain ``char`` unsigned. The default signedness for ``char`` is + selected at the time of installation of the front end (information on + this appears in a later section of this document). + * - | ``--using_std`` + | ``--no_using_std`` + - | Enable or disable implicit use of the ``std`` namespace when standard + header files are included. The default behavior is specified by the + configuration constant ``DEFAULT_IMPLICIT_USING_STD``. This option is + valid only in C++ mode. Note that this does *not* do the equivalent + of putting a "``using namespace std;``" in the program to allow old + programs to be compiled with new header files; it has a special and + localized meaning related to the EDG versions of certain header files, + and is unlikely to be of much use to end-users of the Front End. + +Template Instantiation Options +------------------------------ + +.. list-table:: + + * - | ``--auto_instantiation`` + | ``--no_auto_instantiation`` + | ``-T`` + - | Enable or disable automatic instantiation of templates. The + ``-T`` option is equivalent to ``--auto_instantiation``. The + default behavior is specified by the configuration flag + ``DEFAULT_AUTOMATIC_INSTANTIATION_MODE``. See + :ref:`template-instantiation`. This option is valid only in C++ + mode. + * - | ``--definition_list_file`` *file_name* + | + - | This option specifies the name of the template definition list file + passed between the front end and the prelinker. This file is a + temporary file and does not remain after the compilation is complete. + This option is supplied for use by the driver program that invokes the + front end and is not intended to be used by end-users. + * - | ``--exported_template_file`` *file-name* + | + - | This option specifies the name to be used for the exported template + file used for processing of exported templates. This option is + supplied for use by the driver program that invokes the front end and + is not intended to be used by end-users. + * - | ``--ii_file`` *file-name* + - | This option specifies the name to be used for the template + instantiation request file used in automatic instantiation mode. This + option is supplied for use by the driver program that invokes the + front end and is not intended to be used by end-users. + * - | ``--implicit_include`` + | ``--no_implicit_include`` + | ``-B`` + - | Enable or disable implicit inclusion of source files as a method + of finding definitions of template entities to be instantiated. + ``-B`` is equivalent to ``--implicit_include``. The default + behavior is specified by the configuration flag + ``DEFAULT_IMPLICIT_TEMPLATE_INCLUSION_MODE``. See + :ref:`template-instantiation`. This option is valid only in C++ + mode. + * - | ``--instantiate`` *mode* + | ``-t``\ *mode* + - | Control instantiation of external template entities. External + template entities are external (i.e., noninline and nonstatic) + template functions, variables, and template static data members. The + instantiation mode determines the template entities for which code + should be generated based on the template definition): + + ``none`` + Instantiate no template entities. This is the default. + + ``used`` + Instantiate only the template entities that are used in this + compilation. + + ``all`` + Instantiate all template entities whether or not they are used. + + ``local`` + Instantiate only the template entities that are used in this + compilation and force those entities to be local to this + compilation. + + | See :ref:`template-instantiation`. This option is valid only in + C++ mode. + * - | ``--instantiation_dir`` *dir-name* + | + - | When ``--one_instantiation_per_object`` is used, this option can be + used to specify a directory into which the generated object files (or + C files, if the C-generating back end if being used) should be put. + The ``eccp`` script always specifies this option when invoking the + front end, with the default of ``Template.dir`` if the option is not + specified by the user. + * - | ``--one_instantiation_per_object`` + | + - | Put out each template instantiation in this compilation (function, + variable, or static data member) in a separate object file. The + primary object file contains everything else in the compilation, i.e., + everything that isn't an instantiation. Having each instantiation in + a separate object file is very useful when creating libraries, because + it allows the user of the library to pull in only the instantiations + that are needed. That can be essential if two different libraries + include some of the same instantiations. This option is valid only in + C++ mode, and only if the configuration constant + ``ONE_INSTANTIATION_PER_OBJECT`` is TRUE. + * - | ``--pending_instantiations=`` *n* + | + - | Specifies the maximum number of instantiations of a given template + that may be in process of being instantiated at a given time. This is + used to detect runaway recursive instantiations. If *n* is zero, + there is no limit. The default is specified by the configuration + parameter ``DEFAULT_MAX_PENDING_INSTANTIATIONS``. + * - | ``--suppress_instantiation_flags`` + | + - | When automatic instantiation is being used, this option suppresses the + generation of the special symbols used by the prelinker to do + automatic instantiation processing. This option is for use by the + driver and prelinker and should not be used directly by users. This + option is used by to implement the driver option that removes the + instantiation flags from object files once the prelinking step has + completed. + * - | ``--template_directory`` *dir* + | + - | Specifies a directory name to be placed on the exported template + search path. The directories are used to find the definitions of + exported templates and are searched in the order in which they are + specified on the command-line. The current directory is always the + first entry on the search path. + * - | ``--template_info_file`` *file-name* + | + - | This option specifies the name to be used for the template + instantiation information file used in automatic instantiation mode. + This option is supplied for use by the driver program that invokes the + front end and is not intended to be used by end-users. + +Code Generation Options +----------------------- + +The following options control the IL produced, the C-generating back end, or +the C++-generating back end. + +.. list-table:: + + * - | ``--no_code_gen`` + | ``-n`` + - | Do syntax-checking only, i.e., do not run the back end. + * - | ``--force_vtbl`` + - | Force definition of virtual function tables in cases where the + heuristic used by the front end to decide on definition of virtual + function tables provides no guidance. See ``--suppress_vtbl``. This + option is valid only in C++ mode. + * - | ``--no_il_lowering`` + | ``-N`` + - | On versions that include IL lowering and that write an intermediate + language file, suppress both IL lowering and the back end, and write + an unlowered (i.e., C++ rather than C) IL file. Probably not of + interest to end users. + * - | ``--inline_statement_limit`` *size* + | + - | When inlining is enabled, sets the maximum size (in number of lowered + statements) for a routine to be inlinable. A value of zero allows an + inlined routine to be any size. Only available when + ``MINIMAL_INLINING`` is configured to be TRUE. + * - | ``--inlining`` + | ``--no_inlining`` + - | Enable or disable minimal inlining of function calls. These options + are available only when ``MINIMAL_INLINING`` is configured to be TRUE. + The default is to do inlining when the C-generating back end is used. + * - | ``--keep_restrict_in_signatures`` + | ``--no_keep_restrict_in_signatures`` + - | In most modern configurations, top-level parameter type qualifiers + are removed from function types. In such configurations, this + option overrides or preserves that behavior for the ``restrict`` + qualifier; i.e., when the option is enabled, the mangled name of a + function will reflect the presence of top-level restrict parameter + type qualifiers. + * - | ``--module_init`` *name1,name2,...* + | ``-i``\ *name1,name2,...* + - | When generating C output for testing (see ``c_gen_be`` in an + Appendix), when compiling in C mode, and if the current compilation + contains a main program, force calling of the file-scope + initialization routines in the indicated compiled units. This is + needed only when there are file-scope union initializations in + translation units that do not contain a main program. A message will + be issued during compilation of such units, indicating the need for + the ``--module_init`` option. All necessary names must be specified + in one ``--module_init`` option; a second ``--module_init`` will + overwrite the original list, not add to it. This option is not needed + when object code is generated by a back end other than the + C-generating back end, nor is it needed when the C-generating back end + is configured to generate ANSI C. This option is not needed in C++ + mode, because C++ has a language mechanism for getting initialization + code executed at program start-up. + * - | ``--gen_c_clang_version`` *version-number* + | + - | When using the C- or C++-generating back end to produce code that + is to be compiled with the ``clang`` compiler, this specifies the + version of the compiler being used (e.g., 150000 for version + 15.0). This option is supplied for use by the driver program that + invokes the front end and is not intended to be used by end-users. + * - | ``--gen_c_gnu_version`` *version-number* + | + - | When using the C- or C++-generating back end to produce code that + is to be compiled with the ``gcc`` compiler, this specifies the + version of the compiler being used (e.g., 140100 for version + 14.1.0). This option is supplied for use by the driver program + that invokes the front end and is not intended to be used by + end-users. + * - | ``--gen_c_msvc_version`` *version-number* + | + - | When using the C- or C++-generating back end to produce code that + is to be compiled with the Microsoft compiler, this specifies the + version of the compiler being used (e.g., 1932 for Visual Studio + 2022 Update 2). (This option is identical to the earlier + ``--msvc_target_version`` option, which continues to be accepted.) + This option is supplied for use by the driver program that invokes + the front end and is not intended to be used by end-users. + * - | ``--remove_unneeded_entities`` + | ``--no_remove_unneeded_entities`` + | + - | Enable or disable an optimization to prune the IL tree of types, + variables, routines, and related IL entries that are not "really + needed." (Something may be referenced but unneeded if it is referenced + only by something that is itself unneeded; certain entities, such as + global variables and routines defined in the translation unit, are + always considered to be needed.) The positive form of the option is + available only when ``MAINTAIN_NEEDED_FLAGS`` is TRUE. + * - | ``--suppress_vtbl`` + | ``-V`` + - | Suppress definition of virtual function tables in cases where the + heuristic used by the front end to decide on definition of virtual + function tables provides no guidance. The virtual function table for + a class is defined in a compilation if the compilation contains a + definition of the first non-inline non-pure virtual function of the + class. For classes that contain no such function, the default + behavior is to define the virtual function table (but to define it as + a local static entity). The option ``--suppress_vtbl`` suppresses the + definition of the virtual function tables for such classes, and + ``--force_vtbl`` forces the definition of the virtual function table + for such classes. ``--force_vtbl`` differs from the default behavior + in that it does not force the definition to be local. This option is + valid only in C++ mode. + * - | ``--target`` *target-config-name* + | + - | For configurations that support multiple targets, specifies that the + target configuration named *target-config-name* should be used for the + compilation. If no ``--target`` option is specified, the default + target configuration (which may or may not be the legacy + configuration) is used. + +Precompiled Header Options +-------------------------- + +The following options control how precompiled header files are generated and +used. + +.. list-table:: + + * - | ``--pch`` + - | Automatically use and/or create a precompiled header file -- for + details, see :ref:`precompiled-headers`. If + ``--use_pch`` or ``--create_pch`` (manual PCH mode) appears on the + command line following this option, its effect is erased. + * - | ``--create_pch`` *file-name* + - | If other conditions are satisfied (see + :ref:`precompiled-headers`), create a precompiled header file with + the specified name. If ``--pch`` (automatic PCH mode) or + ``--use_pch`` appears on the command line following this option, + its effect is erased. + * - | ``--use_pch`` *file-name* + - | Use a precompiled header file of the specified name as part of the + current compilation. If ``--pch`` (automatic PCH mode) or + ``--create_pch`` appears on the command line following this option, + its effect is erased. + * - | ``--pch_dir`` *directory-name* + - | The directory in which to search for and/or create a precompiled + header file. This option may be used with automatic PCH mode + (``--pch``) or with manual PCH mode (``--create_pch`` or + ``--use_pch``). + * - | ``--pch_messages`` + | ``--no_pch_messages`` + - | Enable or disable the display of a message indicating that a + precompiled header file was created or used in the current + compilation. + * - | ``--pch_verbose`` + - | In automatic PCH mode, for each precompiled header file that cannot be + used for the current compilation, a message is displayed giving the + reason that the file cannot be used. + * - | ``--pch_mem`` *size* + - | The number of 1024-byte units of preallocated memory in which to save + precompiled-header state (only if ``USE_MMAP_FOR_MEMORY_REGIONS`` is + FALSE). + +C++/CLI Options +--------------- + +.. list-table:: + + * - | ``--mscorlib_file_name`` *file-name* + - | Use the given assembly metadata file instead of ``mscorlib.dll`` to + import system types. + * - | ``--preusing`` *file-name* + - | Import the given assembly metadata file prior to processing the input + source (but after importing ``mscorlib.dll`` or the file specified + with the ``--mscorlib_file_name`` option). + * - | ``--using_directory`` *directory-name* + | + - | Add the given directory to the search path used when searching for + assembly metadata files. + * - | ``--using_framework_directory`` + | ``--no_using_framework_directory`` + | + - | Do or do not implicitly include the installation directory of the + Microsoft .NET runtime in the search path used when searching for + assembly metadata files. The default is to include that directory. + * - | ``--vcmeta_directory`` *directory-name* + | + - | Search for the ``vcmeta.dll`` file in the specified directory. If + omitted, ``vcmeta.dll`` is searched for in the same directory as the + module that contains the front end. + +Front End Debugging Options +--------------------------- + +.. list-table:: + + * - | ``--db``\ *n* + | ``--db``\ *name*\ ``=``\ *n* + | ``-d``\ *n* + | ``-d``\ *name*\ ``=``\ *n* + - | Set the debug output level in the front end, which controls the + output of flow-tracing and similar information to the debug output + file (``stderr``). ``--db``\ *n* sets the debug level to *n* (in + the range 1-5) for the entire execution of the compiler (higher + values generate more voluminous debugging output). One can + control the debug output more precisely by specifying a routine + name and the debug level desired upon entry to that routine, as in + ``--db``\ *name*\ ``=``\ *n*. Regardless of the previous setting + of the debug level, it will be changed to the indicated value on + entry to the indicated routine; on exit, it will be restored to + its former value. One can also use ``+=`` or ``-=`` in place of + ``=`` in that option to increase or decrease the debug level + relative to its current value. The former value is also restored + on exit from the routine in those cases. Ordinarily, a message is + written to debug output whenever the debug level is changed (i.e., + both on entry and exit in the above cases). If that is not + desirable, a ``!`` (implying "not") can be appended to the level + number in the command-line option, to indicate that the + level-change messages should not be produced for that request. + Several routine names can be specified, and/or several requests + can be made, by separating them with commas, as in the following: + + ``--db fe_init,fe_wrapup+=2,get_token=3`` + * - | ``-d-``\ *name1*\ ``,-``\ *name2*\ ``,``\ *...* + - | Enable the named "debug flags", which will enable debug output + associated with the flag. For example, ``-d-dump_layout`` produces + output related to the class type layout process. + * - | ``-d#``\ *name1*\ ``,#``\ *name2*\ ``,``\ *...* + - | Disable the named "debug flags". + * - | ``--db_name=``\ *name* + - | Enable debug output for source entities with the given name. Not all + debug output takes this option into account; i.e., even with this + option some debug output not associated with the given name may be + produced. When simultaneously compiling multiple translation units, + entities in all translation units are considered by default. The + given name can be restricted to entities in the primary translation + units by preceding it with ``[]`` or to entities in a secondary + translation unit by preceding it with ``[``\ *file*\ ``]`` where + *file* is the name of the secondary source file. For example, + + ``-d-trans_corresp --db_name=[x.cpp]A::f`` + + | will output debugging information about cross-translation-unit + correspondences for a member ``A::f`` declared in a secondary + translation unit defined by source file x.cpp. + +Miscellaneous Options +--------------------- + +.. list-table:: + + * - | ``--version`` + | ``-v`` + - | Display the version number of the front end, and the Edison Design + Group copyright. + * - | ``--building_runtime`` + - | Used to indicate that the EDG runtime library is being compiled. This + causes additional macros to be predefined that are used to pass target + configuration information from the front end to the runtime. + * - | ``--edg_base_dir`` + - | The name of the directory in which to find files needed by the front + end at execution time. This option is supplied for use by the driver + program that invokes the front end and is not intended to be used by + end-users. + * - | ``--dump_command_options`` + - | Display the complete set of ``--``\ *name* + command-line options recognized by the front end in a format that is + compatible with, e.g., the bash shell's complete command to allow the + shell's completion facility to be used with front end options. + * - | ``--dump_configuration`` + - | Display the complete set of configuration + macros with which the front end was built. The output (to the error + output file) can be captured and used as the contents of the + ``defines.h`` file to recreate that configuration. This option is + available only in executables built with ``DEBUG`` set to TRUE. + * - | ``--dump_legacy_as_target`` *target-config-name* + - | Displays the legacy configuration in such a manner that the + configuration can be used to specify a new target configuration named + *target-config-name*. For customers who have multiple versions of the + front end (each configured for a specific target), this option can be + used to generate a separate target configuration for each of the + legacy configurations, and the output combined to form a single + configuration where the target can be specified at run-time (via the + ``--target`` option). This option is available only in executables + built with ``DEBUG`` set to TRUE. The output is directed to the error + output file. + * - | ``--incognito`` + | ``--no_incognito`` + - | Enable or disable the suppression of implicitly-defined + EDG-specific macros such as ``__EDG__`` and ``__EDG_VERSION__``. + Suppressing these macros facilitates compilation of code that + incorrectly configures itself via conditional compilation when it + detects that the compiler is based on the EDG front end. The + default behavior of the front end is determined by the value of + the configuration macro DEFAULT_INCOGNITO. + * - | ``--il_display`` + - | Displays the IL in a human-readable form. This is + the same output that would be generated by writing the IL to a file + and displaying it with the ``edgcpdisp`` utility. The IL that is + displayed is lowered IL (if the configuration does lowering) unless + the ``--no_il_lowering`` command-line option is also specified. + * - | ``--mmap_address`` *address* + - | Specify the fixed address to be used in calls to ``mmap``. Valid + addresses are specific to the host operating system (and + architecture), and may change from invocation to invocation + (depending, say on which shared libraries are loaded). The address + chosen should be aligned to the page size of the host. The use of a + fixed address for ``mmap`` is useful in cases where pre-compiled + header files are used (to ensure that the same address space is + available from one invocation of the front end to another). This + option is available only in executables built with + ``USE_FIXED_ADDRESS_FOR_MMAP`` set to TRUE. + * - | ``--check_unicode_security`` + | ``--no_check_unicode_security`` + - | Enable or disable checking of comments, string literals, and + identifiers for Unicode patterns that could be used to disguise + malicious source code by making it appear innocuous; suspicious + patterns are reported as warnings. Checking is only applicable to + UTF-encoded Unicode source and header files. These options are + available only in executables built with + ``UNICODE_VULNERABILITY_CHECKING_SUPPORTED`` set to TRUE. + * - | ``--module_import_diagnostics`` + | ``--no_module_import_diagnostics`` + - | Enable or disable the issuing of diagnostic messages during the import + of entities from a module. The option can be used to reduce verbosity + and condense diagnostics that do not relate to the source file being + compiled. The default setting is specified by the + ``DEFAULT_MODULE_IMPORT_DIAG_ENABLED`` configuration macro. + * - | ``--wdir`` *directory-name* + - | Specify the directory to use in expanding relative path names. All + relative paths are expanded after command-line processing is complete, + so that any ``--wdir`` options preceding the final one have no effect. + +Environment Variables +===================== + +The environment variable ``USR_INCLUDE`` can be set to a directory to be used +instead of ``/usr/include`` on the standard include file search list. (Of +course, this has no effect if the front end has been configured to have an +empty "standard list" of include files.) + +When the front end is built with the ``__MICROSOFT_OS__`` flag set, the +environment variable ``TMP`` is used to specify the directory to be used for +temporary files. If ``TMP`` is not set, and when ``__MICROSOFT_OS__`` is not +set, the environment variable ``TMPDIR`` is used to indicate a directory to be +used for temporary files. If ``TMPDIR`` is not set, a default temporary +directory (often, ``/usr/tmp``) is used. (Note: at the present time, the front +end only uses temporary files when generating an intermediate language file for +immediate use by a back end called in the same program, and in the C-generating +back end.) + +Diagnostic Messages +=================== + +Diagnostic messages have an associated *severity*, as follows: + +* | Catastrophic errors indicate problems of such severity that the compilation + cannot continue. For example: command-line errors, internal errors, and + missing include files. If multiple source files are being compiled, any + source files after the current one will not be compiled. +* | Errors indicate violations of the syntax or semantic rules of the C or C++ + language. Compilation continues, but object code is not generated. +* | Warnings indicate something valid but questionable. Compilation continues + and object code is generated (if no errors are detected). +* | Remarks indicate something that is valid and probably intended, but which a + careful programmer may want to check. These diagnostics are not issued by + default. Compilation continues and object code is generated (if no errors + are detected). + +Diagnostics are written to the error output file with a form like the +following: + +.. code:: text + + "test.c", line 5: a break statement may only be used within a loop + or switch + break; + ^ + +Diagnostics are normally written to ``stderr``, but the front end can be +configured to use ``stdout`` by setting the ``DIRECT_ERROR_OUTPUT_TO_STDOUT`` +configuration macro. When this flag is set, messages are directed to +``stdout``, except when doing preprocessing only. Errors during command-line +processing are always directed to ``stderr``. + +Diagnostic messages can optionally be "colorized". Colorization is enabled +when the ``colorize_diagnostics`` global variable is TRUE. To support +colorization of diagnostics, diagnostics are annotated when the +``annotate_diagnostics`` global variable is TRUE. In that case, annotation +sequences are inserted into the diagnostic message itself to identify pieces of +the diagnostic that might later be highlighted in some fashion. These two +character annotations take the form of an "escape" character +(``DIAG_ANNOTATION_INDICATOR``) followed by an ``a_diagnostic_annotation_kind`` +enumerator. When colorization is enabled, ``format_output_line`` replaces the +annotations with Select Graphic Rendition (SGR) codes that, on most terminal +emulators, can be used to highlight text in various ways. The SGR codes used +for colorization default to a string specified by ``DEFAULT_EDG_COLORS`` which +can be overridden by the ``EDG_COLORS`` environment variable (if set). The +string consists of a colon-separated list of elements, where each element +specifies a string that maps to an ``a_diagnostic_annotation_kind`` value +followed by an "``=``" and the SGR string to use when highlighting text of that +kind. For example: + +.. code:: text + + "error=01;31:warning=01;35:note=01;36:locus=01:quote=01:range1=32" + +A customer can use the annotations in a diagnostic to display the annotated +pieces in any fashion they desire (e.g., when a GUI is available). + +Note that the message identifies the file and line involved, and that the +source line itself (with position indicated by the ``^``) follows the message. +If there are several diagnostics in one source line, each diagnostic will have +the form above, with the result that the text of the source line will be +displayed several times, with an appropriate position each time. + +Long messages are wrapped to additional lines when necessary. + +A configuration flag controls whether or not the string "``error:``" appears, +i.e., the front end can be configured so that the severity string is omitted +when the severity is "``error``". + +A command line option may be used to request a shorter form of the diagnostic +output in which the original source line is not displayed and the error message +text is not wrapped when too long to fit on a single line. + +A command line option may be used to request that the error number be included +in the diagnostic message. When displayed, the error number also indicates +whether the error may have its severity overridden on the command line. If the +severity may be overridden, the error number will include the suffix "``-D``" +(for "discretionary"); otherwise no suffix will be present. + +.. code:: text + + "Test_name.c", line 7: error #64-D: declaration does not declare anything + struct {}; + ^ + "Test_name.c", line 9: error #77: this declaration has no storage class or + type specifier + xxxxx; + ^ + +Because an error is determined to be discretionary based on the error severity +associated with a specific context, a given error may be discretionary in some +cases and not in others. + +For some messages, a list of entities is useful; they are listed following the +initial error message: + +.. code:: text + + "test.c", line 4: error: more than one instance of overloaded function "f" + matches the argument list: + function "f(int)" + function "f(float)" + argument types are: (double) + f(1.5); + ^ + +In some cases, some additional context information is provided; specifically, +such context information is useful when the front end issues a diagnostic while +doing a template instantiation or while generating a constructor, destructor, +or assignment operator function. For example: + +.. code:: text + + "test.c", line 7: error: "A::A()" is inaccessible + B x; + ^ + detected during implicit generation of "B::B()" at line 7 + +Without the context information, it is very hard to figure out what the error +refers to. + +If the front end is configured with ``FULLY_RESOLVED_MACRO_POSITIONS`` (and, +optionally, ``MACRO_INVOCATION_TREE_IN_IL``) set to TRUE, messages referring to +text occurring inside a macro expansion may provide additional information. +This additional information gives the source location from which the text was +copied into the macro expansion (i.e., from a macro definition or one of the +arguments in the top-level macro invocation), as well as possibly the chain of +macro invocations leading to the expanded text to which the diagnostic refers. +If the front end is configured to permit the display of this information, it +can also be enabled or disabled by the command-line option +``--[no_]macro_positions_in_diagnostics``. The information is presented in a +form like the following: + +.. code:: text + + "test.c", line 1: error: identifier "val" is undefined + #define incr(x) (x)+=val + ^ + in expansion of macro "incr" at "test.c", line 2, + in expansion of macro "next_val" at "test.c", line 4: + return next_val(i); + ^ + +Termination Messages +==================== + +When the front end is installed without the ``USING_DRIVER`` option (see +information on configuration later in this document), it writes sign-off +messages to the error output file. For example, one of the following forms of +message + +.. code:: text + + n errors detected in the compilation of "ifile". + 1 catastrophic error detected in the compilation of "ifile". + n errors and 1 catastrophic error detected in the compilation of "ifile". + +is written to indicate the detection of errors in the compilation. No message +is written if no errors were detected. The following message + +.. code:: text + + Error limit reached. + +is written when the count of errors reaches the error limit (see the ``-e`` +option, above); compilation is then terminated. The message + +.. code:: text + + Compilation terminated. + +is written at the end of a compilation that was prematurely terminated because +of a catastrophic error. The message + +.. code:: text + + Compilation aborted. + +is written at the end of a compilation that was prematurely terminated because +of an internal error. Such an error indicates an internal problem in the +compiler and should be reported to those responsible for its maintenance. + +Response to Signals +=================== + +Except in multi-threaded builds, the signals ``SIGINT`` (caused by a user +interrupt, like ``^C``) and ``SIGTERM`` (caused by a ``kill`` command) are +trapped by the front end and cause abnormal termination. When +``MULTIPLE_THREAD_COMPILATION`` is TRUE, it's expected that the customer +application will install handlers as appropriate and no signal handling is +performed by the front end. + +Exit Status +=========== + +On completion, the front end returns with a code indicating the +highest-severity diagnostic detected: 4 if there was a catastrophic error, 2 if +there were any errors, or 0 if there were any warnings or remarks or if there +were no diagnostics of any kind. + +If multiple source files are compiled, the exit status indicates the +highest-severity diagnostic detected in the entire compilation. + +.. _finding-includes: + +Finding Include Files +===================== + +A file name specified in a ``#include`` directive is searched for in a set of +directories specified by command-line options and environment variables. If +the file name specified does not include a suffix, a set of suffixes is used +when searching for the file. + +Files whose names are not absolute pathnames and that are enclosed in ``"..."`` +will be searched for in the following directories, in the order listed: + +#. The directory containing the current input file (the primary source file + or the file containing the ``#include``); [#f2]_ +#. any directories specified in ``--include_directory`` options (in the + order in which they were listed on the command line); +#. any directories on the standard list (this list is selected at the time + of installation of the front end; often, it is just the one directory + ``/usr/include`` or a similar system include directory for C++). + +For file names enclosed in ``<...>``, only the directories that are specified +using the ``--include_directory`` option and those on the standard list are +searched. If the directory name is specified as "``-``", e.g., "``-I-``", the +option indicates the point in the list of ``--include_directory`` options at +which the search for file names enclosed in ``<...>`` should begin. That is, +the search for ``<...>`` names should only consider directories named in +``--include_directory`` options following the ``-I-``, and the directories of +item 3 above. ``-I-`` also removes the directory containing the current input +file (item 1 above) from the search path for file names enclosed in ``"..."``. + +An include directory specified with the ``--sys_include`` option is considered +a "system" include directory. Warnings are suppressed when processing files +found in system include directories. If a default include directory has been +specified using the ``USR_INCLUDE`` configuration flag or environment variable, +it is considered a system include directory. + +If the file name has no suffix it will be searched for by appending each of a +set of include file suffixes. When searching in a given directory all of the +suffixes are tried in that directory before moving on to the next search +directory. The default set of suffixes is specified by the +``DEFAULT_INCLUDE_FILE_SUFFIX_LIST`` configuration parameter. The default can +be overridden using the ``--incl_suffixes`` command-line option. A null file +suffix cannot be used unless it is present in the suffix list (i.e., the front +end will always attempt to add a suffix from the suffix list when the file name +has no suffix). + +.. _finding-modules: + +Finding Module Files +==================== + +An ``import`` directive can specify either a module unit or a header unit, and +the process of finding these differ. A header unit import names the header +identically to the equivalent ``#include`` directive (a file name enclosed in +``<...>`` or ``"..."``), while a module unit is imported by its name and not +the name of the file containing the module unit. + +An ``import`` directive that specifies a header unit first finds the named +header using the process for finding ``#include`` files. See +:ref:`finding-includes`. If the header is found, the corresponding module file +is found by the following search, in the listed order: + +#. Using the direct mappings provided by ``--ms_header_unit``. +#. Using the unresolved mappings provided by ``--ms_header_unit_angle`` (if + the header file name is specified via ``<...>``) or by + ``--ms_header_unit_quote`` (if the header file name is specified via + ``"..."``). If a match is found here, that match is added to the map + for ``--ms_header_unit``. + +An ``import`` directive that specifies a module unit will search for the module +file, in the order listed: + +#. Any direct mappings from that module name to a module file as specified + by ``--ms_mod_file_map`` +#. Any files listed without a direct map by ``--ms_mod_file_map``, examining + those files to determine if the module each represents matches the module + being imported +#. Files in the directory containing the current input file (the primary + source file or the file containing the ``import``) +#. Files in any directories specified by\ ``--modules_directory`` (in the + order in which they were listed on the command line) +#. Files in the directory specified by the ``EDG_MODULES_PATH`` environment + variable, if it's set. + +C++ Dialect Accepted +==================== + +In strict C++ mode, the front end accepts the complete C++ language as defined +by the ISO/IEC 14882:2003 standard, including export templates (if the front +end's configuration allows them). In nonstrict C++ mode (which is the default +in common configurations), a small set of features -- particularly, export +templates -- are not supported, but some minor extensions commonly available on +other compilers are accepted. + +The front end accepts the complete C++17 language as defined by the ISO/IEC +14882:2017 standard (enabled through the command-line option ``--c++17``). The +front end also fully supports the earlier C++14, C++11, and (as noted above) +C++98/03 versions of the language. The front end supports most of the features +of the C++20 language as defined by the 14882:2020 standard (enabled through +the command-line option ``--c++20``). The C++20 features that are not accepted +yet are described below. + +Extensive compatibility modes are also available for the Microsoft Visual C++ +compilers, the GNU C++ ("GCC") compilers, and the clang C++ compiler. A more +basic Sun C++ compatibility mode is also implemented. Only one emulation mode +may be active at a time (but ``--ms_extensions`` or ``--ms_compatibility`` may +be enabled in non-Microsoft emulation modes). + +The front end also has a cfront compatibility mode, which duplicates a number +of "features" and bugs of cfront 2.1 and 3.0.x. Complete compatibility is not +guaranteed or intended -- the mode is there to allow programmers who have +unwittingly used cfront features to continue to compile their existing code. +In particular, if a program gets an error when compiled by cfront, the EDG +front end may produce a different error or no error at all. + +Command-line options are available to enable and disable anachronisms, to +control strict standard-conformance checking, and to adjust the severity of +certain diagnostics. + + + +C++20 Implementation Status +--------------------------- + +Most of the new features and changes in the C++20 standard are accepted by +the front end. Details about the specific changes (e.g., the first version +of the front end to support the feature, and the standard committee papers +that introduced the feature) can be found on the `EDG website +`__. + +The following C++20 features are not yet supported (our web site has links with +further details): + +* | Concepts are supported, but some of the most recent changes to the feature + are not yet supported: + + * | Partial ordering of rewritten operator candidates resulting from + constrained templates + * | Clarify declaration matching and partial ordering requiring substitution + into constraints +* | When are ``constexpr`` member functions defined? (core issue 1581). This + is not yet implemented because of concerns about potential code breakage. +* | Modules. (There is partial support for importing Microsoft modules. See + the release notes for more information.) + +C++23 and C++26 Implementation Status +------------------------------------- + +Some of the new features and changes in the C++23 and draft C++26 standard are +accepted by the front end. Details about the specific changes (e.g., the first +version of the front end to support the feature, and the standard committee +papers that introduced the feature) can be found on the `EDG website +`__. + +"Default" C++ Mode +------------------ + +The following extensions are accepted default C++ mode. Most of these are also +accepted in any other C++ mode that does not diagnose strict ANSI violations as +errors (exceptions are explicitly noted). + +* | A ``friend`` declaration for a class may omit the ``class`` keyword: + + .. code:: c++ + + class B; + class A { + friend B; // Should be "friend class B" + }; + +* | Constants of scalar type may be defined within classes (this is an old + form; the modern form uses an initialized static data member): + + .. code:: c++ + + class A { + const int size = 10; + int a[size]; + }; + +* | In the declaration of a class member, a qualified name may be used: + + .. code:: c++ + + struct A { + int A::f(); // Should be int f(); + }; + +* | If ``ALLOW_NONSTANDARD_ANONYMOUS_UNIONS`` is TRUE, an extension is + supported to allow an anonymous union to be introduced into a containing + class by a ``typedef`` name -- it needn't be declared directly, as with a + true anonymous union. For example: + + .. code:: c++ + + typedef union { + int i, j; + } U; // U identifies a reusable anonymous union. + class A { + U; // Okay -- references to A::i and A::j are allowed. + }; + + | In addition, the extension also permits "anonymous classes" and "anonymous + structs," as long as they have no C++ features (e.g., no static data + members or member functions and no nonpublic members) and have no nested + types other than other anonymous classes, structs, or unions. For + instance, + + .. code:: c++ + + struct A { + struct { + int i, j; + }; // Okay -- references to A::i and A::j are allowed. + }; + +* | If recognition of the ``restrict`` keyword is enabled, the C99 ``restrict`` + feature is supported in a form extended for C++, which allows ``restrict`` + as a type qualifier for reference and pointer-to-member types and for + nonstatic member functions. The set of C++ extensions is described in + J16/92-0057. +* | If ``IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE`` is TRUE, implicit + type conversion between a pointer to an ``extern "C"`` function and a + pointer to an ``extern "C++"`` function is permitted. Here's an example: + + .. code:: c++ + + extern "C" void f(); // f's type has extern "C" linkage + void (*pf)() // pf points to an extern "C++" function + = &f; // error unless implicit conversion is allowed + + | This extension is allowed in environments where C and C++ functions share + the same calling conventions (though it is pointless unless + ``DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT`` is TRUE). When + ``DEFAULT_IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_ALLOWED`` is set, it is + enabled by default; it can also be enabled in cfront-compatibility mode or + with command-line option ``--implicit_extern_c_type_conversion``. +* | A "``?``" operator whose second and third operands are string literals or + wide string literals can be implicitly converted to "``char *``" or + "``wchar_t *``". (Recall that in C++ string literals are ``const``. There + is a deprecated implicit conversion that allows conversion of a string + literal to "``char *``", dropping the ``const``. That conversion, however, + applies only to simple string literals. Allowing it for the result of a + "``?``" operation is an extension.) + + .. code:: c++ + + char *p = x ? "abc" : "def"; + +* | Default arguments may be specified for function parameters other than those + of a top-level function declaration (e.g., they are accepted on ``typedef`` + declarations and on pointer-to-function and pointer-to-member-function + declarations). +* | Nonstatic local variables of an enclosing function can be referenced in a + non-evaluated expression (e.g., a ``sizeof`` expression) inside a local + class. A warning is issued. +* | In default C++ mode (but not other non-C++11 modes), the friend class + syntax is extended to allow nonclass types as well as class types expressed + through a typedef or without an elaborated type name. For example: + + .. code:: c++ + + typedef struct S ST; + class C { + friend S; // Okay (requires S to be in scope). + friend ST; // Okay (same as "friend S;"). + friend int; // Okay (no effect). + friend S const; // Error: cv-qualifiers cannot appear directly. + }; + +* | In default C++ mode, mixed string literal concatenations are accepted. + (This is a feature carried over from C99 and also available in GNU modes. + It is not enabled in other non-C++11 modes.) + + .. code:: c++ + + wchar_t *str = "a" L"b"; // Okay, same as L"ab". + +* | In default C++ mode, variadic macros are accepted. (This is a feature + carried over from C99 and also available in GNU modes. It is not by + default enabled in other non-C++11 modes.) +* | In default C++ mode, empty macro arguments are accepted (a feature carried + over from C99). +* | A trailing comma in the definition of an enumeration type is silently + accepted (a feature carried over from C99): + + .. code:: c++ + + enum E { e, }; + +Except where noted, all of the extensions described in the C dialect section +are also allowed in C++ mode. + +.. _gnu-mode: + +GNU C++ Mode +------------ + +The front end can be built to accept GNU extensions. In GNU C++ mode, a large +number of extensions and bugs are closely emulated. This feature enables the +front end to compile many large and complex projects that were developed using +the GNU tool chain; this includes major open-source projects. + +Support for this emulation is ongoing: New GNU C++ features are added as +needed, with priority given to features used in system headers. + +Because the GNU compiler frequently changes behavior between releases, the +front end provides an option (``--gnu_version``) to specify a specific version +of GCC to emulate. Generally speaking, features and bugs are emulated to +exactly match each known version of GCC, but occasionally the emulation is +approximate and in such cases the front end is often a little more permissive +than GCC on the principle that it is more important to accept source that GCC +accepts than to diagnose every case that GCC diagnoses. The front end does +not, however, attempt to emulate every GCC command-line option; in particular, +GCC options to be extra-permissive are not emulated (however, the severity of +specific error diagnostics can sometimes be decreased to accept constructs that +are not by-default allowed in GNU emulation mode). + +Some GNU features are only emulated when specific configuration options are +enabled. For example, support for complex floating-point types is only +available when the front end is configured to support C99 extensions. + +A few GCC extensions there are likely *not* going to be supported in the +foreseeable future: + +* | The forward declaration of function parameters (so they can participate in + variable-length array parameters). +* | GNU-style complex *integral* types (complex *floating-point* types are + supported) +* | Nested functions +* | Local structs with variable-length array fields. Such fields are treated + (with a warning) as zero-length arrays in GNU C mode, which is a useful + approximation in some circumstances, but not generally equivalent to the + GNU feature. + +Microsoft C++ Mode +------------------ + +The front end also extensively emulates the Microsoft Visual C++ compilers. As +is the case with GNU modes, an option (``--microsoft_version``) is available to +select a specific version of Microsoft's compiler to emulate. + +Although Microsoft C++ and C modes generally emulate both extensions/features +and bugs, the emulation of a certain class of bugs (considered more severe) can +be controlled separately (using the ``--no_microsoft_bugs/--microsoft_bugs`` +options). + +Microsoft C++ mode can be combined with certain other language options to +enable a larger superset of the language accepted by the Microsoft compiler. + +In addition to full Microsoft emulation mode, two subsets of Microsoft +emulation are available: ``--ms_extensions``, and ``--ms_compatibility``, +corresponding to clang's ``-fms-extensions`` and ``-fms-compatibility`` +command-line options, respectively. These command-line options allow a certain +degree of Microsoft emulation while the primary emulation mode is something +else (e.g., ``--clang``). + +Support for Microsoft C++ emulation is ongoing: New features are added as +needed, with priority given to features used in system headers. + +Microsoft C++/CLI Mode +---------------------- + +The front end implements the language extensions known as "C++/CLI" that +simplifies writing C++-like programs for Microsoft's ".NET" environment. These +extensions are formally described through the ECMA-372 standard, but where the +Microsoft compiler deviates from the standard, the front end follows the +Microsoft compiler rather than the standard. + +Almost all C++/CLI features are implemented in the front end. This includes +various managed class kinds and the special members (e.g., properties) that +they can contain, delegates, handles and tracking references, ``gcnew``, +generics, importing of assemblies, hide-by-sig lookup rules, string literal +rules, and so forth. A notable exception is Microsoft-style attributes +(delimited by square brackets): The front end can parse them, but does not +currently implement their semantics. + +An earlier attempt at integrating C++ and .NET was known as "Managed C++": The +front end does not support those earlier Microsoft compiler features (which +have since been deprecated by Microsoft). + +Extensions Accepted in Sun Compatibility Mode +--------------------------------------------- + +The front end provides a "Sun Compatibility" mode. This mode automatically +selects a set of command-line options that provides the greatest compatibility +with the Sun CC 5.x compiler. It also enables certain extensions that are +accepted by the Sun compiler. Note that this mode is provided to enable the +front end to compile code such as commonly used Sun header files, and is not +intended to provide complete compatibility with the Sun compiler. + +Sun compatibility mode currently corresponds to the following combination of +options: + +.. code:: text + + --no_guiding_decls + --extern_inline + --nonstd_using_decl + +These settings can explicitly be overridden using more command-line options. + +The following extensions are accepted in Sun compatibility mode: + +* | The Sun-specific link scope specifiers ``__global``, ``__symbolic``, and + ``__hidden`` can be recognized. In modes that recognize these keywords, + the pragmas "``#pragma disable_ldscope``" and "``#pragma enable_ldscope``" + can be used to temporarily allow these keywords as normal identifiers. For + example: + + .. code:: c++ + + __global int i; // Accepted in some Sun modes. + #pragma disable_ldscope + int __global; // Okay: Keyword (temporarily) deactivated. + #pragma enable_ldscope + struct __global; // Error: __global is a keyword. + +* | The ``__thread`` specifier can be used to indicate that a variable should + be placed in thread-local storage. +* | In Sun mode, a non-tag from one scope hides a tag from another scope when + both are visible as a result of a using-directive. + + .. code:: c++ + + template struct B { }; + namespace N { + typedef B A; + } + using namespace N; + class A;typedef A C; // Sun mode uses typedef N::A instead of ambiguity + +* | A reference to an undeclared function template is accepted when the + reference appears in the definition of a class template. + + .. code:: c++ + + template struct A { + friend void f<>(T&); // Accepted in Sun mode + }; + +* | When a friend class is declared with an unqualified name, the lookup of + that name is not restricted to the nearest enclosing namespace scope. + + .. code:: c++ + + struct S; + namespace N { + class C { + friend struct S; // ::S in Sun and Microsoft modes + }; + // (N::S otherwise) + } + +* | The ``typename`` keyword is ignored in most contexts. + + .. code:: c++ + + // The Sun compiler does recognize typename in a template parameter list + template class C { + // Illegal uses of typename that are accepted by the Sun compiler + typename T t; + typename typename T typename typename x; + }; + +* | A default argument may be specified in the definition of a member function + of a class template declared outside of the class. + + .. code:: c++ + + template struct A { + void f(int); + }; + template void A::f(int = 0) { } + +* | A template argument list may appear following a constructor name in + constructor definition that appears outside of the class definition: + + .. code:: c++ + + template struct A { + A(); + }; + template A::A(){} + +* | Template parameters are (incorrectly) visible in class template + specializations and specializations of members of class templates. + + .. code:: c++ + + template struct A { + void f(); + }; + template <> struct A { + T t; // T should not be visible here + }; + template <> void A::f() { + T t; // T should not be visible here + } + +* | The explicit instantiation of a class does not cause the instantiation of + its inline members. + + .. code:: c++ + + template struct A { + void f() { + g(); + } // Not instantiated in Sun mode + }; + template class A; + +* | An ``extern inline`` function that is referenced but not defined is + permitted (with a warning). +* | Default arguments are retained as part of deduced function types. +* | When searching for a header file specified using the ``<...>`` syntax, the + front end searches for the specified header file name and also for a + version with the suffix ``.SUNWCCh`` appended (e.g., ``stddef.h.SUNWCCh``). +* | The ``std`` namespace is predeclared. +* | A reference to a nonstatic data member may be written without an object + (not even an implicit ``this->``) inside a sizeof: + + .. code:: c++ + + typedef struct _X { + char A[512]; + } X; + static unsigned int foo() { + return sizeof(X::A); + } + +* | A storage class may appear in a declaration that also has a "direct" + linkage specification -- e.g., + + .. code:: c++ + + extern "s" static void f(); + + | is treated as equivalent to + + .. code:: c++ + + extern "C" { static void f(); } + +Anachronisms Accepted +--------------------- + +The following anachronisms are accepted when anachronisms are enabled: + +* | ``overload`` is allowed in function declarations. It is accepted and + ignored. +* | Definitions are not required for static data members that can be + initialized using default initialization. The anachronism does not apply + to static data members of template classes; they must always be defined. +* | The number of elements in an array may be specified in an array ``delete`` + operation. The value is ignored. +* | A single ``operator++()`` and ``operator--()`` function can be used to + overload both prefix and postfix operations. +* | The base class name may be omitted in a base class initializer if there is + only one immediate base class. +* | Assignment to ``this`` in constructors and destructors is allowed. This is + allowed only if anachronisms are enabled and the "assignment to ``this``" + configuration parameter is enabled. +* | A bound function pointer (a pointer to a member function for a given + object) can be cast to a pointer to a function. +* | A nested class name may be used as a nonnested class name provided no other + class of that name has been declared. The anachronism is not applied to + template classes. +* | A reference to a non-const type may be initialized from a value of a + different type. A temporary is created, it is initialized from the + (converted) initial value, and the reference is set to the temporary. +* | A reference to a non-const class type may be initialized from an rvalue of + the class type or a derived class thereof. No (additional) temporary is + used. +* | A function with old-style parameter declarations is allowed and may + participate in function overloading as though it were prototyped. Default + argument promotion is not applied to parameter types of such functions when + the check for compatibility is done, so that the following declares the + overloading of two functions named ``f``: + + .. code:: c++ + + int f(int); + int f(x) char x; { return x; } + + | It will be noted that in C this code is legal but has a different + meaning: a tentative declaration of ``f`` is followed by its definition. +* | When ``--nonconst_ref_anachronism`` is enabled, a reference to a nonconst + class can be bound to a class rvalue of the same type or a derived type + thereof. + + .. code:: c++ + + struct A { + A(int); + A operator=(A&); + A operator+(const A&); + }; + main () { + A b(1); + b = A(1) + A(2); // Allowed as anachronism + } + +Extensions Accepted in Cfront 2.1 Compatibility Mode +---------------------------------------------------- + +The following extensions are accepted in cfront 2.1 compatibility mode in +addition to the extensions listed in the 2.1/3.0 section following (i.e., these +are things that were corrected in the 3.0 release of cfront): + +* | The dependent statement of an ``if``, ``while``, ``do``-``while``, or + ``for`` is not considered to define a scope. The dependent statement may + not be a declaration. Any objects constructed within the dependent + statement are destroyed at exit from the dependent statement. +* | Implicit conversion from integral types to enumeration types is allowed. +* | A non-``const`` member function may be called for a ``const`` object. A + warning is issued. +* | A ``const void *`` value may be implicitly converted to a ``void *`` value, + e.g., when passed as an argument. +* | When, in determining the level of argument match for overloading, a + reference parameter is initialized from an argument that requires a + non-class standard conversion, the conversion counts as a user-defined + conversion. (This is an outright bug, which unfortunately happens to be + exploited in the NIH class libraries.) +* | When a builtin operator is considered alongside overloaded operators in + overload resolution, the match of an operand of a builtin type against the + builtin type required by the builtin operator is considered a standard + conversion in all cases (e.g., even when the type is exactly right without + conversion). +* | A reference to a non-``const`` type may be initialized from a value that is + a ``const``-qualified version of the same type, but only if the value is + the result of selecting a member from a ``const`` class object or a pointer + to such an object. +* | The cfront 2.1 "transitional model" for nested type support is simulated. + In the transitional model a nested type is promoted to the file scope + unless a type of the same name already exists at the file scope. It is an + error to have two nested classes of the same name that need to be promoted + to file scope or to define a type at file scope after the declaration of a + nested class of the same name. This "feature" actually restricts the + source language accepted by the compiler. This is necessary because of the + effect this feature has on the name mangling of functions that use nested + types in their signature. This feature does not apply to template classes + and is only enabled when the configuration switch + ``CFRONT_2_1_OBJECT_CODE_COMPATIBILITY`` is TRUE. +* | A cast to an array type is allowed; it is treated like a cast to a pointer + to the array element type. A warning is issued. +* | When an array is selected from a class, the type qualifiers on the class + object (if any) are not preserved in the selected array. (In the normal + mode, any type qualifiers on the object are preserved in the element type + of the resultant array.) +* | An identifier in a function is allowed to have the same name as a parameter + of the function. A warning is issued. +* | An expression of type ``void`` may be supplied on the return statement in a + function with a ``void`` return type. A warning is issued. +* | Cfront has a bug that causes a global identifier to be found when a member + of a class or one of its base classes should actually be found. This bug + is emulated in cfront compatibility mode but can be disabled by setting the + parameter ``CFRONT_GLOBAL_VS_MEMBER_NAME_LOOKUP_BUG`` to FALSE. A + warning is issued when, because of this feature, a nonstandard lookup is + performed. + | + | The following conditions must be satisfied for the nonstandard lookup to be + performed: + + * | A member in a base class must have the same name as an identifier at the + global scope. The member may be a function, static data member, or + nonstatic data member. Member type names don't apply because a nested + type will be promoted to the global scope by cfront which disallows a + later declaration of a type with the same name at the global scope. + * | The declaration of the global scope name must occur between the + declaration of the derived class and the declaration of an out-of-line + constructor or destructor. The global scope name must be a type name. + * | No other member function definition -- even one for an unrelated class + -- may appear between the destructor and the offending reference. + This has the effect that the nonstandard lookup applies to only one + class at any given point in time. For example: + + .. code:: c++ + + struct B { + void func(const char*); + }; + struct D : public B { + public: + D(); + void Init(const char* ); + }; + struct func { + func( const char* msg); + }; + D::D(){} + void D::Init(const char* t){ + // Should call B::func -- calls func::func instead. + new func(t); + } + + | The global scope name must be present in a base class (``B::func`` in this + example) for the nonstandard lookup to occur. Even if the derived class + were to have a member named ``func``, it is still the presence of + ``B::func`` that determines how the lookup will be performed. +* | A parameter of type "``const void *``" is allowed on ``operator delete``; + it is treated as equivalent to "``void *``". +* | A period ("``.``") may be used for qualification where "``::``" should be + used. Only "``::``" may be used as a global qualifier. Except for the + global qualifier, the two kinds of qualifier operators may not be mixed in + a given name (i.e., you may say ``A::B::C`` or ``A.B.C`` but not ``A::B.C`` + or ``A.B::C``). A period may not be used in a vacuous destructor reference + nor in a qualifier that follows a template reference such as ``A::B``. +* | Cfront 2.1 does not correctly look up names in friend functions that are + inside class definitions. In this example function f should refer to the + functions and variables (e.g., ``f1`` and ``a1``) from the class + declaration. Instead, the global definitions are used. + + .. code:: c++ + + int a1; + int e1; + void f1(); + class A { + int a1; + void f1(); + friend void f() { + int i1 = a1; // cfront uses global a1 + f1(); // cfront uses global f1 + } + }; + + | Only the innermost class scope is (incorrectly) skipped by cfront + as illustrated in the following example. + + .. code:: c++ + + int a1; + int b1; + struct A { + static int a1; + class B { + static int b1; + friend void f() { + int i1 = a1; // cfront uses A::a1 + int j1 = b1; // cfront uses global b1 + } + }; + }; + +* | ``operator=`` may be declared as a nonmember function. (This is flagged as + an anachronism by cfront 2.1) +* | A type qualifier is allowed (but ignored) on the declaration of a + constructor or destructor. For example: + + .. code:: c++ + + class A { + A() const; // No error in cfront 2.1 mode + }; + +* | The preprocessing symbol ``c_plusplus`` is defined in addition to the + standard ``__cplusplus``. + +Extensions Accepted in Cfront 2.1 and 3.0 Compatibility Mode +------------------------------------------------------------ + +The following extensions are accepted in both cfront 2.1 and cfront 3.0 +compatibility mode (i.e., these are features or problems that exist in both +cfront 2.1 and 3.0): + +* | Type qualifiers on the ``this`` parameter may be dropped in contexts + such as this example: + + .. code:: c++ + + struct A { + void f() const; + }; + void (A::*fp)() = &A::f; + + | This is actually a safe operation. A pointer to a ``const`` function may + be put into a pointer to non-``const``, because a call using the pointer is + permitted to modify the object and the function pointed to will actually + not modify the object. The opposite assignment would not be safe. +* | Conversion operators specifying conversion to ``void`` are allowed. +* | A nonstandard friend declaration may introduce a new type. A friend + declaration that omits the elaborated type specifier is allowed in default + mode, but in cfront mode the declaration is also allowed to introduce a new + type name. + + .. code:: c++ + + struct A { + friend B; + }; + +* | The third operand of the ``?`` operator is a conditional expression instead + of an assignment expression as it is in the modern language. +* | A reference to a pointer type may be initialized from a pointer value + without use of a temporary even when the reference pointer type has + additional type qualifiers above those present in the pointer value. For + example, + + .. code:: c++ + + int *p; + const int *&r = p; // No temporary used + +* | A reference may be initialized with a null. +* | Because cfront does not check the accessibility of types, access errors for + types are issued as warnings instead of errors. +* | When matching arguments of an overloaded function, a ``const`` variable + with value zero is not considered to be a null pointer constant. In + general, in overload resolution a null pointer constant must be spelled + "``0``" to be considered a null pointer constant (e.g., ``'\0'`` is not + considered a null pointer constant). +* | Inside the definition of a class type, the qualifier in the declarator for + a member declaration is dropped if that qualifier names the class being + defined. + + .. code:: c++ + + struct S { + void S::f(); // No warning in cfront mode + }; + +* | An alternate form of declaring pointer-to-member-function variables is + supported, namely: + + .. code:: c++ + + struct A { + void f(int); + static void sf(int); + typedef void A::T3(int); // nonstd typedef decl + typedef void T2(int); // std typedef + }; + typedef void A::T(int); // nonstd typedef decl + T* pmf = &A::f; // nonstd ptr-to-member decl + A::T2* pf = A::sf; // std ptr to static mem decl + A::T3* pmf2 = &A::f; // nonstd ptr-to-member decl + + | where ``T`` is construed to name a routine type for a nonstatic member + function of class ``A`` that takes an ``int`` argument and returns + ``void``; the use of such types is restricted to nonstandard + pointer-to-member declarations. The declarations of ``T`` and ``pmf`` in + combination are equivalent to a single standard pointer-to-member + declaration: + + .. code:: c++ + + void (A::* pmf)(int) = &A::f; + + | A nonstandard pointer-to-member declaration that appears outside of a class + declaration, such as the declaration of ``T``, is normally invalid and + would cause an error to be issued. However, for declarations that appear + within a class declaration, such as ``A::T3``, this feature changes the + meaning of a valid declaration. cfront version 2.1 accepts declarations, + such as ``T``, even when ``A`` is an incomplete type; so this case is also + excepted. +* | Protected member access checking is not done when the address of a + protected member is taken. For example: + + .. code:: c++ + + class B { protected: int i; }; + class D : public B { void mf(); }; + void D::mf() { + int B::* pmi1 = &B::i; // error, OK in cfront mode + int D::* pmi2 = &D::i; // OK + } + + | Note that protected member access checking for other operations (i.e., + everything except taking a pointer-to-member address) is done in the normal + manner. +* | The destructor of a derived class may implicitly call the private + destructor of a base class. In default mode this is an error but in cfront + mode it is reduced to a warning. For example: + + .. code:: c++ + + class A { + ~A(); + }; + class B : public A { + ~B(); + }; + B::~B(){} // Error except in cfront mode + +* | When disambiguation requires deciding whether something is a parameter + declaration or an argument expression, the pattern *type-name-or-keyword*\ + ``(``\ *identifier*... ``)`` is treated as an argument. For example: + + .. code:: c++ + + class A { + A(); + }; + double d; + A x(int(d)); + A(x2); + + | By default ``int(d)`` is interpreted as a parameter declaration (with + redundant parentheses), and so ``x`` is a function; but in + cfront-compatibility mode ``int(d)`` is an argument and ``x`` is a + variable. + | The declaration ``A(x2);`` is also misinterpreted by cfront. It should be + interpreted as the declaration of an object named ``x2``, but in cfront + mode is interpreted as a function style cast of ``x2`` to the type ``A``. + | Similarly, the declaration + + .. code:: c++ + + int xyz(int()); + + | declares a function named ``xyz``, that takes a parameter of type "function + taking no arguments and returning an ``int``." In cfront mode this is + interpreted as a declaration of an object that is initialized with the + value ``int()`` (which evaluates to zero). +* | A named bit-field may have a size of zero. The declaration is treated as + though no name had been declared. +* | Plain bit fields (i.e., bit fields declared with a type of ``int``) are + always unsigned. +* | The name given in an elaborated type specifier is permitted to be a + ``typedef`` name that is the synonym for a class name, e.g., + + .. code:: c++ + + typedef class A T; + class T *pa; // No error in cfront mode + +* | No warning is issued on duplicate size and sign specifiers. + + .. code:: c++ + + short short int i; // No warning in cfront mode + +* | An extra comma is allowed after the last argument in an argument list, as + for example in + + .. code:: c++ + + f(1, 2, ); + +* | A constant pointer-to-member-function may be cast to a pointer-to-function. + A warning is issued. + + .. code:: c++ + + struct A { + int f(); + }; + main () { + int (*p)(); + p = (int (*)())A::f; // Okay, with warning + } + +* | Arguments of class types that allow bitwise copy construction but also have + destructors are passed by value (i.e., like C structures), and the + destructor is not called on the "copy." In normal mode, the class object is + copied into a temporary, the address of the temporary is passed as the + argument, and the destructor is called on the temporary after the call + returns. Note that because the argument is passed differently (by value + instead of by address), code like this compiled in cfront mode is not + calling-sequence compatible with the same code compiled in normal mode. In + practice, this is not much of a problem, since classes that allow bitwise + copying usually do not have destructors. +* | A union member may be declared to have the type of a class for which the + user has defined an assignment operator (as long as the class has no + constructor or destructor). A warning is issued. +* | When an unnamed class appears in a ``typedef`` declaration, the ``typedef`` + name may appear as the class name in an elaborated type specifier. + + .. code:: c++ + + typedef struct { + int i, j; + } S; + struct S x; // No error in cfront mode + +* | Two member functions may be declared with the same parameter types when one + is static and the other is nonstatic with a function qualifier. + + .. code:: c++ + + class A { + void f(int) const; + static void f(int); // No error in cfront mode + }; + +* | The scope of a variable declared in the ``for-init-statement`` is the scope + to which the ``for`` statement belongs. + + .. code:: c++ + + int f(int i) { + for (int j = 0; j < i; ++j) { /* ... */ } + return j; // No error in cfront mode + } + +* | Function types differing only in that one is declared ``extern "C"`` and + the other ``extern "C++"`` can be treated as identical: + + .. code:: c++ + + typedef void (*PF)(); + extern "C" typedef void (*PCF)(); + void f(PF); + void f(PCF); + + | When ``DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT`` is FALSE, ``PF`` and + ``PCF`` are considered identical and ``void f(PCF)`` is treated as a + compatible redeclaration of ``f``. (By contrast, in standard C++``PF`` and + ``PCF`` are different and incompatible types -- ``PF`` is a pointer to an + ``extern "C++"`` function whereas ``PCF`` is a pointer to an ``extern "C"`` + function -- and the two declarations of ``f`` create an overload set.) + | + | However, even if ``DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT`` is TRUE, + it is possible to set + ``IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE`` to TRUE as well, so + that in cfront-compatibility mode an implicit type conversion will always + be done between a pointer to an ``extern "C"`` function and a pointer to an + ``extern "``\ C++``"`` function. +* | Functions declared ``inline`` have internal linkage. +* | ``enum`` types are regarded as integral types. +* | An uninitialized ``const`` object of non-POD class type is allowed even if + its default constructor is implicitly declared: + + .. code:: c++ + + struct A { virtual void f(); int i; }; + const A a; + +* | A function parameter type is allowed to involve a pointer or reference to + array of unknown bounds. +* | If the user declares an ``operator=`` function in a class, but not one that + can serve as the default ``operator=``, and bitwise assignment could be + done on the class, a default ``operator=`` is not generated; only the + user-written ``operator=`` functions are considered for assignments (and + therefore bitwise assignment is not done). +* | A member function declaration whose return type is omitted (and thus + implicitly ``int``) and whose name is found to be that of a type is + accepted if it takes no parameters: + + .. code:: c++ + + typedef int I; + struct S { + I(); // Accepted in cfront mode (declares "int S::I()") + I(int); // Not accepted + }; + +* | Default arguments are retained as part of deduced function types. + +C Dialect Accepted +================== + +The front end accepts the ANSI/ISO C language as defined by ANSI/ISO +9899:1990. In C99 mode, it accepts the ANSI/ISO C language defined by +ISO/IEC 9899:1999 as modified by Technical Corrigenda 1 through 3. In C11 +mode, it accepts the C language defined by ISO/IEC 9899:2011 and in C18 +mode the language defined by ISO/IEC 9899:2018 (which only differs from C11 +in minor ways). In C23 mode, many of the features of the latest standard +have been implemented. See the `EDG web site +`__ for up-to-date information about +feature implementation. + +When Embedded C extensions are enabled, the front end can accept the constructs +described in ISO/IEC TR 18037 (fixed-point types, named address space +qualifiers, and named-register storage class specifiers). + +The front end extensively emulates the C modes of the Microsoft, GNU, and clang +compilers. See :ref:`gnu-mode`. As with C++ mode, only one emulation mode may +be in effect for a given compilation. The ``--ms_extensions`` and +``--ms_compatibility`` options can be used to emulate certain Microsoft +behaviors irrespective of the emulation mode. + +There is no Sun C mode corresponding to Sun C++ mode, however. + +The special comments recognized by the UNIX ``lint`` program -- +``/*ARGSUSED*/``, ``/*VARARGS*/`` (with or without a count of non-varying +arguments), and ``/*NOTREACHED*/`` -- are also recognized by the front end. + +When Unified Parallel C (UPC) mode is enabled, it also accepts the core +language extensions described in `version 1.0 of the UPC Language +Specifications `__). + +C99 Features Available in Other Modes +------------------------------------- + +Certain C language features were added in the C99 version of the ISO C standard +and are supported in C99 mode. For a full list of those features, see ISO/IEC +9899:1999. A few features are noteworthy, however, because they are +implementation-specific or because they can be enabled in older C modes or +(when indicated) in C++ mode: + +* | The options ``--variadic_macros``, ``--no_variadic_macros``, + ``--extended_variadic_macros`` and ``--no_extended_variadic_macros`` + control whether macros taking a variable number of arguments are + recognized. Configuration flags are available to select the default + setting of these options; these are also available in C++ mode. + | Ordinary variadic macros (as included in C99) are illustrated by the + following example: + + .. code:: c++ + + #define OVM(x, ...) x(__VA_ARGS__) + void f() { OVM(printf, "%s %d\n", "Three args for ", 1); } + /* Expands to: printf("%s %d\n", "Three args for ", 1) */ + + | During expansion the special identifier ``__VA_ARGS__`` will be replaced by + the trailing arguments of the macro invocation. If variadic macros are + enabled, this special identifier can appear only in the replacement list of + variadic macros. + | Extended variadic macros (as implemented by certain pre-C99 compilers) use + a slightly different syntax and allow the name of the variadic parameter to + be chosen (instead of ``...``/``__VA_ARGS__``): + + .. code:: c++ + + #define EVM(x, args...) x(args) + void f() { EVM(printf, "%s %d\n", "Three args for ", 1); } + /* Same expansion as previous example. */ + + | In addition, enabling extended variadic macros adds a special behavior to + the token pasting operator ## when it is followed by an empty or omitted + macro argument: A preceding comma (possibly followed by white space) is + erased. Hence, + + .. code:: c++ + + #define EVM2(fmt, args) printf(fmt , ## args) + EVM2("Hello World\n") + + | expands to ``printf("Hello World\n")`` and the extraneous comma is erased. +* | If the ``LONG_LONG_ALLOWED`` switch is TRUE, + + * | the ``long long`` and ``unsigned long long`` types are accepted; + * | integer constants suffixed by ``LL`` are given the type ``long long``, + and those suffixed by ``ULL`` are given the type ``unsigned long long`` + (any of the suffix letters may be written in lower case); + * | the specifier ``%lld`` is recognized in ``printf`` and ``scanf`` + formatting strings; and + * | the ``long long`` types are accommodated in the usual arithmetic + conversions. +* | ``restrict`` may be used as a type qualifier for object pointer types and + function parameter arrays that decay to pointers. Its presence is recorded + in the IL so that back ends can perform optimizations that would otherwise + be prevented because of possible aliasing. The keyword is enabled by + ``--restrict``; this is also available in C++. +* | If ``VLA_ALLOWED`` is TRUE, variable length arrays (VLAs) are supported. + VLA types may appear only in the declaration of an identifier that belongs + to a block or function-prototype scope. For example: + + .. code:: c++ + + void addscalar(int n, int m, double a[n][m], double x) { + int i, j; + for (i=0; i.`` The form of + the macro reference is: + + .. code:: c++ + + __generic(x, y, z, func_d, func_f, func_l, func_cd, func_cf, func_cl) + + | where ``x`` and the optional ``y`` and ``z`` are the arguments with which a + type-generic function is called, and the remaining 6 arguments are the + names of functions from which is selected the actual function to be called. + The suffixes with which the function names are supplied here correspond to + function parameter types of ``double``, ``floa``\ t, ``long double``, + ``double _Complex``, ``float _Complex``, and ``long double _Complex``, + respectively. The order is fixed. Function names may be omitted. For + example, ```` may have the following macros defined: + + .. code:: c++ + + #define sin(x) __generic(x,,, sin, sinf, sinl, csin, csinf,csinl)(x) + #define fmax(x,y) __generic(x, y,,fmax, fmaxf, fmaxl,,,)(x, y) + #define conjg(x) __generic(x,,, ,,, conjg, conjgf, conjgl)(x) + + | Note that ``sin`` and ``conjg`` take only one argument, that ``fmax`` has + no forms that accept complex arguments, and that ``conjg`` has no forms + that accept real arguments. + | There is also a ``__genericfx`` pseudo-macro that provides a similar + capability for fixed-point types. The form of the macro reference is: + + .. code:: c++ + + __genericfx(x, fnc_hr, fnc_uhr, fnc_r, fnc_ur, fnc_lr, fnc_ulr, + fnc_hk, fnc_uhk, fnc_k, fnc_uk, fnc_lk, fnc_ulk) + + | where ``x`` is as above and the remaining 12 arguments are the names of + functions, with the suffixes corresponding to function parameter types of + ``short``\ ``_Fract``, ``unsigned``\ ``short``\ ``_Fract``, ``_Fract``, + ``unsigned``\ ``_Fract``, ``long``\ ``_Fract``, ``unsigned``\ ``long``\ + ``_Fract``, ``short``\ ``_Accum``, ``unsigned``\ ``short``\ ``_Accum``, + ``_Accum``, ``unsigned`` _Accum, ``long``\ ``_Accum``, ``unsigned``\ + ``long``\ ``_Accum``, respectively. +* | The keywords ``__I__``, ``__NAN__``, and ``__INFINITY__`` are defined as, + respectively, a float _Imaginary *i*, a float Not-a-Number, and a float + positive Infinity. These are intended to be used by library writers to + implement the C99 macros ``I``, ``NAN``, and ``INFINITY``. ``__NAN__`` and + ``__INFINITY__`` are also available in all modes, not just C99 mode. +* | A trailing array member of unspecified length in a struct type is called a + flexible array member. Such members are a standard feature in C99. In + default C99 mode (but not in strict C99 mode) trailing struct members can + also have a type containing a flexible array member. For example: + + .. code:: c++ + + struct F { + int i; + int f[]; // OK in default and strict C99 modes + }; + struct X { + F x; // OK in default C99 mode (but not in strict mode) + }; + +ANSI C Extensions +----------------- + +The following extensions are accepted (these are flagged if the ``-A`` or +``-a`` option is specified): + +* | A translation unit (input file) can contain no declarations. +* | Comment text can appear at the ends of preprocessing directives. +* | ``__ALIGNOF__`` (or ``__alignof__``) is similar to ``sizeof``, but returns + the alignment requirement value for a type, or ``1`` if there is no + alignment requirement. It may be followed by a type or expression in + parentheses: + + ``__ALIGNOF__(``\ *type*\ ``) __alignof__(``\ *type*\ ``)`` + + ``__ALIGNOF__(``\ *expression*\ ``) __alignof__(``\ *expression*\ ``)`` + + | The expression in the second form is not evaluated. +* | ``__INTADDR__(``\ *expression*\ ``)`` scans the enclosed expression as a + constant expression, and converts it to an integer constant (it is used in + the ``offsetof`` macro). +* | A number of "type traits pseudo-functions" (taking one or more type + names) are accepted: ``__has_nothrow_assign``, + ``__has_nothrow_constructor``, ``__has_nothrow_copy``, + ``__has_nothrow_move_assign``, ``__has_trivial_assign``, + ``__has_trivial_constructor``, ``__has_trivial_copy``, + ``__has_trivial_destructor``, ``__has_trivial_move_assign``, + ``__has_trivial_move_constructor``, ``__has_virtual_destructor``, + ``__is_abstract``, ``__is_base_of``, ``__is_class``, + ``__is_constructible``, ``__is_convertible_to``, ``__is_destructible``, + ``__is_empty``, ``__is_enum``, ``__is_literal_type``, + ``__is_nothrow_assignable``, ``__is_nothrow_constructible``, + ``__is_nothrow_destructible``, ``__is_pod``, ``__is_polymorphic``, + ``__is_standard_layout``, ``__is_trivial``, + ``__is_trivially_assignable``, ``__is_trivially_constructible``, + ``__is_trivially_copyable``, ``__is_trivially_destructible``, and + ``__is_union``. + + .. code:: c++ + + double x[__is_union(union U)]; // Okay. + + | These are silently accepted even in strict modes. They ease the + implementation C++11 metaprogramming templates (many of which were first + introduced by ISO/IEC TR 19768). +* | Bit fields may have base types that are ``enum``\ s or integral types + besides ``int`` and ``unsigned int``. This matches A.6.5.8 in the ANSI + Common Extensions appendix. +* | If the ``ADDR_OF_BIT_FIELD_ALLOWED`` flag is TRUE, the address of a bit + field may be taken if the bit field has the same size and alignment as one + of the integral types. A warning is issued. +* | The last member of a ``struct`` may have an incomplete array type. It may + not be the only member of the struct (otherwise, the struct would have zero + size). +* | A file-scope array may have an incomplete ``struct``, ``union``, or + ``enum`` type as its element type. The type must be completed before the + array is subscripted (if it is), and by the end of the compilation if the + array is not ``extern``. In C++, an incomplete ``class`` is also allowed. +* | Static functions may be declared in function and block scopes. Their + declarations are moved to the file scope. +* | ``enum`` tags may be incomplete: one may define the tag name and resolve it + (by specifying the brace-enclosed list) later. +* | The values of enumeration constants may be given by expressions that + evaluate to unsigned quantities that fit in the ``unsigned int`` range but + not in the ``int`` range. A warning is issued for suspicious cases. + + .. code:: c++ + + /* When ints are 32 bits: */ + enum a {w = -2147483648}; /* No warning */ + enum b {x = 0x80000000}; /* No warning */ + enum c {y = 0x80000001}; /* No warning */ + enum d {z = 2147483649}; /* Warning */ + +* | An extra comma is allowed at the end of an ``enum`` list. A remark is + issued except in ``pcc`` mode. +* | The final semicolon preceding the closing ``}`` of a struct or union + specifier may be omitted. A warning is issued except in ``pcc`` mode. +* | A label definition may be immediately followed by a right brace. + (Normally, a statement must follow a label definition.) A warning is + issued. +* | An empty declaration (a semicolon with nothing before it) is allowed. A + remark is issued. +* | An initializer expression that is a single value and is used to initialize + an entire static array, struct, or union need not be enclosed in braces. + ANSI C requires the braces. +* | In an initializer, a pointer constant value may be cast to an integral type + if the integral type is big enough to contain it. +* | The address of a variable with ``register`` storage class may be taken. A + warning is issued. +* | In an integral constant expression, an integer constant may be cast to a + pointer type and then back to an integral type. +* | ``long float`` is accepted as a synonym for ``double``. +* | If ``PTR_TO_INCOMP_ARRAY_ARITHMETIC_ALLOWED`` is TRUE, pointers to + incomplete arrays may be used in pointer addition, subtraction, and + subscripting: + + .. code:: c++ + + int (*p)[]; + ... + q = p[0]; + + | A warning is issued if the value added or subtracted is anything other than + a constant zero. Since the type pointed to by the pointer has zero size, + the value added to or subtracted from the pointer is multiplied by zero and + therefore has no effect on the result. +* | Benign redeclarations of ``typedef`` names are allowed. That is, a typedef + name may be redeclared in the same scope as the same type. A warning is + issued. +* | Dollar signs can be accepted in identifiers through use of a command line + option or by setting a configuration parameter. The default is to not + allow dollar signs in identifiers. +* | Numbers are scanned according to the syntax for numbers rather than the + ``pp-number`` syntax. Thus, ``0x123e+1`` is scanned as three tokens + instead of one invalid token. (If the ``-A`` or ``-a`` option is + specified, of course, the ``pp-number`` syntax is used.) +* | Assignment and pointer difference are allowed between pointers to types + that are interchangeable but not identical, for example, ``unsigned char + *`` and ``char *``. This includes pointers to same-sized integral types + (e.g., typically, ``int *`` and ``long *``). A warning is issued except in + ``pcc`` mode. Assignment of a string constant to a pointer to any kind of + character is allowed without a warning. +* | Assignment of pointer types is allowed in cases where the destination type + has added type qualifiers that are not at the top level (e.g., ``int **`` + to ``const int **``). Comparisons and pointer difference of such pairs of + pointer types are also allowed. A warning is issued. +* | In operations on pointers, a pointer to ``void`` is always implicitly + converted to another type if necessary, and a null pointer constant is + always implicitly converted to a null pointer of the right type if + necessary. In ANSI C, some operators allow such things, and others + (generally, where it does not make sense) do not allow them. +* | Pointers to different function types may be assigned or compared for + equality (``==``) or inequality (``!=``) without an explicit type cast. A + warning is issued. This extension is not allowed in C++ mode. +* | A pointer to ``void`` may be implicitly converted to or from a pointer to a + function type. +* | If the ``ATT_PREPROCESSING_EXTENSIONS_ALLOWED`` switch is TRUE, the + ``#assert`` preprocessing extensions of AT&T System V release 4 are + allowed. These allow definition and testing of predicate names. Such + names are in a name space distinct from all other names, including macro + names. A predicate name is given a definition by a preprocessing directive + of the form + + | ``#assert`` *name* + | ``#assert`` *name*\ ``(``\ *token-sequence*\ ``)`` + + | which defines the predicate *name*. In the first form, the predicate + is not given a value. In the second form, it is given the value + *token-sequence*. Such a predicate can be tested in a ``#if`` + expression, as follows: + + | ``#``\ *name*\ ``(``\ *token-sequence*\ ``)`` + + | which has the value 1 if a ``#assert`` of that *name* with that + *token-sequence* has appeared, and 0 otherwise. A given predicate may be + given more than one value at a given time. + + | A predicate may be deleted by a preprocessing directive of the form + + | ``#unassert`` *name* + | ``#unassert`` *name*\ ``(``\ *token-sequence*\ ``)`` + + | The first form removes all definitions of the indicated predicate name; the + second form removes just the indicated definition, leaving any others there + may be. +* | GNU line directive flags are accepted on ``#line`` directives. The system + header flag is recognized, and the associated code is treated as if found + in a system include directory. +* | ``asm`` statements and declarations are accepted. This is disabled in + strict ANSI C mode (``-A`` or ``-a`` and ``-m`` options) since it conflicts + with the ANSI C standard for something like + + .. code:: c++ + + asm("xyz"); + + | which ANSI C interprets as a call of an implicitly-defined function ``asm`` + and which by default the front end interprets as an ``asm`` statement. +* | When ``ASM_FUNCTION_ALLOWED`` is TRUE, ``asm`` functions are accepted, and + ``__asm`` is recognized as a synonym for ``asm``. An ``asm`` function body + is represented in the IL by an uninterpreted null-terminated string + containing the text that appears in the source (including the text of + source comments when ``INCLUDE_COMMENTS_IN_ASM_FUNC_BODY`` is TRUE). An + ``asm`` function must be declared with no storage class, with a prototyped + parameter list, and with no omitted parameters: + + .. code:: c++ + + asm void f(int,int) { + ... + } + + | If ``asm`` functions are recognized and the C-generating back end is used, + it is required that ANSI-C be generated, not K&R C, because the ``asm`` + function must be put out with a prototyped parameter list. +* | If ``ALLOW_NONSTANDARD_ANONYMOUS_UNIONS`` is TRUE, an extension is + supported to allow constructs similar to C++ anonymous unions, including + the following: + + * | not only anonymous unions but also anonymous structs are allowed -- that + is, their members are promoted to the scope of the containing struct and + looked up like ordinary members; + * | they can be introduced into the containing struct by a ``typedef`` name + -- they needn't be declared directly, as with true anonymous unions; and + * | a tag may be declared (C mode only). + + | Among the restrictions: the extension only applies to constructs within + structs. +* | If ``DEFAULT_ADDRESS_OF_ELLIPSIS_ALLOWED`` is TRUE, the expression ``&...`` + is accepted in the body of a function in which an ellipsis appears in the + parameter list. It is needed to support some versions of macro + ``va_start`` in ``stdarg.h``. +* | If ``DEFAULT_ALLOW_ELLIPSIS_ONLY_PARAM_IN_C_MODE`` is TRUE, an ellipsis may + appear by itself in the parameter list of a function declaration -- e.g., + ``f(...)``. A diagnostic is issued in strict ANSI C mode. +* | External entities declared in other scopes are visible. A warning is + issued. + + .. code:: c++ + + void f1(void) { extern void f(); } + void f2() { + f(); /* Using out of scope declaration */ + } + +* | A non-lvalue array expression is converted to a pointer to the first + element of the array when it is subscripted or similarly used. +* | The nonstandard preprocessing directive ``#include_next`` is supported. + This is a variant of the ``#include`` directive. It searches for the named + file only in the directories on the search path that follow the directory + in which the current source file (the one containing the ``#include_next`` + directive) is found. (This is an extension found in the GNU C compiler.) +* | The nonstandard preprocessing directive ``#warning`` is supported. It is + similar to the ``#error`` directive, but results in a warning instead of a + catastrophic error when processed. This directive is not recognized in + strict mode. (This is an extension found in GNU C compilers.) + +In the following areas considered "undefined behavior" by the ANSI C standard, +the front end does the following: + +* | Adjacent wide and non-wide string literals are not concatenated unless + ``wchar_t`` and ``char`` are the same type. (In C++ mode, when ``wchar_t`` + is a keyword, adjacent wide and non-wide string literals are never + concatenated.) +* | In character and string escapes, if the character following the ``\`` has + no special meaning, the value of the escape is the character itself. Thus + ``"\s" == "s"``. A warning is issued. +* | A ``struct`` that has no named fields but at least one unnamed field is + accepted by default, but a diagnostic (a warning or error) is issued in + strict ANSI C mode. + +K&R/pcc Mode +------------ + +When ``pcc`` mode is specified, the front end accepts the traditional C +language defined by *The C Programming Language*, first edition, by +Kernighan and Ritchie (K&R), Prentice-Hall, 1978. In addition, it provides +almost complete compatibility with the Reiser ``cpp`` and Johnson ``pcc`` +widely used as part of UNIX systems; since there is no documentation of the +exact behavior of those programs, complete compatibility cannot be +guaranteed. + +In general, when compiling in ``pcc`` mode, the front end attempts to interpret +a source program that is valid to ``pcc`` in the same way that ``pcc`` would. +However, ANSI features that do not conflict with this behavior are not +disabled. + +In some cases where ``pcc`` allows a highly questionable construct, the front +end will accept it but give a warning, where ``pcc`` would be silent (for +example: ``0x``, a degenerate hexadecimal number, is accepted as zero). + +The known cases where the front end is not compatible with ``pcc`` are the +following: + +* | Token pasting is not done outside of macro expansions (i.e., in the primary + source line) when two tokens are separated only by a comment. That is, + ``a/**/b`` is not considered to be ``ab``. The ``pcc`` behavior in that + case can be gotten by preprocessing to a text file and then compiling that + file. + | + | The textual output from preprocessing is also equivalent but not identical: + the blank lines and white space will not be exactly the same. +* | ``pcc`` will consider the result of a ``?:`` operator to be an lvalue if + the first operand is constant and the second and third operands are + compatible lvalues. This front end will not. +* | ``pcc`` mis-parses the third operand of a ``?:`` operator in a way that + some programs exploit: + + .. code:: c++ + + i ? j : k += l + + | is parsed by ``pcc`` as + + .. code:: c++ + + i ? j : (k += l) + + | which is not correct, since the precedence of ``+=`` is lower than the + precedence of ``?:``. This front end will generate an error for that case. +* | ``lint`` recognizes the keywords for its special comments anywhere in a + comment, regardless of whether or not they are preceded by other text in + the comment. The front end only recognizes the keywords when they are the + first identifier following an optional initial series of blanks and/or + horizontal tabs. ``lint`` also recognizes only a single digit of the + ``VARARGS`` count; the front end will accumulate as many digits as appear. + +The differences in ``pcc`` mode relative to the default ANSI mode are as +follows: + +* | The keywords ``signed``, ``const``, and ``volatile`` are disabled, to avoid + problems with items declared with those names in old-style code. Those + keywords were ANSI C inventions. The other non-K&R keywords (``enum`` and + ``void``) are judged to have existed already in code and are not disabled. +* | Declarations of the form + + .. code:: c++ + + typedef some-type void; + + | are ignored. +* | Assignment is allowed between pointers and integers, and between + incompatible pointer types, without an explicit cast. A warning is issued. +* | A field selection of the form *p*\ ``->``\ *field* is allowed even if + *p* does not point to a ``struct`` or ``union`` that contains *field*. + *p* must be a pointer or an integer. Likewise, *x*\ ``.``\ *field* is + allowed even if *x* is not a ``struct`` or ``union`` that contains + *field*. *x* must be an lvalue. For both cases, all definitions of + *field* as a field must have the same offset within their ``struct`` or + ``union``. +* | If the configuration flag ``TARG_NO_ERROR_ON_INTEGER_OVERFLOW`` is TRUE, + overflows detected while folding signed integer operations on constants + will cause warnings rather than errors. Usually this should be set to + match the desired target machine behavior on integer operations in C. +* | If the configuration flag ``SAME_REPR_INTS_INTERCHANGEABLE_IN_IL`` is TRUE, + integral types with the same representation (size, signedness, and + alignment) will be considered identical and may be used interchangeably. + For example, this means that ``int`` and ``long`` will be interchangeable + if they have the same size. +* | A warning will be issued for a ``&`` applied to an array. The type of such + an operation is "address of array element" rather than "address of array". +* | For the shift operators ``<<`` and ``>>``, the usual arithmetic conversions + are done, the right operand is converted to ``int``, and the result type is + the type of the left operand. In ANSI C, the integral promotions are done + on the two operands, and the result type is the type of the left operand. + The effect of this difference is that, in ``pcc`` mode, a ``long`` shift + count will force the shift to be done as ``long``. +* | When preprocessing output is generated, the line-identifying directives + will have the ``pcc`` form instead of the ANSI form. +* | String literals will not be shared. Identical string literals will cause + multiple copies of the string to be allocated. +* | ``sizeof`` may be applied to bit fields; the size is that of the underlying + type (e.g., ``unsigned int``). +* | lvalues cast to a type of the same size remain lvalues, except when they + involve a floating-point conversion. +* | When a function parameter list begins with a ``typedef`` identifier, the + parameter list is considered prototyped only if the ``typedef`` identifier + is followed by something other than a comma or right parenthesis: + + .. code:: c++ + + typedef int t; + int f(t) {} /* Old-style list */ + int g(t x) {} /* Prototyped list, parameter x of type t */ + + | That is, function parameters are allowed to have the same names as + ``typedef``\ s. In the normal ANSI mode, of course, any parameter list + that begins with a ``typedef`` identifier is considered prototyped, so the + first example above would give an error. +* | The names of functions and of external variables are always entered at the + file scope. +* | A function declared ``static``, used, and never defined is treated as if + its storage class were ``extern``. +* | A file-scope array that has an unspecified storage class and remains + incomplete at the end of the compilation will be treated as if its storage + class is ``extern`` (in ANSI mode, the number of elements is changed to 1, + and the storage class remains unspecified). +* | The empty declaration + + | ``struct`` *x*; + + | will not hide an outer-scope declaration of the same tag. +* | In a declaration of a member of a ``struct`` or ``union``, no diagnostic is + issued for omitting the declarator list; nevertheless, such a declaration + has no effect on the layout. For example, + + .. code:: c++ + + struct s {char a; int; char b[2];} v; /* sizeof(v) is 3 */ + +* | ``enum``\ s are always given type ``int``. In ANSI mode, and depending on + the configuration flag ``enum_types_can_be_smaller_than_int``, smaller + integral types will be used if possible. +* | No warning is generated for a storage specifier appearing in other than the + first position in a list of specifiers (as in ``int static``). +* | ``short``, ``long``, and ``unsigned`` are treated as "adjectives" in type + specifiers, and they may be used to modify a ``typedef`` type. +* | A "plain" ``char`` is considered to be the same as either ``signed char`` + or ``unsigned char``, depending on the installation default and + command-line options. In ANSI C, "plain" ``char`` is a third type distinct + from both ``signed char`` and ``unsigned char``. +* | Free-standing tag declarations are allowed in the parameter declaration + list for a function with old-style parameters. +* | ``float`` function parameters are promoted to ``double`` function + parameters. +* | ``float`` functions are promoted to ``double`` functions. +* | Declaration specifiers are allowed to be completely omitted in declarations + (ANSI C allows this only for function declarations). Thus + + .. code:: c++ + + i; + + | declares ``i`` as an ``int`` variable. A warning is issued. +* | The ``=`` preceding an initializer may be omitted. A warning is issued. + See K&R first edition, Appendix A, section 17 (anachronisms). This is + accepted only if ``C_ANACHRONISMS_ALLOWED`` is TRUE. +* | All ``float`` operations are done as ``double``. +* | ``__STDC__`` is left undefined. +* | Extra spaces to prevent pasting of adjacent confusable tokens are not + generated in textual preprocessing output. +* | The first directory searched for include files is the directory containing + the file containing the ``#include`` instead of the directory containing + the primary source file. +* | Trigraphs are not recognized. +* | Comments are deleted entirely (instead of being replaced by one space) in + preprocessing output. +* | ``0x`` is accepted as a hexadecimal ``0``, with a warning. +* | ``1E+`` is accepted as a floating-point constant with an exponent of ``0``, + with a warning. +* | The compound assignment operators may be written as two tokens (e.g., + ``+=`` may be written ``+ =``). +* | The compound assignment operators may be written in their old-fashioned + reversed forms (e.g., ``-=`` may be written ``=-``). A warning is issued. + This is described in K&R first edition, Appendix A, section 17 + (anachronisms). This is accepted only if ``C_ANACHRONISMS_ALLOWED`` is + TRUE. +* | The digits ``8`` and ``9`` are allowed in octal constants. +* | A warning rather than an error is issued for integer constants that are + larger than can be accommodated in an ``unsigned long``. The value is + truncated to an acceptable number of low-order bits. +* | The types of large integer constants are determined according to the K&R + rules (they won't be ``unsigned`` in some cases where ANSI C would define + them that way). Integer constants with apparent values larger than + ``LONG_MAX`` are typed as ``long`` and are also marked as "non-arithmetic", + which suppresses some warnings when using them. +* | The escape ``\a`` (alert) is not recognized in character and string + constants. +* | Macro expansion is done differently. Arguments to macros are not + macro-expanded before being inserted into the expansion of the macro. Any + macro invocations in the argument text are expanded when the macro + expansion is rescanned. With this method, macro recursion is possible and + is checked for. +* | Token pasting inside macro expansions is done differently. End-of-token + markers are not maintained, so tokens that abut after macro substitution + may be parsed as a single token. +* | Macro parameter names inside character and string constants are recognized + and substituted for. +* | Macro invocations having too many arguments are flagged with a warning + rather than an error. The extra arguments are ignored. +* | Macro invocations having too few arguments are flagged with a warning + rather than an error. A null string is used as the value of the missing + parameters. +* | Extra ``#else``\ s (after the first has appeared in an ``#if`` block) are + ignored, with a warning. +* | Expressions in a ``switch`` statement are cast to ``int``; this differs + from the ANSI C definition in that a ``long`` expression is (possibly) + truncated. +* | The promotion rules for integers are different: ``unsigned char`` and + ``unsigned short`` are promoted to ``unsigned int``. +* | An identifier in a function is allowed to have the same name as a parameter + of the function. A warning is issued. + +Extensions Accepted in SVR4 Compatibility Mode +---------------------------------------------- + +The following extensions are accepted in SVR4 C compatibility mode: + +* | Macro invocations having too many arguments are flagged with a warning + rather than an error. The extra arguments are ignored. +* | Macro invocations having too few arguments are flagged with a warning + rather than an error. A null string is used as the value of the missing + parameters. +* | The sequence ``/**/`` in a macro definition is treated as equivalent to the + token-pasting operator ``##``. +* | lvalues cast to a type of the same size remain lvalues, except when they + involve a floating-point conversion. +* | Assignment is allowed between pointers and integers, and between + incompatible pointer types, without an explicit cast. A warning is issued. +* | A field selection of the form *p*\ ``->``\ *field* is allowed even if + *p* does not point to a ``struct`` or ``union`` that contains *field*. + *p* must be a pointer. Likewise, *x*\ ``.``\ *field* is allowed even + if *x* is not a ``struct`` or ``union`` that contains *field*. *x* + must be an lvalue. For both cases, all definitions of *field* as a + field must have the same offset within their ``struct`` or ``union``. +* | In an integral constant expression, an integer constant may be cast to a + pointer type and then back to an integral type. +* | Incompatible external object declarations are allowed if the object types + share the same underlying representation. +* | Certain incompatible function declarations are allowed. A warning is + issued. + + .. code:: c++ + + typedef unsigned int size_t; + extern size_t strlen(const char *); + extern int strlen(); /* Warning */ + +Namespace Support +================= + +Namespaces are enabled by default (see ``DEFAULT_NAMESPACES_ENABLED``) except +in the cfront modes. The command-line options ``--namespaces`` and +``--no_namespaces`` can be used to enable or disable the features. + +When doing name lookup in a template instantiation, some names must be found in +the context of the template definition while others may also be found in the +context of the template instantiation. The front end implements two different +instantiation lookup algorithms: the one mandated by the standard (referred to +as "dependent name lookup"), and the one that existed before dependent name +lookup was implemented. + +Dependent name lookup is done in strict mode (unless explicitly disabled by +another command-line option) or when dependent name processing is enabled by +either a configuration flag or command-line option. + +Dependent Name Processing +------------------------- + +When doing dependent name lookup, the front end implements the instantiation +name lookup rules specified in the standard. This processing requires that +nonclass prototype instantiations be done. This in turn requires that the code +be written using the ``typename`` and ``template`` keywords as required by the +standard. + +Lookup Using the Referencing Context +------------------------------------ + +When not using dependent name lookup, the front end uses a name lookup +algorithm that approximates the two-phase lookup rule of the standard, but does +so in such a way that is more compatible with existing code and existing +compilers. + +When a name is looked up as part of a template instantiation but is not found +in the local context of the instantiation, it is looked up in a synthesized +instantiation context that includes both names from the context of the template +definition and names from the context of the instantiation. Here's an example: + +.. code:: c++ + + namespace N { + int g(int); + int x = 0; + template struct A { + T f(T t) { return g(t); } + T f() { return x; } + }; + } + namespace M { + int x = 99; + double g(double); + N::A ai; + int i = ai.f(0); // N::A::f(int) calls N::g(int) + int i2 = ai.f(); // N::A::f() returns 0 (= N::x) + N::A ad; + double d = ad.f(0); // N::A::f(double) calls M::g(double) + double d2 = ad.f(); // N::A::f() also returns 0 (= N::x) + } + +The lookup of names in template instantiations does not conform to the rules in +the standard in the following respects: + +* | Although only names from the template definition context are considered for + names that are not functions, the lookup is not limited to those names + visible at the point at which the template was defined. +* | Functions from the context in which the template was referenced are + considered for all function calls in the template. Functions from the + referencing context should only be visible for "dependent" function calls. + +For details of the algorithm implemented, see the :ref:`symbol-table` +chapter (in particular the :ref:`instantiation-context-lookup` section). + +Argument Dependent Lookup +-------------------------- + +When argument-dependent lookup is enabled, functions made visible using +argument-dependent lookup overload with those made visible by normal lookup. +The standard requires that this overloading occur even when the name found by +normal lookup is a block ``extern`` declaration. The front end does this +overloading, but in default mode, argument-dependent lookup is suppressed when +the normal lookup finds a block ``extern``. + +This means a program can have different behavior, depending on whether it is +compiled with or without argument-dependent lookup, even if the program makes +no use of namespaces. For example: + +.. code:: c++ + + struct A { }; + A operator+(A, double); + void f() { + A a1; + A operator+(A, int); + a1 + 1.0; // calls operator+(A, double) with arg-dependent + // lookup enabled but otherwise calls + // operator+(A, int); + } + +Runtime Support +--------------- + +The headers and runtime provided with the EDG front end support two different +versions (i.e., with and without namespaces) under control of +``__EDG_RUNTIME_USES_NAMESPACES``, a preprocessing option defined by the front +end. + +.. _template-instantiation: + +Template Instantiation +====================== + +The C++ language includes the concept of *templates*. A template is a +description of a class or function that is a model for a family of related +classes or functions. [#f3]_ For example, one can write a template for a +``Stack`` class, and then use a stack of integers, a stack of floats, and a +stack of some user-defined type. In the source, these might be written +``Stack``, ``Stack``, and ``Stack``. From a single source +description of the template for a stack, the compiler can create +*instantiations* of the template for each of the types required. + +The instantiation of a class template is always done as soon as it is needed in +a compilation. However, the instantiations of template functions, template +variables, member functions of template classes, and static data members of +template classes (hereafter referred to as template entities) are not +necessarily done immediately, for several reasons: + +* | One would like to end up with only one copy of each instantiated entity + across all the object files that make up a program. (This of course + applies to entities with external linkage.) +* | The language allows one to write a *specialization* of a template entity, + i.e., a specific version to be used in place of a version generated from + the template for a specific data type. (One could, for example, write a + version of ``Stack``, or of just ``Stack::push``, that replaces + the template-generated version; often, such a specialization provides a + more efficient representation for a particular data type.) Since the + compiler cannot know, when compiling a reference to a template entity, if a + specialization for that entity will be provided in another compilation, it + cannot do the instantiation automatically in any source file that + references it. (The modern C++ language requires that a specialization be + declared in every compilation in which it is used, but for compatibility + with existing code and older compilers the EDG front end does not require + that in some modes. See the command-line option + ``--no_distinct_template_signatures``.) +* | C++ templates can be *exported* (i.e., declared with the keyword + ``export``). Such templates can be used in a translation unit that does + not contain the definition of the template to instantiate. The + instantiation of such a template must be delayed until the template + definition has been found. +* | The language also dictates that template functions that are not referenced + should not be compiled, that, in fact, such functions might contain + semantic errors that would prevent them from being compiled. Therefore, a + reference to a template class should not automatically instantiate all the + member functions of that class. + +(It should be noted that certain template entities are always instantiated when +used, e.g., inline functions.) + +From these requirements, one can see that if the compiler is responsible for +doing all the instantiations automatically, it can only do so on a program-wide +basis. That is, the compiler cannot make decisions about instantiation of +template entities until it has seen all the source files that make up a +complete program. + +The EDG C++ front end provides an instantiation mechanism that does automatic +instantiation at link time. For cases where the programmer wants more explicit +control over instantiation, the front end also provides instantiation modes and +instantiation pragmas, which can be used to exert fine-grained control over the +instantiation process. + +Automatic Instantiation +----------------------- + +The goal of an automatic instantiation mode is to provide painless +instantiation. The programmer should be able to compile source files to object +code, then link them and run the resulting program, and never have to worry +about how the necessary instantiations get done. + +In practice, this is hard for a compiler to do, and different compilers use +different automatic instantiation schemes with different strengths and +weaknesses: + +* | AT&T/USL/Novell/SCO's *cfront* product saves information about each file it + compiles in a special directory called ``ptrepository``. It instantiates + nothing during normal compilations. At link time, it looks for entities + that are referenced but not defined, and whose mangled names indicate that + they are template entities. For each such entity, it consults the + ``ptrepository`` information to find the file containing the source for the + entity, and it does a compilation of the source to generate an object file + containing object code for that entity. This object code for instantiated + objects is then combined with the "normal" object code in the link step. + | + | The programmer using *cfront* must follow a particular coding + convention: all templates must be declared in "``.h``" files, and for + each such file there must be a corresponding "``.C``" file containing + the associated definitions. The compiler is never told about the + "``.C``" files explicitly; one does not, for example, compile them in + the normal way. The link step looks for them when and if it needs + them, and does so by taking the "``.h``" file name and replacing its + suffix. [#f4]_ + | + | This scheme has the disadvantage that it does a separate compilation for + each instantiated function (or, at best, one compilation for all the member + functions of one class). Even though the function itself is often quite + small, it must be compiled along with the declarations for the types on + which the instantiation is based, and those declarations can easily run + into many thousands of lines. For large systems, these compilations can + take a very long time. The link step tries to be smart about recompiling + instantiations only when necessary, but because it keeps no fine-grained + dependency information, it is often forced to "recompile the world" for a + minor change in a "``.h``" file. In addition, *cfront* has no way of + ensuring that preprocessing symbols are set correctly when it does these + instantiation compilations, if preprocessing symbols are set other than on + the command line. +* | Borland's C++ compiler instantiates everything referenced in a compilation, + then uses a special linker to remove duplicate definitions of instantiated + functions. + | + | The programmer using Borland's compiler must make sure that every + compilation sees all the source code it needs to instantiate all the + template entities referenced in that compilation. That is, one cannot + refer to a template entity in a source file if a definition for that entity + is not included by that source file. In practice, this means that either + all the definition code is put directly in the "``.h``" files, or that each + "``.h``" file includes an associated "``.C``" (actually, "``.CPP``") file. + | + | This scheme is straightforward, and works well for small programs. For + large systems, however, it tends to produce very large object files, + because each object file must contain object code (and symbolic debugging + information) for each template entity it references. + +EDG's approach is a little different. It requires that, for each instantiation +of a non-exported template, there is some (normal, top-level, +explicitly-compiled) source file that contains the definition of the template +entity, a reference that causes the instantiation, and the declarations of any +types required for the instantiation. [#f5]_ This requirement can be met in +various ways: + +* | The Borland convention: each "``.h``" file that declares a template entity + also contains either the definition of the entity or includes another file + containing the definition. +* | Implicit inclusion: when the compiler sees a template declaration in a + "``.h``" file and discovers a need to instantiate that entity, it is + given permission to go off looking for an associated definition file + having the same base name and a different suffix, and it implicitly + includes that file at the end of the compilation. This method allows + most programs written using the *cfront* convention to be compiled with + EDG's approach. See :ref:`implicit-inclusion`. +* | The ad hoc approach: the programmer makes sure that the files that define + template entities also have the definitions of all the available types, and + adds code or pragmas in those files to request instantiation of the + entities there. + +Exported templates are also supported by the EDG automatic instantiation +method, but they require additional mechanisms explained further on. + +The EDG automatic instantiation method works as follows for non-exported +templates: [#f6]_ + +#. | The first time the source files of a program are compiled, no template + entities are instantiated. However, template information files (with, by + default, a "``.ti``" suffix) are generated and contain information about + things that *could* have been instantiated in each compilation [#f7]_. +#. | When the object files are linked together, a program called the + *prelinker* is run. It examines the object files, looking for + references and definitions of template entities, and for the added + information about entities that could be instantiated. +#. | If the prelinker finds a reference to a template entity for which there + is no definition anywhere in the set of object files, it looks for a file + that indicates that it could instantiate that template entity. When it + finds such a file, it assigns the instantiation to it. The set of + instantiations assigned to a given file is recorded in an associated + instantiation request file (with, by default, a "``.ii``" suffix). +#. | The prelinker then executes the compiler again to recompile each file for + which the instantiation request file was changed. The original + compilation command-line options (saved in the template information file) + are used for the recompilation. +#. | When the compiler compiles a file, it reads the instantiation request + file for that file and obeys the requests therein. It produces a new + object file containing the requested template entities (and all the other + things that were already in the object file). The compiler also receives + a definition list file, which lists all the instantiations for which + definitions already exist in the set of object files. If during the + compilation the compiler has the opportunity to instantiate a referenced + entity that is not on that list, it goes ahead and does the instantiation. + It passes back to the prelinker (in the definition list file) a list of + the instantiations that it has "adopted" in this way, so the prelinker can + assign them to the file. This adoption process allows rapid instantiation + and assignment of instantiations referenced from new instantiations, and + reduces the need to recompile a given file more than once during the + prelinking process. +#. | The prelinker repeats steps 3-5 until there are no more instantiations to + be adjusted. +#. | The object files are linked together. + +Once the program has been linked correctly, the instantiation request files +contain a complete set of instantiation assignments. From then on, whenever +source files are recompiled, the compiler will consult the instantiation +request files and do the indicated instantiations as it does the normal +compilations. That means that, except in cases where the set of required +instantiations changes, the prelink step from then on will find that all the +necessary instantiations are present in the object files and no instantiation +assignment adjustments need be done. That's true even if the entire program is +recompiled. + +If the programmer provides a specialization of a template entity somewhere in +the program, the specialization will be seen as a definition by the prelinker. +Since that definition satisfies whatever references there might be to that +entity, the prelinker will see no need to request an instantiation of the +entity. If the programmer adds a specialization to a program that has +previously been compiled, the prelinker will notice that too and remove the +assignment of the instantiation from the proper instantiation request file. + +The instantiation request files should not, in general, require any manual +intervention. One exception: if a definition is changed in such a way that +some instantiation no longer compiles (it gets errors), and at the same time a +specialization is added in another file, and the first file is being recompiled +before the specialization file and is getting errors, the instantiation request +file for the file getting the errors must be deleted manually to allow the +prelinker to regenerate it. + +If the prelinker changes an instantiation assignment, it will issue a message +like + +.. code:: text + + C++ prelinker: A::f() assigned to file test.o + C++ prelinker: executing: /edg/bin/eccp -c test.c + +The automatic instantiation scheme can coexist with partial explicit control of +instantiation by the programmer through the use of pragmas or command-line +specification of the instantiation mode. See the following sections. + +Instantiations are normally generated as part of the object file of the +translation unit in which the instantiations are performed. But when "one +instantiation per object" mode is specified, each instantiation is placed in +its own object file. One-instantiation-per-object mode is useful when +generating libraries that need to include copies of the instances referenced +from the library. If each instance is not placed in its own object file, it +may be impossible to link the library with another library containing some of +the same instances. Without this feature it is necessary to create each +individual instantiation object file using the manual instantiation mechanism. + +The automatic instantiation mode can be configured out altogether by setting +the configuration flag ``AUTOMATIC_TEMPLATE_INSTANTIATION`` to FALSE. It can +be turned on or off using the ``--auto_instantiation`` and +``--no_auto_instantiation`` command-line options. If automatic instantiation +is turned off, the template information file is not generated. + +Instantiation Modes +------------------- + +Normally, when a file is compiled, no template entities are instantiated +(except those assigned to the file by automatic instantiation). The overall +instantiation mode can, however, be changed by a command line option: + +.. list-table:: + + * - | ``-tnone`` + - | Do not automatically create instantiations of any template entities. + This is the default. It is also the usually appropriate mode when + automatic instantiation is done. + * - | ``-tused`` + - | Instantiate those template entities that were used in the compilation. + This will include all static data members for which there are template + definitions. + * - | ``-tall`` + - | Instantiate all template entities declared or referenced in the + compilation unit. For each fully instantiated template class, all of + its member functions and static data members will be instantiated + whether or not they were used. Nonmember template functions will be + instantiated even if the only reference was a declaration. + * - | ``-tlocal`` + - | Similar to ``-tused`` except that the functions are given internal + linkage. This is intended to provide a very simple mechanism for + those getting started with templates. The compiler will instantiate + the functions that are used in each compilation unit as local + functions, and the program will link and run correctly (barring + problems due to multiple copies of local static variables.) However, + one may end up with many copies of the instantiated functions, so this + is not suitable for production use. ``-tlocal`` can not be used in + conjunction with automatic template instantiation. If automatic + instantiation is enabled by default, it will be disabled by the + ``-tlocal`` option. If automatic instantiation is not enabled by + default, use of ``-tlocal`` and ``-T`` is an error. + +In the case where the ``eccp`` script is given a single file to compile and +link, e.g., + +.. code:: text + + eccp t.c + +the compiler knows that all instantiations will have to be done in the single +source file. Therefore, it uses the ``-tused`` mode and suppresses automatic +instantiation. + +Instantiation ``#pragma`` Directives +------------------------------------ + +Instantiation pragmas can be used to control the instantiation of specific +template entities or sets of template entities. There are three instantiation +pragmas: + +* | The ``instantiate`` pragma causes a specified entity to be instantiated. +* | The ``do_not_instantiate`` pragma suppresses the instantiation of a + specified entity. It is typically used to suppress the instantiation of an + entity for which a specific definition will be supplied. +* | The ``can_instantiate`` pragma indicates that a specified entity can be + instantiated in the current compilation, but need not be; it is used in + conjunction with automatic instantiation, to indicate potential sites for + instantiation if the template entity turns out to be required. [#f8]_ + +The argument to the instantiation pragma may be: + +.. list-table:: + + * - | a template class name + - | ``A`` + * - | a template class declaration + - | ``class A`` + * - | a member function name + - | ``A::f`` + * - | a static data member name + - | ``A::i`` + * - | a static data member decl. + - | ``int A::i`` + * - | a member function declaration + - | ``void A::f(int, char)`` + * - | a template function declaration + - | ``char* f(int, float)`` + * - | a template variable name + - | ``x`` + +A pragma in which the argument is a template class name (e.g., ``A`` or +``class A``) is equivalent to repeating the pragma for each member +function and static data member declared in the class. When instantiating an +entire class a given member function or static data member may be excluded +using the ``do_not_instantiate`` pragma. For example, + +.. code:: c++ + + #pragma instantiate A + #pragma do_not_instantiate A::f + +The template definition of a template entity must be present in the compilation +for an instantiation to occur. If an instantiation is explicitly requested by +use of the ``instantiate`` pragma and no template definition is available or a +specific definition is provided, an error is issued. + +.. code:: c++ + + template void f1(T); // No body provided + template void g1(T); // No body provided + void f1(int) {} // Specific definition + void main(){ + int i; + double d; + f1(i); + f1(d); + g1(i); + g1(d); + } + #pragma instantiate void f1(int) // error - specific definition + #pragma instantiate void g1(int) // error - no body provided + +``f1(double)`` and ``g1(double)`` will not be instantiated (because no bodies +were supplied) but no errors will be produced during the compilation (if no +bodies are supplied at link time, a linker error will be produced). + +A member function name (e.g., ``A::f``) can only be used as a pragma +argument if it refers to a single user defined member function (i.e., not an +overloaded function). Compiler-generated functions are not considered, so a +name may refer to a user defined constructor even if a compiler-generated copy +constructor of the same name exists. Overloaded member functions can be +instantiated by providing the complete member function declaration, as in + +.. code:: c++ + + #pragma instantiate char* A::f(int, char*) + +The argument to an instantiation pragma may not be a compiler-generated +function, an inline function, or a pure virtual function. + +Implicit Inclusion +------------------ + +When implicit inclusion is enabled, the front end is given permission to assume +that if it needs a definition to instantiate a template entity declared in a +"``.h``" file it can implicitly include the corresponding "``.C``" file to get +the source code for the definition. For example, if a template entity +``ABC::f`` is declared in file ``xyz.h``, and an instantiation of ``ABC::f`` is +required in a compilation but no definition of ``ABC::f`` appears in the source +code processed by the compilation, the compiler will look to see if a file +``xyz.C`` exists, and if so it will process it as if it were included at the +end of the main source file. + +To find the template definition file for a given template entity the front end +needs to know the path name specified in the original include of the file in +which the template was declared and whether the file was included using the +system include syntax (e.g., ``#include ``). This information is not +available for preprocessed source containing ``#line`` directives. +Consequently, the front end will not attempt implicit inclusion for source code +containing ``#line`` directives. + +The file to be implicitly included is found by replacing the file suffix with +each of the suffixes specified in the instantiation file suffix list. The +normal include search path mechanism is then used to look for the file to be +implicitly included. + +``DEFAULT_INSTANTIATION_FILE_SUFFIX_LIST`` defines the set of definition-file +suffixes tried. By default, the list is "``.c``", "``.C``", "``.cpp``", +"``.CPP``", "``.cxx``", "``.CXX``", and "``.cc``". + +Implicit inclusion works well alongside automatic instantiation, but the two +are independent. They can be enabled or disabled independently, and implicit +inclusion is still useful when automatic instantiation is not done. + +The implicit inclusion mode can be configured out altogether by setting the +configuration flag ``INSTANTIATION_BY_IMPLICIT_INCLUSION`` to FALSE. It can be +turned on or off using the ``--implicit_include`` and ``--no_implicit_include`` +command-line option\ ``s``. + +Implicit inclusions are only performed during the normal compilation of a file, +(i.e., not when doing only preprocessing). A common means of investigating +certain kinds of problems is to produce a preprocessed source file that can be +inspected. When using implicit inclusion it is sometimes desirable for the +preprocessed source file to include any implicitly included files. This may be +done using the ``--no_preproc_only`` command line option. This causes the +preprocessed output to be generated as part of a normal compilation. When +implicit inclusion is being used, the implicitly included files will appear as +part of the preprocessed output in the precise location at which they were +included in the compilation. + +Exported Templates +------------------ + +Exported templates are templates declared with the keyword ``export``. +Exporting a class template is equivalent to exporting each of its static data +members and each of its non-inline member functions. An exported template is +special because its definition does not need to be present in a translation +unit that uses that template. In other words, the definition of an exported +(non-class) template does not need to be explicitly or implicitly included in a +translation unit that instantiates that template. For example, the following +is a valid C++ program consisting of two separate translation units: + +.. code:: c++ + + // File 1: + #include + static void trace() { printf("File 1\n"); } + + export template T const& min(T const&, T const&); + int main() { + trace(); + return min(2, 3); + } + +.. code:: c++ + + // File 2: + #include + static void trace() { printf("File 2\n"); } + + export template T const& min(T const &a, T const &b) { + trace(); + return a T const& min(T const &a, T const &b) { + return a`` header file to get the proper definitions of + ``CHAR_MAX`` and ``CHAR_MIN``. + * - | ``__FUNCTION__`` + - | Defined in all modes to the name of the current function. An error is + issued if it is used outside of a function. An EDG, GNU, and + Microsoft extension. (Depending on the current mode, this identifier + behaves as a variable or as a string literal; never as a preprocessor + macro.) + * - | ``__func__`` + - | Same as ``__FUNCTION__`` in C99, C++11, and GNU modes. (This + identifier behaves as a variable; not as a preprocessor macro.) + * - | ``__PRETTY_FUNCTION__`` + - | Defined in all modes to the name of the current function. This + includes the return type and parameter types of the function. An + error is issued if it is used outside of a function. An EDG and GNU + extension. (Depending on the current mode, this identifier behaves as + a variable or as a string literal; never as a preprocessor macro.) + * - | ``__FUNCSIG__`` + - | Same as ``__PRETTY_FUNCTION__`` in Microsoft mode. (This identifier + behaves as a string literal; not as a preprocessor macro.) + * - | ``__FUNCDNAME__`` + - | Defined to the "decorated" name of the current function (i.e., its + mangled name) in Microsoft mode. (This identifier behaves as a string + literal; not as a preprocessor macro.) + * - | ``__BASE_FILE__`` + - | Defined in all modes. Similar to ``__FILE__`` but indicates the + primary source file rather than the current one (i.e., when the + current file is an included file). + * - | ``_WCHAR_T`` + - | Defined in C++ mode when ``wchar_t`` is a keyword. The name of this + macro and whether it is predefined are specified by configuration + options. ``_WCHAR_T`` is the default. + * - | ``_WCHAR_T_DEFINED`` + - | Defined in Microsoft C++ mode when ``wchar_t`` is a keyword. + * - | ``_NATIVE_WCHAR_T_DEFINED`` + | + - | Defined in Microsoft C++ mode when ``wchar_t`` is a keyword (Microsoft + version 1300 and above). + * - | ``_BOOL`` + - | Defined in C++ mode when ``bool`` is a keyword. The name of this + macro and whether it is predefined are specified by configuration + options. ``_BOOL`` is the default. + * - | ``__BOOL_DEFINED`` + - | Defined in Microsoft C++ mode when ``bool`` is a keyword. + * - | ``__ARRAY_OPERATORS`` + - | Defined in C++ mode when array new and delete are enabled. The name + of this macro and whether it is predefined are specified by + configuration options. ``__ARRAY_OPERATORS`` is the default. + * - | ``__EXCEPTIONS`` + - | Defined in C++ mode when exception handling is enabled. The name of + this macro and whether it is predefined are specified by configuration + options. ``__EXCEPTIONS`` is the default. + * - | ``__RTTI`` + - | Defined in C++ mode when RTTI is enabled. The name of this macro and + whether it is predefined are specified by configuration options. + ``__RTTI`` is the default. + * - | ``__PLACEMENT_DELETE`` + - | Defined in C++ mode when placement delete is enabled. The name of + this macro and whether it is predefined are specified by configuration + options. ``__PLACEMENT_DELETE`` is the default. Placement delete is + enabled when ``ABI_CHANGES_FOR_PLACEMENT_DELETE`` is TRUE and + exception handling is enabled. + * - | ``__NO_LONG_LONG`` + - | Defined in all modes when the ``long long`` type is not supported. + The name of this macro and whether it is predefined are specified by + configuration options. ``__NO_LONG_LONG`` is the default. + * - | ``__EDG_RUNTIME_USES_NAMESPACES`` + | + - | Defined in C++ mode when the configuration flag + ``RUNTIME_USES_NAMESPACES`` is TRUE. The name of this macro and + whether it is predefined are specified by configuration options. + ``__EDG_RUNTIME_USES_NAMESPACES`` is the default. + * - | ``__EDG_IMPLICIT_USING_STD`` + | + - | Defined in C++ mode when the configuration flag + ``RUNTIME_USES_NAMESPACES`` is TRUE and when ``implicit_using_std`` + has been set to TRUE, either by a command line option or by the + configuration flag ``DEFAULT_IMPLICIT_USING_STD``, indicating that the + standard header files should implicitly do a using-directive on the + ``std`` namespace. The name of this macro and whether it is + predefined are specified by configuration options. + ``__EDG_IMPLICIT_USING_STD`` is the default. + * - | ``__EDG_TYPE_TRAITS_ENABLED`` + | + - | Defined in non-Microsoft modes when type traits pseudo-functions (to + ease the implementation of ISO/IEC TR 19768; e.g., "``__is_union``") + are enabled. The name of this predefined macro is specified by a + configuration option. ``__EDG_TYPE_TRAITS_ENABLED`` is the default. + * - | ``__EDG__`` + - | Always defined. + * - | ``__EDG_VERSION__`` + - | Defined to an integral value that represents the version number of the + front end. For example. version 2.30 is represented as 230. + * - | ``__EDG_IA64_ABI`` + - | Defined as 1 when using a front end configured to use the IA-64 ABI. + * - | ``__embedded_cplusplus`` + - | Defined as 1 in Embedded C++ mode. + * - | ``_CHAR_UNSIGNED`` + - | Defined in Microsoft mode when ``char`` is unsigned. + * - | ``_MSC_VER`` + - | Defined in Microsoft mode to the version number of the Microsoft + compiler that is to be emulated. For example, 1100 is the value that + corresponds to Visual C++ version 5.0. + * - | ``_MSC_BUILD`` + - | Defined in Microsoft mode to the value of ``microsoft_build_number``. + * - | ``_M_CEE`` + - | Defined in Microsoft mode when C++/CLI mode is in effect (e.g., when + ``--cppcli`` is specified). + * - | ``_MSC_EXTENSIONS`` + - | Defined in Microsoft mode. + * - | ``_WIN32`` + - | Defined (unconditionally) in Microsoft mode. + * - | ``_WIN64`` + - | Defined in Microsoft mode when ``targ_supports_x86_64`` is TRUE. + * - | ``_INTEGRAL_MAX_BITS`` + - | Defined in Microsoft mode to the number of bits in the largest + integral type that is supported. The value depends on the way in + which the front end was configured. + * - | ``_CPPRTTI`` + - | Defined in Microsoft mode C++ when RTTI is enabled. + * - | ``__GNUC__`` + - | Defined in GNU mode to the value specified by the ``GCC_VERSION`` + configuration macro. + * - | ``__GNUC_MINOR__`` + - | Defined in GNU mode to the value specified by the + ``GCC_MINOR_VERSION`` configuration macro. + * - | ``__VERSION__`` + - | Defined in GNU mode to the value specified by the + ``GCC_VERSION_STRING`` configuration macro. + * - | ``__PRAGMA_REDEFINE_EXTNAME`` + | + - | Defined if all modes when the configuration flag + ``REDEFINE_EXTNAME_PRAGMA_ENABLED`` is TRUE. + * - | ``__upc__`` + - | Defined when UPC extensions are enabled. + * - | ``__COUNTER__`` + - | Defined in Microsoft mode. Returns an integer value, starting with + zero and incremented each time the macro is used. + * - | ``__TIMESTAMP__`` + - | Defined in Microsoft mode. Returns a string literal containing the + modification date and time of the source file in which it is + specified. + * - | ``__EDG_IA64_ABI`` + - | Defined in C++ mode when using the IA-64 ABI. The name of this + predefined macro is specified by a configuration option. + ``__EDG_IA64_ABI`` is the default. + * - | ``__EDG_IA64_ABI_USE_INT_STATIC_INIT_GUARD`` + - | Defined in C++ mode when using the IA-64 ABI when guard variables are + ``int``-sized (i.e., in the ARM EABI). The name of this predefined + macro is specified by a configuration option. + ``__EDG_IA64_ABI_USE_INT_STATIC_INIT_GUARD`` is the default. + * - | ``__EDG_IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS`` + - | Defined in C++ mode when using the IA-64 ABI when constructors and + destructors return the ``this`` pointer (i.e., in the ARM EABI). The + name of this predefined macro is specified by a configuration option. + ``__EDG_IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS`` is the default. + * - | ``__EDG_SIZE_TYPE__`` + - | Defined to be the type of ``size_t``. + | ``__EDG_PTRDIFF_TYPE__`` + | Defined to be the type of ``ptrdiff_t``. + * - | ``__CHAR16_T_AND_CHAR32_T`` + | + - | Defined in C++ mode when ``char16_t`` and ``char32_t`` are keywords. + The name of this macro and whether it is predefined are specified by + configuration options. ``__CHAR16_T_AND_CHAR32_T`` is the default. + * - | ``__CHAR16_TYPE__`` + - | Defined in GNU mode as the underlying type for ``char16_t`` (GNU + version 40400 and above). + * - | ``__CHAR32_TYPE__`` + - | Defined in GNU mode as the underlying type for ``char32_t`` (GNU + version 40400 and above). + * - | ``__VARIADIC_TEMPLATES`` + | + - | Defined in C++ mode when variadic templates are supported. The name + of this macro and whether it is predefined are specified by + configuration options. ``__VARIADIC_TEMPLATES`` is the default. + * - | ``__STDCPP_THREADS__`` + - | Defined in C++ mode when the implementation supports multiple threads + (i.e., when ``IMPLEMENTATION_SUPPORTS_MULTIPLE_THREADS`` is TRUE + and the global variable ``std_thread_local_storage_specifier_enabled`` + is TRUE). + +Pragmas +======= + +``#pragma`` directives are used within the source program to request certain +kinds of special processing. The ``#pragma`` directive is part of the standard +C and C++ languages, but the meaning of any pragma is implementation-defined. + +Instantiation Pragmas +--------------------- + +The following are described in detail in the template instantiation section of +this chapter: + +.. code:: c++ + + #pragma instantiate + #pragma do_not_instantiate + #pragma can_instantiate + +Precompiled Header Pragmas +-------------------------- + +The following are described in the section on precompiled header processing: + +.. code:: c++ + + #pragma hdrstop + #pragma no_pch + +Once Pragma +----------- + +The front end also recognizes ``#pragma once``, which, when placed at the +beginning of a header file, indicates that the file is written in such a way +that including it several times has the same effect as including it once. +Thus, if the front end sees ``#pragma once`` at the start of a header file, it +will skip over it if the file is ``#include``\ d again. + +A typical idiom is to place an ``#ifndef`` guard around the body of the file, +with a ``#define`` of the guard variable after the ``#ifndef``: + + | ``#pragma once // optional`` + | ``#ifndef FILE_H`` + | ``#define FILE_H`` + | ``...`` *body of the header file* ``...`` + | ``#endif`` + +The ``#pragma once`` is marked as optional in this example, because the front +end recognizes the ``#ifndef`` idiom and does the optimization even in its +absence. ``#pragma once`` is accepted for compatibility with other compilers +and to allow the programmer to use other guard-code idioms. + +Diagnostic Pragmas +------------------ + +The following pragmas may be used to control the error severity used when a +given diagnostic message is issued. + +.. code:: c++ + + #pragma diag_suppress + #pragma diag_remark + #pragma diag_warning + #pragma diag_error + #pragma diag_default + #pragma diag_once + +These are similar in function to the equivalent command-line options. Uses of +these pragmas have the following form: + + | ``#pragma diag_``\ *xxx* ``[=]`` *error_number_or_tag*\ ``,`` *error_number_or_tag* ... + +The diagnostic affected is specified using either an error number or an error +tag name. The "``=``" is optional. Any diagnostic may be overridden to be an +error, but only diagnostics with a severity of discretionary error or below may +have their severity reduced to a warning or below, or be suppressed. The +``diag_default`` pragma is used to return the severity of a diagnostic to the +one that was in effect before any pragmas were issued (i.e., the normal +severity of the message as modified by any command-line options). The +following example suppresses the "pointless friend declaration" warning on the +declaration of class ``A``: + +.. code:: c++ + + #pragma diag_suppress 522 + class A { friend class A; }; + #pragma diag_default 522 + class B { friend class B; }; + +The ``diag_once`` pragma causes the specified diagnostics to be issued only +once as a warning or remark. + +Pack Pragma +----------- + +When ``USER_CONTROL_OF_STRUCT_PACKING`` is TRUE, ``#pragma pack`` is +recognized. It is used to specify the maximum alignment allowed for nonstatic +data members of structs and classes, even if that alignment is less than the +alignment dictated by the member's type. + +The basic syntax is: + + | ``#pragma pack(``\ *n*\ ``)`` + | ``#pragma pack()`` + +where argument *n*, a power-of-2 value within the range defined by +``TARG_MINIMUM_PACK_ALIGNMENT`` and ``TARG_MAXIMUM_PACK_ALIGNMENT``, is the new +packing alignment that is to go into effect for subsequent declarations, until +another ``#pragma pack`` is seen. The second form cancels the effect of a +preceding ``#pragma pack(``\ *n*\ ``)`` and either restores the default packing +alignment specified by the ``--pack_alignment`` command-line option or, if the +option was not used, disables the packing of structs and classes. + +An enhanced syntax (intended to be compatible with the similar facility offered +by Microsoft C/C++ compilers) is also supported in which keywords ``push`` and +``pop`` can be used to manage a stack of packing alignment values -- for +instance: + +.. code:: c++ + + #pragma pack (push, xxx, 16) + /* Packing alignment set to 16. */ + #include "xxx.h" + #pragma pack (pop, xxx) + /* Packing alignment reset to what it was prior to the + above #pragma pack directive, even if the included header + left some unrelated pragma pack entries on the stack. */ + +which has the effect saving the current packing alignment value and +establishing a new one, processing the include file (which may leave the +packing alignment with an unknown setting), and restoring the original value. +Finally, the form + +.. code:: c++ + + #pragma pack(show) + +causes the front end to emit a warning describing the current setting of the +maximum member alignment (if any). + +In C++ a ``#pragma pack`` directive has "local" effect when it appears inside a +function template, an instantiation of a class template, or the body of a +member function or friend function that is defined within a class definition. +When such a context is entered, the current pack alignment state is saved, so +that it can be restored when the context is exited. For example, + +.. code:: c++ + + template class A { + : + #pragma pack(1) + : + }; + #pragma pack(4) + main() { + A a; // #pragma pack(1) is local to A + struct S { char c; int i; }; // sizeof(S) == 8, not 5 + } + +Moreover, within an instantiation of a class or function template, the default +pack alignment is that which is in effect at the point of the template's +definition, not at the point of its instantiation. Here is an example: + +.. code:: c++ + + #pragma pack(1) + template int f(T) { + struct S { char c; int i; }; // default pack alignment is 1 for each + return sizeof(S); // instance of f + } + #pragma pack(4) + main() { + int i = f(0); // i = 5, not 8 + } + +These rules apply to inline-defined member functions, too, because their bodies +are also scanned "out of order" relative to the textual order of the source +program (i.e., not till all the class members have been declared). + +.. code:: c++ + + #pragma pack(4) + struct A { + int f() { + #pragma pack(1) // #pragma pack(1) is local to A::f + struct S { char c; int i; }; // sizeof(S) is 5 + } + int g() { + struct S { char c; int i; }; // sizeof(S) is 8 + } + #pragma pack(1) + int h() { + struct S { char c; int i; }; // sizeof(S) is 5 + } + }; + +When ``IDENT_DIRECTIVE_AND_PRAGMA`` is TRUE, ``#pragma ident`` is recognized, +as is ``#ident``: + +.. code:: c++ + + #pragma ident "string" + #ident "string" + +Both are implemented by recording the string in a pragma entry and passing it +to the back end. + +When ``PRAGMA_WEAK_ALLOWED`` is TRUE, ``#pragma weak`` is recognized. Its form +is: + + | ``#pragma weak`` *name1* [ ``=`` *name2* ] + +where *name1* is the name to be given "weak binding" and is a synonym for +*name2* if the latter is specified. The entire argument string is recorded +in the pragma entry and passed to the back end. + +Microsoft Pragmas +----------------- + +The following pragmas are accepted in Microsoft mode: + +.. code:: c++ + + #pragma push_macro("identifier") + #pragma pop_macro("identifier") + #pragma include_alias("a_long_file_name.h", "short.h") + +In addition, when ``NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE`` is TRUE, +the ``setlocale`` pragma is accepted: + +.. code:: c++ + + #pragma setlocale("locale name") + +The ``pack`` pragma is also accepted by the Microsoft compiler, but its +acceptance by the front end is controlled by a separate configuration flag, not +by whether or not Microsoft mode is being used. + +IL Display Pragma +----------------- + +As a debugging aid, in configurations where ``NEED_IL_DISPLAY`` is TRUE, +the ``il_display`` pragma can be used to display the underlying IL for the IL +entity that the pragma is attached to. The ``il_display`` pragma is a +``pbk_next_construct`` pragma that attaches to the subsequent declaration or +statement and displays the IL associated with that entity. Note that the IL +displayed represents the IL at the current point in the compilation and may not +accurately reflect the eventual IL. This can be useful for displaying source +location information. For example: + +.. code:: c++ + + struct A { int x, y; }; + void f(int i) { + #pragma il_display + A a = { 1, 2 }; + #pragma il_display + i++; + } + +.. _precompiled-headers: + +Precompiled Headers +=================== + +It is often desirable to avoid recompiling a set of header files, +especially when they introduce many lines of code and the primary source +files that ``#include`` them are relatively small. The EDG front end +provides a mechanism for, in effect, taking a snapshot of the state of the +compilation at a particular point and writing it to a disk file before +completing the compilation; then, when recompiling the same source file or +compiling another file with the same set of header files, it can recognize +the "snapshot point," verify that the corresponding precompiled header +("PCH") file is reusable, and read it back in. Under the right +circumstances, this can produce a dramatic improvement in compilation time; +the trade-off is that PCH files can take a lot of disk space. Because of +potential memory conflicts between threads, precompiled header processing +is disabled in multi-threaded configurations. In particular, a PCH file +cannot be created if ``MULTIPLE_THREAD_COMPILATION`` is TRUE and, because +the configurations must match, a PCH file by a single-threaded +configuration cannot be used. + +Automatic Precompiled Header Processing +--------------------------------------- + +When ``--pch`` appears on the command line, automatic precompiled header +processing is enabled. This means the front end will automatically look for a +qualifying precompiled header file to read in and/or will create one for use on +a subsequent compilation. + +The PCH file will contain a snapshot of all the code preceding the "header +stop" point. The header stop point is typically the first token in the primary +source file that does not belong to a preprocessing directive, but it can also +be specified directly by ``#pragma hdrstop`` (see below) if that comes first. +For example: + +.. code:: c++ + + #include "xxx.h" + #include "yyy.h" + int i; + +The header stop point is ``int`` (the first non-preprocessor token) and the PCH +file will contain a snapshot reflecting the inclusion of ``xxx.h`` and +``yyy.h``. If the first non-preprocessor token or the ``#pragma hdrstop`` +appears within a ``#if`` block, the header stop point is the outermost +enclosing ``#if``. To illustrate, here's a more complicated example: + +.. code:: c++ + + #include "xxx.h" + #ifndef YYY_H + #define YYY_H 1 + #include "yyy.h" + #endif + #if TEST + int i; + #endif + +Here, the first token that does not belong to a preprocessing directive is +again ``int``, but the header stop point is the start of the ``#if`` block +containing it. The PCH file will reflect the inclusion of ``xxx.h`` and +conditionally the definition of ``YYY_H`` and inclusion of ``yyy.h``; it will +not contain the state produced by ``#if TEST``. + +A PCH file will be produced only if the header stop point and the code +preceding it (mainly, the header files themselves) meet certain requirements: + +* | The header stop point must appear at file scope -- it may not be within an + unclosed scope established by a header file. For example, a PCH file will + not be created in this case: + + .. code:: c++ + + // xxx.h + class A { + + // xxx.C + #include "xxx.h" + int i; }; + +* | The header stop point may not be inside a declaration started within a + header file, nor (in C++) may it be part of a declaration list of a linkage + specification. For example, in the following case the header stop point is + ``int``, but since it is not the start of a new declaration, no PCH file + will be created: + + .. code:: c++ + + // yyy.h + static + + // yyy.C + #include "yyy.h" + int i; + +* | Similarly, the header stop point may not be inside a ``#if`` block or a + ``#define`` started within a header file. +* | The processing preceding the header stop must not have produced any errors. + (Note: warnings and other diagnostics will not be reproduced when the PCH + file is reused.) +* | No references to predefined macros ``__DATE__`` or ``__TIME__`` may have + appeared. +* | No use of the ``#line`` preprocessing directive may have appeared. +* | ``#pragma no_pch`` (see below) must not have appeared. +* | The code preceding the header stop point must have introduced a sufficient + number of declarations to justify the overhead associated with precompiled + headers. This is configurable -- see ``PCH_DECL_SEQ_THRESHOLD``. + +When the host system does not support memory mapping, so that everything to be +saved in the precompiled header file is assigned to preallocated memory (i.e., +when ``USE_MMAP_FOR_MEMORY_REGIONS`` is FALSE), two additional restrictions +apply: + +* | The total memory needed at the header stop point cannot exceed the size of + the block of preallocated memory. +* | No single program entity saved can exceed ``HOST_ALLOCATION_INCREMENT``, + the preallocation unit. + +When a precompiled header file is produced, it contains, in addition to the +snapshot of the compiler state, some information that can be checked to +determine under what circumstances it can be reused. This includes: + +* | The compiler version, including the date and time the compiler was built. +* | The current directory (i.e., the directory in which the compilation is + occurring). +* | The command line options. +* | The initial sequence of preprocessing directives from the primary source + file, including ``#include`` directives. +* | The date and time of the header files specified in ``#include`` directives. + +This information comprises the PCH "prefix." The prefix information of a given +source file can be compared to the prefix information of a PCH file to +determine whether the latter is applicable to the current compilation. + +As an illustration, consider two source files: + +.. code:: c++ + + // a.C + #include "xxx.h" + ... // Start of code + + // b.C + #include "xxx.h" + ... // Start of code + +When ``a.C`` is compiled with ``--pch``, a precompiled header file named +``a.pch`` is created. Then, when ``b.C`` is compiled (or when ``a.C`` is +recompiled), the prefix section of ``a.pch`` is read in for comparison with the +current source file. If the command line options are identical, if ``xxx.h`` +has not been modified, and so forth, then, instead of opening ``xxx.h`` and +processing it line by line, the front end reads in the rest of ``a.pch`` and +thereby establishes the state for the rest of the compilation. + +It may be that more than one PCH file is applicable to a given compilation. If +so, the largest (i.e., the one representing the most preprocessing directives +from the primary source file) is used. For instance, consider a primary source +file that begins with: + +.. code:: c++ + + #include "xxx.h" + #include "yyy.h" + #include "zzz.h" + +If there is one PCH file for ``xxx.h`` and a second for ``xxx.h`` *and* +``yyy.h``, the latter will be selected (assuming both are applicable to the +current compilation). Moreover, after the PCH file for the first two headers +is read in and the third is compiled, a new PCH file for all three headers may +be created. + +When a precompiled header file is created, it takes the name of the primary +source file, with the suffix replaced by an implementation-specified suffix +(see ``PCH_FILE_SUFFIX``, which is set to ``pch`` by default). Unless +``--pch_dir`` is specified (see below), it is created in the directory of the +primary source file. + +When a precompiled header file is created or used, a message such as + +.. code:: text + + "test.C": creating precompiled header file "test.pch" + +is issued. The user may suppress the message by using the command-line option +``--no_pch_messages``. + +When the ``--pch_verbose`` option is used the front end will display a message +for each precompiled header file that is considered that cannot be used giving +the reason that it cannot be used. + +In automatic mode (i.e., when ``--pch`` is used) the front end will deem a +precompiled header file obsolete and delete it under the following +circumstances: + +* | if the precompiled header file is based on at least one out-of-date header + file but is otherwise applicable for the current compilation; or +* | if the precompiled header file has the same base name as the source file + being compiled (e.g., ``xxx.pch`` and ``xxx.C``) but is not applicable for + the current compilation (e.g., because of different command-line options). + +This handles some common cases; other PCH file clean-up must be dealt with by +other means (e.g., by the user). + +Support for precompiled header processing is not available when multiple source +files are specified in a single compilation: an error will be issued and the +compilation aborted if the command line includes a request for precompiled +header processing and specifies more than one primary source file. + +Manual Precompiled Header Processing +------------------------------------ + +Command-line option ``--create_pch`` *file-name* specifies that a precompiled +header file of the specified name should be created. + +Command-line option ``--use_pch`` *file-name* specifies that the indicated +precompiled header file should be used for this compilation; if it is invalid +(i.e., if its prefix does not match the prefix for the current primary source +file), a warning will be issued and the PCH file will not be used. + +When either of these options is used in conjunction with ``--pch_dir``, the +indicated file name (which may be a path name) is tacked on to the directory +name, unless the file name is an absolute path name. + +The ``--create_pch``, ``--use_pch``, and ``--pch`` options may not be used +together. If more than one of these options is specified, only the last one +will apply. Nevertheless, most of the description of automatic PCH processing +applies to one or the other of these modes -- header stop points are determined +the same way, PCH file applicability is determined the same way, and so forth. + +Other Ways for Users to Control Precompiled Headers +--------------------------------------------------- + +There are several ways in which the user can control and/or tune how +precompiled headers are created and used. + +* | ``#pragma hdrstop`` may be inserted in the primary source file at a point + prior to the first token that does not belong to a preprocessing directive. + It enables the user to specify where the set of header files subject to + precompilation ends. For example, + + .. code:: c++ + + #include "xxx.h" + #include "yyy.h" + #pragma hdrstop + #include "zzz.h" + + | Here, the precompiled header file will include processing state for + ``xxx.h`` and ``yyy.h`` but not ``zzz.h``. (This is useful if the user + decides that the information added by what follows the ``#pragma hdrstop`` + does not justify the creation of another PCH file.) +* | ``#pragma no_pch`` may be used to suppress precompiled header processing + for a given source file. +* | Command-line option ``--pch_dir`` *directory-name* is used to specify the + directory in which to search for and/or create a PCH file. + +Moreover, when the host system does not support memory mapping and preallocated +memory is used instead (i.e., when ``USE_MMAP_FOR_MEMORY_REGIONS`` is FALSE) +then one of the command-line options ``--pch``, ``--create_pch``, or +``--use_pch``, if it appears at all, must be the *first* option on the command +line; and in addition: + +* | Command-line option ``--pch_mem`` *size* may be used to change the size + of the preallocated block of memory from its default value. The + argument *size* is the number of 1024-byte units. (``--pch_mem`` must + also be among the first options on the command line.) + +Performance Issues +------------------ + +The relative overhead incurred in writing out and reading back in a precompiled +header file is quite small for reasonably large header files. (An +implementation can adjust ``PCH_DECL_SEQ_THRESHOLD`` to avoid creating +precompiled header files with too little information in them.) + +In general, it doesn't cost much to write a precompiled header file out even if +it does not end up being used, and if it *is* used it almost always produces a +significant speedup in compilation. The problem is that the precompiled header +files can be quite large (from a minimum of about 250K bytes to several +megabytes or more), and so one probably doesn't want many of them sitting +around. + +Thus, despite the faster recompilations, precompiled header processing is not +likely to be justified for an arbitrary set of files with nonuniform initial +sequences of preprocessing directives. Rather, the greatest benefit occurs +when a number of source files can share the same PCH file. The more sharing, +the less disk space is consumed. With sharing, the disadvantage of large +precompiled header files can be minimized, without giving up the advantage of a +significant speedup in compilation times. + +Consequently, to take full advantage of header file precompilation, users +should expect to reorder the ``#include`` sections of their source files and/or +to group ``#include`` directives within a commonly used header file. + +The EDG front end source provides an example of how this can be done. A common +idiom is this: + +.. code:: c++ + + #include "fe_common.h" + #pragma hdrstop + #include ... + +where ``fe_common.h`` pulls in, directly and indirectly, a few dozen header +files; the ``#pragma hdrstop`` is inserted to get better sharing with fewer PCH +files. The PCH file produced for ``fe_common.h`` is a bit over a megabyte in +size. Another idiom, used by the source files involved in declaration +processing, is this: + +.. code:: c++ + + #include "fe_common.h" + #include "decl_hdrs.h" + #pragma hdrstop + #include ... + +``decl_hdrs.h`` pulls in another dozen header files, and a second, somewhat +larger, PCH file is created. In all, the fifty-odd source files of the EDG +front end share just six precompiled header files. If disk space were at a +premium, one could decide to make ``fe_common.h`` pull in *all* the header +files used -- then, a single PCH file could be used in building the EDG +front end. + +Different environments and different projects will have different needs, but in +general, users should be aware that making the best use of the precompiled +header support will require some experimentation and probably some minor +changes to source code. + +.. [#f1] This is not recommended in general, since diagnostic messages and the + like will then not include a file name or will refer to the file name + "``-``". +.. [#f2] However, if ``STACK_REFERENCED_INCLUDE_DIRECTORIES`` is TRUE, the + directories of all the source input files currently in use are + searched, in reverse order of ``#include`` nesting. +.. [#f3] Since templates are descriptions of entities (typically, classes) + that are parameterizable according to the types they operate upon, + they are sometimes called *parameterized types*. +.. [#f4] The actual implementation allows for several different suffixes and + provides a command-line option to change the suffixes sought. +.. [#f5] Isn't this always the case? No. Suppose that file A contains a + definition of class ``X`` and a reference to ``Stack::push``, and + that file B contains the definition for the member function ``push``. + There would be no file containing both the definition of ``push`` and + the definition of ``X``. +.. [#f6] It should be noted that automatic instantiation, more than most + aspects of the C++ language, requires environmental support outside + of the compiler. This is likely to be operating-system and + object-format dependent. The front end is delivered with an + implementation that works under certain UNIX systems, and that + involves code in the front end proper, in IL lowering, in a separate + prelinker program, and in the ``eccp`` driver script. Because the + environmental issues vary so much from system to system, this code + should be viewed as a sample implementation that may need adaptation + to work on other systems. +.. [#f7] As a configuration option, and in older versions of the front end, + the information about entities that could be instantiated, etc. can + be represented in the names of generated variables added to the object + program. For example, a name ``__CBI__``\ *mangled-name* indicates + that the entity with the given mangled name could be instantiated, but + wasn't. This alternate scheme has the advantage that the object file + and the asssociated instantiation flags can never be out of sync. It + has the disadvantage that the object files produced can be quite a bit + larger because of the name strings for these generated external + variables. +.. [#f8] At the moment, the ``can_instantiate`` pragma ends up forcing the + instantiation of the template instance even if it isn't referenced + somewhere else in the program; that's a weakness of the initial + implementation which we expect to address. +.. [#f9] As a consequence, using exported templates may require considerably + more memory that similar uses of regular (included) templates. diff --git a/dev/doc/_sources/il.rst.txt b/dev/doc/_sources/il.rst.txt new file mode 100644 index 0000000..c7c459d --- /dev/null +++ b/dev/doc/_sources/il.rst.txt @@ -0,0 +1,3564 @@ +.. _intermediate-language: + +===================== +Intermediate Language +===================== + +The Intermediate Language is the output of the front end. It is a +representation of the source program that is passed to the back end, and +from which the back end can perform analyses, make transformations, and/or +generate object code. + +The intermediate language is a "high-level" intermediate language, that is, a +representation that is close in spirit to the original source language, rather +than a "low-level" intermediate language that is close to any typical computer +architecture. That fits the EDG philosophy of the function of a front end, +i.e., that a front end should determine the meaning of a source program and +produce an intermediate language representation of the source program that: + +* | accurately represents the meaning of the program; +* | does not destroy information; +* | does not add constraints that are not present in the source program; and +* | makes explicit any implicit or overloaded operations in the source program, + so that the back end does not have to have a deep understanding of the + source language and does not have to search or interpret the intermediate + language. It follows from this that the front end does not do + optimization, does not rewrite source constructs in "simpler" forms, and + does not use a machine-dependent representation. It also follows that + ambiguity and overloading resolution are completely handled by the front + end and a back end need do nothing to deal with them. The intermediate + language is a tree-structured in-memory data structure. Both declarative + and executable constructs are represented in tree form, and in fact all + declarative and executable information at all levels is tied together into + one tree. Having a pointer to the root of this tree gives one all the + information necessary to generate object code for the source program. (In + other words, the intermediate language data structure is the only + information that needs to be passed from the front end to the back end. + There is no additional hidden information.) The source code definitions of + the intermediate language tables are in the file ``il_def.h``. However, + some introductory information is necessary before one dives into that file. + +Memory Management +================= + +Memory management may seem like a strange place to begin an overview of the +intermediate language. However, an understanding of the memory management +structure is necessary to get a feeling for the overall shape of the +intermediate language tree. + +Memory Regions +-------------- + +It was decided early in the design of the front end that the intermediate +language would be an in-memory data structure. That is, it exists in +directly-addressable memory and can be examined without recourse to special +access routines. This is beneficial from the point of view of compilation +speed and ease of programming. However, it could be problematic from the point +of view of memory use, especially when processing extremely large source files. +To deal with that problem, it was decided that the intermediate language should +be set up so that the parts of the tree associated with different top-level +functions are placed in separate blocks of memory that need not all be in +memory at the same time. A top-level function is any function that is not a +lambda defined in a function scope, or the instantiation of a generic lambda +defined in a function scope. Functions that are not top-level are placed in +the memory region of the enclosing function. During the processing of a single +function, the intermediate language for that function (and for other functions +in the same memory region) and for the global declarations visible to that +function must be in memory. The intermediate language for all other functions, +however, is not needed at that time, and can be written out to a file or +otherwise removed from the active address space. As a result, a large source +program looks more like a sequence of reasonably-sized functions and uses +memory accordingly. + +These blocks of memory are called "memory regions". There is a memory region +for the file scope intermediate language and one for the intermediate language +of each top-level function of the source program. + +The memory region scheme is a two-level scheme: there is a file scope memory +region which is always in memory, and a set of function scope memory regions of +which only one is guaranteed to be in memory at a given time. C++ lambdas +defined in function scopes are handled by placing them in the same memory +region as the enclosing function. Member functions of local classes in C++, +while somewhat similar to lambdas, are treated (with some careful allocation of +entities) as top-level functions and have their own memory regions. + +Memory Regions and Pointers +--------------------------- + +The memory management structure has an effect on pointers in the intermediate +language. Clearly, a pointer to an entry in a function scope memory region is +valid only if the associated memory region is actually in memory. Rather than +requiring dynamic checking of pointer legality, we decided to make a rule about +how pointers may be used. Specifically, entries within a function scope memory +region may only be pointed to from within that memory region. Entries in the +file scope memory region may, of course, be pointed to from anywhere, since +they are always in memory. + +This rule has some consequences. The most important one is that anything that +must be referenced from more than one memory region must be allocated in the +file scope memory region. Specifically, since functions may be called from +many other functions, they must have some representation in the file scope +memory region. Of course, since the whole point of the function scope memory +regions is to avoid having everything in memory at one time, it wouldn't make +sense to put the entire routine into the file scope memory region. What's done +instead is to put the description of the interface to the routine (i.e., what's +needed to call it) in the file scope memory region, and the description of the +implementation of the routine (i.e., what's needed to execute it) in the +function scope memory region. Similarly, local static variables of functions +must be allocated in the file scope memory region because they are potentially +referenced from member functions of classes local to the function. + +A second consequence is that anything referenced from the file scope memory +region must also be allocated in the file scope memory region. [#f1]_ This +second consequence becomes significant when combined with another intermediate +language decision, that of placing all entities with external visibility at the +file scope. [#f2]_ Placing the declaration of an external entity at the file +scope means placing all of the entities it references in the file scope memory +region, and that means placing all the entities they reference in the file +scope memory region. The practical consequence of all that is that all types +must be allocated in the file scope memory region, since it is not possible to +know at the time they are allocated whether or not they will be used as part of +the type of some external entity. In C++, that means in particular that all +classes are allocated in the file scope memory region (except for the bodies of +member functions). Likewise, all namespaces are allocated in the file scope +memory region except for the bodies of namespace member functions. + +It is important to bear in mind that the *file scope memory region* is not the +same thing as the *file scope*. They are similar but not identical. The *file +scope* is a language concept: it is the outermost scope in a C or C++ program. +The *file scope memory region* is a memory management concept referring to a +block of memory whose contents must always be accessible. All entities in the +file scope are allocated in the file scope memory region, but some entities +allocated in the file scope memory region are function-scope entities, some are +function-scope entities moved to the file scope because they are externally +visible, and some are class or namespace members allocated in the file scope +memory region because all classes and namespaces are allocated there. + +Intermediate Language Files +=========================== + +The intermediate language and memory management scheme are set up to allow but +not require the use of files to save the intermediate language. The front +end's connection to a back end can be configured in a number of ways: + +* | The entire intermediate language tree can be passed in memory to the back + end. This is fastest but uses the most memory. +* | The intermediate language can be written to a file on a + per-top-level-function basis and read back in on a per-top-level-function + basis in the back end. (Only one file is used, but the intermediate + language for each function is written separately and the memory involved is + reclaimed immediately.) This is slowest but uses the least memory. +* | The intermediate language can be processed on a per--top-level-function + basis in some other way, then thrown away. For example, the intermediate + language can be translated to another intermediate language used by the + back end, and the original intermediate language can be discarded. + +C versus C++ Intermediate language +================================== + +The intermediate language generated for C++ is a superset of the intermediate +language generated for C. + +For the sake of customers that have an existing C back end, EDG provides a +optional and separate "IL lowering" pass that translates the C++ intermediate +language into the C intermediate language. Note that although the process is +called "lowering," the resulting C intermediate language is still "high-level"; +it's just not as high-level as it was. Also note that the IL lowering process +does some implementation of C++ features (e.g., virtual function tables, name +mangling, pointers-to-members, constructor and destructor wrapper code) which +are just abstractions in the unlowered IL. Clearly, a back end has the most +latitude in generating code for C++ if it starts with the unlowered C++ IL, but +it also has quite a bit more work to do. On the other hand, an extra pass over +the intermediate language takes time, so a configuration that uses the IL +lowering pass will not be as fast as one that does not use it. + +The IL lowering pass is useful because + +#. it allows customers to get a C++ compiler going in minimal time; +#. if the features implemented by IL lowering require some minor changes, + the changes can be made in IL lowering, which is relatively small, rather + than in the front end as a whole, which is quite large; and +#. if a customer wants to attach a back end to the unlowered IL (either + initially or for an improved release of a compiler), the IL lowering code + serves as a guide to the tasks that must be done. + +The description of the intermediate language in this chapter is for the +unlowered IL. All C++-specific features are rewritten or removed by the IL +lowering, which means that some of the description in this chapter is of no +interest to a back end that uses the lowered IL. If there is some question +about whether or not a feature would remain in the lowered IL, the description +will indicate what effect IL lowering has. + +There is no way at present to compile the C++ front end so that the IL that it +generates includes only the C IL definitions. Even though IL lowering will +eliminate uses of non-C features, the C++-specific fields and enumeration +values are still present in the source code. Back ends should ignore those +fields (they are not necessarily cleared) and should expect to get IL that is +valid C when one considers (only) the fields that C uses. + +One catch: Dynamic initialization of entities in the middle of blocks is left +in its original form. This is not "incorrect" C IL, but is something that does +not come up in C(89) programs. It was judged that back ends would be capable +of dealing with the ``stmk_init`` statements even if they appear after other +executable statements in a block, and the alternative was to make lowering of +initialization of aggregates to constants quite messy. + +Similarly, the initialization statement attached to an ``stmk_for`` is always a +simple ``stmk_expr`` in C, but in C IL generated by IL lowering, it can be an +arbitrary statement. + +C99 and the Intermediate Language +================================= + +The ANSI/ISO C standard was updated in 1999, and the resulting version of C +is referred to as C99. The C/C++ front end supports C99 (as well as later +versions). In some cases, the IL has been extended to support newly-added +features of C99. + +The IL extensions for C99 and later revisions are enabled by the macro +``C99_IL_EXTENSIONS_SUPPORTED``. If that macro is set to FALSE, C99 and +later modes can still be enabled, but all features that require the IL +extensions are disabled. Note, in particular, that if your interest is +only in supporting C++, or only C89, turning off these features will make +it slightly easier to write a back end, because you will have to implement +fewer IL constructs. + +There is a lowering phase for C99, which rewrites many of the extensions into +standard C89 IL. This lowering phase is enabled by the macro +``DO_IL_LOWERING``. + +See :ref:`il-c99-features` for a detailed list of C99 IL constructs. That list +summarizes the lowering done for each construct; there is more detail in the IL +Lowering chapter of this document. + +C++/CLI and the Intermediate Language +===================================== + +The front end supports the Microsoft C++/CLI language, a set of extensions to +C++ to allow programmers to interface to Microsoft's .NET, which is a +heap-based garbage-collected environment in the style of Java or C#. There is +an ECMA standard for the C++/CLI language (ECMA 372), but the real standard is +the MSVC compiler, as it diverges from the ECMA document in significant ways. + +The C++/CLI extensions involve new types, new expression operators, new member +function kinds, new declarations, and new statements. Those are covered in +detail in the appropriate sections of this document. The data structures and +code for those features are included when ``MICROSOFT_EXTENSIONS_ALLOWED`` is +TRUE; there is no separate macro for C++/CLI to control their inclusion. The +features are enabled only when ``cppcli_enabled`` is TRUE, and there is a macro +``CPPCLI_ENABLING_POSSIBLE`` that when FALSE (the default) prevents the C++/CLI +features from being enabled. So if you do not want to support C++/CLI, leave +``CPPCLI_ENABLING_POSSIBLE`` set to FALSE and you will never see any of its +features in the IL. + +Note that C++/CLI is supported only when the front end is hosted on Windows. +Also note that C++/CLI is Microsoft's second version of a C++ interface for +.NET; there was a previous set of extensions called "Managed C++". The front +end does not support those features (and Microsoft is moving away from +supporting them as well). + +Memory Region Processing Order +============================== + +When a file is compiled, the processing order of memory regions will look like: + +* | Start file scope memory region (1). + + * | Start function scope memory region (2). + * | End function scope memory region (2). + * | Start function scope memory region (3). + * | End function scope memory region (3). + * | Etc. +* | End file scope memory region (1). + +When IL lowering is done, it is done as each memory region is ended. When IL +files are written, they are written as each memory region is ended (after IL +lowering, if any). + +When the front end instantiates functions or generates routines (like +constructors), there can be brief periods when multiple function scope memory +regions are active. The function scope memory region for the instantiated or +generated routine is started and ended while the primary function scope memory +region is still active. If this process kicks off instantiation or generation +of other routines, there can be many active function scope memory regions. + +General Information +=================== + +Each major type of entity in the C/C++ language has a corresponding +intermediate language entry. For example: ``a_constant``, ``a_type``, +``a_variable``, ``a_routine``, ``a_label``, ``a_statement``, and +``an_expr_node``. Each entry kind has a fixed size except for the entries +representing strings (used for literal strings and names), which have a +variable length. The IL entries are not self-labeling; one must know the kind +of thing pointed to to make sense of a pointer. + +The intermediate language is high-level, meaning that the entities in it +correspond fairly closely to C and C++ language constructs. For example, all +of the C and C++ expression operators are present in their original forms. +There is no remapping of complex operators (like "``?``") to lower-level +operations. Statements are kept in their original structured form, and not +flattened to ``if``\ s and ``goto``\ s. + +Since the structure of the intermediate language corresponds so closely to the +original C or C++ form, it implies no ordering of evaluation that was not in +the original program. Timing of side effects for post-increment operations, +for example, which must be completed by the next sequence point, is not +specified explicitly. It is up to the back end to adhere to the C and C++ +language rules when generating object code for such constructs. + +By convention, there can be multiple pointers to any given declarative entity +(for example, many places can point to the constant entry for ``1``), but only +a single pointer to any executable entity (each use of ``1`` in an expression +requires a distinct expression node pointing to the common constant entry for +``1``). + +The intermediate language tables are designed to keep memory requirements +reasonably low. There are several cases where ``enum`` values are stored as +``a_byte``\ s (which means as ``char``\ s of some kind), in order to ensure +that only one byte is used for those rather than whatever the host C compiler +might choose for an ``enum``. An example of such a type is +``a_constant_repr_kind``. This has the unfortunate side effect that explicit +casts are often required when dealing with values of these types. There are +also several cases where, in a union that has one case that is larger than all +the others, the extra information for the unusual case is broken out as a +separate supplement that is pointed to from the union (e.g., +``a_routine_type_supplement``). + +As mentioned, all of the intermediate language is tree-structured. The +expression ``i+1`` is a tree with a ``+`` expression node pointing to two +expression nodes representing ``i`` and ``1``; the statement + +.. code:: c++ + + if (i) i=1; else i=2; + +is a tree with an ``if`` statement node pointing to two statement nodes for +``i=1`` and ``i=2``; and the declaration + +.. code:: c++ + + int *m[5]; + +is a variable node for ``m`` pointing to a tree defining the type "array of +pointer to ``int``". All the statements of a function are bundled into one +tree which is pointed to by the function definition, and all the type, +variable, and function definitions for a given scope are on a list pointed to +by the header for the scope. At the top of the entire tree for a compilation +there is a header that points to the entry for the outermost scope. Beginning +there, one can get to all of the functions and therefore all of the functions' +scopes; one can also get to all of the classes and therefore all of the +classes' scopes. In other words, beginning at the IL header one can reach the +entire IL tree for the compilation. + +The IL Header +============= + +The top of the intermediate language tree is ``il_header``, which contains +several important pointers: + +* | A pointer to the scope entry defining the primary scope of the compilation. + This is the root of the IL tree proper. +* | A pointer to the top of a tree of entries describing the source files from + which the source program came. +* | A pointer to the ``scope_region_entry`` array, which gives pointers to the + scope entries that are the top of the IL tree in each of the function scope + memory regions. +* | A pointer to the ``function_def_table`` array, which gives the pointers to + the scope entries and memory region numbers for a given function + definition. + +Source File Information +======================= + +The source file information structure describes the primary source input file +and the include files of the compilation, and the relationship between them. +It is a structure distinct from the IL tree proper because the file structure +of a program need not have any relationship to its syntactic structure. An +include file, for example, could include half of a routine, or the end of one +routine and the start of another. (This is of course not typical, but it's +possible.) Within the IL tree proper, a source line's position is given by a +*sequence number*, which is the ordinal position of the source line in the +sequence of lines read by the front end, starting at the beginning of the +primary source file and switching into include files when directed to by +``#include`` directives. The sequence number is compact and unambiguous for +internal use, and can be translated easily to a file name and line number for +external use by referring to the source line information structure. The +routine ``conv_seq_to_file_and_line`` in ``il.c`` does that translation. + +Source Correspondence Information +================================= + +Constructs that declare constants, types, variables, routines, fields, labels, +namespaces, templates, template parameters, and macros have information on the +associated source name and the source location of the declaration. This +information is given by the ``source_corresp`` field, which is a ``struct`` of +type ``a_source_correspondence``. A source location is specified by an entry +of type ``a_source_position``, which consists of a sequence number and a column +number. The column number is the 1-origined column number in the original +source line (*not* the logical source line that results after processing +trigraphs and line splices). Tab characters count as one column, so the +"column number" may not match the apparent display position on a terminal or +printer. If multibyte characters appear, including characters that come from +files in formats such as UTF-16, they count as a single column. The node for +statements has a source location as well, but (to save space) it contains only +a sequence number and no column number (see, however, the configuration flag +``FULL_SOURCE_POS_IN_IL_STATEMENT``). + +Aside from a pointer to the name string and the source position, the source +correspondence information contains an ``assoc_info`` pointer. This is +intended to be used by the front end and other components to store a pointer to +information maintained locally about the entity. However, the information does +not survive into the next pass. In the front end, the pointer points back to +an associated symbol entry. That pointer is no longer valid once the front end +is finished (since the space for symbol entries may have been released), but +the pointer can be set in the back end as desired. + +Compiler-generated entities have no source correspondence information +(since they do not appear in the program source). Their source +correspondence name pointer is NULL. + +The source correspondence information also contains the ``name_linkage`` field, +which indicates the kind of linkage the entity has (e.g., is it externally +visible? Should C++ name mangling be done on it?), an access field (which +indicates the access for class members in C++), a ``parent_scope`` pointer to +the containing scope, and a ``referenced`` field. + +When ``IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS`` is TRUE, the name string +in the source correspondence entry can contain multibyte character +sequences (e.g., UTF-8 when ``UNICODE_SOURCE_SUPPORTED`` is TRUE). When it +is FALSE, multibyte characters will be represented as ``\m``\ *XXXX* or +``\M``\ *XXXXXXXX* escape sequences. When a universal-character-name +(e.g., ``\u00d6``) appears in a name, the name string will contain the`` +\u``\ *XXXX* or ``\U``\ *XXXXXXXX* escape sequence, except that when +``UNICODE_SOURCE_SUPPORTED`` and +``IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS`` are both TRUE the UCN value +will be represented directly. IL lowering can do some limited rewriting of +such escape sequences; see ``REWRITE_UCN_ESCAPE_CHAR_IN_LOWERING``. Note +that these flags do not control whether or not multibyte characters are +allowed in identifiers, only how they are represented; see +``MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED``. + +``referenced`` and ``needed`` Flags +----------------------------------- + +The ``referenced`` flag in a source correspondence entry indicates whether an +entity is referenced. All entities that have no source correspondence have +``referenced`` set to TRUE. For named entities, ``referenced`` is TRUE if the +entity is referenced in the intermediate language. The reference can be +implicit: in a case like + +.. code:: c++ + + struct s {int a;} v; + +the ``struct`` type is referenced, but not through the name ``s``. + +The referenced flag is set correctly but simplistically. More precise +information is available in the ``needed`` flag (and, in classes and routines, +the ``definition_needed`` flag). These are optional and are selected by the +configuration switch ``MAINTAIN_NEEDED_FLAGS``. When present, they indicate +whether or not an entity is "really" needed, and whether the definition of a +class is really needed, or merely its declaration. This is determined by +marking as needed all externally-defined functions and variables, and all the +things they reference, and all the things those things reference, etc. + +Depending on the setting of ``DEFAULT_REMOVE_UNNEEDED_ENTITIES``, possibly as +overridden by a command-line option, unneeded entities and unneeded class +definitions will be removed from the IL tree. This process, however, does not +remove all unneeded entities, because some end up being required for IL +consistency even though they are not "needed." One example: if a class and its +definition are needed, all the members of the class must be kept in the IL even +though some of the members may not be "needed" (in the sense of being +referenced directly or indirectly from an externally defined routine or +variable). The IL after removal of unneeded entities will be self-consistent, +in that a back end that does not use the needed flags will find nothing +surprising. If a back end uses the ``needed`` flag, it should also pay +attention to the class ``definition_needed`` flag or it may find some apparent +inconsistencies in the IL tree. + +The setting of the "needed" flags and the removal of unneeded IL entries work +both with and without IL lowering. When IL lowering is done, the setting is +done after lowering, so that the flags reflect the lowered code. + +When ``ONE_INSTANTIATION_PER_OBJECT`` is TRUE, a more complicated set of +"needed" flags is maintained. In that mode, each instantiation is put out as a +separate object file. There is still only one IL tree, but it is marked so +that a back end can sweep through it several times and put out a different +"slice" each time, each slice containing one instantiated entity (function, +variable, or static data member) plus exactly the set of other entities needed +by that entity. This is done via a set of per-instantiation "needed" flags, +represented as a bit vector implemented as a linked list of entries of type +``a_per_instantiation_needed_flags_entry`` attached to the +``per_instantiation_needed_flags`` field of the source correspondence. Each +slice is assigned one bit in that bit vector, and if the bit is 1 the +associated entity is needed in the slice. + +See the :ref:`needed-flags` section. + +Source positions +---------------- + +Source position information is recorded in the IL in various ways. The +``decl_position`` field in the source correspondence indicates the source +position of the primary declaration of an entity. When an entity has more than +one declaration, ``decl_position`` corresponds to the defining declaration or, +if there is no defining declaration, the first declaration. When +``GENERATE_SOURCE_SEQUENCE_LISTS`` is TRUE, source positions on declarations +other than the primary declaration are recorded in the source-sequence list -- +see ``decl_position`` in ``a_src_seq_secondary_decl``. As noted previously, +position information is also recorded in ``a_statement``; in addition, source +position information is recorded in other IL entries that have no source +correspondence field, e.g., ``a_base_class``, ``a_using_decl``, +``an_instantiation_directive``, ``a_static_assertion``, and ``a_pragma``. + +In applications for which additional source position information is needed, +``EXTRA_SOURCE_POSITIONS_IN_IL`` can be configured to TRUE. Note, however, +that this information can take a lot of extra space, so the feature is disabled +by default. + +When ``EXTRA_SOURCE_POSITIONS_IN_IL`` is TRUE, source range information +(beginning and ending source positions of various syntactic constructs) is +supplied. Each source correspondence has a pointer to +``a_decl_position_supplement``, which includes the source range of the complete +identifier (including namespace and class qualifiers, if present), as well as +the source range of the declaration-specifiers and the declarator. For +instance, the source position information for this declaration of ``foo`` is +indicated: + +.. code:: text + + inline void A::foo(A *pa) { /* ... */ } + ^ decl_position + ^^^^^^ identifier_range + ^^^^^^^^^^^ specifiers_range + ^^^^^^^^^^^^^ declarator_range + +Moreover, though the param-type entry for parameter ``pa`` has no source +correspondence entry, it does have a pointer to ``a_decl_position_supplement``, +which records its source range information: + +.. code:: text + + inline void A::foo(A *pa) { /* ... */ } + ^^ identifier_range + ^ specifiers_range + ^^^ declarator_range + +Source range information is supplied for ``a_base_class`` and +``a_constructor_init``, as well as for the initializer construct of explicitly +initialized variables. Moreover, when ``GENERATE_SOURCE_SEQUENCE_LISTS`` is +TRUE, pointers to ``a_decl_position_supplement`` also appear in +``a_src_seq_secondary_decl`` entries; this provides source range information on +declarations that are not the primary declaration of an entity (e.g., +``friend`` declarations). + +Source range information is also provided for expression nodes when +``EXTRA_SOURCE_POSITIONS_IN_IL`` is TRUE. The source positions of the start +and end of the expression, along with the source position of the operator (if +present) are recorded. + +Name Linkage +------------ + +The ``name_linkage`` field of the source correspondence structure indicates the +kind of linkage the name of an entity (routine, variable, class or enumeration +type, or class member) has: + +* | External linkage, used in C mode and for ``extern "C"`` entities in C++ + mode, indicates that the name is visible outside its compilation unit. +* | C++ external linkage, for normal entities in C++ mode, indicates that the + name is visible outside its compilation unit. The name may be subjected to + some kind of name mangling. +* | Internal linkage indicates that the entity name is visible throughout its + compilation unit (e.g., a file-scope static variable). +* | No linkage indicates that the entity name has no connection to other + entities with the same name (e.g., a local variable). + +From a C perspective, the name linkage information seems to be redundant, in +that it would seem that one could decide the name linkage on the basis of a +variable or routine's storage class. In C++, however, class names (i.e., +types) have linkage, and in some compatibility modes if a class is used in the +type of an external entity, it acquires external linkage, and its static data +members and member functions also get external linkage. It gets to be very +complicated to try to encode the storage class (including whether or not it can +be changed on subsequent declarations) and the name linkage in just the storage +class field. + +In addition, the ``routine_name_linkage`` field in the routine type supplement +is significant. The linkage specification in a routine type declaration can +correspond to the routine's calling convention -- for example, when ``extern +"C++"`` and ``extern "C"`` imply distinct calling conventions or an +implementation-defined linkage specification has its own calling convention. +Among other things, this means that in C++ otherwise identical functions are +distinguished for purposes of overloading based on the linkages associated with +their parameter types: + +.. code:: c++ + + typedef void (*PF)(); // Pointer to an extern "C++" function + extern "C" typedef void (*PFC)() // Pointer to an extern "C" function + void f(PF); + void f(PFC); // Overloads f + +Note, moreover, that the linkage specification of a function's *name* need not +be identical to the linkage specification of its *type*. The former might +affect how its external name is generated and the latter might affect its +calling convention. + +Access Control +============== + +Access control information appears in several places: + +* | The ``access`` field of ``a_source_correspondence``, which appears in most + declarative entities. +* | ``using``-declarations and access declarations in classes, which may adjust + the accessibility of inherited members. +* | Base class entries, which indicate the kind of derivation from the base + class to the derived class. +* | Lists of the friend classes and friend functions of a class. These are + also available in reversed form as befriending lists for classes and + functions, which indicate the classes which have named the befriended class + or function as a friend. + +This information is useful to the back end only for generating symbolic +debugging information. The necessary access control checks will have been done +by the front end, and access control does not have an effect on code +generation. + +Only class members are subject to access control. All other entities (and all +entities in C) will have access of ``as_public``. + +The Scope Entry +=============== + +Each scope in the source program is represented by a scope entry in the IL +(type ``a_scope``). There are scope entries for: + +* | the file scope; +* | each function definition scope; +* | each block within a function; +* | each "prototype" scope (for function prototypes in function declarations); +* | each class, struct, and union type (when the type has a body); +* | each namespace (in C++); and +* | each condition (tested initialized variable in C++, e.g., in an "``if``" + statement). + +The scope entry for the file scope is pointed to from ``il_header``; it +contains lists of the file-scope entities in the compilation. In particular, +it points to a list of the functions in the compilation. Each function is +represented by an ``a_routine`` entry. A function without a body (i.e., an +``extern`` function) has just a routine entry. For a function with a body, the +field ``assoc_scope`` in the routine entry gives the region number for the +memory region containing the function, which allows one to get a pointer to the +scope entry for the function scope. That scope entry points to the statements +for the function, and to lists of its parameter definitions and of local +constants, types, variables, labels, and block scopes. + +One can see that the scope entry is the most important entry in terms of the +overall structure of the IL tree, in that it groups entities together into a +scope and also points down to the subscopes. Conversely, many IL entries point +back to their containing scope via the ``parent_scope`` field of their source +correspondence entry. (The scope entries themselves also contain a ``parent`` +pointer to their enclosing scope; this parent pointer is null for the file +scope.) + +A scope entry points to lists of the entities that are defined in the scope: +constants, types, variables, routines, sub-scopes, etc. The lists may be used +or not depending on the type of scope: + +* | File scope (allocated in the file scope memory region): + + * | types: used for tags (``class``, ``struct``, ``union``, and ``enum``) and + ``typedef``\ s. Top-level class definitions appear here. + * | variables: used for static and external variables at the file scope. + * | routines: used for functions both with and without definitions + (bodies). + * | dynamic initializations: used for variables that have dynamic + initializations (eliminated by IL lowering). +* | Function or block scope (allocated in a function scope memory region): + + * | types: used for tags (``class``, ``struct``, ``union``, and ``enum``) and + ``typedef``\ s that are local to the function or block. This pointer is + unusual in that it will point to a list of entries allocated in the file + scope memory region. Local classes appear here. + * | variables: used for local static variables (one list; this pointer is + unusual in that it will point to a list of entries allocated in the file + scope memory region) and automatic/register variables (another list). + * | scopes: for subscopes (blocks that have declarations). Note that every + ``{ }`` has an associated block statement, but a block statement only has + an associated scope if it contains local declarations. +* | Function prototype scope (allocated in the file scope memory region): + + * | types: used for tags (``class``, ``struct``, ``union``, and ``enum``) and + ``typedef``\ s that are local to the prototype scope. + + | Used only in C, not C++. Function prototype scopes are used to contain + types defined in prototyped parameter lists. When the function type is + part of a function declaration (i.e., there is no body), there's nowhere + else to put the types. When the function type is part of a definition, the + prototype scope is effectively part of the function scope, but it must be + kept separate so that it can be available in the file scope memory region + as part of the information on the interface to the function. +* | Class scope (allocated in the file scope memory region): + + * | constants: used for class constants (an extension). + * | types: used for tags (``class``, ``struct``, ``union``, and ``enum``) and + ``typedef``\ s. Nested types appear here. + * | variables: used for static data members of the class. + * | routines: used for member functions of the class. This includes all + member functions: static and non-static, virtual and non-virtual, inline + and non-inline, constructors, destructors, operator functions, and + conversion functions. Friend functions are not listed here (see the + friend and befriending lists under the class type and routine entries). +* | Namespace scope (allocated in the file scope memory region): + + * | types: used for tags (``class``, ``struct``, ``union``, and ``enum``) and + ``typedef``\ s. Type members of the namespace appear here. + * | variables: used for variable members of the namespace. + * | routines: used for function members of the namespace. + * | namespaces: used for nested namespaces. + +The entries appear on the lists in the order of declaration in the source +program, with the exception that tags and routines appear at the point where +the full definition occurs, not where the first forward reference appears. +Unreferenced entities *do* appear on the lists. + +Not all intermediate language entities appear directly on the lists. An entity +appears on a list if: + +* | it is named in the source program; or +* | it is a tag (``class``, ``struct``, ``union``, or ``enum``); or +* | it is a front-end-generated temporary variable or parameter. + +Note that enumerated constants appear as part of the definition of the ``enum`` +tag and not ever on a constants list. + +The type lists will also contain "placeholder typerefs," which are +``tk_typeref`` types with no name and no type qualifiers which provide +information about corresponding positions in different type lists. These are +useful to IL lowering in promoting types out of classes and namespaces. See +the section on placeholder typerefs in the IL lowering chapter of this +document. + +For function scopes, the scope entry contains additional information: + +* | A pointer to the routine entry (in the file scope memory region). +* | A list of parameter variables, and (for a nonstatic member function) a + "``this``" parameter variable. +* | For constructors and destructors, a list of ``a_constructor_init`` entries + indicating initialization or destruction to be done. +* | Labels within the function. +* | A list of entries for computing the bounds of variable length array types. + +.. _il-types: + +Types +===== + +``a_type`` describes a type, which can be ``void``, an integral or enumeration +type, a real, complex, or imaginary floating-point type, a fixed-point type, a +pointer, a reference, ``std::nullptr_t`` (the type of the ``nullptr`` keyword +in C++), an array, a GNU vector type, a ``class`` or ``struct``, a ``union``, a +function type, a pointer-to-member type, a ``typeref``, or a fully generic +template-dependent type. Some of these type kinds -- including fixed-point and +vector types -- are optional (i.e., available only in specific configurations). + +``void``, ``std::nullptr_t``, the fixed-point types, and the floating types are +self-contained. Integer types and enumeration types point to a supplement +entry of type ``an_integer_type_supplement`` (conveniently accessed with the +macro ``integer_type_supp``). Enumeration types are basically integer types, +with an additional pointer to either a list of ``a_constant`` entries that +define the members of the enumeration (for unscoped enumeration types), or a +scope entry (for scoped enumeration types; the scope entry then points to the +list of enumerator constants). The entries representing the enumerator +constants may, e.g., be of interest to a back end for generating symbol +debugging information. + +The integral, fixed-point, and floating types are provided in a fixed set of +sizes, e.g., ``float``, ``double``, and ``long double`` for floating. The +sizes of the types can be configured easily, but they remain essentially +symbolic. That is, ``int`` remains ``int`` and not "integral type of size 4". + +A special type kind is used to represent "template parameters" in a broad +sense. This includes normal template parameters, but also otherwise unknown +template-dependent types like ``typename T::X`` where ``T`` is a template +parameter. This general concept "template parameter type" is also used to +represent the ``auto`` type specifier in modes that support it. The general +type kind for template-dependent types is ``tk_template_param``. + +The other kinds of types are *derived* types -- they point to one or more other +types, and are used to build up type trees. For example, the type entry for +``int`` can be pointed to by an array type entry to build an array of ``int``. +A pointer type entry could be put on top of that to make a pointer to array of +``int``. + +Derived types are built up from their constituent types in the obvious way: + +* | Array types point to the element type and indicate the number of elements. +* | Function types point to the return type. Parameters of prototyped cases + (and of the types of defined unprototyped functions) are represented by a + list of ``a_param_type`` entries (pointed to indirectly by the type entry + via an entry of type ``a_routine_type_supplement``). +* | Pointer and reference types point to the underlying type. Pointers and + references are represented as variants of a common type kind. +* | Pointer-to-member types point to the class type and the underlying type. +* | ``class``, ``struct``, and ``union`` types point to a list of ``a_field`` + entries that define the members. There is a class type supplement that + provides a great deal of additional information, especially in C++. (See + below.) +* | typedefs, type qualifiers (e.g., const and volatile), type operators such + as decltype, and various other types are represented by an entry called a + typeref, described in more detail in a subsection below. + +Simple types are shared. For example, there would only be one type entry for +the type ``int``, and it would be pointed to in all cases where it is needed. +There is also sharing of pointer types, reference types, pointer-to-member +types, and qualified types: the based types list pointer in a type entry points +to a list of types based on the type (e.g., pointer-to the type); when a based +type is created, it is placed on the list and can thereafter be found and +reused. + +Types include information indicating their size and alignment (but beware of +``typeref``\ s, which normally have no size or alignment of their own [#f3]_, +and function types, which have no size or alignment). The sizes and alignments +are set by routines in ``types.c`` and ``class_decl.c`` and are taken on faith +in the rest of the front end. Incomplete types have size zero and have the +flag ``incomplete`` set to TRUE. Other types (including classes that contain +no nonstatic data members) normally have sizes greater than zero (some C and +C++ dialects treat some completely defined types as having size 0). + +When support for ``near`` and ``far`` is enabled (e.g., in 16-bit Microsoft +mode), the ``near`` and ``far`` memory attributes are encoded as type +qualifiers. A qualifier appears only if it is not the default. For example, +if the source specifies ``far`` and the default in that context is ``far``, no +qualifier is added. Back ends that need to know about memory attributes can +check the size of individual pointers (i.e., does the pointer have the size of +a ``far`` pointer) or use the function ``is_far_type`` (e.g., to determine the +calling method for function types). The memory attributes appear only when +``il_header.near_and_far_enabled`` is TRUE; see also ``NEAR_AND_FAR_ALLOWED``. + +When support for named address spaces is enabled (a feature of Embedded C), +named address spaces are also encoded as type qualifiers. Unlike other +qualifiers, named address spaces are *not* encoded as a bit vector (e.g., a bit +per address space) but as a small integer indicating which address space is +selected (zero represents "no specific address space" which is sometimes +referred to as "the generic address space"). This small integer can be used as +an index in the array ``named_address_spaces``; this array is defined in +``targ_def.h`` and can be configured to describe the address spaces of a +particular target. + +Variable length array types are a special case, because the number of elements +in the array is computed at run time, and so the dimension is represented as an +expression. However, the type itself cannot point to the dimension expression, +since the former belongs to the file-scope memory region and the latter to a +function-scope memory region. Instead, the flag ``has_assoc_vla_dimension`` is +set in the type entry, and the dimension expression is stored in an entry of +type ``a_vla_dimension``, which appears on a linked list pointed to by the +routine's IL scope entry (see ``find_vla_dimension`` in ``il.c``). When the +bound of a VLA is unspecified (e.g., because it was declared with the ``[*]`` +syntax), ``is_vla`` will be TRUE but ``has_assoc_vla_dimension`` will be FALSE. + +.. _il-typerefs: + +Typerefs +-------- + +Typerefs are used to record additional information for existing types: + +* | typedefs giving a name for a type, +* | type qualifiers such as ``const`` and ``volatile``, +* | typeof (a GNU extension) and decltype (a C++11 feature) constructs, +* | specializations of alias templates, +* | type splices (a C++26 feature), +* | type-returning traits, +* | type-transforming attributes, +* | dependent type pack index specifiers, and +* | (when configured with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE) + lexical information such as nested name qualifiers and alternative template + arguments. + +Typeref type entries point to a typeref type supplement containing additional +information such as template argument lists, nested name qualifiers, and +operands of type operators. + +For qualified pointer types, the typeref indicating the qualifier is on the +type of the pointer type: for ``int *const q`` the type is a const typeref +pointing to a pointer type entry, which points to an entry for ``int``. +(By comparison, ``const int *q`` produces a pointer type entry pointing to +a const typeref, which points to an entry for ``int``.) + +It is often necessary for code that deals with types to access the target of a +typeref or chain of typerefs. Various convenience functions are provided for +this purpose, including ``skip_typerefs``, ``skip_typerefs_not_typedefs``, +``skip_lexical_typerefs``, etc. + +Class Types +----------- + +Class types are ``class``, ``struct``, and ``union`` types [#f4]_. Their +associated type entry always points to a class type supplement (conveniently +accessed with the macro ``class_type_supp``), which carries additional +information especially relevant to C++. + +In C, a ``struct`` or ``union`` type is relatively simple, and is defined by a +list of ``a_field`` entries. Each entry defines one field (member) of the +``struct`` or ``union``. The offset of a field is given as the combination of +a byte offset (the ``offset`` field) and a bit offset (the +``offset_bit_remainder`` field). The latter is nonzero only for bit fields +(i.e., when ``is_bit_field`` is TRUE); a bit field also has a nonzero +``bit_size``, and its type (an integral type) is significant only as an +indication of the base type specified in the source program. Enum types and +integral types smaller than ``int`` can appear as the base type for a bit +field. A separate flag ``bit_field_is_signed`` indicates whether or not the +bit field is signed. Unnamed fields in the source program, which affect the +offsets of the fields that follow them (i.e., they introduce gaps), also appear +in the list of fields for the ``struct``. + +An associated scope is defined for a ``struct`` or ``union`` in C even though +the C language doesn't really associate a scope with those constructs. The +scope is used only to represent the parent of the type's fields. The type does +have a class type supplement, but that's mostly necessary so that the pointer +to the associated scope can be recorded; the rest of the class type supplement +is irrelevant in C. + +In C++, the fields are the nonstatic data members of the class, and the class +type supplement gives additional information about the class: + +* | A list of the base classes of the class (both direct and indirect). +* | A list of the ``using``-declarations (and access adjustments, from access + declarations), of friend classes and functions, and of classes that have + befriended the class. These are of interest to a back end only for + generating symbolic debugging information. Note that the friendship + information is available in normal and reversed forms: the "befriending" + information is backwards from the source form -- it appears on the class + that is befriended, not the one that granted the friendship with a + ``friend`` declaration. +* | A scope entry for the class, which contains the definitions of the static + data members (as variables) and member functions (as routines) of the + class. The scope is present only if the class has been defined. + +The nonstatic data members are listed in declaration order, which (with the +default class allocation scheme) is the same as allocation order. Members of +base classes are not listed in the derived classes, even though they are in +some sense present by inheritance. + +Base Class Entries +^^^^^^^^^^^^^^^^^^ + +A base class entry describes a specific base class of a specific derived class. +It's more than just the type of a base class -- it describes how that class +type relates to the derived class: + +* | Where the storage for the base class appears in the derived class. +* | The derivation path from the derived class to the base class; for virtual + base classes there may be more than one such path. +* | The type of derivation, e.g., is the base class a virtual base class? +* | The list of virtual functions of the base class that are overridden in the + derived class. (This information is useful for generating virtual function + tables.) + +Base class entries are used for indirect base classes (i.e., base classes of +base classes) as well as for direct base classes. + +The base classes list for a given class lists all of the base classes of the +class all the way down, in depth-first left-to-right order (i.e., an indirect +base class precedes the direct base class derived from it; not coincidentally, +this is the order defined by the language as initialization order.) A +nonvirtual base class can appear more than once on the list -- it is marked as +ambiguous -- but a virtual base class will appear only once, though it may have +more than one derivation path. + +Base class entries are used in the IL wherever it is necessary to provide an +unambiguous specification of a base class instance. + +Class Scopes +^^^^^^^^^^^^ + +If a class is defined, its class type supplement will point to a scope entry +that defines the contents of the class (except the nonstatic data members, +which are provided by the field list of the class type). The class scope will +contain: + +* | Constants, for class constants (an extension). +* | Types, for types defined within the class (including nested classes). +* | Variables, for static data members and instances of variable templates. +* | Routines, for member functions, including static and non-static, virtual + and non-virtual, inline and non-inline, constructors, destructors, operator + functions, and conversion functions, but not friend functions. The routine + entries indicate any special attributes of each function, but the routine + list is just a list in declaration order. It's not broken into sections or + indexed in any way. The only way to find all virtual functions, for + example, is to go through the list and examine each routine to see if it is + virtual. + +Class Member Declaration Lists +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The lists described above group the members of a class by category, and none of +them accounts for constructs like a ``static_assert`` declaration, which +declares nothing. When ``MAINTAIN_CLASS_MEMBER_LIST`` is configured to TRUE, +the class type supplement of every defined class also points to the +``member_declarations`` list, which has one ``an_il_entity_list_entry`` per +declaration that appeared in the body of the class, in the order in which the +declarations appeared. For example, the list built for + +.. code:: c++ + + struct S { + static_assert(sizeof(int) == 4); + int a, b; + template void f(T); + friend void g(); + enum E { e1, e2 }; + }; + +identifies, in order, a static assertion, a field (``a``), a field (``b``), a +template, a routine, and a type. + +Note that: + +* | A friend declaration that appears in the body is included even though the + entity it declares is not a member of the class. +* | Entities that are not explicitly declared in the body are not included: + that is the case for members that the front end generates (e.g., an + implicitly-declared default constructor) and for template instantiations + that are triggered while the body is being processed. A member that is + explicitly defaulted or deleted is declared, and is therefore included. +* | An anonymous union is represented by the entry for its type; no entry is + created for the unnamed field through which the members of the union are + accessed (that field can be reached through the + ``anonymous_union_field`` pointer of the class type supplement). +* | The closure class of a lambda expression that appears in the body (e.g., + in a default member initializer) is not included; that class is reached + through the ``a_lambda`` entry for the expression. +* | An enumerator is not included because the declaration of its enumeration + type is; the enumerators can be reached through that type. +* | A member template is represented by the entry for its template, not by an + entry for the prototype instantiation of the templated entity (see + :ref:`templates-in-the-il`). +* | A *using-declaration* that names an overload set (or, with ``using + enum``, an enumeration) produces several ``a_using_decl`` entries but only + one entry on the list. +* | An entity that is declared more than once in the body is represented by one + entry per declaration. For example, a nested class that is first declared + and later defined in the same body appears twice. + +The list of an instantiated class template specialization describes the +declarations of the instantiated body. + +Class Layout +^^^^^^^^^^^^ + +Class layout is done by routines in ``layout.c``, and the decisions made are +recorded in the IL in the form of offsets, sizes, and alignments. The class +layout can be configured in various ways, or can be replaced in its entirety. +Class layout decides on: + +* | Offsets of nonstatic data members (fields) within the class. +* | Offsets of base classes within the class. For virtual base classes, + offsets of the information that allows access to the virtual base classes + (typically, a pointer to the virtual base class). +* | Offsets of virtual function information (typically, a pointer to a virtual + function table). +* | Ordering of base classes and members, and insertion of necessary alignment + between them. + +Virtual function table pointers and virtual base class pointers can be shared +with base classes. That is, space for such pointers need not be allocated in a +derived class if they are present in a base class; the derived class can use +the pointer in the base class. + +There are many configuration macros that control class layout. See +``targ_def.h``. + +C++/CLI Types +^^^^^^^^^^^^^ + +In addition to the standard types, C++/CLI has + +* | handle and tracking reference types, which are represented as + ``tk_pointer`` types, but aren't considered to be standard pointers or + standard references; +* | ``interior_ptr`` and ``pin_ptr`` types, which are variants of standard + pointer types with certain added attributes and restrictions (they only + appear as the types of local variables, parameters, or return types); +* | managed class types (``ref``\ ``struct``, ``ref``\ ``class``, ``value``\ + ``class``, ``interface``\ ``class``), which are represented like standard + class types, with a value in the ``cli_class_type_kind`` field that + indicates the kind of managed class; +* | ``enum``\ ``class`` types, which are similar to C++11 scoped enum types and + similarly represented; +* | CLI array types, which are represented as managed class types tagged with + the ``is_cli_array`` field; and +* | delegate types, which are represented as managed class types tagged with + the ``is_delegate_class`` field. + +Fundamental types usually have corresponding value class types (e.g., ``int`` +corresponds to the ``System::Int32`` value class type). In general, types +written in the source in either form are converted to the fundamental type +version. In cases where a managed type is required, the fundamental type is +converted to the value class, so for example "``int ^``" becomes "handle to +``System::Int32``" as soon as it is created. Otherwise, conversions between +the two kinds of types are always indicated explicitly. In particular, in +expressions a conversion from one form to the other will be indicated +explicitly, e.g., with a box or unbox operator. + +Namespaces +========== + +Namespaces are represented by entries of type ``a_namespace``. Such an entry +is used for a namespace definition, in which case it points to a scope entry +that describes the contents of the namespace, and also for a namespace alias, +in which case it points to another namespace entry. + +Entries of type ``a_using_decl`` describe ``using-directive``\ s and +``using-declaration``\ s that appear in the source program. This +information is not needed for code generation, but may be useful in the +generation of symbolic debug information or for source-to-source +translation. + +Constants +========= + +``a_constant`` describes a target machine constant, which can be an integer, a +string, a fixed-point constant, a floating-point constant, a complex or +imaginary constant, an address, or a pointer-to-member. Nontype template +parameters and the UPC identifiers ``THREADS`` and ``MYTHREAD`` are also +represented using ``a_constant`` entries. The constants are kept in target +form, and should not be manipulated without using the target-specific routines +for that purpose. Fixed-point constants are stored as ``a_fixed_point_value``\ +s. Floating-point constants are stored as ``an_internal_float_value``. String +constants are stored as a string of bytes in the target character set with an +associated length (to avoid any question about extra or missing null characters +in the string). The text of string constants is always allocated in the file +scope memory region to avoid some memory region problems. + +Integers are usually maintained in a host large integer +(``a_host_large_integer``/``a_host_large_unsigned``) regardless of the size +or signedness of their actual integral type. They are always properly +masked and sign extended. If a host large integer is insufficiently large, +the front end can be configured to use a more general (but computationally +less efficient) representation of integer values (see the configuration +macro ``INTEGER_VALUE_REPR_IS_A_HOST_INTEGER``). In either case, +``an_integer_value`` is the type to use internally to represent an integer +constant. + +Constants are also used as initial values of variables. When those variables +are aggregates (arrays or classes), some special kinds of constant entries are +used to represent aggregates of constants and repetition of constants within +those aggregates. Such constants are acting more as a structuring entity than +as simple constants; it's just convenient to use the ``a_constant`` entry for +that function as well. Getting even farther afield, there is even a constant +kind (``ck_dynamic_init``) that indicates an element in an aggregate constant +that is in fact not a constant at all, and must be computed at run time and +placed at that position in the aggregate. The structure of the aggregate +constant will match the structure of the variable being initialized. For +example, the initial value for a variable whose type is "array of 4 structures +containing 2 integer fields" will be an aggregate constant containing a list of +four constants, each of those an aggregate constant containing a list of two +integer constants. Aggregate constants need not fully initialize an aggregate +(i.e., there may be fewer constants than there are members of the aggregate); +any members not explicitly initialized are implicitly initialized to zero (even +when the variable being initialized is non-static). + +Most constants, specifically those used in expressions, are shared and reused, +so that only one constant ``0``, for example, need be allocated. Constants +used as constant initial values, however, are (and must be) unshared. [#f5]_ +Since the aggregating kinds of constant entries are only used in initial +values, it follows that they are always unshared. In ``pcc`` mode, string +constants are considered writable and are not shared. + +In some cases, a program may include a cast of a constant value to another +type, and the result (clearly constant) may be unrepresentable in any of the +normal forms. An example is an integer constant cast to a pointer type. For +these situations, the ``a_constant`` entry has the ``implicit_cast`` field. +When set, it indicates that the value of the overall constant is to be the +constant value cast to the type indicated by the ``type`` field. The back end +must determine the exact value to be used. + +Address constants are used to refer to the addresses of variables, +functions, string literals, etc. The offset in address constants is +expressed in bytes and is not scaled by the size of the object pointed to +(unlike in the C and C++ languages). Address constants are only used for +addresses that are truly constant, not, for example, for the addresses of +``auto`` variables. Note, however, that the constant value may not be +known until link time, i.e., it might not be a compile-time constant. + +Pointer-to-member constants represent the location of a particular data member +or member function of a class within an arbitrary instance of that class, i.e., +what is written in source as something like ``&A::xx`` (with ``xx`` a nonstatic +member of ``A``). They are defined in a high-level form rather than (for +example) as an offset within the class, to leave it to IL lowering or the back +end to choose an implementation for pointers to members. + +Wide character constants are represented as integral constants. Wide string +literals are represented as string constants. There are routines in +``literals.c`` that do the necessary packing. + +When character or string literals contain a universal-character-name (e.g., +``\u00d6``), the UCN value is converted from Unicode to the appropriate +character value or multibyte character sequence and stored in the string. + +In C++/CLI, string literals start out as standard C++ string constants, and are +converted to C++/CLI strings if the context requires it. So, for example, if a +standard string literal is passed as an argument to a function that takes a +parameter of type "``System::String``\ ``^``", the string will be converted to +a C++/CLI string. This is done by setting the constant type to "handle to +``System::String``" without setting the ``implicit_cast`` flag. There is no +conversion of the characters in the string to Unicode (or in any other way), in +spite of what the ECMA standard seems to require. Wide string literals can +also be converted to C++/CLI strings in this way, and in that case the string +contents are treated as Unicode (as they always are in Microsoft mode, and +therefore in C++/CLI mode; but still no conversion is done). Having C++/CLI +strings represented as constants is a little strange, since ultimately they +have to result in creation of a class object on the heap, and use of its -- +non-constant -- address; however, MSVC treats such strings as constants, so +emulating the Microsoft compiler is easier when they are represented as +constants. It is left to back ends to transform these constants into +executable code as needed. + +The front end generally attempts to fold constant-expressions into a single +``a_constant`` node. The expression that led to the constant is also recorded +in the ``expr`` field in the ``a_constant`` entry. If this field is nonnull, +it points to the expression tree which produced the constant when folded; the +resulting constant is not shareable. + +Variables +========= + +``a_variable`` describes a variable, parameter, static data member, instance of +a variable template, temporary, or structured binding. It indicates the type +and storage class. The storage class can be ``sc_auto``, ``sc_register``, +``sc_static``, ``sc_extern`` (meaning a reference to an external variable +defined in another compilation), or ``sc_unspecified`` (meaning a definition of +a variable visible to other compilations). The storage class is standardized +during declaration processing. Parameter variables can only have storage +classes of ``sc_auto`` or ``sc_register``. File-scope and namespace scope +variables, instances of variable templates, and static data members can only +have storage classes of ``sc_static``, ``sc_extern``, or ``sc_unspecified``. +Function- and block-local variables can only have storage classes of +``sc_auto``, ``sc_register``, or ``sc_static``. + +Variables declared with a named-register storage class (an Embedded C +extension) have storage class ``sc_unspecified`` (not ``sc_register``) but also +have the flag ``has_named_register_storage_class`` set to TRUE. The register +is described using a small integer stored in the variant field +``asm_name_or_reg.id``, which can be used to index the array +``named_register_storage_classes``. This array is defined in ``targ_def.h`` +and can be customized to describe the named-register storage classes available +on a particular target. + +If the variable has an initial value, the field ``init_kind`` indicates whether +the variable should be statically initialized to a constant value (simple or +aggregate) or dynamically initialized to a constant or non-constant value +(simple or aggregate). In the dynamic initialization case, the variable points +to a dynamic initialization entry that indicates the initialization to be done. +(More on this below.) Note that static initialization is never used for +non-static local variables, even ones initialized with a constant value: static +initialization initializes the entity once, at program startup time, whereas an +automatic local variable must be initialized each time the function is invoked +and the variable declaration is reached. Structured bindings (a C++17 feature) +that refer to array elements or to fields are represented as variables, but +they are really aliases for simple expressions referring to parts of the +associated (unnamed) container variable. These bindings have an +``initk_binding`` initializer kind and point to the aliased expression via +``initializer.binding``. Structured bindings that bind to a +``std::tuple``-like container are ordinary reference variables with +``initk_dynamic`` initializers. + +An uninitialized static variable is considered to be implicitly initialized to +zero. There is also an ``initk_zero`` initialization kind, which can be used +to explicitly initialize a variable to zero, statically or dynamically. On an +external variable, such initialization has the added function of indicating +that the variable is a true definition rather than a tentative definition. + +If the address of the variable has been taken anywhere (implicitly by +conversion of an array to a pointer or in binding of a reference, or explicitly +by use of the ``&`` operator), the flag ``address_taken`` will be set. + +If a variable is a local static variable of a function, +``referenced_non_locally`` is TRUE if the variable is referenced from a +different function, specifically from a member function of a local class. This +may have an effect on aliasing analysis. + +Local static variables create a memory-region difficulty: the variable entry +must be allocated in the file scope memory region, because the variable can be +referenced from the bodies of member functions of local classes. Dynamic +initialization of the variable, however, can be based on an expression +referencing a local (nonstatic) variable of the function, and therefore the +dynamic initialization must be allocated in the function scope memory region. +The ``a_local_static_variable_init`` entry solves this problem. When a local +static variable has initialization that must be allocated in the function scope +memory region, the variable ``init_kind`` is set to ``initk_function_local``. +This is an indication that the variable is initialized, but details of the +initialization are not available in the file scope. In the function or block +scope in which the variable is defined, there will be +``a_local_static_variable_init`` entry on the ``local_static_variable_inits`` +list of the scope. That entry will point to the variable, and give the +initialization details. Conceptually, the initialization information in the +local initialization entry is part of the variable information (it provides the +true values for the ``init_kind`` and ``initializer`` fields of the variable); +it's in a different place because of memory region issues. The routine +``get_variable_initializer`` can be used to fetch the complete initializer +information for a variable. It will search for and retrieve the function-local +information when necessary. Local static variables with initial values that +are simple (non-aggregate) constants always use ``initk_static`` initialization +rather than the ``initk_function_local`` form. This is done so that the values +of integral constant variables can be retrieved as constants while compiling +local classes. ``initk_function_local`` is used for dynamic initialization and +for aggregate constant initialization. + +Temporary variables are generated by IL lowering, for class temporaries and +when initializing references. Temporary variables are also generated for +anonymous unions; see :ref:`anonymous-unions` for more information. + +.. _il-dynamic-init: + +Dynamic Initialization +====================== + +A dynamic initialization entry (type ``a_dynamic_init``) is used to represent +initializations that require the execution of code at runtime, i.e., that +cannot be done as static initializations to a constant. + +The ``kind`` field of the entry indicates the kind of initialization to be +done: + +* | Initialization to a constant. Note that this is different than static + initialization to a constant, in that it gets done at a particular time and + possibly more than once. The constant here is unshared and may be an + aggregate (one that is completely constant). +* | Initialization to an expression. An expression is evaluated and its value + is the initial value. +* | Initialization by a constructor. A constructor routine is called to + initialize the entity. +* | Initialization by a routine returning a class object. A routine is called + and the value it returns (by calling a copy constructor) initializes the + entity. + +A dynamic initialization entry can also indicate a destructor that must be +called to destroy the entity initialized. [#f6]_ Such dynamic +initialization entries will be linked onto the destructions list of an +object lifetime entry. The destruction is to be done any time the region +of the object lifetime is exited, and IL lowering generates the appropriate +destructions. See :ref:`object-lifetimes`. + +A dynamic initialization entry indicates *what* the initialization is to +do, but it does not indicate *where* the initialization is to be done +(except if the entity being initialized is a complete variable), and it +does not indicate *when* the initialization is to be done. Dynamic +initialization entries are used in several cases, and the context in each +case provides the additional information needed: + +* | For initialization of file-scope variables, instances of variable + templates, or static data members, the variable points to the dynamic + initialization entry, and the ``dynamic_inits`` list from the scope entry + for the file scope indicates the order in which the initializations should + be performed. Variables from namespaces also appear on this same list, + since their initializations are intermixed with those of the file-scope + variables. +* | For initialization of function and block variables, the variable points to + the dynamic initialization entry, and there is an ``stmk_init`` statement + in the executable code of the function that points to the same dynamic + initialization entry and indicates the point at which the initialization + should be done. An ``stmk_init`` statement can appear in the same block as + the variable declaration or in a nested block. If the variable is a local + static variable, the initialization is to be done only the first time the + ``stmk_init`` is reached, and corresponding end-of-program destruction must + be done only if the initialization was done. Note that if a local variable + uses dynamic initialization it *must* have an associated ``stmk_init`` + statement. +* | For initialization of temporaries in the middle of expressions, an + ``enk_temp_init`` node points to a dynamic initialization entry that + indicates the initialization to be done. +* | For initialization of storage allocated by ``new``, an ``enk_new_delete`` + node points to a dynamic initialization entry that indicates the + initialization to be done. These dynamic initialization entries never + indicate destruction. +* | For destruction of storage in a ``delete``, an ``enk_new_delete`` node + points to a dynamic initialization entry that indicates the destruction to + be done. These dynamic initialization entries never indicate + initialization. +* | For initialization of members in a constructor-initializer (either + user-written or front-end-generated), an entry of type + ``a_constructor_init`` indicates the member or base class to initialize and + points to a dynamic initialization entry to indicate what to do. The order + of the ``a_constructor_init`` entries gives the order in which the + initializations should be done. These dynamic initialization entries never + indicate destruction (except when exceptions are enabled, in which case the + destructions indicated are to be done if an exception is thrown before the + constructor completes). +* | Similarly, for destruction of members in a destructor (which can only be + front-end-generated), an entry of type ``a_constructor_init`` indicates the + member or base class to destroy and points to a dynamic initialization + entry to indicate what to do. The order of the ``a_constructor_init`` + entries gives the order in which the destruction should be done (i.e., if + one looks at a constructor and destructor for a class, the entries on the + destructor will be in the reverse order of those on the constructor). + These dynamic initialization entries never indicate initialization. +* | For non-static data member initializers (NSDMIs), more recently renamed + as default member initializers (DMIs), the field entry ``initializer`` + field points to a dynamic initialization entry giving the initializer. + If such an initialization is not overridden in a given constructor, the + ``a_constructor_init`` entry for the field will have + ``use_field_initializer`` TRUE to indicate that the initial value comes + from the field initializer. +* | For dynamic initialization of entities within an aggregate, for example + + .. code:: c++ + + int i[3] = {1, 2, j+k}; + + | dynamic initialization entries at two levels are needed. The variable + ``i`` will point to a dynamic initialization entry that indicates the + overall initialization. Because the initialization is an aggregate + initialization containing a non-constant value, the dynamic initialization + will have the kind ``dik_nonconstant_aggregate`` and will point to a + ``ck_aggregate`` constant. That constant points to a list of the constants + in the aggregate, beginning with the constants ``1`` and ``2``. Following + that is another constant entry of kind ``ck_dynamic_init`` which indicates + "this position in the aggregate is not really a constant; here's what needs + to be done to compute it" and points to another dynamic initialization + entry, this one of kind ``dik_expression`` and indicating that the value to + use for the initialization is the expression ``j+k``. + | + | Within the aggregate constant list, ``ck_init_repeat`` constants are used + to repeat a particular ``ck_dynamic_init`` initialization a specified + number of times. This is needed to do constructor initialization of arrays + of classes. + | + | In this aggregate case, the top-level dynamic initialization entry serves + as more of an aggregating construct than as a specification of a dynamic + initialization. It shouldn't come as much of a surprise, then, to learn + that to specify only destruction for an aggregate, one uses a top-level + ``dik_nonconstant_aggregate`` dynamic initialization entry as is done in + the initialization case, and the destruction is specified in the + lower-level dynamic initialization entry. The troublesome thing about this + form is that one cannot tell just by looking at the top-level dynamic + initialization whether the overall construct does initialization, + destruction, or both. One must find and examine the lower-level dynamic + initialization entry. +* | For returns from routines that return a class by value, the ``stmk_return`` + statement points to a dynamic initialization that indicates the way to + create the class being passed back to the caller. +* | For expressions that are operands of ``throw``, the ``throw`` expression + node points to a dynamic initialization that indicates the way to copy the + value for use by the runtime. +* | For parameters of ``catch`` clauses, the catch clause points to a dynamic + initialization that describes the way to initialize the parameter from the + runtime's copy of the thrown object. + +IL lowering rewrites all dynamic initializations that are not valid in C, and +therefore constructor and destructor calls and non-constant aggregates do not +appear in the lowered IL. + +.. _object-lifetimes: + +Object Lifetimes +================ + +In C++, class types can have associated destructors, which are called to +destroy objects of the class type at the ends of their lifetimes. These calls +are implicit: the programmer does not write them, and the compiler generates +them in the appropriate places. For example, on a ``goto`` out of a block +containing a class variable, the destructor for the variable must be called. +If there are several possible ways to exit the block (e.g., flowing off the +end, ``goto``\ s, exceptions), the destructor must be called in each case. + +The IL does not make the needed destructor calls explicit (in fact, for +exception handling, the needed destructor calls would be done by the runtime, +so there's no way to put them in the IL without dictating a particular +implementation of exception handling). Instead, it gives information about +needed destructions and the associated object lifetimes in such a way that a +back end can easily generate the required destructor calls. (IL lowering puts +in those calls, so a back end working from the lowered IL need not deal with +object lifetimes.) + +The IL concept of an "object lifetime" is modeled on a source language concept, +the idea that an object's lifetime (the time during which it has a meaningful +value) might be different than the lifetime of the storage for the object. +That is, the object is constructed, used, and destroyed, and then the storage +that contained the object might remain around for some time longer, but it no +longer contains meaningful information and is no longer an object. + +It should be noted that from an IL point of view, the concept of object +lifetime is only applied to objects of class types having destructors. From a +strict language point of view, other kinds of objects do have object lifetimes, +but those object lifetimes are not very interesting because they always match +the lifetime of the object storage; more precisely, in the absence of a +destructor there is no way to tell the difference between an object whose +lifetime has ended and one that is still active, as long as the storage remains +allocated to the entity. Therefore there is no benefit in associating IL +object lifetimes with entities that do not need destruction, and there *is* a +benefit -- space savings -- in not doing so. Note that this means that IL for +C programs, which by definition involve no constructors, never includes object +lifetimes. + +The IL entry ``an_object_lifetime`` represents and defines an object lifetime. +There are several kinds of object lifetimes, each associated with a certain +kind of entity in the IL: [#f7]_ + +* | A static object lifetime, which lasts until the termination of the program. + For packaging reasons, there is a global static object lifetime and + possibly several function static object lifetimes (one for each function + that contains destructible local static entities). Such lifetimes are + bound to the file scope and function scopes. +* | A block object lifetime, which lasts until the termination of a function or + block scope. Such a lifetime is bound to a function or block scope. There + is also a variant of this kind of lifetime, referred to as a + block-after-label lifetime, that lasts from a label or (in + long-lifetime-temporaries mode) a switch case or default label to the end + of the scope. The block-after-label lifetime points to a statement that is + or contains a label or to a ``stmk_switch_case`` statement, respectively. +* | A try-block object lifetime, which surrounds the execution of a ``try`` + statement and its associated ``catch`` clauses, and is bound to a + try-supplement. +* | An expression temporary object lifetime, which lasts until the end of a + full expression, and is bound to an expression node of kind + ``enk_object_lifetime``, or to a dynamic initialization entry. + +Each dynamic initialization in the IL that requires end-of-lifetime destruction +is placed on the linked list of destructions attached to the proper object +lifetime entry. The destructions in a given lifetime are linked together by +the ``next_in_destruction_list`` pointer, in the order in which they should be +destroyed (that is, the reverse of the order of construction). The +``destructions`` pointer in the object lifetime entry points to the first +initialization on the list (the last one constructed and the first one to be +destroyed). + +Not all dynamic initializations are placed on a lifetime list. Initializations +of nonclass objects, or objects of class types that have no destructors, +clearly do not need to go on lifetime lists. Even initializations of objects +of class types with destructors are put on lifetime lists only if the +destruction of the object is automatic at the end of the lifetime, e.g., not +for ``new`` (the programmer controls the time of destruction) or ``return`` by +constructor (the destruction is done by the caller, not the subroutine). + +Each object lifetime has a ``parent_lifetime`` pointer, and also a +``parent_destruction_sublist`` pointer giving the position of the child +lifetime relative to the destructions in the parent. This makes a tree +structure that one can enter at some inner lifetime and follow upward. The +path upward from a given starting point is referred to as the "cleanup chain" +starting at that point. For example: + +.. code:: c++ + + struct A { A(); ~A(); }; + void () { // Lifetime 1 associated with this block + A x; + A y; + { // Lifetime 2 associated with this block + A xx; + // Position R + A yy; + } + A z; + } + +Lifetime 1 has the destructions list ``(z, y, x)`` and lifetime 2 has the +destructions list ``(yy, xx)``. Lifetime 2's ``parent_lifetime`` pointer +points to lifetime 1, and its ``parent_destruction_sublist`` pointer points to +the initialization entry for ``y``. + +One can see that if a ``return`` statement appeared at position R above, one +would want to destroy ``xx`` from the inner lifetime and ``y`` and ``x`` from +the outer lifetime. How would a back end figure that out? Well, as the back +end processes the IL, it would keep track of the latest +initialization-with-destruction encountered, i.e., the one for ``xx`` when at +position R. The pointer to that initialization defines the cleanup chain that +applies at position R. Starting with that initialization, the back end would +follow the ``next_in_destruction`` list to the end, generating destructions for +the entities on that list. Then, using the ``lifetime`` pointer in the last +dynamic initialization and the ``parent_lifetime`` pointer in the lifetime +pointed to, it would go to the parent lifetime, entering its destructions list +at the point indicated by ``parent_destruction_sublist``. It would then +generate destructions for the entities on that list. The process would +continue upward through parent lifetimes until the lifetime for the function is +processed. + +Generating destructions at a ``goto`` is almost as easy. The ``goto`` +statement has a ``common_lifetime`` field set by the front end. It indicates +the first object lifetime that the ``goto`` and the label have in common, that +is, the innermost object lifetime that appears on the cleanup chains for both +the goto and the label. The destructions for the ``goto`` are generated by +working upward through the cleanup chain, as for the ``return`` case, except +that processing stops when the common lifetime is reached (before generating +any destructions in that lifetime; if the ``goto`` is directly in the common +lifetime, then no destructions are generated). + +When labels appear, and are followed by declarations for destructible objects, +a new block-after-label lifetime is begun at the label. This is necessary for +backwards ``goto``\ s: + +.. code:: c++ + + struct A { A(); ~A(); }; + void () { // Lifetime 1 begins + A x; + L:; // Lifetime 2 begins after label + A y; + if (i) goto L; + } + +The destruction of ``x`` will be in lifetime 1, and the destruction of ``y`` +will be in lifetime 2. The ``goto`` is in lifetime 2, and the label is in +lifetime 1 (the parent of lifetime 2), so the common lifetime for the ``goto`` +is lifetime 1. The cleanup code at the ``goto`` therefore destroys ``y`` as it +exits lifetime 2, but it does not destroy ``x``. + +Switch case labels are treated like other labels and can begin new object +lifetimes if necessary. The labels generated for ``break`` and ``continue`` +statements do not ever begin new lifetimes. + +Destructible temporaries are treated much the same way as destructible +variables, and their initializations are likewise placed on lifetime lists. In +its choice of which lifetime to use in each case, the front end represents its +decisions on the lifetimes of temporaries. For example, when a reference +variable is bound to a temporary, the C++ language dictates that the lifetime +of the temporary is extended to match the lifetime of the reference (e.g., for +a static reference the temporary lasts until the end of the program). The +front end would represent this in the IL by placing the temporary on the same +lifetime as the reference variable. + +In the modern C++ language, normal temporaries last until the end of the full +expression within which they occur. In the front end, this is represented by +placing an expr-temporary lifetime around the full expression and placing the +destructions of any temporaries therein. In older dialects of C++, however, +including the dialect implemented by cfront, temporaries lasted until end of +scope. This mode is implemented by the EDG C++ front end in cfront +compatibility mode and when ``--long_lifetime_temps`` is specified. To be more +precise, in long-lifetime-temporaries mode temporaries survive until end of +scope or until a label, and they are limited to a single statement when the +statement is a conditional dependent statement, or to a full expression when +the expression is the tested expression in a conditional or loop statement, or +the initializer for a local static variable. Since long-lifetime temporaries +are destroyed at a label, when walking a cleanup chain and going from a +block-after-label lifetime to its parent one should ignore destructions for +temporaries until one reaches and exits from a block lifetime (all temporaries +in the block lifetime and any intervening block-after-label lifetimes were +destroyed at some label, and are no longer active). Because of the destruction +of temporaries at labels, in this mode block-after-label lifetimes are required +at some labels even when there are no destructible objects created after the +label. + +In addition to its use in generating destructions on programmed exit from +lifetimes, the block object lifetime information is also intended to be useful +in generating the cleanup description information needed by the runtime support +for exception handling. With the default configuration, IL lowering will use +the object lifetime information to generate data structures that support EDG's +implementation of exception handling. Those who wish to create a +higher-performance version of exception handling may find it useful to turn off +lowering of exception handling features and to use the object lifetime +information directly in the back end to generate the required cleanup +information. In either case, because the object lifetime information is used +to generate exception handling information, it includes some information beyond +what is required to generate cleanup on block exits: + +* | There is information about the mem-initializers (both user-written and + front-end-generated) in constructors, and about the similar + (front-end-generated) data structure in destructors. +* | For each ``new`` that does allocation inline (rather than letting a + constructor do it), a dynamic initialization entry is generated to indicate + the freeing of the storage to be done if an exception is thrown before the + storage is fully initialized. +* | For local static variables, a block object lifetime is placed around the + entire initialization and bound to the local static variable initialization + IL entry. Exiting this lifetime via an exception causes the runtime to + reset the state so that the local variable is marked as uninitialized. If + its declaration is encountered again on a subsequent call, the + initialization will be attempted anew. +* | For aggregate classes or arrays initialized by a brace-enclosed list, + individual sub-initializations will indicate destructions to be done if an + exception is thrown before the complete aggregate is initialized. Once the + aggregate has been completely initialized, these destructions to undo + partial construction no longer apply. + +One of the unfortunate consequences of using dynamic initialization entries to +represent destructions is that the contextual nature of dynamic initialization +entries (they don't indicate the entity to be initialized; it's implied by the +context) -- which is an advantage when the entries are used to do +initializations -- is somewhat of a disadvantage when the entries are used to +do destructions. Specifically, unless one saves some information in the +dynamic initialization entry at the time it is processed as an initialization, +it is very hard to know what to destroy when one processes it as a destruction. +However, it's not hard to solve this problem from a practical point of view: +one just adds a field to the dynamic initialization entry to point to +back-end-specific information recorded at the time that the initialization is +processed, and that information is then available, and in just the right form, +when the destruction is processed. That's the technique used by IL lowering. + +Routines +======== + +``a_routine`` describes a function. It indicates the type and storage class. +The storage class can be ``sc_static``, ``sc_extern`` (meaning a reference to a +function defined in another compilation), or ``sc_unspecified`` (meaning a +definition of a function visible to other compilations). The storage class is +standardized during declaration processing. A function with a body will have +storage class ``sc_unspecified`` or ``sc_static``; a function without a body +will have storage class ``sc_extern``. + +The type of a function is always a function type, which describes the +external interface to the function: its return type, its parameter types, +etc. A nonstatic member function will also have an implicit "``this``" +parameter, with a type of ``const`` pointer-to (possibly qualified) class. +The parameter types might have associated default argument value +expressions, although that information is useful to a back end only for +generation of symbolic debugging information, since calls of the routine +will have the default argument values supplied. + +The routine entry also indicates whether or not the routine is inline, virtual, +and/or front-end-generated. (The front end generates routines for constructors +and destructors, assignment operator functions, and, when IL lowering is done, +for global initialization and termination routines, runtime routines, and +wrappers for constructors with default arguments.) The ``special_kind`` field +indicates whether or not the function is a C++ special function such as a +constructor. If the ``special_kind`` indicates that the routine is an operator +function, ``opname_kind`` indicates the kind of operator function it is. The +``special_kind`` is significant to a back end using the unlowered C++ +intermediate code in that wrapper code needs to be generated for constructors +and destructors. Other than that, ``special_kind`` and ``opname_kind`` are +mostly of interest for generating symbolic debugging information and mangled +names. + +The routine entry points to a list of classes that have befriended the +function. Those classes will have the function on their friend lists. + +If the function is a virtual function, the routine entry indicates a virtual +function number assigned to the routine. Typically, this will be used as the +function's index into a virtual function table, but since the unlowered C++ IL +leaves virtual function access as an abstraction, it's only a helpful +identifying number at that level. + +If the function has a body, the routine entry indicates the function +definition number and the memory region that contains the function +definition. By indexing through ``il_header.function_def_table``, one can +get to the scope entry for the function (in the proper function scope +memory region). That scope entry points to the statements and local +declarations of the function. It also points to variables for the +parameters of the function, including a "``this``" parameter variable if +necessary. The parameter and "``this``" variables will match the parameter +and "``this``" types in the function type. (In non-prototyped functions, the +function type parameters might be promoted versions of the parameter +variable types.) For parameters that are passed using a copy constructor +(indicated by a flag in the parameter type entry), a back end using the +unlowered C++ IL may have to expect to receive the address of the class +entity rather than its value, and to do implicit indirections on the +references to the parameter. + +The ``address_taken`` flag in the routine entry will be set if the address of +the function has been taken. Merely calling the function does not cause the +``address_taken`` flag to be set, even though the IL for a call refers to the +routine address. + +An exception specification that appears on a function declaration is +represented by an entry of type ``an_exception_specification``, referred to +by means of the ``exception_specification`` field of the routine type +supplement. When the function is declared with no exception specification +(meaning that *any* exception might be thrown) the +``exception_specification`` pointer will be NULL. The exception +specification entry representing a dynamic exception specification has a +pointer to a linked list of entries of type +``an_exception_specification_type``, each of which indicates a type of +exception that will be thrown from the given routine; that pointer is NULL +to indicate that *no* exceptions will be thrown. An exception +specification representing a ``noexcept`` specification points to an entry +of type ``a_constant`` representing its operand (or NULL if no operand is +specified). + +When ``ASM_FUNCTION_ALLOWED`` is TRUE, ``asm`` functions are recognized and +passed uninterpreted to the back end. They are represented in the IL like +ordinary functions, except that they have a storage class of ``sc_asm`` and the +function body (pointed to from the associated scope entry) is represented by an +``stmk_asm`` statement. The asm entry to which the latter refers points is a +null-terminated string containing the text that appeared in the source; +comments are removed unless ``INCLUDE_COMMENTS_IN_ASM_FUNC_BODY`` is TRUE. + +In order to save space in the ``a_routine`` structure, some (mostly +GNU-specific) fields with default values that are rarely changed are located in +the ``a_gnu_routine_supplement`` struct, which is pointed to by the +``gnu_extra_info`` field. This supplement is only allocated when one of the +fields has a non-default value. + +The GNU function multiversioning feature (available in GNU C++ modes where +``gnu_version`` >= 40800), allows for declarations/definitions of multiple +routines with the same signature but with different ``target`` attributes. The +``target`` attributes specify which CPU architecture is applicable for each of +the functions in the group. Internally, the entire group of functions is +represented by a "representative" function (whose ``is_representative`` field +is TRUE). All target-specific functions are have the +``is_target_specific`` field set to TRUE and are queued on the +``mv_info.representative.targeted_versions`` list. Although each of the +routines (both representative and target-specific) have associated symbols, +only the symbol for the representative routine is entered into the symbol +table. This feature is controlled by the ``GNU_FUNCTION_MULTIVERSIONING`` +configuration macro. + +Constructors and Destructors +============================ + +Constructor and destructor routines must do additional processing beyond what +appears in the body of the routine. Since this processing surrounds the code +in the definition of the routine, it is called "wrapper" code. + +Some of the wrapper code is implicit: there must be code that initializes +the information in the class used to access virtual base classes and +virtual functions (typically, virtual base class pointers and virtual +function table pointers). The wrapper code must also control whether or +not virtual base classes are initialized or destroyed (they should be for a +complete object, but not for a subobject). If a ``new`` or ``delete`` +operation can be folded into a constructor or destructor (a configuration +option, but always true if assignment to "``this``" is supported), the +wrapper code may have to provide for calling a ``new`` or ``delete`` +routine. + +The wrapper code must also do any necessary initialization or destruction for +base classes and members. The required actions are described explicitly by a +list of ``a_constructor_init`` entries which indicate the initialization or +destruction to be done, in the correct order. If the source program contains +constructor-initializer clauses, they will appear on the list in the right +positions. For any base class or member that requires initialization and for +which the source does not provide an initializer, a default initializer is +generated. In a front-end-generated copy constructor, the default +"initialization" will in fact be a copy. In a destructor, there is no source +construct for indicating specific destruction for base classes and members, so +the list is always front-end-generated in its entirety. It is also in the +correct order, i.e., the reverse of the order in the corresponding constructor +list. + +IL lowering modifies constructor and destructors to provide all the necessary +wrapper code. + +Calls of "destructors" for classes that do not have them or for simple types, +as in + +.. code:: c++ + + p->int::~int(); + +are rendered as ``eok_dot_vacuous_destructor_call`` or +``eok_points_to_vacuous_destructor_call`` expression nodes in the IL. No +routine entry is created for the ersatz destructor. Such nodes are rewritten +as casts to ``void`` in IL lowering. + +Labels +====== + +``a_label`` is a declarative entity that describes a label (user-written or +front-end-generated) in a function. It is pointed to by the ``goto`` and label +definition statements in the executable code of the function. + +``asm`` Statements +================== + +An ``asm`` statement (or declaration, whichever way you care to look at them) +can appear in two contexts: + +* | Within the bodies of functions, where it is considered to be executable + code and is represented by an ``stmk_asm`` statement pointing to + ``an_asm_entry`` that gives the ``asm`` statement string. +* | At file or namespace scope, where it is considered to be a declaration and + is represented as ``an_asm_entry`` on a list of such entries attached to + the file or namespace scope ``a_scope`` entry. If such ``asm`` + declarations are supposed to affect declarations that immediately follow + them, the back end must consider the source positions of variables, + routines, and ``asm`` entries and do a merge of those lists. + +Statements +========== + +``a_statement`` describes a statement, which can be an expression, an ``if``, a +``while``, a ``do``-``while``, a ``for``, a ``switch``, a ``goto``, a +``break``, a ``continue``, a label definition, a ``return``, a block (with or +without an associated scope), a ``try`` block, or a declaration statement. + +The representation of ``switch`` statements (``stmk_switch``) matches the +language definition, but the ``case`` and ``default`` labels are represented +using a separate statement entry kind ``stmk_switch_case``. Each +``stmk_switch_case`` entry points to an entry of type ``a_switch_case_entry`` +(which describes the label's value, among other things). An ``stmk_switch`` +statement points to a list of all switch case entries associated with that +statement (via an entry of type ``a_switch_stmt_descr``). A list of switch +case entries in sorted order of label value is usually also available (this +list excludes the ``default`` case), but not if any of the cases is +template-dependent. ``break`` statements to transfer out of a ``switch`` +statement are ``stmk_goto`` statements pointing to a label entry whose +``switch_break_label`` flag is TRUE. + +The ``stmk_init`` statement indicates the point in a sequence of executable +statements where the dynamic initialization of a variable should be done. It +points to the same dynamic initialization entry that the variable does. This +is particularly useful in C++ where variables can be declared and initialized +in the middle of a block. + +The ``stmk_block`` statement is used both for a simple compound statement and +for a block (i.e., a compound statement containing local declarations). The +``a_block`` entry pointed to from the statement indicates whether or not the +block has an associated scope. In C++, a block statement is always generated +for the dependent statement of conditionals (e.g., ``if``), even if no ``{ }`` +are present. However, the block will not have an associated scope unless +something is actually declared inside the block. + +The ``stmk_try_block`` statement is used to represent a ``try`` block. It +points to a compound statement block and a linked list of handlers. The latter +are entries of type ``a_handler``; each points to a (possibly unnamed) +parameter (the local variable to which the thrown object will be copied when +the handler is invoked) and to an ``stmk_block`` statement, the body of the +handler; for a default handler (i.e., the ``catch(...)`` case) the parameter +pointer in the handler entry is NULL. + +The ``stmk_decl`` statement is used to represent a declaration statement. This +could be the declaration of one or more variables and/or functions (using one +of more comma-separated declarators), one or more typedef types, a local class +or enum type, a using-declaration, etc. + +The C++/CLI "for each" statement is represented by an ``stmk_for_each`` +statement. Its representation includes an indication of which "pattern" the +loop matches (the CLI collection pattern, the CLI array pattern, the STL +pattern, or the native array pattern), and for each of those patterns +expressions that give the worked-out expansion for the pieces of the loop, so +that a code-generating back end does not need to figure out the expansion. + +When support for variable length arrays is enabled, two additional statements +may appear. + +* | An ``stmk_set_vla_size`` statement is associated with a VLA declaration and + indicates exactly where the dimension expression for a VLA should be + evaluated. +* | An ``stmk_vla_decl`` statement will refer to a variable of variably + modified type or to a ``tk_typeref`` type to indicate the location of the + corresponding variable or ``typedef`` declaration. This is generally + important because a VLA type has run-time dependencies that need to be + honored. Moreover, when the variable referred by an ``stmk_vla_decl`` + statement has a VLA type (not just a type that "contains" a VLA type), the + ``stmk_vla_decl`` statement indicates the point at which the storage for + the variable should be allocated. Note that a single ``stmk_vla_decl`` + statement may be preceded by multiple ``stmk_set_vla_size`` statements if + the type associated with the ``stmk_vla_decl`` statement has multiple + variable-length dimensions. (See also :ref:`il-types` and + :ref:`il-operation-exprs`.) In C modes, expression statements with a single + node of kind ``enk_vla_dealloc`` (see also :ref:`il-vla-dealloc`) may be + generated to indicate the point at which a variable of VLA type should be + deallocated (e.g., preceding a ``goto`` out of a scope containing a VLA + variable). Such deallocation constructs are generated only when + ``VLA_DEALLOCATIONS_IN_IL`` is TRUE. + +Note that variable-length array types can also appear in ``sizeof`` +expressions. None of the above statement kinds are generated for those cases +since statements cannot in general appear within expressions. Instead, such +expressions result in ``enk_sizeof`` expression nodes. Back ends can find and +examine the ``a_vla_dimension`` entries associated with such nodes to evaluate +the result of the ``sizeof`` expression. + +.. _src-seq-lists: + +Source Sequence Lists +===================== + +When ``GENERATE_SOURCE_SEQUENCE_LISTS`` is TRUE, lists of +``a_source_sequence_entry`` are generated, ordered strictly according to +the order in the source program. This is useful for applications that care +about the exact order of declarations, redeclarations, and definitions in +the source code, e.g., source analysis applications. Each list entry +represents a declaration, a statement, a macro, a pragma, a template, or a +template specialization that represents an instantiation (if either of the +deprecated configuration macros +``CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS`` or +``NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS`` is TRUE). +Those entities representing declarations and statements point to the +corresponding IL entry, and the latter have pointers back (fields +``source_sequence_entry`` in ``a_source_correspondence`` and in +``a_statement``). + +The lists appear in the IL via the ``source_sequence_list`` pointer in +``a_scope`` entries for the file scope and for each function scope. (The +pointer will always be NULL for other scope kinds.) Source sequence entries +themselves have both forward and backward pointers to facilitate list traversal +and management. + +Logically, there is a single source-sequence list in a translation unit. +Actually, however, a number of lists may be involved. The file-scope +source-sequence list is pointed to from the scope entry for the file scope, but +when a function definition appears, another list, pointed to from the scope +entry for the function, is produced. The logical successor of the +source-sequence entry for the function (which is in the file-scope list) is the +first entry on the function-scope list, and the logical successor of the last +entry on the function-scope list is the entry pointed to by the ``next`` +pointer of the function's source-sequence entry. + +The reason for representing the logically continuous source-sequence list by +many discontinuous lists is that source-sequence entries appear in different +memory regions, just as the IL entries they point to do. Thus, the entries on +the file-scope source-sequence list are allocated in the file-scope memory +region, but the entries on a function-scope source-sequence list are usually +allocated in the memory region of that particular function. + +Some declarations within a function, however, create entities that are +allocated at file scope. This is the case for types, static variables, and +variables and functions declared ``extern``. The source-sequence entries for +such entries must also be in the file-scope memory region, but that means they +cannot be on the same linked list with entries allocated in the function-scope +memory region. Therefore, additional side branches are used: entries of type +``a_src_seq_sublist`` ("sublist headers") establish such branches by pointing +to the head and tail of a list of file-scope source-sequence entries that are +logically within the source-sequence list of the function scope. + +The sublist headers for a given function, as well as being pointed to by +entries ("sublist parents") in the function-scope source-sequence list, are +also chained together; the head of the linked list is pointed to by +``src_seq_sublist_list`` in the function's scope entry, and its tail is pointed +to by ``last_src_seq_sublist`` in the corresponding scope stack entry. + +Entries of type ``a_src_seq_end_of_construct`` are inserted into the +source-sequence list to mark the point at which certain constructs terminate +(the entries point back to the associated IL entry). This includes class and +enum definitions and statement blocks. Such entries are also used to mark the +end of a set of source sequence entries for constructs embedded in a variable +or function declaration. For example, in: + +.. code:: c++ + + int x[sizeof(struct S { int i; })]; + +(which is accepted in some modes only), the source sequence list contains an +entry for the definition of variable ``x``, followed by entries for the +definition of struct ``S``, followed by an entry marking the end-of-construct +of variable ``x``\ 's definition. An end-of-construct marker is similarly used +to mark the appearance of the "``while (...)``" part of a do-while statement +(this is, e.g., significant to be able to record whether a pragma appeared +before the statement as a whole, or just before the ``while`` keyword). + +When a declaration is not a definition (e.g., a function declaration with no +body or a variable declared ``extern``), it is represented by an entity of type +``a_src_seq_secondary_decl``, which is pointed to by the source-sequence entry +and points in turn to the corresponding IL entry. Therefore, when an entity +has more than one declaration, multiple source-sequence entries are created, +but only the one that represents the definition points directly to the IL +entry; the others point to secondary declaration entries. If there is no +definition of the entity in the compilation, all of the source sequence entries +for that entity will be secondary declarations. + +(Source sequence lists are not actually added to the IL tree until +``pop_scope`` is called for a function scope or the file scope. During front +end processing, the source sequence lists as described above are assembled from +smaller lists that are managed on a per-scope basis; whenever a scope stack +entry is popped, its list is typically merged into the list of the immediately +enclosing scope. Moreover, the source sequence list describing a function +definition may temporarily be a simple linked list containing a mix of entries +from the memory regions of the function scope and the file scope; the +representation involving sublist headers, as described above, is produced by a +fixup pass when the function scope is popped.) + +Many implementations will not need the kind of information provided by +source-sequence lists and will choose to avoid the processing overhead and +especially the memory overhead they introduce. By default, therefore, +``GENERATE_SOURCE_SEQUENCE_LISTS`` (defined in ``host_envir.h``) is set to +FALSE. + +Expressions +=========== + +``an_expr_node`` describes an expression node, which can be an operator node, a +reference to a constant, variable, or function, an initialization of a +temporary, or a few other things like ``new`` or ``delete``. + +Each expression node has a type, indicated by its ``type`` field. + +The simplest expression nodes are leaf nodes. The most common leaf node kind +are: + +* | ``enk_variable`` refers to a variable. +* | ``enk_routine`` refers to a function. +* | ``enk_constant`` refers to a constant. +* | ``enk_field`` refers to a field. + +Lvalues and Rvalues (Value Categories) +-------------------------------------- + +Each expression node has an ``is_lvalue`` flag, which is TRUE if the node +represents an lvalue and FALSE if it represents an rvalue. (It is also TRUE +for what is called a function designator in C, which is simply called an lvalue +in C++.) + +So, an ``enk_variable`` node with ``is_lvalue`` TRUE indicates an lvalue for +the variable, and the same node with ``is_lvalue`` FALSE indicates an rvalue +for the variable, i.e., the value of the variable. In the statement + +.. code:: c++ + + i = j; + +the left operand would have ``is_lvalue`` TRUE and the right operand would have +``is_lvalue`` FALSE. + +Similarly, an ``enk_routine`` with ``is_lvalue`` is TRUE indicates an lvalue +for the function (which has a function type), and one with ``is_lvalue`` FALSE +indicates an rvalue for the function (which is the address of the function, and +has pointer-to-function type). + +``enk_constant`` nodes are usually rvalues, representing the value of an +indicated constant. The one exception is that an ``enk_constant`` for a +string constant (``ck_string``) can be an lvalue for the string. + +C++11 adds the concept of "xvalues," which are eXpiring values produced by +certain rvalue reference operations. They are indicated by the ``is_xvalue`` +flag in the node being TRUE (``is_lvalue`` and ``is_xvalue`` are never both +TRUE). Lvalues and xvalues are collectively called "glvalues." The things that +were called "rvalues" in pre-C++11 C++ and in C are known in C++11 as +"prvalues," and the term "rvalue" becomes a collective term for prvalues plus +xvalues. [#f8]_ In the IL, xvalues in general can be viewed as funny versions +of lvalues. + +Glvalue nodes shouldn't be considered to have values. They're just a +description of an object in memory. Because they don't have values, they also +can't be considered to be constant or to have constant values, though some +lvalues will have constant addresses (see ``constant_glvalue_address``). + +When a glvalue with a cv-qualified type is converted to a prvalue, the type +qualifiers are dropped (except for class-typed prvalues in C++). In the IL, +this is reflected in the fact that the expression node for the prvalue will +have the unqualified type. When an lvalue with a function type is converted to +a prvalue, its type becomes pointer-to-function. + +Clearing the ``is_lvalue`` flag in an expression node where initially the flag +would be expected to be TRUE indicates a fetch from memory. This is obvious on +the ``enk_variable`` node, but it also applies to many other nodes, such as +field selection and subscripting operators. Nodes that can be made to include +a fetch merely by clearing the ``is_lvalue`` flag (or, similarly, the +``is_xvalue`` flag) are referred to as "rvalueable". One can test for the +presence of an implicit fetch (also known as an lvalue-to-rvalue conversion) in +an expression node by calling ``node_includes_glvalue_to_prvalue_conv``. + +.. _il-operation-exprs: + +Operation Expressions +--------------------- + +Expression nodes of kind ``enk_operation`` are operations. They are the +non-leaf nodes of expression trees, the ones that apply an operator to a set of +operands, to do operations like ``i+j``. + +The operands of an operation are linked together as a list, and the operation +node points to the first expression on the list. + +Most operations take a fixed number of operands. The various forms of calls +are exceptions and take a variable number of operands. + +The operator kind (addition, assignment, call, etc.) is described by the +``variant.operation.kind`` field, which is mostly independent of the type of +the operands. For example, an addition is described with kind ``eok_add`` +independently of the operand type. There are a few exceptions to this when the +semantics of the operation vary sufficiently from the generic case to warrant a +separate operator. For example, pointer arithmetic uses dedicated operators +``eok_padd``, ``eok_psubtract``, and ``eok_pdiff`` instead of the generic +``eok_add`` and ``eok_subtract``. Where applicable, an additional field +``variant.operation.type_kind`` describes the class of types an operation acts +on. For example, this will be ``tk_float`` for the multiplication of two +floating-point values, or ``tk_template_param`` for a multiplication involving +a template-dependent operand. For operations that don't apply to a particular +type kind (e.g., ``eok_call``), the ``type_kind`` field is set to +``tk_unknown``. The ``type_kind`` field is set automatically when calling +``make_operator_node`` or ``set_node_operator`` (it is ultimately computed by +``operation_type_kind``). + +In the case of scalar controlling expressions, the several different cases +(integer, float, and pointer) are reduced to a single case (integer) by +standardizing the expression. Specifically, for the expression of a +``stmk_if``, ``stmk_while``, ``stmk_end_test_while``, or ``stmk_for``, and for +the controlling operands of the ``eok_not``, ``eok_land``, ``eok_lor``, and +``eok_question`` operators, the expression will always be either an integer +constant ``0`` or ``1``, or an expression whose top operator is defined to +yield a ``0`` or ``1`` result. Where necessary, a constant value will be +standardized (e.g., ``5.3`` will be changed to ``1``), or a ``!= 0`` operation +of the proper type (integer, float, or pointer) will be added to the top of the +expression. + +The operands of an expression may be evaluated in any order consistent with +the C and C++ "as-if" rule. By default, parentheses are not directly +represented in the IL; their effect is simply reflected in the operands of +the operators in the expression tree or, in cases where they have semantic +implications, by flags in various IL entries (e.g., +``an_expr_node::is_parenthesized``). Applications that need to be aware of +source-level parentheses can set the ``PARENS_IN_IL`` configuration option; +see :ref:`parentheses`. + +In general, operator nodes that do not correspond directly to something that +appeared in the source, and were added by the front end, are marked by having +``compiler_generated`` set to true. + +Addressing operators +-------------------- + +There are several addressing operators (note that when we refer to ``eok_...`` +names we mean those under the ``enk_operation`` expression variant): + +* | ``eok_address_of`` is the "``&``" operator. Its operand is an lvalue, and + its result is a prvalue of pointer type that is the address of the lvalue. +* | ``eok_indirect`` is the "``*``" operator. Its operand is a prvalue + pointer, and its result is an lvalue that is the object pointed to. It + is rvalueable. +* | ``eok_array_to_pointer`` converts its operand, an array (lvalue, xvalue, or + prvalue), to a prvalue pointer to the first element of the array. + +The "restrict" qualifier on pointers, originally introduced in C99, is a type +qualifier on pointer types that indicates that they can be considered to be +unaliased (nothing else in scope points at what they point at). The function +``node_is_pointer_with_restrict_semantics`` can be used to test an expression +node that is a pointer (e.g., the operand of an ``eok_indirect`` operation) to +see whether it has the "restrict" semantics. + +References +---------- + +References are not pointers, but they are treated as somewhat pointer-like in +the IL, with their own versions of the addressing operators: + +* | ``eok_reference_to`` is the reference version of "``&``". Its operand is a + glvalue, and its result is a prvalue of reference type that is the + "address" of (reference to) the glvalue. Its operand can also be a class + prvalue, in which case its result is the "address" of the underlying class + object. +* | ``eok_ref_indirect`` is the reference version of "``*``". Its operand is a + prvalue with reference type, and its result is an lvalue that is the object + referenced. It is rvalueable. + +These operators do not, of course, appear in the source code; they are added by +the front end where needed. No operations are allowed on references other than +the above, or storing a reference somewhere, or passing it as an argument. + +An example: for something like + +.. code:: c++ + + int i; + int &r = i; + r = r; + +the left operand of the assignment is an ``eok_ref_indirect`` with +``is_lvalue`` TRUE over an ``enk_variable`` for ``r`` with ``is_lvalue`` FALSE, +and the right operand is an ``eok_ref_indirect`` with ``is_lvalue`` FALSE over +an ``enk_variable`` for ``r`` with ``is_lvalue`` FALSE. + +Note that reference type values are typically dealt with as prvalues, in the +same way that pointers are. In the example above, the ``enk_variable`` for +``r`` is effectively fetching the pointer-like value stored in the reference +variable, so its ``is_lvalue`` flag is FALSE. An ``enk_variable`` node with +``is_lvalue`` TRUE for a reference variable would mean an lvalue for the cell +containing the reference value, but there's no real use for that in the C++ +language, since you can't take the address of the cell nor can you change its +value after initialization. + +Address constants with kind ``ck_address`` can have reference type when they +are used to initialize a reference-typed variable. They represent a constant +reference value. + +Rvalue references (source form like "``int``\ ``&&r``") are similar to the +traditional "lvalue" references. ``eok_reference_to`` and ``eok_ref_indirect`` +can be used with them also, and ``ck_address`` constants can have rvalue +reference type. An rvalue reference is always bound to an rvalue (i.e., an +xvalue or prvalue). See :ref:`casts` for information on casts to +rvalue reference types. + +Field Selection +--------------- + +There are several operators that implement field selection: + +* | ``eok_dot_field`` is the "``.``" operator. The left operand is a class + glvalue or prvalue, the right operand is an ``enk_field``, and the result + is a glvalue or prvalue of the type of the selected field (with + cv-qualifier adjustment). When the left operand is an lvalue, the result + is an lvalue (rvalueable), and similarly for an xvalue. When the left + operand is a prvalue, the result is a prvalue. +* | ``eok_points_to_field`` is the "``->``" operator. The left operand is a + prvalue pointer to class, the right operand is an ``enk_field``, and the + result is an lvalue (rvalueable) of the type of the selected field (with + cv-qualifier adjustment). +* | ``eok_pm_field`` is the "``.*``" operator. The left operand is a class + glvalue or prvalue, the right operand is a pointer to data member, and the + result is a glvalue or prvalue of the type of the pointed-to member (with + cv-qualifier adjustment). When the left operand is an lvalue, the result + is an lvalue (rvalueable), and similarly for an xvalue. When the left + operand is a prvalue, the result is a prvalue. +* | ``eok_pm_points_to_field`` is the "``->*``" operator. The left operand is + a prvalue pointer to class, the right operand is a pointer to data member, + and the result is an lvalue (rvalueable) of the type of the pointed-to + member (with cv-qualifier adjustment). +* | ``eok_dot_static`` is the "``.``" operator when the entity selected is + static. The first operand is a class glvalue or prvalue (and it *is* + evaluated) and the second operand is an ``enk_variable`` for a static data + member, an ``enk_routine`` for a static member function, or an + ``enk_constant`` identifying a member constant (e.g., an enumerator). The + result is the second operand. +* | ``eok_points_to_static`` is the "``->``" operator when the entity selected + is static. The first operand is a prvalue pointer to class (and it *is* + evaluated) and the second operand is an ``enk_variable`` for a static data + member, an ``enk_routine`` for a static member function, or an + ``enk_constant`` identifying a member constant (e.g., an enumerator). The + result is the second operand. + +Note that most of the selection operators are rvalueable in some cases, but the +static variants are not; for those, the lvalue-to-rvalue conversion, if there +is one, has to be indicated on the second operand, and not in the +``eok_dot_static`` or ``eok_points_to_static`` operation itself. + +Also note that there are no variants of the pointer-to-member selections for +pointer-to-member-function cases. Those can be used only in calls, and the two +operands of the selection are simply folded into the ``eok_pm_call``. +Likewise, the "``.``" or "``->``" operation in a member function call is simply +folded into the call. + +Subscripting +------------ + +``eok_subscript`` is the array subscripting "``[]``" operator. One operand is +a prvalue pointer to the first element of the array, and the other is an +integral subscript value. The result is an lvalue (rvalueable) for the +specified element of the array. Usually, the pointer operand is first, but +that's not actually a requirement of the language, and the operands can appear +in either order, as for the expression "``1[a]``". See the +``pointer_operand_is_second`` field, which indicates this unusual case, and the +macro ``subscript_or_padd_pointer_operand``, which can be used to extract the +pointer operand. As you will note from the name of that macro, this is also an +issue for the pointer addition (``eok_padd``) operator. + +.. _casts: + +Casts +----- + +The ``eok_cast`` operator is used to indicate simple casts. + +Casting a derived class pointer to a base class pointer is represented by an +``eok_base_class_cast`` operator. Casting a base class pointer to a derived +class pointer uses an ``eok_derived_class_cast`` operator. These casts differ +from ordinary pointer casts in that they may add or subtract an offset to the +pointer, and they must preserve a NULL pointer. They can also be applied +directly to a class glvalue or prvalue, rather than a pointer to a class +object, or to a C++/CLI handle. + +``eok_pm_base_class_cast`` and ``eok_pm_derived_class_cast`` are the similar +casts for pointers-to-members. The same operators are used for +pointers-to-data-members and pointers-to-member-functions, even though the +implementations of those are likely to be different. + +The anachronism of casting a bound pointer-to-member-function to a normal +pointer (which is similar to the processing done by an +``eok_points_to_pm_call`` to determine the function to call) is rendered as an +``eok_virtual_function_ptr`` operation. + +In ``pcc`` mode and in some Microsoft and GNU C++ modes, certain casts to +like-sized types (like ``int`` to ``unsigned int``) leave a result that is +still an lvalue. For these cases, the lvalue is cast to the appropriate type +using the ``eok_lvalue_cast`` operator. The result is still an lvalue. + +The C++ ``dynamic_cast`` operator is rendered as an ``eok_dynamic_cast`` +(pointer or handle case) or ``eok_ref_dynamic_cast`` (reference case), but only +for cases that require runtime processing. The rest are rendered as ordinary +casts. + +Casts to ``bool`` are rendered as an ``eok_bool_cast``, which has the same +effect as a "``!= 0``" test. + +The ``eok_lvalue_adjust`` operator adjusts the type of a glvalue. Its operand +is a glvalue, and its result is a glvalue for the same object but with a +different type. + +The ``eok_class_rvalue_adjust`` operator adjusts the type of a class prvalue. +It is limited to adjusting the cv-qualifiers of the type. Its operand is a +class prvalue, and its result is the same value with a different type. When +``LOWER_CLASS_RVALUE_ADJUST`` is TRUE, IL lowering will rewrite these +adjustments by taking the address of the class rvalue, casting the pointer to +the proper type, and indirecting to get back to a class object. + +Casts to reference types are represented as glvalue-to-glvalue operations. The +simplest cases are represented by the ``eok_ref_cast`` operator. The node type +is the underlying type of the reference, e.g., the node for a cast ``(T &)x`` +has type ``T``, not type ``T&``. The operand is a glvalue, and the result is a +glvalue for the same object but with the type ``T``. More complicated +reference casts that involve related-class adjustments are represented by +``eok_base_class_cast`` and ``eok_derived_class_cast`` operators operating on +class glvalues. Nodes that represent a cast to a reference type are marked +with the ``is_reference_cast`` flag. If several nodes are required (e.g., +multiple casts to base classes) only the topmost node will be marked. Note +that ``eok_ref_cast`` nodes are rvalueable, and when the ``is_lvalue`` flag is +cleared to indicate the presence of an lvalue-to-rvalue conversion the node +type becomes the cv-unqualified type (for non-class lvalues) or pointer-to the +lvalue type (for function lvalues). That means, for a function type ``F``, a +cast to ``F&`` with an included lvalue-to-rvalue conversion is represented by a +node with type ``F*``. + +Casts to rvalue reference types are similarly represented by ``eok_ref_cast``, +``eok_base_class_cast``, and ``eok_derived_class_cast`` nodes. They are marked +with the ``is_rvalue_reference_cast`` flag in addition to the +``is_reference_cast`` flag. Although in the C++ language such reference casts +take an rvalue as their operand, in the IL the operand is always converted to a +glvalue and then cast. The node or nodes that do the cast are then exactly the +same as those that would be used for an lvalue reference cast. The final +(topmost) cast node will always be an ``eok_ref_cast`` node, and it will have +``is_lvalue`` FALSE to indicate the result is an rvalue (unless the result +needs to be converted back to an lvalue for some reason). + +Assignments +----------- + +There are assignment operators for integral types, fixed-point types, floating +types, classes (bitwise copy, or C ``struct`` assignment), pointers, and +pointers-to-members. + +There is also a block-copy assignment, ``eok_bassign``, which is only generated +by IL lowering and inside front-end-generated assignment operator functions, +and is needed to do bitwise copies of arrays when copying classes. It is +unusual in that its second operand is in lvalue form and its result type is +``void``. + +In C++, assignment operators can return lvalues instead of rvalues. Such cases +are indicated by the ``returns_lvalue_instead_of_usual_rvalue`` flag in the +expression node. The expression type matches the type of thing returned (i.e., +it matches the first operand's type). The same flag is used for prefix ``++`` +and ``--`` and the "``?``" and "``,``" operators when they return an lvalue. +When that flag is set, ``is_lvalue`` will also always be set as well (in other +words, they are not rvalueable). + +Compound Assignments +-------------------- + +In cases where a compound assignment operator (e.g., ``+=``) is applied to +operands of two different types, the right side operator will be cast as +necessary to the type of the operation (as it would be for other operators). +The left side operand (the destination, an lvalue), however, is left in its +original type, which is also the type of the entire expression. The back end +must provide a cast of the value of the left operand to the operation type +(generally the type of the right operand, but see below) before performing the +operation on the operands. For example: in ``i-=f`` (``i`` an ``int``, ``f`` a +``float``), the back end must provide the cast of ``i`` to ``float`` before +doing the subtraction; the operation type is ``float``; the result type (and +the type of the expression node) is ``int``. + +As mentioned above, the operation type for the operation is generally the right +operand type. There are two exceptions in which the underlying type of the +left operand is the operation type: shift assignments (``<<=`` and ``>>=``) and +pointer ``+=`` and ``-=`` (for those cases, the right operand is not cast to +the operation type). Fixed-point ``+=``, ``-=``, ``*=``, and ``/=`` are yet +more complicated; the function ``compound_assignment_operation_type`` should be +called to determine the operation type for those (it also works for all the +simpler cases). + +GNU vector cases are even weirder, as no attempt is made to bring the operands +to a common type. + +Binary Conditional Operator +--------------------------- + +In some configurations, the front end supports a GNU extension known as the +"binary conditional operator". The operator has the form ``expr1``\ ``?``\ +``:``\ ``expr2`` (i.e., similar to the regular conditional operator, but with +an omitted middle operand). Such expressions result in the value of ``expr1`` +if ``expr1`` converted to a boolean is true, or the value of ``expr2`` +otherwise. In the IL, this is represented by the usual ``eok_question`` +operator, but with the flag ``is_gnu_two_operand_question_mark`` set to TRUE. +The expression includes a synthesized second operand, which may use an +``enk_reuse_value`` expression node to reuse the value of the first operand +without evaluating it a second time. + +Calls +----- + +The normal call is rendered as an ``eok_call`` operation. The first operand +gives the address of the routine to call, and the rest of the operands are the +arguments for the call. + +For nonstatic member function calls, the operation is ``eok_dot_member_call`` +(for calls in the ``x.f()`` form) or ``eok_points_to_member_call`` (for calls +in the ``p->f()`` form). The first operand is the routine address (as a normal +pointer, not a pointer-to-member); the second operand is the selector object (a +class glvalue or prvalue for ``eok_dot_member_call``, or a pointer to a class +object for ``eok_points_to_member_call``). The remaining operands are the +arguments to the call. In either case, a call with virtual semantics is +indicated by the ``is_virtual_call`` flag in the expression node. + +For pointer-to-member-function calls, the operation is ``eok_dot_pm_call`` (for +calls in the ``(x.*pmf)()`` form) or ``eok_points_to_pm_call`` (for calls in +the ``(p->*pmf)()`` form). The first operand is the pointer-to-member-function +(i.e., a value of pointer-to-member-function type, not a normal pointer type); +the second is the selector object (a class glvalue or prvalue for +``eok_dot_pm_call``, or a pointer to class for ``eok_points_to_pm_call``); the +rest are the actual arguments, as above. + +If a routine has default arguments, the front end will supply the default +expressions if no explicit arguments are provided. The back end need not do +any special handling. + +If a parameter of class type must be passed by using a copy constructor, a call +of the copy constructor into a temporary will be generated on the calling side. +Somewhat arbitrarily, the ``enk_temp_init`` node for that is marked as an +lvalue. + +For routines that return a class object via a copy constructor, the call will +always be immediately underneath a ``dik_call_returning_class_via_cctor`` +dynamic initialization entry. The entity being initialized by the dynamic +initialization entry should be taken as the destination for the copy +constructor call. (IL lowering makes this explicit.) + +Note that uses of operator functions and conversion functions are rendered as +routine calls even through they use operator syntax or are implicit in the +source program. Constructor and destructor "calls" generally only show up in +dynamic initialization entries, and not as standard calls in expressions. + +Inlining is considered to be a back end issue. The front end does not do +inlining of calls. IL lowering optionally offers a limited form of inlining, +but it's intended only for those who have no better alternative. + +Returns +------- + +The ``stmk_return`` statement is used to represent all returns, whether +explicitly written by the programmer or generated by the front end. In +addition to the expected + +.. code:: c++ + + return; + return expr; + +(which are distinguished by a NULL or non-NULL ``expr`` pointer), there is also +a special form of return used for returns in routines that return a class value +by calling a copy constructor. For those, the ``stmk_return`` statement has a +pointer to a dynamic initialization entry, which indicates the initializing +operation to be done to return the class object. IL lowering implements this +by having the caller pass an extra argument that provides the address at which +the class object should be placed, and having the called routine call the copy +constructor using the implicit parameter as its destination address. + +Pointers to Members +------------------- + +Pointer-to-member types are represented as an abstraction in the unlowered C++ +intermediate language. It is up to IL lowering or a back end to translate them +into a particular implementation. Typically, pointers to data members are +implemented as a small integral offset (the offset of the member within the +class) and pointers to member functions are rendered as a structure (see the +ARM, 8.1.2.c). + +Pointer-to-member types are represented by a ``tk_ptr_to_member`` type entry. + +Pointer-to-member constants are represented by a constant entry of kind +``ck_ptr_to_member``. These represent source constructs like ``&A::x``, +meaning some sort of representation of the location of ``x`` in a class object +of type ``A`` (not a pointer to that member in a specific object, but rather a +representation of how to find that member in an arbitrary entity of that +class). + +Operands of pointer-to-member type can be assigned (``eok_assign``) and +compared (``eok_eq`` and ``eok_ne``). They can also be cast to base or derived +classes (``eok_pm_base_class_cast`` and ``eok_pm_derived_class_cast``). + +Temporary Initialization +------------------------ + +The ``enk_temp_init`` node is used to introduce a temporary in the middle of an +expression. It points to a dynamic initialization entry and an expression. +The initialization indicated in the dynamic initialization entry is performed +on the temporary, and then the temporary is returned as the value of the +``enk_temp_init`` node, as an lvalue, xvalue, or prvalue. Any destruction +indicated in the dynamic initialization entry must be done to the temporary at +the end of the object lifetime to which the dynamic initialization is bound. + +Condition Declarations +---------------------- + +In ``if``, ``while``, ``for``, and ``switch`` statements in C++, the expression +tested can be a condition declaration. For example: + +.. code:: c++ + + if (float x = f()) { ... } + +This is represented in the IL as an expression node of kind ``enk_condition``. +The condition has its own associated scope, which contains just the one +variable, and which wraps around the statement. Note that the initializations +for conditions in loops are done each time around the loop; if destruction is +also required, it too must be done each time around the loop. + +New and Delete +-------------- + +A ``new`` operator allocates storage and optionally initializes it. It is +represented by an ``enk_new_delete`` expression node. The supplement to that +node provides information about the ``new`` routine to be called, the arguments +for that call, and optionally a dynamic initialization entry that describes any +initialization to be done. If the allocation fails (i.e., the ``new`` routine +returns NULL), the initialization is not done. + +A ``delete`` operator deallocates storage after optionally calling a +destructor. It is represented by an ``enk_new_delete`` expression node. The +supplement to that node provides information about the ``delete`` routine to be +called, the pointer to the object to be deleted, and optionally a dynamic +initialization entry that describes destruction to be done. + +In both the ``new`` and the ``delete`` cases, the routine indicated in the +new/delete supplement may be NULL to indicate that the allocation or +deallocation should be done by the constructor or destructor. The dynamic +initialization entry in those cases indicates the appropriate constructor +or destructor. This alternative is controlled by configuration options +``NEW_CAN_BE_FOLDED_INTO_CTOR`` and ``DELETE_CAN_BE_FOLDED_INTO_DTOR``, +which must be true if assignment to "``this``" (an anachronism) is +supported, because the constructor or destructor must have control of +allocation and deallocation in that case. + +When a ``delete`` contains the count of array elements (an anachronism), the +expression between ``[]`` is scanned and thrown away; it does not appear in the +IL. + +The C++/CLI ``gcnew`` operator is represented by an ``enk_gcnew`` expression +node. For CLI array cases, the supplment provides both the bound sizes +(whether explicitly specified or determined from the size of the initializer) +and an initializer aggregate for the element values. + +Lambda Expression +----------------- + +A lambda expression -- which produces a temporary "closure object" of a +class type with an ``operator()`` member -- is represented by an +``enk_lambda`` expression node. Such a node points to a supplement entry +of type ``a_lambda`` and to an ``a_dynamic_init`` entry describing the +initialization and (if applicable) the destruction of the temporary +"closure object" resulting from the expression. The ``a_lambda`` entry +describes the static properties of the lambda expression, such as the local +variables it captures (and how they are captured), the closure type, +relevant source positions, etc. + +Throw Expression +---------------- + +A ``throw`` expression is represented by an ``enk_throw`` expression node. It +points to a supplement that points to a dynamic initialization entry that +describes the object to be thrown (or rather, how to make a copy of it, since a +copy is what's actually thrown); the supplement pointer is NULL in the case of +a "rethrow". + +Sizeof +------ + +When a ``sizeof`` operator cannot be evaluated at compile time (for instance, +when it is applied to a variable length array), an ``enk_sizeof`` expression +node is put out. Such nodes are also used to represent dependent ``sizeof`` +expressions in prototype instantiations. + +typeid +------ + +The ``typeid`` operator is represented by an ``enk_typeid`` expression node. +It points to the type whose type information is wanted. For cases that require +runtime type determination (e.g., ``typeid(*p)`` where ``p`` points to a +polymorphic class type), there is also a pointer to an expression whose dynamic +type is to be determined at runtime. + +``enk_typeid`` is also used for the C++/CLI *X*\ ``::typeid`` feature. That's +indicated by the ``is_cli_typeid`` flag. The result value in that case is a +handle to a ``System::Type`` entry. + +.. _il-vla-dealloc: + +VLA Deallocation +---------------- + +In C mode, the front end may generate ``enk_vla_dealloc`` nodes to indicate +where VLAs should be deallocated. Such nodes may also be created when lowering +C++ IL for VLAs (when ``DO_IL_LOWERING`` is TRUE). The nodes are eliminated +from the IL altogether (both in C and C++ modes) if +``LOWER_VARIABLE_LENGTH_ARRAYS`` is TRUE; the nodes are translated to calls +into the run-time support library. + +Parameters +---------- + +When an identifier in an expression refers to a parameter, the resulting IL is +an ``enk_variable`` node if the parameter is referenced in the body of a +function. However, it is possible to refer to parameters in expressions that +appear *outside* the function body. For example, in C++11, a function template +declaration might be as follows: + +.. code:: c++ + + template auto f(T p)->decltype(*p); + +Such uses always appear in unevaluated contexts and are represented with +``enk_param_ref`` nodes, which, like ``enk_variable`` nodes, are rvalueable. + +An ``enk_param_ref`` node doesn't point directly to IL representing a +parameter (e.g., ``a_param_type`` entries) because such a pointer might +become invalid when, e.g., two function types are combined through +``composite_routine_type``. Instead, the parameter is represented by two +integers: The parameter position in its enclosing parameter list, and the +"level" of the parameter list relative to the point of reference (function +declarators may be nested and an inner declarator may refer to a parameter +of an enclosing declarator). + +Fixed-point operations +---------------------- + +Operations on fixed-point values are represented using the usual expression +operators (``eok_negate``, ``eok_post_incr``, ``eok_add``, ``eok_divide``, +``eok_eq``, ``eok_assign``, etc.). For mixed-type arithmetic (i.e., operations +involving two different fixed-point types, or a fixed-point type and an integer +type), these operators are different from most of the other (more common) +operators in that their operands are not converted to a common type. For +example, when adding a ``short int`` to a ``long _Accum``, the operator is +applied directly to the unconverted operands without "usual arithmetic +conversions." A back end is then responsible for performing the operation with +maximum precision and converting the result to the result type indicated in the +operator expression node. This arrangement is necessary to meet the +requirements of the Embedded C extensions (ISO/IEC TR 18037). + +Note that while mixed-type fixed-point arithmetic does not in general attempt +to convert the operands to a common type, a conversion from unsigned to signed +may be applied if one operand is signed and the other not. Furthermore, an +operation involving a fixed-point operand and a floating-point operand is a +floating-point operation: The fixed-point operand is converted to a +floating-point type. + +.. _parentheses: + +Parentheses +----------- + +Parentheses are represented in the IL as expression operation nodes with an +operator of ``eok_parens``. Those are not usually generated; ``PARENS_IN_IL`` +must be set to TRUE to request them. When that flag is TRUE, each pair of +parentheses in a source program expression is represented by an ``eok_parens`` +node in the IL for the expression. If ``EXTRA_SOURCE_POSITIONS_IN_IL`` is also +TRUE, those expression nodes will include position information on the opening +and closing parenthesis tokens. + +``eok_parens`` nodes are not used or allowed in versions that use IL lowering. +They are intended mostly for source-analysis applications. Note that enabling +``PARENS_IN_IL`` should not be done without reason, because it complicates the +code that deals with expressions. Every bit of code that wants to check for a +specific operator in an expression may have to check for and strip parentheses +off the expression before doing the check. That can be done by calling +``skip_parens``, but it's hard to always remember to do that. (This problem is +very similar to the ``skip_typerefs`` problem for types, and that is widely +known as a pain and a source of bugs.) + +Fold Expressions +---------------- + +A C++17 fold-expression like "``(ps + ... + 1)``" where ``ps`` contains an +unexpanded parameter pack is represented in generic template contexts (i.e., +"prototype instantiations") using an ``enk_fold`` node. The expansion of the +construct (in real template instantiations), however, uses the ordinary binary +operator representations. For example, if ``ps`` expands to a sequence of +integer parameter variables, the expanded representation will involve a tree of +``enk_operation``/``eok_add`` nodes. + +Boxing and Unboxing +------------------- + +C++/CLI boxing and unboxing is implemented by several operators: + +* | ``eok_box`` takes an operand of a value type (e.g., ``int``) and returns a + handle to a boxed version of the value on the CLR heap (e.g., handle to + ``System::Int32``). +* | ``eok_handle_to_box`` has the same runtime meaning as ``eok_box``, but is + generated for source uses of the unary ``%`` operator applied to a value + class. +* | ``eok_unbox`` takes an operand that is a handle to a boxed value class or + boxed enum and returns an lvalue (in place on the heap) or rvalue (copied) + for the contained value, depending on the ``is_lvalue`` flag. +* | ``eok_unbox_lvalue`` is similar, but the operand is an lvalue for the value + class or boxed enum. It is always compiler-generated, e.g., on top of an + ``eok_indirect`` applied to a handle to a value class. + +Pragmas +======= + +A ``#pragma`` directive may be represented in the IL by an entry of type +``a_pragma``, which appears on a linked list pointed to by the ``pragmas`` +field of an IL scope entry. It includes a pointer (see the ``entity`` field) +if it is specifically associated with a statement, routine, etc.; the entity +does not point back, but rather has its ``has_associated_pragma`` flag set, +since more than one pragma entry may be associated with a given IL entity. For +additional information, see :ref:`pragmas-and-attributes`. + +.. _anonymous-unions: + +Anonymous Unions +================ + +Anonymous unions are unions that have no name, either for the union type or for +the singular instance of the union. The names of the members of the union are +promoted into the surrounding context. There are two kinds of anonymous +unions: + +* | Anonymous unions within classes, as in + + .. code:: c++ + + class A { + union { + int i; + float j; + }; + } x; + + | Here, the fields of the anonymous union are promoted into the surrounding + class, so one can refer to ``x.i``. +* | Anonymous unions as variables, as in + + .. code:: c++ + + union { + int i; + float j; + }; + + | Here, ``i`` can be used as if it were a variable. Such constructs can + appear at file and namespace scope and within function and block scopes. + +For the first (field) case, the IL reflects the source form: class ``A`` will +contain an unnamed field whose type is an unnamed union, which in turn contains +the fields ``i`` and ``j``. A reference like ``x.i`` appears as a selection of +``i`` directly from ``x``. By looking at the field for ``i``, one can tell +that it is a member of an anonymous union, and infer the additional field +selection. (IL lowering adds the extra field selection.) + +For the second (variable) case, there will be an unnamed variable whose type is +the unnamed union. A reference like ``i`` appears as a selection of ``i`` out +of the unnamed variable, so it is more explicit (and less like the source +program) than the field case. + +Virtual Function Tables +======================= + +There are no "virtual function tables" *per se* in the unlowered IL. There is +only the information that is part of the definition of virtual functions in the +language: + +* | Functions are marked as being virtual, including when they are implicitly + virtual because they override a virtual function from a base class. + Virtual functions are assigned ordinal numbers within a class, which can be + used as their indexes into a virtual function table. +* | Calls to virtual functions use a special operator, ``eok_virtual_call``. +* | Base class entries contain information on virtual function overrides, i.e., + on which virtual functions of a base class are overridden by virtual + functions in derived classes (either the one the base class entry is + attached to or some class on the derivation path between the base class and + that one). + +One can generate a virtual function table for ``A`` in ``B`` by scanning the +member functions of ``A`` looking for virtual functions, along with the +override list for base class ``A`` of ``B``. If a function in ``A`` does not +appear on the override list, the function from ``A`` goes into the virtual +function table. Otherwise, the function from the override list goes into the +virtual function table. More detail can be found in the code in IL lowering +that generates virtual function tables. + +.. _il-c99-features: + +C99 features +============ + +The C99 IL extensions over C89 are as follows: + +* | For variable-length arrays (VLAs), the front end generates two additional + statement kinds (``stmk_set_vla_size`` and ``stmk_vla_decl``) and + optionally one additional expression node kind (``enk_vla_dealloc``; see + :ref:`il-vla-dealloc`). Types and variables are also marked as being VLAs + when appropriate. This feature can be enabled also in C89 and C++ modes + (by ``--vla``), and is controlled by the macro ``VLA_ALLOWED`` (which is + set by default if ``C99_IL_EXTENSIONS_SUPPORTED`` is set). If + ``LOWER_VARIABLE_LENGTH_ARRAYS`` is TRUE, the VLA-specific constructs are + eliminated from the IL (this requires the run-time support library). +* | For compound literals, an ``enk_temp_init`` node is generated. Such a node + generates a temporary, and is otherwise used only in C++ mode. This + feature can be enabled also in C89 mode (by ``--compound_literals``), and + is controlled by the macro ``COMPOUND_LITERAL_ENABLING_POSSIBLE`` (which is + set by default if ``C99_IL_EXTENSIONS_SUPPORTED`` is set). C99 lowering + eliminates compound literals by rewriting them as initialized generated + variables. +* | For designators in initializers, ``ck_designator`` constants are + generated in aggregate initializers. This feature can be enabled also + in C89 mode (by ``--designators``), and is controlled by the macro + ``DESIGNATED_INITIALIZER_ENABLING_POSSIBLE`` (which is set by default + if ``C99_IL_EXTENSIONS_SUPPORTED`` is set). If + ``LOWER_DESIGNATED_INITIALIZERS`` is TRUE (which it is by default if + C99 lowering is done), designators are almost completely eliminated; + they remain only for initializations of members other than the first in + unions, which are not possible in C89. +* | For ``_Bool``, the type is represented as in C++ (the ``bool_type`` flag is + set in the integral type). C99 lowering eliminates ``_Bool`` by rewriting + the type as a typedef to the underlying integer type. +* | For complex and imaginary types, there are new type kinds (``tk_complex`` + and ``tk_imaginary``), new constant kinds (``ck_complex`` and + ``ck_imaginary``), and some new operator kinds (e.g., ``eok_jfadd`` and + ``eok_jmultiply``) and conversions. If ``LOWER_COMPLEX`` is TRUE, C99 + lowering rewrites complex types as structs and imaginary types as + floating-point types, rewrites the constants as aggregate or floating-point + constants, and rewrites the operators and conversions as runtime routine + calls. +* | For flexible array members, the last member of a struct type may have an + array type with an unknown bound. No lowering is done. +* | For non-constant expressions in aggregate initializers, the aggregate + constants contain ``ck_dynamic_init`` constants, as in C++. C99 lowering + rewrites those as executable code. +* | For inline functions, the function is marked with the ``is_inline`` and + ``suppress_inline_body`` flags, as in C++. If ``MINIMAL_INLINING`` is + TRUE, C99 lowering replaces inline function calls with the expansions where + possible (as is done in C++). +* | For ``long``\ ``long``, there are two new integer kinds (``ik_long_long`` + and ``ik_unsigned_long_long``) and new constants of these kinds. This + feature can be enabled also in C89 mode and in C++ mode, and is controlled + by the macro ``LONG_LONG_ALLOWED`` (which is set by default if + ``C99_IL_EXTENSIONS_SUPPORTED`` is set). No lowering is done. +* | For mixed statements and declarations, the statements and declarations + appear intermixed in the statement list of a compound statement, as in C++. + No lowering is done. + +Entry Prefix +============ + +Each IL entry is preceded by a prefix, which is not part of the IL entry proper +but contains information about the entry that is useful to tree walking +routines and the like: + +* | Is the entry allocated in the file-scope memory region? +* | Has the entry been encountered yet on a tree walk of the IL? +* | Has the entry been encountered yet by IL lowering? +* | What entry number has been assigned to the entry (for the alternate IL file + format)? + +This prefix is allocated in space preceding the beginning of the entry (that +is, one has to do special address arithmetic to get to the prefix; see the +macro ``il_entry_prefix_of``). Some of the flags mentioned above are present +only when required by the front end configuration. + +Orphans +======= + +Type entries and static variables that are local to a function require some +special handling. All type entries and all static variables are allocated in +the file scope memory region. However, types and static variables that are +local to a function are placed on the types and static variables list of a +function or block scope. Those are unusual lists: the scope entry (in a +function scope memory region) points to a list that is entirely in the file +scope memory region. Yet, the entries pointed to are not really part of the +file scope. They might, in fact, not be referenced from anywhere except the +function scope memory region. Such entries are "orphaned" in the file scope: +their parents can be processed, written out, and removed from memory, but the +children remain in the file scope, unattached to the rest of the file scope IL +tree. + +A similar problem occurs when an IL entry such as a type is allocated in the +file scope memory region because it might be shared. If the entity is +referenced only from function scope memory regions, it too will be an orphan. + +Orphans are a problem if one wants to process the intermediate language on a +per-memory-region basis. One needs to be able to find all of the orphans when +processing the file scope memory region. There are two mechanisms that help +with this: + +* | ``il_header`` points to a list of entries of type + ``a_scope_orphaned_list_header``. Each entry on this list holds a copy of + the local type and static variable list pointers for a function or block + scope that has such entries. The ``a_scope_orphaned_list_header`` entries + are allocated in the file scope memory region, so they can be used to find + all such lists if the function and block scopes are no longer in memory. + | + | See the routine ``add_scope_orphaned_il_lists``. +* | Each file-scope IL entry is preceded by space for a pointer. (This space + precedes the entry prefix.) The pointer is used to chain potential orphans + onto a list of entries of the same kind headed by an element of the global + array ``orphaned_file_scope_il_entries``. Those lists can be traversed + after processing the file scope to find entries that might otherwise be + lost. Note that entries are placed on the list if they are potential + orphans, i.e., if they are allocated in the file scope memory region and + are referenced from a function scope memory region. Most of the entries on + the lists will not be orphans, but all orphans will appear on the list. + | + | See the routine ``add_orphaned_file_scope_il_entry``. + +All orphan processing is included only if needed. It is needed if IL lowering +is done or if an IL file is written. + +Relationship of the IL and the Symbol Table +=========================================== + +The symbol table of the front end is not part of the intermediate language +structure and is not passed to the back end. It is really mostly a name lookup +mechanism, which one can use to look up a name to get to the associated +intermediate language entry. By the time a back end receives the IL, all +references to entries are simply pointers to the proper entries, and therefore +no name lookup mechanism is needed. + +The symbol table also contains some information that is only needed in the +front end (for error checking or searching) and is not passed to the back end, +or information that has no IL representation (for example, symbol entries for +keywords). + +The symbol table also always reflects the true C and C++ idea of name scoping, +which may not exactly match the IL representation. For example, if we have the +declaration ``extern int xx`` in two scopes, each declares a name ``xx`` whose +visibility is limited to the scope in which it is declared, but the object (an +integer variable) associated with the name exists over the entire program. +During the front end compilation process there would be two different symbol +entries for ``xx`` in two different scopes, but in the intermediate language +there would be only one variable entry for ``xx``, and it would appear at the +file scope level. All references to either ``xx`` of the source program would +point to that one entity, and would not indicate which of the original ``xx``\ +s was referenced. + +.. _templates-in-the-il: + +Templates +========= + +The front end generates IL for instances of templates. For example, class +types are generated for instances of class templates and routines are +generated for instances of function templates. A back end can view a +template as a sort of powerful macro expanded by the front end, and can +deal with the generated IL for instances exactly as if the instances were +non-template classes and routines. A code generator need not, in general, +care that the source program contained templates. + +Each template declaration or definition in the source program is +represented by an IL entry of type ``a_template``. A list of those is +attached to the ``templates`` field of ``a_scope``. A separate +``a_template`` entry is included for each declaration or definition of a +given template (i.e., there can be more that one ``a_template`` entry +associated with a single template; if there is, the first such entry is the +canonical one, and is used when referring to the template itself as opposed +to a given declaration of the template). When the macro +``ALL_TEMPLATE_INFO_IN_IL`` is set to TRUE, ``a_template`` entries are also +generated for member functions, static data members, and member classes +nested in class templates. If ``RECORD_TEMPLATE_STRINGS`` is TRUE, the +``a_template`` entry contains a pointer to a null-terminated string that is +a textual representation of the template declaration or definition. + +The generated IL for an instance generated from a template does preserve some +indications of the fact that the entity came from a template: + +* | The type entry variant for class/struct/union has an ``is_template_class`` + flag that is set for template classes. If the class is an instance of a + template, rather than a member of a class that is a template, the class + type supplement's ``template_arg_list`` field gives the list of template + arguments for the template. +* | The routine entry has an ``is_template_function`` flag that is set for + template functions. If the function is an instance of a template, rather + than a member of a class that is a template, the routine entry's + ``template_arg_list`` field gives the list of template arguments for the + template. +* | The variable entry has an ``is_variable_template`` flag that is set for + template variables and template static data members. +* | The variable and routine entries have instantiation information flags. + +Template argument lists are represented by a list of ``a_template_arg`` +entries. Each entry points to an argument value: an IL type for a type +template argument, an IL constant for a nontype template argument, or an +``a_template`` entry for a template template argument. + +More information about templates is available when the macro +``ALL_TEMPLATE_INFO_IN_IL`` is set to TRUE. With that setting: + +* | The ``assoc_template`` field (in a class type supplement, routine, or + variable) points to the (canonical) ``a_template`` entry for the associated + template. +* | A ``canonical_template`` field of ``a_template`` points the canonical + ``a_template`` entry for the associated template. +* | A ``definition_template`` field of ``a_template`` is set in the canonical + entry to point to the ``a_template`` entry associated with the template + definition (if any). In other entries it is NULL. + +When ``ALL_TEMPLATE_INFO_IN_IL`` is TRUE and, in addition, the variable +``prototype_instantiations_in_il`` is TRUE, the IL tree includes IL for +templates themselves (as opposed to IL for instances of templates). This IL is +produced by doing a "prototype instantiation" of the template, which means +doing syntax and (partial) semantic analysis of the template definition without +the use of actual template argument values. Of necessity, such analysis is +incomplete; the meaning of certain constructs cannot be determined until the +actual template argument values are known. Therefore, the IL for prototype +instantiations can contain special generic operators and variants of other IL +constructs that do not appear in normal IL (e.g., ``eok_lvalue``). + +Prototype instantiations of classes are always done. Prototype instantiations +of functions are done when the variable ``nonclass_prototype_instantiations`` +is TRUE (see the command-line option ``--parse_templates``). The variable +``prototype_instantiations_in_il`` controls whether prototype instantiations +are *preserved* in the IL. If the flag is FALSE, the instantiations -- if done +-- are thrown away and not linked into the IL tree. If the flag is TRUE, the +prototype instantiations are done *and* preserved, and + +* | The ``a_template`` entry for each template poimts to IL for its prototype + instantiation: a class type for a class template, a routine for a function + template, or a variable for a variable template or static data member + template. +* | The ``a_template`` entry points to an entry of type ``a_template_decl``, + which provides information about the template header (source position, + parameter list). The information on parameters is given by a list of + entries of type ``a_template_parameter``. (The pointer is NULL for + a_template entries for member functions, static data members and member + classes nested in class templates.) + +Note that when ``prototype_instantiations_in_il`` is TRUE and +``nonclass_prototype_instantiations`` is FALSE only class prototype +instantiations are included in the IL. + +While the front end is processing templates, it is convenient for it to be able +to generate IL versions of entities (like class members) that are not "real," +i.e., that exist only as part of some template abstraction that will never be +seen by the back end. For those cases, it is helpful to be able to represent +types and constants which are not known but which nevertheless have a certain +identity, e.g., they're derived from template parameters of a current template. +The ``tk_template_param`` type and the ``ck_template_param`` constant are used +for those cases. Likewise, a special ``a_template`` entry is created to +represent the unknown value of a template template parameter inside a prototype +instantiation. These entities will appear in the IL tree only inside prototype +instantiations. + +C++/CLI generics are represented as templates with an extra flag +(``is_generic_definition`` in both class types and routines). They can also +have additional constraint information, provided by entries of type +``a_generic_constraint`` and ``a_generic_constraint_clause``. + +Macros +====== + +If ``RECORD_MACROS_IN_IL`` is set to TRUE, entries of type ``a_macro`` are +created and added to the ``macros`` list of the IL header. The entries +contain a textual version of the macro definition (e.g., a string like +"``#define x(a) a+1``"), except for predefined macros like ``__LINE__`` and +``__FILE__`` whose replacement text varies from one invocation to the next. +The entries for these macros contain an empty (zero-length) text string +instead of a fixed definition. If a macro is redefined (to a different +string), there is another macro entry for the new definition. Macro +entries are also used to represent ``#undef`` directives. + +The front end can also be configured to maintain detailed information regarding +macro invocations. For instance, it is possible to determine the original +source position of text that appears in the expansion of a macro invocation. +This extra position information can be used to produce more-detailed diagnostic +messages regarding such text, and source analysis tools can more accurately +identify the positions and ranges associated with declarations, expressions, +and statements. It is also possible to determine the chain of macro +invocations that led to a particular macro expansion or to obtain a macro +invocation tree (similar to a function call tree) for an entire translation +unit. + +If ``FULLY_RESOLVED_MACRO_POSITIONS`` is TRUE, ``a_source_position`` has an +extra sequence/column pair, ``orig_seq`` and ``orig_column``. For text +appearing directly in the source, both pairs will indicate the same position. +For text that occurs in a macro expansion, however, +``orig_seq``/``orig_column`` will be the source position at which the text +originally appeared before being copied into the macro expansion -- either in +the definition of some macro or in the argument list of the top-level macro +invocation. (Regardless of the value of ``FULLY_RESOLVED_MACRO_POSITIONS``, +the ``seq``/``column`` pair for all positions in a macro expansion indicate the +initial position of the top-level macro invocation.) + +If ``MACRO_INVOCATION_TREE_IN_IL`` is set to TRUE, a flattened macro +invocation tree is kept in the file scope memory region. Because +variably-sized data is awkward to represent in the IL, the list of macro +invocation records is broken into fixed-size blocks of type +``a_macro_invocation_record_block``, each containing +``MACRO_INVOCATIONS_PER_BLOCK`` records, and these blocks are organized +into a binary tree to reduce the cost of accessing an arbitrary invocation +record. + +There is one record in the tree (of type ``a_macro_invocation_record``) for +each macro invocation that was performed. Each such record indicates the +parent invocation, the macro that was invoked, and the (original) source +position of the macro name that introduced the invocation. Furthermore, if +``EXTRA_SOURCE_POSITIONS_IN_IL`` is TRUE, the record will contain the +(original) ending position of the macro invocation (the last character of the +name of an object-like macro or the closing parenthesis in the invocation of a +function-like macro). + +In addition, when ``MACRO_INVOCATION_TREE_IN_IL`` is TRUE, +``a_source_position`` contains the index of the macro invocation record in +whose expansion that position occurs (or ``NO_PARENT_MACRO_INVOCATION`` if the +position refers to text that appears directly in source code). + +The ``macro_context`` field in ``a_source_position`` and +``parent_macro_index`` in ``a_macro_invocation_record`` enable +reconstruction of the stack of macro invocations that resulted in the text +at that position. Each macro invocation record is uniquely identified by +an index value of type ``a_macro_invocation_index``, so the macro +invocation stack can be traced simply by following the chain of +``parent_macro_index`` values. (An invocation of macro ``C`` is considered +to be a child of an invocation of macro ``P`` if ``C``'s invocation appears +in the argument list or the expansion of that invocation of ``P``.) + +For convenience in accessing macro invocation records by index, +``il_def.h`` defines the macro ``set_macro_inv_record_ptr_to_index(``\ +*root*\ ``,`` *index*\ ``,`` *mirp*\ ``)``, which sets a pointer *mirp* of +type ``a_macro_invocation_record_ptr`` to the address of the record at the +specified index, given the tree root (which is found in +``il_header.root_macro_invocation_record_block``). + +In addition to direct access into the tree by record index, it is possible to +scan the tree sequentially; the records are stored in the same order that the +invocations were performed during preprocessing. To facilitate reconstruction +of the invocation tree during such a traversal without the necessity of +maintaining a separate invocation stack, the array contains certain +"placeholder" records that do not denote macro invocations. Such records are +identified by a negative value (other than ``NO_PARENT_MACRO_INVOCATION``) for +the parent invocation. + +To understand the use of these placeholder records, consider two records +*M* and *N* reflecting successive macro invocations. If the parent +invocation of *N* is the same as that of *M*, the two invocations are +siblings and the transition from *M* to *N* implies no change to the +conceptual invocation stack. If the parent invocation of *N* is *M* +itself, then *N* is a child of *M* (i.e., invocation *M* is assumed to be +pushed onto the stack). Otherwise, a non-negative parent index in *N* is +assumed to be a single-level pop of the conceptual stack -- that is, the +parent of *N* is the parent of *M*'s parent. In all these cases, the +invocation records for *M* and *N* will be at consecutive indices. If, on +the other hand, the parent of *N* is a more remote ancestor of *M*, a +placeholder record will be inserted between *M* and *N* with a negative +parent index whose absolute value is the number of invocations to pop from +the conceptual stack in order to restore that remote ancestor to the top of +the stack. + +Attributes +========== + +C++11 ("standard"), GNU, and Microsoft ``__declspec`` attributes are +represented in the IL by entries of type ``an_attribute``. If such attributes +appear on a declaration, they are pointed to by the ``attributes`` field of the +corresponding entry's source correspondence; otherwise, a dedicated attributes +field is used (e.g., in ``a_param_type``). When +``RECORD_UNRECOGNIZED_ATTRIBUTES`` is TRUE, unrecognized attributes are +recorded in the IL with kind ``ak_unrecognized`` (when the macro is FALSE, +unrecognized attributes are not recorded and a warning is issued). All +attributes specified in the same "group" point to an entry of type +``an_attribute_group``. Empty groups contain a pseudo-attribute of kind +``ak_empty_attr`` (or more than one, for a GNU construct like +"``__attribute((,,,))``"). + +If an attribute includes an argument list, the corresponding attribute entry +points to a list of ``an_attribute_arg`` entries. An empty argument list -- as +in ``__attribute((nonnull()))`` -- is represented with an argument entry of +kind ``aak_empty``. Otherwise, the entries in the argument list represent a +constant (``aak_constant``), a type (``aak_type``) or an uninterpreted token +(``aak_token`` or ``aak_raw_token``). ``aak_token`` entries represent single +tokens that may be followed by other arguments separated by a comma. In +contrast, ``aak_raw_token`` entries represent one or more tokens including the +commas; a sequence of ``aak_raw_token`` entries is always followed by a +terminating ``aak_empty`` entry (used primarily to record the position of the +token that follows in the source -- this is useful for diagnostic purposes). +If an unrecognized attribute is followed by a non-empty argument list, that +list consists of ``aak_raw_token`` entries (including entries for any commas in +the list). E.g., the unrecognized C++ attribute ``[[ unrecog(x, y) ]]`` has +three ``aak_raw_token`` argument entries for "``x``", "``,``", and "``y``" +(followed by a ``aak_empty`` entry). + +Microsoft attributes (delimited by single brackets) are represented in the IL +by entries of type ``an_ms_attribute``. Depending on the configuration of the +front end, a given Microsoft attribute may be either "recognized" or +"unrecognized". All attributes include a string representation of the +attribute from the source. In addition, recognized attributes include an +argument list representing the arguments that were specified in the attribute +reference. + +Microsoft attributes that apply to function parameters are pointed to by the +param type entry. All other attributes are pointed to by the ``ms_attributes`` +field of an IL scope entry. Attributes that apply to a particular entity +include a pointer (see the ``entity`` field) to that entity. The entity does +not point back, but rather has its ``has_associated_attribute`` flag in its +source correspondence set. + +Properties +========== + +Microsoft properties come in two kinds: + +* | Old-style properties indicated by the ``__declspec(property(``... )) + attribute. The accessor functions are only loosely associated with the + property, by being named in the attribute. +* | New-style properties in C++/CLI, which begin with the "``property``" + context-dependent keyword. The accessor functions are declared as part of + the property declaration, in a form that looks vaguely like a nested class. + +In both cases, the IL has a description of the property declaration, so that is +retained in something close to the source form (that information is held in +``a_property_or_event_descr`` entry). However, also in both cases, references +to the properties are expanded by the front end, so they are not retained in +source form. A bit of source code like "``p``\ ``+=``\ ``1``" might be +expanded into a series of calls something like "call the get accessor for +``p``, call ``operator+`` on the fetched value and 1, and call the put accessor +to store the computed value." The generated IL contains some tags on various +nodes in the expansion that help source-analysis code recover the original +meaning, though in a cumbersome way. + +C++/CLI events are very similar to the new-style properties, in representation +and in the fact that references are expanded by the front end. + +Microsoft ``__if_exists`` blocks +================================ + +Representing ``__if_exists`` (and ``__if_not_exists``) blocks in the IL is +problematic because, although the Microsoft documentation describes the +contents of an ``__if_exists`` block as a statement, the Microsoft compiler +actually accepts any fragment of a statement or declaration in the block (as +does our front end in Microsoft mode). + +The front end provides a mechanism that can represent ``__if_exists`` blocks +that appear in class definitions, and which surround complete declarations of +the class. When an ``__if_exists`` appears in a valid location in a class +definition, an IL entry (``an_ms_if_exists``) and source sequence entry are +created for the start and end of the block. ``__if_exists`` blocks in other +scopes are not represented in the IL (but are still included in the textual +representation of templates). If an ``__if_exists`` appears in an invalid +context in a class definition, an error is issued. + +IL entries are only created for ``__if_exists`` blocks that appear in the +prototype instantiation of class templates and classes nested within class +templates. In non-template contexts, the ``__if_exists`` is simply evaluated +when it is encountered. + +IL Use Within the Front End +=========================== + +Some aspects of the IL are used only during the front end processing and are +not seen by back ends. + +Most of the primary table types have a kind used to represent errors (e.g., an +error constant, an error expression). These are used to replace parts of the +IL tree that contain errors. Since the back end is not run if there are +errors, a back end will never see these kinds of entries. + +There are also a few table kinds used for unknown entities (not known yet, but +not an error), for example the unknown type kind ``tk_unknown``. These are +replaced by actual kinds by the time a back end sees the IL. + +Constant expressions are generally folded to a single constant value and +the front end uses that folded value for its processing. In scanning +``1+2``, for example, the ``1`` and ``2`` will be folded into a constant +entry for ``3``, and that value will be used internally. The original +expression that was folded is generally preserved via the ``expr`` field of +``a_constant``. + +.. _il-extension-guide: + +How To Extend the IL +==================== + +Extending the intermediate language involves making a coordinated set of +changes in several files. Three kinds of changes are discussed below: + +* | adding a field to an existing IL entry (typically quite straightforward), +* | adding a new operator kind (usually also straightforward), and +* | adding a brand new IL entry (only a little more complicated). + +Note, however, that what is covered is the typical case. There may be +additional complications. And, of course, nothing of a general nature can be +said about how a field or entity is set and used or how it interacts with other +parts of the IL. + +Adding a Field to an Existing IL Entry +-------------------------------------- + +This is what you need to do to add a field *f* of type *T* to existing IL +entry *E* with ``an_il_entry_kind iek_``\ *e*: + +.. list-table:: + + * - | in ``il_def.h``: + - | Add *f* to *E*. + * - | in ``il_alloc.c``: + - | Initialize field *f* in the routine that allocates *E* objects. + * - | in ``il_display.c``: + - | Add code to display the value of *f*. This will typically appear + in a function called ``disp_``\ *e*, and the display will depend + on the type *T*. For example, ``disp_boolean`` will be called for + a flag, ``disp_ptr`` will be called if *T* is of type + pointer-to-IL-entry, and so forth. + +and in addition, if *T* is of type pointer-to-IL-entry: + +.. list-table:: + + * - | in ``walk_entry.h``: + - | In ``WALK_ENTRY_ROUTINE_NAME``, there will be a ``case`` clause + for ``iek_``\ *e* within the main ``switch`` statement. Here you + will usually need to add a call to ``walk_ptr`` or ``remap_ptr``. + (The latter is typically used if *f* is a secondary reference to + the object it points to, but ``walk_ptr`` can be used in any + case.) There are some special cases to look out for, however. For + example, if *f* points to a linked list, instead of ``walk_ptr`` + call either ``walk_list`` (if ``*``\ *T* uses a ``next`` pointer) + or ``walk_list_on_link_field``. + +If *f* is an addition to the ``a_type`` entry, update ``traverse_type_tree`` +accordingly. + +If *f* is an addition to the ``an_expr_node`` entry, update ``traverse_expr`` +accordingly. + +If *f* is an addition to the ``a_statement`` entry, update +``traverse_statement`` accordingly. + +If *f* is an addition to the ``a_dynamic_init`` entry, update +``traverse_dynamic_init`` accordingly. + +If *f* is an addition to the ``a_constant`` entry in its function as the +description of an initializer, update ``traverse_constant`` accordingly. + +Adding a New Operator +--------------------- + +Most expression nodes (``an_expr_node``) represent operations +(``enk_operation``) like additions, assignments, calls, casts, etc. Each of +these operation kinds is identified by an enumeration constant (``eok_add``, +``eok_call``, ...). To add a new operation kind, it is not sufficient to add +another constant; the following updates are also required: + +.. list-table:: + + * - | in ``il_def.h``: + - | Add a string constant to ``db_operator_names``. + * - | in ``il_display.c``: + - | Add a case for the new operator in ``disp_expr_operator_name``. + * - | in ``cp_gen_be.c``: + - | Update ``generated_precedence`` to cover the new operator. + * - | in ``il.c``: + - | Update ``lvalue_rvalue_test`` and ``operation_type_kind``, and if the + operator has side effects, also ``operation_has_side_effects``. + +Furthermore, if the operator may produce an lvalue (``is_lvalue`` is TRUE) or +xvalue (``is_xvalue`` is TRUE), additional functions must know about the new +operator kind: + +.. list-table:: + + * - | in ``il.c``: + - | ``is_rvalueable_node``, ``node_does_fetch``, and + ``operator_takes_lvalue_operand``. + * - | in ``exprutil.c``: + - | ``conv_prvalue_expr_to_glvalue``, and (if ``is_rvalueable_node`` + indicates that the operator is not "rvalueable") + ``conv_glvalue_expr_to_prvalue``. + +Finally, if the operator is an addressing operator, a few other routines +require updating: + +.. list-table:: + + * - | in ``folding.c``: + - | ``constant_glvalue_address`` and ``constant_prvalue_pointer``. + * - | in ``il_walk.c``: + - | ``traverse_addressing_subtree``. + +Adding a new expression node kind (new ``enk_...``\ variant) is harder. That +requires looking at all code that handles expressions, in particular switch +statements that case out on the expression kind, and making appropriate +changes. If the new variant includes an embedded type, be sure to update +``examine_expr_for_dependent_type``. + +Adding an IL Entry +------------------ + +This is what you need to do to add an IL entry of ``struct`` type *X*, +where *X* is a name with the form ``a_``\ *xxx*: + +.. list-table:: + + * - | in ``il_def.h``: + - | Add the definition of *X*. Add ``iek_``\ *xxx* to the enumeration + ``an_il_entry_kind``. Update the initialization of + ``il_entry_kind_names`` and ``sizeof_il_entry``. + * - | in ``walk_entry.h``: + - | Add a ``case`` clause for ``iek_``\ *xxx* in + ``WALK_ENTRY_ROUTINE_NAME``. Add calls to process orphans in + ``WALK_ORPHANED_ENTRY_ROUTINE_NAME``. + * - | in ``il_walk.c``: + - | Add calls to process orphans in + ``remap_first_ptr_of_orphaned_file_scope_entry_array`` and in + ``remap_last_ptr_of_orphaned_file_scope_entry_array``. + * - | in ``il_alloc.c``: + - | Add an ``alloc_``\ *xxx* routine. If the entity should always be + allocated in the file scope memory region, call ``alloc_il``; to use + the current memory region, call ``alloc_cil``. (Do not use + ``alloc_fe`` for entities in the IL.) If the entity is a supplement to + some other entry (to keep down the size of the containing entry), the + space for the supplement should be allocated when the containing entry + kind is set to that variant. See examples in ``set_type_kind``. In + such cases, you should also change the copy routine for the containing + entity so that it copies the supplement as well. See ``copy_type`` + and ``copy_node`` for examples. If you want to track the number of + entities of type *X* that are allocated and how much space they use, + define a static variable ``num_``\ *xxx*\ ``es_allocated``, initialize + it in ``il_alloc_init``, register it in ``il_alloc_one_time_init`` in + case precompiled headers are used, increment it in ``alloc_``\ *xxx*, + and display it by adding code to ``show_il_alloc_space_used``. + * - | in ``il_display.c``: + - | Add a ``disp_``\ *xxx* routine. Add a ``case`` clause for + ``iek_``\ *xxx* in ``disp_entry``. If the entity is a supplement, + add its kind to the list at the beginning of ``disp_entry`` (a + list of entity kinds for which the entity is displayed with the + containing entity), and put the call of ``disp_``\ *xxx* in the + clause for the containing entity. + * - | in ``il.c``: + - | If the entry might be an orphan (allocated in the file-scope memory + region, pointed to from something in a function-scope memory region, + but not pointed to from anything in the file-scope memory region), add + the entry kind as a case in + ``f_possibly_add_orphaned_file_scope_il_entry``. + +This is what is required in the general case, but there are potentially many +other issues to consider. For example, if *X* has a substructure of type +``a_source_correspondence``: + +.. list-table:: + + * - | in ``il_alloc.c``: + - | Be sure ``alloc_``\ *xxx* calls ``set_default_source_corresp``. + Add a ``case`` clause for ``iek_``\ *xxx* in + ``source_corresp_for_il_entry``. + * - | in ``il_display.c``: + - | Add a ``case`` clause for ``iek_``\ *xxx* in ``disp_ptr``. + +If *X* is added to ``a_class_type_supplement``, and the field is one that is +meaningful even if the class does not have a definition: + +.. list-table:: + + * - | in ``il.c``: + - | If you use "needed" flags (``MAINTAIN_NEEDED_FLAGS`` is TRUE), modify + ``turn_class_definition_into_declaration`` to copy *X* when clearing + the class type supplement. + +.. [#f1] The obvious exception to that -- the reference from the interface to a + routine down to the function scope that defines its implementation -- + is handled as a special case. What is stored in the interface is not + a pointer, but rather a function definition number, which can be + looked up in ``function_def_table`` in ``il_header`` to get a pointer + to the scope entry if it is in memory. +.. [#f2] Why do that? Because we need the type of the entities to check other + declarations of the same name and to check calls to external entities + that are functions. +.. [#f3] One exception: GNU and Microsoft allow the alignment of a typedef to + be set explicitly, and that alignment is recorded in the associated + ``tk_typeref`` entry. For this reason, the macro + ``alignment_of_type`` should always be used to retrieve the alignment + of a type. +.. [#f4] A Microsoft ``__interface`` type is treated as a special kind of C++ + ``struct`` type. A C++11 lambda closure type is a generated C++ + class type. +.. [#f5] One compelling reason: constants used as part of aggregate constants + are linked together using their ``next`` pointers, so a unique copy of + the constant is necessary for each initializer list. +.. [#f6] Because dynamic initialization entries can do destruction without + initialization, there is a ``dik_none`` value for ``kind`` to indicate + that no initialization should be done. +.. [#f7] There are some additional kinds of bindings generated by IL lowering; + see ``il_def.h`` for details. +.. [#f8] Following the implementation of C++11 value categories in version + 4.8, the front end has tried to use the C++11 terms in general + internally. That caused a lot of renaming of routines and fields; for + example, ``conv_lvalue_to_rvalue`` became ``conv_glvalue_to_prvalue``. + Ugly until you get used to it, but very helpful in reminding you to + consider xvalues when you write code that deals with expressions. diff --git a/dev/doc/_sources/includes.rst.txt b/dev/doc/_sources/includes.rst.txt new file mode 100644 index 0000000..1a72da1 --- /dev/null +++ b/dev/doc/_sources/includes.rst.txt @@ -0,0 +1,55 @@ +============================ +ANSI C and C++ Include Files +============================ + +Standard C++ Include Files +========================== + +The following include files are supplied with the front end: + +* | ``compare.stdh`` +* | ``coroutine.stdh`` +* | ``cxxabi.h`` +* | ``exception.h`` +* | ``exception.stdh`` +* | ``initializer_list.stdh`` +* | ``new.h`` +* | ``new.stdh`` +* | ``source_location.stdh`` +* | ``stdexcept.h`` +* | ``stdexcept.stdh`` +* | ``stdfloat.stdh`` +* | ``typeinfo.h`` +* | ``typeinfo.stdh`` + +The ". ``stdh``" files are basically the same as the definitions in the C++ +standard. The standard specifies header names without a suffix (e.g., +````). The front end, by default, adds the ``stdh`` suffix when searching +for the header file. The "``.h``" versions are supplied so that older code +that uses header names like ```` will continue to work. + +Not all of the header files for the libraries required by the C++ standard are +provided. In general, header files are only supplied for components of the +library for which an implementation is supplied with the front end. + +The ``typeinfo.h`` header file contains the definition of the ``type_info`` +data structure used by the front end and the runtime library. The +``type_info`` structure must not be changed unless corresponding changes are +also made in the front end and runtime. + +The ``cxxabi.h`` header includes declarations of routines and data structures +specified by the IA-64 ABI. + +Namespaces and the Standard Header Files +---------------------------------------- + +When front end configuration flag ``RUNTIME_USES_NAMESPACES`` is TRUE the front +end defines the preprocessing macro ``__EDG_RUNTIME_USES_NAMESPACES``. This +flag is tested by the C++ header files to determine whether the runtime +declarations should appear in the global scope or in the ``std`` namespace. +The C++ header files also test the ``__EDG_IMPLICIT_USING_STD`` flag, which is +defined by the front end when the front end is configured to use namespace in +the runtime and when the ``--using_std`` option is specified when the front end +is invoked. This flag causes the header files to do a ``using namespace std`` +in any header file that contains declarations for entities in the ``std`` +namespace. diff --git a/dev/doc/_sources/index.rst.txt b/dev/doc/_sources/index.rst.txt new file mode 100644 index 0000000..16cf0b8 --- /dev/null +++ b/dev/doc/_sources/index.rst.txt @@ -0,0 +1,117 @@ +C/C++ Front End Documentation +================================= + +.. toctree:: + build + ext_intf + int_overview + il + lower_il + symbol_tbl + lex_pp + tables + expr + decls + class_decl + statements + templates + exceptions + pragma + modules + trans_unit + admin + err_msgs + includes + runtime + utilities + c_gen_be + cp_gen_be + code_style + testing + :maxdepth: 3 + :numbered: + :hidden: + +============ +Introduction +============ + +This document describes the function and internal structure of the Edison +Design Group C/C++ Front End. More precisely, it gives the general overview +necessary as an introduction to the study of the source code of the Front End. +The source code comments provide more detailed information, and that +information is not necessarily repeated here. + +The front end accepts the C++ language as defined by the ISO/IEC 14882:2020 +standard, as well as a number of the features of the ISO/IEC 14882:2024 +standard. The front end can also be configured to accept earlier revisions of +the C++ standard (e.g., ISO/IEC 14882:2003). With the proper command-line +options, it alternatively accepts the C language of the ISO/IEC 9899:1990, +ISO/IEC 9899:1999, ISO/IEC 9899:2011, and ISO/IEC 9899:2018 standards, as well +as a number of features from the ISO/IEC 9899:2024 standard. Certain other +dialects of C++ and C are also accepted, including Microsoft, GNU and Clang +dialects. C++/CLI, the Microsoft extension to C++ in support of Microsoft's +.NET environment (and formalized through the ECMA-372 standard), is also +implemented. + +It is a single pass, including integrated preprocessing. (Preprocessing +alone -- to a textual output file -- can also be done, as in traditional +compilers with a separate preprocessor.) The syntax-analysis technique is +recursive descent, with a precedence modification to speed up the scanning +of expressions. + +The front end does no optimization. Its goal is to produce a complete and +clean parsed form of the source program, and to diagnose errors. It does +complete error checking, produces clear error messages (including the position +of the error within the source line), and avoids cascading of errors. It also +tries to avoid seeming overly finicky to a knowledgeable C or C++ programmer. + +The front end is written in a portable dialect of C++, using features from the +ISO/IEC 14882:2011 standard (i.e., it's written using C++11 features). Host +and target computer characteristics (e.g., command-line interface, character +sets, integer sizes, floating-point representation) are carefully separated +from the main body of code so that they can be easily changed for rehosting or +retargeting. There is extensive debugging and assertion-checking code, which +can be included or excluded by conditional compilation options. + +The output from the front end is a high-level tree-structured in-memory +intermediate language. This intermediate language contains full information on +declarations, statements, and expressions, all in tree form, and all with +source-correspondence information that simplifies the generation of symbolic +debugging information. + +The intermediate language can, if desired, be written to a file, read back from +such a file, or displayed in human-readable form. + +When it translates C programs to intermediate language, the front end uses only +the C subset of the intermediate language. When it translates C++ programs to +intermediate language, it uses the full intermediate language. However, an +optional IL lowering pass can be used translate the C++ intermediate language +constructs into C intermediate language constructs to reduce the work required +of back ends. + +It is expected that the front end will be combined with an appropriate back end +that will generate object code from the intermediate language. A simple back +end is provided that generates C from the intermediate language, and another +that generates C++ from the intermediate language (the latter is intended for +source-to-source applications). + +Also included: minimal runtime, a template prelinker, an IL display utility, a +name demangler, and prototype header files. + +This document covers: + +* The external interface of the front end -- the command-line options, + language dialect, intermediate language, and host/target configuration + issues. (Error messages are listed in an appendix.) +* The design of the front end -- its philosophy and an overview of the source + code. + +Readers of this document should be familiar with the C++ language, with the C +language, and with the basics of compiler theory. + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` diff --git a/dev/doc/_sources/int_overview.rst.txt b/dev/doc/_sources/int_overview.rst.txt new file mode 100644 index 0000000..d9eb2b3 --- /dev/null +++ b/dev/doc/_sources/int_overview.rst.txt @@ -0,0 +1,1295 @@ +============================== +Overview of Internal Structure +============================== + +Function of the Front End +========================= + +The front end reads source files written in C or C++, diagnoses any errors in +them, and produces an intermediate language tree that represents the source +program. + +The source files are one primary source file (named on the command line) +and zero or more header files (specified by ``#include`` directives). If +``COMPILE_MULTIPLE_SOURCE_FILES`` or ``COMPILE_MULTIPLE_TRANSLATION_UNITS`` +is TRUE, multiple source files may be specified on the command line. + +The intermediate language tree is an in-memory representation of the source +program, from which a back end can generate object code. This intermediate +form is high-level (i.e., its constructs correspond closely to C or C++ +constructs). Implicit transformations in the source language are made explicit +in the intermediate language. Source-correspondence information is preserved +so that symbolic debugging information can be generated. + +When it translates C programs to intermediate language, the front end uses only +the C subset of the intermediate language. When it translates C++ programs to +intermediate language, it uses the full intermediate language. However, an +optional IL lowering pass can be used translate the C++ intermediate language +constructs into C intermediate language constructs (this lowering is not +available for C++/CLI and C++/CX). + +The front end does not do any optimizations. It does not transform the program +in other than trivial ways. + +The front end would usually be run from a *driver*, which invokes the front end +and back end in order, and which validates and distributes the command-line +options. In such a case, the front end would write the intermediate language +information to a file, which would be read by the back end. + +The front end incorporates the preprocessing function of the C and C++ +languages, and does them on the fly as it parses the source program. The front +end can also be run in a preprocessing-only mode, and will generate +preprocessing output as a separate preprocessor would. Comments can be kept or +removed in this process. + +The front end can generate a file containing raw listing information to be used +to assemble a compilation listing. The raw listing file contains raw source +lines, information on transitions into and out of include files, and +diagnostics generated by the front end. A file containing cross-reference +information (information on each reference to an identifier in the source +program) can also be generated in a different file. + +Guide to the Source Files +========================= + +Note that most source files have a ``.c`` file suffix, even though they contain +C++ code and must be compiled with a C++ compiler (with the C++11 dialect). +That naming convention is for historical reasons and for ease in delivering +patches against earlier versions of the front end. Symbolic links (e.g., with +a ``.cpp`` suffix) can be added if required by a build environment. + +The source files are: + +.. list-table:: + + * - | ``attribute.h`` + - | Declarations related to ``attribute.c`` (scanning of attributes). + * - | ``basics.h`` + - | Basic declarations for every compilation. + * - | ``builtin_defs.h`` + - | Declarations related to GCC/clang/Microsoft builtin functions. This + header file is generated automatically by a tool that retrieves the + signatures of these builtin functions from various versions of GCC and + clang compilers (the Microsoft builtin function signatures are + manually input to this automated process). + * - | ``builtin_kinds.h`` + - | Builtin function kinds (split from ``builtin_defs.h`` to improve + compilation times). This header file is generated automatically by a + tool that retrieves the signatures of these builtin functions from + various versions of GCC and clang compilers (the Microsoft builtin + function signatures are manually input to this automated process). + * - | ``c_gen_be.h`` + - | Declarations related to ``c_gen_be.c`` (C-generating back end). + * - | ``cfe_daemon_common.h`` + - | Declarations related to ``cfe_daemon.c`` exposed for utility programs. + * - | ``checking.h`` + - | Fundamental declarations associated with assertion checking. + * - | ``class_decl.h`` + - | Declarations related to ``class_decl.c`` (class declarations + scanning). + * - | ``cmd_line.h`` + - | Declarations related to ``cmd_line.c`` (command-line parsing). + * - | ``const_ints.h`` + - | Declarations related to the manipulation of the internal + representation of integer constants. + * - | ``cp_gen_be.h`` + - | Declarations related to ``cp_gen_be.c`` (C++/C-generating back end). + * - | ``debug.h`` + - | Declarations related to ``debug.c`` (debug output). + * - | ``decl_inits.h`` + - | Declarations related to ``decl_inits.c`` (declaration initializers + scanning). + * - | ``decl_spec.h`` + - | Declarations related to ``decl_spec.c`` (declaration specifiers + scanning). + * - | ``declarator.h`` + - | Declarations related to ``declarator.c`` (declarator scanning). + * - | ``decls.h`` + - | Declarations related to ``decls.c`` (declarations scanning). + * - | ``def_arg.h`` + - | Declarations related to ``def_arg.c`` (default argument scanning). + * - | ``defines.h`` + - | A place to put ``#define``\ s to configure the front end; + ``defines.h`` is included at the beginning of every source file. + * - | ``direct_allocator.h`` + - | Declaration and definition of the ``Direct_allocator`` template. + * - | ``disambig.h`` + - | Declarations related to ``disambig.c`` (C++ expression-declaration + disambiguation). + * - | ``error.h`` + - | Declarations related to ``error.c`` (error reporting). + * - | ``err_codes.h`` + - | Definition of the enumeration of error codes. This file is generated + from the ``error_msg.txt`` file. See :ref:`mk-errinfo`. + * - | ``err_data.h`` + - | Definition of the enumeration of error codes. This file is generated + from the ``error_msg.txt`` and ``error_tag.txt`` files. See + :ref:`mk-errinfo`. + * - | ``expr.h`` + - | Declarations related to ``expr.c`` (expression scanning). + * - | ``exprutil.h`` + - | Declarations related to ``exprutil.c`` (expression scanning + utilities). Also, the data structures used in expression scanning. + * - | ``extasm.h`` + - | Declarations related to ``extasm.c`` (GNU C extended asm statement + scanning). + * - | ``fe_init.h`` + - | Declarations related to ``fe_init.c`` (initialization). + * - | ``fe_wrapup.h`` + - | Declarations related to ``fe_wrapup.c`` (termination). + * - | ``fixed_pt.h`` + - | Declarations related to ``fixed_pt.c`` (manipulation of fixed-point + constants). + * - | ``float_pt.h`` + - | Declarations related to ``float_pt.c`` (manipulation of floating-point + constants). + * - | ``float_type.h`` + - | Definitions of floating-point conversion routines used when + ``USE_HOST_FP_CONVERSION_ROUTINES`` is FALSE. This header file is + included multiple times (once for each distinct floating-point type) + by ``floating.c``. + * - | ``floating.h`` + - | Declarations related to ``floating.c`` (software-based conversion of + floating-point values between binary and decimal). + * - | ``folding.h`` + - | Declarations related to ``folding.c`` (folding of constant + operations). + * - | ``func_def.h`` + - | Declarations related to ``func_def.c`` (processing for function + definitions). + * - | ``header_util.h`` + - | General utility components (mostly templates) intended for use in both + headers and compilation units. + * - | ``host_envir.h`` + - | Declarations related to ``host_envir.c`` (definition of the host + environment, including operating system dependencies). Also, many + host configuration switches. + * - | ``host_util.h`` + - | Definitions of host environment functions that are used by both the + front end and utility programs such as the prelinker. When the front + end is compiled, these routines are included as part of + ``host_envir.c``. + * - | ``ifc_map.h`` + - | Automatically-generated type declarations and definitions for + interacting with the IFC modules format. + * - | ``ifc_map_functions.h`` + - | Automatically-generated function declarations for interacting with the + IFC modules format. + * - | ``ifc_modules_inst.h`` + - | Automatically-generated macro invocations to facilitate instantiations + in ``ifc_modules_templ.c``. + * - | ``ifc_modules_internal.h`` + - | Declarations related only to the internal + implementation files for IFC modules file support. + * - | ``ifc_modules_spec.h`` + - | Automatically-generated macro invocations to facilitate explicit + specializations in ``ifc_modules_templ.c``. + * - | ``ifc_modules.h`` + - | Declarations related to IFC modules files. + * - | ``il.h`` + - | Declarations related to ``il.c`` (intermediate language). + * - | ``il_alloc.h`` + - | Declarations related to ``il_alloc.c`` (allocation of intermediate + language entities). + * - | ``il_def.h`` + - | The definition of the intermediate language. + * - | ``il_display.h`` + - | Declarations related to ``il_display.c`` (display of intermediate + language in human-readable form). + * - | ``il_file.h`` + - | Declarations related to the structure of the intermediate language + file. + * - | ``il_read.h`` + - | Declarations related to ``il_read.c`` (reading the intermediate + language file). + * - | ``il_to_str.h`` + - | Declarations related to ``il_to_str.c`` (creating external string-form + representations for certain IL entries). + * - | ``il_walk.h`` + - | Declarations related to ``il_walk.c`` (walking the intermediate + language tree). + * - | ``il_write.h`` + - | Declarations related to ``il_write.c`` (writing the intermediate + language file). + * - | ``inline.h`` + - | Declarations related to ``inline.c`` (minimal inlining for IL + lowering). + * - | ``interpret.h`` + - | Declarations related to ``interpret.c`` (IL interpreter for + ``constexpr`` functions). + * - | ``lang_feat.h`` + - | Declarations of configuration switches that affect the source language + accepted. + * - | ``layout.h`` + - | Declarations related to ``layout.c`` (class object layout). + * - | ``lexical.h`` + - | Declarations related to ``lexical.c`` (source input and lexical + scanning). Also, the definition of the data structures related to the + current input line. + * - | ``lint.h`` + - | A place to put directives to silence the ``lint`` program. + * - | ``literals.h`` + - | Declarations related to ``literals.c`` (conversion of literal + constants). + * - | ``lookup.h`` + - | Declarations related to ``lookup.c`` (name lookup). + * - | ``lower_c99.h`` + - | Declarations related to ``lower_c99.c`` (C99 IL lowering). + * - | ``lower_eh.h`` + - | Declarations related to ``lower_eh.c`` (IL lowering of exceptions). + * - | ``lower_il.h`` + - | Declarations related to ``lower_il.c`` (IL lowering). + * - | ``lower_init.h`` + - | Declarations related to ``lower_init.c`` (IL lowering of + initializations). + * - | ``lower_name.h`` + - | Declarations related to ``lower_name.c`` (name mangling for IL + lowering). + * - | ``macro.h`` + - | Declarations related to ``macro.c`` (macro definition and invocation). + * - | ``mem_manage.h`` + - | Declarations related to ``mem_manage.c`` (memory management). + * - | ``mem_tables.h`` + - | Declarations related to the memory management data structure. + * - | ``modules.h`` + - | Declarations related to the processing of module files. + * - | ``ms_attrib.h`` + - | Declarations related to Microsoft attribute processing. + * - | ``ms_metadata.h`` + - | Declarations related to ``ms_metadata.cpp`` (reading C++/CLI metadata + from assemblies). + * - | ``overload.h`` + - | Declarations related to ``overload.c`` (overload resolution for + expression processing). + * - | ``pch.h`` + - | Declarations related to ``pch.c`` (precompiled header processing). + * - | ``pragma.h`` + - | Declarations related to ``pragma.c`` (processing of ``#pragma`` + directives). + * - | ``preproc.h`` + - | Declarations related to ``preproc.c`` (preprocessing directives). + * - | ``scope_stk.h`` + - | Declarations related to ``scope_stk.c`` (scope stack management). + * - | ``src_seq.h`` + - | Declarations related to ``src_seq.c`` (source sequence list + management). + * - | ``statements.h`` + - | Declarations related to ``statements.c`` (statement scanning). Also, + the definition of the statement stack. + * - | ``symbol_ref.h`` + - | Declarations related to ``symbol_ref.c`` (symbol references). + * - | ``symbol_tbl.h`` + - | Declarations related to ``symbol_tbl.c`` (symbol table). Also, the + definitions of the symbol table and the scope stack. + * - | ``sys_predef.h`` + - | Declarations related to ``sys_predef.c`` (system-specific predefined + macros). Also declarations related to builtins (and the place to add + user-defined builtins). + * - | ``targ_def.h`` + - | Declarations that define default target machine characteristics, and + target configuration switches. + * - | ``target.h`` + - | Declarations of target configuration variables, initialized to default + values defined in ``targ_def.h``. + * - | ``target_cfg.h`` + - | Definitions of target-specific routines to set and dump target + configurations (included once for each target configuration). + * - | ``target_map.h`` + - | Definition of various routines that map target-specific configuration + macros to global variables in some fashion (included multiple times). + * - | ``templates.h`` + - | Declarations related to ``templates.c`` (class and function + templates). + * - | ``trans_copy.h`` + - | Declarations related to ``trans_copy.c`` (copying of secondary + translation unit IL to primary IL). + * - | ``trans_corresp.h`` + - | Declarations related to ``trans_corresp.c`` (establishment of + correspondences between translation units). + * - | ``trans_unit.h`` + - | Declarations related to ``trans_unit.c`` (driver for translation-unit + processing). + * - | ``types.h`` + - | Declarations related to ``types.c`` (utility routines dealing with + types). + * - | ``util.h`` + - | General utility components. This contains a set of (mostly templated) + utilities that are used in place of those that would normally be found + in a C++ standard library. The declarations are conditionally + enclosed in the ``edg`` namespace (under control of the + ``USE_EDG_NAMESPACE`` configuration macro). + * - | ``version.h`` + - | Definition of the current version number of the front end. + * - | ``walk_entry.h`` + - | Routines used by ``il_walk.c`` to walk through IL entries. + * - | ``attribute.c`` + - | Scanning of attributes. + * - | ``c_gen_be.c`` + - | The C-generating back end (for use in place of a "real" back end; + generates C code which can be compiled by a native target compiler). + * - | ``cp_gen_be.c`` + - | The C++/C-generating back end (for use in source-to-source + transformation). + * - | ``cfe.c`` + - | The main program for the front end. + * - | ``cfe_daemon.c`` + - | The main program for the front end when built as a daemon.. + * - | ``class_decl.c`` + - | Class declarations scanning. + * - | ``cmd_line.c`` + - | Command-line processing. + * - | ``const_ints.c`` + - | Manipulation of the internal representation of integer constants. + * - | ``debug.c`` + - | Debug control routines. + * - | ``decl_inits.c`` + - | Declaration initializers scanning. + * - | ``decl_spec.c`` + - | Declaration specifiers scanning. + * - | ``declarator.c`` + - | Declarator scanning. + * - | ``decls.c`` + - | Declarations scanning. + * - | ``def_arg.c`` + - | Default argument caching and rescanning. + * - | ``disambig.c`` + - | C++ expression-declaration disambiguation. + * - | ``error.c`` + - | Error reporting. + * - | ``expr.c`` + - | Expression scanning. + * - | ``exprutil.c`` + - | Utilities for expression scanning. + * - | ``extasm.c`` + - | Scanning of GNU C extended asm statement. + * - | ``fe_init.c`` + - | Overall initialization. + * - | ``fe_wrapup.c`` + - | Overall termination. + * - | ``fixed_pt.c`` + - | Manipulation of fixed-point constants: conversion to and from internal + form and conversions and operations on the internal form. + * - | ``float_pt.c`` + - | Manipulation of floating-point constants: conversion to and from + internal form and conversions and operations on the internal form. + * - | ``floating.c`` + - | Conversion of floating-point values between binary and decimal + formats. Used only when ``USE_HOST_FP_CONVERSION_ROUTINES`` is + FALSE. + * - | ``folding.c`` + - | Folding of constant operations. + * - | ``func_def.c`` + - | Processing for function definitions. + * - | ``host_envir.c`` + - | Handling of host-environment dependencies (e.g., file name rules and + opening of files). + * - | ``ifc_map_functions.c`` + - | Automatically-generated function definitions for interacting with the + IFC modules format (that do not fit into one of the more specific IFC + map functions files). + * - | ``ifc_map_functions_acc.c`` + - | Automatically-generated accessor function definitions for interacting + with the IFC modules format. + * - | ``ifc_map_functions_dbg.c`` + - | Automatically-generated debug functions for debugging objects of types + declared in ``ifc_map.h``. + * - | ``ifc_map_functions_mut.c`` + - | Automatically-generated mutator function definitions for interacting + with the IFC modules format. + * - | ``ifc_map_functions_val.c`` + - | Automatically-generated validation function definitions for validating + objects of types declared in ``ifc_map.h``. + * - | ``ifc_modules.c`` + - | Handling of operations common to reading and writing IFC module files. + * - | ``ifc_modules_read.c`` + - | Handling of reading IFC modules files. + * - | ``ifc_modules_templ.c`` + - | Template definitions and explicit instantiations shared by + ``ifc_modules.c`` and the IFC map functions files. + * - | ``ifc_modules_write.c`` + - | Handling of writing IFC modules files. + * - | ``il.c`` + - | Low-level manipulation of intermediate language constructs. + * - | ``il_alloc.c`` + - | Allocation and initialization of intermediate language constructs. + * - | ``il_display.c`` + - | Display of the intermediate language in human-readable form. + * - | ``il_read.c`` + - | Reading the intermediate language from a file. + * - | ``il_to_str.c`` + - | Creating textual representations for certain IL entries + (e.g., constants, types). + * - | ``il_walk.c`` + - | Walking the in-memory intermediate language tree. + * - | ``il_write.c`` + - | Writing the intermediate language to a file. + * - | ``inline.c`` + - | Minimal inlining of function calls for IL lowering. + * - | ``interpret.c`` + - | IL interpreter for ``constexpr`` functions. + * - | ``layout.c`` + - | Laying out class objects. + * - | ``lexical.c`` + - | Source input and lexical scanning. + * - | ``literals.c`` + - | Conversion of literal constants to internal form. + * - | ``lookup.c`` + - | Name lookup. + * - | ``lower_c99.c`` + - | IL lowering from C99 to C89. + * - | ``lower_eh.c`` + - | IL lowering of exception handling constructs. + * - | ``lower_il.c`` + - | Intermediate language lowering (C++ constructs are translated to C + constructs). + * - | ``lower_init.c`` + - | IL lowering of initializations, new/delete, and + constructors/destructors. + * - | ``lower_name.c`` + - | Name mangling for IL lowering. + * - | ``macro.c`` + - | Definition of macros (``#define`` directive) and invocation + (expansion) of macros. + * - | ``mem_manage.c`` + - | Memory management (dynamic allocation of storage). + * - | ``modules.c`` + - | Generic module file processing. + * - | ``ms_attrib.c`` + - | Processing of Microsoft attributes. + * - | ``ms_metadata.cpp`` + - | Processing of C++/CLI metadata from assemblies. Contains C++ source + code that can only be compiled on a Microsoft Windows platform. + * - | ``overload.c`` + - | Overload resolution for expression processing. + * - | ``pch.c`` + - | Precompiled header processing. + * - | ``pragma.c`` + - | Processing of ``#pragma`` directives. + * - | ``preproc.c`` + - | Preprocessing directives. + * - | ``scope_stk.c`` + - | Management of the scope stack. + * - | ``src_seq.c`` + - | Management of source sequence lists. + * - | ``statements.c`` + - | Statements scanning. + * - | ``symbol_ref.c`` + - | Processing for symbol references. + * - | ``symbol_tbl.c`` + - | Symbol table entry and look up, maintenance of name scoping. + * - | ``sys_predef.c`` + - | Definitions of system-specific predefined macros and assertions. + * - | ``target.c`` + - | Target configuration support. + * - | ``templates.c`` + - | Declaring and instantiating class and function templates. + * - | ``trans_copy.c`` + - | Copying of secondary translation unit IL to the primary IL. + * - | ``trans_corresp.c`` + - | Establishment of correspondences between externally-linked entities in + different translation units. + * - | ``trans_unit.c`` + - | Driver for translation-unit processing. + * - | ``types.c`` + - | Utility routines dealing with types. + * - | ``unicode_name_fsm.c`` + - | Automatically-generated data file for a finite state machine that + recognizes Unicode character names. + * - | ``error_msg.txt`` + - | Contains the definition of the error codes and error messages and is + used to generate ``err_codes.h`` and ``err_data.h``. See + :ref:`mk-errinfo`. + * - | ``error_tag.txt`` + - | May be used to provide additional error "tags" or aliases that may be + used to reference a given error message in certain command line + options. This is used to generate ``err_data.h``. See + :ref:`mk-errinfo`. + +Note that in general the files are paired. A ``.h`` file containing +declarative information corresponds to a ``.c/.cpp`` file containing +executable code. The file *name*\ ``.h`` contains the declarations of the +data structures and externally-callable routines for the file *name*\ +``.c``, and is, in effect, the definition of the external interface to that +source file. + +There are also some ``.h`` files that contain configuration information and are +not paired with a ``.c`` file (e.g., ``targ_def.h``). + +In addition, there is a set of ``.h`` files that contain ``#include``\ s of +other header files. Their purpose is to group header files -- both to help +manage their often complicated interactions and to make better use of +compilation systems that perform header precompilation. + +.. list-table:: + + * - | ``basic_hdrs.h`` + - | Header files devoted to configuration. + * - | ``fe_common.h`` + - | Header files common to all ``.c`` files. + * - | ``decl_hdrs.h`` + - | Header files used for declaration processing. + * - | ``expr_hdrs.h`` + - | Header files used for expression processing. + * - | ``lower_hdrs.h`` + - | Header files used for IL lowering. + +In rough numbers, the ``.h`` files together are about 320,000 lines, and the +``.c`` files about 1,017,000 lines (including IL lowering, the IL display +utility, and the C- and C++-generating back ends). The utility programs are +another 15,000 lines, and the minimal runtime about 11,000 lines. + +Coding Philosophy +================= + +This section contains miscellaneous information on the coding style and +philosophy used in writing the front end, which may be useful to those who must +maintain it. + +The configuration section of a previous chapter of this document contains some +important information of this type. + +Code should conform to the C++11 standard and not have any dialect-specific +constructs [#f1]_. The environment dialect switches ``__ANSIC__``, +``__SYSV__``, and ``__BSD__`` should used to control inclusion of header files +that are not available in all versions of C++. ``basics.h`` (which should be +included first in every compilation) takes care of the most common header files +and the most common library routines (it will remap them via macros if +necessary). + +The size argument on calls of functions like ``memcpy`` should be wrapped in a +call of the function-like macro ``size_t_arg`` if the size is anything other +than a ``sizeof`` operator. + +Code that is host-dependent should be written only in ``host_envir.c`` and +``cmd_line.c``. + +Target-dependent code should not be written outside of ``const_ints.c``, +``fixed_pt.c`` and ``float_pt.c`` (which are heavily target-dependent) and +``literals.c``, ``folding.c``, and ``layout.c`` (which have some +target-dependent aspects). In particular, be careful about doing anything with +integers without going through the routines in ``const_ints.c``. + +External Names +-------------- + +External routines should always be declared both where the body occurs and in +the corresponding ``.h`` file. The ``.h`` file should be included everywhere +the routine is referenced. + +External variables should be declared in ``.h`` files with ``EXTERN`` as their +storage class. All ``.h`` files that contain external variables must be +included in ``fe_init.c``; there, the macro ``EXTERN``, which ordinarily is +mapped to ``extern``, is mapped to a null string. This makes the same +declarations, when scanned in ``fe_init.c``, external definitions instead of +external references. If an external variable should have an initial value, the +initialization should be included in the ``.h`` file, surrounded by ``#if +VAR_INITIALIZERS``/``#endif``. In ``fe_init.c`` the initializer will be +included. + +Of course, variables should be made ``static`` instead of external if it is +possible to localize them to a single source file. + +All static variables (external, internal, and function-local) must be saved and +restored as necessary when precompiled headers are generated. The point at +which a precompiled header is written or read is outside of any declaration and +at the file scope (etc.); variables that never have interesting values at such +points need not be saved and restored. All others, however (and these cannot +be function-local), must be registered by calling +``register_pch_saved_variables`` so that they will be written to the +precompiled header file and restored. + +Likewise, variables that are translation-unit specific should be registered by +calling ``register_trans_unit_variable``. See the :ref:`multi-tu` chapter. + +Include Files +------------- + +Include files always include any other files on which they depend. They also +define a flag once they have been included, and will skip themselves if +included again. (For example, ``cmd_line.h`` defines ``CMD_LINE_H``). +Therefore, one can include the files in any order and without regard for +whether or not they have been included by other include files. To improve +compilation speed, ``#include``\ s can be surrounded by ``#ifndef`` +*flag*/``#endif``. + +Debug Code +---------- + +Debug code is surrounded by ``#if DEBUG``/``#endif``. In such code, one should +test the value of ``debug_level`` to control output of debug information. +``debug_level`` is zero ordinarily, to indicate that no debug output should be +produced. Debug code should be set to come out at an appropriate level: ``1`` +is for output that comes out once per source line, ``3`` for output that comes +out once per token, and ``5`` for output one would hardly ever want to see. +``2`` and ``4`` lie in between those levels in the expected way. Choosing an +appropriate debug level is more of an art than a science. If in doubt, make a +guess at the best level, run the front end with that level of debug output, and +see if the new messages seem out of place in the overall debug output at that +level. + +One can also use ``db_flag_is_set`` to determine whether specific output should +be generated. For example, calls of ``db_flag_is_set("vtbl")`` are used in IL +lowering to control debug output related to virtual function tables. By +specifying ``-d-vtbl`` on the command line, one can get that particular debug +output and nothing else. A particular "flag" is considered set if the string +of the ``db_flag_is_set`` call is specified in a command-line debug option, so +a new "flag" is added by adding a call of ``db_flag_is_set`` with some new +string; there is no central registry of debug "flags." + +A similar facility for tracing names is provided by the ``--db_name=``\ *xxxx* +command-line option and the ``db_has_traced_name`` macro. This can be used to +control extra output about processing of entities with specific names. +``db_trace`` provides a combination of the features of ``db_flag_is_set`` and +``db_has_traced_name``. + +Debugging options that are specified with the ``-d`` command-line option can +also be specified using the ``db_opt`` pragma. The pragma can be used to +specify a certain debug level or to define a certain debug flag for a portion +of a source program that is being compiled. For example: + +.. code:: c++ + + template void f() { + #pragma db_opt -nondep_call + g(); + #pragma db_opt #nondep_call + } + +When a flag name is preceded by "``#``", the flag is cleared if previously set. + +Debugging options that are specified with the ``--db_name`` command-line option +can also be specified using the ``db_name`` pragma. + +The variable ``db_active`` is TRUE if ``debug_level`` is non-zero or if there +is the potential for it becoming non-zero (i.e., if there is a list of debug +requests from the command line). This can be used to control processing that +may be needed when debug output is generated, but should not be done when no +debugging is requested. + +Diagnostic messages should be written to ``f_error``. This is normally set to +``stderr``, but in some modes is set to ``stdout``, and can be redirected to a +file by use of a command-line option. Debug output should be written to +``f_debug``. This is set to ``f_error``, but is a separate file variable to +allow it to be changed if desired. + +Entries and exits of routines should have calls to ``db_enter`` and +``db_exit``. These provide flow tracing. The ``db_enter`` call looks like + + | ``db_enter(``\ *level*\ ``, "``\ *routine-name*\ ``");`` + +The ``db_exit`` call has no arguments. These calls will cause an entry +message and an exit message when ``debug_level`` is equal to or greater +than the *level* specified. Note that the calls need not be surrounded by +``#if DEBUG``/``#endif``; ``db_enter`` and ``db_exit`` are actually macros, +and when ``DEBUG`` is ``0``, they are defined as null strings. When +``DEBUG`` is non-zero, they expand to calls to ``debug_enter`` and +``debug_exit``. Those calls are surrounded by ``if``\ s testing +``db_active`` so that the routine calls are only done when debug output is +actually being generated (or may be generated, when a list of +routine-related debug requests is specified on the command line). + +It should be clear that for ``db_exit`` to work correctly one should have a +single exit point for each routine, and not have ``return`` statements in the +middle of routines. + +Some routines do not have ``db_enter`` and ``db_exit`` calls for speed +reasons -- even the overhead of two ``if``\ s would be visible. An example is +``skip_white_space`` in ``lexical.c``. + +Checking Code +------------- + +Checking code performs dynamic consistency checking, e.g., verifying the entry +conditions for routines and the consistency of tables. Checking code is always +surrounded by ``#if CHECKING``/``#endif``. When a problem is found, this code +calls + + | ``internal_error("``\ *routine-name*\ ``:`` *problem found*\ ``");`` + +which displays the argument string and causes abnormal termination of the front +end. + +As a concrete example of checking code: *all* ``switch`` statements should +have a default clause; if the default clause does not correspond to any +legal possibility, it should be present as checking code, and should call +``internal_error`` to indicate that a bad value appeared as the switch +selector. (See ``CHECK_SWITCH_DEFAULT_UNEXPECTED`` in ``basics.h`` and +``default_is_unexpected`` in ``checking.h`` for macros that assist in +applying this rule.) + +Several routines are provided as convenient ways to do consistency +checking. Calls of these routines need not be surrounded by ``#if +CHECKING``/``#endif``; they are defined as macros that expand to nothing +when ``CHECKING`` is disabled. ``check_assertion`` can be used to check an +expression to make sure it is true. ``expect_error`` checks that +``total_errors`` is nonzero at the point of invocation or that it becomes +nonzero before the end of the compilation. This is useful to ensure that +situations that are expected to lead to error diagnostics will indeed do so +(only the first invocation will be reported on failure). +``check_assertion_or_expect_error`` combines the previous two routines: it +has no effect if either the given condition is TRUE, or if ``total_errors`` +is nonzero by the end of the compilation. ``unexpected_condition`` is used +when a piece of code is not expected to be reached (for example, the +default clause of a switch). Three versions of each of these routines are +provided: the version described above, a version with a ``_str`` suffix +that accepts a single string argument, and a version with a ``_str2`` +suffix that accepts two strings. The string(s) are printed on error +termination to provide additional information about the cause of the error. + +The consistency checks that are enabled by the ``CHECKING`` flag do not +significantly affect the performance of the front end. There are other +consistency checks whose execution does affect the performance of the front +end. These extra consistency checks are enabled by the ``EXPENSIVE_CHECKING`` +flag. These checks are not intended to be enabled when optimum performance is +required (e.g., in production versions of a product). + +Conventions for Declarations +---------------------------- + +The type ``a_boolean`` (defined by default as ``int``) should be used for +true/false variables, along with the constants ``TRUE`` and ``FALSE``. +These are defined in ``basics.h`` and thus are available everywhere. In +``struct``\ s, ``a_byte_boolean`` is used for boolean fields when there is +just one of them. When there are several, bit fields of length one are +used, to save space. Obviously, these rules will not work on all host +machines, but they will work well enough on most. + +Fields in ``struct``\ s are ordered to some extent to reduce the space wasted +in gaps for alignment. It's assumed that pointers and large integers have +similar size and alignment requirements, and thus a sequence of them will leave +no gaps. When small fields appear, however, they are grouped together to avoid +the gaps one would expect from a series of short/long/short/long fields. + +Bit fields are declared with the type ``a_bit_field``. It is usually +``unsigned int``, but when compiling with a compiler that uses the Microsoft +bit-field layout algorithm it can be set to ``unsigned char`` to get better +packing of the bit fields. + +The type ``a_byte`` should be used for small integer fields (i.e., fields +whose values lie in the range 0-127), rather than ``char`` or ``unsigned +char``. ``enum`` types are often given a base type of ``a_byte`` so that +their size is explicitly controlled to save space in ``struct``\ s. + +For each table type (whether or not it is part of the intermediate +language) there is an associated allocation routine and an associated +routine that will set the fields of the table to default values. (In some +cases, these two functions are provided by one routine.) When a table has a +variant section and an associated tag field, there is also a routine to set +the tag field and set the associated variant fields to default values. A +tag field should never be assigned directly; it should only be set by this +routine. Consistent use of the allocation, clear, and set-kind routines +ensures that no uninitialized fields will cause sporadic problems, and that +new fields can be easily added. In addition, it can be useful to add the +following snippet to ``defines.h`` : + +.. code:: c++ + + #if UNION_AS_STRUCT + #define union struct + #endif + +Setting ``UNION_AS_STRUCT`` in a testing build allocates each variant field +in its own storage. This often allows detection of cases where code +accesses an incorrect variant for a given IL entry. + +The names of macros are written in upper case in the front end source when they +are object-like (e.g., manifest constants), but in lower case when they are +function-like. The names of types and enumerators are written in lower case. + +The names of ``typedef``\ ed, class, and templated types always begin with +``a_`` or ``an_`` (e.g., ``a_type``, ``an_expr_node``). Pointer type names +end in ``_ptr``. The names of constants in enumerations always begin with +a prefix that hints at the enumeration type (e.g., ``enk_`` for +``an_expr_node_kind``). + +Storage Allocation +------------------ + +Allocation of space is never done by calling ``malloc`` or the like directly. +For all table entries, as mentioned earlier, the associated allocation routine +should be called. It will allocate and clear the space, and will also make +sure that the space is allocated in the right area (e.g., intermediate language +constructs must be allocated in the right memory region). For any other +allocation cases, one of the routines in ``mem_manage.c`` should be called +instead. ``alloc_fe`` has an interface like ``malloc``, and allocates storage +that need not survive the execution of the front end. ``alloc_general`` is +similar, and allocates storage that will survive into the back end if the back +end is called as part of the same program (this should not be used ordinarily). + +One case to do carefully: all names that become part of the intermediate +language (file names, directory names, identifier names) should be allocated in +the file-scope intermediate language region, by calling ``alloc_il``. + +Space is never freed by calling ``free`` or related routines. Where tables are +reused, the front end maintains individual lists of available entries for each +type of table, and takes entries off those lists before allocating new ones. +Space can be released on a memory region basis, for example to free up all the +space used for a given function once the function has been processed. When the +front end is configured in such a way that it can be re-initialized (by setting +``MAKE_FRONT_END_CALLABLE``) the front end keeps a record of all memory +allocations and automatically frees the memory when the front end terminates. + +In general, every reasonable attempt is made to not allocate tables unless they +are actually needed. The intermediate language, for example, will contain some +wasted space, but extremely little. + +In order to avoid any fixed limits in the front end, the primary non-IL data +structures are designed so they can be dynamically allocated and expanded +(``curr_source_line``, ``scope_stack``, etc.). An initial allocation is done +that should cover all expected uses; if more space is needed, the table is +reallocated with a larger size. That means that there is a danger inherent in +keeping around pointers into those data structures, because if the table moves, +all pointers to the table become obsolete. In the input line/macro area, such +pointers are necessary, and there is a pointer registration scheme that is used +to make sure that all pointers are updated if a reallocation occurs. In other +areas, pointers can be avoided relatively easily. A simple rule to remember is +that one should never make a local pointer into one of the primary stacks +(``scope_stack``, ``struct_stmt_stack``); one should instead use an index value +into the stack, since an index is not invalidated by a reallocation of a table. +When memory is allocated that may later be resized, it must initially be +allocated using either ``alloc_resizable_buffer`` or ``realloc_buffer``. It +may then be resized later by calling ``realloc_buffer``. + +One can get a summary of space use by having ``debug_level`` non-zero in +``fe_wrapup``. This can be requested by specifying ``-dfe_wrapup=1`` on the +command line. A summary of symbol table and constant sharing efficiency is +also included. + +Typerefs +-------- + +The ``a_type`` IL entry can have a ``tk_typeref`` kind; such entries +represent a type that is based on another type in some way. For example, a +``typedef`` is represented by a typeref entry designating the type for +which it is a synonym. Similarly, cv-qualified types like ``const int`` are +represented by a ``const`` typeref pointing to the entry for the ``int`` +type. Additional uses for typerefs include type operators like +``decltype``, capturing the specific template arguments used when a +class or alias template specialization is referred to, and many others. + +In general, typerefs do not have complete information about the type they +represent, such as the size and alignment. As a result, it is often +necessary to access the type on which a given typeref is based, and +various macros and functions are provided for that operation, such as +``skip_typerefs``, ``skip_lexical_typerefs``, +``skip_typerefs_not_typedefs``, etc. It is a common source of bugs to +omit a call to one of these functions and operate on the typeref itself +instead of its underlying type. + +See the :ref:`il-typerefs` section in the Intermediate Language +chapter for further details. + +Source Positions +---------------- + +Source positions are represented as a structure of type ``a_source_position`` +(see ``basics.h``). It contains a sequence number and a column number. The +sequence number is a unique number assigned in ascending order to each source +line as it is read. Unlike a file name and line number, the sequence number is +unambiguous. It's also more compact, and can be converted to a file name and +line number for external use (this is done in error messages, for example). + +The column number is a 1-origined character position in the original source +line. The character position is the logical character number in the line, not +simply a byte offset. This is significant if the source file contains +multibyte characters or is in a format such as UTF-16. Tab characters are +counted as a single column. The position of text within a macro expansion is +considered to be the first character of the macro name in the macro call in the +original source line that directly or indirectly generated the text. + +If the front end is configured with ``FULLY_RESOLVED_MACRO_POSITIONS`` set to +TRUE, each source position contains an additional sequence/column number pair. +For text within a macro expansion, this additional position information gives +the location from which the associated text was copied into the macro +expansion, i.e., a macro definition or macro argument. + +If ``MACRO_INVOCATION_TREE_IN_IL`` is configured to TRUE, each source position +referring to text within a macro expansion contains the index of the macro +invocation record that identifies the macro in whose expansion the text at that +position occurs. For text appearing directly in the source, this index will be +``NO_PARENT_MACRO_INVOCATION``. + +A sequence number of zero is used to indicate an unknown position or a +"position" in initialization, in a predefined macro, or in the command-line. +The column number indicates which. See ``basics.h``. + +Importing assembly metadata in C++/CLI is a process that creates a string +containing C++ code that expresses that metadata and then parses the contents +of that string. Each import is associated with a particular sequence number, +and that number is assigned to the position of each token extracted from that +string (with a column number zero). For example, when compiling a C++/CLI +source file, sequence number one will usually correspond to ``mscorlib.dll``. + +Language Dialect +---------------- + +The global variable ``C_dialect`` (in ``cmd_line.h``) indicates the C +dialect to be accepted: the choices are ``C_dialect_cplusplus``, +``C_dialect_ANSI``, and ``C_dialect_pcc``. The macro ``C_mode()`` is +useful as a way of testing for C versus C++. ``cpp``\ *NN*\ ``_mode`` +(where *NN* is the year of the relevant C++ Standard, e.g., ``cpp03_mode``, +``cpp17_mode``, etc.) is TRUE when the features of the corresponding +revision of the language should be accepted, and similarly ``c``\ *NN*\ +``_mode`` for versions of the C language. + +The global variable ``strict_ansi_mode`` is TRUE if use of features that +are not part of the selected C or C++ Standard should cause diagnostics. +``strict_ansi_error_severity`` indicates the level of diagnostic (warning, +discretionary error, or error) that should be produced for such cases. + +``microsoft_mode`` indicates whether a Microsoft dialect (C, C++, C++/CLI, +or C++/CX) is in effect. In configurations that do not allow Microsoft +extensions (i.e., when ``MICROSOFT_EXTENSIONS_ALLOWED`` is FALSE), it is a +macro equivalent to FALSE. This allows many Microsoft-mode-specific bits +of code to be written without surrounding them with conditional compilation +directives testing ``MICROSOFT_EXTENSIONS_ALLOWED``. ``cppcli_enabled`` +and ``cppcx_enabled`` similarly indicate that the Microsoft dialect is +C++/CLI or C++/CX, respectively (if TRUE, ``microsoft_mode`` is TRUE too, +and C_mode() is FALSE). Some C++/CLI- and C++/CX-specific code is +delimited by conditional compilation directives testing +``MICROSOFT_EXTENSIONS_ALLOWED`` because it uses variables, data members, +or functions that are available only when that macro is TRUE. (The macro +``CPPCLI_ENABLING_POSSIBLE`` is tested in a few places for code that deals +with the importing of assembly metadata, but it shouldn't be used to +conditionalize other C++/CLI-specific code. In particular, the IL +extensions representing C++/CLI and C++/CX constructs are only conditioned +on ``MICROSOFT_EXTENSIONS_ALLOWED``.) + +``gpp_mode`` and ``gcc_mode`` indicate that, respectively, GNU C++ or GNU C +emulation is in effect. In configurations where ``GNU_EXTENSIONS_ALLOWED`` is +FALSE, these are macros equivalent to ``FALSE``. + +``clang_mode`` indicates that clang emulation is in effect. Because the +initial emulation of the clang C++ compiler in the front end was very close +to g++, ``clang_mode`` also implies that ``gpp_mode`` or ``gcc_mode`` will +be set. When it is necessary to distinguish between the GNU and clang +emulations, the macros ``gnu_version_is``, ``gpp_version_is``, +``gcc_version_is``, ``clang_version_is``, ``clangcpp_version_is``, and +``clangc_version_is`` (see ``lang_feat.h``) allow finer-grained +discrimination (including the compiler version to be emulated). (There are +also corresponding Microsoft-specific macros, ``ms_version_is``, +``mscpp_version_is``, and ``msc_version_is``.) + +``cfront_2_1_mode`` is TRUE if the cfront 2.1 dialect of C++ is to be compiled. +``cfront_3_0_mode`` indicates the cfront 3.0 dialect. The macro +``any_cfront_mode()`` tests for either of those being set to TRUE. + +(There are other variables/macros that control dialect variations. The ones +mentioned here are among the more frequently used ones.) + +Expression Processing +--------------------- + +See :ref:`rescanning-exprs` for some additional coding rules that apply +only within the expression-processing routines. + +Recursive Descent Parsing +========================= + +"Recursive descent" is an ad-hoc syntax parsing technique. It works well for +languages (like C) where very little lookahead is required to resolve local +ambiguities, and where the language in which the compiler is written is +recursive (as is true for the front end). + +The idea of recursive descent provides a framework and a discipline for parsing +a language, but it is implemented entirely by hand-crafted code. There is +nothing automatic about the parsing. Thus, there is more possibility for error +in developing a recursive-descent parser than there is in developing a +table-driven parser. However, if one writes carefully and tests thoroughly, +the end result is better with a recursive descent parser: faster parsing, +better error recovery, and a clearer compiler (because all of the logic related +to a particular construct appears in one place). + +To implement recursive descent, one writes routines for each non-terminal +construct in the language syntax. For example, one writes a routine to scan an +expression, and one to scan a statement, and one to scan a declaration. The +internal structure of these routines looks a great deal like the syntax of the +constructs they implement. For example, if a declaration is defined as a list +of declaration specifiers followed by a declarator followed by a semicolon, the +routine that scans a declaration would call the routine to scan a list of +declaration specifiers, then the routine to scan a declarator, and then check +for and discard a semicolon. Where the language has recursive constructs, the +routines involved will call each other recursively. + +The terminal tokens that are being parsed come from the lexical routines, +specifically from ``get_token``. At any given moment, there is a current +token (``curr_token``). It is the *next* token of input, the one that +hasn't yet been taken. If the token is an identifier or a literal +constant, there is additional information associated with it. See +``lexical.h``. + +As the recursive descent routines parse the input tokens, they build up +information on what they have parsed, in the intermediate language trees and in +the symbol table. They also check for and recover from errors. + +The scanning of expressions is one area where recursive descent is inefficient +for languages (like C) where the expression syntax has many levels. A naive +recursive descent implementation would provide a routine for each level of the +expression syntax, and thus scanning a simple expression would involve perhaps +a dozen subroutine calls. For this reason, the front end uses a modified +recursive descent technique to scan expressions. Internal calls to the +``scan_expr`` routine (in ``expr.c``) specify a precedence level, and the scan +routine can decide whether to call itself recursively or not based on the +relative precedences of adjacent operators. With this modification, the number +of calls is reduced to very nearly one per operator. See the description of +``expr.c`` later in this document for more detail. + +To reduce the possibilities for errors in writing the parsing routines, one +should not check for the start of constructs by checking directly for all the +possible first tokens in that construct. Such a list of tokens is inherently +error-prone. For constructs of this kind, there are functions that will +indicate whether or not the current token looks like the start of the construct +(see, for example, ``is_decl_start`` in ``decls.c``). Such routines might +themselves call other ``is_``\ *xxx*\ ``_start`` routines if the constructs can +themselves begin with other complex constructs. + +Several utility routines in ``lexical.c`` are useful for recursive descent +parsing. ``required_token`` can be used to check for and discard a required +token, and to issue a specific error message if the token is not present. +``loop_token`` is used to check (at the bottom of the loop implementing an +iterative syntactic construct) for the occurrence of a particular token. The +token is taken if found, but no error is given if the token is not found. +``next_token`` is useful for doing a limited kind of lookahead: it will return +the kind of the token following the current token, without actually getting +that token (actually, it gets it and then puts it back). In many cases, that +one token is enough to allow a decision to be made at a fork in the syntax. +See, for example, the code that recognizes statement labels in ``statement`` in +``statements.c``. + +Consult any of the popular books on compiler theory for a more detailed +overview of recursive descent. + +Error Recovery +============== + +When the front end discovers an error, it has several goals: + +* | To describe the error clearly and indicate its position (including the + position within the source line); +* | to recover from the error without generating extra errors; +* | to preserve as much information as possible about the valid parts of the + construct containing the error, so that detection of other errors is not + needlessly compromised. + +("Error" here of course refers to remarks and warnings as well.) + +Describing an error clearly requires that one not only detect the error, but +detect it at an appropriate level, so that the front end can guess better at +what was intended. Sometimes this requires clever code at decision points in +recursive descent parsing, so that on invalid constructs one goes to the more +likely of two subcases. Within the ``{ }`` for a ``struct``, for example, we +have a series of member declarations separated by semicolons. If a semicolon +is missing, one should not fall out of the loop and leave the scanning of the +``struct``. In other situations, clearly invalid cases should be flagged at +the higher level, and none of the subcases should be entered. For example, at +the beginning of a statement or a declaration, if the first token is not a +valid start for that construct, an error message ("expected a statement" or +"expected a declaration") is more informative than descending into any of the +subcases and letting them issue errors. + +Error Positions +--------------- + +The position of an error is often just as important as the error text. The +front end tries to give useful error positions. This is aided by the fact that +column positions are maintained for each token. A global variable +``error_position`` indicates the position of the beginning of the last language +construct scanned. It is set by ``get_token`` on scanning each token, and it +is also set by each medium-sized language construct (e.g., an expression, a +declarator). Most recursive descent routines save the position of the first +token of the construct they scan, and then set ``error_position`` to that +position on return. ``error_position`` is the default position for errors when +no explicit position is specified, and this protocol for setting it works well +in ensuring that the error positions are right. Some cases take extra work. +For example, in the expression routines, the position of the left operand and +right operand, and the position of the operator itself, are known for each +operation. If an error is due to a problem with one of the operands, the error +position used is the position of that operand. If the problem is with the +combination of those operands (as in adding a pointer and a float), the error +position used is the position of the operator. + +The macro ``set_err_pos_to_curr_token`` is used when one is going forward in +scanning. It sets the error position to the position of the current token. +One would use it, for example, when looking for the ``=`` that indicates an +initializer in a declaration. The previous construct (a declarator) has been +scanned and checked, and its position is in ``error_position``. Now, however, +we are going forward, and the ``=`` that may have ended the expression scan +should once again be the current construct. In practice, there are few cases +like this; they only come up for optional tokens in the middle of constructs. +``required_token`` handles the change of error position in the more usual case +of a required token. + +When an error refers back to something earlier in the source, it often makes +sense to give the position of the other location rather than the current +location. Variables declared but never used, for example (a warning), are +detected at the closing brace of functions. However, that position is much +less informative than the position of the declaration of the variable in +question, so that is used. Likewise, when a comment is unclosed at end of +file, it is more useful to indicate the position of the start of the comment +instead of the location of the end of file, where the error was detected. + +Error Codes +----------- + +Error messages are mapped to values of the enumeration ``an_error_code`` (see +``err_codes.h``, along with ``err_data.h`` for the associated error message +text). For example, ``ec_exp_line_number`` represents the message "expected a +line number". ``ec_no_error`` is first in the enumeration, and therefore has +the value zero. Thanks to it, one can return error codes of type +``an_error_code``, and test them in ``if`` statements (non-zero means an +error). + +Errors with codes beginning ``ec_exp_`` (and texts beginning "expected a ...") +are uniformly syntax errors -- some expected token or construct was not found. + +The severity of an error is determined by the error routine called (e.g., +``error`` instead of ``warning``) and not by the error code. In fact, there +are cases where the same error code is used as both a warning and an error. +The severity of certain diagnostic messages may be overridden using a command +line option. A diagnostic that is issued with a severity that is less than an +error (i.e., remark, warning, or discretionary error) may have its severity +changed, or may be suppressed completely. + +Some error message texts have fill-ins, as in + + | ``could not open source file "``\ *name*\ ``"`` + +For these, variants of the error routines should be called. For the case +above, for example, ``str_error`` would be called. The fill-in string is +passed to the error routine as a null-terminated string, and replaces +``%s`` where it appears in the error text string. See +:ref:`error-reporting` for details on the kinds of fill-ins available. + +Syntax Errors +------------- + +In terms of internal processing, one must distinguish syntax errors from +semantic errors. Syntax errors are discovered when the sequence of tokens +in the source program cannot be parsed according to the language syntax +(for example, ``i=j+;``\ --there's something missing between the ``+`` and +the ``;``). All other errors are semantic errors -- things that can be +parsed but are still nonsensical (for example, use of an undefined +variable, or adding two ``struct``\ s). In error recovery, the important +distinction between the two is that for a syntax error one must decide how +to continue parsing, whereas for a semantic error everything is fine as far +as parsing and there's no question about how to continue. + +Syntax errors should always cause the calling of ``flush_tokens`` in +``lexical.c``, and semantic errors should never call it. The routine +``syntax_error`` records the occurrence of an error, and then calls +``flush_tokens``, which is a convenient combination. + +``flush_tokens`` scans and throws again tokens until it finds one in the +*stop tokens set*, and then returns. Paired tokens are also considered: if +a ``(`` is scanned while flushing tokens, for example, the corresponding +``)`` will be sought before continuing the search for a stop token. There +are some other special cases; see the code in ``lexical.c``. + +The stop tokens set is an array indexed by token kind. Each element of the +array is non-zero if the corresponding token is currently in the stop tokens +set (and thus should halt a flush). As recursive descent routines scan +constructs, they add to the stop tokens set those terminal tokens they expect +to see in their constructs, and then remove those tokens once they are +encountered. The macros ``add_stop_token`` and ``remove_stop_token`` are +called to add and remove tokens from the set by incrementing and decrementing +the associated element of the array. Since syntactic constructs are nested +inside one another, having each recursive descent routine add the tokens it +recognizes produces a stop tokens set that will halt a flush at a token with +which one of the active routines feels it can continue. + +At boundaries where the syntax changes dramatically, ``push_stop_token_stack`` +is called to establish a new set of stop token values. The old values are +restored later by calling ``pop_stop_token_stack``. This is done, for example, +when entering the processing for preprocessing directives, whose syntax is +dramatically different than the context in which they are embedded. + +Uses of ``add_stop_token`` and ``remove_stop_token`` must be very carefully +paired. A missing call of either would probably cause the associated token to +be handled incorrectly in error flushes for the rest of the compilation. +Skipping a ``remove_stop_token`` call is easy to do if one does a ``goto`` out +of an inner loop in a recursive descent routine (say, because there is an +error) and one skips over the point where the ``remove_stop_token`` is done. +The likelihood of such a problem is lessened by having ``debug_enter`` and +``debug_exit`` verify (by means of a checksum) that the contents of +``stop_token_array`` are the same on exit as they were on entry. This check is +only done when debugging is active, however, because it's time-consuming. +Also, ``fe_wrapup`` verifies that all the counts have returned to zero by the +end of the compilation; that check is always done. In addition, when expensive +checking code is enabled, ``pop_stop_token_stack`` verifies that all of the +elements of the stop token set that is being discarded have been reset to zero. + +If ``required_token`` does not find the token it expects, it adds that token to +the stop tokens set, and calls ``syntax_error``. After ``flush_tokens`` +finishes, ``required_token`` checks again to see if the desired token has come +up, and if so, scans over it. + +Error Entries +------------- + +For both syntax and semantic errors, another part of error recovery is +producing something sensible, in spite of the error, in the data structure that +represents the program. This task is eased by having special "error" entries +for all of the major table types. There are, for example, error constants, +error types, and error expression nodes. They are used to take the place of +any part of the program tree that cannot be built because of an error. In +general, the code tries to build as much of the complete tree as possible. An +error in one part of an expression, for example, need not mean that the entire +expression tree will be replaced by an error expression node. Throughout the +front end, code must be capable of dealing with error entries. The basic +philosophy is that an error entry is considered to be compatible with anything +else. No additional errors should be issued on encountering an error entry, +since it is assumed that some error was issued when the entry was created. + +When syntax errors involve missing identifiers, special error symbols are +created. A different error symbol is created for each error case. All error +symbols point to the same special associated symbol header (see the +documentation of ``symbol_tbl.c``). + +When errors involve duplicate declarations of the same symbol, the second +symbol is entered anyway. Both symbols are in the symbol table, but because of +the symbol table structure, the later declaration will the one that is visible, +and it therefore effectively replaces the earlier declaration. + +In general, scanning routines do not need to return indications of success or +failure, since they always return a tree representing the construct scanned. +Some routines must deal with unusual cases where there is no possible +representation for the thing scanned, and so they return an error parameter. +The caller must check it. + +Intelligent Error Diagnosis +--------------------------- + +The front end attempts to diagnose as many errors and warnings as possible. If +one uses header files with function prototypes for all external functions and +variables, it should be possible when writing in ANSI C or in C++ to do away +with ``lint``, or at least to relegate it to use in unusual cases. That is the +goal of the front end: diagnose not only errors but also questionable +constructs such as those flagged by ``lint``. However, since ``lint`` is run +on request and the front end must be run on each compilation, one must take +care that the errors are not overly pedantic. The front end tries to do this +by being selective about errors. It's a good idea, for example, to warn about +value-less ``return`` statements in functions that should return a value. +However, in old-style C, before the keyword ``void`` existed, it was standard +practice to omit the type specifier altogether on a function that returned +nothing. The C language says such a function has type ``int``, but the C +programmer usually thinks of such a function as having type ``void``. So, in +the front end, a warning is issued for a value-less return in a function with +an explicit type, but not for one in a function with an implicit ``int`` type. +In ``pcc`` mode, a warning is never issued. + +A similar issue comes up in expressions. An expression like ``1/0`` looks like +an error (division by zero), but should not necessarily cause a compilation +error. If it occurs in a context where it is not evaluated (such as +``0&&1/0``), it never causes an error; if it occurs in a context where it must +be evaluated at compile time (as in the size of an array), it causes an error; +and if it occurs elsewhere (i.e., in executable code), it causes a warning and +is left as-is to cause a fault (or not) at execution time. + +Likewise, when a constant seems to be part of a bit-oriented operation (it is a +non-decimal constant, or it results from a bit-wise operator applied to +constant operands), the normal warnings about implicit sign changes when the +constant is changed from signed to unsigned or vice-versa are suppressed. + +.. [#f1] Except for ``ms_metadata.cpp`` and its corresponding header: They are + written to be compilable by a current Microsoft C++ compiler and by + the front end in a corresponding Microsoft C++ mode. diff --git a/dev/doc/_sources/lex_pp.rst.txt b/dev/doc/_sources/lex_pp.rst.txt new file mode 100644 index 0000000..9c10a0d --- /dev/null +++ b/dev/doc/_sources/lex_pp.rst.txt @@ -0,0 +1,2138 @@ +================================== +Lexical Analysis and Preprocessing +================================== + +Source Line Data Structure +========================== + +Before describing the routines involved in lexical analysis and preprocessing, +it is necessary to discuss the data structure that represents the current +source line. This data structure is used throughout the lexical routines, and +its form is dictated by the types of processing that must be done in the +lexical and macro routines. The routines and data structures described in this +section are defined in ``lexical.c`` and ``lexical.h``. + +The Current Source Line +----------------------- + +A logical source line, in the ANSI C standard (2.1.2.2), is what results after +trigraphs have been replaced by the corresponding characters (e.g., ``??=`` by +``#``) and line splices have been done (i.e., each line ending with a backslash +is spliced with the following line). The routine ``read_logical_source_line`` +does this processing, and the global array ``curr_source_line`` contains the +result. That is, in ``curr_source_line`` trigraphs have already been replaced, +and several physical source lines may have been spliced into one logical source +line. If any such transformations were made to produce the current source +line, the global variable ``orig_line_modif_list`` points at a list of entries +that describe all the transformations made, in a form such that + +* | the original source lines can be reconstructed from ``curr_source_line``, + if that is necessary (e.g., for error-reporting purposes); and +* | from a location within ``curr_source_line``, one can determine the file + name, line number, and column from which that text came, for + error-reporting purposes. + +.. _lex-src-line-modifications: + +Modifications to the Current Source Line +---------------------------------------- + +When changes to the current logical source line are made because of +preprocessing, they are handled in a different way: ``curr_source_line`` is not +changed (much); instead, the global variable ``source_line_modif_list`` points +to a list of entries that indicate changes that have been made logically to +``curr_source_line``. Each of these changes is a deletion of some number of +characters at a given location, and an insertion of some number of characters +(possibly none) at that location. These entries represent changes due to +deletion of comments and replacement of macro invocations by the expansions of +those macros. (Comments need not be deleted, even logically, if preprocessing +output is not being produced. In ``pcc`` mode, comments are deleted entirely, +but in other modes they are replaced by one blank.) + +The two sets of changes are handled differently, and one might ask why the +trigraphs and line splices are actually rendered in ``curr_source_line`` (with +instructions on undoing them), while the macro changes are not rendered (and +the instructions are for doing them rather than undoing them). The reason is +that the first set of changes is applicable at the character or intra-token +level, and the second set only applies at the inter-token level. It is a basic +goal of the lexical routines that the current position must be representable as +a single pointer, and that one be able to move forward efficiently in the input +by just incrementing that pointer. Trigraphs and line splices can occur within +tokens, and therefore if they were not rendered in ``curr_source_line`` one +would have to check for them in every case where one wants to move forward in +the input. The other modifications, on the other hand, can only occur between +tokens, and therefore they need not be expanded in the source line. They occur +between tokens, and special marker characters in the input stream are used to +indicate their presence. The marker characters cause the termination of +scanning of the previous token, followed (on the next call of ``get_token``) by +interpretation of the marker character to decide where the input goes next. +This makes macro expansion efficient (the source line need not actually be +subjected to insertions and deletions) while preserving the ability to advance +through the input using just one pointer. It also preserves information that +allows one to construct either the original source line or the macro-expanded +line, and to know the origin of any particular part of the resultant line. + +The modification entries can apply to the inserted text of other modifications, +so one can have modifications of modifications. Wherever a modification is +made, the original character (in ``curr_source_line`` or inserted text) is +replaced by a marker character (``ATTENTION_MARKER``) so that if that spot is +reached by sequential scanning from preceding text, one is cued to look at the +modification list to find the text that follows. + +In extreme cases the data structure can get quite complex, with modifications +on modifications. In cases involving real-world macros, however, it remains +fairly simple. + +``ATTENTION_MARKER`` is a one-character lexical escape sequence. It has to be, +because a macro invocation can be as short as a single character, and the +``ATTENTION_MARKER`` overwrites the beginning of the macro invocation. There +are also two-character lexical escape sequences, which begin with the +``LE_ESCAPE`` character (which is zero). The second character of the escape +sequence is one of the following: + +* | ``LE_END_OF_LINE``, which marks the end of the primary source line. +* | ``LE_NEWLINE``, which represents the newline character at the end of the + primary source line. +* | ``LE_END_OF_INSERTION``, which marks the end of the text inserted by a + source line modification. +* | ``LE_END_OF_TOKEN``, which separates tokens in macro text (see below). +* | ``LE_INERT_MACRO``, which indicates a macro name that should not be + expanded (see below). +* | ``LE_NULL``, which indicates a null (zero) character in the source line\ + ``.`` + +To ensure that the ``ATTENTION_MARKER`` and ``LE_ESCAPE`` characters are always +lexical escapes, rather than characters accidentally introduced into the +lexical data structure because of special characters in the input file, the +front end does two rewrites on input: + +* | The newline character at the ends of input lines is transformed into a + lexical escape sequence. This frees up the newline character to be used as + ``ATTENTION_MARKER``. +* | A null (zero) character in an input line is flagged with an error and + replaced by a space. In modes that allow null characters in the source + (e.g., gcc mode), the character is replaced by an ``LE_NULL`` escape + sequence (and an original line modification is created, so that column + numbers can be determined correctly). + +The characters newline and null were selected for use as these reserved +characters because they are already special in the C language and in character +sets in general. No other pair of characters can be guaranteed not to occur in +source files, especially when international character encodings such as SJIS +are considered. + +Note that because ``LE_ESCAPE`` is a zero character, the source line and +inserted text cannot be considered to be simple null-terminated strings. Also +note that the ``ATTENTION_MARKER`` and ``LE_ESCAPE`` characters will naturally +terminate the accumulation of the characters of a token. + +The modification entries of both kinds are dynamically allocated, used, and +then freed when the next logical source line is about to be read. For each +kind, there is an available list (freed entries that are available for reuse), +an allocation routine, and a free routine. See + +* | ``add_orig_line_modif``, +* | ``free_orig_line_modif``, +* | ``add_source_line_modif``, +* | ``free_source_line_modif``, and +* | ``rem_source_line_modif``. + +The majority (75%?) of source lines have no modifications of any kind (not +counting comments), so the code in the lexical routines is optimized to deal +efficiently with that case. + +Routines ``assoc_source_line_modif`` and ``nested_source_line_modif``, along +with the associated macros ``go_into_insertion`` and ``leave_insertion``, +handle the low-level tasks of determining where to go next in the input stream +based on the source modifications. + +The current position in the input stream in given by ``curr_char_loc``. +Ordinarily, it points to somewhere within ``curr_source_line``, but when macros +are expanded it can point to somewhere in ``macro_buffer`` or to a +dynamically-allocated argument. + +In the text of macro arguments and the replacement text for macros, the +individual characters have already been tokenized once. To ensure that the +tokenization is done the same way if and when it is done again, the text of +each token in source line modifications is followed by an ``LE_END_OF_TOKEN`` +lexical escape sequence. That escape sequence terminates the accumulation of +characters to make up a token, and is then ignored as part of the white-space +skip at the start of the next call of ``get_token``. End-of-token sequences +are usually removed by ``gen_pp_output_for_curr_line``, but an individual +end-of-token will be output as a blank if there is the possibility that two +adjacent tokens might be misparsed without one. See the discussion in +``macro.c`` for further information. + +In some obscure cases involving thwarted macro expansion, it is necessary to do +a true insertion into the source line, rather than the usual replacement of +some characters by some others. Fortunately, this only needs to be done at the +beginning of the line, so a simple mechanism suffices: a source line +modification with a NULL location is taken to be an insertion before the first +character of the line. Only one such insertion is allowed per line, and if one +exists, ``line_start_source_line_modif`` points to it. + +``curr_source_line`` and ``macro_buffer`` are actually dynamically-allocated +arrays, and can be expanded (by reallocation) as necessary. Therefore, there +is no limit to the length of source lines or of macros except that imposed by +available memory. + +Lexical Analysis +================ + +"Lexical analysis" includes the reading of source lines and the breaking of +them into lexical tokens. It is also closely tied to preprocessor directives +and to macro processing, since they are invoked at the lexical level, and are +defined in terms of tokens. The source code for lexical processing is in +``lexical.c``, and associated declarations are in ``lexical.h``. + +Getting Tokens +-------------- + +The primary interface to the lexical routines is the routine ``get_token``, +which fetches and returns the next token of input. When compiling C, these +tokens are the input for syntax analysis. When preprocessing only, the tokens +are fetched (by a loop in ``cpp_driver`` in ``preproc.c``), and then discarded; +calling ``get_token`` repeatedly forces the reading of input lines and the +necessary preprocessing on each line, and each modified line is then written +out just before the next line is read. ``do_preprocessing_only`` and +``generate_pp_output`` will be TRUE in that case. ``get_token`` is used in +both cases; in fact, it is used for all fetching of tokens in all contexts. + +When ``get_token`` is called, it scans the next token of input and returns its +kind. The kind of token is also saved in ``curr_token``. See the enumeration +``a_token_kind``, in ``lexical.h``, for the list of token kinds (e.g., +``tok_identifier``, ``tok_lparen``). + +Much of the rest of the processing is dependent on several global switches, as +described in the following paragraphs. Most of these switches are defined in +``preproc.h``. + +If ``fetch_pp_tokens`` is TRUE when ``get_token`` is called, a preprocessing +token (pp-token) is fetched instead of a regular token. Constants are not +converted (and numeric ones are returned as pp-numbers); adjacent string +literals are not concatenated; keywords are not recognized; and errors are not +issued for malformed tokens. Also, ``start_of_curr_token`` and +``end_of_curr_token`` are set to point to the beginning and end of the current +token, and ``len_of_curr_token`` is set to its length. + +If ``expand_macros`` is TRUE, preprocessing macros are expanded as they are +scanned. The caller sees only the tokens after expansion. If a macro name is +preceded by an ``LE_INERT_MACRO`` escape sequence, the macro is not expanded +and the identifier is returned to the caller with ``curr_token_is_inert_macro`` +set to TRUE. + +When ``fetch_pp_tokens`` is FALSE, ``do_string_literal_concatenation`` controls +whether adjacent string literals are concatenated. + +If ``in_preprocessing_directive`` is TRUE, the definition of white space is +changed to that for within preprocessing directives; i.e., keywords are not +recognized, and newline, ``#``, and ``##`` are recognized and returned as +tokens. However, if ``caching_pragma_tokens`` is TRUE, a pragma is being +recoded as a token cache, and this requires disabling some of the processing +that is normally done when ``in_preprocessing_directive`` is TRUE -- +identifiers will be looked up and ``#`` and ``##`` are not returned as tokens. +And if ``recognize_keywords_in_pragma`` is also set, keywords are looked up and +returned as keyword tokens rather than as identifier tokens. (This is required +for dealing with ``#pragma`` directives involving C or C++ constructs that must +be scanned by the compiler's normal scanning routines; for instance, it is used +for processing the pragmas that control template instantiation.) + +If ``in_pp_if_expression`` is TRUE (indicating that we are inside a +preprocessing ``#if`` expression), integer constants will get an implicit ``L`` +suffix, and undefined identifiers will be returned as the integer constant +``0L``. + +If ``exp_header_name`` is TRUE, then ``"..."`` will be scanned as a header name +for an ``#include`` (``tok_header_name``). Other tokens will be processed +normally. ``exp_system_header_name`` is similar, for header names of the form +``<...>``. + +If ``exp_digit_sequence`` is TRUE (indicating a string of decimal digits) then +the digits will be scanned as a ``tok_digit_sequence`` (used in the ``#line`` +directive). Other tokens will be processed normally. + +For tokens that are literal constants, the struct ``const_for_curr_token`` is +set to the value of the constant (if ``fetch_pp_tokens`` is FALSE). This +global variable is also set for the literal portion of user-defined literals +(when user_defined_literals_enabled is TRUE), along with +ud_lit_op_sym_for_cur_token, which designates the symbol for the literal +operator or literal operator template chosen to produce the value of the +user-defined literal. When ud_lit_op_sym_for_curr_token designates a raw +literal operator or a literal operator template, const_for_curr_token is a +ck_string constant whose value is the actual spelling of the literal part of +the toke; otherwise, it is the value of that literal part. + +For tokens that are identifiers, the corresponding symbol header is looked up +in the symbol table and ``locator_for_curr_id`` is set accordingly. For +user-defined literal tokens, ``locator_for_curr_id`` is set to designate the +*literal-operator-id* of the literal operator or literal operator template +denoted by the literal's *ud-suffix*. It can be used later to refer to the +current definition of the identifier or operator (if there is one) or to enter +a new definition for the identifier or operator. + +The routine ``get_token`` is basically one large ``switch`` statement that fans +out based on the current character of input. The various cases are: + +* | For operators and similar special-character tokens, ``get_token`` looks at + the next character or two and selects the appropriate token. +* | For the lexical escape sequences (the ATTENTION_MARKER character or the + two-character LE_ESCAPE sequences), ``skip_white_space`` is called. These + characters are not all actually white space, but it simplifies processing + to let that routine handle them. All reads of new source lines are + requested by ``skip_white_space``. +* | For numbers, ``scan_number`` is called (it handles decimal, octal, and + hexadecimal integer literals, as well as decimal and hexadecimal + fixed-point and float literals). ``scan_number`` will determine the kind + of number, accumulate its characters, and, if appropriate, call the proper + conversion routine in ``literals.c`` to convert the literal constant string + to internal form in ``const_for_curr_token``. It also handles recognition + of numeric user-defined literals and, when one is recognized, setting + ud_lit_op_sym_for_curr_token. +* | For identifiers, the characters are accumulated and ``find_symbol`` is + called. This yields a list of symbols with the given name. The list is + then searched for a definition that is a macro or keyword. If the + identifier is a macro and if macro expansion is required, + ``macro_invocation`` (in ``macro.c``) is called. Note that because this + look-up finds both macros and other uses of identifiers, a symbol only has + to be looked up once; it does not have to be looked up once to see whether + or not it is a macro, and then again later to see if it is something else. +* | For quoted tokens (character constants and string literals, and the wide + versions thereof), an appropriate scanning routine is called, which in turn + calls ``accum_quoted_string``. The latter accumulates the characters of + the string, checking for escapes and the like. When a string literal or + wide string literal is scanned outside of preprocessing mode, ``get_token`` + will call ``concat_adjacent_string_literals``, which will check if the next + token is another string literal. If so, the adjacent strings will be + concatenated into a single string literal token. scan_char_constant + recognizes user-defined character literals and sets + ud_lit_op_sym_for_curr_token, as appropriate. In order to handle merging + of suffixes across concatenated string literals, the similar task for + user-defined string literals is handled by concat_adjacent_string_literals, + except when fetch_pp_tokens is TRUE; in that case, get_token performs the + requisite processing, as string literals are not concatenated in that mode. +* | When a ``#`` appears as the first non-white-space character on a line, a + call to ``pp_directive`` (in ``preproc.c``) is made to process a + preprocessing directive. + +One very important requirement is that ``get_token`` be fast. About 30 percent +of total time time in the front end is likely to be spent in ``get_token`` and +its subordinate routines. Every effort has been made to make those routines +fast, and in particular, to avoid unnecessary subroutine calls. As an example, +simple white space (blanks and horizontal tabs) is skipped in ``get_token`` +itself, rather than incurring the overhead of calling ``skip_white_space``. + +The handling for pp-tokens and normal tokens differs in a number of ways, but +the most fundamental of those is the information returned to the caller. The +kind of token is returned in both cases. However, for identifiers and literal +constants, where additional information must be returned to precisely specify +the token, the returned value in the pp-token case is the actual characters of +the token, and in the normal token case it is something one step removed from +that: a symbol locator for identifiers, or a constant entry for constants. +This is useful, but it's also necessary -- when scanning normal tokens, and in +particular identifiers and literal constants, there are some cases where it is +necessary to skip forward to the next token to see if it has some effect on the +current one. For example, after scanning a string literal, one must look ahead +to see if the next token is another string literal, and if so, one concatenates +the two. Since the next token may be on another line, it's clear that the +original string for the token in the current source line may be gone by the +time the next token is reached. Therefore, the locator or constant entry form +is necessary even inside of ``get_token``. + +Token Lookahead and Caching +--------------------------- + +Sometimes syntactic analysis requires lookahead -- it requires the fetching +of one or more tokens past the current position to discriminate between two +possible parses. + +This comes up even in C, although the lookahead there is limited to a single +token. For example, when a statement begins with an identifier, one must look +past the identifier to see whether or not the next token is a "``:``" -- if so, +the identifier is a label. (The routine ``next_token`` provides this +capability.) + +In C++, lookahead is needed in many more contexts, and is not limited to +one-token lookahead. In addition, there are some language constructs that must +be saved in some lexical form when they appear, and then parsed later on the +basis of the saved information. The most obvious example is the bodies of +member functions declared inside a class: their name binding cannot be done +until the entire class declaration has been scanned, so the easiest +implementation is to save the member function bodies and then parse them when +the closing brace of the class is reached. + +A construct called a *token cache* supports all these needs for lookahead, as +well as recording the tokens of template definitions and other syntactic +elements for delayed use. a_token_cache is a data structure that represents a +sequence of tokens. The tokens in a cache are represented by a list of shared +tokens (a_shared_token), each one describing an immutable token state (this +includes not just the token kind, but also any additional information required +to fully specify the token, e.g., a symbol locator for an identifier or a +constant entry for a literal constant). A similar data structure, +a_reusable_token_cache, is used for the tokens of a template definition or +delayed construct. + +To build a nonreusable token cache, one declares a variable of type +a_token_cache. Then one reads through tokens in the usual way, calling +get_token to fetch each token, and then calls cache_curr_token before advancing +to the next. When enough lookahead or caching has been done, one can put all +the tokens in the token cache back on the front of the input stream by calling +rescan_cached_tokens. + +get_token does not read directly from nonreusable token caches (although it +does do so with reusable token caches; see below). Instead, +rescan_cached_tokens adds the current token to the end of the cache and then +pushes the cached tokens in LIFO order onto the global +cached_token_rescan_stack (implemented as a stack instead of a list for +efficiency reasons), and finally calls get_token to fetch what was the first +token of the cache from the cached token rescan stack as the current token. As +long as the global rescan stack is non-empty, get_token will fetch a token from +the rescan stack (by calling get_token_from_cached_token_rescan_stack) instead +of scanning a new token from the current source line. + +``next_token`` is a simple user of the token caching facility; it caches the +current token, fetches the next and remembers its kind, then pushes the cache +back on the input stream to restore the original token (and also the next one, +behind it). + +``unget_token`` puts the current token back on the front of the input stream, +so that in effect afterwards there is no current token (although it doesn't +actually go so far as to change ``curr_token``). It is used in some unusual +error situations that want to fabricate and insert an identifier token where +one was missing in the source. + +Two routines are available to cache sequences of tokens delimited by given +tokens: + +* ``cache_token_stream_until_matching_token`` +* ``cache_token_stream_with_coalesce_flag`` + +``cache_token_stream_with_coalesce_flag`` is not intended to be called +directly. Instead, it is called by one of two interface routines: + +* ``cache_token_stream`` +* ``cache_token_stream_coalesce_identifiers`` + +``cache_token_stream`` is used to cache tokens until one of a specified set of +stop tokens is found. This is used, for example, when caching the body of a +class or function template when all tokens up to a closing brace should be +cached. In such situations, the only special processing that is needed is to +keep track of paired delimiter tokens (e.g., ``{}``, ``[]``, ``()``) so that, +for example, the closing brace of an inner block is not incorrectly taken as +the end of the template body. + +When the stop token could appear within a template argument list, additional +processing must be done to determine whether a "``<``" that is encountered is +the start of a template argument list or simply a less than sign. In order to +determine this, the identifiers found while the tokens are cached must be +coalesced (the identifier coalescing process is described later in this +chapter). This special kind of token stream caching is done by calling +``cache_token_stream_coalesce_identifiers``. The process of coalescing an +identifier involves fetching some number of tokens. Because these tokens are +not fetched directly by ``cache_token_stream_coalesce_identifiers``, a +mechanism is needed to get access to those tokens. +``begin_caching_of_fetched_tokens`` is called to request that a cache of +fetched tokens be automatically constructed. Each new token returned by +``get_token`` is added to a special cache. The token stream is then cached by +recording the starting token sequence number, getting each token, and +coalescing each identifier that is encountered until the stop token is found. +Once the starting and ending token sequence numbers are known, the tokens in +that range are extracted from the special cache. +``end_caching_of_fetched_tokens`` is then used to indicate that the automatic +caching of tokens is no longer needed. + +As noted above, token caches are also used to represent template definitions +and other syntactic constructs that require delayed processing. The tokens +that comprise the syntactic element are cached when it is scanned and are +rescanned later when needed. While other token caches are rescanned once and +discarded, reusable token caches may be rescanned over and over again. +Reusable token caches should be constructed by calling the factory function +shared_obj with reusable set to TRUE (this acts as a sanity +check to ensure the token cache is used in the intended way, but they are +otherwise built in exactly the same manner as other token caches). The +reusable token cache object (of type a_reusable_token_cache) is then +constructed from the result. + +Various scenarios can cause multiple reusable token caches to be pending rescan +at a given time; calling rescan_reusable_cache pushes a reusable token cache +onto the global reusable_cache_stack. get_token first rescans tokens from the +(nonreusable) cached token rescan stack, as described above. When this stack +is exhausted it rescans tokens from the reusable cache at the top of the +reusable cache stack by calling get_token_from_reusable_cache_stack. When all +of the entries in a reusable cache have been scanned the cached token rescan +stack is restored and the entry is popped off of the reusable cache stack. +Token scanning then resumes with the next token on the cached token rescan +stack. + +Reusable and nonreusable token caches may be freely intermixed; template +instantiations may occur while scanning tokens from a cache and a template +instantiation will usually create new caches, as needed, when doing +look-aheads, as described earlier. + +Source Positions +---------------- + +Each time a token is fetched, the global variable ``pos_curr_token`` is set to +the source position of the first character of the token. A source position +means a sequence number (which can be converted to a file name and line number) +and a column number from the original source line. The position is determined +by the macro ``macro_line_loc_to_source_pos``. In the simplest and most common +case, a pointer to the starting character of the current token can be converted +easily to a source position by using the current sequence number and +determining the column number by taking the difference between the pointer and +the start of ``curr_source_line`` and applying an offset to convert the byte +offset into a logical column number using the macro ``logical_column_offset`` +(which can in some cases result in a call of ``f_logical_column_offset``). In +more complicated cases, ``conv_line_loc_to_source_pos`` is called, and it uses +the information in both ``orig_line_modif_list`` and ``source_line_modif_list`` +to determine the source position. The source position of something in a +preprocessing modification is taken to be the position of the first character +of the original source line that contains the macro invocation that leads to +the given modification. + +The Input Stack +--------------- + +``open_file_and_push_input_stack`` is called to enter both the primary source +file and ``#include`` files -- by ``fe_init`` (in ``fe_init.c``) and by +``proc_include`` (in ``preproc.c``), respectively -- and it in turn calls +``open_file_for_input`` and ``push_input_stack`` to do the work; when end of +file is reached, ``pop_input_stack`` is called. + +``open_file_for_input`` loops to try each possible include file directory when +attempting to open an include file; it also contains code for the (optional) +implicit inclusion feature of automatic template instantiation, permitting a +series of suffixes to be tried in each directory. + +Together, the push/pop routines manage the ``input_stack``, which contains +information about the current nesting of input files. To limit the number of +open files, they will reuse files once a few files have been opened (see +``MAX_INCLUDE_FILES_OPEN_AT_ONCE``). The storage for ``input_stack`` is +dynamically allocated and is reallocated larger as needed. + +If the options requesting ``makefile`` information or a list of header files +were specified on the command line, ``do_preprocessing_only`` will be TRUE but +``generate_pp_output`` will be FALSE. Either ``list_makefile_dependencies`` or +``list_included_files`` will be TRUE. ``push_input_stack`` writes out the +appropriate information to the preprocessing output file. + +The front end recognizes certain idioms used to allow an include file to be +included more than once with all of the includes after the first having no +effect. When one of these idioms is recognized the front end will ignore +subsequent attempts to include the file again. The front end recognizes two +commonly used mechanisms used to allow a file to be included multiple time: +placing the entire contents of a file inside a ``#ifndef`` or ``#ifdef``, and +use of the ``#pragma once`` directive. A simple state machine is used to +determine whether subsequent includes of a given file may be suppressed. The +state information is maintained in the input stack entry. +``suppress_subsequent_include_of_file`` is called for each file to be included. +If it returns TRUE then the call of ``push_input_stack`` is skipped and the +include is suppressed. See the comments that precede ``find_include_history`` +for additional information. + +Skipping White Space +-------------------- + +``skip_white_space`` is called to skip over any white space and get to the +start of the next token (some simple cases of white space are skipped in +``get_token``, for efficiency). Besides the usual white-space characters, it +also handles the skipping of comments, calling ``read_logical_source_line`` to +fetch the next line of input, and going into and leaving source modifications +upon encountering lexical escape sequences (e.g., ``ATTENTION_MARKER`` to go +into a modification, ``LE_ESCAPE/LE_END_OF_INSERTION`` to leave a +modification). + +``skip_white_space`` tracks the kind of white space it has skipped over +(comment/other) and sets global variable ``kind_of_white_space_skipped``. This +information is useful in the macro processing routines, where white space can +be significant. Note that ``kind_of_white_space_skipped`` is not necessarily +set correctly if one calls ``get_token``, since ``get_token`` does some +white-space skipping on its own. + +When ``skip_white_space`` recognizes one of the ``lint`` comments + + | ``/*ARGSUSED*/``, + | ``/*NOTREACHED*/``, + | ``/*VARARGS*/``, or + | ``/*VARARGS`` *n*\ ``*/`` + +``add_curr_token_pseudo_pragma`` is called. It adds a pending pragma entry to +the current token pragma list. Later, the pending pragma entry is removed via +a call to ``extract_specific_pragmas``, and processed (by setting global state +information or flags in IL entries). For ARGSUSED and VARARGS, that's done in +``record_lint_argsused_and_varargs_state``. For NOTREACHED, it's done in +``check_lint_notreached_state``. + +Hanging Delete +-------------- + +If global variable ``delete_source_from_loc`` is non-NULL, the text that +extends from that location in the current line to the position immediately +preceding ``curr_char_loc`` is to be deleted. This is referred to as a +"hanging delete", and is used in deleting macro invocations. This flag is +necessary because the complete text of a macro invocation must be deleted (to +be replaced by the expansion of the macro), but the macro invocation may span +several lines, and the macro routines are not in control when ends of lines are +passed in ``skip_white_space``. By setting this flag, the macro routines can +request that the text of a macro invocation be correctly deleted even if it +spills over onto additional lines. When the deletion is handled at line end, +``delete_source_from_loc`` is updated to point to the start of the new source +line so that the hanging delete remains in effect. + +Whitespace keywords +------------------- + +C++/CLI has "whitespace keywords," which are keywords made up of two words +separated by whitespace but considered a single keyword, for example "``ref``\ +``class``". These are scanned by ``scan_whitespace_keyword``. One interesting +detail is that the characters that make up the token (which can be spread over +multiple lines because of the embedded whitespace) are replaced by a canonical +spelling of the keyword containing a single embedded space, the same way that a +macro is replaced in the input line by its expansion. That allows processing +that deals with tokens on the pp-token level to handle those whitespace keyword +tokens like any others, as a contiguous sequence of characters. + +Textual Preprocessing Output +---------------------------- + +When compiling C to intermediate language, there is no need to assemble the +actual logical source line that results after preprocessing. All that is +required is that the tokens of that line can be extracted. But when +preprocessing only is being done, the preprocessed line is output from +``curr_source_line`` and the information in ``source_line_modif_list``. [#f1]_ +``gen_pp_output_for_curr_line`` assembles and puts out the effective line, +calling ``gen_pp_line_info`` to generate line-identification directives when +the file/line of the current line does not immediately follow that of the line +previously output. ``gen_pp_output_for_curr_line`` is called by +``read_logical_source_line`` right before a new line is read; it is also called +when the input stack is pushed and popped for the starts and ends of input +files. + +There are some special problems in producing the preprocessing output line when +preprocessing directives are passed to output. This must be done for certain +directives (like ``#pragma``) that the preprocessor cannot process. If a +directive of that type contains a multi-line comment, the parts of the +directive preceding and following the comment must be written out on the same +line. In this case, the part preceding the comment will be written without a +terminating newline, and the part following the comment will be written later +on the end of that line. + +Reading Logical Source Lines +---------------------------- + +Aside from its primary function of reading the next logical source line and +processing trigraphs and line splices, ``read_logical_source_line`` also calls +``gen_pp_output_for_curr_line`` to output the previous line (if needed), clears +the modification lists, and handles ends of files. It can be told to stay at +the end of a file (rather than popping out to the enclosing file) on end of +file, if that is desirable (as it is when scanning a comment that is unclosed +at end of file). On the ultimate end of file, it returns a special end-of-file +line (containing just an ``LE_END_OF_LINE`` lexical escape sequence) in +``curr_source_line``, and sets ``after_end_of_all_source``. + +If ``curr_source_line`` is too small, ``expand_curr_source_line`` is called to +reallocate it, and ``adjust_curr_source_line_structure_after_realloc`` (in +``macro.c``) is then called to walk through the data structure associated with +``curr_source_line`` and change any pointers to ``curr_source_line`` to point +to the proper addresses within the new allocation for ``curr_source_line``. + +Multibyte characters in source code +----------------------------------- + +When ``MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED`` is TRUE, multibyte character +sequences are accepted in comments, string literals, character constants, +identifiers, and header names. Multibyte character sequences are not wide +characters (e.g., Unicode); they are sequences of one or more characters, +appearing in a string of characters of the usual ``char`` size, and +representing single logical characters. For example, in the Japanese SJIS +encoding, the sequence 82A9 (in hexadecimal) represents a single Kanji +character: the first character (82) is in a range that indicates it is the +first character of a two-character sequence. Typically, the characters in the +ASCII code set will be accepted as themselves in multibyte character encodings, +i.e., they will be sequences of length one. Since each character sequence in a +multibyte character string need not have the same length (and some encodings +have explicit shift-state-change characters), a multibyte character string can +be understood only by scanning it from beginning to end, advancing over one +logical character at a time. + +Moreover, since characters after the first in a multibyte sequence can look +like simple ASCII characters, it is not generally okay to look for an ASCII +character by doing a simple ``strchr``-type search. The lexical routines count +on being able to do this for only two characters: the zero/null character (this +is guaranteed by the C standard; characters after the first in a multibyte +character sequence are not allowed to be zero) and the newline character (this +is effectively guaranteed by the fact that one must be able to read files +containing multibyte character sequences and discern the ends of lines without +tracking the multibyte character state as each character is read). [#f2]_ + +To advance over logical characters, one needs a routine that will determine the +length of the multibyte character sequence at a given location. This is done +by the macro ``mbc_length`` and routine ``f_mbc_length``. In the usual +configuration, that routine is implemented by calling the standard C library +routine ``mblen``. ``mbc_length`` and related routines are used to do special +processing in the following places: + +* | In ``read_logical_source_line``, the line splice ("``\``") and trigraph + ("``?``") characters are ignored if they appear in the middle of a + multibyte character sequence. +* | In ``skip_white_space``, the closing character for a C-style comment + ("``*``") is ignored if it appears in the middle of a multibyte character + sequence. ("``//``" end-of-line comments require no special handling, + because the end-of-line marker is rendered as a lexical escape + sequence,which cannot appear within a multibyte character sequence.) +* | In ``accum_quoted_string``, ``scan_char_literal``, ``scan_string_literal``, + ``conv_single_char``, and ``conv_single_wide_char``, the characters inside + quoted strings are scanned as multibyte characters as necessary. The + routine ``mbc_to_wide_char`` is used to convert a multibyte character + sequence in a wide string literal or wide character constant to the + appropriate ``wchar_t`` character. In the usual configuration, + ``mbc_to_wide_char`` is implemented by calling the C library routine + ``mbtowc``. +* | In ``get_token``, the scanning for identifiers uses ``is_identifier_char`` + to recognize identifier characters beyond the basic character set. + ``make_canonical_identifier`` handles encoding the multibyte characters + appropriately in the name string for the identifier. + +Note that not all source code is scanned as multibyte characters, because that +would take too much time. The special scanning is done only in the contexts +listed above. For the line-splice and trigraph cases, when the line-read +routine sees those characters it goes to the beginning of the line and steps +through the characters of the line to find out where the character falls in the +multibyte character sequences, but that processing is done only if a potential +line splice or trigraph appears. Note also that there are configuration +options to turn off the special processing for several of the special +characters, for cases where the encoding guarantees no confusion on the +particular character. + +If the encoding has locking state-change characters (e.g., JIS), each C-style +comment and string is assumed to begin in the initial shift state. This +follows a requirement stated in 5.2.1.2 of the ANSI/ISO C standard + +If ``UNICODE_SOURCE_SUPPORTED`` is TRUE, the multibyte encoding selected is the +UTF-8 encoding of Unicode. UTF-16 is also supported, in the little-endian or +big-endian format, and is converted immediately to UTF-8 on input. The type of +source code in a file can be specified by a byte order mark (BOM) at the start +of the file, or by way of the ``--unicode_source_kind`` command-line option. +There is also a macro ``DEFAULT_UNICODE_SOURCE_KIND`` that can be used to +establish the default for files without a byte order mark. + +When ``UNICODE_SOURCE_SUPPORTED`` is set to TRUE, identifiers and file name +strings in the front end are represented in UTF-8. For file names, there is +the expectation that the standard system fopen will be able to deal with UTF-8 +file names. If that isn't the case, some host-specific code may have to be +added to ``fopen_interface``. (For Windows-hosted configurations, specific +code is provided which calls the ``_wfopen`` function.) + +If UTF-8 identifier name strings are somehow undesirable (e.g., a back end or +linker can't handle them), the macro +``IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS`` can be set to FALSE, in which case +characters in identifiers outside of the basic character set will be rendered +in the ``\u``\ *xxxx* or ``\U``\ *xxxxxxxx* form also used for UCNs. Note, +however, that the encoded form will come out in diagnostic messages that name +an entity in the source. + +If ``DEFAULT_UNICODE_SOURCE_KIND`` is ``usk_none``, source files without a byte +order mark are assumed to be encoded in ISO-8859-1 (otherwise known as +Latin-1), which matches the first 256 code points in Unicode. +(``LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED`` should be set to a locale that +matches ISO-8859-1.) Such a mode (which is the default for Windows-hosted +versions) is a hybrid mode in which some files are Unicode and some are not, +and in which therefore a character like a u-umlaut would be encoded differently +depending on the kind of source file it appears in. Such characters in +non-Unicode files are converted to UTF-8 (or the identifier encoding ``\u``\ +*xxxx*) when they appear in identifiers and file names. In hybrid +configurations, characters in textual preprocessing output are always converted +to UTF-8 if ``DEFAULT_UNICODE_SOURCE_KIND`` is not ``usk_none``, and to +ISO-8859-1 otherwise. Characters that cannot be represented in ISO-8859-1 in +the latter case are converted to "``?``". + +When ``UNICODE_SOURCE_SUPPORTED`` is TRUE, +``NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE`` may be set to TRUE to +indicate that non-Unicode files are encoded in some character set other than +ISO-8859-1.This feature requires the ability to translate other character sets +to and from Unicode. Such a facility is provided in newer versions of the +Windows API (Microsoft version 1400 and above) so this feature is enabled when +the front end is built with ``EDG_WIN32`` set to TRUE. In identifiers and file +names, native characters are translated to their UTF-8 equivalent. In wide +strings, native characters are translated to their Unicode equivalent. In +narrow strings, they are left in their original form. + +When Microsoft extensions are enabled and ``EDG_WIN32`` is TRUE, this feature +enables support for the Microsoft setlocale pragma, which specifies the +character encoding to be used for the translation to and from Unicode. + +Raw Listing Output +------------------ + +``gen_raw_listing_output_for_curr_line`` is called to write source lines to +``f_raw_listing`` when raw listing information is requested; it calls +``gen_expanded_raw_listing_output_for_curr_line`` to write out the +macro-expanded form of the source line if the source line has some +modifications. + +``gen_rlisting_line_info`` writes information about transitions into and out of +include files; it is called by ``push_input_stack`` at beginnings of files and +by ``pop_input_stack`` at ends of files. + +Inserting Text into the Token Stream +------------------------------------ + +``insert_string_into_token_stream`` may be called to cause a string to be +scanned as tokens that are processed as part of the input stream either before +or after processing the current token. When scanning tokens from the string, +macros are optionally expanded and adjacent string literals are concatenated. +The string cannot contain preprocessing directives, and trigraphs are not +recognized. + +This mechanism is used is used to internalize C++ code generated by the C++ +metadata reader (see :ref:`cppcli-assembly-decls`) in the functions +``scan_top_level_metadata_declarations`` and ``get_definition_of_class``. + +Utility Routines +---------------- + +There are several routines in ``lexical.c`` that are utility routines for +syntax analysis, and are not directly related to ``get_token``: + +* | ``flush_tokens`` is called on the occurrence of a syntax error, and throws + away tokens (by calling ``get_token``) until a token is found that seems an + appropriate place to restart. The current stop token set pointed to by + ``curr_stop_token_stack_entry`` contains the set of tokens on which to stop + the flush (it is maintained by the macros ``add_stop_token``, + ``remove_stop_token``, and the routines ``push_stop_token_stack`` and + ``pop_stop_token_stack``). Recursive-descent routines place the tokens + they expect in the set of stop tokens; then, if an error occurs, the flush + will stop at a point that one of the recursive descent routines will + recognize. ``flush_tokens`` should not in general be called directly; + ``syntax_error`` should be called to report a syntax error, and it will + call ``flush_tokens``. +* | ``flush_until_matching_token`` is called by ``flush_tokens`` (and can be + called from elsewhere) to flush from an opening token such as a left + parenthesis to the matching closing token. +* | ``loop_token`` is a utility routine that can be called at the bottom of a + loop for a repeated syntactic construct (e.g., a comma-separated list). It + tests for a particular token and takes it if it is found. +* | ``required_token`` is a utility routine that should be called when a + particular token is required to appear next. It checks for that token, and + issues an error if the token is not found. +* | ``next_token`` returns the next token after the current one, without + disturbing the current token. This is used in recursive descent parsing + routines to look ahead at the next token to decide between two paths + through the syntax. +* | ``next_two_tokens`` is similar to ``next_token`` except that if the next + token matches a value supplied by the caller the token after the next token + is fetched and returned to the caller. This is used when scanning vacuous + destructor references in C++ where it is necessary to look for a tilde + following a ``::`` to recognize a nonclass vacuous destructor reference + [#f3]_. +* | ``push_lexical_state_stack`` and ``pop_lexical_state_stack`` are used to + enter and exit a new lexical context. These are used, for example, when + instantiating a template and when switching from fetching normal tokens to + scanning a preprocessing directive. + +Scanning Names in C++ +===================== + +Unlike C, in which all names are simple identifiers, in C++ the names of +entities are often more complicated. Names may be preceded by one or more +qualifiers such as namespace and class qualifiers (e.g., ``A::B::i``) and +global scope qualifiers (e.g., ``::i``); class qualifiers may include template +references (e.g., ``A::i``); and the name that follows these qualifiers +may be more complicated than a simple identifier: it may also be an operator +name (e.g., ``operator+``), a conversion function name (e.g., ``operator +int``), a (C++11) literal operator name (e.g., operator ``""``\ _km), or a +destructor name (e.g., ``~A``). An arbitrarily complex name is referred to as +a "generalized identifier". The process of collecting the tokens of a +generalized identifier and replacing them with a single ``tok_identifier`` +pseudo-token is referred to as "coalescing" the generalized identifier. A +hierarchy of routines is provided that scan generalized identifiers: + +* | ``is_generalized_identifier_start`` determines whether the current token + begins a generalized identifier and, if so, scans the tokens that comprise + the generalized identifier and records its description in + ``locator_for_curr_id``. +* | ``coalesce_and_lookup_qualified_name`` calls + ``is_generalized_identifier_start`` and, if the generalized identifier + includes a qualifier, the name after the qualifier is looked up in the + scope specified by the qualifier. Names without qualifiers are not looked + up. [#f4]_ +* | ``coalesce_and_lookup_generalized_identifier`` is used to scan and look up + a generalized identifier. It calls ``coalesce_and_lookup_qualified_name`` + and looks up the name if it does not include a qualifier. Names that + include qualifiers will have already been looked up by + ``coalesce_and_lookup_qualified_name``. + +The arguments to these routines include options used to specify the kinds of +names that may be accepted and, for the coalesce-and-look-up routines, a lookup +mode that specifies the type of name lookup to be performed. The ``options`` +parameter specifies a set of "generalized identifier" (GID) flags. The GID +flags specify several different types of information: + +* | The kinds of identifiers that should be recognized. For example, ``~A`` + may be recognized as a destructor, or the tilde may be an operator. +* | The kinds of identifiers that are allowed. For example, are qualified + names allowed in this context? Are operator names allowed? The difference + between constructs that are "recognized" and those that are "allowed" is + that constructs that are not recognized (i.e., ``~D``) are not considered + identifiers by ``is_generalized_identifier_start`` while constructs that + are not allowed are considered identifiers but cause errors to be issued + indicating that the particular type of identifier is not permitted in the + current context. + +.. _recognizing-generalized-identifiers: + +Recognizing Generalized Identifiers +----------------------------------- + +``is_generalized_identifier_start`` is the lowest-level generalized identifier +routine and does most of the work. As the name suggests, +``is_generalized_identifier_start`` is used to determine whether the current +token is the beginning of a generalized identifier. + +``is_generalized_identifier_start`` is actually a macro that first checks +whether the current identifier has already been coalesced. If it has, the +macro immediately returns TRUE; otherwise it calls +``f_is_generalized_identifier_start``, which performs the rest of the +processing described here. + +For these examples ``is_generalized_identifier_start`` returns TRUE and sets +the current token to ``tok_identifier``: + + | ``i::iX::i`` + | ``::X::i`` + | ``::A::B::i`` + | ``A::i`` + | ``A::operator =`` + | ``A::operator int`` + | ``A::operator ""_km // When user-defined literals are recognized`` + | ``A::~A`` + | ``NS::i`` + | ``NS::A::i`` + | ``operator =`` + | ``operator int`` + | ``operator ""_km // When user-defined literals are recognized`` + | ``~A // When destructors are recognized`` + | ``A`` + | ``NS::A`` + | ``~int // When nonclass vacuous destructors are recognized`` + | ``int::~int // When nonclass vacuous destructors are recognized`` + | ``A::``\ *anything else except* ``* // Error`` + +For these examples FALSE is returned and current token is set to +``tok_ptr_to_member``: + + | ``X::*`` + | ``A::* // Template reference will be coalesced`` + +For these examples FALSE is returned and the current token is not changed: + + | ``::new`` + | ``::delete`` + | ``~A // When destructors are not recognized`` + | *anything else* + +Determining whether or not the current token is the start of an identifier may +involve scanning all of the tokens that comprise the identifier. Consequently, +all of the tokens that make up an identifier are scanned the first time that +``is_generalized_identifer_start`` is called for a given identifier. The +information needed to describe the generalized identifier is recorded in the +symbol locator, and on subsequent calls the information from the locator is +used to return the appropriate value to the caller. When a sequence of tokens +is coalesced the original tokens are replaced with a single ``tok_identifier`` +or ``tok_ptr_to_member``. The resulting token and related state information in +the locator is referred to as a "pseudo-token". When +``is_generalized_identifier_start`` determines that the thing being scanned is +an identifier, the current token is set to ``tok_identifier``, the locator is +updated with a description of the identifier, and the return value of the +function is TRUE. The fields in the locator that are set are + +* | ``is_qualified_name`` +* | ``is_global_qualified_name`` +* | ``is_file_scope_qualified_name`` +* | ``is_operator_name`` +* | ``is_destructor_name`` +* | ``is_udl_operator_name`` +* | ``is_class_member`` +* | ``parent`` +* | ``has_been_coalesced`` +* | ``is_vacuous_destructor_reference`` +* | ``is_nonclass_destructor`` + +When coalescing a qualified name such as ``A::xxx`` the result is a locator +whose symbol header points to the name ``xxx``, and whose ``parent`` points to +the ``A``. If ``A`` is a class, ``is_class_member`` is TRUE and +``parent.class_type`` points to the type of ``A``. If ``A`` is a namespace, +``is_class_member`` is FALSE and ``parent.namespace_ptr`` points to the +namespace entry for ``A``. The final identifier (``xxx``) is not looked up. +Instead, the information is preserved in the locator so that, if necessary, +``xxx`` can be looked up by ``coalesce_and_lookup_qualified_name``. + +``is_generalized_identifier_start`` coalesces template class references of the +form ``A::i``, [#f5]_ ``A``, and ``A::i`` (but not simply ``A``) by +calling ``coalesce_template_id``. These references must be coalesced to +determine whether the template reference is the beginning of a qualified name +(e.g., ``A::i`` cannot be determined to be a qualified name until +the ``::`` is seen.) The result of a template class reference is an incomplete +instantiation. A complete instantiation is only generated when it is required +for a name to be looked up. A complete instantiation will be generated for +references like ``A::X::Y``, because ``X`` must be looked up in ``A``. A +complete instantiation will not be generated (at least not here) for references +like ``A::X``. The complete instantiation is delayed until ``X`` needs to +be looked up (typically in ``coalesce_and_lookup_qualified_name``.) A template +argument list may also follow a function template name or an overloaded +function name in which one of the members of the overload set is a function +template. This is known as "explicit specification of function template +arguments". Unlike template class references, a template function reference +cannot be resolved to a given template instance when the template argument list +is scanned (because function templates can be overloaded). As a result, when a +function template argument list is scanned, a pointer to the list is retained +in the symbol locator, but the reference is not otherwise resolved at this +point. + +The pointer operator used when declaring a pointer-to-member looks a lot like a +qualified name; the only difference is that the final identifier is replaced +with an asterisk (``*``). For example, a pointer-to-member operator may look +like ``A::B::C::*``. Because of this similarity pointer-to-member +operators are also coalesced by ``is_generalized_identifier_start`` even though +they are not considered identifiers. When a pointer-to-member operator is +coalesced the current token is set to ``tok_ptr_to_member``, the +``parent.class_type`` field of the locator points to the type specified in the +operator (e.g., ``A::A::B::C`` in the previous example), and the return +value of the function is FALSE. + +The operators ``::new`` and ``::delete`` look like qualified names but are +actually operators. When called for these operators, +``is_generalized_identifier_start`` leaves the current token unchanged and +returns FALSE. + +C++ allows a destructor to be called for classes that have no destructor and +for nonclass types. We refer to this kind of destructor call as a "vacuous +destructor" reference. A GID option is used to indicate whether a vacuous +destructor should be recognized and, if so, whether it must be a nonclass +destructor. Vacuous destructor references, which are only allowed in field +selection operations, differ from other generalized identifiers in several +important ways: + +* | the qualifier, if present, and the identifier that follows the tilde may be + a nonclass type. +* | the nonclass type found may be a keyword that names a basic type (e.g., + ``int::~int``). + +When a vacuous destructor reference is coalesced, the ``parent.class_type`` +points to the type specified by the name *after* the ``::~`` because it must be +possible to record the type of the vacuous destructor reference for cases that +do not include a qualifier. + +Coalesce-and-Look-Up Routines +----------------------------- + +The coalesce-and-look-up routines are: + +* ``coalesce_and_lookup_qualified_name`` +* ``coalesce_and_lookup_generalized_identifier`` + +After ``is_generalized_identifier_start`` has determined that the current token +does in fact begin an identifier the coalesce-and-look-up routines are used to +do the appropriate kind of name lookup. The difference between the two +routines is that ``coalesce_and_lookup_qualified_name`` will only perform a +lookup of the final identifier of a qualified name while both qualified names +and names without qualifiers will be handled by +``coalesce_and_lookup_generalized_identifier``. + +One of the arguments passed to these routines is an "identifier lookup mode", +an enumeration that specifies the kind of lookup to be performed. The lookup +mode is translated into a set of "identifier lookup" (IDL) flags that are +passed to the symbol table lookup routines. An error is issued by +``coalesce_and_lookup_qualified_name`` if the name lookup fails, except in +``ilm_tentative_type`` mode. [#f6]_ In all other respects the various +identifier lookup modes are identical as far as the coalesce and lookup +routines are concerned. ``coalesce_and_lookup_generalized_identifier`` does +not issue an error if the lookup of an unqualified name fails. + +Generalized Identifier Errors +----------------------------- + +``check_for_generalized_identifier_errors`` is called by the +coalesce-and-look-up routines and also by ``is_generalized_identifier_start`` +to ensure that the identifier that has been scanned meets the constraints +specified by the GID "allowed" flags. The error tests are done by comparing +the current GID options with the information in the locator. When one +generalized identifier routine calls another, it masks off the error flags so +that the errors are diagnosed only once by the highest-level routine. + +``check_for_template_declarator_errors`` is called by the coalesce-and-look-up +routines to verify that the declarator in a template declaration does actually +refer to a template entity that is permitted in a template declaration. These +checks are done to provide diagnostics that are more helpful than those that +would result if the identifier were simply returned to ``declarator``. + +Template References +------------------- + +``coalesce_template_id`` coalesces references to class and function templates. +The kind of reference to be coalesced is determined based on a symbol that is +provided. If the symbol refers to a function template or an overload set +containing one or more function templates, +``coalesce_template_function_reference`` is called, otherwise +``coalesce_template_class_reference`` is called to handle class template +references or to diagnose the improper use of a template argument list. + +Template Class References +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``coalesce_template_class_reference`` coalesces template class references, such +as ``A``, into identifiers for which the ``specific_symbol`` field of +the locator points to a specific instance of the template. A class template +name is usually, but not always, followed by a template argument list. The +argument list may be omitted in declarations of the class template, + +.. code:: c++ + + template class A; + template class A { /* ... */ }; + +in which case the name refers to the class template (not to one of its +instances), and may also be omitted inside the definition of a class template +or in the definition of a member function or static data member of the class +template, + +.. code:: c++ + + template class A { + A* a; // Equivalent to A* a + int A::* pma; // Equivalent to A::* pma + }; + +in which case the name refers to the current instance of the class template +(e.g., ``A``). + +There are several contexts in which template class references must be +coalesced. Most calls of ``coalesce_template_class_reference`` are from +``is_generalized_identifier_start`` and include a template argument list or are +part of a qualified name. ``coalesce_template_class_reference`` is also called +by ``coalesce_and_lookup_generalized_identifier``, which scans simple class +template names such as ``A``, and by ``scan_tag_name``, which scans specific +definitions of a template classes such as ``class A {}``. Like the +generalized identifier routines, ``coalesce_template_class_reference`` accepts +a set of generalized identifier options as one of its arguments. The only +value actually used is ``GID_TEMPLATE_ARGS_OPTIONAL`` which specifies that the +template argument list may be omitted for a reference that is not within the +class template definition. As described above, the argument list may always be +omitted within the class template definition. + +The template argument list, if present, is scanned by calling either +``scan_template_argument_list`` or ``scan_unknown_template_arg_list:`` + +* | ``scan_unknown_template_arg_list`` is used when scanning the template + argument list associated with a "nonreal" template -- a class template that + is a member of a proxy or nonreal class. A nonreal template is created in + contexts in which a member class template of a template parameter dependent + class is used. For example: + + .. code:: c++ + + template struct A { + typename T::X tx; + }; + + | In such cases, it is assumed that ``T::X`` is a template because there are + no cases in which a less than sign could immediately follow a type name, so + the "``<``" must indicate the beginning of a template argument list. When + scanning a nonreal template argument list there is no information available + about the number of template parameters, their types, etc. All of this + must be inferred by scanning the actual arguments. Consequently, no + attempt is made to determine whether the number of arguments, the types, + etc. are correct. The disambiguation routines are used to determine + whether a given argument is a type or nontype (see below for the use of + this function in scanning function template references.) +* | ``scan_template_argument_list`` is used when scanning the template + arguments of "real" templates. Default values are provided for any omitted + arguments. If the type of a nontype parameter depends on another template + parameter, the type of the parameter is generated by rescanning a token + cache constructed when the template was defined. Similarly, if the type of + the default value, or the default value itself, involves a template + parameter, the default value is also generated by rescanning a token cache + constructed when the template was defined. + +Both routines call ``scan_template_argument_constant_expression`` for nontype +arguments and ``type_name`` for type arguments. ``find_template_class`` is +called, once a complete template argument list has been created, to find the +type that corresponds to the particular set of arguments. If no such type +exists, ``find_template_class`` creates one. In either case the symbol +associated with the type is returned. + +Function Template References +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``coalesce_function_template_reference`` coalesces references to functions that +employ an explicit template argument list. Unlike class templates, function +templates may be overloaded; therefore an explicit template argument list does +not necessarily identify a specific template instance. The function type of +the instance is also needed to determine the actual instance that is being +referenced, but is not available when the template argument list is scanned, so +the argument list must be retained until some later point when the function +type is also available. + +``scan_unknown_template_arg_list`` is used to scan explicit template argument +lists because, in general, there is no template parameter list that can be used +to determine the kind of argument expected (type vs. nontype), or the type of +the argument (for nontype arguments). As with nonreal template argument lists, +the disambiguation routines are used to determine whether a given argument is a +type or nontype. ``type_name`` is used to scan arguments that are types. +``scan_nontype_template_argument`` is used to scan nontype arguments. Function +template argument lists differ from those of class templates in that, for +function templates, the corresponding template parameter list is not available +when the template argument list is scanned. The presence of the template +parameter list for a class template makes it possible to convert nontype +arguments to the type of the corresponding template parameter (or to a special +nonreal type in the case of a nonreal argument list). For function templates, +such conversions cannot be done until the specific function template to be used +has been identified. Consequently, when a nontype argument is scanned it must +be retained in a form that permits the conversion to be done later. +``scan_nontype_template_argument`` returns a pointer to ``an_arg_operand``, a +data structure used by the expression scanning routines to represent an +expression. The ``constant_is_an_arg_operand`` field in the template argument +is set to indicate that the nontype argument is represented in this form. + +Variable Template References +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``coalesce_variable_template_reference`` coalesces references to variable +templates. ``scan_template_argument_list`` is used to scan the template +arguments. ``find_template_variable`` is used to produce a variable symbol for +the instantiation of the given variable template using the specified template +arguments. + +Conversion of Literal Constants +=============================== + +The source file ``literals.c`` contains the code to handle conversion of +literal constants to internal form. The external form is a string of +characters, a token, as accumulated by ``get_token`` and its subroutines; the +internal form is a structure of type ``a_constant``, representing an integer, +fixed-point, float, character, or string constant. + +``conv_integer_literal`` converts decimal, octal, and hexadecimal integer +constants. Aside from computing the value of the constant, it also recognizes +the trailing ``L`` and ``U`` suffixes, and determines the type of the overall +constant (on the basis of its value and the suffixes). For ``pcc`` mode, the +rules for determining the type of a constant are modified slightly. + +``conv_fixed_point_literal`` converts fixed-point constants (an Embedded C +feature), calling ``fxp_string_to_fixed_point`` or +``fxp_hex_string_to_fixed_point`` in ``fixed_pt.c`` to actually do the +conversion. It also recognizes the various suffixes (``k``, ``r``, ...), and +sets the type of the result accordingly. + +``conv_float_literal`` converts float constants, calling ``fp_string_to_float`` +or ``fp_hex_string_to_float_point`` in ``float_pt.c`` to actually do the +conversion. It also recognizes the ``L`` and ``F`` suffixes, and sets the type +of the result accordingly. + +``conv_char_literal`` converts character constants to an integer value. It +uses ``conv_single_char`` to fetch and convert each character. If there is +more than one character, they are assembled into one integer (with ordering +controlled by ``TARG_CHAR_CONSTANT_FIRST_CHAR_MOST_SIGNIFICANT``). + +``conv_string_literal`` converts string literals. It receives a count of +effective characters in the string from its caller (as computed by +``accum_quoted_string``), so it can dynamically allocate the space for the +string before scanning it. It also uses ``conv_single_char`` to convert each +character of the string. + +``conv_single_char`` converts one character to an integer value. This includes +simple characters, escapes like ``\n``, and octal and hexadecimal escapes. At +the moment, this routine assumes that the host and target character sets are +the same. + +``concat_string_literals`` concatenates several string literals (in constant +form in a token cache) into one string. This is used for the concatenation of +adjacent string literals. + +Preprocessing Directives +======================== + +The source file ``preproc.c`` contains the code to handle preprocessing +directives (except for ``#define``, which is handled in ``macro.c``). +Associated declarations are in ``preproc.h``. + +The routine ``cpp_driver`` is the top-level routine when the front end is being +run as a C preprocessor, typically to produce a preprocessed output file. It +calls ``get_token`` repeatedly until end of source, with +``do_preprocessing_only`` set to TRUE to indicate that preprocessing only -- +and not compilation -- is being done. + +Normally, when preprocessing output is required, ``generate_pp_output`` is TRUE +as well. But ``cpp_driver`` is also called when preprocessing is being done to +generate a list of ``#include`` files or a list of ``makefile`` dependencies. +In those cases, ``generate_pp_output`` is FALSE, and either +``list_included_files`` or ``list_makefile_dependencies`` is TRUE. + +``pp_directive`` is called (by ``get_token``) when a ``#`` is encountered at +the beginning of a source line. It sets ``in_preprocessing_directive``, +fetches the directive identifier and identifies it by calling +``identify_dir_keyword`` (which uses a simple linear search), calls the +appropriate routine to process the directive (which may call +``ignore_harmless_trailing_comment`` to ignore extra text at the end of the +directive), calls ``end_of_directive_processing`` (to check for any extra text +that is not harmless), and then resets ``in_preprocessing_directive``. If a +syntax error is detected in a directive, ``some_error_in_curr_directive`` is +set; this suppresses the check for extra text at the end of the directive. + +When the text of a preprocessing directive is not to be written to the +preprocessing output, ``do_not_put_curr_line_in_pp_output`` is set -- initially +in ``pp_directive`` and on each subsequent line, because of multi-line +comments, in ``read_logical_source_line``; the flag is checked by the output +routine, ``gen_pp_output_for_curr_line``. In the rare case that the text of a +preprocessing directive should be passed to output (because some C compiler +should see the directive to handle it), ``pass_pp_directive_to_output`` is set +to TRUE while the directive is scanned. + +Each preprocessing directive has an associated processing routine (for example, +``proc_if`` handles the ``#if`` directive). + +``proc_pragma`` processes the ``#pragma`` directive. This is an area that +would be configured for specific versions. Unrecognized pragmas must be +ignored (no error should be generated). When preprocessing only, ``#pragma`` +directives are passed to output (see ``pass_directive_to_output``). + +``proc_ident`` processes the ``#ident`` directive, although the "processing" it +does is to ignore it. When preprocessing only, ``#ident`` directives are +passed to output (see ``pass_directive_to_output``). + +``proc_error`` passes the rest of the directive to an error reporting routine, +as a catastrophic error, which terminates the compilation. + +``proc_line`` scans a line number, treating it as a digit-sequence rather than +an integer constant; optionally, it also scans a file name, calling +``copy_header_name`` to extract the file name from the header name token. It +puts this information into the input stack and calls routines in ``il.c`` to +remember the proper correspondence between source sequence numbers and file +name/line number pairs. + +``proc_include`` scans the file name (as a header name in one of two forms) and +then calls ``push_input_stack`` to request reading from that include file. It +calls ``copy_header_name`` to extract the file name from the header name token. + +``proc_undef`` scans an identifier, looks it up, and removes any macro +definition under that name. It will not remove predefined macros. (A +predefined macro has a source position with a sequence number of zero, and a +column number of ``SP_COL_PREDEFINED_MACRO``.) + +``#if`` and related directives depend on the ``pp_if_stack``, which is a stack +of entries describing active ``#if`` constructs. The current depth of the +stack is indicated by ``pp_if_stack_depth``. Each ``#if`` that has not yet +been closed by a corresponding ``#endif`` appears on the stack. The stack +entry indicates whether or not the ``#else`` for the ``#if`` has already +appeared, and has the source position of the ``#if`` for use as the error +position if the corresponding ``#endif`` never appears. In ANSI C or C++ mode, +each ``#if`` is required to be ended in the file in which it was begun: to +implement this, the variable ``base_pp_if_stack_depth`` contains the value of +``pp_if_stack_depth`` as of the beginning of the current source file. The part +of the stack between ``base_pp_if_stack_depth`` and ``pp_if_stack_depth`` is +considered the only active part of the stack at any given moment. ``#endif``\ +s encountered must be associated with ``#if``\ s in the active part of the +stack, and all of the ``#if``\ s in the active part of the stack must be closed +by the end of the source file (this is checked by +``verify_that_all_pp_ifs_were_closed``, which is called from +``pop_input_stack``). In ``pcc`` mode, the ``#if``\ s do not have to match up +within each file; they only have to come out right at the end of the +compilation. + +The various if-directives are handled by ``proc_if``, ``proc_ifdef`` (which +also handles ``#ifndef``), ``proc_else``, ``proc_elif``, and ``proc_endif``. +``proc_if`` and ``proc_elif`` call ``scan_if_expr``, which calls +``scan_pp_expression`` (in ``expr.c``) to scan the if-expression (there are +restrictions on what can appear in such an expression). All of the +if-processors call ``perform_if`` once they know whether or not the ``#if`` +should be executed; ``perform_if`` returns if the condition is TRUE, and calls +``skip_to_endif`` if the condition is FALSE. The latter reads lines looking +for preprocessing directives, counts nesting of ``#if``\ s, and looks for an +``#else`` or ``#endif`` that matches the current ``if``. + +A new preprocessing directive can be added by: + +* | Adding an enumeration constant to ``a_pp_directive_kind``; +* | adding a test for the directive keyword in ``identify_dir_keyword``; +* | adding a switch clause for the directive in ``pp_directive``; and +* | adding a routine ``proc_``\ *directive* to process the directive. Note + that the routine must take all the tokens in the directive (up to the + ``tok_newline``) before returning. + +AT&T Preprocessing Extensions +----------------------------- + +When ``ATT_PREPROCESSING_EXTENSIONS_ALLOWED`` is defined some of the AT&T +System V release 4 extensions to the preprocessor are supported. In that case, +the ``#assert`` and ``#unassert`` directives are handled by ``proc_assert`` and +``proc_unassert``. The data structure built for assert predicates is a simple +one: ``assert_predicates`` points to a list of ``an_assert_predicate`` entries, +each of which gives a predicate name and a list of ``an_assert_value`` entries +giving the value or values for the predicate. Entry and lookup are done with a +simple linear search. The token sequences involved are processed into +character strings (containing the token characters with a blank after each +token, and ended with a null character). Such character strings then represent +the token sequences, and can be saved and compared. +``scan_assert_predicate_reference`` is called from ``get_token`` on detection +of a ``#`` inside of an ``#if`` expression; it scans the reference and returns +1 or 0 depending on whether or not the predicate is defined with the indicated +token sequence. ``enter_assert_predicate`` can be called from ``fe_init.c`` to +enter predefined predicate names. + +C++/CLI Assembly Import +----------------------- + +The front supports the C++/CLI ``#using`` directive to import the metadata of +an assembly. This is done in function ``proc_using``. In C++/CLI mode, a +"core library assembly" (usually, ``mscorlib.dll``) is imported before input +source is processed, as well as any assemblies specified with the +``--preusing`` command-line option: Function ``process_preusings`` handles that +part (see also :ref:`cppcli-assembly-decls` and :ref:`cppcli-init`). + +Macro Processing +================ + +``macro.c`` contains the code to handle the ``#define`` preprocessing directive +and invocations of macros. ``macro.h`` contains associated declarations. + +Macro Definition Data Structure +------------------------------- + +When a macro is defined, the symbol created for it points to an entry of type +``a_macro_def`` (defined in ``symbol_tbl.h``). The macro's parameter list is +represented by a linked list of entries of type ``a_macro_param``; these give +the names of the parameters (needed only to verify that, on a benign +redefinition of the macro, the parameter names are the same). The replacement +text of the macro is a sequence of sections, each of which indicates text that +should be placed in the macro expansion at that point. Each section begins +with a byte that identifies the kind of section, as follows: + +.. list-table:: + + * - | ``rt_null`` (0) + - | marks the end of the replacement text. + * - | ``rt_text`` + - | indicates raw text that is part of the macro replacement text. The + next three bytes contain the count of characters following. + * - | ``rt_raw_argument`` + | ``rt_right_raw_argument`` + - | indicate that the raw (non-macro-expanded) text of an argument is to + be inserted at this point. This results from use of the ``##`` + operator, or from parameters scanned in ``pcc`` mode. The next three + bytes contain a number indicating the argument to be used (1 is the + first argument, 2 the second, etc.). ``rt_raw_argument`` is used for + a parameter to the left of ``##`` and for all parameters in pcc mode, + and ``rt_right_raw_argument`` is used for a parameter to the right of + ``##``. + * - | ``rt_stringized_raw_argument`` + | + - | indicates that the "stringized" text of an argument is to be inserted + at this point (this results from use of the ``#`` operator). The next + three bytes contain a number indicating the argument to be used. + * - | ``rt_argument`` + - | indicates that the macro-expanded text of an argument is to be + inserted at this point. The next three bytes contain a number + indicating the argument to be used. + +The ``##`` (paste) operator has no direct representation in the replacement +text; it just results in the two entities being placed next to each other. For +example, + +.. code:: c++ + + #define x(a,b) a ## b + +results in ``rt_raw_argument(1)`` followed by ``rt_right_raw_argument(2)``. + +White space in the replacement text is standardized. Any white space preceding +or following the replacement text is removed, as is any white space preceding +or following a ``##``, and any white space following a ``#``. All other white +space is replaced by a single space. + +Each token in the raw text (except the last, and any token preceding a ``##``) +is followed by an ``LE_END_OF_TOKEN`` lexical escape sequence. The raw text +immediately following insertions of arguments (except immediately following a +``##``) also starts with an end-of-token marker, to terminate the last token of +the inserted argument text. The end-of-token markers ensure that the tokens +will be tokenized the same way each time. For example, one problem comes up in + +.. code:: c++ + + #define z(a) ..##a + +The value of ``z(.)`` should be three "``.``" tokens, not the one token +"``...``". End-of-token markers are not used when in pcc mode, since ``cpp`` +does not operate on a token level. + +Similar standardization of white space and insertion of end-of-token markers is +done when the raw form of macro arguments is accumulated. This standardization +(of replacement text and macro argument text) makes it easier to check for +benign redefinitions and to generate the stringized form of arguments. + +The Macro Buffer +---------------- + +The global variable ``macro_buffer`` points to a large character array used as +a work area during macro processing. During macro definition, it holds the +replacement text. During macro invocation, it holds the expansions of all +macro invocations in the current line. It is dynamically allocated, and can be +expanded as necessary by calling ``expand_macro_buffer``. +``expand_macro_buffer`` will, in turn, call +``adjust_curr_source_line_structure_after_realloc`` to walk through the data +structure associated with ``curr_source_line`` and change pointers to +``macro_buffer`` to reference addresses within the new allocation for +``macro_buffer``. ``adjust_curr_source_line_structure_after_realloc`` +automatically finds such pointers in global variables and the public data +structure, but it has no way of knowing about local pointer variables. +Therefore, routines that have such variables register them by calling +``register_pointer_variable``, so that they will be found and adjusted if +reallocation is done. + +In order to reduce memory consumption when processing very complex and lengthy +macro expansions, the reallocation process for ``macro_buffer`` differs from +that of the other extensible buffers. While the other buffers are simply +reallocated, relying on the C runtime to copy the complete old contents to the +new allocation, ``expand_macro_buffer`` compacts the contents of +``macro_buffer`` by explicitly allocating a new buffer, copying data to the new +allocation only if it might still be in use, and then freeing the old buffer. +First, each existing source line modification (see +:ref:`lex-src-line-modifications`) is processed to copy its inserted text. +Within that text, only the ``ATTENTION_MARKER`` is copied from each portion +that is marked for deletion by another source line modification. (The +``ATTENTION_MARKER``\ s must be copied in order to allow scanning for inert +macro names, as described in :ref:`macro-invocations`.) As a result, the +original text of already-expanded macro invocations and the expanded text of +macro arguments will not occupy space in the new ``macro_buffer`` allocation. + +Second, text that is in the process of being constructed at the end of the +``macro_buffer`` is copied to the end of the data in the new allocation. Any +routines that build data structures incrementally, so that reallocation can +occur before the structure is complete (e.g., macro replacement text in +``proc_define``), must identify the beginning of such data using +``begin_macro_buffer_region`` and its completion with +``release_macro_buffer_region``. + +Macro Definitions +----------------- + +Macro definitions (``#define`` directive) are handled by ``proc_define``. It +scans the macro identifier, and looks it up in the symbol table (predefined +macros may not be redefined, and normal macros may be redefined only if the new +parameters and text match the existing parameters and text -- a "benign" +redefinition). If a "``(``" follows immediately (with no intervening white +space), the macro is function-like; its parameter names are accumulated as a +list. Otherwise, the macro is object-like. ``proc_define`` then scans the +replacement text and builds the replacement text string in ``macro_buffer``. +It calls ``mdefn_get_token`` to fetch tokens of the body and remember whether +or not any white space preceded each. White space is standardized, +end-of-token markers are inserted (if in ANSI C or C++ mode), parameter names +are recognized, and ``#`` and ``##`` are handled as described above. + +If in pcc mode, the opening and closing quoting characters of character +constants and string literals are scanned as single-character tokens, and the +insides of the quoted strings are tokenized. This results in recognition (and +later replacement) of parameter names within strings, as ``cpp`` does it. +Invalid tokens are passed textually to the replacement text (this is necessary +always, not just for this case), and skipped white space is kept in its +original form, so the contents of the string will be accurately rendered in the +final expansion of the macro. + +After the replacement text is accumulated, it is copied to +dynamically-allocated storage, and the macro definition is completed and +attached to the symbol. For a redefinition, the new parameter list and +replacement text are first compared textually against the old. If they match, +the new definition is thrown away. + +.. _macro-invocations: + +Macro Invocations +----------------- + +``macro_invocation`` handles the scanning and replacement of macro invocations. +It is called by ``get_token`` when an identifier that is a macro name is +scanned. + +The first thing that ``macro_invocation`` checks is whether or not the macro +name is "inert". The standard says that when a macro's name is generated in +its own expansion (directly or indirectly), it is forever after protected +against further expansion (it is inert). This is implemented by the +``assoc_macro`` field in the ``a_source_line_modif`` entry. A macro invocation +is replaced by the macro's expansion by creating a modification entry that +indicates the textual changes to be made to the source line or to a previous +modification. The ``assoc_macro`` field records the origin of any given +change, by pointing to the definition of the macro that generated the change. +Given a pointer to the name of a macro at the beginning of a possible macro +invocation, one can therefore determine whether it is in the main source line +or in a modification (or nested in several), and from that one can see whether +the macro name appears as part of its own expansion. If so, the macro name is +inert, and is left as an identifier. (Actually, it is replaced by an +``LE_INERT_MACRO`` lexical escape followed by the macro name. Once a macro +name is preceded by an inert-macro escape, it is considered inert every time it +is scanned, regardless of the context.) In pcc mode, macros are not considered +to be inert, and recursion is checked for by counting the number of nested +invocations of a given macro. + +If the macro name is not inert, processing for expansion continues. +``delete_source_from_loc`` is set to point to the beginning of the macro +identifier. This begins a "hanging delete" which will be closed when the end +of the macro invocation is found. At that point, the text of the hanging +delete will be replaced by the macro expansion, this replacement being +indicated by a source line modification entry. + +If the macro is object-like, no parameters need be scanned. However, there are +several special cases in object-like macros: For ``__FILE__`` and ``__LINE__``, +the proper expansion string is developed from the current position information +in the input stack; for ``defined``, which is an operator allowed in ``#if`` +expressions but handled as a pseudo-macro, the routine +``scan_defined_operator`` is called. It scans both forms of the ``defined`` +operator, and returns ``0`` or ``1``. Alternatively, if the identifier +``defined`` is not followed by appropriate tokens, it is left as an identifier +(see the discussion of ``check_for_following_parenthesis`` below). + +If the macro is function-like, ``check_for_following_parenthesis`` is called to +scan forward looking for a parenthesis that begins the argument list. If the +next token is not a parenthesis, then the macro name is left as an identifier. +However, this is complicated, because in skipping white space while looking for +a left parenthesis, we may have gone onto a new source line. We have to delete +the identifier before leaving the old source line, on the assumption that we +are scanning a macro invocation. If it turns out that the identifier is not +the start of a macro invocation, the identifier must be reinserted into the new +source line. + +Note the field ``sequence_id`` in ``a_source_line_modif``; it is an integer +sequence number indicating the sequence in which source line modifications were +added. This is useful in cases where modifications must be undone (as in +identifier un-deletion when a macro identifier is followed by something other +than a left parenthesis on the same line); one can find all entries with +sequence numbers greater than a certain number, and remove them. + +If a left parenthesis *is* found, the argument list is scanned, and this +requires a new data structure. An entry of type ``a_macro_arg`` contains +the text of a single argument value. That text exists in two forms -- as +"raw" text (not macro-expanded), and as "expanded" text. The +``a_macro_arg`` entries are dynamically allocated, and freed when no longer +needed (see ``alloc_macro_arg``, ``free_macro_arg``, and the variable +``avail_macro_args``). The text of macro arguments is not kept in +``macro_buffer``. + +Each macro argument is initially scanned in raw form. ``arg_get_token`` is +called, with macro expansion turned off, and the characters of each token, with +standardized white space and end-of-token markers, are placed in the array +pointed to by ``raw_text`` in the ``a_macro_arg`` entry (a +dynamically-allocated array, which can be reallocated as needed to expand it). +The scan stops when a comma or right parenthesis is found. A variable is used +to count the nesting of parentheses, so that non-zero-level commas and right +parentheses will not stop the scan. + +After the raw form of the argument has been accumulated, the raw text is +temporarily re-inserted in the source line and is re-scanned with macro +expansion on. The standard says that this must be done as if this text forms +the rest of the source file (i.e., the macro expansion is done in isolation +from the text following the raw argument value). This is implemented by having +the source modification entry that re-inserts the raw text have the field +``is_isolated_text`` TRUE. This will cause ``get_token`` and +``skip_white_space``, upon reaching the ``LE_END_OF_INSERTION`` lexical escape +sequence at the end of the raw text, to return ``tok_end_of_source`` instead of +continuing into the surrounding text. ``macro_invocation`` scans the entire +raw argument again, saving the text of the tokens scanned in the +``expanded_text`` array in the macro argument entry, and stopping when it gets +``tok_end_of_source``. If any modifications of the raw text were done because +of macro expansions (this can be determined by sequence id), they are removed. +This restores the raw text to its original state. In pcc mode, and when the +definition of the macro does not use the parameter in a context that requires +expansion,only the raw form of each argument is needed, so the rescan is not +done. + +In cases where the macro argument is the result of a previous macro expansion, +the rescan begins in the text inserted by the macro expansion modifications +rather than in the ``raw_text`` buffer. That ensures that the inertness test +can be done properly on macro names encountered in the rescanned source. Once +the rescan reaches the end of the insertions and would continue into the +primary source line, the input stream is switched to the tail of the +``raw_text`` buffer. (``raw_text`` is used instead of the primary source line +because macro arguments can be continued to subsequent source lines, and once +the next line is read the only copy of the raw argument text is in the +``raw_text`` array; the previous source line is gone.) + +This process is repeated for each argument. After all arguments are scanned +(or immediately for object-like macros), expansion is done. The length of the +expansion is first determined, and then the textual change is made, by building +up text in ``macro_buffer`` and placing a source line modification to delete +the characters of the macro invocation and insert the characters of the +expansion. + +For the special cases of predefined macros, the replacement text is already +available as a simple null-terminated string. For these cases, determining the +length and building the replacement string are easily done. + +For the other, more normal, cases, the length is determined and the expansion +string is built up by interpreting the sections of the replacement text in +order. For unexpanded uses of parameters, the ``raw_text`` is copied. For +macro-expanded uses of parameters, the ``expanded_text`` is copied. For +stringized parameters, ``stringized_arg`` is called; it copies the +``raw_text``, inserting the surrounding quotes and the additional backslashes +to protect quotes and backslashes in the string. + +The source line modification is then inserted to perform the macro expansion. + +When, in pcc mode, the expansion is for a top-level macro, +``expand_top_level_pcc_macro`` is called to expand any macro calls within the +body of the macro. A complete string for the expanded version is constructed +in an auxiliary buffer (``aux_buffer_for_pcc_macros``) and then copied back +into ``macro_buffer``, replacing the original expansion and any source line +modifications associated with it. Getting a fully-expanded string is necessary +to get pcc-like token pasting behavior across internal macro expansion +boundaries. A variant of this processing is also done in Microsoft mode. + +``macro_invocation`` then returns. It indicates to ``get_token`` whether or +not the inserted text should be rescanned. If ``macro_invocation`` already +knows what the next token should be, it returns it directly (``*rescan`` = +FALSE), thus saving ``get_token`` the time and trouble of scanning the token +text again. + +A utility debug routine ``print_markered_text`` is available for use in +printing out text strings that contain end-of-token markers and/or transitions +into or out of source modifications. + +Macro Position Tracking +----------------------- + +When ``FULLY_RESOLVED_MACRO_POSITIONS`` is TRUE, the front end keeps track of +the original location of text that is copied into macro expansions -- i.e., +either in a ``#define`` line or in an argument to a top-level macro invocation. +This "original position" information is reflected in the ``orig_seq`` and +``orig_column`` fields of ``a_source_position``. + +The principal data structure used in tracking original position information +through the various manipulations performed during macro definition and +invocation is ``a_macro_text_map``, which defines an extensible array of +``a_macro_text_map_entry`` elements (both defined in ``lexical.h``). Each of +the repositories of text associated with macro definition and invocation -- +macro definitions, the raw and expanded forms of macro arguments, and source +line modifications -- has an associated macro text map. + +A macro text map provides an ordered sequence of correspondences between +offsets in the associated text buffer and the original source locations from +which that text was copied. Each map entry defines a region of the associated +text buffer, beginning at offset ``start_of_region`` and extending up to but +not including the ``start_of_region`` of the next entry. The text at offset +``start_of_region`` originally came from the location given by +``corresponding_source_pos``, with a one-to-one correspondence of increasing +offsets and source column positions throughout the entry's buffer region. +Because the entries are ordered by buffer offset, the original source position +for a given offset can be efficiently found using a binary search (the +requisite ``bsearch`` predicate is +``compare_macro_text_map_entry_with_offset``, defined in ``lexical.c``). + +It will be helpful to trace the overall flow of information through the +definition and invocation of a macro before covering the details of how it is +accomplished. When a ``#define`` is processed, ``proc_define`` builds a text +map by incrementally recording the source position and offset in the +replacement text for each token of the definition that will be copied to the +macro expansion. A similar process occurs as each macro argument is copied to +the corresponding raw and expanded text buffers. During the interpretation of +the replacement text by ``macro_invocation``, as each section of text is copied +from the replacement text or macro argument, the corresponding entries from the +associated macro text map are copied, adjusting the offsets to reflect the +location of the text in the macro expansion (but leaving the original source +positions). Finally, when ``conv_line_loc_to_source_pos`` is called to compute +a source position for a given character location in the expanded text, the +macro text map in the source line modification is used to determine the +corresponding original source position. + +There are two principal patterns for adding entries to a text map. The simpler +pattern is when a sequence of map entries is copied from one map to another, +adjusting the offsets from being relative to the start of the source buffer to +being relative to the start of the target buffer. This technique is used to +create the text map for the source line modification containing the macro +expansion by copying portions of the text maps for the macro definition +replacement text and macro arguments. The function that performs this +operation is ``clone_macro_text_map_entries``, defined in ``macro.c``. + +The other pattern occurs when a text buffer is built incrementally by fetching +one token at a time and adding its text to a buffer. In this case, the map +entries are built to reflect either the source position of the token, if the +token is in source text, or a copy of the corresponding text map entry, if the +token comes from a source line modification (e.g., a macro argument in a macro +invocation appearing in the expansion of another macro invocation). This +technique is used to create the replacement text in a macro definition and for +both the raw and expanded text of macro arguments. It is also used when +processing a top-level macro invocation in pcc and Microsoft modes. + +Facilitating this process are the struct ``a_text_map_position_tracker`` and +the functions ``init_text_map_position_tracker``, +``add_token_to_macro_text_map``, and ``terminate_macro_text_map`` (all defined +in ``macro.c``). As each token is added to the text buffer, +``add_token_to_macro_text_map`` is called to determine whether a new entry is +required in the map for the new token: if the token is from the same source +line or source line modification as the preceding token and its offset within +the current buffer region is the same as the column offset from the region's +corresponding source position, then no new map entry is needed. If a new map +entry is required, either the appropriate map entries from the previous token's +source line modification are copied, using ``clone_macro_text_map_entries``, or +(for tokens from the current source line) a new entry is added covering the +appropriate region of the current source line for the preceding token(s). + +One complication in this processing occurs when ``macro_buffer`` is +reallocated, as described earlier. Because ``a_text_map_position_tracker`` +objects in use at the time ``macro_buffer`` is reallocated might contain the +offset of text in a source line modification's inserted text that occurs after +a portion of deleted text, and because that deleted text might be compacted as +part of the reallocation process, it is necessary to keep track of all active +position tracker objects so their current offset values can be adjusted if +necessary. + +This is done using the variable ``active_text_map_position_trackers`` (in +``macro.c``), which is the top of a stack of all trackers currently in use, and +the field ``num_active_position_trackers`` in ``a_source_line_modif``. +Whenever a token scan under control of a text map position tracker enters the +inserted text of a source line modification, its +``num_active_position_trackers`` is incremented, and it is decremented when the +scan leaves that source line modification. + +Whenever ``macro_buffer`` is reallocated, all the entries in each source line +modification's text map are examined and each offset adjusted, if necessary, to +compensate for the removal of deleted text. Furthermore, if the modification's +``num_active_position_trackers`` field is greater than zero, all the trackers +in the ``active_text_map_position_trackers`` stack are checked for references +to that source line modification and their offsets adjusted as needed. + +The text maps for macro definitions and the raw and expanded text of macro +arguments are completely self-contained: each has its own array of text map +entries and is associated with the containing data structure for the duration +of the compilation. (The array of entries for a macro definition is of fixed +size and is allocated in front-end memory, so that it will be stored in a +precompiled header, while the arrays for macro arguments are extensible.) A +different scheme is used for the text maps in source line modifications, +however. The reason for this decision is that the text map for a source line +modification may well be very large, with thousands or tens of thousands of +entries, while source line modifications themselves are ephemeral, generally no +longer needed once processing of the current logical source line has been +completed. The same reasoning led to the use of ``macro_buffer`` for the +inserted text of source line modification, so the memory management for source +line modification text maps is patterned after that of ``macro_buffer``. Just +as each modification's inserted text is simply a subrange of the text in +``macro_buffer``, the entries created during macro expansion are built in a +single map, called ``macro_text_map`` and defined in ``macro.c``, and each +modification's text map simply refers to a subrange of them. Initialization +and truncation of ``macro_text_map`` is done in parallel with the corresponding +operations on ``macro_buffer``. + +Macro Invocation Tree +--------------------- + +Maintaining the macro invocation tree is selected by setting +``MACRO_INVOCATION_TREE_IN_IL`` to TRUE. Each macro invocation is recorded in +an object of type ``a_macro_invocation_record`` (defined in ``il_def.h``), +giving the parent invocation, if any; the macro invoked; and its starting +position (as well as its ending position, if ``EXTRA_SOURCE_POSITIONS_IN_IL`` +is set to TRUE). (The "parent invocation" refers to the macro invocation in +whose argument list or expansion this macro invocation occurred. For macro +invocations occurring in program text and not in a macro argument list, +``parent_macro_index`` will have the value ``NO_PARENT_MACRO_INVOCATION``.) + +Each time ``macro_invocation`` is called to expand a macro, it calls +``register_macro_invocation`` to add an entry to the list and obtain the index +of the newly-added entry. This index and the macro invocation stack depth at +that point are stored into the source line modification created to hold the +macro's expanded text. These values are used by recursive calls of +``macro_invocation`` (to expand macro arguments) and by calls resulting from +rescanning expanded text to maintain the chain of parent invocations when the +macro name comes from a source line modification rather than directly from +source text. + +Because variable-length data is awkward to represent in the IL (and extensible +arrays are not possible in memory regions), the macro invocation records are +grouped into fixed-size blocks (``a_macro_invocation_record_block``, defined in +``il_def.h``). In the IL, these blocks are organized into a binary tree to +facilitate relatively-efficient random access by index. During front-end +processing, however, they are kept in a doubly-linked list: apart from +diagnostic output, which need not be terribly efficient, there is no need for +random access to the invocation records (and even diagnostic output will most +often refer to records near the end of the list, so long linear searches are +uncommon). It is more efficient to create the binary tree form once, after the +total number of records is known, than to balance the tree repeatedly while it +is being created. + +The ``macro_invocation_record_block``\ s are reorganized into a binary tree and +the relevant fields of ``il_header`` are set at the end of the translation unit +by a call to ``copy_macro_invocation_tree_to_il`` (defined in ``macro.c``). + +An additional effect of setting ``MACRO_INVOCATION_TREE_IN_IL`` is that +``a_source_position`` is extended to include the ``macro_context`` field. This +field reflects the macro invocation in whose expansion the source position +resides, i.e., it is logically simply a copy of the ``invocation_record`` field +of the containing source line modification. However, the special treatment +given to top-level macros in pcc and Microsoft mode, in which the expansion of +the macro is rescanned for expansion and the result is copied back into the +source line modification corresponding to the top-level macro invocation, means +that the subsidiary source line modifications are no longer available at the +time source positions are being computed. + +To avoid this problem, the macro invocation index that will be stored by +``macro_invocation`` into source line modifications is also kept in the +``macro_context`` field of each text map entry created for that invocation. +This information is preserved when the text maps for the subsidiary source line +modifications are cloned into the top-level modification by +``expand_top_level_pcc_macro``. This additional information allows the +``macro_context`` field in source positions to be set in the same way as the +original position information, by looking up the offset in the text map of the +top-level modification. (This is the reason that it is not permitted to set +``MACRO_INVOCATION_TREE_IN_IL`` to TRUE without also setting +``FULLY_RESOLVED_MACRO_POSITIONS`` to TRUE.) + +Unicode Version-Dependent Features +================================== + +The front end has three distinct features that depend on the definitions +and classifications of characters in the Unicode standard and thus might +need to be updated when new versions of Unicode are released. The following +subsections discuss each of these features and what is involved in a potential +update. + +Classification of Identifier Characters +--------------------------------------- + +The front end must, of course, determine whether a given character can +appear in a C/C++ identifier in order to find the start and end of +identifier tokens during lexical analysis. There is also a distinction +between characters that can begin an identifier and those that can appear +only after the initial character; for example, ``'0'`` cannot be the first +character of an identifier but it is valid in the succeeding positions. + +For single-byte character sets, this classification is done using boolean +arrays indexed by the character value; see the declarations of +``is_id_char``, ``is_id_char_no_mbc``, and ``char_ends_id`` in +``lexical.h`` and their initialization in ``lexical_one_time_init`` in +``lexical.c`` for details. + +The situation is more complicated for multi-byte characters, whether +appearing directly in the source or via a *universal-character-name*. For +C++23 (and, because the relevant paper was adopted as a defect report, for +previous versions as well) and C23, the determination is based on the +Unicode ``XID_Start`` and ``XID_Continue`` Derived Properties as specified +in `www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt +`__. +(Specific versions of this file can be found by replacing ``UCD/latest`` +with the version number, e.g., ``15.1.0``, in the URL.) Earlier versions of +the C and C++ standards used different methods to specify these +classifications, however, and the front end continues to support those +variants for backward compatibility. + +The mechanism for achieving compatibility with multiple classification +schemes is the ``UCN_table`` array, defined in ``lexical.c``. The elements +of the array are objects of the following struct: + +.. code:: c++ + + typedef struct a_UCN_range { + unsigned long start; /* The first character in the range. */ + unsigned long end; /* The last character in the range. */ + a_byte dialects; + /* A bit set indicating the dialects for which this + range of characters is accepted. See below for + the encoding masks. */ + a_byte non_initial_dialects; + /* A bit set indicating the dialects for which this + range of characters is not permitted as the + first character of an identifier. This uses the + same encoding as dialects. */ + } a_UCN_range; + +Characters tend to occur in groups, so to reduce the storage requirements +of the array, each element describes a contiguous range of characters, all +of which share the same treatment in all of the supported classification +schemes. The elements of the array are sorted in strictly-ascending order +of code point so that the array can be efficiently searched using a binary +search. The ``dialects`` and ``non_initial_dialects`` members are bit sets +with each bit representing a different language dialect, specifying how the +characters in the specified range are classified in the various +dialects. The C++23/C23 dialect is represented by the ``UAX44`` bit (so +named because the ``XID_Start`` and ``XID_Continue`` properties are +described in Unicode Annex #44). + +From the perspective of updating this table when new versions of Unicode +are published, the principal requirement of this table is that all members +of a given character range must be classified the same way in all of the +supported dialects. A change in the classification of a character in a new +Unicode version thus typically means that an existing range in the table +must be split, so that any characters before and/or after the character of +interest can maintain their previous values while that character's +``UAX44`` bits reflect the new Unicode classification (maintaining the +previous values for all the other flags). As a specific example, the +``DerivedCoreProperties.txt`` file for Unicode version 15.1.0 contained +(among others) the following changes from version 15.0.0: + +.. code:: text + + +2EBF0..2EE5D ; XID_Start # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D + . . . + +2EBF0..2EE5D ; XID_Continue # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D + +These changes indicate that the characters in the indicated range can now +appear both within identifiers and as the first character of an +identifier. These code points were previously contained within the range of +the following element of the ``UCN_table`` array: + +.. code:: c++ + + { 0x2ebe1, 0x2f7ff, _ | _ | CPP11 | _ , _ | _ | _ }, + +As a result, the range needed to be split in order to preserve the +classification of the characters before and after the new 15.1.0 range, +resulting in the following three elements to replace the existing one: + +.. code:: c++ + + + { 0x2ebe1, 0x2ebef, _ | _ | CPP11 | _ , _ | _ | _ }, + { 0x2ebf0, 0x2ee5d, _ | _ | CPP11 | UAX44, _ | _ | _ }, + { 0x2ee5e, 0x2f7ff, _ | _ | CPP11 | _ , _ | _ | _ }, + +Note both the addition of the ``UAX44`` flag in the initializer for +``dialects`` and its absence in the initializer for +``non_initial_dialects``, since the latter specifies dialects for which the +characters are *not* permitted to start an identifier. + +Detection of Source Code Unicode Vulnerabilities +------------------------------------------------ + +One potential avenue of source-level exploits relies on the fact that a +number of distinct Unicode characters have similar or identical glyphs. For +example, the Latin, Greek, and Cyrillic alphabets each have a character +whose visual appearance is "A", even though the code points for those +characters are different. This permits the creation of programs with +vulnerabilities that cannot be detected by even a careful code review (by +hijacking overloaded function calls, for example). + +Unicode provides a table, +`www.unicode.org/Public/security/latest/confusables.txt +`__, that +enumerates such potentially-confused characters (replace "latest" with the +version number to access the specification for a specific version). This +table is described in +`www.unicode.org/reports/tr39/ `__. + +The front end incorporates this data as the array ``confusable_map``, +defined in ``lexical.h``, which is a lightly-massaged version of the +contents of ``confusables.txt``. Each element of the array is an object of +the following struct: + +.. code:: c++ + + struct a_confusable_map_elem { + int src_char; /* The numeric value of a Unicode code point whose + glyph could be confused with that of another + code point. */ + int prototype[MAX_PROTOTYPE_LENGTH]; + /* The numeric values of the Unicode code points of + the prototype character(s) for src_char, as + defined in unicode.org/reports/tr39, "Unicode + Security Mechanisms", section 4. */ + }; /* a_confusable_map_elem */ + +The elements are in strictly-ascending order of ``src_char``, to facilitate +efficient searching using a binary search. + +Although the entries in ``confusables.txt`` are not in the same order as +the elements of ``confusable_map``, that does not present a significant +issue for updating the front end for new Unicode versions, as the mapping +from the Unicode data to the corresponding array initializer is +obvious. For example, a representative line of the version 15.1.0 file is: + +.. code:: text + + 2238 ; 002D 0307 ; MA #* ( ∸ → -̇ ) DOT MINUS → HYPHEN-MINUS, COMBINING DOT ABOVE # + +and the corresponding initializer element is: + +.. code:: c++ + + { 0x02238, { 0x002D, 0x0307 } }, + +Thus, a simple ``diff`` of two versions of the ``confusables.txt`` file +provides sufficient information for any required updates. + +Such updates are expected to be infrequent, in any event, as the base data +is not likely to change very much over time. If desired, the +``edg-make-confusables-data`` script can be used with a given version of +``confusables.txt`` to create the entire initializer for +``confusable_map``. + +Named Unicode Escapes +--------------------- + +C++23 introduced the capability of incorporating a given Unicode character +into the source text by specifying its full name, using the syntax ``\N{``\ +*character-name*\ ``}``. This feature requires the front end to be able to +distinguish valid *character-name*\ s from invalid ones and to determine the +code point associated with each valid name. + +Because Unicode defines tens of thousands of characters, with the average +name being over thirty characters in length, this task is necessarily +data-intensive. A naive straightforward approach, e.g., a sorted array of +character names and code points searched using a binary search, would +require around 1.5 megabytes of data and up to sixteen probes to match a +given character name, so it would be fairly inefficient in both data and +execution time. + +The approach chosen for the front end implementation of this feature uses a +fairly straightforward finite state machine (FSM), with each state +representing the initial substring of characters in one or more character +names and each transition designating the state that would result for a +specific character following that initial substring in a valid Unicode +character name. There are a few simple optimizations to reduce the size of +the data containing the FSM; sequences of single-transition states are +compressed into a single state that matches a sequence of characters and +has a single transition on the final one, and the algorithmically-named +ranges for CJK and Tangut ideographs are also condensed into single states +matching the common prefix and specifying their respective ranges of code +points. Incorporating these optimizations, the storage required for the +state machine for the names in Unicode 15.1.0 is about 510 kilobytes, much +less than the naive implementation, and its performance is also much +better. + +The data for the Unicode character names and code points comes from two +files: `www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt +`__ and +`www.unicode.org/Public/UCD/latest/ucd/NameAliases.txt +`__. (The +files for specific versions can be found by substituting the version +number, e.g., ``15.1.0``, for ``UCD/latest`` in the URLs.) + +The data for the state machine in the front end is contained in the array +``unicode_name_fsm``, defined in the file ``unicode_name_fsm.c``. Because +this table cannot be edited by hand, there is a utility that produces that +file in its entirety, with no manual editing required. To run the utility, +download the two files above from the ``unicode.org`` web site and issue +the following command: + + ``process_unicode_names UnicodeData.txt NameAliases.txt`` *output-file version date* + +where *output-file* is any file name (it must be copied to +``unicode_name_fsm.c`` if that file is not updated *in situ*); *version* is +the Unicode version number (e.g., ``15.1.0``); and *date* is the release +date of the Unicode version (e.g., ``2023-08-28``). (The latter two +command-line arguments are incorporated into the comments in the generated +source file.) + +The source for the utility is found in the +``dev_tools/cpp_tools/process_unicode_names`` subdirectory. Any changes +desired in the contents of ``unicode_name_fsm.c`` (such as updating the +copyright date) should be edited into the utility source in the +initializer for the ``header_text`` variable, since any manual edits in +``unicode_name_fsm.c`` will be overwritten by the next run of the utility. + +.. [#f1] Trigraphs and line splices are not undone and so do not appear in the + output. +.. [#f2] As mentioned previously, the actual newline character is replaced by + a lexical escape sequence beginning with ``LE_ESCAPE`` (zero) so that + the newline character can be freed up for use as ``ATTENTION_MARKER``. +.. [#f3] See :ref:`recognizing-generalized-identifiers` for more + information regarding vacuous destructors. +.. [#f4] A name is "looked up" by calling the appropriate symbol table lookup + routine, which updates the ``specific_symbol`` field in the symbol + locator. +.. [#f5] ``A`` is equivalent to ``A`` in the scope of a template class + instance. +.. [#f6] Which is used in looking up identifiers that might be types or might + be part of a declarator. diff --git a/dev/doc/_sources/lower_il.rst.txt b/dev/doc/_sources/lower_il.rst.txt new file mode 100644 index 0000000..fcf36e7 --- /dev/null +++ b/dev/doc/_sources/lower_il.rst.txt @@ -0,0 +1,3917 @@ +.. + The following substitutions are used to align code that must be written + without using a code block because of embedded formatting. |_| is a + Unicode em space, while |.| is an en space. A combination of the two in + the leading white space of a line can closely approximate the desired + alignment of the following text. + +.. |_| unicode:: U+2003 +.. |.| unicode:: U+2002 + +.. _il-lowering: + +=========== +IL Lowering +=========== + + + + +When we started developing the C++ front end, one of the first design decisions +we had to make was what intermediate language it would generate. + +We already had a C front end (supporting the C89 version of the language) and a +Fortran front end. The C front end generated an intermediate language that +looked a lot like C, and the Fortran front end generated an intermediate +language that looked a lot like Fortran. The two intermediate languages were +compatible in the sense that they had the same structure and could be combined +into an intermediate language that is the union of the two. + +It seemed clear that the C++ intermediate language ought to be compatible with +the other two languages in that same sense, and that in fact it should be a +superset of the C intermediate language, since C++ is (almost) a superset of +C89. (When we talk about the C intermediate language or "C IL", we generally +refer to the IL to represent C89 constructs, not to the extensions supporting +the current C99 standard and other dialects like GNU C.) + +But how much of a superset? Since our IL philosophy for Fortran and C had been +to make "high-level" ILs that were very close to the source language, our +initial inclination was to make an intermediate language with lots of new C++ +features that would be the same sort of thing for C++. It seemed like the +obvious approach. When we analyzed that idea, and discussed it with customers, +however, we realized a few things: + +* | There's a big semantic jump from C to C++. Some of the C++ features are + much more complicated than C or Fortran features. Implementing them in a + back end would add a *lot* of work, and requires a lot of knowledge of the + C++ language. + | Since our corporate mission is to deliver front ends that take care of + all of the language issues and the attendant grief so that back ends + can just worry about code generation (and *its* attendant grief), it + didn't seem that we would be doing our full job by generating the + high-level C++ IL. +* | We had customers that had existing C back ends and were interested in + adding C++ with minimum development cost. + +Okay then, what about generating an IL that's very close to the C IL? After +all, because of USL's cfront, people view C++ as a language that can be +translated into C, maybe even as a macro language on top of C. Well, there are +problems with that, too: + +* | It hides information that is useful in generating symbolic debugging + information. (This has historically been a weakness of cfront-based + compilers, forcing programmers to debug using the generated C code.) +* | It makes it harder for a back end to use unconventional or aggressive code + generation techniques for C++ constructs. +* | It makes the front end less suitable for use in source-analysis tools (they + want to analyze the C++ source, not some version of it translated into C). + +We considered various levels of intermediate language between the full C++ and +full C extremes, and all were unsatisfactory in some way. Then David Callahan +of Tera Computer suggested that we do it both ways, that we generate a full C++ +IL and also supply a piece of software that translates that IL into the +existing C IL. + +Thus was born IL lowering. The front end proper generates a true C++ IL, and +IL lowering translates that IL into C IL, which can then be fed into a C back +end or the C-generating back end we use for testing. It should be noted that +although "lowering" is what's done, the output is still "high-level" -- it's +not as high-level as it was, but it's still at the level of the intermediate +language for C89. + +The IL lowering pass is optional. It need not be used if it's not wanted. The +IL utilities work with both versions of the IL. + +Since many C++ features go into IL lowering as abstractions and come out as C +code, IL lowering is actually choosing implementations of those features. The +implementations are at the same level as those in cfront. That is, they are +relatively "standard" implementations. As one would expect, the generated C +has some of the same complex unreadable quality that cfront output has, and the +same ridiculously complex expressions. The front end can even be configured to +produce constructs that are object-code compatible with cfront's. +Alternatively, the front end can generate code compatible with the IA-64 +(Itanium) ABI. + +IL lowering can also do inlining, though we firmly believe that that is +something that only a back end can really do properly. [#f1]_ + +The IL lowering pass seems to solve the problems raised: + +* | Both the C++ and C forms are available for those who prefer one form or the + other. In fact, one can use both forms, e.g., one could generate symbolic + debugging information from the C++ form and object code from the C form. +* | It allows customers to get a C++ compiler going in minimal time. +* | If the features implemented by IL lowering require some minor changes, the + changes can be made in IL lowering, which is relatively small, rather than + in the front end as a whole, which is quite large. +* | If a customer wants to attach a back end to the unlowered IL (either + initially or for an improved release of a compiler), the IL lowering code + serves as a guide to the tasks that must be done. + +Even though IL lowering will rewrite uses of non-C89 features, the C++-specific +fields of the IL are still present in the IL entries. Back ends should not +count on those fields being cleared; rather, they should ignore them and +consider only the fields that C uses. Viewed that way, the lowered IL should +contain nothing that would not show up in a C intermediate language tree. + +One catch: Dynamic initialization of entities in the middle of blocks is left +in its original form. This is not "incorrect" C IL, but is something that does +not come up in C89 programs. It was judged that back ends would be capable of +dealing with the ``stmk_init`` statements even if they appear after other +executable statements in a block, and the alternative was to make lowering of +initialization of aggregates to constants quite messy. + +The code for IL lowering is in ``lower_il.c``, and the associated declarations +are in ``lower_il.h``. Name mangling code is in ``lower_name.c`` and +``lower_name.h``. Code for lowering initializations, new/delete, and +constructors/destructors is in ``lower_init.c`` and ``lower_init.h``. Code for +lowering exception handling features is in ``lower_eh.c`` and ``lower_eh.h``. + +Certain higher-level constructs -- like variable-length arrays and complex +floating-point types -- from more recent C dialects (primarily C99, but also +GNU C) can also be lowered to C89-level IL. The code for this is done +primarily in ``lower_c99.c``. See :ref:`lowering-c-dialects` for an overview +of the constructs in this category that can be lowered. + +Finally, IL lowering can also ensure that boolean controlling expressions +(e.g., the expression controlling which way an if-statement goes) always +produce an integer value 0 or 1 (as opposed to "zero or nonzero" or "null or +nonnull"). This normalization -- enabled by setting +``LOWERING_NORMALIZES_BOOLEAN_CONTROLLING_EXPRESSIONS`` to TRUE -- can occur in +all modes (C++, C89, etc.) and usually involves adding a "``!= 0``" comparison +to the controlling expression. + +ABI support +=========== + +The front end and IL lowering support two ABIs (Application Binary Interfaces). +An ABI is a set of conventions for the runtime environment, which prescribes +class layout, access to virtual functions, name mangling, etc. Code generated +by two compilers that are compatible with a given ABI should, in theory, be +able to interact properly, and with libraries that are compatible with that +ABI. + +Up through version 3.0, the front end supported a single ABI and some minor +variants thereof. This ABI, referred to as the "cfront-like ABI," is an +extended version of the original ABI used by cfront. The extensions were +invented by EDG, and therefore the ABI does not conform to any industry +standard, other than in its general compatibility with what was once a *de +facto* standard. The variants of the cfront-like ABI are: + +* | cfront 3.0.1 compatibility, selected by setting + ``CFRONT_3_0_OBJECT_CODE_COMPATIBILITY`` to TRUE. +* | cfront 2.1 compatibility, selected by setting + ``CFRONT_2_1_OBJECT_CODE_COMPATIBILITY`` to TRUE. +* | If neither of those variants is selected, the default ABI is cfront-like + with some minor quirks eliminated, principally with respect to allocation + of space for virtual base classes. This variant was originally intended as + the default and best ABI, but in practice it hasn't been used very much, + and the IA-64 ABI (see below) is a better choice. + +As of version 3.1, the front end also supports the IA-64 ABI, described by +https://itanium-cxx-abi.github.io/cxx-abi/abi.html. This is a modern ABI +originally designed for the Intel IA-64 ("Itanium") architecture, but now an +industry standard widely used on other architectures as well. In particular, +the GNU g++ compiler uses the IA-64 ABI on many platforms. This ABI is +selected by setting ``IA64_ABI`` to TRUE. Note that the fully-lowered +implementation of exception handling provided by EDG works with the IA-64 ABI, +but does not conform to the spec, and that versions using the C-generating back +end do not fully conform because of some layout cases not easily represented in +C. + +Note that the IA-64 ABI requires linker support in the form of a feature (often +called COMDAT) that allows different object files to contain (identical) +definitions of certain functions and variables. The linker discards the +duplicates, ending up with a single definition. + +The ABI support in the front end changes from time to time as features are +added and bugs are fixed. The macro ``ABI_COMPATIBILITY_VERSION`` can be set +to a version number of the front end to keep the ABI frozen as it was at that +version. Source language features that require ABI changes made after that +version are disabled. + +What Does C++ IL Lowering Do? +============================= + +IL lowering is called at the end of processing of each "top-level" scope (i.e., +once at the end of each top-level function, and once at the end of the file +scope). It rewrites any C++ IL constructs in the scope as semantically +equivalent C IL constructs. (A similar process occurs for C99 IL; see +:ref:`lowering-c-dialects` for details.) + +IL Lowering is suppressed if there are errors in the source program, if the +dialect of C language being compiled doesn't require it, if preprocessing only +is being done, or if syntax-checking only is being done. + +Name Mangling +------------- + +(Code for name mangling is in ``lower_name.c`` and ``lower_name.h``.) + +"Name mangling" means transforming the names of C++ entities so that the names +include information on aspects of the entity's type and fully qualified name. +This is made necessary by the fact that the object code and C environments into +which a C++ program is translated typically contain fewer and simpler name +spaces than there are in the C++ language. Specifically: + +* | Overloaded function names are not allowed in C, and probably not in object + code. +* | Classes have their own scopes in C++, but not in the generated C form. An + entity ``x`` from inside a class must not conflict with an entity ``x`` + from the file scope, for example. +* | External names in C and (probably) in the object code form a completely + flat name space. The names of C++ entities with external linkage must be + projected onto that name space so that they do not conflict with one + another. A function ``f`` from a class ``A``, for example, must not have + the same external name as a function ``f`` from class ``B``. +* | Some C++ "names" are not names in the conventional sense of the word + (they're not strings of alphanumeric characters), e.g., ``operator=``. + +We can see that there are three problems here: + +* | Generating C code names that will not clash for non-external entities. + This is only a problem when generating C code. +* | Generating external names that will not clash. This is a problem whether + the output is C or object code. +* | Generating alphanumeric names for entities with strange "names" in C++. + This is a problem whether the output is C or object code, at least for + external names. + +As it happens, the name mangling process solves all three problems. It also +solves the problem of generating hidden names for some behind-the-scenes +language support in such a way that they will match up across separate +compilations (e.g., virtual function table names). + +Once name mangling has been done, the name linkage of C++ external entities is +changed to C external. + +Cfront-like ABI name mangling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The cfront-like ABI name mangling algorithm is the same as the one used by +cfront, and also matches the description in 7.2.1c of the ARM (except for some +minor details). The reader is referred there for a complete description. +Here, we just hit the highlights and the things that differ from or are +extensions to that description. + +Each type has a corresponding mangled encoding. For example, a class type +is represented as the class name preceded by the number of characters in +the class name, as in ``5abcde`` for ``abcde``. Simple types are encoded +as lower-case letters, as in ``i`` for ``int`` or ``f`` for ``float``. +``long long``, ``wchar_t``, and ``bool``, which do not appear in the ARM, +are encoded as "``L``", "``w``", and "``b``", respectively. The C++11 +types ``char16_t`` and ``char32_t`` are encoded as "``g``" and "``k``", +respectively. A ``std::nullptr_t`` type is encoded as "``n``", while the +C++/CLI ``__nullptr`` is encoded as "``j``". (In some Microsoft modes, +there are distinct integral types named ``__int8``, ``__int16``, +``__int32`` and ``__int64``. They are encoded as "``m1``", "``m2``", +"``m4``", and "``m8``", respectively.) 128-bit integers (in GNU +compatibility mode) are mangled with "``m16``" and "``Um16``" (signed and +unsigned, respectively). Type modifiers and declarators are encoded as +upper-case letters preceding the types they modify, as in ``U`` for +unsigned or ``P`` for pointer. In GNU C++ mode, complex types are encoded +with an "``x``" preceding the code for the corresponding real +floating-point type (e.g., "``xf``" for "_Complex float"). The ``long +double`` type is indicated by an "``r``" encoding. In addition to the type +declarators mentioned in the ARM (i.e., "``P``" for pointer, "``R``" for +reference, "``A``" for array, "``F``" for function, and "``M``" for +member), an "``E``" encoding has been added to indicate an rvalue +reference. For ref-qualified member function types, an optional "``_R``" +(for an lvalue req-qualifier) or "``_E``" (for an rvalue ref-qualifier) can +follow the "``F``" that indicates a function type. When C++/CLI is +enabled, the "``Ht``" encoding is used for tracking references, "``Hh``" is +used for handles, "``Hi``" is used for ``interior_ptr``, and "``Hp``" is +used for ``pin_ptr``. ``__underlying_type`` (enabled when type trait +helpers are enabled) is mangled as "``o``". See +``mangled_encoding_for_type``. + +Types specified using the C++11 keyword ``decltype`` are encoded in one of +three ways. When a ``decltype`` expression is either type-dependent or +value-dependent (i.e., it has some component that could be affected by the +C++11 SFINAE rules), it is said to be instantiation-dependent and it is +encoded using the character "``y``" or "``Y``" followed by a mangled +encoding of the expression ("``y``" is used when the expression is an +unparenthesized id-expression or a class member access; "``Y``" is used +otherwise). ``decltype`` expressions that are not instantiation-dependent +are encoded using the known underlying type or value (e.g., +``decltype(sizeof(int))`` is mangled using the mangled encoding for the +``size_t`` type, i.e., "``Ui``" in a front end that is configured to use +``unsigned int`` to represent ``size_t``). In a manner similar to +``decltype``, ``typeof``\ (*type*) is mangled using the encoding "``t``" +and ``typeof``\ (*expression*) is mangled using the encoding "``p``". The +"``u``" mangled encoding is also introduced in C++11 to represent the use +of ``auto`` as a type specifier when it appears in a *new-expression* that +is mangled because it appears in the context of an instantiation-dependent +expression (e.g., ``decltype(new auto(p1))``). The letter "``n``" is used +to encode the type for ``nullptr`` (i.e., ``std::nullptr_t``). The "``q``" +mangled encoding is used for the ``decltype(auto)`` notation. + +When a function parameter is a C++11 function parameter pack, its type is +represented by the encoding "``Dp``" followed by the function parameter type. + +Nested class types are encoded as a "``Q``" followed by a digit indicating the +depth of nesting, followed by a "``_``", followed by the mangled-form names of +the class types in the fully-qualified name of the class, from outermost to +innermost: + +.. code:: c++ + + class A { + class B { // Q2_1A1B + }; + }; + +The name of the nested class itself is mangled to the form described above with +a prefix ``__``, which serves to make the class name distinct from all user +names. The same mangling technique is used for namespaces. In cases where the +mangled entity is specified in the source code as being in the global scope +(e.g., ``p->::X::y``), and the entity is a selection or call operand, the +global scope indication is specified using the letter "``G``" as the first +qualifier in a qualified name; for example: + +.. code:: c++ + + int g(int); + template auto f(T p1) -> decltype(::g(p1)); + // f__tm__2_i__FZ1Z_YOcl_2_4g__GI1IO + +Local class names and scoped enumerators are encoded by following the name by +"``__L``" followed by a number (which has no special meaning; it uniquely +identifies the type within the function scope). This example (which requires +--c++11) shows a local class and its mangling within a function template: + +.. code:: c++ + + template void f(T) {} + void x() { + struct A {} a; // __12A__L1__x__Fv + f(a); // f__tm__15_12A__L1__x__Fv__FZ1Z_v + } + +This form is used when encoding the local class name as a type. It's not +actually necessary to mangle the name of the local class itself unless it's +also a nested class. See ``mangled_type_name_full``. This is not in the ARM, +and cfront does it slightly differently. + +The "``__L``" indicator is also used in the names of entities promoted out of +functions. There, the "``__L``" appears between the name of the entity and the +mangled name of the function: + +.. code:: c++ + + void *f() { + struct A {}; // __12A__L1__f__Fv + static struct A a; // a__L0__f__Fv + return &a; + } + +The instance number (after the "``__L``") serves to ensure that the mangled +name is unique (and is chosen so as to make it repeatable across translation +units in cases where the ODR requires it). Note that in configurations where +local types cannot be used in template arguments (i.e., other than --c++11 or +when microsoft_mode >= 1400) and therefore can't appear in external names, the +mangled names may differ slightly from those listed above. + +Unnamed namespace names are mangled as ``__N`` followed by a unique string. +The unique string is the "module id" generated by IL lowering from the source +file name and some other information, but from the perspective of name mangling +it is simply ignored. Such names appear only in contexts where their length is +given, so it's easy to know how much to ignore. + +Template classes have mangled names that encode the arguments of the template: + +.. code:: text + + template class abc {}; + abc x; + abc__tm__3_ii + ^^--- Two template arguments of type int. + ^------ Total length of template argument list string, including + the underscore. + ^^--------- Fixed string, indicates "template". + ^^^------------- The name of the class template. + +When distinct mangling for templates is disabled, "``tm``" is replaced by +"``pt``" (which is what cfront uses). + +The encoding for nontype template arguments encodes both the parameter type and +the actual argument value: + +.. code:: text + + template class def {}; + def<5> x; + def__tm__7_XCiL15 + ^-- Literal constant representation. + ^--- Length of literal constant. + ^---- "L" indicates literal constant, "c" indicates address + of variable, etc. + ^^----- Type of template argument, with "const" added. + ^------- "X" indicates beginning of constant argument. + +Template argument packs are introduced by "``__pk__``": + + .. code:: text + + template int f(); + int x = f(); + f__tm__12_s__pk__3_id__Fv_i <-- encoding for "f()" + ^---- Return type (int). + ^------ Argument list (void). + ^------- Function. + ^---------- Second argument of the pack (double). + ^----------- First argument of the pack (int). + ^------------- Total length of template argument pack. + ^^---------------- Beginning of a template argument pack. + ^-------------------- First template argument type (short). + ^^---------------------- Total length of template argument list. + ^^-------------------------- Introduces template arguments. + ^------------------------------ The name of the function template. + +Constants are encoded with the letter "``C``" followed by the type of the +constant and the encoding of the constant value (e.g., "``CiL_2_59``" +represents the integer constant 59). There are several different encodings +for different kinds of constants: + +* | Integer: + + .. code:: text + + L3n12 <-- encoding for "-12" + ^^----- Literal value. + ^------- "n" indicates negative. + ^-------- Length of the literal. + ^--------- "L" indicates a number. + + | This is compatible with cfront 3.0.1. + | + | The length of the literal uses an encoding compatible with cfront, i.e., + it's either a single digit or two digits followed by an underscore (e.g., + "``L10_1234567890``"). This encoding has some ambiguity problems when the + template argument is followed by an underscore. Such cases did not come up + in the cfront world, but they do come up when template arguments are + applied to template functions (see paragraphs on distinct mangling for + templates, below). To deal with this, a new unambiguous mangling for + literal lengths has been introduced as of version 2.32. It has the length + enclosed in underscores in all cases (single- or multi-digit), e.g., + "``L_1_2``". This form is used in the new contexts that didn't come up for + cfront, and the old form continues to be used in the cfront contexts. +* | Float: + + .. code:: text + + L4n1p5 <-- encoding for "-1.5" + ^^^---- Literal value ("p" for decimal point). + ^------- "n" indicates negative. + ^-------- Length of the literal. + ^--------- "L" indicates a number. + + | cfront 3.0.1 does not implement this, so we made it up. In actuality, the + literal form of the floating constant depends on the ``fp_to_string`` + routine, so the encoding is likely to be longer (for example, it's likely + to include an exponent). +* | Complex floating point literals are mangled like floating point literals + above except that both real and imaginary components are included: + + .. code:: text + + L_3_0d0_3_1d1 <-- encoding for "0.0+1.0i" + ^^^---- Imaginary portion of complex number. + ^^^------- Length of the imaginary portion of the number. + ^^^---------- Real portion of complex number. + ^^^------------- Length of the real portion of the complex number. + ^---------------- "L" indicates a number. + +* | Address of variable or routine: + + .. code:: text + + 4abcd <-- encoding for address of "abcd" + ^^^^---- Name of entity. + ^-------- Length of the name. + + | This is compatible with cfront 3.0.1. +* | For pointers to data members, the offset value encoded as an integer: + + .. code:: text + + L212 <--- encoding for an offset of "12" + ^^------ Literal value. + ^-------- Length of the literal. + ^--------- "L" indicates a number. + + | This is compatible with cfront 3.0.1. +* | For pointers to member functions, the ``__mptr`` triplet of values (delta, + index, function or offset), encoded as follows: + + .. code:: text + + LM0_L2n1_1j + ^^- Function name, or alternatively "0" if the pointer + to member uses an offset (e.g., LM0_L11_0). + ^^^^---- Index value, encoded as an integer. + ^--------- Delta value. + ^^---------- "LM" indicates a pointer to member function. + + | This is compatible with cfront 3.0.1. Note that "``0``" is always used + for the offset, not the actual offset value. This follows cfront. The + idea seems to be that "0" is really a way of saying "there is no + function;" the offset value itself would not be of interest to a name + demangler. +* | For strings, the type of the string is encoded. The character "``S``" + is used to indicate a string literal. The string ``L"xyz"`` is encoded + as "``CA4_CwLS``" (i.e., a string literal of type ``const wchar_t[4]``). +* | ``nullptr`` is encoded using the encoding for integers given above; the + type is always "``n``" (for ``std::nullptr_t``), and the value is + always zero, so the entire mangled encoding for ``nullptr`` is always + "``CnL_1_0``". + +The fact that there are rules for mangling type names seems to suggest that +names of types are mangled. Strictly speaking, except for nested class names, +they are not. It is really only the names of variables and routines that need +to be mangled. The mangled form of type names does have a use, however: it is +used when building the mangled names of variables and routines, to represent +the types referenced by the entity (e.g., parameter types). + +Unnamed (class/struct/union, enums, lambda closure) types are given a generated +name during mangling; that name is then used as described above (e.g., in +mangled names of variables and routines). The names generated for these +unnamed types are constructed so as to ensure that types subject to ODR +constraints across translation units are given the same name; other types are +given names guaranteed not to collide with similar constructs in other +translation units. + +Unnamed class/struct/union and enums are given the name "``__Ut``" followed by +an instance number (within the namespace/class/function scope) which makes the +generated name unique within that scope. A mangled encoding of the type will +include its parent's encoding as well. + +Lambda closure types are a special kind of unnamed class type, and they are +mangled with a similar "``__Ul``" encoding that additionally gives information +about the lambda's parameter types: + + .. code:: text + + __Ul1_Fif <-- [](int, float)->float {return 0.0;}(i, f); + ^^^---- Lambda operator() function type (int, float). + ^-------- Instance (within parent scope). + ^^^^--------- "__Ul" indicates lambda. + +Lambdas defined in certain contexts, specifically some default arguments and +member initializers, are subject to ODR constraints and therefore must get +names that can be generated identically in different compilations. That's +accomplished by making the default argument or member initializer a +"pseudo-parent scope" and encoding the closure type as a member of that +pseudo-scope. + +Lambdas defined in default arguments (and subject to ODR constraints) are given +a name based on this encoding: + + .. code:: text + + __Ud1_2_Fv__L0__f__FiT1 <-- void f(int i=[]{return 0;}(),int k=0) + ^^^^^^^^^^^^^---- Local to function f(int,int). + ^^----------------- Lambda operator() function type. + ^-------------------- Declared in trailing parameter 2. + ^---------------------- Instance 1 (within parameter). + ^^^^----------------------- "__Ud" indicates lambda in default arg. + +Lambdas in member initializers are given a name that is prefixed with +"``__Um``": + + .. code:: text + + __Q3_10S__tm__2_i1x8__Um1_Fv < template int S::x = + []{return 1;}(); + ^^-- Lambda operator() function type. + ^----- Instance (within member initializer). + ^^^^------ "__Um" indicates lambda in initializer. + ^---------- Length of type name that follows. + ^^^^^^^^^^^^^^^^^^^----------- Nested encoding for S::x::. + +The following kinds of entity names (only) are mangled: + +* | Function names. Even non-member function names are mangled, to deal with + overloading. Names of functions with ``extern "C"`` linkage are not + mangled. See ``mangle_function_name``. + | Mangled function names have the function name followed by "``__``" followed + by "``F``" followed by the mangled description of the types of the + parameters of the function. If the function is a member function, the + mangled form of the class name precedes the "``F``". If the member + function is static, an "``S``" also precedes the "``F``". In cases where + the function has ``extern "C"`` linkage on the function type, a "``K``" + modifier immediately follows the "``F``" indication. + + .. code:: c++ + + int f(float); // f__Ff + class A { + int f(float); // f__1AFf + static int g(float); // g__1ASFf + }; + + | Members of namespaces are mangled like member functions. + | For the Microsoft extension that allows explicit specification of a virtual + function to be overridden, name mangling adds the class of the overridden + virtual function as ``O`` followed by the class type encoding, after the + class name. So, for example, a member ``D::f`` that explicitly overrides + ``B::f`` would be encoded as ``f__1DO1BFv``. +* | Special and operator function names, like constructors and ``operator=()``. + The encoding is similar to that for normal functions, but a coded name is + used instead of the routine name: + + .. code:: c++ + + class A { + int operator+(float); // __pl__1AFf + A(float); // __ct__1AFf + }; + int operator+(A, float); // __pl__F1Af + + | The ARM contains a full list of the name encodings. Static constructors, + used in C++/CLI, are encoded with "``__st__``"; finalizers are encoded with + "``__df__``". See ``mangled_operator_name``. +* | Static data member names. The mangled form is the member name followed by + "``__``" followed by the mangled form of the class name: + + .. code:: c++ + + class A { + static int i; // i__1A + }; + + | This type of mangling is also used for variables that are members of + namespaces. Generally speaking, the names of variables at the file scope + don't need to be mangled, but that's not true for variable templates, or + for variables that may have implicit or explicit ``abi_tag``\ s. See + ``mangle_variable_name``. +* | Functions that are instances or specializations of templates. These + are mangled to include the template signature. This is controlled by + the variable ``distinct_template_signatures``. Template parameters + (both type and nontype) are mangled as "``Z``\ *n*\ ``Z``" or "``Z``\ + *n*\ ``_``\ *m*\ ``Z``", where *n* is the template parameter position + number (first is 1) and *m* is the template parameter depth (top level + is 1, which is assumed in the case where it is not specified). The + return type of the function is also included in the mangled name. + "``__S``" can appear either directly after the template name, to + indicate that the template is specialized, or after the template + argument list, to indicate that the instance is specialized. + + .. code:: c++ + + template struct A { + template void f(T2); + }; + template <> template void A::f(T2) {} + template <> template<> void A::f(int) {} + A ai; + A ac; + A af; + int main(){ + ai.f(1); // f__tm__2_i__10A__tm__2_iFZ1_2Z_v + ac.f(1); // f__S__tm__2_i__10A__tm__2_cFZ1_2Z_v + af.f(1); // f__tm__2_i__S__10A__tm__2_fFZ1_2Z_v + } + + | + | The specialization indications are also placed in the names of parent + classes of functions and static data members generated from templates. A + "``__S``" following directly after the class itself indicates that the + class is specialized (and similarly for a class template), and a "``__S``" + after the template argument list of a class template indicates that the + instance is specialized. + + .. code:: c++ + + template struct A { + void f(); + struct B { + void bf(T); + }; + }; + template <> struct A { + void f(); + }; + template <> struct A::B { + void bf(int); + }; + A as; + A::B aib; + main () { + as.f(); // f__13A__tm__2_s__SFv + aib.bf(1); // bf__Q2_10A__tm__2_i4B__SFi + } + + | When a partial specialization of a class template appears, the mangled name + has two template argument lists. The first (which begins with + "``__ps__``") gives the template arguments that appear on the declaration + of the partial specialization, and the second gives the arguments according + to the template parameters of the partial specialization. + + .. code:: c++ + + template struct A {}; + template struct A { + void f(); // f__23A__ps__6_PZ1Zi__tm__2_iFv_v + // A + }; + + | Where expressions appear in template signatures, they are mangled as in the + following example: + + .. code:: text + + Opl_2_Z1ZZ2ZO <-- "Z1 + Z2", Z1/Z2 indicating nontype template + parameters. + ^---- "O" to end the operation encoding. + ^^^----- Second operand. + ^^^-------- First operand. + ^^^----------- Count of operands (with bracketing underscores). + ^^-------------- Operation, using same encoding as for operator + function names. + ^---------------- "O" for operation. + + | The two or three letter operation encodings (e.g., "``pl``" in the example + above) are the same as the operator function encodings specified in the ARM + (without the leading double underscores). + | The operands can be template parameters, constants (using the encoding + described for nontype template arguments, not including the initial + "``X``"), subexpressions (using the expression operation encoding described + above), mangled names (e.g., of variables or routines), or (in ``decltype`` + expressions) function parameter references. + | + | In addition to those operations specified in the ARM, the following + operation encodings have been added as EDG extensions: + + .. code:: text + + "ds" = .* + "dt" = . + "ps" = unary plus + "ng" = unary minus + "de" = * (indirection) + "ao" = & (address of) + "ppe" = prefix increment (pp indicates postfix increment) + "mme" = prefix decrement (mm indicates postfix decrement) + "tw" = throw + "rl" = __real + "im" = __imag + "mn" = GNU min operator (?) + "sp" = ... (pack expansion) + "ht" = % (C++/CLI unary "%" operator which returns a handle) + "sb" = [] (C++/CLI array subscript -- has variable number of operands) + "gc" = gcnew (C++/CLI gcnew -- optional list of dimension expressions + precedes a type operand) + "cp" = () (call operation with ADL suppressed -- has variable number of + operands) + "il" = {} (brace-enclosed initializer list -- has variable number of + initializers) + "tl" = T{} (cast of a brace-enclosed initializer list -- has a type + followed by a variable number of initializers) + "nx" = noexcept + "li" = literal operator (for user-defined literals -- has zero or one + operand and is followed immediately by a count and the ud-suffix + for the literal operator, e.g., operator "" _miles would be + "li6_miles") + + | The following added operations differ from the standard operation encoding + in that they include an initial type before a single operand. The "``cs``" + encoding is used to encode both the old-style cast (where there is one + non-type operand) as well as the functional-notation cast (where there can + be zero or more non-type operands). The case where a functional-notation + cast is used with one argument is indistinguishable from the old-style cast + case: + + .. code:: text + + "sc" = static_cast + "dc" = dynamic_cast + "rc" = reinterpret_cast + "cc" = const_cast + "cs" = old-style (one argument) or functional-notation cast + "sf" = C++/CLI safe_cast + + | The following operation differs in that it takes a single type argument: + + .. code:: text + + "ct" = C++/CLI ::typeid + + | The following operations differ in that their source can specify either a + type or an expression: + + .. code:: text + + "sz" = sizeof + "af" = __ALIGNOF__ + "uu" = __uuidof + "ty" = typeid + "sk" = sizeof... + + | The mangled encodings for these cases are: + + .. code:: text + + OszZ1Z0O <-- "sizeof(Z1)", Z1 indicating a template parameter. + ^---- "O" to end the operation encoding. + ^----- Count of operands, 0 for type and "e" cases, 1 for "X". + ^^^------ Encoding for type or "e" or "X" (for expression cases). + ^^--------- Operation ("sz" for sizeof, "af" for __ALIGNOF__, + "uu" for __uuidof, or "ty" for typeid) + ^----------- "O" for operation. + + | There are three cases. When the operation takes a type, then the type + is encoded after the operation encoding and there are no operands. + Prior to version 4.2, an expression was indicated with an "``e``" in + place of the type (but no expression was contained in the mangled name + and the operand count was still zero). In version 4.2 and later, the + mangled expression is included (operand count is 1), and the type is + replaced with an "``X``" to indicate that an expression follows. | | The + ``new`` and ``delete`` operations (as well as ``new[]`` and + ``delete[]``) are encoded thusly: + + .. code:: text + + v--------------vvvvvvvvvv----- These are optional. + Onwg_1_CiL_2_10Z1Z_1_CiL_1_0O <-- encoding for "::new (10) T (0)" + ^---- "O" to end the encoding. + ^^^^^^^----- Initializers (if any). An optional + "bi" indicates the use of a + brace-enclosed initializer list. + ^^^------------ Optional initializer count (zero + or more). Omitted (along with + initializers) if none were + specified. + ^^^--------------- Type of new operation. + ^^^^^^^^------------------ Placement arguments (if any). + ^^^-------------------------- Placement argument count (zero + or more). + ^----------------------------- "g" indicates global new. + ^^------------------------------ new operation (nw, nwa). + ^-------------------------------- "O" for operation. + + v----------- This is optional. + Odlg_1_I1IO <-- encoding for "::delete p1" + ^---- "O" to end the operation encoding. + ^^^----- Argument to delete. + ^^^-------- Argument count (always one for delete). + ^----------- "g" indicates global delete. + ^^------------ delete operation (dl, dla). + ^-------------- "O" for operation. + + | Builtin operations (i.e., vendor-specific extensions like Microsoft + ``__is_base_of``) use the operation "``bi``", and any operands that are + types are prefixed by "``T``". The encoding "``__dn``" was added to + represent a destructor name (and is followed by a single type name). + See ``mangled_encoding_for_expression`` for details on the mangling of + expressions. | | Where arrays with sizes based on template parameters + appear, they are mangled as "``A_``\ *mangled-expression*\ ``_``\ + *element-type*" (the underscore following the "``A``" differentiates + this case from the usual known-size array case). | | A template + template parameter that is followed by a template argument list, e.g., + ``ttparam`` in source code, is represented by the ``Z...Z`` + encoding, with the template argument list encoding inserted before the + closing ``Z``, as in ``Z1__tm__4_Z2ZZ``. | | References to function + parameters in ``decltype`` expressions (e.g., ``p`` in ``template + auto f(T p) -> decltype(p)``) are mangled as such: + + .. code:: text + + v-vv----- These are optional. + IC1_2I <-- "const param#1 two levels up" + ^---- Terminating non-digit character so parameter number won't run + into an entity with an initial length. + ^^----- Number of "levels up" for this parameter (0-based). Omitted + if zero. + ^------- Parameter number (1-based) or 0 for "this". + ^-------- Optional cv-qualifiers. + ^--------- "I" indicates parameter reference. + +* | The implicit or explicit use of ``this`` in a mangled name is also + represented with the function parameter mangling given above (where the + parameter number is set to zero). +* | Names of variables generated for virtual function tables. These have names + like + + ``__vtbl__``\ *mangled-class-name* + + | or + + ``__vtbl__``\ *mangled-base-class-name*\ ``__``\ *mangled-class-name* + + | In the case of a virtual function table used during construction or + destruction of a subobject, there can be an additional mangled class name + on the end. See ``make_var_for_virtual_function_table``. +* | Names of variables generated to contain runtime type information. These + have names like + + ``__T_``\ *type-encoding* + + | and + + ``__TID_``\ *type-encoding* + + | See ``mangled_typeinfo_name`` and ``mangled_id_object_name``. +* | Names of wrapper routines generated to deal with covariant virtual function + return types. These are pointed to from virtual function tables and have + names of the form + + ``__VFE__``\ *overridden-class*\ ``__``\ *overriding-function* + + | See ``mangle_wrapper_name``. +* | Names of static variables and functions made external, e.g., because they + are referenced from an instantiation and each instantiation is placed in a + separate object file. The form of the mangled names is + + | ``__STV__``\ *variable-name*\ ``__``\ *module-id* + | ``__STF__``\ *mangled-function-name*\ ``__``\ *module-id* + + | where *module-id* is a unique name generated for the current compilation. +* | The GNU ``ifunc`` attribute, when lowered, creates a variable through which + calls to the function are dispatched. The variable uses the ``__IFV__`` + prefix: + + ``__IFV__``\ *variable-name* + +* | When GNU function multiversioning is used, a set of routines with the same + unmangled name are given unique mangled names based on their use. The + following prefixes are used to create these names: + + .. list-table:: + + * - | ``__RES__``\ *mangled-function_name* + - | resolver function + * - | ``__IFC__``\ *mangled-function-name* + - | ifunc function + * - | ``__TGT__``\ *targets*\ ``__``\ *identifier* + - | target-specific function + +* | For classes and function names with the GNU ``abi_tag`` attribute, the + "``__ab``" prefix is used (once for each string literal that is specified + in the ``abi_tag`` attribute list): + + ``__ab``\ ** + + | where ** represents the number of characters in the ** string + literal. + +* | Structured binding container variables (at namespace scope) are given + mangled names based on the binding variable(s) they refer to. The + "``__SBC__``" prefix is used to identify this mangling. Each of the + binding variables, in order, are included in the container's mangled name, + separated by "``__``". A final "``__``" indicates the end of the + structured binding container mangled name. For example, + ``__SBC__x__y______1N`` indicates a structured binding container for + ``[x,y]`` in namespace ``N``. + +Once a mangled name has been generated, a compression step examines it to see +whether it can be shortened by compression. The compression approach is +simple-minded: the sequence "``J``\ *nnn*\ ``J``" means "repeat the sequence +beginning at offset *nnn* in the mangled name." The offset is 0-origined. Only +sequences that begin with a length (e.g., ``7ABCDEFG``) are eligible to be +repeated in this way. Each "``J``" in the original mangled name is replaced by +"``JJ``" to avoid ambiguities. If compression is done, the mangled name is +given a prefix of "``__CPR``\ *nnnn*\ ``__``", where *nnnn* is the length of +the uncompressed form of the name. + +IA-64 ABI name mangling +^^^^^^^^^^^^^^^^^^^^^^^ + +In the IA-64 ABI, name mangling is done according to the ABI spec +(https://itanium-cxx-abi.github.io/cxx-abi/abi.html). We will not repeat that +description here. + +There is no compression *per se* in the IA-64 ABI name mangling scheme. +Instead, entities that have appeared earlier in a mangled name can be +referenced again by way of a "substitution," which is essentially the encoding +"``S``" followed by a number (base 36) indicating which of the preceding +entities is repeated. Entities of certain kinds (types, qualified name +prefixes, templates) are assigned numbers in their order of appearance in the +mangled name, and a later substitution can refer to such an entity by number. +Certain types and templates in the standard ``iostream`` header are assigned +predefined substitution codes so that they can be referenced cheaply. For the +implementation of substitutions, see ``add_substitution_if_available`` and +``alloc_substitution``. Note that one consequence of substitutions is that it +is impossible to reuse mangled names for entities as part of a larger mangled +name including that entity, because the substitution numbering in the reused +piece would be wrong for the overall mangled name. + +Mangled names for entities local to a function are distinguished by a trailing +"discriminator," a number that serves to distinguish like-named entities within +one function. Such entities are assigned discriminator numbers in the front +end, in strict order of appearance in the function. For example, the first +variable "``i``" in a function is assigned discriminator number zero, the next +one, etc. regardless of block scope nesting. These discriminator values are +recorded in the symbol table (rather than the IL) and IL lowering retrieves +them and includes them in mangled names. + +Similarly, string literals within (certain) functions are numbered so that +mangled names can be generated for them. The C++ standard requires that if an +``extern inline`` function is implemented by multiple copies, a string literal +that appears in the function has the same address in all copies. This is +implemented by assigning a sequence number to each string in functions that +might exist in multiple copies. Name mangling then uses that number to +generate a mangled name for the variable created to hold the string value. + +For entities "externalized," i.e., static variables or functions made external +because they must be referenced from multiple compilations (e.g., for exported +templates, or in one-instantiation-per-object mode), name mangling uses an +extension to the ABI spec. This is an encoding of the form + + ``B`` *length module_id* + +where *module_id* is a generated string describing the current compilation, +formed from the source file name and some other bits that help make it unique. +This encoding is used as a prefix on the syntax term and is used to make +a local name unique when it is externalized. + +For the Microsoft extension that allows explicit specification of a virtual +function to be overridden, name mangling adds the name of the overridden +virtual function as the encoding ``Q``\ ** following the nested +name for the function, i.e., an ** has an alternative of **\ ``Q``\ * *. So, for example, a member +``D::f`` that explicitly overrides ``B::f`` would be encoded as +``_ZN1D1fEQN1B1fEv``. This is an extension to the ABI spec. + +Builtin operations in expressions (i.e., vendor-specific extensions like the +Microsoft __is_base_of) are encoded as a vendor-specific operator ``builtin``\ +*XX*, where *XX* is the number of the builtin operation. Any type operands are +encode as "``TO``" followed by the encoding for the type. + +When C++/CLI is enabled, tracking references, ``interior_ptr``\ s, ``pin_ptr``\ +s, and handles are mangled using the vendor extended type qualifier: + + ** ::= ``U``\ ** # vendor extended type qualifier + +Tracking references use the encoding "``8__trkref``" for **, +``interior_ptr``\ s are encoded as "``14__interior_ptr``", ``pin_ptr``\ s +as "``9__pin_ptr``", and handles are encoded as "``8__handle``". C++/CLI +static constructors are encoded as "``C8``" and finalizers are "``D7``". +``__nullptr`` is encoded as "``DN``"; ``__underlying_type`` is encoded as +"``Du``". + +C++/CLI operators are generally mangled using the IA-64 ABI vendor extended +operator syntax: + + | ** ::= ``v``\ ** # vendor extended + operator + +The unary "``%``" operation (which produces a handle to its operand) uses the +"``9clihandle``" <*source-name*>; the array subscript operation (which has a +variable number of operands) is encoded with a <*source-name*> of +"``12clisubscript``". Due to the limitation of a single digit in this +encoding, only 8 subscripts can be represented in the mangled name. The +``::typeid`` operation is mangled as "``9clitypeid``"; ``safe_cast`` is +"``12clisafe_cast``". + +The vendor extended operator syntax isn't flexible enough to support ``gcnew``, +so an EDG-specific mangling (patterned after the mangling for ``new``) is used: + + .. list-table:: + + * - | ::= ``gc_``\ **\ ``E`` + - | # gcnew ** + * - | ::= ``gc_``\ ** + - | # gcnew *e* {init} + * - | ::= ``gc``\ **\*\ ``_``\ **\ ``E`` + - | # gcnew array\ **\ (dims) + * - | ::= ``gc``\ **\*\ ``_``\ ** + - | # gcnew array\ **\ (dims) {init} + +The IA-64 ABI specification doesn't specify how to mangle function names that +use the GNU multiversion feature. For these functions, the front end produces +mangled names similar to the names that GNU produces. More specifically, for +the resolver function and for target-specific functions, a suffix is appended +to the name ("``.resolver``" for resolver functions and a string that contains +a sorted list of the canonicalized ``target`` attributes for target-specific +functions). The mangling for an ``ifunc`` function is somewhat different: the +original name is mangled, then "``.ifunc``" is appended, then the name is +mangled again (with the signature of the lowered routine type). Note that +these GNU manglings contain periods which can cause problems in certain back +ends (e.g., C-generating back ends), so a configuration macro, +``REPLACE_SPECIAL_CHARACTERS_IN_MANGLED_NAMES``, is available to change the +periods into underscores. Note also that due to their non-standard nature, +these names cannot be demangled (either with or without the periods). + +.. _dynamic-init: + +Dynamic Initialization +---------------------- + +The ``a_dynamic_init`` entry, which describes a dynamic initialization, is used +both in C and C++. IL lowering rewrites cases that are not valid in C and +leaves the others. See ``lower_dynamic_init``. Cases that must be rewritten +are: + +* | Initialization of a file-scope variable to a nonconstant value. + | + | See ``lower_file_scope_dynamic_inits``. + | + | The initialization is rewritten as executable code in a file-scope + initialization routine (called ``__sti__``\ *module-id*, or ``__tls_init`` + for initialization of objects with ``thread_local`` storage). + | + | The existence of the initialization routine is communicated to the + environment through creation of a file-scope static variable called + ``__link``: + + .. code:: c++ + + void __sti__module_id() {...} + struct __linkl { + struct __linkl *next; + void (*ctor)(); + void (*dtor)(); + }; + static struct __linkl __link = {NULL, __sti__module_id, NULL}; + + | This is compatible with the cfront ``patch`` step. That tool or something + similar to it can find the ``__link`` variable and place it on a list of + entries to be consulted at program startup and termination. It is also + compatible with the alternative cfront ``munch`` tool, which looks for + routines with names beginning with ``__sti__`` and ``__std__``. Note that + the cfront approach allows the specification of a termination routine, but + that facility is not used by this front end (end-of-program destructions + are requested individually by calling a runtime routine, e.g., + ``__record_needed_destruction`` for the cfront-like ABI). This ``__link`` + variable is included in the program even if initialization is handled by + some fancier mechanism (see, for example, + ``USE_INIT_SECTION_IN_GENERATED_C`` for the C-generating back end), and + even in the IA-64 ABI, even though it may not be used in those cases. + | + | See ``make_code_to_invoke_file_scope_init_routine``. + | + | When ``ONE_INSTANTIATION_PER_OBJECT`` is TRUE, each instantiation in a + compilation is put out as a separate object file. There is still only one + IL tree, but it is marked so that a back end can sweep through it several + times and put out a different "slice" each time, each slice containing one + instantiated entity (function, variable, or static data member) plus + exactly the set of other entities needed by that entity. This is done via + a set of per-instantiation "needed" flags. For slices that contain + variable template or static data member instantiations, the slice may + require file-scope initialization code. In these cases, multiple + file-scope initialization routines and multiple ``__link`` variables are + generated, each one marked to be included in the proper slice. Each + file-scope initialization is placed in the initialization routine for the + appropriate slice and any initialization for objects with ``thread_local`` + storage are put out in a ``__tls_init_``\ N routine where the N indicates + the number of the slice). +* | Initialization of a local static variable to a nonconstant value. The + initialization is rewritten as executable code, then surrounded by a + first-time test so that the initialization is done only once: + + .. code:: c++ + + void f() { + static int i = j+k; + } + + | is translated to (cfront-like ABI): + + .. code:: c++ + + static int temp; // Implicitly initialized to zero + void f() { + static int i; + if (temp == 0) { + temp = 1; + i = j+k; + } + } + + | In the IA-64 ABI, the guard variable is set after the initialization. If + ``IA64_ABI_USE_GUARD_ACQUIRE_RELEASE`` is TRUE, the routines given in the + ABI spec are called, making the full (and potentially thread-safe) sequence + + .. code:: c++ + + static long long temp; // Implicitly initialized to zero + void f() { + static int i; + if (temp == 0) { + if (__cxa_guard_acquire(&temp)) { + i = j+k; + __cxa_guard_release(&temp); + } + } + } + + | See ``add_first_time_test``. +* | Initialization by calling a routine that returns a class object via a copy + constructor. The initialization is rewritten as a call of the routine. +* | Initialization using a constructor. The initialization is rewritten as a + call of the constructor. + | + | See ``add_constructor_call``. +* | Initialization to a nonconstant aggregate. The initialization is rewritten + as initialization to a constant aggregate combined with executable code to + initialize the nonconstant positions. + + .. code:: c++ + + void f() { + int a[3] = {1, i+1, 3}; + } + + | is rewritten as + + .. code:: c++ + + void f() { + int a[3] = {1, 0, 3}; + a[1] = i+1; + } + + | See + + * | ``lower_ck_dynamic_init`` + * | ``lower_dynamic_init_aggregate_constant`` + * | ``add_destructor_call`` + +* | Any dynamic initialization requiring a destructor. The required destructor + call will be on a list of destructions to be done at the end of an object + lifetime. See :ref:`object-lifetimes`. + | + | If the dynamic initialization is a valid C initialization except for the + requirement to call a destructor, it is left as-is; otherwise, it is + rewritten as described above. + | + | When a global or local static variable is constructed, and the variable + requires later destruction, this is recorded at runtime by calling the + routine ``__record_needed_destruction`` [#f2]_ (cfront-like ABI) or + ``__cxa_atexit`` (IA-64 ABI) The calls of that routine build a list of + entities to be destroyed at the time of program termination. If a + destruction requires only a destructor call, the data structure passed to + the runtime routine gives the address of the object and the address of the + destructor. Otherwise (for more complex cases, e.g., arrays), a routine is + generated containing the necessary destruction code, and the address of + that routine is passed in the data structure, along with a NULL object + pointer indicating the complex case. + | + | See ``record_needed_destruction``. + +In routines that return a class value by calling a copy constructor, the +``stmk_return`` statement is unusual in that it points to a dynamic +initialization entry that describes the initializing operation to be done to +return a value. The destination of the initialization is taken to be the +address given by the implicit return value parameter added to the routine. The +caller passes in the address of a class object, and the code generated for the +return statement initializes that object before returning. + +Main Program +------------ + +A call of the runtime routine ``_main`` is inserted at the start of the main +program. That routine invokes initialization code for file-scope variables, +and arranges things so that the corresponding termination code will be called +when the program terminates. See ``lower_scope``, and the section on dynamic +initialization in this chapter. + +Class Types +----------- + +The following processing is done on class types: + +* | If the class has virtual base classes, a copy of the class type is made + without the virtual base classes. This copy is given the name of the + original class prefixed with "``__SO__``". This type is attached to the + original type through the ``type_as_subobject`` pointer. If the class has + no virtual base classes, the type-as-subobject is the same as the original + class type. See ``make_subobject_class_type``. +* | The field list of the class is augmented by adding generated fields for the + base classes of the class (using the type-as-subobject of the base classes + for the field types) and pointer to a virtual function table and (for the + cfront-like ABI) any required pointers to virtual base classes . This does + not change the size of the class -- these entities were already part of the + class; they are just made explicit so they can be referenced as fields. + See ``prelower_class_type``. +* | If the class has virtual functions, a variable will be created for a + virtual function table for the class and for each base class of the class + as a subobject of the class. The declaration is created as an ``extern`` + declaration, and is turned into a definition (either external or static) + that is initialized if the virtual function table definition should be put + out. (See next section and ``make_vars_for_virtual_function_tables``). +* | If the class has virtual base classes, in the IA-64 ABI, information needed + to access virtual base classes and to call virtual functions in such bases + is determined and recorded. See + ``compute_vbase_and_vcall_offset_indices``. +* | The members of the class (local constants, local types including nested + classes, static data members, and member functions) are promoted out of the + class into the surrounding context. See ``promote_class_members`` and + ``do_scope_class_member_promotion``. +* | To support the anachronism that allows a static data member to be declared + but never defined, the storage class of static data members that are + externally visible and have no initial value is changed to ``sc_extern``. + See ``lower_scope``. + +Virtual Function Tables +----------------------- + +Each class containing virtual functions has associated with it a virtual +function table. If it has base classes that also contain virtual functions, it +will also have associated with it an instance of each base class's virtual +function table adjusted for use when that base class is a subobject within a +complete object of the derived class. So, associated with a class ``C`` we +might have a virtual function table for ``C`` as a complete object, one for +``B`` as a subobject of a complete object of type ``C``, and one for ``A`` as a +subobject of a complete object of type ``C``. + +In the cfront-like ABI, each of these virtual function tables is embodied in a +variable whose type is an array of entries of type + +.. code:: c++ + + typedef void (*__vptp)(); + struct __mptr { + short d; + short i; + __vptp f; + }; + +``d`` is the "delta" value to be added to the "``this``" pointer to adjust +it to point to the class in which the virtual function is defined; ``f`` +points to the virtual function. For a pure virtual function, the function +pointer points to the runtime routine ``__pure_virtual_called``. In the +case of a deleted virtual function, a pointer to the runtime routine +``__deleted_virtual_called`` is used for the function pointer. + +Note that field ``i`` in the above is not used; it's there for cfront +compatibility. cfront uses the same data structure for pointers to member +functions and virtual function table entries, even though a simpler structure +could have been used for virtual function tables. + +In the IA-64 ABI, each of these virtual function tables is embodied in a +variable whose type is an array of entries of type ``ptrdiff_t``, which is +used to encode function pointers, offsets, etc. There is no "delta" value. +Entries that require such an adjustment point to a thunk routine, which +adjusts the "``this``" pointer and then calls the proper routine. For a +pure virtual function, the function pointer points to the runtime routine +``__cxa_pure_virtual``; a deleted virtual function has its function pointer +initialized to the ``__cxa_deleted_virtual`` runtime routine. + +Each entry defines one virtual function of the class. The routine entry for +the virtual function gives the virtual function number for the function, which +serves as the index into the virtual function table. In the cfront-like ABI, +the code generated uses entry ``[0]`` of the virtual function table to point to +the typeinfo for the class, and the first function is at entry [1]. In the +IA-64 ABI, the first function is at entry [0], but there are also negative +entries: [-1] points to the typeinfo for the class, [-2] gives the offset to +the beginning of the complete object , and [-3], [-4], etc., if needed, give +offsets to virtual base classes and offsets to be added to the "``this``" value +when calling virtual functions. + +When an entity of a class type having virtual functions is initialized (by a +constructor), the virtual function table pointer in the class entity is set to +point to the virtual function table that is appropriate for that object (i.e., +the one that properly reflects whether the class entity is a complete object or +a subobject of some other class). Note that it's the virtual function pointer +that is changed; the virtual function tables themselves are constant and are +not changed. They are not built up, on a per-routine basis or otherwise, for a +given entity. Rather, the proper complete table is chosen and a pointer to it +is put into the class entity. Many class entities can point to the same +virtual function table. + +The variables for virtual function tables are externally visible (except for +classes with internal or no linkage), and they are shared between compilation +units to save space. For the sharing scheme to work correctly, exactly one +compilation unit must define the contents of each virtual function table. The +rest of the compilation units must put out the variable as an ``extern`` +declaration. What IL lowering does is to build every variable as an ``extern`` +declaration first, then change it to a definition (external or static) if the +virtual function table should be defined in the present compilation. The +heuristic used to decide whether or not a virtual function table definition +should be put out is the one described in ARM 10.8.1c: The virtual function +table for a class is put out if the compilation contains a definition for the +first non-inline virtual member function of the class. If the class contains +no non-inline virtual function, the virtual function table is defined as a +local static variable unless the ``--suppress_vtbl`` or ``--force_vtbl`` option +is specified on the command line. This same heuristic is used for the IA-64 +ABI [#f3]_, with the modification that virtual function tables that would be +put out as static are put out as COMDATs, so that the multiple copies can be +joined together by the linker. + +To define a virtual function table, the variable is given a static initial +value that's specified by a ``ck_aggregate`` constant. Each entry in the table +is defined appropriately. For a complete-object virtual function table, the +functions that go into the table are simply the virtual functions of the class +in the order of their virtual function numbers. For a virtual function table +for a subobject of class ``A`` in a complete object of class ``B``, the member +functions of ``A`` are scanned looking for virtual functions, while at the same +time the override list for base class ``A`` of ``B`` is scanned. If a function +in ``A`` does not appear on the override list, the function from ``A`` goes +into the virtual function table. Otherwise, the function from the override +list goes into the virtual function table. + +During the execution of constructors and destructors for base class subobjects, +virtual functions should act as if the complete object has the type of the +constructor or destructor class. That is, functions in classes further out +than the subobject class do not override during the subobject construction or +destruction. When virtual base classes are involved, this means that some +virtual function table instances need to be built to reflect three classes: a +class A (whose virtual function table this is) that is a subobject of a class B +(whose constructor is executing, and which therefore dictates overriding) that +is a subobject of a class C (which is the complete object type, and which +therefore dictates layout). This is necessary when there are virtual base +classes, and not otherwise, because the "delta" field in the virtual function +table is based on the offset between the objects for the classes of the +overridden and overriding functions, and that offset varies depending on the +type of the complete object. + +In the IA-64 ABI, the normal (non-construction) virtual function table variable +for a class contains the primary virtual function table plus the virtual +function tables for the base classes of an object of that type, all +concatenated end-to-end in the single array. This is as required by the ABI +specification. For construction vtables, however, where the spec makes no such +requirement, each vtable is in a separate variable. In the cfront-like ABI, +every vtable is in a separate variable. + +See + +* | ``make_vars_for_virtual_function_tables`` +* | ``make_var_for_virtual_function_table`` +* | ``define_one_virtual_function_table`` +* | ``define_virtual_function_tables`` +* | ``define_scope_virtual_function_tables`` +* | ``add_vtbl_entry_init`` +* | ``virtual_function_table_should_be_defined_here`` +* | ``make_construction_vtbls`` + +Covariant return types on virtual functions +------------------------------------------- + +An overriding virtual function can return a pointer or reference to a +derived class where the overridden function returns a pointer or reference +to a base class. Such an overriding function is said to be *covariant* +with the overridden function. This requires special handling in IL +lowering because a call that appears (statically) to be to the overridden +function may in fact (dynamically) be a call to the overriding function, +and the value returned from the overriding function must undergo a +derived-to-base adjustment before it is returned to the caller. This is +implemented by adding wrapper functions: for each combination of an +overriding function and an overridden function, a wrapper is generated that +calls the overriding function, casts the returned value to the proper type, +and returns it. The virtual function table points to the wrapper function +from slots that need to call the overriding function but need the interface +of the overridden function. + +This mechanism is also used more generally in the IA-64 ABI, for thunks +required for virtual function calls where a "``this``" adjustment is needed. + +The IL representation for a wrapper function is a routine with + +* | ``overriding_function_for_wrapper`` and +* | ``overridden_function_for_wrapper`` + +set appropriately. In the case where a wrapper is being used for a covariant +return type adjustment, the wrapper body is simply a return of an +``enk_result_of_overriding_function`` node cast to the proper +pointer-to-base-class. The ``enk_result_of_overriding_function`` node +represents the value returned from calling the overriding function with the +arguments passed to the wrapper. + +This is controlled by the macro +``ABI_CHANGES_FOR_COVARIANT_VIRTUAL_FUNC_RETURN``. + +While the IL representation is a wrapper function, the underlying +implementation need not be. In fact, for functions with variable-length +argument lists, a wrapper approach may not be feasible. Instead, a back end +can turn the wrapper routines into entry points of the overriding function, or +duplicate the body of the overriding function within each wrapper routine. + +Namespaces +---------- + +The processing for namespaces is simply the promotion of the namespace members +out of the namespaces, with appropriate name mangling. See +``do_namespace_member_promotion``. + +Routines +-------- + +The lowering for routines consists of making two kinds of implicit parameters +explicit: + +* | The implicit "``this``" parameter. This is present on nonstatic member + functions. +* | The implicit parameter that provides the address into which a class value + should be returned, for functions returning a class by value. This + mechanism is not used for simple C-style structures, but is needed for more + complicated classes, because for those it must be possible to take the + address of a class value even if it is an rvalue, e.g., to cast to a base + class or call a member function. In this more complicated calling scheme, + the caller passes in the address of a temporary and the called routine + places the class value there on return. + +Both the ``param_type_list`` in the routine type and the parameter variable +entries in the routine scope are updated to make the implicit parameters +explicit. + +Parameters that are classes passed by value and requiring a copy constructor +require additional processing: Since classes that require a copy constructor +cannot be copied arbitrarily and cannot be moved, the caller actually does the +copy constructor call into a temporary and passes the address of the temporary +as the argument. The parameters on the receiving end must be changed to be +pointers to the class object, and all the references to the parameters must be +changed to add the extra indirection. + +See ``lower_type`` and ``lower_scope``. + +Promotion of Local Entities to File Scope +----------------------------------------- + +If the flag ``PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE`` is TRUE, local static +variables and local types of functions will be promoted out of those functions +into the file scope under some conditions. Such promotion is enabled when the +IL will be fed into the C-generating back end, and may be desirable in other +cases where the output is textual and block-structured in some way. + +The problem addressed by this transformation is shown by the following example: + +.. code:: c++ + + void f() { + static int i; + class A { + void g() { + i = 1; // Reference to variable local to function f + } + }; + } + +The body of ``A::g`` will become a free-standing function at file scope and yet +will have to reference the variable ``i`` of ``f``. Therefore ``i`` must be +promoted out of ``f`` into the file scope so that it will be put out in the +file scope in the generated C code. + +This is not a problem for an ordinary back end, as the reference to ``i`` will +be made in object code form or within the flat name space of an +assembly-language program. + +See + +* | ``local_entities_should_be_promoted`` +* | ``promote_local_entities_to_file_scope`` + +.. _ctor-wrapper: + +Constructor Wrapper Code +------------------------ + +Constructors are modified to add the "wrapper" code that is required. + +The constructor-initializer list indicates all the initializations that must be +done for base classes and members. It is in the language-defined order for +initialization: virtual base classes, then non-virtual base classes, then +members. Each base class or member that requires initialization will appear on +the list, with a front-end-generated default initialization if there is no +user-written one in the source. + +The modifications made are: + +* | In the cfront-like ABI, if the class has virtual base classes, a parameter + is added for each such class. These parameters are used to pass in the + addresses of the virtual base classes when the constructor is called (from + another constructor) to initialize a subobject; when the constructor is + called to initialize a complete object, the parameters are passed as NULL. + In the IA-64 ABI, a single parameter is always added, for the VTT (virtual + table table) pointer passed in. Again, NULL is passed in to indicate a + complete object. +* | In the cfront-like ABI, code is added to set any virtual base class + pointers in the class. The virtual base class pointers in the base classes + are set by the constructor calls for the base classes and therefore need + not be set by code at this level. +* | Code is added to call a constructor for each virtual base class that + appears on the constructor-initializer list if a complete object is being + initialized. +* | Code is added to call a constructor for each non-virtual base class that + appears on the constructor-initializer list. +* | Code is added to initialize each member that appears on the + constructor-initializer list. +* | If the class has any virtual functions, code is added to set the virtual + function table pointers in the current class and all of its base classes + that have virtual functions. +* | If allocation can be folded into the constructor (a configuration + option, but always true if assignment to "``this``" is supported), the + entire routine is surrounded by code that tests the incoming "``this``" + parameter, and if it is NULL calls an appropriate ``new`` routine to + allocate space, which is then initialized. If the constructor actually + contains an assignment to "``this``", the ``new`` code is not inserted and + the wrapper code above is inserted after each assignment to "``this``" + instead of at the beginning of the routine. + +If the class has any virtual functions that are overridden in such a way that +there is a virtual base class step between the class of the overridden function +and the class of the overriding function, special virtual function instances +are required during construction of the class as a subobject. A constructor +for such a class, when called for a subobject, expects to receive an array of +virtual function table pointers from its caller (the constructor for the +derived class). It uses these virtual function table instances when setting +virtual function table pointers, and it passes parts of the array to its own +subobject constructors. In the cfront-like ABI, the pointer to the array is +passed (and received, in the subobject constructor) by setting the so-called +"transfer pointer" (a virtual function table or virtual base class pointer in +the class object that is unset at that point and can be borrowed for this +purpose). In the IA-64 ABI, the pointer to the array is passed in via the +added VTT pointer parameter. + +In the IA-64 ABI, constructors have multiple entry points. The entry for a +complete object has a "``C1``" encoding in its mangled name, and has no added +parameters. The entry for a subobject has "``C2``", and has an added VTT +pointer parameter if the class has virtual bases. The IL lowering +implementation puts the real code for the constructor in one function, which is +the subobject constructor if the class has virtual bases and the complete +object constructor otherwise. The other constructor is referred to as the +alternate entry point. When the class has virtual bases and +``HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS`` is TRUE, the construction of +virtual bases is performed in the complete constructor before invoking the +subobject constructor; otherwise the alternate entry is simply an entry point +that calls the primary routine. Calls from an entry point to the primary +routine can be inlined if appropriate, or a back end can implement the entry +point functions as actual entry points to a single routine. See +``alternate_entry_point``. + +See + +* | ``lower_constructor_code`` +* | ``add_constructor_params`` +* | ``add_constructor_wrapper_code`` +* | ``lower_ctor_init`` + +Destructor Wrapper Code +----------------------- + +Destructors are modified to add the "wrapper" code that is required. + +The constructor-initializer list indicates all the destructions that must be +done for base classes and members. It is in the language-defined order for +destruction, i.e., the reverse of the initialization order. Each base class or +member that requires destruction will appear on the list, with a +front-end-generated destruction (there is no way to explicitly write one in the +source program). + +The modifications made are: + +* | A parameter of type ``int`` is added. This parameter is used by the caller + as a bit mask: the ``0x2`` bit of the parameter set to ``1`` indicates a + complete object, and the ``0x1`` bit set to ``1`` indicates that the + storage for the object should be freed. +* | If the class has any virtual functions, code is added to set the virtual + function table pointer in the class and in all of its base classes, so that + virtual function calls executed during the destruction will not call + functions in further-derived classes. + +The above code is added at the beginning of the routine. The rest of the +wrapper code is added at the end of the routine. To make sure the code at the +end is reached, all ``return``\ s in the routine body are rewritten as +``goto``\ s to the epilogue code. + +* | Code is added to destroy each member that appears on the + constructor-initializer list. +* | Code is added to destroy each non-virtual base class that appears on the + constructor-initializer list. +* | Code is added to destroy each virtual base class that appears on the + constructor-initializer list if a complete object is being destroyed. +* | A ``delete`` routine is called to free the storage if the proper bit in + the implicit parameter is set. The entire routine is also enclosed in + an ``if`` statement so it will do nothing if the "``this``" parameter + passed in is NULL. If an assignment to "``this``" was actually done in the + routine, this ``delete`` is protected by a test to see if the "``this``" + parameter is (still) non-NULL. + +See :ref:`ctor-wrapper` regarding special virtual function tables used +during subobject construction. Similar processing is also needed in +destructor wrappers for subobject destruction. + +In the IA-64 ABI, destructors have multiple entry points. The entry for a +complete object has a "``D1``" encoding in its mangled name, and has no added +parameters. The entry for a subobject has "``D2``", and has an added VTT +pointer parameter if the class has virtual bases. The entry to destroy and +free storage for a complete object has "``D0``" and no added parameters. The +IL lowering implementation puts the real code for the destructor in one +function, which is the subobject destructor if the class has virtual bases and +the complete object destructor otherwise. The other destructors are known as +alternate entry points. When the class has virtual bases and +``HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS`` is TRUE, the destruction of +virtual bases is performed in the complete destructor after invoking the +subobject destructor; otherwise alternate entry points simply call the primary +routine (for the deleting destructor, the entry point also contains the +deallocation code). Calls from an entry point to the primary routine can be +inlined if appropriate, or a back end can implement the entry point functions +as actual entry points to a single routine. See ``alternate_entry_point``. + +See + +* | ``lower_destructor_code`` +* | ``add_destructor_params`` +* | ``lower_dtor_init`` +* | ``lower_destructor_dynamic_init`` + +Calls +----- + +See ``lower_call``. + +Calls of constructors and destructors are altered to add the implicit +parameters described in the previous sections. Except for constructor and +destructor calls in wrapper code, constructor and destructor calls are for +complete objects. + +See ``make_ctor_implied_arg_list`` and ``make_dtor_implied_arg_list``. + +Calls of "vacuous" destructors, as in + +.. code:: c++ + + p->int::~int(); + +are changed from ``eok_vacuous_destructor_call`` or +``eok_points_to_vacuous_destructor_call`` operations to a cast to ``void``. + +Virtual function calls are rewritten from + +.. code:: c++ + + object->func(args ...) + +to (cfront-like ABI) + +.. code:: c++ + + ((vtbl_temp = (object->__vptr)+index), + (object+vtbl_temp->d)->(vtbl_temp->f)(args ...)) + +(Omitting some casting for clarity.) In other words, ``vtbl_temp`` is +assigned the address of the proper virtual function table entry, the +"``this``" pointer is adjusted by the "delta" value in the entry, and the +function indicated in the entry is called. If ``object`` is not a reusable +expression, the first occurrence of ``object`` above is replaced by +``(object_temp = object)``, and the second by ``object_temp``. + +For the IA-64 ABI, the code is + +.. code:: c++ + + (object->__vptr[index])(object, additional_args ...) + +(recall that any required "``this``" adjustment is handled by thunk +routines and therefore is not needed at the call site). + +See ``lower_virtual_function_call``. + +A related case (though not a call) is lowering of ``eok_virtual_function_ptr``, +the operator that implements the anachronism of casting a bound member function +pointer to a normal function pointer. It rewrites + +.. code:: c++ + + (func-type *)(object->func) + +to (cfront-like ABI) + +.. code:: c++ + + (func-type *)((object->__vptr)+index)->f) + +or (IA-64 ABI) + +.. code:: c++ + + (func-type *)*(object->__vptr)+index + +See ``lower_virtual_function_ptr``. + +Return Value Optimization +------------------------- + +Return value optimization applies to functions that return a value via a copy +constructor. It can be done when all ``return`` statements in the function +return the same nonstatic local variable. The optimization is to rewrite all +references to the local variable to refer instead to the return-value address +passed in by the caller, thus avoiding a copy constructor call on exit. For +example: + +.. code:: c++ + + struct A { + A(int); + A(const A&); + }; + A f() { + A a(1); // Constructed into temp passed by caller + return a; // No copy needed + } + +The front end proper detects the possibility of doing the optimization, but the +transformation is done by IL lowering. There are several parts to the +optimization: + +* | References to the address of the local variable are rewritten as references + to the (pointer) value of the return-value address parameter. +* | The local variable is marked as unreferenced, and any initialization on it + is turned into initialization of the object pointed to by the return-value + address parameter. +* | Return statements are transformed into simple returns doing no copy + constructor call and returning no value. + +Expression Temporaries +---------------------- + +``enk_temp_init`` nodes are used to introduce class temporaries in the middle +of expressions. They indicate the initialization to be done on the temporary +and any destruction to be done once the temporary is no longer needed. The +temporary is implicit in the high-level IL; IL lowering allocates a variable +for the temporary and uses it in place of references to the ``enk_temp_init`` +node. + +The initialization and destruction are indicated by a dynamic initialization +entry, which is rewritten in the usual way. See ``lower_expr_full``. + +One special problem: When class temporaries created under a conditional +operator ("``?``", "``&&``", or "``||``") require destruction, the destruction +must be done only if the initialization was done. For each case like this, it +is necessary to create a temporary, initialize it to zero at the start of the +block containing the expression, set it to one if the initialization is done, +and test it on exit from the block to determine whether or not to do the +destruction. See ``add_dyn_init_cleanup, init_conditional_flag_var, +set_conditional_flag_var, add_conditional_flag_test``. + +New and Delete +-------------- + +``new`` and ``delete`` are represented as an ``enk_new_delete`` expression +node. + +There are three main ``new`` cases (see ``lower_new``): + +* | A simple ``new`` is translated to a call of the appropriate ``new`` + routine. If the allocated object must be initialized, the pointer returned + from the allocation is tested to ensure that it is non-NULL, and then the + initialization is done. +* | A simple class ``new`` is often translated to a constructor call, passing a + NULL pointer as an indication that the constructor should do the + allocation. (This is enabled by ``NEW_CAN_BE_FOLDED_INTO_CTOR``. When + that is FALSE, the new routine is called, and if the allocation succeeds + the constructor is called.) +* | An array ``new`` is translated into a call of a runtime routine; see below. + +There are three main ``delete`` cases (see ``lower_delete``): + +* | A simple ``delete`` is translated into a call of the appropriate ``delete`` + routine. If the allocated object must be destroyed, the destructor is + called before the deallocation routine. +* | A simple class ``delete`` is usually translated into a destructor call, + passing a flag indicating that the destructor should do the deallocation. +* | An array ``delete`` is translated into a call of a runtime routine; see + below. + +Calls of ``new`` and ``delete`` that allocate or free arrays of classes that +have constructors or destructors are specially handled. They are converted to +calls of: + + | cfront-like ABI: + + | ``__vec_new(``\ *array, num_elems, elem_size, ctor_routine*\ ``)`` + | ``__vec_delete(``\ *array, num_elems, elem_size, dtor_routine, + free,* ``0)`` + + | IA-64 ABI: + + | ``__cxa_vec_new(``\ *num_elems, elem_size, padding, + ctor_routine, dtor_routine*\ ``)`` + | ``__cxa_vec_delete(``\ *array, elem_size, padding, + dtor_routine*\ ``)`` + +where + +.. list-table:: + + * - | *array* + - | is the address of the first element of the array. For + ``__vec_new``, it may be ``NULL`` to indicate that the space for the + array should be allocated. For ``__vec_delete``, it may be ``NULL`` + to indicate that the routine should do nothing. + * - | *num_elems* + - | is the number of elements in the array. For + ``__vec_delete``, it may be ``-1`` to indicate that the number of + elements given in the corresponding ``__vec_new`` should be used. + * - | *elem_size* + - | is the size in bytes of each array element. + * - | *ctor_routine* or *dtor_routine* + - | is the address of the constructor or destructor routine to call, or + NULL if no routine should be called. + * - | *free* + - | is non-zero to indicate that the storage for the array should + be freed. + * - | *padding* + - | is the size of the array prefix in which the number of elements is + recorded by the runtime. + +The final argument of the ``__vec_delete`` call is not used; it is present for +compatibility with cfront. + +These routines are necessary in order to save the number of elements in the +array from the time of the ``new`` (where it is known) to the time of the +``delete`` (where it is not available), and also to call the constructors and +destructors for all the array elements. + +For the cfront-like ABI, when exception handling is enabled, and only for +classes that have destructors, ``__vec_new_eh`` is called instead of +``__vec_new``. It has an additional final parameter that is a pointer to the +destructor. This is used to destroy any constructed elements if an exception +is thrown while ``__vec_new_eh`` is initializing the array elements. + +For the cfront-like ABI, when value-initialization is to be done for a class +that has a generated constructor, ``__vec_new_eh_zero`` is called. It has the +same parameter list as ``__vec_new_eh``, but it zeroes the storage before +calling the constructor. + +With array new and delete, it is possible to define class-specific + +* | ``operator new[]`` and +* | ``operator delete[]`` + +functions. When those are specified, different runtime routines are called: + + | cfront-like ABI: + + | ``__array_new(``\ *num_elems, elem_size, ctor_routine,* + | |_| |_| |_| |_| |.| |.| + *dtor_routine, new_routine, delete_routine, is_two_arg*\ ``)`` + | ``__array_delete(``\ *entity_node, num_elems, elem_size, dtor_routine,* + | |_| |_| |_| |_| |_| |_| |.| + *delete_routine, is_two_arg*\ ``)`` + + | IA-64 ABI: + + | ``__cxa_vec_new2(``\ *num_elems, elem_size, padding, ctor_routine,* + | |_| |_| |_| |_| |_| |_| |.| + *dtor_routine, new_routine, delete_routine*\ ``)`` + | ``__cxa_vec_new3(``\ *num_elems, elem_size, padding, ctor_routine,* + | |_| |_| |_| |_| |_| |_| |.| + *dtor_routine, new_routine, delete_routine*\ ``)`` + | ``__cxa_vec_delete(``\ *array, elem_size, padding, dtor_routine*\ ``)`` + +Most of the parameters are as described above. The others are: + +.. list-table:: + + * - | *new_routine* + - | is the address of the special ``operator new[]`` + routine, or NULL if the default routine should be used. + * - | *delete_routine* + - | is the address of the special ``operator delete[]`` + routine, or NULL if the default routine should be used. Also NULL on + ``__array_new`` if exceptions are disabled. + * - | *is_two_arg* + - | is ``1`` to indicate that the ``delete_routine`` takes + two arguments, ``0`` otherwise. + +These routines are used only if ``ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE`` is +TRUE. For the cfront-like ABI, if value-initialization is to be done, +``__array_new_zero`` is called in place of ``__array_new``. The IA-64 ABI +"``new3``" routine is used for the two-argument delete case. + +For the cfront-like ABI, when ``ABI_CHANGES_FOR_PLACEMENT_DELETE`` is TRUE, it +is possible to do a placement new of an array type and later deallocate the +storage via the ``delete`` operator. For that case, a special runtime routine +is called to ensure that the array size is recorded: + + | ``__placement_array_new(``\ *entity_node, num_elems, size_elem,* + *ctor_routine, dtor_routine*\ ``)`` + +and the value of the global runtime variable ``__array_new_prefix_size`` is +added to the size of the allocation requested in the placement new to allocate +extra space to contain the array prefix. See +``make_placement_array_new_call``. If value-initialization is to be done, +``__placement_array_new_zero`` is called in place of ``__placement_array_new``. + +See ``lower_array_new`` and ``lower_array_delete``. + +Constructors and Destructors for Arrays +--------------------------------------- + +Construction or destruction of an entire (static or automatic) array is done by +calling runtime routines. For the cfront-like ABI, ``__vec_new`` or +``__vec_delete`` are used (see previous section). The address of the array is +passed into ``__vec_new``, thus suppressing allocation, and ``0`` for the flag +``free`` is passed into ``__vec_delete``, thus suppressing freeing of the +storage. For the IA-64 ABI, there are specific runtime routines for these +functions: + + | ``__cxa_vec_ctor(``\ *array, num_elems, elem_size, ctor_routine,* + *dtor_routine*\ ``)`` + | ``__cxa_vec_dtor(``\ *array, num_elems, elem_size, dtor_routine*\ ``)`` + +Copying of an entire array using a copy constructor is done in the cfront-like +ABI by calling ``__vec_cctor``, passing the array address, the number of +elements, the element size, the address of the routine to call, and the source +array address. [#f4]_ In the IA-64 ABI, the runtime routine is +``__cxa_vec_cctor.`` + +If the constructor involved has default arguments, a wrapper routine is created +that requires no arguments other than the "``this``" parameter and calls the +constructor with the proper default arguments. The wrapper routine is then +passed to the runtime routine, which can call it like a normal constructor. + +See + +* | ``add_array_constructor_call`` +* | ``add_destructor_call`` +* | ``default_version_of_routine`` +* | ``make_vec_delete_call`` + +Pointers to Members +------------------- + +Pointer-to-member types (``tk_ptr_to_member``) are transformed as follows: + +* | Pointers to data members are converted to values of an integral type. The + integer contains a byte offset to the data member in the class. In the + cfront-like ABI, one is added to leave the zero value free to indicate a + NULL pointer to data member. In the IA-64 ABI, nothing is added, and -1 is + used for a NULL pointer to data member. + + .. code:: c++ + + struct A { int i; int j;}; + int A::*pdm = &A::j; // unsigned int pdm = 5(cfront) 4(IA-64) + int A::*pdmn = 0; // unsigned int pdmn = 0(cfront) -1(IA-64) + +* | Pointers to member functions are represented by structures with the form + + * | cfront-like ABI: + + .. code:: c++ + + typedef void (*__vptp)(); + struct __mptr { short d; short i; __vptp f; }; + + | This is essentially the structure described in 8.1.2.c of the ARM. + ``d`` is the offset to be added to the "``this``" pointer; ``i`` is the + index into the virtual function table (or -1 for a nonvirtual function, + or 0 for a NULL pointer); ``f`` is the nonvirtual function pointer when + ``i`` is -1 or the offset to the virtual function table pointer + (appropriately cast) when ``i`` is greater than zero. + + .. code:: c++ + + struct A {int f(); virtual int g();}; + int (A::*pmf)() = &A::f; // struct __mptr pmf = {0, -1, &f__1AFv}; + int (A::*pmg)() = &A::g; // struct __mptr pmg = {0, 1, 0}; + + * | IA-64 ABI: + + .. code:: c++ + + typedef void (*__vptp)(); + struct __mptr { __vptp f; ptrdiff_t d; }; + + | ``f`` is zero for a NULL pointer, is a pointer to a function for the + non-virtual case, and is the vtable offset in bytes plus one for the + virtual function case. ``d`` is the offset to be added to the "``this``" + pointer. When ``IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR`` is + TRUE, an alternate representation is used that works on architectures where + the low-order bit of a function address can be non-zero. In that + representation, ``f`` is zero for a NULL pointer (but you also have to + check that the low-order bit of ``d`` is zero), is a pointer to a function + for the non-virtual case, and is the vtable offset in bytes for the virtual + function case. ``d`` is the offset to be added to the "``this``" pointer, + shifted left one bit, and its low-order bit is one for the virtual function + case. + +See ``lower_type``. + +Pointer-to-member constants (``ck_ptr_to_member``) are transformed to the above +forms. See ``lower_ptr_to_member_constant``. The function case generates a +``ck_aggregate`` constant. Such constants can only be used when the constant +appears as an initializer value; for other kinds of references (e.g., in an +assignment statement), the reference to the constant is changed to a reference +to a temporary variable that is initialized with the aggregate constant. + +Assignment and comparison of pointers to data members are changed to integer +assignment and comparison operators. Assignment of pointers to member +functions is changed to structure assignment. Comparison of pointers to member +functions is changed to + + | cfront-like ABI: + + .. code:: c++ + + (op1.i == op2.i) && (op1.i == 0 || (op1.d == op2.d && op1.f == op2.f)) + + IA-64 ABI: + + .. code:: c++ + + (op1.f == op2.f) && (op1.f == 0 || op1.d == op2.d) + + IA-64 ABI alternate representation: + + .. code:: c++ + + (op1.f == op2.f) && ((op1.f == 0 && (((op1.d | op2.d) & 1) == 0)) + || op1.d == op2.d) + +(That is the code for ``==``; the code for ``!=`` is similar.) If one of the +operands is a constant, the comparisons are done directly against the constant +values of the components of the constant, and unnecessary parts of the +expression above are omitted. A comparison against a null pointer to member +constant, for example, becomes simply + +.. code:: c++ + + (op1.i == 0) + +for the cfront-like ABI. + +Casting a pointer to a data member to a base or derived class is changed to + + | cfront-like ABI: + + .. code:: c++ + + (pdm != 0) ? (pdm + offset) : 0 + + IA-64 ABI: + + .. code:: c++ + + (pdm != -1) ? (pdm + offset) : -1 + +Casting a pointer to a member function to a base or derived class is changed to + + | cfront-like ABI: + + .. code:: c++ + + (temp = pmf, (temp.i != 0) ? (temp.d += offset) : 0, temp) + + IA-64 ABI: + + .. code:: c++ + + (temp = pmf, (temp.f != 0) ? (temp.d += offset) : 0, temp) + + IA-64 ABI alternate representation: + + .. code:: c++ + + (temp = pmf, (temp.f != 0 || temp.d != 0) + ? (temp.d += offset) : 0, temp) + +The tricky issue in both cases is preserving a NULL pointer to member. + +See ``lower_pm_related_class_cast``. + +Casts from one pointer-to-member-function type to another (not related) are +removed since both types will now have the same representation and since the +cast, left in, would be a cast to a structure type. Similar casts between +pointers to data members are casts from an integral type to the same integral +type and are left alone. + +The ``eok_pm_points_to_field`` and\ ``eok_pm_field`` operators, which implement +the ``->*`` and ``.*`` operators for pointers to data members, are rewritten: + +.. code:: c++ + + p->*pdm + +is lowered to + +.. code:: c++ + + (member-type *)(((char *)p)+(pdm-1)) + +The IA-64 ABI version does not need the -1. + +See ``lower_pm_field``. + +The ``eok_pm_call`` operator, which implements calls of functions identified by +a pointer to member, is rewritten: + +.. code:: c++ + + object->pmf(args ...) + +is lowered to (cfront-like ABI) + +.. code:: c++ + + ((this_temp = (object_type *)((char *)object + pmf.d)), + // Adjust "this" pointer by delta from + // pointer-to-member. + (func_temp = (function_type *) + // The computed function address gets cast to the + // proper function type. + ((pmf.i < 0) ? // Check virtual/non-virtual pointer-to-member. + pmf.f : // Function address for non-virtual case. + // Virtual function case: + ((vtbl_temp = // Virtual function table entry address is address + // of virtual function table + offset in table. + *(__vtbl_entry **)((char *)this_temp + + (short)(pmf.f)) + + // Pointer to virtual function table is at offset + // pmf.f in the object. + pmf.i), // + offset into table + this_temp = (object_type *) + ((char *)this_temp + vtbl_temp->d), + // Adjust "this" pointer to get pointer to subobject + // expected by the virtual function. + vtbl_temp->f))), // Address of virtual function. + func_temp( // Call using the function pointer computed. + // Arguments for the call: + this_temp, // "this" pointer. + args ...)) // Additional arguments, if any. + +If ``pmf`` is not a reusable expression, the first occurrence of ``pmf`` above +is replaced by ``(pmf_temp = pmf)``, and the rest by ``pmf_temp``. + +If the class and its base classes have no virtual functions, and the variable +``pointer_to_member_call_optimization_allowed`` is TRUE (which does not conform +to the C++ standard), the following simpler version is used: + +.. code:: c++ + + ((this_temp = (object_type *)((char *)object + pmf.d)), + eok_call((function_type *)pmf.f, + this_temp, + additional_args ...)) + +This seems slightly more complicated than is needed, but it makes sure that if +a reusable copy of ``pmf`` is needed, the temp for it is initialized before the +call is begun. + +For the IA-64 ABI, the code is: + +.. code:: c++ + + ((this_temp = (object_type *)((char *)object + pmf.d)), + // Adjust "this" pointer by delta + // from pointer-to-member. + (func_temp = (function_type *) + // The computed function address gets cast to the + // proper function type. + ((pmf.f & 1) == 0) ? // Check virtual/non-virtual pointer-to-member. + pmf.f : // Function address for non-virtual case. + // Virtual function case: + ((vtbl_temp = // Virtual function table entry address is address + // of virtual function table + offset in table. + *(__vtbl_entry **) + ((char *)this_temp + + // Pointer to virtual function table is at offset + // zero in the object + ((ptrdiff_t)pmf.f - 1)), + // + offset into table, dropping low-order bit. + *vtbl_temp))), // Address of virtual function. + func_temp( // Call using the function pointer computed. + // Arguments for the call: + this_temp, + // "this" pointer. + additional_args ...)) // Additional arguments, if any. + +See ``lower_pm_call``. + +Operations Returning Lvalues +---------------------------- + +Operations that return lvalues in C++ but not in C, i.e., assignment operators, +prefix ``++`` and ``--``, and "``?``" and "``,``" operators, are rewritten in C +form. Often this involves duplication of expressions. This rewriting +operation is enabled or disabled by ``LOWER_LVALUE_RETURNING_OPERATIONS``. + +Lvalue-returning assignments are rewritten from + +.. code:: c++ + + (c1 = c2) + +to + +.. code:: c++ + + ((c1 = c2), rcc2) + +where ``rcc2`` is a reusable copy of ``c2`` (see +``make_lvalue_reusable_copy``). The comma operator is an lvalue-returning +operator, which is then further rewritten (see following). + +Lvalue-returning "``?``" operators are rewritten from + +.. code:: c++ + + ((g1 ? g2 : g3) = c2) + +to + +.. code:: c++ + + (g1 ? (g2 = c2) : (g3 = c2)) + +Lvalue-returning "``,``" operators are rewritten from + +.. code:: c++ + + ((g1 , g2) = c2) + +to + +.. code:: c++ + + (g1 , (g2 = c2)) + +For both the "``?``" and the "``,``" cases, the operations in the rewritten +form are lvalue operations iff the "``=``" operation in the original is an +lvalue operation. The operation indicated as "``=``" can in fact be any +operation (e.g., simple or complex assignment, prefix ``++`` or ``--``, field +selection). ``c2`` isn't present for unary operations. + +Related Class Casts +------------------- + +Base or derived class casts are lowered by replacing the cast with an operation +that adds or subtracts the byte offset required. A few issues require special +handling: + +* | If the offset is zero, which it always is with single inheritance, the cast + can remain a cast between two pointer types. +* | A NULL pointer must pass through a related class cast unaltered. To do + that, a conditional test is required around the code that adds or subtracts + the offset. To avoid putting out this code in too many places, it is put + only once around a sequence of related class casts, and it is suppressed + altogether if (a) all the casts in the sequence have zero offsets, or (b) + the expression is known to be non-NULL (e.g., the "this" pointer in a + member function). +* | Casts to virtual base classes involve fetching the virtual base class + pointer rather than adding or subtracting an offset. + +See ``lower_related_class_cast``. + +.. _il-bool-type: + +bool +---- + +In modern C++, there is a ``bool`` type, and operations like "``!=``" return +``bool`` instead of ``int``. (C99 has a ``_Bool`` type, but the boolean +operation -- like "``!=``" and "``>``" -- produce ``int`` values.) The IL +representation of a boolean type is identical to an ordinary small integer +type, except that the variant field ``variant.integer.bool_type`` is TRUE. +That representation is therefore not lowered: A back end can just ignore the +``bool_type`` field and treat a boolean type as the underlying integer type. + +Several ``bool`` operations are rewritten by IL lowering: + +* | ``eok_bool_cast``, which represents a cast to ``bool`` (or ``_Bool``), is + rewritten as a "``!= 0``" test of the appropriate type. See + ``lower_bool_cast``. +* | An increment of a ``bool`` lvalue is rewritten to set the lvalue to 1 + (``true``). In the postincrement case, this involves saving the original + value, setting the lvalue to 1, and then returning the saved original + value. See ``lower_bool_increment``. +* | The return types of operations that yield a ``bool`` in C++ but an ``int`` + in C, e.g., "``!=``" and "``&&``", are rewritten to yield an ``int``. In + contexts where the result is tested directly, the type is simply changed; + where something else is done with the result (e.g., storing it in a + variable), a cast to the proper type is inserted. See + ``adjust_bool_operation_types``. +* | Compound assignment operators whose left-hand operand has type ``bool`` (or + ``_Bool``) are rewritten to ensure that the result value is restricted to + 0/1. See ``rewrite_compound_assignment``. + +Condition Declarations +---------------------- + +In ``if``, ``while``, ``for``, and ``switch`` statements, the expression tested +can be a condition declaration. For example: + +.. code:: c++ + + if (float x = f()) { ... } + +This is represented in the IL as an expression node of kind ``enk_condition``. + +Loops and non-loops are handled somewhat differently by IL lowering. Non-loops +(``if``, ``switch``) are rewritten as follows: + +.. code:: c++ + + if (A x = y) { ... } + +is transformed into + +.. code:: c++ + + { A x = y; if (x) { ... }} + +The test in the ``if`` actually uses the expression from the ``expr`` field of +the condition, which is the value of the declared variable converted to a +testable type if necessary. + +Loops (``while``, ``for``) are rewritten as follows: + +.. code:: c++ + + for (w; A x = y; z) { ... } + +or + +.. code:: c++ + + while (A x = y) { ... } + +is transformed into + +.. code:: c++ + + { { + for (w;;) { while (1) { + A x = y; A x = y; + if (!x) { if (!x) { + destroy x if necessary; destroy x if necessary; + goto break_label; goto break_label; + } } + { ... } // Original statement { ... } // Original statement + z; // Increment code + destroy x if necessary; destroy x if necessary; + } } + break_label:; break_label:; + } } + +Again, the ``x`` in ``!x`` is the value of the declared variable converted to a +testable type if necessary. If the ``break_label`` exists already, it and the +block around the for/while are not added. + +See ``lower_condition``. + +Anonymous Unions +---------------- + +In the unlowered IL, field selections of fields of anonymous unions that are +embedded in classes elide the field selection(s) for the anonymous union(s). +For example: + +.. code:: c++ + + class A { + union { + int i; + float j; + }; + } x; + +``x.i`` appears as a selection of ``i`` directly out of ``x``. IL lowering +adds the implied field selection through the unnamed union. + +See ``adjust_field_selection_for_anonymous_union_references``. + +Automatic Template Instantiation +-------------------------------- + +When automatic template instantiation is enabled and +``instantiation_flags_in_template_info_file`` is FALSE (an old mode not longer +much used), IL lowering helps the cause by getting certain information about +instantiations passed into the object file. The instantiation information is +recorded in the flags + +* | ``can_be_instantiated``, +* | ``do_not_instantiate``, and +* | ``instance_required`` + +that appear in variable and routine entries. + +IL lowering passes the values of these flags into the object code by generating +tentative definitions of global-scope variables that have names formed by +combining a prefix with the mangled name for the entity for which the flag is +being generated. The prefixes are + +* | ``__CBI__`` for the ``can_be_instantiated`` flag, +* | ``__DNI__`` for the ``do_not_instantiate`` flag, and +* | ``__TIR__`` for the ``instance_required`` flag. + +The routine ``make_instantiation_info_var`` is used to create these variables. + +For template classes with virtual functions, where the decision on whether or +not to output a definition of the virtual function table is based on the +presence of a definition for the first non-inline virtual function of the +class, a reference to the virtual function table causes a ``__TIR__`` for the +first virtual function to be generated (that requests a definition of the +function, and therefore of the virtual function table, somewhere in the +program). When a virtual function definition is generated, it references all +the virtual functions of the class, so ``__TIR__`` variables are generated for +them (except for the first virtual function, to avoid the chicken-and-egg +problem of the first virtual function and the virtual function table each +forcing the other to be instantiated, with neither actually referenced from +anywhere). + +The prelinker phase notices these names in the object files, and from them can +recover the associated instantiation information. + +Guard Code on Variable Template and Template Static Data Member Initializations +------------------------------------------------------------------------------- + +When ``TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE`` (in ``targ_def.h``) is +TRUE, "guard" code is placed around initializations of instances of variable +templates and static data members of templates. Such guard code is necessary +if template instantiation resolution is done by instantiating everything and +then having the (specially-modified) linker discard duplicate copies of +instantiated routines. Dynamically-initialized template variables and static +data members of templates are a particular problem: because the initialization +code is generated in startup routines, and is undifferentiated from other code +in those routines, a flag is needed to indicate that initialization has already +been done. After any one instance of the code does initialization, all other +instances will do nothing. + +The initialization guard code looks like (cfront-like ABI): + +.. code:: c++ + + int guard_var; // Implicitly initialized to 0 + { + if (guard_var == 0) { + guard_var = 1; // Initialization of static data member + } + } + +For the IA-64 ABI, the code sequence is the one generated by +``add_first_time_test``, which has either calls of ``__cxa_guard_acquire`` et +al. or is like the above but with the setting of the guard variable after the +initialization. + +If the template variable or static data member is a specialization, its +initialization should take precedence over any other (non-specialization) +initializations. For that case, the guard variable is put out as a definition +with an initial value of ``-1``. That disables the construction guard code for +all other instances. + +Destruction is not a problem, since all destructions of static entities are put +on a list to be done at the end of program execution. The entry is only put on +the list exactly once when and if the initialization is done. + +Runtime Type Information +------------------------ + +Runtime type information is needed for exception processing and for the RTTI +features of the C++ language. IL lowering generates special ``typeinfo`` +variables for each type that requires such information. + +In the cfront-like ABI, note that the runtime ``typeinfo`` is not the same type +as the programmer-visible ``type_info``; the runtime ``typeinfo`` contains a +``type_info`` structure as a member, and has other information besides. The +``typeinfo`` variables have mangled names of the form + + | ``__T_``\ *mangled-type-encoding* + +(except static ``typeinfo`` variables for non-class types, which are unnamed). + +The variables are ``typeinfo`` structures (this is still for the cfront-like +ABI): + +.. code:: c++ + + struct typeinfo { + type_info tinfo; // User-visible type_info structure + const char *name; // Null-terminated string for name + char *id; // Id object pointer + base_class_spec *bc; // Array of base class information + }; + +Each pointer field is NULL if it is not applicable. In versions preceding +2.38, there was an additional field after ``id`` which contained a destructor +pointer. It was eliminated when the\ ``__throw_setup_dtor`` runtime routine +was added. In versions preceding 2.41, the ``name`` field was not const (it +was made const when const string literals were implemented). + +In the IA-64 ABI, the ``type_info`` type visible to the user is the same as the +implementation type, and it has a number of derived classes that provide +additional information for pointer types, class types, etc. as described in +the ABI spec. ``typeinfo`` variables have mangled names beginning with +"``_ZTI``". + +If the type represented by a ``typeinfo`` variable is a polymorphic class, the +``typeinfo`` variable is external if and only if the virtual function table +variable for the class is external, and the ``typeinfo`` variable is defined +(i.e., initialized) if and only if the virtual function table is defined. For +other cases (non-polymorphic classes and non-classes), the ``typeinfo`` +variable is always static and always defined. + +In the IA-64 ABI, the typeinfo variable is made a COMDAT so that there will be +only one copy in the linked program even when the virtual function table +heuristic does not place the definition in a single file. Likewise, the name +string for a ``typeinfo`` variable is placed in a separate variable with a +predictable mangled name (beginning with "``_ZTS``"), which is made a COMDAT so +that all instances of the name are shared. + +In the cfront-like ABI, when the ``typeinfo`` variable is static, and the +type is not an internally-linked class, it is possible that the same type +is represented by several ``typeinfo`` variables. [#f5]_ In those cases, +the object id pointer is used to indicate that those ``typeinfo`` entries +all correspond to the same type: the object id pointer is non-NULL and +points to an id object variable of type ``char`` whose name has the form + + ``__TID_``\ *mangled-type-encoding* + +This variable is put out as a tentative definition and therefore there will be +only one copy of a given id object variable in the executable program. Two +``typeinfo`` variables are considered to represent the same type if their id +object pointers are non-NULL and equal to one another. + +In the cfront-like ABI, for classes that have base classes, the base class +array field points to a (static) variable initialized to an array of entries +with the following structure: + +.. code:: c++ + + struct base_class_spec { + typeinfo *tinfo; // typeinfo for base class + short offset; // Offset of base class in derived class + unsigned char flags; // Flags + }; + +Only direct, virtual, and ambiguous base classes of the derived class +appear in the base class list. The flags byte contains a bit set: +``0x01`` indicates a virtual base class, ``0x02`` is set to mark the +last entry in the array, ``0x04`` indicates a public base class, ``0x08`` +indicates an ambiguous base class, and ``0x10`` indicates a direct base +class. + +When ``ABI_CHANGES_FOR_RTTI`` is FALSE, an older form of the ``typeinfo`` entry +is generated, which is adequate for exception handling but not for RTTI. The +differences are as follows: + +* | The ``type_info`` and ``name`` fields are not present. +* | ``typeinfo`` variables for nonclass types are put out as tentative + definitions and rely on default initialization to zero. Because of the + name mangling and the fact that the variable is external, there will be + only one copy of the ``typeinfo`` variable for any given nonclass type in + the executable program. No id object variable is needed. +* | The public base class and ambiguous bits in the base class specification + are not set. + +The ``typeid`` operator +^^^^^^^^^^^^^^^^^^^^^^^ + +The C++ ``typeid`` operator is represented by an expression node with kind +``enk_typeid``. + +If the ``typeid`` node has a null expression pointer, the type is known +statically. IL lowering generates a ``typeinfo`` entry for the static type, +and replaces the ``typeid`` node with a field selection that computes the +address of the ``tinfo`` member of the ``typeinfo`` variable. + +If the ``typeid`` node has a non-null expression pointer, the type (a +polymorphic class) must be determined at runtime. + +In the cfront-like ABI, IL lowering replaces the ``typeid`` node with a runtime +routine call + +.. code:: c++ + + __get_typeid((typeid_expr != NULL) ? vptr : NULL) + +where ``typeid_expr`` is the ``typeid`` expression (or more precisely the +address indicated by that expression) and ``vptr`` is an expression for the +value of the virtual function table pointer for the class object pointed to. +If ``typeid_expr`` is not reusable, it will be assigned to a temporary and the +temporary will be used in the ``vptr`` expression. Note that when +``typeid_expr`` is null, a null pointer is passed to ``__get_typeid``; the +latter then throws ``bad_typeid``. + +In the IA-64 ABI, the code sequence is entirely inline: + +.. code:: c++ + + (typeid_expr != NULL) ? (typeinfo*)(vptr[-1]) : + (__cxa_bad_typeid(), NULL) + +The ``dynamic_cast`` operator +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A ``dynamic_cast`` is represented by an expression node with operator +``eok_dynamic_cast``. IL lowering rewrites that into + + cfront-like ABI: + + .. code:: c++ + + (src != NULL) ? __dynamic_cast (src, vptr, desired_type, orig_src, + static_type) : + NULL + + or + + .. code:: c++ + + (src != NULL) ? __dynamic_cast_ref(src, vptr, desired_type, orig_src, + static_type) : + NULL + + IA-64 ABI: + + .. code:: c++ + + (src != NULL) ? __dynamic_cast (src, static_type, desired_type, hint) : + NULL + + or + + .. code:: c++ + + (temp = __dynamic_cast (src, static_type, desired_type, hint)) + ? temp : __cxa_bad_cast() + +The second form in each ABI is for a cast to a reference type. ``src`` is the +expression being cast (or its address, in the reference case); ``vptr`` is the +virtual function pointer for the class (note that it's protected by the +null-pointer check); ``desired_type`` is a pointer to the ``typeinfo`` for the +desired class, or NULL for a dynamic cast to "``void *``"; ``orig_src`` is the +original source pointer in the dynamic cast (the value passed as the first +parameter may have been cast to a base class if the original class has no +virtual function pointer); and ``static_type`` points to the ``typeinfo`` for +the underlying class of the source pointer's static type. + +In the IA-64 ABI, a ``dynamic_cast`` to ``void *`` is done as inline code, by +extracting the offset-to-base from the [-2] entry in the virtual function table +and adding that to the object address. + +Note that ``dynamic_cast``\ s that do not require runtime processing are +translated by the front end into simple casts or base class casts. + +Exceptions +---------- + +The lowering of exception handling (EH) features can be configured three +different ways: + +#. Full lowering: all exception handling features are reduced to C, and + no support for EH features is required in the back end. This solution + is easy to use and highly portable, but entails a fairly significant + overhead in execution cost (15-20%). This mode is required for the + C-generating back end, and is supported by the minimal runtime + provided by EDG. It is enabled by the configuration switch + ``DO_FULL_PORTABLE_EH_LOWERING``. + +#. Partial lowering: the data tables of the portable scheme are generated, + but they use stack offsets for variables (in the portable scheme, all + addresses are computed at runtime and stored in an object address table). + ``try``, ``catch``, and ``throw`` are preserved in the IL. Much of the + minimal runtime provided by EDG would still be applicable, but some + parts would require changes. This mode is enabled by the configuration + switch ``GENERATE_EH_TABLES``. + +#. No lowering: No data tables are generated; the object lifetime + information is preserved for use in generating tables in a back end. + ``try``, ``catch``, and ``throw`` are preserved in the IL. The back + end makes all decisions about the way in which EH features are + implemented. This mode is enabled by having both ``GENERATE_EH_TABLES`` + and ``DO_FULL_PORTABLE_EH_LOWERING`` set to FALSE. + +It should be noted that in all three schemes the statements and expressions +attached under EH constructs are lowered. Even in the partial/no lowering +schemes, lowering generates the code needed for things like copying thrown and +caught objects. Special expression nodes that represent (partially) lowered +exception handling constructs, of kind ``enk_lowered_eh_construct``, are used +to represent the parts of those operations that remain for the back end to +define. + +The portable implementation is the one that involves the most transformations +in IL lowering, and the other two schemes are essentially scaled-back versions +of the full-lowering scheme. Therefore, the description that follows covers +the processing for the full-lowering scheme and indicates differences in the +other schemes. + +Exception handling imposes a nontrivial overhead in time and/or space on +programs, including those that do not make use of exceptions. Accordingly, +exception handling can be enabled or disabled by a command-line option, and +when it is disabled IL lowering will not generate the code or data structures +to support it. + +The fully- and partially-lowered implementations do work with the IA-64 ABI, +but they are not compatible with the ABI spec. For a fully-comforming IA-64 +ABI implementation, it is necessary to do the EH implementation in the back +end. + +Maintaining Context +^^^^^^^^^^^^^^^^^^^ + +When an exception is thrown, the stack is unwound to the catch point, and +destructible objects created in the stack frames removed from the stack must be +destroyed by the runtime. In order to be able to do that, the runtime must +have access to information about the stack frames and the destructible objects +therein. This information is provided by entries linked into an exception +handling stack. There are three kinds of stack entries: + +* | Entries representing a function. These are pushed on entry to a function + and popped on exit from that function, and they point to information about + the destructible objects in the function. No stack frame is needed for any + function that has no destructible objects and no try blocks. +* | Entries for exception specifications of a function. These are pushed at + the beginning of each function having an exception-specification (i.e., a + list of the exception types that the function is permitted to throw), and + popped at the end of each such function. The stack frame points to an + array that describes the types that may be thrown. +* | Entries for ``try`` blocks. These are pushed at the beginning of each + ``try`` block and popped on exit from each such block. The stack frame + provides space for a ``setjmp`` buffer, and a pointer to an array that + describes the types caught at each associated ``catch`` handler clause. + +The code to push and pop stack frames is generated by + +* | ``push_eh_stack_frame`` and +* | ``pop_eh_stack_frame``. + +The function and exception-specification stack frames are requested by +``add_eh_function_prologue`` (which also handles epilogue code). + +The function stack frame points to several data structures that describe the +destructible objects: + +* | The region table, which has entries that describe objects and the cleanup + to be done for them. See ``make_region_table_entry``. The table is an + array, and an index into that array is called a *cleanup region number*. + Each entry contains a cleanup region number for a "next" entry in the + table, which makes it possible to link entries into lists of cleanup + actions. At any given point in a function, one can describe the sequence + of cleanup actions required on termination of that routine by indicating a + cleanup region number, i.e., the index number of the first entry of a + linked list of region table entries that enumerates the destructions and + deallocations to be done, in the order they are to be done. IL lowering + generates code to maintain the global variable ``__eh_curr_region`` + appropriately to indicate the set of cleanup actions necessary at each + point in each function. See ``assign_to_eh_curr_region``. +* | The array table, which provides additional information about destructible + objects that are arrays (for example, the array element size). See + ``make_array_table_entry``. +* | The object address table, which provides the addresses of destructible + objects. The region table identifies objects by indicating their index + numbers in the object address table. This extra level of indirection is + necessary to separate the static parts of the region table, which can be + used for all activations of a function, from the changeable part, which is + different for each activation. (When a function calls itself recursively, + for example, the exception stack entries for the various activations will + point to distinct copies of the object address table but to a common static + copy of the region table.) See ``object_addr_table_index``. + +The exception-specification stack frame indicates the types that may be thrown +by pointing to an array whose elements are exception type specifications. An +exception type specification is a structure defined as follows: + +.. code:: c++ + + struct exception_type_specification { + typeinfo *tinfo; + unsigned char flags; + unsigned char *ptr_flags; + }; + +The ``tinfo`` pointer points to a ``typeinfo`` variable for a type. The +``flags`` value is a bit set that indicates modifications of that type, e.g., +pointer-to the type. One of the bits is used to indicate the last entry in the +array. The ``ptr_flags`` field (added in version 2.41) is non-null for +multi-level pointer types. It points to an array of flags values, each one +describing the cv-qualifiers at one level of a multi-level pointer type. +Again, one of the bits is used to indicate the last entry in the array. + +The try-block stack frame contains space for a ``setjmp`` buffer, and a pointer +to an array in which each entry represents a catch handler. The entries in the +array are exception type specification structures, each one describing the type +to be caught by the associated handler. + +Note that local and global static variables are never handled in normal +exception cleanup. The required destructions for all static entities that have +been constructed are placed on a runtime list, and therefore the cleanup for +those entities need not and should not be described in the region tables. + +In the partial-lowering scheme, the region table and array table are generated, +but the object address table is not used. Instead, the addresses of variables +in the region table and array table are given as stack offsets using +``ck_stack_offset`` constants. Since there is no object address table, the +code that computes addresses and places them in the object address table is +unnecessary. No exception stack is maintained; instead, expression nodes with +subkinds ``leck_function_prologue`` and ``leck_function_epilogue`` are inserted +at the appropriate places to indicate to the back end that appropriate +maintenance should be done at those points, and to identify the variables for +the region table and array table. It is assumed that the back end will also +deal with the exception-specification, if any, for the function. In place of +assignments to ``__eh_curr_region``, expression nodes with subkind +``leck_cleanup_state`` are used to communicate the new region table entry +number to the back end at each place that changes it. ``typeinfo`` information +is still put out for all types involved in exception handling operations, but +there will be no references to those entries in the lowered code. They are +pointed to from the type entries, available for use by a back end. + +In the no-lowering scheme, none of the tables are generated (including the +``typeinfo`` entries). As in the partial-lowering scheme, + +* | ``leck_function_prologue``, +* | ``leck_function_epilogue``, and +* | ``leck_cleanup_state`` + +nodes will be inserted. The latter have a pointer to a dynamic initialization +entry, rather than a region number, as the indication of the cleanup state to +be established at that point. + +When ``INDICATE_CLEANUP_STATE_IN_UNREACHABLE_CODE`` is TRUE, cleanup state +instructions will be emitted even at the unreachable ends of blocks. This may +be desirable if the back end is using the cleanup state information to build a +table of cleanup address ranges rather than leaving them as some kind of +executable code. The instructions generated will have the special kind +``leck_unreachable_cleanup_state``. + +Throwing an Exception +^^^^^^^^^^^^^^^^^^^^^ + +The ``enk_throw`` expression node is rewritten either as + +.. code:: c++ + + __rethrow(); + +for the rethrow case (``throw`` with no operand), or as + +.. code:: c++ + + ((temp = __throw_setup(&typeinfo, size, flags)), + (initialization, __throw())) + +for the normal case. ``typeinfo`` is the runtime type information variable for +the base type being thrown, ``size`` is the size in bytes of the object being +thrown, and ``flags`` is a bit set that indicates the relationship of the type +thrown to the ``typeinfo`` type -- for example, that the type being thrown is a +pointer to the type indicated by the ``typeinfo`` variable. The +``__throw_setup`` call allocates space for a copy of the thrown object; the +initialization code makes a copy of the thrown object in that allocated space; +and the ``__throw`` call actually does the throw (and does not return). If the +thrown object requires destruction, ``__throw_setup_dtor`` is called instead of +``__throw_setup`` (this routine was added in version 2.38). +``__throw_setup_dtor`` has an additional final parameter, which is the +destructor pointer. If the thrown object is a multi-level pointer, +``__throw_setup_ptr`` is called instead of ``__throw_setup`` (this routine was +added in version 2.41). ``__throw_setup_ptr`` has a parameter in place of the +flags parameter, which is a pointer to an array of flag bytes that indicate the +cv-qualifiers at each level of the multi-level pointer type. In cases where +the thrown object is copied to the allocated space using a copy constructor, +and the copy is implicit, ``__exception_started`` is called before the copy +constructor call to tell the runtime to consider the copy constructor call as +"inside" the throw. + +In front end versions preceding 2.29, and when ``ABI_CHANGES_FOR_RTTI`` is +FALSE, a runtime routine ``__throw_alloc`` is called instead of +``__throw_setup``. It has one additional argument: if the ``typeinfo`` +type is a class with base classes, the argument is a character string +containing the letter "``Y``" or "``N``" for each base class to indicate +whether the base class is accessible. Otherwise, it is a NULL pointer. + +In the partial-lowering and no-lowering schemes, the ``enk_throw`` node is +preserved. The dynamic initialization that copies the thrown object is +lowered, using a node with subkind + +* | ``leck_thrown_object_address`` + +to indicate the address in the runtime to which the thrown object should be +copied. A node with subkind ``leck_exception_started`` is used to mark the +point before a copy constructor call. + +See ``lower_throw``. + +Catching an Exception +^^^^^^^^^^^^^^^^^^^^^ + +The routine ``lower_try_block`` lowers the ``stmk_try_block`` statement to +generate code for a ``try`` and its associated ``catch`` clauses. The code +does roughly the following: + +* | Push a try-block entry on the exception stack. This entry points to an + array whose elements describe the types to be caught by each ``catch`` + handler. The index of an entry in the array is the number assigned to + identify the associated ``catch`` handler. +* | Do a ``setjmp`` in an "``if``" surrounding the dependent statement of the + ``try``. This records the address to be jumped back to in the event that + one of the catch handlers is to be executed. When the call to ``setjmp`` + returns (the first time), the ``try`` block is executed. +* | For each ``catch`` handler, test the global variable + ``__catch_clause_number`` (which is set by the runtime before the transfer + back to this code) to see if it matches the number of the catch clause. If + so, copy the value of the caught object (whose address the runtime provides + in ``__caught_object_address``) to the handler parameter (see + ``begin_catch_clause``). Call ``__exception_caught`` to indicate to the + runtime that the exception is fully caught. Execute the dependent + statement of the ``catch``, and, on exit, call ``__free_thrown_object`` + (see ``cleanup_on_exit_from_catch``). +* | At the end of the ``try`` block, whether reached from the ``try`` or from a + ``catch`` handler, pop the try-block entry off the exception stack. + +Note three aspects of using ``setjmp`` to implement ``try``: + +#. The size of the ``setjmp`` buffer must be configured to match the target + environment. See + + * | ``TARG_JMP_BUF_NUM_ELEMENTS``, + * | ``TARG_J _BUF_ELEMENT_INT_KIND``. + * | ``TARG_JMP_BUF_ELEMENTS_ARE_FLOAT``, and + * | ``TARG_JMP_BUF_ELEMENT_FLOAT_KIND`` + + in ``targ_def.h``. +#. The ``setjmp`` is represented as a runtime routine call. This may + necessitate some sleight of hand from a back end if ``setjmp`` is not really + a runtime routine. +#. Some optimization may have to be suppressed for the region of the ``try`` + block. In C, on return from a ``setjmp`` only ``volatile`` variables are + guaranteed to be set correctly. The code generated by IL lowering, however, + assumes that all variables are set correctly, which means that variables + cannot be kept in registers over calls in any code in which exceptions might + be thrown. The ``contains_try_block`` flag in the routine entry is a + partial solution. See also the ``modified_within_try_block`` flag. + +In the partial-lowering and no-lowering schemes, the ``stmk_try_block`` +statement is preserved, with things under it lowered. The initializations of +``catch`` parameters are lowered, with a node with subkind +``leck_caught_object_address`` used to represent the address in the runtime +from which the caught object should be copied. (Note that the implicit +indirection inserted for reference parameters in the full-lowering approach is +not inserted in these modes; a back end can check the handler parameter type +and generate such an indirection if one is necessary.) A node of subkind +``leck_exception_caught`` is used to indicate the point (after the +initialization, if any) where the exception is considered fully caught. On +exit from a ``try`` or ``catch`` (by flowing off the end or by ``goto`` or +``return``), a node of subkind ``leck_try_epilogue`` or ``leck_catch_epilogue`` +is inserted. + +Unordered Evaluation +^^^^^^^^^^^^^^^^^^^^ + +The C and C++ language rules do not fully define the order of evaluation of +parts of expressions. For example, in "``A(1) + A(2)``" the evaluation of +``A(1)`` could occur before or after the evaluation of ``A(2)``. When +destructible temporaries appear in such contexts, the order of construction and +destruction of the temporaries cannot be predicted from the language rules +alone, e.g., the temporary for ``A(1)`` could be constructed before or after +the temporary for ``A(2)``. Such temporaries are called "unordered" +temporaries, and the dynamic initialization entries for them are marked as +such. These temporaries cause a problem for a portable implementation, because +is it necessary when indicating the cleanup to be done at the point of +construction of ``A(1)`` or ``A(2)`` to indicate that the other temporary might +or might not already have been constructed. This is done by adding a +conditional flag for each temporary, which indicates whether or not the +construction has been done, and having the cleanup position in the cleanup +region table include destructions for both temporaries. The runtime then tests +the conditional flags to indicate whether the destructions should actually be +done. This method, of course, involves a time and space overhead, so the flag +``DO_UNORDERED_EH_PROCESSING`` can be set to FALSE to switch it off. It can be +switched off if the back end will do the constructions in the canonical order +indicated by the IL, or if the ``next_in_destruction_list`` linkage of the +initializations is changed before IL lowering to match the order that will +actually be used by the back end, or if the back end will use some different +technique to accomplish the same result. Note that when using the C-generating +back end, the order in which temporaries are constructed depends on the C +compiler that will be used, so if one has detailed information about the order +in which it will evaluate expressions, one may be able to switch off this +processing. The unordered processing is turned off in the no-lowering scheme. + +Placement Delete +^^^^^^^^^^^^^^^^ + +When a placement ``new`` is done, and there exists a corresponding +``operator``\ ``delete`` function (one with the same parameter types as the +``operator``\ ``new``, ignoring the first parameter), if an exception is thrown +before the initialization associated with the ``new`` completes, the +``operator``\ ``delete`` is called to deallocate the storage. This is +implemented by wrapping the code that performs the initialization inside an +internal ``try`` block. If an exception is thrown while executing the ``try`` +expression, the associated ``catch`` expression, a call of the delete routine, +is executed. In the fully-lowered scheme, this internal ``try`` block is +expanded into the same code sequence used for a statement-level ``try`` (but as +part of an expression). In the partial-lowering and no-lowering schemes, the +internal ``try`` is indicated by an expression node with subkind +``leck_internal_try``. See ``make_internal_try_expr``. + +Lowering ``extern inline`` +------------------------------- + +``When LOWER_EXTERN_INLINE`` is TRUE, ``extern inline`` functions are processed +specially. In the cfront-like ABI, they are lowered to normal static inline +functions; this mainly involves just a change of the storage class in the +routine entry. In the IA-64 ABI, they are left external but put into a COMDAT +so that multiple copies are folded into one by the linker. + +The code generated in ``LOWER_EXTERN_INLINE`` mode in the cfront-like ABI does +not quite conform to the standard, because it does not ensure that when the +address of an ``extern inline`` function is taken the address is the same +across different compilation units. Setting ``INSTANTIATE_EXTERN_INLINE`` to +TRUE (instead of setting ``LOWER_EXTERN_INLINE``) provides standard-conforming +behavior: ``extern inline`` functions are treated like template instances, and +the template prelinker assigns the "instantiation" of the function to a single +file, thus ensuring that if its address is taken it is the same everywhere. + +Two transformations that apply to all extern inline functions, whether +``LOWER_EXTERN_INLINE`` is specified or not: + +* | For functions that have local static variables, the static variables are + promoted out of the function and made external (and given mangled names), + so that all copies of the function will refer to a common set of static + variables. If the static variables are initialized, the initialization + guard variables are also made external, with mangled names that begin with + ``__LSG__`` (cfront-like ABI) or ``_ZGV`` (IA-64 ABI). +* | If ``ASSIGN_STRING_LITERAL_SEQUENCE_NUMBERS`` is TRUE, similar processing + is done for string literals: they are moved into external variables with + mangled names so that every copy of the extern inline function gets the + same address for the same string literal. This is off by default in the + cfront-like ABI, even though it should be TRUE for full conformance to the + C++ standard, because it's expensive way out of proportion to its benefit. + Not being able to count on a COMDAT-like mechanism, the cfront-like ABI + must put out the variables for the string literals as tentative definitions + (therefore uninitialized), and initialize them at each point of use. It's + not at all pretty, especially in small inline functions, and it's a feature + that hardly anyone ever counts on. + +Inlining +-------- + +As an option, IL lowering can do inlining of function calls. That is, when it +encounters a call of a function declared ``inline``, it can replace the call +with IL corresponding to the body of the function with the parameters replaced +by the corresponding arguments. When a function call occurs as a statement, +the statements of the function body are inserted in place of the call. When +the function call occurs within an expression, the body of the function is +rewritten as one large expression and that expression is inserted in the proper +place in the containing expression. It is not always possible to do this sort +of inlining: there are certain constructs (e.g., loops) that cannot be rendered +in expression form. Even when the inlining is done at the statement level, +there are certain constructs that are not practical to inline. Calls that +cannot be inlined are left in their original call form, and an out-of-line copy +of the function is used. A remark is issued. + +Inlining of this style has some serious limitations. Aside from the +impossibility of inlining certain function bodies, there is also the problem +that inlining at this level is done without knowledge of the target +architecture, and therefore without the ability to know whether the inlined +version of a call is preferable to the original version. The inlined version +might be ridiculously large, or might be worse in some other way. Inlined +calls produce extremely convoluted expressions, which stress back ends and C +compilers. + +In short, if you want inlining (and you do, for C++), you probably want to do +it some other way. The version EDG supplies is provided as a convenience for +those who use the C-generating back end and whose C compilers do not handle +inlining. It's intended to give roughly the same functionality as cfront, and +EDG does not plan to enhance it in any substantial way. + +The code to perform inlining is contained in ``inline.c``, with the associated +declarations in ``inline.h``. Inlining of function calls is enabled by the +configuration switch ``MINIMAL_INLINING``. The default is to inline only when +using the C-generating back end. + +Inlining is done on code that has already been lowered, which is to say on C +code. When the end of the lowering of a function's body is reached, +``set_up_routine_for_inlining`` is called to determine whether the routine can +be inlined. If so, the ``inlinable`` flag in the routine entry is set. Note +that this means that a routine call cannot be inlined until the full definition +of the function has been seen and lowered. Also note that lowering is not done +if any errors are detected, so inlining is always done using correct code. A +function is disqualified for inlining immediately if any of the following are +true: + +* | The function has local static variables. +* | The function has local constants. +* | The function has local types. +* | The function has block scopes. +* | The function includes pragmas. +* | The function has an ellipsis in its parameter list. + +A function that passes these tests is eligible to be inlined. When a call is +seen, ``do_inlining_of_call`` is invoked to do the expansion. The expansion is +done in three steps: + +#. ``set_up_variable_remapping_for_inlining`` makes temporary variables + for the parameters and local variables of the function, and generates + assignment code to initialize each parameter temporary with the + corresponding argument expression. If the argument is constant-valued + and the parameter is not modified in the function, no temporary is + needed; the constant will be used directly. + +#. ``expand_statement_inline`` does the expansion of the function body. + It makes a copy of the statements and expressions of the function, + replacing references to the parameters and local variables with the + appropriate temporaries or constants. If the function call being + inlined appears at the statement level, the copy is made in statement + form. Otherwise, the function body is translated into expression + form as the copy is made. Expression statements are copied as + expressions; a sequence of statements is formed via comma operations; + and ``if`` statements are rendered as "``?``" operations. Loops cannot + be translated to expression form, and therefore can be inlined only in + the statement mode. ``goto``\ s and labels generally preclude inlining + in both modes, but the special case of a ``goto`` to a label + immediately following it is allowed and eliminated. ``return``\ s + are allowed only at the end of the function at the top level (or as + the last statement in a block that is the last statement in a block + ... that is the last statement of the top-level block of the function). + Dynamic initialization of local variables is translated to + assignments, but aggregate initialization precludes inlining. + +#. ``finish_variable_remapping_for_inlining`` adds the created temporaries + to the calling context scope, and then the statement sequence or + expression tree is inserted into the IL tree, replacing the original + call. + +Since the inlining operation is an attempt to inline the function, one that may +fail, the statement sequence or expression tree for the inlined call is built +off to the side, and attached to the IL tree only once the inlining operation +is completed successfully. Likewise, the temporaries created for parameters +and local variables are not entered into the scope of the call until the end of +the operation. If an inlining operation fails, the original call is left in +place and the routine is marked as requiring an out-of-line copy. (An +out-of-line copy is also required if the address of the routine was taken.) If +inlining of a call fails because of something that precludes *all* inlining of +the function, the ``inlinable`` flag of the routine is cleared so no further +attempts will be made. If the inlining operation failed only because of the +context (e.g., the function includes a loop and the call is inside an +expression), the ``inlinable`` flag is left TRUE. + +As the function body is copied with substitution for the parameters and local +variables, new constant expressions may be created. That is, when a constant +argument is passed for an unmodified parameter, the references to the parameter +in the function body are replaced by the proper constant value. That may +produce operations whose operands are constant (e.g., ``p + 1`` becomes ``1 + +1``, which can be simplified to ``2``). + +This substitution and folding is done by +``adjust_copied_expression_for_inlining``, which is called from +``copy_expr_tree`` as each node in the tree is copied. The list of remappings +to be done is built by ``set_up_variable_remapping_for_inlining`` and pointed +to by the static variable ``variable_remappings_for_inlining``. +``get_var_remapping_for_inlining`` consults the list to find the applicable +remapping for a variable. + +More dramatic simplification is possible for short-circuiting operators like +"``?``" and for ``if`` statements (whether they are rewritten in expression +form or not). If the tested expression is constant, parts of the expression +tree or statement tree are discarded accordingly. For example, when parameter +``p`` is replaced by ``1``, + +.. code:: c++ + + p ? i : (j + 1) + +becomes simply ``i``, and + +.. code:: c++ + + if (p > 0) i = 1; else i = 2; + +becomes simply ``i = 1``. This is handled by +``copy_and_simplify_short_circuited_operation`` for the operator cases, and in +``expand_statement_inline`` for the ``if`` statement. + +Arguments can be considered to be constant even if they are not literally +constants. For example, the address of a local variable is not a compile-time +constant, but it is constant over the duration of a call, and therefore can be +considered constant-valued for purposes of parameter remapping. + +The ``this`` parameter of constructors is given special treatment so that the +allocation sequence at the beginning of constructors will be eliminated when +the constructor is operating on a known variable. According to the normal +parameter rules, ``this`` in a constructor is modified within the function and +therefore a temporary must be used. However, we know how constructors work, +and if there is no assignment to ``this`` in the constructor we know the only +modification is one that will be eliminated when the constructor is called with +a non-null argument for ``this``. In such cases, the ``this`` parameter is +remapped directly to a constant, and the allocation sequence is eliminated by +the normal short-circuit optimization. + +Lowering ``thread_local`` +------------------------- + +The ``thread_local`` keyword was added in C++11 and the dynamic initialization +and destruction of objects with ``thread_local`` storage requires lowering +support. + +If the back end has the capability to execute code at thread creation time, +then it is most efficient to set the configuration macro +``USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES`` to FALSE in which +case lowering creates one or more initialization routines (depending on the +setting of ``SEPARATE_ROUTINES_FOR_FILE_SCOPE_DYNAMIC_INITS``) for each +dynamically-initialized variable with ``thread_local`` storage in the +translation unit and sets ``il_header.thread_local_dynamic_init_routines`` to +point to the list (in the proper order). It is the responsibility of the back +end to ensure that this list of routines is invoked at thread creation time. + +In most cases, however, the compiler won't have the capability to execute code +at thread creation time, in which case +``USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES`` should be set to +TRUE. In such configurations, each use of an object with ``thread_local`` +storage duration that may be dynamically initialized is re-written to invoke +the "wrapper" routine for the object (see ``lower_thread_local_variable``). +Lowering creates a "wrapper" routine (see +``thread_local_wrapper_for_variable``) that invokes an "initialization" routine +(if one exists) and then returns a pointer to the ``thread_local`` object. +This ensures that each ``thread_local`` object is properly initialized (though +at considerable run-time cost). Mangled names for wrapper routines contain the +mangled name of the ``thread_local`` object along with a prefix ( ``_ZTW`` in +the IA-64 ABI and ``__TWR__`` in the Cfront ABI). + +Note that although "wrapper" routines are only required for dynamically +initialized ``thread_local`` variables, the lack of "wrapper" routines for +``thread_local`` variables with external linkage that are not dynamically +initialized results in a non-compliant implementation (i.e., the standard +requires that all ``thread_local`` variables be initialized before the first +odr-use of any ``thread_local`` variable, but the use of a statically +initialized ``thread_local`` circumvented the initialization process). As a +result, the ``all_thread_locals_have_wrappers`` global variable was introduced +in 4.10, and when set to TRUE, results in standard compliant behavior. The +previous behavior matches g++'s behavior and is achieved by setting +``all_thread_locals_have_wrappers`` to FALSE. + +The "initialization" routines that wrappers call perform the actual +initialization for the ``thread_local`` objects (and incorporate a +``thread_local`` guard variable to ensure the initialization is performed only +once per thread). When the back end supports weak references, +``LAZY_INITIALIZATION_USES_WEAK_REFERENCES`` should be set to TRUE, in +which case each "initialization" routine is aliased to the ``__tls_init`` +routine that initializes that particular ``thread_local`` object. In cases +where a ``thread_local`` object is used in one translation unit and defined in +another, a reference to an initialization routine is created in the first +translation unit but there may or may not be a definition for the +initialization routine in the second routine (it will be aliased to the +``__tls_init`` routine in that translation unit only if the ``thread_local`` +object is dynamically initialized). When weak references are used wrapper +routines need to allow for the case where an initialization routine is +``NULL``. For back ends that do not support weak references, a do-nothing +initialization routine is created for this case (see +``make_null_thread_local_init_routine_for_variable``). Mangled names for +initialization routines contain the mangled name of the ``thread_local`` object +along with a prefix (``_ZTH`` in the IA-64 ABI and ``__THI__`` in the Cfront +ABI). + +The ``__tls_init`` routines themselves (or ``__tls_init_N`` in +one-instantiation-per-object mode) are created during the lowering of +file-scope dynamic initializations (see :ref:`dynamic-init`). + +In a manner similar to the handling of destructions of static entities, +destructions of file-scope objects with ``thread_local`` duration are +registered with the run-time library through calls to ``__cxa_thread_atexit`` +(for the IA-64 ABI) or ``__record_needed_thread_destruction`` (for the Cfront +ABI). The run-time library is then responsible for invoking these destructors +when the thread terminates (see ``record_needed_destruction``). + +Lowering ``ifunc`` +------------------ + +The GNU ``ifunc`` attribute maps to the ``STT_GNU_IFUNC`` symbol type in the +ELF standard and is not available on many architectures. The ``STT_GNU_IFUNC`` +symbol type allows a routine's symbol to be determined dynamically at load +time. At load time, the routine specified as the resolver (in the ``ifunc`` +attribute) is invoked (once) and returns a pointer to the routine that will be +used to resolve all instances of that symbol for that execution of the +executable. This provides a very low overhead mechanism to select one of a +family of functions (typically based on the underlying CPU architecture). +Here's an example (with ``--gcc --gnu_version 40600``): + +.. code:: c++ + + int printf(const char *,...); + void target() { + printf("Here\n"); + } + static void (*resolver(void))(void) { + return (void(*)(void))⌖ + } + void source() __attribute__ ((ifunc ("resolver"))); + int main() { + source(); // Prints "Here" + } + +For back ends that don't support the ``STT_GNU_IFUNC`` symbol, an approximation +of the run-time behavior can be achieved by setting ``LOWER_IFUNC`` to +TRUE. In that case, lowering will convert the routine with the ``ifunc`` +attribute into a "wrapper" routine as such: + +.. code:: c++ + + decltype(source) resolver_result = source; + source(args...) { + if (resolver_result == source) { + resolver_result = (decltype(source))resolver(); + } + return *resolver_result(args...); + } + +This has the effect of invoking the resolver only once (though at run time +rather than at load time). Invocations of ``source`` incur an extra function +call and indirection, but lowering re-writes references to ``source`` so they +are dispatched through the resolver variable whenever possible (in which case +the only overhead is an extra indirection). + +Note that there are a few caveats: + +* | The re-writing of calls to avoid the wrapper routine only occurs once the + declaration with the ``ifunc`` attribute has been seen; any reference prior + to that point will be unlowered (and will hence invoke the wrapper). That + can be an issue if, for example, the declaration with the ``ifunc`` + attribute is only in a library's implementation (and not in the shared + header file). In that case, code that is compiled with the shared header + file will contain references to the wrapper routine. +* | Constants (i.e., ``ck_address``/``abk_routine``) that refer to the + ``ifunc`` are not re-written in lowering, so they'll always point to the + wrapper routine. + +See ``lower_ifunc_routine`` and ``lower_ifunc_expr`` for more information. + +Lowering GNU function multiversioning +------------------------------------- + +GNU supports function multiversioning in version 4.8.0 and later via the +``target`` attribute in C++ mode. Detailed documentation is available here: +``http://gcc.gnu.org/wiki/FunctionMultiVersioning``. The ``target`` attribute +allows multiple versions of a function definition to be supplied, and the +choice of which version to call is determined at load time based on +characteristics of the machine where the program is running. The choice is +made by a compiler-generated (when lowering is enabled) "resolver" routine that +selects the best routine from the target-specific versions. The resolver +routine is executed once at load time (because it is associated with an +``ifunc`` routine) to determine which target-specific routine to use for the +particular CPU. For back ends that don't support ``ifunc``, see +``LOWER_IFUNC``. + +For example (assuming ``USE_X86_FUNCTION_MULTIVERSIONING`` is ``TRUE,`` with\ +``--gnu_version 40800``): + +.. code:: c++ + + __attribute__ ((target("default"))) int foo () { return 222; } + __attribute__ ((target("arch=corei7"))) int foo () { return 777; } + __attribute__ ((target("avx"))) int foo () { return 333; } + int main () { + int (*fp)() = foo; + return fp() != foo(); + } + +Would generate lowered pseudo-code like this: + +.. code:: c++ + + int foo_default () { return 222; } // "default" foo + int foo_corei7 () { return 777; } // "corei7" foo + int foo_avx () { return 333; } // "avx" foo + // Resolver function returns address of specific function + static (int *foo.resolver()) { // lowering-generated resolver function + resolved_foo = // one of foo_default, foo_corei7, foo_avx + return resolved_foo; + } + int foo.ifunc() __attribute__((ifunc("foo.resolver")); + int main () { + int (*fp)() = foo.ifunc; // &foo lowered to &foo.ifunc + // Dynamic loader invokes foo.resolver + // to select which specific foo. + // foo.ifunc is invoked once during + // startup. + return fp() != foo.ifunc(); // call of foo is lowered to foo.ifunc + } + +Note that at present, lowering is only performed when +USE_X86_FUNCTION_MULTIVERSIONING is TRUE (the rules that are used to determine +at run-time which of a set of target-specific functions are machine-specific +and only the x86 case is implemented). + +See ``lower_mv_routine``, ``lowered_mv_routine``, and ``create_mv_resolver``. + +How is IL Lowering Done? +======================== + +Sequencing +---------- + +All the individual transformations done by IL lowering are relatively +straightforward. What makes the job of IL lowering so difficult is the fact +that it must operate under some very difficult sequencing constraints. + +They come about because IL lowering must be done on a per-function basis, so +that individual memory regions can be lowered and then written to a file. That +means that when function scope memory regions are lowered, the file scope +entities that they reference are not yet lowered. And they cannot be: since +the file-scope entities are still active entities in the compilation, if they +were modified by IL lowering it would disturb the rest of the compilation. + +To pick an example: to lower a virtual function call in a function scope, one +needs to be able to reference the virtual function pointer field in the class +entity. That field is added by IL lowering. But the class type is in the file +scope memory region, and therefore has not yet been lowered at the time the +virtual function call is lowered. + +Another example: IL lowering changes reference types into pointer types. +However, mangled names of functions must be based on the original types, +including reference types. Therefore, mangled names must be generated before +reference types are changed to pointer types. + +Another example: the variable that contains a virtual function table must be +available when constructors and destructors for classes are lowered. However, +it is not possible to know at that point in the compilation whether or not the +definition of the virtual function table should be put out. In fact, it's not +possible to tell whether it should be internal or external. Therefore, virtual +function table variable definitions cannot be done at the time the variable +declarations are done. + +In short, lots of processing that would be fairly straightforward if the entire +IL tree could be lowered at once becomes convoluted because some parts of the +tree have already been lowered, some haven't, some cannot be yet, etc. + +One technique that helps is the concept of "prelowering" classes. This is +processing that's done as soon as possible on completed class definitions. It +does not modify the class, but it adds information that is needed to use the +class in lowering code: + +* | The type-as-subobject (a copy of the type with any virtual base classes + removed). +* | The fields that make the base classes, virtual base class pointers, and + virtual function table pointer of the class explicit. (Note that this + change affects the field list of the type, which would seem to be a + modification; however, since the fields are not in the symbol table, they + cannot be found by the front end. It does mean that front end code should + not traverse the field list to visit all the fields. It should use the + symbol list instead.) +* | Variables for virtual function tables. These are all created as ``extern`` + declarations, and they are changed to definitions or to static variables + later if that is appropriate. + +See ``prelower_class_type``. + +Another technique is to not clear C++-specific fields when they are +lowered, where that's possible. One example: the implicit "``this``" +parameter type in a routine type entry becomes an explicit first parameter +type when lowered. However, the pointer to the implicit type is not +cleared. That allows code that wants to see whether or not a function is a +nonstatic member function to fetch the "``this``" parameter type without having +to know whether or not the type has already been lowered. One consequence +of this technique is that back ends cannot count on having the C++-specific +fields cleared, and should therefore not look at them. + +The IL Lowering Flag +-------------------- + +The IL lowering flag is a two-state flag that appears in the prefix that +precedes each IL entry. It is flipped from 0 to 1 when the associated entry is +visited during IL lowering. This allows IL lowering to know that it has +already processed a given entry and thereby avoid looping when there are cycles +in the IL graph. + +This flag is similar to the ``il_walk_flag`` used by the IL walk routines, but +is kept separate so that IL lowering is not forced to visit all of the IL tree +even if it knows that certain parts cannot contain entries that will be +modified by lowering. It should be noted that even though every entry has a +flag, not all entries' flags are maintained by IL lowering. For example, IL +lowering does not maintain the flag on expression nodes, because it knows that +it will visit each expression node exactly once. + +Why not use the standard IL walk routines to do the traversal? The problem is +that the IL walk routines cannot co-exist with processing that changes the +structure of the IL tree. Since IL lowering can eliminate entries, move them +around, add entries, and swap entries, the IL walk routines could get into +loops, get lost, or process entries more than once. Therefore they are not +suitable, and IL lowering has its own IL traversal code. + +Orphaned Entries +---------------- + +Type entries and static variables that are local to a function require some +special handling. All type entries and all static variables are allocated in +the file scope memory region. However, types and static variables that are +local to a function are placed on the types and static variables list of a +function or block scope. Those are unusual lists: the function scope entries +(in a function scope memory region) point to lists that are entirely in the +file scope memory region. Yet, the entries pointed to are not really part of +the file scope. They might, in fact, not be referenced from anywhere except +the function scope memory region. Such entries are "orphaned" in the file +scope: their parents are processed, written out, and removed from memory, but +the children remain in the file scope, unattached to the rest of the file scope +IL tree. + +There is special processing in the IL write, read, and walk routines to deal +with such orphans, but special handling is also required in IL lowering. + +Such entries clearly must be lowered at some point. Do we lower them when the +function scope is lowered, or do we lower them when the file scope is lowered? +Well, lowering them with the function scope is impractical, since it's hard to +tell which of the file-scope references are orphans and which are not. Even if +we know that a static variable, say, is an orphan, how much of its subtree do +we process? Is its type an orphan, or just a normal file-scope type? + +So it's easier not to do lowering on orphans. The processing then lowers +entries in the function scope, and leaves all those in the file scope alone. +Whenever a pointer hops into the file scope memory region, IL lowering leaves +that entry alone, regardless of whether or not it might be an orphan. + +This solves one problem but creates another. If there truly are orphaned +entries, how will the IL lowering for the file scope find them to lower them? +The answer is that orphans or potential orphans are recorded on a special list, +using support routines and data structures provided by the IL support +components. When a pointer hops into the file scope memory region, the entry +pointed to is recorded as a potential orphan, and at the end of the lowering +for the file scope all the orphans are visited. If they turn out not to be +orphans, the IL lowering flag will indicate that they have already been visited +and they will not be processed again. + +See ``lower_orphaned_entries``. + +Maintained Context +------------------ + +While IL lowering works through a top-level scope, it maintains a stack that +shows the nesting of scopes for the present position (the spot for which +lowering is being done). This makes it easy to find the innermost enclosing +scope or the innermost enclosing function at any given moment, for example to +create a temporary in the innermost scope. The global variable +``curr_context`` points to the top of the context stack. + +Object Lifetimes +---------------- + +The object lifetime entries in the IL provide information about regions of the +program on exit from which automatic destructions of class objects are done. +The destructions to be done appear in a list attached to the object lifetime +entry (in the form of dynamic initialization entries). IL lowering uses this +information to insert destructor calls on exit from those regions (whether by +flowing off the end of the region or branching out of it via a ``goto`` or the +like), and to build region table information for exception handling. + +As IL lowering works through the IL, it keeps track of the current position in +cleanup terms, which is to say the latest initialization encountered that +requires automatic destruction. This is maintained in the +``latest_initialization`` field of the current context. Given the pointer to +the latest initialization, ``gen_cleanup_actions`` and its subroutines can walk +up the cleanup chain, generating the appropriate destructions. In the case of +a ``return``, the walk up the chain continues until the lifetime for the +function scope is reached. In the case of a ``goto``, the cleanup continues +until the lifetime indicated in the ``goto`` statement is reached (that +lifetime is determined by the front end, and is the innermost lifetime that the +``goto`` and the label have in common). + +At the beginning of lowering of a block, the object lifetime for the block and +for any expression-temporary lifetimes immediately within it are processed. +This processing (which is performed by ``begin_object_lifetime``) involves +allocating an entry of type ``a_destructible_entity_descr`` and attaching it to +each dynamic initialization on the lifetime destructions lists. These entries +are used to record information that will be needed when generating the +initialization and the later destruction. In particular, the position of the +entity (in initialization position form; see below) is determined and recorded +in the entry at the time of initialization. That position is then used when +generating the destruction code. The beginning-of-lifetime processing also +includes deciding whether the entity will require a conditional flag to +indicate that the construction has been done. If one is required, the variable +for it is created and code to initialize it to zero is inserted. + +At the beginning of block-after-label lifetimes, similar processing is done, +but it takes a bit of effort to get it done at the right time, because there is +no explicit indication of a new lifetime on a statement that ushers in a +block-after-label lifetime. One must note, at the beginning of the previous +block or block-after-label lifetime, the next block-after-label lifetime in +sequence, and watch for the appearance of the associated statement during the +normal processing of statements. Also at labels (including switch case +labels), long lifetime temporaries must be destroyed (and when exceptions are +enabled, the region table is adjusted accordingly). (For this reason, +block-after-label lifetimes can begin at ``stmk_switch_case`` statements in +long-lifetime-temporaries mode.) + +Initialization Positions +------------------------ + +``an_init_pos_descr`` is used to contain a description of a position within an +initialization. As an aggregate initialization is processed, such a +description is maintained for the current position. The description can then +be turned into an expression that addresses the indicated position, which is +necessary when generating code to initialize pieces of aggregates: + +.. code:: c++ + + int j; + void f() { + struct {int i; int j;} k[2] = {{1, 1}, {j+1, 2}}; + } + +becomes + +.. code:: c++ + + int j; + void f() { + struct {int i; int j;} k[2] = {{1, 1}, {0, 2}}; + k[1].i = j+1; + } + +Insert Locations +---------------- + +Many transformations work by inserting new pieces of code into expressions or +statement lists. The insert location for such insertions is described by a +structure of type ``an_insert_location``. It can describe an insert location +either within an expression or within a sequence of statements. The code +inserted is typically in units of "statements", even when the insertion is +within expressions. That is, a lowering routine would assemble something like +``temp = 1`` and that construct would be inserted, either as a free-standing +expression statement, or as a clause in a comma operation added within an +expression. For the expression insertion case, for example, + +.. code:: c++ + + i ? (void)A(i) : (void)0 + +might be modified by insertion of an assignment: + +.. code:: c++ + + i ? (temp = 1, (void)A(i)) : (void)0 + +Since the insertion is done in statement units, the callers of the insert +routines need not in general be concerned about whether or not the insert +location is in an expression or a statement. The low-level routines do the +necessary adjustment, including rendering conditional tests as ``if`` +statements or "``?``" operators. + +See + +* | ``insert_expr`` +* | ``insert_statement`` +* | ``insert_if_statement`` + +Reusable Copies +--------------- + +There are a few cases where an expression that is used once in the original IL +tree is used more than once in the lowered IL tree. Without special handling, +such cases might cause problems if the expression involved has side effects. +The routine ``make_reusable_copy`` solves the problem: given an expression +tree, it returns a distinct expression tree that produces the same value. If +the original tree has no side effects, it is simply copied. If it has side +effects, the original expression is modified to assign the expression value to +a temporary, and the new copy is simply a reference to the temporary. + +Note that the new copy does not replace the original expression. The original +expression continues to be used in its original location, and the copy is used +for the second reference. Further copies can be made from either of the +expressions. + +``make_lvalue_reusable_copy`` does a similar operation for expressions that are +lvalues. It handles bit-field lvalues specially. + +.. _lowering-c-dialects: + +Lowering C Dialects +=================== + +In some newer C modes like C99 or GNU C mode, some features create IL +constructs that are not used in IL for C89. In order to make things easier for +back ends, the front end includes a C lowering phase, which can rewrite many +(but not all) of these newer C constructs. Many (but not all) of the +additional IL features are enabled by ``C99_IL_EXTENSIONS_SUPPORTED``. Most of +the code for this lowering is in ``lower_c99.c``, with related declarations in +``lower_c99.h``. + +* | For compound literals, the generated ``enk_temp_init`` node is rewritten as + an initialized generated variable. See ``lower_c99_temp_init``. +* | Designated initializers are processed to produce a C89-style aggregate + initializer. This is done outside of the primary C99 lowering phase, and + is enabled by ``LOWER_DESIGNATED_INITIALIZERS``. ``ck_designator`` + constants remain in the IL after this lowering for initializations of + members other than the first in unions, which are not expressible in C89 + IL. See ``lower_designated_initializers``. Note that there are some + advantages to not doing this lowering and instead handling the designators + in a back end, notably that that can avoid some very large IL structures + for big sparsely-initialized arrays. +* | The ``_Bool`` type is unchanged, but a C89 view of the IL does not consider + the ``bool_type`` flag and therefore sees the underlying integer. Compound + assignment operators whose left-hand operand has type ``_Bool`` are + rewritten to ensure that the result value is restricted to 0/1, via the + same routines that do this processing in C++ lowering; see + ``rewrite_compound_assignment``. Boolean casts are also handled as in C++; + see :ref:`il-bool-type`. +* | Complex types are rewritten as structs, imaginary types are rewritten as + floating-point types, complex constants are rewritten as aggregate + initializers, imaginary constants are rewritten as floating-point + constants, and operators and conversions on complex and imaginary types are + rewritten as runtime routine calls. This is controlled by + ``LOWER_COMPLEX``. See ``lower_c99_nonreal_float_types``, + ``lower_c99_complex_cast``, and ``lower_c99_operator``. Also see the file + ``c99_complex.c`` in the runtime library for descriptions and sample + implementations of the complex runtime routines. Note that a back end + could treat the runtime routines as intrinsics and generate machine + instructions directly for the calls. (Again, the C99-centric names are + historical: These routines also handle complex types appearing in GNU C + source.) + | + | For compound assignment operators, the operation is rewritten in terms + of the underlying operation, and the result is then converted and + stored in the destination variable (e.g., ``x += y`` is rewritten as + ``x = x + y``). If the left side is an expression with side effects, + its address is evaluated and stored in a temporary, and the two + references to the left hand side (to fetch its value as as input to the + operation, and to store the result) are done by way of indirection + through the temporary. See ``rewrite_compound_assignment``. + +* | If ``LOWER_FIXED_POINT`` is TRUE, fixed-point operations, types, and + constants are rewritten into standard C. Fixed-point types are lowered to + typedefs for appropriately-size integral types (see + ``lower_c99_fixed_point_types``). Fixed-point constants are lowered to + integral constants (see ``lower_c99_fixed_point_constant``). Fixed-point + operations and conversions are lowered to calls to runtime routines (see + ``lower_c99_fixed_point_operation``, ``lower_c99_fixed_point_cast``, + ``lower_c99_fixed_point_incr_decr``, and ``rewrite_compound_assignment``). + The runtime routines are not provided by EDG; they are available from + Dinkumware, Ltd. There is a long comment beginning with "Fixed-point + lowering:" in ``lower_c99.c`` that gives more details on the runtime + interface. +* | When ``LOWER_VARIABLE_LENGTH_ARRAYS`` is TRUE variable-length arrays (VLAs) + are rewritten as pointers to storage allocated by the run-time library. + Storage for a VLA is allocated by a call to ``__vla_alloc``, which is + produced by the lowering of certain ``stmk_vla_decl`` statements. The + storage is freed by calls to ``__vla_dealloc``, which are the result of + lowering ``enk_vla_dealloc`` expression nodes (which may be produced + directly by the front end in C modes, or as the result of IL lowering in + C++ modes). + | + | A VLA type can be defined recursively to be either an array type with a + nonconstant bound, or a normal (constant-bound) array whose element is + a VLA type. The lowering process eventually replaces all VLA types and + pointer to VLA types by pointer types pointing to the underlying + (non-array) element type of the VLA type. For example, the type ``int + [3][n][4]`` is replaced by ``int*`` and the type + ``double*(*)[3][n][4]`` is replaced by ``double**``. To avoid certain + subtle ordering problems, this type replacement is done in two stages. + First, all VLA types are collected on a linked list (see + ``record_vla_component_types_for_lowering``) during the main C99 IL + lowering traversal (this is necessary because these types may only be + pointed to from an expression node, unlike, e.g., class types which are + listed on a scope's type list). After the main tree traversal, the + actual replacement is done by a call to the function + ``lower_vla_types``. + | + | The length of VLA types must in general be computed at run time. This + is achieved by evaluating the array bound expression and storing the + result in temporary helper variables. To further simplify the VLA size + computations in expressions, these variables are updated to hold a + total count of the number of (non-array) elements for a particular VLA + type component. For example, the type ``char[n][m]`` would produce two + variables, one holding the value ``m`` and the other holding the value + ``n*m``. Once created, the IL entries for these variables can be + accessed through the ``a_vla_dimension`` entries of the associated VLA + type components. For VLA types appearing in explicit declarations + (variable declarations and typedef declarations), the front end adds + adds explicit ``stmk_set_vla_size`` statement indicating when the value + of these variables ought to be computed. However, in expression + contexts that introduce new VLA types (``sizeof`` and cast expressions, + as well as compound literals) there are no such statements. Either + way, the bulk of the work to produce and compute these variables is + done in ``lower_vla_dimensions``, which creates all the necessary + variables for an arbitrarily complex VLA type and returns an expression + that sets all the variables to their required values. + | + | With those variables available, the lowering of various array-related + operations (subscripting, pointer arithmetic, and run-time ``sizeof`` + expressions) is relatively straightforward. There is a long comment + near the beginning of ``lower_c99.c`` (conditioned on + ``LOWER_VARIABLE_LENGTH_ARRAYS``) that gives more details on the + lowering of VLAs. +* | Extended identifiers containing universal character names (``\u``\ *xxxx*), + whose name strings contain the ``\u`` etc., are rewritten as standard + identifiers if ``REWRITE_UCN_ESCAPE_CHAR_IN_LOWERING`` is TRUE. The + "``\``" character is changed to "``_``". This is the same processing that + is done in C++ lowering. +* | Non-constant expressions in aggregate initializers, i.e., those indicated + by ``ck_dynamic_init`` constants, are rewritten as executable code. This + is done via the same routines that do this processing in C++ lowering. See + ``lower_c99_stmk_init``. +* | Inline function calls are replaced by their expansions if + ``MINIMAL_INLINING`` is TRUE. This is done via the same routines that do + this processing in C++ lowering. +* | Boolean controlling expressions are optionally normalized to always yield + an integer value of 0 or 1. This transformation occurs even in C89 mode + (and the same processing is done in C++ mode). + +Some features are not lowered but use IL constructs that exist in IL produced +by lowering C++, which a back end is likely already to accept: + +* | For mixed statements and declarations, the statements and declarations + appear intermixed in the statement list of a compound statement. +* | For ``long``\ ``long``, there are two new integer kinds (``ik_long_long`` + and ``ik_unsigned_long_long``) and new constants of these kinds. + +One feature is not lowered at all: + +* | For flexible array members, the last member of a struct type may have an + array type with an unknown bound. This probably does not require special + processing in a back end. + + + +.. [#f1] The configuration flag ``MINIMAL_INLINING`` can be used to enable a + minimal version of inlining for those who have no better alternative. +.. [#f2] This routine is not present in the cfront runtime. It would have to + be added to a cfront runtime library to make the library usable with + the EDG front end. +.. [#f3] One nit: a function is considered inline only if it is inline in the + class definition, and not if inline was added on the out-of-class + definition. +.. [#f4] This feature is not implemented in cfront 2.1, and therefore this + runtime routine is not present in the cfront 2.1 runtime library. It + would have to be added to such a library to make the library usable + with the EDG front end. +.. [#f5] In the IA-64 ABI, IL lowering avoids generating duplicate + ``typeinfo`` variables by checking a new needed type against all + previously generated ``typeinfo`` variables. diff --git a/dev/doc/_sources/modules.rst.txt b/dev/doc/_sources/modules.rst.txt new file mode 100644 index 0000000..c37e350 --- /dev/null +++ b/dev/doc/_sources/modules.rst.txt @@ -0,0 +1,2033 @@ +======= +Modules +======= + +The EDG modules implementation is based upon the Microsoft IFC specification. + +The EDG front end has experimental support for both the IFC variant produced by +Microsoft's Visual Studio compiler and an EDG variant produced by the EDG front +end. + +Roles +===== + +To make the system work, every IFC type is understood in terms of a "role". The +type's role in effect defines what semantics it will be generated with. + +The roles are as follows: + +* :ref:`ifc-simple-sort-role` - Any kind of enumeration of named values + unrelated to an index. +* :ref:`ifc-index-sort-role` - A "sort" that encodes a simple sort and an + associated index (e.g., ``DeclIndex`` is the "Index Sort", with a "Simple + Sort" ``DeclSort``). +* :ref:`ifc-bitfield-role` - Any IFC type that encodes things using bit flags. +* :ref:`ifc-raw-numeric-role` - Any IFC type that is an integer with no + associated implicit interpretation (from a format perspective, it's just a + "dumb" number). +* :ref:`ifc-raw-bytes-role` - Similar to Raw Numeric, anything that's just a + raw byte array. +* :ref:`ifc-node-roles` + * :ref:`ifc-partition-node-role` - An IFC Node that can be directly read + from a partition, for instance a ``DeclFunction``. + * :ref:`ifc-basic-node-role` - An IFC Node that only appears as a + sub-node (doesn't have a partition of its own), for instance, a + ``ModuleReference``. + * :ref:`ifc-header-node-role` - Basically what it says, an IFC Node that's + part of the header (``FileHeader`` and ``Partition``). +* :ref:`ifc-foreign-index-role` - A special role for IFC types that represent + an Index in another module file. +* :ref:`ifc-value-category-role` - A role representing several levels of + discriminated values (conceptually similar to an IFC ``std::variant``) + +.. _ifc-simple-sort-role: + +Simple Sort +----------- + +Simple sorts are represented as an enum (sorted in alphabetical order): + +.. code-block:: c++ + + enum an_ifc_access_sort { + ifc_as_none, + ifc_as_private, + ifc_as_protected, + ifc_as_public + }; /* an_ifc_access_sort */ + +Simple sorts can also be converted to a c-string of their respective EDG name +via a call to the respective ``str_for`` function. This can be useful for +debugging and diagnostic purposes. + +.. _ifc-index-sort-role: + +Index Sort +---------- + +Index sorts are represented as an index type (a struct with a module binding, +an associated :ref:`ifc-simple-sort-role` value, and the associated index +value): + +.. code-block:: c++ + + enum an_ifc_decl_sort { + ifc_ds_decl_alias, + ifc_ds_decl_barren, + ifc_ds_decl_bitfield, + ifc_ds_decl_concept, + ifc_ds_decl_constructor, + ifc_ds_decl_deduction_guide, + ifc_ds_decl_destructor, + ifc_ds_decl_enumeration, + ifc_ds_decl_enumerator, + ifc_ds_decl_expansion, + ifc_ds_decl_explicit_instantiation, + ifc_ds_decl_explicit_specialization, + ifc_ds_decl_field, + /* snip */ + }; /* an_ifc_decl_sort */ + + /* + The universal representation for an IFC DeclIndex. + */ + struct an_ifc_decl_index { + an_ifc_module* + mod; + /* The associated module. */ + an_ifc_decl_sort + sort; + /* The associated DeclSort value for this index. */ + uint32_t value; + /* The index value into the associated partition of + "sort" for this index. Represented as the + largest common underlying type. */ + }; /* an_ifc_decl_index */ + +.. _ifc-bitfield-role: + +Bitfield +-------- + +Bitfields are represented as a bitfield type (a struct with a module binding +and the raw value pulled from the module file): + +.. code-block:: c++ + + /* + The universal representation for an IFC FunctionTraitsBitfield. + */ + struct an_ifc_function_traits_bitfield { + an_ifc_module* + mod; + /* The associated module. */ + an_ifc_function_traits_bitfield_storage + value; + /* The raw bit value obtained from the module. + Represented as the largest common underlying + type. */ + }; /* an_ifc_function_traits_bitfield */ + +This is then paired with a (alphabetically sorted) set of bit queries. + +.. code-block:: c++ + + enum an_ifc_function_traits_bitfield_query : uint32_t { + ifc_ftb_constexpr = 1 << 0, + ifc_ftb_constrained = 1 << 1, + ifc_ftb_defaulted = 1 << 2, + ifc_ftb_deleted = 1 << 3, + ifc_ftb_explicit = 1 << 4, + ifc_ftb_hidden_friend = 1 << 5, + ifc_ftb_immediate = 1 << 6, + ifc_ftb_inline = 1 << 7, + ifc_ftb_no_return = 1 << 8, + ifc_ftb_none = 1 << 9, + ifc_ftb_pure_virtual = 1 << 10, + ifc_ftb_virtual = 1 << 11 + }; /* an_ifc_function_traits_bitfield_query */ + +A bitmask can then before formed and tested on a bitfield like so: + +.. code-block:: c++ + + an_ifc_function_traits_bitfield bitfield = ...; + + if (test_bitmask(bitfield)) { + /* matched bitfield & (ifc_ftb_immediate | ifc_ftb_explicit) */ + } else { + /* didn't match */ + } /* if */ + +.. _ifc-raw-numeric-role: + +Raw Numeric +----------- + +Raw numerics are represented as a raw numeric type (a struct with a module +binding and the raw value pulled from the module file, along with a convenience +conversion operator): + +.. code-block:: c++ + + /* + The universal representation for an IFC Index. + */ + struct an_ifc_index { + an_ifc_module* + mod; + /* The associated module. */ + an_ifc_index_storage + value; + /* The raw bit value obtained from the module. + Represented as the largest common underlying + type. */ + + inline operator an_ifc_index_storage() const + { return this->value; } + }; /* an_ifc_index */ + +Thus, the value itself can be passed around safely without concern of changes +in the underlying type, and with access to the module, while being trivial to +work with as an unsigned number: + +.. code-block:: c++ + + an_ifc_index power_idx = ...; + + if (power_idx > 9000) { + /* panic */ + } /* if */ + +.. _ifc-raw-bytes-role: + +Raw Bytes +--------- + +Types generated from the raw bytes role are derived from +:ref:`ifc-byte-buffers`. + +.. code-block:: c++ + + /* + The universal representation of an IFC SHA256 node. + + The representation is declared as a derived struct of an_ifc_Byte_buffer + rather than simply an alias of the instantiation to improve the debugger + experience. + */ + struct an_ifc_sha256 : an_ifc_Byte_buffer { + using storage_type = an_ifc_sha256_storage; + using base_type = an_ifc_Byte_buffer; + using base_type::an_ifc_Byte_buffer; + }; /* an_ifc_sha256 */ + +These types also include an additional table documenting the number of bytes +available (starting from a specific version). For example, if a type has +32 bytes starting with version 0.33, and that doubles to 64 bytes in 0.41 +the following table will be written: + +.. code-block:: text + + |----------------| + | Version | Size | + |---------|------| + | 0.33 | 32 | + | 0.41 | 64 | + |---------|------| + + +.. _ifc-node-roles: + +Nodes +----- + +The node roles (:ref:`ifc-partition-node-role`, :ref:`ifc-basic-node-role`, and +:ref:`ifc-header-node-role`) are all very similar, differing only in their +construction. + +The node types are -- similarly to :ref:`ifc-raw-bytes-role` types -- derived +from :ref:`ifc-byte-buffers`. + +.. code-block:: c++ + + /* + The universal representation of an IFC DeclFunction node. + + The representation is declared as a derived struct of an_ifc_Byte_buffer + rather than simply an alias of the instantiation to improve the debugger + experience. + */ + struct an_ifc_decl_function : + an_ifc_Byte_buffer { + using storage_type = an_ifc_decl_function_storage; + using base_type = an_ifc_Byte_buffer; + using base_type::an_ifc_Byte_buffer; + }; /* an_ifc_decl_function */ + +Additionally, -- again similarly to :ref:`ifc-raw-bytes-role` types -- node +types include a descriptive table to aid in development: + +.. code-block:: text + + |------------------------------------------------------------| + | DeclFunction - 0.33 (32 bytes) | + |-------------|-----------------------------|---------|------| + | Name | Type | Version | Size | + |-------------|-----------------------------|---------|------| + | name | NameIndex | 0.33 | 4 | + | locus | SourceLocation | 0.33 | 8 | + | type | TypeIndex | 0.33 | 4 | + | home_scope | DeclIndex | 0.33 | 4 | + | chart | ChartIndex | 0.33 | 4 | + | traits | FunctionTraitsBitfield | 0.33 | 2 | + | specifiers | BasicSpecifiersBitfield | 0.33 | 1 | + | access | AccessSort | 0.33 | 1 | + | properties | ReachablePropertiesBitfield | 0.33 | 1 | + | __padding__ | uint8_t[3] | | 3 | + |-------------|-----------------------------|---------|------| + + |------------------------------------------------------------| + | DeclFunction - 0.41 (32 bytes) | + |-------------|-----------------------------|---------|------| + | Name | Type | Version | Size | + |-------------|-----------------------------|---------|------| + | name | NameIndex | 0.33 | 4 | + | locus | SourceLocation | 0.33 | 8 | + | type | TypeIndex | 0.33 | 4 | + | home_scope | DeclIndex | 0.41 | 4 | + | chart | ChartIndex | 0.33 | 4 | + | traits | FunctionTraitsBitfield | 0.33 | 2 | + | specifiers | BasicSpecifiersBitfield | 0.33 | 1 | + | access | AccessSort | 0.33 | 1 | + | properties | ReachablePropertiesBitfield | 0.33 | 1 | + | __padding__ | uint8_t[3] | | 3 | + |-------------|-----------------------------|---------|------| + | home_scope | DeclIndex | 0.41 | TF | + |-------------|-----------------------------|---------|------| + +Here, the first table describes ``DeclFunction`` from IFC version 0.33 up until +0.41 (non-inclusive) as a 32 byte structure. Each of the structure's fields are +listed with their name, return type, the interpretation version of the return +type, and the size of the field. Additionally, a ``__padding__`` field is +listed specifying there are 3 bytes of unused (or unknown) data padding the end +of the structure (which would otherwise be 29 bytes). + +The second table describes ``DeclFunction`` for IFC version 0.41+ +(inclusive). This table is very similar to the structure describing the +earlier version of ``DeclFunction``. However, this table specifies that the +home_scope's ``DeclIndex`` has an updated value interpretation, and in the +bottom row of the table sized "TF" that a tacit field is being used to +define (in this case redefine) home_scope (see :ref:`ifc-tacit-field` for +more information on tacit fields). + +The values of these fields can be retrieved via calling the ``get_ifc_``\ *X* +function where *X* is the name of the field (for information on the inner +workings of these functions, see :ref:`ifc-node-versioning`). For instance, to +retrieve the ``home_scope`` (independent of the IFC version and underlying +semantics) the following function can be used: + +.. code-block:: c++ + + an_ifc_decl_function func_decl = /* ... */; + an_ifc_decl_index home_scope = get_ifc_home_scope(func_decl); + +The returned ``home_scope`` is pre-validated during the node's +construction, and ready for usage (for more information, see +:ref:`validation`). + +.. _ifc-partition-node-role: + +Partition Node +^^^^^^^^^^^^^^ + +To get a partition node, in effectively all front end code, ``construct_node`` +should be used (for information on exceptional cases, see +:ref:`skipping-validation`). This looks something like: + +.. code-block:: c++ + + Opt opt_idf; + + construct_node(&opt_idf, index); + +This will load the appropriate value found at the given index, run validation +(if necessary), and (if validation is successful) store the node in the ``Opt`` +variable. + +.. _ifc-basic-node-role: + +Basic Node +^^^^^^^^^^ + +Basic nodes are only obtainable from a ``get_ifc_``\ *X* operation, and used to +represent nodes which are nested in other nodes. For instance, you might have: + +.. code-block:: c++ + + an_ifc_decl_reference decl_ref = ...; + + an_ifc_module_reference module_reference = get_ifc_unit(decl_ref); + +Here the returned ``an_ifc_module_reference`` is a basic node. Note that this +is not wrapped in an optional, as the ``an_ifc_module_reference`` being a +sub-node of ``an_ifc_decl_reference`` was validated when +``an_ifc_decl_reference`` was constructed. + +.. _ifc-header-node-role: + +Header Node +^^^^^^^^^^^ + +Header nodes rarely need new code written for them, there are only two at the +time of writing (and for the foreseeable future): + +* ``an_ifc_file_header`` +* ``an_ifc_partition`` + +To get a header node, the low level ``construct_node_from_module`` is used +directly. Similarly, since header nodes are lower level, validate functions +need called explicitly. + +The flow for interaction with these nodes is typically something like the +following (if not in practice, conceptually): + +.. code-block:: c++ + + Opt get_module_header(an_ifc_module *mod) + { + Opt result; + an_ifc_file_header raw_result; + + init_byte_buffer(4, mod->f_size - 4); + raw_result = construct_node_from_module(mod); + if (validate(raw_result, /*parent=*/NULL)) { + result = raw_result; + } /* if */ + return result; + } /* get_module_header */ + +This is conceptually very similar to what ``construct_node`` is doing behind +the scenes. + +.. _ifc-foreign-index-role: + +Foreign Index +------------- + +Currently in the IFC spec there's a ``DeclSort::Reference`` structure: + ++-----------------+---------------------+ +| Field | Type | ++=================+=====================+ +| ``unit`` | ``ModuleReference`` | ++-----------------+---------------------+ +| ``local_index`` | ``DeclIndex`` | ++-----------------+---------------------+ + +The problem is that the ``local_index`` field uses a ``DeclIndex``, but +that ``DeclIndex`` is valid in a completely different module. This has +caused issues for the front end in the past where the index is accidentally +being used in the current module's code. + +The "Foreign Index" role is used to replace the ``DeclIndex`` type with a +new ``DeclForeignIndex`` type. This new type is more akin to a +:ref:`ifc-raw-numeric-role` than a :ref:`ifc-index-sort-role`. + +The front end thus represents this as the following node structure: + ++-----------------+----------------------+ +| Field | Type | ++=================+======================+ +| ``unit`` | ``ModuleReference`` | ++-----------------+----------------------+ +| ``local_index`` | ``DeclForeignIndex`` | ++-----------------+----------------------+ + +The ``DeclForeignIndex`` type in C++ code looks as follows: + +.. code-block:: c++ + + /* + The universal representation for an IFC DeclForeignIndex. + */ + struct an_ifc_decl_foreign_index { + an_ifc_module* + mod; + /* The associated module. */ + an_ifc_decl_foreign_index_storage + value; + /* The raw bit value obtained from the module. + Represented as the largest common underlying + type. */ + }; /* an_ifc_decl_foreign_index */ + +This allows the index value to be imported into the current module in a +type safe way that can't be accidentally treated as a ``DeclIndex``. Thus, +interacting with the ``DeclReference`` you get something like: + +.. code-block:: c++ + + an_ifc_decl_reference decl_ref = ...; + + an_ifc_decl_foreign_index local_index = get_ifc_local_index(decl_ref); + process_ifc_decl(local_index); /* type error */ + +In terms of correct usage, foreign indexes are typically deserialized via an +associated :ref:`ifc-tacit-field` which reconstructs them as the appropriate +:ref:`ifc-index-sort-role` in the context of their respective module. + +As an example consider the DeclReference type: + +.. code-block:: text + + |-------------------------------------------------| + | DeclReference - 0.33 (12 bytes) | + |-------------|------------------|---------|------| + | Name | Type | Version | Size | + |-------------|------------------|---------|------| + | unit | ModuleReference | 0.33 | 8 | + | local_index | DeclForeignIndex | 0.33 | 4 | + |-------------|------------------|---------|------| + | index | DeclIndex | ANY | TF | + |-------------|------------------|---------|------| + +Using the tacit field ``index``, ``local_index`` can be retrieved in the +context of the associated ``unit`` (i.e., IFC module) transparently: + +.. code-block:: c++ + + an_ifc_decl_reference ref = ...; + an_ifc_decl_index idx = get_ifc_index(ref); + +.. _ifc-value-category-role: + +Value Category +-------------- + +Value categories are roughly equivalent to a variant type. The categories have +a :ref:`ifc-simple-sort-role` which describes which variant is valid. The +actual variants can be any role. + +This allows for handling of nested hierarchies like IFC Operators where an +``OperatorSort`` selects the interpretation of the variant value which may +be one of several different :ref:`Simple Sorts`. + +Versioning +========== + +.. _ifc-simple-sort-versioning: + +Simple Sort +----------- + +The :ref:`ifc-simple-sort-role` versioning system works by converting from a +"versioned sort" (i.e., enumeration) to a "universal sort" (i.e., enumeration). +Each IFC version gets its own unique, and appropriately sized enumeration, like +so: + +.. code-block:: c++ + + enum an_ifc_decl_sort_0_33 : uint32_t { + ifc_0_33_ds_decl_vendor_extension = 0, + ifc_0_33_ds_decl_enumerator = 1, + ifc_0_33_ds_decl_variable = 2, + ifc_0_33_ds_decl_parameter = 3, + ifc_0_33_ds_decl_field = 4, + ifc_0_33_ds_decl_bitfield = 5, + ifc_0_33_ds_decl_scope = 6, + ifc_0_33_ds_decl_enumeration = 7, + /* snip */ + }; /* an_ifc_decl_sort_0_33 */ + + enum an_ifc_decl_sort_0_41 : uint32_t { + ifc_0_41_ds_decl_vendor_extension = 0, + ifc_0_41_ds_decl_enumerator = 1, + ifc_0_41_ds_decl_variable = 2, + ifc_0_41_ds_decl_parameter = 3, + ifc_0_41_ds_decl_field = 4, + ifc_0_41_ds_decl_bitfield = 5, + ifc_0_41_ds_decl_scope = 6, + ifc_0_41_ds_decl_enumeration = 7, + /* snip */ + }; /* an_ifc_decl_sort_0_41 */ + +Note that these versioned enumerators do not follow the typical naming +convention. This is done to reduce the amount of possible completions editor +auto complete has for ``ifc_ds_`` (and similar). + +The universal sort representation by contrast takes all of the unique names, +from all the versioned sorts, and puts them in one enumeration: + +.. code-block:: c++ + + enum an_ifc_decl_sort : uint32_t { + ifc_ds_decl_alias, + ifc_ds_decl_barren, + ifc_ds_decl_bitfield, + ifc_ds_decl_concept, + ifc_ds_decl_constructor, + ifc_ds_decl_deduction_guide, + ifc_ds_decl_destructor, + ifc_ds_decl_enumeration, + ifc_ds_decl_enumerator, + ifc_ds_decl_expansion, + ifc_ds_decl_explicit_instantiation, + ifc_ds_decl_explicit_specialization, + ifc_ds_decl_field, + /* snip */ + }; /* an_ifc_decl_sort */ + +This enumeration is sorted alphabetically to make things easier to find and to +prevent the list from being "shuffled" when new IFC versions are adopted. + +Functions are then added to convert between the versioned sort (read from the +module file) to the universal sort, they look something like this: + +.. code-block:: c++ + + inline an_ifc_decl_sort to_universal_sort(an_ifc_decl_sort_0_33 versioned) + /* + Given the versioned representation of DeclSort, return the corresponding + universal representation. + */ + { + an_ifc_decl_sort result; + + switch (versioned) { + case ifc_0_33_ds_decl_vendor_extension: + result = ifc_ds_decl_vendor_extension; + break; + case ifc_0_33_ds_decl_enumerator: + result = ifc_ds_decl_enumerator; + break; + case ifc_0_33_ds_decl_variable: + result = ifc_ds_decl_variable; + break; + /* snip */ + +This allows for stability in all of our logic despite a number of possible +changes to the sort for a particular version (e.g., numbering changes, removal, +and addition). Effectively, sorts become unique on name rather than unique on +value. + +.. _ifc-index-sort-versioning: + +Index Sort +---------- + +As an :ref:`ifc-index-sort-role` is composed of a :ref:`ifc-simple-sort-role` +and an index value, its versioning relies upon the versioning of the associated +:ref:`ifc-simple-sort-role` (see :ref:`ifc-simple-sort-versioning`). + +.. _ifc-bitfield-versioning: + +Bitfield +-------- + +:ref:`ifc-bitfield-role` versioning works very similarly to +:ref:`ifc-simple-sort-versioning`. + +There's similarly a versioned bitfield enum for each version, of appropriate +size, using the values that are correct for that version: + +.. code-block:: c++ + + enum an_ifc_basic_specifiers_bitfield_0_33 : uint8_t { + ifc_0_33_bsb_cxx = 0, + ifc_0_33_bsb_c = 1 << 0, + ifc_0_33_bsb_internal = 1 << 1, + ifc_0_33_bsb_vague = 1 << 2, + ifc_0_33_bsb_external = 1 << 3, + ifc_0_33_bsb_deprecated = 1 << 4, + ifc_0_33_bsb_initialized_in_class = 1 << 5, + ifc_0_33_bsb_non_exported = 1 << 6, + ifc_0_33_bsb_is_member_of_global_module = 1 << 7 + }; /* an_ifc_basic_specifiers_bitfield_0_33 */ + +Unlike sorts, it's not super practical to try and normalize the representation +itself, so instead the value is captured with a module reference. + +.. code-block:: c++ + + /* + The universal representation for an IFC BasicSpecifiersBitfield. + */ + struct an_ifc_basic_specifiers_bitfield { + an_ifc_module* + mod; + /* The associated module. */ + an_ifc_basic_specifiers_bitfield_storage + value; + /* The raw bit value obtained from the module. + Represented as the largest common underlying + type. */ + }; /* an_ifc_basic_specifiers_bitfield */ + +This is then paired with a universal query enum (similar to the universal sort) +that gives a unique bit value to each possible bitfield and a ``test_bitmask`` +function. + +.. code-block:: c++ + + enum an_ifc_basic_specifiers_bitfield_query : uint32_t { + ifc_bsb_c = 1 << 0, + ifc_bsb_cxx = 1 << 1, + ifc_bsb_deprecated = 1 << 2, + ifc_bsb_external = 1 << 3, + ifc_bsb_initialized_in_class = 1 << 4, + ifc_bsb_internal = 1 << 5, + ifc_bsb_is_member_of_global_module = 1 << 6, + ifc_bsb_non_exported = 1 << 7, + ifc_bsb_vague = 1 << 8 + }; /* an_ifc_basic_specifiers_bitfield_query */ + + + template + inline a_boolean test_bitmask( + const an_ifc_basic_specifiers_bitfield &universal) + /* + Given the universal representation of BasicSpecifiersBitfield, return TRUE + if the universal bitmask specified by a_Query matches; otherwise, return + FALSE. + */ + { + a_boolean result; + + uint8_t mask = to_bitmask_0_33(a_Query); + uint8_t test_value = universal.value & mask; + + result = test_value == mask; + return result; + } /* test_bitmask */ + +At a high level, these functions generate per-version branches. Each of these +branches calls a function that converts the universal query, into a version +specific query (i.e., bitmask) for respective version (in this case there's +only one version of the bitfield, so there are no branches, just a call to +``to_bitmask_0_33``). These bitmask conversion functions look something like +the following: + +.. code-block:: c++ + + uint8_t to_bitmask_0_33(an_ifc_basic_specifiers_bitfield_query query) + /* + Given the universal representation of a BasicSpecifiersBitfield bitmask, + return the corresponding IFC version 0.33 representation of the bitmask. + */ + { + uint8_t result = 0; + + if (query & ifc_bsb_cxx) { + result |= ifc_bsb_0_33_cxx; + } /* if */ + if (query & ifc_bsb_c) { + result |= ifc_bsb_0_33_c; + } /* if */ + /* snip */ + +The versioned specific bitmask is then tested against the version specific +value, returning the result. + +This approach allows the front end to test "the same" bitmasks in a version +agnostic way, with a very small runtime performance overhead. + +Bitwidth Limitations +^^^^^^^^^^^^^^^^^^^^ + +As bitfield versioning relies upon native integer types, there are limitations +imposed, namely there are a limited number of expressible bitfield queries +across all versions of the IFC. + +If this becomes a problem in the future, two approaches are noted as promising. + +The first (and simplest) being, the removal of the ability to create a bitmask +by joining two queries (bit-or) in favor of two (effectively bit-and) +tests. This would allow a much larger number of bitfield queries to be +represented as the bitfield query would no longer require its own bit position. + +The second option being, the usage of a "big integer" type with overloaded +operators in place of a native integer type. As the translation process is +realistically performed at compile time (either via language level guarantees +if the front end moves to C++14 and these functions are made constexpr, or via +the optimizer), while this approach may on the surface seem more expensive, at +runtime it would *likely* be more efficient than the former. + +If this problem is encountered, existing usage will guide the resolution (the +formation and usage of bit-or joined queries has thus far been limited, and may +not be useful long term). + +Raw Values +---------- + +:ref:`ifc-raw-numeric-role` and :ref:`ifc-raw-bytes-role` values effectively +aren't versioned. As raw values have no semantic meaning at the format level, +there's "nothing to be done." + +.. _ifc-node-versioning: + +Nodes +----- + +:ref:`Node` versioning relies upon a number of "field +accessors" (i.e., ``get_ifc_``\ *X*) that read from the underlying byte +representation (abstracted by :ref:`ifc-byte-buffers`). These accessors +additionally, abstract away the exact location and representation of various +field values within the node, allowing for complex changes to the node +representation to be "normalized." + +These accessor functions look something like the following: + +.. code-block:: c++ + + template<> + an_ifc_decl_index get_ifc_decl( + const an_ifc_parameterized_entity &universal) + /* + Given the universal representation of ParameterizedEntity, return the + universal representation of the field "decl". + */ + { + an_ifc_decl_index result; + + /* Ensure the decl field exists in the current module version. */ + check_assertion(has_ifc_decl(universal)); + if (is_at_least(universal.get_module(), 0, 41)) { + /* version specific logic */ + } else { + /* version specific logic */ + } /* if */ + return result; + } /* get_ifc_decl */ + +For every version where the retrieval logic is different, we end up with a +separate branch gated on the lower bound of the version range. Newer values are +always checked first, as it's presumed newer IFC versions will be the common +case. + +.. _ifc-node-stages: + +Stages +^^^^^^ + +The exact logic in a given branch used to read a field value, is represented in +the generator as a sequence of "stages." These stages are setup via a "stage +builder" for the specific IFC node version. The stage builder allocates a +result variable for every stage (and can also allocate some additional +variables with extra name information if necessary). + +In most cases the stages and the associated logic are fairly trivial. As an +example, consider: + +.. code-block:: c++ + + an_ifc_decl_index_0_41 stage_0; + an_ifc_decl_index stage_1; + + /* Copy the field (ParameterizedEntity::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/0); + stage_1 = to_universal_index(universal.get_module(), stage_0); + result = stage_1; + +Here the raw value is copied (via ``copy_ifc_field``) from an offset into a +version specific variable (stage 0). Then, said version specific variable is +converted (via ``to_universal_index``) into a universal representation (stage +1). Finally, the resulting value is assigned to the ``result`` return +variable. + +This is a trivial case of data retrieval where the data is directly stored as +part of the node, and only needs converted to a universal representation. For +more information about this process, and additional similar cases, see +:ref:`ifc-field-deserialization`. + +Additionally, it's important to note that in some cases, more complicated +processing is similarly implemented via stages (for a variety of reasons). For +more information on this process, and advanced uses of the stage builder, see +:ref:`ifc-tacit-field`. + +.. _ifc-field-presence-checking: + +Field Presence Checking +^^^^^^^^^^^^^^^^^^^^^^^ + +The presence of an accessor sometimes depends on the IFC version. In +contexts where this is not obvious ``has_ifc_``\ *X* functions can be used to +check to see if the associated ``get_ifc_``\ *X* is valid. These are fairly +simple calls that return TRUE when field *X* is relevant to the node for +the corresponding IFC version, and FALSE otherwise. + +Foreign Index +------------- + +:ref:`Foreign Indexes`, despite conceptually being an +:ref:`ifc-index-sort-role` are versioned more like :ref:`Raw +Numerics`. This is done as foreign indexes have an +associated module which contains its own revision information. Thus, using the +current (referencing) module's version information to convert the raw value to +a universal understanding would be unreliable at best. + +Value Category +-------------- + +:ref:`Value Categories` rely upon the fact that the +types they're composed of are themselves versioned. Thus, while value +categories are versioned, they do not have any versioning rules specific to +them. + +.. _ifc-deserialization: + +Deserialization +=============== + +IFC deserialization is notable for intricacies introduced by supporting +optional memory mapped IFC reading and support for big-endian and little-endian +byte orders. + +.. _ifc-byte-buffers: + +Byte Buffers +------------ + +The ``an_ifc_Byte_buffer`` class template is the class that's fundamentally +responsible for abstracting away the location of the in memory representation +of a given byte sequences taken from the IFC file. + +The most notable use the byte buffer abstraction being for the representation +of :ref:`ifc-node-roles` but some other IFC roles, such as +:ref:`ifc-raw-bytes-role`, also make use of byte buffers. + +The byte buffer fulfills its duty of abstracting away the memory location for a +given byte sequence via a union. Said union contains either the bytes required +for storage, or a storage_ptr; this determination is made during construction +of the respective byte buffer. + +.. _ifc-endianness: + +Endianness Agnostic Reading +--------------------------- + +Endianness agnostic reading requires considerations for cases that are +and aren't memory mapped. + +Without Memory Mapping +---------------------- + +When memory mapping isn't enabled, the front end resorts to calls to +``get_bytes`` for each field in each node. + +Each call copies the appropriate number of bytes for the field into a +:ref:`Byte Buffer`, reversing the byte order for the bytes +stored in the field if the host and IFC endianness do not match. + +For nodes that contain nested (i.e., :ref:`ifc-basic-node-role`) node +structures, the internal node's fields are copied individually rather than +copying the entire internal node as "one field." + +With Memory Mapping +------------------- + +When memory mapping is enabled, if there is an endianness mismatch, the +non-memory mapped approach described above is used. + +Otherwise, the front end will use only a pointer to the start of the node +(within the broader memory mapped memory region). This pointer is then stored +and dereferenced when retrieving data in place of copying bytes into the +:ref:`Byte Buffer`. + +There is also support for a-typical cases where the front end, even when +operating with memory mapping and matching endianness, explicitly requests an +explicit copy of the data. In practice, this isn't currently used by the front +end and may be removed in the future. + +.. _ifc-field-deserialization: + +Field Deserialization +--------------------- + +Fields are deserialized from the associated :ref:`Byte +Buffer` for the corresponding node. This process makes use +of one of two ``copy_ifc_field`` field functions, and in some cases an adjusted +:ref:`Byte Buffer` pointer instead of a copy. + +Implicit Bounds Copying +----------------------- + +Copying with implicit bounds occurs when the destination object type is exactly +equivalent size. These copies additionally include a static assert as a +functional "sanity check" to ensure the code generation tool is right about the +size of the destination object (not just in theory, but in practice). + +.. code-block:: c++ + + an_ifc_keyword_sort_0_33 stage_0; + an_ifc_keyword_sort stage_1; + + /* Copy the field (KeywordSyntax::value - KeywordSort) into version-specific + storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/8); + + +Explicit Bounds Copying +----------------------- + +Copying with explicit bounds occurs when the destination object type is a +buffer of at least equivalent size. + +.. code-block:: c++ + + enum an_ifc_source_location_part : uint8_t {}; + using an_ifc_source_location_storage = an_ifc_source_location_part[8]; + #if USE_MMAP_FOR_MODULES + using an_ifc_source_location_bytes = const an_ifc_source_location_storage*; + #else /* !USE_MMAP_FOR_MODULES */ + using an_ifc_source_location_bytes = an_ifc_source_location_storage; + #endif /* USE_MMAP_FOR_MODULES */ + + an_ifc_source_location_bytes stage_0; + + /* Copy the field (KeywordSyntax::locus - SourceLocation) into universal + storage. */ + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/0, + /*size=*/8); + +Byte Buffer Adjustment +---------------------- + +:ref:`ifc-byte-buffers` are adjusted in place of a copy when the front end is +operating in memory mapped mode, and the resulting value is a byte buffer based +type. This process allows the front end to avoid unnecessary copies in memory +mapped modes when working with subobjects. + +.. code-block:: c++ + + enum an_ifc_source_location_part : uint8_t {}; + using an_ifc_source_location_storage = an_ifc_source_location_part[8]; + using an_ifc_source_location_bytes = const an_ifc_source_location_storage*; + + an_ifc_source_location_bytes stage_0; + + /* Update the universal storage pointer to the start of the field + (KeywordSyntax::locus - SourceLocation). */ + stage_0 = (an_ifc_source_location_bytes)((*universal.get_storage()) + 0); + +This optimization is only performed when memory mapped mode is available as +otherwise it creates an unsafe implicit dependence. In said case, the value +retrieved from a node via a field accessor depends on the lifetime of the +owning node's storage. In other words, without memory mapping, it's possible +for the memory that owns the subobject to go out of scope. + +.. _field-copying: + +Field Copying +------------- + +The respective implementation of both overloads of ``copy_ifc_field`` perform a +``memcpy`` operation; this is an intentional choice over casting and +dereferencing the pointer. + +This decision is also closely related to the usage of :ref:`ifc-byte-buffers` +over dedicated structs representing each version (which have debugging benefits +over the chosen approach). + +In the case of both decisions, the driving force behind this choice is +alignment. In the former case attempting to dereference an misaligned pointer +is undefined behavior. Thus, attempting to "avoiding the copy" via a +``reinterpret_cast`` paired with a deference could lead to severe portability +issues, and -- ironically -- degraded performance. However, the ``memcpy`` +operation can be safely optimized and used, even for unaligned inputs. Thus, +the approach of usage a ``memcpy`` to copy data into known fixed size types +gives maximum performance without the associated portability concerns. + +In the case of the latter decision specifically, the individual data members +within a struct will be padded differently on different host compilers, +operating systems, and different architectures (to comply with alignment +requirements). Thus, attempting to "overlay" a struct onto the underlying IFC +byte representation, results in similar severe portability issues. + +.. _ifc-tacit-field: + +Tacit Field +----------- + +A "tacit field" is a field that isn't actually part of the official field list +for a node. Tacit fields are regularly used to expose information that's +(indirectly) always present. For instance, a node might have no "home_scope" +field but the home scope can always be resolved via a different field. + +As an example, consider the following made up node "``FooDef``" (which for +the sake of the hypothetical, pairs a declaration with a syntactic +definition): + ++-----------------+----------------------+ +| Field | Type | ++=================+======================+ +| ``declaration`` | ``DeclIndex`` | ++-----------------+----------------------+ +| ``definition`` | ``SyntaxIndex`` | ++-----------------+----------------------+ + +Continuing with the hypothetical, in practice for "``FooDef``" nodes the +``DeclIndex`` for declaration, when valid, *always* points to a node that has a +``home_scope`` field. A tacit field exposes this invariant explicitly. From +the front end's perspective, adding a tacit field for ``home_scope`` is +"as-if" the binary representation defined "``FooDef``" to be: + ++-----------------+----------------------+ +| Field | Type | ++=================+======================+ +| ``declaration`` | ``DeclIndex`` | ++-----------------+----------------------+ +| ``definition`` | ``SyntaxIndex`` | ++-----------------+----------------------+ +| ``home_scope`` | ``DeclIndex`` | ++-----------------+----------------------+ + +This also exposes this invariant to the validator, which will then make sure +declaration points to a node with a ``home_scope`` field containing a valid +``DeclIndex``. + +Not all tacit fields perform this sort of "proxy retrieval" operation, +effectively *any* invariant can be exposed and validated in this way. + +Impact on Versioning +^^^^^^^^^^^^^^^^^^^^ + +This conceptual breadth of functionality allows tacit fields play a large +role in supporting different IFC versions as well. Consider a later +revision of "``FooDef``" changes ``declaration`` so that the ``DeclIndex`` +sometimes points to a new intermediary node "``FooProxyDecl``", which then +itself always points to a third node that has a ``home_scope``. + +Tacit fields allow this change to be "invisible" to existing logic. The +existing ``home_scope`` tacit field can be updated to follow the new rules +and properly retrieve the ``home_scope`` as one might expect. However, +tacit fields can also "replace" (or "override") a field that's explicitly +part of the binary node representation (i.e., "explicitly declared") if +they share the same name. + +In the context of this example, existing code might break -- badly -- when +it encounters the new intermediary "``FooProxyDecl``" node after a call to +the field accessor ``get_ifc_declaration(const an_ifc_foo_decl&)``. A new +``declaration`` tacit field can be added that automatically "sees through" +the wrapper, "as-if" it was never added. The existing logic then goes back +to functioning as it did before, as from its perspective nothing changed. + +Code that then needs to observe the new "``FooProxyDecl``" can then be +accounted for by adding additional tacit fields that either expose the +"true" value of ``declaration`` or information from "``FooProxyDecl``." + +The exact approach taken is situational, however, tacit fields are a powerful +tool for resolving versioning issues. + +Tacit Field Implementation +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As noted in :ref:`ifc-node-versioning`, field accessors work via "stages" +constructed from a "stage builder" in the code generation tool. + +These can get *exceptionally* complicated in terms of implemented +code. Consider the following real example, taken verbatim from the front end: + +.. code-block:: c++ + + template<> + an_ifc_decl_index get_ifc_home_scope( + const an_ifc_decl_enumerator &universal) + /* + Given the universal representation of DeclEnumerator, return the universal + representation of the field "home_scope". + */ + { + an_ifc_decl_index result; + + /* Ensure the home_scope field exists in the current module version. */ + check_assertion(has_ifc_home_scope(universal)); + if (is_at_least(universal.get_module(), 0, 41)) { + an_ifc_type_index_0_33 stage_0; + an_ifc_type_index stage_1; + an_ifc_type_designated stage_2; + an_ifc_decl_index_0_41 stage_3; + an_ifc_decl_index stage_4; + a_boolean stage_5; + an_ifc_decl_index stage_6; + + /* Copy the field (DeclEnumerator::type - TypeIndex) into + version-specific storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12); + stage_1 = to_universal_index(universal.get_module(), stage_0); + /* Use the obtained index to retrieve the appropriate instance of + TypeDesignated (the type tag should have been prechecked by + validation). Then, retrieve and return the desired value held by + the field decl. */ + construct_node_unchecked(&stage_2, stage_1); + /* Copy the field (TypeDesignated::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_3) == 4, + "stage_3 is not properly sized storage!"); + copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0); + stage_4 = to_universal_index(stage_2.get_module(), stage_3); + if (stage_4.sort == ifc_ds_decl_specialization) { + stage_5 = TRUE; + } else { + stage_5 = FALSE; + } /* if */ + if (stage_5) { + an_ifc_decl_index stage_6_0; + an_ifc_decl_specialization stage_6_1; + an_ifc_decl_index_0_41 stage_6_2; + an_ifc_decl_index stage_6_3; + + stage_6_0 = stage_4; + /* Use the obtained index to retrieve the appropriate instance of + DeclSpecialization (the type tag should have been prechecked by + validation). Then, retrieve and return the desired value held by + the field decl. */ + construct_node_unchecked(&stage_6_1, stage_6_0); + /* Copy the field (DeclSpecialization::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_6_2) == 4, + "stage_6_2 is not properly sized storage!"); + copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4); + stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2); + stage_6 = stage_6_3; + } else { + an_ifc_decl_index stage_6_0; + + stage_6_0 = stage_4; + stage_6 = stage_6_0; + } /* if */ + result = stage_6; + } else { + an_ifc_type_index_0_33 stage_0; + an_ifc_type_index stage_1; + an_ifc_type_designated stage_2; + an_ifc_decl_index_0_33 stage_3; + an_ifc_decl_index stage_4; + + /* Copy the field (DeclEnumerator::type - TypeIndex) into + version-specific storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12); + stage_1 = to_universal_index(universal.get_module(), stage_0); + /* Use the obtained index to retrieve the appropriate instance of + TypeDesignated (the type tag should have been prechecked by + validation). Then, retrieve and return the desired value held by + the field decl. */ + construct_node_unchecked(&stage_2, stage_1); + /* Copy the field (TypeDesignated::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_3) == 4, + "stage_3 is not properly sized storage!"); + copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0); + stage_4 = to_universal_index(stage_2.get_module(), stage_3); + result = stage_4; + } /* if */ + return result; + } /* get_ifc_home_scope */ + +Stage Breakdown +~~~~~~~~~~~~~~~ + +This is an intimidating amount of logic, however it's composed of bite sized +pieces of principled logic coming together. At a high level, there are two +cases here, one for IFC version 0.41+ and one for earlier supported versions of +the IFC. + +Consider the " earlier " code (i.e., the code for supporting IFC versions +prior to 0.41, which will be known from this point as the 0.33+ code): + +.. code-block:: c++ + + an_ifc_type_index_0_33 stage_0; + an_ifc_type_index stage_1; + an_ifc_type_designated stage_2; + an_ifc_decl_index_0_33 stage_3; + an_ifc_decl_index stage_4; + + /* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific + storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12); + stage_1 = to_universal_index(universal.get_module(), stage_0); + /* Use the obtained index to retrieve the appropriate instance of + TypeDesignated (the type tag should have been prechecked by validation). + Then, retrieve and return the desired value held by the field decl. */ + construct_node_unchecked(&stage_2, stage_1); + /* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific + storage. */ + static_assert(sizeof(stage_3) == 4, + "stage_3 is not properly sized storage!"); + copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0); + stage_4 = to_universal_index(stage_2.get_module(), stage_3); + result = stage_4; + +The code generation tool represents this as in effect, a directly constructed +expression AST, simplifying a bit: + +.. code-block:: python + + IFCRemoteDelegate( + IFCDirectDelegate('type'), + 'Type', + 'TypeDesignated', + 'decl' + ) + +This is conceptually an "expression" representing the retrieval of the +value. The innermost operation ``IFCDirectDelegate`` is thus the first to be +evaluated. + +While fully documenting the tacit field system within the code generation tool +is out of scope, for purposes of understanding, an ``IFCDirectDelegate`` simply +means "read the type field" from the node. + +Similarly, ``IFCRemoteDelegate`` simply means "take the input value (the +type field value), it's a ``Type(Index)`` that must point to a +``TypeDesignated`` node, read said node's ``decl`` field." + +The "stage builder" takes this expression and transforms it into a series of +"stages." + +Stage 0 +""""""" + +Read the versioned value of the type field: + +.. code-block:: c++ + + an_ifc_type_index_0_33 stage_0; + + /* snip */ + /* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific + storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12); + +Stage 1 +""""""" + +Turn the versioned type field value into a universal value: + +.. code-block:: c++ + + an_ifc_type_index_0_33 stage_0; + an_ifc_type_index stage_1; + + /* snip */ + stage_1 = to_universal_index(universal.get_module(), stage_0); + +Stage 2 +""""""" + +Load the ``TypeDesignated`` node: + +.. code-block:: c++ + + an_ifc_type_index stage_1; + an_ifc_type_designated stage_2; + + /* Use the obtained index to retrieve the appropriate instance of + TypeDesignated (the type tag should have been prechecked by validation). + Then, retrieve and return the desired value held by the field decl. */ + construct_node_unchecked(&stage_2, stage_1); + + +Stage 3 +""""""" + +Read the versioned value of the ``decl`` field from the ``TypeDesignated`` +node: + +.. code-block:: c++ + + an_ifc_type_designated stage_2; + an_ifc_decl_index_0_33 stage_3; + + /* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific + storage. */ + static_assert(sizeof(stage_3) == 4, + "stage_3 is not properly sized storage!"); + copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0); + +Stage 4 +""""""" + +Turn the versioned ``decl`` field value into a universal value: + +.. code-block:: c++ + + an_ifc_decl_index_0_33 stage_3; + an_ifc_decl_index stage_4; + + stage_4 = to_universal_index(stage_2.get_module(), stage_3); + result = stage_4; + +Stage 5 (Wrap-up) +""""""""""""""""" + +Assign the result: + +.. code-block:: c++ + + an_ifc_decl_index stage_4; + + result = stage_4; + +The stage builder facilitates the creation of these stages from the expression, +creating a metaphorical "data retrieval pipeline." The usage of expression +nodes and this system of generating C++ stages from these nodes, allows tacit +fields to be quickly written via reusable building blocks. + +Examination of the validation logic will reveal it's very similar to the logic +generated for field data retrieval, however rather than returning a result, it +performs a number of checks to make sure the would-be result and everything +required in-between is validated as necessary. + +Advanced Stage Breakdown +~~~~~~~~~~~~~~~~~~~~~~~~ + +After establishing an understanding of the flow of the 0.33+ code, consider the +0.41+ code: + +.. code-block:: c++ + + an_ifc_type_index_0_33 stage_0; + an_ifc_type_index stage_1; + an_ifc_type_designated stage_2; + an_ifc_decl_index_0_41 stage_3; + an_ifc_decl_index stage_4; + a_boolean stage_5; + an_ifc_decl_index stage_6; + + /* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific + storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12); + stage_1 = to_universal_index(universal.get_module(), stage_0); + /* Use the obtained index to retrieve the appropriate instance of + TypeDesignated (the type tag should have been prechecked by validation). + Then, retrieve and return the desired value held by the field decl. */ + construct_node_unchecked(&stage_2, stage_1); + /* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific + storage. */ + static_assert(sizeof(stage_3) == 4, + "stage_3 is not properly sized storage!"); + copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0); + stage_4 = to_universal_index(stage_2.get_module(), stage_3); + if (stage_4.sort == ifc_ds_decl_specialization) { + stage_5 = TRUE; + } else { + stage_5 = FALSE; + } /* if */ + if (stage_5) { + an_ifc_decl_index stage_6_0; + an_ifc_decl_specialization stage_6_1; + an_ifc_decl_index_0_41 stage_6_2; + an_ifc_decl_index stage_6_3; + + stage_6_0 = stage_4; + /* Use the obtained index to retrieve the appropriate instance of + DeclSpecialization (the type tag should have been prechecked by + validation). Then, retrieve and return the desired value held by the + field decl. */ + construct_node_unchecked(&stage_6_1, stage_6_0); + /* Copy the field (DeclSpecialization::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_6_2) == 4, + "stage_6_2 is not properly sized storage!"); + copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4); + stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2); + stage_6 = stage_6_3; + } else { + an_ifc_decl_index stage_6_0; + + stage_6_0 = stage_4; + stage_6 = stage_6_0; + } /* if */ + result = stage_6; + +Here stages 0 through 4 are identical to the 0.33+ code, however additional +stages have been added (i.e., the "pipeline" has been extended). Stage 6 is +particularly interesting as it works with substages. + +To understand what's going on here, consider the following simplified code from +the code generation tool: + +.. code-block:: python + + existing_logic = IFCRemoteDelegate( + IFCDirectDelegate('type'), + 'Type', + 'TypeDesignated', + 'decl' + ) + source_value = IFCReusableResult(existing_logic) + + IFCConditionalDelegate( + IFCTestSortMatch( + source_value, + 'Decl', + {'DeclSpecialization'} + ), + 'DeclIndex', + IFCRemoteDelegate( + source_value, + 'Decl', + 'DeclSpecialization', + 'decl' + ), + source_value + ) + +The ``existing_logic``, the associated ``IFCRemoteDelegate``, and +``IFCDirectDelegate`` were already covered, so those won't be +revisited. However, ``IFCReusableResult``, ``IFCTestSortMatch``, and +``IFCConditionalDelegate`` are new. + +``IFCReusableResult`` can be thought of like a lazily-evaluated, "memoization +instruction." This allows reuse of the same value without reevaluation. + +``IFCTestSortMatch`` means "take the input value (the possibly memoized +``TypeDesignated decl`` field value), evaluate true if its ``Decl(Sort)`` +value is ``DeclSpecialization``; otherwise, evaluate false." + +``IFCConditionalDelegate`` means "compute a ``DeclIndex`` value one of two +ways, if the input value (the test sort match) evaluates as true use the +first sub-expression, otherwise use the second." + +``IFCConditionalDelegate``\ s are particularly notable as they allow logic +to have branched evaluation. When these branches are translated to C++ +code, these are implemented via substages (effectively stage builders that +inherent a prefix and their input from a parent stage builder's stage). + +Note how this all composes to allow the existing logic to be sanely extended. +Looking at what's new, stage 5 is where things diverge. + +Stage 5 +""""""" + +The resulting ``DeclIndex`` is check to see if its sort is a +``DeclSpecialization``, storing the result as a boolean value: + +.. code-block:: c++ + + an_ifc_decl_index stage_4; + a_boolean stage_5; + + if (stage_4.sort == ifc_ds_decl_specialization) { + stage_5 = TRUE; + } else { + stage_5 = FALSE; + } /* if */ + +Stage 6 (Wrap-up) +""""""""""""""""" + +The previous result of the ``DeclSpecialization`` sort test is used, forking to +evaluate one of two sub-expressions before the result is assigned: + +.. code-block:: c++ + + if (stage_5) { + /* substage content */ + } else { + /* substage content */ + } /* if */ + result = stage_6; + +The first sub-expression (when a ``DeclSpecialization`` is used) unwraps +the ``decl`` field value from the ``DeclSpecialization`` node, storing the +result in stage 6: + +.. code-block:: c++ + + an_ifc_decl_index stage_6_0; + an_ifc_decl_specialization stage_6_1; + an_ifc_decl_index_0_41 stage_6_2; + an_ifc_decl_index stage_6_3; + + stage_6_0 = stage_4; + /* Use the obtained index to retrieve the appropriate instance of + DeclSpecialization (the type tag should have been prechecked by + validation). Then, retrieve and return the desired value held by the + field decl. */ + construct_node_unchecked(&stage_6_1, stage_6_0); + /* Copy the field (DeclSpecialization::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_6_2) == 4, + "stage_6_2 is not properly sized storage!"); + copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4); + stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2); + stage_6 = stage_6_3; + +The second sub-expression (when a ``DeclSpecializtion`` is not used) passes +through the value as a no-op: + +.. code-block:: c++ + + an_ifc_decl_index stage_6_0; + + stage_6_0 = stage_4; + stage_6 = stage_6_0; + +Note that even though the second sub-expression ends up being generated as an +effective no-op case with no special processing of its own, a substage +(stage_6_0) is initialized. There is no special meaning to this, it's merely an +implementation detail that falls out from the semantics of the code generation +tool. This may be improved in future revisions, but it's largely a visual +defect that gets cleaned up during optimization. + +.. _validation: + +Validation +---------- + +The IFC validation system is designed to check all data read from the IFC file +while being "out of the way", performant, and extendable. + +Point of Validation +^^^^^^^^^^^^^^^^^^^ + +Data is validated upon construction of a node, namely within the +``construct_node`` function (via a call to the ``validate`` function +corresponding to the node). This validation covers all ``get_ifc_``\ *X* return +values (and in the case of :ref:`ifc-tacit-field`, any intermediate data). + +The validation system leverages the stage builder (for more information +about stages in general, see :ref:`ifc-node-stages`) system used to create +the ``get_ifc_``\ *X* functions themselves. The stage builder knows how to +create not only the typical "data retrieval pipeline", but one which +validates the intermediate steps, and the returned data. + +The extent of the validation depends on the role associated with the type +being validated. + +Simple Sort +~~~~~~~~~~~ + +:ref:`ifc-simple-sort-role` validation ensures that the input value corresponds +to a valid simple sort value for the current IFC version and simple sort type. + +Index Sort +~~~~~~~~~~ + +:ref:`ifc-index-sort-role` validation first checks the associated +:ref:`ifc-simple-sort-role` for validation issues, then ensures that the +requested element exists in the associated partition. This latter step can be +thought of as a sort of pointer validation, it doesn't ensure the validity of +the data being pointed to, but it does ensure the pointer itself is valid. + +Nodes +~~~~~ + +:ref:`ifc-node-roles` sometimes appear within other nodes (for more +information, see :ref:`ifc-basic-node-role`). In these cases, the validator +recurses into the sub-node and also ensures the validity of its fields. This +reduces the number of calls required to work with sub-nodes, and improves +diagnostics (by providing extra context to work with). + +Value Categories +~~~~~~~~~~~~~~~~ + +:ref:`ifc-value-category-role` validation similar to :ref:`ifc-index-sort-role` +validation first checks the associated :ref:`ifc-simple-sort-role` for +validation issues. The respective variant is then validated as necessary. + +Validation Cache +^^^^^^^^^^^^^^^^ + +The validation system is made more efficient by a bit-based caching mechanism. + +Each partition position in the IFC has its validation status represented as two +bits that are part of a 32-bit integer. The higher 16 bits are used to +represent an "invalid" flag while the lower 16 bits are used to represent a +"validated" flag. The choice to represent "invalid" status instead of "valid" +status is deliberate to minimize the number of writes to the validation cache +for a valid IFC file. + +These 32-bit integers are themselves part of an array that's allocated +per-partition representing all elements in the partition. The cache thus has +both high locality and high space efficiency. + +When a node is constructed via ``construct_node`` the validation cache is +checked, and if the node has already been validated, the cached validation +status will be reused rather than rerunning the ``validate`` function for the +node. + +The caching process also provides -- as an adverse affect -- a guarantee that +validation diagnostics are only emitted once. + +.. _skipping-validation: + +Skipping Validation +^^^^^^^^^^^^^^^^^^^ + +In general, data validation should not be skipped. However, in some cases it's +desirable to skip validation. + +Pre-checked Data +~~~~~~~~~~~~~~~~ + +``construct_node_prechecked`` can be useful as an optimization in places where +it's known -- with certainty -- that the node being constructed has previously +been validated. + +Note that when ``CHECKING`` is enabled this function will check the validation +cache to ensure that the node being constructed truly was previously validated. + +Unchecked Data +~~~~~~~~~~~~~~ + +``construct_node_unchecked`` can be used as part of low level implementation +details that can safely ignored validation status (or code that takes special +care to ensure safe usage). It's important to emphasize, this function truly +bypasses all checks, and thus can introduce unsafe data or crashes if used +improperly. + +An example of a time this function is useful is the ``find_trait`` +function. Traits are found via a binary search, attempting to validate the data +during the search would significantly degrade performance, and might lead to a +large number of unnecessary diagnostics about data that's never used. The usage +is made safe as after the search completes the final result (if any) is +validated. + +.. _ifc-reader-visitors: + +Visitors +-------- + +The visitor system is designed to allow the use of ``get_ifc_``\ *X* +functions on a given :ref:`ifc-index-sort-role` value. As an example, +consider the following: + +.. code-block:: c++ + + an_ifc_decl_index decl_idx = ...; + an_ifc_decl_index home_scope_idx = get_ifc_home_scope(decl_idx); + +This is not a field accessor as described in the :ref:`ifc-node-roles` section. +Instead, this function will load the appropriate node for the index, and then +delegate to that node's field accessor of the same name. It's thus in essence, +equivalent to writing: + +.. code-block:: c++ + + switch (decl_idx.sort) { + case ifc_ds_decl_function: + { an_ifc_decl_function universal; + + construct_node_prechecked(&universal, decl_idx); + home_scope_idx = get_ifc_home_scope(universal); + } + break; + } /* switch */ + +Note that this has some limitations, namely, the sort has to point to a node +that has the given field name for the current IFC version, and the node has to +have been previously validated. + +To accommodate these limitations additional visitors are exposed for the +corresponding ``has_ifc_``\ *X* function (for more information, see: +:ref:`ifc-field-presence-checking`) and for node validation. + +Thus, in most cases the correct usage looks something like the following: + +.. code-block:: c++ + + an_ifc_decl_index decl_idx = ...; + an_ifc_decl_index home_scope_idx; + + /* Check if a valid version of the node pointed to by this decl_idx would + ever have a valid home_scope */ + if (has_ifc_home_scope(decl_idx)) { + /* Make sure we're working with a valid node */ + if (validate(decl_idx)) { + /* Guaranteed retrieval of a valid home scope index. */ + home_scope_idx = get_ifc_home_scope(decl_idx); + } /* if */ + } /* if */ + +This is often just simplified to: + +.. code-block:: c++ + + an_ifc_decl_index decl_idx = ...; + an_ifc_decl_index home_scope_idx; + + if (has_ifc_home_scope(decl_idx) && validate(decl_idx)) { + home_scope_idx = get_ifc_home_scope(decl_idx); + } /* if */ + +Passthrough +^^^^^^^^^^^ + +In the case of certain nodes, a reasonable answer can be obtained, but is not +implicitly present. For these cases, an "implicit dereference" is added to the +code generation tool. These allow visitors to recurse using the "dereferenced" +value. + +As an example, consider the following: + +.. code-block:: python + + # Implicit dereferencing on the DeclIndex. + 'Decl': { + # Implicitly dereference DeclReference via the get_ifc_index function. + 'DeclReference': 'get_ifc_index' + } + +This is an implicit dereference on the Decl :ref:`ifc-index-sort-role`, that +applies the requested traversal to the result of a DeclReference's +``get_ifc_index`` field accessor. + +In generated code, this looks something like the following: + +.. code-block:: c++ + + case ifc_ds_decl_reference: + { an_ifc_decl_reference universal; + + construct_node_prechecked(&universal, idx); + + an_ifc_decl_index remote_idx = get_ifc_index(universal); + result = get_ifc_home_scope(remote_idx); + } + break; + +This notably also applies to the ``has_ifc_``\ *X* function: + +.. code-block:: c++ + + case ifc_ds_decl_reference: + { Opt opt_universal; + + construct_node(&opt_universal, idx); + if (opt_universal.has_value()) { + an_ifc_decl_index remote_idx = get_ifc_index(*opt_universal); + + if (has_ifc_home_scope(remote_idx)) { + result = TRUE; + } /* if */ + } /* if */ + } + break; + +Thus, in contrast to an :ref:`ifc-tacit-field`, a visitor is much more lenient +form of data retrieval, often used both in instances of "may-have" as opposed +to instances of "must-have." + +.. _visitor-implicit-conversion: + +Implicit Conversion +^^^^^^^^^^^^^^^^^^^ + +Some visitors are additionally configured with implicit conversions. These +conversions allow the visitor to return one return type while the underlying +``get_ifc_``\ *X* field accessors return different types. + +As an example, the IFC's ``TextOffset`` can be represented as a +NameIndex. Thus, to allow for one ``get_ifc_name`` visitor, a conversion is +added. + +Limited Scope +^^^^^^^^^^^^^ + +As most fields don't need exposed by visitors, generating every possible +visitor could get quite expensive (both for the code generation tool and for +build times). Thus, instead, the code generation tool requires desired visitors +to be explicitly listed. + +For instance, to define a simple visitor to expose the home_scope DeclIndex: + +.. code-block:: python + + # Add a visitor over the Decl index for get_ifc_home_scope returning + # an_ifc_decl_index with no conversions. + ( + 'Decl', + 'home_scope', + 'an_ifc_decl_index', + {} + ) + +In more advanced cases like the +:ref:`aforementioned` ``get_ifc_name`` visitor, +conversions are specified like so: + +.. code-block:: python + + # Add a visitor over the Decl index for get_ifc_name returning + # an_ifc_name_index with a potential conversion from a an_ifc_text_offset + # to an_ifc_name_index. + ( + 'Decl', + 'name', + 'an_ifc_name_index', + { + 'conversions': { + 'an_ifc_text_offset': IFCTextOffsetToNameIndex() + } + } + ) + +Partition Kinds +=============== + +The generation tool manages a list of partition kinds known to said tool (and +thus the front end). + +These partition kinds are exposed via the ``an_ifc_partition_kind`` enum with +an additional ``ifc_pk_none`` value written to represent invalid states. + +The total number of IFC partition kinds known to the front end (not including +``ifc_pk_none``) can be retrieved via the ``IFC_PARTITION_COUNT`` macro. + +A alphabetically sorted mapping of IFC partition kind names to +``an_ifc_partition_kind`` values (not including ``ifc_pk_none``) named +``ifc_partition_map`` is also maintained to enable binary search based mapping +between a given IFC partition kind name and the corresponding front end value +used for its representation. + +As this mapping is extensive (with the exception of ``ifc_pk_none``) +``ifc_partition_mapping[partition_kind - 1].name`` can be used to retrieve the +name of any ``an_ifc_partition_kind`` value in constant time. + +Additionally, the associated relationships between partition kinds and other +roles is also captured by several utility functions. + +``get_ifc_partition_kind`` +-------------------------- + +Some operations require knowing the partition kind associated with a given node +type. The ``get_ifc_partition_kind`` explicit template specializations +expose this information via template instantiation. + +``get_ifc_partition_element_size`` +---------------------------------- + +Some operations require knowing the expected element size for a given partition +at a given IFC version. The ``get_ifc_partition_element_size`` function +provides this functionality taking a module and partition kind and returning +the expected size. + +``has_partition_kind`` +---------------------- + +Some operations require knowing whether or not a given +:ref:`ifc-simple-sort-role` value has an associated partition kind. The +``has_partition_kind`` functions take a simple sort and return TRUE if the +sort has an associated partition kind, otherwise they return FALSE. + +``to/from_partition_kind`` +--------------------------- + +Some operations require a transition from an :ref:`Index +Sort's` :ref:`ifc-simple-sort-role` to a partition sort or +vice versa. + +The ``to_partition_kind`` functions take a :ref:`ifc-simple-sort-role` and +convert the sort to ``an_ifc_partition_kind``. + +Conversely, the ``to_X`` sort functions take ``an_ifc_partition_kind`` and +convert it to the desired :ref:`ifc-simple-sort-role`. + +Note that in both cases, any conversion failures will result in a crash. + +Debugging +========= + +Nodes +----- + +As noted in the :ref:`field-copying` subsection, to provide a portable +implementation of :ref:`IFC Deserialization`, sacrifices +were made that negatively impact the debugger experience of working with IFC +:ref:`ifc-node-roles`. + +To mitigate this issue, ``DEBUG`` builds of the front end include ``db_node`` +functions which can be invoked to get a pretty-printed summary of the node's +contents from within the debugger. + +Consider the following: + +.. code-block:: c++ + + an_ifc_decl_alias foo = ...; + /* break point */ + +When debugging this code, the ``db_node(const an_ifc_decl_alias &universal)`` +function (in most cases invoked simply as ``db_node(foo)``) can be used to +print the node contents. + +This results in output similar to the following: + +.. code-block:: none + + =============================== DeclAlias ================================ + access: AccessSort::None + aliasee: + sort: TypeSort::TypePointer + value: 0 + home_scope: NULL + locus: + column: 22 + line: 2 + name: 189 + specifiers: + - C + - Cxx + - IsMemberOfGlobalModule + type: + sort: TypeSort::TypeFundamental + value: 0 + +Code Organization +================= + +This system generates a *lot* of code, as a result, to keep the front end build +times down code has been carefully organized and separated to prevent any one +translation unit from having an excessive impact on the build time. + +The code generated files currently include: + +* ``ifc_map.h`` - A forward declaration of all types so they can be used in + ``ifc_module.h`` without polluting ``ifc_module.h`` with a large number of + functions. +* ``ifc_map_functions.h`` - The forward declarations of functions imported in + files that need access to low level IFC reading operations. +* ``ifc_map_functions.c`` - The implementation of functions declared in + ``ifc_map_functions.h`` that do not have a more specific implementation file. +* ``ifc_map_functions_acc.c`` - The implementation of all IFC field accessor + functions. +* ``ifc_map_functions_dbg.c`` - The implementation of all IFC debug functions. +* ``ifc_map_functions_val.c`` - The implementation of all IFC validation + functions. +* ``ifc_modules_inst.h`` - A list of macros imported in ``ifc_modules_templ.c`` + to manage explicit template instantiations. +* ``ifc_modules_spec.h`` - A list of macros imported in ``ifc_modules_templ.c`` + to manage explicit template specializations. + +Note that :ref:`Visitor` implementations are currently +found in ``ifc_map_functions.c``. + +The portion of the front end that handles deserialization is primarily found in +``ifc_modules_read.c``. The portion of the front end that handles +serialization is primarily found in ``ifc_modules_write.c``. Code that is +common between the two is found in ``ifc_modules_internal.h`` and +``ifc_modules.c``. + +All supporting template definitions and instantiations (that used by a mix of +``ifc_modules.c``, ``ifc_modules_read.c``, `ifc_modules_write.c``, and the +``ifc_map_functions*.c`` files) are isolated to ``ifc_modules_templ.c``, +preventing multiple translation units from instantiating the same template. diff --git a/dev/doc/_sources/pragma.rst.txt b/dev/doc/_sources/pragma.rst.txt new file mode 100644 index 0000000..0633761 --- /dev/null +++ b/dev/doc/_sources/pragma.rst.txt @@ -0,0 +1,851 @@ +.. _pragmas-and-attributes: + +====================== +Pragmas and Attributes +====================== + +Support for the processing of ``#pragma`` directives appears in several files +(including ``preproc.c``, ``lexical.c``, and ``il.c``), but the principal +routines are in ``pragma.c``. ``pragma.h`` and ``il_def.h`` contain +definitions of the data structures that are used. + +Standard attributes, GNU attributes, and Microsoft ``__declspec`` attributes +are like pragmas in their semantic scope (i.e., a generic mechanism for small +language extensions), but unlike pragmas they fit in ordinary grammar-based +based front end processing. The principal routines for attribute processing +are in ``attribute.c`` (and ``attribute.h``); the main data structures are in +``il_def.h``. + +Introduction to Pragma Processing +================================= + +Pragma processing differs from other front end processing in several ways. +Pragmas are scanned as part of the inter-token processing of the lexical +routines, yet the actual interpretation of the pragmas must be performed at a +suitable point in the syntactic and semantic processing of the front end. In +fact tokens may need to be scanned far in advance of when they are actually +used, and so pragmas may be encountered at the lexical level when it is +impossible for them to be fully processed. This occurs in scanning the bodies +of template definitions, in doing the lookahead to disambiguate declarations +and expressions, and so forth. + +Moreover, it is clear that the "suitable point in syntactic and semantic +processing" where the pragma is interpreted will be different for different +pragmas. And some pragmas simply carry information for use by the back end and +do not affect front-end processing at all. Each pragma has special +requirements. + +Pragmas are also unusual because, by definition, they are specific to a given +implementation. The mechanism that the EDG front end provides is intended to +make it relatively easy for customers to add pragmas and to customize how they +are processed, from how they are tokenized to how IL pragma entries are +generated. The handful of pragmas that are supplied by default with the EDG +front end can serve as prototypes for such customization. + +A pivotal role in pragma processing is played by an entry of type +``a_pending_pragma``, a front-end-only repository of information about a +specific ``#pragma`` directive in the source. It is "pending" in that it is +awaiting interpretation, after which it is disposed of. Interpreting a pragma +may mean setting a flag in a symbol, causing a diagnostic to be suppressed, +creating an IL pragma entry to pass information on to the back end, and so +forth. + +Pragma processing can be summarized as consisting of three steps: + +#. The ``#pragma`` directive that appears in the source code is identified and + recorded in a pending pragma entry. Although most pragmas are simply + recorded for later interpretation, "preprocessing immediate" pragmas are + dispatched immediately upon being recognized by the preprocessing + routines. + +#. The pending pragma entry is "dispatched" -- i.e., made available for + additional processing by being placed on a list where it can be found + later. + +#. The pending pragma entry is interpreted, with its message transferred to + another form (e.g., a flag is set somewhere), and then it is disposed + of. + +Pragmas must be recognized to be processed, and once they have been recognized +much of the processing is table-driven. The key pieces of information about +every pragma are: + +* | The pragma kind -- an element of the enumeration ``a_pragma_kind`` (defined + in ``il_def.h``). Every pragma that is recognized corresponds to one + pragma kind. +* | The pragma-id -- the identifier string that follows the ``#pragma`` keyword + and that may be looked up in the array ``pragma_ids`` (defined in + ``il_def.h``) to determine the pragma kind. +* | The pragma kind description -- a data structure of type + ``a_pragma_kind_description`` (defined in ``pragma.h`` and available to the + front end only) that summarizes the attributes and processing requirements + of a given pragma. + +When the pragma has been recognized, much of the processing is governed by the +corresponding pragma kind description, which contains information such as how +(and whether) the pragma binds to an IL construct, whether the pragma is +intended to be processed by the front end or back end, and how tokens that +comprise the pragma should be passed from the point at which the pragma is +initially scanned to the point at which the pragma is semantically processed. +The pragma kind description also contains an optional processing function +pointer, which, if present, points to a function to be called to process this +kind of pragma. + +``pragma_description_for_pragma_kind`` is an array of pointers to pragma kind +descriptions that may be indexed by pragma kind. It is initialized in +``pragma_init`` by a series of calls to ``add_pragma_kind_description``. + +Phase One: Recording Pragmas +============================ + +Pragma directives are initially scanned by the routine ``proc_pragma``, which +is one of the preprocessing routines in ``preproc.c``. As mentioned earlier, +the initial scanning of the pragma may occur far too early for the pragma to be +processed in any meaningful way. The most extreme example of this is a +template definition containing a pragma that must be reevaluated for each +instantiation generated from the template. + +To accommodate this kind of use, the initial scanning of a pragma typically +consists simply of identifying the kind of pragma being scanned, and recording +the body of the pragma in a form in which it may easily be processed later. +Preprocessing immediate pragmas are the exception to this rule, and are +dispatched immediately upon being identified by the preprocessing routines. + +Pragmas are expected to have the form + + ``#pragma identifier`` *token1 token2 token3 ...* + +The pragma kind is determined by comparing the identifier with each the +elements of the array ``pragma_ids``. Once the pragma kind has been +determined, the associated pragma kind description determines how the body of +the pragma is to be recorded. The body may be recorded as either a token cache +or a character string. Most pragmas will be recorded as token caches since +this is usually the easiest representation for the front end to use later. +Pragmas that are to be reemitted by the C or C++ generating back end must be +recorded as character strings. + +When a pragma is recorded as a token cache, the pragma kind description +specifies how the lexical routines should tokenize the pragma body. +Specifically, it specifies whether macros should be expanded and whether the +recognition of certain preprocessing tokens (e.g., ``#`` and ``##``) should be +disabled. Typically both of these flags would be FALSE, but when scanning a +pragma containing what looks like a source language construct (as is the case +with the instantiation pragmas) these fields would be TRUE. + +If the configuration parameter ``INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL`` is TRUE, +any pragma identifier that is not recognized is processed using the pragma kind +description associated with the ``pk_unrecognized`` pragma kind. + +To record the pragma a pending pragma entry is allocated (see +``alloc_pending_pragma`` in ``pragma.c``), and the pragma representation (token +cache or text) is attached to it. A pragma is associated with a token that +immediately follows it in the source, so the newly created pending pragma entry +is appended to ``curr_token_pragmas``, a list of pending pragma entries that +are associated with the current token (see ``add_to_curr_token_pragma_list``). + +Since the current token may be cached, the list of pending pragma entries +associated with it is cacheable, too (see ``add_pragma_entry_to_cache`` in +``lexical.c``). When a token is cached, the pragmas associated with it are +recorded in the cache as well, and when the token is retrieved from the cache +the associated pragmas are restored as the ``current_token_pragmas`` list. If +the cache from which the token was retrieved is a reusable cache, a copy of the +pragma list is made (instead of using the original list). + +Pending pragma entries are also created to represent "pseudo pragmas", +constructs that are processed by the front end like pragmas even though they +are not actually represented in the source code by a pragma directive. Thus, +lint comments are implemented as pseudo pragmas; e.g., when a ``/*ARGSUSED*/`` +comment is encountered, the front end generates a ``pk_lint_argsused`` pragma +entry, and all subsequent processing is handled just like a pragma specified +using a ``#pragma`` directive. + +Phase Two: Dispatching Pragmas +============================== + +The result of the initial scanning process is ``curr_token_pragmas``, a list of +pending pragma entries that represent the pragmas immediately preceding the +current token. However, the pragma is not subject to further processing simply +as a consequence of being associated with the current token. For example, with + +.. code:: c++ + + #pragma xyz + int a; + +the ``xyz`` pragma is on the current token pragma list for ``int`` but is not +made available for additional processing until processing begins on the +construct that ``int`` introduces or else until the next token, ``a``, is about +to fetched. This convention is followed to avoid processing the pending pragma +entry prematurely -- we wouldn't want to process pragma ``xyz`` if there is a +chance token ``int`` will end up in a token cache. + +The pending pragma entries on the ``curr_token_pragmas`` list are dispatched +for additional processing either by ``select_curr_construct_pragmas`` or by +``process_curr_token_pragmas``. These routines do most of the middle phase +processing of pending pragma entries. How they differ and how they interact +can be explained in terms of pragma binding kinds. + +Each pragma kind specifies one of three pragma binding kinds [#f1]_; each +binding kind represents a different processing pathway; and each form of +processing implies a different form of dispatching. + +* | Pending pragma entries with a binding kind of ``pbk_immediate`` and + ``pbk_next_token`` are processed immediately at the point the current token + is consumed. Such pragmas may appear anywhere in the program, and though + they may be recorded in the IL, they are not bound to any particular IL + entity (the difference between ``pbk_immediate`` and ``pbk_next_token`` is + described below). +* | Pending pragma entries with a binding kind of ``pbk_next_construct`` are + subject to processing during the processing of the given statement or + declaration. They must appear immediately before the first token of the + construct to which they will be bound. If they appear in the IL, they will + be bound to a particular IL entity. +* | Pending pragma entries with a binding kind of ``pbk_other`` are not subject + to processing at any particular time -- that is up to the implementation. + They may appear anywhere in the source program. They are dispatched onto a + list to wait for a processing function to check for them; if they are not + explicitly handled and removed, they simply remain there until the scope + they belong to is terminated. + +Bound Pragmas +------------- + +``select_curr_construct_pragmas`` is called at the start of each new +declaration or statement. It is always called before advancing past the first +token of the construct; this is to ensure that it is called before +``process_curr_token_pragmas`` is called. Its principal job is go through the +``curr_token_pragmas`` list, removing each ``pbk_next_construct`` entry and +dispatching it to a list specifically reserved for pragmas bound to the current +construct, the ``curr_construct_pragmas`` list in the current scope stack +entry. The pragmas wait on the list to be processed sometime during the +processing of the current construct. + +The pending pragma entries associated with the current construct will remain on +the list to which they are dispatched only for the life of the declaration or +statement. If the current construct cannot be bound to (this is the case, for +example, with the declaration of an unnamed enumeration or a ``break`` +statement), ``cannot_bind_to_curr_construct`` is called to issue diagnostics, +if appropriate, and clear the list. If, usually as a result of an error, the +processing of the pending pragma entries cannot be completed, +``discard_curr_construct_pragmas`` is called to clear the list. + +Normally, therefore, when ``select_curr_construct_pragmas`` is called, the list +it updates will have been cleared, since entries on the list for the previous +construct will already have been disposed of by the time the current construct +is dealt with. An exception is when a pragma precedes a label: such a pragma +is construed as applying not to the label but to the construct following, so it +must be preserved on the ``curr_construct_pragmas`` list as processing advances +past the label. In such situations pending pragma entries may accumulate, +e.g., for this case + +.. code:: c++ + + #pragma some_pragma + l: + #pragma another_pragma + f(); + +both pragmas can end up bound to the call of function ``f``. + +Another job of ``select_curr_construct_pragmas``, when source sequence entries +are being generated, is to add a source sequence entry for each pending pragma +entry on the ``curr_token_pragmas`` list. If an IL entry is subsequently +created for the pragma, it uses the source sequence entry; otherwise, the +source sequence entry is returned to an available list. + +Unbound Pragmas +--------------- + +``process_curr_token_pragmas`` is called each time the current token is about +to be consumed and a new token is about to become the current token. Its job +is to handle pending pragma entries that remain on the ``curr_token_pragmas`` +list and then to clear that list before the next token is taken. + +If it finds a ``pbk_immediate`` or ``pbk_next_token`` pragma on the list, it +initiates the completion of its processing. There is no dispatching of these +pragmas. They are processed immediately and automatically. In non-cached +contexts, ``pbk_immediate`` pragmas will have already been procesed when +``process_curr_token_pragmas`` is called and will be ignored. + +``pbk_other`` pragmas are dispatched to a list of the pragmas that are +currently available for further processing in a given scope -- see +``pending_pragmas`` in ``a_scope_stack_entry``. The pending pragma entry is +placed on the list of the current scope and is discarded when the current scope +terminates. Such a pragma simply waits on the list until some event removes it +to complete its processing; there is no default mechanism to trigger such +processing automatically. + +Since ``select_curr_construct_pragmas`` will already have been called, there +should not be any ``pbk_next_construct`` entries remaining on the +``curr_token_pragmas`` list. If there are, they must have appeared in the +source somewhere other than immediately before a declaration or statement. +``process_curr_token_pragmas`` removes them from the list, optionally issuing a +diagnostic of the severity specified in the corresponding pragma kind +description. + +If source sequence entries are being generated, ``process_curr_token_pragmas`` +will also add source sequence entries for each pending pragma entry that needs +one. If an IL entry is subsequently created for the pragma, it uses that +source sequence entry; otherwise, the source sequence entry is returned to an +available list. + +Phase Three: Interpreting Pragmas +================================= + +The pragma representations that result from the scanning of pragmas are called +"pending pragmas" because, having been created as repositories of uninterpreted +information about a specific pragma directive, they wait around for the right +moment for their processing to be completed. The completion can be described +as the "interpretation" of the pragma -- its translation into another form so +that it will have the intended effect on subsequent compilation. + +The different pragma binding kinds indicate, as noted above, different +processing pathways: + +* | Pending pragma entries with a binding kind of ``pbk_next_token`` are + processed automatically by ``process_curr_token_pragmas``, at the point the + current token is consumed. +* | Pending pragma entries with a binding kind of ``pbk_immediate`` are + processed immediately after they have been scanned. In cached contexts + they are also processed by ``process_curr_token_pragmas`` (in the same way + as ``pbk_next_token`` pragmas) each time the cache is rescanned. +* | Pending pragma entries with a binding kind of ``pbk_next_construct`` are + subject to processing during the processing of the given statement or + declaration. Either they are processed as the result of an explicit action + involving a call to ``extract_specific_pragmas``, or else the processing is + initiated automatically when (at an appropriate point, depending on the + construct they are associated with) ``process_curr_construct_pragmas`` is + called. +* | Pending pragma entries with a binding kind of ``pbk_other`` are subject to + processing only as the result of an explicit action involving a call to + ``extract_specific_pragmas``; otherwise they simply remain on the + ``pending_pragmas`` list of the current scope stack entry and their + processing is never completed. + +``process_curr_construct_pragmas`` is the routine that initiates automatic +processing for the ``pbk_next_construct`` pragmas associated with a given +declaration or statement. It traverses the list of them on the current scope +stack entry, making sure that each pragma binds to the sort of construct +(statement or declaration) that is currently being processed; it (optionally) +issues a diagnostic otherwise. If ``automatically_include_in_il`` (in the +corresponding pragma kind description) is TRUE, it calls +``create_il_entry_for_pragma``. If ``next_construct_processing_function`` is +non-NULL, it calls it do any additional processing that is required. It also +returns all the pending pragma entries to the available list. + +If a pragma should be included in the IL, ``create_il_entry_for_pragma`` is +called; it calls ``add_pragma_to_il``, which in turn calls ``alloc_pragma`` to +create the entry of type ``a_pragma`` and ``add_to_pragmas_list`` to add it to +the end of the ``pragmas`` list of the proper scope. + +``create_il_entry_for_pragma`` is called automatically -- by +``process_curr_token_pragmas`` for ``pbk_immediate`` pragmas and by +``process_curr_construct_pragmas`` for ``pbk_next_construct`` pragmas -- when +the ``automatically_include_in_il`` flag is set. It is also called +automatically by ``extract_specific_pragmas`` when that flag is set. It can be +called directly from pragma-processing code when automatic creation of IL +entries is undesirable. + +The scope to which the IL pragma entry is attached is determined based on +several considerations. If a ``pbk_next_construct`` pragma is bound to a class +member, it belongs to the scope of the class; otherwise, if it is bound to an +IL entry allocated in the file-scope memory region, it belongs to the file +scope; otherwise, it belongs to the current (block or function) scope. A +``pbk_immediate``, ``pbk_next_token``, or ``pbk_other`` pragma belongs to the +file scope if the ``global`` flag in the corresponding pragma kind description +is TRUE; otherwise it belongs to the current scope. + +``pbk_next_construct`` pragmas that are added to the IL have a pointer to the +IL entry with which they are associated (a statement, a variable, etc.), but +the latter has no pointer back to the pragma. Instead, the +``has_associated_pragma`` flag (in ``a_source_correspondence`` and in +``a_statement``) is set, indicating that one or more pragmas is bound to it. +``find_assoc_pragma`` may be called to locate the pragma entry (or entries) +associated with a given IL entry. + +The automatic processing of pending pragma entries may also involve calling a +routine to do whatever special processing is required for the particular pragma +kind. The address of this routine, which must be declared with the appropriate +type (see ``a_next_construct_pragma_function``, +``an_immediate_pragma_function``, and ``an_other_pragma_function``) is recorded +in the pragma kind description. Here are some examples from pragmas supplied +by default by the EDG front end: + +* | ``instantiate_pragma`` is specified as the processing function for the + ``pbk_next_token`` pragma of kind ``pk_instantiate``; it is called by + ``process_curr_token_pragmas`` when such pending pragma entries are + encountered; no IL entry is required. +* | ``record_arg_pragma`` is the processing function for pragmas of kind + ``pk_printf_args`` and ``pk_scanf_args``; it is called from + ``process_curr_construct_pragmas``. Note that a symbol pointer is included + in the interface of the processing functions for ``pbk_next_construct`` + pragmas, and so ``record_arg_pragma`` is able to record the event for the + current routine. + +The timing of the call to ``process_curr_construct_pragmas`` and therefore to +the corresponding processing function may be critical. The rules, in general, +are: + +* | for declarations, ``process_curr_construct_pragma`` is called at the point + the symbol is bound to its corresponding IL entry; +* | for statements, it is called immediately after the statement entry is + created (but before other processing is done). + +For reasons of timing and other considerations it is sometimes inappropriate to +use the automatic mechanisms that are provided. An alternative is to call +``extract_specific_pragmas``, which returns a pending pragma entry of a given +pragma kind, [#f2]_ and to do the required processing directly. For an example +of this style of pragma use see ``record_lint_argsused_and_varargs_state``, +which is called *only* when a function is being defined: if +``extract_specific_pragmas`` returns a pending pragma entry of the specified +kind, it sets a flag in the routine type supplement and, since the entry will +have been removed from the current construct pragma list, calls +``free_pending_pragma_list`` to dispose of it. + +``extract_specific_pragmas`` is also called for ``pbk_other`` pragmas. In +fact, it is essential for completing the processing of such pragmas and should +be included in custom code to implement a specific pragma. Once this routine +has been called for a given pragma kind, the pending pragma entry returned is +no longer on the ``pending_pragmas`` list, so it cannot be found a second time. +Note also that the calling routine is responsible for freeing the pending +pragma entry. + +How to Add A New Pragma +======================= + +The mechanisms provided to support ``#pragma`` directives have been designed +with extensibility in mind. This section is intended to provide some +additional guidance in adding new pragma kinds. In general, this is what you +will need to do to: + +* | Add a new entry to the enumeration ``a_pragma_kind`` in ``il_def.h``, and + add an identifier string to the array ``pragma_ids``. +* | Decide on the binding kind for the pragma. + + * | ``pbk_immediate`` is appropriate when the pragma's effect is quite + independent of the context in which it appears in the source. It is + processed unconditionally immediately after the pragma is scanned. If + the pragma appears in a cached context, the pragma is also processed each + time the cache is rescanned. + * | ``pbk_next_token`` is similar to ``pbk_immediate`` except that the pragma + is not processed until the next regular (non-preprocessing) token is + fetched and if the pragma appears in a cached context it is not processed + when it is first encountered but only each time the cache is rescanned. + * | ``pbk_next_construct`` is appropriate when the pragma is meant to affect + the construct that immediately follows it in the source. Set one or both + of ``may_bind_to_decl`` or ``may_bind_to_statement`` depending on what + sort of construct it applies to. These pragmas are discarded (optionally + with a diagnostic) if they appear in front of the wrong kind of + construct. + * | ``pbk_other`` is appropriate for maximum flexibility, though it requires + additional intervention by you, since the automated mechanisms are not + available. + * | ``pbk_preproc_immediate`` is appropriate when the pragma must be + processed when encountered by the preprocessing routines and cannot be + deferred until the next nonpreprocessing token of the program is scanned. + No pending pragma entry is created for these pragmas and they cannot be + entered into the IL. +* | Create the pragma kind description by adding a call to + ``add_pragma_kind_description`` in ``pragma_init``; the call should be made + using the interface function that is specific to the binding kind. +* | If you want to store information -- say, the value of a pragma argument + that will be used when the pragma is processed -- you can add one or more + variant fields to ``a_pending_pragma``. The switch statement in + ``alloc_pending_pragma`` (where the variant field, if any, is initialized) + should be updated to recognize the new pragma kind. +* | If the pragma is to be entered in the IL and additional information is + needed in the IL entry, you should add variant fields to ``a_pragma`` + (defined in ``il_def.h``) and initialize them in ``alloc_pragma`` (in + ``il_alloc.c``). +* | If the pragma is to be entered in the IL automatically, set + ``automatically_include_in_il`` when creating the pragma kind description + entry. +* | If the pragma binding kind is ``pbk_immediate``, pbk_next_token, or + ``pbk_next_construct``, decide whether you want a processing function to be + called automatically. If so, be sure to include a pointer to it when + creating the pragma kind description entry. + | + | Even if you have specified a processing function, be sure that + ``automatically_include_in_il`` is FALSE if you want control over whether + the IL pragma entry should be created; if you do this, you can call + ``create_il_entry_for_pragma``. If ``automatically_include_in_il`` is + TRUE, the IL pragma entry will already have been created before your + routine is called, but you will still be able to set any variant fields + that are specific to this pragma kind. +* | If the pragma binding kind is ``pbk_other`` -- or if it is + ``pbk_next_construct`` but you don't want to use the automatic facility of + ``process_curr_construct_pragma`` -- you will have to write code to call + ``extract_specific_pragmas`` and to do the required processing. Note that, + if ``automatically_include_in_il`` is set to TRUE, + ``extract_specific_pragmas`` will cause an IL pragma entry to be created; + if you want more control, be sure the flag is FALSE when you create the + pragma kind description entry. +* | If your code uses ``extract_specific_pragmas``, be sure to call + ``free_pending_pragma_list`` to dispose of the pending pragma entry (or + entries) returned to you. +* | If your pragma processing function needs to deal with more than the pragma + identifier, decide whether your code requires the pragma to be represented + as a text string or as a token cache. If the former, set + ``record_pragma_text`` to TRUE when you create the pragma kind description + entry. However, if you choose to deal with tokens, the following + convention should be observed: + + #. Call ``begin_rescan_of_pragma_tokens`` to find the appropriate token + cache for rescanning the tokens that comprise the pragma body; it also + pushes a ``sck_pragma`` scope. The first token you will see is the one + following the pragma identifier. + + #. When you have finished scanning the tokens, call + ``wrapup_rescan_of_pragma_tokens`` to pop the ``sck_pragma`` scope and + check that all of the tokens were scanned from the cache; if the current + token is not the ``tok_end_of_source`` at the end of the pragma + directive, an "extra text in preprocessing directive" error will be + issued. + +* | You should set ``expand_macros`` to FALSE if you want to suppress macro + expansion while the pragma tokens are scanned. Furthermore, setting + ``processing_C_code`` when generating a token cache means keywords will be + recognized and adjacent string literals will be concatenated together. +* | If you are simply passing the pragma on to the back end without processing + it in the front end, be sure that ``make_text_not_tokens`` is TRUE when you + create the pragma kind description entry -- a pragma cannot be passed to + the back end in the form of a token cache. +* | If you want a diagnostic issued when a ``pbk_next_construct`` pragma + appears in the wrong place in the source program or an unprocessed + ``pbk_other`` pragma is encountered when a scope is popped, set the + ``error_severity`` appropriately when you create the pragma kind + description entry; use ``es_none`` to suppress the diagnostic. + +Introduction to Attributes +========================== + +Unlike pragmas, attributes are parsed like other ordinary language features. +This parsing is usually achieved with a call to ``scan_attributes``, which +returns a list of attributes (``an_attribute`` entries) in the order that they +were encountered. Each attribute entry represent a standard attribute, a GNU +attribute, or a Microsoft ``__declspec`` attribute [#f3]_: The specific variant +is recorded in the ``family`` field (which can be ``af_std``, ``af_gnu``, or +``af_ms_declspec``). Whether a specific attribute family syntax is accepted is +determined by the global variables ``std_attributes_enabled``, +``gnu_attributes_enabled``, and ``ms_declspec_attributes_enabled``. The +parsing process also classifies attributes according to their kind +(``ak_align``, ``ak_nothrow``, etc.) and their syntactic location +(``al_prefix``, ``al_declarator_id``, etc.). As with pragmas, the front end +accepts attributes that it doesn't recognize (these are assigned attribute kind +``ak_unrecognized``). + +Attributes appear in "groups". For example: + +.. code:: c++ + + __attribute((align(4))) __attribute((pure,nothrow)) void f(); + +The ``an_attribute`` entry corresponding to the ``align`` attribute will point +to a first entry of type ``an_attribute_group``, whereas the ``an_attribute`` +entries for ``pure`` and ``nothrow`` will both point to a second +``an_attribute_group`` entry. Attribute groups can be empty (typically as the +result of macro expansion). To represent empty groups, an ``ak_empty`` +attribute is created (which then points to an ordinary entry of type +``an_attribute_group``). Attribute group entries do not carry information of +their own other than the position of delimiting tokens: Their principal +function is to indicate how attributes were grouped in the source code. The +"upside-down" arrangement of attributes vs. groups keeps all the attributes +associated with a given entity on a "flat" list, which simplifies traversing +them (the alternative would consist in having to traverse groups and within +each group traversing a list of attributes). + +After attributes have been parsed, they are "attached" and "applied" to an +appropriate IL entity. This is usually done by calling ``attach_attributes``. + +Attaching an attribute means recording its entry in the IL by placing it on a +list pointed to by the IL entry of the entity to which the attribute applies. +Usually, the list is pointed to by the ``attributes`` field in +``a_source_correspondence``. Unrecognized attributes are recorded in the IL +only when the global variable ``record_unrecognized_attributes`` (initialized +with the configuration macro ``RECORD_UNRECOGNIZED_ATTRIBUTES``) is TRUE. If +unrecognized attributes are not recorded in the IL, they elicit a warning. + +Applying an attribute means that the validity of the attribute for its target +entity is checked (e.g., it is an error for a standard ``[[nothrow]]`` +attribute to be applied to a variable) and, possibly, that the IL entry for the +target entity is updated (e.g., the ``noreturn`` attribute causes the +``does_not_return`` flag in the corresponding routine type supplement to be set +to TRUE). Applying an unrecognized or an empty attribute has no effect. + +When simultaneously compiling multiple translation units, the attributes +attached to corresponding declarations are checked. By default, attributes +must match exactly, but alternative policies are possible for specific +attributes and contexts. + +The parsing/classification of attributes, their application to IL entities, and +the checking of corresponding attributes across translation units (when +applicable) is at least in part table-driven. + +Parsing Attributes +================== + +As mentioned above, attributes are usually parsed by calling +``scan_attributes``. However, if only GNU attributes should be considered, +``scan_gnu_attribute_groups`` is called instead. Both functions take an +argument of type ``an_attribute_location``, which specifies the syntactic +context in which the call is made. For example, in the declaration + +.. code:: c++ + + [[nothrow]] int __attribute((pure)) + f [[final]] () __attribute((deprecated)); + +the ``nothrow`` attribute is parsed as ``al_prefix``, the ``pure`` attribute is +parsed as ``al_specifier``, the ``final`` attribute is parsed as +``al_declarator_id``, and the ``deprecated`` attribute is parsed as +``al_post_func``. (I.e., the front end contains calls to ``scan_attributes`` +or ``scan_gnu_attribute_groups`` in various places, each call passing an +argument reflecting the current parsing context.) + +In the case of standard attributes, strict *appertaining rules* allow the +syntactic context to unambiguously determine what entity the attribute applies +to. For example, standard ``al_prefix`` attributes apply to the variables, +functions, or typedefs being declared, while standard ``al_specifier`` +attributes apply to the type specified by the declaration specifiers. + +In contrast, the syntactic location of GNU attributes does not unambiguously +determine the entity they apply to; instead, the affected entity depends on the +attribute kind. For example, in + +.. code:: c++ + + __attribute((align(16))) int f1(); + __attribute((vector_size(16))) int f2(); + +the ``align`` attribute modifies function ``f1``, but the ``vector_size`` +attribute modifies type ``int``. To deal with this, the front end reclassifies +some GNU attributes after they are parsed based on whether the attribute +transforms a type or not. This ensures that the attribute is applied to the +correct entity. For example, the ``vector_size`` attribute in the example +above is parsed as ``al_prefix``, but then reclassified as ``al_specifier`` +(this is done in ``attach_specifier_attributes``). A related example is + +.. code:: c++ + + void f3() __attribute((warn_unused_result)); + void f4() __attribute((pure)); + +These attributes are originally parsed with context ``al_post_func`` +(indicating they appear after a function declarator), which for a C++11 +attribute would imply that the attribute applies to the associated function +type. However, GNU attributes in this syntactic context can apply to the +function type (e.g., ``warn_unused_result``) or to the function itself (e.g., +``pure``). In cases like these, the attributes are reclassified to +``al_postfix`` (in ``scan_declarator_attributes``) and the attribute +application function modifies the function or its type depending on the +attribute (and the same process applies to attributes after array declarators). + +Microsoft ``__declspec`` attributes also lack strict appertaining rules, but +their treatment is simpler because there are no type-transforming +``__declspec`` attributes and ``__declspec`` attributes can appear in fewer +syntactic locations (only ``al_prefix``, ``al_specifier``, and ``al_tag_name`` +contexts are valid, and the former two are usually equivalent). There are some +special cases, however. For example, the ``align`` attribute in + +.. code:: c++ + + __declspec(align(16)) struct S { ... } x; + +is equivalent to + +.. code:: c++ + + struct __declspec(align(16)) S { ... } x; + +and the front end handles this by recording the ``align`` attribute as an +``al_tag_name`` attribute in such cases. + +Unscanning Attributes +--------------------- + +Sometimes, it is not clear at the time of parsing the attribute which context +the attributes will end up in. E.g., GNU attributes can appear after the left +parenthesis introducing function parameters and after the left parenthesis +introducing a nested declarator (see ``r_declarator`` in ``declarator.c``). In +such circumstances, the attributes can be scanned (by calling +``scan_attributes``) with an assumed context, then "unscanned" (with +``unscan_attributes``), and then "rescanned" by calling ``scan_attributes`` +with the correct syntactic location. Note that the call to +``unscan_attributes`` does not restore the tokens that made up the attributes; +it just stores the given attribute entries to be returned by the next call to +``scan_attributes``. + +Recognizing Attributes +====================== + +For an attribute to be recognized in the front end, it must have a description +in the array ``known_attr_table`` defined in ``attribute.c``. The description +(type ``an_attr_descr``) contains four fields: + +* | A string with the source form of the attribute name (e.g., "``section``"). + The optional leading and trailing underscores in the case of GNU attributes + should not be included in this string. +* | A string encoding what kind of arguments (if any) the attribute takes. + This the "signature" of the attribute. The details of this encoding are + described in the definition of ``an_attr_descr`` in ``attribute.c``. For + example, the code ``"(sn+)"`` would indicate that an argument list is + required and that it should contain one or more (narrow) string literals. +* | A string encoding the general conditions (primarily, the mode) in which an + attribute should be accepted, and, in the case of standard attributes, the + attribute namespace for the attribute. This encoding too is described in + the definition of ``an_attr_descr`` in ``attribute.c``. For example, + ``"g+(-39999)"`` indicates that the attribute should be accepted as a GNU + attribute in GNU C++ modes with ``gnu_version`` less than 40000, while + ``"c+[EDG]"`` specifies that the attribute should be accepted with standard + syntax and namespace-prefix ``EDG::`` in modes that accept standard C++11 + attribute syntax. +* | The attribute kind (e.g., ``ak_section``) that should be assigned to the + attribute. + +Note that there can be multiple entries for the same attribute kind. For +example, the ``nothrow`` attribute is accepted as a GNU attribute, as a +Microsoft ``__declspec`` attribute, and as a standard attribute, and therefore +(at the time of this writing) it has three description entries as follows: + +.. code:: c++ + + ... + { "nothrow", "", "1c+", ak_nothrow }, + ... + { "nothrow", "", "gx", ak_nothrow }, + ... + { "nothrow", "", "m+", ak_nothrow }, + ... + +(the prefix "``1``" in ``"1c+"`` indicates that the attribute cannot be +repeated in an attribute group). + +If an attribute name is recognized, but it does not meet other constraints, a +diagnostic is issued and the attribute is reclassified as ``ak_unrecognized`` +(by calling the macro ``make_attr_unrecognized``). This recovery technique is +used throughout attribute processing: Rather than dropping an attribute +altogether, it is generally just reclassified by calling +``make_attr_unrecognized``. + +Applying Attributes +=================== + +The application of attributes is highly dependent on the specific attribute +being applied, but some of the processing is also table-driven. Specifically, +the array ``known_attr_appl_table`` contains an entry of type +``an_attr_appl_descr`` for every attribute kind. Each entry contains the +following fields: + +* | The attribute kind, included only for readability and consistency checking + (the array contents must match the enumeration ``an_attribute_kind``). +* | A string encoding which entity kinds an attribute applies to, and, + optionally, simple constraints for matching entities. The details of the + encoding are described in the definition of ``an_attr_appl_descr`` in + ``attribute.c``. For example, ``"r|v"`` means the attribute applies to + routines and variables only, while ``"r|v:-a"`` means the same thing, but + requires the variable not to have automatic storage duration. (A failure + to meet these constraints causes the attribute to be reclassified as + ``ak_unrecognized``.) +* | A pointer to a callback function (of type ``an_attr_application_fn``). If + this pointer is non-NULL and if the constraints in the previous field are + fullfilled, the indicated function is called with the attribute and the IL + entry it applies to (the "target entity") passed in as arguments. The + callback function can check additional constraints on the target entity and + update the entry (and any other structures) as appropriate. + +A few Microsoft ``__declspec`` attributes require special handling in the front +end. For example, the presence of a ``property(...)`` attribute is detected +soon after being scanned because it affects certain semantic checks performed +by the front end before the complete declaration has been parsed (and, +therefore, before the application callback function can be called). + +Type-Transforming Attributes +---------------------------- + +Most attributes only modify relatively minor properties of the entities to +which they apply, and this modification is to the entity itself. For example, +the standard attribute ``[[final]]`` when applied to a class type ``X`` +prevents other classes from deriving from ``X``; it does not create a new IL +entry. Some GNU attributes, however, can transform a type into a new type +requiring a distinct IL entry [#f4]_. For example, the GNU attribute in: + +.. code:: c++ + + float __attribute((vector_size(16))) vec; + +transforms type ``float`` to a type "vector of ``float``". Such +type-transforming attributes are applied (and attached) using function +``attach_type_attributes``. It uses the array ``known_attr_appl_table`` much +like ``attach_attributes``, but instead of making the resulting type entry +point directly to the attributes list, it adds a ``tk_typeref`` entry on top of +the resulting type for that purpose. + +Because of the possibility of entity transformation, the callback functions +recorded in ``known_attr_appl_table`` must return an IL entry pointer that +represents the entity resulting from the application of the attribute to a +given entity. Except for type-transforming attributes, the returned IL entry +is the same entry as the one passed to the callback function. + +Attributes in Back Ends +======================= + +Most known attributes have an effect on IL fields that provides sufficient +information to a traditional code-generating back end. For example, the +``nothrow`` attribute causes the ``never_throws`` flag in ``a_routine`` to be +set to TRUE. However, since attribute entries are also pointed to by affected +entities, it is not strictly necessary to add separate fields to IL entries. A +specific attribute can be found using the function ``find_attribute``. For +example, the standard attribute ``carries_dependency`` is currently only +represented by its ``an_attribute`` entry. + +The C-generating back end ignores most ``an_attribute`` entries. Instead, it +usually renders GNU attributes (when the target compiler is known to be a +version of GCC) based on other fields in the IL. However, for some attributes +that are only represented in the IL through their ``an_attribute`` entry, the +C-generating back end may emit a GNU attribute construct based on the presence +of the corresponding entry. + +The C++-generating back end, on the other hand, renders attributes based *only* +on applicable ``an_attribute`` entries. To ensure that the rendered code is +close to the original form, attributes specified on a secondary declaration are +recorded twice in the IL (i.e., the entries are duplicated): Once on the list +pointed to by the source correspondence of the target entity, and once on a +list pointed by the associated ``a_src_seq_secondary_decl``. Attributes on +primary declarations are recorded only once, but are marked as having appeared +on the primary declaration (flag ``on_primary_declaration`` in +``an_attribute``). + +How to Add a New Attribute +========================== + +The framework described above make the addition of many common kinds of +attributes relatively simple: + +* | Add an ``ak_``... attribute kind in ``il_def.h``. +* | Add one or more entries to the ``known_attr_table`` in ``attribute.c``. +* | Add an entry in the ``known_attr_appl_table`` in ``attribute.c``. +* | Write the callback function specified in the new ``known_attr_appl_table`` + entry (if such a callback is needed at all). +* | If the attribute is not required to match exactly across translation units, + add one or more entries describing the correspondence handling to the + ``attr_corresp_table`` defined in ``attribute.c``. (In some cases this may + involve adding additional functions or updating the code in + ``trans_corresp.c``.) + +(The attribute may require new IL entry fields or even new IL entry kinds. If +so, see :ref:`il-extension-guide`.) + +If attributes must be recognized in contexts that do not currently allow them, +additional calls to ``scan_attributes`` and ``attach_attributes`` must be added +to the front end (and, most likely, additional enumeration constants for +``an_attribute_location``). If the C++-generating back end is used, it will +also require a matching call to ``gen_attributes``. + +.. [#f1] Pragmas of a fourth kind, ``pbk_preproc_immediate``, are dispatched + when scanned by the preprocessing routines. A pending pragma entry is + never created. +.. [#f2] Actually, it returns a list, though this would seldom be significant. +.. [#f3] Microsoft attributes delimited by single brackets are not handled by + this mechanism (see :ref:`ms-attributes`). +.. [#f4] Currently, this is limited to the GNU attributes ``vector_size`` and + ``mode``. diff --git a/dev/doc/_sources/runtime.rst.txt b/dev/doc/_sources/runtime.rst.txt new file mode 100644 index 0000000..e4273db --- /dev/null +++ b/dev/doc/_sources/runtime.rst.txt @@ -0,0 +1,141 @@ +=============== +Runtime Library +=============== + + + + +The runtime library routines provide basic runtime support. The source for +these routines is in the ``lib_src`` directory of the release structure. + +"Basic" runtime support means support for operations built in to the C++ +language, like ``new`` and ``delete``, and for operations for which code is +generated by IL lowering, e.g., array initialization. (This includes code +generated by the lowering of C99 constructs.) It does not mean support for all +libraries required by the C++ standard, e.g., ``iostream``\ s. + +The front end supports two different runtime models. A configuration macro is +used to select the runtime model to be used. The models supported are the +IA-64 ABI and one that is an extension of the one used with *cfront*. + +The IA-64 model is a complete implementation of the IA-64 ABI, except that the +exception handling implementation does not conform to the ABI (because +producing a conforming implementation of exception handling requires back end +support). + +The *cfront* runtime model is generally compatible with the one used by +*cfront* version 3.0.2, and in fact the code generated by the front end in +*cfront* object code compatibility mode will work with the libraries +supplied with *cfront* (with one exception that is described below). +Another way of saying the same thing: The runtime library is an independent +implementation of the runtime interface defined by *cfront*. + +One incompatibility between our runtime support library and the one provided +with *cfront* is the handling of static destructors. The *cfront* static +destruction mechanism does not conform to the C++ standard, which requires all +static objects, including local static objects, to be destroyed in the reverse +order of construction. The EDG static destruction mechanism relies on a new +data structure called the needed destructions list. If a *cfront* runtime +library is to be used, the ``dtor_list.o`` file from the EDG library must be +included when a program is linked. This may be done by explicitly including +``dtor_list.o`` in the link command generated by the driver, or by adding +``dtor_list.o`` to the library file containing the *cfront* libraries. + +In the area of exception handling, there is no standard *cfront* runtime +model (because no version of *cfront* that supports exception handling was +released by USL), so the model is invented by EDG, drawing on some +published aspects of the implementation done by Hewlett-Packard. + +The runtime routines should be considered to be a sample implementation of a +runtime library. They are believed to be complete and to work correctly, but +they might require adaptation to make them work correctly in a given +environment, or to make them compatible with other runtime libraries or +conventions on the target system. In particular, if runtime compatibility with +*cfront* is not required, there are probably better ways of doing some of these +things. Also, the target system may provide efficient support for things that +can only be done in a clumsy way in a portable runtime library, e.g., getting +start-up initialization code run automatically at the beginning of execution. + +The ``--building_runtime`` option +================================= + +Like the front end, the runtime contains a number of configuration flags. In +many cases, it is essential that the same values be used by both the front end +and the runtime with which the generated code will be linked. To help make +sure the runtime is configured properly the ``--building_runtime`` option +should be specified when compiling the runtime. This causes additional +preprocessing macros to be defined that pass the value of certain configuration +flags from the front end to the runtime. The following preprocessing macros +are defined when the ``--building_runtime`` option is used: + +.. list-table:: + + * - | ``__EDG_JMP_BUF_ELEMENT_TYPE`` + | + - | The name of the integer or floating point type that is used as the + element type of the ``jmp_buf`` array used by ``setjmp``. + * - | ``__EDG_JMP_BUF_NUM_ELEMENTS`` + | + - | The number of elements in the ``jmp_buf`` array used by ``setjmp``. + * - | ``__EDG_DELTA_TYPE`` + - | The name of the integer type that is used to represent the offset in a + virtual function table entry. + * - | ``__EDG_VIRTUAL_FUNCTION_INDEX_TYPE`` + | + - | The name of the integer type that is used to represent the index field + in a virtual function table entry. + * - | ``__EDG_VAR_HANDLE_TYPE`` + | + - | The name of the integer type that is used to represent a "handle" in + exception handling tables. Defined only when ``GENERATE_EH_TABLES`` + is TRUE. + * - | ``__EDG_REGION_NUMBER_TYPE`` + | + - | The type of a region number field in the exception handling tables. + Defined only when ``GENERATE_EH_TABLES`` is TRUE. + * - | ``__EDG_ETS_FLAG_TYPE`` + | + - | The type used to pass exception types flags to the runtime library. + Defined only when ``GENERATE_EH_TABLES`` is TRUE. + * - | ``__EDG_NULL_EH_REGION_NUMBER`` + | + - | The value used as the null region number value in the exception + handling tables. Defined only when ``GENERATE_EH_TABLES`` is TRUE. + * - | ``__EDG_LOWER_VARIABLE_LENGTH_ARRAYS`` + | + - | Indicates whether or not the front end is configured to lower + variable-length arrays. Set to the value of ``(VLA_ALLOWED && + LOWER_VARIABLE_LENGTH_ARRAYS)`` in the front end. + * - | ``__EDG_IA64_ABI_USE_VARIANT_ARRAY_COOKIES`` + | + - | Non-zero when the variant representation of array cookies is used in + the IA-64 ABI. Defined only when ``IA64_ABI`` is TRUE. + * - | ``__EDG_ELEM_COUNT_PARAM_TYPE`` + | + - | The type used to represent the ``number_of_elements`` argument in the + Cfront-like ABI. Defined only when ``IA64_ABI`` is FALSE. + * - | ``__EDG_ABI_COMPATIBILITY_VERSION`` + | + - | The value of ``ABI_COMPATIBILITY_VERSION`` used when the front end was + built. + * - | ``__EDG_ABI_CHANGES_FOR_RTTI`` + | + - | The value of ``ABI_CHANGES_FOR_RTTI`` used when the front end was + built. + * - | ``__EDG_ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE`` + | + - | The value of ``ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE`` used when the + front end was built. + * - | ``__EDG_ABI_CHANGES_FOR_PLACEMENT_DELETE`` + | + - | The value of ``ABI_CHANGES_FOR_PLACEMENT_DELETE`` used when the front + end was built. + * - | ``__EDG_BSD`` + - | The value of the ``__BSD__`` macro when the front end was built. + * - | ``__EDG_SYSV`` + - | The value of the ``__SYSV__`` macro when the front end was built. + * - | ``__EDG_ANSIC`` + - | The value of the\ ``__ANSIC__`` macro when the front end was built. + * - | ``__EDG_CPP11_IL_EXTENSIONS_SUPPORTED`` + - | The value of ``CPP11_IL_EXTENSIONS_SUPPORTED`` when the front end was + built. diff --git a/dev/doc/_sources/statements.rst.txt b/dev/doc/_sources/statements.rst.txt new file mode 100644 index 0000000..0c811db --- /dev/null +++ b/dev/doc/_sources/statements.rst.txt @@ -0,0 +1,259 @@ +================== +Statement Scanning +================== + +``statements.c`` contains the code to scan statements, and ``statements.h`` +contains the associated declarations. + +The top-level routine here is ``compound_statement``, which scans a +brace-enclosed list of statements. This is used for the bodies of functions +and for blocks (with and without local declarations) that appear within +functions. In C mode, it first calls ``opt_declaration_list`` to scan the +optional list of declarations; then, in C or C++ mode, it calls ``statement`` +(in a loop) to scan the statements. + +``statement`` scans one statement, with an optional preceding label or labels. +Its job is mostly to call the appropriate statement-scanning routine based on +the first token of the statement. For most statements, the first token is a +keyword that identifies the statement. Otherwise, the statement is an +expression statement (in C or C++) or a declaration (in C++ only; +``is_decl_not_expr`` is called to decide whether the construct is an expression +or a declaration). + +A stack of active statements is maintained in ``struct_stmt_stack``. For each +active statement, it contains the kind of statement and some information about +what has been scanned so far in the statement. ``push_stmt_stack`` and +``pop_stmt_stack`` manage the stack. ``find_enclosing_struct_stmt`` can be +used to find the nearest enclosing structured statement of a given type; this +is used in finding the construct associated with a ``break`` or ``continue``. + +One important function of the statement stack is that it points to the +intermediate language for the associated statement. The top-most entry +contains enough information to enable one to find the "current" location in the +intermediate language being generated, the point at which one would like to add +a statement. This is, in fact, exactly what ``add_statement_list`` does: it +links the given list of statements (possibly just a single statement) into the +growing tree of statements for the function. Usually, this is called through\ +``add_statement_at_stmt_pos`` , which allocates a statement of a given kind and +also maintains the ``code_reachable`` flag, indicating whether or not the +current location in the code is reachable. This flag is used to check for +unreachable code and issue appropriate warnings. Code is attached to the +statement tree even if it is unreachable. As statements are pushed onto and +popped off the stack, the ``code_reachable`` flag is maintained accordingly, +based on whether or not the beginning of the statement can be reached, whether +the end can be reached from the beginning, and whether the end can be reached +from the inside. The ``lint_notreached_flag`` is also consulted. For +statements that have several clauses (``if`` and ``switch``) +``start_stmt_clause`` and ``term_stmt_clause`` are called at the appropriate +locations in processing to keep the ``code_reachable`` flag up to date. + +The statement stack contains pointers to ``break`` and ``continue`` labels for +the statement. These are initialized to ``NULL``, and later made to point to a +label if a ``goto`` is actually generated for a ``break`` or ``continue``. At +``pop_stmt_stack`` time, the definition for the ``break`` label is generated if +one is needed. The statement scanning routine must handle the ``continue`` +label is there is one. + +If a statement is labeled with a simple label, ``statement`` calls +``scan_label`` to look up or enter the label, then ``define_label`` to add a +label definition statement to the intermediate language. + +Nothing tricky is involved in statement processing routines ``if_statement``, +``while_statement``, ``do_statement``, ``goto_statement``, ``break_statement``, +and ``continue_statement``. ``asm_statement`` is called for asm statements; it +in turn calls ``asm_declaration``. + +``dependent_statement`` is called to scan statements that are dependent +statements of ``if``, ``switch``, ``while``, ``do while``, and ``for`` +statements. In C mode, it just scans a statement. In C++ mode, it creates a +block statement and places the dependent statement under it, unless the +dependent statement is a block statement. That ensures that if anything is +declared in the dependent statement, its scope will be limited to the dependent +statement (this is a post-ARM C++ language rule). + +``for_statement`` scans a ``for`` or range-based ``for`` statement (or, in UPC +mode, a ``upc_forall`` statement). Since it is unknown at the beginning of +scanning whether a ``for`` or range-based ``for`` statement is being scanned, +two block scopes (used to contain the range-based ``for`` temporary variables) +are pushed in preparation for the range-based ``for`` case (they're discarded +if scanning reveals a ``for`` statement). The first entity inside the +parentheses (initialization) is scanned by calling ``for_init_statement``, +which allows an expression (in C or C++), a declaration (in C++ only), or a +``for-range-declaration`` (in C++11). ``for_init_statement`` also determines +(through a call to ``decl_statement_full``) which type of statement is being +scanned. If the ``for-init`` is a declaration (and a ``for`` statement is +being scanned), ``start_for_init_block`` is called to push an ``sck_block`` +scope (with ``is_for_init_block`` set to TRUE) onto the scope stack, where +it remains till after the dependent statement of the loop is scanned (see +``finish_for_init_block``). If the second expression (test) is present, it is +scanned by calling ``can_boolean_controlling_expression``. The third +expression (increment) is scanned by calling ``scan_void_expression``. For any +of those expressions/statements that is omitted, a ``NULL`` pointer is used in +the ``stmk_for`` statement. In the range-based ``for`` case, the statement +kind is set to ``stmk_range_based_for`` (this is somewhat unusual since the +statement kind is typically known earlier) and +``scan_range_based_for_expression`` is called to scan the range expression. +Semantic checks, determination of the type of range-based ``for`` (see header +comments), and IL generation are handled by +``check_range_based_for_statement``. + +The Microsoft for-each statement (available in C++/CLI emulation mode, as well +as when ``microsoft_version`` >= 1400) is scanned by ``for_each_statement``. +If the for-each statement contains a previously declared iterator variable, it +is scanned by ``scan_previously_decl_iterator_name``, otherwise the iterator +declaration is scanned by ``for_each_iterator_declaration``. Two block scopes +are pushed (an outer block scope for the loop temporary variables, and an inner +scope for the iterator variable). The collection expression is scanned by +``scan_for_each_expression`` and semantic checks (and IL generated) by +``check_for_each_statement``. ``check_for_each_statement`` handles the various +types of for-each statements (see the header comment for details). Much of the +underlying code is shared with the range-based ``for`` statement. + +``return_statement`` scans the ``return`` statement. It examines the type of +the current function. A ``void`` function should have ``return``\ s that +return no value; other functions should return a value. +``check_void_return_okay`` checks whether or not a value-less ``return`` is +okay in the current function. It is also used at the final closing brace of +the function if that position is reachable (since there is an implicit +``return`` there). + +``switch`` statements cause the most problems. ``switch_statement`` itself is +not too complicated: it just pushes an entry on the statement stack, scans the +selector expression, and scans the dependent statement. The complex processing +comes with ``case_label`` (which also handles the GNU extension of case ranges; +e.g., "``case 1 ... 3:``") and ``default_label``, or more precisely, with the +subroutine those two cases call, ``add_switch_clause``. That routine +determines whether or not the label can be added to the list of labels for the +currently-active clause, or whether instead a new clause must be begun. It +also determines where the case value (or the default) belongs in the list of +constants for the clause. The configuration macro +``RECORD_SWITCH_CASE_ENTRIES`` determines how individual case labels are +represented. When TRUE (the default), all the labels (including the default +case and any GNU case ranges) are represented using type +``a_switch_case_entry``. When FALSE (an option maintained primarily for +backward compatibility purposes), the labels within a clause are usually +represented as a list of ``a_constant`` entries, but in a clause labeled with +``default``, any specific values from ``case`` labels are superfluous and are +removed. In the latter approach, GNU case ranges are represented as a list +containing all the constants in the range (which doesn't scale well for large +ranges). Because the intermediate language idiom for ``switch`` statements is +slightly different from the C language idiom, a bit of translation from one +idiom to the other is necessary: + +* | A ``break`` in a ``switch`` usually just ends the current clause and makes + the code following it unreachable. Since the intermediate language + ``switch`` clauses end with a ``break`` by default, no ``goto`` to a + ``break`` label is usually needed. +* | Fall-through from one clause into the next is translated as a ``goto`` to a + generated label at the start of the next clause. +* | When ``case`` or ``default`` labels are not at the top level in the + ``switch`` body (i.e., they are defined within structured statements inside + the ``switch``), the ``switch`` clause is just a ``goto`` to a generated + label at the right location, and the unusual statement(s) inside the + ``switch`` body go into the body statement attached to the intermediate + language ``switch``. +* | Likewise, when there are local declarations in the compound statement that + is the body of the ``switch``, those declarations go into the body + statement. + +There is also processing to detect and report cases in which a declaration that +involves implicit or explicit initialization is bypassed by a transfer of +control (by means of a ``goto`` or ``switch``). A separate data structure is +maintained to assist in this checking: variable ``control_flow_descr_list`` +identifies a doubly linked list of entries of type ``a_control_flow_descr`` +that represents a view of the static control flow pattern of a given function. +Blocks, ``goto``\ s, labels, ``case`` labels, and initializing declarations are +all represented by entries on the list. Some of these entries point to IL +entries, but the IL does not point back. + +The list is dynamically pruned -- it has only enough information on it for the +checking that is required. For instance, once a forward goto has been checked, +it is no longer interesting and is removed, and entire blocks may be removed +once they become irrelevant to subsequent analysis. (See +``remove_control_flow_descr`` and ``remove_list_of_flow_control_descrs``, which +place entries onto an available list, and ``alloc_control_flow_descr``, which +reuses freed entries in preference to allocating new ones.) + +``add_to_control_flow_descr_list`` is called (from ``add_stmt_at_stmt_pos`` for +initializations, from ``push_stmt_stack`` for blocks, etc.) to add a new entry +to the end of the list, though in some cases the entry will not be +added -- because it is not required after all -- and sometimes it will even +cause other entries to be removed -- for instance, if a completed block turns +out to have no labels or gotos, the entire block can be eliminated. + +At the end of a block within a ``switch`` statement, +``add_to_control_flow_descr_list`` may call ``report_switch_past_init``, which +examines the entries on the list for initializing declarations that may be +bypassed by a transfer of control to a ``case`` label. An error is issued in +C++ mode, a warning otherwise. + +``check_for_jump_over_initialization`` is called from ``goto_statement`` and +from ``statement`` when a label definition is seen. For a forwards ``goto`` it +calls ``add_to_control_flow_descr_list`` to record information that will be +used for checking when the label is processed. For a label it calls +``check_goto_and_label`` to report any previously recorded ``goto``\ s that may +now be recognized to involve bypassing an initializing declaration (see +``report_goto_past_init``, which issues an error in C++ and a warning +otherwise); and an entry representing the label is added to the list. For a +backwards ``goto`` it again calls ``check_goto_and_label``, which in turn calls +``report_goto_past_init``, if appropriate. + +The control flow descriptor list is also used by +``check_for_branch_into_handler``, which reports attempts to branch into an +exception handler from code outside the handler. + +An important part of statement processing is the management of object +lifetimes. For example, each time a compound statement starts, a new object +lifetime begins; and it ends when the compound statement terminates. In other +words, objects (e.g., automatic variables and long-lifetime expression +temporaries) created inside the compound statement have lifetimes that +terminate when it does. The destructor (if any) for such an object must be +called in the event of the normal termination of the scope, a branch out of it, +or unwinding through it as the result of an exception. The information +enabling back ends to support these implicit destructor calls, in the right +place and in the right order, is provided by entries of type +``an_object_lifetime``, discussed in detail in the chapter on the intermediate +language. + +Each time a new function or block scope is created, a new object lifetime is +pushed on the object lifetime stack -- ``push_object_lifetime`` is called in +``push_scope``, and the object lifetime is bound to the scope entry for block +scopes in ``ensure_il_scope_exists`` (in ``il.c``). In addition, an object +lifetime is pushed for try blocks in ``try_block_statement`` and for cfront +dependent statements in ``start_block_statement``; in the latter case, since +there is no scope, the lifetime entry is bound to the block entry associated +with the block statement. + +When a label is defined, a block-after-label object lifetime is pushed. Such +lifetimes are effectively subblocks of the current lifetime that run from the +label to the end of the block in which the label appears. When a label is +defined inside an inner block, a block-after-label lifetime is also pushed in +the containing block when the inner block terminates. (See +``terminate_curr_block_object_lifetime`` and +``reset_curr_block_object_lifetime``.) Block-after-label lifetimes are also +pushed for case labels. + +The object lifetime that is current at the point of the label's definition is +recorded in the label statement. A ``goto`` statement that references that +label will point to the innermost object lifetime shared by the label and the +``goto``; this is computed by ``common_object_lifetime``. + +The general strategy is always to create an object lifetime at standard +transitions in the source code (e.g., upon entering a block or when a label is +seen) and then, when the construct it belongs to terminates, to decide whether +there is justification for retaining that lifetime entry in the IL. If not (as +determined by ``is_useless_object_lifetime``), it is removed from the IL tree. + +Consequently, a label or ``goto`` statement may be assigned an object lifetime +that subsequently proves "useless". In that case the object lifetime pointers +of the statement entries are promoted (see +``fixup_curr_block_labels_and_gotos``, which calls +``promote_label_and_goto_lifetimes``; this is also where +``pop_object_lifetime`` is called for block-after-label lifetimes). This +processing is driven by management of the control flow description list (see +``add_to_control_flow_descr_list``). + +If all the labels and ``goto``\ s in a function end up pointing to the function +scope lifetime but the function scope lifetime itself turns out to be useless, +then the lifetime pointers in the label and ``goto`` statements are cleared +(see ``wrapup_control_flow_processing``). diff --git a/dev/doc/_sources/symbol_tbl.rst.txt b/dev/doc/_sources/symbol_tbl.rst.txt new file mode 100644 index 0000000..92d8a98 --- /dev/null +++ b/dev/doc/_sources/symbol_tbl.rst.txt @@ -0,0 +1,1967 @@ +.. _symbol-table: + +============ +Symbol Table +============ + +The primary function of the symbol table is to provide a mechanism for +associating names and entities: a name can be entered into the symbol table in +association with a particular definition and then later looked up to get back +to the same definition. Name visibility is controlled by an implementation of +nested name scopes and class member inheritance. Provision is also made for +overloaded operators and user-defined conversion functions, which are not +looked up by name. In addition, the symbol table serves as a repository of +information that is needed for front-end processing but is of no use to back +ends. ``symbol_tbl.c`` contains the code to manage the symbol table, +``lookup.c`` contains the code that looks up identifiers, ``scope_stk.c`` +contains the code that manages the scope stack, and ``symbol_ref.c`` contains +the code that manages the recording of references to symbols. +``symbol_tbl.h``, ``lookup.h``, ``scope_stk.h``, and ``symbol_ref.h`` contain +the associated declarations. + +Basic Organization +================== + +Symbols and Symbol Headers +-------------------------- + +The key components of the symbol table are entries of type ``a_symbol`` and +``a_symbol_header``. Typically, symbols represent specific uses of a name +(e.g., the same name may be declared in different name scopes or belong to +different name spaces), but all symbols for a particular name share the same +symbol header. Each symbol entry points to a header which identifies the name +associated with it; the symbol header points in turn to symbols that share its +name. Symbols with the same name from different translation units (see +:ref:`multi-tu`) share the same symbol header. + +For certain special cases (overloaded operators and user-defined conversions) +the symbol header has no actual name but can be thought of as representing a +family of virtual names to be constructed for the associated symbols: a single +symbol header is shared by all symbols that overload a given operator or, for +user-defined conversions, a given return type. (The names generated by the +compiler to assure type-safe linkage are not produced by the front end and so +do not appear in the symbol table.) + +At the gross level the symbol table has three distinct pieces, each of which +has its own "root", a global variable that is accessed in the lookup process: + +* | For named symbols ``symbol_table`` is a hash table where each bucket points + to a linked list of symbol headers. The name is reduced to a hash value + that is used to index the array. +* | For overloaded operator symbols ``opname_symbol_table`` is an array of + symbol header pointers that is indexed by members of the enumeration + ``an_opname_kind``. There will be one symbol header for each overloaded + operator. +* | For user-defined conversion symbols ``conversion_header_list`` points to a + linked list of entities of type ``a_conversion_header``, one for each + result type for which the user has declared a conversion routine. Each + conversion header points to a single symbol header. + +Active, Inactive, and "Other" Symbols +------------------------------------- + +Each symbol header contains pointers to three lists of symbols of the same name +(or that otherwise share the symbol header): the active symbol list, the +inactive symbol list, and the other symbol list. + +The Active Symbol List +^^^^^^^^^^^^^^^^^^^^^^ + +The list of active symbols includes all symbols that are still in scope. The +order of the symbols on the list is significant since certain of the lookup +mechanisms take the first symbol found. When symbols are entered into the +symbol table, their entries are always placed at the beginning of the list, so +that declarations in inner scopes will eclipse outer-scope declarations of the +same names. An exception is made when a tag and a nontype with the same name +exist in the same scope in C++. In such cases the tag is always placed on the +list following the nontype so that it will be hidden except when accessed using +an elaborated type specifier. When the inner scope ends, its symbol entries +are removed, which exposes the outer declarations. + +Note, however, that symbols from the same scope can coexist on the active list, +since different kinds of symbols can belong to different name spaces. For +instance, a variable, a macro, and (in ordinary C) a tag can all share the same +name. The array ``name_space_for_symbol_kind`` maps a symbol kind into +``a_name_space_kind`` (e.g., ``nsk_label``, ``nsk_macro``, ``nsk_other``). The +lookup mechanism must check for name-space compatibility: in most cases, it +takes the first in the active list whose kind maps into the appropriate name +space. The name space kind ``nsk_other`` is the normal name space for types, +variables, enumeration constants, and functions. + +The Inactive Symbol Lists +^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a scope terminates, the symbol for each name declared in that scope is +removed from the active list of the associated symbol header. In most cases, +this means the symbol is removed from the symbol table (i.e., that it can no +longer be found by any lookup mechanism). But for some symbols (e.g., class +and namespace members) it must remain possible to look up a name even after it +passes out of scope, and so its symbol is moved from the symbol header's active +list to its inactive list. The order of symbols on the inactive list is not +significant. + +Thus, the inactive symbol list will comprise symbols for class members that are +no longer in scope but are still indirectly accessible, whenever the class is +accessed. + +Similarly, when the template declaration scope terminates, its symbols +representing the template parameters are also added to the inactive list. This +enables them to be accessible during instantiation of the template. + +Namespace scopes are not terminated when the namespace is closed because the +namespace may be extended later in the compilation. Namespaces may be extended +either explicitly by opening a namespace extension scope, or implicitly as a +side-effect of a namespace member definition in the file scope or as a +side-effect of the instantiation of a template entity defined in a namespace +scope. When the original namespace definition scope is closed, the namespace +members are moved from the active list to the inactive list. If the namespace +scope is later extended, new symbols for the namespace are entered directly on +to the inactive list. + +The file scope is popped when the scanning of a translation unit is completed +so that its symbols are not on the active list if any other translation units +must be processed. As with namespaces, the symbols are moved to the inactive +list to permit the file scope to be reactivated later, if additional processing +of the original translation unit is required (e.g., to generate template +instantiations). + +The "Other" Symbol List +^^^^^^^^^^^^^^^^^^^^^^^ + +The "other" symbols list is used for symbols that are never found using the +normal lookup routines. Specifically, the "other" symbols list includes +"extern" symbols and synthesized namespace projection symbols, both of which +are described below. + +Scope List +---------- + +When symbols are entered into the symbol table, they are also entered onto a +list of the symbols declared in the current name scope (discussed in detail +below). [#f1]_ This list preserves the names in declaration order and is +referenced in removing symbols from the active list (and usually from the +symbol table) when the name scope is terminated. + +Typically, this list lasts no longer than the scope stack entry that points to +it -- when the entry is popped off the scope stack, the associated list is +discarded. In some cases, however, the list must be kept around for later use. + +* | For class scopes it is stored in the class symbol supplement for the class + for use in cases in which the declaration order must be observed (e.g., in + doing member initialization). +* | For function prototype scopes it is used to reenter parameter symbols in + the function scope. +* | For namespace scopes it is preserved in the pointers block for the + namespace. +* | For file scopes it is preserved in the translation unit entry (there can be + more than one file scope when processing multiple translation units). + +Special Cases +------------- + +There are several classes of symbol for which special treatment is required. + +Symbol entries for constructors, though they have names, are not entered +directly into the symbol table. That is, they do not appear on the active or +inactive list of the symbol header for the name. Rather, they are accessed +from the ``constructor`` field of the class's supplement entry. Thus the +symbol lookup for constructor ``X::X`` is always by way of the symbol +supplement for class ``X``. + +A tagless class, struct, or union presents an interesting case because it has +no name but must have a symbol to serve as a repository of information for the +front end's processing. Such symbols all share a single symbol header (see +static variable ``unnamed_tag_symbol_header`` in ``symbol_tbl.c``) but are not +entered on any list. + +C++/CLI property accessor functions are members of a property which is itself a +member of a class, but the property is not a nested class; it's a data member. +For the accessors, special symbol headers are generated that are a combination +of the symbol header for the property and the symbol header for the access +name. See ``get_property_or_event_accessor_symbol_header``. Event accessors +are handled similarly. + +Error symbols are created in various cases when errors are detected. They have +no name associated with them, and, like unnamed class symbols, they all share +the same symbol header (see static variable ``error_symbol_header`` in +``symbol_tbl.c``). + +Symbols and IL Entries +---------------------- + +For the most part symbol entries are little more than an indication of the kind +of symbol and a pointer to an IL entry that provides more information. Thus, +``sk_variable`` and ``sk_static_data_member`` symbols point to an entry of type +``a_variable``; constants, types, tags, fields, functions, and labels are +similar. The principal function of most symbol entries is simply to indicate a +mapping between names and the intermediate language constructs to which those +names correspond. + +But symbol entries also serve as repositories of information that the front end +requires for its processing but that back ends do not care about. For +instance, ``sk_keyword`` symbols contain the keyword token value and for +``sk_macro`` symbols there is a pointer to ``a_macro_def``. Most notably, +symbols representing classes, structs, and unions point not only to the +corresponding IL entry but also to an entry of type +``a_class_symbol_supplement``, which contains a number of flags and pointers +(including a pointer to the constructor symbol, as described above). + +Some symbols just point to other symbols: ``sk_projection`` symbols, which +represent names in a derived class that are inherited from a base class, +contain a pointer to the original symbol, and ``sk_overloaded_function`` +symbols point to a linked list of routine symbols that represent instances of +the overloaded name. + +``sk_parameter`` symbols are created during parameter processing. They are +needed because parameter names hide names from containing scopes (e.g., in +default argument expressions). However, they do not refer to any IL entity; +rather, when a function definition is present, they are reentered into the +function scope and turned into ``sk_variable`` symbols which do point to +variable entries. + +Function Overloading +-------------------- + +Each instance of an overloaded function is represented by a symbol -- of kind +``sk_member_function`` for member functions and ``sk_routine`` otherwise. +However, these symbols are not directly present in the symbol table. Rather, +the whole family of functions that share the common name or operator in a given +scope is represented by an ``sk_overloaded_function`` symbol, and that is what +actually appears in the symbol table (i.e., is on the active or inactive list +of a symbol header). Consequently, name lookup finds only the overloaded +function symbol, not the symbol for the particular function required. [#f2]_ + +The actual function symbols appear on a linked list pointed to from the +overloaded function symbol. The order of symbols on the list is not +significant, since the argument matching algorithm requires visiting every +instance anyway. The list may contain function symbols, function template +symbols, projection or namespace projection symbols that point to functions or +function templates, or a combination of any or all of these. + +Name Scopes +=========== + +``push_scope`` and ``pop_scope`` +-------------------------------- + +Aside from the structure described above, the symbol table also has a name +scope structure. Each time a new name scope is entered (for the file scope, a +class, struct, or union, a function, a block, function prototype, namespace, +template declaration, or template instantiation), ``push_scope`` is called to +push a new entry onto the scope stack. (See ``scope_stack``, a global variable +that points to an array of elements of type ``a_scope_stack_entry``. Since the +scope stack is implemented as a dynamically allocated array that can be +extended by reallocation when necessary, elements should always be accessed by +indexing into the array rather than by reusing a pointer.) + +There are actually a number of different routines used to push different kinds +of scopes (e.g., ``push_template_instantiation_scope``). The various routines +all call ``push_scope_full``, which does most of the processing. +``push_scope`` is used for pushing "normal" scopes that don't require that +extra arguments be supplied when called. This section uses the name +``push_scope`` to refer to the set of functions that add scopes to the scope +stack. Most of the actions described here are performed by +``push_scope_full``. + +``push_scope`` assigns a unique number to each scope, and when an identifier is +entered into the symbol table, the scope number is recorded in its symbol +(field ``decl_scope``); this number may be referenced during symbol lookup, and +it is used to detect multiple declaration errors during symbol entry. When the +name scope ends, ``pop_scope`` is called to remove its symbols from the symbol +table (class member symbols are an exception, as described above) and to pop +the scope stack entry off the stack. ``pop_scope`` calls ``wrapup_scope``, +which removes the symbol entries for the scope from the active list and +reenters them on the inactive list when appropriate (for class, namespace, and +template declaration scopes). ``wrapup_scope`` also calls +``end_of_scope_symbol_check``, which issues diagnostics on incomplete types and +on entities that were declared and never referenced or set and never used. +When the file scope is popped at the end of the translation unit, ``pop_scope`` +calls ``wrapup_namespace_scopes``, which in turn calls ``wrapup_scope`` for all +of the namespace scopes in the translation unit. + +The ``previous_scope`` field of the scope stack entry is used to determine the +order in which scopes on the scope stack are to be considered for name lookup +purposes. For most scopes, this field is set by ``push_scope_full``. + +``push_scope`` and ``pop_scope`` maintain a number of state variables, some +global and some local to ``symbol_tbl.c``: + +* | ``depth_scope_stack`` gives the depth of the current name scope in the + scope stack. [#f3]_ +* | ``decl_scope_level`` gives the scope depth of the scope entry with which + declarations should be associated. [#f4]_ +* | ``depth_innermost_function_scope`` is the depth of a ``sck_routine`` scope + stack entry that is or contains the current scope; if there is none or if a + class scope intervenes its value is ``NO_SCOPE_DEPTH``. +* | ``num_classes_on_scope_stack`` is the number of class entries currently on + the scope stack (including ``sck_class_reactivation`` as well as + ``sck_class_struct_union`` scopes). +* | ``depth_of_innermost_scope_that_affects_access_control`` is used in + determining whether a piece of code has member access privileges to a given + class (e.g., in a ``friend`` function). +* | ``depth_innermost_namespace_scope`` is the depth of the innermost namespace + scope that is visible on the scope stack, or the depth of the file scope if + no namespace scopes are visible. +* | ``depth_innermost_instantiation_scope`` is the depth of the current + template instantiation scope or ``NO_SCOPE_DEPTH`` if no instantiations are + active. + +``push_scope`` also causes new memory regions to be created for the file scope +and for function scopes. When the scope is popped, the following processing is +done: + +* | If IL lowering is being performed, ``should_delay_lowering_on_function`` is + called to determine whether the function should be lowered at this point. + A number of circumstances can cause lowering to be delayed, such as the + need to preserve unlowered IL for ``constexpr`` evaluations, the need for a + module-id that has not yet been determined, etc. +* | ``should_delay_finishing_of_function_body`` is called to determine whether + a function body should be "finished" at this point. If so, + ``finish_function_body_processing`` is called. This will lower the + function, if it has not already been lowered, do needed flag processing (if + necessary), and any other operations that may be needed before the memory + is potentially freed. +* | ``check_for_done_with_memory_region`` is called either to write out the + entries in the memory region to a file and reclaim the entire region for + reuse or, if the interface to the back end is in memory, to reclaim only + the unused portion of it. In some cases the memory must be kept and IL + file generation deferred. This is done, for example, when a function body + is kept for potential inlining, or if the function contains a generic + lambda that may be instantiated later. + +The name scope for a class whose definition is completed must be reinstated to +process the definition of a member function of that class or the initializer of +static data member of that class. This is accomplished by calling +``push_class_reactivation_scope``, which has the effect of making the symbols +on a symbol header's inactive list visible (that is, those inactive list +symbols whose ``decl_scope`` value matches the scope number of the reactivated +scope become visible). When the class to be reactivated is a nested class, +``push_class_reactivation_scope`` reactivates its enclosing class first to +create the required name visibility and hiding. If the class being reactivated +is from a namespace, the namespace will also be reactivated (see below). A +matching call to ``pop_class_reactivation_scope`` is required once processing +for the member function definition or static member initializer is finished. + +The ``assoc_type`` field in ``sck_class_struct_union`` and +``sck_class_reactivation`` scope stack entries points to the type entry for the +corresponding class, struct, or union. + +Namespace scopes, like class scopes, are reactivated when processing the +declarations of namespace members outside of their namespace. As mentioned +earlier, namespace scopes are unique in that they are not actually closed +when the end of a namespace definition is reached. The namespace can be +extended later either by a namespace extension declaration or by a name +that is injected while processing the definition of a member of a namespace +outside of the namespace (including the instantiation of templates defined +in the namespace). Namespaces are reactivated by calling +``push_namespace_reactivation_scope``. +``pop_namespace_reactivation_scope`` is called when the reactivated +namespace is no longer required. Reactivating a namespace causes any +namespaces that enclose the reactivated namespace also to be reactivated. +Namespaces are extended by calling ``push_namespace_extension_scope``. +When the namespace extension scope is no longer required, +``pop_namespace_extension_scope`` must be called. Extending a namespace +causes any namespaces that enclose the extended namespace also to be +extended. A namespace is *reactivated* in contexts in which the names from +the namespace must be visible but new names cannot be added to the +namespace. A namespace is *extended* in contexts in which names from the +namespace must be visible and new names can be added. + +The scope stack contains a set of pointers that are used to track the symbols +for the scope and the "last" pointers that point to the end of the each of the +lists of IL entries associated with the scope. For most scope kinds, this +information is no longer needed when the scope stack entry is popped off of the +stack. Because namespace scopes can be extended, this information must be +preserved for those scopes. Furthermore, a given namespace can appear on the +scope stack more than once when templates are being instantiated. When more +than one scope stack entry exists for a given namespace, they must share the +same set of symbol and IL entry pointers. The pointers that must be preserved +between extensions of the namespace and shared between scope stack entries for +the namespace are in a structure called ``a_scope_pointers_block``. Each scope +stack entry contains a pointers block structure and field named +``assoc_pointers_block`` that points to a pointers block structure. For all +scopes except namespace and namespace extension scopes, the +``assoc_pointers_block`` pointer is NULL, indicating that the pointers block +within the scope stack entry should be used. For namespace and namespace +extension scopes, the ``assoc_pointers_block`` pointer points to a pointers +block in the namespace symbol supplement for the namespace. The macro +``assoc_pointers_block_of`` should be used to obtain a pointer to the +appropriate pointers block for a given scope stack entry. + +``push_template_instantiation_scope`` is called when the appropriate context in +which a given template can be instantiated needs to be established. When a +template instantiation scope is pushed, the sequence of scopes used for name +lookup purposes is changed. In fact, there are four distinct sets of scopes +used for name lookup when a template instantiation in progress: + +* | the scopes associated with the local context of the template: These include + the template instantiation scope (with which the template parameters are + associated), the scope associated with the class or function being + instantiated, and any scopes nested within the class or function being + instantiated. +* | the template definition context scopes: The scopes that are only part of + the context in which the template was defined. +* | the referencing context scopes: The scopes that are only part of the + context in which the template reference that caused the instantiation + occurred, beginning with the innermost namespace scope. +* | the common scopes: The scopes that enclose both the definition context and + the referencing context. This always contains at least the file scope. + +``push_instantiation_context`` determines which of the required namespace +scopes are already present on the scope stack and pushes those entries that are +not already present. It then calls +``reactivate_class_and_instantiation_scopes`` to reactivate any classes that +may enclose the template that is being instantiated. If an enclosing class is +itself a template class, an instantiation scope for that class is also pushed +so that its template parameters will be visible to the entity being +instantiated. + +``fixup_instantiation_scopes`` is called after all of the scopes have been +pushed. It performs the following functions: + +* | All of the instantiation scopes that were pushed, except for the outermost + one, are flagged as nested instantiations. Only nonnested instantiation + scopes are considered for special instantiation context lookups, as + described later. +* | The context and common scope depths are recorded in the nonnested + instantiation scope. +* | The previous scope pointers of the outermost definition context scope and + the referencing context scope are set to point to the common scope. +* | The ``next_scope_that_affects_access_control`` field is updated to make + sure that it does not point at a scope that is not part of the current + context. +* | In the set of instantiation scopes pushed by a call to + ``push_template_instantiation_scope``, all except the innermost one have + their ``exclude_from_context_output`` flag set. This prevents unnecessary + context information from being generated during diagnostic output. + +The ``previous_scope`` field is also updated when a namespace reactivation +scope is pushed within a template declaration scope. In such cases, the names +from the namespace extension scope must not be considered until after the +template parameters. For example, in the following case the ``T`` in the +function parameter list must refer to the template parameter and not ``N::T``. + +.. code:: c++ + + namespace N { typedef int T;} + template void N::f(T); + +If ``GENERATE_SOURCE_SEQUENCE_LISTS`` is configured to TRUE, source sequence +lists for active scopes are recorded in the scope stack entry (see +``source_sequence_list`` and ``end_of_source_sequence_list`` in +``a_scope_stack_entry``). When ``pop_scope`` is called for the file scope or a +function scope, the list is moved to the corresponding IL scope. Otherwise, +the list is merged into the list of a containing scope, which usually means +that the list is simply appended to the list of the immediately containing +scope; for ``sck_template_instantiation`` scopes, however (when a +compiler-generated specialization represents an automatic instantiation -- that +is, when either ``CLASS``- or +``NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS`` is configured to +TRUE), ``insert_instantiation_src_seq_list`` is called to move the list to an +appropriate location in the list of an enclosing scope. + +Connection With IL Scope Entries +-------------------------------- + +While not all scope stack entries correspond to an intermediate language scope +entry, all intermediate language scope entries have a corresponding scope stack +entry. Every scope stack entry has a (possibly NULL) pointer to an +intermediate language scope entry; every intermediate language scope entry +refers back to the corresponding scope stack entry by means of a scope number. + +For example, a new scope stack entry is pushed for a statement block whether or +not it contains any declarations, but the intermediate language scope is not +created until it is needed, and not till then is the ``IL_scope`` pointer in +the scope stack entry updated. + +The scope stack entries for the file scope, namespaces, classes, routines, and +blocks are closely tied to a corresponding intermediate language scope entry: +the latter has pointers to the lists of types, variables, etc. for that scope, +and the pointers block has the pointers to the ends of those lists. The +pointers block in the scope stack entry is used for all scopes except for +namespace and namespace extension scopes, for which the pointers block is +located in the namespace symbol supplement. These tail pointers are only +needed while the scope is active, to add entries at the end of the list, and +having them in the pointers block reduces the size of the intermediate language +scope entry. + +Classes +======= + +Classes (in the generic sense, including structs and unions) require the +management of quite a lot of information. Some of this must reside in the +intermediate language. For instance, the entities that represent members of a +class are kept on lists pointed to from the intermediate language scope entry +associated with the class; and the base classes from which the class is derived +are associated with the class's type entry. In these and other cases +information associated with a class is stored in intermediate language +declarative constructs, and appropriately so, since the information is of use +to back ends. + +However, there is a great deal of information that the front end needs but back +ends do not care about, and it would be wasteful to store it in the +intermediate language. Instead, it is kept in the symbol table so that it can +be thrown away when front-end processing is complete. + +Class Symbol Supplement +----------------------- + +Entities of type ``a_class_symbol_supplement``, pointed to from all class, +struct, and union tag symbols, constitute the main repository for +front-end-only information about classes. + +Among the fields in class symbol supplements are: + +* | ``symbols``, the symbol list pointed to from the scope stack entry for the + class, retained even after the scope stack entry disappears. The symbols + are in declaration order, which is the order in which initialization is to + be performed. +* | ``constructor``, a pointer to the ``sk_member_function`` or + ``sk_overloaded_function`` symbol that represents the constructor(s) for + the class. As noted above, the constructor symbol cannot be accessed + directly by normal name lookup, but only via this pointer. +* | ``destructor`` and ``assignment_operator``, pointers to the symbols + representing the destructor and ``operator=()`` functions for the class. + Both could also be accessed by normal name lookup, but having the pointers + directly available makes some processing, especially implicit invocations + of these functions, more efficient and facilitates deciding whether the + compiler needs to generate one. +* | ``conversion_list``, a linked list of entries that provide quick access to + the symbols for the user-defined conversion functions for the class (i.e., + that define a conversion from the class to some other type). The list + includes symbols for inherited conversion functions. +* | ``routine_fixup_list``, a pointer to entities that store cached tokens to + allow for delayed scanning of default arguments and the bodies of member + functions that are defined inline. + | + | ``operator_lookup_namespaces``, a pointer to a list of namespaces that are + the parent namespaces of the class or one of its base classes. The global + scope is explicitly represented on this list by an entry with a NULL + namespace pointer. This list is used to specify the namespaces to be + searched for operator functions when an overloaded operator function is + called with an operand of the class. +* | A number of flags to summarize attributes of the class. Most of these + flags are redundant -- the attributes could also be computed by examining + other data. For instance, ``any_ref_member`` is checked when putting out + warnings on variables that should be initialized; its value could also be + determined by looking at all the nonstatic data members to see if any have + reference types. + +Class Member Projection Symbols +------------------------------- + +Symbols of kind ``sk_projection`` provide a mechanism to represent names that +are visible in a derived class having been declared in a base class. Each +projection symbol has a supplementary entity of type ``a_projection_descr`` +which identifies the fundamental base class member by pointing to the base +class entry and to a symbol from that base class. [#f5]_ + +Projection symbols are created as needed (in the course of looking up a name) +and are added to the scope of the derived class. Once entered in a class +scope, they permanently associate the name in the derived class with a +declaration in a base class. The next time the name is looked up in the +lexical context of the class, the projection symbol will be found directly, +without the more expensive search of the base classes. + +A projection symbol records a name's accessibility in the current scope (e.g., +it may have been declared ``public`` originally but be less accessible in the +context of the derived class). It also notes whether a name is ambiguous. +These attributes of name inheritance are computed on the initial lookup, when +the projection symbol is created, and thus need not be recomputed on subsequent +references to the name. + +Projection symbols are also used to represent base class member names that are +explicitly incorporated into the derived class by means of a +``using``-declaration; for these cases the flag ``is_using_decl`` is set to +TRUE. + +When a ``using``-declaration in a derived class specifies an overloaded member +function from a base class, each member of the original overload set will be +projected into the base class independently and recorded in an overload set +created in the derived class. The latter may contain a mix of +``sk_member_function`` symbols from the derived class and ``sk_projection`` +symbols referring to member functions in one or more base classes. For +example: + +.. code:: c++ + + struct A { + void f(int); + void f(); + }; + struct B { + void f(double); + }; + struct C : public A, public B { + using A::f; + using B::f; + void f(char); + }; + +Here, the overload set for ``C::f`` will include ``C::f(char)`` along with +projections into ``C`` of ``A::f(int)``, ``A::f()``, and ``B::f(double)``. + +On the other hand, when ``is_using_decl`` is FALSE in an ``sk_projection`` +symbol, the projection may refer to an entire overload set and not to any +particular instance of the name. In such cases the ``access`` value will +represent the greatest access available; a particular function may turn out to +have less accessibility. + +Namespace Projection Symbols +---------------------------- + +Symbols of kind ``sk_namespace_projection`` are used to represent names made +visible by ``using``-declarations that refer to namespace members +(``using``-declarations that refer to class members are described above). As +with class member ``using``-declarations, when a ``using``-declaration +specifies a overloaded function from another namespace, each member of the +overload set is projected into the current scope separately. The resulting +overload set may contain a mix of function, function template and namespace +projection symbols. + +Template Symbols +================ + +Symbols of kind ``sk_class_template`` and ``sk_function_template`` have an +associated entry of kind ``a_template_symbol_supplement``. Template processing +is discussed in detail in another chapter. + +Namespace Symbols +================= + +Symbols of kind ``sk_namespace`` have an associated entry of kind +``a_namespace_symbol_supplement``. As described above, the namespace symbol +supplement contains the pointers block used by scope stack entries that refer +to the namespace. It is possible for more than one scope stack entry for a +namespace or namespace extension scope to refer to a single namespace. In such +cases the scope stack entries all refer to the one pointers block structure in +the namespace symbol supplement. The namespace symbol supplement also contains +information used by the name lookup routines when doing lookups in the presence +of ``using``-directives. + +Symbol Lookup +============= + +Symbol Locator +-------------- + +Symbol lookup is the process whereby a name, a qualified name, an operator +token, or a conversion result type is used to search for a symbol in the symbol +table and, if it exists, return it to the caller. A key intermediary construct +in this process is the entity of type ``a_symbol_locator``. It consists of + +* | A pointer to a symbol header. (Sometimes error locators have a NULL symbol + header pointer; in all other cases a locator will point to a valid symbol + header.) +* | A source position, the line and column in the source program at which the + reference starts. +* | ``specific_symbol``, a pointer to a symbol. This is usually NULL, but if + preliminary processing happens to turn up a symbol (e.g., in validating a + qualified name), it is saved here so that the lookup need not be done + again. +* | The ``is_qualified_name``, ``is_global_qualified_name``, + ``is_file_scope_qualified_name``, and ``is_super_qualified`` flags, which + specify the kind of qualifier, if any, that preceded the name. +* | ``is_class_member``, a flag that is TRUE for qualified names for which the + qualifier names a class. Note that the qualifier may also contain a + namespace specifier, but the last qualifier specifies a class name. +* | ``parent``, a union that, for qualified names, contains a pointer to either + the class or namespace specified by the qualifier. The ``is_class_member`` + field is used to specify whether the qualifier is a class or a namespace. + This field is also used to specify the class type associated with a vacuous + destructor reference. +* | ``The is_template_id`` flag is TRUE if the name was followed by a template + argument list that has been coalesced. If the name is a class template + name, the ``specific_symbol`` will point to the template class designated + by the template argument list. The ``do_not_clear_specific_symbol`` flag + is set to TRUE when a class template argument list is coalesced because the + template argument list is not retained in the locator, and it would be + impossible to recompute the ``specific_symbol`` value if it were cleared. +* | ``template_arg_list`` is used when an explicit function template argument + list is specified, and points to the template argument list that was + scanned. The ``is_template_id`` flag is also set. An empty template + argument list may be specified (e.g., "``<>``"), so the ``is_template_id`` + flag should be used to check for the presence of an explicit function + template argument list, not the ``template_arg_list`` field. +* | The ``is_operator_name`` flag and the operator name kind. This flag is + TRUE and the associated field is defined only when it is an operator name + that is being looked up. +* | The ``is_conversion_name`` flag and the conversion result type. This flag + is TRUE and the associated field is defined only when it is a user-defined + conversion that is being looked up. +* | The ``is_destructor_name`` flag is TRUE when the name is a destructor name. +* | The ``is_vacuous_destructor_reference`` and ``is_nonclass_destructor`` + flags, which are used to identify explicit destructor references for + classes without destructors or for nonclass types. +* | The ``is_semivisible_nested_class`` flag is TRUE when the name is not + visible by standard scoping rules but only by a special search that + implements the "nested class anachronism" (ARM 18.3.5). +* | The ``access_control_error_reported`` flag is TRUE if an accessibility + error has already been issued on the symbol. +* | The ``is_error`` flag is TRUE when the locator represents an error. +* | The ``do_not_clear_specific_symbol`` flag is TRUE if the + ``specific_symbol`` points to a value that should be retained because it + cannot or should not be reproduced by a repeated lookup. This is primarily + used for coalesced class template references, as described above, but is + also used for specific symbol error locators (error locators that refer to + a specially created error symbol). + +Symbol locators are necessary because symbol lookup sometimes occurs in several +stages at separate points of processing. They provide a way to save and use +the intermediate results. For instance, when an identifier is scanned by +``get_token``, the locator is stored in ``locator_for_curr_id``. Often a local +copy is made so that the information can be preserved as additional tokens are +scanned. Then when it comes time to actually enter the symbol in the symbol +table, all the information needed is right there in the locator. + +Identifiers and Symbol Headers +------------------------------ + +Each name in the source program is looked up as it is scanned. This is +necessary in part so that ``get_token`` processing can distinguish identifiers +from keywords. + +``find_symbol`` is called to look up the names in the hash table pointed to by +global variable ``symbol_table``. The interface to ``find_symbol`` uses a name +string with a length rather than a null-terminated string because the string in +question is usually part of the source line buffer. + +After the bucket number is computed, it searches the list of symbol headers +pointed to by the bucket till it finds a matching name. If it finds a match, +it moves the symbol header to the front of its bucket list so that +frequently-used entries will cluster near the beginning. If no match is found, +a new symbol header is created and entered. A pointer to the symbol header +(whether newly created or not) is returned in the symbol locator, and a pointer +to the list of active symbols associated with the symbol header is also +returned. + +``normal_id_lookup`` +-------------------- + +``find_symbol`` locates a symbol header but does not actually find the symbol +itself. For simple names (e.g., not qualified names) that is done by +``normal_id_lookup``, which searches the symbol header's active list -- and, if +appropriate, its inactive list -- to find a symbol in the appropriate name +space and lexical scope. + +``normal_id_lookup`` uses one of two search algorithms. The fast search (which +is the only one used in ordinary C mode) simply searches the active list: the +first symbol found which meets the search requirements is returned; in C++ mode +this search may only be used when there are no scopes on the scope stack that +alter the sequence in which scopes are considered for name lookup, and when the +lookup is not one of a number of special lookups that disregard certain kinds +of symbols. + +The second and slower algorithm is required when + +* | A class or class reactivation scope is present, in which case one must look + for inactive symbols for the class members and for member names that are + inherited from base classes. +* | A namespace, namespace extension, or namespace reactivation scope is + present, in which case one must look for inactive symbols for the namespace + members. +* | A template instantiation scope is present, in which case inactive symbols + for the template parameters must be considered, and the scopes must be + searched in an irregular order (as described earlier). +* | A ``using``-directive is in effect, in which case one must look for symbols + for the namespaces referenced directly or indirectly by the + ``using``-directive. +* | A special lookup option has been specified for a given lookup. For + example, the lookup may optionally ignore class scopes, etc. + +In such cases each scope must be considered individually, since there is no +single list that summarizes the visibility of names. + +This comes up, for instance, in the non-inline definition of a member function: +the class definition has been completed and its names have been removed from +the active list, so those names must be searched for on the inactive list. For +example, + +.. code:: c++ + + int i; + struct S { int i; int f(); }; + int S::f() { return i; } + +Here, when the body of ``S::f()`` is being scanned, the symbol for ``::i`` will +be on the active list of the symbol header for ``i``, whereas the symbol for +``S::i`` will no longer be in scope, having been moved over to the inactive +list when the definition of ``S`` was completed. However, since the scope for +``S`` is reactivated before the member function body is scanned, and since the +reactivated scope is examined before the file scope, it is ``S::i`` rather than +``::i`` that will be found. + +Similarly, when a namespace member is defined outside of its namespace a +namespace extension scope is pushed onto the scope stack at the point at which +names from the namespace should be visible. + +.. code:: c++ + + int i; + namespace N { int i; int f(); } + void N::f() { return i; } + +Here, as with the class member example shown above, the namespace member +``N::i`` is found, hiding ``::i``. + +Slow Lookup Processing (``scope_stack_lookup)`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``scope_stack_lookup`` and the routines it calls are used to implement the slow +lookup. It is passed a range of scope depths to be included in the lookup. +Each scope is examined separately. The lookup begins with the scope stack +entry indicated by the global variable ``depth_of_initial_lookup_scope`` and +proceeds by following the ``previous_scope`` link in the scope stack entry +until a scope entry with no previous scope is found. ``active_scope_lookup`` +is called for scopes whose symbols are still on the active list and +``inactive_scope_lookup`` is called for scopes whose symbols have been +transferred to the inactive list. When a class or class reactivation scope is +processed, a flag is returned that specifies whether ``scope_stack_lookup`` +should look for a projection symbol for the class as described below. + +When a template instantiation scope has been processed, and a symbol has not +yet been found, names from both the context in which the template was defined +and from the context in which the template was used must be considered. This +is done by calling ``instantiation_context_lookup``, which is described below. + +A ``using``-directive can cause names from other namespaces to be visible in a +namespace scope (including the global scope) that is currently on the scope +stack. The ``using_directives_apply`` flag in the scope stack entry is used to +indicate that such processing is required. When this flag is set for a +namespace scope or the global scope, ``do_using_directive_lookup`` is called to +search for applicable symbols from namespaces named in ``using``-directives. + +The presence of ``using``-directives can result in more than one symbol +being found that satisfies the lookup. In such cases +``do_using_directive_lookup`` creates a synthesized namespace projection +symbol that represents the set of symbols found (See :ref:`using-dir` and +:ref:`namespace-proj`). The lookup could determine that the name is +ambiguous in the current context, in which case a synthesized namespace +projection symbol that is flagged as ambiguous is returned. + +Looking for Class Member Projection Symbols +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a name is not found in a class, the classes from which it is derived must +be searched before the containing scope is examined. This is done by +``find_projected_symbol``, which looks for the name among the base classes (see +``find_progenitor_symbol`` and ``symbol_projected_from_base_class``) and if +successful creates an ``sk_projection`` symbol in the derived class and adds it +to either the active or the inactive list of the symbol header for the name. A +pointer to the projection symbol, which (as described previously) represents +the inheritance, is returned to ``normal_id_lookup``, where it is placed in the +locator (field ``specific_symbol``); a pointer to the symbol of which it is the +projection is returned from ``normal_id_lookup`` as the function return value. +Consider this example: + +.. code:: c++ + + int i; + struct S { int i; }; + struct T : public S { int f(); }; + int T::f() { return i; } + +In this case the scope for ``T`` is reactivated when the body of ``T::f()`` is +scanned. No ``T::i`` is found in the scope of ``T``, but before the containing +scope (namely the file scope) is searched, the base class must be examined, and +so ``normal_id_lookup`` calls ``find_projected_symbol``. This search turns up +``S::i``, so again ``::i`` is eclipsed. In addition, a projection symbol for +``i`` is created in class ``T`` (it points to ``S::i`` since it represents the +"projection" of ``i`` from ``S`` into ``T``). Thus, on subsequent searches for +``i`` in the scope of ``T`` a ``T::i`` *will* be found, namely the projection +symbol referring to ``S::i``, and so the base class search will not have to be +repeated. + +``find_projected_symbol`` and its subroutines also compute the accessibility of +the inherited name and determine whether it is ambiguous. No errors are put +out at this point, since the name lookup routines are interested in name +*visibility* only; instead, the status is recorded in the projection symbol and +diagnostics can be issued later if appropriate. + +.. _instantiation-context-lookup: + +Instantiation Context Lookup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a name is looked up as part of a template instantiation, and the name is +not found in the local context of the instantiation (the template parameters +and the scope(s) associated with the class or function being instantiated) it +must be looked up in the instantiation context. The front end implements two +different instantiation context lookup algorithms: the one mandated by the +standard (referred to as "dependent name lookup"), and the one that existed +before dependent name lookup was implemented that more closely reflects +existing practice and is more compatible with other compilers. + +As described earlier, ``push_template_instantiation_scope`` configures the +scope stack so that three distinct contexts exist outside of the local context +of the instantiation: the template definition scopes, the referencing context +scopes, and the scopes common to both. + +When doing dependent name lookup, the following steps are used to produce the +final result of the lookup: + +* | The name is looked up in the context of the template definition and only + names visible at the point of the template definition are considered. +* | Only those base classes that do not depend on template parameters are + considered. + +When not doing dependent name lookup, the following steps are used to produce +the final result of the lookup: + +* | The name is looked up in both the template definition context and the + referencing context by calling ``scope_stack_lookup`` with the appropriate + starting and ending scope depths. The lookup in the referencing context is + suppressed if the lookup in the definition context finds a class member. +* | If none or only one of the lookups produces a symbol, and if the lookup in + the definition context did not find a class member, ``scope_stack_lookup`` + is called again to look in the common scopes. +* | If no symbols were found by the two context lookups, the result of the + common scope lookup is used. +* | If only one of the two context lookups produced a symbol, the result of the + common scope lookup is used as the value of the context lookup that did not + produce a symbol, and the next rule is followed. +* | If the symbol from the referencing context is not a function or function + template, it is discarded. +* | If there is still only one symbol from the two context lookups, that symbol + is used. +* | If there are two symbols, a synthesized namespace projection symbol is + created that represents the result of the lookup. + +Note that in both cases, these algorithms describe the result of the "normal" +lookup of the name. In addition to the entities made visible by the normal +lookup, additional functions and/or function templates may be made visible by +argument-dependent lookup. + +Nested Class Anachronism Lookup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the processing described thus far in ``normal_id_lookup`` fails to find a +qualifying symbol, an additional search implementing the "nested class +anachronism" (ARM 18.3.5) is performed by calling ``find_nested_class_symbol``, +which finds names of nested classes which, strictly speaking, should not be +visible. For example, + +.. code:: c++ + + struct S { + struct T { + int a; + }; + int b; + }; + struct T x; + +After the normal search for ``T`` is exhausted without turning up a symbol, an +additional search is made through the inactive list of the corresponding symbol +header for a symbol of a nested class whose innermost non-class containing +scope (in this case, the file scope) is still an active scope (in this case, it +is). When such a symbol is found, and it is the only symbol that qualifies, it +is returned to ``normal_id_lookup`` and a warning is issued. [#f6]_ + +Nonreal and Proxy Class Lookup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the processing described thus far in ``normal_id_lookup`` fails to find a +qualifying symbol, and one or more of the classes included in the lookup has a +"nonreal" base class, a nonreal class member is created by calling +``add_member_to_proxy_or_nonreal_class``, and the symbol for the newly created +class member is returned. + +.. code:: c++ + + typedef int Y; + template struct A : T { + X x; // assumed to be T::X + Y y; // ::Y + }; + +The nonreal lookup is only done when the normal lookup fails to find a symbol. +In the example above, ``::Y`` is found, so no nonreal member is created. The +lookup of ``X`` fails to find a symbol, so a nonreal member is created. + +Hide-by-sig lookup +^^^^^^^^^^^^^^^^^^ + +C++/CLI has a special kind of lookup used for members of managed classes, +called "hide-by-sig" lookup. In normal C++ name lookup, a name in a derived +class hides all instances of the same name in a base class; this is called +"hide-by-name" lookup. In hide-by-sig lookup, on the other hand, a member +function in a derived class hides a member in a base class only if their +signatures match. A function "``void``\ ``f(int)``" in a derived class, for +example, would not hide a function "``void``\ ``f(char)``" in a base class; +both would appear in an overload set and might compete with each other. In +addition, hide-by-sig lookup considers access -- inaccessible members of base +classes are not seen by the lookup. And there are special rules regarding +interfaces, which are too arcane to describe here. Hide-by-sig lookup only +applies to functions. + +Hide-by-sig lookup is implemented by building a list of +``a_hide_by_sig_list_entry``\ s that enumerates all the symbols that co-exist +with a given symbol in an overload set. The list is built by +``use_hide_by_sig_lookup`` and saved in the symbol's +``hide_by_sig_lookup_result`` field so it only needs to be constructed the +first time a hide-by-sig lookup is done on the symbol. Overload resolution +traverses that list to build up the set of functions in an overload resolution +set. Access is checked while the overload set is built up, and inacessible +functions are discarded at that point (different places in the program may have +differing access to the base class members; this allows a single general +hide-by-sig list to be built and then used with different access contexts). + +Lookup of Entities Imported from C++/CLI Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When C++/CLI metadata files are imported by way of a ``#using`` directive or +implicitly for the entities in ``mscorlib``, only the namespace-scope-level +names in the file are added to the symbol table. For a class, for example, the +class name is entered as an incomplete type, and its definition and members are +not immediately entered. Later, if a lookup is done in the class scope, the +members of the class are fetched from metadata and added to the symbol table. +This "lazy" lookup makes the use of metadata files much more efficient, since +things are not loaded until they are actually needed. This is implemented by +piggy-backing on the mechanism that instantiates templates when a member of the +template is required: ``f_instantiate_template_class`` (often invoked from the +macro ``complete_class_type_is_needed)``\ will call ``get_definition_of_class`` +to fill in the definition of an entity imported from metadata. This is done +automatically whenever a class-scope lookup is done in a class that came from +metadata. The definition is loaded, the lookup is then done, and the result is +returned to the caller, who has no need to know that the class definition had +to be loaded to be able to perform the name lookup. + +C mode out-of-scope declarations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When compiling C code, if the processing described thus far in +``normal_id_lookup`` fails to find a qualifying symbol, +``find_out_of_scope_declaration`` is called to look for an external variable or +function that was declared in a scope that is no longer visible. If such a +symbol is found, it is reentered in the current scope and returned as the +result of the lookup. + +.. code:: c++ + + void g1(void) { + extern void f(int); + f(1); + } + void g2(void) { + f(2); + } + +A symbol for ``void f(int)`` is reentered in ``g2``, even though ``f`` is no +longer visible. This lookup is not performed in strict mode. + +Lookup Options +^^^^^^^^^^^^^^ + +Options flags may be supplied to ``normal_id_lookup`` that affect the kinds of +symbols that are visible and other aspects of the name lookup process. In +certain contexts a name lookup is required to determine whether a given name is +a type. In this context a projection symbol should not be created unless the +name is a type. The flag ``IDL_TENTATIVE_TYPE_LOOKUP`` is used to suppress the +creation of a projection symbol in this instance. + +A special lookup is also required when scanning a constructor initializer list +that may include member names and base class names but may not reference the +names of parameters of the constructor. The ``IDL_SKIP_CURR_FUNCTION_SCOPE`` +flag is used to request this kind of lookup. + +``IDL_LINKAGE_LOOKUP`` indicates that the lookup is being used to find a +previous declaration of a name and that certain special lookup features should +be suppressed and that the lookup should terminate at the nearest enclosing +namespace scope. This option suppresses nested class anachronism, nonreal +member lookup, and out-of-scope declaration processing. + +``IDL_SKIP_CLASS_SCOPES`` causes class and class reactivation scopes to be +ignored. This is used when looking up nonmember operator functions. + +``IDL_INSTANTIATION_CONTEXT`` is used to indicate that a lookup operation is +part of a special instantiation lookup that looks in both the template +definition and reference contexts. + +Looking Up Names in the Current Scope +------------------------------------- + +``curr_scope_id_lookup`` looks up a name in the current scope and returns the +symbol found or NULL if no symbol is found. The symbol must be a name declared +in the scope. ``using``-directives are not considered and projection symbols +to base class members are not considered unless the +``IDL_PROJECTION_SYMBOL_ALLOWED`` option is specified. + +Looking Up Class Members +------------------------ + +``class_qualified_id_lookup`` is used to look up a name in the scope of a class +and its base classes. As with ``normal_id_lookup``, the caller provides a +symbol locator that contains a pointer to the symbol header for the identifier +being looked up. The search begins by looking through the inactive list for a +symbol from the scope associated with the class type passed by the caller. If +the symbol is not found on the inactive list, the active list is also checked. +The active list check is needed when a class-qualified lookup is done while the +class is being defined. For example, + +.. code:: c++ + + struct A { + struct B {}; + A::B f(); // the A:: is not necessary, but is allowed + }; + +If the symbol has still not been found, and the lookup is being done in a +nonreal class, a symbol for a nonreal class member is created by calling +``add_member_to_proxy_or_nonreal_class``, and the newly created symbol is +returned (see :ref:`nonreal-and-proxy-members` for more information). + +If the symbol has still not been found, the name is checked to see if it is a +constructor or destructor for the class. If so, the symbol for the constructor +or destructor from the class symbol supplement is returned. + +Finally, if the symbol has still not been found, ``find_projected_symbol`` is +called to search the base classes for a member that may be projected into the +class. + +.. _nonreal-and-proxy-members: + +Nonreal and Proxy Class Members +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A nonreal class is a template class that has one or more template arguments +that depend on template parameters. A proxy class is a class that stands in +for a template parameter when that template parameter is used in a context that +requires a class type. For example: + +.. code:: c++ + + template struct A { + typename T::A a; + typename A::X b; + typename T::Z c; + int n[T::B]; + }; + +In this example a proxy class is created for ``T`` so that ``A`` and ``B`` may +be looked up in ``T``. A nonreal class for ``A`` is created, a nonreal +template named ``T::Z`` is created, and the nonreal instance ``T::Z`` is +created. + +``proxy_class_for_template_param`` creates a proxy class associated with a +given template parameter. The proxy class is created the first time that it is +needed + +``create_proxy_or_nonreal_class_member`` creates a member of a nonreal or proxy +class. It is called by ``add_member_to_proxy_or_nonreal_class`` which also +adds the newly created symbol to the inactive list so that it may be found by +subsequent lookups. The kind of entity that is created (type, constant, or +template) depends on the kind of lookup that is done, and on whether the +"implicit typename" option is enabled. ``nonreal_member_symbol_kind`` is used +to determine the kind of symbol to be created for a given set of lookup +options. + +Looking Up Namespace Members +---------------------------- + +``namespace_qualified_id_lookup`` is used to look up a name in the scope of a +namespace. If the name is not found in the namespace, the name is also sought +in any namespaces referenced by ``using``-directives in the specified +namespace. ``lookup_in_namespace`` is called to look for the name in the +specified namespace. If a symbol is found, it is returned; otherwise +``lookup_in_namespace`` calls ``qualified_using_directive_lookup``, which loops +though the ``using``-directives found in the original namespace and calls +``lookup_in_namespace`` recursively to look for the name in those namespaces. +``qualified_using_directive_lookup`` always considers all namespaces named in +``using``-directives within a given namespace (i.e., it does not stop searching +when a symbol is found in a given namespace). For example, the hierarchy below +would be created by the following example: + +.. code:: c++ + + // D E + // \ / + // B C + // \ / + // A + namespace E { } + namespace D { } + namespace C { using namespace E; } + namespace B { using namespace D; } + namespace A { using namespace B; using namespace C;} + +In such a hierarchy, when looking up a name in namespace ``A`` + +* | If the name is found in ``A``, the lookup will not look in any other + namespace. +* | If the name is not found in ``A``, the lookup will always look in both + ``B`` and ``C``. +* | If the name is not found in ``B``, the lookup will look in ``D``. +* | If the name is not found in ``C``, the lookup will look in ``E``. + +The presence of ``using``-directives can result in more than one symbol +being found that satisfies the lookup. In such cases +``qualified_using_directive_lookup`` creates a synthesized namespace +projection symbol that represents the set of symbols found (see +:ref:`using-dir` and :ref:`namespace-proj`). The lookup could determine +that the name is ambiguous in the current context, in which case a +synthesized namespace projection symbol that is flagged as ambiguous is +returned. + +When a namespace contains an inline namespace (a C++11 feature), or a namespace +named in a GNU strong using-diirective, namespace lookup is done slightly +differently. Normally, if a name is found in a namespace, other namespaces +made visible in that namespace by using-directives are not searched, but a +namespace was made visible as an inline namespace (or strong using-directive) +is searched even when a symbol was found in the original namespace. + +Looking Up Names in the File Scope +---------------------------------- + +The file scope is also known as the global scope, and, with the addition of +namespaces, as the "global namespace". The same qualified name lookup rules +apply to both namespace qualified lookups and file scope qualified lookups. +``file_scope_id_lookup`` looks on the active list for a name declared at the +file scope. If the name is not found on the active list, the inactive list is +seached. If the name is not found in the file scope, +``qualified_using_directive_lookup`` is called to look in scopes named by +using-directives in the file scope. + +In the presence of multiple translation units there can be more than one file +scope. The scope pointer for the file scope to be used is passed to +``file_scope_id_lookup``. + +Argument-Dependent Lookup +------------------------- + +When an unqualified name is used as the function name in a function call, the +name is looked up using both the normal lookup mechanism and also using what is +known as "argument-dependent lookup". Argument-dependent lookup uses the types +of the function arguments to produce a set of "associated classes" and +"associated namespaces" to be searched for candidate functions. + +``argument_dependent_lookup`` is called to perform an argument-dependent +lookup. It calls ``determine_assoc_namespaces_and_classes`` to determine the +associated namespaces and classes to be used for the lookup. Normally, only +names from the current translation unit are considered by the +argument-dependent lookup process, but when instantiating exported templates +(and non-exported templates whose instantiation results from the instantiation +of an exported template) argument-dependent lookup is done in each of the +translation units on the translation unit stack and the results of the lookups +are combined. + +Argument-dependent lookup returns a list of symbols representing the candidate +functions being found. The symbol list may contain functions, function +templates, and overload sets. Argument-dependent lookup is normally done in +conjunction with a normal lookup. The symbol representing the normal lookup +result is passed to ``argument_dependent_lookup`` and is returned as an element +of the resulting symbol list. The resulting symbol list may directly or +indirectly (as part of an overload set) include multiple instances of a given +function or function template. This occurs for several reasons: + +* | The symbol list includes the result of both the normal and + argument-dependent lookups, which may produce overlapping results. +* | The symbol list includes overload sets which may, as a result of + using-directives, include the same functions or function templates. +* | The argument-dependent lookup may be done in multiple translation units + when exported templates are used. The same functions or templates may be + found in more than one of the translation units. + +.. _using-dir: + +``using``-Directive Processing +------------------------------ + +``using``-directives are used to make names from a namespace visible at a +certain point in the unqualified lookup process (i.e., the lookup performed by +``normal_id_lookup``). ``using``-directives that appear in namespace scopes +can also affect qualified lookups in the namespace in which they appear. +Qualified ``using``-directive lookups simply make use of the +``using``-directives list found in the scope entry. Unqualified +``using``-directive lookups, on the other hand, rely on additional data +structures that are maintained to optimize the process of finding names made +visible by ``using``-directives during the ``normal_id_lookup`` process. + +A ``using``-directive can appear in a namespace scope (including the files +scope), or in a block scope. The scope that contains the ``using``-directive +is often not the scope at which the ``using``-directive "applies", however. A +``using``-directive "applies" at the nearest enclosing scope that is or +contains the namespace named in the ``using``-directive, and contains the +``using``-directive. For example, + +.. code:: c++ + + namespace A {} + namespace B { + namespace C { + using namespace A; // applies to the file scope + } + using namespace C; // applies to B + } + using namespace B::C; // applies to the file scope + +The primary piece of information that is maintained to optimize unqualified +``using``-directive lookups is a field in the namespace symbol supplement that +indicates the scope depth of the scope at which a ``using``-directive for that +namespace applies, or contains ``NO_SCOPE_DEPTH`` if there is no +``using``-directive in effect that makes symbols from the associated namespace +visible. + +``do_using_directive_lookup`` simply looks through the inactive symbols for a +symbol whose parent namespace has a ``using``-directive that applies at the +scope depth currently being processed by ``scope_stack_lookup``. + +The problem with this kind of state information is that it needs to be reset +each time a template instantiation begins and restored each time an +instantiation ends. To make the process of clearing and restoring the state +information as efficient as possible, the scope stack entry contains a list of +"active" ``using``-directives for the scope. An active ``using``-directive is +one that appeared in the scope or appeared in one of the namespaces named by a +``using``-directive in the scope. + +When a ``using``-directive appears, ``add_active_using_directive`` is called to +add it to the active ``using``-directive list for the current scope. It then +calls ``add_active_using_directive_to_scope``, which actually adds it to the +list. + +``using``-directives are transitive, meaning that any ``using``-directives that +appear in the namespace nominated by a ``using``-directive are treated as if +they also appeared in ``using``-directives in the scope containing the original +``using``-directive. ``add_active_using_directives_for_namespace`` is called +to add the namespaces that appear in ``using``-directives in the nominated +namespace to the active ``using``-directive list, which it does by recursively +calling ``add_active_using_directive_to_scope``. When +``add_active_using_directive`` adds a ``using``-directive to a namespace scope +it searches through the scope stack to find active ``using``-directive lists +that refer to the namespace containing the new ``using``-directive. If such +scopes are found, ``add_active_using_directive_to_scope`` is called to add the +newly nominated namespace to those scopes. + +``add_active_using_directive_to_scope`` determines the scope depth at which a +``using``-directive applies. This scope depth is recorded in the namespace +symbol supplement of the namespace being added. The scope stack entry +associated with that scope depth is updated to indicate that there are +``using``-directives that apply when that scope is reached in an unqualified +lookup. + +``set_active_using_list_scope_depths`` is called to reset and restore the state +of the scope depth information in the namespace symbol supplement and the +``using_directives_apply`` field in the scope stack entry. This is done at the +beginning and end of a template instantiation scope, and is also done whenever +a scope containing active ``using``-directives is popped off of the stack. + +.. _namespace-proj: + +Synthesized Namespace Projection Symbols +---------------------------------------- + +The addition of namespaces creates situations in which the result of a lookup +can be a set of symbols from different scopes. A synthesized namespace +projection symbol is created to represent the result of such a lookup. +Synthesized namespace projection symbols are created + +* | by an unqualified lookup in which the symbols found were made visible by a + ``using``-directive, +* | by an qualified lookups in which the symbols found were made visible by a + ``using``-directive, and +* | by an instantiation context lookup in which symbols were found in both the + definition and referencing contexts. + +The ``synthesized_namespace_projection`` flag in the symbol entry identifies a +symbol as a synthesized namespace projection. Such symbols can be of kind +``sk_namespace_projection`` or ``sk_overloaded_function``. In the latter case, +each of the entries on the list of overloaded functions points to a +``sk_namespace_projection`` symbol. + +Where synthesized namespace projection symbols are used, the lookup must result +in at most one symbol being found, or, all of the symbols found must be +functions that can be combined into an overload set. If more than one symbol +is found and they are not all functions, the lookup is ambiguous. The +``ambiguous`` flag in the symbol entry is set in that case. + +The following steps are used to construct a synthesized namespace projection +symbol for a given lookup: + +#. ``find_synthesized_projection_symbol`` is called to find a previously + created namespace projection symbol. This is done so that the space used + by a previously created synthesized projection symbol can be reused. + The actual information pointed to by the symbol is not reused because it + may have changed since the last lookup was done. More specifically, a + set of overloaded functions is assumed always to contain at least the + functions that were previously in the set. When looking for a previously + created symbol, the lookup options used for the new lookup must match + the options used when the symbol was created. A number of symbols with + the same name but with different lookup options may be created in a + given scope. Some combinations of lookup options are considered to be + sufficiently unusual that they are not entered in the symbol header for + reuse. Such symbols are identified by setting the ``do_not_reuse`` flag in + the symbol entry. ``find_synthesized_projection_symbol`` suppresses the + search and returns NULL when asked to find a symbol with a set of lookup + options for which symbols cannot be reused. The lookup options used when + a synthesized namespace projection symbol is created are stored in a set + of flags in the symbol entry. The flags used for this purpose are + + * | ``qualified_lookup`` + * | ``must_be_class_or_namespace_lookup`` + * | ``must_be_tag_lookup`` + * | ``tentative_type_lookup`` + * | ``do_not_reuse`` + * | ``instantiation_context_lookup`` + +#. | As symbols are found that match the lookup criteria, + ``add_symbol_to_lookup_set`` is called with a pointer to the previously + created synthesized projection symbol (if any) and the symbol to be added. + The symbol returned is used as the new synthesized projection symbol. +#. | ``add_symbol_to_lookup_set`` calls ``merge_function_into_lookup_set`` + when the symbol being added is a function or function template. Before a + function is actually added, the current lookup set is examined, by calling + ``already_in_lookup_set``, to make sure it is not already present. +#. | ``add_symbol_to_lookup_set`` determines whether the symbol being added + can coexist with any symbols already in the lookup set, whether the new + symbol should hide a previous symbol, or whether the lookup is ambiguous. + +Reusable synthesized projection symbols are entered on the "other" symbols list +in the symbol header and on the ``synth_namespace_projection_symbols`` list in +the pointers block for the scope with which they are associated. Symbols that +are not reusable are only entered on the list in the pointers block. +Synthesized projection symbols that are created by a qualified lookup are +entered in the scope of the namespace of the qualifier. All other synthesized +projection symbols are entered into the current scope. + +Overloaded Operators +-------------------- + +Overloaded operators are not looked up by name, so ``find_symbol`` cannot be +used to locate the symbol header. Instead, the header is found by indexing +into the array of symbol header pointers ``opname_symbol_table``. The index +value will be a member of the enumeration ``an_opname_kind``, which maps to the +subset of the enumeration ``a_token_kind`` that comprises those operators +subject to overloading. [#f7]_ + +When an overloaded operator is explicitly named (for instance, ``operator+`` or +``A::operator new``), it is represented by a ``tok_identifier`` "pseudo-token" +somewhat like qualified names. The symbol locator's ``is_operator_name`` flag +will be set and the field ``opname`` will identify the operator being +overloaded. ``make_opname_locator`` is called to set these fields and as well +to create and enter the symbol header if one does not yet exist. Scanning the +token sequence representing an overloaded operator is handled by +``f_get_opname`` , [#f8]_ which does error checking and also deals with +conversion operators (discussed below). + +``nonmember_operator_function_lookup`` is used to find the set of nonmember +overloaded operator functions for a given operator kind and a pair of operand +types. When looking for a nonmember operator function, one must do a normal +(i.e, unqualified) lookup of the operator name, and one must also look up the +operator name in the namespaces of the operand types and the base classes of +the operand types. For each class type, there is a list of namespaces in which +to look for nonmember operator functions. The list is pointed to by the +``operator_lookup_namespaces`` field of the class symbol supplement. The +search is done by looking at both the active and inactive lists from the +appropriate symbol header and checking whether the parent namespace of the +symbol is on the operator lookup namespaces list of one of the operand class +types. Note that only immediate members of the namespaces on the operator +lookup namespaces list are considered. ``using``-directives in those +namespaces have no effect on the lookup. The result of the lookup is a pointer +to a list of entry of kind ``a_symbol_list_entry`` or NULL if no such operator +functions have been declared. Each entry points to a symbol that meets the +lookup criteria. The caller is responsible for freeing the symbol list when it +is no longer needed by calling ``free_list_of_symbol_list_entries``. +``opname_function_symbol`` is a simplified version of +``nonmember_operator_function_lookup`` that is used for looking up new and +delete operators, which cannot be declared in namespaces. + +``global_operator_new_or_delete_symbol`` looks up symbols for the default +versions of operator new and delete at file scope (i.e., ``::operator +new(size_t)`` and ``::operator delete(void*)``), but unlike +``opname_function_symbol`` it will, if no such symbol exists yet, implicitly +declare the function, creating and entering its symbol and adding the routine +entry to the IL. + +Template Conversion Operators +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a class contains a template conversion operator, the lookup of a +particular conversion operator may require the partial instantiation of the +conversion operator template. For example: + +.. code:: c++ + + struct A { + template operator T(); + }; + int main(){ + A a; + a.operator int(); + } + +Class ``A`` does not contain an ``operator int`` conversion function that can +be found by the normal lookup mechanism. Instead, the lookup operation must +match the required type (``int``) with the available conversion templates to +see if a match can be found. ``look_up_conversion_template_instance`` is +called to look for the matching conversion template. If more than one matching +template is found a symbol that is marked as ambiguous is returned. + +If the result type of the conversion depends on a template parameter, or if the +class type on which the conversion operator is being called is a nonreal class, +it is not possible to find a matching conversion operator. In such cases an +"unknown conversion function" entry is created. This is represented by a +special kind of template parameter constant that contains a pointer to the +conversion result type. + +Constructors and Destructors +---------------------------- + +Several routines search for a constructor or destructor of a particular kind in +a given class. + +``select_default_constructor`` finds the default constructor for a given class. +A default constructor is one that can be called with no arguments. If the +class has no default constructor, an error is issued. + +``select_destructor`` finds the destructor for a given class. If the class has +no destructor, it returns NULL. + +``select_copy_constructor`` finds a copy constructor for a given class. It can +be told to look for a copy constructor that will accept ``const``- or +``volatile``-qualified objects. If no appropriate copy constructor exists, an +error is issued. + +User-Defined Conversions +------------------------ + +Like overloaded operators user-defined conversion functions (or "conversion +operators") cannot be looked up by name. Rather, the symbol header is looked +up by result type, using the linked list of entries of type +``a_conversion_header`` and pointed to by ``conversion_header_list``, as +described earlier. Since all user-defined conversion functions are member +functions, once the symbol header is found, searching for a symbol simply +involves discriminating on the basis of the ``parent.class_type`` field. + +An explicitly named conversion function (e.g., ``operator int()``), is +represented (like overloaded operators) by an identifier token; in its +associated symbol locator ``is_conversion_name`` is TRUE and +``conversion_result_type`` points to a type entry for the result of the +conversion. The routine called to find the conversion header (and thereby the +symbol header) and to set these fields is ``make_type_conversion_locator``. It +also creates the conversion header (as well as the symbol header) if none +exists yet. The token sequence representing a conversion function is scanned +by ``scan_conversion_operator``, which is called from ``f_get_opname``. + +Sometimes the question to be answered in processing an expression is, "What +user-defined conversion function exists to convert an object of class ``A`` to +type ``T``?" In such cases it would be straightforward to find the appropriate +symbol by using the result type to identify the conversion header and then the +class type to choose among the associated conversion function symbols. But at +other times -- for instance, when looking for the best implicit conversion or +when there are inherited conversion functions -- the question is subtly +different: "Which, if any, of the user-defined conversion functions that exist +for class ``A`` is most suitable for converting to type ``T``?" To optimize +answering this question, another construct appears in the symbol table, +``a_conversion_list_entry``, each instance of which points to a symbol entry +representing a conversion function. A class's symbol supplement contains a +pointer to such a list, which is updated in ``decl_member_function`` each time +a conversion function is declared; the list also contains projection symbols to +represent inherited conversion functions (see +``project_base_class_conversion_functions``). + +"Extern" Symbols +================ + +When it is required that distinct declarations in different name scopes refer +to the same entity, an extra symbol is created to represent the shared entity. +For instance, + +.. code:: c++ + + void f() { + extern int i; + } + void g() { + extern int i; + } + extern int i; + +In this example, although all three declarations of ``i`` refer to the same +variable, three independent ``sk_variable`` symbols are created to represent +it, one in the scope of function ``f``, one in the scope of function ``g``, and +one in the file scope. So a fourth symbol is created at file scope to +represent ``i`` -- its kind is ``sk_extern_variable``, and it is created at the +first declaration of ``i``. Then, even after the ``sk_variable`` symbol for +the declaration of ``i`` in function ``f`` goes out of scope, the +``sk_extern_variable`` symbol is still around to be found again on the +subsequent declarations of ``i``; this assures that all three ``i`` symbols +point to the same IL entity. A similar technique, using ``sk_extern_function`` +symbols, is employed for functions. These "extern" symbols are put on the +"other" symbols list instead of being put on either the active or inactive list +and so are not found during normal name lookup. + +The routine that manages all this is ``find_external_symbol``. It also has +special logic, subject to configurable control, to deal with instances in which +different source names resolve to the same "external" name because of object +language constraints -- e.g., where linkers can handle only so many characters +or are not case sensitive. + +Symbol Management +================= + +It remains to describe briefly some of the other low-level routines and macros +used to manage the symbol table and return information about symbols. + +* | ``alloc_symbol`` is called to allocate a symbol entry of a specified kind. + When a NULL symbol header is passed, it allocates an error symbol, one + whose header is ``error_symbol_header``. It calls ``clear_symbol`` and + ``set_symbol_kind`` to initialize the new entities; the latter also + allocates the supplementary constructs for class and projection symbols. + Other routines called to allocate and initialize the entities from which + the symbol table is constructed are + + * | ``alloc_symbol_header``, + * | ``alloc_conversion_header``, and + * | ``alloc_conversion_list_entry`` + +* | ``enter_namespace_projection_symbol`` is called to create new namespace + projection symbols and enter them in the symbol table. Passed a pointer to + the fundamental symbol, it allocates and initializes the symbol and links + it into the symbol table and scope list. This routine is needed because a + namespace projection symbol cannot be entered into the symbol table via + ``enter_symbol`` because that doesn't allow specification/setting of the + fundamental symbol and the fundamental symbol is used by ``enter_symbol`` + for checking compatibility with previous declarations of the name in the + current scope. +* | ``enter_synthesized_namespace_projection_symbol`` creates new synthesized + namespace projection symbols and enters them on the "other" symbols list if + they can be reused. This routine also determines the scope list on which + the symbol should be placed based on the lookup options and the qualifier + namespace, and sets the lookup option fields in the symbol entry. +* | ``enter_symbol`` is called to create new symbols and enter them in the + symbol table. Passed a symbol kind, it allocates and initializes the + symbol, marks it as having been referenced, and links it onto the symbol + header's active list and onto the current scope's symbol list. +* | ``reenter_symbol`` takes an existing symbol (one that may have been entered + already and then removed) and links it into the symbol table. +* | ``full_enter_symbol`` calls ``find_symbol`` to locate the symbol header for + a name and then calls ``enter_symbol``. This is convenient when creating + symbols for the reserved names of keywords and predefined macros (see + ``enter_keyword`` and ``enter_predef_macro`` in ``fe_init.c``). +* | ``link_symbol_into_symbol_table``, called from ``enter_symbol`` and + elsewhere, links a symbol onto the symbol header's active list. Though it + normally ends up adding the symbol to the front of the list, it is careful + to account for special cases by determining the precise location based on + the scope number and name space overloading. It will issue a redeclaration + error when it detects that the name has already been declared in the + current scope. +* | ``add_symbol_to_scope_list`` is also called from ``enter_symbol``; it adds + a symbol to the end of the symbol list [#f9]_ of the scope stack entry at + the specified scope depth. +* | ``enter_overloaded_symbol`` is called to enter a function symbol in the + symbol table when its name is overloaded. First, it allocates and + initializes the ``sk_routine`` or ``sk_member_function`` symbol. Then, if + an ``sk_overloaded_function`` symbol already exists for the name, the new + symbol is added to its list. If not, a new ``sk_overloaded_function`` + symbol must also be created; it will replace the existing function symbol + in the symbol table. +* | ``make_namespace_projection_symbol`` allocates and initializes namespace + projection symbols. A pointer to the fundamental symbol is provided. +* | ``make_projection_symbol`` allocates and initializes ``sk_projection`` + symbols, leaving it to the caller, ``find_projected_symbol``, to add the + new symbol to the symbol table, since it may be inserted in either the + active list or the inactive list of the symbol header. +* | ``make_template_class_symbol`` creates and initializes a symbol for an + instance of a class template. It is linked in the template's instantiation + list rather than added directly to the symbol table. +* | ``make_unnamed_tag_symbol`` is invoked to allocate and initialize a tagless + class, struct, and union symbol. It is not actually entered into the + symbol table since, like error symbols, it uses a special symbol header + (see static variable ``unnamed_tag_symbol_header``). If the class + subsequently acquires a name, ``relink_unnamed_tag_symbol`` is called to + modify the symbol entry and add it to the symbol table. +* | ``unlink_symbol_from_symbol_table`` is called from ``pop_scope`` for each + name that passes out of scope: it removes the symbol from the symbol + header's active symbol list, but the symbol remains on the scope list. +* | ``remove_symbol`` removes a symbol from the symbol table, e.g., for a macro + definition when a ``#undef`` is encountered. + ``unlink_symbol_from_symbol_table`` is called to remove a symbol from the + active list and ``remove_symbol_from_scope_list`` is called to remove it + from the symbol list of the scope stack entry. +* | When cross-reference information is being generated, ``write_xref_entry`` + is called to create a record describing a reference and to write it to the + file indicated by ``f_xref_info``. +* | ``record_symbol_declaration`` is called for every declaration and + definition of a name. It sets the source sequence number if this is the + initial declaration, may set the source position (for initial declarations + and for definitions), optionally calls ``write_xref_entry``, and (when + ``GENERATE_SOURCE_SEQUENCE_LISTS`` is TRUE) calls + ``sym_update_source_sequence_list``. +* | ``mark_defined`` and ``mark_declared`` are macro interfaces to + ``record_symbol_declaration``, for definitions and non-defining + declarations, respectively. +* | ``record_symbol_reference`` is called for nondeclarative references to + symbols. It optionally calls ``write_xref_entry``, specifying the + *kind* of reference (see ``a_symbol_reference_kind``), sets the + symbol's ``referenced`` flag, and may set the ``referenced`` flag in + the IL entry. For variables, it checks for the need to issue a + "used-before-set" warning and calls ``mark_variable_value_set`` if + appropriate. +* | ``mark_variable_value_set`` is called to set the ``value_has_been_set`` + flag in the symbol of a variable or static data member. For a variable + entry that represents function parameter or a handler parameter it also + sets ``param_value_has_been_changed``. +* | ``sym_update_source_sequence_list`` is called (when + ``GENERATE_SOURCE_SEQUENCE_LISTS`` is TRUE) to generate a source sequence + entry for a declaration. (Source sequence lists are discussed in greater + detail in the context of the intermediate language.) +* | ``clear_locator`` is a macro used to clear the fields of a locator and + initialize ``source_position`` to a specified value; + ``set_to_error_locator`` is similar but is used when errors are + encountered. +* | ``set_to_named_error_locator`` turns a locator into an error locator -- but + one that preserves information about the identifier with which the locator + is associated. +* | ``tildize_locator`` takes the locator for an identifier token, turns the + name into a destructor name by prepending a ``~``, calls ``find_symbol`` to + find (or create) the associated symbol header, and returns a locator for + new name. +* | ``change_class_locator_into_constructor_locator`` takes a locator for a + class name (its ``specific_symbol`` field will point to the class, struct, + or union symbol) and modifies it to point to a separate header of the same + name that serves as the header for a constructor. [#f10]_ +* | ``make_opname_locator`` creates a locator to represent a token sequence + consisting of ``operator`` and the token (or token pair) for an + overloadable operator. It looks for the corresponding header in the + ``opname_symbol_header`` array; if none is found, it creates one and adds + it to the array. +* | ``make_type_conversion_locator`` creates a locator to represent a token + sequence consisting of ``operator`` and tokens making up a type name. It + looks for the corresponding header by scanning ``conversion_header_list``; + if none is found, it creates one, along with a new conversion header entry, + and adds the latter to the head of the linked list. +* | ``make_locator_for_symbol`` is called to initialize a locator based on an + already existing symbol. +* | ``set_source_corresp`` is called to establish a correspondence between an + IL entry and a symbol. It links the IL entry back to the symbol. +* | ``set_decl_sequence_number`` is called to set a declaration sequence number + for a symbol. Such numbers identify the sequential position of one + declaration relative to others in the same translation unit. When a name + is multiply declared, the position of its definition is recorded in the + declaration sequence number. +* | A number of macros in ``symbol_tbl.h`` provide the preferred method of + identifying a given symbol's special characteristics: + + * | ``is_class_symbol`` + * | ``is_tag_symbol`` + * | ``is_type_symbol`` + * | ``is_function_symbol`` + * | ``is_member_function_symbol`` + * | ``is_constructor_symbol`` + * | ``is_destructor_symbol`` + * | ``is_copy_constructor_symbol`` + +* | ``type_symbol_type`` is a macro that may be invoked for symbols for which + ``is_type_symbol`` is TRUE; it returns a pointer to the associated type + entry. +* | ``symbol_supplement_for_class`` takes a type entry of kind ``tk_class``, + ``tk_struct``, or ``tk_union`` and returns a pointer to the associated + symbol's class symbol supplement entry. + +Access Control +============== + +The function of access control is to determine whether or not a given name can +be accessed from the current location in the source program. Every reference +to a name, whether qualified or not, whether part of an expression or a type, +is checked to make sure the identifier is unambiguous and accessible. There +are several things to remember about access control: + +* | Only class members are subject to access control. Non-class members are + always accessible. +* | Access control is site-specific. A given member can be accessible from one + place in a program and not accessible from somewhere else. In particular, + members and friends of a class have special access to the members of the + class and its base classes. +* | Access control limits access, not visibility. Members that are not + accessible are still visible. They are found, the access error is issued, + and then (the way the front end does it) they are used anyway. +* | When members are inherited into derived classes, the access to the members + in the derived class is affected by the type of derivation of the derived + class (see ARM 11.2). +* | The same member may have different access in different classes, and may be + accessible at a given point in the program through one qualified name and + not through another. In other words, access control applies to names + rather than objects. +* | A name is ambiguous if the name refers to two or more entities, with no + reason to prefer one over the others. Only inherited class members can be + ambiguous. Ambiguity checking is done before access control checking. + +The problem of access control, then, reduces to "given a symbol for a class +member, which might be a projection symbol, is the member unambiguous and do we +have access to it from the current location in the program?" + +The ambiguity aspect is easily dealt with: the ``ambiguous`` flag in the symbol +indicates whether or not it is ambiguous. The flag can be set only in +projection symbols and in symbols for sets of overloaded functions synthesized +for lookups done in the presence of ``using``-directives. + +Access checking is harder. + +The access to a class member, in its simplest form, is given by the +``source_corresp.access`` field in the member's IL entry. + +When the member is a direct member of a class, there will be a symbol entry +pointing directly to the IL entry, and the access to that symbol is simply the +access indicated in the IL entry. When the member is inherited, however, each +derived class will have a projection symbol that points to the fundamental +symbol. The access to the member through a projection symbol is filtered +through the class derivations that lead to the derived class containing the +projection symbol; that access is indicated in the projection symbol. + +If the simple access in the symbol or in the projection symbol is +``as_public``, then the member is accessible. Otherwise, some kind of member +access privilege is required to access it. + +Member access privileges are available when the current position is inside a +class or a function. Being inside a class confers special access to members of +the class and to classes that have befriended the class. Being inside a +function confers special access to classes that have befriended the function, +and, if the function is a member function, to the class of which it is a member +(and classes that have befriended it). + +The ``scope_stack`` provides the necessary information about the functions +and/or classes that the current position is inside of. + +For there to be special access to a member ``x`` across the derivation +represented by a projection symbol, there must exist a class ``A`` somewhere on +the derivation (including either of the endpoints) such that: + +#. ``A`` is accessible (meaning that its public members are accessible) from + the current position in the program, starting from the most-derived + class on the derivation. In other words, we can implicitly cast a pointer + to the derived class we start with to a pointer to ``A``. + +#. We have member access to ``A``. + +#. ``x`` is accessible in ``A``, meaning that if one starts with the access + to ``x`` in the fundamental class and works outward through the + derivation steps until one gets to ``A``, there is some remaining access + at that point. + +The implementation of the above is broken up as follows: + +* | ``access_for_symbol`` extracts the simple access for a symbol. +* | ``access_to_end_of_path`` determines the effect of a set of derivation + steps on such an access. +* | ``have_access_to_symbol`` determines whether or not there is access to a + symbol. Most of the work is done in ``have_access_across_path``. +* | The macro ``is_accessible_imm_base_class`` determines whether or not a base + class is accessible (ARM 4.6). The macro is also used directly in + determining whether or not base class casts and the like are valid. The + function ``is_accessible_base_class`` is similar, but is not limited to + immediate base classes. +* | ``have_member_access_privilege`` determines whether or not there is member + access privilege to a given class. + | + | When there are ``protected`` members or ``protected`` derivation steps + involved, derived classes can have a limited form of member access (see + ``have_protected_member_access_privilege``). + | + | The additional restrictions on access to protected members of ARM 11.5 + require special processing in the expression routines over and above the + access checking done here. The checking there ends up calling the macro + ``check_protected_member_access``, which in turn calls the function + ``f_check_protected_member_access``. +* | ``check_ambiguity_and_verify_access`` (a macro) is the main interface to + access checking. It in turn calls + ``member_check_ambiguity_and_verify_access`` for class members. + +Overloaded functions pose some special problems, because they are represented +as several symbols (which may have distinct accesses) clustered under one +overloaded function symbol. When the cluster is inherited into a derived +class, a single projection symbol points to the overloaded function symbol. +This means that: + +* | One cannot determine the access to a name in a set of overloaded functions + until one has determined which specific function is being referenced. For + that reason, when an overloaded function symbol is passed through the + normal access checking routines, it is always judged to be accessible. + Note that ambiguity checking can still be done in the usual way. +* | Once one has determined which function is being referenced, one cannot use + the normal interface to the access checking routines, because the + projection symbol does not point to the specific function. + | + | ``overload_check_ambiguity_and_verify_access`` does the access check in + this case on the basis of a projection symbol and a (not directly attached) + specific function symbol. In the presence of member + ``using``-declarations, the specific function symbol can be a projection + symbol. + +It is not possible to determine the access to certain names used in namespace +scope declarations at the point at which the name is seen. In the following +example, the accessibility of ``A::B`` in the declaration of ``A::f`` cannot be +determined until we know we are scanning a declaration of a member of class +``A``. In the friend case, we cannot determine the access to ``A::B`` until we +know the signature of the function being declared, because we have to determine +that it has been befriended by class ``A``. + +.. code:: c++ + + class A { + class B {}; + B f(); + friend B g(B); + }; + A::B A::f(){ B b; return b; } + A::B g(A::B b){ return b; } + +When a namespace scope declaration is processed, a flag is set in the scope +stack indicating that any access errors that occur should, instead of being +issued, be recorded in a list pointed to by the scope stack entry. Later, when +more information about the declaration is available, the accessibility is +rechecked. If the name is now accessible, the entry is removed from the list +of deferred access checks. If it is still not accessible, it will either +remain on the list if the defer access checks flag is still set, otherwise the +error will be issued. + +``begin_deferral_of_access_checks`` and ``end_deferral_of_access_checks`` are +macros used to bracket the processing of a declaration that requires deferred +access checking. + +``perform_deferred_access_checks`` is used to retry the access checks that had +failed earlier, and is called during declarator processing to check the +accessibility of member declarations. This is done after the class +reactivation scope for the member declaration has been pushed. + +For the accessibility of friend declarations to be checked, the scope stack +must contain information about the function that is being declared. The +function access scope fulfills this need. After a complete function +declaration has been scanned, ``perform_deferred_access_checks_for_function`` +is called with a pointer to the routine that has been declared. It pushes a +function access scope and then calls ``perform_deferred_access_checks`` to +determine whether the names are now accessible. + +.. [#f1] Note that symbol entries need two "``next``" pointers: the ``next`` + field is for linking symbols in the active and inactive lists of the + symbol header, and the ``next_in_scope`` field links symbols in the + scope list. +.. [#f2] The selection of a particular function based on function type is not + part of *name* lookup but belongs to another phase of processing. +.. [#f3] Note that it is the depth of the scope entry, not its uniquely + identifying number, that is saved; this value permits indexing + directly into the scope stack array rather than searching through the + scope stack. +.. [#f4] It almost always has the same value as ``depth_scope_stack``. + However, in C mode the scope of a struct or union is not a "real" + scope, in which case ``decl_scope_level`` identifies the block, + function, or namespace scope to which the struct or union belongs. + The depth of the pseudo-scope itself is recorded in + ``depth_scope_stack``. +.. [#f5] Both the symbol and the base class entry are required since it is + legal for a class to be derived from a base class more than once + (even though unqualified member references may be ambiguous); since + each instance of derivation is represented by a unique base class + entry, its presence makes clear which derivation is involved in the + projection. +.. [#f6] Note that a nested class name is treated as hidden by a name that is + visible according to standard lookup rules, even if the latter belongs + to an outer scope. Moreover, no error is reported when there is more + than one qualifying nested class symbol. +.. [#f7] Given a token, one finds the corresponding ``an_opname_kind`` value + with the array ``opname_kind_for_token``. +.. [#f8] ``f_get_opname`` is always invoked by macro ``get_opname``. +.. [#f9] Adding the symbol to the end of the list assures that the list + preserves the declaration order for the scope. +.. [#f10] As described above, the constructor header is not in the symbol + table and consequently will not be found by ``find_symbol``. diff --git a/dev/doc/_sources/tables.rst.txt b/dev/doc/_sources/tables.rst.txt new file mode 100644 index 0000000..059ba21 --- /dev/null +++ b/dev/doc/_sources/tables.rst.txt @@ -0,0 +1,665 @@ +================ +Table Management +================ + + + + +For a description of the intermediate language itself, see +:ref:`intermediate-language`. + +The source file ``il_alloc.c`` contains routines to allocate and clear the +intermediate language tables, and ``il.c`` contains routines to debug-print +them. These routines should always be used, so that new tables are always set +to the proper default values and problems with undefined fields are avoided. +``il_def.h``, ``il_alloc.h``, and ``il.h`` contain associated declarations. + +Note that some of these routines should not be called from a back end, because +the front end data structures they need are no longer set up properly at that +point. In general, routines that allocate new storage or new entries should +not be called, and routines that answer questions about existing entries are +okay to call. The + +.. code:: c++ + + #if !STANDALONE_UTILITY_PROGRAM + +guards indicate routines that should not be called by back ends. + +Storage Allocation +------------------ + +``alloc_cil`` has an interface like ``malloc``; it allocates space in the +current intermediate language memory region. ``new_il_region`` begins a new +intermediate language memory region. ``switch_il_region`` switches to a +previously-created region. ``alloc_il`` allocates space in the file-scope +intermediate language memory region. + +When the alternate IL file format is used, space is reserved preceding each IL +entry so that the IL entry number can be stored there. + +Constant Entries +---------------- + +Constant entries (type ``a_constant``) are usually allocated by +``alloc_constant``; ``fs_constant`` is similar to it but allocates the constant +entry at the file scope. ``make_zero_of_proper_type`` makes a zero constant of +a given type. ``clear_constant`` and ``set_constant_kind`` are called to +re-initialize existing constant entries, and ``set_error_constant`` changes an +existing constant entry to an error constant. + +In most cases, a constant entry need not be unique -- the same entry can be +used for all occurrences of a given literal constant. For these cases, one +should call ``alloc_shareable_constant`` instead of ``alloc_constant``. (The +interface is slightly different; one passes a filled-in constant entry rather +than just a kind.) ``alloc_shareable_constant`` maintains +``shareable_constants_table``, a hash table that is searched by hashing a +constant entry to a bucket number (routine ``hash_constant``), then searching a +linked list of constants in that bucket to see if there is a match (comparison +is done by ``eq_constants``). If an entry is found, it is reused. If none is +found, one is entered into the table. + +In cases where the constant entry cannot be shared (as when it must be linked +into an initializer list), ``alloc_unshared_constant`` should be called +instead. It basically just calls ``alloc_constant``, but adjusts a few things +in the constant entry. + +Type Entries +------------ + +Type entries (type ``a_type``) are allocated by ``alloc_type``. + +``integer_type``, ``fixed_point_type``, ``float_type``, ``string_type``, +``void_type``, and ``error_type`` can be called to create type entries for the +most common types; these routines will reuse the entries once they have created +them. ``make_pointer_type`` creates a pointer type pointing to a given base +type. It uses the routine ``get_based_type`` to determine if a pointer to the +type has already been created, and it calls ``add_based_type_list_member`` to +record the fact that a pointer type has been allocated. +``make_reference_type`` is the similar routine for (lvalue) reference types, +and ``make_rvalue_reference_type`` is the similar routine for rvalue reference +types. ``ptr_to_member_type`` is the similar routine for pointer-to-member +types. + +``make_qualified_type`` is used to add type qualifiers to an existing type; +``make_unqualified_type`` is used to remove them. + +``unknown_type`` creates an unknown type entry; such an entry is used as a +place-holder within the front end and the references to it must be eliminated +before the back end is called. Another type that is normally not seen by the +back end (unless prototype instantiations are recorded in the IL) is the +template parameter type, which is used in processing template declarations. + +There are several routines that allocate various pieces of the description of a +class type: + +* | ``alloc_derivation_step`` +* | ``alloc_base_class_derivation`` +* | ``alloc_overriding_virtual_function`` +* | ``alloc_base_class`` +* | ``alloc_list_entry_for_class`` +* | ``alloc_class_type_supplement`` + +Other Declarative Entries +------------------------- + +``alloc_variable``, ``alloc_field``, ``alloc_label``, and ``alloc_routine`` +allocate variable, field, label, and routine entries. They do nothing terribly +interesting. ``remove_from_routines_list`` can be used to remove a routine +from the routines list so that it can be added again at the position where its +actual definition appears. + +Routines that allocate other IL entities resulting from declarations include: + +* | ``alloc_param_type`` allocates a param-entry pointed to from the routine + type supplement of a ``tk_routine`` type entry. +* | ``alloc_template``, ``alloc_template_arg`` and + ``alloc_template_param_type_descr`` are used in template processing. +* | ``alloc_namespace`` allocates an entry to represent either a namespace or a + namespace alias. +* | ``alloc_using_decl`` allocates an entry to represent a ``using``-directive, + a member ``using``-declaration, or a nonmember ``using``-declaration. +* | ``alloc_macro`` allocates an entry representing a macro definition (when + ``RECORD_MACROS_IN_IL`` is set). +* | ``alloc_pragma`` allocates an entry representing a ``#pragma`` declaration. +* | ``alloc_asm_entry`` allocates an entry representing an ``asm`` declaration. + To support certain extensions (i.e., when ``ASM_FUNCTION_ALLOWED`` is set) + ``alloc_asm_function_body`` is also available. +* | ``alloc_scope`` allocates a scope entry. +* | ``alloc_ctor_init`` allocates a constructor-initializer entry, a list of + which is recorded in the scope entry associated with a constructor. +* | ``alloc_temporary_variable`` allocates a variable entry for a temporary. +* | ``alloc_dynamic_init`` allocates a dynamic initialization entry, used + (among other things) to represent dynamic initialization on variable + declarations. +* | ``alloc_local_static_variable_init`` allocates an entry used to represent + the initialization of a function-local variable with static storage class. +* | ``alloc_list_entry_for_routine`` allocates an entry used to record a list + of routine entries (used to support ``friend`` declarations). +* | ``alloc_exception_specification`` allocates an entry that represents an + exception specification in a function declaration. +* | ``alloc_accessible_base_class`` allocates an accessible base class entry + (unused in implementations in which ``ABI_CHANGES_FOR_RTTI`` is set). +* | ``alloc_hidden_name`` allocates a hidden-name entry (for use by the + C++-generating back end, when ``RECORD_HIDDEN_NAMES_IN_IL`` is set). + +Expressions +----------- + +``alloc_expr_node`` allocates an expression node. + +``set_expr_node_kind`` and ``clear_expr_node`` re-initialize existing entries. +``make_operator_node`` creates an expression node for an operation. + +``set_node_operator`` changes the operator or type in an existing operation +expression node. + +``error_node`` makes an error expression node (a new one on each call, since +executable constructs cannot be shared). + +There are several utility routines that help in constructing expressions: + +* | ``alloc_node_for_constant`` builds an expression node that points to a + constant entry. +* | ``node_for_integer_constant`` builds an expression node for an integer + constant. +* | ``var_lvalue_expr`` builds an expression node for a variable as an lvalue. +* | ``var_rvalue_expr`` builds an expression node for a variable as an rvalue. +* | ``var_addr_expr`` builds an expression node for the address of a variable. + The ``address_taken`` flag is set. +* | ``function_lvalue_expr`` builds an expression node for a function as an + lvalue. +* | ``function_rvalue_node`` builds an expression node for a function as an + rvalue, i.e., for the address of the function. This is suitable for + calling the function, but not for the "``&``" operator applied to the + function, because the ``address_taken`` flag is not set. +* | ``function_addr_expr`` builds an expression node for the address of a + function. The ``address_taken`` flag is set. +* | ``rvalue_expr_for_lvalue`` converts an lvalue expression to an rvalue. It + also works for function lvalues, but not for arrays. +* | ``add_indirection_to_node`` adds an indirection ("``*``" operator) to an + expression. +* | ``add_ref_indirection_to_node`` adds the reference equivalent of + "``*``" to an expression. +* | ``add_address_of_to_node`` adds a "``&``" operator to an expression. +* | ``add_reference_to_to_node`` adds the reference equivalent of "``&``" to an + expression. (Note that that is not a typo; the name really does have + "``to_to_``" in it.) +* | ``field_lvalue_selection_expr`` builds an expression for a field selection + that produces an lvalue. +* | ``field_rvalue_selection_expr`` builds an expression for a field selection + that produces an rvalue. + +``copy_expr_tree`` makes a copy of an expression tree. When it does so, it can +optionally "clone" any temporary variables found within the tree so that the +copy uses different but equivalent temporaries. + +In addition, ``alloc_lowered_eh_construct_node`` allocates an expression node +to represent one of several (partially) lowered exception handling constructs +(used only when IL lowering is enabled and ``DO_FULL_PORTABLE_EH_LOWERING`` is +configured to FALSE. + +Statements +---------- + +``alloc_statement`` allocates a statement (which may allocate a supplement of +type ``a_for_loop``, ``a_switch_stmt_descr``, etc.). +``alloc_switch_case_entry`` allocates the entry used to represent one case +(possibly, the "``default:``" case) of a ``switch`` statement. + +Object Lifetimes +---------------- + +``alloc_object_lifetime`` allocates an object lifetime entry, and +``bind_object_lifetime`` binds it to a specified IL entry (a scope, an +expression, a dynamic init, etc.). + +A dynamic init entry with a destructor is added to the destructions list of an +object lifetime by ``record_end_of_lifetime_destruction``, which calls +``add_to_destructions_list``. Conversely, it is removed from the list by +``remove_from_destructions_list``. + +During front-end processing object lifetime entries are pushed onto the object +lifetime stack (see ``push_object_lifetime`` and global variable +``curr_object_lifetime``, which is the top of the stack) and popped off the +stack when appropriate (see ``pop_object_lifetime``). + +If, when it is popped off the object lifetime stack, the entry is not actually +required in the IL (see ``is_useless_object_lifetime``), it is unbound from the +IL entry with which it is associated (see ``unbind_object_lifetime``) and +placed on an available list for reuse (see ``free_object_lifetime``). + +Source Sequence Entries +----------------------- + +Source-sequence entries are created only when +``GENERATE_SOURCE_SOURCE_SEQUENCE_LISTS`` is configured to TRUE. See +:ref:`intermediate-language` for additional information. + +``f_update_source_sequence_list`` creates new source sequence entries and adds +them to the appropriate list. + +* | For declarations it is called by ``sym_update_source_sequence_list`` (in + ``symbol_ref.c``), which also calls ``alloc_src_seq_secondary_decl`` when + the declaration is not a primary declaration. +* | For statements it is called by ``stmt_update_source_sequence_list`` (in + ``statements.c``). +* | In certain other cases -- e.g., for the declaration of unnamed ``enum`` + types, for which there is no symbol -- it is called via macros + ``update_source_sequence_list`` and ``add_to_source_sequence_list``. + +Other functions called to create and manage source sequence lists include: + +* | ``alloc_source_sequence_entry`` allocates and initializes a source-sequence + entry. +* | ``add_source_sequence_entry_to_list`` is called to add entries to the end + of the list of the current scope stack entry (see ``source_sequence_list`` + in ``a_scope_stack_entry``). When ``pop_scope`` is called, the list for a + given scope stack entry is either appended to the list of the enclosing + scope stack entry or, for function scopes and the file scope, moved to the + associated IL scope (see ``source_sequence_list`` in ``a_scope).`` +* | ``add_empty_source_sequence_entry`` creates and adds a source sequence + entry that does not yet point to an IL entry. Such entries are + placeholders to reserve a position in the list for a declarator when the + particular IL entry it represents is not yet known; they do not persist + beyond the front end. +* | ``add_end_of_construct_source_sequence_entry`` creates a source sequence + entry to mark the end of a construct for a given entity (see + ``alloc_src_seq_end_of_construct)`` and adds it to the current source + sequence list. (See also :ref:`src-seq-lists`.) +* | ``make_source_sequence_secondary_decl`` creates a source sequence entry to + represent a non-defining declaration (see ``a_src_seq_secondary_decl``), + and ``set_src_seq_secondary_decl_fields`` can be called to locate the entry + on the current source sequence list (see + ``last_matching_source_sequence_entry``) and to update various of its + pointers and flags. +* | When either ``CLASS``- or + ``NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS`` is TRUE, + ``add_source_sequence_entry_for_partial_instantiation`` is called to enter + a secondary declaration entry to represent the declaration of a + compiler-generated template specialization that stands for a template + instantiation, and when the body of such a specialization is generated, its + source sequence list is added by ``insert_instantiation_src_seq_list``; in + both cases, ``find_instantiation_insert_scope`` is called to locate the + point at which the instantiation should be inserted in the source sequence + list (since it is not necessarily at the end of the list for the current + scope stack entry). +* | ``insert_src_seq_list`` inserts a list into another list at a specified + point; it is also called to append a list to another list. +* | ``remove_from_source_sequence_list`` removes a given source sequence entry + from its list; see also macros ``unlink_src_seq_entries`` and + ``unlink_src_seq_entry`` (which operate on source sequence lists and single + entries, respectively). +* | ``fixup_function_scope_source_sequence_list`` creates both a sublist header + (see ``alloc_src_seq_sublist``) and the source sequence entry that points + to it. + +Lists of Entries +---------------- + +The routines + +* | ``add_to_constants_list``, +* | ``add_to_types_list``, +* | ``add_to_variables_list``, +* | ``add_to_parameters_list``, +* | ``add_to_dynamic_inits_list``, +* | ``add_to_routines_list``, and +* | ``add_to_labels_list`` +* | ``add_to_namespaces_list`` +* | ``add_to_using_decls_list`` +* | ``add_to_asm_entries_list`` +* | ``add_to_templates_list`` +* | ``add_to_macros_list`` +* | ``add_to_pragma_list`` + +add entries of the indicated type to end of the list of similar entries under a +scope entry. The scope will vary depending on the type of entry and what the +caller specifies. In many cases it is either the current scope or the +innermost namespace scope that is used (e.g., variables, constants, types). +Routines that are not class members are added to the list for the file scope or +a namespace scope. Labels are always added to an ``sck_function`` scope. And +so forth. + +There is also an ``add_to_scopes_list``; it is called by ``create_block_scope`` +when a scope for a statement block is created. Special handling is required +because the IL scope for a block is not created until there is some declaration +in that block. + +Orphaned Entries +---------------- + +Orphans are entries in the file scope memory region that are referenced only +from function scope memory regions. When the parents of such entries are +written out and then removed from memory, the entries are orphaned because they +are not attached to the rest of the file-scope IL tree. + +The orphan mechanism makes lists of such entries so that they can be found +during traversal of the file-scope IL. In the file scope, each entry is +preceded by space for an orphan-list pointer. When a potential orphan entry is +encountered, for example when an entry in a function scope memory region points +to an entry in the file scope memory region, +``add_orphaned_file_scope_il_entry`` is called. It adds the potential orphan +to a list of entries of its type headed by the proper element of the array +``orphaned_file_scope_il_entries`` and linked by the hidden pointer. An entry +is ignored if it is already on the list (which can be discerned from the fact +that the orphan-list pointer is already non-NULL or the fact that the entry +address matches the last-on-list pointer for that entry type). + +There is also a special mechanism for keeping track of the lists of local +static variables and types in function and block scopes. These are lists that +are entirely in the file scope memory region but originate with a pointer that +is in a function scope memory region. To keep track of these, entries of type +``a_scope_orphaned_list_header`` are allocated in the file scope memory region +and attached to the ``il_header``. Each entry contains a copy of the static +variables and types pointers from a function or block scope, so that the lists +can be visited in the file scope memory region even if the associated function +scope memory region is no longer in memory. See +``add_scope_orphaned_il_lists``. + +Source File Information +----------------------- + +``record_start_of_source_file`` and ``record_end_of_source_file`` build +information about the correspondence between source files and sequence numbers. +Basically, this is a tree that shows the nesting of include files, with added +entries to show the information provided by ``#line`` directives. These +routines are called from ``push_input_stack`` and ``pop_input_stack`` in +``lexical.c``, and ``proc_line`` in ``preproc.c``. +``conv_seq_to_file_and_line`` uses that data structure to map sequence numbers +into file names and line numbers. + +Debug Print Routines +-------------------- + +The following debug-print routines can be used to display intermediate language +constructs for debugging purposes: + +* | ``db_name`` +* | ``db_type_name`` +* | ``db_name_linkage`` +* | ``db_type`` +* | ``db_abbreviated_type`` +* | ``db_access_control`` +* | ``db_field`` +* | ``db_static_data_member`` +* | ``db_member_function`` +* | ``db_virtual_function_info`` +* | ``db_constant`` +* | ``db_variable`` +* | ``db_expression`` +* | ``db_dynamic_initializer`` +* | ``db_initializer`` +* | ``db_statement`` +* | ``db_statement_list`` +* | ``db_object_lifetime`` +* | ``db_object_lifetime_stack`` +* | ``db_scope`` +* | ``db_source_sequence_entry`` + +Types +===== + +The routines and data structures described in this section are defined in +``types.c`` and ``types.h``. These are routines that manipulate intermediate +language types in various ways. They answer questions about them, and do +various language transformations on them. + +Typerefs +-------- + +In type trees, typedefs, type qualifiers (e.g., const and volatile), type +operators such as decltype, and various other types are represented by an entry +called a typeref. It indicates a reference to an existing type. For qualified +pointer types, the ``typeref`` indicating the qualifier is on top of the +pointer type: for ``int *const q`` the type is a ``const``\ ``typeref`` +pointing to a pointer type entry, which points to an entry for ``int``. Macros +``get_type_qualifiers`` and ``get_top_level_type_qualifiers`` (the former may +check for qualifiers on the underlying array element type, the latter does not) +call ``f_get_type_qualifiers`` when appropriate, returning a bit set (see +``a_type_qualifier_set``). + +It is often necessary for code that deals with types to access the target of a +typeref or chain of typerefs. Various convenience functions are provided for +this purpose, including skip_typerefs, skip_typerefs_not_typedefs, +skip_lexical_typerefs, etc. + +Asking Questions About Types +---------------------------- + +There are many predicates that determine whether or not a given type is of a +given kind. Having predicate functions (instead of doing the testing by direct +coding) is necessary because of the possibility of there being ``typeref`` +entries on a type. These predicates are implemented as functions, although +they could be implemented as macros for any cases where it seems desirable. +Within ``types.c``, macros are used so as to avoid having one predicate routine +call a half-dozen others to get an answer. The predicate macros have the same +names as the corresponding predicate functions, with the final ``_type`` of the +name removed (i.e., ``is_integral`` corresponds to ``is_integral_type``). They +do not call ``skip_typerefs``. + +The predicate functions are + +* | ``is_error_type`` +* | ``is_function_type`` +* | ``is_incomplete_type`` +* | ``is_object_type`` +* | ``is_void_type`` +* | ``is_integral_type`` +* | ``is_signed_integral_type`` +* | ``is_enum_typeis_integral_or_enum_type`` +* | ``is_character_type`` +* | ``is_fixed_point_type`` +* | ``is_floating_type`` +* | ``is_arithmetic_or_enum_type`` +* | ``is_pointer_type`` +* | ``is_reference_type`` +* | ``is_lvalue_reference_type`` +* | ``is_rvalue_reference_type`` +* | ``is_ptr_or_ref_type`` +* | ``is_scalar_type`` +* | ``is_array_type`` +* | ``is_char_array_type`` +* | ``is_class_struct_union_type`` +* | ``is_complete_class_struct_union_type`` +* | ``is_union_type`` +* | ``is_aggregate_or_union_type`` +* | ``is_polymorphic_class_type`` +* | ``is_ptr_to_member_type`` +* | ``is_template_class_type`` +* | ``is_template_param_type`` +* | ``is_nullptr_type`` + +Macros that may be called to get information about the type (when +``skip_typerefs`` is not to be called) include + +* | ``is_immediate_error_type`` +* | ``is_immediate_class_type`` +* | ``is_qualified_type`` +* | ``is_const_qualified_type`` +* | ``is_volatile_qualified_type`` +* | ``is_top_level_qualified_type`` +* | ``is_top_level_const_qualified_type`` +* | ``is_top_level_volatile_qualified_type`` + +(Among those that check type qualifiers, the ``is_top_level_``\ *xxx* versions +differ from the others in not checking for qualifiers on underlying array +element types.) Other type qualifiers besides ``const`` and ``volatile`` may be +recognized; for instance, when support for ``restrict`` is enabled, +``is_restrict_qualified_type`` and ``is_top_level_restrict_qualified_type`` are +also defined. + +``is_illegal_abstract_class_type`` returns TRUE if the type is that of an +abstract class, struct, or union, or if it is an array of abstract class +objects, or if it is pointer or reference to an array of abstract class +objects. + +``int_kind_is_signed`` determines whether a given integer kind is a signed +type. + +There are in addition some predicate functions that examine an entire type +tree, if necessary, to return information about a type: + +* | ``is_or_contains_local_type`` +* | ``is_or_contains_unnamed_or_local_type`` +* | ``is_or_contains_template_param`` +* | ``is_or_contains_specific_template_param`` + +These routines call ``traverse_type_tree``, a generic type-walking routine; it +is passed the address of a service routine that examines a node in the type +tree, and its detailed behavior is governed by setting some combination of +flags (see ``a_type_tree_traversal_flag_set``). + +Another set of predicates tests C++/CLI types and can be used only inside +``#if`` guards for ``MICROSOFT_EXTENSIONS_ALLOWED:`` + +* | ``is_handle_type`` +* | ``is_managed_nullptr_type`` +* | ``is_ref_class_type`` +* | ``is_value_class_type`` +* | ``is_managed_class_type`` +* | ``is_standard_class_type`` +* | ``is_cli_interface_type`` +* | ``is_tracking_reference_type`` +* | ``is_handle_or_tracking_ref_type`` +* | ``is_interior_ptr_type`` +* | ``is_pin_ptr_type`` +* | ``is_cli_array_type`` +* | ``is_handle_to_cli_array_type`` +* | ``is_cli_generic_param_type`` +* | ``is_cli_generic_constraint_type`` +* | ``is_boxable_type`` +* | ``is_delegate_type`` +* | ``is_cli_system_object_type`` +* | ``is_cli_system_string_type`` + +To ease pointer/reference/handle tests in code that might have to deal with +C++/CLI types, the following test certain general categories of pointers and +references: + +* | ``is_any_reference_type`` +* | ``is_any_ptr_or_ref_type`` +* | ``is_pointer_or_handle_type`` +* | ``types_are_both_pointers_or_both_handles`` + +Taking Apart Types +------------------ + +Given an array type, ``array_element_type`` and +``underlying_array_element_type`` return the type of an element; the second +deals with multidimensional arrays. ``type_pointed_to`` is used to get the +base type from a pointer or reference type. ``pm_member_type`` and +``pm_class_type`` extract the base types from pointer-to-member types. +``underlying_type_of_derived_type`` extracts the underlying type for all +derived types (pointer, pointer-to-member, array, etc.). + +Given a C++/CLI array type, ``cli_array_element_type`` returns the type of the +element. ``cli_array_rank_constant`` and ``cli_array_rank`` return the rank +(number of dimensions) of the array in different forms. + +Setting Sizes and Alignments of Types +------------------------------------- + +The size and alignment for a type are recorded in the type entry (except for +``typeref``\ s, which have their sizes and alignments dictated by the type they +refer to). These values, however, are not set all over the front end, but only +by isolated routines. The main routine is ``set_type_size``, which will set +the size of an arbitrary type. The type must be completely built by the time +this routine is called. ``set_type_size`` calls ``set_array_type_size`` for +arrays. Size and alignment for class types are set by code in ``layout.c``. + +Modifying Type Trees +-------------------- + +``set_used_in_exception_or_rtti_flag`` is called for types that appear as the +type of a throw object, in an exception specification list, as the type of a +handler, or in a ``typeid`` operator. It sets the type entry's +``used_in_exception_or_rtti`` flag. To assure that such types have external +linkage, it also calls ``set_force_external_linkage_flag``, which in turn calls +``traverse_type_tree`` to mark all the components of the type tree that have +linkage. + +``strip_local_typedefs`` is called to remove all local ``typedef`` components +of a type tree. It calls ``traverse_and_modify_type_tree`` to help accomplish +this task. If a subtree of the type tree is modified, a new type tree is built +to accommodate the change. + +Getting Information About Base Classes +-------------------------------------- + +``find_base_class_of`` returns a pointer to a base class entry if a given class +type is represented on the base classes list of another class type. Similar +functionality, but with the implied restrictions, is provided by +``find_direct_base_class_of`` and ``find_direct_or_virtual_base_class_of``. +``related_class_pointers`` will do the same for pointers to classes. + +``corresponding_base_class``, given a base class belonging to one class, +searches the base classes of another class, finds the corresponding entry, and +returns a pointer to it. + +``is_on_any_derivation_of`` returns TRUE if a given base class is on the +derivation of another base class. + +Routines that Implement Language Concepts +----------------------------------------- + +The routines described in this section implement concepts of the C or C++ +languages. + +Two routines handle type promotions: ``type_after_integral_promotion`` +determines the type that results from integral promotion done in an expression, +and ``default_argument_promotion`` determines the type of an argument to a +function with old-style parameter declarations after default promotion. See +also ``type_after_bit_field_integral_promotion`` in ``exprutil.c`` for a +special case involving bit-fields. + +Several routines compare two types to see if they are compatible in some way. +``identical_types`` determines whether the two types are structurally identical +(they don't have to be the same pointer). ``il_identical_types`` sees if the +two types are identical from an IL perspective (e.g., ``int`` and ``long`` +might be identical if the front end is configured that way). +``types_are_compatible`` sees if two types are compatible (C standard, +3.1.2.6). (Those three names are actually macros which call +``f_identical_types`` and ``f_types_are_compatible`` only if the type pointers +are not exactly the same.) ``interchangeable_types`` sees if two types are +interchangeable as arguments to functions (basically, this is true if they are +compatible except for signedness issues). + +``impl_pointer_conversion`` determines whether or not an implicit conversion +from a given type to a given pointer type is valid, with some special cases for +pointers to ``void`` and for null pointer constants. + +``impl_conversion_possible`` determines whether or not an implicit conversion +from a given type to another is valid. ``impl_ptr_to_member_conversion`` +handles the subcase of implicit conversion of one pointer-to-member type to +another. + +``expl_conversion_possible`` determines whether or not an explicit conversion +(cast) from a given type to another is valid. It relies on two subroutines for +the major subcases: + +* | ``static_cast_conversion_possible`` and +* | ``reinterpret_cast_conversion_possible``. + +``composite_type`` develops a composite type from two types (C standard, +3.1.2.6). + +``overload_distinguishable`` determines whether or not two function types are +sufficiently different that they can be distinguished by overload processing +(and therefore routines with those types can be overloaded). + +``impl_handle_conversion`` determines whether or not an implicit conversion +from a given type to a given C++/CLI handle type is valid. + +``boxing_conversion_possible`` determines whether a conversion from one given +type to another is a C++/CLI boxing conversion. The cases accepted convert a +value type to a handle to that value type. + +``unboxing_conversion_possible`` determines whether a conversion from one given +type to another is a C++/CLI unboxing conversion. The cases accepted convert a +handle type to a value type. + +``system_type_from_fundamental_type`` and ``fundamental_type_from_system_type`` +are a pair of functions that convert back and forth between fundamental types +and the corresponding C++/CLI value class types (e.g., between ``int`` and +``System::Int32``). diff --git a/dev/doc/_sources/templates.rst.txt b/dev/doc/_sources/templates.rst.txt new file mode 100644 index 0000000..91535b9 --- /dev/null +++ b/dev/doc/_sources/templates.rst.txt @@ -0,0 +1,2823 @@ +.. _templates: + +========= +Templates +========= + +Support for template declarations and the instantiation of classes and objects +based on templates is found principally in ``templates.c``; ``templates.h`` +contains the associated declarations. + +Overview +======== + +Template support is almost entirely a front-end issue. By default, templates +themselves are not represented in the IL, and classes and functions that are +generated on the basis of templates look just like any other class or function. +The exceptions to this rule are: + +* | Classes, functions, variables, and aliases generated from templates + identify the associated template arguments, because those arguments may + be needed in generating the name of the entity. +* | In automatic instantiation mode additional flags are provided in the + variable and routine entries so that the information provided by the flags + may be represented in the resulting object file in some form. +* | A template IL entry is created for each template declaration. When + ``PROTOTYPE_INSTANTIATIONS_IN_IL`` is TRUE, the entry points to a + "prototype instantiation", which is an IL entry that represents the entity + declared by the template. When ``RECORD_TEMPLATE_STRINGS`` is TRUE, the + entry contains a null-terminated string that represents the template + declaration. The IL template entry is also used to represent the value of + a template template argument. +* | The template instantiation mechanism may require support in the back end. + For example, if each instantiation is placed in its own object file, the + back end must recognize the data structures provided to accomplish this. + +Generally speaking, when a template definition is scanned, the definition of +the template is saved and then used later to generate instances of the +template. There are two common techniques used by compilers to save the +definition of a template: in the first technique, the template is parsed +(without semantic analysis) and the parse tree is saved; in the second, some +unparsed (more or less textual) representation of the template is saved. A +parse tree may be a reasonable choice for a multi-pass front-end featuring a +separate parser. However, in the EDG C++ front end (which uses a single pass +approach in which parsing and semantic analysis are done together), a textual +representation, which we call a "token cache", is more appropriate. Correctly +implemented, the two techniques are semantically equivalent. + +When using exported templates (see :ref:`exported-templates`) the front end +reloads the translation unit(s) that define the exported templates that require +instantiation so that the information from all of the translation units is +available to the front end. Even though there is a great deal of special +processing required to make exported templates work properly, the underlying +mechanism of rescanning tokens from a token cache is still used to produce the +actual instantiation. + +Since the method one chooses to record the definition of the template affects +the data structures used in the implementation and also influences the +terminology used to describe them, it will be helpful to introduce some terms +that are used in the EDG C++ front end: + +* | A *template* denotes a sequence of tokens that, along with one or more + template parameters and a declarative context, is used as the basis for + generating an *instance* of the template. + | + | A template entity may be + + * | a class template (e.g., class ``A``), + * | a function template (e.g., function ``f``), + * | a member function of a class template (e.g., ``A::f``), + * | a static data member of a class template (e.g., ``A::t``), + * | a nested class of a class template (e.g., ``A::B``), + * | a member class template (e.g., ``A::C``), + * | a member function template (e.g., ``A::g``), + * | a variable template (e.g., ``x``), + * | an alias template, or + * | a partial specialization of a class template, member class template, + or variable template. + + | For example, + + .. code:: c++ + + template void f(T); // function template + template class A { // class template + T f() { return t; } // member function of class template + static T t; // static data member of class template + struct B {}; // nested class of class template + template void g(U); // member function template + template struct C {}; // member class template + template struct C {}; // partial specialization + template static U vt; // member variable template + }; + template T x = 1; // variable template + template using B = A; // alias template + +* | A *template parameter* refers to a template formal argument, and a + *template argument* is a template actual argument. +* | A *template instance* is a class (sometimes called a *template class*) + generated on the basis of a class template, an alias (i.e., typedef, + sometimes called a *template alias*) generated on the basis of an alias + template, a function (sometimes called a *template function*) generated on + the basis of a function template, or a variable (sometimes called a + *template variable*) generated on the basis of a variable template. In + addition, a member function or static data member of a template class is + itself an instance of the corresponding member function or static data + member of the class template. For example, + + .. code:: c++ + + template class A { + static T t; + T f() { return t; } + }; + A ai; + template T g(T t) { return t; } + int i = g(0); + + | With the declaration of ``ai`` an instance of class template ``A``, namely, + ``A``, is generated, and in the process instances ``A::f`` and + ``A::t`` are also generated. Similarly, the reference to ``g(int)`` + causes an instance of function template ``g`` to be generated. +* | In many cases instances of variable templates and static data members of + template classes are treated similarly. The term "template variable" is + used to refer to both cases, unless otherwise specified. +* | The generation of an instance of a template is called *instantiation*. + (Sometimes the result of instantiation, namely an instance, is also called + an instantiation.) +* | An instantiation may be either a *partial instantiation* or a *full + instantiation*. A partial instantiation of a class template is like a + declaration of an ordinary class when no body is supplied; similarly, a + partial instantiation of a function template is like a declaration of a + function without a function body. On the other hand, a full instantiation + is the generation of a class or function definition -- i.e., it includes + the body. For instance, + + .. code:: c++ + + template class A {}; + A *pal; + A ai; + + | In this case the declaration of ``pal`` causes the partial instantiation of + ``A`` -- that is, no body needs to be generated -- whereas the + declaration of ``ai`` causes the full instantiation of ``A``. The + instantiation of an alias template is always a full instantiation. +* | The first time a class template is scanned -- partly to record its member + functions, static data members, nested classes, and friend declarations, + and partly to check for errors -- the result is referred to as a *prototype + instantiation* of the class template, and the class produced is called a + *"nonreal" class*; in general, a template class based on template arguments + that include at least one template parameter is called "nonreal". In + addition, a template class based on a template that is a member of a + nonreal class is also called "nonreal". Consider this example: + + .. code:: c++ + + template struct A { + template struct X {}; + }; + template struct B { + A a; + typename T::X x; + }; + B > b; + + | In this example, when class template ``A`` is scanned, the prototype + instantiation produces nonreal class ``A``, and during the scanning of + class template ``B`` nonreal classes ``A`` and ``T::X`` are + generated. Subsequently, when ``b`` is declared and ``B >`` is + instantiated, ``A``, a real class, is instantiated to serve as the + type for member ``B::a``, and ``A::X`` is instantiated to + serve as the type for member ``B::x``. +* | A prototype instantiation is also performed for alias templates resulting + in a nonreal alias. Nonreal aliases are also created for instantiations of + alias templates if the template argument list depends on a template + parameter. Unlike nonreal classes, nonreal aliases are actually + instantiated by rescanning the tokens of the alias. +* | Nested classes of class templates are not themselves referred to as + templates, but their member functions and static data members are, + respectively, member functions of class templates and static data members + of class templates, and a member function or static data member of a class + nested within a template class is handled as an instance of the + corresponding member function or static data member from the class + template. A class nested within a nonreal class is considered a nonreal + class. +* | The definition of a template instance may be supplied explicitly by the + user instead of being generated based on the template. Such instances are + referred to as *explicit specializations* of the template. +* | A class template or variable template may be *partially specialized*. A + partial specialization is an alternate version of the template that is used + to generate instances whose template argument lists match a specified + pattern. For example, a partial specialization could be provided that will + be used to generate all instances for which a specified template argument + is a pointer type. + + .. code:: c++ + + template struct A {}; // primary template + template struct A {}; // partial specialization + + | The template that is specialized by a partial specialization is called + the *primary template*. +* | Function templates may be overloaded with normal functions and with other + function templates. Overload resolution is used to select the function or + template to be used for a given call. If, as a result of overload + resolution, there are two or more templates that could generate equivalent + functions, *partial ordering* rules are used to select the template to be + used. Partial ordering is different from partial specialization in that + there is no relationship between the function templates being ordered (i.e, + one is not considered to be a specialization of the other). +* | In some modes, prototype instantiations are performed for entities other + than classes and aliases. When semantic analysis of nonclass templates has + been requested, prototype instantiations are done for the bodies and + default arguments of function templates and member functions of class + templates, the initializers of template static data members, and the + default values of template arguments. +* | Template template parameters are class templates for which the template + definition to be used for a given reference is supplied by a template + template argument. + +By default, prototype instantiations and entries associated with nonreal +classes and aliases do not appear in the IL. When +``PROTOTYPE_INSTANTIATIONS_IN_IL`` is TRUE, IL entries for prototype +instantiations are generated. See :ref:`templates-in-the-il` for more +information. + +Template definitions are typically placed in header files that are included by +the programs that make use of the templates. Alternatively, the definitions of +template static data members and non-inline template functions may be provided +using the "export" facility of the C++ language (see +:ref:`exported-templates`). + +The major part of template support falls into several phases. The first is +processing the declaration of the template, which for a class template also +involves doing a prototype instantiation. The second phase is recognizing a +reference to an instance of a template and producing a partial template +instantiation, which can be thought of as an on-the-fly declaration of the +instance. The third phase is the full instantiation of the template instance; +typically, a template class is fully instantiated at the first point of +reference in a given translation unit, but a template function presents special +complications, since the full instantiation of a noninline template function +may occur only once in a program, no matter how many translation units it may +appear in. + +Each of these phases of template processing will be examined in detail, but +first it is necessary to describe the data structures that are built to +represent templates and their instances. + +Data Structures +=============== + +Each collection of tokens that is stored so that the tokens may be rescanned +later is represented by an entry of type ``a_template_cache``. The fields of +the template cache entry are: + +* | ``tokens``, where the tokens are kept on which an instantiation of the + template is to be based. + + * | For classes the tokens comprise the base specifiers list as well as the + body of the class. + * | For functions, including member functions, they extend from the opening + left brace to the closing right brace of the function body, except that + for templates of constructors the *ctor-initializer* list, if present, is + also included. + * | For static data members the tokens identify the initializer, if any. + + | The last token in the token cache is always a ``tok_end_of_source`` token. +* | ``decl_info``, a pointer to an entry of type ``a_template_decl_info``, + which describes the context in which the tokens stored in the token cache + appeared. + +The template declaration information entry (``a_template_decl_info``) in turn +includes the following fields: + +* | ``parameters``, a pointer to list of entries of type ``a_template_param``; + they record the template parameters declared in the template declaration. + + * | For type parameters a template param entry points to an ``sk_type`` + symbol (which in turn refers to a ``tk_template_param`` type entry). + * | For nontype parameters a template param entry points to an + ``sk_constant`` symbol (which refers to a ``ck_template_param`` constant + entry). + * | For template template parameters a template param entry pointed to an + ``sk_class_template`` symbol. The template symbol supplement for which + the ``template_template_param`` field is TRUE. +* | ``declaration_scope``, identifying the ``sck_template_declaration`` scope + in which the template parameter symbols were declared. +* | ``enclosing_scope``, a pointer to the scope containing the template + declaration. This is important, for example, when a function template is + defined in a friend declaration within a class, in which case the class + must be reactivated when instantiations of that function template are + generated. +* | ``enclosing_template_decl``, a pointer to the template declaration + information for an enclosing template declaration. This is used for member + class templates and member function templates when one needs to know, for + example, not only the template parameters of the member template, but also + the template parameter lists of any enclosing class templates. +* | ``decl_seq``, the declaration sequence number at the point of the template + declaration. This is used when doing dependent name lookup to exclude + names not visible at the point of the template definition. +* | ``nondependent_calls``, used when doing dependent name processing to record + the result of overload resolution for nondependent calls that were + evaluated during a prototype instantiation. + +A template (of whatever flavor) is represented by the combination of a symbol +and an associated entry of type ``a_template_symbol_supplement`` (defined in +``symbol_tbl.h``). An instance of the template is then represented by an entry +that appears on a list pointed to from the template symbol supplement. That is +the basic pattern for representing a template and its instances -- a template +symbol, a supplement, and a list of instances -- but each sort of template +presents a different version of the pattern. + +The template symbol supplement contains a template cache entry for the template +body and also has fields that are specific to the kind of template it is +associated with; these are discussed below. + +In most cases the instantiation of a template creates one or more classes, +functions, and/or static data members. However, when a class template contains +members that are themselves templates (i.e, member function templates or member +class templates) the instantiation of the enclosing class template results in +the creation of entities that are templates. When this happens, it is +necessary to record the template from which the new template was generated. +The template symbol supplement field named ``prototype_template`` contains a +pointer to the symbol associated with the template from which a given member +template was generated. Similarly the prototype template contains a field +named ``subordinate_templates`` that points to a list of templates that were +generated from the prototype template. + +Class Templates +--------------- + +An ``sk_class_template`` symbol represents a class template; it contains a +pointer to a template symbol supplement. The supplement for a class template +includes the variant field ``instantiations``, a pointer to a list of the +symbols (of kind ``sk_class_or_struct_tag`` or ``sk_union_tag``) that represent +instances of the template. The symbol for the prototype instantiation is +pointed to by the field ``prototype_instantiation``. + +For each template class represented by a symbol on the instantiations list the +class symbol supplement has several important fields: + +* | ``class_template`` is a pointer back to the ``sk_class_template`` symbol + that represents the template upon which its instantiation is based. + However, for a nested class of a template class the ``class_template`` + pointer will always be NULL. +* | ``corresp_prototype_sym`` is a pointer to the template class symbol for the + prototype instantiation and is present for template class instances and + classes nested within template classes. +* | ``is_nonreal_class`` is TRUE for template classes produced by prototype + instantiations (and in general for template classes for which the template + argument list contains at least one template parameter reference). It is + also TRUE for a class that is a nested class of a nonreal template class. + +A class symbol for a template class (i.e., for an instance of a class template) +does not otherwise appear in the symbol table. It cannot be looked up directly +but rather must be looked up via the class template symbol. + +The type entry associated with a template class is like that of any other class +except that it contains the following additional information about template +classes: + +* | ``template_arg_list`` points to the template argument used to generate the + type (the template arguments are incorporated in the type so that back ends + can use them to generate names for template classes). +* | ``is_template_class`` TRUE for template class instances and classes nested + within template class instances. +* | ``is_nonreal_class`` is TRUE for nonreal instantiations and for local + classes of prototype instantiations. +* | ``is_prototype_instantiation`` is TRUE for prototype instantiations of + class templates and nested classes of class templates. +* | ``is_specialized`` is TRUE for template classes declared or defined in an + explicit specialization declaration. +* | ``specialized_with_old_syntax`` was specialized, but not with the + "``template <>``" syntax that is now required by the standard. +* | ``partial_spec_template_arg_list`` is used when a partial specialization is + used to generate the definition of the template class. It points to the + template argument list that is specified with respect to the partial + specialization's template parameter list. + +A class template may have associated with it a set of partial specializations +that may be used instead of the primary template when generating full +instantiations of instances of the class template. The template symbol +supplement contains a field named ``partial_specializations`` that points to a +list of ``sk_class_template`` symbols for any partial specializations that may +exist. Instances created from partial specializations go on the instantiations +list of the primary template. Each partial specialization has its own +prototype instantiation, which also goes on the instantiations list of the +primary template. The class type supplement field +``partial_spec_template_arg_list`` is used in class types generated from class +template partial specializations (including the prototype instantiation). It +contains the template argument list with respect to the partial specialization, +while the ``template_arg_list`` field contains the template argument list with +respect to the primary template. In the following example, the template +argument list with respect to the primary template is "````", while +the template argument list with respect to the partial specialization is +"````". + +.. code:: c++ + + template struct A {}; + template struct A {}; + A a; + +As mentioned previously, it is here that the type entries of real and nonreal +template classes differ -- the template arguments of a nonreal template class +involve at least one ``tk_template_param`` type or ``ck_template_param`` +constant. In addition, the type entry for a nonreal class does not appear in +the IL that is passed on to the back end for further processing. + +When an instance of a class template is fully instantiated, partial +instantiations for all of its member functions, static data members, and nested +classes are generated. Because these entities are not themselves templates, +they do not have their own template argument lists. The template argument list +for their enclosing class is used when a full instantiation is performed. + +Alias Templates +--------------- + +Alias templates are represented in much the same way as class templates. An +``sk_class_template`` symbol is used to represent the alias template, however +the instantiation list and prototype instantiation fields of the template +symbol supplement point to ``sk_type`` symbols. The ``is_alias_template`` +field of the template symbol supplement is used to identify alias templates. + +The typeref type created for instantiations of alias templates (with typeref +kind trk_is_template_alias) is like that of normal aliases except that it +contains additional information, including the template argument list and flags +such as ``is_template_alias``, ``is_nonreal``, and +``is_prototype_instantiation``. + +Function Templates +------------------ + +An ``sk_function_template`` symbol is used to represent a function template, +including member function templates, but not member functions of class +templates. It contains a pointer to a template symbol supplement whose variant +field ``instantiations`` points to a list of entries of type +``a_template_instance``: each time a partial instantiation is performed on the +function template, the resulting instance is recorded in this list. + +Entries of type ``a_template_instance`` are also utilized to record instances +of member function of class templates and static data members of class +templates, but they are used somewhat differently in those cases (as described +later). When a template instance is used to record an instance of a function +template, the following use is made of its fields: + +* | ``instance_sym`` points to the ``sk_routine`` symbol that represents the + instance. That symbol will in turn point to the routine entry created to + represent the instantiated function. A full instantiation need not have + been done. The routine entry contains a pointer to the template arguments + on which the instance is based. +* | ``template_sym`` points to the ``sk_function_template`` symbol that + represents the template. +* | ``instantiation_required`` is TRUE if the routine instance was actually + called or had its address taken. It means that a *full* instantiation + needs to be performed -- i.e., that the function body needs to be + generated. When this flag is set, the instance is placed on the + ``instantiations_required`` list, to assure that it is checked for + additional processing once the entire translation unit has been + scanned. +* | ``is_guiding_decl`` is TRUE if this routine was explicitly declared by the + user (whether or not a body was supplied). When this flag is set, the + symbol pointed to by ``instance_sym`` will have been added to the overload + list for this name. Note that a "specific declaration" is different than + an "explicit specialization". A specifically declared function + participates in overload resolution, but need not be explicitly + specialized. + | + | Here's an example: + + .. code:: c++ + + template void f(T) {} + void f(int); + + | The second declaration assures that ``f(int)`` is represented both in the + instantiations list for function template ``f`` and on the overload list + associated with an ``sk_overloaded_function`` symbol with an identifier + ``f``. Such a declaration affects how the function is found during + overload resolution, but it does not prevent a body from being generated + for it based on the function template. +* | ``explicit_instantiation`` is TRUE if the user has explicitly requested + full instantiation by means of an explicit instantiation directive or + ``#pragma instantiate`` directive. +* | ``referencing_namespace`` points to the namespace in which the use that + first required the instantiation of the template was encountered, or NULL + if the first reference was in the global namespace. This field is set when + the ``instantiation_required`` flag is set to TRUE. + +In addition to the pointer to the instantiations list, the template symbol +supplement for a function template makes use of some other variant fields: + +* | ``routine`` is a pointer to a routine entry. This entry is generated when + the function template declaration is scanned, but it doesn't actually map + to a real routine (and does not appear in the IL proper). Rather, it + serves as a convenient place to store the routine type and other + information about the function (e.g., the storage class, the special + function kind, and whether inlining was specified in the original + declaration). +* | ``func_info`` is a field of type ``a_func_info_block`` and stores + information picked up during declaration processing that needs to be reused + during instantiation (e.g., the names of the function parameters). +* | ``def_arg_expr_list`` is a list of entries containing information about + default arguments to be applied to the function parameters when the + instantiation is done. + +Whereas, as noted previously, an instance of a class template cannot be looked +up independently of its template, the same is not necessarily the case for an +instance of a function template. When there has been a guiding declaration, +the template function's symbol may be found during ordinary overload +resolution. However, when there is no guiding declaration, the symbol can only +be found via the function template symbol and its list of instantiations. +Consider this example: + +.. code:: c++ + + template T f(T t) { return t; } + char f(char); // Guiding declaration + int i = f(0); // Instantiation of f(int) + void f(int, int); // Unrelated to the template + +Symbols are arrayed under the symbol header for "``f``" as follows: + +* | overloaded function symbol with overload list: +* | template function symbol ``f(T)`` with instantiation list: +* | instance entry pointing to routine symbol ``f(char)`` +* | instance entry pointing to routine symbol ``f(int)`` +* | routine symbol ``f(char)`` +* | routine symbol ``f(int,int)`` + +Notice that the symbol for ``f(char)`` appears both on the overload list and on +the instantiation list (there are not two different symbols), whereas +``f(int)`` appears only on the instantiation list. The former, consequently, +is subject to the ordinary lookup rules, whereas the latter must be looked up +using the stricter rules for template functions. Guiding declarations have +been removed from the standard language, but are still supported by the front +end depending on the command line options and configuration flags being used. +When guiding declarations are disabled, declarations such as ``f(char)`` are +simply declarations of normal functions that are unrelated to the template. + +Member Function of Class Templates +---------------------------------- + +A member function of a class template is represented by an +``sk_member_function`` symbol created during the prototype instantiation of the +class template. These symbols look like ordinary member function symbols, +which among other things means they do not have their own pointer to a template +symbol supplement; rather they point to a template instance entry, and it has a +pointer to a template symbol supplement. + +The problem being addressed with this somewhat roundabout arrangement is that a +member function of a class template is really a "quasi-template" whose partial +instantiation is in fact always part of any full instantiation of the class +template to which it belongs. A consequence of this approach is that the +instantiations list from the associated template symbol supplement includes +both + +#. ordinary instance entries that point to ordinary member function symbols + (members of *real* instantiations of the class template) and + +#. one special instance entry that represents the quasi-template by + pointing to a member function symbol of the *nonreal* prototype + instantiation of the class template. + +The template instance entries for member functions are similar to those for +ordinary template functions: + +* | ``instance_sym`` points to the ``sk_member_function`` symbol that + represents the instance. +* | ``template_sym`` points to the ``sk_member_function`` symbol that + represents the template. +* | When ``instance_sym`` and ``template_sym`` are identical, the + ``template_info`` field is non-NULL and points to the template symbol + supplement belonging to this member function of a class template. +* | The flags are used as for nonmember function instances, except that + ``specific_decl`` is always TRUE. + +Variable Templates +------------------ + +A variable template is represented by an ``sk_variable_template`` symbol. +Instantiations of the template result in variable entries and associated +``sk_variable`` symbols. Variable templates declared in class scopes are, from +a language point of view, static data members, but they and their +instantiations are represented in the same way as non-member variable +templates. When a variable template is instantiated using a dependent template +argument list, the ``is_nonreal`` flag is set in the variable entry. The +``variable`` variant of the template symbol supplement contains information +used for both variable templates and static data members of class templates +(although some fields are only used for one or the other). The +``instantiations`` field points to a list of symbols for the real +instantiations of the variable template. Template instance entries are created +for the real instantiations of a variable template. + +Static Data Members of Class Templates +-------------------------------------- + +Static data members of class templates are represented much like member +functions of class templates. The template symbol, an +``sk_static_data_member`` symbol from the prototype instantiation of the class +template, points to an instance entry whose ``template_sym`` field points back +to it and whose ``template_info`` field points on to a template symbol +supplement. The latter has a ``definitions`` field that points to the instance +list. The fields in the instance entries are used just like those for member +functions. + +Template Declaration Information +-------------------------------- + +As described earlier, each token cache that is used in the template +instantiation process is associated with a pointer to an entry of type +``a_template_decl_info``, which contains information about the template +parameters, the scope in which the template was declared, and a pointer to an +enclosing template declaration information entry, if applicable. An enclosing +template declaration information pointer is used when a member function +template or member class template is declared within another class template. A +function template, or member function of a class template, contains a token +cache that contains the function declaration and a separate token cache +containing the function body. Each token cache has associated with it a +separate template declaration information pointer, because the two caches may +have come from different declarations with different template parameter lists, +etc. + +There is one template declaration information entry for each ``template <...>`` +clause that is scanned (except for those with empty parameter lists, which are +used in explicit specializations). When there is more than one template clause +in a given declaration, the inner template clauses contain a pointer to the +enclosing template declaration clause (the one to the left of a given template +clause). + +When a template is defined within another template the enclosing template +declaration information pointer is NULL indicating that the template +declaration information for the enclosing template should be obtained by +consulting its template symbol supplement. + +Template Declarations +===================== + +Overview +-------- + +``template_directive_or_declaration`` is the top-level routine for handling +template directives and template declarations. It is called when the +``template`` or ``export`` keyword is encountered during declaration +processing. This occurs for template declarations, explicit specialization +declarations, and explicit instantiation directives. For example: + +.. code:: c++ + + template struct A {}; // template declaration + export template void f(T){} // exported template declaration + template <> class A {}; // explicit specialization + template class A; // explicit instantiation + +When no template parameter list is present ``explicit_instantiation`` is +called. See :ref:`explicit-instantiation` for further information. When a +template parameter list is present, including an empty one (e.g., ``<>``), +``template_or_specialization_declaration`` is called. + +It first calls ``cache_template_declaration`` to create a token cache +containing the entire template declaration, including both the template +parameter list(s) and the declaration that follows. The definition of the +template (e.g., the class or function body) is not included in this cache. An +initial scan of the tokens in the cache is done to determine whether the +declaration is a full specialization, and whether it is a friend declaration. + +Template Parameter Clauses +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A template declaration or template specialization declaration contains one or +more "template parameter clauses". A template parameter clause consists of the +``template`` keyword followed by a possibly empty template parameter list. The +initial declaration of a template always has a single template parameter clause +(although a template declaration may be nested within another template +declaration). Multiple template parameter clauses are used only when a member +template of a class template is defined or specialized outside of its class. + +Each template parameter list has associated with it a template "nesting depth". +The nesting depth of the parameter list and the position within the template +parameter list are the attributes used when comparing two template parameters +to see if they represent the same parameter. The names of the template +parameters are not significant. The nesting depth and position are +collectively called the template parameter's "coordinates". + +For example: + +.. code:: c++ + + template struct A { + template void f(T1, T2, T3); + }; + template template void A::f(X,Y,Z){} + +where + +* | ``T1`` and ``X`` both have a nesting depth of 1 and a position of 1 +* | ``T2`` and ``Y`` both have a nesting depth of 2 and a position of 1 +* | ``T3`` and ``Z`` both have a nesting depth of 2 and a position of 2 + +The nesting depth of a template parameter clause in a namespace scope is 1, a +template parameter clause declared within one enclosing class template is 2, +etc. When scanning a template friend declaration any enclosing class templates +are ignored and the template parameter clauses are numbered beginning with 1. +This is necessary so that any types declared in the friend declaration match up +correctly with the template that is being made a friend. For example, to make +the template in the example above a friend of another template, you would do +the following: + +.. code:: c++ + + template struct B { + template + template friend void A::f(X,Y,Z); + }; + +The declaration of a template template parmeter also includes a template +parameter clause. The template parameters in the template parameter clause for +a template template parameter have a nesting depth of zero. + +For each nonempty template parameter list, the template parameters from the +parameter list are scanned. This process includes the following steps: + +* | An ``sck_template_declaration`` scope is pushed. This will be the + declaration scope to which the template parameter names belong. +* | ``scan_template_param_list`` is called to scan the template parameters and + build a linked list of entries of type ``a_template_param`` to represent + them. Each template parameter has an associated symbol. These symbols + initially point to special "prototype argument" values that, for class + templates, are used during the prototype instantiation. During real + instantiation these symbols are modified to point to the actual argument + values to be used. + + * | A type parameter points to an ``sk_type`` symbol that initially points to + a ``tk_template_param`` type. The type symbol points to the actual + argument type during an instantiation. + * | A nontype parameter points to an ``sk_constant`` symbol that initially + points to a ``ck_template_param`` constant. The constant symbol points + to the actual argument constant during an instantiation. + * | A template template parameter points to an ``sk_class_template`` symbol. + Unlike the type and nontype cases, the template template parameter symbol + always points to the template symbol supplement for that template + template parameter. The ``argument_template`` field of the template + symbol supplement points to the actual argument to be used during an + instantiation. Template template parameters differ from other template + parameters in that they have certain properties that must persist through + real instantiations. For example, the default template argument values + used for a template template parameter are always the ones specified in + the template template parameter declaration, never those associated with + the actual template template argument. +* | If the template parameter has a default argument, the type or expression is + scanned on the spot if possible. However, if the default argument depends + on another template parameter, the default argument must be rescanned when + its value is needed using the actual argument values for the template + parameters on which it depends. Therefore, its tokens are cached so that + they may be scanned later (see ``prescan_default_arg_expr``). There are a + number of ways in which a default argument can depend on another template + parameter: + + * | The type of a nontype parameter may make use of another template type + parameter. + * | The value of a default nontype argument may depend on a template type + parameter or nontype parameter. + * | The type used as the default argument for a type parameter may make use + of another template parameter. + + | For example: + + .. code:: c++ + + template class A {} + + | The default type of ``T`` and the default constant value for ``I`` can + be known when the template parameters are scanned, but the default type + of ``T2`` and the value for ``J`` are dependent upon whatever type + ``T`` takes on, and the value of ``J`` depends on the value used for + ``I``. + +Classifying the Template Declaration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When processing specializations a distinction is made between a "full +specialization" and a "template specialization". A full specialization is one +in which the entity being declared is a class, function, variable, or static +data member, while a template specialization is one in which the entity being +declared is still a template. For example: + +.. code:: c++ + + template struct A { + void f(); + template void g(T2); + template struct B {}; + struct C {}; + }; + // Full specializations + template <> void A::f(); + template <> struct A::C {}; + // Template specializations + template <> template void A::g(T2); + template <> template struct A::B {}; + +A partial specialization of a template is treated as a normal template +declaration, not as a template specialization. A template specialization is a +template with one or more empty template parameter clauses. + +Full specializations are handled by calling ``full_specialization``. See +:ref:`explicit-specializations` for more information. The rest of this +section describes ``template_declaration``, which is responsible for +processing template declarations and template specializations. + +Earlier, a token cache was built that contains the template parameter clauses +and the declaration that follows them. We are now at the point in the token +stream that marks the division between the two components. Because the +declaration component must be prescanned to determine the kind of template +being declared, and because the declaration may be needed later for the purpose +of generating partial instantiations of functions, the existing cache is split +into a template parameter cache and a template declaration cache. In certain +error cases, such as the presence of a syntax error in the template parameter +list, the template declaration may not have been cached correctly when the +initial cache was built. When this occurs, the template declaration is +recached now that the true position of the beginning of the declaration is +known. + +Next, ``is_class_template_decl`` is called. If the declaration is in fact of a +class template, TRUE is returned. If it is not a class template declaration, +FALSE is returned to signal that processing for other kinds of template +declarations should be done. + +The template parameters are checked to ensure that they are compatible with any +previous declaration of the template, and for class members, that the template +parameter lists that correspond to enclosing class templates are compatible +with the template parameter lists of those class templates. + +Class Templates +--------------- + +``class_template_declaration`` is called to process class template +declarations. This includes normal class templates, partial specializations, +and template specializations. It is also called to process declarations of +nested classes of class templates that are defined outside of the class. +``class_template_declaration`` performs the following functions: + +* | Looks up and verifies the template name. +* | Creates the ``sk_class_template`` symbol and enters it into the symbol + table, if necessary. The symbols for partial specializations are not + entered into the symbol table. +* | Calls ``create_prototype_type`` to create the symbol and type for the + prototype instantiation, and to create the template argument list(s) for + the prototype instantiation. +* | If a definition is provided, collects the tokens for the base class + specifiers and the class body and caches them for use later. +* | For partial specializations, the template parameters of the partial + specialization must appear in the template argument list associated with + the partial specialization in such a way that their values can be deduced. + In addition, nontype arguments cannot have types that depend on other + template parameters, nor may they be used in expressions. These error + tests are accomplished by calling + ``check_partial_spec_nontype_param_usage``. +* | If the template is a partial specialization, + ``check_for_prior_use_of_partial_spec`` is called to determine whether the + newly declared partial specialization would have been used to generate any + existing full instantiations of the primary template, had it been declared + when the full instantiation had been done. If any such full instantiations + are found, an error is issued. + +Then the template declaration scopes that were pushed when the template +parameter clauses were scanned are popped, and ``instantiate_class_template`` +is called to do a prototype instantiation -- i.e., to scan the template +definition even though the template parameters have not yet been given "real" +values. Because declaration/expression disambiguation often cannot be done +based on dummy types, only declarative information is scanned; inline function +bodies and default argument expressions are cached and, in some modes, have +their prototype instantiations done later. Most syntax errors and some +semantic errors are detected, but some errors cannot be reported until a real +instantiation is done. + +The main benefit of prototype instantiation is to record the names and types of +member functions and static data members -- in effect, to create symbols to +represent member functions of class templates and static data members of class +templates. ``instantiate_class_template`` accomplishes its work in the +following steps: + +* | An ``sck_template_instantiation`` scope is pushed onto the scope stack. +* | The token cache for the class template body is activated. +* | ``scan_class_definition`` is called to process the tokens. Special + provisions are made for prototype instantiations: + + * | Diagnostics are suppressed where appropriate. + * | ``decl_member_function`` and ``decl_static_data_member`` create template + instance entries, template symbol supplements, and whatever else is + needed to make the member symbols serve as templates. + * | ``delayed_scan_fixup_for_class`` moves the tokens cached for member + function bodies into the appropriate template symbol supplement; it also + moves the entries describing default argument expressions onto a list in + the appropriate template symbol supplement. The cached tokens for + inline-defined friend functions are discarded -- they will be picked up + during real instantiation. +* | The starting and ending token positions of any nested classes, member + functions whose definitions were provided in the class, and member + templates (functions or classes) whose definitions were provided in the + class are recorded. These token positions will be used to remove the + definitions from the token cache for the class template body. +* | The template instantiation scope is popped. +* | The bodies of nested classes, etc. are removed from the class template + body token cache. Nested classes, member functions, and member templates + may all be specialized. In other words, the definitions provided in the + class template definition may not be the ones actually used for a given + instance of the class template, so there is no sense in scanning them while + instantiating the class. As with class templates and function templates, + nested classes of class templates, member functions of class templates, and + member class and function templates are only instantiated when needed, and + may be specialized any time before the point at which they are first used + in a way that requires their instantiation. + +Alias templates +--------------- + +``alias_template_declaration`` is called to process alias template declarations +and performs the following functions: + +* | Verifies the template name. +* | Creates the ``sk_class_template`` symbol and enters it into the symbol + table. +* | Calls ``create_prototype_type`` to create the symbol and type for the + prototype instantiation, and to create the template argument list(s) for + the prototype instantiation. +* | Collects the tokens for the type defined by the alias and caches them for + use later. + +After calling ``alias_template_declaration``, ``template_declaration`` calls +``alias_prototype_instantiation`` to create the prototype instantiation of the +alias. + +Function Templates +------------------ + +The above is what happens when ``is_class_template_decl`` does in fact +determine that the declaration is a class declaration. However, if it returns +FALSE, ``template_declaration`` proceeds to examine what must be a template +declaration for something other than a class template. + +If the template declaration appears within the definition of a class it must be +a member function template declaration or a template friend declaration. If it +is a member function template declaration ``class_member_template_declaration`` +(in ``class_decl.c``) is called to scan its declaration, then +``complete_function_template_decl`` is called to create the necessary template +data structures and to scan the template body, if present. + +For all other cases, ``scan_template_declaration`` is called to scan the +declaration, which it does by calling ``decl_specifiers`` and ``declarator``. +If that produces a function type, the declaration is processed as a function +template or member function of a class template declaration; otherwise, it is +processed as a variable template or static data member of a class template +declaration or reported as an error. + +``function_template_declaration`` is called for function templates. It, in +turn, calls either ``decl_function_template`` (in ``decls.c``) or +``template_specialization``. + +``decl_function_template`` does for member and nonmember template declarations +more or less what ``decl_routine`` does for ordinary function declarations. +The processing for nonmember function templates includes the following: + +* | ``id_linkage`` is called to determine whether this is a redeclaration of a + function template that is already in the symbol table and whether the name + of the function template is overloaded. +* | If this is not a redeclaration, then: + + * | An ``sk_function_template`` symbol is entered into the symbol table + (either directly or into an overload set). + * | A routine entry is allocated and its fields are set to record the type, + storage class, and so forth specified in the declaration. It is not + added to the IL, however, because it does not designate a "real" routine. + +Member functions, for which a qualified name must be present, will already have +been declared in the class template definition. Their processing includes a +call to ``member_function_redecl_sym``, which returns the member function +symbol with a matching type signature. + +``decl_function_template`` returns to ``function_template_declaration`` an +already existing or newly created symbol that represents the function template. +Then, as with member function template declarations, +``complete_function_template_decl`` is called. + +Completing the Function Template +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The next step is to collect the tokens of the function body (including, for +a constructor, the *ctor-initializer*\ s) and store them in a cache in the +template symbol supplement. For both member and nonmember function +templates the new template declaration information (parameter list, etc.) +is recorded in the associated template symbol supplement. + +When doing nonclass prototype instantiations, +``function_prototype_instantiation`` is called to perform a prototype +instantiation on the body of a function template or member function of a class +template, and ``default_arg_prototype_instantiation`` is called to perform a +prototype instantiation on the default arguments of such functions. + +Variable Templates and Static Data Member Templates +--------------------------------------------------- + +Variable template declarations can be either ``extern`` declarations, or are +definitions. Static data member declarations are always definitions. For +definitions, the template parameter list is recorded in the template symbol +supplement, and the tokens comprising the initializer, if any, are cached. In +some cases, some or all of the initializer may have already been cached as part +of the template declaration. In such cases, ``split_token_cache`` is used to +move the initializer tokens from the declaration cache to the initializer +cache; the remaining initializer tokens are then appended to the initializer +cache. + +When doing nonclass prototype instantiations, +``variable_template_prototype_instantiation`` is called to perform a prototype +instantiation on the initializer of the variable template or template static +data member. + +Variadic Templates +------------------ + +The C++11 standard adds "variadic templates," which are templates that take a +variable number of arguments. For example: + +.. code:: c++ + + template void f(T ...args) { + int a[] = {0, args..., 5}; + } + int main() { + f(1, 2, 3, 4); + } + +The template ``f`` can be called with zero or more arguments. For a given +call, the parameter pack ``T`` is deduced to be a list of types, matching the +types of the arguments supplied, and ``args`` is a function parameter pack that +is a series of parameters of the types given by ``T``. + +The front end implements variadic templates by storing, along with the tokens +of the template, information on the location and details of any pack references +and expansions. When the template is instantiated, the cached tokens of its +declaration or definition are scanned, and in places where there are pack +expansions, the processing loops over a sequence of tokens, substituting a +different value for the pack name on each iteration, thus producing an expanded +version of the source text. + +The language definition of variadic templates uses a syntax-based trick: in +contexts that allow a list of items (usually, a comma-separated list), an item +in the list can be suffixed by "``...``" to indicate that it is a pack +expansion. In an instantiation of the template, that pack expansion is +replaced by, in effect, a list of entities generated by the expansion of the +pack. So, in the above example, the aggregate initialization expands to the +equivalent of + +.. code:: c++ + + int a[] = {0, 1, 2, 3, 4, 5}; + +with the elements of the pack expansion inserted into the surrounding list. + +Such expansions are allowed in parameter lists, call argument lists, +brace-enclosed aggregate initializers, base class specifiers, +*mem-initializer*\ s, template argument lists, exception specifications, +attributes, and capture lists. + +The front end uses its own trick to expand these patterns. In each of those +contexts, the code that handles the normal, non-variadic, case is enclosed in a +loop with the following general structure: + +.. code:: c++ + + a_pack_expansion_stack_entry_ptr pesep; + a_boolean any_more; + + any_more = begin_potential_pack_expansion_context(&pesep); + while (any_more) { + a_pack_expansion_descr_ptr pedep; + + /* Normal processing for one item is done here. */ + ... + pedep = end_potential_pack_expansion_context(pesep, + /*is_declarator=*/FALSE); + if (pedep != NULL) { + /* Mark the IL created as being for a pack expansion. */ + } /* if */ + any_more = advance_to_next_pack_element(pesep); + } /* while */ + +When no pack expansions are present, the "``begin...``" call returns TRUE, the +"``end...``" call returns NULL, and the "``advance...``" call returns FALSE, so +the loop goes around exactly once and handles one item on the list. + +When a pack expansion is present, in the prototype instantiation the +"``begin...``" call returns TRUE, the "``end...``" call swallows the "``...``" +indicating the pack expansion and returns a pointer to a structure that +describes the pack expansion, and the "``advance...``" call returns FALSE. +Again, the loop goes around exactly once, but information about the pack +expansion is recorded in the IL and in data structures attached to the +template. + +In a real instantiation, the loop goes around as many times as the pack being +expanded has values. Each time through, the source token position is reset to +the start of the expansion, the pack identifier is given an appropriate value +for that iteration, and the tokens are scanned again. After the right number +of iterations, the "``advance...``" call returns FALSE and the loop exits. If +the pack has zero elements, the "``begin...``" call advances the source token +position to after the "``...``" at the end of the expansion, and returns FALSE, +and the loop goes around zero times, thus producing no items on the list for +the pack expansion. + +The pattern above appears in every place where a pack expansion could occur. +In a call argument list, for example, it must be done around the scanning of +every argument, which means in a lot of places. (Or, at least, in a lot of +places when inside a template that has variadic parameters.) Almost all the +time, the variadic processing notes a starting position and starts a potential +expansion context, but then finds out later that there is no trailing "``...``" +and therefore no pack expansion, and discards the information saved. This has +to be done, however, so that we can recall the starting position of a pack +expansion in the cases where one does occur. + +The information saved for a pack expansion in the prototype scope (and, +incidentally, prototype instantiations are forced for variadic templates, so +that such information can be recorded) includes the starting position of the +pack expansion, so that, in a real instantiation, the "``begin...``" call can +look up the current token position and see whether a pack expansion starts at +the current token, and what the details of the expansion are. The saved +information includes the list of pack names that were referenced and are to be +iterated over in the loop. With that information, the "``begin...``" routine +can set up the proper looping over the proper sequence of tokens. + +There are variant versions of these variadic-loop-management routines that are +used for expression rescan contexts (no source tokens are consumed; pack +identifiers are updated and the right number of iterations of the loop are +done) and prescan and disambiguation contexts (where we don't know yet the +context of the code, and therefore can't be certain about what pack expansions +mean, so we don't want to record anything permanent). + +Template argument lists need to contain some extra information when variadic +templates are used. For example, for a case like + +.. code:: c++ + + template void f(U p, T ...args) { + } + int main() { + f(1, 2.0, 3.0f); + } + +the complete deduced template argument list for ``f`` has ``int`` for ``U``, +and then a list of ``double`` and ``float`` for T. In diagnostics, this is +displayed as ``>``. Internally, it requires a way to +indicate that part of the list is a pack expansion. That's the function of the +``tak_start_of_pack_expansion`` kind of template argument: it marks the start +of a sequence of template arguments associated with a pack expansion (and each +member of that sequence is marked with the ``is_pack_element`` flag). + +That causes problems for lots of code in the front end that traverses template +argument lists. In most cases, that code does not want to worry about +start-of-pack-expansion entries. It just wants the "real" entries on the list. +That's what the traversal routines ``begin_template_arg_list_traversal``, +``advance_to_next_template_arg``, and the "``..._simple``" versions of those +routines do. They allow easy set up of a traversal of a template argument list +that ignores the start-of-pack-expansion entries. They should be used in +general to process template argument lists, to avoid problems. + +Deduction does special processing to handle parameter packs, matching up +template parameters with multiple types, or nontype values, or template +template parameters. Zero-length packs are a particular problem, in that they +are deduced from an absense of information (e.g., no arguments corresponding to +that parameter pack). + +Overload resolution does special processing for parameter packs, and in +particular has to be careful because the normal one-to-one correspondence +between arguments and parameters does not always hold. + +Initializer processing deals with pack expansions by using expresison caches. +The initializer routines call to fetch one expression. If the expression +scanned is a pack expansion, the first expresison of the expansion is returned, +and the rest are pushed into an expression cache. They are then returned on +subsequent calls at the same or a higher or lower level. If the pack expansion +produces zero expressions, another expression is scanned, unless we hit the end +of the initializer (e.g., a closing brace). In some cases an expression is +prescanned so we can decide whether the expression-list is over before going +down a path in the code that will expects to be able to fetch an expression. + +Partial ordering and partial specialization processing also deal specially with +variadic templates. + +Templates in the IL +=================== + +An entry of type ``a_template`` is created for each template declaration (see +``make_il_template_entry``). By default, no information about the template +itself is preserved in the IL. There are two different optional mechanisms +that can be used to record information about templates: + +* | If ``PROTOTYPE_INSTANTIATIONS_IN_IL`` is TRUE, any prototype instantiation + is recorded in the IL. If nonclass prototype instantiations have been + requested, prototype instantiations will be generated for each template + entity declared; otherwise, prototype instantiations will be recorded only + for class templates. A prototype instantiation is an IL entry whose kind + corresponds to the kind of entry being declared, but that represents the + template itself and not any particular instantiation thereof. In other + words, it still contains references to the template parameters. A type + entry is used to represent a class template, a routine entry is used to + represent a function template, and a variable entry is used to represent a + variable template or template static data member. +* | If ``RECORD_TEMPLATE_STRINGS`` to TRUE, the IL template entry will point to + a null-terminated string that reproduces the text (minus comments, after + preprocessing) of the template declaration in the source program (see + ``make_template_string``). If a template has more than one declaration + (e.g., a nondefining declaration followed by a definition), an IL template + entry is produced for each declaration. + +Both of these mechanisms can be used at the same time. Note that while all +templates can be represented as template strings, only those templates that +make use of the standard-mandated ``typename`` and ``template`` keywords +can have prototype instantiation IL entries generated (because without such +keywords it is not possible to parse the template definitions in the +absence of a set of actual template argument values). See +:ref:`templates-in-the-il` for more information. + +Partial Instantiation +===================== + +Partial instantiation occurs automatically for nested classes, member +functions, and static data members when the class of which they are members is +instantiated. That is to say, the full instantiation of a class necessarily +entails the implicit declaration of all its members: symbols are introduced +into the symbol table, type entries are created as required, IL entries are +created and added to the IL, and so forth. The partial instantiation of class +templates and function templates, on the other hand, is triggered by a +reference. + +Class Templates +--------------- + +When a class template reference -- *class-template-name*\ ``<``\ +*template-arg-list*\ ``>`` -- is encountered, a call is made to +``coalesce_template_class_reference`` to scan the template argument list and +look up the reference. Having verified that types in the template argument +list correspond to type template parameters and constants correspond to nontype +template parameters, it builds a linked-list representation of the template +arguments. If there are more template parameters than template arguments and +if the template parameters have default values, entries are supplied for the +default values as well, whether from a saved constant value or after rescanning +the cached tokens comprising the default argument expression. + +The template argument list is then passed to ``find_template_class``, which +searches among the instantiations that already exist for the class template, +calling ``equiv_template_arg_lists`` to compare the template arguments scanned +for the current reference against the template arguments associated with +existing instantiations. If an instance with matching template arguments is +located, the symbol for it is returned. If no match is found, a new symbol is +created (see ``make_template_class_sym`` in ``symbol_tbl.c``) and added to the +instantiations list for the class template. A new class type is also created, +but, since this is a partial instantiation, no body is generated for it yet. + +A reference to an instance of a class template *always* causes a partial +instantiation, but not all references cause full instantiation. Partial +instantiation occurs during the *lexical* scan of a template class reference, +whereas the decision whether to do full instantiation occurs during *semantic* +processing. Partial and full instantiation are always separate steps in +template processing. + +Note that a partial instantiation can be generated on the basis of an +incomplete class template. For example: + +.. code:: c++ + + template class A; + A *x; + +Even though no body has been supplied for class template ``A``, a partial +instantiation of ``A`` can be produced. On the other hand, ``A`` is +an incomplete (and incompletable) type, and so an error would be issued if it +were used in a context that required a complete type. Similarly, partial +specializations are not relevant when a partial instantiation is generated. +They are only considered when a full instantiation is done. + +Function Templates +------------------ + +A function template may be referenced in several different ways: + +* | as a function call, +* | by taking the address of a function, +* | and by declaring a function in an explicit specialization, explicit + instantiation, or friend instance declaration. + +In each case, determining which function template is to be used, and which +instance of the template is being referenced, requires the evaluation of an +explicitly specified template argument list, deducing template arguments from +the function template's parameters, or some combination of the two. This +process involves the following steps for each of the candidate function +templates: + +* | If an explicit template argument list was specified, + ``substitute_template_arguments`` is called. Note that an explicit + template argument list is completely scanned before + ``substitute_template_arguments`` is called. When it is scanned, the + number of parameters, and their types are not known. Consequently, the + template argument list needs to be converted into one that matches the + template parameter list of the candidate template. This is done by calling + ``create_initial_template_arg_list``. If the specified template arguments + cannot be converted to the types of the corresponding parameters, or if + there are more template arguments than template parameters, no template + argument list is created and the candidate template is disqualified. Note + that an error is not issued because there may be another candidate template + that is actually the one intended to be used. +* | Once an appropriate template argument list has been produced, + ``substitute_template_arguments`` calls ``copy_type_with_substitution`` to + create a function type that represents the function type of the candidate + template with the template parameters that correspond to the explicitly + specified template arguments replaced with the specified template argument + values. If the substitution process would result in an invalid type (e.g., + a pointer to a reference type, or an array of void) the candidate template + is disqualified. +* | Template argument deduction is done using the substituted function type + created above in an attempt to deduce the template arguments that were not + explicitly specified. Template argument deduction is done by calling + ``matches_template_type``, which is described below. +* | If template argument deduction succeeds, + ``wrapup_function_template_argument_deduction`` is called to verify that + values have been deduced for all of the template parameters, and that the + types of any deduced nontype parameters match the types of the + corresponding template parameters. ``copy_type_with_substitution`` is + called once again to create a new function type in which all of the + template parameters have been replaced with the corresponding template + argument values. + +When the reference is from a function call, the routines described above are +called from the overload resolution routines. When the reference is from the +address of a function or from a declaration, these routines are called by +``is_match_for_function_template``, which in turn is called from either +``matching_template_function`` or ``has_matching_template_function``. + +There are several routines in ``templates.c`` that directly and indirectly +support the process described above: + +* | ``matches_template_type`` is designed to be called successively to build a + template argument list while checking for a match between a type from the + function template routine type and a type from a new routine type; it also + calls itself recursively to apply the processing to type trees. When a + template parameter type is found, the "real" type with which it is paired + is recorded in the corresponding template argument entry -- unless it + already has some other type, in which case an inconsistency has been found. + As long as there are no inconsistencies or type incongruities, this process + of augmenting the template argument list continues; otherwise, + ``matches_template_type`` returns FALSE to halt further processing and + invalidate the template argument list built thus far. + | + | After ``matches_template_type`` has indicated that each of the arguments + match the template, ``verify_template_nontype_args`` must be called to + verify that nontype parameters whose types depend on a template parameter + are consistent with the deduced types. It also supplies types for nontype + parameters that are deduced entirely from array bounds. +* | ``compare_function_templates`` is used to determine whether one function + template is *more specialized* than another based on the partial ordering + rules for function templates. It is called by the overload resolution + routines to compare two function templates that are otherwise identical + from the point of view of overload resolution. +* | ``add_to_partial_order_candidates_list`` is used in contexts other than + overload resolution in which a function template must be selected from a + set of function templates using the partial ordering rules. This is done + when taking the address of a function that is determined to be an instance + of a function template, and when the lookup of a conversion operator name + results in the partial instantiation of a template (e.g., when ``operator + int*`` is a reference to an instance of a function template such as + ``operator T*``). After this routine has been called for each candidate + template, ``select_best_partial_order_candidate`` is called to return the + best matching template. +* | ``find_template_function`` is passed a function template symbol and a + template argument list. After checking for the use of a local type among + the template arguments (an error), it goes through the instances that + already exist for the template, calling ``equiv_template_arg_lists`` until + a match is found. If none of the existing instances match the new template + argument list, it creates a new instance by calling + ``make_template_function``, to which the new template argument list is + passed. +* | ``is_match_for_function_template`` is passed a function template symbol and + a new routine type. It returns TRUE if the type fits the type signature of + the template and FALSE if not. First, obvious mismatches are detected, + such as mismatches in the number of function parameters. Next, if an + explicit template argument list was specified, the template arguments are + compared with the corresponding template parameters. Type arguments must + be associated with type parameters, nontype arguments must be associated + with nontype parametersm, and the specific nontype value specified must + match the type of the nontype parameter or must be capable of being + converted to the type of the nontype parameter. It then tries to find + among the instances of the template one whose type signature exactly + matches the new routine type. If it finds such an instance, it returns + TRUE, along with the symbol it found. Otherwise, it makes successive calls + to ``matches_template_type`` in an attempt to construct a template argument + list based on any explicitly specified template arguments, the template + parameter types, the template routine type, and the new routine type; if + this is successful, it returns TRUE, along with the new template argument + list, but otherwise it returns FALSE. +* | ``matching_template_function`` is passed a function template symbol and a + routine type. It calls ``is_match_for_function_template`` which checks for + a match between the routine type and the template. If there is a match but + no instance already exists, it creates a new instance by calling + ``make_template_function``, to which the routine type is passed. +* | ``has_matching_template_function`` is similar to + ``matching_template_function`` in that it determines whether a given + routine type matches a potential instance of the specified template, but it + does not create an instance of the template. It is primarily used when + issuing diagnostics, to choose the most appropriate of several possible + messages. In the following example, the error "specializing overloaded + function ``"A::f"`` requires ``template <>`` syntax" is used because the + function type matches the template declared in the class. + + .. code:: c++ + + struct A { + template void f(T); + }; + void A::f(int) {} + +* | ``make_template_function`` is the routine that actually does the partial + instantiation. When it is passed a non-NULL routine type, it simply uses + that type; otherwise, it activates the declaration token cache (see the + ``decl_token_cache`` field in the template symbol supplement) and calls + either ``scan_member_declaration`` or ``scan_template_declaration``, for + member and nonmember function templates, respectively, to assure that + template arguments are correctly substituted for template parameters in the + new routine type; and then, if there are default arguments, it calls + ``delayed_scan_for_function_template_default_args``. In addition, it + creates the ``sk_member_funciont`` or ``sk_routine`` symbol entry, the + routine entry, and the template instance, setting all their pointers and + other fields appropriately. The symbol is not entered directly into the + symbol table -- it is accessible to lookup via the instantiation list only. + +Variable Templates +------------------ + +A reference to a variable template results in a full instantiation of the +instance if a definition is available. The only exception is when the variable +template is used in a declarative context (i.e., to declare an explicit +specialization of the variable template). In a partial instantiation the +initializer is not scanned. + +Full Instantiation +================== + +Full instantiation of a template means providing an instance of the template +with a defining body (or, in the case of a static data member, a definition +with an implicit or explicit initializer). Typically, this occurs +automatically, on the basis of the template provided. However, it can also +occur when the user provides an explicit specialization definition. Both cases +are discussed in this section. + +.. _explicit-specializations: + +Explicit Specializations +------------------------ + +Two forms of explicit specialization are supported by the front end: the new +explicit specialization syntax (e.g., ``template <> ...``), and the old form +that used the normal declaration syntax. The new form is accepted in all +modes, while acceptance of the old form is controlled by a command line option. +Member function templates and member class templates may only be explicitly +specialized using the new syntax. + +For example: + +.. code:: c++ + + template void f(T); + template class A {}; + template <> class A; // new specialization declaration + template <> class A {}; // new specialization definition + class A; // old specialization declaration + class A {}; // old specialization definition + template <> void f(int); // new specialization declaration + template <> void f(int){} // new specialization definition + void f(char); // guiding declaration + void f(double){} // old specialization + +Explicit specializations that use the new syntax begin with one or more +template parameter clauses in which the parameter list is empty. An explicit +specialization can be a declaration or a definition. The language requires +that an explicit specialization be declared before its first use in a +translation unit. + +When using the old syntax, only classes can be declared as specializations. +For all other kinds of entities, specializations can only be supplied as +definitions. A function declaration that looks like an old-style +specialization declaration is actually what is known as a "guiding +declaration", whose only purpose is to cause a template instance to be treated +like a normal function for overload resolution purposes. There are no member +guiding declarations. + +Old-style explicit specializations look like normal class, function, and static +data member declarations and are handled by the same routines that handle +normal declarations. + +``full_specialization`` processes new-style explicit specializations and is +called after the template parameter clauses have been scanned. +``decl_specifiers`` and ``declarator`` are called to scan the declaration that +follows the template parameter clauses. If the entity being specialized is a +class, the call to ``declarator`` is bypassed. ``full_specialization`` then +identifies the template instance that is being specialized. + +Class Templates +^^^^^^^^^^^^^^^ + +An explicit specialization of a class template occurs when the explicit +specialization syntax is used, or when old specializations are enabled, when an +ordinary class definition is provided in which the class name is a template +class reference, for example: + +.. code:: c++ + + template class A {}; + template <> class A {}; + class A {}; + A x; + +In this example the bodies for ``A`` and ``A`` are the ones +provided by the user's explicit definitions. The bodies for all other +instances of template class ``A``, such as ``A``, are based on the +template definition. + +The processing of class template explicit specializations is done within +``class_specifier``, even when the new specialization syntax is used. This is +necessary because only when ``class_specifier`` is called is it possible to +determine whether the class is being specialized or whether the class specifier +is part of an elaborated type specifier in some other kind of declaration. + +When the template class reference is encountered as a tag name (see +``scan_tag_name``), a partial instantiation is done automatically and the +symbol is entered on the instantiations list of the class template. Then +``class_specifier`` marks the class as being explicitly specialized by setting +the ``is_specialized`` flag in the type entry, and adds the definition, if one +has been supplied. Because the ``is_specialized`` flag is set, no subsequent +automatic instantiation will be attempted. + +The same processing applies to both class templates and member class templates. +The processing for nested classes of class templates is basically the same +except that, as with other members of class templates, the partial +instantiation of the nested class is done when the enclosing class is +instantiated. + +Function Templates and Member Functions of Class Templates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An instance of a function template may be explicitly specialized using the +explicit specialization syntax, or when old specializations are enabled, by +providing a function definition that happens to match the type signature of a +function template. For example: + +.. code:: c++ + + template void f(T) {} + template <> void f(char); // explicit specialization + void f(int) {} // old explicit specialization + void f(int,int} {} // Unrelated to the template + +In both the old and new style specializations, the ``is_specialized`` flag in +the routine entry is set, which suppresses the full instantiation of the +template. The old-style specialization of a function also acts as a guiding +declaration for overload resolution purposes. + +When the new specialization syntax is used, ``find_matching_template_instance`` +is called to find the template instance that matches the routine type returned +by ``declarator``. This is done not only for instances of function templates +and member function templates, but also for member functions of class +templates. + +Processing for old-style explicit specializations follows the track for +ordinary function definitions. The primary difference appears in +``find_linked_symbol`` (called from ``decl_routine`` via ``id_linkage``), which +searches for previous declarations of the entity being declared. If the +ordinary search fails to turn up a matching function but does find a function +template with the given name, a call is made to ``matching_template_function``, +which extends the search to instances of the template function and, as +described above, creates a new one when appropriate. In other words, this +search in ``id_linkage`` may have the effect of doing a partial instantiation +of a new template function. Once the instance symbol has been found (or +created by means of a partial instantiation), attaching the function definition +to the routine involves no special processing. + +It can happen that an old-style explicit specialization of a function template +precedes the declaration of the template itself. For example: + +.. code:: c++ + + void f(int) {} // Specific definition + template void f(T) {} + +When the function template declaration is encountered, +``decl_function_template`` goes back through existing functions of the same +name and calls ``record_predeclared_template_function`` for each -- if the +function turns out to match the new template, it is retroactively entered as an +instance. + +Old-style explicit specializations of member functions or static data members +of instances of a class templates involve little special handling beyond what +is normally done for definitions of member functions and static data members of +nontemplate classes. Here's an example: + +.. code:: c++ + + template class A { + void f(T); + static T s; + }; + void A::f(int) {} + int A::s = 0; + +The reason no special processing is required is that the full instantiation of +``A`` entails the partial instantiation of its members ``f(int)`` and +``s``. After that it's just a matter of marking the symbols as ``defined`` and +adding the function body or initializer. + +Variable Templates +^^^^^^^^^^^^^^^^^^ + +The use of a variable template in an expression context results in a full +instantiation if a definition is available. If a definition is not available, +the normal instantiation processing is done as for template functions and +static data members of template classes (e.g., an instantiation could be done +later in the translation unit if a definition was provided, depending on the +instantiation mode). Even though a full instantiation may be done, an external +definition of the instance may or may not be emitted depending on the +instantiation mode. + +Automatically Generated Definitions +----------------------------------- + +Class Templates +^^^^^^^^^^^^^^^ + +The full instantiation of a template class occurs at the first point in the +translation unit where a reference to the instance requires it to be a complete +type. In other words, it is done as soon as necessary, but no sooner. For +example: + +.. code:: c++ + + template class A {}; + A *p; // Partial instantiation of A + A a; // Full instantiation of A + +The first declaration involving ``A`` does not require that it be a +complete type, but the second one does, and so that is the point at which the +full instantiation occurs. At points in the front end where a complete type is +required, the macro ``complete_class_type_is_needed`` is invoked, resulting, if +appropriate, in a call to ``instantiate_template_class`` to generate the full +instantiation. + +Partial Specializations +~~~~~~~~~~~~~~~~~~~~~~~ + +A class or variable template may be partially specialized. A partial +specialization is a version of the template that should be used for certain +instantiations. The template to be used is selected based on the template +argument list on which the instantiation is to be based. + +When a full instantiation is required, ``check_partial_specializations`` is +called to match the template argument list of the class being instantiated with +each of the partial specializations that have been declared for the template. +``matches_partial_specialization`` is called to perform the actual matching. + +The matching is done using the same process and routines that are used to do +function template argument deduction (see ``matches_template_type`` above). If +the template parameters for a given partial specialization can be deduced from +the actual template arguments, then the template class matches the partial +specialization. For example: + +.. code:: c++ + + template struct A {}; // #1 + template struct A {}; // #2 + template struct A {}; // #3 + template struct A {}; // #4 + A a1; // uses primary template (#1) + A a2; // uses #2 + A a3; // uses #3 + +The declaration of ``a1`` does not match any of the partial specializations, so +the primary template is used. The declaration of ``a2`` matches the partial +specialization labeled #2 because ``U1`` and ``U2`` can be deduced from +```` (as ``int`` and ``int``, respectively). Partial specialization +#3 is used when the two template arguments are the same, as in the declaration +of ``a3``. + +Each partial specialization that matches the argument list is added to a list +of candidate partial specializations using the routine +``add_to_partial_order_candidates_list``, which compares the new entry with any +entries already on the candidates list. The comparison is done by +``is_more_specialized``, which determines whether a given partial +specialization is "more specialized" than another. If the entry being added is +not as specialized as an entry already on the list, the new entry is not added. +If the new entry is more specialized than an entry already on the list, that +entry is removed from the list. After all of the partial specializations have +been evaluated, the candidates list contains a set of partial specializations +that match the template argument list of the class being instantiated and which +are unordered relative to one another. If there are no entries on the list, +the primary template is used to generate the class. If there is exactly one +entry on the list, that partial specialization is used to generate the class or +variable. If there is more than one entry on the list, the instantiation is +ambiguous and an error is issued. + +.. code:: c++ + + A a4; // ambiguous - could be #2 or #3 + A a5; // uses #4 + +The declaration of ``a5`` uses partial specialization #4, even though both #2 +and #4 match. #4 is preferred because it is "more specialized" than #2. +Whether a given partial specialization is more specialized than another is +determined in much the same way in which a partial specialization is determined +to match a given actual template argument list, i.e., though use of the +argument deduction routines. In the example above, if the argument list of #4 +was considered to be the actual argument list and the argument list of #2 was +considered to be the parameter list, the parameters of #2 could be deduced as +``U1=X1`` and ``U2=short``. If the roles of the two partial specializations +are reversed, making #2 the actual argument list and #4 the formal parameter +list, the type deduction fails. Therefore, #4 is considered more specialized +than #2. + +Generating the Template Class +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once the appropriate template has been selected (i.e., either the primary +template or a partial specialization), the body of the template class is +generated. These are the steps: + +* | The ``pending_instantiations`` value in the template symbol supplement for + the class template is incremented. This allows the compiler to catch and + report "runaway recursive instantiation," as the following example would + produce: + + .. code:: c++ + + template class A { A a; }; + A<0> x; + + | Once the pending instantiations counter reaches + ``max_pending_instantiation`` (a global variable that can be set by a + command-line option, and whose default is defined in ``lang_feat.h``), an + error is issued and the recursion is halted. +* | ``push_template_instantiation_scope`` is called to push a template + instantiation scope onto the scope stack and to do some special processing + for template instantiations: + + * | Pointers to the template symbol, the instance symbol, and the template + argument list are recorded in the scope stack entry. + * | ``depth_innermost_instantiation_scope`` is updated with the current scope + stack depth. + * | ``update_template_param_symbols`` is called to bind the symbols for + template parameters to the values in the corresponding template + arguments. For example: + + .. code:: c++ + + template class A {}; + A x; + + | By default the ``sk_type`` symbol for template parameter ``T`` refers to a + ``tk_template_param`` type entry and the ``sk_constant`` symbol for ``I`` + refers to a ``ck_template_param`` constant. But during the instantiation + of ``A`` -- that is, while the template instantiation scope is + active -- any reference to ``T`` or ``I`` should be translated into a + reference to the value of the corresponding template argument, namely, to + ``int`` or ``0``, respectively. This is done by modifying the pointers in + the symbols; the default pointers are restored when the template + instantiation scope is popped. +* | The cache containing the tokens for class template definition is activated. +* | ``scan_class_definition`` is called. In most respects processing is + identical to the processing for any class definition. The differences have + mainly to do with recording member functions and static data members as + instances: + + * | ``find_corresp_prototype_tag_sym`` is called to find the symbol for the + prototype instantiation of the class. (When a nested class within a + template class is scanned, the symbol returned is the corresponding + nested class of the prototype instantiation.) That symbol is required for + calling the two routines described next. + * | ``find_member_function_template`` is called for member functions of the + new template class. It locates the template symbol (i.e., the symbol for + the corresponding member function in prototype instantiation), creates a + template instance entry for the new member function, and adds it to the + instantiation list of the template. The template argument list for the + new template class serves for the instance, too. + * | ``find_variable_member_template`` is called for variable templates and + static data members of the new template class. The processing is similar + to what is done for member functions. + * | ``find_function_template_member`` is called for member function templates + of the new template class. The processing is similar to what is done for + member functions. + * | ``find_class_template_member`` is called for member class templates of + the new template class. The processing is similar to what is done for + member functions. + * | ``set_nested_template_class_symbol_info`` is called for nested classes of + the new template class. This call is made by ``class_specifier`` when + the nested class is first encountered. The processing is otherwise + similar to what is done for member function. + * | ``delayed_scan_fixup_for_class``, called at the end of scanning the class + definition, provides somewhat special handling for template classes. For + inline-defined member functions the function bodies are not scanned at + this time; such functions are only instantiated if they are called, so + that errors are not issued on functions that are not actually used. + Also, ``delayed_scan_for_function_template_default_args`` is called to + process the default arguments on the function parameters: the token cache + to be used is accessed through the template symbol supplement. +* | ``set_instantiation_required_for_template_class_members`` is invoked; for + each member function and static data member, both of the template class and + of any classes nested within the template class, it calls + ``update_instantiation_required_flag``. +* | ``pop_template_instantiation_scope`` is called to pop the template + instantiation scope. The template parameter symbols and + ``depth_innermost_instantiation_scope`` are restored to the values they had + before the scope was pushed. (Note that the possibility of recursive + instantiation prohibits restoring these values to default values.) +* | The ``pending_instantiations`` value in the template symbol supplement for + the class template is decremented. + +Alias Templates +^^^^^^^^^^^^^^^ + +When an instance of an alias template is referenced, ``find_template_class`` is +called to look for a previously created template alias or instantiate a new +alias if no previously created instance exists. Template aliases are +instantiated by ``instantiate_template_alias``. Note that unlike class +templates, there are no partial instantiations of alias templates + +Function Templates +^^^^^^^^^^^^^^^^^^ + +The timing for the instantiation of member and nonmember template functions is +partly controlled by the user (as discussed in the next section). A function +may end up being instantiated + +* | at the point of first reference in a given translation unit (e.g., + functions declared ``inline``); +* | at the end of the translation unit; or +* | externally to the current translation unit. + +Wherever it occurs, it is ``instantiate_template_function`` that is called to +generate a function body based on a template. These are the steps in the +process: + +* | The function's storage class and name linkage are set, along with its + ``is_inline`` flag if required. +* | The ``pending_instantiations`` value in the template symbol supplement is + incremented. As for class templates, this field is used to catch runaway + recursive instantiation. +* | ``push_template_instantiation_scope`` is called to push a template + instantiation scope onto the scope stack. +* | The token cache is activated. +* | ``push_scope`` is called again to push a function scope onto the scope + stack. +* | On the basis of the ``param_id`` list saved in the template symbol + supplement the function parameters are entered into the symbol table (in + the function scope) by ``decl_parameter``. +* | For constructors a call is made to ``ctor_initializer`` to process the + *ctor-initializer* list, if any, as well as to do default processing, + and for destructors a call is made to ``dtor_initializer``. +* | In case a function is being instantiated "on the fly" in the midst of + executable code, the structured statement stack is suspended and a new one + begun by a call to ``new_struct_stmt_stack``. +* | ``compound_statement`` is called to process the tokens comprising the + function body. The IL produced is recorded in the function scope. +* | If appropriate, ``restore_struct_stmt_stack`` is called. +* | ``pop_scope`` is called for the function scope. +* | ``pop_template_instantiation_scope`` is called for the template + instantiation scope. +* | The ``pending_instantiations`` value in the template symbol supplement for + the class template is decremented. + +Variable Templates and Static Data Members of Class Templates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``instantiate_template_variable`` is invoked to handle full instantiation of +static data members and for partial and full instantiations of variable +templates. It performs the following: + +* | Static data members are marked as defined. Variable templates are marked + as defined if the declaration is a definition. +* | If an explicit initializer was specified in the static data member template + declaration, then: + + * | ``push_template_instantiation_scope`` is called to push a template + instantiation scope onto the scope stack. + * | The token cache is activated. + * | The type is scanned to determine the type of a template variable, or to + make sure the type agrees with the declaration in the class for static + data members. + * | For a full instantiation, if a definition is available, ``initializer`` + is called to process the tokens comprising the initializer. + * | ``pop_template_instantiation_scope`` is called for the template + instantiation scope. +* | If no initializer was specified for a defined variable template or static + data member, ``def_initializer`` is called. + +Constrained Templates +===================== + +C++20 introduces the notion of "constrained templates", which is often referred +to as "concepts" (although concepts are just one feature in support of +constrained templates). For example: + +.. code:: c++ + + template requires(sizeof(T)<4*sizeof(int*)) + int hash(T *p); + +Constraints are boolean predicates. In the example above, it's just a normal +expression. Whenever template instance is considered (e.g., for overload +resolution or for a partial instantiation), its constraint predicates are +substituted and evaluated: If the predicates evaluates to ``false``, the +template is discarded. For functions and partial specializations, that may not +be an error (assuming other candidates satisfy their constraint or are +unconstrained), but other cases will then elicit an error that will indicate +which constraint failed to be satisfied. + +Concepts +-------- + +A constraint expression can be abstracted through a *concept template*. For +example: + +.. code:: c++ + + template concept SmallHashable = sizeof(T)<4*sizeof(int*); + +After that definition, the declaration of hash above can instead be rewritten +as: + +.. code:: c++ + + template requires SmallHashable(T) + int hash(T *p); + +or + +.. code:: c++ + + template + int hash(T *p) requires SmallHashable(T); + +or + +.. code:: c++ + + template int hash(T *p); + +or even + +.. code:: c++ + + int hash(SmallHashable auto *p); + +Although concept template are a kind of template, they are not (partially or +fully) instantiated. Instead, they are "substituted" somewhat like function +templates are substituted during the deduction process. + +Concept templates are represented in the IL using ``a_template`` entries of +``templk_concept`` kind, and in the symbol table using ``sk_concept_template`` +symbols (that point to ``a_template_symbol_supplement`` entries with no variant +fields). A ``templk_concept`` template points to the predicate, which is +represented as an ordinary expression tree (``an_expr_node`` structure). + +Concept templates can also be "invoked" directly to produce a boolean value. +For example: + +.. code:: c++ + + auto cond = SmallHashable; + +Such expressions are represented using ``enk_concept_id`` nodes: They point to +a ``templk_concept``\ ``a_template`` entry and, optionally, to a list of +template arguments. + +Representation of constraints +----------------------------- + +As hinted above, there are four possible syntactic locations for constraints: + +* | A concept name used to introduce a template type parameter. Such + constraints -- called *type constraints* -- are represented as + ``enk_concept_id`` nodes pointed to by the + ``a_template_param_type_supplement`` associated with the constrained + template parameter. The first template argument for such + ``enk_concept_id`` nodes are implied (it's the template parameter being + constrained) and that is indicated by the ``is_type_constraint`` flag in + the ``enk_concept_id`` node. +* | A *requires clause* following a ``template<...>`` header, as in our + original example. Such constrains are represented using + ``a_requires_clause`` entries pointed to from ``a_template_decl``, + itself pointed to from ``a_template``. ``a_requires_clause`` is itself + mostly a structure pointing to an expression tree. +* | An implicit template type parameter introduces by a so-called "abbreviated + function template declaration", as in the example ``int hash(SmallHashable + auto *p);`` above. This case is represented very much as the first case + (concept name used to introduce a template type parameter): By having the + associated ``a_template_param_type_supplement`` entry point to an + ``enk_concept_id`` node representing the constraint. However, in this + case, the ``a_param_type`` entry corresponding to the parameter that + introduced the constrained also has the flag ``is_auto_param`` set to TRUE. + +* | A trailing requires clause following the function declaration itself, as we + showed in the second variation of our example: + + .. code:: c++ + + template + int hash(T *p) requires SmallHashable(T); + + | This is represented by having the ``a_routine`` entry for the prototype + instantiation of the function template point to an entry of type + ``a_requires_clause``. It's worth noting that this variation of a + constraint can also be applied to ordinary member functions of class + templates (hence the need to point to it from an ``a_routine`` entry rather + than a template-specific entry). + + | To ease the description of constraints, C++20 also introduces + *requires-expression*\ s (not to be confused with *requires-clause*\ s, + which were described above). For example: + +.. code:: c++ + + template void f() { + bool b = requires { typename T::node; }; + } + +Such expressions are represented by an ``enk_requires`` node, which points to a +list of expression nodes: Entries on that list that are of kind +``enk_type_operand``, ``enk_compound_req``, and ``enk_nested_req`` are of +special significance. See ``il_def.h`` and ``expr.c`` for details. + +Important Constrained-Template Functions +---------------------------------------- + +The following are some functions that are central to the handling of +constrained templates: + +* | ``scan_requires_clause`` and ``scan_concept_expression`` (both in + ``expr.c``). These are the functions that parse constraint expressions, + which requires special treatment of the logical operators (``&&`` and + ``||``). +* | ``scan_requires_expr`` (``expr.c``), which parses *requires-expression*\ s. +* | ``check_template_constraints`` (``templates.c``), which determines if a + given template's constraints are satisfied by a given set of template + arguments. +* | ``requires_clause_satisfied`` (``exprutil.c``). This function performs + substitution of constraint expression, which is subject to various subtle + rules. It leans heavily on the expression rescanning facilities (see + :ref:`rescanning-exprs`). +* | ``compare_constraints`` (``exprutil.c``). When determining the partial + order of function templates or partial specializations, constraint can play + a special role. This function, is the main function for comparing the + constraints on templates (to determine whether a template is more or less + constrained than another, or maybe neither is more constrained than the + other). The algorithm for this comparison is relatively complex and + described in great detail in ``exprutil.c``. + +Managing Instantiation of Functions, Variables, and Static Data Members +======================================================================= + +As noted previously, the full instantiation of template classes occurs as soon +as necessary, but no sooner. The timing for the automatic instantiation of +template functions, variables and members of template classes is more +complicated. + +For example, if a member function of a template class is not referenced, +there is no reason to instantiate it. But even if it is referenced, its +instantiation may occur elsewhere. The EDG C++ front end supports several +methods whereby the user can manage the instantiation of templates: +automatic instantiation, instantiation modes that are specified on the +command line, and explicit instantiation directives included in the source +code of the program. Explicit instantiation directives are supported in +both the form specified by the C++ standard and as ``#pragma`` directives. +For a detailed description of how the instantiation modes and pragmas are +used, see :ref:`template-instantiation`. + + +The ``instantiation_required`` flag in template instance entries is set to +indicate that a function, variable, or static data member has been referenced +in such a way as to require its definition (i.e., full instantiation) somewhere +in the program, even if not in the current translation unit. For example, +calling a template function causes the flag to be set. + +``update_instantiation_required_flag`` is called to set the flag and to place +the instance on a linked list (see ``add_to_instantiations_required_list``) so +that it can be readily found later, when the actual instantiation is done. +Sometimes the routine to do full instantiation is called immediately, however +(e.g., for calls to template functions that are declared as ``inline`` or when +in the midst of instantiation wrapup processing); in such cases the instance is +not placed on the list. + +It is ``do_any_needed_instantiations``, called by +``template_and_inline_function_wrapup``, as part of the ``fe_wrapup`` process, +that goes through the ``instantiations_required`` list. It determines for each +instance whether full instantiation is actually required in the current +translation unit as a result of the instantiation mode being used, explicit +instantiation and ``#pragma`` directives found in the program (see +``should_be_instantiated``, which checks instantiation modes and directives), +and whether the instantiation has been assigned to the current translation unit +by the automatic instantiation mechanism. It then will call +``instantiate_entity``, if appropriate. + +Instantiations are normally generated as part of the object file of the +translation unit in which the instantiations are performed. But when "one +instantiation per object" mode is specified, each instantiation is placed in +its own object file, and the names of those object files are written to the +template information file (which is described below). One instantiation per +object mode is useful when generating libraries that need to include copies of +the instances referenced from the library. If each instance is not placed in +its own object file it may be impossible to link the library with another +library containing some of the same instances. Without this feature it is +necessary to create each individual instantiation object file using the manual +instantiation mechanism. + +.. _template-auto-instantiation: + +Automatic Instantiation +----------------------- + +The EDG C++ front end provides a complete prototype implementation of an +automatic instantiation mechanism. The EDG automatic instantiation mechanism +is a "linker feedback" mechanism. It works by providing additional information +in the object file that is used by a "prelinker" to determine which template +entities require instantiation so that the program can be linked successfully. +Unlike most aspects of the front end the automatic instantiation mechanism is, +by its nature, dependent on certain operating system and object file format +properties. In particular the prelinker is a separate program that makes use +of the UNIX ``nm`` command to access information about the symbols defined in +object files. Furthermore it relies on features implemented in the ``eccp`` +driver script. Consequently, this code should be viewed as a sample +implementation that may need adaptation to work on other systems. + +This section describes the steps involved in automatic instantiation. The +steps are described in the sequence in which they would occur while compiling +and linking an application and not necessarily the sequence in which they occur +in a given execution of the front end. While one might expect the two +sequences to be the same the automatic instantiation mechanism may, in fact, +compile a given file a number of times while determining the set of +instantiations that are needed to link the application. + +Initial Compilation +^^^^^^^^^^^^^^^^^^^ + +When a program is compiled, the front end generates a set of flags that are +provided to the back end and are ultimately either output as a separate file by +the front end or are encoded in some form in the generated object file. The +flags are stored in the IL variable and routine entries. + +* | The ``can_be_instantiated`` flag indicates that this translation unit is + capable of generating an instantiation for a given function, variable, or + static data member (hereafter referred to as a "template entity"). This is + used by the prelinker to determine which source files are possible + instantiation sites for the template entity. This flag is set even if the + translation unit provides an instantiation of the template entity. +* | The ``instance_required`` flag indicates that a definition of the template + entity must be supplied by some translation unit (but not necessarily this + one). Both the ``instance_required`` and the ``can_instantiate`` flags + indicate that the entity is one that can potentially be defined by a + generated template instantiation. This information allows the prelinker to + distinguish between an unresolved template reference and a plain undefined + symbol. These flags are also used by the prelinker to distinguish class + specializations, whose members cannot be defined by generated + instantiations, from regular template classes whose members may be defined + by generated instantiations. +* | The ``do_not_instantiate`` flag indicates that instantiation of the + template entity has been explicitly prohibited by use of the + ``do_not_instantiate``\ ``#pragma`` directive. When automatic + instantiation is used, the ``do_not_instantiate`` pragma prohibits + instantiation not only in the file in which the pragma was included but + anywhere within the application with which the resulting object file is + being linked. + +In the default configuration, these flags are written to the template +information file, which is descibed below. In earlier versions of the front +end these flags were translated by IL lowering into tentative definitions of +specially named symbols. The old behavior can be selected using the +``INSTANTIATION_FLAGS_IN_TEMPLATE_INFO_FILE`` configuration flag. The flags +were removed from the object file because the amount of space consumed by the +names of the flags could be excessive, because the mangled names of template +entities can be very long. When the flags are generated as part of the object +file, the symbol names include a code that indicates the flag kind and also +includes the name of the symbol being described. The special symbol includes a +prefix of ``__CBI__`` (can be instantiated), ``__TIR__`` (template instance +required), or ``__DNI__`` (do not instantiate) followed by the mangled name of +the entity. For example, a template function of type ``void f(int)`` could +have the following flags generated. + +.. code:: text + + __CBI__f__fi__TIR__f__fi__DNI__f__fi`` + +Because they are generated as tentative definitions, they may each appear in +any or all of the object files being linked into an application while only +appearing once in the generated executable file + +When a template class contains noninline virtual functions, the instantiation +mechanism must ensure that the virtual function table is defined. IL lowering +does this by generating a "template instance required" flag for the first +noninline virtual function of any template class, because it's the presence or +absence of a definition for that function that controls whether or not IL +lowering puts out a definition for the virtual function table. By requiring +the first noninline virtual function to be defined we ensure that the virtual +function table will also be defined + +The Template Information and Instantiation Request Files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Information is exchanged between the front end and prelinker using the +"template information" and "instantiation request" files. These files are also +known respectively as the ``.ti`` and ``.ii`` files [#f1]_. The template +information file is used for infomation produced by the front end for use by +the prelinker. The instantiation request file is produced by the prelinker for +use by the front end. The template information file was added in version 2.37 +of the front end to support features such as one-instantiation-per-object mode, +and generation of instantiation flags in a separate file instead of the object +file. The front end can be configured to not use a template information file +in order to be compatible with earlier versions of the front end, but this +requires that the features that use the template information file be disabled. + +The template information file provides several diferent kinds of information to +the prelinker. Each line of the file contains a type code followed by a +string. The type code indicates the type of information being provided. The +following types of lines are generated by either the front end or driver: + +* | ``cmd:`` command line (supplied by the driver) +* | ``dir:`` compilation directory (supplied by the driver) +* | ``fnm:`` compilation file name (supplied by the driver) +* | ``idn:`` instantiation directory (in one-instantiation-per-object mode, + supplied by the driver) +* | ``flg:`` instantiation flags (when not encoded in the object file) +* | ``ifn:`` instantiation file names (in one-instantiation-per-object mode) +* | ``stu:`` secondary translation units (supplied by the driver) +* | ``tnm:`` export templates defined in this file +* | ``dep:`` dependency information when exported instantiations have been + generated + +The order in which these are specified is not, in general, significant except +that the prelinker currently requires that the instantiation directory entry +precede any instantiation file name entries. + +The template information and instantiation request files have the same base +name as the source file, but use special suffixes specified by configuration +parameters in ``host_envir.h``, with the default values indicated above. + +At the end of each compilation the front end determines whether any template +entities were referenced in the translation unit. If so a template information +file is created (or an instantiation request file, if template information +files are not being used). If no template entities were referenced in the +translation unit the file will not be created and any existing file will be +removed. When template information files are being used, the instantiation +request file is also removed if the template information file is removed. + +After invoking the front end the driver checks for the existence of either the +template information or instantiation request file, depending on the +configuration. If one exists, the driver updates it with the command line used +to compile the source file, the name of the current directory when the +compilation was done, and the name of the file that was compiled. This +information is used later if the prelinker needs to recompile the file. + +Prelinker +^^^^^^^^^ + +Once a complete set of object files has been generated, including the +appropriate flags, the prelinker is invoked to determine whether any new +instantiations are required or if any existing instantiations are no longer +required. The command line arguments to the prelinker include a list of input +files to be analyzed. The input files are the object files and libraries that +constitute the application. The prelinker begins by looking for template +information files for each of the object files (or instantiation request files, +if template information files are not being used). If no template information +(or instantiation request) files are present, the prelinker concludes that no +further action is required. + +If there are template information (or instantiation request) files, the +prelinker reads the template information file and the current instantiation +list from the instantiation request file. The instantiation list is the list +of instantiations assigned to a given source file by a previous invocation of +the prelinker. The prelinker uses the UNIX ``nm`` command to produce a list of +the global symbols that are referenced or defined by each of the input files. +The prelinker then simulates a link operation to determine which symbols must +be defined for the application to link successfully. + +When the link simulation has been completed, the prelinker processes each input +file to determine whether any new instantiations should be assigned to the +input file or if any existing instantiations should be removed. The prelinker +goes through the current instantiation list from the instantiation request file +to determine whether any of the existing instantiations are no longer needed. +An instantiation may be no longer needed because the template entity is no +longer referenced by the program or because a user supplied specialization has +been provided. If the instantiation is no longer needed, it is removed from +the list (internally; the file will be updated later) and the file is flagged +as requiring recompilation. + +The prelinker then examines any symbols referenced by the input file. The +responsibility for generating an instantiation of a given entity that has not +already been defined is assigned to the first file that is capable of +generating that instantiation. + +If a given file contains instantiations of exported templates, the template +information file contains dependency information. If a source file that is +part of an exported template translation unit changes, the dependency +information is used to detect such a change so that the prelinker can recompile +the file and regenerate the instantiations of the exported templates. + +Recompilation +^^^^^^^^^^^^^ + +Once all of the assignments have been updated, the prelinker once again goes +through the list of object files. For each, if the corresponding instantiation +request file must be updated, the new file is written. Only source files whose +corresponding instantiation request file has been modified will be recompiled. + +At this point the combination of the template information and instantiation +request files contains the information needed to recompile the source file, and +a list of instantiations assigned to the source file (in the form of mangled +function, variable and static data member names). + +Then, during recompilation the front end reads the entries from the +instantiation request file produced by the prelinker and checks them against +entries on its own "instantiations required" list. Whenever a match is found, +based on comparing the mangled name from the instantiation request file and the +name returned by either ``get_mangled_function_name`` or +``get_mangled_variable_name`` (in ``lower_il.c``), the +``automatically_instantiated`` flag is set in the template instance entry. + +When the prelinker invokes the front end, it provides a "definition list file", +which contains a list of all the external definitions found in the object files +and libraries specified on the prelinker command line. The front end reads the +definition list file and determines whether each of the entries on its +instantiations required list has already been defined elsewhere. If an entity +is found that is not defined elsewhere, its ``automatically_instantiated`` flag +is set. + +Later, in ``instantiation_wrapup``, instantiations will be generated for all +instances for which the ``automatically_instantiated`` flag is set, whether as +a result of being included in the instantiation request file or "adopted" by +the front end when it was determined that the instance was not defined +elsewhere. A list of the entities adopted by the front end is written to the +definition list file. This list is used by the prelinker to add the adopted +entities to the adopting translation unit's instantiation request file. + +The definition list file permits the front end to perform instantiations that +have become necessary as a result of other instantiations that were assigned by +the prelinker, without requiring that the prelinker invoke the front end an +additional time to perform those instantiations. This reduces the number of +iterations of the prelinker and front end that are required to generate a +complete set of instantiations for a program. + +If an error occurs during a recompilation, the prelinker exits without updating +the remaining information files and without attempting any additional +compilations. + +Iteration and Termination +^^^^^^^^^^^^^^^^^^^^^^^^^ + +If all recompilations complete without error, the prelink process is repeated, +since an instantiation can produce the demand for another instantiation. This +prelink cycle (finding uninstantiated templates, updating the appropriate +instantiation request files, and dispatching recompilations) continues until no +further recompilations are required. [#f2]_ + +When the prelinker is finished, the linker is invoked. Note that simply +because the prelinker completes successfully does not assure that the linker +will not detect errors. Unresolvable template references and other linker +errors will not be diagnosed by the prelinker. + +In many cases, once the application has been successfully linked, the +recompilation overhead will have become a one-time-only expense, because the +next time the source file is compiled, the instantiation request file will +provide precisely the right list of instantiations to be done. Recompilation +will be required again only if the instantiation request file is invalidated, +that is: + +* | if additional instantiations come to be needed (in this or another file); +* | if existing instantiations are not longer referenced; +* | if a different set of command-line options is used to compile the file; or +* | if the instantiation request file is deleted. + +Except in such cases, once the complete set of instantiation request files has +been generated, the prelinker should not need to force recompilation for any +source files in the application. + +Implementing Alternative Automatic Instantiation Mechanisms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The default automatic instantiation implementation uses the instantiation +request file as described above. The routines in ``templates.c`` are designed +to permit an alternative mechanism to be used (e.g., querying a database) to +determine whether a given entity should be instantiated. This may be done by +modifying the following routines: + +* | ``init_auto_instantiation_information`` is called at the beginning of the + automatic instantiation processing. The default version calls + ``read_auto_instantiation_information``, which opens the instantiation + request file and reads its contents. +* | ``check_if_entity_should_be_automatically_instantiated`` is called for each + instantiatable entity (external function, variable, or static data member). + It sets the ``automatically_instantiated`` flag if the entity is to be + instantiated in this translation unit, and the ``add_to_request_file`` flag + if the instantiation was "adopted" by this translation unit and must be + added to the instantiation request file by the prelinker. The default + version calls ``check_if_present_in_request_file`` to determine whether the + specified entity was named in the instantiation request file and/or the + definition list file. +* | ``wrapup_auto_instantiation_information`` is called by ``fe_wrapup``. The + default version calls ``create_or_remove_instantiation_information_file`` + and ``close_or_remove_template_info`` file. + +Instantiation Modes +------------------- + +The instantiation mode is specified by a command line option and determines +whether the compiler should automatically generate instances of template +entities (function templates, variable templates, member function of template +classes, and static data members of template classes.) The command line option +is used to set the global variable ``instantiation_mode`` to one of the +following values: + +.. list-table:: + + * - | ``tim_none`` + - | Do not automatically create instantiations of any template entities. + This is the default. + * - | ``tim_used`` + - | Instantiate those template entities that were used in the compilation. + This will include all static data members for which there are template + definitions. + * - | ``tim_all`` + - | Instantiate all template entities declared or referenced in the + compilation unit. For each fully instantiated template class, all of + its member functions and static data members will be instantiated + whether or not they were used. Nonmember template functions will be + instantiated even if the only reference was a declaration. + * - | ``tim_local`` + - | Similar to ``tim_used`` except that the functions are given internal + linkage. This is intended to provide a very simple mechanism for + those getting started with templates. The compiler will instantiate + the functions, variables and static data members used in the + compilation as local (static) functions and local (static) variables. + +Inline functions are usually instantiated when they are first referenced, and +so unreferenced inline functions are usually not instantiated. However, in +``tim_all`` mode they are always instantiated -- either during +``instantiation_wrapup`` or, for member functions for which the body is +supplied in the class template definition, when the class is instantiated. + +``#pragma`` Directives +---------------------- + +There are three instantiation pragmas, ``instantiate``, which causes the +specified entity to be instantiated, ``do_not_instantiate``, which causes +instantiation of the specified entity to be suppressed, and +``can_instantiate``, which indicates that the specified entity can be +instantiated by an automatic instantiation mechanism, but need not be. [#f3]_ +The ``do_not_instantiate`` pragma is typically used with the manual +instantiation mechanisms when a specific definition will be supplied elsewhere. + +The argument to the instantiation pragmas may be a template class name, a +member function name, a variable name, a static data member name, a member +function declaration, a function declaration, an elaborated type specifier for +a class, or a static data member declaration. When a class name or elaborated +type specifier is specified, the directive is applied to all member functions +and static data members of the class. + +Processing the pragmas results in setting some flags in the template instance. +They are later checked by ``should_be_instantiated`` (called from +``instantiation_wrapup``) to determine whether the entity requires full +instantiation. The ``instantiate`` pragma sets the ``instantiation_required`` +and ``explicit_instantiation`` flags and records the current source position +(for reporting errors later). The ``do_not_instantiate`` pragma clears +``instantiation_required`` and sets ``specific_def`` to block instantiation +based on the instantiation mode. + +Explicit instantiations are processed by ``instantiation_wrapup`` in much the +same way as instantiations that may be generated depending on the instantiation +mode. The only difference is that certain conditions that are ignored for +nonexplicit instantiations cause errors to be issued for explicit +instantiation. If no template definition has been supplied from which to +generate an instantiation, an error is issued for explicit instantiation +requests. Likewise, if a specific definition has been supplied and an explicit +instantiation was requested, an error is also issued. + +.. _explicit-instantiation: + +Explicit Instantiation Directives +--------------------------------- + +Explicit instantiation directives are processed in nearly the same way as +instantiation pragmas. The differences between the handling of the +instantiation pragma and an explicit instantiation directive are as follows: + +* | Inline functions may be specified in explicit instantiation directives, + even though doing so is meaningless. +* | An entity may not appear in more than one explicit instantiation directive. +* | Explicit instantiation directives require that a declaration follow the + ``template`` keyword, while the instantiation pragmas permit a simple name + to be specified. + +.. _implicit-inclusion: + +Implicit Inclusion +------------------ + +In the *cfront* model of programming with templates the template +declarations are placed in a header (e.g., "``.h``") file while the +definitions of noninline functions and static data members are placed in a +source (e.g., "``.c``") file. To support this style of programming the +front end provides an optional "implicit inclusion" feature. When this +feature is enabled, the front end will implicitly include a source file +when needed to provide definitions of template entities declared in a given +header file. + +When a header file is included, information about the kind of include statement +used is stored in the IL source file structure. This specifies whether the +include statement was a "normal" include (e.g., ``#include "file.h"``) or a +system include (e.g., ``#include ``). + +At the end of compilation, during instantiation wrapup processing, the source +file associated with a given header file will be included if needed. A file is +"needed" if an instantiation of an entity is required as a result of a command +line option, pragma directive, or instantiation list file. In automatic +instantiation mode implicit inclusions of template definition files will +essentially always be done so that accurate "can be instantiated" flags may be +generated. + +The implicit inclusion is done by searching through each of the directories in +the appropriate search path list (based on the kind of include statement used +to include the header file). A configuration parameter specifies a list of +file suffixes to be used during the search for a file to be implicitly +included. In each directory on the search path each of the possible suffixes +will be tried in sequence. If no matching file is found, the next directory in +the list is used. If no matching file is found in any directory, no error is +reported (unless the instantiation was explicitly requested using an +``instantiate`` pragma in which case an error will be issued indicating that no +template definition was supplied). + +Instantiating Non-Template Inline Functions +------------------------------------------- + +The front end provides two implementations of C++``extern inline`` functions, +referred to as "lower extern inline" and "instantiate extern inline". The +"lower" version is the default, and causes extern inline functions to be +translated into static functions with special care taken to ensure that +entities such as local static variables have the proper semantics. (See the +comments on the definition of ``INSTANTIATE_EXTERN_INLINE`` in ``targ_def.h`` +for the advantages and disadvantages of each implementation.) + +The "instantiate" version, which is enabled by setting the +``INSTANTIATE_EXTERN_INLINE`` configuration flag, ensures that only a single +external out-of-line copy of the inline function is generated, and then only if +one is required by the program. The automatic template instantiation mechanism +is used to implement this mechanism. + +When an inline function is defined, ``add_to_inline_function_list`` is called +to add the function to a list of all of the inline functions in the translation +unit. During the wrapup processing at the end of the compilation, +``inline_function_wrapup`` uses the inline function list to determine which +inline functions should have their bodies emitted as part of this compilation. +The ``suppress_inline_body`` flag in the routine entry is cleared if a back end +should emit an out-of-line body of an inline function. +``update_inline_function_flags`` emits instantiation flags as is done for +template entities. The prelinker will then assign the "instantiation" of +inline functions for which out-of-line bodies are required. + +.. _exported-templates: + +Exported Templates +================== + +The C++ standard specifies that the definition of certain templates (static +data members and non-inline functions) can be separately compiled. This +feature is generally referred to as "export" as such templates are declared +using the ``export`` keyword. The definition of an exported template is +provided in a single translation unit. Other translation units that use the +template require only a declaration of the template. + +Exported templates require special processing not needed for normal +(non-exported) templates: + +* | When the definition of an exported template is encountered, a record of the + translation unit containing the exported template must be made so that the + definition can be found later when an instantiation is needed. +* | When an instantiation of an exported template is generated, the front end + must be able to search for a definition of the template. +* | Generating an instantiation of an exported template requires that the front + end have access to information about the translation unit containing the + template definition and the translation unit containing the reference. One + exported template may call another, which may call another, and so on. As + a result, the front end must be able to simultaneously process an arbitrary + number of translation units at the same time (see :ref:`multi-tu`). +* | Whenever a partial or full instantiation of an entity must be done, the + front end must update its context information so that the translation unit + containing the template is the current translation unit + (see :ref:`multi-tu-dispatch`). + +When an exported template is defined, information about the definition must be +recorded. ``add_to_exported_templates_list`` is called when an exported +definition is encountered. This information is used at the end of the +compilation to create a file that provides a list of the exported templates +defined in the translation unit. This file is known as the "exported template" +file and, by default, has a suffix of ``.et``. The following is an example of +an exported template file: + +.. code:: text + + fnm:t.c + tnm:f__tm__4_Z1Z__FZ1Z_v + tnm:f2__tm__4_Z1Z__FZ1Z_v + mid:t_c_ee131b0b + def:XXX=3 + und:YYY + end: + +The following types of lines appear in such a file: + +* | ``fnm:`` The name of the primary source file to be used when reloading the + translation unit. +* | ``tnm:`` The mangled name of a template defined in the translation unit. +* | ``mid:`` The module ID to be used when instantiating templates from the + file. +* | ``def:`` A command-line macro definition to be used when reloading the + translation unit. +* | ``und:`` A command-line macro un-definition to be used when reloading the + translation unit. +* | ``end:`` The end of the entries associated with the previous ``fnm:`` + entry. + +The information for a given file always begins with "``fnm:``" and ends with +"``end:``". This makes it possible to concatenate a group of exported template +files together, which is useful when creating a library that defines exported +templates. + +When the front end compiles a file that makes use of exported templates, a +search path of exported template directories is used to locate the file that +defines a given exported template. The entries on the search path are +specified with the ``--template_directory`` command-line option. The front end +searches each of the directories in the search path to find any exported +template files that exist there. Each of the exported template files is read +to determine which exported templates are defined, and the name of the file +that defines each template. An exported template directory can also contain a +file named ``export_info``, which provides information used when reloading +exported template translation units. The export info file contains the include +search path to be used when reloading a translation unit. If no export info +file is present, the include search path associated with the primary +translation unit is used. + +A translation unit may contain entities that must be given unique names (e.g., +unnamed namespace members). A "module ID" is used as part of the name in such +cases to ensure that the name is unique. The instantiation of an exported +template must be able to refer to, and generate additional, entities with +appropriate unique names. To accomplish this, the module ID is saved in the +exported template file and that module ID is re-used when the translation unit +containing the exported template definitions is reloaded. + +When an exported template translation unit is reloaded, it undergoes what is +basically the normal compilation process, except that none of the external +entities defined in the translation unit are emitted. Only the instantiations +of exported templates, and other templates or inline functions referenced as a +result of such instantiations (directly or indirectly) are emitted. The +entities that are emitted are copied into the IL of the primary file being +compiled (see :ref:`multi-tu-copy`). The command-line options used when the +exported template translation unit is loaded are the same options used to +compile the primary translation unit. The only exceptions are command-line +macro definitions/undefinitions, and the include search path to be used. The +command-line macro definitions/undefinitions are saved in the exported template +file, and those values are used when the exported template translation unit is +loaded (include search path handling is described above). + +A mangled name is generated for each exported template. It is this mangled +name that is used to match a reference to an exported template with the +definition found elsewhere. A hash table of exported template definitions is +built as the exported template files are read. When an instantiation is +needed, the mangled name is looked up in the hash table to see if a definition +is available. If a definition is available, ``process_translation_unit`` is +called to load the translation unit that defines the exported template. + +A template instance entry is created for each function, variable, or static +data member instance that is partially or fully instantiated. If a given +instance is declared in more than one translation unit, there will be multiple +template instance entries created. In addition, a "master instance" entry is +created to represent the information that is shared among translation units. +For template instances in the primary translation unit, the master instance is +created when the template instance is added to the instantiation required list. +For template instances in secondary translation units, the correspondence +information is used to find a master instance entry that may have been already +created for an earlier translation unit. Because the correspondence +information is not set until a translation unit has been completely scanned, +the master instance information cannot be established until after scanning has +completed. The master instance entry points to the template instance entry +associated with the canonical copy of the instance (see +:ref:`canonical-entries`). Each template instance contains a pointer to the +associated master instance. + +Instantiations of exported templates are generated during the "instantiation +wrapup" process, which is performed by ``template_and_inline_function_wrapup``. +The instantiations required list for each translation unit is examined, and +instantiations are generated if appropriate. An instantiation in one +translation unit may result in the need for an instantiation in another +translation unit. Because the other translation unit may already have been +processed, the wrapup process must iterate over the set of translation units +until no additional instantiations are added for during an iteration. + +The instantiation of a function, variable, or static data member is initiated +by calling ``instantiate_entity`` with the template instance entry of the +instance to be generated. For exported templates defined in other translation +units, the translation unit is loaded and ``find_corresponding_instance`` is +called to find or create the template instance entry in the exported template +translation unit that corresponds to the one for which the instantiation is +being generated. The corresponding instance is then used for the remainder of +the instantiation process. + +A "translation unit stack" is maintained when instantiating an entities defined +in other translation units. This stack serves two purposes: it provides a +sequence of lookup contexts for resolving dependent function names during the +instantiation process, and it provides a record of the translation unit +switches that have taken place so that the prior translation unit state can be +restored when an instantiation has completed. + +C++/CLI Generics +================ + +C++/CLI generics are sort of like templates, and sort of not. They have +arguments, but the arguments are more constrained than for templates, being +effectively only managed class types or handles to them, value classes, +fundamental types, or scoped enum types. (And types only: No nontype +arguments, no template template arguments.) In addition, generics can have +user-written constraint clauses that further restrict the valid argument values +to certain kinds of class types. Generic classes do get instantiated for each +set of template arguments, much like template classes, but generic functions +effectively have just one instantiation, which corresponds to a single routine +body that can operate on all types. That's possible because the function can +only perform those operations that are valid based on the declared constraints. +That allows the instantiation of generic functions to be delayed until runtime +and for most references to share a single instantiation (for example, all +instantiations based on handles to ref classes share a single instantiation at +runtime). That in turn forces some restrictions on the code that can be +written in generic functions. + +Generics are represented as templates marked with the ``is_generic_definition`` +flag in the class type or routine entry. If they have constraints, those are +represented by entries of type ``a_generic_constraint`` and +``a_generic_constraint_clause``. + +Generic classes and generic functions don't get the standard prototype +instantiations. Instead, they undergo a process similar to prototype +instantiation (and kicked off by the same routine that does prototype +instantiations) using invented types based on the constraints. The result is +marked as a "generic definition" instead of a prototype instantiation. The +same process applies to static data members as well. + +During the generic definition instantiation, a "constraint type" is created for +each generic parameter. It is a class type that reflects the constraints, +e.g., if the generic parameter is required to be derived from a class X, the +constraint type has X as a base class. The constraint type is a real type (not +a nonreal type), and lookups can be done in it. Such lookups in fact +significantly define what can be done with an object of that generic parameter +type, in the sense, for example, that a "``+``" operation can be done only if a +lookup finds an appropriate "``operator+``" function in the constraint type. + +The actual type that is used for a given generic parameter type during the +generic defintition instantiation is known as the "generic definition argument +type." It is a handle to the constraint type except in cases when the generic +parameter is constrained to be a value class type, in which case it is the same +as the constraint type. + +During the generic definition instantiation, the template parameter symbols for +the generic are set to the generic definition argument type. That makes a lot +of processing, in declarations and expressions, work out fine without special +handling: uses of the template parameter name produce the generic definition +argument type, and for the most part that that can be processed without +difficulty. In particular, the generic definition argument type is not a +dependent type, and therefore real types can be built (instead of unknown +template parameter types), real results of overload resolution can be +determined, etc. However, there are also cases where one wants to think of the +type as being the generic parameter type. There's a duality here: the template +parameter type and the generic definition argument type are really equivalent +types, and sometimes we want one and sometimes the other. We chose to make the +default value be the generic definition argument type, because that seemed to +work out better in terms of requiring less special-case code, but whichever way +we had decided that there would be cases that wanted to look at the type the +other way. Fortunately, because the types point to each other, it's easy to +flip to the other representation if one has the wrong one. See, for example, +``generic_param_if_generic_definition_argument``. + +Because the rules for valid generic template arguments are different than those +for normal template arguments, a special routine is used to scan generic +template argument lists: ``scan_generic_argument_list``. It calls +``is_valid_generic_argumen``\ t to check that each argument is valid for any +kind of generic. Later, when one has a full set of generic type arguments +(whether from an explicit list or through type deduction), +``verify_generic_arg_list_satisfies_constraints`` is called to check that the +arguments satisfy their constraints. + +Generic classes can overload on arity, meaning that there can be multiple +generic classes with the same name, but differing numbers of type arguments, +declared in the same scope. That is not valid in source code, but it does come +up in libraries written in other languages and imported via metadata. When +such overloading occurs, the first generic that is declared is what is entered +into the symbol table and what is returned by lookup. The template symbol +supplement for that symbol has a pointer to a list of any other generic classes +with the same name and different arities in the same scope. If there is also a +non-generic class in the same scope, it is pointed to by another pointer there. +With this information, references to the name can be resolved to the proper +instance of the generic or to the non-generic. + +Template deduction for generics is done in the usual way; there are no special +tricks to speak of. + +.. [#f1] The instantiation request file was formerly known as the + "instantiation information" file, before the template information file + came into existence. The name of the instantiation information file + was changed to avoid confusion, but the ``.ii`` suffix was retained + for compatibility reasons. +.. [#f2] The number of iterations is limited by a parameter defined in + ``edg_prelink.h``. The default is 30 iterations. This prevents the + prelinker from getting in an infinite loop if a recursive + instantiation is encountered. +.. [#f3] At the moment, the ``can_instantiate`` pragma ends up forcing the + instantiation of the template instance even if it isn't referenced + somewhere else in the program; that's a weakness of the initial + implementation which we expect to address. diff --git a/dev/doc/_sources/testing.rst.txt b/dev/doc/_sources/testing.rst.txt new file mode 100644 index 0000000..e781be5 --- /dev/null +++ b/dev/doc/_sources/testing.rst.txt @@ -0,0 +1,1007 @@ +===================== +EDG Testing Framework +===================== + +The EDG front end testing framework is fundamentally based on process exit +codes and recorded "expected output." + +Writing a Test File +=================== + +Test files are written using a series of directives at the start of the test +file. + +The following is a sample single-file test (the common case) to help illustrate +some of the features described below: + +.. code:: c++ + + //remark:Simple friend functions in class template + //options::;cn + template class A { + friend int f(A); + int i; + }; + + A a; + + int f(A a) { + return a.i; // Should be OK + } + + #if TEST_NUMBER==2 + int f(A a, int i) { + return a.i; // No access -- should fail + } + #endif + +Single-file Testing +------------------- + +Individual test files end in either ``.sft.c`` or ``.sft.cpp`` depending on +the programming language being tested. The testing directives that can be +used in a single-file test are enumerated below. Additional directives +have meaning in multi-file tests and are described in :ref:`mtu-testing`. + + | ``//remark:``\ *A string that gets printed on the output* + | ``//type:``\ *xx* + | ``//name:``\ *xxx* + | ``//options:-a:-b=xx:-c=`` + | ``//options_all:-A`` + | ``//options_sep:``\ *x* + | ``//match_regex:``\ *regular expression* + | ``//cases:``\ *n* + | ``//eccp_command:``\ *compile-command* + | ``//ulimit:``\ *options* + | ``//linker_options:``\ *options* + | ``//execution_args:``\ *command line arguments* + | ``//use_system_includes:``\ *true/false* + | ``//edg_header_pack:``\ *string* + | ``//require:``\ *string* + | ``//filter:``\ *pipe-command* + +*xx* is a type identifier. The accepted values are: + ++------------+--------------------------------------------------------------+ +| Identifier | Meaning | ++============+==============================================================+ +| ``fn`` | front end only negative | ++------------+--------------------------------------------------------------+ +| ``fp`` | front end only positive | ++------------+--------------------------------------------------------------+ +| ``fc`` | front end - expect catastrophic error | ++------------+--------------------------------------------------------------+ +| ``cn`` | compile negative | ++------------+--------------------------------------------------------------+ +| ``cp`` | compile positive (including compiling generated C) - DEFAULT | ++------------+--------------------------------------------------------------+ +| ``cc`` | compile - expect catastrophic error | ++------------+--------------------------------------------------------------+ +| ``ln`` | compile and link negative | ++------------+--------------------------------------------------------------+ +| ``lp`` | compile and link positive | ++------------+--------------------------------------------------------------+ +| ``rn`` | runtime negative | ++------------+--------------------------------------------------------------+ +| ``rp`` | runtime positive | ++------------+--------------------------------------------------------------+ +| ``ra`` | runtime - expect abort | ++------------+--------------------------------------------------------------+ +| ``cppbe`` | a special C++-generating back end only mode that dumps the | +| | generated code for review and validation | ++------------+--------------------------------------------------------------+ +| ``s`` | skip the test | ++------------+--------------------------------------------------------------+ + +Positive tests expect a return code of zero. Negative tests expect a +non-zero return code. + +The ``//name:`` directive specifies the name to be used when the file is +compiled. This is useful for tests that need to test platform support for +Unicode file names and similar file name-dependent scenarios. + +The ``//options:`` directive specifies a set of command line options to be +used, separated (by default) by colons. The compiler will be invoked once +for each set of options. An option set can override the type specified by +appending the optional string ``;``\ *xx* on the end of an option +specification. + +If the options need to include a colon, the ``//options_sep:`` directive +can be used to specify a different separator. For example, +``//options_sep:!`` will change the separator to ``!``. The separator can +be multiple characters. + +The ``//options_all:`` directive specifies a set of command line options +that will be provided on every compilation. This is useful for tests with +a single case and for options that don't vary from case to case. This may +be used in conjunction with the ``//options:`` directive. The options from +each option set are put in the command line after the ``//options_all:`` +string so that they can override values in the ``//options_all:`` string. + +The ``//match_regex:`` directive allows specification of a regular +expression (expressed in the Python regex dialect) that must be found in +the output for the test to pass. Matches will additionally add sections to +the captured output highlighting the matching lines (thus serving as a +further sanity check against unintended changes). This directive is +particularly useful if wanting to require fine grained details like +specific diagnostics, IL output fragments, or generated C++ code (when +using a ``cppbe`` test). + +The ``//linker_options:`` directive specifies an additional set of options +that are placed at the end of the command used to compile and link the +program and is intended to be used for library names. + +The string specified in the ``//remark:`` directive is printed in the test +results output to help identify what a test is doing. + +As shown in the initial testing example, it is often useful to be able to have +code conditionally compiled for each of the different compilations specified by +the options string. The test driver defines a preprocessor variable named +``TEST_NUMBER``. This variable has the value "1" for the first set of options, +"2" for the second, and so on. + +If you have a number of test cases that don't require different command +line options and that have the same result type you can use the +``//cases:``\ *n* directive to specify that the compiler should by invoked +*n* times, with ``TEST_NUMBER`` set to the current invocation number. + +``//options:`` and ``//cases:`` can be used together. For example, you may +have five test cases but only need to specify options for the first two. + +.. code:: c++ + + //options:-A;cn:-O;cn + //cases:5 + +The ``//ulimit:`` directive specifies command-line options passed to a +``ulimit`` command prior to compiling, linking, and running the test. This +can be used to prevent a test from exhausting system resources or running +in a non-terminating loop. + +Special characters can be incorporated into the test case by using special +escape sequences. The escapes are of the form ``???``\ *nnn* where *n* is +a decimal digit. + +If ``//require:`` is specified, the string that follows is searched for in the +output of ``--dump_configuration``; if not found, the test is skipped. If +multiple ``//require:`` cases are specified, all strings must be found or the +test will be skipped. + +If ``//use_system_includes:`` is set to ``true``, the system headers +associated with the current EDG base will be added to the default include +paths. Additionally, EDG compiler emulation modes will be enabled as +appropriate. For instance, if the test is run using a GCC 15.1 base this will +add the include paths for system headers associated with GCC 15.1 and +``--gnu_version 150100`` to the command line. Otherwise, if this directive is +set to ``false``, EDG headers in ``include_c99`` (for C programs) and +``include_c++`` (for C++ programs) will be added to the default include paths. + +The ``//edg_header_pack:`` directive specifies an "EDG header pack" to include +as system headers for testing. Header packs are include directories that are +themselves subdirectories of ``$TEST_ROOT/.includes/``. For instance, +``//edg_header_pack: foo`` will result in a hidden +``--sys_include $TEST_ROOT/.includes/foo`` command line argument. + +If ``//filter:`` is specified, the specified command will be used to filter +the ``run_test`` output before ``diff``-ing it. By default, a test driver +uses in-process test normalization logic as a filter. + +.. _mtu-testing: + +Multi-file Testing +------------------ + +Multi-file tests work similarly to single-file tests; however, they end +with either ``.mft.c`` or ``.mft.cpp``. Additionally, for correct +operation, these tests live in their own test directory, typically +following the convention of ``test-name/test.mft.cpp``. This allows the +test to live alongside its supporting files. + +For instance, testing a simple C++ ``#include`` might using the following +structure: + +.. code:: text + + simple-include/ + test.h + test.mft.cpp + +Similarly, for testing an import of a module, the test might use the +following structure: + +.. code:: text + + modules-function/ + exporting-module.ixx + test.mft.cpp + +where ``test.mft.cpp`` contains the testing directives (described below) that +compile ``exporting-module.ixx``. + +As previously noted, there are additional directives which are useful for +multi-file testing: + + | ``//header_unit_files:t.h t2.h`` + | ``//module_files:i-part.ixx internal:i-internal.cpp i.ixx obj:msvc-module.ixx`` + | ``//script:``\ *script_file* + +The ``//header_unit_files:`` directive specifies any header files that should +be compiled via ``--create_header_unit`` and passed to the test invocation via +a ``--header_unit`` mapping. + +The ``//module_files:`` directive specifies any module files to be compiled for +the test. + +In most cases these files should be listed without a prefix; such files are +presumed to be module interface source files and will be compiled with the +``--module_interface`` flag to generate both an IFC and a ``.obj`` file for +the module source file. + +If given the ``obj:`` prefix it's assumed the IFC file is already present and +only the ``.obj`` file should be compiled. + +If given the ``internal:`` prefix this is a module implementation unit that an +IFC file should be force-generated for (this is unusual). These module +source files are compiled under the ``--module_internal_partition`` flag to +generate both an IFC and a ``.obj`` file. + +Note that when testing modules in a compiler emulation mode (e.g., with +``--gnu_version=150100`` added to ``//options_all:``), the ``--modules`` +option must also be specified: emulation modes disable the module keywords +by default to match the emulated compiler (no version of g++ enables them +without ``-fmodules-ts``). For example: + +.. code:: text + + //options_all:--c++20 --gnu_version=150100 --modules + +See the ``modules/eifc/modules/import-function-gnu`` and +``modules/eifc/modules/export-float16-gnu`` tests for examples. + +If ``//script:`` is specified, that script is executed instead of any other +commands. In general, the test type does not matter for script files except +for checking the return code. For example, a ``cp`` test will expect a zero +return code, while a ``cn`` will expect a non-zero. The script will be passed +command-line arguments in the same way that the compile command would. + +Advanced Concepts +----------------- + +The directives are processed in the following sequence: + +- those specified in ``$TEST_ROOT/.run_test_flags`` +- (for multi-file tests) the ``flags.txt`` file in the directory of the test +- those specified at the start of the test file + +In some cases later directives overwrite earlier ones (e.g., ``//type:``). +In other cases, a list of the specified values is accumulated (in the order in +which the various lists are specified above). The directives for which the +values are accumulated are: + +- ``options`` +- ``options_all`` +- ``match_regex`` +- ``linker_options`` +- ``execution_args`` +- ``require`` +- ``header_unit_files`` +- ``module_files`` + +Compile tests are processed through ``eccp -c``. Runtime tests are +compiled and linked using ``eccp``. Compile and link tests are also +compiled and linked using ``eccp``, however a ``ln`` test is expected to +return a non-zero status from ``eccp`` where a ``rn`` test is expected to +return a zero status from ``eccp`` and a nonzero status when the program is +executed. If the ``//eccp_command:`` directive is used, the command +specified is used instead of the ``eccp`` command. + + +Testing Tools +============= + +There are two primary tools for testing, ``edgy`` and ``edg-run-test``. +Both of these tools rely on the same internal ``edgtest`` Python library, +they just provide a different interface to it. + +In most cases ``edgy`` is the preferred testing tool as it's designed for +large-scale testing. However, when authoring a new test ``edg-run-test`` +can be a great way to get immediate feedback. + +``edgy`` +-------- + +Usage information: + +.. code:: text + + usage: edgy [-h] [-c RUN_CONFIGS] [--runs-dir TEST_RUNS_DIRECTORY] + [--run-timestamp TEST_RUN_TIMESTAMP] [-j JOB_COUNT] [-T TIMEOUT_SECONDS] + [-A] [-D] [-E] [-M] [-R] [-n MAX_FAIL_COUNT] [--pick PICK_COUNT] + [--disp-run-dir] [-W] [--crash-avoidance] [--no-flakey-tests] + [--replay {all-failing,output-mismatch,regress,unexpected}] + [--slow-tests NUM_SLOW_TESTS_REPORTED] [--fully-random-order] + [--cmd] [--verbose] [filters] + + EDG test runner. + + positional arguments: + filters the test filter to apply; "all" for all suites + + options: + -h, --help show this help message and exit + -c, --config RUN_CONFIGS + the run configurations to apply + --runs-dir TEST_RUNS_DIRECTORY + override the directory where tests runs are stored + --run-timestamp TEST_RUN_TIMESTAMP + override the timestamp when creating a new test run (does + not apply to replay runs) + -j, --jobs JOB_COUNT the number of concurrent jobs + -T, --timeout TIMEOUT_SECONDS + the number of seconds to wait for tests before killing them + (0 to disable) + -A include slow tests (marked by an "_" prefix) + -D, --debug-failures print debug commands for failures + -E, --no-expectations + disable expectations + -M, --meticulous disable faster mode (on by default) and run all expensive + checking + -R, --regress silence non-regressive changes + -n, --max-failure-count MAX_FAIL_COUNT + the maximum number of failures + --pick PICK_COUNT the maximum number of tests to run (this option implies + --fully-random-order) + --disp-run-dir print the directory where the run output is being stored + -W, --record record tests + --crash-avoidance avoid tests that are likely to crash the compiler (this option + also implies --no-flakey-tests) + --no-flakey-tests do not run tests that are known to be flakey + --replay {all-failing,output-mismatch,regress,unexpected} + rerun tests from the last run + --slow-tests NUM_SLOW_TESTS_REPORTED + the number of the slowest tests to report + --fully-random-order completely randomize test execution order (this can help lower + system pressure by mixing more "intensive" test suites with + less intensive test suites) + --cmd print all run test commands + --verbose enable verbose mode + +Setup Requirements +^^^^^^^^^^^^^^^^^^ + +``edgy`` was designed to be usable from any directory. To facilitate this, +the ``EDG_TEST_HOME`` environment variable must be set to the directory +where the tests subdirectory and ``.edgy/config.json`` are. + +In the typical configuration, ``CPFE`` should be set to the C-generating +back end binary being tested and ``CPFE_CP`` should be set to the +C++-generating back end binary being tested. + +Filtering +^^^^^^^^^ + +```edgy`` works off of one or more (comma-separated) filters. These +filters are typically test suite names, e.g., + +.. code:: bash + + edgy regressions,stdlib + +Filter Reduction +~~~~~~~~~~~~~~~~ + +These can be reduced by adding addition path components. For instance, if +you want to run the tests in the ``modules`` directory of the +``regressions`` test suite, you can do so via + +.. code:: bash + + edgy regressions/modules + +You can also elaborate on this to dive down to a single test, e.g., +``regressions/foo.sft.cpp``: + +.. code:: bash + + edgy regressions/modules/foo.sft.cpp + +Special Filters +~~~~~~~~~~~~~~~ + +There are also a couple of special filters, the primary one is ``all`` +(which simply means all the test suites ``edgy`` knows about), e.g., + +.. code:: bash + + edgy all + +An additional very useful one is the ``mine`` filter. This filter is +configured by setting the ``EDGY_MY_TESTS`` environment variable to a +comma-separated list of test suites. For instance, if concerned primarily +with ``regressions`` and the ``stdlib`` impact in your work, this might be +a reasonable use: + +.. code:: bash + + export EDGY_MY_TESTS=regressions,stdlib + edgy mine + +Note that special filters cannot be reduced (e.g., ``edgy mine/xyz`` +does not work). + +Negative Filters +~~~~~~~~~~~~~~~~ + +Negative filters can be applied as well. These start with a ``!`` and are +applied as a reduction of positive filters, e.g., + +.. code:: bash + + edgy regressions,!regressions/modules + +Here we're running all tests in the ``regressions`` suite except for the +tests in the ``modules`` subdirectory. + +File-Loaded Filters +~~~~~~~~~~~~~~~~~~~ + +Filters can also be loaded from a file: + +.. code:: bash + + $> cat my_filters.txt + regressions + !regressions/modules + $> edgy @my_filters.txt + +The above is logically equivalent to the above negative filter example (the +filters are just spelled out in a file on a line-separated basis). + +This feature is particularly useful for working with fine-grained lists of +tests (such as ``edgy``'s ``.elog`` files). + +Live Feedback +^^^^^^^^^^^^^ + +Test Run Status +~~~~~~~~~~~~~~~ + +Progress reporting is provided by a (fairly rapidly) updating status line: + +.. code:: text + + 588/83,651 (0%) in 00:00:04 ~127/sec (00:10:54 remaining) + +This status line shows: + +.. code:: text + + / + (%) in + ~/sec + ( remaining) + +Problem Reporting +~~~~~~~~~~~~~~~~~ + +Any encountered problems are reported above the status line as they're +discovered. + +A completed run might look something like:: + + - regressions/foo.sft.cpp cp::ABORT: + + regressions/foo.sft.cpp cp::PASS--OUTPUT MISMATCH: + +"+" is used to indicate an unexpected problem, while "-" is used to indicate an +unsatisfied expectation (the above is an example of what might happen if there +was a regression resulting in a crash that has been resolved). + +When multiple configurations are in use, the configuration is specified in +parens prior to the test "name", e.g.:: + + + (edg_x86_64) regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH: + + (edg_x86_64_cp) regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH: + +``edgy`` also will print "commentary" in this output without using a marking +character. These are used to report extra information that might be +good to know (e.g., that a particular test ran very slowly), e.g., + +.. code:: text + + + regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH: + Consider marking regressions/foo.sft.cpp slow (Took: 00:01:04) + +Test Termination +~~~~~~~~~~~~~~~~ + +``edgy`` supports early termination when it receives ``SIGINT`` (Ctrl + C +in most shells) or ``SIGTERM``. Early termination will make edgy quickly +terminate all spawned process groups (and thus their processes). Any tests +terminated in this fashion will be reported to the user with an "X" prefix, +e.g., + +.. code:: text + + X regressions/foo.sft.cpp + X stdlib/bar/test.mft.cpp + X regressions/baz/test.mft.cpp + +Note: This is particularly helpful both for killing (and finding) tests that +are stuck in an infinite loop if your tests aren't terminating. + +Failure Debug Mode +^^^^^^^^^^^^^^^^^^ + +``edgy`` has a failure debug mode (enabled via ``-D`` or +``--debug-failures``) that enables additional "commentary" for failed +tests, aimed at debugging issues with said tests. + +For exposition purposes the below section uses ```` for the path +represented by ``EDG_TEST_HOME`` and ```` for the location of +the directory containing the front end ``cpfe`` binary. Additionally ``\`` +lines have been added to wrap lines. + +As an example, commentary from this option typically looks something like: + +.. code:: text + + RUN_TEST_DEFAULT_CONFIG="edg_x86_64" LC_ALL="C" CDISP="" \ + edg-run-test -o \ + /runs/2026.06.25-17.14.55/edg_x86_64/regressions + --driver-debug --faster -t \ + /tests/regressions \ + /tests/regressions/foo.sft.cpp + +This can be copied verbatim and when executed will print something like +the following: + +.. code:: text + + Source file clone: + cd $(clone-test-to-tmp /tests/regressions/foo.sft.cpp) + /cpfe -DTEST_NUMBER=1 --c++20 Test_name.c + +This combined information can then be used to set up a test directory, and a +debug command, following the general setup: + +.. code:: text + + + + +Using the above sample output, that would look something like: + +.. code:: text + + cd $(clone-test-to-tmp /tests/regressions/foo.sft.cpp) + RUN_TEST_DEFAULT_CONFIG="edg_x86_64" LC_ALL="C" CDISP="" \ + gdb --args /cpfe -DTEST_NUMBER=1 --c++20 Test_name.c + +This will quickly give you a debugger invocation (modulo any bugs/missing +features for test directory setup driver debug) that should exactly reproduce +the circumstances that resulted in ``edgy`` seeing what it saw. + +Note that many tests may not have a ``Source file clone`` line reported by +the test executor. In these cases it's perfectly safe to omit this (i.e., +```` may not always be a part of the pattern). + +.. _regress-mode: + +Regress Mode +^^^^^^^^^^^^ + +``edgy`` has a test regression reporting mode (enabled via ``-R`` or +``--regress``). This is aimed at reporting only those tests whose status +changed to something worse and is particularly useful for noisy tests where +there may be lots of valid ``--OUTPUT-MISMATCH``\ s. The severity ranking +used to determine what's "worse" is represented in the following table: + ++-------------------+------------------+ +| Test Status | Severity Ranking | ++===================+==================+ +| ``PASS`` | 0 | ++-------------------+------------------+ +| ``FAIL`` | 1 | ++-------------------+------------------+ +| ``BADC`` | 1 | ++-------------------+------------------+ +| ``CATASTROPHE`` | 2 | ++-------------------+------------------+ +| ``ABORT`` | 3 | ++-------------------+------------------+ +| ``RUNTIME ABORT`` | 3 | ++-------------------+------------------+ + +As an example, a ``FAIL`` to an ``ABORT`` will be reported, but an +``ABORT`` to a ``FAIL`` will not be reported. Similarly, ``FAIL`` to +``BADC`` (or vice versa) will not be reported. + +Failure Limiting +^^^^^^^^^^^^^^^^ + +``edgy`` has a failure limit mode (enabled via ``-n`` *MAX_FAIL_COUNT* or +``--max-failure-count`` *MAX_FAIL_COUNT*, where *MAX_FAIL_COUNT* is an +integer) that stops test execution after *MAX_FAIL_COUNT* tests have +been reported as problematic. This is compatible with regression mode, and +will only count reported regressions. + +Re-record Mode +^^^^^^^^^^^^^^ + +``edgy`` has a mode for updating test recordings and patching expectations +in the process (enabled via ``-W`` or ``--record``). + +As this mode is intended for usage only to update output, ``edgy`` does not +check expectations or otherwise report test status during re-recording. +The process for using re-record mode is something akin to the following: + +1. Run the tests +2. Review the changes +3. Determine if any tests' expectations or output need to be updated +4. Rerecord the tests that need to be updated (e.g, + ``edgy -W regressions/foo.sft.cpp``) + +When re-recording multiple configurations, the default configuration's +expectations are updated first. The expectations of the other configurations +are then recorded as their differences from the default configuration's (see +`Expectation Inheritance`_). + +No Expectations Mode +^^^^^^^^^^^^^^^^^^^^ + +``edgy`` has a no expectations mode (enabled via ``-E`` or +``--no-expectations``) which as the name implies disables expectations. +This is useful for seeing true test statuses (i.e., seeing all failures, +including failures that were previously marked as expected). + +No Flakey Tests Mode +^^^^^^^^^^^^^^^^^^^^ + +``edgy`` has a "no flakey tests" mode (enabled via ``--no-flakey-tests``) +which, as the name implies, skips known flakey tests. This is useful for +avoiding problematic tests that are known to regularly misdiagnose problems +in your configuration. + +For this to work, the configuration in use must have the flakey tests +listed in the ``$EDG_TEST_HOME/flakey-tests`` directory. For example, to +mark ``regressions/baz/foo.sft.cpp`` flakey in the ``foo-bar`` +configuration, one would add a file +``$EDG_TEST_HOME/flakey-tests/foo-bar/regressions.txt`` with the contents: + +.. code:: text + + baz/foo.sft.cpp + +Note: It's recommended (but not required) to organize this file alphabetically +for easier maintenance. + +Replay mode +^^^^^^^^^^^ + +``edgy`` has a mode for replaying a portion of the previous test run +(enabled via ``--replay``). It's important to note that the "runs" that +are replayed are the original "run" not a "replay", i.e., replay 2 is not +run against replay 1 but is run against the last run that wasn't a replay +run. + +Replay mode is compatible with the normal ``edgy`` options (e.g., filters). +Replay mode itself supports the following sub-options: + ++---------------------+-------------------------------------------------------+ +| Option | Description | ++=====================+=======================================================+ +| ``all-failing`` | All tests without ``PASS`` status/all tests that | +| | appear in the previous run's log files. | ++---------------------+-------------------------------------------------------+ +| ``output-mismatch`` | All tests with ``OUTPUT MISMATCH`` status (including | +| | tests that are otherwise passing). | ++---------------------+-------------------------------------------------------+ +| ``regress`` | All tests that had a status regression vs the current | +| | configuration's expectations (see the | +| | :ref:`regress-mode` section for more information | +| | about status regressions). | ++---------------------+-------------------------------------------------------+ +| ``unexpected`` | All tests that are reporting a status differing from | +| | the current configuration's expectations. | ++---------------------+-------------------------------------------------------+ + +Replay results are stored in the last test execution's run output directory +(typically ``tests/runs/``\ *some-timestamp*) in their own ``replays`` +subdirectory. Every time a replay is performed a new subdirectory will be +created within the respective replays subdirectory for the replay output. +This gives replay runs a few special characteristics: + +- Test selections are stable across all replay runs (in other words, if you + have run "T" you're replaying, replay "{N, N + 1, ...}" will not affect each + other's output/test selections). +- Replays can be run many times without resulting in ``edgy``'s test run + cleanup deleting anything. + +As a visual aid, this is the expected directory structure for a run with two +replays in the ``runs`` directory: + +.. code:: text + + . + ├── 2026.06.07-16.19.15 + │ ├── replays + │ │ ├── 1 + │ │ │ └── edg_x86_64 + │ │ │ ├── regressions + │ │ │ │ ├── test-a.rt + │ │ │ │ ├── test-b.rt + │ │ │ │ └── test-c.rt + │ │ │ └── regressions.log + │ │ └── 2 + │ │ └── edg_x86_64 + │ │ ├── regressions + │ │ │ ├── test-a.rt + │ │ │ ├── test-b.rt + │ │ │ └── test-c.rt + │ │ └── regressions.log + │ └── edg_x86_64 + │ ├── regressions + │ │ ├── test-a.rt + │ │ ├── test-b.rt + │ │ └── test-c.rt + │ └── regressions.log + ... + +Replaying Failed Test +~~~~~~~~~~~~~~~~~~~~~ + +As an example, consider you've run a test suite: + +.. code:: text + + edgy regressions + +This then revealed 5 of the 500 tests are failing. You then make a change, and +then want to run those 5 tests again to see if you've fixed the problem: + +.. code:: text + + edgy --replay all-failing + +This runs only the 5 failing tests. + +Replaying Subset of Failed Test +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As an example, consider you've run a test suite: + +.. code:: text + + edgy regressions + +This then revealed 50 of the 500 tests are failing, but you're only +interested in the 10 tests in ``regressions/foo``. You then make a change, +and then want to run those 10 tests again to see if you've fixed the +problem: + +.. code:: text + + edgy --replay all-failing regressions/foo + +This runs only the 10 failing tests. + +Replaying Mismatched +~~~~~~~~~~~~~~~~~~~~ + +As an example, consider you've run a test suite: + +.. code:: text + + edgy regressions + +This then revealed 5 of the 500 tests have an output mismatch due to changes +you made. You review the changes, and decide you want to rerecord these +tests: + +.. code:: text + + edgy --replay output-mismatch -W + +This runs only the 5 tests with the output mismatch, rerecording them and +updating expectations in the process. + +Replaying Regressions +~~~~~~~~~~~~~~~~~~~~~ + +As an example, consider you're working with volatile code that's failing many +tests, and you're using regression mode to focus down the reported tests: + +.. code:: text + + edgy -R regressions + +This then revealed 5 of the 500 tests are regressing while 50 are unexpected +status changes, and 200 are failing. The other replay modes will not help you +realistically narrow down the set of test output being reviewed. This is where +regress replays shine: + +.. code:: text + + edgy --replay regress + +This runs only the 5 tests that actually have regressive status changes, +allowing you to evaluate much more effectively whether your iterative +changes are improvements. + +Replaying Unexpected +~~~~~~~~~~~~~~~~~~~~ + +As an example, consider you've run a test suite: + +.. code:: text + + edgy regressions + +This then revealed 5 of the 500 tests differ from their expected status or +otherwise have an output mismatch. You review the changes, and decide you want +to rerecord these tests: + +.. code:: text + + edgy --replay unexpected -W + +This runs only the 5 tests, rerecording them and updating expectations in the +process. + +Slow Test Reporting +^^^^^^^^^^^^^^^^^^^ + +``edgy`` has a slow test reporting mode (enabled via ``--slow-tests`` +*NUM_SLOW_TESTS_REPORTED*, where *NUM_SLOW_TESTS_REPORTED* is an integer) +that reports the *NUM_SLOW_TESTS_REPORTED* slowest test executions. This +is compatible with all modes (with the exception of re-record mode which does +not record the necessary timings). + +Verbose Mode +^^^^^^^^^^^^ + +``edgy`` has a verbose mode (enabled via ``--verbose``) that enables +printing of additional details. Verbose mode provides additional +information about environment variables, what cleanup actions are being +taken, and remarks for failure debugging are turned on for every tests +(regardless of its pass/fail status). This can be useful for initial +setup, or when attempting to get a debug invocation for one or more test(s) +that aren't currently failing. + +Copying Tested Binaries +^^^^^^^^^^^^^^^^^^^^^^^ + +By default ``edgy`` copies the executables being tested for each test run. +This allows for (some degree of) working on the front end while testing +occurs as updated binaries will not impact testing. + +If the environment variable ``EDG_TEST_NO_COPY_``\ *X* is set or +``TEST_``\ *X* (where *X* is the environment variable corresponding +to the tested binary -- typically ``CPFE`` or ``CPFE_CP``) is set, this +functionality is disabled. + +Test Run Cleanup +^^^^^^^^^^^^^^^^ + +If the environment variable ``EDG_TEST_RUNS_KEPT`` is set to a valid +integer *N* (e.g., 10), ``edgy`` will only keep the last *N* entries in the +run directory. + +Note: This does not take into account directory names, it simply deletes +directories in the ``runs`` directory based on their modification time. +Make sure you don't have any subdirectories in the ``runs`` directory that +should be kept around before setting this environment variable. + +Multi-Configuration Support +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``edgy``, as previously noted, has support for simultaneous testing of +different configurations. The configurations that can be tested, as well as +the default set of configurations to test, is configured in the +``.edgy/config.json`` file. + +To manually specify which configurations to run, the ``-c`` flag can be +used with a comma-separated list of configurations, e.g.: + +.. code:: text + + edgy -c edg_x86_64,edg_x86_64_cp regressions + +This will run the regression test suite, in both the ``edg_x86_64`` and +``edg_x86_64_cp`` configurations (which is also the default as edgy is +typically configured). + +Expectation Inheritance +~~~~~~~~~~~~~~~~~~~~~~~ + +Test output recordings and test expectations are both inherited from the +default configuration (``edg_x86_64`` unless ``RUN_TEST_DEFAULT_CONFIG`` says +otherwise). For expectations, each configuration other than the default +configuration starts from the default configuration's expectations +(``tests/expectations//.log``), and its own expectations file +(``tests/expectations//.log``) only needs to hold the +differences. For each test (and test case): + +* a line in the configuration's own file is the expectation, otherwise +* a line in the default configuration's file is the expectation, otherwise +* the test is expected to pass. + +As the absence of a line means the default configuration's expectation applies, +a configuration that passes a test that the default configuration fails +records an explicit ``PASS`` line (e.g., +``regressions/foo.sft.cpp:fp:-DTEST_NUMBER=1:PASS:``) to say so. Lines in a +configuration's own file that are the same as the default configuration's +are redundant, and are removed the next time the configuration is re-recorded. +A configuration with an empty (or missing) expectations file expects exactly +what the default configuration does. + +edg-run-test +------------ + +Usage information: + +.. code:: text + + usage: edg-run-test [-h] [-d] [-r] [--driver-debug] [--faster] [-q] [-t TOP_DIR] + [-o OUTPUT_DIR] test_files [test_files ...] + + EDG Python based test executor. + + positional arguments: + test_files the paths to the test files to run + + options: + -h, --help show this help message and exit + -d, --debug keep the output files + -r, --record, --silent-record + update the expected test output to be the output from this run. + --driver-debug add --driver_debug to the test's command line arguments. The + resulting additional output will be printed to stdout with the + original test file replacing the generic name. This makes the + underlying command more easily accessible so that it may be + more easily fed to a debugger (e.g., gdb) or checked for + correctness. + --faster enable command line flags that might speed up the compilation + of the test files + -q only display log output for errors + -t, --top-dir TOP_DIR + the path to the contextually "top" directory + -o OUTPUT_DIR the path where output will be stored + +``edg-run-test`` is a considerably simpler tool than ``edgy``. Consider +the following edgy command: + +.. code:: bash + + edgy regressions + +Assuming ``EDG_TEST_HOME`` is ``/edg/tests``, the corresponding +``edg-run-test`` invocation would be approximately the following: + +.. code:: bash + + edg-run-test -t /edg/tests/tests/regressions \ + /edg/tests/tests/regressions/**/*.sft.c \ + /edg/tests/tests/regressions/**/*.sft.cpp \ + /edg/tests/tests/regressions/**/*.mft.c \ + /edg/tests/tests/regressions/**/*.mft.cpp + +Here ``TEST_ROOT`` is specified by ``-t`` so that any ``.run_test_flags`` file +can be correctly processed. + +Of note, ``edg-run-test`` does not support expectations or have a notion of +configuration, so this will report the status of all tests regardless of +expected output. + +Additionally, by default all statuses are reported; ``-q`` can be used to +reduce the output to something closer to what's given by ``edgy``. + +The tested binary is the binary found at the ``CPFE`` environment variable by +default. However, alternative environment variables can be tested by +specifying the ``PRIMARY_CPFE`` environment variable to a different environment +variable (e.g., ``CPFE_CUSTOM``). + +The occasional advantage of ``edg-run-test`` over ``edgy`` is simplicity. +It's possible to author a new test outside of the test tree and quickly +execute and iterate on the test before moving the file(s) to include the +test in a test suite. diff --git a/dev/doc/_sources/trans_unit.rst.txt b/dev/doc/_sources/trans_unit.rst.txt new file mode 100644 index 0000000..6ec6d1b --- /dev/null +++ b/dev/doc/_sources/trans_unit.rst.txt @@ -0,0 +1,562 @@ +.. _multi-tu: + +========================== +Multiple Translation Units +========================== + +A *translation unit* is a set of source files translated as a unit, comprising +a primary source file and all of the source files included by that file. +Sometimes, the front end has to deal with more than one translation unit at a +time: + +* | When exported templates are used, the source file in which a template is + defined may be different than the one in which is it used. The front end + has to read in a translation unit for the defining source file while + retaining the translation unit for the referencing source file, and then + perform the instantiation in a merged context that includes both + translation units. Additional translation units may be read in for + instantiations of other templates. +* | When ``COMPILE_MULTIPLE_TRANSLATION_UNITS`` is TRUE, multiple files can be + specified on the command line for the front end. Each file is read in turn + as the primary file of a translation unit. + +In both these cases, the first translation unit read is called the *primary +translation unit*, and any translation units read after the first are called +*secondary translation units*. The translation units are kept separate within +the front end. They have separate intermediate language (IL) trees and +conceptually separate symbol tables. After all translation units have been +processed, the IL for each secondary translation unit is merged into the IL for +the primary translation unit. Duplicate copies of entities that appear in more +than one translation unit are eliminated during the merge, and errors are +issued for conflicts between entities that have incompatible definitions in +different translation units. The final merged primary IL tree is then passed +to a back end, looking much like an IL tree from a simple one-translation-unit +compilation. + +The process of translating a primary translation unit and zero or more +secondary translation units into an IL tree is called a *compilation*. + +Note that when ``COMPILE_MULTIPLE_SOURCE_FILES`` [#f1]_ is TRUE and the front +end is given several source file names on the command line, each translation +unit is treated as a separate compilation. It is read separately and its IL +tree is written to a separate IL file. No merging is done on the translation +unit IL trees, and no checking for matching between translation units. There +are no secondary translation units in this mode (except those that might be +brought in for exported templates). + +The principal source files of the front end involved in +multiple-translation-unit processing are ``trans_unit.c``, ``trans_unit.h``, +``trans_corresp.c``, ``trans_corresp.h``, ``trans_copy.c``, and +``trans_copy.h``. + +.. _multi-tu-dispatch: + +Initialization, Termination, and Keeping Translation Units Separate +=================================================================== + +By and large, the code in the front end is written as if there is only one +translation unit. Global variables and tables indicate the state at the +current point in the input, which is a particular point within a single +translation unit. For the handling of multiple translation units, this global +state must be carefully managed, and updated when one switches between +translation units. + +The process of initialization in the front end is broken down into three parts: + +* | Initialization that is done only once in the entire front end invocation. + Initialization routines in this class have names that have the suffix + "``_one_time_init``". +* | Initialization that is redone for each compilation. Initialization + routines in this class have names that have the suffix "``_init``". +* | Initialization that is redone for each translation unit. Initialization + routines in this class have names that have the suffix + "``_trans_unit_init``". + +It can be seen that in ``COMPILE_MULTIPLE_TRANSLATION_UNITS`` mode, the front +end does one-time initialization, compilation initialization, and then, for +each source file specified on the command line, translation unit +initialization. In ``COMPILE_MULTIPLE_SOURCE_FILES`` mode, on the other hand, +the front end does one-time initialization and then, for each source file +specified on the command line, compilation initialization and then +translation-unit initialization. See the top-level routines in ``fe_init.c``. + +Similarly, termination is done in several parts: + +* | ``pop_scope`` for the file scope does necessary processing at the end of + the file scope for a translation unit. +* | ``translation_unit_wrapup`` does necessary processing at the end of a + translation unit. +* | ``fe_wrapup`` does necessary processing at the end of a compilation. This + includes calling ``template_and_inline_function_wrapup``, which does most + template instantiation. +* | ``wrap_up_file_scopes`` finishes up each translation unit and merges the + IL. + +The instantiation process (during the third step above) can bring in additional +secondary translation units for exported templates, which go through their own +initialization, reading/parsing, and termination phases. Eventually, all +necessary templates have been instantiated, which means all necessary +translation units have been created and processed, and ``wrap_up_file_scopes`` +is called. + +The source code for a secondary translation unit is read, and the corresponding +IL is generated, all at one time. There is no switching between translation +units while the source code is being read. Once a secondary translation unit +has been read, additional processing may be done in that translation unit that +will add more IL to it, but that is done through template instantiations, and +never by going back and reading more source code. Likewise, instantiations can +add additional IL to the primary translation unit, but no additional source +code will be read into it. + +A structure of type ``a_translation_unit`` contains information about a single +translation unit within a compilation, and the global variable +``curr_translation_unit`` points to the entry for the translation unit that is +currently active. By calling ``switch_translation_unit``, one can switch to a +different translation unit, i.e., make another translation unit the "active" +one. This is a relatively expensive process that changes the values of many +global variables to match the new translation unit. + +How does ``switch_translation_unit`` know what to update? It updates the +variables recorded by calling ``register_trans_unit_variable`` during one-time +initialization. Variables registered in that way are known as *trans unit +variables*, and their per-translation-unit values are recorded in a data +structure associated with the ``a_translation_unit`` structure: They are saved +when the translation unit becomes inactive, and restored when the translation +unit is reactivated. Certain values that need to be accessed efficiently even +when the corresponding translation unit is not the active one are stored +directly in the ``a_translation_unit`` structure (e.g., +``file_scope_pointers_block``), or are pointed to by fields in that structure +(e.g., ``module_id_ptr``; variables of this kind are registered via +``register_trans_unit_variable_with_field``). + +``process_translation_unit`` is the driver for the reading/parsing of a single +translation unit. + +Some data structures and numbering sequences are deliberately shared across +multiple translation units. The source file data structure and source line +sequence numbers, for example, are shared, so that a source position consisting +of a sequence number and column number is unique across the entire compilation. +Likewise, the symbol table and scope number sequence is shared, which ensures +that scopes always have unique numbers, and therefore that one can do a lookup +in the symbol table by scope number and find only entities from a single scope +from a single translation unit. + +Memory Regions and Intermediate Language +======================================== + +Each secondary translation unit has its own set of IL memory regions, one for +its file scope and one for each top-level function definition. The global +variable ``file_scope_region_number`` indicates the region number of the file +scope of the current translation unit, whether it is a primary or secondary +translation unit. + +The function ``alloc_primary_file_scope_il`` allocates space in the primary +translation unit IL even if the current translation unit is a secondary +translation unit. + +The macro ``is_secondary_trans_unit`` returns true for an IL entry allocated in +a memory region that is part of a secondary translation unit. The global array +``trans_unit_for_scope`` maps a scope number back to a pointer to the +translation unit that contains that scope. Note that when IL is moved from +secondary translation units to the primary IL at the end of the compilation, +the value of ``is_secondary_trans_unit`` will change, but that of +``trans_unit_for_scope`` stays as it was. + +The front end memory region is shared across all translation units. + +Translation Unit Correspondences +================================ + +Each IL entry with external linkage is assigned to a correspondence set +containing all of the related IL entries from different translation units, +i.e., all the entries that represent the same entity. So, for example, all +external global variables called "``i``" will be in one correspondence set. + +A correspondence set is represented by an entry of type +``a_trans_unit_corresp``, which is allocated in front end memory (so it is not +really part of the IL). Each entry that is a member of the correspondence set +points to the appropriate ``a_trans_unit_corresp`` entry via the +``trans_unit_corresp`` pointer in its ``source_corresp`` field. These pointers +are set when secondary translation units are processed, and therefore in a +compilation consisting only of a single translation unit the pointers will be +NULL and the correspondence-set entries will not be allocated. [#f2]_ For +entries without linkage, or with internal linkage, the ``trans_unit_corresp`` +pointer is always NULL. + +IL entries of type ``a_base_class`` are also matched up in correspondence sets +and therefore contain a ``trans_unit_corresp`` pointer (though it is not part +of a ``source_corresp`` field in that case). + +.. _canonical-entries: + +Canonical Entries +================= + +In each correspondence set, one entry is chosen as the *canonical* entry, and +the ``canonical`` field in the ``a_trans_unit_corresp`` points to it. The +entry chosen as the canonical entry is an instance that contains the most +detailed information available about the entity: one with a definition if a +definition is available, and a specialization if both specialized and +unspecialized versions of a template instance are available. All other things +being e qual, an entry in the primary IL is chosen over one in a secondary +translation unit, because that means less copying later. + +The canonical entry chosen can change as the compilation progresses. The first +instance seen will generally be chosen as the canonical entry, but it may be +replaced afterwards by a better choice from some other secondary translation +unit scanned later. + +Note that it is possible for a class or namespace not to be the canonical entry +in its correspondence set while at the same time some of its members are the +canonical entries in their sets. + +The macro ``canonical_il_entry_of`` can be used to fetch the address of the +canonical entry corresponding to a given entry. For an entry without linkage, +the entry itself is returned. + +The Copy Address Pointer +======================== + +All IL entries have a prefix that contains various flags and numbers. IL +entries in the file scope of a secondary translation unit have, in addition, a +copy address pointer, which is set during the copy process to indicate the +address in the primary IL to which the entry should be copied or remapped. + +For entries in correspondence sets, generally the canonical entry will be +copied to the primary IL and its copy address pointer will be set to the +address of the copy. The other members of the correspondence set will not be +copied, but their copy address pointers will be set to the same copy address so +that references to them can be remapped to the unique copy in the primary IL. + +For entries not in correspondence sets, including non-declarative entries like +statement and expression nodes, no copy address is pre-assigned. When the +entry is encountered during the copy process, it is copied to the primary IL +and the copy address pointer is set to the address of the copy. All references +to the entry encountered thereafter are remapped to the established copy +address. + +In some cases, entries in the secondary IL are "merged" into the primary IL. +This is necessary, for example, if the canonical entry for a correspondence set +is in a secondary translation unit but there is also a member of that +correspondence set in the primary IL. The address in the primary IL must be +preserved (because there are references to it from elsewhere in the primary IL, +which will not be rewritten), so the canonical entity must be copied on top of +the existing primary IL entry. In such cases, the copy address pointer is used +to form a two-element list: The copy address pointer of the entry in the +secondary translation unit points to allocated space for a copy (also in the +secondary translation unit IL), and the copy address pointer of that copy entry +points in turn to the address of the existing entry in the primary IL. The +copy process copies the original entry to the intermediate copy, with pointer +remapping, and then later overwrites the primary IL entry, carefully preserving +certain information (e.g., next-on-list pointers). + +The macro ``trans_unit_copy_address_of`` gives access to the correspondence +pointer of an IL entry (for both fetching and setting). The macro +``checked_trans_unit_copy_address_of`` does the same thing, but also checks +that the entry pointer provided is actually in the file scope of a secondary +translation unit. + +Correspondence Checking +======================= + +The code in ``trans_corresp.c`` establishes correspondences between entities in +a secondary translation unit and similar entities in the primary translation +unit and in other secondary translation units. It sets the correspondence +pointer of IL entries to indicate the correspondences found. While +establishing these correspondences, it checks that linked entities are in fact +compatible, and issues errors when they are not. The entities that have +correspondences set in this way are types, routines, variables, fields, +namespaces, base classes (i.e., ``a_base_class`` entries), using-declarations +appearing in class scopes, and templates (including template instances). + +Correspondence checking can occur in three stages of the compilation: + +* | Built-in types have their correspondences set by ``record_builtin_type`` as + soon as they are created. +* | When a translation unit has been processed, + ``set_trans_unit_correspondences`` is called from + ``translation_unit_wrapup`` to establish correspondences for the entities + that were created in that translation unit. The global variable + ``correspondence_checking_underway`` is TRUE during this stage (and only + during this stage); after that ``correspondence_checking_done`` is TRUE. +* | The correspondence checking process is notified of every template + instantiation by calls to ``record_instantiation``. When this occurs in a + translation unit after its ``translation_unit_wrapup`` call, the + correspondence pointer is established for the new instantiation. The + instantiation process also notifies the correspondence checking process of + template instantiations being completed, through calls to + ``establish_class_instantiation_corresp``, + ``establish_function_instantiation_corresp``, + ``establish_variable_instantiation_corresp``, + ``establish_block_extern_function_correspondence``, + ``establish_block_extern_variable_correspondence`` and + ``establish_friend_type_correspondence``. + +Finding Corresponding Pairs +--------------------------- + +Several different mechanisms are used to find an entity in another translation +unit that corresponds to a given entity: + +* | For named entities in namespace scope, the symbol table is used. The + search process simply traverses the list of symbols attached to the symbol + header of the entity for which a correspondence is being searched. This is + done in functions with the prefix ``find_`` (e.g., + ``find_type_correspondence``). +* | For class members, we can rely on the fact that the lists of IL entities + representing the members should have their elements correspond on a + one-to-one basis. Hence no search is needed, although care must be taken + with compiler-generated members that may not appear in every translation + unit. This principle is implemented by + ``establish_trans_unit_correspondences_for_class``. A similar process can + be used for enumeration constants. +* | Correspondences for instantiations of templates are usually established + after the templates from which they are generated have been matched up. To + support the search for a matching instantiation, a field + ``all_instantiations`` was added to ``a_template_symbol_supplement``. This + field is set only in the supplement for the canonical template entry and + points to a list of all the instantiation symbols for the template, + including those for corresponding templates in other translation units. + Some of the key functions manipulating this list are ``add_instantiation``, + ``find_class_template_instantiation`` and + ``find_function_template_instantiation``. +* | Correspondences are also sometimes established between unnamed types. This + happens when matching up declarations of entities with linkage involving + unnamed types. For example: + + .. code:: c++ + + struct { float a, b; } *p, q; // Could appear in two translation units + + | In such cases, the correspondence is first established for the entities + with linkage (variables or routines), and the correspondence between the + types is sought by comparing the two types using ``f_types_are_compatible`` + with the option ``TCF_SEEK_CORRESP``. + +Ordering Dependencies +--------------------- + +Determining whether two entities from different translation units correspond +may require that other correspondences are known. For example, suppose we have +two namespace scope functions ``f`` that are declared as + +.. code:: c++ + + extern R N::f(); + +then the two must correspond if the entities denoted by ``N`` correspond, and +if that is the case the entities denoted by ``R`` must correspond too. The +ordering of corresponding checks must therefore be managed carefully. + +To reduce the magnitude of this issue, correspondences are determined in two +steps. In the first step, correspondences are *established*: Only those +components of the entity that uniquely identify it are compared (e.g., the +entity's name, its enclosing classes and namespaces, parameter types of +functions, etc.) and if they match the correspondence pointer is set. Some +diagnostics may be issued at this time. This process is mostly done in +functions with the prefix ``establish_``. In the second step, which starts +after all the correspondences for the translation unit have been established, +the correspondences are *verified*. This involves comparing the remaining +relevant attributes of entities that were found to correspond after the first +step; diagnostics are issued if the entities do not match. Most of the +verification work is done in functions with the prefix ``verify_``. This +separation into two steps makes sure that in our example above the +correspondence for ``R`` has been established by the time it is needed. + +To deal with other ordering issues, such as the requirement that the +correspondence of ``N`` be established in our example, the correspondence +checking process may be stacked. For example, while searching for a +correspondence for ``N::f`` above, another search for a correspondence for +``N`` may be initiated. This is driven by calls to functions named +``canonical_``\ *entity*\ ``_entry_of`` where *entity* is one of +``namespace``, ``type``, ``field``, ``routine``, ``variable`` or ``template``. +If a correspondence was already established, these functions return the +requested canonical entry; if not, they first determine the correspondence by +calling ``determine_correspondence`` [#f3]_. + +Other ordering issues sometimes arise because establishing a correspondence for +a template instantiation seemingly leads to infinite recursion. Such +situations are resolved in part by placing appropriate markers in the +``all_instantiations`` list and in part by as much as possible establishing the +correspondences of all templates before attempting to match their +instantiations. To that end, the front end maintains a list of instantiations +whose correspondences are yet to be determined (the list is pointed to by +``instantiations_to_process``). That list is processed at appropriate times +(i.e., when the correspondences of the various templates have been found) by +calls to ``process_pending_instantiations``. + +Finally, we should note that the verification process always compares an entity +with its canonical counterpart. If a canonical entry (from an already +processed translation unit) is replaced by a new entry (from the current +translation unit) the former will need to be compared with the latter when all +the correspondences have been established in the current translation unit. +This is done in ``process_verification_list``. + +Debugging Facilities +-------------------- + +When the preprocessor symbol ``DEBUG`` is TRUE,a few facilities are provided by +``trans_corresp.c`` to help identify problems during correspondence checking. +First, the command-line option "``-d-trans_corresp``" will cause a line of +output to be produced for each correspondence pointer being set (or cleared), +as well as for certain operations on the ``all_instantiations`` lists. Second, +the function ``db_corresp`` can be called from a debugger to examine the +correspondence of a given entity. Finally, the modification of a +correspondence pointer for a specific entity can easily be intercepted in a +debug environment where addresses are reproducible from run to run. To enable +this, set breakpoints on ``main`` and on ``corresp_intercept``. Rerun the +front end and at the stop in ``main``, set the static variable +``trace_corresp_ptr`` to the address of the entity whose correspondence value +should be tracked: ``corresp_intercept`` will be called (triggering the +breakpoint) when that value is modified. + +.. _multi-tu-copy: + +Copying from Secondary Translation Units +======================================== + +The code in ``trans_copy.c`` copies IL from a secondary translation unit to the +primary translation unit IL. It is run after elimination of unneeded entries +in the secondary translation unit, so it copies only entries that are actually +"needed." It also runs after correspondence checking has established the +correspondences between externally-linked entities, so it does not copy entries +for which there is already an instance in the primary translation unit IL; for +such cases, all references to the entity are simply rewritten to point to the +primary IL instance. + +The secondary translation unit IL consists of a file scope memory region and +zero or more function scope memory regions. The file scope memory region is +actually copied into the primary IL, via a tree walk, with duplicates +eliminated as indicated above. The function scope memory regions, on the other +hand, are not copied. Instead, they are walked to update pointers +appropriately, and then the memory region numbers are simply reassigned to the +primary IL. + +The copy process is handled by ``copy_secondary_trans_unit_IL_to_primary``, +which has five main phases: + +* | ``prepare_for_trans_unit_copy`` walks through the declaration lists of the + file scope of a secondary translation unit and its subscopes, and puts each + entry into one of four categories: (a) entries that should be copied to the + primary IL; (b) entries that should overwrite a corresponding entry in the + primary IL (e.g., a function in the secondary translation unit that has a + definition, where the corresponding function in the primary IL has only a + declaration); (c) entries that are in a correspondence set but are not the + canonical entry, which should be removed from the lists and discarded; and + (d) entries in a correspondence set that provide additional (minor) + information over what is present in the canonical entry, which should be + merged into the corresponding entry. +* | ``copy_from_secondary_to_primary_IL`` uses the IL-walking routines to walk + the IL tree, copy over entries that need to be copied, and update pointers + so that the copied IL refers only to copies or to pre-existing entries in + the primary IL. +* | ``copy_function_bodies_to_primary_IL`` processes the bodies of any + functions that are to be moved over, by using the IL-walking routines to + walk the IL tree and update pointers appropriately. +* | ``finish_trans_unit_copy`` walks through the declaration lists again, and + links copied entries into the declaration lists of the primary IL. A + struct type copied over, for example, would be linked into the types list + of the primary scope of the primary IL. Variables, types, and routines + that must be merged into the corresponding entries are also copied onto the + corresponding entries at this point. This part of the processing runs + while switched into the primary translation unit. See also + ``finish_moved_entity_processing``, which is similar but reaches all copied + or merged entities, even those from non-merged scopes. +* | ``finish_processing_for_function_bodies`` calls + ``finish_function_body_processing`` for each copied function scope memory + region, and kicks off IL lowering for the function if it's needed. This + part of the processing runs while switched into the primary translation + unit. + +For entries that are being merged into the primary IL, the copy process sets +the ``il_lowering`` flag in the IL entry prefix to indicate merging rather than +copying. (The flag is available for this use because IL lowering is never done +on secondary translation units.) For merged entries, the copy process uses an +extra copy of the entity allocated in the secondary translation unit: The +entity's copy address pointer points to the copy, whose copy address pointer +points to the corresponding entity in the primary IL. During the copy, the +original entry is copied to the copy space, and its pointers are remapped +there. This allows ``finish_trans_unit_copy`` later to have access to both the +original entity in the primary IL and the entity from the secondary translation +unit as updated for the copy. This is often important because some flags from +the two entries need to be merged. + +The bodies of functions not copied over are eliminated, and likewise for the +initializers of variables. See ``clear_body_for_routine`` and +``clear_variable_definition``. Non-template functions and variables in +secondary translation units included only to get exported templates are turned +into external declarations, because the definition of those entities is put out +when the file is compiled as a primary translation unit. + +The IL for secondary translation units can contain references to other +translation units. In some ways, the IL trees for all secondary translation +units have to be viewed as one big somewhat interconnected tree. For this +reason, each of the processing phases described above is done for all secondary +translation units before advancing to the next phase. + +Part of the function of the copy process is to produce a primary IL tree that +contains no references to IL entries in secondary translation units, and this +is done by making sure that every entity copied over has only pointers that +refer to the primary IL. Sometimes, however, the instantiation of a template +that is defined in the primary translation unit introduces exactly the kind of +mixed-translation-unit IL that we are trying to avoid. To eliminate such +references, a pair of routines in ``trans_copy.c`` is called: + +* | ``mark_secondary_trans_unit_IL_entities_used_from_primary_as_needed`` + sweeps the primary translation unit IL and looks for references to + secondary translation unit entries. When it finds them, it marks the + secondary translation unit entries as needed so that they will be copied to + the primary IL when the secondary translation unit is copied. +* | ``rewrite_secondary_trans_unit_IL_entity_pointers_used_in_primary`` sweeps + the primary translation unit IL after the secondary translation units have + been copied in, and looks for references to secondary translation unit + entries. When it finds them, it rewrites them either as references to the + corresponding entity in the primary translation unit (if there is one) or + it copies them and rewrites the pointer to the copy. + +In some (relatively rare) cases, the merged IL produced by the copy process has +some type entries out of order on the type lists, where "out of order" is +defined according to the peculiar ordering required by the C-generating back +end so that it can generate compilable C code. +``fix_type_list_ordering_problems`` is called after IL lowering to examine the +file-scope types list to look for ordering problems and to move types to fix +those problems. If there are no ordering problems (which is almost always the +case), the checking is done fairly quickly and efficiently. + +Externalization of statics +========================== + +When a source file includes exported templates, it is possible that the +exported templates will refer to static entities in the file. Because the +template instances may be generated as part of the translation of other source +files, and be included in the object code for those files, it may be necessary +to refer to the static entities from another compilation. Therefore, the front +end externalizes all statics when a compilation includes exported templates. +This gives the static functions and variables external linkage and special +mangled names. This has a number of consequences, such as that static inline +functions become extern inline functions, which in some configurations makes +them instantiatable. See ``externalize_statics_for_exported_templates``. + +One-instantiation-per-object mode +================================= + +In one-instantiation-per-object mode, each instantiated template is put into a +separate "slice" of the IL, so that a back end can put out each instantiation +in a separate object file. The slices are defined by having a separate +"needed" flag for each slice (there's an array of them attached to each IL +entity), and setting the slice-specific needed flags so that each slice +contains only the types, variables, etc. referenced by the template +instantiation in that slice. + +When there are multiple translation units, the per-instantiation needed flags +are not maintained in the secondary translation unit IL. Once the IL is copied +to the primary IL, the flags are built up and maintained appropriately there. + +.. [#f1] Not ``COMPILE_MULTIPLE_TRANSLATION_UNITS``. +.. [#f2] There are some circumstances involving templates where the + correspondence pointer is set even if there is only a primary + translation unit. The important point is simply that one shouldn't + count on the pointer being set when there is only one translation + unit. +.. [#f3] Note that this is different from ``canonical_il_entry_of`` which does + not attempt to establish a correspondence. diff --git a/dev/doc/_sources/utilities.rst.txt b/dev/doc/_sources/utilities.rst.txt new file mode 100644 index 0000000..55e3868 --- /dev/null +++ b/dev/doc/_sources/utilities.rst.txt @@ -0,0 +1,309 @@ +.. _utility-programs: + +================ +Utility Programs +================ + +Several utility programs are provided with the front end. Most of the utility +programs help with various link-time issues and are meant to be called from a +driver program or script. One (``mk_errinfo``) is a tool program used when +modifying the front end. The source for these programs is in the ``util`` +directory of the release structure. + +``edg_prelink`` +=============== + +``edg_prelink.c`` contains the "prelinker" program. ``edg_prelink.h`` contains +related declarations. The prelinker is invoked at link time to manage +automatic instantiation of template entities. It is given a complete list of +the object files and libraries that are to be linked together. It examines the +external names defined and referenced within those files, and finds cases where +template entities are referenced but not defined. It then examines information +in the object files that describes instantiations that could have been done +during compilation, and assigns the needed instantiations to appropriate files. +``edg_prelink`` then invokes the compiler again to compile those files, which +will do the necessary instantiations. + +The prelinker uses UNIX commands like ``nm`` to extract information about +object files, so it may need adaptation to run in other environments. + +The invocation of the prelinker looks like + + | ``edg_prelink`` [ *options* ] *files* + +where the *files* list includes all object files and libraries, and the +*options* are: + +.. list-table:: + + * - | ``-a`` *n* + - | Specify whether a definition list file should be created. A + definition list file is created if *n* is nonzero. The default is + specified by the ``PL_DEFAULT_USE_DEFINITION_LIST_FILE`` configuration + flag. + * - | ``-b`` + - | List object files mode. This mode is used when the driver needs to + get a list of object files including any instantiation object files + created in one instantiation perobject mode. The prelinker simply + creates an object file list that is written to the file specified by + the ``-o`` option. + * - | ``-c`` *command* + - | Specify the version of the ``nm`` command to be used. + * - | ``-D`` + - | Do not assign instantiation to nonlocal object files. Instantiations + may only be assigned to object files in the current directory. + * - | ``-f`` *fmt* + - | Specify the ``nm`` format to be used. *fmt* is one of ``solaris``, + ``SGI``, ``SVR4``, ``HPUX``, ``gnu``, ``CLIX, MacOSX``, or\ + ``MacOSX64``. + * - | ``-i`` + - | Ignore ``nm`` output lines that are not formatted properly. + * - | ``-L`` *directory* + - | Specify a library directory to be searched for libraries. + * - | ``-m`` + - | Do not demangle identifier names that are displayed. + * - | ``-n`` + - | Update the instantiation list but don't recompile the files. + * - | ``-N`` + - | If a file from a nonlocal directory needs to be recompiled, do the + compilation in the current directory. An updated list of object files + and library names is written to the file specified by the ``-o`` + option so that the driver program can tell that alternate versions of + some of the object files should be used. + * - | ``-o`` *file-name* + - | Write an updated list of object files and library names is written to + the file specified by *file-name*. This option must be specified when + the ``-N`` or -O option is used. + * - | ``-O`` + - | One instantiation per object mode is being used. A list of object + files, including the instantiation object files associated with the + object files specified on the prelinker command line, is written to + the file specified by the ``-o`` option. + * - | ``-q`` + - | Turns off verbose mode. + * - | ``-r`` + - | Don't stop after a certain number of iterations. (The instantiation + process is iterative: a recompilation may bring up new template + entities that need to be instantiated, which requires another + recompilation, etc. Some recursive templates can cause iteration that + never terminates, because each iteration introduces another new entity + that wasn't previously there. By default, this process is stopped + after a certain number of iterations.) + * - | ``-R`` *number* + - | Override the number of reserved instantiation information file lines + to be used. + * - | ``-s`` *number* + - | Specifies whether the prelinker should check for entities that are + referenced as both explicit specializations and generated + instantiations. If *number* is zero the check is disabled, otherwise + the check is enabled. + * - | ``-S`` + - | Suppress instantiation flags in the object files. This causes the + prelinker to recompile all of the local object files with the + ``--suppress_instantiation_flags`` option. + * - | ``-u`` + - | Specify whether external names have an added leading underscore. The + command-line option selects the opposite of the configuration flag + ``TARG_EXTERNAL_NAMES_GET_UNDERSCORE_ADDED``. + * - | ``-v`` + - | Verbose mode. + * - | ``-d``\ *n* + - | Set the debug level to *n*. + +The *files* list may also have the following options intermixed with the file +names: + +.. list-table:: + + * - | ``-l``\ *xxx* + - | Specify a library (e.g., ``-lstd``). + * - | ``-B``\ *linkage* + - | Specify the kind of linking to be done (e.g., static or dynamic). The + linkage kind is not checked for validity. + * - | ``--`` + - | Marks the end of the list of file names that is passed back to the + driver when the ``-N`` option is used. + +``edg_munch`` +============= + +``edg_munch`` is the EDG version of the USL ``munch`` utility. Its source +code is in ``edg_munch.c``, with associated declarations in +``edg_munch.h``. ``edg_munch`` implements a lowest-common-denominator +method for getting global initialization and termination code executed on +systems that have no special support for that. [#f1]_ + +``edg_munch`` operates by reading as input a file that is the output of ``nm`` +run on a linked executable program. It looks for names beginning with +``__sti__`` or ``__std__``, those being, respectively, initialization and +termination routines to be called at runtime. It generates a C program that +defines a data structure containing a list of pointers to the initialization +and termination routines. This generated program is then compiled and linked +in with the executable. The data structure is consulted at runtime by startup +code invoked from ``_main``, and the routines on the list are invoked at the +appropriate times. + +``edg_munch`` takes only a single option: ``-u``, if used, specifies whether +external names have an added leading underscore. The command-line option +selects the opposite of the configuration flag +``TARG_EXTERNAL_NAMES_GET_UNDERSCORE_ADDED``. + +``edg_decode`` +============== + +``edg_decode`` is a name demangler. The demangling code is in ``decode.c``, +with associated declarations in ``decode.h``. A main program that uses the +demangling code is provided in ``edg_decode.c``. + +``edg_decode`` reads input from ``stdin`` and writes output to ``stdout``. +Things that look like mangled names in the input are demangled. Everything +else is passed through unchanged. This makes the program suitable, for +example, as a filter for the output of a linker: error messages in general are +passed through unaltered, but mangled names are demangled. For example, using +the cfront-like ABI, + +.. code:: text + + ld: Undefined symbol + _f__Fif + +is turned into + +.. code:: text + + ld: Undefined symbol + f(int, float) + +Mangled names that are ill-formed in some way are also passed through +unchanged. + +``edg_decode`` usually has only a single option: ``-u``, if used, specifies +whether external names have an added leading underscore. The command-line +option selects the opposite of the configuration flag +``TARG_EXTERNAL_NAMES_GET_UNDERSCORE_ADDED``. When the IA-64 ABI is used, +however, there is also a ``-g`` option, which selects the opposite of the +configuration flag DEFAULT_EMULATE_GNU_ABI_BUGS, which when TRUE extends the +demangling to cover some invalid mangled names put out by g++ 3.2 (and the EDG +front end, when configured to emulate those bugs). + +The demangling is intended to work only on names of external entities. There +is some name mangling done for internal entities, or by the C-generating back +end, that this program does not try to decode. + +In the cfront-like ABI, names that contain double underscores in the source +code will probably not be demangled correctly. This is an unfortunate +consequence of using a mangling scheme that is based on the one used by cfront. +The standard forbids use of double underscores in names in user code, reserving +such names for the implementation, so the effect of this shortcoming is +limited. Implementors should try to avoid using such names for entities with +external linkage. Double underscores at the beginnings of external names do, +however, work correctly. In the IA-64 ABI, a similar problem applies to names +that begin with "``_Z``". + +The name demangling is also available through a callable interface, which is +used in ``edg_prelink``. See routine ``decode_identifier``. + +.. _mk-errinfo: + +``mk_errinfo`` +============== + +``mk_errinfo`` translates a text file containing error message codes and +associated descriptions into a pair of header files that represent this +information in a manner more readily used by the front end. + +The invocation of the ``mk_errinfo`` is typically + +.. code:: bash + + mk_errinfo error_msg.txt error_tag.txt err_codes.h err_data.h + +The ``error_msg.txt`` file defines the diagnostic messages generated by the +front end. This file, along with ``error_tag.txt``, is processed by +``mk_errinfo`` to generate the ``err_codes.h`` and ``err_data.h`` include +files. ``mk_errinfo`` may also be used to automatically generate the file used +to generate the :ref:`error-messages` appendix of this manual. + +When used to generate a documentation file, the invocation is typically one of +the following: + + | ``mk_errinfo -d error_msg.txt error_tag.txt`` *generated.tex* + | ``mk_errinfo -mml error_msg.txt error_tag.txt`` *generated.mml* + | ``mk_errinfo -rst error_msg.txt error_tag.txt`` *generated.rst* + +*generated.tex* is the name of the generated output file containing the +documentation in LaTeX format. *generated.mml* is the name of the generated +output file containing the documentation in MML (Maker Markup Language), which +can be used to create a FrameMaker document. *generated.rst* is the name of +the generated output file containing the documentation in reStructuredText +format, which can be used with Sphinx and various other tools. + +``error_msg.txt`` contains lines that have the following form: + +.. code:: text + + error_code;tag;"text" + +The error code is the enumeration element name that is used by the front end. +The file must be specified in enumeration order. To preserve the numbering of +error codes, errors may not be inserted in the middle of the file, nor may +lines be removed. If an error message is no longer in use, the line on which +it is defined should be prefixed with the string ``REMOVED``. This will retain +its sequence number but eliminate it from the generated tables. + +The tag is an alias for a given error code to be used by the end-user to name +that error in the command-line options that change the severities of +diagnostics. If no tag is specified, the error code (with the ``ec_`` removed) +is used as the tag. + +Some messages are used as part of the formatting of other messages (for +example, the messages used to provide error context information). These +messages should have a tag of ``INTERNAL``. This prevents the message from +being entered in the tag table and also prevents the message from appearing in +the automatically generated documentation file. + +The text string contains a quoted string similar to one that would be used in a +C program to define the equivalent string. Any quote characters within the +text string must be escaped. + +The text string includes markers indicating the location of fill-ins in the +message (e.g., ``%t`` for a type). Full information on those fill-in codes can +be found in :ref:`error-reporting`. + +The message text may include supplementary information that is only used to +improve the automatically generated documentation file (which is formatted +into the :ref:`error-messages` appendix of this manual). For example, an +error text string might look like this + +.. code:: text + + "a message with %s\='fill-in' included" + +The string ``\='fill-in'`` is used when creating the documentation file as the +value to be substituted for the ``%s``. This string is removed from the error +text information when the ``err_data.h`` file is created. + +``error_tag.txt`` is used to supply additional tags that may be used as aliases +for diagnostic messages. This mechanism is intended to be used by customers +who are packaging the front end as part of their product and allows them to +assign their own set of error tags without the need to modify the distributed +``error_msg.txt`` file. Note that these tags are used in addition to (not in +place of) the default tags specified in the ``error_msg.txt`` file. + +Each line should be formatted as: + +.. code:: text + + error_code;tag + +The error code is the enumeration element name used by the front end. The tag +is the alias being assigned. There may be more than one alias that references +a given enumerator. + +In both ``error_msg.txt`` and ``error_tag.txt``, blank lines are ignored and +lines that begin with a "``#``" are treated as comments. + +.. [#f1] The *patch* approach, by comparison, is more machine-dependent and + more efficient, but still doesn't require special linker support. + The code generated by the EDG front end will work with USL's + ``patch``, but EDG does not provide its own version of ``patch``. diff --git a/dev/doc/_static/base-stemmer.js b/dev/doc/_static/base-stemmer.js new file mode 100644 index 0000000..e6fa0c4 --- /dev/null +++ b/dev/doc/_static/base-stemmer.js @@ -0,0 +1,476 @@ +// @ts-check + +/**@constructor*/ +BaseStemmer = function() { + /** @protected */ + this.current = ''; + this.cursor = 0; + this.limit = 0; + this.limit_backward = 0; + this.bra = 0; + this.ket = 0; + + /** + * @param {string} value + */ + this.setCurrent = function(value) { + this.current = value; + this.cursor = 0; + this.limit = this.current.length; + this.limit_backward = 0; + this.bra = this.cursor; + this.ket = this.limit; + }; + + /** + * @return {string} + */ + this.getCurrent = function() { + return this.current; + }; + + /** + * @param {BaseStemmer} other + */ + this.copy_from = function(other) { + /** @protected */ + this.current = other.current; + this.cursor = other.cursor; + this.limit = other.limit; + this.limit_backward = other.limit_backward; + this.bra = other.bra; + this.ket = other.ket; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.in_grouping = function(s, min, max) { + /** @protected */ + if (this.cursor >= this.limit) return false; + var ch = this.current.charCodeAt(this.cursor); + if (ch > max || ch < min) return false; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false; + this.cursor++; + return true; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_in_grouping = function(s, min, max) { + /** @protected */ + while (this.cursor < this.limit) { + var ch = this.current.charCodeAt(this.cursor); + if (ch > max || ch < min) + return true; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) + return true; + this.cursor++; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.in_grouping_b = function(s, min, max) { + /** @protected */ + if (this.cursor <= this.limit_backward) return false; + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch > max || ch < min) return false; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false; + this.cursor--; + return true; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_in_grouping_b = function(s, min, max) { + /** @protected */ + while (this.cursor > this.limit_backward) { + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch > max || ch < min) return true; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return true; + this.cursor--; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.out_grouping = function(s, min, max) { + /** @protected */ + if (this.cursor >= this.limit) return false; + var ch = this.current.charCodeAt(this.cursor); + if (ch > max || ch < min) { + this.cursor++; + return true; + } + ch -= min; + if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) == 0) { + this.cursor++; + return true; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_out_grouping = function(s, min, max) { + /** @protected */ + while (this.cursor < this.limit) { + var ch = this.current.charCodeAt(this.cursor); + if (ch <= max && ch >= min) { + ch -= min; + if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) != 0) { + return true; + } + } + this.cursor++; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.out_grouping_b = function(s, min, max) { + /** @protected */ + if (this.cursor <= this.limit_backward) return false; + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch > max || ch < min) { + this.cursor--; + return true; + } + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) { + this.cursor--; + return true; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_out_grouping_b = function(s, min, max) { + /** @protected */ + while (this.cursor > this.limit_backward) { + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch <= max && ch >= min) { + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) != 0) { + return true; + } + } + this.cursor--; + } + return false; + }; + + /** + * @param {string} s + * @return {boolean} + */ + this.eq_s = function(s) + { + /** @protected */ + if (this.limit - this.cursor < s.length) return false; + if (this.current.slice(this.cursor, this.cursor + s.length) != s) + { + return false; + } + this.cursor += s.length; + return true; + }; + + /** + * @param {string} s + * @return {boolean} + */ + this.eq_s_b = function(s) + { + /** @protected */ + if (this.cursor - this.limit_backward < s.length) return false; + if (this.current.slice(this.cursor - s.length, this.cursor) != s) + { + return false; + } + this.cursor -= s.length; + return true; + }; + + /** + * @param {Among[]} v + * @return {number} + */ + this.find_among = function(v) + { + /** @protected */ + var i = 0; + var j = v.length; + + var c = this.cursor; + var l = this.limit; + + var common_i = 0; + var common_j = 0; + + var first_key_inspected = false; + + while (true) + { + var k = i + ((j - i) >>> 1); + var diff = 0; + var common = common_i < common_j ? common_i : common_j; // smaller + // w[0]: string, w[1]: substring_i, w[2]: result, w[3]: function (optional) + var w = v[k]; + var i2; + for (i2 = common; i2 < w[0].length; i2++) + { + if (c + common == l) + { + diff = -1; + break; + } + diff = this.current.charCodeAt(c + common) - w[0].charCodeAt(i2); + if (diff != 0) break; + common++; + } + if (diff < 0) + { + j = k; + common_j = common; + } + else + { + i = k; + common_i = common; + } + if (j - i <= 1) + { + if (i > 0) break; // v->s has been inspected + if (j == i) break; // only one item in v + + // - but now we need to go round once more to get + // v->s inspected. This looks messy, but is actually + // the optimal approach. + + if (first_key_inspected) break; + first_key_inspected = true; + } + } + do { + var w = v[i]; + if (common_i >= w[0].length) + { + this.cursor = c + w[0].length; + if (w.length < 4) return w[2]; + var res = w[3](this); + this.cursor = c + w[0].length; + if (res) return w[2]; + } + i = w[1]; + } while (i >= 0); + return 0; + }; + + // find_among_b is for backwards processing. Same comments apply + /** + * @param {Among[]} v + * @return {number} + */ + this.find_among_b = function(v) + { + /** @protected */ + var i = 0; + var j = v.length + + var c = this.cursor; + var lb = this.limit_backward; + + var common_i = 0; + var common_j = 0; + + var first_key_inspected = false; + + while (true) + { + var k = i + ((j - i) >> 1); + var diff = 0; + var common = common_i < common_j ? common_i : common_j; + var w = v[k]; + var i2; + for (i2 = w[0].length - 1 - common; i2 >= 0; i2--) + { + if (c - common == lb) + { + diff = -1; + break; + } + diff = this.current.charCodeAt(c - 1 - common) - w[0].charCodeAt(i2); + if (diff != 0) break; + common++; + } + if (diff < 0) + { + j = k; + common_j = common; + } + else + { + i = k; + common_i = common; + } + if (j - i <= 1) + { + if (i > 0) break; + if (j == i) break; + if (first_key_inspected) break; + first_key_inspected = true; + } + } + do { + var w = v[i]; + if (common_i >= w[0].length) + { + this.cursor = c - w[0].length; + if (w.length < 4) return w[2]; + var res = w[3](this); + this.cursor = c - w[0].length; + if (res) return w[2]; + } + i = w[1]; + } while (i >= 0); + return 0; + }; + + /* to replace chars between c_bra and c_ket in this.current by the + * chars in s. + */ + /** + * @param {number} c_bra + * @param {number} c_ket + * @param {string} s + * @return {number} + */ + this.replace_s = function(c_bra, c_ket, s) + { + /** @protected */ + var adjustment = s.length - (c_ket - c_bra); + this.current = this.current.slice(0, c_bra) + s + this.current.slice(c_ket); + this.limit += adjustment; + if (this.cursor >= c_ket) this.cursor += adjustment; + else if (this.cursor > c_bra) this.cursor = c_bra; + return adjustment; + }; + + /** + * @return {boolean} + */ + this.slice_check = function() + { + /** @protected */ + if (this.bra < 0 || + this.bra > this.ket || + this.ket > this.limit || + this.limit > this.current.length) + { + return false; + } + return true; + }; + + /** + * @param {number} c_bra + * @return {boolean} + */ + this.slice_from = function(s) + { + /** @protected */ + var result = false; + if (this.slice_check()) + { + this.replace_s(this.bra, this.ket, s); + result = true; + } + return result; + }; + + /** + * @return {boolean} + */ + this.slice_del = function() + { + /** @protected */ + return this.slice_from(""); + }; + + /** + * @param {number} c_bra + * @param {number} c_ket + * @param {string} s + */ + this.insert = function(c_bra, c_ket, s) + { + /** @protected */ + var adjustment = this.replace_s(c_bra, c_ket, s); + if (c_bra <= this.bra) this.bra += adjustment; + if (c_bra <= this.ket) this.ket += adjustment; + }; + + /** + * @return {string} + */ + this.slice_to = function() + { + /** @protected */ + var result = ''; + if (this.slice_check()) + { + result = this.current.slice(this.bra, this.ket); + } + return result; + }; + + /** + * @return {string} + */ + this.assign_to = function() + { + /** @protected */ + return this.current.slice(0, this.limit); + }; +}; diff --git a/dev/doc/_static/basic.css b/dev/doc/_static/basic.css new file mode 100644 index 0000000..4738b2e --- /dev/null +++ b/dev/doc/_static/basic.css @@ -0,0 +1,906 @@ +/* + * Sphinx stylesheet -- basic theme. + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin-top: 10px; +} + +ul.search li { + padding: 5px 0; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/dev/doc/_static/custom.css b/dev/doc/_static/custom.css new file mode 100644 index 0000000..2f80bab --- /dev/null +++ b/dev/doc/_static/custom.css @@ -0,0 +1,7 @@ +.yue code span.pre { + white-space: preserve nowrap; +} + +.line-block .line { + margin-bottom: 5px; +} diff --git a/dev/doc/_static/doc-logo-dark.png b/dev/doc/_static/doc-logo-dark.png new file mode 100644 index 0000000..554d2bf Binary files /dev/null and b/dev/doc/_static/doc-logo-dark.png differ diff --git a/dev/doc/_static/doc-logo-light.png b/dev/doc/_static/doc-logo-light.png new file mode 100644 index 0000000..3654181 Binary files /dev/null and b/dev/doc/_static/doc-logo-light.png differ diff --git a/dev/doc/_static/doctools.js b/dev/doc/_static/doctools.js new file mode 100644 index 0000000..807cdb1 --- /dev/null +++ b/dev/doc/_static/doctools.js @@ -0,0 +1,150 @@ +/* + * Base JavaScript utilities for all Sphinx HTML documentation. + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})`, + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)), + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS + && !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) + return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/dev/doc/_static/documentation_options.js b/dev/doc/_static/documentation_options.js new file mode 100644 index 0000000..af32e4c --- /dev/null +++ b/dev/doc/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '7.0', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'dirhtml', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/dev/doc/_static/english-stemmer.js b/dev/doc/_static/english-stemmer.js new file mode 100644 index 0000000..056760e --- /dev/null +++ b/dev/doc/_static/english-stemmer.js @@ -0,0 +1,1066 @@ +// Generated from english.sbl by Snowball 3.0.1 - https://snowballstem.org/ + +/**@constructor*/ +var EnglishStemmer = function() { + var base = new BaseStemmer(); + + /** @const */ var a_0 = [ + ["arsen", -1, -1], + ["commun", -1, -1], + ["emerg", -1, -1], + ["gener", -1, -1], + ["later", -1, -1], + ["organ", -1, -1], + ["past", -1, -1], + ["univers", -1, -1] + ]; + + /** @const */ var a_1 = [ + ["'", -1, 1], + ["'s'", 0, 1], + ["'s", -1, 1] + ]; + + /** @const */ var a_2 = [ + ["ied", -1, 2], + ["s", -1, 3], + ["ies", 1, 2], + ["sses", 1, 1], + ["ss", 1, -1], + ["us", 1, -1] + ]; + + /** @const */ var a_3 = [ + ["succ", -1, 1], + ["proc", -1, 1], + ["exc", -1, 1] + ]; + + /** @const */ var a_4 = [ + ["even", -1, 2], + ["cann", -1, 2], + ["inn", -1, 2], + ["earr", -1, 2], + ["herr", -1, 2], + ["out", -1, 2], + ["y", -1, 1] + ]; + + /** @const */ var a_5 = [ + ["", -1, -1], + ["ed", 0, 2], + ["eed", 1, 1], + ["ing", 0, 3], + ["edly", 0, 2], + ["eedly", 4, 1], + ["ingly", 0, 2] + ]; + + /** @const */ var a_6 = [ + ["", -1, 3], + ["bb", 0, 2], + ["dd", 0, 2], + ["ff", 0, 2], + ["gg", 0, 2], + ["bl", 0, 1], + ["mm", 0, 2], + ["nn", 0, 2], + ["pp", 0, 2], + ["rr", 0, 2], + ["at", 0, 1], + ["tt", 0, 2], + ["iz", 0, 1] + ]; + + /** @const */ var a_7 = [ + ["anci", -1, 3], + ["enci", -1, 2], + ["ogi", -1, 14], + ["li", -1, 16], + ["bli", 3, 12], + ["abli", 4, 4], + ["alli", 3, 8], + ["fulli", 3, 9], + ["lessli", 3, 15], + ["ousli", 3, 10], + ["entli", 3, 5], + ["aliti", -1, 8], + ["biliti", -1, 12], + ["iviti", -1, 11], + ["tional", -1, 1], + ["ational", 14, 7], + ["alism", -1, 8], + ["ation", -1, 7], + ["ization", 17, 6], + ["izer", -1, 6], + ["ator", -1, 7], + ["iveness", -1, 11], + ["fulness", -1, 9], + ["ousness", -1, 10], + ["ogist", -1, 13] + ]; + + /** @const */ var a_8 = [ + ["icate", -1, 4], + ["ative", -1, 6], + ["alize", -1, 3], + ["iciti", -1, 4], + ["ical", -1, 4], + ["tional", -1, 1], + ["ational", 5, 2], + ["ful", -1, 5], + ["ness", -1, 5] + ]; + + /** @const */ var a_9 = [ + ["ic", -1, 1], + ["ance", -1, 1], + ["ence", -1, 1], + ["able", -1, 1], + ["ible", -1, 1], + ["ate", -1, 1], + ["ive", -1, 1], + ["ize", -1, 1], + ["iti", -1, 1], + ["al", -1, 1], + ["ism", -1, 1], + ["ion", -1, 2], + ["er", -1, 1], + ["ous", -1, 1], + ["ant", -1, 1], + ["ent", -1, 1], + ["ment", 15, 1], + ["ement", 16, 1] + ]; + + /** @const */ var a_10 = [ + ["e", -1, 1], + ["l", -1, 2] + ]; + + /** @const */ var a_11 = [ + ["andes", -1, -1], + ["atlas", -1, -1], + ["bias", -1, -1], + ["cosmos", -1, -1], + ["early", -1, 5], + ["gently", -1, 3], + ["howe", -1, -1], + ["idly", -1, 2], + ["news", -1, -1], + ["only", -1, 6], + ["singly", -1, 7], + ["skies", -1, 1], + ["sky", -1, -1], + ["ugly", -1, 4] + ]; + + /** @const */ var /** Array */ g_aeo = [17, 64]; + + /** @const */ var /** Array */ g_v = [17, 65, 16, 1]; + + /** @const */ var /** Array */ g_v_WXY = [1, 17, 65, 208, 1]; + + /** @const */ var /** Array */ g_valid_LI = [55, 141, 2]; + + var /** boolean */ B_Y_found = false; + var /** number */ I_p2 = 0; + var /** number */ I_p1 = 0; + + + /** @return {boolean} */ + function r_prelude() { + B_Y_found = false; + /** @const */ var /** number */ v_1 = base.cursor; + lab0: { + base.bra = base.cursor; + if (!(base.eq_s("'"))) + { + break lab0; + } + base.ket = base.cursor; + if (!base.slice_del()) + { + return false; + } + } + base.cursor = v_1; + /** @const */ var /** number */ v_2 = base.cursor; + lab1: { + base.bra = base.cursor; + if (!(base.eq_s("y"))) + { + break lab1; + } + base.ket = base.cursor; + if (!base.slice_from("Y")) + { + return false; + } + B_Y_found = true; + } + base.cursor = v_2; + /** @const */ var /** number */ v_3 = base.cursor; + lab2: { + while(true) + { + /** @const */ var /** number */ v_4 = base.cursor; + lab3: { + golab4: while(true) + { + /** @const */ var /** number */ v_5 = base.cursor; + lab5: { + if (!(base.in_grouping(g_v, 97, 121))) + { + break lab5; + } + base.bra = base.cursor; + if (!(base.eq_s("y"))) + { + break lab5; + } + base.ket = base.cursor; + base.cursor = v_5; + break golab4; + } + base.cursor = v_5; + if (base.cursor >= base.limit) + { + break lab3; + } + base.cursor++; + } + if (!base.slice_from("Y")) + { + return false; + } + B_Y_found = true; + continue; + } + base.cursor = v_4; + break; + } + } + base.cursor = v_3; + return true; + }; + + /** @return {boolean} */ + function r_mark_regions() { + I_p1 = base.limit; + I_p2 = base.limit; + /** @const */ var /** number */ v_1 = base.cursor; + lab0: { + lab1: { + /** @const */ var /** number */ v_2 = base.cursor; + lab2: { + if (base.find_among(a_0) == 0) + { + break lab2; + } + break lab1; + } + base.cursor = v_2; + if (!base.go_out_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + if (!base.go_in_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + } + I_p1 = base.cursor; + if (!base.go_out_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + if (!base.go_in_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + I_p2 = base.cursor; + } + base.cursor = v_1; + return true; + }; + + /** @return {boolean} */ + function r_shortv() { + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + if (!(base.out_grouping_b(g_v_WXY, 89, 121))) + { + break lab1; + } + if (!(base.in_grouping_b(g_v, 97, 121))) + { + break lab1; + } + if (!(base.out_grouping_b(g_v, 97, 121))) + { + break lab1; + } + break lab0; + } + base.cursor = base.limit - v_1; + lab2: { + if (!(base.out_grouping_b(g_v, 97, 121))) + { + break lab2; + } + if (!(base.in_grouping_b(g_v, 97, 121))) + { + break lab2; + } + if (base.cursor > base.limit_backward) + { + break lab2; + } + break lab0; + } + base.cursor = base.limit - v_1; + if (!(base.eq_s_b("past"))) + { + return false; + } + } + return true; + }; + + /** @return {boolean} */ + function r_R1() { + return I_p1 <= base.cursor; + }; + + /** @return {boolean} */ + function r_R2() { + return I_p2 <= base.cursor; + }; + + /** @return {boolean} */ + function r_Step_1a() { + var /** number */ among_var; + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab0: { + base.ket = base.cursor; + if (base.find_among_b(a_1) == 0) + { + base.cursor = base.limit - v_1; + break lab0; + } + base.bra = base.cursor; + if (!base.slice_del()) + { + return false; + } + } + base.ket = base.cursor; + among_var = base.find_among_b(a_2); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + switch (among_var) { + case 1: + if (!base.slice_from("ss")) + { + return false; + } + break; + case 2: + lab1: { + /** @const */ var /** number */ v_2 = base.limit - base.cursor; + lab2: { + { + /** @const */ var /** number */ c1 = base.cursor - 2; + if (c1 < base.limit_backward) + { + break lab2; + } + base.cursor = c1; + } + if (!base.slice_from("i")) + { + return false; + } + break lab1; + } + base.cursor = base.limit - v_2; + if (!base.slice_from("ie")) + { + return false; + } + } + break; + case 3: + if (base.cursor <= base.limit_backward) + { + return false; + } + base.cursor--; + if (!base.go_out_grouping_b(g_v, 97, 121)) + { + return false; + } + base.cursor--; + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_1b() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_5); + base.bra = base.cursor; + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + switch (among_var) { + case 1: + /** @const */ var /** number */ v_2 = base.limit - base.cursor; + lab2: { + lab3: { + /** @const */ var /** number */ v_3 = base.limit - base.cursor; + lab4: { + if (base.find_among_b(a_3) == 0) + { + break lab4; + } + if (base.cursor > base.limit_backward) + { + break lab4; + } + break lab3; + } + base.cursor = base.limit - v_3; + if (!r_R1()) + { + break lab2; + } + if (!base.slice_from("ee")) + { + return false; + } + } + } + base.cursor = base.limit - v_2; + break; + case 2: + break lab1; + case 3: + among_var = base.find_among_b(a_4); + if (among_var == 0) + { + break lab1; + } + switch (among_var) { + case 1: + /** @const */ var /** number */ v_4 = base.limit - base.cursor; + if (!(base.out_grouping_b(g_v, 97, 121))) + { + break lab1; + } + if (base.cursor > base.limit_backward) + { + break lab1; + } + base.cursor = base.limit - v_4; + base.bra = base.cursor; + if (!base.slice_from("ie")) + { + return false; + } + break; + case 2: + if (base.cursor > base.limit_backward) + { + break lab1; + } + break; + } + break; + } + break lab0; + } + base.cursor = base.limit - v_1; + /** @const */ var /** number */ v_5 = base.limit - base.cursor; + if (!base.go_out_grouping_b(g_v, 97, 121)) + { + return false; + } + base.cursor--; + base.cursor = base.limit - v_5; + if (!base.slice_del()) + { + return false; + } + base.ket = base.cursor; + base.bra = base.cursor; + /** @const */ var /** number */ v_6 = base.limit - base.cursor; + among_var = base.find_among_b(a_6); + switch (among_var) { + case 1: + if (!base.slice_from("e")) + { + return false; + } + return false; + case 2: + { + /** @const */ var /** number */ v_7 = base.limit - base.cursor; + lab5: { + if (!(base.in_grouping_b(g_aeo, 97, 111))) + { + break lab5; + } + if (base.cursor > base.limit_backward) + { + break lab5; + } + return false; + } + base.cursor = base.limit - v_7; + } + break; + case 3: + if (base.cursor != I_p1) + { + return false; + } + /** @const */ var /** number */ v_8 = base.limit - base.cursor; + if (!r_shortv()) + { + return false; + } + base.cursor = base.limit - v_8; + if (!base.slice_from("e")) + { + return false; + } + return false; + } + base.cursor = base.limit - v_6; + base.ket = base.cursor; + if (base.cursor <= base.limit_backward) + { + return false; + } + base.cursor--; + base.bra = base.cursor; + if (!base.slice_del()) + { + return false; + } + } + return true; + }; + + /** @return {boolean} */ + function r_Step_1c() { + base.ket = base.cursor; + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + if (!(base.eq_s_b("y"))) + { + break lab1; + } + break lab0; + } + base.cursor = base.limit - v_1; + if (!(base.eq_s_b("Y"))) + { + return false; + } + } + base.bra = base.cursor; + if (!(base.out_grouping_b(g_v, 97, 121))) + { + return false; + } + lab2: { + if (base.cursor > base.limit_backward) + { + break lab2; + } + return false; + } + if (!base.slice_from("i")) + { + return false; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_2() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_7); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + if (!r_R1()) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_from("tion")) + { + return false; + } + break; + case 2: + if (!base.slice_from("ence")) + { + return false; + } + break; + case 3: + if (!base.slice_from("ance")) + { + return false; + } + break; + case 4: + if (!base.slice_from("able")) + { + return false; + } + break; + case 5: + if (!base.slice_from("ent")) + { + return false; + } + break; + case 6: + if (!base.slice_from("ize")) + { + return false; + } + break; + case 7: + if (!base.slice_from("ate")) + { + return false; + } + break; + case 8: + if (!base.slice_from("al")) + { + return false; + } + break; + case 9: + if (!base.slice_from("ful")) + { + return false; + } + break; + case 10: + if (!base.slice_from("ous")) + { + return false; + } + break; + case 11: + if (!base.slice_from("ive")) + { + return false; + } + break; + case 12: + if (!base.slice_from("ble")) + { + return false; + } + break; + case 13: + if (!base.slice_from("og")) + { + return false; + } + break; + case 14: + if (!(base.eq_s_b("l"))) + { + return false; + } + if (!base.slice_from("og")) + { + return false; + } + break; + case 15: + if (!base.slice_from("less")) + { + return false; + } + break; + case 16: + if (!(base.in_grouping_b(g_valid_LI, 99, 116))) + { + return false; + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_3() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_8); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + if (!r_R1()) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_from("tion")) + { + return false; + } + break; + case 2: + if (!base.slice_from("ate")) + { + return false; + } + break; + case 3: + if (!base.slice_from("al")) + { + return false; + } + break; + case 4: + if (!base.slice_from("ic")) + { + return false; + } + break; + case 5: + if (!base.slice_del()) + { + return false; + } + break; + case 6: + if (!r_R2()) + { + return false; + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_4() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_9); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + if (!r_R2()) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_del()) + { + return false; + } + break; + case 2: + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + if (!(base.eq_s_b("s"))) + { + break lab1; + } + break lab0; + } + base.cursor = base.limit - v_1; + if (!(base.eq_s_b("t"))) + { + return false; + } + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_5() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_10); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + switch (among_var) { + case 1: + lab0: { + lab1: { + if (!r_R2()) + { + break lab1; + } + break lab0; + } + if (!r_R1()) + { + return false; + } + { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab2: { + if (!r_shortv()) + { + break lab2; + } + return false; + } + base.cursor = base.limit - v_1; + } + } + if (!base.slice_del()) + { + return false; + } + break; + case 2: + if (!r_R2()) + { + return false; + } + if (!(base.eq_s_b("l"))) + { + return false; + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_exception1() { + var /** number */ among_var; + base.bra = base.cursor; + among_var = base.find_among(a_11); + if (among_var == 0) + { + return false; + } + base.ket = base.cursor; + if (base.cursor < base.limit) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_from("sky")) + { + return false; + } + break; + case 2: + if (!base.slice_from("idl")) + { + return false; + } + break; + case 3: + if (!base.slice_from("gentl")) + { + return false; + } + break; + case 4: + if (!base.slice_from("ugli")) + { + return false; + } + break; + case 5: + if (!base.slice_from("earli")) + { + return false; + } + break; + case 6: + if (!base.slice_from("onli")) + { + return false; + } + break; + case 7: + if (!base.slice_from("singl")) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_postlude() { + if (!B_Y_found) + { + return false; + } + while(true) + { + /** @const */ var /** number */ v_1 = base.cursor; + lab0: { + golab1: while(true) + { + /** @const */ var /** number */ v_2 = base.cursor; + lab2: { + base.bra = base.cursor; + if (!(base.eq_s("Y"))) + { + break lab2; + } + base.ket = base.cursor; + base.cursor = v_2; + break golab1; + } + base.cursor = v_2; + if (base.cursor >= base.limit) + { + break lab0; + } + base.cursor++; + } + if (!base.slice_from("y")) + { + return false; + } + continue; + } + base.cursor = v_1; + break; + } + return true; + }; + + this.stem = /** @return {boolean} */ function() { + lab0: { + /** @const */ var /** number */ v_1 = base.cursor; + lab1: { + if (!r_exception1()) + { + break lab1; + } + break lab0; + } + base.cursor = v_1; + lab2: { + { + /** @const */ var /** number */ v_2 = base.cursor; + lab3: { + { + /** @const */ var /** number */ c1 = base.cursor + 3; + if (c1 > base.limit) + { + break lab3; + } + base.cursor = c1; + } + break lab2; + } + base.cursor = v_2; + } + break lab0; + } + base.cursor = v_1; + r_prelude(); + r_mark_regions(); + base.limit_backward = base.cursor; base.cursor = base.limit; + /** @const */ var /** number */ v_3 = base.limit - base.cursor; + r_Step_1a(); + base.cursor = base.limit - v_3; + /** @const */ var /** number */ v_4 = base.limit - base.cursor; + r_Step_1b(); + base.cursor = base.limit - v_4; + /** @const */ var /** number */ v_5 = base.limit - base.cursor; + r_Step_1c(); + base.cursor = base.limit - v_5; + /** @const */ var /** number */ v_6 = base.limit - base.cursor; + r_Step_2(); + base.cursor = base.limit - v_6; + /** @const */ var /** number */ v_7 = base.limit - base.cursor; + r_Step_3(); + base.cursor = base.limit - v_7; + /** @const */ var /** number */ v_8 = base.limit - base.cursor; + r_Step_4(); + base.cursor = base.limit - v_8; + /** @const */ var /** number */ v_9 = base.limit - base.cursor; + r_Step_5(); + base.cursor = base.limit - v_9; + base.cursor = base.limit_backward; + /** @const */ var /** number */ v_10 = base.cursor; + r_postlude(); + base.cursor = v_10; + } + return true; + }; + + /**@return{string}*/ + this['stemWord'] = function(/**string*/word) { + base.setCurrent(word); + this.stem(); + return base.getCurrent(); + }; +}; diff --git a/dev/doc/_static/file.png b/dev/doc/_static/file.png new file mode 100644 index 0000000..a858a41 Binary files /dev/null and b/dev/doc/_static/file.png differ diff --git a/dev/doc/_static/language_data.js b/dev/doc/_static/language_data.js new file mode 100644 index 0000000..5776786 --- /dev/null +++ b/dev/doc/_static/language_data.js @@ -0,0 +1,13 @@ +/* + * This script contains the language-specific data used by searchtools.js, + * namely the set of stopwords, stemmer, scorer and splitter. + */ + +const stopwords = new Set(["a", "about", "above", "after", "again", "against", "all", "am", "an", "and", "any", "are", "aren't", "as", "at", "be", "because", "been", "before", "being", "below", "between", "both", "but", "by", "can't", "cannot", "could", "couldn't", "did", "didn't", "do", "does", "doesn't", "doing", "don't", "down", "during", "each", "few", "for", "from", "further", "had", "hadn't", "has", "hasn't", "have", "haven't", "having", "he", "he'd", "he'll", "he's", "her", "here", "here's", "hers", "herself", "him", "himself", "his", "how", "how's", "i", "i'd", "i'll", "i'm", "i've", "if", "in", "into", "is", "isn't", "it", "it's", "its", "itself", "let's", "me", "more", "most", "mustn't", "my", "myself", "no", "nor", "not", "of", "off", "on", "once", "only", "or", "other", "ought", "our", "ours", "ourselves", "out", "over", "own", "same", "shan't", "she", "she'd", "she'll", "she's", "should", "shouldn't", "so", "some", "such", "than", "that", "that's", "the", "their", "theirs", "them", "themselves", "then", "there", "there's", "these", "they", "they'd", "they'll", "they're", "they've", "this", "those", "through", "to", "too", "under", "until", "up", "very", "was", "wasn't", "we", "we'd", "we'll", "we're", "we've", "were", "weren't", "what", "what's", "when", "when's", "where", "where's", "which", "while", "who", "who's", "whom", "why", "why's", "with", "won't", "would", "wouldn't", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves"]); +window.stopwords = stopwords; // Export to global scope + + +/* Non-minified versions are copied as separate JavaScript files, if available */ +BaseStemmer=function(){this.current="",this.cursor=0,this.limit=0,this.limit_backward=0,this.bra=0,this.ket=0,this.setCurrent=function(t){this.current=t,this.cursor=0,this.limit=this.current.length,this.limit_backward=0,this.bra=this.cursor,this.ket=this.limit},this.getCurrent=function(){return this.current},this.copy_from=function(t){this.current=t.current,this.cursor=t.cursor,this.limit=t.limit,this.limit_backward=t.limit_backward,this.bra=t.bra,this.ket=t.ket},this.in_grouping=function(t,r,i){return!(this.cursor>=this.limit||i<(i=this.current.charCodeAt(this.cursor))||i>>3]&1<<(7&i))||(this.cursor++,0))},this.go_in_grouping=function(t,r,i){for(;this.cursor>>3]&1<<(7&s)))return!0;this.cursor++}return!1},this.in_grouping_b=function(t,r,i){return!(this.cursor<=this.limit_backward||i<(i=this.current.charCodeAt(this.cursor-1))||i>>3]&1<<(7&i))||(this.cursor--,0))},this.go_in_grouping_b=function(t,r,i){for(;this.cursor>this.limit_backward;){var s=this.current.charCodeAt(this.cursor-1);if(i>>3]&1<<(7&s)))return!0;this.cursor--}return!1},this.out_grouping=function(t,r,i){return!(this.cursor>=this.limit)&&(i<(i=this.current.charCodeAt(this.cursor))||i>>3]&1<<(7&i)))&&(this.cursor++,!0)},this.go_out_grouping=function(t,r,i){for(;this.cursor>>3]&1<<(7&s)))return!0;this.cursor++}return!1},this.out_grouping_b=function(t,r,i){return!(this.cursor<=this.limit_backward)&&(i<(i=this.current.charCodeAt(this.cursor-1))||i>>3]&1<<(7&i)))&&(this.cursor--,!0)},this.go_out_grouping_b=function(t,r,i){for(;this.cursor>this.limit_backward;){var s=this.current.charCodeAt(this.cursor-1);if(s<=i&&r<=s&&0!=(t[(s-=r)>>>3]&1<<(7&s)))return!0;this.cursor--}return!1},this.eq_s=function(t){return!(this.limit-this.cursor>>1),o=0,a=e=(l=t[r])[0].length){if(this.cursor=s+l[0].length,l.length<4)return l[2];var g=l[3](this);if(this.cursor=s+l[0].length,g)return l[2]}}while(0<=(r=l[1]));return 0},this.find_among_b=function(t){for(var r=0,i=t.length,s=this.cursor,h=this.limit_backward,e=0,n=0,c=!1;;){for(var u,o=r+(i-r>>1),a=0,l=e=(u=t[r])[0].length){if(this.cursor=s-u[0].length,u.length<4)return u[2];var g=u[3](this);if(this.cursor=s-u[0].length,g)return u[2]}}while(0<=(r=u[1]));return 0},this.replace_s=function(t,r,i){var s=i.length-(r-t);return this.current=this.current.slice(0,t)+i+this.current.slice(r),this.limit+=s,this.cursor>=r?this.cursor+=s:this.cursor>t&&(this.cursor=t),s},this.slice_check=function(){return!(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>this.current.length)},this.slice_from=function(t){var r=!1;return this.slice_check()&&(this.replace_s(this.bra,this.ket,t),r=!0),r},this.slice_del=function(){return this.slice_from("")},this.insert=function(t,r,i){r=this.replace_s(t,r,i);t<=this.bra&&(this.bra+=r),t<=this.ket&&(this.ket+=r)},this.slice_to=function(){var t="";return t=this.slice_check()?this.current.slice(this.bra,this.ket):t},this.assign_to=function(){return this.current.slice(0,this.limit)}}; +var EnglishStemmer=function(){var a=new BaseStemmer,c=[["arsen",-1,-1],["commun",-1,-1],["emerg",-1,-1],["gener",-1,-1],["later",-1,-1],["organ",-1,-1],["past",-1,-1],["univers",-1,-1]],o=[["'",-1,1],["'s'",0,1],["'s",-1,1]],u=[["ied",-1,2],["s",-1,3],["ies",1,2],["sses",1,1],["ss",1,-1],["us",1,-1]],t=[["succ",-1,1],["proc",-1,1],["exc",-1,1]],l=[["even",-1,2],["cann",-1,2],["inn",-1,2],["earr",-1,2],["herr",-1,2],["out",-1,2],["y",-1,1]],n=[["",-1,-1],["ed",0,2],["eed",1,1],["ing",0,3],["edly",0,2],["eedly",4,1],["ingly",0,2]],f=[["",-1,3],["bb",0,2],["dd",0,2],["ff",0,2],["gg",0,2],["bl",0,1],["mm",0,2],["nn",0,2],["pp",0,2],["rr",0,2],["at",0,1],["tt",0,2],["iz",0,1]],_=[["anci",-1,3],["enci",-1,2],["ogi",-1,14],["li",-1,16],["bli",3,12],["abli",4,4],["alli",3,8],["fulli",3,9],["lessli",3,15],["ousli",3,10],["entli",3,5],["aliti",-1,8],["biliti",-1,12],["iviti",-1,11],["tional",-1,1],["ational",14,7],["alism",-1,8],["ation",-1,7],["ization",17,6],["izer",-1,6],["ator",-1,7],["iveness",-1,11],["fulness",-1,9],["ousness",-1,10],["ogist",-1,13]],m=[["icate",-1,4],["ative",-1,6],["alize",-1,3],["iciti",-1,4],["ical",-1,4],["tional",-1,1],["ational",5,2],["ful",-1,5],["ness",-1,5]],b=[["ic",-1,1],["ance",-1,1],["ence",-1,1],["able",-1,1],["ible",-1,1],["ate",-1,1],["ive",-1,1],["ize",-1,1],["iti",-1,1],["al",-1,1],["ism",-1,1],["ion",-1,2],["er",-1,1],["ous",-1,1],["ant",-1,1],["ent",-1,1],["ment",15,1],["ement",16,1]],k=[["e",-1,1],["l",-1,2]],g=[["andes",-1,-1],["atlas",-1,-1],["bias",-1,-1],["cosmos",-1,-1],["early",-1,5],["gently",-1,3],["howe",-1,-1],["idly",-1,2],["news",-1,-1],["only",-1,6],["singly",-1,7],["skies",-1,1],["sky",-1,-1],["ugly",-1,4]],d=[17,64],v=[17,65,16,1],i=[1,17,65,208,1],w=[55,141,2],p=!1,y=0,h=0;function q(){var r=a.limit-a.cursor;return!!(a.out_grouping_b(i,89,121)&&a.in_grouping_b(v,97,121)&&a.out_grouping_b(v,97,121)||(a.cursor=a.limit-r,a.out_grouping_b(v,97,121)&&a.in_grouping_b(v,97,121)&&!(a.cursor>a.limit_backward))||(a.cursor=a.limit-r,a.eq_s_b("past")))}function z(){return h<=a.cursor}function Y(){return y<=a.cursor}this.stem=function(){var r=a.cursor;if(!(()=>{var r;if(a.bra=a.cursor,0!=(r=a.find_among(g))&&(a.ket=a.cursor,!(a.cursora.limit)a.cursor=i;else{a.cursor=e,a.cursor=r,(()=>{p=!1;var r=a.cursor;if(a.bra=a.cursor,!a.eq_s("'")||(a.ket=a.cursor,a.slice_del())){a.cursor=r;r=a.cursor;if(a.bra=a.cursor,a.eq_s("y")){if(a.ket=a.cursor,!a.slice_from("Y"))return;p=!0}a.cursor=r;for(r=a.cursor;;){var i=a.cursor;r:{for(;;){var e=a.cursor;if(a.in_grouping(v,97,121)&&(a.bra=a.cursor,a.eq_s("y"))){a.ket=a.cursor,a.cursor=e;break}if(a.cursor=e,a.cursor>=a.limit)break r;a.cursor++}if(!a.slice_from("Y"))return;p=!0;continue}a.cursor=i;break}a.cursor=r}})(),h=a.limit,y=a.limit;i=a.cursor;r:{var s=a.cursor;if(0==a.find_among(c)){if(a.cursor=s,!a.go_out_grouping(v,97,121))break r;if(a.cursor++,!a.go_in_grouping(v,97,121))break r;a.cursor++}h=a.cursor,a.go_out_grouping(v,97,121)&&(a.cursor++,a.go_in_grouping(v,97,121))&&(a.cursor++,y=a.cursor)}a.cursor=i,a.limit_backward=a.cursor,a.cursor=a.limit;var e=a.limit-a.cursor,r=((()=>{var r=a.limit-a.cursor;if(a.ket=a.cursor,0==a.find_among_b(o))a.cursor=a.limit-r;else if(a.bra=a.cursor,!a.slice_del())return;if(a.ket=a.cursor,0!=(r=a.find_among_b(u)))switch(a.bra=a.cursor,r){case 1:if(a.slice_from("ss"))break;return;case 2:r:{var i=a.limit-a.cursor,e=a.cursor-2;if(!(e{a.ket=a.cursor,o=a.find_among_b(n),a.bra=a.cursor;r:{var r=a.limit-a.cursor;i:{switch(o){case 1:var i=a.limit-a.cursor;e:{var e=a.limit-a.cursor;if(0==a.find_among_b(t)||a.cursor>a.limit_backward){if(a.cursor=a.limit-e,!z())break e;if(!a.slice_from("ee"))return}}a.cursor=a.limit-i;break;case 2:break i;case 3:if(0==(o=a.find_among_b(l)))break i;switch(o){case 1:var s=a.limit-a.cursor;if(!a.out_grouping_b(v,97,121))break i;if(a.cursor>a.limit_backward)break i;if(a.cursor=a.limit-s,a.bra=a.cursor,a.slice_from("ie"))break;return;case 2:if(a.cursor>a.limit_backward)break i}}break r}a.cursor=a.limit-r;var c=a.limit-a.cursor;if(!a.go_out_grouping_b(v,97,121))return;if(a.cursor--,a.cursor=a.limit-c,!a.slice_del())return;a.ket=a.cursor,a.bra=a.cursor;var o,c=a.limit-a.cursor;switch(o=a.find_among_b(f)){case 1:return a.slice_from("e");case 2:var u=a.limit-a.cursor;if(a.in_grouping_b(d,97,111)&&!(a.cursor>a.limit_backward))return;a.cursor=a.limit-u;break;case 3:return a.cursor!=h||(u=a.limit-a.cursor,q()&&(a.cursor=a.limit-u,a.slice_from("e")))}if(a.cursor=a.limit-c,a.ket=a.cursor,a.cursor<=a.limit_backward)return;if(a.cursor--,a.bra=a.cursor,!a.slice_del())return}})(),a.cursor=a.limit-r,a.limit-a.cursor),r=(a.ket=a.cursor,e=a.limit-a.cursor,(a.eq_s_b("y")||(a.cursor=a.limit-e,a.eq_s_b("Y")))&&(a.bra=a.cursor,a.out_grouping_b(v,97,121))&&a.cursor>a.limit_backward&&a.slice_from("i"),a.cursor=a.limit-i,a.limit-a.cursor),e=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(_))&&(a.bra=a.cursor,z()))switch(r){case 1:if(a.slice_from("tion"))break;return;case 2:if(a.slice_from("ence"))break;return;case 3:if(a.slice_from("ance"))break;return;case 4:if(a.slice_from("able"))break;return;case 5:if(a.slice_from("ent"))break;return;case 6:if(a.slice_from("ize"))break;return;case 7:if(a.slice_from("ate"))break;return;case 8:if(a.slice_from("al"))break;return;case 9:if(a.slice_from("ful"))break;return;case 10:if(a.slice_from("ous"))break;return;case 11:if(a.slice_from("ive"))break;return;case 12:if(a.slice_from("ble"))break;return;case 13:if(a.slice_from("og"))break;return;case 14:if(!a.eq_s_b("l"))return;if(a.slice_from("og"))break;return;case 15:if(a.slice_from("less"))break;return;case 16:if(!a.in_grouping_b(w,99,116))return;if(a.slice_del())break}})(),a.cursor=a.limit-r,a.limit-a.cursor),i=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(m))&&(a.bra=a.cursor,z()))switch(r){case 1:if(a.slice_from("tion"))break;return;case 2:if(a.slice_from("ate"))break;return;case 3:if(a.slice_from("al"))break;return;case 4:if(a.slice_from("ic"))break;return;case 5:if(a.slice_del())break;return;case 6:if(!Y())return;if(a.slice_del())break}})(),a.cursor=a.limit-e,a.limit-a.cursor),r=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(b))&&(a.bra=a.cursor,Y()))switch(r){case 1:if(a.slice_del())break;return;case 2:var i=a.limit-a.cursor;if(!a.eq_s_b("s")&&(a.cursor=a.limit-i,!a.eq_s_b("t")))return;if(a.slice_del())break}})(),a.cursor=a.limit-i,a.limit-a.cursor),e=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(k)))switch(a.bra=a.cursor,r){case 1:if(!Y()){if(!z())return;var i=a.limit-a.cursor;if(q())return;a.cursor=a.limit-i}if(a.slice_del())break;return;case 2:if(!Y())return;if(!a.eq_s_b("l"))return;if(a.slice_del())break}})(),a.cursor=a.limit-r,a.cursor=a.limit_backward,a.cursor);(()=>{if(p)for(;;){var r=a.cursor;r:{for(;;){var i=a.cursor;if(a.bra=a.cursor,a.eq_s("Y")){a.ket=a.cursor,a.cursor=i;break}if(a.cursor=i,a.cursor>=a.limit)break r;a.cursor++}if(a.slice_from("y"))continue;return}a.cursor=r;break}})(),a.cursor=e}}return!0},this.stemWord=function(r){return a.setCurrent(r),this.stem(),a.getCurrent()}}; +window.Stemmer = EnglishStemmer; diff --git a/dev/doc/_static/minus.png b/dev/doc/_static/minus.png new file mode 100644 index 0000000..d96755f Binary files /dev/null and b/dev/doc/_static/minus.png differ diff --git a/dev/doc/_static/plus.png b/dev/doc/_static/plus.png new file mode 100644 index 0000000..7107cec Binary files /dev/null and b/dev/doc/_static/plus.png differ diff --git a/dev/doc/_static/print.css b/dev/doc/_static/print.css new file mode 100644 index 0000000..bd88769 --- /dev/null +++ b/dev/doc/_static/print.css @@ -0,0 +1,42 @@ +.sy-head { + position: static; + border-bottom: 1px solid var(--sy-c-divider); +} + +.sy-head-inner { + padding: 0; +} + +.sy-breadcrumbs { + display: none; +} + +h1, h2, h3, h4, h5, h6 { + page-break-inside: avoid; + page-break-after: avoid; +} + +.code-block-caption, +pre, code { + page-break-inside: avoid; + white-space: pre-wrap; + + -webkit-print-color-adjust: exact; +} + +.yue a.headerlink { + display: none; +} + +.highlight .linenos { + box-shadow: none; +} + +.admonition, +.sd-sphinx-override { + -webkit-print-color-adjust: exact; +} + +.sd-card { + page-break-inside: avoid; +} diff --git a/dev/doc/_static/pygments.css b/dev/doc/_static/pygments.css new file mode 100644 index 0000000..352b22c --- /dev/null +++ b/dev/doc/_static/pygments.css @@ -0,0 +1,278 @@ +:root { +--syntax-light-background: #ffffff; +--syntax-light-highlight: #4ac26b40; +--syntax-light-text: #1F2328; +--syntax-light-escape: #0A3069; +--syntax-light-error: #82071E; +--syntax-light-keyword: #CF222E; +--syntax-light-keyword-constant: #0550AE; +--syntax-light-keyword-type: #953800; +--syntax-light-name-attribute: #0550AE; +--syntax-light-name-builtin: #0550AE; +--syntax-light-name-class: #953800; +--syntax-light-name-constant: #0550AE; +--syntax-light-name-decorator: #0550AE; +--syntax-light-name-entity: #0550AE; +--syntax-light-name-exception: #0550AE; +--syntax-light-name-function: #8250DF; +--syntax-light-name-function-magic: #0550AE; +--syntax-light-name-property: #0550AE; +--syntax-light-name-label: #0A3069; +--syntax-light-name-tag: #116329; +--syntax-light-name-variable-class: #953800; +--syntax-light-literal: #0A3069; +--syntax-light-literal-string: #0A3069; +--syntax-light-literal-string-affix: #CF222E; +--syntax-light-literal-string-backtick: #0550AE; +--syntax-light-literal-string-interpol: #CF222E; +--syntax-light-literal-string-regex: #0A3069; +--syntax-light-literal-string-symbol: #0550AE; +--syntax-light-literal-number: #0550AE; +--syntax-light-operator: #CF222E; +--syntax-light-operator-word: #0550AE; +--syntax-light-comment: #6E7781; +--syntax-light-comment-preproc: #CF222E; +--syntax-light-comment-preprocfile: #0A3069; +--syntax-light-generic-deleted: #82071E; +--syntax-light-generic-emph: #1F2328; +--syntax-light-generic-error: #82071E; +--syntax-light-generic-heading: #0550AE; +--syntax-light-generic-inserted: #116329; +--syntax-light-generic-output: #0A3069; +--syntax-light-generic-prompt: #CF222E; +--syntax-light-generic-strong: #1F2328; +--syntax-light-generic-subheading: #0550AE; +--syntax-light-generic-emphstrong: #1F2328; +--syntax-light-generic-traceback: #82071E; +--syntax-light-text-whitespace: #1F2328; +--syntax-light-keyword-declaration: #CF222E; +--syntax-light-keyword-namespace: #CF222E; +--syntax-light-keyword-pseudo: #CF222E; +--syntax-light-keyword-reserved: #CF222E; +--syntax-light-name-builtin-pseudo: #0550AE; +--syntax-light-literal-date: #0A3069; +--syntax-light-literal-string-char: #0A3069; +--syntax-light-literal-string-delimiter: #0A3069; +--syntax-light-literal-string-doc: #0A3069; +--syntax-light-literal-string-double: #0A3069; +--syntax-light-literal-string-escape: #0A3069; +--syntax-light-literal-string-heredoc: #0A3069; +--syntax-light-literal-string-other: #0A3069; +--syntax-light-literal-string-single: #0A3069; +--syntax-light-literal-number-bin: #0550AE; +--syntax-light-literal-number-float: #0550AE; +--syntax-light-literal-number-hex: #0550AE; +--syntax-light-literal-number-integer: #0550AE; +--syntax-light-literal-number-integer-long: #0550AE; +--syntax-light-literal-number-oct: #0550AE; +--syntax-light-comment-hashbang: #6E7781; +--syntax-light-comment-multiline: #6E7781; +--syntax-light-comment-single: #6E7781; +--syntax-light-comment-special: #6E7781; +} +html.light .highlight .c { color: var(--syntax-light-comment) } +html.light .highlight .err { color: var(--syntax-light-error) } +html.light .highlight .esc { color: var(--syntax-light-escape) } +html.light .highlight .k { color: var(--syntax-light-keyword) } +html.light .highlight .l { color: var(--syntax-light-literal) } +html.light .highlight .o { color: var(--syntax-light-operator) } +html.light .highlight .ch { color: var(--syntax-light-comment-hashbang) } +html.light .highlight .cm { color: var(--syntax-light-comment-multiline) } +html.light .highlight .cp { color: var(--syntax-light-comment-preproc) } +html.light .highlight .cpf { color: var(--syntax-light-comment-preprocfile) } +html.light .highlight .c1 { color: var(--syntax-light-comment-single) } +html.light .highlight .cs { color: var(--syntax-light-comment-special) } +html.light .highlight .gd { color: var(--syntax-light-generic-deleted) } +html.light .highlight .ge { color: var(--syntax-light-generic-emph); font-style: italic } +html.light .highlight .ges { color: var(--syntax-light-generic-emphstrong); font-weight: bold; font-style: italic } +html.light .highlight .gr { color: var(--syntax-light-generic-error) } +html.light .highlight .gh { color: var(--syntax-light-generic-heading); font-weight: bold } +html.light .highlight .gi { color: var(--syntax-light-generic-inserted) } +html.light .highlight .go { color: var(--syntax-light-generic-output) } +html.light .highlight .gp { color: var(--syntax-light-generic-prompt) } +html.light .highlight .gs { color: var(--syntax-light-generic-strong); font-weight: bold } +html.light .highlight .gu { color: var(--syntax-light-generic-subheading) } +html.light .highlight .gt { color: var(--syntax-light-generic-traceback) } +html.light .highlight .kc { color: var(--syntax-light-keyword-constant) } +html.light .highlight .kd { color: var(--syntax-light-keyword-declaration) } +html.light .highlight .kn { color: var(--syntax-light-keyword-namespace) } +html.light .highlight .kp { color: var(--syntax-light-keyword-pseudo) } +html.light .highlight .kr { color: var(--syntax-light-keyword-reserved) } +html.light .highlight .kt { color: var(--syntax-light-keyword-type) } +html.light .highlight .ld { color: var(--syntax-light-literal-date) } +html.light .highlight .m { color: var(--syntax-light-literal-number) } +html.light .highlight .s { color: var(--syntax-light-literal-string) } +html.light .highlight .na { color: var(--syntax-light-name-attribute) } +html.light .highlight .nb { color: var(--syntax-light-name-builtin) } +html.light .highlight .nc { color: var(--syntax-light-name-class) } +html.light .highlight .no { color: var(--syntax-light-name-constant) } +html.light .highlight .nd { color: var(--syntax-light-name-decorator) } +html.light .highlight .ni { color: var(--syntax-light-name-entity) } +html.light .highlight .ne { color: var(--syntax-light-name-exception) } +html.light .highlight .nf { color: var(--syntax-light-name-function) } +html.light .highlight .nl { color: var(--syntax-light-name-label) } +html.light .highlight .py { color: var(--syntax-light-name-property) } +html.light .highlight .nt { color: var(--syntax-light-name-tag) } +html.light .highlight .ow { color: var(--syntax-light-operator-word) } +html.light .highlight .w { color: var(--syntax-light-text-whitespace) } +html.light .highlight .mb { color: var(--syntax-light-literal-number-bin) } +html.light .highlight .mf { color: var(--syntax-light-literal-number-float) } +html.light .highlight .mh { color: var(--syntax-light-literal-number-hex) } +html.light .highlight .mi { color: var(--syntax-light-literal-number-integer) } +html.light .highlight .mo { color: var(--syntax-light-literal-number-oct) } +html.light .highlight .sa { color: var(--syntax-light-literal-string-affix) } +html.light .highlight .sb { color: var(--syntax-light-literal-string-backtick) } +html.light .highlight .sc { color: var(--syntax-light-literal-string-char) } +html.light .highlight .dl { color: var(--syntax-light-literal-string-delimiter) } +html.light .highlight .sd { color: var(--syntax-light-literal-string-doc) } +html.light .highlight .s2 { color: var(--syntax-light-literal-string-double) } +html.light .highlight .se { color: var(--syntax-light-literal-string-escape) } +html.light .highlight .sh { color: var(--syntax-light-literal-string-heredoc) } +html.light .highlight .si { color: var(--syntax-light-literal-string-interpol) } +html.light .highlight .sx { color: var(--syntax-light-literal-string-other) } +html.light .highlight .sr { color: var(--syntax-light-literal-string-regex) } +html.light .highlight .s1 { color: var(--syntax-light-literal-string-single) } +html.light .highlight .ss { color: var(--syntax-light-literal-string-symbol) } +html.light .highlight .bp { color: var(--syntax-light-name-builtin-pseudo) } +html.light .highlight .fm { color: var(--syntax-light-name-function-magic) } +html.light .highlight .vc { color: var(--syntax-light-name-variable-class) } +html.light .highlight .il { color: var(--syntax-light-literal-number-integer-long) } +:root { +--syntax-dark-background: #0d1117; +--syntax-dark-highlight: #3fb95040; +--syntax-dark-text: #E6EDF3; +--syntax-dark-escape: #A5D6FF; +--syntax-dark-error: #FFA198; +--syntax-dark-keyword: #FF7B72; +--syntax-dark-keyword-constant: #79C0FF; +--syntax-dark-keyword-type: #FFA657; +--syntax-dark-name-attribute: #79C0FF; +--syntax-dark-name-builtin: #79C0FF; +--syntax-dark-name-class: #FFA657; +--syntax-dark-name-constant: #79C0FF; +--syntax-dark-name-decorator: #79C0FF; +--syntax-dark-name-entity: #79C0FF; +--syntax-dark-name-exception: #79C0FF; +--syntax-dark-name-function: #D2A8FF; +--syntax-dark-name-function-magic: #79C0FF; +--syntax-dark-name-property: #79C0FF; +--syntax-dark-name-label: #A5D6FF; +--syntax-dark-name-tag: #7EE787; +--syntax-dark-name-variable-class: #FFA657; +--syntax-dark-literal: #A5D6FF; +--syntax-dark-literal-string: #A5D6FF; +--syntax-dark-literal-string-affix: #FF7B72; +--syntax-dark-literal-string-backtick: #79C0FF; +--syntax-dark-literal-string-interpol: #FF7B72; +--syntax-dark-literal-string-regex: #A5D6FF; +--syntax-dark-literal-string-symbol: #79C0FF; +--syntax-dark-literal-number: #79C0FF; +--syntax-dark-operator: #FF7B72; +--syntax-dark-operator-word: #79C0FF; +--syntax-dark-comment: #8B949E; +--syntax-dark-comment-preproc: #FF7B72; +--syntax-dark-comment-preprocfile: #A5D6FF; +--syntax-dark-generic-deleted: #FFA198; +--syntax-dark-generic-emph: #E6EDF3; +--syntax-dark-generic-error: #FFA198; +--syntax-dark-generic-heading: #79C0FF; +--syntax-dark-generic-inserted: #7EE787; +--syntax-dark-generic-output: #A5D6FF; +--syntax-dark-generic-prompt: #FF7B72; +--syntax-dark-generic-strong: #E6EDF3; +--syntax-dark-generic-subheading: #79C0FF; +--syntax-dark-generic-emphstrong: #E6EDF3; +--syntax-dark-generic-traceback: #FFA198; +--syntax-dark-text-whitespace: #E6EDF3; +--syntax-dark-keyword-declaration: #FF7B72; +--syntax-dark-keyword-namespace: #FF7B72; +--syntax-dark-keyword-pseudo: #FF7B72; +--syntax-dark-keyword-reserved: #FF7B72; +--syntax-dark-name-builtin-pseudo: #79C0FF; +--syntax-dark-literal-date: #A5D6FF; +--syntax-dark-literal-string-char: #A5D6FF; +--syntax-dark-literal-string-delimiter: #A5D6FF; +--syntax-dark-literal-string-doc: #A5D6FF; +--syntax-dark-literal-string-double: #A5D6FF; +--syntax-dark-literal-string-escape: #A5D6FF; +--syntax-dark-literal-string-heredoc: #A5D6FF; +--syntax-dark-literal-string-other: #A5D6FF; +--syntax-dark-literal-string-single: #A5D6FF; +--syntax-dark-literal-number-bin: #79C0FF; +--syntax-dark-literal-number-float: #79C0FF; +--syntax-dark-literal-number-hex: #79C0FF; +--syntax-dark-literal-number-integer: #79C0FF; +--syntax-dark-literal-number-integer-long: #79C0FF; +--syntax-dark-literal-number-oct: #79C0FF; +--syntax-dark-comment-hashbang: #8B949E; +--syntax-dark-comment-multiline: #8B949E; +--syntax-dark-comment-single: #8B949E; +--syntax-dark-comment-special: #8B949E; +} +html.dark .highlight .c, html.light .dark-code .highlight .c { color: var(--syntax-dark-comment) } +html.dark .highlight .err, html.light .dark-code .highlight .err { color: var(--syntax-dark-error) } +html.dark .highlight .esc, html.light .dark-code .highlight .esc { color: var(--syntax-dark-escape) } +html.dark .highlight .k, html.light .dark-code .highlight .k { color: var(--syntax-dark-keyword) } +html.dark .highlight .l, html.light .dark-code .highlight .l { color: var(--syntax-dark-literal) } +html.dark .highlight .o, html.light .dark-code .highlight .o { color: var(--syntax-dark-operator) } +html.dark .highlight .ch, html.light .dark-code .highlight .ch { color: var(--syntax-dark-comment-hashbang) } +html.dark .highlight .cm, html.light .dark-code .highlight .cm { color: var(--syntax-dark-comment-multiline) } +html.dark .highlight .cp, html.light .dark-code .highlight .cp { color: var(--syntax-dark-comment-preproc) } +html.dark .highlight .cpf, html.light .dark-code .highlight .cpf { color: var(--syntax-dark-comment-preprocfile) } +html.dark .highlight .c1, html.light .dark-code .highlight .c1 { color: var(--syntax-dark-comment-single) } +html.dark .highlight .cs, html.light .dark-code .highlight .cs { color: var(--syntax-dark-comment-special) } +html.dark .highlight .gd, html.light .dark-code .highlight .gd { color: var(--syntax-dark-generic-deleted) } +html.dark .highlight .ge, html.light .dark-code .highlight .ge { color: var(--syntax-dark-generic-emph); font-style: italic } +html.dark .highlight .ges, html.light .dark-code .highlight .ges { color: var(--syntax-dark-generic-emphstrong); font-weight: bold; font-style: italic } +html.dark .highlight .gr, html.light .dark-code .highlight .gr { color: var(--syntax-dark-generic-error) } +html.dark .highlight .gh, html.light .dark-code .highlight .gh { color: var(--syntax-dark-generic-heading); font-weight: bold } +html.dark .highlight .gi, html.light .dark-code .highlight .gi { color: var(--syntax-dark-generic-inserted) } +html.dark .highlight .go, html.light .dark-code .highlight .go { color: var(--syntax-dark-generic-output) } +html.dark .highlight .gp, html.light .dark-code .highlight .gp { color: var(--syntax-dark-generic-prompt) } +html.dark .highlight .gs, html.light .dark-code .highlight .gs { color: var(--syntax-dark-generic-strong); font-weight: bold } +html.dark .highlight .gu, html.light .dark-code .highlight .gu { color: var(--syntax-dark-generic-subheading) } +html.dark .highlight .gt, html.light .dark-code .highlight .gt { color: var(--syntax-dark-generic-traceback) } +html.dark .highlight .kc, html.light .dark-code .highlight .kc { color: var(--syntax-dark-keyword-constant) } +html.dark .highlight .kd, html.light .dark-code .highlight .kd { color: var(--syntax-dark-keyword-declaration) } +html.dark .highlight .kn, html.light .dark-code .highlight .kn { color: var(--syntax-dark-keyword-namespace) } +html.dark .highlight .kp, html.light .dark-code .highlight .kp { color: var(--syntax-dark-keyword-pseudo) } +html.dark .highlight .kr, html.light .dark-code .highlight .kr { color: var(--syntax-dark-keyword-reserved) } +html.dark .highlight .kt, html.light .dark-code .highlight .kt { color: var(--syntax-dark-keyword-type) } +html.dark .highlight .ld, html.light .dark-code .highlight .ld { color: var(--syntax-dark-literal-date) } +html.dark .highlight .m, html.light .dark-code .highlight .m { color: var(--syntax-dark-literal-number) } +html.dark .highlight .s, html.light .dark-code .highlight .s { color: var(--syntax-dark-literal-string) } +html.dark .highlight .na, html.light .dark-code .highlight .na { color: var(--syntax-dark-name-attribute) } +html.dark .highlight .nb, html.light .dark-code .highlight .nb { color: var(--syntax-dark-name-builtin) } +html.dark .highlight .nc, html.light .dark-code .highlight .nc { color: var(--syntax-dark-name-class) } +html.dark .highlight .no, html.light .dark-code .highlight .no { color: var(--syntax-dark-name-constant) } +html.dark .highlight .nd, html.light .dark-code .highlight .nd { color: var(--syntax-dark-name-decorator) } +html.dark .highlight .ni, html.light .dark-code .highlight .ni { color: var(--syntax-dark-name-entity) } +html.dark .highlight .ne, html.light .dark-code .highlight .ne { color: var(--syntax-dark-name-exception) } +html.dark .highlight .nf, html.light .dark-code .highlight .nf { color: var(--syntax-dark-name-function) } +html.dark .highlight .nl, html.light .dark-code .highlight .nl { color: var(--syntax-dark-name-label) } +html.dark .highlight .py, html.light .dark-code .highlight .py { color: var(--syntax-dark-name-property) } +html.dark .highlight .nt, html.light .dark-code .highlight .nt { color: var(--syntax-dark-name-tag) } +html.dark .highlight .ow, html.light .dark-code .highlight .ow { color: var(--syntax-dark-operator-word) } +html.dark .highlight .w, html.light .dark-code .highlight .w { color: var(--syntax-dark-text-whitespace) } +html.dark .highlight .mb, html.light .dark-code .highlight .mb { color: var(--syntax-dark-literal-number-bin) } +html.dark .highlight .mf, html.light .dark-code .highlight .mf { color: var(--syntax-dark-literal-number-float) } +html.dark .highlight .mh, html.light .dark-code .highlight .mh { color: var(--syntax-dark-literal-number-hex) } +html.dark .highlight .mi, html.light .dark-code .highlight .mi { color: var(--syntax-dark-literal-number-integer) } +html.dark .highlight .mo, html.light .dark-code .highlight .mo { color: var(--syntax-dark-literal-number-oct) } +html.dark .highlight .sa, html.light .dark-code .highlight .sa { color: var(--syntax-dark-literal-string-affix) } +html.dark .highlight .sb, html.light .dark-code .highlight .sb { color: var(--syntax-dark-literal-string-backtick) } +html.dark .highlight .sc, html.light .dark-code .highlight .sc { color: var(--syntax-dark-literal-string-char) } +html.dark .highlight .dl, html.light .dark-code .highlight .dl { color: var(--syntax-dark-literal-string-delimiter) } +html.dark .highlight .sd, html.light .dark-code .highlight .sd { color: var(--syntax-dark-literal-string-doc) } +html.dark .highlight .s2, html.light .dark-code .highlight .s2 { color: var(--syntax-dark-literal-string-double) } +html.dark .highlight .se, html.light .dark-code .highlight .se { color: var(--syntax-dark-literal-string-escape) } +html.dark .highlight .sh, html.light .dark-code .highlight .sh { color: var(--syntax-dark-literal-string-heredoc) } +html.dark .highlight .si, html.light .dark-code .highlight .si { color: var(--syntax-dark-literal-string-interpol) } +html.dark .highlight .sx, html.light .dark-code .highlight .sx { color: var(--syntax-dark-literal-string-other) } +html.dark .highlight .sr, html.light .dark-code .highlight .sr { color: var(--syntax-dark-literal-string-regex) } +html.dark .highlight .s1, html.light .dark-code .highlight .s1 { color: var(--syntax-dark-literal-string-single) } +html.dark .highlight .ss, html.light .dark-code .highlight .ss { color: var(--syntax-dark-literal-string-symbol) } +html.dark .highlight .bp, html.light .dark-code .highlight .bp { color: var(--syntax-dark-name-builtin-pseudo) } +html.dark .highlight .fm, html.light .dark-code .highlight .fm { color: var(--syntax-dark-name-function-magic) } +html.dark .highlight .vc, html.light .dark-code .highlight .vc { color: var(--syntax-dark-name-variable-class) } +html.dark .highlight .il, html.light .dark-code .highlight .il { color: var(--syntax-dark-literal-number-integer-long) } diff --git a/dev/doc/_static/searchtools.js b/dev/doc/_static/searchtools.js new file mode 100644 index 0000000..e29b1c7 --- /dev/null +++ b/dev/doc/_static/searchtools.js @@ -0,0 +1,693 @@ +/* + * Sphinx JavaScript utilities for the full-text search. + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename, kind] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +// Global search result kind enum, used by themes to style search results. +// prettier-ignore +class SearchResultKind { + static get index() { return "index"; } + static get object() { return "object"; } + static get text() { return "text"; } + static get title() { return "title"; } +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _escapeHTML = (text) => { + return text + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); +}; + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename, kind] = item; + + let listItem = document.createElement("li"); + // Add a class representing the item's type: + // can be used by a theme's CSS selector for styling + // See SearchResultKind for the class names. + listItem.classList.add(`kind-${kind}`); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = _escapeHTML(title); + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + ` (${_escapeHTML(descr)})`; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) + // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js + highlightTerms.forEach((term) => + _highlightText(listItem, term, "highlighted"), + ); + } else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor), + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) + // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js + highlightTerms.forEach((term) => + _highlightText(listItem, term, "highlighted"), + ); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.", + ); + else + Search.status.innerText = Documentation.ngettext( + "Search finished, found one page matching the search query.", + "Search finished, found ${resultCount} pages matching the search query.", + resultCount, + ).replace("${resultCount}", resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5, + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename, kind]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => + query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter((term) => term); // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString( + htmlString, + "text/html", + ); + for (const removalQuery of [".headerlink", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { + el.remove(); + }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector( + `[role="main"] ${anchor}`, + ); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.`, + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template.", + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.setAttribute("role", "list"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords set is from language_data.js + if (stopwords.has(queryTermLower) || queryTerm.match(/^\d+$/)) return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { + // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js + localStorage.setItem( + "sphinx_highlight_terms", + [...highlightTerms].join(" "), + ); + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: ( + query, + searchTerms, + excludedTerms, + highlightTerms, + objectTerms, + ) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename, kind]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if ( + title.toLowerCase().trim().includes(queryLower) + && queryLower.length >= title.length / 2 + ) { + for (const [file, id] of foundTitles) { + const score = Math.round( + (Scorer.title * queryLower.length) / title.length, + ); + const boost = titles[file] === title ? 1 : 0; // add a boost for document titles + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score + boost, + filenames[file], + SearchResultKind.title, + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && queryLower.length >= entry.length / 2) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round((100 * queryLower.length) / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + SearchResultKind.index, + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)), + ); + + // lookup as search terms in fulltext + normalResults.push( + ...Search.performTermsSearch(searchTerms, excludedTerms), + ); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result + .slice(0, 4) + .concat([result[5]]) + .map((v) => String(v)) + .join(","); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [ + searchQuery, + searchTerms, + excludedTerms, + highlightTerms, + objectTerms, + ] = Search._parseQuery(query); + const results = Search._performSearch( + searchQuery, + searchTerms, + excludedTerms, + highlightTerms, + objectTerms, + ); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4]; + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + SearchResultKind.object, + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => objectSearchCallback(prefix, array)), + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + // find documents, if any, containing the query word in their text/title term indices + // use Object.hasOwnProperty to avoid mismatching against prototype properties + const arr = [ + { + files: terms.hasOwnProperty(word) ? terms[word] : undefined, + score: Scorer.term, + }, + { + files: titleTerms.hasOwnProperty(word) ? titleTerms[word] : undefined, + score: Scorer.title, + }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, new Map()); + const fileScores = scoreMap.get(file); + fileScores.set(word, record.score); + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2, + ).length; + if ( + wordList.length !== searchTerms.size + && wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file + || titleTerms[term] === file + || (terms[term] || []).includes(file) + || (titleTerms[term] || []).includes(file), + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file).get(w))); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + SearchResultKind.text, + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = + top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/dev/doc/_static/shibuya.css b/dev/doc/_static/shibuya.css new file mode 100644 index 0000000..859edaa --- /dev/null +++ b/dev/doc/_static/shibuya.css @@ -0,0 +1,2 @@ +/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--container-6xl:72rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.relative{position:relative}.order-last{order:9999}.mx-auto{margin-inline:auto}.mr-3{margin-right:calc(var(--spacing) * 3)}.ml-1{margin-left:var(--spacing)}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline-flex{display:inline-flex}.table{display:table}.w-8{width:calc(var(--spacing) * 8)}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.max-w-6xl{max-width:var(--container-6xl)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.gap-1{gap:var(--spacing)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-1{padding-block:var(--spacing)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pt-12{padding-top:calc(var(--spacing) * 12)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}@media not all and (min-width:40rem){.max-sm\:max-w-full{max-width:100%}}@media (min-width:48rem){.md\:sticky{position:sticky}.md\:flex{display:flex}.md\:hidden{display:none}.md\:inline{display:inline}.md\:w-72{width:calc(var(--spacing) * 72)}.md\:shrink-0{flex-shrink:0}}@media (min-width:64rem){.lg\:absolute{position:absolute}.lg\:top-8{top:calc(var(--spacing) * 8)}.lg\:right-6{right:calc(var(--spacing) * 6)}}@media (min-width:80rem){.xl\:sticky{position:sticky}.xl\:top-16{top:calc(var(--spacing) * 16)}.xl\:right-12{right:calc(var(--spacing) * 12)}.xl\:hidden{display:none}.xl\:px-12{padding-inline:calc(var(--spacing) * 12)}.xl\:pl-0{padding-left:0}}@media print{.print\:hidden{display:none}.print\:pt-6{padding-top:calc(var(--spacing) * 6)}}}@font-face{font-family:Twemoji Country Flags;unicode-range:U+1F1E6-1F1FF,U+1F3F4,U+E0062-E0063,U+E0065,U+E0067,U+E006C,U+E006E,U+E0073-E0074,U+E0077,U+E007F;src:url(https://cdn.jsdelivr.net/npm/country-flag-emoji-polyfill@0.1/dist/TwemojiCountryFlags.woff2)format("woff2")}::selection{color:var(--accent-contrast);background-color:var(--accent-a8)}html{scroll-behavior:smooth}body{font-family:var(--sy-f-text);color:var(--sy-c-text)}.win{font-family:"Twemoji Country Flags", var(--sy-f-text)}h1,h2,h3,h4,h5{color:var(--sy-c-heading);font-family:var(--sy-f-heading)}strong,em{color:var(--sy-c-bold)}.sy-container{max-width:90rem}.sy-scrollbar{scrollbar-gutter:stable;overflow-y:auto}.sy-scrollbar::-webkit-scrollbar{width:.75rem;height:.75rem}.sy-scrollbar::-webkit-scrollbar-thumb{border-radius:10px}.sy-scrollbar::-webkit-scrollbar-track{background-color:#0000}.sy-scrollbar:hover::-webkit-scrollbar-thumb{background-color:var(--gray-a3);background-clip:content-box;border:3px solid #0000}iconify-icon{vertical-align:middle}.i-lucide{-webkit-mask:var(--icon-url) no-repeat;-webkit-mask:var(--icon-url) no-repeat;mask:var(--icon-url) no-repeat;vertical-align:middle;background-color:currentColor;width:1em;height:1em;font-style:normal;display:inline-block;-webkit-mask-size:100% 100%;mask-size:100% 100%}.theme-switch .theme-icon,[data-color-mode=auto] .theme-switch .theme-icon{--icon-url:var(--lucide-sun-moon-url)}[data-color-mode=light] .theme-switch .theme-icon{--icon-url:var(--lucide-sun-url)}[data-color-mode=dark] .theme-switch .theme-icon{--icon-url:var(--lucide-moon-url)}:root,.light,.light-theme{--tomato-1:#fffcfc;--tomato-2:#fff8f7;--tomato-3:#feebe7;--tomato-4:#ffdcd3;--tomato-5:#ffcdc2;--tomato-6:#fdbdaf;--tomato-7:#f5a898;--tomato-8:#ec8e7b;--tomato-9:#e54d2e;--tomato-10:#dd4425;--tomato-11:#d13415;--tomato-12:#5c271f}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--tomato-1:color(display-p3 .998 .989 .988);--tomato-2:color(display-p3 .994 .974 .969);--tomato-3:color(display-p3 .985 .924 .909);--tomato-4:color(display-p3 .996 .868 .835);--tomato-5:color(display-p3 .98 .812 .77);--tomato-6:color(display-p3 .953 .75 .698);--tomato-7:color(display-p3 .917 .673 .611);--tomato-8:color(display-p3 .875 .575 .502);--tomato-9:color(display-p3 .831 .345 .231);--tomato-10:color(display-p3 .802 .313 .2);--tomato-11:color(display-p3 .755 .259 .152);--tomato-12:color(display-p3 .335 .165 .132)}}}.dark,.dark-theme{--tomato-1:#181111;--tomato-2:#1f1513;--tomato-3:#391714;--tomato-4:#4e1511;--tomato-5:#5e1c16;--tomato-6:#6e2920;--tomato-7:#853a2d;--tomato-8:#ac4d39;--tomato-9:#e54d2e;--tomato-10:#ec6142;--tomato-11:#ff977d;--tomato-12:#fbd3cb}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--tomato-1:color(display-p3 .09 .068 .067);--tomato-2:color(display-p3 .115 .084 .076);--tomato-3:color(display-p3 .205 .097 .083);--tomato-4:color(display-p3 .282 .099 .077);--tomato-5:color(display-p3 .339 .129 .101);--tomato-6:color(display-p3 .398 .179 .141);--tomato-7:color(display-p3 .487 .245 .194);--tomato-8:color(display-p3 .629 .322 .248);--tomato-9:color(display-p3 .831 .345 .231);--tomato-10:color(display-p3 .862 .415 .298);--tomato-11:color(display-p3 1 .585 .455);--tomato-12:color(display-p3 .959 .833 .802)}}}:root,.light,.light-theme{--tomato-a1:#ff000003;--tomato-a2:#ff200008;--tomato-a3:#f52b0018;--tomato-a4:#ff35002c;--tomato-a5:#ff2e003d;--tomato-a6:#f92d0050;--tomato-a7:#e7280067;--tomato-a8:#db250084;--tomato-a9:#df2600d1;--tomato-a10:#d72400da;--tomato-a11:#cd2200ea;--tomato-a12:#460900e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--tomato-a1:color(display-p3 .675 .024 .024/.012);--tomato-a2:color(display-p3 .757 .145 .02/.032);--tomato-a3:color(display-p3 .831 .184 .012/.091);--tomato-a4:color(display-p3 .976 .192 .004/.165);--tomato-a5:color(display-p3 .918 .192 .004/.232);--tomato-a6:color(display-p3 .847 .173 .004/.302);--tomato-a7:color(display-p3 .788 .165 .004/.389);--tomato-a8:color(display-p3 .749 .153 .004/.499);--tomato-a9:color(display-p3 .78 .149 0/.769);--tomato-a10:color(display-p3 .757 .141 0/.8);--tomato-a11:color(display-p3 .755 .259 .152);--tomato-a12:color(display-p3 .335 .165 .132)}}}.dark,.dark-theme{--tomato-a1:#f1121208;--tomato-a2:#ff55330f;--tomato-a3:#ff35232b;--tomato-a4:#fd201142;--tomato-a5:#fe332153;--tomato-a6:#ff4f3864;--tomato-a7:#fd644a7d;--tomato-a8:#fe6d4ea7;--tomato-a9:#fe5431e4;--tomato-a10:#ff6847eb;--tomato-a11:#ff977d;--tomato-a12:#ffd6cefb}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--tomato-a1:color(display-p3 .973 .071 .071/.026);--tomato-a2:color(display-p3 .992 .376 .224/.051);--tomato-a3:color(display-p3 .996 .282 .176/.148);--tomato-a4:color(display-p3 1 .204 .118/.232);--tomato-a5:color(display-p3 1 .286 .192/.29);--tomato-a6:color(display-p3 1 .392 .278/.353);--tomato-a7:color(display-p3 1 .459 .349/.45);--tomato-a8:color(display-p3 1 .49 .369/.601);--tomato-a9:color(display-p3 1 .408 .267/.82);--tomato-a10:color(display-p3 1 .478 .341/.853);--tomato-a11:color(display-p3 1 .585 .455);--tomato-a12:color(display-p3 .959 .833 .802)}}}:root,.light,.light-theme{--red-1:#fffcfc;--red-2:#fff7f7;--red-3:#feebec;--red-4:#ffdbdc;--red-5:#ffcdce;--red-6:#fdbdbe;--red-7:#f4a9aa;--red-8:#eb8e90;--red-9:#e5484d;--red-10:#dc3e42;--red-11:#ce2c31;--red-12:#641723}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--red-1:color(display-p3 .998 .989 .988);--red-2:color(display-p3 .995 .971 .971);--red-3:color(display-p3 .985 .925 .925);--red-4:color(display-p3 .999 .866 .866);--red-5:color(display-p3 .984 .812 .811);--red-6:color(display-p3 .955 .751 .749);--red-7:color(display-p3 .915 .675 .672);--red-8:color(display-p3 .872 .575 .572);--red-9:color(display-p3 .83 .329 .324);--red-10:color(display-p3 .798 .294 .285);--red-11:color(display-p3 .744 .234 .222);--red-12:color(display-p3 .36 .115 .143)}}}.dark,.dark-theme{--red-1:#191111;--red-2:#201314;--red-3:#3b1219;--red-4:#500f1c;--red-5:#611623;--red-6:#72232d;--red-7:#8c333a;--red-8:#b54548;--red-9:#e5484d;--red-10:#ec5d5e;--red-11:#ff9592;--red-12:#ffd1d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--red-1:color(display-p3 .093 .068 .067);--red-2:color(display-p3 .118 .077 .079);--red-3:color(display-p3 .211 .081 .099);--red-4:color(display-p3 .287 .079 .113);--red-5:color(display-p3 .348 .11 .142);--red-6:color(display-p3 .414 .16 .183);--red-7:color(display-p3 .508 .224 .236);--red-8:color(display-p3 .659 .298 .297);--red-9:color(display-p3 .83 .329 .324);--red-10:color(display-p3 .861 .403 .387);--red-11:color(display-p3 1 .57 .55);--red-12:color(display-p3 .971 .826 .852)}}}:root,.light,.light-theme{--red-a1:#ff000003;--red-a2:#ff000008;--red-a3:#f3000d14;--red-a4:#ff000824;--red-a5:#ff000632;--red-a6:#f8000442;--red-a7:#df000356;--red-a8:#d2000571;--red-a9:#db0007b7;--red-a10:#d10005c1;--red-a11:#c40006d3;--red-a12:#55000de8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--red-a1:color(display-p3 .675 .024 .024/.012);--red-a2:color(display-p3 .863 .024 .024/.028);--red-a3:color(display-p3 .792 .008 .008/.075);--red-a4:color(display-p3 1 .008 .008/.134);--red-a5:color(display-p3 .918 .008 .008/.189);--red-a6:color(display-p3 .831 .02 .004/.251);--red-a7:color(display-p3 .741 .016 .004/.33);--red-a8:color(display-p3 .698 .012 .004/.428);--red-a9:color(display-p3 .749 .008 0/.675);--red-a10:color(display-p3 .714 .012 0/.714);--red-a11:color(display-p3 .744 .234 .222);--red-a12:color(display-p3 .36 .115 .143)}}}.dark,.dark-theme{--red-a1:#f4121209;--red-a2:#f22f3e11;--red-a3:#ff173f2d;--red-a4:#fe0a3b44;--red-a5:#ff204756;--red-a6:#ff3e5668;--red-a7:#ff536184;--red-a8:#ff5d61b0;--red-a9:#fe4e54e4;--red-a10:#ff6465eb;--red-a11:#ff9592;--red-a12:#ffd1d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--red-a1:color(display-p3 .984 .071 .071/.03);--red-a2:color(display-p3 .996 .282 .282/.055);--red-a3:color(display-p3 1 .169 .271/.156);--red-a4:color(display-p3 1 .118 .267/.236);--red-a5:color(display-p3 1 .212 .314/.303);--red-a6:color(display-p3 1 .318 .38/.374);--red-a7:color(display-p3 1 .4 .424/.475);--red-a8:color(display-p3 1 .431 .431/.635);--red-a9:color(display-p3 1 .388 .384/.82);--red-a10:color(display-p3 1 .463 .447/.853);--red-a11:color(display-p3 1 .57 .55);--red-a12:color(display-p3 .971 .826 .852)}}}:root,.light,.light-theme{--ruby-1:#fffcfd;--ruby-2:#fff7f8;--ruby-3:#feeaed;--ruby-4:#ffdce1;--ruby-5:#ffced6;--ruby-6:#f8bfc8;--ruby-7:#efacb8;--ruby-8:#e592a3;--ruby-9:#e54666;--ruby-10:#dc3b5d;--ruby-11:#ca244d;--ruby-12:#64172b}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--ruby-1:color(display-p3 .998 .989 .992);--ruby-2:color(display-p3 .995 .971 .974);--ruby-3:color(display-p3 .983 .92 .928);--ruby-4:color(display-p3 .987 .869 .885);--ruby-5:color(display-p3 .968 .817 .839);--ruby-6:color(display-p3 .937 .758 .786);--ruby-7:color(display-p3 .897 .685 .721);--ruby-8:color(display-p3 .851 .588 .639);--ruby-9:color(display-p3 .83 .323 .408);--ruby-10:color(display-p3 .795 .286 .375);--ruby-11:color(display-p3 .728 .211 .311);--ruby-12:color(display-p3 .36 .115 .171)}}}.dark,.dark-theme{--ruby-1:#191113;--ruby-2:#1e1517;--ruby-3:#3a141e;--ruby-4:#4e1325;--ruby-5:#5e1a2e;--ruby-6:#6f2539;--ruby-7:#883447;--ruby-8:#b3445a;--ruby-9:#e54666;--ruby-10:#ec5a72;--ruby-11:#ff949d;--ruby-12:#fed2e1}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--ruby-1:color(display-p3 .093 .068 .074);--ruby-2:color(display-p3 .113 .083 .089);--ruby-3:color(display-p3 .208 .088 .117);--ruby-4:color(display-p3 .279 .092 .147);--ruby-5:color(display-p3 .337 .12 .18);--ruby-6:color(display-p3 .401 .166 .223);--ruby-7:color(display-p3 .495 .224 .281);--ruby-8:color(display-p3 .652 .295 .359);--ruby-9:color(display-p3 .83 .323 .408);--ruby-10:color(display-p3 .857 .392 .455);--ruby-11:color(display-p3 1 .57 .59);--ruby-12:color(display-p3 .968 .83 .88)}}}:root,.light,.light-theme{--ruby-a1:#ff005503;--ruby-a2:#ff002008;--ruby-a3:#f3002515;--ruby-a4:#ff002523;--ruby-a5:#ff002a31;--ruby-a6:#e4002440;--ruby-a7:#ce002553;--ruby-a8:#c300286d;--ruby-a9:#db002cb9;--ruby-a10:#d2002cc4;--ruby-a11:#c10030db;--ruby-a12:#550016e8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--ruby-a1:color(display-p3 .675 .024 .349/.012);--ruby-a2:color(display-p3 .863 .024 .024/.028);--ruby-a3:color(display-p3 .804 .008 .11/.079);--ruby-a4:color(display-p3 .91 .008 .125/.13);--ruby-a5:color(display-p3 .831 .004 .133/.185);--ruby-a6:color(display-p3 .745 .004 .118/.244);--ruby-a7:color(display-p3 .678 .004 .114/.314);--ruby-a8:color(display-p3 .639 .004 .125/.412);--ruby-a9:color(display-p3 .753 0 .129/.679);--ruby-a10:color(display-p3 .714 0 .125/.714);--ruby-a11:color(display-p3 .728 .211 .311);--ruby-a12:color(display-p3 .36 .115 .171)}}}.dark,.dark-theme{--ruby-a1:#f4124a09;--ruby-a2:#fe5a7f0e;--ruby-a3:#ff235d2c;--ruby-a4:#fd195e42;--ruby-a5:#fe2d6b53;--ruby-a6:#ff447665;--ruby-a7:#ff577d80;--ruby-a8:#ff5c7cae;--ruby-a9:#fe4c70e4;--ruby-a10:#ff617beb;--ruby-a11:#ff949d;--ruby-a12:#ffd3e2fe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--ruby-a1:color(display-p3 .984 .071 .329/.03);--ruby-a2:color(display-p3 .992 .376 .529/.051);--ruby-a3:color(display-p3 .996 .196 .404/.152);--ruby-a4:color(display-p3 1 .173 .416/.227);--ruby-a5:color(display-p3 1 .259 .459/.29);--ruby-a6:color(display-p3 1 .341 .506/.358);--ruby-a7:color(display-p3 1 .412 .541/.458);--ruby-a8:color(display-p3 1 .431 .537/.627);--ruby-a9:color(display-p3 1 .376 .482/.82);--ruby-a10:color(display-p3 1 .447 .522/.849);--ruby-a11:color(display-p3 1 .57 .59);--ruby-a12:color(display-p3 .968 .83 .88)}}}:root,.light,.light-theme{--crimson-1:#fffcfd;--crimson-2:#fef7f9;--crimson-3:#ffe9f0;--crimson-4:#fedce7;--crimson-5:#facedd;--crimson-6:#f3bed1;--crimson-7:#eaacc3;--crimson-8:#e093b2;--crimson-9:#e93d82;--crimson-10:#df3478;--crimson-11:#cb1d63;--crimson-12:#621639}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--crimson-1:color(display-p3 .998 .989 .992);--crimson-2:color(display-p3 .991 .969 .976);--crimson-3:color(display-p3 .987 .917 .941);--crimson-4:color(display-p3 .975 .866 .904);--crimson-5:color(display-p3 .953 .813 .864);--crimson-6:color(display-p3 .921 .755 .817);--crimson-7:color(display-p3 .88 .683 .761);--crimson-8:color(display-p3 .834 .592 .694);--crimson-9:color(display-p3 .843 .298 .507);--crimson-10:color(display-p3 .807 .266 .468);--crimson-11:color(display-p3 .731 .195 .388);--crimson-12:color(display-p3 .352 .111 .221)}}}.dark,.dark-theme{--crimson-1:#191114;--crimson-2:#201318;--crimson-3:#381525;--crimson-4:#4d122f;--crimson-5:#5c1839;--crimson-6:#6d2545;--crimson-7:#873356;--crimson-8:#b0436e;--crimson-9:#e93d82;--crimson-10:#ee518a;--crimson-11:#ff92ad;--crimson-12:#fdd3e8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--crimson-1:color(display-p3 .093 .068 .078);--crimson-2:color(display-p3 .117 .078 .095);--crimson-3:color(display-p3 .203 .091 .143);--crimson-4:color(display-p3 .277 .087 .182);--crimson-5:color(display-p3 .332 .115 .22);--crimson-6:color(display-p3 .394 .162 .268);--crimson-7:color(display-p3 .489 .222 .336);--crimson-8:color(display-p3 .638 .289 .429);--crimson-9:color(display-p3 .843 .298 .507);--crimson-10:color(display-p3 .864 .364 .539);--crimson-11:color(display-p3 1 .56 .66);--crimson-12:color(display-p3 .966 .834 .906)}}}:root,.light,.light-theme{--crimson-a1:#ff005503;--crimson-a2:#e0004008;--crimson-a3:#ff005216;--crimson-a4:#f8005123;--crimson-a5:#e5004f31;--crimson-a6:#d0004b41;--crimson-a7:#bf004753;--crimson-a8:#b6004a6c;--crimson-a9:#e2005bc2;--crimson-a10:#d70056cb;--crimson-a11:#c4004fe2;--crimson-a12:#530026e9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--crimson-a1:color(display-p3 .675 .024 .349/.012);--crimson-a2:color(display-p3 .757 .02 .267/.032);--crimson-a3:color(display-p3 .859 .008 .294/.083);--crimson-a4:color(display-p3 .827 .008 .298/.134);--crimson-a5:color(display-p3 .753 .008 .275/.189);--crimson-a6:color(display-p3 .682 .004 .247/.244);--crimson-a7:color(display-p3 .62 .004 .251/.318);--crimson-a8:color(display-p3 .6 .004 .251/.408);--crimson-a9:color(display-p3 .776 0 .298/.702);--crimson-a10:color(display-p3 .737 0 .275/.734);--crimson-a11:color(display-p3 .731 .195 .388);--crimson-a12:color(display-p3 .352 .111 .221)}}}.dark,.dark-theme{--crimson-a1:#f4126709;--crimson-a2:#f22f7a11;--crimson-a3:#fe2a8b2a;--crimson-a4:#fd158741;--crimson-a5:#fd278f51;--crimson-a6:#fe459763;--crimson-a7:#fd559b7f;--crimson-a8:#fe5b9bab;--crimson-a9:#fe418de8;--crimson-a10:#ff5693ed;--crimson-a11:#ff92ad;--crimson-a12:#ffd5eafd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--crimson-a1:color(display-p3 .984 .071 .463/.03);--crimson-a2:color(display-p3 .996 .282 .569/.055);--crimson-a3:color(display-p3 .996 .227 .573/.148);--crimson-a4:color(display-p3 1 .157 .569/.227);--crimson-a5:color(display-p3 1 .231 .604/.286);--crimson-a6:color(display-p3 1 .337 .643/.349);--crimson-a7:color(display-p3 1 .416 .663/.454);--crimson-a8:color(display-p3 .996 .427 .651/.614);--crimson-a9:color(display-p3 1 .345 .596/.832);--crimson-a10:color(display-p3 1 .42 .62/.853);--crimson-a11:color(display-p3 1 .56 .66);--crimson-a12:color(display-p3 .966 .834 .906)}}}:root,.light,.light-theme{--pink-1:#fffcfe;--pink-2:#fef7fb;--pink-3:#fee9f5;--pink-4:#fbdcef;--pink-5:#f6cee7;--pink-6:#efbfdd;--pink-7:#e7acd0;--pink-8:#dd93c2;--pink-9:#d6409f;--pink-10:#cf3897;--pink-11:#c2298a;--pink-12:#651249}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--pink-1:color(display-p3 .998 .989 .996);--pink-2:color(display-p3 .992 .97 .985);--pink-3:color(display-p3 .981 .917 .96);--pink-4:color(display-p3 .963 .867 .932);--pink-5:color(display-p3 .939 .815 .899);--pink-6:color(display-p3 .907 .756 .859);--pink-7:color(display-p3 .869 .683 .81);--pink-8:color(display-p3 .825 .59 .751);--pink-9:color(display-p3 .775 .297 .61);--pink-10:color(display-p3 .748 .27 .581);--pink-11:color(display-p3 .698 .219 .528);--pink-12:color(display-p3 .363 .101 .279)}}}.dark,.dark-theme{--pink-1:#191117;--pink-2:#21121d;--pink-3:#37172f;--pink-4:#4b143d;--pink-5:#591c47;--pink-6:#692955;--pink-7:#833869;--pink-8:#a84885;--pink-9:#d6409f;--pink-10:#de51a8;--pink-11:#ff8dcc;--pink-12:#fdd1ea}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--pink-1:color(display-p3 .093 .068 .089);--pink-2:color(display-p3 .121 .073 .11);--pink-3:color(display-p3 .198 .098 .179);--pink-4:color(display-p3 .271 .095 .231);--pink-5:color(display-p3 .32 .127 .273);--pink-6:color(display-p3 .382 .177 .326);--pink-7:color(display-p3 .477 .238 .405);--pink-8:color(display-p3 .612 .304 .51);--pink-9:color(display-p3 .775 .297 .61);--pink-10:color(display-p3 .808 .356 .645);--pink-11:color(display-p3 1 .535 .78);--pink-12:color(display-p3 .964 .826 .912)}}}:root,.light,.light-theme{--pink-a1:#ff00aa03;--pink-a2:#e0008008;--pink-a3:#f4008c16;--pink-a4:#e2008b23;--pink-a5:#d1008331;--pink-a6:#c0007840;--pink-a7:#b6006f53;--pink-a8:#af006f6c;--pink-a9:#c8007fbf;--pink-a10:#c2007ac7;--pink-a11:#b60074d6;--pink-a12:#59003bed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--pink-a1:color(display-p3 .675 .024 .675/.012);--pink-a2:color(display-p3 .757 .02 .51/.032);--pink-a3:color(display-p3 .765 .008 .529/.083);--pink-a4:color(display-p3 .737 .008 .506/.134);--pink-a5:color(display-p3 .663 .004 .451/.185);--pink-a6:color(display-p3 .616 .004 .424/.244);--pink-a7:color(display-p3 .596 .004 .412/.318);--pink-a8:color(display-p3 .573 .004 .404/.412);--pink-a9:color(display-p3 .682 0 .447/.702);--pink-a10:color(display-p3 .655 0 .424/.73);--pink-a11:color(display-p3 .698 .219 .528);--pink-a12:color(display-p3 .363 .101 .279)}}}.dark,.dark-theme{--pink-a1:#f412bc09;--pink-a2:#f420bb12;--pink-a3:#fe37cc29;--pink-a4:#fc1ec43f;--pink-a5:#fd35c24e;--pink-a6:#fd51c75f;--pink-a7:#fd62c87b;--pink-a8:#ff68c8a2;--pink-a9:#fe49bcd4;--pink-a10:#ff5cc0dc;--pink-a11:#ff8dcc;--pink-a12:#ffd3ecfd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--pink-a1:color(display-p3 .984 .071 .855/.03);--pink-a2:color(display-p3 1 .2 .8/.059);--pink-a3:color(display-p3 1 .294 .886/.139);--pink-a4:color(display-p3 1 .192 .82/.219);--pink-a5:color(display-p3 1 .282 .827/.274);--pink-a6:color(display-p3 1 .396 .835/.337);--pink-a7:color(display-p3 1 .459 .831/.442);--pink-a8:color(display-p3 1 .478 .827/.585);--pink-a9:color(display-p3 1 .373 .784/.761);--pink-a10:color(display-p3 1 .435 .792/.795);--pink-a11:color(display-p3 1 .535 .78);--pink-a12:color(display-p3 .964 .826 .912)}}}:root,.light,.light-theme{--plum-1:#fefcff;--plum-2:#fdf7fd;--plum-3:#fbebfb;--plum-4:#f7def8;--plum-5:#f2d1f3;--plum-6:#e9c2ec;--plum-7:#deade3;--plum-8:#cf91d8;--plum-9:#ab4aba;--plum-10:#a144af;--plum-11:#953ea3;--plum-12:#53195d}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--plum-1:color(display-p3 .995 .988 .999);--plum-2:color(display-p3 .988 .971 .99);--plum-3:color(display-p3 .973 .923 .98);--plum-4:color(display-p3 .953 .875 .966);--plum-5:color(display-p3 .926 .825 .945);--plum-6:color(display-p3 .89 .765 .916);--plum-7:color(display-p3 .84 .686 .877);--plum-8:color(display-p3 .775 .58 .832);--plum-9:color(display-p3 .624 .313 .708);--plum-10:color(display-p3 .587 .29 .667);--plum-11:color(display-p3 .543 .263 .619);--plum-12:color(display-p3 .299 .114 .352)}}}.dark,.dark-theme{--plum-1:#181118;--plum-2:#201320;--plum-3:#351a35;--plum-4:#451d47;--plum-5:#512454;--plum-6:#5e3061;--plum-7:#734079;--plum-8:#92549c;--plum-9:#ab4aba;--plum-10:#b658c4;--plum-11:#e796f3;--plum-12:#f4d4f4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--plum-1:color(display-p3 .09 .068 .092);--plum-2:color(display-p3 .118 .077 .121);--plum-3:color(display-p3 .192 .105 .202);--plum-4:color(display-p3 .25 .121 .271);--plum-5:color(display-p3 .293 .152 .319);--plum-6:color(display-p3 .343 .198 .372);--plum-7:color(display-p3 .424 .262 .461);--plum-8:color(display-p3 .54 .341 .595);--plum-9:color(display-p3 .624 .313 .708);--plum-10:color(display-p3 .666 .365 .748);--plum-11:color(display-p3 .86 .602 .933);--plum-12:color(display-p3 .936 .836 .949)}}}:root,.light,.light-theme{--plum-a1:#aa00ff03;--plum-a2:#c000c008;--plum-a3:#cc00cc14;--plum-a4:#c200c921;--plum-a5:#b700bd2e;--plum-a6:#a400b03d;--plum-a7:#9900a852;--plum-a8:#9000a56e;--plum-a9:#89009eb5;--plum-a10:#7f0092bb;--plum-a11:#730086c1;--plum-a12:#40004be6}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--plum-a1:color(display-p3 .675 .024 1/.012);--plum-a2:color(display-p3 .58 .024 .58/.028);--plum-a3:color(display-p3 .655 .008 .753/.079);--plum-a4:color(display-p3 .627 .008 .722/.126);--plum-a5:color(display-p3 .58 .004 .69/.177);--plum-a6:color(display-p3 .537 .004 .655/.236);--plum-a7:color(display-p3 .49 .004 .616/.314);--plum-a8:color(display-p3 .471 .004 .6/.42);--plum-a9:color(display-p3 .451 0 .576/.687);--plum-a10:color(display-p3 .42 0 .529/.71);--plum-a11:color(display-p3 .543 .263 .619);--plum-a12:color(display-p3 .299 .114 .352)}}}.dark,.dark-theme{--plum-a1:#f112f108;--plum-a2:#f22ff211;--plum-a3:#fd4cfd27;--plum-a4:#f646ff3a;--plum-a5:#f455ff48;--plum-a6:#f66dff56;--plum-a7:#f07cfd70;--plum-a8:#ee84ff95;--plum-a9:#e961feb6;--plum-a10:#ed70ffc0;--plum-a11:#f19cfef3;--plum-a12:#feddfef4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--plum-a1:color(display-p3 .973 .071 .973/.026);--plum-a2:color(display-p3 .933 .267 1/.059);--plum-a3:color(display-p3 .918 .333 .996/.148);--plum-a4:color(display-p3 .91 .318 1/.219);--plum-a5:color(display-p3 .914 .388 1/.269);--plum-a6:color(display-p3 .906 .463 1/.328);--plum-a7:color(display-p3 .906 .529 1/.425);--plum-a8:color(display-p3 .906 .553 1/.568);--plum-a9:color(display-p3 .875 .427 1/.69);--plum-a10:color(display-p3 .886 .471 .996/.732);--plum-a11:color(display-p3 .86 .602 .933);--plum-a12:color(display-p3 .936 .836 .949)}}}:root,.light,.light-theme{--purple-1:#fefcfe;--purple-2:#fbf7fe;--purple-3:#f7edfe;--purple-4:#f2e2fc;--purple-5:#ead5f9;--purple-6:#e0c4f4;--purple-7:#d1afec;--purple-8:#be93e4;--purple-9:#8e4ec6;--purple-10:#8347b9;--purple-11:#8145b5;--purple-12:#402060}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--purple-1:color(display-p3 .995 .988 .996);--purple-2:color(display-p3 .983 .971 .993);--purple-3:color(display-p3 .963 .931 .989);--purple-4:color(display-p3 .937 .888 .981);--purple-5:color(display-p3 .904 .837 .966);--purple-6:color(display-p3 .86 .774 .942);--purple-7:color(display-p3 .799 .69 .91);--purple-8:color(display-p3 .719 .583 .874);--purple-9:color(display-p3 .523 .318 .751);--purple-10:color(display-p3 .483 .289 .7);--purple-11:color(display-p3 .473 .281 .687);--purple-12:color(display-p3 .234 .132 .363)}}}.dark,.dark-theme{--purple-1:#18111b;--purple-2:#1e1523;--purple-3:#301c3b;--purple-4:#3d224e;--purple-5:#48295c;--purple-6:#54346b;--purple-7:#664282;--purple-8:#8457aa;--purple-9:#8e4ec6;--purple-10:#9a5cd0;--purple-11:#d19dff;--purple-12:#ecd9fa}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--purple-1:color(display-p3 .09 .068 .103);--purple-2:color(display-p3 .113 .082 .134);--purple-3:color(display-p3 .175 .112 .224);--purple-4:color(display-p3 .224 .137 .297);--purple-5:color(display-p3 .264 .167 .349);--purple-6:color(display-p3 .311 .208 .406);--purple-7:color(display-p3 .381 .266 .496);--purple-8:color(display-p3 .49 .349 .649);--purple-9:color(display-p3 .523 .318 .751);--purple-10:color(display-p3 .57 .373 .791);--purple-11:color(display-p3 .8 .62 1);--purple-12:color(display-p3 .913 .854 .971)}}}:root,.light,.light-theme{--purple-a1:#aa00aa03;--purple-a2:#8000e008;--purple-a3:#8e00f112;--purple-a4:#8d00e51d;--purple-a5:#8000db2a;--purple-a6:#7a01d03b;--purple-a7:#6d00c350;--purple-a8:#6600c06c;--purple-a9:#5c00adb1;--purple-a10:#53009eb8;--purple-a11:#52009aba;--purple-a12:#250049df}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--purple-a1:color(display-p3 .675 .024 .675/.012);--purple-a2:color(display-p3 .443 .024 .722/.028);--purple-a3:color(display-p3 .506 .008 .835/.071);--purple-a4:color(display-p3 .451 .004 .831/.114);--purple-a5:color(display-p3 .431 .004 .788/.165);--purple-a6:color(display-p3 .384 .004 .745/.228);--purple-a7:color(display-p3 .357 .004 .71/.31);--purple-a8:color(display-p3 .322 .004 .702/.416);--purple-a9:color(display-p3 .298 0 .639/.683);--purple-a10:color(display-p3 .271 0 .58/.71);--purple-a11:color(display-p3 .473 .281 .687);--purple-a12:color(display-p3 .234 .132 .363)}}}.dark,.dark-theme{--purple-a1:#b412f90b;--purple-a2:#b744f714;--purple-a3:#c150ff2d;--purple-a4:#bb53fd42;--purple-a5:#be5cfd51;--purple-a6:#c16dfd61;--purple-a7:#c378fd7a;--purple-a8:#c47effa4;--purple-a9:#b661ffc2;--purple-a10:#bc6fffcd;--purple-a11:#d19dff;--purple-a12:#f1ddfffa}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--purple-a1:color(display-p3 .686 .071 .996/.038);--purple-a2:color(display-p3 .722 .286 .996/.072);--purple-a3:color(display-p3 .718 .349 .996/.169);--purple-a4:color(display-p3 .702 .353 1/.248);--purple-a5:color(display-p3 .718 .404 1/.303);--purple-a6:color(display-p3 .733 .455 1/.366);--purple-a7:color(display-p3 .753 .506 1/.458);--purple-a8:color(display-p3 .749 .522 1/.622);--purple-a9:color(display-p3 .686 .408 1/.736);--purple-a10:color(display-p3 .71 .459 1/.778);--purple-a11:color(display-p3 .8 .62 1);--purple-a12:color(display-p3 .913 .854 .971)}}}:root,.light,.light-theme{--violet-1:#fdfcfe;--violet-2:#faf8ff;--violet-3:#f4f0fe;--violet-4:#ebe4ff;--violet-5:#e1d9ff;--violet-6:#d4cafe;--violet-7:#c2b5f5;--violet-8:#aa99ec;--violet-9:#6e56cf;--violet-10:#654dc4;--violet-11:#6550b9;--violet-12:#2f265f}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--violet-1:color(display-p3 .991 .988 .995);--violet-2:color(display-p3 .978 .974 .998);--violet-3:color(display-p3 .953 .943 .993);--violet-4:color(display-p3 .916 .897 1);--violet-5:color(display-p3 .876 .851 1);--violet-6:color(display-p3 .825 .793 .981);--violet-7:color(display-p3 .752 .712 .943);--violet-8:color(display-p3 .654 .602 .902);--violet-9:color(display-p3 .417 .341 .784);--violet-10:color(display-p3 .381 .306 .741);--violet-11:color(display-p3 .383 .317 .702);--violet-12:color(display-p3 .179 .15 .359)}}}.dark,.dark-theme{--violet-1:#14121f;--violet-2:#1b1525;--violet-3:#291f43;--violet-4:#33255b;--violet-5:#3c2e69;--violet-6:#473876;--violet-7:#56468b;--violet-8:#6958ad;--violet-9:#6e56cf;--violet-10:#7d66d9;--violet-11:#baa7ff;--violet-12:#e2ddfe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--violet-1:color(display-p3 .077 .071 .118);--violet-2:color(display-p3 .101 .084 .141);--violet-3:color(display-p3 .154 .123 .256);--violet-4:color(display-p3 .191 .148 .345);--violet-5:color(display-p3 .226 .182 .396);--violet-6:color(display-p3 .269 .223 .449);--violet-7:color(display-p3 .326 .277 .53);--violet-8:color(display-p3 .399 .346 .656);--violet-9:color(display-p3 .417 .341 .784);--violet-10:color(display-p3 .477 .402 .823);--violet-11:color(display-p3 .72 .65 1);--violet-12:color(display-p3 .883 .867 .986)}}}:root,.light,.light-theme{--violet-a1:#5500aa03;--violet-a2:#4900ff07;--violet-a3:#4400ee0f;--violet-a4:#4300ff1b;--violet-a5:#3600ff26;--violet-a6:#3100fb35;--violet-a7:#2d01dd4a;--violet-a8:#2b00d066;--violet-a9:#2400b7a9;--violet-a10:#2300abb2;--violet-a11:#1f0099af;--violet-a12:#0b0043d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--violet-a1:color(display-p3 .349 .024 .675/.012);--violet-a2:color(display-p3 .161 .024 .863/.028);--violet-a3:color(display-p3 .204 .004 .871/.059);--violet-a4:color(display-p3 .196 .004 1/.102);--violet-a5:color(display-p3 .165 .008 1/.15);--violet-a6:color(display-p3 .153 .004 .906/.208);--violet-a7:color(display-p3 .141 .004 .796/.287);--violet-a8:color(display-p3 .133 .004 .753/.397);--violet-a9:color(display-p3 .114 0 .675/.659);--violet-a10:color(display-p3 .11 0 .627/.695);--violet-a11:color(display-p3 .383 .317 .702);--violet-a12:color(display-p3 .179 .15 .359)}}}.dark,.dark-theme{--violet-a1:#4422ff0f;--violet-a2:#853ff916;--violet-a3:#8354fe36;--violet-a4:#7d51fd50;--violet-a5:#845ffd5f;--violet-a6:#8f6cfd6d;--violet-a7:#9879ff83;--violet-a8:#977dfea8;--violet-a9:#8668ffcc;--violet-a10:#9176fed7;--violet-a11:#baa7ff;--violet-a12:#e3defffe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--violet-a1:color(display-p3 .282 .141 .996/.055);--violet-a2:color(display-p3 .51 .263 1/.08);--violet-a3:color(display-p3 .494 .337 .996/.202);--violet-a4:color(display-p3 .49 .345 1/.299);--violet-a5:color(display-p3 .525 .392 1/.353);--violet-a6:color(display-p3 .569 .455 1/.408);--violet-a7:color(display-p3 .588 .494 1/.496);--violet-a8:color(display-p3 .596 .51 1/.631);--violet-a9:color(display-p3 .522 .424 1/.769);--violet-a10:color(display-p3 .576 .482 1/.811);--violet-a11:color(display-p3 .72 .65 1);--violet-a12:color(display-p3 .883 .867 .986)}}}:root,.light,.light-theme{--iris-1:#fdfdff;--iris-2:#f8f8ff;--iris-3:#f0f1fe;--iris-4:#e6e7ff;--iris-5:#dadcff;--iris-6:#cbcdff;--iris-7:#b8baf8;--iris-8:#9b9ef0;--iris-9:#5b5bd6;--iris-10:#5151cd;--iris-11:#5753c6;--iris-12:#272962}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--iris-1:color(display-p3 .992 .992 .999);--iris-2:color(display-p3 .972 .973 .998);--iris-3:color(display-p3 .943 .945 .992);--iris-4:color(display-p3 .902 .906 1);--iris-5:color(display-p3 .857 .861 1);--iris-6:color(display-p3 .799 .805 .987);--iris-7:color(display-p3 .721 .727 .955);--iris-8:color(display-p3 .61 .619 .918);--iris-9:color(display-p3 .357 .357 .81);--iris-10:color(display-p3 .318 .318 .774);--iris-11:color(display-p3 .337 .326 .748);--iris-12:color(display-p3 .154 .161 .371)}}}.dark,.dark-theme{--iris-1:#13131e;--iris-2:#171625;--iris-3:#202248;--iris-4:#262a65;--iris-5:#303374;--iris-6:#3d3e82;--iris-7:#4a4a95;--iris-8:#5958b1;--iris-9:#5b5bd6;--iris-10:#6e6ade;--iris-11:#b1a9ff;--iris-12:#e0dffe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--iris-1:color(display-p3 .075 .075 .114);--iris-2:color(display-p3 .089 .086 .14);--iris-3:color(display-p3 .128 .134 .272);--iris-4:color(display-p3 .153 .165 .382);--iris-5:color(display-p3 .192 .201 .44);--iris-6:color(display-p3 .239 .241 .491);--iris-7:color(display-p3 .291 .289 .565);--iris-8:color(display-p3 .35 .345 .673);--iris-9:color(display-p3 .357 .357 .81);--iris-10:color(display-p3 .428 .416 .843);--iris-11:color(display-p3 .685 .662 1);--iris-12:color(display-p3 .878 .875 .986)}}}:root,.light,.light-theme{--iris-a1:#0000ff02;--iris-a2:#0000ff07;--iris-a3:#0011ee0f;--iris-a4:#000bff19;--iris-a5:#000eff25;--iris-a6:#000aff34;--iris-a7:#0008e647;--iris-a8:#0008d964;--iris-a9:#0000c0a4;--iris-a10:#0000b6ae;--iris-a11:#0600abac;--iris-a12:#000246d8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--iris-a1:color(display-p3 .02 .02 1/.008);--iris-a2:color(display-p3 .024 .024 .863/.028);--iris-a3:color(display-p3 .004 .071 .871/.059);--iris-a4:color(display-p3 .012 .051 1/.099);--iris-a5:color(display-p3 .008 .035 1/.142);--iris-a6:color(display-p3 0 .02 .941/.2);--iris-a7:color(display-p3 .004 .02 .847/.279);--iris-a8:color(display-p3 .004 .024 .788/.389);--iris-a9:color(display-p3 0 0 .706/.644);--iris-a10:color(display-p3 0 0 .667/.683);--iris-a11:color(display-p3 .337 .326 .748);--iris-a12:color(display-p3 .154 .161 .371)}}}.dark,.dark-theme{--iris-a1:#3636fe0e;--iris-a2:#564bf916;--iris-a3:#525bff3b;--iris-a4:#4d58ff5a;--iris-a5:#5b62fd6b;--iris-a6:#6d6ffd7a;--iris-a7:#7777fe8e;--iris-a8:#7b7afeac;--iris-a9:#6a6afed4;--iris-a10:#7d79ffdc;--iris-a11:#b1a9ff;--iris-a12:#e1e0fffe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--iris-a1:color(display-p3 .224 .224 .992/.051);--iris-a2:color(display-p3 .361 .314 1/.08);--iris-a3:color(display-p3 .357 .373 1/.219);--iris-a4:color(display-p3 .325 .361 1/.337);--iris-a5:color(display-p3 .38 .4 1/.4);--iris-a6:color(display-p3 .447 .447 1/.454);--iris-a7:color(display-p3 .486 .486 1/.534);--iris-a8:color(display-p3 .502 .494 1/.652);--iris-a9:color(display-p3 .431 .431 1/.799);--iris-a10:color(display-p3 .502 .486 1/.832);--iris-a11:color(display-p3 .685 .662 1);--iris-a12:color(display-p3 .878 .875 .986)}}}:root,.light,.light-theme{--indigo-1:#fdfdfe;--indigo-2:#f7f9ff;--indigo-3:#edf2fe;--indigo-4:#e1e9ff;--indigo-5:#d2deff;--indigo-6:#c1d0ff;--indigo-7:#abbdf9;--indigo-8:#8da4ef;--indigo-9:#3e63dd;--indigo-10:#3358d4;--indigo-11:#3a5bc7;--indigo-12:#1f2d5c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--indigo-1:color(display-p3 .992 .992 .996);--indigo-2:color(display-p3 .971 .977 .998);--indigo-3:color(display-p3 .933 .948 .992);--indigo-4:color(display-p3 .885 .914 1);--indigo-5:color(display-p3 .831 .87 1);--indigo-6:color(display-p3 .767 .814 .995);--indigo-7:color(display-p3 .685 .74 .957);--indigo-8:color(display-p3 .569 .639 .916);--indigo-9:color(display-p3 .276 .384 .837);--indigo-10:color(display-p3 .234 .343 .801);--indigo-11:color(display-p3 .256 .354 .755);--indigo-12:color(display-p3 .133 .175 .348)}}}.dark,.dark-theme{--indigo-1:#11131f;--indigo-2:#141726;--indigo-3:#182449;--indigo-4:#1d2e62;--indigo-5:#253974;--indigo-6:#304384;--indigo-7:#3a4f97;--indigo-8:#435db1;--indigo-9:#3e63dd;--indigo-10:#5472e4;--indigo-11:#9eb1ff;--indigo-12:#d6e1ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--indigo-1:color(display-p3 .068 .074 .118);--indigo-2:color(display-p3 .081 .089 .144);--indigo-3:color(display-p3 .105 .141 .275);--indigo-4:color(display-p3 .129 .18 .369);--indigo-5:color(display-p3 .163 .22 .439);--indigo-6:color(display-p3 .203 .262 .5);--indigo-7:color(display-p3 .245 .309 .575);--indigo-8:color(display-p3 .285 .362 .674);--indigo-9:color(display-p3 .276 .384 .837);--indigo-10:color(display-p3 .354 .445 .866);--indigo-11:color(display-p3 .63 .69 1);--indigo-12:color(display-p3 .848 .881 .99)}}}:root,.light,.light-theme{--indigo-a1:#00008002;--indigo-a2:#0040ff08;--indigo-a3:#0047f112;--indigo-a4:#0044ff1e;--indigo-a5:#0044ff2d;--indigo-a6:#003eff3e;--indigo-a7:#0037ed54;--indigo-a8:#0034dc72;--indigo-a9:#0031d2c1;--indigo-a10:#002ec9cc;--indigo-a11:#002bb7c5;--indigo-a12:#001046e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--indigo-a1:color(display-p3 .02 .02 .51/.008);--indigo-a2:color(display-p3 .024 .161 .863/.028);--indigo-a3:color(display-p3 .008 .239 .886/.067);--indigo-a4:color(display-p3 .004 .247 1/.114);--indigo-a5:color(display-p3 .004 .235 1/.169);--indigo-a6:color(display-p3 .004 .208 .984/.232);--indigo-a7:color(display-p3 .004 .176 .863/.314);--indigo-a8:color(display-p3 .004 .165 .812/.432);--indigo-a9:color(display-p3 0 .153 .773/.726);--indigo-a10:color(display-p3 0 .137 .737/.765);--indigo-a11:color(display-p3 .256 .354 .755);--indigo-a12:color(display-p3 .133 .175 .348)}}}.dark,.dark-theme{--indigo-a1:#1133ff0f;--indigo-a2:#3354fa17;--indigo-a3:#2f62ff3c;--indigo-a4:#3566ff57;--indigo-a5:#4171fd6b;--indigo-a6:#5178fd7c;--indigo-a7:#5a7fff90;--indigo-a8:#5b81feac;--indigo-a9:#4671ffdb;--indigo-a10:#5c7efee3;--indigo-a11:#9eb1ff;--indigo-a12:#d6e1ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--indigo-a1:color(display-p3 .071 .212 .996/.055);--indigo-a2:color(display-p3 .251 .345 .988/.085);--indigo-a3:color(display-p3 .243 .404 1/.223);--indigo-a4:color(display-p3 .263 .42 1/.324);--indigo-a5:color(display-p3 .314 .451 1/.4);--indigo-a6:color(display-p3 .361 .49 1/.467);--indigo-a7:color(display-p3 .388 .51 1/.547);--indigo-a8:color(display-p3 .404 .518 1/.652);--indigo-a9:color(display-p3 .318 .451 1/.824);--indigo-a10:color(display-p3 .404 .506 1/.858);--indigo-a11:color(display-p3 .63 .69 1);--indigo-a12:color(display-p3 .848 .881 .99)}}}:root,.light,.light-theme{--blue-1:#fbfdff;--blue-2:#f4faff;--blue-3:#e6f4fe;--blue-4:#d5efff;--blue-5:#c2e5ff;--blue-6:#acd8fc;--blue-7:#8ec8f6;--blue-8:#5eb1ef;--blue-9:#0090ff;--blue-10:#0588f0;--blue-11:#0d74ce;--blue-12:#113264}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--blue-1:color(display-p3 .986 .992 .999);--blue-2:color(display-p3 .96 .979 .998);--blue-3:color(display-p3 .912 .956 .991);--blue-4:color(display-p3 .853 .932 1);--blue-5:color(display-p3 .788 .894 .998);--blue-6:color(display-p3 .709 .843 .976);--blue-7:color(display-p3 .606 .777 .947);--blue-8:color(display-p3 .451 .688 .917);--blue-9:color(display-p3 .247 .556 .969);--blue-10:color(display-p3 .234 .523 .912);--blue-11:color(display-p3 .15 .44 .84);--blue-12:color(display-p3 .102 .193 .379)}}}.dark,.dark-theme{--blue-1:#0d1520;--blue-2:#111927;--blue-3:#0d2847;--blue-4:#003362;--blue-5:#004074;--blue-6:#104d87;--blue-7:#205d9e;--blue-8:#2870bd;--blue-9:#0090ff;--blue-10:#3b9eff;--blue-11:#70b8ff;--blue-12:#c2e6ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--blue-1:color(display-p3 .057 .081 .122);--blue-2:color(display-p3 .072 .098 .147);--blue-3:color(display-p3 .078 .154 .27);--blue-4:color(display-p3 .033 .197 .37);--blue-5:color(display-p3 .08 .245 .441);--blue-6:color(display-p3 .14 .298 .511);--blue-7:color(display-p3 .195 .361 .6);--blue-8:color(display-p3 .239 .434 .72);--blue-9:color(display-p3 .247 .556 .969);--blue-10:color(display-p3 .344 .612 .973);--blue-11:color(display-p3 .49 .72 1);--blue-12:color(display-p3 .788 .898 .99)}}}:root,.light,.light-theme{--blue-a1:#0080ff04;--blue-a2:#008cff0b;--blue-a3:#008ff519;--blue-a4:#009eff2a;--blue-a5:#0093ff3d;--blue-a6:#0088f653;--blue-a7:#0083eb71;--blue-a8:#0084e6a1;--blue-a9:#0090ff;--blue-a10:#0086f0fa;--blue-a11:#006dcbf2;--blue-a12:#002359ee}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--blue-a1:color(display-p3 .024 .514 1/.016);--blue-a2:color(display-p3 .024 .514 .906/.04);--blue-a3:color(display-p3 .012 .506 .914/.087);--blue-a4:color(display-p3 .008 .545 1/.146);--blue-a5:color(display-p3 .004 .502 .984/.212);--blue-a6:color(display-p3 .004 .463 .922/.291);--blue-a7:color(display-p3 .004 .431 .863/.393);--blue-a8:color(display-p3 0 .427 .851/.55);--blue-a9:color(display-p3 0 .412 .961/.753);--blue-a10:color(display-p3 0 .376 .886/.765);--blue-a11:color(display-p3 .15 .44 .84);--blue-a12:color(display-p3 .102 .193 .379)}}}.dark,.dark-theme{--blue-a1:#004df211;--blue-a2:#1166fb18;--blue-a3:#0077ff3a;--blue-a4:#0075ff57;--blue-a5:#0081fd6b;--blue-a6:#0f89fd7f;--blue-a7:#2a91fe98;--blue-a8:#3094feb9;--blue-a9:#0090ff;--blue-a10:#3b9eff;--blue-a11:#70b8ff;--blue-a12:#c2e6ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--blue-a1:color(display-p3 0 .333 1/.059);--blue-a2:color(display-p3 .114 .435 .988/.085);--blue-a3:color(display-p3 .122 .463 1/.219);--blue-a4:color(display-p3 0 .467 1/.324);--blue-a5:color(display-p3 .098 .51 1/.4);--blue-a6:color(display-p3 .224 .557 1/.475);--blue-a7:color(display-p3 .294 .584 1/.572);--blue-a8:color(display-p3 .314 .592 1/.702);--blue-a9:color(display-p3 .251 .573 .996/.967);--blue-a10:color(display-p3 .357 .631 1/.971);--blue-a11:color(display-p3 .49 .72 1);--blue-a12:color(display-p3 .788 .898 .99)}}}:root,.light,.light-theme{--cyan-1:#fafdfe;--cyan-2:#f2fafb;--cyan-3:#def7f9;--cyan-4:#caf1f6;--cyan-5:#b5e9f0;--cyan-6:#9ddde7;--cyan-7:#7dcedc;--cyan-8:#3db9cf;--cyan-9:#00a2c7;--cyan-10:#0797b9;--cyan-11:#107d98;--cyan-12:#0d3c48}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--cyan-1:color(display-p3 .982 .992 .996);--cyan-2:color(display-p3 .955 .981 .984);--cyan-3:color(display-p3 .888 .965 .975);--cyan-4:color(display-p3 .821 .941 .959);--cyan-5:color(display-p3 .751 .907 .935);--cyan-6:color(display-p3 .671 .862 .9);--cyan-7:color(display-p3 .564 .8 .854);--cyan-8:color(display-p3 .388 .715 .798);--cyan-9:color(display-p3 .282 .627 .765);--cyan-10:color(display-p3 .264 .583 .71);--cyan-11:color(display-p3 .08 .48 .63);--cyan-12:color(display-p3 .108 .232 .277)}}}.dark,.dark-theme{--cyan-1:#0b161a;--cyan-2:#101b20;--cyan-3:#082c36;--cyan-4:#003848;--cyan-5:#004558;--cyan-6:#045468;--cyan-7:#12677e;--cyan-8:#11809c;--cyan-9:#00a2c7;--cyan-10:#23afd0;--cyan-11:#4ccce6;--cyan-12:#b6ecf7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--cyan-1:color(display-p3 .053 .085 .098);--cyan-2:color(display-p3 .072 .105 .122);--cyan-3:color(display-p3 .073 .168 .209);--cyan-4:color(display-p3 .063 .216 .277);--cyan-5:color(display-p3 .091 .267 .336);--cyan-6:color(display-p3 .137 .324 .4);--cyan-7:color(display-p3 .186 .398 .484);--cyan-8:color(display-p3 .23 .496 .6);--cyan-9:color(display-p3 .282 .627 .765);--cyan-10:color(display-p3 .331 .675 .801);--cyan-11:color(display-p3 .446 .79 .887);--cyan-12:color(display-p3 .757 .919 .962)}}}:root,.light,.light-theme{--cyan-a1:#0099cc05;--cyan-a2:#009db10d;--cyan-a3:#00c2d121;--cyan-a4:#00bcd435;--cyan-a5:#01b4cc4a;--cyan-a6:#00a7c162;--cyan-a7:#009fbb82;--cyan-a8:#00a3c0c2;--cyan-a9:#00a2c7;--cyan-a10:#0094b7f8;--cyan-a11:#007491ef;--cyan-a12:#00323ef2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--cyan-a1:color(display-p3 .02 .608 .804/.02);--cyan-a2:color(display-p3 .02 .557 .647/.044);--cyan-a3:color(display-p3 .004 .694 .796/.114);--cyan-a4:color(display-p3 .004 .678 .784/.181);--cyan-a5:color(display-p3 .004 .624 .733/.248);--cyan-a6:color(display-p3 .004 .584 .706/.33);--cyan-a7:color(display-p3 .004 .541 .667/.436);--cyan-a8:color(display-p3 0 .533 .667/.612);--cyan-a9:color(display-p3 0 .482 .675/.718);--cyan-a10:color(display-p3 0 .435 .608/.738);--cyan-a11:color(display-p3 .08 .48 .63);--cyan-a12:color(display-p3 .108 .232 .277)}}}.dark,.dark-theme{--cyan-a1:#0091f70a;--cyan-a2:#02a7f211;--cyan-a3:#00befd28;--cyan-a4:#00baff3b;--cyan-a5:#00befd4d;--cyan-a6:#00c7fd5e;--cyan-a7:#14cdff75;--cyan-a8:#11cfff95;--cyan-a9:#00cfffc3;--cyan-a10:#28d6ffcd;--cyan-a11:#52e1fee5;--cyan-a12:#bbf3fef7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--cyan-a1:color(display-p3 0 .647 .992/.034);--cyan-a2:color(display-p3 .133 .733 1/.059);--cyan-a3:color(display-p3 .122 .741 .996/.152);--cyan-a4:color(display-p3 .051 .725 1/.227);--cyan-a5:color(display-p3 .149 .757 1/.29);--cyan-a6:color(display-p3 .267 .792 1/.358);--cyan-a7:color(display-p3 .333 .808 1/.446);--cyan-a8:color(display-p3 .357 .816 1/.572);--cyan-a9:color(display-p3 .357 .82 1/.748);--cyan-a10:color(display-p3 .4 .839 1/.786);--cyan-a11:color(display-p3 .446 .79 .887);--cyan-a12:color(display-p3 .757 .919 .962)}}}:root,.light,.light-theme{--teal-1:#fafefd;--teal-2:#f3fbf9;--teal-3:#e0f8f3;--teal-4:#ccf3ea;--teal-5:#b8eae0;--teal-6:#a1ded2;--teal-7:#83cdc1;--teal-8:#53b9ab;--teal-9:#12a594;--teal-10:#0d9b8a;--teal-11:#008573;--teal-12:#0d3d38}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--teal-1:color(display-p3 .983 .996 .992);--teal-2:color(display-p3 .958 .983 .976);--teal-3:color(display-p3 .895 .971 .952);--teal-4:color(display-p3 .831 .949 .92);--teal-5:color(display-p3 .761 .914 .878);--teal-6:color(display-p3 .682 .864 .825);--teal-7:color(display-p3 .581 .798 .756);--teal-8:color(display-p3 .433 .716 .671);--teal-9:color(display-p3 .297 .637 .581);--teal-10:color(display-p3 .275 .599 .542);--teal-11:color(display-p3 .08 .5 .43);--teal-12:color(display-p3 .11 .235 .219)}}}.dark,.dark-theme{--teal-1:#0d1514;--teal-2:#111c1b;--teal-3:#0d2d2a;--teal-4:#023b37;--teal-5:#084843;--teal-6:#145750;--teal-7:#1c6961;--teal-8:#207e73;--teal-9:#12a594;--teal-10:#0eb39e;--teal-11:#0bd8b6;--teal-12:#adf0dd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--teal-1:color(display-p3 .059 .083 .079);--teal-2:color(display-p3 .075 .11 .107);--teal-3:color(display-p3 .087 .175 .165);--teal-4:color(display-p3 .087 .227 .214);--teal-5:color(display-p3 .12 .277 .261);--teal-6:color(display-p3 .162 .335 .314);--teal-7:color(display-p3 .205 .406 .379);--teal-8:color(display-p3 .245 .489 .453);--teal-9:color(display-p3 .297 .637 .581);--teal-10:color(display-p3 .319 .69 .62);--teal-11:color(display-p3 .388 .835 .719);--teal-12:color(display-p3 .734 .934 .87)}}}:root,.light,.light-theme{--teal-a1:#00cc9905;--teal-a2:#00aa800c;--teal-a3:#00c69d1f;--teal-a4:#00c39633;--teal-a5:#00b49047;--teal-a6:#00a6855e;--teal-a7:#0099807c;--teal-a8:#009783ac;--teal-a9:#009e8ced;--teal-a10:#009684f2;--teal-a11:#008573;--teal-a12:#00332df2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--teal-a1:color(display-p3 .024 .757 .514/.016);--teal-a2:color(display-p3 .02 .647 .467/.044);--teal-a3:color(display-p3 .004 .741 .557/.106);--teal-a4:color(display-p3 .004 .702 .537/.169);--teal-a5:color(display-p3 .004 .643 .494/.24);--teal-a6:color(display-p3 .004 .569 .447/.318);--teal-a7:color(display-p3 .004 .518 .424/.42);--teal-a8:color(display-p3 0 .506 .424/.569);--teal-a9:color(display-p3 0 .482 .404/.702);--teal-a10:color(display-p3 0 .451 .369/.726);--teal-a11:color(display-p3 .08 .5 .43);--teal-a12:color(display-p3 .11 .235 .219)}}}.dark,.dark-theme{--teal-a1:#00deab05;--teal-a2:#12fbe60c;--teal-a3:#00ffe61e;--teal-a4:#00ffe92d;--teal-a5:#00ffea3b;--teal-a6:#1cffe84b;--teal-a7:#2efde85f;--teal-a8:#32ffe775;--teal-a9:#13ffe49f;--teal-a10:#0dffe0ae;--teal-a11:#0afed5d6;--teal-a12:#b8ffebef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--teal-a1:color(display-p3 0 .992 .761/.017);--teal-a2:color(display-p3 .235 .988 .902/.047);--teal-a3:color(display-p3 .235 1 .898/.118);--teal-a4:color(display-p3 .18 .996 .929/.173);--teal-a5:color(display-p3 .31 1 .933/.227);--teal-a6:color(display-p3 .396 1 .933/.286);--teal-a7:color(display-p3 .443 1 .925/.366);--teal-a8:color(display-p3 .459 1 .925/.454);--teal-a9:color(display-p3 .443 .996 .906/.61);--teal-a10:color(display-p3 .439 .996 .89/.669);--teal-a11:color(display-p3 .388 .835 .719);--teal-a12:color(display-p3 .734 .934 .87)}}}:root,.light,.light-theme{--jade-1:#fbfefd;--jade-2:#f4fbf7;--jade-3:#e6f7ed;--jade-4:#d6f1e3;--jade-5:#c3e9d7;--jade-6:#acdec8;--jade-7:#8bceb6;--jade-8:#56ba9f;--jade-9:#29a383;--jade-10:#26997b;--jade-11:#208368;--jade-12:#1d3b31}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--jade-1:color(display-p3 .986 .996 .992);--jade-2:color(display-p3 .962 .983 .969);--jade-3:color(display-p3 .912 .965 .932);--jade-4:color(display-p3 .858 .941 .893);--jade-5:color(display-p3 .795 .909 .847);--jade-6:color(display-p3 .715 .864 .791);--jade-7:color(display-p3 .603 .802 .718);--jade-8:color(display-p3 .44 .72 .629);--jade-9:color(display-p3 .319 .63 .521);--jade-10:color(display-p3 .299 .592 .488);--jade-11:color(display-p3 .15 .5 .37);--jade-12:color(display-p3 .142 .229 .194)}}}.dark,.dark-theme{--jade-1:#0d1512;--jade-2:#121c18;--jade-3:#0f2e22;--jade-4:#0b3b2c;--jade-5:#114837;--jade-6:#1b5745;--jade-7:#246854;--jade-8:#2a7e68;--jade-9:#29a383;--jade-10:#27b08b;--jade-11:#1fd8a4;--jade-12:#adf0d4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--jade-1:color(display-p3 .059 .083 .071);--jade-2:color(display-p3 .078 .11 .094);--jade-3:color(display-p3 .091 .176 .138);--jade-4:color(display-p3 .102 .228 .177);--jade-5:color(display-p3 .133 .279 .221);--jade-6:color(display-p3 .174 .334 .273);--jade-7:color(display-p3 .219 .402 .335);--jade-8:color(display-p3 .263 .488 .411);--jade-9:color(display-p3 .319 .63 .521);--jade-10:color(display-p3 .338 .68 .555);--jade-11:color(display-p3 .4 .835 .656);--jade-12:color(display-p3 .734 .934 .838)}}}:root,.light,.light-theme{--jade-a1:#00c08004;--jade-a2:#00a3460b;--jade-a3:#00ae4819;--jade-a4:#00a85129;--jade-a5:#00a2553c;--jade-a6:#009a5753;--jade-a7:#00945f74;--jade-a8:#00976ea9;--jade-a9:#00916bd6;--jade-a10:#008764d9;--jade-a11:#007152df;--jade-a12:#002217e2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--jade-a1:color(display-p3 .024 .757 .514/.016);--jade-a2:color(display-p3 .024 .612 .22/.04);--jade-a3:color(display-p3 .012 .596 .235/.087);--jade-a4:color(display-p3 .008 .588 .255/.142);--jade-a5:color(display-p3 .004 .561 .251/.204);--jade-a6:color(display-p3 .004 .525 .278/.287);--jade-a7:color(display-p3 .004 .506 .29/.397);--jade-a8:color(display-p3 0 .506 .337/.561);--jade-a9:color(display-p3 0 .459 .298/.683);--jade-a10:color(display-p3 0 .42 .271/.702);--jade-a11:color(display-p3 .15 .5 .37);--jade-a12:color(display-p3 .142 .229 .194)}}}.dark,.dark-theme{--jade-a1:#00de4505;--jade-a2:#27fba60c;--jade-a3:#02f99920;--jade-a4:#00ffaa2d;--jade-a5:#11ffb63b;--jade-a6:#34ffc24b;--jade-a7:#45fdc75e;--jade-a8:#48ffcf75;--jade-a9:#38feca9d;--jade-a10:#31fec7ab;--jade-a11:#21fec0d6;--jade-a12:#b8ffe1ef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--jade-a1:color(display-p3 0 .992 .298/.017);--jade-a2:color(display-p3 .318 .988 .651/.047);--jade-a3:color(display-p3 .267 1 .667/.118);--jade-a4:color(display-p3 .275 .996 .702/.173);--jade-a5:color(display-p3 .361 1 .741/.227);--jade-a6:color(display-p3 .439 1 .796/.286);--jade-a7:color(display-p3 .49 1 .804/.362);--jade-a8:color(display-p3 .506 1 .835/.45);--jade-a9:color(display-p3 .478 .996 .816/.606);--jade-a10:color(display-p3 .478 1 .816/.656);--jade-a11:color(display-p3 .4 .835 .656);--jade-a12:color(display-p3 .734 .934 .838)}}}:root,.light,.light-theme{--green-1:#fbfefc;--green-2:#f4fbf6;--green-3:#e6f6eb;--green-4:#d6f1df;--green-5:#c4e8d1;--green-6:#adddc0;--green-7:#8eceaa;--green-8:#5bb98b;--green-9:#30a46c;--green-10:#2b9a66;--green-11:#218358;--green-12:#193b2d}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--green-1:color(display-p3 .986 .996 .989);--green-2:color(display-p3 .963 .983 .967);--green-3:color(display-p3 .913 .964 .925);--green-4:color(display-p3 .859 .94 .879);--green-5:color(display-p3 .796 .907 .826);--green-6:color(display-p3 .718 .863 .761);--green-7:color(display-p3 .61 .801 .675);--green-8:color(display-p3 .451 .715 .559);--green-9:color(display-p3 .332 .634 .442);--green-10:color(display-p3 .308 .595 .417);--green-11:color(display-p3 .19 .5 .32);--green-12:color(display-p3 .132 .228 .18)}}}.dark,.dark-theme{--green-1:#0e1512;--green-2:#121b17;--green-3:#132d21;--green-4:#113b29;--green-5:#174933;--green-6:#20573e;--green-7:#28684a;--green-8:#2f7c57;--green-9:#30a46c;--green-10:#33b074;--green-11:#3dd68c;--green-12:#b1f1cb}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--green-1:color(display-p3 .062 .083 .071);--green-2:color(display-p3 .079 .106 .09);--green-3:color(display-p3 .1 .173 .133);--green-4:color(display-p3 .115 .229 .166);--green-5:color(display-p3 .147 .282 .206);--green-6:color(display-p3 .185 .338 .25);--green-7:color(display-p3 .227 .403 .298);--green-8:color(display-p3 .27 .479 .351);--green-9:color(display-p3 .332 .634 .442);--green-10:color(display-p3 .357 .682 .474);--green-11:color(display-p3 .434 .828 .573);--green-12:color(display-p3 .747 .938 .807)}}}:root,.light,.light-theme{--green-a1:#00c04004;--green-a2:#00a32f0b;--green-a3:#00a43319;--green-a4:#00a83829;--green-a5:#019c393b;--green-a6:#00963c52;--green-a7:#00914071;--green-a8:#00924ba4;--green-a9:#008f4acf;--green-a10:#008647d4;--green-a11:#00713fde;--green-a12:#002616e6}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--green-a1:color(display-p3 .024 .757 .267/.016);--green-a2:color(display-p3 .024 .565 .129/.036);--green-a3:color(display-p3 .012 .596 .145/.087);--green-a4:color(display-p3 .008 .588 .145/.142);--green-a5:color(display-p3 .004 .541 .157/.204);--green-a6:color(display-p3 .004 .518 .157/.283);--green-a7:color(display-p3 .004 .486 .165/.389);--green-a8:color(display-p3 0 .478 .2/.55);--green-a9:color(display-p3 0 .455 .165/.667);--green-a10:color(display-p3 0 .416 .153/.691);--green-a11:color(display-p3 .19 .5 .32);--green-a12:color(display-p3 .132 .228 .18)}}}.dark,.dark-theme{--green-a1:#00de4505;--green-a2:#29f99d0b;--green-a3:#22ff991e;--green-a4:#11ff992d;--green-a5:#2bffa23c;--green-a6:#44ffaa4b;--green-a7:#50fdac5e;--green-a8:#54ffad73;--green-a9:#44ffa49e;--green-a10:#43fea4ab;--green-a11:#46fea5d4;--green-a12:#bbffd7f0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--green-a1:color(display-p3 0 .992 .298/.017);--green-a2:color(display-p3 .341 .98 .616/.043);--green-a3:color(display-p3 .376 .996 .655/.114);--green-a4:color(display-p3 .341 .996 .635/.173);--green-a5:color(display-p3 .408 1 .678/.232);--green-a6:color(display-p3 .475 1 .706/.29);--green-a7:color(display-p3 .514 1 .706/.362);--green-a8:color(display-p3 .529 1 .718/.442);--green-a9:color(display-p3 .502 .996 .682/.61);--green-a10:color(display-p3 .506 1 .682/.66);--green-a11:color(display-p3 .434 .828 .573);--green-a12:color(display-p3 .747 .938 .807)}}}:root,.light,.light-theme{--grass-1:#fbfefb;--grass-2:#f5fbf5;--grass-3:#e9f6e9;--grass-4:#daf1db;--grass-5:#c9e8ca;--grass-6:#b2ddb5;--grass-7:#94ce9a;--grass-8:#65ba74;--grass-9:#46a758;--grass-10:#3e9b4f;--grass-11:#2a7e3b;--grass-12:#203c25}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--grass-1:color(display-p3 .986 .996 .985);--grass-2:color(display-p3 .966 .983 .964);--grass-3:color(display-p3 .923 .965 .917);--grass-4:color(display-p3 .872 .94 .865);--grass-5:color(display-p3 .811 .908 .802);--grass-6:color(display-p3 .733 .864 .724);--grass-7:color(display-p3 .628 .803 .622);--grass-8:color(display-p3 .477 .72 .482);--grass-9:color(display-p3 .38 .647 .378);--grass-10:color(display-p3 .344 .598 .342);--grass-11:color(display-p3 .263 .488 .261);--grass-12:color(display-p3 .151 .233 .153)}}}.dark,.dark-theme{--grass-1:#0e1511;--grass-2:#141a15;--grass-3:#1b2a1e;--grass-4:#1d3a24;--grass-5:#25482d;--grass-6:#2d5736;--grass-7:#366740;--grass-8:#3e7949;--grass-9:#46a758;--grass-10:#53b365;--grass-11:#71d083;--grass-12:#c2f0c2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--grass-1:color(display-p3 .062 .083 .067);--grass-2:color(display-p3 .083 .103 .085);--grass-3:color(display-p3 .118 .163 .122);--grass-4:color(display-p3 .142 .225 .15);--grass-5:color(display-p3 .178 .279 .186);--grass-6:color(display-p3 .217 .337 .224);--grass-7:color(display-p3 .258 .4 .264);--grass-8:color(display-p3 .302 .47 .305);--grass-9:color(display-p3 .38 .647 .378);--grass-10:color(display-p3 .426 .694 .426);--grass-11:color(display-p3 .535 .807 .542);--grass-12:color(display-p3 .797 .936 .776)}}}:root,.light,.light-theme{--grass-a1:#00c00004;--grass-a2:#0099000a;--grass-a3:#00970016;--grass-a4:#009f0725;--grass-a5:#00930536;--grass-a6:#008f0a4d;--grass-a7:#018b0f6b;--grass-a8:#008d199a;--grass-a9:#008619b9;--grass-a10:#007b17c1;--grass-a11:#006514d5;--grass-a12:#002006df}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--grass-a1:color(display-p3 .024 .757 .024/.016);--grass-a2:color(display-p3 .024 .565 .024/.036);--grass-a3:color(display-p3 .059 .576 .008/.083);--grass-a4:color(display-p3 .035 .565 .008/.134);--grass-a5:color(display-p3 .047 .545 .008/.197);--grass-a6:color(display-p3 .031 .502 .004/.275);--grass-a7:color(display-p3 .012 .482 .004/.377);--grass-a8:color(display-p3 0 .467 .008/.522);--grass-a9:color(display-p3 .008 .435 0/.624);--grass-a10:color(display-p3 .008 .388 0/.659);--grass-a11:color(display-p3 .263 .488 .261);--grass-a12:color(display-p3 .151 .233 .153)}}}.dark,.dark-theme{--grass-a1:#00de1205;--grass-a2:#5ef7780a;--grass-a3:#70fe8c1b;--grass-a4:#57ff802c;--grass-a5:#68ff8b3b;--grass-a6:#71ff8f4b;--grass-a7:#77fd925d;--grass-a8:#77fd9070;--grass-a9:#65ff82a1;--grass-a10:#72ff8dae;--grass-a11:#89ff9fcd;--grass-a12:#ceffceef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--grass-a1:color(display-p3 0 .992 .071/.017);--grass-a2:color(display-p3 .482 .996 .584/.038);--grass-a3:color(display-p3 .549 .992 .588/.106);--grass-a4:color(display-p3 .51 .996 .557/.169);--grass-a5:color(display-p3 .553 1 .588/.227);--grass-a6:color(display-p3 .584 1 .608/.29);--grass-a7:color(display-p3 .604 1 .616/.358);--grass-a8:color(display-p3 .608 1 .62/.433);--grass-a9:color(display-p3 .573 1 .569/.622);--grass-a10:color(display-p3 .6 .996 .6/.673);--grass-a11:color(display-p3 .535 .807 .542);--grass-a12:color(display-p3 .797 .936 .776)}}}:root,.light,.light-theme{--orange-1:#fefcfb;--orange-2:#fff7ed;--orange-3:#ffefd6;--orange-4:#ffdfb5;--orange-5:#ffd19a;--orange-6:#ffc182;--orange-7:#f5ae73;--orange-8:#ec9455;--orange-9:#f76b15;--orange-10:#ef5f00;--orange-11:#cc4e00;--orange-12:#582d1d}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--orange-1:color(display-p3 .995 .988 .985);--orange-2:color(display-p3 .994 .968 .934);--orange-3:color(display-p3 .989 .938 .85);--orange-4:color(display-p3 1 .874 .687);--orange-5:color(display-p3 1 .821 .583);--orange-6:color(display-p3 .975 .767 .545);--orange-7:color(display-p3 .919 .693 .486);--orange-8:color(display-p3 .877 .597 .379);--orange-9:color(display-p3 .9 .45 .2);--orange-10:color(display-p3 .87 .409 .164);--orange-11:color(display-p3 .76 .34 0);--orange-12:color(display-p3 .323 .185 .127)}}}.dark,.dark-theme{--orange-1:#17120e;--orange-2:#1e160f;--orange-3:#331e0b;--orange-4:#462100;--orange-5:#562800;--orange-6:#66350c;--orange-7:#7e451d;--orange-8:#a35829;--orange-9:#f76b15;--orange-10:#ff801f;--orange-11:#ffa057;--orange-12:#ffe0c2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--orange-1:color(display-p3 .088 .07 .057);--orange-2:color(display-p3 .113 .089 .061);--orange-3:color(display-p3 .189 .12 .056);--orange-4:color(display-p3 .262 .132 0);--orange-5:color(display-p3 .315 .168 .016);--orange-6:color(display-p3 .376 .219 .088);--orange-7:color(display-p3 .465 .283 .147);--orange-8:color(display-p3 .601 .359 .201);--orange-9:color(display-p3 .9 .45 .2);--orange-10:color(display-p3 .98 .51 .23);--orange-11:color(display-p3 1 .63 .38);--orange-12:color(display-p3 .98 .883 .775)}}}:root,.light,.light-theme{--orange-a1:#c0400004;--orange-a2:#ff8e0012;--orange-a3:#ff9c0029;--orange-a4:#ff91014a;--orange-a5:#ff8b0065;--orange-a6:#ff81007d;--orange-a7:#ed6c008c;--orange-a8:#e35f00aa;--orange-a9:#f65e00ea;--orange-a10:#ef5f00;--orange-a11:#cc4e00;--orange-a12:#431200e2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--orange-a1:color(display-p3 .757 .267 .024/.016);--orange-a2:color(display-p3 .886 .533 .008/.067);--orange-a3:color(display-p3 .922 .584 .008/.15);--orange-a4:color(display-p3 1 .604 .004/.314);--orange-a5:color(display-p3 1 .569 .004/.416);--orange-a6:color(display-p3 .949 .494 .004/.455);--orange-a7:color(display-p3 .839 .408 0/.514);--orange-a8:color(display-p3 .804 .349 0/.62);--orange-a9:color(display-p3 .878 .314 0/.8);--orange-a10:color(display-p3 .843 .29 0/.836);--orange-a11:color(display-p3 .76 .34 0);--orange-a12:color(display-p3 .323 .185 .127)}}}.dark,.dark-theme{--orange-a1:#ec360007;--orange-a2:#fe6d000e;--orange-a3:#fb6a0025;--orange-a4:#ff590039;--orange-a5:#ff61004a;--orange-a6:#fd75045c;--orange-a7:#ff832c75;--orange-a8:#fe84389d;--orange-a9:#fe6d15f7;--orange-a10:#ff801f;--orange-a11:#ffa057;--orange-a12:#ffe0c2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--orange-a1:color(display-p3 .961 .247 0/.022);--orange-a2:color(display-p3 .992 .529 0/.051);--orange-a3:color(display-p3 .996 .486 0/.131);--orange-a4:color(display-p3 .996 .384 0/.211);--orange-a5:color(display-p3 1 .455 0/.265);--orange-a6:color(display-p3 1 .529 .129/.332);--orange-a7:color(display-p3 1 .569 .251/.429);--orange-a8:color(display-p3 1 .584 .302/.572);--orange-a9:color(display-p3 1 .494 .216/.895);--orange-a10:color(display-p3 1 .522 .235/.979);--orange-a11:color(display-p3 1 .63 .38);--orange-a12:color(display-p3 .98 .883 .775)}}}:root,.light,.light-theme{--brown-1:#fefdfc;--brown-2:#fcf9f6;--brown-3:#f6eee7;--brown-4:#f0e4d9;--brown-5:#ebdaca;--brown-6:#e4cdb7;--brown-7:#dcbc9f;--brown-8:#cea37e;--brown-9:#ad7f58;--brown-10:#a07553;--brown-11:#815e46;--brown-12:#3e332e}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--brown-1:color(display-p3 .995 .992 .989);--brown-2:color(display-p3 .987 .976 .964);--brown-3:color(display-p3 .959 .936 .909);--brown-4:color(display-p3 .934 .897 .855);--brown-5:color(display-p3 .909 .856 .798);--brown-6:color(display-p3 .88 .808 .73);--brown-7:color(display-p3 .841 .742 .639);--brown-8:color(display-p3 .782 .647 .514);--brown-9:color(display-p3 .651 .505 .368);--brown-10:color(display-p3 .601 .465 .344);--brown-11:color(display-p3 .485 .374 .288);--brown-12:color(display-p3 .236 .202 .183)}}}.dark,.dark-theme{--brown-1:#12110f;--brown-2:#1c1816;--brown-3:#28211d;--brown-4:#322922;--brown-5:#3e3128;--brown-6:#4d3c2f;--brown-7:#614a39;--brown-8:#7c5f46;--brown-9:#ad7f58;--brown-10:#b88c67;--brown-11:#dbb594;--brown-12:#f2e1ca}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--brown-1:color(display-p3 .071 .067 .059);--brown-2:color(display-p3 .107 .095 .087);--brown-3:color(display-p3 .151 .13 .115);--brown-4:color(display-p3 .191 .161 .138);--brown-5:color(display-p3 .235 .194 .162);--brown-6:color(display-p3 .291 .237 .192);--brown-7:color(display-p3 .365 .295 .232);--brown-8:color(display-p3 .469 .377 .287);--brown-9:color(display-p3 .651 .505 .368);--brown-10:color(display-p3 .697 .557 .423);--brown-11:color(display-p3 .835 .715 .597);--brown-12:color(display-p3 .938 .885 .802)}}}:root,.light,.light-theme{--brown-a1:#aa550003;--brown-a2:#aa550009;--brown-a3:#a04b0018;--brown-a4:#9b4a0026;--brown-a5:#9f4d0035;--brown-a6:#a04e0048;--brown-a7:#a34e0060;--brown-a8:#9f4a0081;--brown-a9:#823c00a7;--brown-a10:#723300ac;--brown-a11:#522100b9;--brown-a12:#140600d1}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--brown-a1:color(display-p3 .675 .349 .024/.012);--brown-a2:color(display-p3 .675 .349 .024/.036);--brown-a3:color(display-p3 .573 .314 .012/.091);--brown-a4:color(display-p3 .545 .302 .008/.146);--brown-a5:color(display-p3 .561 .29 .004/.204);--brown-a6:color(display-p3 .553 .294 .004/.271);--brown-a7:color(display-p3 .557 .286 .004/.361);--brown-a8:color(display-p3 .549 .275 .004/.487);--brown-a9:color(display-p3 .447 .22 0/.632);--brown-a10:color(display-p3 .388 .188 0/.655);--brown-a11:color(display-p3 .485 .374 .288);--brown-a12:color(display-p3 .236 .202 .183)}}}.dark,.dark-theme{--brown-a1:#91110002;--brown-a2:#fba67c0c;--brown-a3:#fcb58c19;--brown-a4:#fbbb8a24;--brown-a5:#fcb88931;--brown-a6:#fdba8741;--brown-a7:#ffbb8856;--brown-a8:#ffbe8773;--brown-a9:#feb87da8;--brown-a10:#ffc18cb3;--brown-a11:#fed1aad9;--brown-a12:#feecd4f2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--brown-a1:color(display-p3 .855 .071 0/.005);--brown-a2:color(display-p3 .98 .706 .525/.043);--brown-a3:color(display-p3 .996 .745 .576/.093);--brown-a4:color(display-p3 1 .765 .592/.135);--brown-a5:color(display-p3 1 .761 .588/.181);--brown-a6:color(display-p3 1 .773 .592/.24);--brown-a7:color(display-p3 .996 .776 .58/.32);--brown-a8:color(display-p3 1 .78 .573/.433);--brown-a9:color(display-p3 1 .769 .549/.627);--brown-a10:color(display-p3 1 .792 .596/.677);--brown-a11:color(display-p3 .835 .715 .597);--brown-a12:color(display-p3 .938 .885 .802)}}}:root,.light,.light-theme{--sky-1:#f9feff;--sky-2:#f1fafd;--sky-3:#e1f6fd;--sky-4:#d1f0fa;--sky-5:#bee7f5;--sky-6:#a9daed;--sky-7:#8dcae3;--sky-8:#60b3d7;--sky-9:#7ce2fe;--sky-10:#74daf8;--sky-11:#00749e;--sky-12:#1d3e56}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sky-1:color(display-p3 .98 .995 .999);--sky-2:color(display-p3 .953 .98 .99);--sky-3:color(display-p3 .899 .963 .989);--sky-4:color(display-p3 .842 .937 .977);--sky-5:color(display-p3 .777 .9 .954);--sky-6:color(display-p3 .701 .851 .921);--sky-7:color(display-p3 .604 .785 .879);--sky-8:color(display-p3 .457 .696 .829);--sky-9:color(display-p3 .585 .877 .983);--sky-10:color(display-p3 .555 .845 .959);--sky-11:color(display-p3 .193 .448 .605);--sky-12:color(display-p3 .145 .241 .329)}}}.dark,.dark-theme{--sky-1:#0d141f;--sky-2:#111a27;--sky-3:#112840;--sky-4:#113555;--sky-5:#154467;--sky-6:#1b537b;--sky-7:#1f6692;--sky-8:#197cae;--sky-9:#7ce2fe;--sky-10:#a8eeff;--sky-11:#75c7f0;--sky-12:#c2f3ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sky-1:color(display-p3 .056 .078 .116);--sky-2:color(display-p3 .075 .101 .149);--sky-3:color(display-p3 .089 .154 .244);--sky-4:color(display-p3 .106 .207 .323);--sky-5:color(display-p3 .135 .261 .394);--sky-6:color(display-p3 .17 .322 .469);--sky-7:color(display-p3 .205 .394 .557);--sky-8:color(display-p3 .232 .48 .665);--sky-9:color(display-p3 .585 .877 .983);--sky-10:color(display-p3 .718 .925 .991);--sky-11:color(display-p3 .536 .772 .924);--sky-12:color(display-p3 .799 .947 .993)}}}:root,.light,.light-theme{--sky-a1:#00d5ff06;--sky-a2:#00a4db0e;--sky-a3:#00b3ee1e;--sky-a4:#00ace42e;--sky-a5:#00a1d841;--sky-a6:#0092ca56;--sky-a7:#0089c172;--sky-a8:#0085bf9f;--sky-a9:#00c7fe83;--sky-a10:#00bcf38b;--sky-a11:#00749e;--sky-a12:#002540e2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sky-a1:color(display-p3 .02 .804 1/.02);--sky-a2:color(display-p3 .024 .592 .757/.048);--sky-a3:color(display-p3 .004 .655 .886/.102);--sky-a4:color(display-p3 .004 .604 .851/.157);--sky-a5:color(display-p3 .004 .565 .792/.224);--sky-a6:color(display-p3 .004 .502 .737/.299);--sky-a7:color(display-p3 .004 .459 .694/.397);--sky-a8:color(display-p3 0 .435 .682/.542);--sky-a9:color(display-p3 .004 .71 .965/.416);--sky-a10:color(display-p3 .004 .647 .914/.444);--sky-a11:color(display-p3 .193 .448 .605);--sky-a12:color(display-p3 .145 .241 .329)}}}.dark,.dark-theme{--sky-a1:#0044ff0f;--sky-a2:#1171fb18;--sky-a3:#1184fc33;--sky-a4:#128fff49;--sky-a5:#1c9dfd5d;--sky-a6:#28a5ff72;--sky-a7:#2badfe8b;--sky-a8:#1db2fea9;--sky-a9:#7ce3fffe;--sky-a10:#a8eeff;--sky-a11:#7cd3ffef;--sky-a12:#c2f3ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sky-a1:color(display-p3 0 .282 .996/.055);--sky-a2:color(display-p3 .157 .467 .992/.089);--sky-a3:color(display-p3 .192 .522 .996/.19);--sky-a4:color(display-p3 .212 .584 1/.274);--sky-a5:color(display-p3 .259 .631 1/.349);--sky-a6:color(display-p3 .302 .655 1/.433);--sky-a7:color(display-p3 .329 .686 1/.526);--sky-a8:color(display-p3 .325 .71 1/.643);--sky-a9:color(display-p3 .592 .894 1/.984);--sky-a10:color(display-p3 .722 .933 1/.992);--sky-a11:color(display-p3 .536 .772 .924);--sky-a12:color(display-p3 .799 .947 .993)}}}:root,.light,.light-theme{--mint-1:#f9fefd;--mint-2:#f2fbf9;--mint-3:#ddf9f2;--mint-4:#c8f4e9;--mint-5:#b3ecde;--mint-6:#9ce0d0;--mint-7:#7ecfbd;--mint-8:#4cbba5;--mint-9:#86ead4;--mint-10:#7de0cb;--mint-11:#027864;--mint-12:#16433c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--mint-1:color(display-p3 .98 .995 .992);--mint-2:color(display-p3 .957 .985 .977);--mint-3:color(display-p3 .888 .972 .95);--mint-4:color(display-p3 .819 .951 .916);--mint-5:color(display-p3 .747 .918 .873);--mint-6:color(display-p3 .668 .87 .818);--mint-7:color(display-p3 .567 .805 .744);--mint-8:color(display-p3 .42 .724 .649);--mint-9:color(display-p3 .62 .908 .834);--mint-10:color(display-p3 .585 .871 .797);--mint-11:color(display-p3 .203 .463 .397);--mint-12:color(display-p3 .136 .259 .236)}}}.dark,.dark-theme{--mint-1:#0e1515;--mint-2:#0f1b1b;--mint-3:#092c2b;--mint-4:#003a38;--mint-5:#004744;--mint-6:#105650;--mint-7:#1e685f;--mint-8:#277f70;--mint-9:#86ead4;--mint-10:#a8f5e5;--mint-11:#58d5ba;--mint-12:#c4f5e1}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mint-1:color(display-p3 .059 .082 .081);--mint-2:color(display-p3 .068 .104 .105);--mint-3:color(display-p3 .077 .17 .168);--mint-4:color(display-p3 .068 .224 .22);--mint-5:color(display-p3 .104 .275 .264);--mint-6:color(display-p3 .154 .332 .313);--mint-7:color(display-p3 .207 .403 .373);--mint-8:color(display-p3 .258 .49 .441);--mint-9:color(display-p3 .62 .908 .834);--mint-10:color(display-p3 .725 .954 .898);--mint-11:color(display-p3 .482 .825 .733);--mint-12:color(display-p3 .807 .955 .887)}}}:root,.light,.light-theme{--mint-a1:#00d5aa06;--mint-a2:#00b18a0d;--mint-a3:#00d29e22;--mint-a4:#00cc9937;--mint-a5:#00c0914c;--mint-a6:#00b08663;--mint-a7:#00a17d81;--mint-a8:#009e7fb3;--mint-a9:#00d3a579;--mint-a10:#00c39982;--mint-a11:#007763fd;--mint-a12:#00312ae9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--mint-a1:color(display-p3 .02 .804 .608/.02);--mint-a2:color(display-p3 .02 .647 .467/.044);--mint-a3:color(display-p3 .004 .761 .553/.114);--mint-a4:color(display-p3 .004 .741 .545/.181);--mint-a5:color(display-p3 .004 .678 .51/.255);--mint-a6:color(display-p3 .004 .616 .463/.334);--mint-a7:color(display-p3 .004 .549 .412/.432);--mint-a8:color(display-p3 0 .529 .392/.581);--mint-a9:color(display-p3 .004 .765 .569/.381);--mint-a10:color(display-p3 .004 .69 .51/.416);--mint-a11:color(display-p3 .203 .463 .397);--mint-a12:color(display-p3 .136 .259 .236)}}}.dark,.dark-theme{--mint-a1:#00dede05;--mint-a2:#00f9f90b;--mint-a3:#00fff61d;--mint-a4:#00fff42c;--mint-a5:#00fff23a;--mint-a6:#0effeb4a;--mint-a7:#34fde55e;--mint-a8:#41ffdf76;--mint-a9:#92ffe7e9;--mint-a10:#aefeedf5;--mint-a11:#67ffded2;--mint-a12:#cbfee9f5}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mint-a1:color(display-p3 0 .992 .992/.017);--mint-a2:color(display-p3 .071 .98 .98/.043);--mint-a3:color(display-p3 .176 .996 .996/.11);--mint-a4:color(display-p3 .071 .996 .973/.169);--mint-a5:color(display-p3 .243 1 .949/.223);--mint-a6:color(display-p3 .369 1 .933/.286);--mint-a7:color(display-p3 .459 1 .914/.362);--mint-a8:color(display-p3 .49 1 .89/.454);--mint-a9:color(display-p3 .678 .996 .914/.904);--mint-a10:color(display-p3 .761 1 .941/.95);--mint-a11:color(display-p3 .482 .825 .733);--mint-a12:color(display-p3 .807 .955 .887)}}}:root,.light,.light-theme{--lime-1:#fcfdfa;--lime-2:#f8faf3;--lime-3:#eef6d6;--lime-4:#e2f0bd;--lime-5:#d3e7a6;--lime-6:#c2da91;--lime-7:#abc978;--lime-8:#8db654;--lime-9:#bdee63;--lime-10:#b0e64c;--lime-11:#5c7c2f;--lime-12:#37401c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--lime-1:color(display-p3 .989 .992 .981);--lime-2:color(display-p3 .975 .98 .954);--lime-3:color(display-p3 .939 .965 .851);--lime-4:color(display-p3 .896 .94 .76);--lime-5:color(display-p3 .843 .903 .678);--lime-6:color(display-p3 .778 .852 .599);--lime-7:color(display-p3 .694 .784 .508);--lime-8:color(display-p3 .585 .707 .378);--lime-9:color(display-p3 .78 .928 .466);--lime-10:color(display-p3 .734 .896 .397);--lime-11:color(display-p3 .386 .482 .227);--lime-12:color(display-p3 .222 .25 .128)}}}.dark,.dark-theme{--lime-1:#11130c;--lime-2:#151a10;--lime-3:#1f2917;--lime-4:#29371d;--lime-5:#334423;--lime-6:#3d522a;--lime-7:#496231;--lime-8:#577538;--lime-9:#bdee63;--lime-10:#d4ff70;--lime-11:#bde56c;--lime-12:#e3f7ba}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--lime-1:color(display-p3 .067 .073 .048);--lime-2:color(display-p3 .086 .1 .067);--lime-3:color(display-p3 .13 .16 .099);--lime-4:color(display-p3 .172 .214 .126);--lime-5:color(display-p3 .213 .266 .153);--lime-6:color(display-p3 .257 .321 .182);--lime-7:color(display-p3 .307 .383 .215);--lime-8:color(display-p3 .365 .456 .25);--lime-9:color(display-p3 .78 .928 .466);--lime-10:color(display-p3 .865 .995 .519);--lime-11:color(display-p3 .771 .893 .485);--lime-12:color(display-p3 .905 .966 .753)}}}:root,.light,.light-theme{--lime-a1:#66990005;--lime-a2:#6b95000c;--lime-a3:#96c80029;--lime-a4:#8fc60042;--lime-a5:#81bb0059;--lime-a6:#72aa006e;--lime-a7:#61990087;--lime-a8:#559200ab;--lime-a9:#93e4009c;--lime-a10:#8fdc00b3;--lime-a11:#375f00d0;--lime-a12:#1e2900e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--lime-a1:color(display-p3 .412 .608 .02/.02);--lime-a2:color(display-p3 .514 .592 .024/.048);--lime-a3:color(display-p3 .584 .765 .008/.15);--lime-a4:color(display-p3 .561 .757 .004/.24);--lime-a5:color(display-p3 .514 .698 .004/.322);--lime-a6:color(display-p3 .443 .627 0/.4);--lime-a7:color(display-p3 .376 .561 .004/.491);--lime-a8:color(display-p3 .333 .529 0/.624);--lime-a9:color(display-p3 .588 .867 0/.534);--lime-a10:color(display-p3 .561 .827 0/.604);--lime-a11:color(display-p3 .386 .482 .227);--lime-a12:color(display-p3 .222 .25 .128)}}}.dark,.dark-theme{--lime-a1:#11bb0003;--lime-a2:#78f7000a;--lime-a3:#9bfd4c1a;--lime-a4:#a7fe5c29;--lime-a5:#affe6537;--lime-a6:#b2fe6d46;--lime-a7:#b6ff6f57;--lime-a8:#b6fd6d6c;--lime-a9:#caff69ed;--lime-a10:#d4ff70;--lime-a11:#d1fe77e4;--lime-a12:#e9febff7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--lime-a1:color(display-p3 .067 .941 0/.009);--lime-a2:color(display-p3 .584 .996 .071/.038);--lime-a3:color(display-p3 .69 1 .38/.101);--lime-a4:color(display-p3 .729 1 .435/.16);--lime-a5:color(display-p3 .745 1 .471/.215);--lime-a6:color(display-p3 .769 1 .482/.274);--lime-a7:color(display-p3 .769 1 .506/.341);--lime-a8:color(display-p3 .784 1 .51/.416);--lime-a9:color(display-p3 .839 1 .502/.925);--lime-a10:color(display-p3 .871 1 .522/.996);--lime-a11:color(display-p3 .771 .893 .485);--lime-a12:color(display-p3 .905 .966 .753)}}}:root,.light,.light-theme{--yellow-1:#fdfdf9;--yellow-2:#fefce9;--yellow-3:#fffab8;--yellow-4:#fff394;--yellow-5:#ffe770;--yellow-6:#f3d768;--yellow-7:#e4c767;--yellow-8:#d5ae39;--yellow-9:#ffe629;--yellow-10:#ffdc00;--yellow-11:#9e6c00;--yellow-12:#473b1f}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--yellow-1:color(display-p3 .992 .992 .978);--yellow-2:color(display-p3 .995 .99 .922);--yellow-3:color(display-p3 .997 .982 .749);--yellow-4:color(display-p3 .992 .953 .627);--yellow-5:color(display-p3 .984 .91 .51);--yellow-6:color(display-p3 .934 .847 .474);--yellow-7:color(display-p3 .876 .785 .46);--yellow-8:color(display-p3 .811 .689 .313);--yellow-9:color(display-p3 1 .92 .22);--yellow-10:color(display-p3 .977 .868 .291);--yellow-11:color(display-p3 .6 .44 0);--yellow-12:color(display-p3 .271 .233 .137)}}}.dark,.dark-theme{--yellow-1:#14120b;--yellow-2:#1b180f;--yellow-3:#2d2305;--yellow-4:#362b00;--yellow-5:#433500;--yellow-6:#524202;--yellow-7:#665417;--yellow-8:#836a21;--yellow-9:#ffe629;--yellow-10:#ffff57;--yellow-11:#f5e147;--yellow-12:#f6eeb4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--yellow-1:color(display-p3 .078 .069 .047);--yellow-2:color(display-p3 .103 .094 .063);--yellow-3:color(display-p3 .168 .137 .039);--yellow-4:color(display-p3 .209 .169 0);--yellow-5:color(display-p3 .255 .209 0);--yellow-6:color(display-p3 .31 .261 .07);--yellow-7:color(display-p3 .389 .331 .135);--yellow-8:color(display-p3 .497 .42 .182);--yellow-9:color(display-p3 1 .92 .22);--yellow-10:color(display-p3 1 1 .456);--yellow-11:color(display-p3 .948 .885 .392);--yellow-12:color(display-p3 .959 .934 .731)}}}:root,.light,.light-theme{--yellow-a1:#aaaa0006;--yellow-a2:#f4dd0016;--yellow-a3:#ffee0047;--yellow-a4:#ffe3016b;--yellow-a5:#ffd5008f;--yellow-a6:#ebbc0097;--yellow-a7:#d2a10098;--yellow-a8:#c99700c6;--yellow-a9:#ffe100d6;--yellow-a10:#ffdc00;--yellow-a11:#9e6c00;--yellow-a12:#2e2000e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--yellow-a1:color(display-p3 .675 .675 .024/.024);--yellow-a2:color(display-p3 .953 .855 .008/.079);--yellow-a3:color(display-p3 .988 .925 .004/.251);--yellow-a4:color(display-p3 .98 .875 .004/.373);--yellow-a5:color(display-p3 .969 .816 .004/.491);--yellow-a6:color(display-p3 .875 .71 0/.526);--yellow-a7:color(display-p3 .769 .604 0/.542);--yellow-a8:color(display-p3 .725 .549 0/.687);--yellow-a9:color(display-p3 1 .898 0/.781);--yellow-a10:color(display-p3 .969 .812 0/.71);--yellow-a11:color(display-p3 .6 .44 0);--yellow-a12:color(display-p3 .271 .233 .137)}}}.dark,.dark-theme{--yellow-a1:#d1510004;--yellow-a2:#f9b4000b;--yellow-a3:#ffaa001e;--yellow-a4:#fdb70028;--yellow-a5:#febb0036;--yellow-a6:#fec40046;--yellow-a7:#fdcb225c;--yellow-a8:#fdca327b;--yellow-a9:#ffe629;--yellow-a10:#ffff57;--yellow-a11:#fee949f5;--yellow-a12:#fef6baf6}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--yellow-a1:color(display-p3 .973 .369 0/.013);--yellow-a2:color(display-p3 .996 .792 0/.038);--yellow-a3:color(display-p3 .996 .71 0/.11);--yellow-a4:color(display-p3 .996 .741 0/.152);--yellow-a5:color(display-p3 .996 .765 0/.202);--yellow-a6:color(display-p3 .996 .816 .082/.261);--yellow-a7:color(display-p3 1 .831 .263/.345);--yellow-a8:color(display-p3 1 .831 .314/.463);--yellow-a9:color(display-p3 1 .922 .22);--yellow-a10:color(display-p3 1 1 .455);--yellow-a11:color(display-p3 .948 .885 .392);--yellow-a12:color(display-p3 .959 .934 .731)}}}:root,.light,.light-theme{--amber-1:#fefdfb;--amber-2:#fefbe9;--amber-3:#fff7c2;--amber-4:#ffee9c;--amber-5:#fbe577;--amber-6:#f3d673;--amber-7:#e9c162;--amber-8:#e2a336;--amber-9:#ffc53d;--amber-10:#ffba18;--amber-11:#ab6400;--amber-12:#4f3422}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--amber-1:color(display-p3 .995 .992 .985);--amber-2:color(display-p3 .994 .986 .921);--amber-3:color(display-p3 .994 .969 .782);--amber-4:color(display-p3 .989 .937 .65);--amber-5:color(display-p3 .97 .902 .527);--amber-6:color(display-p3 .936 .844 .506);--amber-7:color(display-p3 .89 .762 .443);--amber-8:color(display-p3 .85 .65 .3);--amber-9:color(display-p3 1 .77 .26);--amber-10:color(display-p3 .959 .741 .274);--amber-11:color(display-p3 .64 .4 0);--amber-12:color(display-p3 .294 .208 .145)}}}.dark,.dark-theme{--amber-1:#16120c;--amber-2:#1d180f;--amber-3:#302008;--amber-4:#3f2700;--amber-5:#4d3000;--amber-6:#5c3d05;--amber-7:#714f19;--amber-8:#8f6424;--amber-9:#ffc53d;--amber-10:#ffd60a;--amber-11:#ffca16;--amber-12:#ffe7b3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--amber-1:color(display-p3 .082 .07 .05);--amber-2:color(display-p3 .111 .094 .064);--amber-3:color(display-p3 .178 .128 .049);--amber-4:color(display-p3 .239 .156 0);--amber-5:color(display-p3 .29 .193 0);--amber-6:color(display-p3 .344 .245 .076);--amber-7:color(display-p3 .422 .314 .141);--amber-8:color(display-p3 .535 .399 .189);--amber-9:color(display-p3 1 .77 .26);--amber-10:color(display-p3 1 .87 .15);--amber-11:color(display-p3 1 .8 .29);--amber-12:color(display-p3 .984 .909 .726)}}}:root,.light,.light-theme{--amber-a1:#c0800004;--amber-a2:#f4d10016;--amber-a3:#ffde003d;--amber-a4:#ffd40063;--amber-a5:#f8cf0088;--amber-a6:#eab5008c;--amber-a7:#dc9b009d;--amber-a8:#da8a00c9;--amber-a9:#ffb300c2;--amber-a10:#ffb300e7;--amber-a11:#ab6400;--amber-a12:#341500dd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--amber-a1:color(display-p3 .757 .514 .024/.016);--amber-a2:color(display-p3 .902 .804 .008/.079);--amber-a3:color(display-p3 .965 .859 .004/.22);--amber-a4:color(display-p3 .969 .82 .004/.35);--amber-a5:color(display-p3 .933 .796 .004/.475);--amber-a6:color(display-p3 .875 .682 .004/.495);--amber-a7:color(display-p3 .804 .573 0/.557);--amber-a8:color(display-p3 .788 .502 0/.699);--amber-a9:color(display-p3 1 .686 0/.742);--amber-a10:color(display-p3 .945 .643 0/.726);--amber-a11:color(display-p3 .64 .4 0);--amber-a12:color(display-p3 .294 .208 .145)}}}.dark,.dark-theme{--amber-a1:#e63c0006;--amber-a2:#fd9b000d;--amber-a3:#fa820022;--amber-a4:#fc820032;--amber-a5:#fd8b0041;--amber-a6:#fd9b0051;--amber-a7:#ffab2567;--amber-a8:#ffae3587;--amber-a9:#ffc53d;--amber-a10:#ffd60a;--amber-a11:#ffca16;--amber-a12:#ffe7b3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--amber-a1:color(display-p3 .992 .298 0/.017);--amber-a2:color(display-p3 .988 .651 0/.047);--amber-a3:color(display-p3 1 .6 0/.118);--amber-a4:color(display-p3 1 .557 0/.185);--amber-a5:color(display-p3 1 .592 0/.24);--amber-a6:color(display-p3 1 .659 .094/.299);--amber-a7:color(display-p3 1 .714 .263/.383);--amber-a8:color(display-p3 .996 .729 .306/.5);--amber-a9:color(display-p3 1 .769 .259);--amber-a10:color(display-p3 1 .871 .149);--amber-a11:color(display-p3 1 .8 .29);--amber-a12:color(display-p3 .984 .909 .726)}}}:root,.light,.light-theme{--gold-1:#fdfdfc;--gold-2:#faf9f2;--gold-3:#f2f0e7;--gold-4:#eae6db;--gold-5:#e1dccf;--gold-6:#d8d0bf;--gold-7:#cbc0aa;--gold-8:#b9a88d;--gold-9:#978365;--gold-10:#8c7a5e;--gold-11:#71624b;--gold-12:#3b352b}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--gold-1:color(display-p3 .992 .992 .989);--gold-2:color(display-p3 .98 .976 .953);--gold-3:color(display-p3 .947 .94 .909);--gold-4:color(display-p3 .914 .904 .865);--gold-5:color(display-p3 .88 .865 .816);--gold-6:color(display-p3 .84 .818 .756);--gold-7:color(display-p3 .788 .753 .677);--gold-8:color(display-p3 .715 .66 .565);--gold-9:color(display-p3 .579 .517 .41);--gold-10:color(display-p3 .538 .479 .38);--gold-11:color(display-p3 .433 .386 .305);--gold-12:color(display-p3 .227 .209 .173)}}}.dark,.dark-theme{--gold-1:#121211;--gold-2:#1b1a17;--gold-3:#24231f;--gold-4:#2d2b26;--gold-5:#38352e;--gold-6:#444039;--gold-7:#544f46;--gold-8:#696256;--gold-9:#978365;--gold-10:#a39073;--gold-11:#cbb99f;--gold-12:#e8e2d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gold-1:color(display-p3 .071 .071 .067);--gold-2:color(display-p3 .104 .101 .09);--gold-3:color(display-p3 .141 .136 .122);--gold-4:color(display-p3 .177 .17 .152);--gold-5:color(display-p3 .217 .207 .185);--gold-6:color(display-p3 .265 .252 .225);--gold-7:color(display-p3 .327 .31 .277);--gold-8:color(display-p3 .407 .384 .342);--gold-9:color(display-p3 .579 .517 .41);--gold-10:color(display-p3 .628 .566 .463);--gold-11:color(display-p3 .784 .728 .635);--gold-12:color(display-p3 .906 .887 .855)}}}:root,.light,.light-theme{--gold-a1:#55550003;--gold-a2:#9d8a000d;--gold-a3:#75600018;--gold-a4:#6b4e0024;--gold-a5:#60460030;--gold-a6:#64440040;--gold-a7:#63420055;--gold-a8:#633d0072;--gold-a9:#5332009a;--gold-a10:#492d00a1;--gold-a11:#362100b4;--gold-a12:#130c00d4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--gold-a1:color(display-p3 .349 .349 .024/.012);--gold-a2:color(display-p3 .592 .514 .024/.048);--gold-a3:color(display-p3 .4 .357 .012/.091);--gold-a4:color(display-p3 .357 .298 .008/.134);--gold-a5:color(display-p3 .345 .282 .004/.185);--gold-a6:color(display-p3 .341 .263 .004/.244);--gold-a7:color(display-p3 .345 .235 .004/.322);--gold-a8:color(display-p3 .345 .22 .004/.436);--gold-a9:color(display-p3 .286 .18 0/.589);--gold-a10:color(display-p3 .255 .161 0/.62);--gold-a11:color(display-p3 .433 .386 .305);--gold-a12:color(display-p3 .227 .209 .173)}}}.dark,.dark-theme{--gold-a1:#91911102;--gold-a2:#f9e29d0b;--gold-a3:#f8ecbb15;--gold-a4:#ffeec41e;--gold-a5:#feecc22a;--gold-a6:#feebcb37;--gold-a7:#ffedcd48;--gold-a8:#fdeaca5f;--gold-a9:#ffdba690;--gold-a10:#fedfb09d;--gold-a11:#fee7c6c8;--gold-a12:#fef7ede7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gold-a1:color(display-p3 .855 .855 .071/.005);--gold-a2:color(display-p3 .98 .89 .616/.043);--gold-a3:color(display-p3 1 .949 .753/.08);--gold-a4:color(display-p3 1 .933 .8/.118);--gold-a5:color(display-p3 1 .949 .804/.16);--gold-a6:color(display-p3 1 .925 .8/.215);--gold-a7:color(display-p3 1 .945 .831/.278);--gold-a8:color(display-p3 1 .937 .82/.366);--gold-a9:color(display-p3 .996 .882 .69/.551);--gold-a10:color(display-p3 1 .894 .725/.601);--gold-a11:color(display-p3 .784 .728 .635);--gold-a12:color(display-p3 .906 .887 .855)}}}:root,.light,.light-theme{--bronze-1:#fdfcfc;--bronze-2:#fdf7f5;--bronze-3:#f6edea;--bronze-4:#efe4df;--bronze-5:#e7d9d3;--bronze-6:#dfcdc5;--bronze-7:#d3bcb3;--bronze-8:#c2a499;--bronze-9:#a18072;--bronze-10:#957468;--bronze-11:#7d5e54;--bronze-12:#43302b}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--bronze-1:color(display-p3 .991 .988 .988);--bronze-2:color(display-p3 .989 .97 .961);--bronze-3:color(display-p3 .958 .932 .919);--bronze-4:color(display-p3 .929 .894 .877);--bronze-5:color(display-p3 .898 .853 .832);--bronze-6:color(display-p3 .861 .805 .778);--bronze-7:color(display-p3 .812 .739 .706);--bronze-8:color(display-p3 .741 .647 .606);--bronze-9:color(display-p3 .611 .507 .455);--bronze-10:color(display-p3 .563 .461 .414);--bronze-11:color(display-p3 .471 .373 .336);--bronze-12:color(display-p3 .251 .191 .172)}}}.dark,.dark-theme{--bronze-1:#141110;--bronze-2:#1c1917;--bronze-3:#262220;--bronze-4:#302a27;--bronze-5:#3b3330;--bronze-6:#493e3a;--bronze-7:#5a4c47;--bronze-8:#6f5f58;--bronze-9:#a18072;--bronze-10:#ae8c7e;--bronze-11:#d4b3a5;--bronze-12:#ede0d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--bronze-1:color(display-p3 .076 .067 .063);--bronze-2:color(display-p3 .106 .097 .093);--bronze-3:color(display-p3 .147 .132 .125);--bronze-4:color(display-p3 .185 .166 .156);--bronze-5:color(display-p3 .227 .202 .19);--bronze-6:color(display-p3 .278 .246 .23);--bronze-7:color(display-p3 .343 .302 .281);--bronze-8:color(display-p3 .426 .374 .347);--bronze-9:color(display-p3 .611 .507 .455);--bronze-10:color(display-p3 .66 .556 .504);--bronze-11:color(display-p3 .81 .707 .655);--bronze-12:color(display-p3 .921 .88 .854)}}}:root,.light,.light-theme{--bronze-a1:#55000003;--bronze-a2:#cc33000a;--bronze-a3:#92250015;--bronze-a4:#80280020;--bronze-a5:#7423002c;--bronze-a6:#7324003a;--bronze-a7:#6c1f004c;--bronze-a8:#671c0066;--bronze-a9:#551a008d;--bronze-a10:#4c150097;--bronze-a11:#3d0f00ab;--bronze-a12:#1d0600d4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--bronze-a1:color(display-p3 .349 .024 .024/.012);--bronze-a2:color(display-p3 .71 .22 .024/.04);--bronze-a3:color(display-p3 .482 .2 .008/.083);--bronze-a4:color(display-p3 .424 .133 .004/.122);--bronze-a5:color(display-p3 .4 .145 .004/.169);--bronze-a6:color(display-p3 .388 .125 .004/.224);--bronze-a7:color(display-p3 .365 .11 .004/.295);--bronze-a8:color(display-p3 .341 .102 .004/.393);--bronze-a9:color(display-p3 .29 .094 0/.546);--bronze-a10:color(display-p3 .255 .082 0/.585);--bronze-a11:color(display-p3 .471 .373 .336);--bronze-a12:color(display-p3 .251 .191 .172)}}}.dark,.dark-theme{--bronze-a1:#d1110004;--bronze-a2:#fbbc910c;--bronze-a3:#faceb817;--bronze-a4:#facdb622;--bronze-a5:#ffd2c12d;--bronze-a6:#ffd1c03c;--bronze-a7:#fdd0c04f;--bronze-a8:#ffd6c565;--bronze-a9:#fec7b09b;--bronze-a10:#fecab5a9;--bronze-a11:#ffd7c6d1;--bronze-a12:#fff1e9ec}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--bronze-a1:color(display-p3 .941 .067 0/.009);--bronze-a2:color(display-p3 .98 .8 .706/.043);--bronze-a3:color(display-p3 .988 .851 .761/.085);--bronze-a4:color(display-p3 .996 .839 .78/.127);--bronze-a5:color(display-p3 .996 .863 .773/.173);--bronze-a6:color(display-p3 1 .863 .796/.227);--bronze-a7:color(display-p3 1 .867 .8/.295);--bronze-a8:color(display-p3 1 .859 .788/.387);--bronze-a9:color(display-p3 1 .82 .733/.585);--bronze-a10:color(display-p3 1 .839 .761/.635);--bronze-a11:color(display-p3 .81 .707 .655);--bronze-a12:color(display-p3 .921 .88 .854)}}}:root,.light,.light-theme{--gray-1:#fcfcfc;--gray-2:#f9f9f9;--gray-3:#f0f0f0;--gray-4:#e8e8e8;--gray-5:#e0e0e0;--gray-6:#d9d9d9;--gray-7:#cecece;--gray-8:#bbb;--gray-9:#8d8d8d;--gray-10:#838383;--gray-11:#646464;--gray-12:#202020}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--gray-1:color(display-p3 .988 .988 .988);--gray-2:color(display-p3 .975 .975 .975);--gray-3:color(display-p3 .939 .939 .939);--gray-4:color(display-p3 .908 .908 .908);--gray-5:color(display-p3 .88 .88 .88);--gray-6:color(display-p3 .849 .849 .849);--gray-7:color(display-p3 .807 .807 .807);--gray-8:color(display-p3 .732 .732 .732);--gray-9:color(display-p3 .553 .553 .553);--gray-10:color(display-p3 .512 .512 .512);--gray-11:color(display-p3 .392 .392 .392);--gray-12:color(display-p3 .125 .125 .125)}}}.dark,.dark-theme{--gray-1:#111;--gray-2:#191919;--gray-3:#222;--gray-4:#2a2a2a;--gray-5:#313131;--gray-6:#3a3a3a;--gray-7:#484848;--gray-8:#606060;--gray-9:#6e6e6e;--gray-10:#7b7b7b;--gray-11:#b4b4b4;--gray-12:#eee}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gray-1:color(display-p3 .067 .067 .067);--gray-2:color(display-p3 .098 .098 .098);--gray-3:color(display-p3 .135 .135 .135);--gray-4:color(display-p3 .163 .163 .163);--gray-5:color(display-p3 .192 .192 .192);--gray-6:color(display-p3 .228 .228 .228);--gray-7:color(display-p3 .283 .283 .283);--gray-8:color(display-p3 .375 .375 .375);--gray-9:color(display-p3 .431 .431 .431);--gray-10:color(display-p3 .484 .484 .484);--gray-11:color(display-p3 .706 .706 .706);--gray-12:color(display-p3 .933 .933 .933)}}}:root,.light,.light-theme{--gray-a1:#00000003;--gray-a2:#00000006;--gray-a3:#0000000f;--gray-a4:#00000017;--gray-a5:#0000001f;--gray-a6:#00000026;--gray-a7:#00000031;--gray-a8:#0004;--gray-a9:#00000072;--gray-a10:#0000007c;--gray-a11:#0000009b;--gray-a12:#000000df}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--gray-a1:color(display-p3 0 0 0/.012);--gray-a2:color(display-p3 0 0 0/.024);--gray-a3:color(display-p3 0 0 0/.063);--gray-a4:color(display-p3 0 0 0/.09);--gray-a5:color(display-p3 0 0 0/.122);--gray-a6:color(display-p3 0 0 0/.153);--gray-a7:color(display-p3 0 0 0/.192);--gray-a8:color(display-p3 0 0 0/.267);--gray-a9:color(display-p3 0 0 0/.447);--gray-a10:color(display-p3 0 0 0/.486);--gray-a11:color(display-p3 0 0 0/.608);--gray-a12:color(display-p3 0 0 0/.875)}}}.dark,.dark-theme{--gray-a1:#0000;--gray-a2:#ffffff09;--gray-a3:#ffffff12;--gray-a4:#ffffff1b;--gray-a5:#fff2;--gray-a6:#ffffff2c;--gray-a7:#ffffff3b;--gray-a8:#fff5;--gray-a9:#ffffff64;--gray-a10:#ffffff72;--gray-a11:#ffffffaf;--gray-a12:#ffffffed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gray-a1:color(display-p3 0 0 0/0);--gray-a2:color(display-p3 1 1 1/.034);--gray-a3:color(display-p3 1 1 1/.071);--gray-a4:color(display-p3 1 1 1/.105);--gray-a5:color(display-p3 1 1 1/.134);--gray-a6:color(display-p3 1 1 1/.172);--gray-a7:color(display-p3 1 1 1/.231);--gray-a8:color(display-p3 1 1 1/.332);--gray-a9:color(display-p3 1 1 1/.391);--gray-a10:color(display-p3 1 1 1/.445);--gray-a11:color(display-p3 1 1 1/.685);--gray-a12:color(display-p3 1 1 1/.929)}}}:root,.light,.light-theme{--mauve-1:#fdfcfd;--mauve-2:#faf9fb;--mauve-3:#f2eff3;--mauve-4:#eae7ec;--mauve-5:#e3dfe6;--mauve-6:#dbd8e0;--mauve-7:#d0cdd7;--mauve-8:#bcbac7;--mauve-9:#8e8c99;--mauve-10:#84828e;--mauve-11:#65636d;--mauve-12:#211f26}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--mauve-1:color(display-p3 .991 .988 .992);--mauve-2:color(display-p3 .98 .976 .984);--mauve-3:color(display-p3 .946 .938 .952);--mauve-4:color(display-p3 .915 .906 .925);--mauve-5:color(display-p3 .886 .876 .901);--mauve-6:color(display-p3 .856 .846 .875);--mauve-7:color(display-p3 .814 .804 .84);--mauve-8:color(display-p3 .735 .728 .777);--mauve-9:color(display-p3 .555 .549 .596);--mauve-10:color(display-p3 .514 .508 .552);--mauve-11:color(display-p3 .395 .388 .424);--mauve-12:color(display-p3 .128 .122 .147)}}}.dark,.dark-theme{--mauve-1:#121113;--mauve-2:#1a191b;--mauve-3:#232225;--mauve-4:#2b292d;--mauve-5:#323035;--mauve-6:#3c393f;--mauve-7:#49474e;--mauve-8:#625f69;--mauve-9:#6f6d78;--mauve-10:#7c7a85;--mauve-11:#b5b2bc;--mauve-12:#eeeef0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mauve-1:color(display-p3 .07 .067 .074);--mauve-2:color(display-p3 .101 .098 .105);--mauve-3:color(display-p3 .138 .134 .144);--mauve-4:color(display-p3 .167 .161 .175);--mauve-5:color(display-p3 .196 .189 .206);--mauve-6:color(display-p3 .232 .225 .245);--mauve-7:color(display-p3 .286 .277 .302);--mauve-8:color(display-p3 .383 .373 .408);--mauve-9:color(display-p3 .434 .428 .467);--mauve-10:color(display-p3 .487 .48 .519);--mauve-11:color(display-p3 .707 .7 .735);--mauve-12:color(display-p3 .933 .933 .94)}}}:root,.light,.light-theme{--mauve-a1:#55005503;--mauve-a2:#2b005506;--mauve-a3:#30004010;--mauve-a4:#20003618;--mauve-a5:#20003820;--mauve-a6:#14003527;--mauve-a7:#10003332;--mauve-a8:#08003145;--mauve-a9:#05001d73;--mauve-a10:#0500197d;--mauve-a11:#0400119c;--mauve-a12:#020008e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--mauve-a1:color(display-p3 .349 .024 .349/.012);--mauve-a2:color(display-p3 .184 .024 .349/.024);--mauve-a3:color(display-p3 .129 .008 .255/.063);--mauve-a4:color(display-p3 .094 .012 .216/.095);--mauve-a5:color(display-p3 .098 .008 .224/.126);--mauve-a6:color(display-p3 .055 .004 .18/.153);--mauve-a7:color(display-p3 .067 .008 .184/.197);--mauve-a8:color(display-p3 .02 .004 .176/.271);--mauve-a9:color(display-p3 .02 .004 .106/.451);--mauve-a10:color(display-p3 .012 .004 .09/.491);--mauve-a11:color(display-p3 .016 0 .059/.612);--mauve-a12:color(display-p3 .008 0 .027/.879)}}}.dark,.dark-theme{--mauve-a1:#0000;--mauve-a2:#f5f4f609;--mauve-a3:#ebeaf814;--mauve-a4:#eee5f81d;--mauve-a5:#efe6fe25;--mauve-a6:#f1e6fd30;--mauve-a7:#eee9ff40;--mauve-a8:#eee7ff5d;--mauve-a9:#eae6fd6e;--mauve-a10:#ece9fd7c;--mauve-a11:#f5f1ffb7;--mauve-a12:#fdfdffef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mauve-a1:color(display-p3 0 0 0/0);--mauve-a2:color(display-p3 .996 .992 1/.034);--mauve-a3:color(display-p3 .937 .933 .992/.077);--mauve-a4:color(display-p3 .957 .918 .996/.111);--mauve-a5:color(display-p3 .937 .906 .996/.145);--mauve-a6:color(display-p3 .953 .925 .996/.183);--mauve-a7:color(display-p3 .945 .929 1/.246);--mauve-a8:color(display-p3 .937 .918 1/.361);--mauve-a9:color(display-p3 .933 .918 1/.424);--mauve-a10:color(display-p3 .941 .925 1/.479);--mauve-a11:color(display-p3 .965 .961 1/.712);--mauve-a12:color(display-p3 .992 .992 1/.937)}}}:root,.light,.light-theme{--slate-1:#fcfcfd;--slate-2:#f9f9fb;--slate-3:#f0f0f3;--slate-4:#e8e8ec;--slate-5:#e0e1e6;--slate-6:#d9d9e0;--slate-7:#cdced6;--slate-8:#b9bbc6;--slate-9:#8b8d98;--slate-10:#80838d;--slate-11:#60646c;--slate-12:#1c2024}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--slate-1:color(display-p3 .988 .988 .992);--slate-2:color(display-p3 .976 .976 .984);--slate-3:color(display-p3 .94 .941 .953);--slate-4:color(display-p3 .908 .909 .925);--slate-5:color(display-p3 .88 .881 .901);--slate-6:color(display-p3 .85 .852 .876);--slate-7:color(display-p3 .805 .808 .838);--slate-8:color(display-p3 .727 .733 .773);--slate-9:color(display-p3 .547 .553 .592);--slate-10:color(display-p3 .503 .512 .549);--slate-11:color(display-p3 .379 .392 .421);--slate-12:color(display-p3 .113 .125 .14)}}}.dark,.dark-theme{--slate-1:#111113;--slate-2:#18191b;--slate-3:#212225;--slate-4:#272a2d;--slate-5:#2e3135;--slate-6:#363a3f;--slate-7:#43484e;--slate-8:#5a6169;--slate-9:#696e77;--slate-10:#777b84;--slate-11:#b0b4ba;--slate-12:#edeef0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--slate-1:color(display-p3 .067 .067 .074);--slate-2:color(display-p3 .095 .098 .105);--slate-3:color(display-p3 .13 .135 .145);--slate-4:color(display-p3 .156 .163 .176);--slate-5:color(display-p3 .183 .191 .206);--slate-6:color(display-p3 .215 .226 .244);--slate-7:color(display-p3 .265 .28 .302);--slate-8:color(display-p3 .357 .381 .409);--slate-9:color(display-p3 .415 .431 .463);--slate-10:color(display-p3 .469 .483 .514);--slate-11:color(display-p3 .692 .704 .728);--slate-12:color(display-p3 .93 .933 .94)}}}:root,.light,.light-theme{--slate-a1:#00005503;--slate-a2:#00005506;--slate-a3:#0000330f;--slate-a4:#00002d17;--slate-a5:#0009321f;--slate-a6:#00002f26;--slate-a7:#00062e32;--slate-a8:#00083046;--slate-a9:#00051d74;--slate-a10:#00071b7f;--slate-a11:#0007149f;--slate-a12:#000509e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--slate-a1:color(display-p3 .024 .024 .349/.012);--slate-a2:color(display-p3 .024 .024 .349/.024);--slate-a3:color(display-p3 .004 .004 .204/.059);--slate-a4:color(display-p3 .012 .012 .184/.091);--slate-a5:color(display-p3 .004 .039 .2/.122);--slate-a6:color(display-p3 .008 .008 .165/.15);--slate-a7:color(display-p3 .008 .027 .184/.197);--slate-a8:color(display-p3 .004 .031 .176/.275);--slate-a9:color(display-p3 .004 .02 .106/.455);--slate-a10:color(display-p3 .004 .027 .098/.499);--slate-a11:color(display-p3 0 .02 .063/.62);--slate-a12:color(display-p3 0 .012 .031/.887)}}}.dark,.dark-theme{--slate-a1:#0000;--slate-a2:#d8f4f609;--slate-a3:#ddeaf814;--slate-a4:#d3edf81d;--slate-a5:#d9edfe25;--slate-a6:#d6ebfd30;--slate-a7:#d9edff40;--slate-a8:#d9edff5d;--slate-a9:#dfebfd6d;--slate-a10:#e5edfd7b;--slate-a11:#f1f7feb5;--slate-a12:#fcfdffef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--slate-a1:color(display-p3 0 0 0/0);--slate-a2:color(display-p3 .875 .992 1/.034);--slate-a3:color(display-p3 .882 .933 .992/.077);--slate-a4:color(display-p3 .882 .953 .996/.111);--slate-a5:color(display-p3 .878 .929 .996/.145);--slate-a6:color(display-p3 .882 .949 .996/.183);--slate-a7:color(display-p3 .882 .929 1/.246);--slate-a8:color(display-p3 .871 .937 1/.361);--slate-a9:color(display-p3 .898 .937 1/.42);--slate-a10:color(display-p3 .918 .945 1/.475);--slate-a11:color(display-p3 .949 .969 .996/.708);--slate-a12:color(display-p3 .988 .992 1/.937)}}}:root,.light,.light-theme{--sage-1:#fbfdfc;--sage-2:#f7f9f8;--sage-3:#eef1f0;--sage-4:#e6e9e8;--sage-5:#dfe2e0;--sage-6:#d7dad9;--sage-7:#cbcfcd;--sage-8:#b8bcba;--sage-9:#868e8b;--sage-10:#7c8481;--sage-11:#5f6563;--sage-12:#1a211e}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sage-1:color(display-p3 .986 .992 .988);--sage-2:color(display-p3 .97 .977 .974);--sage-3:color(display-p3 .935 .944 .94);--sage-4:color(display-p3 .904 .913 .909);--sage-5:color(display-p3 .875 .885 .88);--sage-6:color(display-p3 .844 .854 .849);--sage-7:color(display-p3 .8 .811 .806);--sage-8:color(display-p3 .725 .738 .732);--sage-9:color(display-p3 .531 .556 .546);--sage-10:color(display-p3 .492 .515 .506);--sage-11:color(display-p3 .377 .395 .389);--sage-12:color(display-p3 .107 .129 .118)}}}.dark,.dark-theme{--sage-1:#101211;--sage-2:#171918;--sage-3:#202221;--sage-4:#272a29;--sage-5:#2e3130;--sage-6:#373b39;--sage-7:#444947;--sage-8:#5b625f;--sage-9:#63706b;--sage-10:#717d79;--sage-11:#adb5b2;--sage-12:#eceeed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sage-1:color(display-p3 .064 .07 .067);--sage-2:color(display-p3 .092 .098 .094);--sage-3:color(display-p3 .128 .135 .131);--sage-4:color(display-p3 .155 .164 .159);--sage-5:color(display-p3 .183 .193 .188);--sage-6:color(display-p3 .218 .23 .224);--sage-7:color(display-p3 .269 .285 .277);--sage-8:color(display-p3 .362 .382 .373);--sage-9:color(display-p3 .398 .438 .421);--sage-10:color(display-p3 .453 .49 .474);--sage-11:color(display-p3 .685 .709 .697);--sage-12:color(display-p3 .927 .933 .93)}}}:root,.light,.light-theme{--sage-a1:#00804004;--sage-a2:#00402008;--sage-a3:#002d1e11;--sage-a4:#001f1519;--sage-a5:#00180820;--sage-a6:#00140d28;--sage-a7:#00140a34;--sage-a8:#000f0847;--sage-a9:#00110b79;--sage-a10:#00100a83;--sage-a11:#000a07a0;--sage-a12:#000805e5}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sage-a1:color(display-p3 .024 .514 .267/.016);--sage-a2:color(display-p3 .02 .267 .145/.032);--sage-a3:color(display-p3 .008 .184 .125/.067);--sage-a4:color(display-p3 .012 .094 .051/.095);--sage-a5:color(display-p3 .008 .098 .035/.126);--sage-a6:color(display-p3 .004 .078 .027/.157);--sage-a7:color(display-p3 0 .059 .039/.2);--sage-a8:color(display-p3 .004 .047 .031/.275);--sage-a9:color(display-p3 .004 .059 .035/.471);--sage-a10:color(display-p3 0 .047 .031/.51);--sage-a11:color(display-p3 0 .031 .02/.624);--sage-a12:color(display-p3 0 .027 .012/.895)}}}.dark,.dark-theme{--sage-a1:#0000;--sage-a2:#f0f2f108;--sage-a3:#f3f5f412;--sage-a4:#f2fefd1a;--sage-a5:#f1fbfa22;--sage-a6:#edfbf42d;--sage-a7:#edfcf73c;--sage-a8:#ebfdf657;--sage-a9:#dffdf266;--sage-a10:#e5fdf674;--sage-a11:#f4fefbb0;--sage-a12:#fdfffeed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sage-a1:color(display-p3 0 0 0/0);--sage-a2:color(display-p3 .976 .988 .984/.03);--sage-a3:color(display-p3 .992 .945 .941/.072);--sage-a4:color(display-p3 .988 .996 .992/.102);--sage-a5:color(display-p3 .992 1 .996/.131);--sage-a6:color(display-p3 .973 1 .976/.173);--sage-a7:color(display-p3 .957 1 .976/.233);--sage-a8:color(display-p3 .957 1 .984/.334);--sage-a9:color(display-p3 .902 1 .957/.397);--sage-a10:color(display-p3 .929 1 .973/.452);--sage-a11:color(display-p3 .969 1 .988/.688);--sage-a12:color(display-p3 .992 1 .996/.929)}}}:root,.light,.light-theme{--olive-1:#fcfdfc;--olive-2:#f8faf8;--olive-3:#eff1ef;--olive-4:#e7e9e7;--olive-5:#dfe2df;--olive-6:#d7dad7;--olive-7:#cccfcc;--olive-8:#b9bcb8;--olive-9:#898e87;--olive-10:#7f847d;--olive-11:#60655f;--olive-12:#1d211c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--olive-1:color(display-p3 .989 .992 .989);--olive-2:color(display-p3 .974 .98 .973);--olive-3:color(display-p3 .939 .945 .937);--olive-4:color(display-p3 .907 .914 .905);--olive-5:color(display-p3 .878 .885 .875);--olive-6:color(display-p3 .846 .855 .843);--olive-7:color(display-p3 .803 .812 .8);--olive-8:color(display-p3 .727 .738 .723);--olive-9:color(display-p3 .541 .556 .532);--olive-10:color(display-p3 .5 .515 .491);--olive-11:color(display-p3 .38 .395 .374);--olive-12:color(display-p3 .117 .129 .111)}}}.dark,.dark-theme{--olive-1:#111210;--olive-2:#181917;--olive-3:#212220;--olive-4:#282a27;--olive-5:#2f312e;--olive-6:#383a36;--olive-7:#454843;--olive-8:#5c625b;--olive-9:#687066;--olive-10:#767d74;--olive-11:#afb5ad;--olive-12:#eceeec}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--olive-1:color(display-p3 .067 .07 .063);--olive-2:color(display-p3 .095 .098 .091);--olive-3:color(display-p3 .131 .135 .126);--olive-4:color(display-p3 .158 .163 .153);--olive-5:color(display-p3 .186 .192 .18);--olive-6:color(display-p3 .221 .229 .215);--olive-7:color(display-p3 .273 .284 .266);--olive-8:color(display-p3 .365 .382 .359);--olive-9:color(display-p3 .414 .438 .404);--olive-10:color(display-p3 .467 .49 .458);--olive-11:color(display-p3 .69 .709 .682);--olive-12:color(display-p3 .927 .933 .926)}}}:root,.light,.light-theme{--olive-a1:#00550003;--olive-a2:#00490007;--olive-a3:#00200010;--olive-a4:#00160018;--olive-a5:#00180020;--olive-a6:#00140028;--olive-a7:#000f0033;--olive-a8:#040f0047;--olive-a9:#050f0078;--olive-a10:#040e0082;--olive-a11:#020a00a0;--olive-a12:#010600e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--olive-a1:color(display-p3 .024 .349 .024/.012);--olive-a2:color(display-p3 .024 .302 .024/.028);--olive-a3:color(display-p3 .008 .129 .008/.063);--olive-a4:color(display-p3 .012 .094 .012/.095);--olive-a5:color(display-p3 .035 .098 .008/.126);--olive-a6:color(display-p3 .027 .078 .004/.157);--olive-a7:color(display-p3 .02 .059 0/.2);--olive-a8:color(display-p3 .02 .059 .004/.279);--olive-a9:color(display-p3 .02 .051 .004/.467);--olive-a10:color(display-p3 .024 .047 0/.51);--olive-a11:color(display-p3 .012 .039 0/.628);--olive-a12:color(display-p3 .008 .024 0/.891)}}}.dark,.dark-theme{--olive-a1:#0000;--olive-a2:#f1f2f008;--olive-a3:#f4f5f312;--olive-a4:#f3fef21a;--olive-a5:#f2fbf122;--olive-a6:#f4faed2c;--olive-a7:#f2fced3b;--olive-a8:#edfdeb57;--olive-a9:#ebfde766;--olive-a10:#f0fdec74;--olive-a11:#f6fef4b0;--olive-a12:#fdfffded}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--olive-a1:color(display-p3 0 0 0/0);--olive-a2:color(display-p3 .984 .988 .976/.03);--olive-a3:color(display-p3 .992 .996 .988/.068);--olive-a4:color(display-p3 .953 .996 .949/.102);--olive-a5:color(display-p3 .969 1 .965/.131);--olive-a6:color(display-p3 .973 1 .969/.169);--olive-a7:color(display-p3 .98 1 .961/.228);--olive-a8:color(display-p3 .961 1 .957/.334);--olive-a9:color(display-p3 .949 1 .922/.397);--olive-a10:color(display-p3 .953 1 .941/.452);--olive-a11:color(display-p3 .976 1 .965/.688);--olive-a12:color(display-p3 .992 1 .992/.929)}}}:root,.light,.light-theme{--sand-1:#fdfdfc;--sand-2:#f9f9f8;--sand-3:#f1f0ef;--sand-4:#e9e8e6;--sand-5:#e2e1de;--sand-6:#dad9d6;--sand-7:#cfceca;--sand-8:#bcbbb5;--sand-9:#8d8d86;--sand-10:#82827c;--sand-11:#63635e;--sand-12:#21201c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sand-1:color(display-p3 .992 .992 .989);--sand-2:color(display-p3 .977 .977 .973);--sand-3:color(display-p3 .943 .942 .936);--sand-4:color(display-p3 .913 .912 .903);--sand-5:color(display-p3 .885 .883 .873);--sand-6:color(display-p3 .854 .852 .839);--sand-7:color(display-p3 .813 .81 .794);--sand-8:color(display-p3 .738 .734 .713);--sand-9:color(display-p3 .553 .553 .528);--sand-10:color(display-p3 .511 .511 .488);--sand-11:color(display-p3 .388 .388 .37);--sand-12:color(display-p3 .129 .126 .111)}}}.dark,.dark-theme{--sand-1:#111110;--sand-2:#191918;--sand-3:#222221;--sand-4:#2a2a28;--sand-5:#31312e;--sand-6:#3b3a37;--sand-7:#494844;--sand-8:#62605b;--sand-9:#6f6d66;--sand-10:#7c7b74;--sand-11:#b5b3ad;--sand-12:#eeeeec}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sand-1:color(display-p3 .067 .067 .063);--sand-2:color(display-p3 .098 .098 .094);--sand-3:color(display-p3 .135 .135 .129);--sand-4:color(display-p3 .164 .163 .156);--sand-5:color(display-p3 .193 .192 .183);--sand-6:color(display-p3 .23 .229 .217);--sand-7:color(display-p3 .285 .282 .267);--sand-8:color(display-p3 .384 .378 .357);--sand-9:color(display-p3 .434 .428 .403);--sand-10:color(display-p3 .487 .481 .456);--sand-11:color(display-p3 .707 .703 .68);--sand-12:color(display-p3 .933 .933 .926)}}}:root,.light,.light-theme{--sand-a1:#55550003;--sand-a2:#25250007;--sand-a3:#20100010;--sand-a4:#1f150019;--sand-a5:#1f180021;--sand-a6:#19130029;--sand-a7:#19140035;--sand-a8:#1915014a;--sand-a9:#0f0f0079;--sand-a10:#0c0c0083;--sand-a11:#080800a1;--sand-a12:#060500e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sand-a1:color(display-p3 .349 .349 .024/.012);--sand-a2:color(display-p3 .161 .161 .024/.028);--sand-a3:color(display-p3 .067 .067 .008/.063);--sand-a4:color(display-p3 .129 .129 .012/.099);--sand-a5:color(display-p3 .098 .067 .008/.126);--sand-a6:color(display-p3 .102 .075 .004/.161);--sand-a7:color(display-p3 .098 .098 .004/.208);--sand-a8:color(display-p3 .086 .075 .004/.287);--sand-a9:color(display-p3 .051 .051 .004/.471);--sand-a10:color(display-p3 .047 .047 0/.514);--sand-a11:color(display-p3 .031 .031 0/.632);--sand-a12:color(display-p3 .024 .02 0/.891)}}}.dark,.dark-theme{--sand-a1:#0000;--sand-a2:#f4f4f309;--sand-a3:#f6f6f513;--sand-a4:#fefef31b;--sand-a5:#fbfbeb23;--sand-a6:#fffaed2d;--sand-a7:#fffbed3c;--sand-a8:#fff9eb57;--sand-a9:#fffae965;--sand-a10:#fffdee73;--sand-a11:#fffcf4b0;--sand-a12:#fffffded}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sand-a1:color(display-p3 0 0 0/0);--sand-a2:color(display-p3 .992 .992 .988/.034);--sand-a3:color(display-p3 .996 .996 .992/.072);--sand-a4:color(display-p3 .992 .992 .953/.106);--sand-a5:color(display-p3 1 1 .965/.135);--sand-a6:color(display-p3 1 .976 .929/.177);--sand-a7:color(display-p3 1 .984 .929/.236);--sand-a8:color(display-p3 1 .976 .925/.341);--sand-a9:color(display-p3 1 .98 .925/.395);--sand-a10:color(display-p3 1 .992 .933/.45);--sand-a11:color(display-p3 1 .996 .961/.685);--sand-a12:color(display-p3 1 1 .992/.929)}}}:root{--black-a1:#0000000d;--black-a2:#0000001a;--black-a3:#00000026;--black-a4:#0003;--black-a5:#0000004d;--black-a6:#0006;--black-a7:#00000080;--black-a8:#0009;--black-a9:#000000b3;--black-a10:#000c;--black-a11:#000000e6;--black-a12:#000000f2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root{--black-a1:color(display-p3 0 0 0/.05);--black-a2:color(display-p3 0 0 0/.1);--black-a3:color(display-p3 0 0 0/.15);--black-a4:color(display-p3 0 0 0/.2);--black-a5:color(display-p3 0 0 0/.3);--black-a6:color(display-p3 0 0 0/.4);--black-a7:color(display-p3 0 0 0/.5);--black-a8:color(display-p3 0 0 0/.6);--black-a9:color(display-p3 0 0 0/.7);--black-a10:color(display-p3 0 0 0/.8);--black-a11:color(display-p3 0 0 0/.9);--black-a12:color(display-p3 0 0 0/.95)}}}:root{--white-a1:#ffffff0d;--white-a2:#ffffff1a;--white-a3:#ffffff26;--white-a4:#fff3;--white-a5:#ffffff4d;--white-a6:#fff6;--white-a7:#ffffff80;--white-a8:#fff9;--white-a9:#ffffffb3;--white-a10:#fffc;--white-a11:#ffffffe6;--white-a12:#fffffff2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root{--white-a1:color(display-p3 1 1 1/.05);--white-a2:color(display-p3 1 1 1/.1);--white-a3:color(display-p3 1 1 1/.15);--white-a4:color(display-p3 1 1 1/.2);--white-a5:color(display-p3 1 1 1/.3);--white-a6:color(display-p3 1 1 1/.4);--white-a7:color(display-p3 1 1 1/.5);--white-a8:color(display-p3 1 1 1/.6);--white-a9:color(display-p3 1 1 1/.7);--white-a10:color(display-p3 1 1 1/.8);--white-a11:color(display-p3 1 1 1/.9);--white-a12:color(display-p3 1 1 1/.95)}}}:root{--tomato-contrast:white;--red-contrast:white;--ruby-contrast:white;--crimson-contrast:white;--pink-contrast:white;--plum-contrast:white;--purple-contrast:white;--violet-contrast:white;--iris-contrast:white;--indigo-contrast:white;--blue-contrast:white;--cyan-contrast:white;--teal-contrast:white;--jade-contrast:white;--green-contrast:white;--grass-contrast:white;--orange-contrast:white;--brown-contrast:white;--sky-contrast:#1c2024;--mint-contrast:#1a211e;--lime-contrast:#1d211c;--yellow-contrast:#21201c;--amber-contrast:#21201c;--gold-contrast:white;--bronze-contrast:white;--gray-contrast:white}:root,.light,.light-theme{--gray-surface:#fffc;--mauve-surface:#fffc;--slate-surface:#fffc;--sage-surface:#fffc;--olive-surface:#fffc;--sand-surface:#fffc;--tomato-surface:#fff6f5cc;--red-surface:#fff5f5cc;--ruby-surface:#fff5f6cc;--crimson-surface:#fef5f8cc;--pink-surface:#fef5facc;--plum-surface:#fdf5fdcc;--purple-surface:#faf5fecc;--violet-surface:#f9f6ffcc;--iris-surface:#f6f6ffcc;--indigo-surface:#f5f8ffcc;--blue-surface:#f1f9ffcc;--cyan-surface:#eff9facc;--teal-surface:#f0faf8cc;--jade-surface:#f1faf5cc;--green-surface:#f1faf4cc;--grass-surface:#f3faf3cc;--brown-surface:#fbf8f4cc;--bronze-surface:#fdf5f3cc;--gold-surface:#f9f8efcc;--sky-surface:#eef9fdcc;--mint-surface:#effaf8cc;--lime-surface:#f6f9f0cc;--yellow-surface:#fefbe4cc;--amber-surface:#fefae4cc;--orange-surface:#fff5e9cc}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--gray-surface:color(display-p3 1 1 1/.8);--mauve-surface:color(display-p3 1 1 1/.8);--slate-surface:color(display-p3 1 1 1/.8);--sage-surface:color(display-p3 1 1 1/.8);--olive-surface:color(display-p3 1 1 1/.8);--sand-surface:color(display-p3 1 1 1/.8);--tomato-surface:color(display-p3 .9922 .9647 .9608/.8);--red-surface:color(display-p3 .9961 .9647 .9647/.8);--ruby-surface:color(display-p3 .9961 .9647 .9647/.8);--crimson-surface:color(display-p3 .9922 .9608 .9725/.8);--pink-surface:color(display-p3 .9922 .9608 .9804/.8);--plum-surface:color(display-p3 .9843 .9647 .9843/.8);--purple-surface:color(display-p3 .9804 .9647 .9922/.8);--violet-surface:color(display-p3 .9725 .9647 .9961/.8);--iris-surface:color(display-p3 .9647 .9647 .9961/.8);--indigo-surface:color(display-p3 .9647 .9725 .9961/.8);--blue-surface:color(display-p3 .9529 .9765 .9961/.8);--cyan-surface:color(display-p3 .9412 .9765 .9804/.8);--teal-surface:color(display-p3 .9451 .9804 .9725/.8);--jade-surface:color(display-p3 .9529 .9804 .9608/.8);--green-surface:color(display-p3 .9569 .9804 .9608/.8);--grass-surface:color(display-p3 .9569 .9804 .9569/.8);--brown-surface:color(display-p3 .9843 .9725 .9569/.8);--bronze-surface:color(display-p3 .9843 .9608 .9529/.8);--gold-surface:color(display-p3 .9765 .9725 .9412/.8);--sky-surface:color(display-p3 .9412 .9765 .9843/.8);--mint-surface:color(display-p3 .9451 .9804 .9725/.8);--lime-surface:color(display-p3 .9725 .9765 .9412/.8);--yellow-surface:color(display-p3 .9961 .9922 .902/.8);--amber-surface:color(display-p3 .9922 .9843 .902/.8);--orange-surface:color(display-p3 .9961 .9608 .9176/.8)}}}.dark,.dark-theme{--gray-surface:#21212180;--mauve-surface:#22212380;--slate-surface:#1f212380;--sage-surface:#1e201f80;--olive-surface:#1f201e80;--sand-surface:#21212080;--tomato-surface:#2d191580;--red-surface:#2f151780;--ruby-surface:#2b191d80;--crimson-surface:#2f151f80;--pink-surface:#31132980;--plum-surface:#2f152f80;--purple-surface:#2b173580;--violet-surface:#25193980;--iris-surface:#1d1b3980;--indigo-surface:#171d3b80;--blue-surface:#11213d80;--cyan-surface:#11252d80;--teal-surface:#13272580;--jade-surface:#13271f80;--green-surface:#15251d80;--grass-surface:#19231b80;--brown-surface:#271f1b80;--bronze-surface:#27211d80;--gold-surface:#25231d80;--sky-surface:#13233b80;--mint-surface:#15272780;--lime-surface:#1b211580;--yellow-surface:#231f1380;--amber-surface:#271f1380;--orange-surface:#271d1380}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gray-surface:color(display-p3 .1255 .1255 .1255/.5);--mauve-surface:color(display-p3 .1333 .1255 .1333/.5);--slate-surface:color(display-p3 .1176 .1255 .1333/.5);--sage-surface:color(display-p3 .1176 .1255 .1176/.5);--olive-surface:color(display-p3 .1176 .1255 .1176/.5);--sand-surface:color(display-p3 .1255 .1255 .1255/.5);--tomato-surface:color(display-p3 .1569 .0941 .0784/.5);--red-surface:color(display-p3 .1647 .0863 .0863/.5);--ruby-surface:color(display-p3 .1569 .0941 .1098/.5);--crimson-surface:color(display-p3 .1647 .0863 .1176/.5);--pink-surface:color(display-p3 .1725 .0784 .149/.5);--plum-surface:color(display-p3 .1647 .0863 .1725/.5);--purple-surface:color(display-p3 .149 .0941 .1961/.5);--violet-surface:color(display-p3 .1333 .102 .2118/.5);--iris-surface:color(display-p3 .1098 .102 .2118/.5);--indigo-surface:color(display-p3 .0941 .1098 .2196/.5);--blue-surface:color(display-p3 .0706 .1255 .2196/.5);--cyan-surface:color(display-p3 .0784 .1412 .1725/.5);--teal-surface:color(display-p3 .0863 .149 .1412/.5);--jade-surface:color(display-p3 .0863 .149 .1176/.5);--green-surface:color(display-p3 .0941 .1412 .1098/.5);--grass-surface:color(display-p3 .102 .1333 .102/.5);--brown-surface:color(display-p3 .1412 .1176 .102/.5);--bronze-surface:color(display-p3 .1412 .1255 .1176/.5);--gold-surface:color(display-p3 .1412 .1333 .1098/.5);--sky-surface:color(display-p3 .0863 .1333 .2196/.5);--mint-surface:color(display-p3 .0941 .149 .1412/.5);--lime-surface:color(display-p3 .1098 .1255 .0784/.5);--yellow-surface:color(display-p3 .1333 .1176 .0706/.5);--amber-surface:color(display-p3 .1412 .1176 .0784/.5);--orange-surface:color(display-p3 .1412 .1098 .0706/.5)}}}[data-accent-color=tomato]{--color-surface-accent:var(--tomato-surface);--accent-1:var(--tomato-1);--accent-2:var(--tomato-2);--accent-3:var(--tomato-3);--accent-4:var(--tomato-4);--accent-5:var(--tomato-5);--accent-6:var(--tomato-6);--accent-7:var(--tomato-7);--accent-8:var(--tomato-8);--accent-9:var(--tomato-9);--accent-contrast:var(--tomato-contrast);--accent-10:var(--tomato-10);--accent-11:var(--tomato-11);--accent-12:var(--tomato-12);--accent-a1:var(--tomato-a1);--accent-a2:var(--tomato-a2);--accent-a3:var(--tomato-a3);--accent-a4:var(--tomato-a4);--accent-a5:var(--tomato-a5);--accent-a6:var(--tomato-a6);--accent-a7:var(--tomato-a7);--accent-a8:var(--tomato-a8);--accent-a9:var(--tomato-a9);--accent-a10:var(--tomato-a10);--accent-a11:var(--tomato-a11);--accent-a12:var(--tomato-a12)}[data-accent-color=red]{--color-surface-accent:var(--red-surface);--accent-1:var(--red-1);--accent-2:var(--red-2);--accent-3:var(--red-3);--accent-4:var(--red-4);--accent-5:var(--red-5);--accent-6:var(--red-6);--accent-7:var(--red-7);--accent-8:var(--red-8);--accent-9:var(--red-9);--accent-contrast:var(--red-contrast);--accent-10:var(--red-10);--accent-11:var(--red-11);--accent-12:var(--red-12);--accent-a1:var(--red-a1);--accent-a2:var(--red-a2);--accent-a3:var(--red-a3);--accent-a4:var(--red-a4);--accent-a5:var(--red-a5);--accent-a6:var(--red-a6);--accent-a7:var(--red-a7);--accent-a8:var(--red-a8);--accent-a9:var(--red-a9);--accent-a10:var(--red-a10);--accent-a11:var(--red-a11);--accent-a12:var(--red-a12)}[data-accent-color=ruby]{--color-surface-accent:var(--ruby-surface);--accent-1:var(--ruby-1);--accent-2:var(--ruby-2);--accent-3:var(--ruby-3);--accent-4:var(--ruby-4);--accent-5:var(--ruby-5);--accent-6:var(--ruby-6);--accent-7:var(--ruby-7);--accent-8:var(--ruby-8);--accent-9:var(--ruby-9);--accent-contrast:var(--ruby-contrast);--accent-10:var(--ruby-10);--accent-11:var(--ruby-11);--accent-12:var(--ruby-12);--accent-a1:var(--ruby-a1);--accent-a2:var(--ruby-a2);--accent-a3:var(--ruby-a3);--accent-a4:var(--ruby-a4);--accent-a5:var(--ruby-a5);--accent-a6:var(--ruby-a6);--accent-a7:var(--ruby-a7);--accent-a8:var(--ruby-a8);--accent-a9:var(--ruby-a9);--accent-a10:var(--ruby-a10);--accent-a11:var(--ruby-a11);--accent-a12:var(--ruby-a12)}[data-accent-color=crimson]{--color-surface-accent:var(--crimson-surface);--accent-1:var(--crimson-1);--accent-2:var(--crimson-2);--accent-3:var(--crimson-3);--accent-4:var(--crimson-4);--accent-5:var(--crimson-5);--accent-6:var(--crimson-6);--accent-7:var(--crimson-7);--accent-8:var(--crimson-8);--accent-9:var(--crimson-9);--accent-contrast:var(--crimson-contrast);--accent-10:var(--crimson-10);--accent-11:var(--crimson-11);--accent-12:var(--crimson-12);--accent-a1:var(--crimson-a1);--accent-a2:var(--crimson-a2);--accent-a3:var(--crimson-a3);--accent-a4:var(--crimson-a4);--accent-a5:var(--crimson-a5);--accent-a6:var(--crimson-a6);--accent-a7:var(--crimson-a7);--accent-a8:var(--crimson-a8);--accent-a9:var(--crimson-a9);--accent-a10:var(--crimson-a10);--accent-a11:var(--crimson-a11);--accent-a12:var(--crimson-a12)}[data-accent-color=pink]{--color-surface-accent:var(--pink-surface);--accent-1:var(--pink-1);--accent-2:var(--pink-2);--accent-3:var(--pink-3);--accent-4:var(--pink-4);--accent-5:var(--pink-5);--accent-6:var(--pink-6);--accent-7:var(--pink-7);--accent-8:var(--pink-8);--accent-9:var(--pink-9);--accent-contrast:var(--pink-contrast);--accent-10:var(--pink-10);--accent-11:var(--pink-11);--accent-12:var(--pink-12);--accent-a1:var(--pink-a1);--accent-a2:var(--pink-a2);--accent-a3:var(--pink-a3);--accent-a4:var(--pink-a4);--accent-a5:var(--pink-a5);--accent-a6:var(--pink-a6);--accent-a7:var(--pink-a7);--accent-a8:var(--pink-a8);--accent-a9:var(--pink-a9);--accent-a10:var(--pink-a10);--accent-a11:var(--pink-a11);--accent-a12:var(--pink-a12)}[data-accent-color=plum]{--color-surface-accent:var(--plum-surface);--accent-1:var(--plum-1);--accent-2:var(--plum-2);--accent-3:var(--plum-3);--accent-4:var(--plum-4);--accent-5:var(--plum-5);--accent-6:var(--plum-6);--accent-7:var(--plum-7);--accent-8:var(--plum-8);--accent-9:var(--plum-9);--accent-contrast:var(--plum-contrast);--accent-10:var(--plum-10);--accent-11:var(--plum-11);--accent-12:var(--plum-12);--accent-a1:var(--plum-a1);--accent-a2:var(--plum-a2);--accent-a3:var(--plum-a3);--accent-a4:var(--plum-a4);--accent-a5:var(--plum-a5);--accent-a6:var(--plum-a6);--accent-a7:var(--plum-a7);--accent-a8:var(--plum-a8);--accent-a9:var(--plum-a9);--accent-a10:var(--plum-a10);--accent-a11:var(--plum-a11);--accent-a12:var(--plum-a12)}[data-accent-color=purple]{--color-surface-accent:var(--purple-surface);--accent-1:var(--purple-1);--accent-2:var(--purple-2);--accent-3:var(--purple-3);--accent-4:var(--purple-4);--accent-5:var(--purple-5);--accent-6:var(--purple-6);--accent-7:var(--purple-7);--accent-8:var(--purple-8);--accent-9:var(--purple-9);--accent-contrast:var(--purple-contrast);--accent-10:var(--purple-10);--accent-11:var(--purple-11);--accent-12:var(--purple-12);--accent-a1:var(--purple-a1);--accent-a2:var(--purple-a2);--accent-a3:var(--purple-a3);--accent-a4:var(--purple-a4);--accent-a5:var(--purple-a5);--accent-a6:var(--purple-a6);--accent-a7:var(--purple-a7);--accent-a8:var(--purple-a8);--accent-a9:var(--purple-a9);--accent-a10:var(--purple-a10);--accent-a11:var(--purple-a11);--accent-a12:var(--purple-a12)}[data-accent-color=violet]{--color-surface-accent:var(--violet-surface);--accent-1:var(--violet-1);--accent-2:var(--violet-2);--accent-3:var(--violet-3);--accent-4:var(--violet-4);--accent-5:var(--violet-5);--accent-6:var(--violet-6);--accent-7:var(--violet-7);--accent-8:var(--violet-8);--accent-9:var(--violet-9);--accent-contrast:var(--violet-contrast);--accent-10:var(--violet-10);--accent-11:var(--violet-11);--accent-12:var(--violet-12);--accent-a1:var(--violet-a1);--accent-a2:var(--violet-a2);--accent-a3:var(--violet-a3);--accent-a4:var(--violet-a4);--accent-a5:var(--violet-a5);--accent-a6:var(--violet-a6);--accent-a7:var(--violet-a7);--accent-a8:var(--violet-a8);--accent-a9:var(--violet-a9);--accent-a10:var(--violet-a10);--accent-a11:var(--violet-a11);--accent-a12:var(--violet-a12)}[data-accent-color=iris]{--color-surface-accent:var(--iris-surface);--accent-1:var(--iris-1);--accent-2:var(--iris-2);--accent-3:var(--iris-3);--accent-4:var(--iris-4);--accent-5:var(--iris-5);--accent-6:var(--iris-6);--accent-7:var(--iris-7);--accent-8:var(--iris-8);--accent-9:var(--iris-9);--accent-contrast:var(--iris-contrast);--accent-10:var(--iris-10);--accent-11:var(--iris-11);--accent-12:var(--iris-12);--accent-a1:var(--iris-a1);--accent-a2:var(--iris-a2);--accent-a3:var(--iris-a3);--accent-a4:var(--iris-a4);--accent-a5:var(--iris-a5);--accent-a6:var(--iris-a6);--accent-a7:var(--iris-a7);--accent-a8:var(--iris-a8);--accent-a9:var(--iris-a9);--accent-a10:var(--iris-a10);--accent-a11:var(--iris-a11);--accent-a12:var(--iris-a12)}[data-accent-color=indigo]{--color-surface-accent:var(--indigo-surface);--accent-1:var(--indigo-1);--accent-2:var(--indigo-2);--accent-3:var(--indigo-3);--accent-4:var(--indigo-4);--accent-5:var(--indigo-5);--accent-6:var(--indigo-6);--accent-7:var(--indigo-7);--accent-8:var(--indigo-8);--accent-9:var(--indigo-9);--accent-contrast:var(--indigo-contrast);--accent-10:var(--indigo-10);--accent-11:var(--indigo-11);--accent-12:var(--indigo-12);--accent-a1:var(--indigo-a1);--accent-a2:var(--indigo-a2);--accent-a3:var(--indigo-a3);--accent-a4:var(--indigo-a4);--accent-a5:var(--indigo-a5);--accent-a6:var(--indigo-a6);--accent-a7:var(--indigo-a7);--accent-a8:var(--indigo-a8);--accent-a9:var(--indigo-a9);--accent-a10:var(--indigo-a10);--accent-a11:var(--indigo-a11);--accent-a12:var(--indigo-a12)}[data-accent-color=blue]{--color-surface-accent:var(--blue-surface);--accent-1:var(--blue-1);--accent-2:var(--blue-2);--accent-3:var(--blue-3);--accent-4:var(--blue-4);--accent-5:var(--blue-5);--accent-6:var(--blue-6);--accent-7:var(--blue-7);--accent-8:var(--blue-8);--accent-9:var(--blue-9);--accent-contrast:var(--blue-contrast);--accent-10:var(--blue-10);--accent-11:var(--blue-11);--accent-12:var(--blue-12);--accent-a1:var(--blue-a1);--accent-a2:var(--blue-a2);--accent-a3:var(--blue-a3);--accent-a4:var(--blue-a4);--accent-a5:var(--blue-a5);--accent-a6:var(--blue-a6);--accent-a7:var(--blue-a7);--accent-a8:var(--blue-a8);--accent-a9:var(--blue-a9);--accent-a10:var(--blue-a10);--accent-a11:var(--blue-a11);--accent-a12:var(--blue-a12)}[data-accent-color=cyan]{--color-surface-accent:var(--cyan-surface);--accent-1:var(--cyan-1);--accent-2:var(--cyan-2);--accent-3:var(--cyan-3);--accent-4:var(--cyan-4);--accent-5:var(--cyan-5);--accent-6:var(--cyan-6);--accent-7:var(--cyan-7);--accent-8:var(--cyan-8);--accent-9:var(--cyan-9);--accent-contrast:var(--cyan-contrast);--accent-10:var(--cyan-10);--accent-11:var(--cyan-11);--accent-12:var(--cyan-12);--accent-a1:var(--cyan-a1);--accent-a2:var(--cyan-a2);--accent-a3:var(--cyan-a3);--accent-a4:var(--cyan-a4);--accent-a5:var(--cyan-a5);--accent-a6:var(--cyan-a6);--accent-a7:var(--cyan-a7);--accent-a8:var(--cyan-a8);--accent-a9:var(--cyan-a9);--accent-a10:var(--cyan-a10);--accent-a11:var(--cyan-a11);--accent-a12:var(--cyan-a12)}[data-accent-color=teal]{--color-surface-accent:var(--teal-surface);--accent-1:var(--teal-1);--accent-2:var(--teal-2);--accent-3:var(--teal-3);--accent-4:var(--teal-4);--accent-5:var(--teal-5);--accent-6:var(--teal-6);--accent-7:var(--teal-7);--accent-8:var(--teal-8);--accent-9:var(--teal-9);--accent-contrast:var(--teal-contrast);--accent-10:var(--teal-10);--accent-11:var(--teal-11);--accent-12:var(--teal-12);--accent-a1:var(--teal-a1);--accent-a2:var(--teal-a2);--accent-a3:var(--teal-a3);--accent-a4:var(--teal-a4);--accent-a5:var(--teal-a5);--accent-a6:var(--teal-a6);--accent-a7:var(--teal-a7);--accent-a8:var(--teal-a8);--accent-a9:var(--teal-a9);--accent-a10:var(--teal-a10);--accent-a11:var(--teal-a11);--accent-a12:var(--teal-a12)}[data-accent-color=jade]{--color-surface-accent:var(--jade-surface);--accent-1:var(--jade-1);--accent-2:var(--jade-2);--accent-3:var(--jade-3);--accent-4:var(--jade-4);--accent-5:var(--jade-5);--accent-6:var(--jade-6);--accent-7:var(--jade-7);--accent-8:var(--jade-8);--accent-9:var(--jade-9);--accent-contrast:var(--jade-contrast);--accent-10:var(--jade-10);--accent-11:var(--jade-11);--accent-12:var(--jade-12);--accent-a1:var(--jade-a1);--accent-a2:var(--jade-a2);--accent-a3:var(--jade-a3);--accent-a4:var(--jade-a4);--accent-a5:var(--jade-a5);--accent-a6:var(--jade-a6);--accent-a7:var(--jade-a7);--accent-a8:var(--jade-a8);--accent-a9:var(--jade-a9);--accent-a10:var(--jade-a10);--accent-a11:var(--jade-a11);--accent-a12:var(--jade-a12)}[data-accent-color=green]{--color-surface-accent:var(--green-surface);--accent-1:var(--green-1);--accent-2:var(--green-2);--accent-3:var(--green-3);--accent-4:var(--green-4);--accent-5:var(--green-5);--accent-6:var(--green-6);--accent-7:var(--green-7);--accent-8:var(--green-8);--accent-9:var(--green-9);--accent-contrast:var(--green-contrast);--accent-10:var(--green-10);--accent-11:var(--green-11);--accent-12:var(--green-12);--accent-a1:var(--green-a1);--accent-a2:var(--green-a2);--accent-a3:var(--green-a3);--accent-a4:var(--green-a4);--accent-a5:var(--green-a5);--accent-a6:var(--green-a6);--accent-a7:var(--green-a7);--accent-a8:var(--green-a8);--accent-a9:var(--green-a9);--accent-a10:var(--green-a10);--accent-a11:var(--green-a11);--accent-a12:var(--green-a12)}[data-accent-color=grass]{--color-surface-accent:var(--grass-surface);--accent-1:var(--grass-1);--accent-2:var(--grass-2);--accent-3:var(--grass-3);--accent-4:var(--grass-4);--accent-5:var(--grass-5);--accent-6:var(--grass-6);--accent-7:var(--grass-7);--accent-8:var(--grass-8);--accent-9:var(--grass-9);--accent-contrast:var(--grass-contrast);--accent-10:var(--grass-10);--accent-11:var(--grass-11);--accent-12:var(--grass-12);--accent-a1:var(--grass-a1);--accent-a2:var(--grass-a2);--accent-a3:var(--grass-a3);--accent-a4:var(--grass-a4);--accent-a5:var(--grass-a5);--accent-a6:var(--grass-a6);--accent-a7:var(--grass-a7);--accent-a8:var(--grass-a8);--accent-a9:var(--grass-a9);--accent-a10:var(--grass-a10);--accent-a11:var(--grass-a11);--accent-a12:var(--grass-a12)}[data-accent-color=orange]{--color-surface-accent:var(--orange-surface);--accent-1:var(--orange-1);--accent-2:var(--orange-2);--accent-3:var(--orange-3);--accent-4:var(--orange-4);--accent-5:var(--orange-5);--accent-6:var(--orange-6);--accent-7:var(--orange-7);--accent-8:var(--orange-8);--accent-9:var(--orange-9);--accent-contrast:var(--orange-contrast);--accent-10:var(--orange-10);--accent-11:var(--orange-11);--accent-12:var(--orange-12);--accent-a1:var(--orange-a1);--accent-a2:var(--orange-a2);--accent-a3:var(--orange-a3);--accent-a4:var(--orange-a4);--accent-a5:var(--orange-a5);--accent-a6:var(--orange-a6);--accent-a7:var(--orange-a7);--accent-a8:var(--orange-a8);--accent-a9:var(--orange-a9);--accent-a10:var(--orange-a10);--accent-a11:var(--orange-a11);--accent-a12:var(--orange-a12)}[data-accent-color=brown]{--color-surface-accent:var(--brown-surface);--accent-1:var(--brown-1);--accent-2:var(--brown-2);--accent-3:var(--brown-3);--accent-4:var(--brown-4);--accent-5:var(--brown-5);--accent-6:var(--brown-6);--accent-7:var(--brown-7);--accent-8:var(--brown-8);--accent-9:var(--brown-9);--accent-contrast:var(--brown-contrast);--accent-10:var(--brown-10);--accent-11:var(--brown-11);--accent-12:var(--brown-12);--accent-a1:var(--brown-a1);--accent-a2:var(--brown-a2);--accent-a3:var(--brown-a3);--accent-a4:var(--brown-a4);--accent-a5:var(--brown-a5);--accent-a6:var(--brown-a6);--accent-a7:var(--brown-a7);--accent-a8:var(--brown-a8);--accent-a9:var(--brown-a9);--accent-a10:var(--brown-a10);--accent-a11:var(--brown-a11);--accent-a12:var(--brown-a12)}[data-accent-color=sky]{--color-surface-accent:var(--sky-surface);--accent-1:var(--sky-1);--accent-2:var(--sky-2);--accent-3:var(--sky-3);--accent-4:var(--sky-4);--accent-5:var(--sky-5);--accent-6:var(--sky-6);--accent-7:var(--sky-7);--accent-8:var(--sky-8);--accent-9:var(--sky-9);--accent-contrast:var(--sky-contrast);--accent-10:var(--sky-10);--accent-11:var(--sky-11);--accent-12:var(--sky-12);--accent-a1:var(--sky-a1);--accent-a2:var(--sky-a2);--accent-a3:var(--sky-a3);--accent-a4:var(--sky-a4);--accent-a5:var(--sky-a5);--accent-a6:var(--sky-a6);--accent-a7:var(--sky-a7);--accent-a8:var(--sky-a8);--accent-a9:var(--sky-a9);--accent-a10:var(--sky-a10);--accent-a11:var(--sky-a11);--accent-a12:var(--sky-a12)}[data-accent-color=mint]{--color-surface-accent:var(--mint-surface);--accent-1:var(--mint-1);--accent-2:var(--mint-2);--accent-3:var(--mint-3);--accent-4:var(--mint-4);--accent-5:var(--mint-5);--accent-6:var(--mint-6);--accent-7:var(--mint-7);--accent-8:var(--mint-8);--accent-9:var(--mint-9);--accent-contrast:var(--mint-contrast);--accent-10:var(--mint-10);--accent-11:var(--mint-11);--accent-12:var(--mint-12);--accent-a1:var(--mint-a1);--accent-a2:var(--mint-a2);--accent-a3:var(--mint-a3);--accent-a4:var(--mint-a4);--accent-a5:var(--mint-a5);--accent-a6:var(--mint-a6);--accent-a7:var(--mint-a7);--accent-a8:var(--mint-a8);--accent-a9:var(--mint-a9);--accent-a10:var(--mint-a10);--accent-a11:var(--mint-a11);--accent-a12:var(--mint-a12)}[data-accent-color=lime]{--color-surface-accent:var(--lime-surface);--accent-1:var(--lime-1);--accent-2:var(--lime-2);--accent-3:var(--lime-3);--accent-4:var(--lime-4);--accent-5:var(--lime-5);--accent-6:var(--lime-6);--accent-7:var(--lime-7);--accent-8:var(--lime-8);--accent-9:var(--lime-9);--accent-contrast:var(--lime-contrast);--accent-10:var(--lime-10);--accent-11:var(--lime-11);--accent-12:var(--lime-12);--accent-a1:var(--lime-a1);--accent-a2:var(--lime-a2);--accent-a3:var(--lime-a3);--accent-a4:var(--lime-a4);--accent-a5:var(--lime-a5);--accent-a6:var(--lime-a6);--accent-a7:var(--lime-a7);--accent-a8:var(--lime-a8);--accent-a9:var(--lime-a9);--accent-a10:var(--lime-a10);--accent-a11:var(--lime-a11);--accent-a12:var(--lime-a12)}[data-accent-color=yellow]{--color-surface-accent:var(--yellow-surface);--accent-1:var(--yellow-1);--accent-2:var(--yellow-2);--accent-3:var(--yellow-3);--accent-4:var(--yellow-4);--accent-5:var(--yellow-5);--accent-6:var(--yellow-6);--accent-7:var(--yellow-7);--accent-8:var(--yellow-8);--accent-9:var(--yellow-9);--accent-contrast:var(--yellow-contrast);--accent-10:var(--yellow-10);--accent-11:var(--yellow-11);--accent-12:var(--yellow-12);--accent-a1:var(--yellow-a1);--accent-a2:var(--yellow-a2);--accent-a3:var(--yellow-a3);--accent-a4:var(--yellow-a4);--accent-a5:var(--yellow-a5);--accent-a6:var(--yellow-a6);--accent-a7:var(--yellow-a7);--accent-a8:var(--yellow-a8);--accent-a9:var(--yellow-a9);--accent-a10:var(--yellow-a10);--accent-a11:var(--yellow-a11);--accent-a12:var(--yellow-a12)}[data-accent-color=amber]{--color-surface-accent:var(--amber-surface);--accent-1:var(--amber-1);--accent-2:var(--amber-2);--accent-3:var(--amber-3);--accent-4:var(--amber-4);--accent-5:var(--amber-5);--accent-6:var(--amber-6);--accent-7:var(--amber-7);--accent-8:var(--amber-8);--accent-9:var(--amber-9);--accent-contrast:var(--amber-contrast);--accent-10:var(--amber-10);--accent-11:var(--amber-11);--accent-12:var(--amber-12);--accent-a1:var(--amber-a1);--accent-a2:var(--amber-a2);--accent-a3:var(--amber-a3);--accent-a4:var(--amber-a4);--accent-a5:var(--amber-a5);--accent-a6:var(--amber-a6);--accent-a7:var(--amber-a7);--accent-a8:var(--amber-a8);--accent-a9:var(--amber-a9);--accent-a10:var(--amber-a10);--accent-a11:var(--amber-a11);--accent-a12:var(--amber-a12)}[data-accent-color=gold]{--color-surface-accent:var(--gold-surface);--accent-1:var(--gold-1);--accent-2:var(--gold-2);--accent-3:var(--gold-3);--accent-4:var(--gold-4);--accent-5:var(--gold-5);--accent-6:var(--gold-6);--accent-7:var(--gold-7);--accent-8:var(--gold-8);--accent-9:var(--gold-9);--accent-contrast:var(--gold-contrast);--accent-10:var(--gold-10);--accent-11:var(--gold-11);--accent-12:var(--gold-12);--accent-a1:var(--gold-a1);--accent-a2:var(--gold-a2);--accent-a3:var(--gold-a3);--accent-a4:var(--gold-a4);--accent-a5:var(--gold-a5);--accent-a6:var(--gold-a6);--accent-a7:var(--gold-a7);--accent-a8:var(--gold-a8);--accent-a9:var(--gold-a9);--accent-a10:var(--gold-a10);--accent-a11:var(--gold-a11);--accent-a12:var(--gold-a12)}[data-accent-color=bronze]{--color-surface-accent:var(--bronze-surface);--accent-1:var(--bronze-1);--accent-2:var(--bronze-2);--accent-3:var(--bronze-3);--accent-4:var(--bronze-4);--accent-5:var(--bronze-5);--accent-6:var(--bronze-6);--accent-7:var(--bronze-7);--accent-8:var(--bronze-8);--accent-9:var(--bronze-9);--accent-contrast:var(--bronze-contrast);--accent-10:var(--bronze-10);--accent-11:var(--bronze-11);--accent-12:var(--bronze-12);--accent-a1:var(--bronze-a1);--accent-a2:var(--bronze-a2);--accent-a3:var(--bronze-a3);--accent-a4:var(--bronze-a4);--accent-a5:var(--bronze-a5);--accent-a6:var(--bronze-a6);--accent-a7:var(--bronze-a7);--accent-a8:var(--bronze-a8);--accent-a9:var(--bronze-a9);--accent-a10:var(--bronze-a10);--accent-a11:var(--bronze-a11);--accent-a12:var(--bronze-a12)}[data-accent-color=gray]{--color-surface-accent:var(--gray-surface);--accent-1:var(--gray-1);--accent-2:var(--gray-2);--accent-3:var(--gray-3);--accent-4:var(--gray-4);--accent-5:var(--gray-5);--accent-6:var(--gray-6);--accent-7:var(--gray-7);--accent-8:var(--gray-8);--accent-9:var(--gray-9);--accent-contrast:var(--gray-contrast);--accent-10:var(--gray-10);--accent-11:var(--gray-11);--accent-12:var(--gray-12);--accent-a1:var(--gray-a1);--accent-a2:var(--gray-a2);--accent-a3:var(--gray-a3);--accent-a4:var(--gray-a4);--accent-a5:var(--gray-a5);--accent-a6:var(--gray-a6);--accent-a7:var(--gray-a7);--accent-a8:var(--gray-a8);--accent-a9:var(--gray-a9);--accent-a10:var(--gray-a10);--accent-a11:var(--gray-a11);--accent-a12:var(--gray-a12)}:root{--sy-f-sys:-apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Droid Sans, Helvetica Neue;--sy-f-cjk:Noto Sans;--sy-f-heading:var(--sy-f-sys), var(--sy-f-cjk), sans-serif;--sy-f-text:var(--sy-f-sys), var(--sy-f-cjk), sans-serif;--sy-f-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--sy-s-banner-height:0rem;--sy-s-navbar-height:56px;--sy-s-offset-top:calc(var(--sy-s-navbar-height) + var(--sy-s-banner-height));--sy-c-divider:var(--gray-4);--sy-c-border:var(--gray-5);--sy-c-text:var(--gray-12);--sy-c-light:var(--gray-11);--sy-c-bold:var(--slate-12);--sy-c-heading:var(--sage-12);--sy-c-link:var(--accent-9);--sy-c-link-hover:var(--accent-a11);--sy-c-background:white;--sy-c-surface:var(--gray-a2);--sy-c-overlay:var(--black-a5);--sy-c-background-contrast:black;--sy-c-background-dropback:#fffc;--sy-c-foot-text:var(--sy-c-text);--sy-c-foot-background:var(--slate-2);--sy-c-foot-divider:var(--sy-c-divider);--sy-dropdown-shadow:0 12px 32px var(--gray-a6), 0 2px 6px var(--gray-a4)}[lang^=zh-Hans],[lang=zh],[lang=zh-CN]{--sy-f-cjk:PingFang SC, Hiragino Sans GB, Noto Sans SC, Microsoft YaHei}[lang^=zh-Hant],[lang=zh-TW]{--sy-f-cjk:PingFang TC, Noto Sans TC, Microsoft JhengHei}[lang=zh-HK],[lang=zh-Hant-HK]{--sy-f-cjk:PingFang HK, Noto Sans HK, Microsoft JhengHei}[lang=ja]{--sy-f-cjk:Hiragino Sans, Noto Sans JP, Yu Gothic}[data-accent-color=sky],[data-accent-color=mint],[data-accent-color=lime],[data-accent-color=yellow],[data-accent-color=amber]{--sy-c-link:var(--accent-a10)}html.light{color-scheme:light;--sy-c-background:white;--sy-c-background-contrast:black}html.dark{color-scheme:dark;--sy-c-background:var(--slate-1);--sy-c-overlay:var(--white-a2);--sy-c-background-contrast:var(--white-a10);--sy-c-foot-background:var(--black-a11);--sy-c-foot-divider:var(--black-a12);--sy-c-background-dropback:#212328cc}html{color:var(--sy-c-text);background-color:var(--sy-c-background)}:root{--lucide-alert-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3zM12 9v4m0 4h.01'/%3E%3C/svg%3E");--lucide-arrows-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m7 15 5 5 5-5M7 9l5-5 5 5'/%3E%3C/svg%3E");--lucide-award-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='8' r='6'/%3E%3Cpath d='M15.477 12.89 17 22l-5-3-5 3 1.523-9.11'/%3E%3C/svg%3E");--lucide-bell-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9m-4.27 13a2 2 0 0 1-3.46 0'/%3E%3C/svg%3E");--lucide-bookmark-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z'/%3E%3C/svg%3E");--lucide-calendar-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='18' height='18' x='3' y='4' rx='2' ry='2'/%3E%3Cpath d='M16 2v4M8 2v4m-5 4h18'/%3E%3C/svg%3E");--lucide-check-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");--lucide-chevron-down-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-down'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");--lucide-chevron-left-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-left'%3E%3Cpath d='m15 18-6-6 6-6'/%3E%3C/svg%3E");--lucide-chevron-right-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-right'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E");--lucide-chevron-up-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-up'%3E%3Cpath d='m18 15-6-6-6 6'/%3E%3C/svg%3E");--lucide-close-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");--lucide-copy-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-copy-icon lucide-copy' viewBox='0 0 24 24'%3E%3Crect width='14' height='14' x='8' y='8' rx='2' ry='2'/%3E%3Cpath d='M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2'/%3E%3C/svg%3E");--lucide-external-link-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M13 5h6v6m0-6L5 19'/%3E%3C/svg%3E");--lucide-flame-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z'/%3E%3C/svg%3E");--lucide-git-fork-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='18' r='3'/%3E%3Ccircle cx='6' cy='6' r='3'/%3E%3Ccircle cx='18' cy='6' r='3'/%3E%3Cpath d='M18 9v1a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V9m6 3v3'/%3E%3C/svg%3E");--lucide-help-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3m.08 4h.01'/%3E%3C/svg%3E");--lucide-languages-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-languages'%3E%3Cpath d='m5 8 6 6m-7 0 6-6 2-3M2 5h12M7 2h1m14 20-5-10-5 10m2-4h6'/%3E%3C/svg%3E");--lucide-laptop-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='18' height='12' x='3' y='4' rx='2' ry='2'/%3E%3Cpath d='M2 20h20'/%3E%3C/svg%3E");--lucide-link-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71'/%3E%3Cpath d='M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71'/%3E%3C/svg%3E");--lucide-loader-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-loader-icon lucide-loader' viewBox='0 0 24 24'%3E%3Cpath d='M12 2v4M16.2 7.8l2.9-2.9M18 12h4M16.2 16.2l2.9 2.9M12 18v4M4.9 19.1l2.9-2.9M2 12h4M4.9 4.9l2.9 2.9'/%3E%3C/svg%3E");--lucide-menu-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-menu'%3E%3Cpath d='M4 12h16M4 6h16M4 18h16'/%3E%3C/svg%3E");--lucide-milestone-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M18 6H5a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h13l4-3.5L18 6zm-6 7v8m0-18v3'/%3E%3C/svg%3E");--lucide-moon-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M12 3a6.364 6.364 0 0 0 9 9 9 9 0 1 1-9-9z'/%3E%3C/svg%3E");--lucide-outdent-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m7 8-4 4 4 4m14-4H11m10-6H11m10 12H11'/%3E%3C/svg%3E");--lucide-rocket-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09zM12 15l-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z'/%3E%3Cpath d='M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0m1 7v5s3.03-.55 4-2c1.08-1.62 0-5 0-5'/%3E%3C/svg%3E");--lucide-skull-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='9' cy='12' r='1'/%3E%3Ccircle cx='15' cy='12' r='1'/%3E%3Cpath d='M8 20v2h8v-2m-3.5-3-.5-1-.5 1h1z'/%3E%3Cpath d='M16 20a2 2 0 0 0 1.56-3.25 8 8 0 1 0-11.12 0A2 2 0 0 0 8 20'/%3E%3C/svg%3E");--lucide-star-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'/%3E%3C/svg%3E");--lucide-sun-moon-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-sun-moon-icon lucide-sun-moon' viewBox='0 0 24 24'%3E%3Cpath d='M12 2v2M14.837 16.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715M16 12a4 4 0 0 0-4-4M19 5l-1.256 1.256M20 12h2'/%3E%3C/svg%3E");--lucide-sun-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32 1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/svg%3E");--lucide-zap-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M13 2 3 14h9l-1 8 10-12h-9l1-8z'/%3E%3C/svg%3E")}.i-lucide.alert{--icon-url:var(--lucide-alert-url)}.i-lucide.arrows{--icon-url:var(--lucide-arrows-url)}.i-lucide.award{--icon-url:var(--lucide-award-url)}.i-lucide.bell{--icon-url:var(--lucide-bell-url)}.i-lucide.bookmark{--icon-url:var(--lucide-bookmark-url)}.i-lucide.calendar{--icon-url:var(--lucide-calendar-url)}.i-lucide.check{--icon-url:var(--lucide-check-url)}.i-lucide.chevron-down{--icon-url:var(--lucide-chevron-down-url)}.i-lucide.chevron-left{--icon-url:var(--lucide-chevron-left-url)}.i-lucide.chevron-right{--icon-url:var(--lucide-chevron-right-url)}.i-lucide.chevron-up{--icon-url:var(--lucide-chevron-up-url)}.i-lucide.close{--icon-url:var(--lucide-close-url)}.i-lucide.copy{--icon-url:var(--lucide-copy-url)}.i-lucide.external-link{--icon-url:var(--lucide-external-link-url)}.i-lucide.flame{--icon-url:var(--lucide-flame-url)}.i-lucide.git-fork{--icon-url:var(--lucide-git-fork-url)}.i-lucide.help{--icon-url:var(--lucide-help-url)}.i-lucide.languages{--icon-url:var(--lucide-languages-url)}.i-lucide.laptop{--icon-url:var(--lucide-laptop-url)}.i-lucide.link{--icon-url:var(--lucide-link-url)}.i-lucide.loader{--icon-url:var(--lucide-loader-url)}.i-lucide.menu{--icon-url:var(--lucide-menu-url)}.i-lucide.milestone{--icon-url:var(--lucide-milestone-url)}.i-lucide.moon{--icon-url:var(--lucide-moon-url)}.i-lucide.outdent{--icon-url:var(--lucide-outdent-url)}.i-lucide.rocket{--icon-url:var(--lucide-rocket-url)}.i-lucide.skull{--icon-url:var(--lucide-skull-url)}.i-lucide.star{--icon-url:var(--lucide-star-url)}.i-lucide.sun-moon{--icon-url:var(--lucide-sun-moon-url)}.i-lucide.sun{--icon-url:var(--lucide-sun-url)}.i-lucide.zap{--icon-url:var(--lucide-zap-url)}:root{--simpleicons-bitbucket-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M.778 1.213a.768.768 0 0 0-.768.892l3.263 19.81c.084.5.515.868 1.022.873H19.95a.772.772 0 0 0 .77-.646l3.27-20.03a.768.768 0 0 0-.768-.891zM14.52 15.53H9.522L8.17 8.466h7.561z'/%3E%3C/svg%3E");--simpleicons-discord-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z'/%3E%3C/svg%3E");--simpleicons-git-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.546 10.93 13.067.452a1.55 1.55 0 0 0-2.188 0L8.708 2.627l2.76 2.76a1.838 1.838 0 0 1 2.327 2.341l2.658 2.66a1.838 1.838 0 0 1 1.9 3.039 1.837 1.837 0 0 1-2.6 0 1.846 1.846 0 0 1-.404-1.996L12.86 8.955v6.525c.176.086.342.203.488.348a1.848 1.848 0 0 1 0 2.6 1.844 1.844 0 0 1-2.609 0 1.834 1.834 0 0 1 0-2.598c.182-.18.387-.316.605-.406V8.835a1.834 1.834 0 0 1-.996-2.41L7.636 3.7.45 10.881c-.6.605-.6 1.584 0 2.189l10.48 10.477a1.545 1.545 0 0 0 2.186 0l10.43-10.43a1.544 1.544 0 0 0 0-2.187'/%3E%3C/svg%3E");--simpleicons-github-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E");--simpleicons-gitlab-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m23.6 9.593-.033-.086L20.3.98a.851.851 0 0 0-.336-.405.875.875 0 0 0-1 .054.875.875 0 0 0-.29.44L16.47 7.818H7.537L5.332 1.07a.857.857 0 0 0-.29-.441.875.875 0 0 0-1-.054.859.859 0 0 0-.336.405L.433 9.502l-.032.086a6.066 6.066 0 0 0 2.012 7.01l.01.009.03.021 4.977 3.727 2.462 1.863 1.5 1.132a1.008 1.008 0 0 0 1.22 0l1.499-1.132 2.461-1.863 5.006-3.75.013-.01a6.068 6.068 0 0 0 2.01-7.002z'/%3E%3C/svg%3E");--simpleicons-linkedin-url:url("data:image/svg+xml;utf8,%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3ELinkedIn%3C/title%3E%3Cpath d='M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z'/%3E%3C/svg%3E");--simpleicons-mastodon-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z'/%3E%3C/svg%3E");--simpleicons-readthedocs-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.732 0a59.316 59.316 0 0 0-4.977.218V24a62.933 62.933 0 0 1 3.619-.687c.17-.028.34-.053.509-.078.215-.033.43-.066.644-.096l.205-.03zm1.18.003V22.96a61.042 61.042 0 0 1 12.333-.213V1.485A60.859 60.859 0 0 0 8.912.003zm1.707 1.81a.59.59 0 0 1 .015 0c3.06.088 6.125.404 9.167.95a.59.59 0 0 1 .476.686.59.59 0 0 1-.569.484.59.59 0 0 1-.116-.009 60.622 60.622 0 0 0-8.992-.931.59.59 0 0 1-.573-.607.59.59 0 0 1 .592-.572zm-4.212.028a.59.59 0 0 1 .578.565.59.59 0 0 1-.564.614 59.74 59.74 0 0 0-2.355.144.59.59 0 0 1-.04.002.59.59 0 0 1-.595-.542.59.59 0 0 1 .54-.635c.8-.065 1.6-.114 2.401-.148a.59.59 0 0 1 .035 0zm4.202 2.834a.59.59 0 0 1 .015 0 61.6 61.6 0 0 1 9.167.8.59.59 0 0 1 .488.677.59.59 0 0 1-.602.494.59.59 0 0 1-.076-.006 60.376 60.376 0 0 0-8.99-.786.59.59 0 0 1-.584-.596.59.59 0 0 1 .582-.583zm-4.211.097a.59.59 0 0 1 .587.555.59.59 0 0 1-.554.622c-.786.046-1.572.107-2.356.184a.59.59 0 0 1-.04.003.59.59 0 0 1-.603-.533.59.59 0 0 1 .53-.644c.8-.078 1.599-.14 2.4-.187a.59.59 0 0 1 .036 0zM10.6 7.535a.59.59 0 0 1 .015 0c3.06-.013 6.125.204 9.167.65a.59.59 0 0 1 .498.67.59.59 0 0 1-.593.504.59.59 0 0 1-.076-.006 60.142 60.142 0 0 0-8.992-.638.59.59 0 0 1-.592-.588.59.59 0 0 1 .573-.592zm1.153 2.846a61.093 61.093 0 0 1 8.02.515.59.59 0 0 1 .509.66.59.59 0 0 1-.586.514.59.59 0 0 1-.076-.005 59.982 59.982 0 0 0-8.99-.492.59.59 0 0 1-.603-.577.59.59 0 0 1 .578-.603c.382-.008.765-.012 1.148-.012zm1.139 2.832a60.92 60.92 0 0 1 6.871.394.59.59 0 0 1 .52.652.59.59 0 0 1-.577.523.59.59 0 0 1-.076-.004 59.936 59.936 0 0 0-8.991-.344.59.59 0 0 1-.61-.568.59.59 0 0 1 .567-.611c.765-.028 1.53-.042 2.296-.042z'/%3E%3C/svg%3E");--simpleicons-reddit-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5.373 0 0 5.373 0 12c0 3.314 1.343 6.314 3.515 8.485l-2.286 2.286A.72.72 0 0 0 1.738 24H12c6.627 0 12-5.373 12-12S18.627 0 12 0Zm4.388 3.199a1.999 1.999 0 1 1-1.947 2.46v.002a2.368 2.368 0 0 0-2.032 2.341v.007c1.776.067 3.4.567 4.686 1.363a2.802 2.802 0 1 1 2.908 4.753c-.088 3.256-3.637 5.876-7.997 5.876-4.361 0-7.905-2.617-7.998-5.87a2.8 2.8 0 0 1 1.189-5.34c.645 0 1.239.218 1.712.585 1.275-.79 2.881-1.291 4.64-1.365v-.01a3.229 3.229 0 0 1 2.88-3.207 2 2 0 0 1 1.959-1.595Zm-8.085 8.376c-.784 0-1.459.78-1.506 1.797-.047 1.016.64 1.429 1.426 1.429.786 0 1.371-.369 1.418-1.385.047-1.017-.553-1.841-1.338-1.841Zm7.406 0c-.786 0-1.385.824-1.338 1.841.047 1.017.634 1.385 1.418 1.385.785 0 1.473-.413 1.426-1.429-.046-1.017-.721-1.797-1.506-1.797Zm-3.703 4.013c-.974 0-1.907.048-2.77.135a.222.222 0 0 0-.183.305 3.199 3.199 0 0 0 2.953 1.964 3.2 3.2 0 0 0 2.953-1.964.222.222 0 0 0-.184-.305 27.75 27.75 0 0 0-2.769-.135Z'/%3E%3C/svg%3E");--simpleicons-slack-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zm0-1.268a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z'/%3E%3C/svg%3E");--simpleicons-x-twitter-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z'/%3E%3C/svg%3E");--simpleicons-youtube-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z'/%3E%3C/svg%3E")}.i-icon.bitbucket,.i-simpleicons.bitbucket{--icon-url:var(--simpleicons-bitbucket-url)}.i-icon.discord,.i-simpleicons.discord{--icon-url:var(--simpleicons-discord-url)}.i-icon.git,.i-simpleicons.git{--icon-url:var(--simpleicons-git-url)}.i-icon.github,.i-simpleicons.github{--icon-url:var(--simpleicons-github-url)}.i-icon.gitlab,.i-simpleicons.gitlab{--icon-url:var(--simpleicons-gitlab-url)}.i-icon.linkedin,.i-simpleicons.linkedin{--icon-url:var(--simpleicons-linkedin-url)}.i-icon.mastodon,.i-simpleicons.mastodon{--icon-url:var(--simpleicons-mastodon-url)}.i-icon.readthedocs,.i-simpleicons.readthedocs{--icon-url:var(--simpleicons-readthedocs-url)}.i-icon.reddit,.i-simpleicons.reddit{--icon-url:var(--simpleicons-reddit-url)}.i-icon.slack,.i-simpleicons.slack{--icon-url:var(--simpleicons-slack-url)}.i-icon.x-twitter,.i-simpleicons.x-twitter{--icon-url:var(--simpleicons-x-twitter-url)}.i-icon.youtube,.i-simpleicons.youtube{--icon-url:var(--simpleicons-youtube-url)}:root{--yue-c-text:var(--sy-c-text);--yue-c-heading:var(--sy-c-heading);--yue-c-bold:var(--sy-c-bold);--yue-c-link-1:var(--sy-c-text);--yue-c-link-2:var(--sy-c-bold);--yue-c-link-border:var(--sy-c-link);--yue-c-ol-marker:var(--gray-9);--yue-c-ul-marker:var(--sage-a5);--yue-c-hr:var(--sy-c-border);--yue-c-quote:var(--sy-c-text);--yue-c-quote-border:var(--accent-a3);--yue-c-quote-symbol:var(--accent-9);--yue-c-caption:var(--sy-c-light);--yue-c-code-text:var(--accent-a11);--yue-c-code-background:var(--accent-a3);--yue-c-table-border:var(--gray-a5);--yue-c-th-background:var(--color-surface-accent);--yue-c-th-border:var(--gray-a5);--yue-c-td-border:var(--gray-a4);--yue-c-row-background:var(--sy-c-surface)}.yue{color:var(--yue-c-text);font-size:1rem;line-height:1.75}.yue p{margin-top:1rem;margin-bottom:1.25rem}.yue a{color:var(--yue-c-link-1);text-decoration:underline;-webkit-text-decoration-color:var(--yue-c-link-border);-webkit-text-decoration-color:var(--yue-c-link-border);text-decoration-color:var(--yue-c-link-border);font-weight:500;text-decoration-thickness:1px}.yue a:hover{color:var(--yue-c-link-2);text-decoration-thickness:2px}.yue pre{overflow:auto}.yue pre a,.yue pre a:hover{border-bottom:none;text-decoration:none}.yue strong{color:var(--yue-c-bold);font-weight:600}.yue a strong,.yue blockquote strong,.yue thead th strong{color:inherit}.yue ol{margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em;list-style-type:decimal}.yue ol[type="1"]{list-style-type:decimal}.yue ol[type=A],.yue ol.upperalpha{list-style-type:upper-alpha}.yue ol[type=a],.yue ol.loweralpha{list-style-type:lower-alpha}.yue ol[type=I],.yue ol.upperroman{list-style-type:upper-roman}.yue ol[type=i],.yue ol.lowerroman{list-style-type:lower-roman}.yue ul{margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em;list-style-type:disc}.yue ol>li::marker{color:var(--yue-c-ol-marker);font-weight:400}.yue ul>li::marker{color:var(--yue-c-ul-marker)}.yue dl{margin-top:1.5rem;margin-bottom:1.5rem}.yue dt{color:var(--yue-c-bold);font-weight:600}.yue dd{margin-left:1.5rem}.yue hr{border-color:var(--yue-c-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.yue blockquote{color:var(--yue-c-quote);border-left-width:.25rem;border-left-color:var(--yue-c-quote-border);margin-top:1.2rem;margin-bottom:1.2rem;padding-left:1rem}.yue blockquote .attribution{font-size:.85em;font-style:italic}[lang^=zh] .yue blockquote .attribution,[lang=ko] .yue blockquote .attribution,[lang=ja] .yue blockquote .attribution{font-style:normal}.yue h1{color:var(--yue-c-heading);margin-top:0;margin-bottom:.888889em;font-size:2.25em;font-weight:800;line-height:1.11111}.yue h1 strong{color:inherit;font-weight:900}.yue h2{color:var(--yue-c-heading);margin-top:2em;margin-bottom:1em;font-size:1.5em;font-weight:700;line-height:1.33333}.yue h2 strong{color:inherit;font-weight:800}.yue h3{color:var(--yue-c-heading);margin-top:1.6em;margin-bottom:.6em;font-size:1.25em;font-weight:600;line-height:1.6}.yue h3 strong{color:inherit;font-weight:700}.yue h4{color:var(--yue-c-heading);margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.5}.yue h4 strong{color:inherit;font-weight:700}.yue h5,.yue h6{color:var(--yue-c-heading);font-weight:600}.yue img{max-width:100%;display:inline}.yue img.rounded{border-radius:.5rem}.yue a>img,.yue figure>*,.yue figure img{margin-top:0;margin-bottom:0}.yue figcaption{color:var(--yue-c-caption);margin-top:.857143em;font-size:.875em;line-height:1.42857}.yue figcaption>p{margin-top:0}.yue code{color:var(--yue-c-code-text);font-size:.875em;font-weight:600}.yue a code,.yue h1 code,.yue h2 code,.yue h3 code,.yue h4 code,.yue blockquote code,.yue th code{color:inherit}.yue h2 code{font-size:.875em}.yue li>code,.yue p>code{background-color:var(--yue-c-code-background);border-radius:3px;padding:2px 4px;font-weight:500}.yue h3 code{font-size:.9em}.yue kbd{font-family:var(--sy-f-mono)}.yue video,.yue figure{margin-top:2em;margin-bottom:2em}.yue li{margin-top:.5em;margin-bottom:.5em}.yue ol>li,.yue ul>li{padding-left:.375em}.yue ul ul,.yue ul ol,.yue ol ul,.yue ol ol{margin-top:.75em;margin-bottom:.75em}.yue hr+*,.yue h2+*,.yue h3+*,.yue h4+*{margin-top:0}.yue table{table-layout:auto;text-align:left;width:100%;margin-top:2em;margin-bottom:2em;font-size:.86em;line-height:1.7}.yue table>caption{color:var(--yue-c-caption);margin-bottom:.4rem}.yue thead tr{border-bottom-width:1px;border-bottom-color:var(--yue-c-th-border)}.yue thead th{color:var(--yue-c-heading);vertical-align:middle;font-weight:600}.yue tbody tr{border-bottom-width:1px;border-bottom-color:var(--yue-c-td-border)}.yue tbody tr:last-child{border-bottom-width:0}.yue tbody td{vertical-align:middle}.yue tfoot{border-top-width:1px;border-top-color:var(--yue-c-th-border)}.yue tfoot td{vertical-align:top}.yue td>p{margin:.25rem 0}.yue thead th>p{margin:0}.yue thead th,.yue tbody td,.yue tfoot td{padding:.5rem}.yue section{clear:both}.yue section>div{margin-bottom:2rem}.yue dd>p:first-child{margin-top:0}.yue p.lead{color:var(--sy-c-light);margin-bottom:0;font-size:1.2rem}.yue p.lead+hr{margin-top:1rem}.yue p.rubric{color:var(--yue-c-heading);margin-top:2rem;font-weight:600}.yue .sidebar{background-color:var(--sy-c-surface);border:1px solid var(--sy-c-border);clear:right;float:right;border-radius:6px;width:30%;margin-bottom:1rem;margin-left:1rem;margin-right:0}@media (max-width:767px){.yue .sidebar{float:none;width:100%;margin-left:0}}.yue .sidebar>*{padding-left:1rem;padding-right:1rem}.yue .sidebar img{margin-top:1rem;margin-bottom:1rem}.yue .sidebar-title{border-bottom:1px solid var(--sy-c-border);margin:0;padding-top:.5rem;padding-bottom:.5rem;font-weight:500}.yue dl.simple>dd>p{margin:0}.yue ul.simple p,.yue ol.simple p{margin-top:.85rem;margin-bottom:.85rem}.yue a.headerlink{visibility:hidden;vertical-align:middle;opacity:.5;color:var(--sy-c-light);font-size:85%;font-weight:300;font-family:var(--sy-f-mono);border-bottom:none;margin-left:6px;font-style:normal;text-decoration:none;display:inline-block}.yue a.headerlink:hover{opacity:1}.yue .math-wrapper{width:100%;margin-top:2rem;margin-bottom:2rem;overflow-x:auto}.yue .math a.headerlink{opacity:1;visibility:visible}.yue a.headerlink:hover,dt:hover a.headerlink,h1:hover a.headerlink,h2:hover a.headerlink,h3:hover a.headerlink,h4:hover a.headerlink,h5:hover a.headerlink,h6:hover a.headerlink{visibility:visible}.yue a.image-reference,.yue .toctree-wrapper a{border-bottom:none;text-decoration:none}.yue .toctree-wrapper p.caption{font-size:.86rem;font-weight:500;font-family:var(--sy-f-heading);color:var(--sy-c-light);text-transform:uppercase;letter-spacing:.4px;border-bottom:1px solid var(--sy-c-divider);padding:.8rem 0 .4rem}.yue .align-left{clear:left;float:left;margin:0 1rem 1rem}.yue .align-right{clear:right;float:right;margin:0 1rem 1rem}.yue .align-center{text-align:center;margin-left:auto;margin-right:auto;display:block}.yue figure.align-center img{margin-left:auto;margin-right:auto}a.footnote-reference{vertical-align:top;font-size:.65rem}aside.footnote>span,div.citation>span{float:left;padding-right:.25rem;font-weight:500}aside.footnote>p,div.citation>p{margin-top:.5rem;margin-bottom:.5rem;margin-left:2rem}.yue kbd.kbd:not(.compound){border-radius:3px;margin-right:.25rem;padding:2px 5px;font-size:.86rem}.yue kbd.compound>kbd{margin-left:.25rem}.yue .menuselection{font-size:.86rem;font-weight:500}.light .searchbox kbd,.light .yue kbd.kbd:not(.compound){background:linear-gradient(-225deg,#e6e6e6,#f8f8f8);border:0;box-shadow:inset 0 -2px #dbdbdb,inset 0 0 1px 1px #fff,0 1px 2px 1px #50505066}.dark .searchbox kbd,.dark .yue kbd.kbd:not(.compound){background:linear-gradient(-225deg,#353434,#141414);border:0;box-shadow:inset 0 -2px #373737,inset 0 0 1px 1px #222,0 1px 2px 1px #000}.yue p.centered{text-align:center}.yue section>img{margin-bottom:1rem}.hlist td{vertical-align:top}.light .light-hidden,.dark .dark-hidden,.light .dark-only,.dark .light-only{display:none}.yue .genindex-jumpbox,.yue .modindex-jumpbox{border-top:1px solid var(--sy-c-border);border-bottom:1px solid var(--sy-c-border);padding:2px .4rem}.yue table.modindextable td:first-of-type{width:28px}.yue table.modindextable img.toggler{margin:0}.yue table.modindextable tr.cap{background:var(--sy-c-surface);font-size:1.12rem;font-family:var(--sy-f-mono)}.yue h2+table.indextable,.yue table.indextable ul{margin-top:0}:root{--attention-icon:var(--lucide-alert-url);--attention-1:var(--crimson-surface);--attention-2:var(--crimson-a3);--attention-3:var(--crimson-9);--attention-4:var(--crimson-a11);--caution-icon:var(--lucide-zap-url);--caution-1:var(--amber-surface);--caution-2:var(--amber-a3);--caution-3:var(--amber-9);--caution-4:var(--amber-11);--danger-icon:var(--lucide-skull-url);--danger-1:var(--ruby-surface);--danger-2:var(--ruby-a3);--danger-3:var(--ruby-9);--danger-4:var(--ruby-a11);--error-icon:var(--lucide-close-url);--error-1:var(--red-surface);--error-2:var(--red-a3);--error-3:var(--red-9);--error-4:var(--red-a11);--hint-icon:var(--lucide-bell-url);--hint-1:var(--cyan-surface);--hint-2:var(--cyan-a3);--hint-3:var(--cyan-9);--hint-4:var(--cyan-a11);--important-icon:var(--lucide-flame-url);--important-1:var(--violet-surface);--important-2:var(--violet-a3);--important-3:var(--violet-9);--important-4:var(--violet-a11);--note-icon:var(--lucide-calendar-url);--note-1:var(--blue-surface);--note-2:var(--blue-a3);--note-3:var(--blue-9);--note-4:var(--blue-a11);--tip-icon:var(--lucide-rocket-url);--tip-1:var(--green-surface);--tip-2:var(--green-a3);--tip-3:var(--green-9);--tip-4:var(--green-a11);--warning-icon:var(--lucide-zap-url);--warning-1:var(--orange-surface);--warning-2:var(--orange-a3);--warning-3:var(--orange-9);--warning-4:var(--orange-a11);--seealso-icon:var(--lucide-link-url);--seealso-1:var(--gold-surface);--seealso-2:var(--gold-a3);--seealso-3:var(--gold-9);--seealso-4:var(--gold-a11);--todo-icon:var(--lucide-bookmark-url);--todo-1:var(--bronze-surface);--todo-2:var(--bronze-a3);--todo-3:var(--bronze-9);--todo-4:var(--bronze-a11);--versionadded-icon:var(--lucide-flame-url);--versionadded-1:var(--green-surface);--versionadded-2:var(--green-9);--versionchanged-icon:var(--lucide-zap-url);--versionchanged-1:var(--amber-surface);--versionchanged-2:var(--amber-9);--versionremoved-icon:var(--lucide-skull-url);--versionremoved-1:var(--red-surface);--versionremoved-2:var(--red-9);--deprecated-icon:var(--lucide-alert-url);--deprecated-1:var(--orange-surface);--deprecated-2:var(--orange-9)}.admonition{--icon-url:var(--lucide-bell-url);--color-1:var(--color-surface-accent);--color-2:var(--accent-a3);--color-3:var(--accent-9);--color-4:var(--accent-a11);border-left:4px solid var(--color-3);background-color:var(--color-1);flex-direction:column;margin-top:1rem;margin-bottom:1rem;padding:.825rem 1rem;display:flex;position:relative}.admonition:before{content:"";background-color:var(--color-3);border-radius:100%;width:20px;height:20px;position:absolute;top:6px;left:-12px}.admonition:after{content:"";-webkit-mask:var(--icon-url) no-repeat;-webkit-mask:var(--icon-url) no-repeat;mask:var(--icon-url) no-repeat;background-color:#fff;width:12px;height:12px;font-style:normal;position:absolute;top:10px;left:-8px;-webkit-mask-size:100% 100%;mask-size:100% 100%}.admonition p.admonition-title{color:var(--color-4);background-color:var(--color-2);--yue-c-code:var(--color-4);--yue-c-bold:var(--color-4);margin:-.825rem -1rem .825rem -19px;padding:4px 18px;font-size:.85rem;font-weight:600;line-height:1.72;position:relative}.admonition p.admonition-title svg{display:inline-block}.admonition.attention{--icon-url:var(--attention-icon);--color-1:var(--attention-1);--color-2:var(--attention-2);--color-3:var(--attention-3);--color-4:var(--attention-4)}.admonition.caution{--icon-url:var(--caution-icon);--color-1:var(--caution-1);--color-2:var(--caution-2);--color-3:var(--caution-3);--color-4:var(--caution-4)}.admonition.danger{--icon-url:var(--danger-icon);--color-1:var(--danger-1);--color-2:var(--danger-2);--color-3:var(--danger-3);--color-4:var(--danger-4)}.admonition.error{--icon-url:var(--error-icon);--color-1:var(--error-1);--color-2:var(--error-2);--color-3:var(--error-3);--color-4:var(--error-4)}.admonition.hint{--icon-url:var(--hint-icon);--color-1:var(--hint-1);--color-2:var(--hint-2);--color-3:var(--hint-3);--color-4:var(--hint-4)}.admonition.important{--icon-url:var(--important-icon);--color-1:var(--important-1);--color-2:var(--important-2);--color-3:var(--important-3);--color-4:var(--important-4)}.admonition.note{--icon-url:var(--note-icon);--color-1:var(--note-1);--color-2:var(--note-2);--color-3:var(--note-3);--color-4:var(--note-4)}.admonition.tip{--icon-url:var(--tip-icon);--color-1:var(--tip-1);--color-2:var(--tip-2);--color-3:var(--tip-3);--color-4:var(--tip-4)}.admonition.warning{--icon-url:var(--warning-icon);--color-1:var(--warning-1);--color-2:var(--warning-2);--color-3:var(--warning-3);--color-4:var(--warning-4)}.admonition.seealso{--icon-url:var(--seealso-icon);--color-1:var(--seealso-1);--color-2:var(--seealso-2);--color-3:var(--seealso-3);--color-4:var(--seealso-4)}.admonition.admonition-todo{--icon-url:var(--todo-icon);--color-1:var(--todo-1);--color-2:var(--todo-2);--color-3:var(--todo-3);--color-4:var(--todo-4)}.yue .admonition>*{margin-top:0;margin-bottom:1rem}.yue .admonition>:last-child{margin-bottom:0!important}span.versionmodified{color:var(--sy-c-bold);font-weight:600}div.versionadded,div.versionchanged,div.versionremoved,div.deprecated{border-left:4px solid var(--color-2);background-color:var(--color-1);margin:1rem 0;padding:6px 1rem;line-height:1.72;position:relative}div.versionadded:before,div.versionchanged:before,div.versionremoved:before,div.deprecated:before{content:"";color:#fff;background-color:var(--color-2);text-align:center;width:20px;height:20px;font:normal bold 14px/20px var(--sy-f-mono);border-radius:100%;position:absolute;top:10px;left:-12px}div.versionadded:after,div.versionchanged:after,div.versionremoved:after,div.deprecated:after{content:"";-webkit-mask:var(--icon-url) no-repeat;-webkit-mask:var(--icon-url) no-repeat;mask:var(--icon-url) no-repeat;background-color:#fff;width:12px;height:12px;font-style:normal;position:absolute;top:14px;left:-8px;-webkit-mask-size:100% 100%;mask-size:100% 100%}div.versionadded{--color-1:var(--versionadded-1);--color-2:var(--versionadded-2);--icon-url:var(--versionadded-icon)}div.versionchanged{--color-1:var(--versionchanged-1);--color-2:var(--versionchanged-2);--icon-url:var(--versionchanged-icon)}div.versionremoved{--color-1:var(--versionremoved-1);--color-2:var(--versionremoved-2);--icon-url:var(--versionremoved-icon)}div.deprecated{--color-1:var(--deprecated-1);--color-2:var(--deprecated-2);--icon-url:var(--deprecated-icon)}div.versionadded>p,div.versionchanged>p,div.versionremoved>p,div.deprecated>p{margin:0}.yue blockquote.epigraph{text-align:center;border-left:0;padding:1rem 2.4rem}.yue blockquote.highlights{background-color:var(--sy-c-surface);border-left-width:4px;padding-top:.2rem;padding-bottom:.2rem}.yue blockquote.pull-quote{border-left:0;padding:2.4rem 3.6rem 1.2rem;font-size:1.24rem;position:relative}.yue blockquote.pull-quote:before{content:"“";color:var(--yue-c-quote-symbol);font:700 4rem/1 Times New Roman,Georgia,Palatino,Times,serif;position:absolute;top:0;left:.5rem}.yue blockquote.pull-quote .attribution{text-align:right}:root{--code-block-background:var(--accent-a2);--code-block-caption-background:var(--accent-a3);--code-block-highlight:var(--accent-a3);--code-block-linenos-divider:var(--gray-a6)}html.light{--syntax-text:var(--syntax-light-text);--syntax-comment:var(--syntax-light-comment)}html.dark,html.light .dark-code{--syntax-text:var(--syntax-dark-text);--syntax-comment:var(--syntax-dark-comment)}.light .dark-code{--code-block-background:var(--black-a12);--code-block-caption-background:#1c2024;--code-block-highlight:var(--white-a2);--code-block-linenos-divider:var(--white-a4)}.highlight{color:var(--syntax-text)}.highlight .hll{background-color:var(--code-block-highlight);display:block}pre.literal-block{background-color:var(--code-block-background);border-radius:6px;padding:1rem;font-size:.96rem;line-height:1.48;overflow:auto}.highlight,.literal-block-wrapper{--margin:1rem;--radius:6px}.literal-block-wrapper div[class^=highlight-]{display:flex}.literal-block-wrapper .highlight{width:100%}.highlight>pre{padding:var(--margin);font-size:.96rem;line-height:1.48;font-family:var(--sy-f-mono);background-color:var(--code-block-background);border-radius:var(--radius);overflow:auto}.win .highlight>pre{font-family:"Twemoji Country Flags", var(--sy-f-mono)}.highlight .gp,.highlight .linenos{-webkit-user-select:none;user-select:none}.highlight .linenos{box-shadow:-.05rem 0 var(--code-block-linenos-divider) inset;opacity:.6;margin-right:.8rem;padding-right:.8rem;display:inline-block}.highlight .hll{margin-left:calc(0rem - var(--margin));margin-right:calc(0rem - var(--margin));padding:0 var(--margin)}.code-block-caption{color:var(--syntax-text);background-color:var(--code-block-caption-background);padding:.4rem var(--margin);border-radius:var(--radius) var(--radius) 0 0;font-size:.84rem;font-weight:600;display:flex}.code-block-caption+div>.highlight>pre{border-top-left-radius:0;border-top-right-radius:0}div[class^=highlight]>.highlight>pre{display:grid}.yue .table-wrapper{border:1px solid var(--yue-c-table-border);border-radius:6px;width:100%;margin-top:2rem;margin-bottom:2rem;overflow-x:auto}.yue .table-wrapper table{margin:0}.yue .table-wrapper thead tr{border-top:1px solid var(--yue-c-td-border)}.yue .table-wrapper thead tr:first-child{border-top:0}.yue .table-wrapper th{background-color:var(--yue-c-th-background);border-left:1px solid var(--yue-c-td-border);padding:.725rem 1rem}.yue .table-wrapper td{border-left:1px solid var(--yue-c-td-border);padding:.5rem 1rem}.yue .table-wrapper tr>th:first-child,.yue .table-wrapper tr>td:first-child{border-left:0}.yue .table-wrapper caption{border-bottom:1px solid var(--yue-c-th-border);margin:0;padding:.5rem}.yue .table-wrapper tbody tr.row-odd{background-color:var(--yue-c-row-background)}.yue table.hlist td{vertical-align:top}.table-wrapper{scrollbar-gutter:auto;overflow-x:auto}.table-wrapper::-webkit-scrollbar{width:.75rem;height:.75rem}.table-wrapper::-webkit-scrollbar-thumb{border-radius:10px}.table-wrapper::-webkit-scrollbar-track{background-color:#0000}.table-wrapper:hover::-webkit-scrollbar-thumb{background-color:#9b9b9b33;background-clip:content-box;border:3px solid #0000}.yue table.ghost th,.yue table.ghost td{background-color:#0000;border-left:0;border-right:0}.yue table.ghost caption{border-bottom:3px solid var(--yue-c-td-border);margin-bottom:0;padding-bottom:.5rem}.yue table.ghost thead tr:first-child{border-top:0;border-bottom-width:3px}.yue .table-wrapper.ghost{border:0}.yue .table-wrapper.sphinx-datatable{overflow-x:hidden}.yue .table-wrapper:not(.ghost) .dt-layout-row{margin:0}.table-wrapper .dt-layout-row:not(.dt-layout-table){padding:.5rem 1rem}.table-wrapper .dt-layout-row.dt-layout-table{border-top:1px solid var(--yue-c-th-border);border-bottom:1px solid var(--yue-c-th-border);overflow-x:auto}.table-wrapper .dt-layout-table th,.yue .table-wrapper div.dt-container.dt-empty-footer td{border-bottom:0}.yue .table-wrapper .dt-layout-table th:hover{outline-color:var(--accent-a3)}.table-wrapper div.dt-container .dt-search input{border-color:var(--sy-c-border);font-size:.92rem;line-height:1.4}.table-wrapper div.dt-container .dt-input{border-color:var(--sy-c-border)}.table-wrapper div.dt-container .dt-paging .dt-paging-button{justify-content:center;align-items:center;width:32px;height:32px;padding:0;font-size:.875rem;display:inline-flex}.table-wrapper div.dt-container .dt-paging .dt-paging-button:hover{background:var(--accent-a3);border-color:var(--accent-a3);color:var(--accent-a11)!important}.table-wrapper div.dt-container .dt-paging .dt-paging-button.current{border-color:var(--gray-a4);background:0 0}.table-wrapper div.dt-container .dt-paging .dt-paging-button.current:hover{background:var(--accent-a3)}.table-wrapper .dt-info{font-size:.875rem}:root{--sig-property:var(--gray-12);--sig-name:var(--accent-10);--sig-typehint:var(--indigo-9);--sig-param:var(--gray-11)}dt.sig{text-indent:-2.4rem;border-radius:6px;padding:.25rem .5rem .25rem 3rem;font-size:.92rem;position:relative}dt.sig:after{content:"";clear:both;display:table}dt.sig:hover{background:var(--sy-c-surface)}dt.sig+dd{margin-left:2rem;font-size:.92rem}dt.sig>em.property:first-child{color:var(--sig-property)}dl.field-list{margin-top:0}dl.field-list a{font-weight:400}dt.sig+dd>div{margin-bottom:1rem}dt.sig+dd>dl.field-list>dt{text-transform:uppercase;font-size:.76rem}em.property,em.sig-param{font-style:normal}em.sig-param{color:var(--sig-param)}.sig-param a.reference{font-weight:400}span.sig-prename{color:var(--sig-name);font-weight:400}span.sig-name{color:var(--sig-name);font-weight:600}span.sig-return-icon{color:var(--sy-c-light)}span.sig-return-typehint,span.sig-return-typehint>a{color:var(--sig-typehint)}span.sig-paren,span.pre{font-family:var(--sy-f-mono)}dt.sig>a.internal{color:var(--sy-c-light);border:0;font-size:.82rem}dt.sig>a.internal:before{content:"\a ";white-space:pre}.viewcode-block{position:relative}.viewcode-back{font-size:.8rem;position:absolute;top:-1.5rem}.classifier{font-style:oblique;font-weight:400}.classifier:before{content:":";margin-left:.1rem;margin-right:.5rem;font-style:normal;display:inline-block}.yue .table-wrapper.autosummary{border-left:0;border-right:0;border-radius:0}.yue .table-wrapper table.autosummary td{border:none;padding-top:.25rem;padding-bottom:.25rem}.yue p.rubric+div.autosummary{margin-top:0}.hamburger{cursor:pointer;width:16px;height:14px;display:inline-block;position:relative;overflow:hidden}.hamburger>span{background-color:var(--sy-c-text);width:16px;height:2px;transition:top .25s,transform .25s;position:absolute;left:0}.hamburger_1{top:0}.hamburger_2{top:6px;transform:translate(-.5rem)}.hamburger_3{top:12px;transform:translate(-.25rem)}button[aria-expanded=true] .hamburger .hamburger_1{top:6px;transform:translate(0)rotate(225deg)}button[aria-expanded=true] .hamburger .hamburger_2{top:6px;transform:translate(18px)}button[aria-expanded=true] .hamburger .hamburger_3{top:6px;transform:translate(0)rotate(135deg)}.searchbox{position:relative}.searchbox input{appearance:none;width:100%;font-size:.92rem;font-family:var(--sy-f-text);background:var(--sy-c-surface);border-radius:6px;outline:0;padding:6px 12px}.searchbox kbd,.searchbox button{font-size:.68rem;font-weight:600;font-family:var(--sy-f-mono);border:1px solid var(--sy-c-border);background-color:var(--sy-c-background);opacity:1;border-radius:3px;margin:6px;padding:2px 6px;transition:opacity .2s;position:absolute;right:0}.searchbox input:focus+kbd{opacity:0}.searchform{align-items:center;display:flex;position:relative}.searchform input[name=q]{appearance:none;width:100%;font-size:.92rem;font-family:var(--sy-f-text);background:var(--sy-c-surface);border-radius:6px;outline:0;padding:6px 12px}.searchform input[name=q]+button{font-size:.68rem;font-weight:600;font-family:var(--sy-f-text);border:1px solid var(--sy-c-divider);background-color:var(--sy-c-background);opacity:1;border-radius:3px;margin:6px;padding:2px 6px;transition:opacity .2s;position:absolute;right:0}.search .highlighted{background-color:var(--accent-a4)}#search-results{border-top:1px solid var(--sy-c-border)}#search-results h2{margin-top:2rem;margin-bottom:.725rem}#search-results .search-summary{color:var(--sy-c-light);font-weight:500}#search-results ul.search{margin-left:0;padding-top:.625rem;padding-bottom:2rem;padding-left:0;list-style-type:none}#search-results ul.search>li{padding-left:0}#search-results ul.search>li+li{border-top:1px solid var(--sy-c-divider);padding-top:1rem}#search-results ul.search li>a{font-weight:600}#search-results ul.search p.context{margin-top:.5rem;font-size:.875rem}.demo{border:1px solid var(--sy-c-border);border-radius:6px}.demo-code .highlight>pre{border-bottom-right-radius:0;border-bottom-left-radius:0}.demo-result{padding:1rem}.container.image-1,.container.video-1{border:.5rem solid var(--accent-a3);border-radius:6px}.container.image-1>img{border-radius:4px;margin:0}.container.video-1 video,.container.video-1 iframe{border-radius:4px;width:100%;margin:0}.container.image-2,.container.video-2{border:1px solid var(--sy-c-border);border-radius:6px;padding:1rem}.container.image-2>img,.container.video-2>video{margin:0}.container.buttons{margin:2rem 0 4.2rem}.container.buttons>p{flex-wrap:wrap;gap:1rem;display:flex}.container.buttons a{border:2px solid var(--sy-c-border);background-color:var(--sy-c-surface);border-radius:2.6rem;padding:0 2rem;font-weight:600;line-height:2.6rem;text-decoration:none;transition:all .2s;display:inline-block}.container.buttons a:first-child{color:var(--accent-contrast);background-color:var(--accent-9);border-color:var(--accent-9)}.container.buttons a:hover{color:var(--sy-c-bold);border-color:var(--accent-9);background-color:var(--sy-c-background)}.container.rounded-image img{border-radius:99999px}#ethical-ad-placement .ethical-sidebar{background-color:var(--sy-c-surface);border:none;padding:.8rem;position:relative}#ethical-ad-placement .ethical-text a{color:var(--sy-c-text)!important}#ethical-ad-placement .ethical-text a:hover{color:var(--sy-c-link-hover)!important}.sy-main #ethical-ad-placement .ethical-sidebar{max-width:380px;margin-left:0}.sy-main #ethical-ad-placement .ethical-image-link{flex-shrink:0;margin-right:.4rem}.sy-main #ethical-ad-placement .ethical-content{display:flex}.sy-main #ethical-ad-placement .ethical-text{margin-top:0}.sy-main #ethical-ad-placement .ethical-callout{position:absolute;bottom:.4rem;right:.4rem}#carbonads{background-color:var(--sy-c-surface);border:none;border-radius:8px;margin:1rem 0;padding:.8rem .8rem 1.6rem;display:block;position:relative}#carbonads a{border:0;font-weight:400}#carbonads img{margin:0}.carbon-wrap{flex-direction:column;justify-content:space-between;align-items:center;display:flex}.carbon-text{text-align:center;margin:.5rem 0;font-size:.78rem;line-height:1.42;display:block}.carbon-text:hover{color:var(--sy-c-link-hover)}.carbon-poweredby{opacity:.68;text-transform:uppercase;font-size:.68rem;position:absolute;bottom:.5rem;right:.8rem}.carbon-poweredby:hover{text-decoration:underline}.sy-main #carbonads{max-width:380px;margin-top:1.6rem;padding:1rem}.sy-main .carbon-wrap{flex-direction:row;align-items:flex-start}.sy-main .carbon-text{text-align:left;margin-top:0;margin-left:1rem;font-size:.86rem}#bsa-custom-container{text-align:right}.yue a.bsa-container{text-align:left;border-bottom:0;border-radius:6px;flex-flow:row;justify-content:space-between;align-items:center;padding:15px 20px;text-decoration:none;display:flex;box-shadow:inset 0 0 0 1px #0000001a}.yue a.bsa-ad-via{background:var(--gray-a3);border:none;border-radius:2px;padding:3px 10px;font-size:10px;font-weight:300}.bsa-main{flex-flow:row;flex-grow:1;justify-content:center;align-items:center;margin:0 auto;display:flex}.bsa-img{max-height:40px;margin-right:20px;line-height:0}.yue a.bsa-container .bsa-img{margin-top:0;margin-bottom:0}.bsa-details{flex-flow:column;margin-right:20px;display:flex}.bsa-tagline{letter-spacing:1.5px;text-transform:uppercase;margin-bottom:3px;font-size:9px;font-weight:600;line-height:1}.bsa-desc{letter-spacing:1px;max-width:600px;font-size:12px;font-weight:400;line-height:1.4}.bsa-cta{letter-spacing:1px;text-transform:uppercase;white-space:nowrap;border-radius:3px;padding:10px 16px;font-size:10px;font-weight:600;line-height:1;transition:all .3s ease-in-out;transform:translateY(-1px)}@media (max-width:940px){.bsa-details{margin-right:0;font-size:14px}.bsa-cta{display:none}}@media (min-width:768px) and (max-width:820px){.bsa-img{display:none}}@media (max-width:480px){.bsa-img{display:none}}.repo-stats{border:1px solid var(--sy-c-divider);border-radius:6px;margin-bottom:1rem;padding:.5rem}.repo-stats:hover{background-color:var(--sy-c-surface)}.repo-stats-count{color:var(--sy-c-light)}.repo-stats strong{font-weight:500;font-family:var(--sy-f-mono);color:inherit}.edit-this-page{border-top:1px solid var(--sy-c-divider);margin:1rem 0;padding:.5rem 0;font-size:.8rem;font-weight:600}.repo-stats+.edit-this-page{border-top:0;margin-top:0;padding-top:0}.edit-this-page a{color:var(--sy-c-text)}.edit-this-page a:hover{color:var(--sy-c-link-hover)}.edit-this-page a:after{content:" →"}.back-to-top{z-index:10;background:var(--sy-c-background);border-radius:2rem;align-items:center;gap:.25rem;padding:.4rem .8rem .4rem .6rem;font-size:.8rem;display:none;position:fixed;bottom:68px;left:50%;transform:translate(-50%);box-shadow:0 .2rem .5rem #0000000d,0 0 1px #6b728080}.dark .back-to-top{background:var(--slate-2);box-shadow:0 .2rem .5rem #ffffff0d,0 0 1px #9aa4b880}.back-to-top:hover{color:var(--accent-contrast);background:var(--accent-9)}.back-to-top svg{fill:currentColor;width:1rem;height:1rem;display:inline-block}.back-to-top[data-visible=true]{display:flex}.icon-link{display:inline-block}.icon-link span{vertical-align:middle;display:inline-block}.icon-link .icon{border:1px solid var(--sy-c-border);opacity:.8;border-radius:6px;margin-right:.4rem;padding:.1rem}.icon-link svg{width:1.5rem;height:1.5rem}.icon-link:hover .icon{opacity:1}#copy-page-trigger{border:1px solid var(--gray-a4);background-color:var(--sy-c-background);border-radius:.625rem;align-items:center;font-size:.875rem;display:inline-flex;overflow:hidden}#copy-page-trigger i.i-lucide{transition:transform .2s}#copy-page-trigger button[aria-expanded=true]>i{transform:rotate(-180deg)}#copy-page-trigger button{background-color:var(--sy-c-background);vertical-align:middle;height:32px;transition:background-color .2s}#copy-page-trigger button:hover{background-color:var(--sy-c-surface)}#copy-page-trigger button+button{border-left:1px solid var(--gray-a4)}#copy-page-content{z-index:9;border:1px solid var(--gray-a4);box-shadow:var(--sy-dropdown-shadow);background:var(--sy-c-background);border-radius:.625rem;min-width:200px;margin-top:.25rem;padding:.75rem .5rem;position:absolute}#copy-page-content[aria-hidden=true]{display:none}#copy-page-content button,#copy-page-content a{white-space:nowrap;border-radius:.25rem;align-items:center;padding:.4rem .5rem;font-size:.875rem;display:inline-flex}#copy-page-content button:hover,#copy-page-content a:hover{background:var(--gray-a3)}#copy-page-content .iconify-icon,#copy-page-content iconify-icon{border:1px solid var(--gray-a4);border-radius:.25rem;justify-content:center;align-items:center;width:28px;height:28px;margin-right:.5rem;font-size:.825rem;display:inline-flex}#copy-page-content a:after{content:"";-webkit-mask:var(--lucide-external-link-url) no-repeat;-webkit-mask:var(--lucide-external-link-url) no-repeat;mask:var(--lucide-external-link-url) no-repeat;vertical-align:top;background-color:var(--gray-a9);width:.625em;height:.625em;margin-left:.1rem;font-style:normal;display:inline-block;position:relative;top:-2px;-webkit-mask-size:100% 100%;mask-size:100% 100%}#copy-page-trigger .i-lucide[data-icon=copy],#copy-page-content .i-lucide[data-icon=copy]{--icon-url:var(--lucide-copy-url)}#copy-page-trigger .i-lucide[data-icon=check],#copy-page-content .i-lucide[data-icon=check]{--icon-url:var(--lucide-check-url)}#copy-page-trigger .i-lucide[data-icon=loader],#copy-page-content .i-lucide[data-icon=loader]{--icon-url:var(--lucide-loader-url)}@media (min-width:64rem){.copy-page-wrapper+.yue>section>h1:first-of-type{padding-right:180px}#copy-page-content{right:0}}.announcement{width:100%;color:var(--sy-c-banner,var(--accent-contrast));background-color:var(--sy-c-banner-bg,var(--accent-a11));z-index:20;align-items:center;padding:.8rem 2rem;display:flex;position:sticky;top:0;left:0}.announcement a{text-decoration:underline}.announcement ::selection{color:var(--sy-c-banner,var(--accent-contrast))}.announcement-inner{width:100%}.announcement-close{position:absolute;top:.8rem;right:1rem}.sy-head{top:var(--sy-s-banner-height);height:var(--sy-s-navbar-height);z-index:20;background-color:#0000;position:sticky}.sy-head-blur{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);background-color:var(--sy-c-background-dropback);width:100%;height:100%;box-shadow:0 0 var(--sy-c-background-contrast), 0 2px 4px var(--gray-a1), 0 1px 0 var(--sy-c-divider);z-index:-1;position:absolute;top:0;left:0}.sy-head-inner{padding-left:max(env(safe-area-inset-right), 1.5rem);padding-right:max(env(safe-area-inset-right), 1rem);height:var(--sy-s-navbar-height);justify-content:space-between;align-items:center;display:flex}.sy-head-brand img{height:28px}.sy-head-brand img+strong,.sy-head-brand .dark-logo{display:none}.dark .sy-head-brand .dark-logo{display:inline}.dark .sy-head-brand .light-logo{display:none}.light .sy-head-brand .light-logo{display:inline}.light .sy-head-brand .dark-logo{display:none}.sy-head-links button,.sy-head-links a{white-space:nowrap;padding:.5rem;font-size:.95rem;font-weight:500}.sy-head-links .link i.external-link{opacity:.6;color:var(--sy-c-light);margin-left:2px;font-size:68%}.sy-head-links .link>ul a{white-space:normal;display:block}.sy-head-links .link>ul a:hover{background:var(--sy-c-surface);border-radius:6px}.sy-head-links .link>ul small{color:var(--sy-c-light);font-weight:400;display:block}.sy-head-socials{align-items:center;display:flex}.sy-head-socials a{align-items:center;padding:.5rem;display:flex}.sy-head-actions button{height:var(--sy-s-navbar-height);padding:0 .5rem}@media (max-width:767px){body[data-expanded*=head-nav]{overflow:hidden}.sy-head-nav{top:var(--sy-s-offset-top);box-sizing:border-box;border-top:1px solid var(--sy-c-divider);background-color:var(--sy-c-background);width:100%;padding:4rem 1.8rem 0;display:none;position:fixed;bottom:0;left:0;right:0;overflow-y:auto}.sy-head-nav[aria-hidden=false]{display:block}.sy-head-links{margin-left:auto;margin-right:auto}.sy-head-links .link{margin:.5rem 0}.sy-head-links .link i.chevron{display:none}.sy-head-links .link>ul{margin:.5rem 0 .5rem 1rem}.sy-head-extra form.searchbox{position:absolute;top:1rem;left:1.8rem;right:1.8rem}.sy-head-extra{flex-direction:column;width:100%;padding:2rem 0 1rem}}@media (min-width:768px){.sy-head-inner{padding-right:max(env(safe-area-inset-right), 1.5rem)}.sy-head-nav{flex-grow:1;justify-content:space-between;align-items:center;display:flex}.sy-head-links[data-align=right]{--head-links-justify-content:flex-end}.sy-head-links[data-align=center]{--head-links-justify-content:center}.sy-head-links{white-space:nowrap;justify-content:var(--head-links-justify-content,flex-start);flex-grow:1;padding:0 1rem;display:flex;overflow:auto}.sy-head-links .link{height:var(--sy-s-navbar-height);align-items:center;display:inline-flex}.sy-head-links a:hover{color:var(--sy-c-link-hover)}.sy-head-links .link:hover>a{background-color:var(--sy-c-surface);border-radius:6px}.sy-head-links .link i.chevron-down{color:var(--sy-c-light)}.sy-head-links .link>ul{visibility:hidden;background-color:var(--sy-c-background);height:0;top:var(--sy-s-navbar-height);border:1px solid var(--sy-c-divider);box-shadow:var(--sy-dropdown-shadow);z-index:9;border-radius:6px;max-width:320px;margin-top:-10px;padding:15px;position:absolute}.sy-head-links .link>ul[aria-hidden=false],.sy-head-links .link:hover>ul{visibility:visible;height:auto}.sy-head-links .link>ul>li{padding:.2rem 0}.sy-head-socials{margin-left:.5rem}}.sy-foot{border-top:1px solid var(--sy-c-foot-divider);color:var(--sy-c-foot-text);background-color:var(--sy-c-foot-background);padding-top:1.5rem;padding-bottom:1rem}.sy-foot-inner{padding-left:max(env(safe-area-inset-right), 1.5rem);padding-right:max(env(safe-area-inset-right), 1.5rem)}.sy-foot-copyright{font-size:.84rem}.sy-foot-copyright a{font-weight:500}.sy-foot-copyright a:hover{text-decoration:underline}.sy-foot-socials a{color:var(--sy-c-foot-text);font-size:1.4rem}.sy-foot-socials a+a{margin-left:.5rem}.sy-foot-socials a svg{width:1.4rem;height:1.4rem;display:inline-block}.sy-lside .sidebar-links{margin-bottom:2rem}@media (min-width:768px){.sy-lside .sy-lside-inner{top:var(--sy-s-offset-top)}.sy-lside .sy-scrollbar{max-height:calc(100vh - var(--sy-s-offset-top));overflow-x:hidden}}.yue *{scroll-margin-top:calc(var(--sy-s-offset-top) + 68px)}.sy-main{min-height:calc(100vh - var(--sy-s-offset-top) - 80px)}.sy-content{max-width:64rem;min-height:calc(100vh - var(--sy-s-offset-top) - 80px)}@media (max-width:767px){#lside{z-index:18;top:var(--sy-s-offset-top);width:300px;max-width:100%;height:calc(100vh - var(---sy-s-offset-top));background:var(--sy-c-background);transition:transform .2s;position:fixed;bottom:0;left:0;overflow:auto;transform:translate(-100%)}#lside[aria-hidden=false]{transform:translate(0)}.lside-overlay{top:var(--sy-s-offset-top);background-color:var(--sy-c-overlay);opacity:0;width:0;height:0;transition:width 0 .25s, height 0 .25s, opacity .25s;position:fixed;left:0}#lside[aria-hidden=false]+.lside-overlay{opacity:1;z-index:16;width:100%;height:100%}}@media (max-width:1279px){.sy-rside{z-index:25;background:var(--sy-c-background);width:20rem;max-width:100%;box-shadow:0 0 var(--sy-c-background-contrast), -12px 0 16px var(--gray-a1);padding-top:2rem;padding-bottom:1rem;transition:transform .2s;position:fixed;top:0;bottom:0;right:0;overflow:auto;transform:translate(110%)}#rside[aria-hidden=false]{transform:translate(0)}.rside-close{justify-content:center;align-items:center;width:2rem;height:2rem;font-size:1.4rem;display:flex;position:absolute;top:16px;right:16px}.rside-overlay{background-color:var(--sy-c-overlay);opacity:0;width:0;height:0;transition:width 0 .25s, height 0 .25s, opacity .25s;position:fixed;top:0;left:0}#rside[aria-hidden=false]+.rside-overlay{opacity:1;z-index:22;width:100%;height:100%}}@media (min-width:768px){.sy-main{width:calc(100% - 18rem);max-width:52rem}}@media (min-width:1280px){.sy-main{width:calc(100% - 34rem);max-width:none}.sy-rside .sy-scrollbar{max-height:calc(100vh - var(--sy-s-offset-top) - env(safe-area-inset-bottom))}.yue *{scroll-margin-top:calc(var(--sy-s-offset-top) + 24px)}}.nav-languages button,.nav-versions button{cursor:pointer;white-space:nowrap;background:0 0;border:0;margin:0;padding:0}.nav-versions .chevron-down{color:var(--sy-c-light)}@media (max-width:767px){.nav-versions,.nav-languages{background-color:var(--sy-c-surface);border-radius:6px;width:100%;margin-bottom:1rem;padding-bottom:.6rem}.nav-versions button,.nav-languages button{color:var(--sy-c-light);padding:.5rem 1rem;font-size:.76rem;font-weight:500}.nav-versions button>i,.nav-languages button>i{display:none}.nav-versions ul{padding:0 .6rem}.nav-versions li{padding:.2rem .4rem;display:inline-block}.nav-languages li{padding:.32rem 1rem;font-size:.94rem}}@media (min-width:768px){.nav-versions,.nav-languages{width:auto;height:var(--sy-s-navbar-height);color:var(--sy-c-text);background:0 0;align-items:center;display:flex;position:relative}.nav-languages button,.nav-versions button{border-right:1px solid var(--gray-3);padding:0 .5rem}.nav-versions-choices,.nav-languages-choices{visibility:hidden;box-sizing:border-box;background-color:var(--sy-c-background);min-width:120px;max-height:60vh;box-shadow:var(--sy-dropdown-shadow);border-radius:6px;padding:.8rem 1rem;position:absolute;top:3rem;right:-.6rem;overflow:hidden auto}.nav-versions:hover .nav-versions-choices,.nav-languages:hover .nav-languages-choices{visibility:visible}.nav-versions li,.nav-languages li{padding:.1rem 0}.nav-versions a,.nav-languages a{color:var(--sy-c-text);white-space:nowrap;padding:.2rem .6rem;display:block}.nav-versions a:hover,.nav-languages a:hover{color:var(--sy-c-link-hover);background:var(--sy-c-surface);border-radius:6px}}.sy-breadcrumbs{top:var(--sy-s-offset-top);background-color:var(--sy-c-background);z-index:5;padding:0 1.5rem;position:sticky}.sy-breadcrumbs-inner{border-bottom:1px solid var(--sy-c-divider);padding:.8rem 0}.sy-breadcrumbs ol{white-space:nowrap;font-size:.94rem;display:flex;overflow:auto}.sy-breadcrumbs button{align-items:center;display:flex}.sy-breadcrumbs ol a{color:var(--sy-c-light)}.sy-breadcrumbs ol a:hover{color:var(--sy-c-bold)}.sy-breadcrumbs ol a+span{color:var(--sy-c-light);padding:0 .4rem;font-weight:300}@media (min-width:1280px){.sy-breadcrumbs{display:none}}@media (min-width:768px){.sy-breadcrumbs-inner{padding:1.5rem 0 1rem}}.globaltoc{padding-bottom:20px}.globaltoc .caption{font-size:.86rem;font-weight:500;font-family:var(--sy-f-heading);color:var(--sy-c-light);text-transform:uppercase;letter-spacing:.4px;border-top:1px solid var(--sy-c-divider);padding:.8rem 0 .4rem}.globaltoc>p.caption:first-of-type{border-top:none;padding-top:0}.globaltoc .caption+ul{margin-bottom:1.5rem}.globaltoc ul+.caption{margin-top:2.5rem}.globaltoc li{margin:.6rem 0}.globaltoc li>ul{margin-left:.6rem;font-size:.96rem}.globaltoc li.toctree-l1>ul{border-left:1px solid var(--gray-3);margin-left:.2rem}.globaltoc li.toctree-l2{border-left:1px solid #0000;margin-left:-1px;padding-left:.9rem}.globaltoc li.toctree-l2.current{border-color:var(--sy-c-link)}.globaltoc>ul a.current{color:var(--sy-c-link);font-weight:500}.globaltoc>ul a:hover{color:var(--sy-c-link-hover)}.globaltoc a.external:after{content:"";-webkit-mask:var(--lucide-external-link-url) no-repeat;-webkit-mask:var(--lucide-external-link-url) no-repeat;mask:var(--lucide-external-link-url) no-repeat;vertical-align:middle;background-color:var(--sy-c-light);width:.825rem;height:.825rem;margin-left:.2rem;font-style:normal;display:inline-block;-webkit-mask-size:100% 100%;mask-size:100% 100%}.globaltoc li{position:relative}.globaltoc li>button{border-radius:3px;justify-content:center;align-items:center;width:1.2rem;height:1.2rem;display:flex;position:absolute;top:.2rem;right:0}.globaltoc li>button:hover{background-color:var(--sy-c-surface)}.globaltoc li.current>ul,.globaltoc li._expand>ul{display:block}.globaltoc li>ul,.globaltoc li._collapse>ul{display:none}.globaltoc li>button>i{transition:transform .2s;transform:rotate(0)}.globaltoc li.current>button>i,.globaltoc li._expand>button>i{transform:rotate(90deg)}.globaltoc li._collapse>button>i{transform:rotate(0)}.sy-deprecated{background-color:#ffdd001a;border-radius:6px;padding:.8rem;font-size:.85rem}.sy-deprecated a{color:var(--sy-c-link);text-decoration:underline}.sy-deprecated a:hover{color:var(--sy-c-link-hover)}.sy-rside-inner>div{margin-bottom:1rem}.sy-rside-inner>div>h3{letter-spacing:.4px;text-transform:uppercase;margin-bottom:1rem;font-size:.8rem;font-weight:500}html[lang=zh] .sy-rside-inner>div>h3,html[lang=zh-TW] .sy-rside-inner>div>h3,html[lang=ja] .sy-rside-inner>div>h3,html[lang=ko] .sy-rside-inner>div>h3{letter-spacing:0;font-size:.86rem;font-weight:600}.localtoc>ul li{margin-top:.36rem;margin-bottom:.36rem}.localtoc>ul li>a:hover{color:var(--sy-c-link-hover)}.localtoc>ul li.active>a{color:var(--sy-c-link)}.localtoc>ul>li ul{padding-left:.8rem}.sy-rside ul.this-page-menu{margin-top:-.6rem}.sy-rside ul.this-page-menu a{font-size:.96rem}.sy-rside ul.this-page-menu a:hover{color:var(--sy-c-link-hover)}.navigation{border-top:1px solid var(--sy-c-divider);gap:2rem;margin-top:2rem;padding-top:1rem}.navigation>div{width:100%}.navigation a{align-items:center;display:inline-flex}.navigation a:hover{color:var(--sy-c-link-hover)}.navigation-next{text-align:right}.navigation-next a{justify-content:end}.navigation .page-info{padding:0 8px}.navigation .page-info>span{color:var(--sy-c-light);font-size:.8rem}:root{--readthedocs-search-font-family:var(--sy-f-text);--readthedocs-search-color:var(--sy-c-text);--readthedocs-search-input-background-color:var(--gray-3);--readthedocs-search-content-border-color:var(--gray-4);--readthedocs-search-content-background-color:var(--sy-c-background);--readthedocs-search-result-section-color:var(--sy-c-text);--readthedocs-search-result-section-subheading-color:var(--sy-c-heading);--readthedocs-search-result-section-highlight-color:var(--accent-9);--readthedocs-search-result-section-border-color:var(--sy-c-border)}.yue button.copybtn{color:var(--syntax-text);background-color:#0000;border:none;justify-content:center;align-items:center}.yue button.copybtn>svg{width:1.4rem;height:1.4rem}.yue button.copybtn:hover{color:var(--syntax-comment)}.yue .highlight button.copybtn:hover{background-color:#0000}.yue button.copybtn:after{color:var(--syntax-text);background-color:#0000}.yue button.copybtn.success{border-color:var(--green-a10);color:var(--green-a10)}.yue button.copybtn.success:after{color:var(--green-a10)}.code-block-caption+div>.highlight .copybtn{opacity:.5;top:-2em}html.light .sd-tab-content{--code-block-background:var(--color-surface-accent);--code-block-caption-background:var(--accent-3)}.yue{--sd-color-primary:var(--accent-a11);--sd-color-secondary:var(--gold-a11);--sd-color-success:var(--green-a11);--sd-color-info:var(--blue-a11);--sd-color-warning:var(--orange-a11);--sd-color-danger:var(--red-a11);--sd-color-light:var(--sand-a2);--sd-color-muted:var(--gray-8);--sd-color-dark:#212122;--sd-color-black:black;--sd-color-white:white;--sd-color-primary-highlight:var(--accent-a8);--sd-color-secondary-highlight:var(--gold-a8);--sd-color-success-highlight:var(--green-a8);--sd-color-info-highlight:var(--blue-a8);--sd-color-warning-highlight:var(--orange-a8);--sd-color-danger-highlight:var(--red-a8);--sd-color-light-highlight:var(--gray-4);--sd-color-muted-highlight:var(--gray-11);--sd-color-dark-highlight:#121211;--sd-color-black-highlight:black;--sd-color-white-highlight:#d9d9d9;--sd-color-primary-text:var(--accent-contrast);--sd-color-secondary-text:var(--gold-contrast);--sd-color-success-text:var(--green-contrast);--sd-color-info-text:var(--blue-contrast);--sd-color-warning-text:var(--orange-contrast);--sd-color-danger-text:var(--red-contrast);--sd-color-light-text:var(--sy-c-text);--sd-color-muted-text:#fff;--sd-color-dark-text:#fff;--sd-color-black-text:#fff;--sd-color-white-text:#212529;--sd-color-shadow:var(--gray-1);--sd-color-card-border:var(--sy-c-border);--sd-color-card-border-hover:var(--accent-a9);--sd-color-tabs-label-inactive:var(--sy-c-bold);--sd-color-tabs-label-active:var(--sd-color-primary);--sd-color-tabs-underline-active:var(--sd-color-primary);--sd-color-tabs-label-hover:var(--accent-9);--sd-color-tabs-underline-hover:var(--accent-9)}.yue .surface{--sd-color-card-text:var(--sy-c-light);--sd-color-card-border:transparent;--sd-color-card-background:var(--sy-c-surface)}.yue a.sd-badge,.yue a.sd-badge:hover{border-bottom:0}.yue .sd-badge{border-radius:3px;font-weight:600}.yue .sd-btn{border-color:var(--sy-c-border)}.yue .sd-tab-set.outline{border:1px solid var(--sy-c-border);border-radius:4px;overflow:auto}.yue .sd-tab-set>label{padding:1rem .25rem .5rem;font-size:.84rem;font-weight:500}.yue .sd-tab-set.outline>label{margin-left:1rem;padding-top:.5rem}.yue .sd-tab-set>label~label{margin-left:1rem}.yue .sd-tab-content{box-shadow:0 -.0625rem var(--sy-c-divider);padding:0}.yue .sd-tab-content .code-block-caption,.yue .sd-tab-content .highlight pre{border-radius:0}.yue .sd-card-title{color:var(--sy-c-text)}.yue .sd-card-title a{border-bottom:0}.yue .sd-card-title>svg,.yue .sd-card-title>iconify-icon{margin-right:.25rem;position:relative;top:-1px}.yue .sd-card-hover:hover{transform:scale(1)}.yue .sd-card-hover:hover .sd-card-title{color:var(--sy-c-link-hover)}.yue .sd-card a.sd-hide-link-text,.yue .sd-card a.sd-hide-link-text:hover{border-bottom:0}.yue .surface .sd-card-header,.yue .surface .sd-card-body,.yue .surface .sd-card-footer{padding-left:1.5rem;padding-right:1.5rem}.yue .surface .sd-card-header,.yue .surface .sd-card-footer{border-color:var(--sy-c-border)}@media (print){.yue .sd-card{page-break-inside:avoid}}.yue a.sd-text-wrap:hover{border-bottom-width:1px}.sphinx-tabs [role=tablist]{border-color:var(--sy-c-divider)}.yue .sphinx-tabs-tab{color:var(--sy-c-text);line-height:inherit;border:none;border-bottom:.125rem solid #0000;padding:1rem .25rem .5rem;font-size:.84rem;font-weight:500}.yue .sphinx-tabs-tab:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.yue .sphinx-tabs-tab[aria-selected=true]{border:none;border-bottom:.125rem solid var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active);background-color:#0000}.yue .sphinx-tabs-tab+.sphinx-tabs-tab{margin-left:1rem}.yue .sphinx-tabs-panel{background-color:#0000;border:none;border-radius:0;margin:0;padding:0}.yue .sphinx-tabs-panel.code-tab{padding:0}.yue .sphinx-tabs-panel.code-tab .code-block-caption,.yue .sphinx-tabs-panel.code-tab .highlight pre{border-radius:0}html.light .jupyter_container .cell_output{--code-block-background:var(--color-surface-accent);--code-block-caption-background:var(--accent-3)}.yue{--jp-widgets-input-border-color:var(--gray-5);--jp-widgets-input-focus-border-color:var(--gray-8);--jp-widgets-slider-active-handle-color:var(--gray-4);--jp-widgets-slider-handle-border-color:var(--sy-c-border)}.yue .jupyter_container{background-color:var(--sy-c-background);border:3px solid var(--sy-c-border);box-shadow:none;border-radius:6px;overflow:hidden}.sy-main .yue .jupyter_container div[class^=highlight]{padding:0}.yue .jupyter_container div.highlight{background-color:var(--code-block-background)}.yue .jupyter_container div.cell_input{background-color:var(--code-block-background);border:0;border-radius:0}.yue .jupyter_container div.code_cell pre{padding:0}.jupyter_container div.cell_output .output,.jupyter_container div.cell_output .stderr,.jupyter_container div.cell_output .widget-subarea{padding:.5rem}.jupyter_container div.cell_output .stderr .stderr{padding:0}.widget-hslider .slider-container,.jupyter-widget-hslider .slider-container{align-items:center;display:flex}.widget-slider .noUi-target,.jupyter-widget-slider .noUi-target{width:100%}.jupyter_container div.code_cell .highlight>pre{padding:1rem}.jupyter_container div.code_cell .highlight .hll{margin-left:-1rem;margin-right:-1rem;padding:0 1rem}.jupyter_container div.code_cell .highlight .linenos{margin-right:.8rem}.yue .jupyter_container .stderr{color:var(--red-a11);background-color:var(--red-a3)}.yue .jupyter_container .stderr .stderr{background-color:#0000}.nbinput .highlight{--radius:1px}.yue div.nblast.container{padding-top:5px}.yue div.nbinput.container div.input_area{border-color:var(--sy-c-border)}.yue div.nboutput.container div.output_area.stderr{color:var(--red-a11);background-color:var(--red-a3)}.yue div.nboutput.container div.output_area>.math-wrapper>div.math{padding-top:0}.yue .jp-RenderedHTMLCommon thead,.yue div.rendered_html thead{border-color:var(--sy-c-border)}.yue .jp-RenderedHTMLCommon tbody tr,.yue div.rendered_html tbody tr{color:var(--sy-c-text)}.yue .jp-RenderedHTMLCommon tbody tr:nth-child(odd),.yue div.rendered_html tbody tr:nth-child(odd){background-color:var(--sy-c-surface)}.yue .jp-RenderedHTMLCommon tbody tr:hover,.yue div.rendered_html tbody tr:hover{background-color:var(--color-surface-accent)}.yue{--sg-text-color:var(--sy-c-text);--sg-background-color:var(--sy-c-background);--sg-code-background-color:var(--code-block-background);--sg-tr-hover-color:var(--accent-a3);--sg-tr-odd-color:var(--sy-c-surface);--sg-tooltip-foreground:var(--sy-c-background-contrast);--sg-tooltip-background:var(--sy-c-background);--sg-tooltip-border:var(--gray-7) transparent;--sg-thumb-box-shadow-color:var(--gray-a4);--sg-thumb-hover-border:var(--accent-a9);--sg-script-out:var(--sy-c-light);--sg-script-pre:var(--code-block-background);--sg-pytb-foreground:var(--syntax-text);--sg-pytb-background:var(--red-a2);--sg-pytb-border-color:var(--red-a8);--sg-download-a-background-color:var(--accent-a3);--sg-download-a-background-image:none;--sg-download-a-border-color:1px solid var(--accent-a3);--sg-download-a-color:var(--accent-a11);--sg-download-a-hover-background-color:var(--accent-a4);--sg-download-a-hover-box-shadow-1:transparent;--sg-download-a-hover-box-shadow-2:transparent}.yue .sphx-glr-thumbnails a,.yue .sphx-glr-download a,.yue .sphx-glr-download a:hover{border-bottom:0}.yue p.sphx-glr-signature a{border-bottom:0;border-radius:0;text-decoration:underline}.yue p.sphx-glr-signature a:hover{color:var(--sy-c-link-hover)}.yue .sphx-glr-footer img{margin:0;display:inline}html.light,html.dark{--docsearch-background-color:var(--sy-c-background);--docsearch-icon-color:var(--gray-11);--docsearch-secondary-text-color:var(--gray-11);--docsearch-modal-background:var(--sy-c-background);--docsearch-footer-background:var(--sy-c-surface);--docsearch-primary-color:var(--accent-9);--docsearch-soft-primary-color:var(--accent-a2);--docsearch-subtle-color:var(--gray-4);--docsearch-text-color:var(--sy-c-text);--docsearch-key-background:var(--gray-1);--docsearch-searchbox-background:var(--gray-3);--docsearch-searchbox-focus-background:var(--sy-c-background);--docsearch-muted-color:var(--gray-10);--docsearch-focus-color:var(--accent-a8);--docsearch-highlight-color:var(--accent-a11);--docsearch-hit-color:var(--sy-c-text);--docsearch-hit-background:var(--gray-a2);--docsearch-hit-highlight-color:var(--accent-a3);--docsearch-hit-shadow:inset 0 0 1px 0 var(--gray-a11);--docsearch-container-background:var(--gray-a5)}html.dark{--docsearch-modal-shadow:inset 1px 1px 0 0 #373737,0 3px 8px 0 #141414}#docsearch .DocSearch-Button{box-sizing:border-box;width:auto;height:32px;margin:0}#docsearch .DocSearch-Search-Icon{width:1rem;height:1rem}@media (max-width:767px){html.light,html.dark{--docsearch-searchbox-background:transparent}#docsearch{position:absolute;top:1rem;left:1.8rem;right:1.8rem}#docsearch .DocSearch-Button{width:100%;margin-left:0}}dl.sqla dt{color:var(--sig-name);margin-bottom:.5rem}dl.sqla dt>em{color:var(--sig-param);font-style:normal;font-weight:400}dl.sqla dd>p.rubric{text-transform:uppercase;margin-top:1.5rem;font-size:.76rem}dl.sqla dd>p.rubric+.table-wrapper{border-left:0;border-right:0;border-radius:0;margin-top:.75rem}dl.sqla p.rubric+.table-wrapper th,dl.sqla p.rubric+.table-wrapper td{background-color:#0000;border-left:0;border-right:0}dl.sqla p.rubric+.table-wrapper td>p{margin:0}dl.sqla p.rubric+.table-wrapper tr.row-odd{background-color:#0000}dl.sqla p.rubric+.table-wrapper tr.row-even{background-color:var(--yue-c-row-background)}.yue details.toggle-details{background-color:var(--slate-a2);border-radius:.2em;padding:0 1rem}.yue details.toggle-details summary{border-left-color:var(--accent-a9);background-color:var(--gray-a2);margin-left:-1rem;margin-right:-1rem}.yue details.toggle-details[open] summary{border-radius:.2em .2em 0 0}.yue .toggle-details__container{margin-top:0;margin-bottom:0;padding-top:1rem;padding-bottom:1rem}.yue .toggle-details__container :first-child{margin-top:0}.yue .toggle-details__container :last-child{margin-bottom:0}.yue .admonition.toggle-hidden .admonition-title~*{margin-bottom:0!important}.sphinx-contributors{container:contributors/inline-size}.sphinx-contributors .sphinx-contributors_list__item{margin:0;padding:0}.sphinx-contributors .sphinx-contributors_contributor__username,.sphinx-contributors .sphinx-contributors_contributor__contributions{margin:0}.sphinx-contributors.sphinx-contributors--avatars .sphinx-contributors_list{justify-content:flex-start;gap:1rem;padding:0}.sphinx-contributors--avatars .sphinx-contributors_contributor__username{margin-top:.5rem}.sphinx-contributors--avatars .sphinx-contributors_contributor__contributions{font-size:.875rem}.sphinx-contributors--avatars .sphinx-contributors_contributor__contributions:before{content:"";padding:0}.sphinx-contributors--avatars .sphinx-contributors_contributor{align-items:center}@container contributors (max-width:800px){.sphinx-contributors.sphinx-contributors--avatars .sphinx-contributors_list{column-gap:0}.sphinx-contributors--avatars .sphinx-contributors_list__item{flex-basis:25%}}@container contributors (max-width:700px){.sphinx-contributors--avatars img.sphinx-contributors_contributor__image{width:120px}}@container contributors (max-width:600px){.sphinx-contributors--avatars .sphinx-contributors_list__item{flex-basis:33.33%}}@container contributors (max-width:500px){.sphinx-contributors--avatars img.sphinx-contributors_contributor__image{width:120px}}@container contributors (max-width:400px){.sphinx-contributors--avatars .sphinx-contributors_list__item{flex-basis:50%}}.sphinx-sponsors--2xl{--sponsor-avatar-size:120px;--sponsor-item-padding:20px}.sphinx-sponsors--xl{--sponsor-avatar-size:90px;--sponsor-item-padding:15px}.sphinx-sponsors--lg{--sponsor-avatar-size:70px;--sponsor-item-padding:15px}.sphinx-sponsors--md{--sponsor-avatar-size:50px;--sponsor-item-padding:10px}.sphinx-sponsors--base{--sponsor-avatar-size:40px;--sponsor-item-padding:6px}.sphinx-sponsors--sm{--sponsor-avatar-size:35px;--sponsor-item-padding:5px}.sphinx-sponsors--xs{--sponsor-avatar-size:25px;--sponsor-item-padding:4px}.sphinx-sponsors{margin:2rem 0}.sphinx-sponsors .rubric{font-size:1.25em}ul.sphinx-sponsors_container{gap:var(--sponsor-item-padding);flex-wrap:wrap;margin:0;padding:0;list-style-type:none;display:flex}.sphinx-sponsors li.sphinx-sponsors_item{flex-direction:column;align-items:center;margin:0;padding:0;display:flex}.sphinx-sponsors_avatar{width:var(--sponsor-avatar-size);background:var(--gray-a3);display:inline-flex}.sphinx-sponsors_name{margin-top:.25rem;font-size:.875rem}.sphinx-sponsors--center{text-align:center}.sphinx-sponsors--center ul.sphinx-sponsors_container{gap:0}.sphinx-sponsors--center li.sphinx-sponsors_item{padding:var(--sponsor-item-padding)}.sphinx-sponsors--center .sphinx-sponsors_container{justify-content:center}.sphinx-sponsors--rounded .sphinx-sponsors_avatar,.sphinx-sponsors--rounded img{border-radius:100%}.yue{--xr-font-color0:var(--sy-c-heading);--xr-font-color2:var(--sy-c-text);--xr-font-color3:var(--sy-c-light);--xr-border-color:var(--sy-c-border);--xr-disabled-color:var(--gray-a6);--xr-background-color:var(--sy-c-background);--xr-background-color-row-even:var(--sy-c-background);--xr-background-color-row-odd:var(--gray-2)}.yue .xr-array-data pre{margin:0}.yue iconify-icon[data-accent-color]{color:var(--accent-9)}.dark pre.mermaid>svg{filter:brightness(.8)invert(.82)contrast(1.2)}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false} \ No newline at end of file diff --git a/dev/doc/_static/shibuya.js b/dev/doc/_static/shibuya.js new file mode 100644 index 0000000..be39892 --- /dev/null +++ b/dev/doc/_static/shibuya.js @@ -0,0 +1,43 @@ +(()=>{var ie=Object.create;var ft=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var ce=Object.getPrototypeOf,ae=Object.prototype.hasOwnProperty;var le=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,n)=>(typeof require<"u"?require:e)[n]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var ue=(t,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of se(e))!ae.call(t,o)&&o!==n&&ft(t,o,{get:()=>e[o],enumerable:!(i=re(e,o))||i.enumerable});return t};var de=(t,e,n)=>(n=t!=null?ie(ce(t)):{},ue(e||!t||!t.__esModule?ft(n,"default",{value:t,enumerable:!0}):n,t));var Lt=Object.freeze({left:0,top:0,width:16,height:16}),R=Object.freeze({rotate:0,vFlip:!1,hFlip:!1}),j=Object.freeze({...Lt,...R}),K=Object.freeze({...j,body:"",hidden:!1}),fe=Object.freeze({width:null,height:null}),Et=Object.freeze({...fe,...R});function he(t,e=0){let n=t.replace(/^-?[0-9.]*/,"");function i(o){for(;o<0;)o+=4;return o%4}if(n===""){let o=parseInt(t);return isNaN(o)?0:i(o)}else if(n!==t){let o=0;switch(n){case"%":o=25;break;case"deg":o=90}if(o){let r=parseFloat(t.slice(0,t.length-n.length));return isNaN(r)?0:(r=r/o,r%1===0?i(r):0)}}return e}var pe=/[\s,]+/;function ge(t,e){e.split(pe).forEach(n=>{switch(n.trim()){case"horizontal":t.hFlip=!0;break;case"vertical":t.vFlip=!0;break}})}var Tt={...Et,preserveAspectRatio:""};function ht(t){let e={...Tt},n=(i,o)=>t.getAttribute(i)||o;return e.width=n("width",null),e.height=n("height",null),e.rotate=he(n("rotate","")),ge(e,n("flip","")),e.preserveAspectRatio=n("preserveAspectRatio",n("preserveaspectratio","")),e}function me(t,e){for(let n in Tt)if(t[n]!==e[n])return!0;return!1}var Ot=/^[a-z0-9]+(-[a-z0-9]+)*$/,N=(t,e,n,i="")=>{let o=t.split(":");if(t.slice(0,1)==="@"){if(o.length<2||o.length>3)return null;i=o.shift().slice(1)}if(o.length>3||!o.length)return null;if(o.length>1){let s=o.pop(),a=o.pop(),l={provider:o.length>0?o[0]:i,prefix:a,name:s};return e&&!M(l)?null:l}let r=o[0],c=r.split("-");if(c.length>1){let s={provider:i,prefix:c.shift(),name:c.join("-")};return e&&!M(s)?null:s}if(n&&i===""){let s={provider:i,prefix:"",name:r};return e&&!M(s,n)?null:s}return null},M=(t,e)=>t?!!((e&&t.prefix===""||t.prefix)&&t.name):!1;function be(t,e){let n=t.icons,i=t.aliases||Object.create(null),o=Object.create(null);function r(c){if(n[c])return o[c]=[];if(!(c in o)){o[c]=null;let s=i[c]&&i[c].parent,a=s&&r(s);a&&(o[c]=[s].concat(a))}return o[c]}return Object.keys(n).concat(Object.keys(i)).forEach(r),o}function ye(t,e){let n={};!t.hFlip!=!e.hFlip&&(n.hFlip=!0),!t.vFlip!=!e.vFlip&&(n.vFlip=!0);let i=((t.rotate||0)+(e.rotate||0))%4;return i&&(n.rotate=i),n}function pt(t,e){let n=ye(t,e);for(let i in K)i in R?i in t&&!(i in n)&&(n[i]=R[i]):i in e?n[i]=e[i]:i in t&&(n[i]=t[i]);return n}function ve(t,e,n){let i=t.icons,o=t.aliases||Object.create(null),r={};function c(s){r=pt(i[s]||o[s],r)}return c(e),n.forEach(c),pt(t,r)}function jt(t,e){let n=[];if(typeof t!="object"||typeof t.icons!="object")return n;t.not_found instanceof Array&&t.not_found.forEach(o=>{e(o,null),n.push(o)});let i=be(t);for(let o in i){let r=i[o];r&&(e(o,ve(t,o,r)),n.push(o))}return n}var we={provider:"",aliases:{},not_found:{},...Lt};function J(t,e){for(let n in e)if(n in t&&typeof t[n]!=typeof e[n])return!1;return!0}function Nt(t){if(typeof t!="object"||t===null)return null;let e=t;if(typeof e.prefix!="string"||!t.icons||typeof t.icons!="object"||!J(t,we))return null;let n=e.icons;for(let o in n){let r=n[o];if(!o||typeof r.body!="string"||!J(r,K))return null}let i=e.aliases||Object.create(null);for(let o in i){let r=i[o],c=r.parent;if(!o||typeof c!="string"||!n[c]&&!i[c]||!J(r,K))return null}return e}var F=Object.create(null);function xe(t,e){return{provider:t,prefix:e,icons:Object.create(null),missing:new Set}}function v(t,e){let n=F[t]||(F[t]=Object.create(null));return n[e]||(n[e]=xe(t,e))}function Pt(t,e){return Nt(e)?jt(e,(n,i)=>{i?t.icons[n]=i:t.missing.add(n)}):[]}function Ie(t,e,n){try{if(typeof n.body=="string")return t.icons[e]={...n},!0}catch{}return!1}function Ae(t,e){let n=[];return(typeof t=="string"?[t]:Object.keys(F)).forEach(i=>{(typeof i=="string"&&typeof e=="string"?[e]:Object.keys(F[i]||{})).forEach(o=>{let r=v(i,o);n=n.concat(Object.keys(r.icons).map(c=>(i!==""?"@"+i+":":"")+o+":"+c))})}),n}var T=!1;function Mt(t){return typeof t=="boolean"&&(T=t),T}function O(t){let e=typeof t=="string"?N(t,!0,T):t;if(e){let n=v(e.provider,e.prefix),i=e.name;return n.icons[i]||(n.missing.has(i)?null:void 0)}}function qt(t,e){let n=N(t,!0,T);if(!n)return!1;let i=v(n.provider,n.prefix);return e?Ie(i,n.name,e):(i.missing.add(n.name),!0)}function gt(t,e){if(typeof t!="object")return!1;if(typeof e!="string"&&(e=t.provider||""),T&&!e&&!t.prefix){let i=!1;return Nt(t)&&(t.prefix="",jt(t,(o,r)=>{qt(o,r)&&(i=!0)})),i}let n=t.prefix;return M({prefix:n,name:"a"})?!!Pt(v(e,n),t):!1}function Se(t){return!!O(t)}function Ce(t){let e=O(t);return e&&{...j,...e}}function Rt(t,e){t.forEach(n=>{let i=n.loaderCallbacks;i&&(n.loaderCallbacks=i.filter(o=>o.id!==e))})}function ke(t){t.pendingCallbacksFlag||(t.pendingCallbacksFlag=!0,setTimeout(()=>{t.pendingCallbacksFlag=!1;let e=t.loaderCallbacks?t.loaderCallbacks.slice(0):[];if(!e.length)return;let n=!1,i=t.provider,o=t.prefix;e.forEach(r=>{let c=r.icons,s=c.pending.length;c.pending=c.pending.filter(a=>{if(a.prefix!==o)return!0;let l=a.name;if(t.icons[l])c.loaded.push({provider:i,prefix:o,name:l});else if(t.missing.has(l))c.missing.push({provider:i,prefix:o,name:l});else return n=!0,!0;return!1}),c.pending.length!==s&&(n||Rt([t],r.id),r.callback(c.loaded.slice(0),c.missing.slice(0),c.pending.slice(0),r.abort))})}))}var _e=0;function Le(t,e,n){let i=_e++,o=Rt.bind(null,n,i);if(!e.pending.length)return o;let r={id:i,icons:e,callback:t,abort:o};return n.forEach(c=>{(c.loaderCallbacks||(c.loaderCallbacks=[])).push(r)}),o}function Ee(t){let e={loaded:[],missing:[],pending:[]},n=Object.create(null);t.sort((o,r)=>o.provider!==r.provider?o.provider.localeCompare(r.provider):o.prefix!==r.prefix?o.prefix.localeCompare(r.prefix):o.name.localeCompare(r.name));let i={provider:"",prefix:"",name:""};return t.forEach(o=>{if(i.name===o.name&&i.prefix===o.prefix&&i.provider===o.provider)return;i=o;let r=o.provider,c=o.prefix,s=o.name,a=n[r]||(n[r]=Object.create(null)),l=a[c]||(a[c]=v(r,c)),u;s in l.icons?u=e.loaded:c===""||l.missing.has(s)?u=e.missing:u=e.pending;let f={provider:r,prefix:c,name:s};u.push(f)}),e}var X=Object.create(null);function mt(t,e){X[t]=e}function Z(t){return X[t]||X[""]}function Te(t,e=!0,n=!1){let i=[];return t.forEach(o=>{let r=typeof o=="string"?N(o,e,n):o;r&&i.push(r)}),i}function ot(t){let e;if(typeof t.resources=="string")e=[t.resources];else if(e=t.resources,!(e instanceof Array)||!e.length)return null;return{resources:e,path:t.path||"/",maxURL:t.maxURL||500,rotate:t.rotate||750,timeout:t.timeout||5e3,random:t.random===!0,index:t.index||0,dataAfterTimeout:t.dataAfterTimeout!==!1}}var B=Object.create(null),_=["https://api.simplesvg.com","https://api.unisvg.com"],q=[];for(;_.length>0;)_.length===1||Math.random()>.5?q.push(_.shift()):q.push(_.pop());B[""]=ot({resources:["https://api.iconify.design"].concat(q)});function bt(t,e){let n=ot(e);return n===null?!1:(B[t]=n,!0)}function H(t){return B[t]}function Oe(){return Object.keys(B)}var je={resources:[],index:0,timeout:2e3,rotate:750,random:!1,dataAfterTimeout:!1};function Ne(t,e,n,i){let o=t.resources.length,r=t.random?Math.floor(Math.random()*o):t.index,c;if(t.random){let d=t.resources.slice(0);for(c=[];d.length>1;){let b=Math.floor(Math.random()*d.length);c.push(d[b]),d=d.slice(0,b).concat(d.slice(b+1))}c=c.concat(d)}else c=t.resources.slice(r).concat(t.resources.slice(0,r));let s=Date.now(),a="pending",l=0,u,f=null,h=[],g=[];typeof i=="function"&&g.push(i);function w(){f&&(clearTimeout(f),f=null)}function x(){a==="pending"&&(a="aborted"),w(),h.forEach(d=>{d.status==="pending"&&(d.status="aborted")}),h=[]}function p(d,b){b&&(g=[]),typeof d=="function"&&g.push(d)}function z(){return{startTime:s,payload:e,status:a,queriesSent:l,queriesPending:h.length,subscribe:p,abort:x}}function I(){a="failed",g.forEach(d=>{d(void 0,u)})}function y(){h.forEach(d=>{d.status==="pending"&&(d.status="aborted")}),h=[]}function m(d,b,k){let P=b!=="success";switch(h=h.filter(A=>A!==d),a){case"pending":break;case"failed":if(P||!t.dataAfterTimeout)return;break;default:return}if(b==="abort"){u=k,I();return}if(P){u=k,h.length||(c.length?G():I());return}if(w(),y(),!t.random){let A=t.resources.indexOf(d.resource);A!==-1&&A!==t.index&&(t.index=A)}a="completed",g.forEach(A=>{A(k)})}function G(){if(a!=="pending")return;w();let d=c.shift();if(d===void 0){if(h.length){f=setTimeout(()=>{w(),a==="pending"&&(y(),I())},t.timeout);return}I();return}let b={status:"pending",resource:d,callback:(k,P)=>{m(b,k,P)}};h.push(b),l++,f=setTimeout(G,t.rotate),n(d,e,b.callback)}return setTimeout(G),z}function Ft(t){let e={...je,...t},n=[];function i(){n=n.filter(c=>c().status==="pending")}function o(c,s,a){let l=Ne(e,c,s,(u,f)=>{i(),a&&a(u,f)});return n.push(l),l}function r(c){return n.find(s=>c(s))||null}return{query:o,find:r,setIndex:c=>{e.index=c},getIndex:()=>e.index,cleanup:i}}function yt(){}var Y=Object.create(null);function Pe(t){if(!Y[t]){let e=H(t);if(!e)return;Y[t]={config:e,redundancy:Ft(e)}}return Y[t]}function Dt(t,e,n){let i,o;if(typeof t=="string"){let r=Z(t);if(!r)return n(void 0,424),yt;o=r.send;let c=Pe(t);c&&(i=c.redundancy)}else{let r=ot(t);if(r){i=Ft(r);let c=Z(t.resources?t.resources[0]:"");c&&(o=c.send)}}return!i||!o?(n(void 0,424),yt):i.query(e,o,n)().abort}function vt(){}function Me(t){t.iconsLoaderFlag||(t.iconsLoaderFlag=!0,setTimeout(()=>{t.iconsLoaderFlag=!1,ke(t)}))}function qe(t){let e=[],n=[];return t.forEach(i=>{(i.match(Ot)?e:n).push(i)}),{valid:e,invalid:n}}function L(t,e,n){function i(){let o=t.pendingIcons;e.forEach(r=>{o&&o.delete(r),t.icons[r]||t.missing.add(r)})}if(n&&typeof n=="object")try{if(!Pt(t,n).length){i();return}}catch(o){console.error(o)}i(),Me(t)}function wt(t,e){t instanceof Promise?t.then(n=>{e(n)}).catch(()=>{e(null)}):e(t)}function Re(t,e){t.iconsToLoad?t.iconsToLoad=t.iconsToLoad.concat(e).sort():t.iconsToLoad=e,t.iconsQueueFlag||(t.iconsQueueFlag=!0,setTimeout(()=>{t.iconsQueueFlag=!1;let{provider:n,prefix:i}=t,o=t.iconsToLoad;if(delete t.iconsToLoad,!o||!o.length)return;let r=t.loadIcon;if(t.loadIcons&&(o.length>1||!r)){wt(t.loadIcons(o,i,n),l=>{L(t,o,l)});return}if(r){o.forEach(l=>{wt(r(l,i,n),u=>{L(t,[l],u?{prefix:i,icons:{[l]:u}}:null)})});return}let{valid:c,invalid:s}=qe(o);if(s.length&&L(t,s,null),!c.length)return;let a=i.match(Ot)?Z(n):null;if(!a){L(t,c,null);return}a.prepare(n,i,c).forEach(l=>{Dt(n,l,u=>{L(t,l.icons,u)})})}))}var it=(t,e)=>{let n=Ee(Te(t,!0,Mt()));if(!n.pending.length){let s=!0;return e&&setTimeout(()=>{s&&e(n.loaded,n.missing,n.pending,vt)}),()=>{s=!1}}let i=Object.create(null),o=[],r,c;return n.pending.forEach(s=>{let{provider:a,prefix:l}=s;if(l===c&&a===r)return;r=a,c=l,o.push(v(a,l));let u=i[a]||(i[a]=Object.create(null));u[l]||(u[l]=[])}),n.pending.forEach(s=>{let{provider:a,prefix:l,name:u}=s,f=v(a,l),h=f.pendingIcons||(f.pendingIcons=new Set);h.has(u)||(h.add(u),i[a][l].push(u))}),o.forEach(s=>{let a=i[s.provider][s.prefix];a.length&&Re(s,a)}),e?Le(e,n,o):vt},Fe=t=>new Promise((e,n)=>{let i=typeof t=="string"?N(t,!0):t;if(!i){n(t);return}it([i||t],o=>{if(o.length&&i){let r=O(i);if(r){e({...j,...r});return}}n(t)})});function xt(t){try{let e=typeof t=="string"?JSON.parse(t):t;if(typeof e.body=="string")return{...e}}catch{}}function De(t,e){if(typeof t=="object")return{data:xt(t),value:t};if(typeof t!="string")return{value:t};if(t.includes("{")){let r=xt(t);if(r)return{data:r,value:t}}let n=N(t,!0,!0);if(!n)return{value:t};let i=O(n);if(i!==void 0||!n.prefix)return{value:t,name:n,data:i};let o=it([n],()=>e(t,n,O(n)));return{value:t,name:n,loading:o}}var Bt=!1;try{Bt=navigator.vendor.indexOf("Apple")===0}catch{}function Be(t,e){switch(e){case"svg":case"bg":case"mask":return e}return e!=="style"&&(Bt||t.indexOf("=0;){let o=t.indexOf(">",i),r=t.indexOf("",r);if(c===-1)break;n+=t.slice(o+1,r).trim(),t=t.slice(0,i).trim()+t.slice(c+1)}return{defs:n,content:t}}function Ve(t,e){return t?""+t+""+e:e}function Ue(t,e,n){let i=Qe(t);return Ve(i.defs,e+i.content+n)}var ze=t=>t==="unset"||t==="undefined"||t==="none";function Ht(t,e){let n={...j,...t},i={...Et,...e},o={left:n.left,top:n.top,width:n.width,height:n.height},r=n.body;[n,i].forEach(x=>{let p=[],z=x.hFlip,I=x.vFlip,y=x.rotate;z?I?y+=2:(p.push("translate("+(o.width+o.left).toString()+" "+(0-o.top).toString()+")"),p.push("scale(-1 1)"),o.top=o.left=0):I&&(p.push("translate("+(0-o.left).toString()+" "+(o.height+o.top).toString()+")"),p.push("scale(1 -1)"),o.top=o.left=0);let m;switch(y<0&&(y-=Math.floor(y/4)*4),y=y%4,y){case 1:m=o.height/2+o.top,p.unshift("rotate(90 "+m.toString()+" "+m.toString()+")");break;case 2:p.unshift("rotate(180 "+(o.width/2+o.left).toString()+" "+(o.height/2+o.top).toString()+")");break;case 3:m=o.width/2+o.left,p.unshift("rotate(-90 "+m.toString()+" "+m.toString()+")");break}y%2===1&&(o.left!==o.top&&(m=o.left,o.left=o.top,o.top=m),o.width!==o.height&&(m=o.width,o.width=o.height,o.height=m)),p.length&&(r=Ue(r,'',""))});let c=i.width,s=i.height,a=o.width,l=o.height,u,f;c===null?(f=s===null?"1em":s==="auto"?l:s,u=tt(f,a/l)):(u=c==="auto"?a:c,f=s===null?tt(u,l/a):s==="auto"?l:s);let h={},g=(x,p)=>{ze(p)||(h[x]=p.toString())};g("width",u),g("height",f);let w=[o.left,o.top,a,l];return h.viewBox=w.join(" "),{attributes:h,viewBox:w,body:r}}function rt(t,e){let n=t.indexOf("xlink:")===-1?"":' xmlns:xlink="http://www.w3.org/1999/xlink"';for(let i in e)n+=" "+i+'="'+e[i]+'"';return'"+t+""}function Ge(t){return t.replace(/"/g,"'").replace(/%/g,"%25").replace(/#/g,"%23").replace(//g,"%3E").replace(/\s+/g," ")}function Je(t){return"data:image/svg+xml,"+Ge(t)}function $t(t){return'url("'+Je(t)+'")'}var Ye=()=>{let t;try{if(t=fetch,typeof t=="function")return t}catch{}},D=Ye();function We(t){D=t}function Ke(){return D}function Xe(t,e){let n=H(t);if(!n)return 0;let i;if(!n.maxURL)i=0;else{let o=0;n.resources.forEach(c=>{o=Math.max(o,c.length)});let r=e+".json?icons=";i=n.maxURL-o-n.path.length-r.length}return i}function Ze(t){return t===404}var tn=(t,e,n)=>{let i=[],o=Xe(t,e),r="icons",c={type:r,provider:t,prefix:e,icons:[]},s=0;return n.forEach((a,l)=>{s+=a.length+1,s>=o&&l>0&&(i.push(c),c={type:r,provider:t,prefix:e,icons:[]},s=a.length),c.icons.push(a)}),i.push(c),i};function en(t){if(typeof t=="string"){let e=H(t);if(e)return e.path}return"/"}var nn=(t,e,n)=>{if(!D){n("abort",424);return}let i=en(e.provider);switch(e.type){case"icons":{let r=e.prefix,c=e.icons.join(","),s=new URLSearchParams({icons:c});i+=r+".json?"+s.toString();break}case"custom":{let r=e.uri;i+=r.slice(0,1)==="/"?r.slice(1):r;break}default:n("abort",400);return}let o=503;D(t+i).then(r=>{let c=r.status;if(c!==200){setTimeout(()=>{n(Ze(c)?"abort":"next",c)});return}return o=501,r.json()}).then(r=>{if(typeof r!="object"||r===null){setTimeout(()=>{r===404?n("abort",r):n("next",o)});return}setTimeout(()=>{n("success",r)})}).catch(()=>{n("next",o)})},on={prepare:tn,send:nn};function rn(t,e,n){v(n||"",e).loadIcons=t}function sn(t,e,n){v(n||"",e).loadIcon=t}var W="data-style",Qt="";function cn(t){Qt=t}function It(t,e){let n=Array.from(t.childNodes).find(i=>i.hasAttribute&&i.hasAttribute(W));n||(n=document.createElement("style"),n.setAttribute(W,W),t.appendChild(n)),n.textContent=":host{display:inline-block;vertical-align:"+(e?"-0.125em":"0")+"}span,svg{display:block;margin:auto}"+Qt}function Vt(){mt("",on),Mt(!0);let t;try{t=window}catch{}if(t){if(t.IconifyPreload!==void 0){let n=t.IconifyPreload,i="Invalid IconifyPreload syntax.";typeof n=="object"&&n!==null&&(n instanceof Array?n:[n]).forEach(o=>{try{(typeof o!="object"||o===null||o instanceof Array||typeof o.icons!="object"||typeof o.prefix!="string"||!gt(o))&&console.error(i)}catch{console.error(i)}})}if(t.IconifyProviders!==void 0){let n=t.IconifyProviders;if(typeof n=="object"&&n!==null)for(let i in n){let o="IconifyProviders["+i+"] is invalid.";try{let r=n[i];if(typeof r!="object"||!r||r.resources===void 0)continue;bt(i,r)||console.error(o)}catch{console.error(o)}}}}return{iconLoaded:Se,getIcon:Ce,listIcons:Ae,addIcon:qt,addCollection:gt,calculateSize:tt,buildIcon:Ht,iconToHTML:rt,svgToURL:$t,loadIcons:it,loadIcon:Fe,addAPIProvider:bt,setCustomIconLoader:sn,setCustomIconsLoader:rn,appendCustomStyle:cn,_api:{getAPIConfig:H,setAPIModule:mt,sendAPIQuery:Dt,setFetch:We,getFetch:Ke,listAPIProviders:Oe}}}var et={"background-color":"currentColor"},Ut={"background-color":"transparent"},At={image:"var(--svg)",repeat:"no-repeat",size:"100% 100%"},St={"-webkit-mask":et,mask:et,background:Ut};for(let t in St){let e=St[t];for(let n in At)e[t+"-"+n]=At[n]}function Ct(t){return t?t+(t.match(/^[-0-9.]+$/)?"px":""):"inherit"}function an(t,e,n){let i=document.createElement("span"),o=t.body;o.indexOf("");let r=t.attributes,c=rt(o,{...r,width:e.width+"",height:e.height+""}),s=$t(c),a=i.style,l={"--svg":s,width:Ct(r.width),height:Ct(r.height),...n?et:Ut};for(let u in l)a.setProperty(u,l[u]);return i}var E;function ln(){try{E=window.trustedTypes.createPolicy("iconify",{createHTML:t=>t})}catch{E=null}}function un(t){return E===void 0&&ln(),E?E.createHTML(t):t}function dn(t){let e=document.createElement("span"),n=t.attributes,i="";n.width||(i="width: inherit;"),n.height||(i+="height: inherit;"),i&&(n.style=i);let o=rt(t.body,n);return e.innerHTML=un(o),e.firstChild}function nt(t){return Array.from(t.childNodes).find(e=>{let n=e.tagName&&e.tagName.toUpperCase();return n==="SPAN"||n==="SVG"})}function kt(t,e){let n=e.icon.data,i=e.customisations,o=Ht(n,i);i.preserveAspectRatio&&(o.attributes.preserveAspectRatio=i.preserveAspectRatio);let r=e.renderedMode,c;r==="svg"?c=dn(o):c=an(o,{...j,...n},r==="mask");let s=nt(t);s?c.tagName==="SPAN"&&s.tagName===c.tagName?s.setAttribute("style",c.getAttribute("style")):t.replaceChild(c,s):t.appendChild(c)}function _t(t,e,n){let i=n&&(n.rendered?n:n.lastRender);return{rendered:!1,inline:e,icon:t,lastRender:i}}function fn(t="iconify-icon"){let e,n;try{e=window.customElements,n=window.HTMLElement}catch{return}if(!e||!n)return;let i=e.get(t);if(i)return i;let o=["icon","mode","inline","noobserver","width","height","rotate","flip"],r=class extends n{_shadowRoot;_initialised=!1;_state;_checkQueued=!1;_connected=!1;_observer=null;_visible=!0;constructor(){super();let s=this._shadowRoot=this.attachShadow({mode:"open"}),a=this.hasAttribute("inline");It(s,a),this._state=_t({value:""},a),this._queueCheck()}connectedCallback(){this._connected=!0,this.startObserver()}disconnectedCallback(){this._connected=!1,this.stopObserver()}static get observedAttributes(){return o.slice(0)}attributeChangedCallback(s){switch(s){case"inline":{let a=this.hasAttribute("inline"),l=this._state;a!==l.inline&&(l.inline=a,It(this._shadowRoot,a));break}case"noobserver":{this.hasAttribute("noobserver")?this.startObserver():this.stopObserver();break}default:this._queueCheck()}}get icon(){let s=this.getAttribute("icon");if(s&&s.slice(0,1)==="{")try{return JSON.parse(s)}catch{}return s}set icon(s){typeof s=="object"&&(s=JSON.stringify(s)),this.setAttribute("icon",s)}get inline(){return this.hasAttribute("inline")}set inline(s){s?this.setAttribute("inline","true"):this.removeAttribute("inline")}get observer(){return this.hasAttribute("observer")}set observer(s){s?this.setAttribute("observer","true"):this.removeAttribute("observer")}restartAnimation(){let s=this._state;if(s.rendered){let a=this._shadowRoot;if(s.renderedMode==="svg")try{a.lastChild.setCurrentTime(0);return}catch{}kt(a,s)}}get status(){let s=this._state;return s.rendered?"rendered":s.icon.data===null?"failed":"loading"}_queueCheck(){this._checkQueued||(this._checkQueued=!0,setTimeout(()=>{this._check()}))}_check(){if(!this._checkQueued)return;this._checkQueued=!1;let s=this._state,a=this.getAttribute("icon");if(a!==s.icon.value){this._iconChanged(a);return}if(!s.rendered||!this._visible)return;let l=this.getAttribute("mode"),u=ht(this);(s.attrMode!==l||me(s.customisations,u)||!nt(this._shadowRoot))&&this._renderIcon(s.icon,u,l)}_iconChanged(s){let a=De(s,(l,u,f)=>{let h=this._state;if(h.rendered||this.getAttribute("icon")!==l)return;let g={value:l,name:u,data:f};g.data?this._gotIconData(g):h.icon=g});a.data?this._gotIconData(a):this._state=_t(a,this._state.inline,this._state)}_forceRender(){if(!this._visible){let s=nt(this._shadowRoot);s&&this._shadowRoot.removeChild(s);return}this._queueCheck()}_gotIconData(s){this._checkQueued=!1,this._renderIcon(s,ht(this),this.getAttribute("mode"))}_renderIcon(s,a,l){let u=Be(s.data.body,l),f=this._state.inline;kt(this._shadowRoot,this._state={rendered:!0,icon:s,inline:f,customisations:a,attrMode:l,renderedMode:u})}startObserver(){if(!this._observer&&!this.hasAttribute("noobserver"))try{this._observer=new IntersectionObserver(s=>{let a=s.some(l=>l.isIntersecting);a!==this._visible&&(this._visible=a,this._forceRender())}),this._observer.observe(this)}catch{if(this._observer){try{this._observer.disconnect()}catch{}this._observer=null}}}stopObserver(){this._observer&&(this._observer.disconnect(),this._observer=null,this._visible=!0,this._connected&&this._forceRender())}};o.forEach(s=>{s in r.prototype||Object.defineProperty(r.prototype,s,{get:function(){return this.getAttribute(s)},set:function(a){a!==null?this.setAttribute(s,a):this.removeAttribute(s)}})});let c=Vt();for(let s in c)r[s]=r.prototype[s]=c[s];return e.define(t,r),r}var hn=fn()||Vt(),{iconLoaded:Nn,getIcon:Pn,listIcons:Mn,addIcon:qn,addCollection:Rn,calculateSize:Fn,buildIcon:Dn,iconToHTML:Bn,svgToURL:Hn,loadIcons:$n,loadIcon:Qn,setCustomIconLoader:Vn,setCustomIconsLoader:Un,addAPIProvider:zn,_api:Gn}=hn;function pn(t){let e=t.getAttribute("aria-controls"),n=document.getElementById(e);n&&(n.addEventListener("click",i=>{i.stopPropagation()}),t.addEventListener("click",i=>{i.stopPropagation();let o=Gt(),r=o.indexOf(e);n.getAttribute("aria-hidden")==="false"?(o.splice(r,1),document.body.setAttribute("data-expanded",o.join(" ")),n.setAttribute("aria-hidden","true"),st(e,"false")):(o.push(e),document.body.setAttribute("data-expanded",o.join(" ")),n.setAttribute("aria-hidden","false"),st(e,"true"))}))}function st(t,e){let n=document.querySelectorAll('[aria-controls="'+t+'"]');for(let i=0;i{let t=Gt();document.body.setAttribute("data-expanded",""),t.forEach(e=>{document.getElementById(e).setAttribute("aria-hidden","true"),st(e,"false")})});var Jt=new Map;function gn(t){t.addEventListener("click",()=>{let e=t.querySelector("i");e.setAttribute("data-icon","loader");let n=t.getAttribute("data-url");n?mn(e,n):bn(e)})}function mn(t,e){let n=Jt.get(e);if(n){navigator.clipboard.writeText(n),ct(t);return}navigator.clipboard.write([new ClipboardItem({"text/plain":fetch(e).then(i=>i.text()).then(i=>(Jt.set(e,i),ct(t),i))})]).catch(()=>{t.setAttribute("data-icon","copy")})}function bn(t){import("https://esm.sh/turndown").then(e=>{let n=new e.default({headingStyle:"atx",bulletListMarker:"-",codeBlockStyle:"fenced"});return n.addRule("highlight",{filter:i=>i.nodeName==="DIV"&&i.classList.contains("highlight"),replacement:function(i,o){let r=Yt(o.parentNode.className),c="```";return r&&(c+=r),c+` +`+o.textContent.trim()+"\n```"}}),n.addRule("literal-block-wrapper",{filter:i=>i.nodeName==="DIV"&&i.classList.contains("literal-block-wrapper")&&i.querySelector(".highlight"),replacement:function(i,o){let r=o.querySelector(".highlight"),c=Yt(r.parentNode.className),s="```";if(c){let a=o.querySelector(".caption-text");s+=c,a&&(s+=' "'+a.textContent.trim()+'"')}return s+` +`+r.textContent+"\n```"}}),n}).then(e=>{let n=document.querySelector(".yue").cloneNode(!0),i=e.turndown(yn(n));return navigator.clipboard.writeText(i)}).then(()=>{ct(t)})}function ct(t){t.setAttribute("data-icon","check"),setTimeout(()=>{t.setAttribute("data-icon","copy")},500)}function yn(t){return t.querySelectorAll(".headerlink").forEach(e=>{e.remove()}),t.querySelectorAll(".copybtn").forEach(e=>{e.remove()}),t.querySelectorAll("span.linenos").forEach(e=>{e.remove()}),t.innerHTML}function Yt(t){let e=t.match(/highlight-(\S+)/);if(e)return e[1]}var Wt=document.querySelectorAll(".js-copy");for(let t=0;t{$.parentNode.removeChild($),document.head.removeChild(t)}),e(),window.addEventListener("resize",e)}var wn;var Q=["auto","light","dark"],V=document.querySelector(".js-theme");function xn(){let t=Xt();t+=1,Q[t]||(t=0);let e=Q[t];setColorMode(e),localStorage._theme=e,Zt(e)}function Kt(){return document.documentElement.getAttribute("data-color-mode")||"auto"}function Xt(){return Q.indexOf(Kt())}function Zt(t){let e=V.getAttribute("data-aria-"+t);V.setAttribute("aria-label",e)}V&&(V.addEventListener("click",xn),Zt(Q[Xt()]||"auto"));window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{Kt()==="auto"&&setColorMode("auto")});function In(){let t=document.querySelector(".globaltoc");if(!t)return;let e=parseInt(t.getAttribute("data-expand-depth"),10),n=o=>{if(!e)return!1;let r=0;for(;o.parentNode&&o.parentNode!==t;)o=o.parentNode,o.nodeName==="UL"&&(r+=1);return e>=r};t.querySelectorAll("li > ul").forEach(o=>{let r=o.parentNode;r.classList.contains("current")||n(r)?r.classList.add("_expand"):r.classList.add("_collapse");let c=An(o);r.appendChild(c)})}function An(t){let e=document.createElement("button");e.innerHTML='';let n=t.parentNode,i=t.previousSibling,o=i.textContent,r=()=>{n.classList.contains("_expand")?e.setAttribute("aria-label","Collapse "+o):e.setAttribute("aria-label","Expand "+o)};r();let c=s=>{s.preventDefault(),n.classList.contains("_expand")?(n.classList.remove("_expand"),n.classList.add("_collapse")):(n.classList.remove("_collapse"),n.classList.add("_expand")),r()};return i.getAttribute("href")==="#"&&i.addEventListener("click",c),e.addEventListener("click",c),e}var at=document.querySelector(".globaltoc a.current");at&&at.scrollIntoViewIfNeeded&&at.scrollIntoViewIfNeeded();In();var te=0,lt=200,S=[],C=document.querySelector(".back-to-top");function ee(){let t=document.querySelector(".yue > section");if(t){let e=window.getComputedStyle(t);lt=parseInt(e.scrollMarginTop,10)||0}}function Sn(t){let e;return t.nodeName==="DT"?e=t.parentNode.getBoundingClientRect():e=t.getBoundingClientRect(),e.top<=lt&&e.bottom>=lt}function Cn(){document.querySelectorAll(".localtoc li.active").forEach(t=>{t.classList.remove("active")})}function ne(t){let e=document.querySelector(`.localtoc a[href="#${t}"]`);if(!e)return;let n=e.parentNode;n.classList.contains("active")||(Cn(),n.classList.add("active"),n.scrollIntoViewIfNeeded&&n.scrollIntoViewIfNeeded(!1))}function oe(){let t;for(let e=0;e=t){let e=S[S.length-1];e&&ne(e.id)}else oe();C&&(window.scrollY&&window.scrollY{window.scrollTo(0,0)});document.querySelector(".localtoc")&&(window.addEventListener("scroll",kn),window.addEventListener("DOMContentLoaded",()=>{S=[...document.querySelectorAll(".yue > section section[id]"),...document.querySelectorAll(".yue dt.sig[id]")],ee(),oe()}),window.addEventListener("resize",ee));var U=document.querySelector(".js-repo-stats");async function _n(t,e){let n=`https://api.github.com/repos/${t}/${e}`,o=await(await fetch(n)).json(),r={stars:o.watchers,forks:o.forks};ut(r),sessionStorage.setItem("_sy/repo/stats",JSON.stringify(r))}async function Ln(t,e){let n="https://gitlab.com/api/v4/projects/"+encodeURIComponent(t+"/"+e),o=await(await fetch(n)).json(),r={stars:o.star_count,forks:o.forks_count};ut(r),sessionStorage.setItem("_sy/repo/stats",JSON.stringify(r))}function ut({stars:t,forks:e}){t&&(document.querySelector(".js-repo-stars").textContent=t),e&&(document.querySelector(".js-repo-forks").textContent=e)}function En(){let t=sessionStorage.getItem("_sy/repo/stats");if(t)ut(JSON.parse(t));else{let e=U.getAttribute("data-user"),n=U.getAttribute("data-repo"),i=U.getAttribute("data-type");i==="github"?_n(e,n):i==="gitlab"&&Ln(e,n)}}U&&En();function Tn(t,e){let n=document.createElement("script");n.id="_carbonads_js",n.src=`//cdn.carbonads.com/carbon.js?serve=${t}&placement=${e}`;let i=document.querySelector(".yue > section"),o=document.querySelector(".yue > section > section");if(o)i.insertBefore(n,o);else{let r=document.querySelector(".yue > section > p");r?i.insertBefore(n,r.nextSibling):i.appendChild(n)}}var dt=document.querySelector(".js-carbon");if(dt){let t=dt.getAttribute("data-carbon-code"),e=dt.getAttribute("data-carbon-placement");t&&e&&Tn(t,e)}var On=` +:host > div .results .hit h2 { + color: var(--sy-c-heading); + margin-bottom: 0; + border-bottom: 0; + font-weight: 600; +} +:host > div .results .hit .hit-block .content { + color: var(--sy-c-text); +} +:host > div .results .hit-block a.hit:hover, :host > div .results .hit-block .hit.active { + background-color: var(--gray-5); + border-radius: 4px; +} + +:host > div div.hit-block a.hit-block-heading:hover { + text-decoration: underline; +} + +:host > div div.hit-block a.hit-block-heading i, +:host > div div.hit-block .hit-block-heading-container .close-icon { + color: var(--sy-c-light); + margin-bottom: 0; + display: flex; +} +`;document.addEventListener("readthedocs-addons-data-ready",function(t){document.querySelector(".searchbox input").addEventListener("focusin",()=>{let e=new CustomEvent("readthedocs-search-show");document.dispatchEvent(e)}),setTimeout(()=>{let e=document.querySelector("readthedocs-search");if(e){let n=document.createElement("style");n.textContent=On,e.shadowRoot.appendChild(n)}},1e3)});/windows/i.test(navigator.userAgent)&&document.body.classList.add("win");})(); +/*! Bundled license information: + +iconify-icon/dist/iconify-icon.mjs: + (** + * (c) Iconify + * + * For the full copyright and license information, please view the license.txt + * files at https://github.com/iconify/iconify + * + * Licensed under MIT. + * + * @license MIT + * @version 3.0.2 + *) +*/ diff --git a/dev/doc/_static/sphinx_highlight.js b/dev/doc/_static/sphinx_highlight.js new file mode 100644 index 0000000..a74e103 --- /dev/null +++ b/dev/doc/_static/sphinx_highlight.js @@ -0,0 +1,159 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true; + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 + && !parent.classList.contains(className) + && !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore(span, parent.insertBefore(rest, node.nextSibling)); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect", + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target), + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms"); + // Update history only if '?highlight' is present; otherwise it + // clears text fragments (not set in window.location by the browser) + if (url.searchParams.has("highlight")) { + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + } + + // get individual terms from highlight string + const terms = highlight + .toLowerCase() + .split(/\s+/) + .filter((x) => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '", + ), + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms"); + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) + return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) + return; + if ( + DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + && event.key === "Escape" + ) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/dev/doc/admin/index.html b/dev/doc/admin/index.html new file mode 100644 index 0000000..b0e707a --- /dev/null +++ b/dev/doc/admin/index.html @@ -0,0 +1,2015 @@ + + + + + 18. Administrative Functions - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    18. Administrative Functions#

    +

    The source file cfe.c contains the main program. It calls +proc_command_line (in cmd_line.c) to parse the command line; +fe_init (in fe_init.c) to do global initialization; +translation_unit (in decls.c) to compile or cpp_driver (in +preproc.c) to do preprocessing; and fe_wrapup (in fe_wrapup.c) +to do global termination. If a back end should be called, and there were no +errors, it also calls back_end. Then, it calls fe_wrapup_part_2 +(also in fe_wrapup.c) to do post-back-end wrapup. Finally, it calls +exit_compilation to exit with the exit status appropriate to the +severity of the errors detected.

    +

    If multiple source files can be compiled, the main program includes a loop +around the steps from fe_init to back_end. It calls +get_next_source_file to see if there are any more source file names in +the command line.

    +

    Usually, the front end has its own main program, but it can instead be used +as part of some other main program. This is done by setting the +MAKE_FRONT_END_CALLABLE configuration macro. The name of the main entry +point into the front end is specified by the EDG_MAIN macro, and is +edg_main by default. When the front end is callable, +exit_compilation does not actually exit the program, but instead +returns control to the routine that called the front end.

    +
    +

    18.1. Initialization and Wrapup#

    +

    fe_init.c contains one-time initialization. Declarations of external +variables in .h files, which must begin with EXTERN, are compiled +here with EXTERN defined as an empty string, so storage is actually +allocated. Likewise, VAR_INITIALIZERS is defined as 1, so that +initializers on those variables are put out. The main routine is +fe_init; it calls other routines to initialize predefined macros, +keywords, and assorted state variables. In particular, it calls some +initialization routines in other files (e.g., lexical_init, +sym_tbl_init). There are several different kinds of initialization +routines:

    +
      +
    • +
      “early” initialization routines (e.g., cmd_line_early_init), which +are called before command-line processing is done.
      +
      +
    • +
    • +
      “one time” initialization routines (e.g., lexical_one_time_init), +which are called only once per invocation of the front end, even if +multiple source files have been specified on the command-line (when +COMPILE_MULTIPLE_SOURCE_FILES is enabled).
      +
      +
    • +
    • +
      “per-compilation” initialization routines (e.g., lexical_init), +which are called for each source file specified on the command-line +(when COMPILE_MULTIPLE_SOURCE_FILES is enabled).
      +
      +
    • +
    • +
      “trans-unit” initialization routines (e.g., +lexical_trans_unit_init), which are called once for each +translation unit processed when processing exported template definition +files or when COMPILE_MULTIPLE_TRANSLATION_UNITS is enabled.
      +
      +
    • +
    +

    Because the front end can be reinitialized (when +MAKE_FRONT_END_CALLABLE is used), most variables must be initialized +dynamically, not statically. Variables that are modified by command-line +processing must be initialized in early initialization routines.

    +

    Command-line -D and -U options are also handled here (see +preproc_init).

    +

    If multiple source files are accepted, fe_init is called at the start +of compilation of each file.

    +

    fe_wrapup.c contains one-time wrapup code. This involves popping the +file name scope, checking for errors on files written, and dumping debug +statistics, such as information on symbol table efficiency and on total +memory used. fe_wrapup is called after the front end is done but before +the back end (if any) is executed, and fe_wrapup_part_2 is called after +the back end (if any) is executed.

    +
    +

    18.1.1. C++/CLI Initialization#

    +

    The C++/CLI language depends in some essential ways on its core library, +which is loaded from assembly metadata (usually a file called +mscorlib.dll). The initialization process therefore preloads that +library and any others specified via the --preusing command-line option +with a call to process_preusings.

    +

    Immediately after loading the top-level declarations of the core library, +process_preusings also initializes a number of global variables (and +global array elements) to point to the symbols for special entities from +the core library (for example, the ref class System::Object). This is +done in init_cli_symbols.

    +

    init_cli_symbols also creates templates for cli::array, +cli::interior_ptr, and cli::pin_ptr. This is achieved by running +ordinary front end processing on string literals (via calls to +scan_top_level_metadata_declarations) containing the declarations for +those templates. The symbols representing these templates are recorded at +this time (for ease of reference in later contexts).

    +

    The symbol for namespace ::cli itself is created even earlier by a call +to make_symbol_for_namespace_cli.

    +
    +
    +
    +

    18.2. Debug Routines#

    +

    The source file debug.c contains the routine that processes the +command-line debug request option (-d), and also the routines +debug_enter and debug_exit which are called for flow tracing. When +the command-line debug request includes routine names, debug_enter +checks the name of the routine entered against the names on the request +list. If the name is found, the associated modification of debug_level +is done. An internal stack is used to preserve information from +debug_enter time to debug_exit time for a function. One trick: A +checksum of the stop tokens set is computed and stored on entry, and +recomputed and checked on exit. This helps catch mismatched +add_stop_token and remove_stop_token calls in recursive descent +scanning routines.

    +

    debug_enter and debug_exit are not called if there is no +command-line debug request (i.e., if db_active is FALSE).

    +
    +
    +

    18.3. Generating Strings from IL Types and Constants#

    +

    il_to_str.c contains code that converts IL types and constants into +C/C++-form strings. Associated declarations are in il_to_str.h.

    +

    To use these routines, one needs to declare a control block of type +an_il_to_str_output_control_block, call +clear_il_to_str_output_control_block to initialize it, and then set +applicable fields to describe how the string output should be done. The +control block includes, among other things, a pointer to a routine to +output a string, so one can establish a control block that provides an +output routine that writes to a file, or a control block that provides a +routine that puts the output string into a buffer, etc. Other fields in the +control block control the style of output and provide other (optional) +callback routines to do specialized output (instead of the default version) +for certain constructs.

    +

    form_type produces a string for a type. It does this by calling

    +
      +
    • +
      form_type_first_part, which outputs the type specifiers and the +part of the declarator that precedes the name, and then
      +
      +
    • +
    • +
      form_type_second_part, which outputs the part of the declarator +following the name.
      +
      +
    • +
    +

    So, for example, for the type

    +
    +
    +
    array [10] of pointer to const int
    +
    +
    +

    the “first part” would be

    +
    const int *
    +
    +
    +

    and the second part would be

    +
    [10]
    +
    +
    +

    If one wants to put out a declaration of an identifier, one can do so by

    +
      +
    1. calling form_type_first_part, then

    2. +
    3. outputting the identifier, then

    4. +
    5. calling form_type_second_part.

    6. +
    +

    producing an overall output string like “const int *a[10]”.

    +

    form_type_first_part descends through any derived types that are at the +top of the type by calling itself recursively. When it reaches a +non-derived type, it calls form_type_specifier to output the specifiers +part of the type (e.g., “const int” for the above example). Then, while +reascending, it puts out the parts of the declarator that appear on the +left-hand side of the declarator (pointers, references, +pointers-to-members, and any required parentheses).

    +

    form_type_second_part also descends through any derived types by +calling itself recursively. While descending, it puts out the parts of the +declarator that appear on the right-hand side of the declarator (arrays, +functions, and any required parentheses). form_array_declarator puts +out array declarators. form_function_declarator puts out function +declarators; it can be replaced by a user-provided routine if desired. One +reason to replace it: It does not handle putting out function declarators +for function definitions.

    +

    form_type_specifier puts out non-derived types. Most cases are simple +(see, for example, form_int_kind_name and +form_float_kind_name). Typedef names are put out as such. class, +struct, union, and enum types are always put out as references +to those types, i.e., a definition is never put out.

    +

    form_name puts out names; it can be replaced by a user-provided routine +if desired. It handles qualified names (see +form_class_or_namespace_qualifier), unnamed entities, and template +argument lists on classes (see form_template_args).

    +

    form_constant produces a string for a constant. It does some processing +itself, and has several important helper routines:

    +
      +
    • +
      form_integer_constant puts out integer constants, including sign, +suffix, and implicit casts. It also handles integer constants cast to +pointer types (e.g., null pointers).
      +
      +
    • +
    • +
      form_address_constant puts out address constants, including the +“&” and optimizations for arrays and for adding a byte offset to +the base address.
      +
      +
    • +
    • +
      form_pm_constant puts out pointer-to-member constants, including +null constants and any required implicit casts.
      +
      +
    • +
    • +
      form_char puts out a single character of a string or character +constant, dealing with unprintable characters and the like.
      +
      +
    • +
    +
    +
    +

    18.4. Error Reporting#

    +

    error.c contains code that handles reporting of errors. error.h +contains the declarations needed to use the error +routines. error_msg.txt defines the error codes and associated error +message text for all of the error messages, and, along with +error_tag.h, is used by mk_errinfo to generate the err_codes.h +and err_data.h files. It is the generated files that are actually used +by the front end to define the an_error_code enumeration and the array +of error message text. See mk_errinfo for a description.

    +

    an_error_code defines enumeration constants that represent each error +message (for example, ec_unclosed_string represents the error message +“missing closing quote”). ec_no_error is the first member of the +enumeration, and therefore has the value 0, which has the effect of +allowing flags with the value 0 for no error, and a non-zero value to +indicate a specific error.

    +

    Within the error message texts, fill-in codes beginning with “%” +indicate points at which information is to be inserted:

    +
    + + + + + + + + + + + + + + + + + + +
    +
    %%
    +
    +
    +
    A “%” is inserted into the message.
    +
    +
    +
    %d
    +
    +
    +
    A number is inserted into the message.
    +
    +
    +
    %s
    +
    +
    +
    A character string is inserted into the message. %sq indicates +that the inserted string should be placed in quotes, e.g.,
    +
    +
    +

    could not open source file "abc.h"

    +
    +
    +
    %t
    +
    +
    +
    A description of a type is inserted into the message. It is always +placed in quotes, e.g.,
    +
    +
    +

    cast to array type is nonstandard (treated as cast to +"int *")

    +
    +
    +
    %n
    +
    +
    +
    A description of an entity in the program (identified by a symbol) +is inserted into the message. The default %n (“name”) can be +modified by appending an “o” (%no, “name only”) to get just +the name of the entity, a “p” (%np, “name with function +parameters”) to force parameter information on a function, an +“f” (%nf, “name full”) to get full type information on the +name, an “a” (%na, “name with template arguments”) to get +arguments on a template, “t” to force the “A<T> with T=int” +form of template name to be used, or a “T” to get the translation +unit in which the symbol was declared.
    +
    +
    + + + + + + + + + + + + + + + + + + + + + +
    +
    %n
    +
    +
    +
    function "A::f"
    +
    +
    +
    %no
    +
    +
    +
    "A::f"
    +
    +
    +
    %np
    +
    +
    +
    "A::f(int, float)"
    +
    +
    +
    %na
    +
    +
    +
    "A<int>"
    +
    +
    +
    %nt
    +
    +
    +
    "A<T> with T=int"
    +
    +
    +
    %nT
    +
    +
    +
    function "f(int)" (from translation unit "x.c")
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + +
    +
    %p
    +
    +
    +
    A source position is inserted into the message.
    +
    +
    +
    %[label]
    +
    +
    +
    The specified label is looked up in the label_fill_ins array +and one of two error messages is substituted depending on the +value of a boolean variable associated with the label. The +substituted error messages cannot themselves have fill-ins. See +the definition of label_fill_ins to determine the list of +valid label fill-ins (or to add a new one).
    +
    +
    +
    %T
    +
    +
    +
    A template argument list is inserted into the message.
    +
    +
    +
    +

    In the default mode, the entity description is preceded by a keyword that +identifies the type of the entity (e.g., function above). That is also +done in the “full” mode for entities that are not variable-like or +function-like. The normal “%n” displays function parameter types only +for overloaded functions. Any of the %n codes can be modified by +appending a “d” to request information on the point of declaration of +the symbol:

    +
    declaration is incompatible with "int f(char)" (declared at line 17)
    +
    +
    +

    Following the optional “d” modifier, the “T” modifier may be used +to display the translation unit associated with the symbol (”from +translation unit "x.c"”). When compiling a primary translation unit, this +will cause the translation unit to be displayed for symbols from secondary +translation units. When compiling a secondary translation unit, this will +cause the translation unit to be displayed for all symbols.

    +

    There can be more than one fill-in code in a message. When there is, each +fill-in code can be numbered (e.g., %t1, %t2) to tie it to a +corresponding fill-in argument. Note that this technique allows one to +reorder the fill-ins in a message (say, when changing the error messages to +a language other than English) without changing the order of the fill-in +arguments on error calls throughout the front end.

    +

    Each normal diagnostic includes four kinds of information:

    +
      +
    • +
      the error code, which is a value from the enumeration just mentioned, +and indicates the error message text;
      +
      +
    • +
    • +
      a severity (remark, warning, discretionary error, error, or +catastrophic error);
      +
      +
    • +
    • +
      the error position (a sequence number and column); and
      +
      +
    • +
    • +
      optionally, some information that goes into fill-in spots in the error +message text.
      +
      +
    • +
    +

    The severity is usually indicated by the routine called (e.g., warning +instead of error). There are also routines that accept the severity as +an argument. A given message can be (and is, in many cases) output with +different severities in different modes or different places.

    +

    The severity of a given error code may be overridden through the use of a +command line option or pragma. For example, the option +--diag_error=extra_semicolon may be used to cause the extra semicolon +diagnostic to be issued as an error, even if the warning function was +actually called to report the error. Only diagnostics that would by default +be issued as remarks, warnings, or discretionary errors may have their +severities overridden (i.e., nondiscretionary errors and catastrophic +errors may not have their severities overridden). When a severity is +overridden by a pragma, the default severity can be restored by use of the +diag_default pragma. The default severity is the severity as would +normally be used for the message as adjusted by any command-line options.

    +

    The error severity may be overridden by specifying either an error “tag” or +an error number. The error tag is a name assigned to each error code. The +error number is the numeric value of the error code enumerator that +represents the message. By default, the error tag is the same as the error +code enumerator name with the ec_ prefix removed. The error tag may be +changed by specifying an alternate tag in the error_msg.txt +file. Additional tags may be provided by creating entries in the +error_tag.txt file. set_severity_for_error_tag and +set_severity_for_error_number are used to override the severity for a +given diagnostic. These routines are called to process the error severity +options during command line processing.

    +

    The error position is usually given by the global variable +error_position, but it can also be explicitly +supplied. error_position is set to the start of each token as it is +scanned, and is set on exit from recursive descent routines to the start of +the entity just scanned, unless that entity is extremely large (like +several lines). This usually results in the correct position in +error_position, at least for syntax errors.

    +

    When the sequence number of a_source_position is 0, the column has +special meaning (for example, it can indicate that the error occurred in +the command line). See basics.h.

    +

    The error routines themselves have names that encode the severity (one of +remark, warning, error, catastrophe or the generic +diagnostic), and the particular combination of fill-ins and a source +position that they accept. That is, an error routine name may be as simple +as error or as complicated as pos_ty2_warning. pos indicates +that a source position is provided; str or st indicates that a +string fill-in is provided; sym or sy indicates that a symbol +fill-in is provided; type or ty indicates that a type fill-in is +provided. These can be followed by a number if more than one fill-in is +needed, e.g., ty2 for two types. So, for example, pos_ty2_warning +issues a warning, and the caller is expected to provide the error code, the +source position, and two fill-in types. See error.c for the full list +of routines. Not all combinations exist, but it is easy to add any routine +that does not exist.

    +

    For a syntax error, one can instead call

    +
    syntax_error(error_code);
    +
    +
    +

    which will call error and then flush_tokens (see lexical.c).

    +

    For complicated errors that may have to list an arbitrary number of items, +for example diagnostics for overloading ambiguity, one can make an initial +call to issue the initial line of the error (calling start_error or one +of its variants such as type_start_error), then any number of calls to +add individual lines of additional information (calling add_diag_info +or one of its variants such as sym_add_diag_info), and then a call to +end_error to finish the error processing (including writing the source +line in error). The end result is illustrated by

    +
    "test.C", line 7: more than one constructor applies to convert from
    +          "double" to "A":
    +            function "A::A(int)"
    +            function "A::A(float)"
    +    f(2.0);
    +      ^
    +
    +
    +

    The usual fill-in processing is available on both the initial line and any +lines of additional information. The additional lines are described by an +error code, so they can also contain arbitrary text.

    +

    The error formatting and processing is done by construct_message. It +fetches the error message text, builds a linked list of message segments +describing the message and its fill-in codes, expands each fill-in +appropriately, and writes the full message.

    +

    If an error is detected while processing a template instantiation or during +implicit generation of a routine (e.g., a constructor), it is helpful to +provide additional information on the context in which the error was +detected:

    +
    "test.c", line 7: error: "A::A()" is inaccessible
    +  B x;
    +     ^
    +          detected during implicit generation of "B::B()" at line 7
    +
    +
    +

    The context is deduced from the entries in the scope +stack. include_in_context_output identifies the scope stack entries +that merit extra context information. If there are any such entries, +diag_message outputs an extra context line for each, in order from +innermost context to outermost.

    +

    format_output_line is the routine that actually prints the diagnostic +messages; it is the routine to change to modify the error output. To output +the source line associated with the diagnostic, write_source_line is +called. If the error is in the current line, write_orig_source_line +reconstructs and writes out the original source line, with a caret under +the column position of the error. If the error is not in the current line, +write_error_source_line reads the line from the source file, if +possible, and writes out the source line. Long diagnostic messages are +wrapped across multiple lines. If raw listing information is requested, +similar information is written to f_raw_listing (in encoded form). The +diagnostic routines count the number of diagnostics of each severity so +that the compilation can be ended with an appropriate exit status. They +suppress diagnostics that are below the error display threshold. If an +error is catastrophic or if the error limit is reached, the compilation is +terminated.

    +

    The severity of diagnostics for strict ANSI violations and C++ anachronisms +can be specified by command line options. To simplify handling of these +diagnostics the global variables strict_ansi_error_severity and +strict_ansi_discretionary_severity contain the error severity to be +used for strict ANSI violations. The former is either es_warning or +es_error, while the latter is either es_warning or +es_discretionary_error, depending on which strict mode was selected on +the command line. anachronism_error_severity contains the error +severity to be used when anachronistic features are used. These global +variables can be used as arguments to the diagnostic reporting +routines.

    +

    command_line_error and str_command_line_error are the routines +called for command-line errors (without or with fill-in text, +respectively). They do not return.

    +

    The routine internal_error should be called for internal errors, such +as failures of consistency checks. It should not be called for anything +that is due to a source program error or some environmental error (like a +missing file). The call should look like

    +
    +

    internal_error("routine-name: problem found");

    +
    +

    Several routines are provided as convenient ways to do consistency +checking. Calls of these routines need not be surrounded by #if +CHECKING/#endif; they are defined as macros that expand to nothing +when CHECKING is disabled. check_assertion can be used to check an +expression to make sure it is true; check_assertion_str is similar, but +includes a string to be printed on error +termination. unexpected_condition is used when a piece of code is not +expected to be reached (for example, the default clause of a switch); +unexpected_condition_str is similar, but includes a string to be +printed on error termination.

    +
    +
    +

    18.5. Memory Management#

    +

    mem_manage.c contains memory management routines. mem_manage.h +contains the associated declarations.

    +

    Memory is allocated in memory regions. File-scope intermediate language +information is put in memory region 1, and the functions in the source +program will each have one of the memory regions 2, 3, and so forth. Memory +region 0 is used for storage that need not survive the front end, like the +symbol table.

    +

    Before using a memory region, one calls either init_memory_region (for +regions 0 and 1) or new_memory_region (for regions for functions) to +initialize the new region.

    +

    alloc_in_region is then called when needed to allocate space in a given +region. (alloc_fe can be called for the special case of allocation in +region 0, the front-end-only region.) alloc_in_region allocates a large +block of memory for each memory region by calling malloc, then parcels +out that storage as it is needed. When the block is exhausted, a new block +is allocated and put on a linked list of blocks for that memory region.

    +

    When one is done with an IL memory region, +check_for_done_with_memory_region is called; it will either write the +information to a file and free the block, or trim the end of the memory +region to reclaim any unused space (depending on whether an IL file is +being generated), or defer this processing until later if the memory is +potentially needed for operations such as inlining or generic lambda +instantiation. “Trimming” means making a separate available block from the +remaining space at the end of the last block in the region. Since the +blocks are large (typically, 64K) and a typical function will use less than +10K of the block, this is an important feature. The combination of using a +large block size and reusing the remaining space improves efficiency (in +reducing the number of calls to malloc) and avoids the need to guess at +the amount of storage a particular memory region is likely to +need. Eventually, when the partial blocks created in this way are released, +they are recombined into the original large blocks allocated via +malloc, and freed using the system free. Thus storage used is +freed, but only on a large-block basis, so fragmentation is not a problem.

    +

    alloc_general is a more-or-less direct interface to malloc to be +used in the infrequent cases where storage must be allocated that will +survive into the back end if the back end is called in the same program. An +example of such storage is the debug option control list, which holds +information about the command-line debug option.

    +

    alloc_resizable_buffer and realloc_buffer are used to allocate +tables that can be enlarged (e.g., input_stack).

    +

    When MAKE_FRONT_END_CALLABLE is used, the front end keeps a record of +all memory allocations so that all of the memory allocated can be freed +before returning control to the caller.

    +

    When precompiled headers are used, the memory management routines work to +allocate the IL memory region blocks at reproducible addresses, so that the +information in a precompiled header file can be read back in without the +need to walk the IL and remap pointer references. See +Memory Management Issues.

    +
    +
    +

    18.6. File Variables#

    +

    Normally, any open files are closed when the front end exits, but when +MAKE_FRONT_END_CALLABLE is used, any open files must be closed if the +front-end were to terminate abnormally. This is accomplished by having a +special cleanup routine (e.g., templates_cleanup) in any file that +opens and closes files. The cleanup routine is present only when +MAKE_FRONT_END_CALLABLE is used. File variables must be set to NULL +when they do not refer to an open file. The cleanup routine generally calls +close_file_if_open, to close any files that may be open. The cleanup +routines are called by fe_cleanup (in fe_wrapup.c).

    +
    +
    +

    18.7. Command-line Parsing#

    +

    cmd_line.c contains code to parse the command line; cmd_line.h +contains the associated declarations. The main routine is +proc_command_line. Aside from setting switches, proc_command_line +establishes the primary source file, the preprocessing output file if there +is one, the raw listing output file if there is one, the cross-reference +output file if there is one, and the include file search list.

    +

    If multiple source files can be compiled, get_next_source_file is +called after each source file is compiled to see if there is another file +name on the command line. It also does some minor initialization.

    +

    proc_command_line is called only once, even if multiple source files +are specified on the command line. Since the IL memory for each source file +is separate and self-contained, proc_command_line cannot allocate +anything in the IL memory: For one thing, it does not exist yet, and for +another, there will be a distinct copy for each source file +compiled. Therefore, file names and other information saved by +proc_command_line must be saved in general memory, and copied into IL +memory later (e.g., in fe_init) for each source file.

    +
    +
    +

    18.8. Host-dependent Routines#

    +

    host_envir.c contains host-dependent routines; host_envir.h +contains the associated declarations.

    +

    The following routines are used to maintain the list of directory names to +be searched for include files:

    +
      +
    • +
      add_default_include_search_path
      +
      +
    • +
    • +
      add_to_include_search_path
      +
      +
    • +
    • +
      add_to_front_of_include_search_path
      +
      +
    • +
    • +
      push_primary_include_search_dir
      +
      +
    • +
    • +
      pop_primary_include_search_dir
      +
      +
    • +
    • +
      change_primary_include_search_dir
      +
      +
    • +
    +

    The following routines are used to tear apart and build up file names:

    +
      +
    • +
      directory_of
      +
      +
    • +
    • +
      gs_directory_of
      +
      +
    • +
    • +
      derived_name
      +
      +
    • +
    • +
      replace_file_name_suffix
      +
      +
    • +
    • +
      combine_dir_and_file_name
      +
      +
    • +
    +

    The following routines are used to open files in various ways:

    +
      +
    • +
      open_source_file
      +
      +
    • +
    • +
      reopen_source_file
      +
      +
    • +
    • +
      okay_as_output_file
      +
      +
    • +
    • +
      open_output_file
      +
      +
    • +
    • +
      reopen_error_output_file
      +
      +
    • +
    +

    delete_file is used to delete files (specifically, files that were +partially generated and are to be canceled because of detection of an +error).

    +

    open_temp_file and close_temp_file provide support for creating +temporary files. (Note: At the present time, the front end only uses +temporary files when generating an intermediate language file for immediate +use by a back end called in the same program, and in the C-generating back +end.)

    +

    normal_termination and term_compilation are used for termination of +the compilation. The low-level functions of term_compilation are +available individually through write_signoff and exit_compilation.

    +

    identify_source_file is called from fe_init at the start of +compilation of each source file when there are multiple source files on the +command line. It outputs a message identifying the start of the compilation +of the file.

    +

    set_signal_handlers is called during initialization to set up handling +for signals that should abort the compilation.

    +

    This file is likely to be modified for different hosts. See the section on +host configuration for more information.

    +
    +
    +

    18.9. Intermediate Language Traversal#

    +

    il_walk.c contains the routines that walk the intermediate language +tree, and il_walk.h contains the associated +declarations. walk_entry.h contains the detailed code to process the +fields of each IL entry kind.

    +

    “Walking” the tree means traversing the in-memory form of the IL and +calling a supplied routine for each node in the tree. This is used in +displaying the IL in human-readable form, in writing the IL to a file, and +in reading the IL from a file.

    +

    The walking is done on a memory region basis, i.e., for the file-scope +memory region or the memory region for a function. The routines for those +cases are walk_file_scope_il and walk_routine_scope_il. They call +walk_entry_and_subtree or walk_string_entry for each entry, and +those in turn call the user-supplied entry processing functions. There are +two separate entry processing functions supplied for each traversal: one +for strings, and one for non-strings. The main reason for the difference is +that string entries do not have fixed sizes, so the string routine has an +extra parameter for the size.

    +

    Since the tree is actually a graph and has cycles, there needs to be a way +to tell when the traversal returns to an entry that has already been +visited. This is provided by the il_walk_flag in the prefix that +precedes each IL entry. This flag starts out as 0 in all entries. On the +first traversal, it is changed to 1 in all entries, and it keeps +alternating between 0 and 1 on each subsequent traversal. Therefore, on a +given traversal, the entries already seen have one value, and those not yet +seen have the other value.

    +

    While the tree is traversed, one can also request that all the pointers in +the tree be remapped in some way. For example, when writing to an IL file +in the alternate form, each pointer is replaced by an entry number. Such +remapping can be requested by providing a pointer remap function for the IL +walk, or explicitly by calling remap_pointers_in_il_entry or +remap_il_header_pointers.

    +

    Special handling is required for “orphan” entries. These are entries +allocated in the file scope memory region that are referenced only from +function scope memory regions. When the parents of such entries are written +out and then removed from memory, the entries are orphaned because they are +not attached to the rest of the file-scope IL tree.

    +

    The orphan mechanism makes lists of such entries so that they can be found +during traversal of the file-scope IL.

    +

    The array orphaned_file_scope_il_entries heads lists of orphaned +entries linked together by a hidden orphan-list pointer that precedes the +storage for each file-scope IL entry. (It also precedes the +an_il_entry_prefix structure.)

    +

    The orphan lists are built up while the function scope memory regions are +walked. Each time an entry in a function scope memory region contains a +pointer into the file scope memory region, the entry pointed to is recorded +as a potential orphan. Later, at the end of the walk of the file scope IL, +the entries on the orphan lists are visited. If the entries are not in fact +orphans, they will have been previously visited, and the IL walk flag will +indicate that fact.

    +

    A separate mechanism exists for orphaned lists, specifically the lists of +local types and local static variables in function and block scopes. Those +are unusual in that the list is completely in the file scope memory region +but the pointer to the list is in a function scope memory region +entry. Each of the entries on those lists is placed on the orphaned entries +list, but there needs in addition to be a way to remember the head-of-list +pointers so that the next pointers in the entries can be +remapped. That’s done with a list of entries of type +a_scope_orphaned_list_header pointed to by the +scope_orphaned_list_headers field of il_header. Each entry on the +list points to a list of types and a list of static variables preserved +from a function or block scope.

    +

    Obviously, the code in walk_entry.h must be kept up-to-date whenever +the IL definition in il_def.h is changed.

    +

    il_walk.c also contains some special-purpose walking routines: +walk_declarative_entities_in_scope can be used to walk entities like +variables in a given scope; traverse_expr can be used to walk an +expression tree; and traverse_statement can be used to walk a statement +tree. In each case, user-provided callback routines can be called for each +node of the tree.

    +
    +
    +

    18.10. Needed Flags#

    +

    When the configuration switch MAINTAIN_NEEDED_FLAGS is TRUE, the front +end will maintain the needed flag in the source-correspondence entry, +and the definition_needed flag in class types and routines. The code to +do this is in il_walk.c, walk_entry.h, il.c, and +scope_stk.c. The needed flags are a more sophisticated version of the +referenced flag. They are set by beginning with all externally-defined +variables, static data members, and functions in the compilation unit, and +marking those as needed. Then the entities referenced by those are marked +as needed, and so on. The resulting needed flag setting indicates +whether something is “really” needed, as opposed to referenced from +something that is itself unneeded. For example:

    +
    static int i;         // i is referenced, not needed
    +static void f() {     // f is not referenced, not needed
    +  i = 1;
    +}
    +int main () {}        // main is needed, not referenced
    +
    +
    +

    The definition_needed flag indicates whether the definition of a class +is needed, as opposed to merely a declaration. For example:

    +
    struct A { };
    +struct B { };
    +A *p;      // forces needed on A, but not definition_needed
    +B b;       // forces needed and definition_needed on B
    +
    +
    +

    There is a similar flag for functions as well.

    +

    If DEFAULT_REMOVE_UNNEEDED_ENTITIES is TRUE, and that setting is not +overridden via a command-line option, unneeded entities are removed from +the IL. Classes that have needed TRUE and definition_needed FALSE +are modified to eliminate their definitions. Function-local entities are +never affected by this process (they are not removed, and local classes are +never turned into declarations). The IL tree after alteration is +self-consistent, in that a back end that does not use the “needed” flags +will find all the IL entries it expects. A back end that does use the +“needed” flags should be sure to use both of them, i.e., +definition_needed as well as needed.

    +

    The “needed” flags processing and removal of unneeded entries works with +and without IL lowering, and for both C and C++. When IL lowering is used, +the “needed” flag information is determined on the basis of the lowered +code. When the C++-generating back end is used, and the source program has +templates, elimination of unneeded entities is disabled, because the +template bodies may contain references to apparently unneeded +entities. This can be changed, carefully, if one has a situation where all +template instantiation will be done by the EDG front end rather than by +some compiler operating on the source code generated by the C++-generating +back end.

    +

    The setting of the “needed” flags is done as follows:

    +
      +
    • +
      At the end of scanning a function definition, if the function is +externally defined, pop_scope calls mark_as_needed on the +routine, which in turn calls set_routine_definition_needed. These +use a specialized version of the walk_entry.h IL-walking code to +sweep through the IL tree and set the needed flag on all +transitively-referenced entities. If the type of reference requires a +complete type, and the type is a class, set_class_definition_needed +is called to set the definition_needed flag on the class. If a +reference to a routine requires that the routine have a definition, +set_routine_definition_needed is called for the routine.
      +

      +
      When a routine’s definition is needed, the definition is also walked, +and then the memory region for the function can be disposed +of. (mark_to_keep_in_il is also called for the function memory +region; more on this below.) That means the memory region can be +written to a file and then freed, if an IL file is being +used. Conversely, as long as a function is not known to be needed, its +body must be retained. If the function is still marked as unneeded at +the end of the compilation, it is then clear that the function truly is +unneeded. It is deleted and its memory region is freed (without writing +it to the IL file, if there is one).
      +
      +
    • +
    • +
      When the file scope is being +popped from the scope stack, several things are done. First, +set_needed_flags_at_end_of_file_scope is called. It visits all +variables (including static data members), and calls mark_as_needed +for those that are externally-defined. This causes the variables and +everything they reference to be marked as “needed.”
      +
      +
    • +
    • +
      Then, +mark_to_keep_in_il is called for the file scope. This uses another +variant of the walk_entry.h IL-walking code to sweep through the IL +tree and set the keep_in_il flags in the IL entry prefix and the +keep_definition_in_il flag in classes and routines. These flags +have meanings similar to the needed and definition_needed +flags, but they are set in more cases, to deal with the fact that some +entities in the IL tree must be retained (for consistency) even if they +are “unneeded.” In this sweep, entities that can and will be removed +(based on the needed and definition_needed flags and the +context where the entities appear) will not be visited. The +keep_in_il sweep also notes whether complete class types are +needed, and calls set_class_keep_definition_in_il when appropriate, +and whether routine definitions are needed, and calls +set_routine_keep_definition_in_il.
      +

      +
      All decisions about +removing IL entries from the IL tree are based on the keep_in_il +and keep_definition_in_il flags, rather than on needed and +definition_needed.
      +
      +
    • +
    • +
      Then, +eliminate_bodies_of_unneeded_functions is called. It eliminate the +bodies (but not the declarations) of functions that are not needed.
      +
      +
    • +
    • +
      Then, eliminate_unneeded_il_entries is called. It removes types, +variables, and routines in the file scope that are unneeded, and +reduces classes to declarations where appropriate (by calling +turn_class_definition_into_declaration). Auxiliary parts of the IL +data structure, such as source sequence entries and the hidden-name +table, are updated as necessary.
      +
      +
    • +
    +

    The IL-walk process used to set these “needed” flags stops when it +encounters an entry with the flag already set. This is desirable for +compilation speed reasons, and necessary to avoid loops for parts of the IL +structure that are graphs instead of trees, but it also makes certain kinds +of problems possible. Variables, routines, and types that are not +function-local have the potential to be redeclared after the “needed” flag +is initially set. For example, a class A might be declared, then marked +as needed, then defined. Or, a function might be defined, then declared to +add an additional default argument. In all such cases, The needed or +keep_in_il flag would be set already on the entry, and therefore an +attempt to set it again would result in an immediate return, rather than a +sweep through the updated subtree. To avoid this problem, the subtrees of +these redeclarable entities are not swept ordinarily; the appropriate flag +is set on the entry itself, but its subtree is not visited. At the end of +the file scope, when no more redeclarations are possible, the global flag +end_of_file_scope_needed_flags_phase is set to TRUE, and that enables +the subtree walks. set_needed_flags_at_end_of_file_scope and +mark_to_keep_in_il, as they are doing the needed and keep_in_il +walks respectively, look for these delayed-subtree-processing entries, and +handle them by clearing the needed or keep_in_il flag and then +calling the subroutine to set them again, which this time will visit the +subtree. For the needed flag walk, remark_as_needed provides a +convenient way of doing this.

    +

    When ONE_INSTANTIATION_PER_OBJECT is TRUE, a more complicated set of +“needed” flags is maintained. In that mode, each instantiation is put out +as a separate object file. There is still only one IL tree, but it is +marked so that a back end can sweep through it several times and put out a +different “slice” each time, each slice containing one instantiated entity +(function, variable, or static data member) plus exactly the set of other +entities needed by that entity. This is done via a set of per-instantiation +“needed” flags, represented as a bit vector implemented as a linked list of +entries of type a_per_instantiation_needed_flags_entry attached to the +per_instantiation_needed_flags field of the source correspondence. Each +slice is assigned one bit in that bit vector, and if the bit is 1 the +associated entity is needed in the slice.

    +

    The per-instantiation “needed” flags are tested and set by the macros +needed_flag_is_set and set_needed_flag. The global variable +needed_flag_bit_number indicates the bit number to be tested or set. +If it is zero, the needed flag is tested or set instead of the bit +vector.

    +

    Each instantiation is actually assigned two bits in the bit vector, the +second one used for the per-instantiation versions of the class and +function definition_needed flags. These are tested and set by +class_definition_needed_flag_is_set, +set_class_definition_needed_flag, +routine_definition_needed_flag_is_set, and +set_routine_definition_needed_flag. As with the needed-flag macros, +these macros depend on the value of needed_flag_bit_number and use the +definition_needed flags if that variable is zero.

    +

    The bit number assigned to a given instantiation entity is recorded in the +instantiation_needed_bit_number field in the variable or routine. When +mark_as_needed is called for the entity, after the standard “needed” +flag processing has been done, another sweep is done to set the proper bit +in the per-instantiation “needed” flag bit vectors of all entities +referenced from the instantiation. The class and function per-instantiation +definition-needed bits are also set in this sweep.

    +

    All externally-defined entities that are not instantiations are assigned to +the slice numbered 1 (though their instantiation_needed_bit_number +fields are left as zero), and a similar sweep is done for them. By the end +of the compilation, therefore, every externally-defined entity has been +assigned to a slice, and the per-instantiation bits show what must be +included in each slice. The “1” slice includes everything that isn’t in an +instantiation slice.

    +

    Some entities are present in multiple slices. Constants, types, and class +definitions appear in each slice as needed. Inline functions are also +present in a slice if they are referenced in that slice. In general, +however, functions and variables can only appear in one slice, or more +precisely, their definitions can only appear in one slice. If other slices +reference them, they appear only as declarations in those slices. This +causes a problem for static functions and variables, which by definition +cannot be referenced from other object files. This is handled by making +those entities external with generated names. The sweeping routines will +set the static_used_by_instantiation flag in static entities that are +used by an instantiation, and IL lowering will turn such routines and +variables into external entities.

    +

    The simple needed and definition_needed flags end up being in +effect the unions of the corresponding per-instantiation sets. That is, if +any per-instantiation “needed” flag is set on an entity, then the +needed flag will be set, and likewise for the definition-needed +flags. Therefore, when the normal processing to remove unneeded entities is +done, it will remove only entities that are unneeded in all slices.

    +
    +
    +

    18.11. Intermediate Language Display#

    +

    il_display.c contains routines to display the IL in human-readable +form. il_display.h contains the associated declarations. The code is +currently set up to be compiled as a standalone utility program: It reads +the IL from a file (by calling the IL read routines), then traverses the +in-memory form using the IL walk routines, producing output on +stdout. il_display could be set up as a subroutine to be called +from within the front end.

    +

    The processing is very simple: Using the IL walk routines, it walks the +file scope and displays it, then walks each routine scope and displays +that. The IL walk routines are told to call disp_entry for each +non-string entry, and to call nothing for string entries (string entries +are displayed when pointers pointing to them are displayed). Most of the +display routines are very straightforward. When pointers are displayed, an +attempt is made to show what is pointed to. That is, if the entity pointed +to is named, or if it is a string, a constant, or a type, a brief summary +of the entity is given so one does not have to look at, say, a type entry +to find out that it is the entry for int.

    +

    If there are errors in the IL, they are highlighted (e.g., +“BAD-TYPE-SPECIFIER-KIND”) and the display continues as well as it +can. An internal error is not generated.

    +

    Obviously, the code in il_display.c must be kept up-to-date whenever +the IL definition in il_def.h is changed.

    +
    +
    +

    18.12. Writing the Intermediate Language to a File#

    +

    il_write.c contains routines that write the intermediate language to a +file, and il_write.h contains associated declarations.

    +

    IL writing takes the in-memory IL and writes it to a file for later +reading.

    +

    start_il_file is called to open the IL file, and finish_il_file to +close it. Alternatively, cancel_il_file can be called to delete the IL +file and suppress further IL file generation if an error is detected during +the compilation.

    +

    write_memory_region is called to write out each memory region, i.e., +the file-scope memory region or a memory region for a function. It writes +the memory region at the end of the intermediate language file.

    +

    There are two IL file formats. The switch ALTERNATE_IL_FILE_FORMAT in +host_envir.h indicates which is to be used. The file header is the same +in both formats:

    +
      +
    • +
      A special string identifying the file as an IL file, and including the +version number of the IL (see il_file.h).
      +
      +
    • +
    • +
      The number of memory regions.
      +
      +
    • +
    • +
      The number of function definitions.
      +
      +
    • +
    • +
      The file position of the file index (at the end of the file).
      +
      +
    • +
    • +
      The file position of the file-scope memory region.
      +
      +
    • +
    • +
      The il_header struct, which is the root of the IL tree.
      +
      +
    • +
    • +
      The array of orphan-list pointers.
      +
      +
    • +
    +

    In terms of processing, the space for the header information is reserved at +start_il_file time, but the full information is not known until all +regions have been written. At finish_il_file time, the file pointer is +repositioned and the final information is overwritten on the reserved +space.

    +

    The file index is also the same in both formats: It is an array of file +positions, such that file-index[i] gives the file position of the start of +the information for memory region i. The index is the last thing written in +the file. No entry 0 is written; the first entry is entry 1 (i.e., for the +file scope), which is at the position indicated by the file index position +in the header. The other entries follow. There are as many entries as the +“number of memory regions” given in the header.

    +

    Between the header and the file index is a sequence of one or more memory +regions. Since the file-scope region is not complete until the end of the +compilation, the file contains all the function regions first, in order of +definition, and then the file-scope region at the end.

    +

    In both formats, the information for a memory region begins with the memory +region number, and the overall sequence of regions is followed by a zero +which serves as an end marker if the regions are read sequentially.

    +

    Beyond that, the information for a memory region is quite different in the +two file formats.

    +

    The default file format involves writing out the memory blocks for each +region exactly as they appear in memory – i.e., large blocks, in memory image +form. On the reading side, these blocks are read back in, and since they +are probably not read in at the same address they had when written out, the +IL tree is walked to find and remap all the pointers. A tree walk is also +required on the writing side, at least for function scope memory regions, +to get the data structure for orphaned entries built. The process is fairly +fast on both the writing side and the reading side; although the tree walk +takes time, at least the I/O for reading the blocks can be done +efficiently, in large blocks.

    +

    The information for a region in the default format is as follows:

    +
      +
    • +
      The memory region number.
      +
      +
    • +
    • +
      The original memory address for the first block header.
      +
      +
    • +
    • +
      The original memory address for the primary scope entry for the region.
      +
      +
    • +
    • +
      The total size in bytes of the information following (i.e., the total +size of all blocks and their associated headers).
      +
      +
    • +
    • +
      For each memory block, the block header and block data. The header +contains pointers that point to the next block and to the data (all as +original memory addresses).
      +
      +
    • +
    +

    In the alternate file format, each entry is assigned an entry number (which +is recorded in the prefix preceding the entry), all pointers are changed to +the corresponding entry numbers, and each entry is written individually to +the file, preceded by an indication of the entry kind and by the entry +number. On the reading side, the entries are read individually and the +pointers in them are changed to the proper new pointer values. This format +is less efficient than the default format, because the actual I/O is done +one entry at a time for both writing and reading (there is of course +buffering under this, but it is still less efficient to make thousands of +calls to fwrite and fread than to make dozens of calls). The +advantage of the alternate file format is that it allows resizing or other +alteration of the entries on the reading side. If one wants to add +back-end-specific information, for example, one can do so.

    +

    The information for a region in the alternate file format is as follows:

    +
      +
    • +
      The memory region number.
      +
      +
    • +
    • +
      An array giving, for all the IL entry kinds (see il_walk.h), the +number of entries of each kind in this memory region.
      +
      +
    • +
    • +
      A sequence of entries, giving for each entry the entry kind, the entry +number, the entry length (only for string entries), the orphan-list +pointer (only for non-string file-scope memory region entries), and the +entry itself. After the last entry, a zero entry kind marks the end of +the sequence.
      +
      +
    • +
    +

    Entry numbers are assigned from 1 for each kind of table; there can be, for +example, a type entry 27 and a constant entry 27. 0 is used to represent a +NULL pointer. The entry numbers in each function scope start again from 1, +but in addition they have the top bit on, i.e., they effectively start with +LONG_MAX+2. Thus there can be identical entry numbers in two function +scopes (and that is not a problem), but a file-scope entry number can +always be distinguished from a function-scope number.

    +

    For string entries, the “entry number” used is an offset into a conceptual +block formed by concatenating all the strings of that kind, including the +terminating null if any, and with space reserved between the strings for +the entry prefix and for any required alignment. The offsets start from 1 +to preserve 0 as a NULL pointer. In the array of entry counts, the values +for string entries indicate the total size of the conceptual block, in +bytes, rather than an entry count. Thus, if there were three strings “abc”, +“de”, and “fghi” in a region, the prefix takes 4 bytes, and the host +machine requires 4-byte alignment, the strings’ entry numbers would be 5, +13, and 21, respectively, and the entry in the count array would be 25.

    +
    +
    +

    18.13. Reading the Intermediate Language from a File#

    +

    il_read.c contains routines that read the intermediate language from a +file, and il_read.h contains associated declarations.

    +

    File reading takes the IL in file form and reads it in to re-create the +in-memory form.

    +

    The routine il_read reads the file header and the file index, then +calls read_memory_region to read the file-scope memory region. Other +(function-scope) regions must be read explicitly by calling +read_memory_region directly. This allows the back end to read each +function, process it, and then free its IL by calling +free_memory_region, to reduce overall memory requirements.

    +

    With the default file format, the information for each memory region is +read with one large read, and the pointers in the region are then remapped +to the proper values by calling walk_file_scope_il or +walk_routine_scope_il with a pointer remap function. If all the memory +blocks are read back in at their original addresses (an attempt is made to +do this), the IL walk is not needed.

    +

    With the alternate file format, the array of entry counts is read at the +beginning of processing the region. For each entry kind, an area is +allocated that is large enough to contain all the entries of that kind (its +size is the number of entries times the size of each entry). This area is +then considered an array of entries of that kind, and the entry number is +an index into the area. (For string entries, the “entry count” is the +actual total size, and the “entry number” is still an index – with the area +treated as an array of characters.) Each entry is then read, placed at the +right place in the allocated space, and its pointers changed from entry +numbers back to real pointers. Note that no overall tree walk is done, and +no special orphan processing is required: Since each entry is read +individually, one can do all the processing for each entry when it is read, +and be sure no entries were missed.

    +

    As each region is read, the associated entry of region_scope_entry in +il_header is set to point to the primary scope entry for the region.

    +
    +
    +

    18.14. Precompiled Headers#

    +

    The precompiled headers (“PCH”) facility is intended to speed up +compilations that include relatively stable header files. It does this by +writing a precompiled header file that is a snapshot of the front end’s +internal state at a point in the compilation process immediately following +the initial sequence of #includes. On a recompilation of that file +(or another that begins with the same sequence of #includes), the front +end checks to see if all the header files are unchanged since the +precompiled header file was generated, and if so reads in the precompiled +header file to re-establish the front end state as it would be after +reading and compiling the header files. Reading in the PCH file takes less +time than compiling the header files from source, so there is a net savings +in compilation time.

    +

    Since the point of this feature is saving time, it is important that the +process of writing and reading the PCH files be as fast as possible. One +would like to see savings of 80% or the like (comparing the time to restore +a PCH file to the time to compile the original source code); an improvement +of only 30% or so would barely be worth the extra complexity. In addition, +one should not have to pay a large price to write out the precompiled +header file; it’s okay to slow compilations a little to get the benefits of +precompiled headers on later compilations, but if it takes too long to +write the file, the net gain is marginal or negative.

    +

    These speed issues suggest some basic design decisions:

    +
      +
    • +
      The information written to the precompiled header file must not require +a tree walk, because visiting every entry takes a lot of time. (It also +requires code or data structures that describe how to do the tree walk, +which exist for IL entries but not for the front-end-only data +structures.) Therefore, the information must be written out and read +back in as large chunks (rather than one entry at a time), and it must +not be necessary to remap all pointers in the information to new values +(i.e., it must be possible to bring the information back in at the same +address). These requirements also make it possible to exploit memory +mapping on systems that support it.
      +
      +
    • +
    • +
      Precompiled header files should contain snapshots of compilation +states, and not information about individual header files. While it’s +tempting to imagine writing precompiled header files for individual +header files, the work required in carving out the right information +and the description of dependencies so that the information can be +written to a file, and the work to bring it back in and merge it with +the front end state, will make substantial time savings unlikely.
      +
      +
    • +
    +

    An unfortunate consequence of this latter design decision is that users are +probably forced to change their source code to get any meaningful benefit +from the PCH facility. In average source code, the order of inclusion of +header files is essentially random. The net effect of the various orders of +inclusion is often the same, because of the way header files tend to be +written, but it is difficult to deduce that fact, and time-consuming. So we +have a dilemma: If we strive for maximum save/restore speed, we will find +few “natural” common sequences, and therefore generate many PCH files for +little benefit. On the other hand, if we try for maximum ability to reuse +precompiled headers from unaltered source files, we lose something +significant on save/restore speed.

    +

    We’ve chosen to go in the direction of maximum save/restore speed. We +believe that users are willing to make small changes in their source code +to get large reductions in compilation time, and that given a choice +between

    +
      +
    1. +
      You don’t have to change your source, and precompiled headers will +give you a 15% savings, or
      +
      +
    2. +
    3. +
      You may have to reorder your initial #includes or add the +equivalent of
      +
      +
      +

      #include <everything.h>

      +
      +
      +
      to the beginning of your source files, and precompiled headers will +give you a 50% savings,
      +
      +
    4. +
    +

    users will choose option 2. This, of course, is a matter of opinion, and +the percentages are fictitious. But for better or worse, this is what we +decided.

    +

    Because PCH processing is not likely to be helpful on arbitrary files, it +is disabled by default.

    +

    The code for precompiled header processing is mostly in pch.c, with +associated declarations in pch.h.

    +
    +

    18.14.1. Prefix and Header Stop Point#

    +

    The initial sequence of the source code of the primary source file that is +subject to the PCH optimization is referred to as the prefix. It consists +of the preprocessing directives preceding the header stop point. The header +stop point is determined as follows:

    +
      +
    • +
      Start at the first token of the primary source file that is not part of +a preprocessing directive (or the end of the file if there is no such +token).
      +
      +
    • +
    • +
      If there is a #pragma hdrstop preceding that token, back up to the +pragma position.
      +
      +
    • +
    • +
      If the position determined by the first two steps is inside a +preprocessing directive like an #if, back up to (just after) the +previous top-level preprocessing directive.
      +
      +
    • +
    +

    For example:

    +
    /* Comments. */
    +#define flag 1
    +#if flag
    +#include "abc.h"
    +#else
    +#include "def.h"
    +#endif
    +#include <stdio.h>
    +/* header-stop point. */
    +int i = 1;
    +#include "abc.h"
    +/* header-stop point. */
    +#if xyz
    +#include "def.h"
    +#pragma hdrstop
    +#endif
    +
    +
    +

    Note that, while determining the prefix, #ifs and the like are not +evaluated, so code that will be skipped in the actual compilation can +nevertheless serve as a header stop point. This is particularly important +with #pragma hdrstop.

    +

    At the beginning of compilation, if precompiled headers are enabled, the +prefix for the primary source file is accumulated. This is done by opening +the primary source file, reading the beginning of it in a special mode +while building an in-memory representation of the preprocessing directives +read, and closing the source file. This is a separate process from the +normal compilation of the file, and is a necessary first step whether the +front end ends up using an existing PCH file or creating a new one. See +build_prefix_information.

    +

    The prefix scan is done by setting building_pch_prefix and calling +get_token once. That causes the scanning of all of the preprocessing +directives preceding the first “real” token of the primary source file. The +preprocessing directives are not evaluated in the usual way; they are just +placed on the prefix event list. (In particular, #include directives +are just accumulated like the others; the included files are not read.) +Each such event contains an enumeration code for the preprocessing +directive and a null-terminated string giving the text of the directive +following the directive keyword.

    +

    After the initial prefix list is built up, the list is trimmed down by +discarding anything after a #pragma hdrstop and then, if the end is +inside an #if or the like, discarding preprocessing directives back to +the last top-level directive.

    +

    If the primary source for the compilation is coming from stdin instead +of a file, the prefix construction cannot be done (and therefore PCH files +cannot be created or used).

    +

    A list of the command-line options for the current compilation is also +built. It is also a linked list, and each entry on the list indicates one +command-line option. Options that have no effect on the state preserved by +PCH processing are not put on the list, but the rest (most of them) +are. The option code is represented by an enumeration, so the difference +between the single-letter form of the option and the keyword form is +erased, but in all other respects the list built up will have to match the +corresponding list for a PCH file exactly – same options, same order.

    +
    +
    +

    18.14.2. Using a PCH file#

    +

    Once the prefix has been created, the front end will look to see if any of +the existing PCH files can be used to avoid some part of the compilation +for the current file. A host-dependent routine is used to fetch the names +of all PCH files in the appropriate directory (the directory can be +specified via the --pch_dir command-line option). Each file is checked +to make sure it is a regular file (not, say, a directory), that it has the +right header string identifying it as a PCH file, that the compiler version +number and generation date/time are the same, and that the flag indicating +that the file is completely written has been set. If any of those checks +fails, the file is closed and not considered further; in effect, it’s +considered not to be a PCH file.

    +

    The next round of checks seeks to determine whether the PCH file is +applicable to the current compilation. The front end checks that the +current directory and the one recorded in the PCH file are the same; that +the command-line event lists are the same; and that the preprocessing +directive event lists are the same (or the current file’s prefix list is +longer than the prefix list in the PCH file). If those are okay, the front +end checks that the header files included in the PCH file have not changed +since the PCH file was built (this is done by checking the timestamps of +the files against the timestamps recorded in the PCH file). If the +timestamps indicate that the PCH file is out of date, it is deleted.

    +

    A PCH file that makes it this far can be used, but it might not be the best +choice: There might be another PCH file that also matches but includes more +of the prefix preprocessing directives. Therefore, if the match is not +perfect, other PCH files are considered and the best-matching PCH file is +chosen. Each PCH file is closed after it is considered and must be reopened +later if selected as the best file.

    +

    If the user has used the --use_pch command-line option, the indicated +PCH file is chosen directly. No other PCH files are considered, and the +applicability test is not done (at this point; see below).

    +

    Once the best-matching PCH file is selected for a file called (say) +x.C, if the PCH file selected is not x.pch, and there exists an +x.pch, x.pch is deleted. This is a simple way of getting rid of PCH +files that are no longer needed.

    +

    Once a PCH file is selected, the front end state is restored from the +file. The PCH file is opened again and the prefix check is done again to +make sure the file has not changed since the first check. For a PCH file +specified via a --use_pch command-line option, this is the only +applicability test done (and if the file fails, a warning is issued and the +compilation continues without using the PCH file); for other cases, this is +a repetition of the applicability test already done. Next, the global +variables registered via register_pch_saved_variables are read and +restored. Finally, the contents of the various memory regions (IL and front +end) are restored. These are restored at the original addresses, so it is +not necessary to walk through the restored data to adjust pointers. (See +the section on memory management issues below for more information on this +aspect.)

    +

    The restoration process occurs after most initialization of the front end, +so some variables are initialized then overwritten by the restoration from +the PCH file.

    +

    Once the front end state has been restored from the PCH file, the lexical +routines are reset and the primary source file is opened again. The prefix +is skipped by doing a get_token in a special lexical mode. This is very +similar to the scan done to accumulate the prefix, in that initial +preprocessing directives are passed over uninterpreted. However, once the +preprocessing directive that marks the end of the matched part of the +prefix is processed, normal processing of preprocessing directives is +re-enabled. Shortly thereafter, the initial get_token finishes, and +normal compilation continues from that point (we know we are between +top-level declarations, so we can continue simply by entering the main +compilation-unit loop).

    +

    The PCH restoration process restores the front end state after compilation +of the precompiled headers, but it doesn’t duplicate the output that would +have been done on auxiliary files during the skipped part of the +compilation. Diagnostics that would have been written, and output lines on +the raw listing and cross-reference output files that would have been +generated, are not put out when a PCH file is used. If the front end is +configured to use an IL file, that file also is not generated as this +point. However, the IL file does get generated by a catch-up process done +after the point where a PCH file is generated or a decision is made not to +generate one; see below.

    +

    Because the source sequence numbers of the original compilation may not +exactly match the sequence numbers in the current compilation (e.g., +because of whitespace differences), the source file mapping information in +the IL in the PCH file is restored as, in effect, the first include file on +the list under the primary source file of the current compilation.

    +
    +
    +

    18.14.3. Creating a PCH File#

    +

    After the front end has read in a PCH file or chosen not to use one, the +“normal” compilation process begins. When the compilation reaches the +header stop point, we have the option of creating a PCH file that +encapsulates the front end’s state at that point for later restoration.

    +

    Note that it is possible to both use and create a PCH file in the same +compilation, because the best-matching PCH file might contain only the head +of the full prefix. In that case, the internal state is restored from the +PCH file, then the rest of the prefix is compiled in the normal way, and at +the header stop point the compiled form of the full prefix is saved to a +new PCH file.

    +

    The position of the header stop point was determined by the prefix scan at +the very beginning of the compilation. Its position is defined in terms of +a preprocessing directive, more specifically as the end of the processing +for that directive. Compilation starts up or continues in a mostly normal +way, with the header stop position set as a sort of breakpoint. When the +end of the indicated preprocessing directive is reached, the front end will +check to see whether a PCH file can be generated.

    +

    On the way to the header stop point, some things may happen to preclude +generation of a PCH file:

    +
      +
    • +
      A reference to one of the macros __DATE__ or __TIME__. Since +these would change from compilation to compilation, there is no point +to saving the state of a compilation that uses them.
      +
      +
    • +
    • +
      A #pragma no_pch. This is an explicit request not to generate a PCH +file.
      +
      +
    • +
    • +
      A #line directive. (Such directives could probably be allowed but +are not accommodated at present.)
      +
      +
    • +
    +

    When the header stop point is reached, generate_precompiled_header is +called. It starts by making several checks that the current position is +acceptable:

    +
      +
    • +
      The current position is not inside a declaration, i.e., it is between +two file-scope declarations, or before the first such declaration, or +after the last. next_token_is_top_level_decl_start, maintained by +the declaration-scanning routines, gives this information.
      +
      +
    • +
    • +
      The preprocessing #if stack is empty, i.e., the current position is +not inside a conditionally-compiled section.
      +
      +
    • +
    • +
      There have been no errors.
      +
      +
    • +
    • +
      The global variable cannot_create_pch_file is not set. It is set +for things that preclude generation of a PCH file (e.g., referencing +__DATE__).
      +
      +
    • +
    +

    If the current position is acceptable, a precompiled header file can be +written, and the front end will write out a file xxx.pch, where “xxx” +is the base file name of the file being compiled. The user can specify a +different file name via the --create_pch command-line option. If a file +with the chosen name already exists, it is deleted. Precompiled header +files are written in the current directory by default, but another +directory can be specified via the --pch_dir command-line option.

    +

    The following information is written to the PCH file, in the order given:

    +
      +
    • +
      An string that identifies the file as a PCH file, and gives the front +end version number and generation date/time.
      +
      +
    • +
    • +
      The current directory name (this may affect the include file search +order, etc.).
      +
      +
    • +
    • +
      The list of command-line events, i.e., all the command-line options +that could have an effect on PCH files.
      +
      +
    • +
    • +
      The list of preprocessing directive events, i.e., the sequence of +preprocessing directives whose compiled form is encapsulated in the PCH +file.
      +
      +
    • +
    • +
      Timestamps for all the header files referenced by the compilation (this +includes all files, not just those included directly from the primary +source file).
      +
      +
    • +
    • +
      The values of all front end variables registered with +register_pch_saved_variables.
      +
      +
    • +
    • +
      The contents of all memory regions, i.e., the front end memory region +and all IL memory regions.
      +
      +
    • +
    • +
      Once the rest of the information has been written, the front end goes +back to the header and writes a flag indicating that the PCH file is +complete. This flag prevents other compilations from using a PCH file +that is not yet completely written.
      +
      +
    • +
    +

    After writing out the PCH file, the front end continues with +compilation. Because the header-stop point has been passed, no further +precompiled-header checking or processing is done in the rest of the +compilation.

    +

    If an IL file is being generated, function scope memory regions that are +completed before the header stop point are held in memory and neither +written to the IL file nor freed. Once the header stop point has been +reached, and a PCH file has been written or a decision made not to write +one, those memory regions are written to the IL file and freed.

    +
    +
    +

    18.14.4. Memory Management Issues#

    +

    As was mentioned earlier, one of the prerequisites for fast PCH processing +is the ability to bring memory regions back into memory at the same +addresses they had when written out. Clearly, that requires that (a) +nothing else happens to have been allocated at the desired addresses, and +(b) there is some way to request allocation or assignment of those +addresses so that no later allocation uses them.

    +

    The front end provides two schemes that accomplish this goal. The first and +better scheme requires memory mapping support from the underlying operating +system (UNIX and Windows NT versions are provided). A fixed set of +addresses is chosen for all memory regions (the exact addresses are either +left to the discretion of the operating system or chosen in the +configuration of the front end; see +USE_FIXED_ADDRESS_FOR_MMAP). Initially, these memory addresses are +mapped onto a temporary file. When a PCH file is created, the memory is +written to the PCH file (using normal file I/O). On restoration of a PCH +file, the default mapping to the temporary file is released, and the +reserved memory addresses are mapped onto the PCH file being restored. This +brings the saved information into the front end’s address space without any +immediate I/O. (In the actual implementation, the memory addresses are +tentatively mapped once to verify that the mapping can be done, and then, +once it is known that all the mappings will be successful, they are done +again with the official mappings.) All dynamically allocated memory that is +not part of a memory region is just allocated in the normal way through +malloc, since it need not be at any particular addresses. This means, +in effect, that there are two completely separate pools of memory – memory +region allocations are done at the fixed mappable addresses, and everything +else is done more casually in the traditional way.

    +

    The other implementation does not require memory mapping, but it is +slightly less friendly to users. Very early in the execution of the front +end a large amount of memory is preallocated in large blocks and saved off +to the side for use exclusively for memory regions. This is done early so +that the allocated addresses are reproducible (i.e., one can get the same +addresses on all compilations). If the allocations were done later, their +addresses would be affected by minor variations in the amount of memory +used during the command-line processing, and perhaps by memory allocated by +runtime routines of the host C compiler (e.g., printf formatting). As +the compilation proceeds, requests for memory for memory region blocks are +satisfied by taking blocks from this preallocated list. All other +allocations (for things not in memory regions) are done directly through +malloc. When a PCH file is created, the memory addresses of blocks are +written to the PCH file along with the block contents. Also written is an +array of the preallocated memory block addresses used, serving as a sort of +allocation history (this array is written to the file also in the +memory-mapped mode). Once the header stop point is passed, and either a PCH +file was written or a decision was made not to write one, the remaining +preallocated memory is freed, and subsequent allocation for all purposes is +done directly through malloc.

    +

    If the preallocated space is too small to hold the memory regions created +up to the header stop point, the precompiled header cannot be created +(since the remaining required space cannot be allocated at predictable +addresses). A warning is issued, telling the programmer that the +--pch_mem option can be used (on a subsequent invocation of the front +end) to request a larger preallocation to avoid the problem. The +compilation continues normally – the PCH file cannot be created, but the +compilation can be completed regardless.

    +

    Since the preallocated blocks have a fixed (though large) size, any +requirement to allocate a single entity larger than that fixed size cannot +be satisfied from the preallocated pool, and therefore precludes generation +of a PCH file. This could happen, for example, if a user program contains a +single literal string containing 200,000 characters. Again, the compilation +continues without difficulty, but a warning is issued that a PCH file could +not be generated.

    +

    When a PCH file is read back in the non-memory-mapped mode, the allocation +history information history is read in from the PCH file and used to check that +the preallocated blocks are indeed at the same addresses (on some systems, in +spite of the care taken to allocate the blocks early, the addresses still +change; for example, under MS-DOS, the addresses can be affected by placing a +new TSR program in memory). If the addresses are not right, it is still +possible to give up on using the PCH file and continue with normal compilation. +If the history information matches, the memory regions are read in: The address +for each block is read from the file, the preallocated block at the right +address is assigned, and the memory region contents are read from the PCH file +into the proper addresses.

    +

    It should be noted that if a given environment provides a (nonstandard) way +of allocating memory from a pool distinct from the normal malloc +allocation pool, the non-memory-mapped approach can be made to work without +preallocation and without the --pch_mem command-line option.

    +

    When multiple source files are specified in one invocation of the front +end, the preallocation scheme breaks down: The first file can be processed +okay, but on subsequent files the preallocated memory has been used and +reclaimed and is no longer in quite the right predictable state. This can +probably be solved in some way, but the current implementation takes the +easy way out and disallows PCH file use on compilations where more than one +source file is specified on the command line.

    +
    +
    +
    +

    18.15. Predefined Macro Definition File#

    +

    Macros may be predefined either by explicit calls of +enter_predef_macro, and/or through use of a predefined macro definition +file. Whether or not the front end reads a predefined macro definition file +is controlled by the DEFAULT_USE_PREDEFINED_MACRO_FILE macro. The file +EDG_BASE/EDG_AUXILIARY_INFO_DIR_NAME/PREDEFINED_MACRO_FILE_NAME is read +to provide the macro definitions. The EDG_BASE directory can be +specified by an environment variable (EDG_BASE), build-time macro +(DEFAULT_EDG_BASE), or command-line option +(--edg_base_dir). EDG_AUXILIARY_INFO_DIR_NAME and +PREDEFINED_MACRO_FILE_NAME are configuration macros with default values +of “lib” and “predefined_macros.txt”. If +EDG_AUXILIARY_INFO_DIR_NAME is null, the EDG_BASE directory is used +directly. The format of the entries in the file is:

    +
    mode,!mode,mode   cannot_redefine   macro_name   macro_value
    +
    +
    +
      +
    • +
      mode is a label from the predefined macro modes table. The macro is +defined if the mode is set, or if the mode is not set when !mode is +used. The macro is defined if any of the mode tests is TRUE. The set of +mode values is specified in host_envir.h.
      +
      +
    • +
    • +
      cannot_redefine indicates whether the predefined macro may later be +redefined. The value must be “yes” or “no”.
      +
      +
    • +
    • +
      macro_name is the name of the macro to be defined.
      +
      +
    • +
    • +
      macro_value is the value to which the macro should be defined. All +of the characters until the end of the line are used as the macro +value.
      +
      +
    • +
    +

    For example:

    +
    gcc no  __HAVE_BUILTIN_SETJMP__ 1
    +gpp no  __CHAR_BIT__ 8
    +gnu no  __GNUC_PATCHLEVEL__ 0
    +gnu no  __WINT_TYPE__ unsigned int
    +gnu,microsoft __IS_GNU_OR_MICROSOFT_MODE 1
    +
    +
    +

    A script (make_predefined_macro_file) is provided that automatically +generates the predefined_macros.txt file for a given version of gcc/g++ +or clang. It does this by invoking gcc and g++ or clang and capturing the +predefined macro information.

    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/build/index.html b/dev/doc/build/index.html new file mode 100644 index 0000000..56fdfae --- /dev/null +++ b/dev/doc/build/index.html @@ -0,0 +1,1501 @@ + + + + + 1. Configuring and Building the C++ Front End - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    1. Configuring and Building the C++ Front End#

    +

    This chapter is an introduction to configuring and building the front end and +the various tools that come with it. Bringing up the front end on a new +platform typically can be done in a few hours, and if the platform is close +enough to a system for which sample configurations are available (e.g., Linux, +Windows, etc.) that initial process can be reduced to a matter of minutes.

    +

    The front end can be configured for a variety of uses. For example, it could +be part of a compiler with a custom code generator, or a compiler with a +portable C-generating back end (the latter is provided). Alternatively, it +could be part of a source analysis tool (without a code generator) or of a +source transformation/translation tool (using the supplied C/C++-generating +back end). Some of the tools supplied with the front end will not be needed +for some of these applications. For example, a source analysis tool is +unlikely to need the supplied prelinker tool to perform automatic +instantiations. The details of the build process are therefore likely going to +depend on the application. However, the overall structure of the source code +is simple enough that customizing the build process should be straightforward.

    +

    The source code implementing the front end and associated tools is written in +C++11 (i.e., ISO/IEC 14882:2011) and can be compiled using relatively current +C++ compilers. The front end has been compiled with g++ 4.8.1, clang 3.3, and +Microsoft Visual Studio 2015 (build 19.00.24215.1). The front end does not +explicitly throw or catch exceptions and does not use C++ features that would +requite runtime type information (RTTI), so those features can be disabled when +compiling the front end (for compilers that support that). (The sample +run-time support library is written in C++ and (if needed) is normally compiled +using the front end itself. When building on Microsoft Windows, a component is +also available to read metadata in C++/CLI mode: This is written in C++ for the +Microsoft C++ compiler.)

    +
    +

    1.1. Directories and Files in a Release#

    +

    After unpacking a release, its top-level directory should contain the following +directories and files:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    Makefile
    +
    +
    +
    In a Unix-like environment (including Windows-hosted environments like +Cygwin or MinGW), the make utility can be used to build the front +end and its supporting tools and components. This top-level +Makefile runs the make tool in the various subdirectories as +needed. It is geared primarily toward building a compiler using the +C-generating back end along with the sample run-time support library. +A make process using this top-level Makefile may therefore +terminate with errors for other situations; in that case, the +Makefiles in the appropriate subdirectories (especially +misc/ and src/) are still likely to be useful.
    +
    +
    +
    src/
    +
    +
    +
    The directory containing the source files of the C++ front end and +its optional components (such as the C- and C++-generating back +ends). In addition to source code, the src/ directory also +holds the Changes file, which describes the various changes +made to the front end in the current and previous releases. Note +that most of the source files have the .c suffix that would +normally indicate a C source file. Starting with the 6.0 release, +these files contain C++ source code and must be compiled using a +C++ compiler (with the C++14 dialect). The original filenames +have been maintained to make patching files easier. If desired, +symbolic links can be added to accommodate build environments as +necessary.
    +
    +
    +
    bin/
    +
    +
    +
    Initially, this directory contains a script eccp that can be used +to run the front end much like typical C++ compilers in Unix-like +environments (such as CC and g++). See +“The eccp script” for details. Once the front end is built (in +the src/ directory), it can be moved here for invocation by +eccp (this is done automatically if the top-level Makefile is +used).
    +
    +
    +
    sample_edg_eccp_config/
    +
    +
    +
    The eccp script can be configured in various ways. This directory +contains sample configuration files for some popular Unix-like +operating systems (Linux, MacOS X, and Solaris). It also includes a +script make_g++_incl_paths (to be run from the lib/ directory) +to establish the location of g++‘s header files (in cases where +eccp should rely on a native g++ installation for system and +standard header files).
    +
    +
    +
    include/
    +
    +
    +
    This directory contains prototype implementations for a few standard +C++ header files that are closely tied to the compiler’s internals. +(For example, the contents of the <typeinfo> header must match the +compiler’s understanding of the std::type_info type.)
    +
    +
    +
    lib_src/
    +
    +
    +
    This directory contains C++ source code implementing a minimal C++ +run-time support library (in support of C++ features like exception +handling, the dynamic_cast operator, and operator new). The +library also includes support for certain extensions to the C89 +language (like operations on complex floating-point types and support +for variable-length arrays). All of this code is primarily meant for +demonstration purposes, and is probably not suitable for end-user +products: It is very portable, but not very efficient. It is usually +not needed for non-compiler applications such as source analysis or +source-to-source translation. This directory also contains a +Changes file describing the history of the run-time support +library.
    +
    +
    +
    lib/
    +
    +
    +
    Initially, this directory only contains a file +predefined_macros.txt. This file is read by the front end to +predefine certain macros. It is typically used to define macros +that are defined by compilers being emulated (see +make_predef_macro_table and make_win_predef_macro_table.c +for utilities that automatically generate a set of predefined +macros for GNU and clang and Microsoft compilers, respectively). +Once the run-time support library is built (in the lib_src/ +directory), it can be moved here so the eccp script can find +it (this is done automatically if the top-level Makefile is +used). Note that this directory is only used when an unnamed +“legacy” target configuration is specified – see lib_target/ below for cases where a named target configuration +is used.
    +
    +
    +
    lib_target/
    +
    +
    +
    Target-specific version of the lib/ directory described above +used when the “--target target” command-line option is +specified. This directory can have the same +predefined_macros.txt and libC.a files as lib/, or can +be different as required by the specific target. If a +target-specific version of libC.a is required, it must be +built manually (see lib_src/Makefile).
    +
    +
    +
    misc/
    +
    +

    This directory contains sources for four utility programs (and a +Makefile to build them) to build and configure the front end:

    +
      +
    • make_predef_macro_table: A script to generate a predefined +macros file (like lib/predefined_macros.txt) to match given +versions of gcc/g++ and clang.

    • +
    • make_win_predef_macro_table.c: A program to generate a +predefined macros file (like lib/predefined_macros.txt) to match +a given version of Microsoft Visual Studio. Note that this program +is not built by the Makefile (and must be built manually if +required).

    • +
    • mk_errinfo.c: A program to translate the files describing the +diagnostics emitted by the front end to plain C++ code.

    • +
    • dettarg.c: A utility to determine basic configuration settings for +a target platform (e.g., the size and alignment of various integer +types). See “The dettarg Utility” below.

    • +
    +
    +
    util/
    +
    +

    This directory contains sources for three utility programs (and a +Makefile to build them) that can be used in conjunction with the +front end (e.g., by the eccp script):

    +
      +
    • edg_prelink.c: A program that implements automatic template +instantiation by re-running the front end to generate missing +instantiations.

    • +
    • edg_decode.c: A name demangler (which can, for example, be used on +the output of a linker to make that output more readable). It is +an interface for the actual demangling logic, which is contained +in decode.c to allow its use in other programs as well.

    • +
    • edg_munch.c: A utility that generates a C program that will call +all required start-up initialization routines. This is needed only +if your linker does not provide a way to invoke code automatically at +program start-up time.

    • +
    +
    +
    doc/
    +
    +
    +
    This directory contains a PDF version of this document (plm.pdf).
    +
    +
    +
    README
    +
    +
    +
    A plain text file summarizing some of the information in this chapter.
    +
    +
    +
    +
    +
    +

    1.2. Configuring the Front End#

    +

    A large number of behaviors of the front end can be configured by appropriately +defining various configuration macros. These macros can affect which +components of the front end are enabled, which dialects are supported, what +host and target platform characteristics are assumed, and so forth. See +lang_feat.h, host_envir.h, targ_def.h, and target.h below for information about where all the macros are +documented.

    +

    Beginning with version 4.10.1 of the front end, a facility to provide for +run-time selection of a target configuration (through the use of the +--target command-line option) is provided. To support this run-time +target-configuration feature, a number of the configuration macros have +been designated as “target-specific”. See +Target-Specific Configuration for more information.

    +
    +

    1.2.1. The defines.h File#

    +

    It is highly recommended that the front end be configured by defining the +appropriate macros in the src/defines.h file. Occasionally, it may be +expedient to set the macros directly through src/Makefile or a similar +build-system mechanism (e.g., to enable debugging facilities), but modifying +other front end sources to set the configuration macros is not a recommended +option.

    +

    Sample configuration files are provided in the src/ directory for Linux, +MacOS X, Solaris, and Windows (defines.h.linux, defines.h.macosx, +defines.h.solaris, and defines.h.win32, respectively). These are +recommended starting points when building the front end on these platforms: For +example, to build the front end on MacOS X, one can start by copying +src/defines.h.macosx to src/defines.h.

    +

    A partial configuration file src/defines.h.proto is also provided: It +contains the macros needed to enable the modern IA-64 ABI (also called the +Itanium ABI), but it must be complemented by additional target characteristics +(which can be obtained by running the dettarg utility described next).

    +
    +
    +

    1.2.2. The dettarg Utility#

    +

    File misc/dettarg.c is a simple C++ program that can be compiled, linked, +and run on a system for which the compiler is targeted to determine some basic +characteristics (like endianness, size and alignment of fundamental types, and +so forth) of that target platform. The output produced by dettarg is in a +form suitable for addition to the src/defines.h file.

    +
    +
    +

    1.2.3. lang_feat.h, host_envir.h, targ_def.h, and target.h#

    +

    A typical src/defines.h file will not explicitly set all the configuration +macros available in the front end. Instead, most macros are just left to their +default values. These defaults are specified in four header files. Perhaps +more importantly, these header files are also the place where all the +configuration macros are documented (in comments preceding the directives +determining the default values). The header files are as follows:

    +
    + + + + + + + + + + + + +
    +
    src/lang_feat.h
    +
    +
    +
    Configuration macros controlling language features. Some macros +control a single language feature detail, whereas others control whole +dialects.
    +
    +
    +
    src/host_envir.h
    +
    +
    +
    Configuration macros that determine characteristics of the host +platform (the platform on which the front end runs).
    +
    +
    +
    src/targ_def.h
    +
    src/target.h
    +
    +
    +
    Configuration macros describing characteristics of the target platform +(the platform for which code must be generated). Many of these macros +have names that begin with TARG_. Characteristics that are +entirely fixed at the time the front end is built are normally +documented in targ_def.h, whereas target.h describes target +characteristics that can be overridden for every invocation of the +front end.
    +
    +
    +
    +

    These descriptions are generally correct, but occasionally a configuration +macro may need to be placed in a header that doesn’t quite match that macro’s +function. For example, targ_def.h contains some macros that would more +naturally belong to lang_feat.h, but the default value of the macro depends +on a target platform characteristic.

    +

    Note that these files should not be modified to set configuration options. +Instead, the appropriate macros should be defined in src/defines.h or +perhaps in a Makefile or similar build system tool.

    +
    +
    +

    1.2.4. basics.h and Build Environment Configuration#

    +

    The front end is written in portable C++11 (except for one file in the +Microsoft dialect if the capability of reading Microsoft metadata for +C++/CLI is needed). The basics.h header adds abstractions to allow +most of the remainder of the front end source code to be written without +concern for variations in system headers. The build environment type can +often be determined by the preprocessor tests in basics.h, but when +that is not the case, one should define one of the following build +environment macros (on the command-line or in src/defines.h): +__ANSIC__ (for ANSI C; also used for Borland and Microsoft C under +MS-DOS and Windows), __SYSV__ (for System V), __BSD__ (for Berkeley +4.n), __VMS__ (for VAX/VMS C; this will cause __SYSV__ to be +defined, but the __VMS__ flag will control some minor variations from +System V).

    +

    Some ANSI library functions do not exist in all system libraries. This problem +is handled by remapping such function calls (via macros) to functions that do +exist. For example, traditional Berkeley UNIX does not have memcpy, but +does have bcopy; the front end source is written using calls to memcpy, +but when it is compiled with the __BSD__ flag set, a macro memcpy +transforms those calls into calls to bcopy. Another function of the build +environment macros is controlling inclusion of appropriate header files. Even +when identical functions exist on different host systems, they are sometimes +defined by different header files (e.g., Berkeley systems use <strings.h> +instead of the ANSI/System V <string.h>). basics.h includes the +appropriate definitions for the most common functions (standard I/O, string and +block operations, and character typing); any other required headers are +included only in those source files that need them, with appropriate +conditional compilation surrounding the #includes.

    +

    Very occasionally, the macro definitions in basics.h must be modified +directly (i.e., by editing basics.h). Specifically, when __ANSIC__ is +not set, some #defines in basics.h must establish values for about a +dozen of the most useful values (specifically, CHAR_BIT, CHAR_MIN, +CHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, +LONG_MIN, and ULONG_MAX). These should be set to proper values for the +host. sizeof_t should also be defined as the integral type to be used for +sizes of things. Usually this is the same as size_t, but it might be +different if size_t is too small (e.g., 16 bits). These values cannot be +set in defines.h or on the compilation command line.

    +

    Finally, basics.h also determines the default values of some macros that +control the presence of code aiding in the development of the front end (e.g., +DEBUG for debugging aids and CHECKING for internal consistency checks).

    +

    The front end requires a minimal C++ standard library. Prior to release 6.0, +the front end was written in C and used various host C standard library +functions (e.g., for file I/O). When switching to C++, it was decided not to +use the additional portions of the C++ standard library that became available +(e.g., std::string) as this would add a burden to our customers and would +require testing against many versions of the C++ standard library. Instead, a +small subset of library-like utility functions was developed for the front end +(in util.h). As a result, the portion of a C++ standard library that the +front end requires is about the same as that provided by a C standard library.

    +
    +
    +

    1.2.5. Commonly-used Configuration Macros#

    +

    The following subsections describe a selection of macros that commonly appear +in src/defines.h. This list is not meant to be exhaustive. Many (but not +all) configuration macros are used to initialize global variables with a +similar name, and it is the value of the variable that controls a particular +behavior. For example, GCC_IS_GENERATED_CODE_TARGET (described below) +initializes the global variable gcc_is_generated_code_target. This allows +particular behaviors to be controlled at run time (via the command line or via +custom code additions).

    +

    Note that none of the configuration macros described below are +“target-specific” (so, for example, there can’t be one target configuration +where DO_IL_LOWERING is TRUE and another where it is FALSE).

    +
    +

    1.2.5.1. Optional Components#

    +
    + + + + + + + + + + + + + + + + + + +
    +
    BACK_END_SHOULD_BE_CALLED
    +
    +
    +
    TRUE if a back end should be called (the call is to a function +back_end).
    +
    +
    +
    DO_IL_LOWERING
    +
    +
    +
    TRUE if IL lowering (rewriting C++-specific constructs in the +intermediate language in C form) should be done.
    +
    +
    +
    BACK_END_IS_C_GEN_BE
    +
    +
    +
    TRUE if the C-generating back end should be used. If FALSE, some +other back end must be supplied or BACK_END_SHOULD_BE_CALLED must +be FALSE. The C-generating back end takes the lowered IL for a +translation unit and generates a C source file suitable for +compilation to binary code by a native C compiler.
    +
    +
    +
    BACK_END_IS_CP_GEN_BE
    +
    +
    +
    TRUE if the C++/C-generating back end should be used. If FALSE, some +other back end must be supplied or BACK_END_SHOULD_BE_CALLED must +be FALSE. The C++/C-generating back end is intended for +source-to-source transformation applications. It takes the unlowered +IL for a translation unit and generates a source file that is similar +to the original C or C++ input.
    +
    +
    +
    MINIMAL_INLINING
    +
    +
    +
    TRUE if minimal inlining of function calls should be done during IL +lowering. This option is intended mostly for use with the +C-generating back end, and is limited to inlining calls to very simple +functions that are defined inline in the source.
    +
    +
    +
    +
    +
    +

    1.2.5.2. Support for Source Language Dialects#

    +
    + + + + + + + + + + + + + + + +
    +
    GNU_EXTENSIONS_ALLOWED
    +
    DEFAULT_GNU_COMPATIBILITY
    +

    +
    +
    +
    Control whether compatibility with GNU’s gcc and g++ compilers +should be enabled, either by default or only when the --gcc or +--g++ command-line options are specified.
    +
    +
    +
    MICROSOFT_EXTENSIONS_ALLOWED
    +
    DEFAULT_MICROSOFT_COMPATIBILITY
    +

    +
    +
    +
    Control whether compatibility with Microsoft’s C and C++ compilers +should be enabled, either by default or only when the --microsoft +command-line option is specified.
    +
    +
    +
    SUN_EXTENSIONS_ALLOWED
    +
    DEFAULT_SUN_COMPATIBILITY
    +

    +
    +
    +
    Control whether compatibility with Sun CC should be enabled, either by +default or only when the --sun command-line option is specified.
    +
    +
    +
    DEFAULT_CLANG_COMPATIBILITY
    +

    +
    +
    +
    Controls whether compatibility with clang C and C++ should be +enabled by default or only when the --clang command-line +option is specified. (Clang extensions are mostly identical to GNU +extensions and are controlled by GNU_EXTENSIONS_ALLOWED.)
    +
    +
    +
    +

    Setting an …_ALLOWED macro to TRUE makes the corresponding +DEFAULT_… macro TRUE by default. If the front end is configured to +support multiple dialects, the DEFAULT_… macros must be set explicitly +to avoid selecting more than one dialect as the default.

    +
    + + + + + + + + + +
    +
    CPPCLI_ENABLING_POSSIBLE
    +
    CPPCX_ENABLING_POSSIBLE
    +

    +
    +
    +
    Control whether a mode compatible with Microsoft’s C++/CLI or +C++/CX extensions should be available through the command-line +options --cppcli/--cppcx. Setting either of these options +to TRUE requires that MICROSOFT_EXTENSIONS_ALLOWED also be +TRUE.
    +
    +
    +
    DEFAULT_CPPCLI_ENABLED
    +
    DEFAULT_CPPCX_ENABLED
    +

    +
    +
    +
    TRUE if C++/CLI or C++/CX extensions should be enabled by default +when Microsoft extensions are enabled.
    +
    +
    +
    +
    +
    +

    1.2.5.3. IL Features#

    +
    + + + + + + + + + + + + + + + +
    +
    EXTRA_SOURCE_POSITIONS_IN_IL
    +

    +
    +
    +
    TRUE if certain additional IL entries, besides those that already have +a_source_correspondence fields, should contain source position +information. For example, expression nodes will record the starting +and ending position of the corresponding expression, as well as the +position of that expression’s top-level operator. Note that this can +increase the size of the IL substantially.
    +
    +
    +
    EXPR_RANGE_MODIFIERS_IN_IL
    +

    +
    +
    +
    TRUE to extend the tracking of source ranges for expressions by +including position information for operators that generally do not +appear in the IL, such as *, &, and ().
    +
    +
    +
    RECORD_MACROS_IN_IL
    +
    RECORD_MACRO_INVOCATIONS
    +
    RECORD_MACRO_ARGS
    +
    FULLY_RESOLVED_MACRO_POSITIONS
    +
    MACRO_INVOCATION_TREE_IN_IL
    +

    +
    +
    +
    Indicate whether extra information should be recorded in the IL +describing macros and their expansions. Setting +RECORD_MACRO_ARGS to TRUE requires that +RECORD_MACRO_INVOCATIONS be set to TRUE. Setting either of +the latter two configuration macros to TRUE can increase the size +of the IL substantially.
    +
    +
    +
    ALL_TEMPLATE_INFO_IN_IL
    +

    +
    +
    +
    TRUE if prototype template instantiations (i.e., the parsed generic +form of templates) should be recorded in the main IL tree.
    +
    +
    +
    +
    +
    +

    1.2.5.4. Target Platform Options#

    +

    Note that although these configuration macros deal with issues related to the +target, they are not considered “target-specific” (because these values cannot +differ between target configurations).

    +
    + + + + + + + + + + + + + + + +
    +
    IA64_ABI
    +
    +
    +
    Controls whether the IA-64 ABI standard is used for code +generation and object layout. This is a “modern” C++ object +layout (unlike the cfront layout), and is a good starting point +even on architectures other than IA-64 (Itanium). This ABI is +used by many versions of g++ (3.2 and later) and clang. For a +complete specification, see +https://itanium-cxx-abi.github.io/cxx-abi/. See also other macro +names beginning with IA64_ABI, some of which enable compatibility +with the ARM EABI variant of the IA64_ABI. If IA64_ABI is +set to FALSE (or 0), a cfront-like ABI is used instead.
    +
    +
    +
    DEFAULT_GNU_ABI_VERSION
    +
    DEFAULT_EMULATE_GNU_ABI_BUGS
    +

    +
    +
    +
    Control the emulation of the GNU variant of the IA-64 ABI.
    +
    +
    +
    GCC_IS_GENERATED_CODE_TARGET
    +
    GNU_TARGET_VERSION_NUMBER
    +
    MSVC_IS_GENERATED_CODE_TARGET
    +
    MSVC_TARGET_VERSION_NUMBER
    +
    SUN_IS_GENERATED_CODE_TARGET
    +
    SUN_TARGET_VERSION_NUMBER
    +
    CLANG_IS_GENERATED_CODE_TARGET
    +
    CLANG_TARGET_VERSION_NUMBER
    +

    +
    +
    +
    Control whether the code generated by the C- or C++-generating +back end should target a specific GNU, Microsoft, Sun, or clang +compiler. This is information is used to avoid limitations of +those compilers and to exploit extensions they provide.
    +
    +
    +
    CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT
    +

    +
    +
    +
    TRUE if the C++-generating back end should generate code that matches +the dialect selected for the front end. (E.g., if the front end is +set to parse GNU code, the back end can generate GNU __attribute +constructs, whereas if the front end is set to accept Microsoft +extensions, the back end might generate __declspec specifiers.)
    +
    +
    +
    +
    +
    +

    1.2.5.5. Front End Behaviors#

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    MAKE_FRONT_END_CALLABLE
    +

    +
    +
    +
    TRUE if, instead of having its own main program, the front end is to +be linked as part of some other main program. When this flag is set, +the EDG_MAIN macro provides the name of the main entry point into +the front end.The front end can then be called repeatedly by the same +process (each call reinitializes the front end’s internal state).
    +
    +
    +
    COMPILE_MULTIPLE_SOURCE_FILES
    +

    +
    +
    +
    Indicates that the front end should be capable of compiling a list of +source files in a single invocation.
    +
    +
    +
    IL_SHOULD_BE_WRITTEN_TO_FILE
    +

    +
    +
    +
    TRUE if the intermediate language should be written to a file; FALSE +if the intermediate language is passed in memory to the back end +(assuming BACK_END_SHOULD_BE_CALLED is TRUE).
    +
    +
    +
    USING_DRIVER
    +
    +
    +
    Indicates that the front end is being run from a driver program. +Setting this flag suppresses termination messages (like +“Compilation terminated.”) written to the error output file +because it is expected that the driver will write those.
    +
    +
    +
    MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED
    +

    +
    +
    +
    TRUE if multibyte character sequences (e.g., like Unicode UTF-8 or +those in the Japanese SJIS encoding) are supported in comments, +string literals, identifiers, and character constants.
    +
    +
    +
    USE_OWN_SJIS_MULTIBYTE_CHAR_PROCESSING
    +

    +
    +
    +
    TRUE if, instead of the routines in the standard C library (e.g., +mblen), custom routines in host_envir.c should be used to deal +with Japanese SJIS multibyte characters in source code.
    +
    +
    +
    LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED
    +

    +
    +
    +
    Indicates the locale to be established by a call to setlocale to +get the desired processing of multibyte characters from the C library +while reading the source code.
    +
    +
    +
    UNICODE_SOURCE_SUPPORTED
    +

    +
    +
    +
    TRUE if the character set to be supported is Unicode. When +MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED is TRUE, source files +encoded as UTF-8 and UTF-16 are accepted, depending on the +--unicode_source_kind command-line option, +DEFAULT_UNICODE_SOURCE_KIND configuration macro, or Byte Order +Mark (BOM), and UTF-16 is translated to UTF-8 immediately on +input. When MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED is FALSE, the +source file is assumed to be encoded as ISO/IEC 8859-1 (Latin-1).
    +
    +
    +
    +
    +
    +

    1.2.5.6. Development Aids#

    +
    + + + + + + + + + + + + + + + +
    +
    DEBUG
    +
    +
    +
    Enables additional code in the front end to simplify debugging. This +includes flow/event tracing options, routines that can be called from +a debugger to examine the IL, and an option to output the settings of +the configuration macros.
    +
    +
    +
    CHECKING
    +
    +
    +
    Enables inexpensive internal consistency checking. Recommended even +in production builds.
    +
    +
    +
    EXPENSIVE_CHECKING
    +
    +
    +
    Enables more expensive internal consistency checking. (Not generally +recommended for production builds.)
    +
    +
    +
    WRITE_CPPCLI_PORTABLE_ASSEMBLIES
    +

    +
    +
    +
    When TRUE, this enables an internal command-line option +“--set_flag generate_portable_assemblies” that causes a front +end built with support for C++/CLI (for Microsoft Windows) to +write out all assemblies used in the compilation (likely including +mscorlib.dll) in the current directory in a format that is +readable on non-Windows platforms (i.e., with a front end not +built with EDG_WIN32 set to TRUE). Since the assemblies are +written in the current directory with their original file name +(e.g., “mscorlib.dll”), care should be taken that no required +assemblies are in the current directory when the front end is +invoked in this way.
    +
    +
    +
    +
    +
    +
    +

    1.2.6. Target-Specific Configuration#

    +

    A target configuration is defined by giving appropriate values to a set of +configuration macros (dubbed the target-specific configuration macros). +Multiple target configurations can be specified when the front end is built; +the --target command-line option is used to select a non-default target +configuration when the front end is invoked. The --dump_legacy_as_target +command-line option can be used to display the set of target-configuration +macros.

    +

    Each target-specific configuration macro has a “legacy” version, i.e., one +without any target-specific suffix, as well as a version for each target +configuration that is specified when the front end is built. Non-legacy +configuration macro names are formed by appending an underscore and the target +configuration name to the legacy configuration macro name. For example, the +legacy macro TARG_LITTLE_ENDIAN would have a corresponding +TARG_LITTLE_ENDIAN_win32 configuration macro for the win32 target +configuration.

    +

    By default, the legacy configuration has no name, but one may be specified by +setting LEGACY_TARGET_CONFIGUATION_NAME to the desired name. The default +target configuration can be specified by giving its name as the definition of +the DEFAULT_TARGET_CONFIGURATION_NAME configuration macro; otherwise, the +legacy target configuration will be used as the default.

    +

    Note that specifying a named target configuration (either explicitly or through +defaults) requires that an $EDG_BASE/lib_target/ directory be +present at run time. Having target-specific $EDG_BASE/lib_target/ directories allows each target configuration to have different predefined +macros (e.g., to define _M_IX86 in one and _M_X64 in another).

    +

    A legacy configuration can be configured manually (by specifying values for +each target-specific macro), or automatically (by using the dettarg tool +and defaults that many configuration macros have). The +--dump_configuration command-line option provides a convenient display of +all configuration macros and their settings.

    +

    By default, the --version and --dump_configuration output (and the +string that identifies precompiled header files) includes the date and time the +front end was built, so no two builds produce identical executables. Defining +the configuration macro BUILD_IDENTIFIER as a string literal (with CMake, +-DEDG_BUILD_IDENTIFIER=string) replaces the date and time with that +string, making the build reproducible. Builds of different sources should use +different identifiers so their precompiled headers aren’t mistaken for each +other.

    +

    A non-legacy target configuration is most easily generated as a derivative from +an existing legacy target configuration using the --dump_legacy_as_target +command-line option. This option takes a target configuration name and +generates a list of the target-specific macro names for the given target +configuration name along with the values of the legacy configuration. This +file (after verifying that TARGET_CONFIGURATION_number is unique) can +then be included in defines.h as the basis for a new target configuration. +Additional target configurations can be generated from different legacy +configurations in the same manner, or by using an existing target configuration +as a template (and changing the target configuration name in each macro, along +with the TARGET_CONFIGURATION_number). Note that all target-specific +configurations must share the same non-target-specific configuration, so for +instance, it’s not possible to have an IA-64 ABI target configuration and a +Cfront target configuration in the same front end configuration (because +IA64_ABI is not a target-specific configuration macro and must have the +same value across all target configurations).

    +

    Note that it is inadvisable to use a target-specific global variable as the +value for a target-specific configuration macro. For example:

    +
    +

    #define TARG_IA64_VTABLE_ENTRY_INT_KIND targ_ptrdiff_t_int_kind

    +
    +

    is subject to race conditions (because targ_ptrdiff_t_int_kind may or may +not have been initialized before its value is used to set +targ_ia64_vtable_entry_int_kind). The following will work as expected:

    +
    +

    #define TARG_IA64_VTABLE_ENTRY_INT_KIND TARG_PTRDIFF_T_INT_KIND

    +
    +

    An important aspect of this architecture is that each legacy configuration +macro has an associated global variable whose value is set at initialization +time to the value of the (legacy or per-target) configuration macro for the +selected target. Because of this, it is imperative that user modifications to +the front end use the run-time value of global variables rather than the +compile-time values of legacy configuration macros.

    +
    +
    +

    1.2.7. Replaceable Code#

    +

    Occasionally, some customizations are needed that cannot simply be expressed +through configuration macros. Those may require instead that various routines +be replaced with custom code. The following files in src/ are written with +such modifications in mind:

    +
    + + + + + + + + + + + + + + + +
    +
    fixed_pt.c
    +
    +
    +
    Routines implementing operations on fixed-point values (only supported +in some configurations).
    +
    +
    +
    float_pt.c
    +
    +
    +
    Routines implementing operations on floating-point values.
    +
    +
    +
    host_envir.c
    +
    +
    +
    Includes routines dealing with operations on files and directories. +Signal handlers can also be set up there.
    +
    +
    +
    sys_predef.c
    +
    +
    +
    Routines to predefine platform-specific entities (macros, types, +routines, etc.)
    +
    +
    +
    +
    +
    +
    +

    1.3. Building the Front End#

    +
    +

    1.3.1. Using the Top-Level Makefile#

    +

    Assuming a Unix-like environment, a complete demonstration compiler can be +configured and built using a sequence of shell commands like the one shown +below (for a typical Linux platform, but other Unix-like environments are +similar). The sequence assumes that the current directory is the top-level +directory of a freshly unpacked release.

    +
    cp sample_edg_eccp_config/edg_eccp_config.linux edg_eccp_config
    +cp src/defines.h.linux src/defines.h
    +cd lib
    +../sample_edg_eccp_config/make_g++_incl_paths
    +../misc/make_predef_macro_table
    +cd ..
    +export EDG_BASE=`pwd` # or setenv EDG_BASE `pwd`
    +make
    +
    +
    +

    This builds a front end with a C-generating back end, along with a run-time +support library and helper tools such as the prelinker and demangler. The +entire toolset can be driven with the eccp script (see +“The eccp script”).

    +
    +
    +

    1.3.2. Building the Front End Only#

    +

    In an environment with a Unix-like make utility, the front end can be +compiled and linked by running

    +
    make edgcpfe
    +
    +
    +

    in the src/ directory (after constructing an appropriate defines.h file +and editing src/Makefile to select the desired compiler and compiler +options for building the front end). This can be useful to update the front +end for modifications after building the complete tool set, or when only the +front end program itself is desired. If make is not available, the front +end can be built using the following manual steps.

    +
      +
    • +
      Configure the defines.h file. For example, under Windows the following +is a useful starting point:
      +
      +
      copy src\defines.h.win32 src\defines.h
      +
      +
      +
    • +
    • +
      In the misc/ directory, compile and link the mk_errinfo program +into a mk_errinfo executable file. For example, using a Windows +command line and the Microsoft C++ compiler:
      +
      +
      cd misc
      +cl /TP /I..\src mk_errinfo.c
      +cd ..
      +
      +
      +
      +
      See mk_errinfo for additional information about mk_errinfo and +the format of its input files.
      +
      +
    • +
    • +
      In the src/ directory, translate the diagnostic messages using the +mk_errinfo program that was built in the previous step. For example, +using a Windows command line
      +
      +
      cd src
      +..\misc\mk_errinfo error_msg.txt error_tag.txt err_codes.h err_data.h
      +
      +
      +
    • +
    • +
      Still in the src/ directory, compile and link all the .c and +.cpp files. For example:
      +
      +
      cl /TP /EHsc /Feedgcpfe.exe *.c *.cpp /link mscoree.lib oleaut32.lib
      +
      +
      +
    • +
    +
    +
    +

    1.3.3. Building Support for C++/CLI and C++/CX Modes#

    +

    C++/CLI is a Microsoft extension to C++ that simplifies writing C++-like +programs for Microsoft’s “.NET” environment. It is formally specified by the +ECMA standard ECMA-372. The front end can support this extension, provided it +is built on a sufficiently recent Microsoft Windows platform with a compiler +that is sufficiently compatible with Microsoft’s “Visual C++” compiler. This +support is currently limited to producing high-level IL. The C++-generating +back end can consume this IL (and render the C++/CLI constructs it describes), +but lowering and the C-generating back end are not available in C++/CLI mode.

    +

    C++/CX is a Microsoft extension to C++ similar to C++/CLI, but it targets the +“Windows Runtime” (WinRT) platform instead of the “.NET” environment. Unlike +C++/CLI, there is no formal document specifying this extension. The front end +can also support C++/CX, with the same caveats as those mentioned for C++/CLI +support (in particular, IL lowering is not available for C++/CX mode).

    +

    To include support for C++/CLI and/or C++/CX the configuration macros +CPPCLI_ENABLING_POSSIBLE and/or CPPCX_ENABLING_POSSIBLE +(respectively) must be set to TRUE. (The macros +MICROSOFT_EXTENSIONS_ALLOWED and EDG_WIN32 must also be TRUE when +building such configurations.) In addition to compiling the C++ files +constituting the front end proper (as explained above), support for C++/CLI +and/or C++/CX requires that the C++ source file ms_metadata.cpp be +compiled and the resulting object file must be added to the set of files +linked into the final front end executable (or library). The system +libraries mscoree.lib and oleaut32.lib are then also required in +the final executable.

    +

    Compiling ms_metadata.cpp requires Visual C++ 2012 or later (or a C++ +compiler and libraries that are sufficiently compatible with that). The free +“Express” version of Visual C++ is not sufficient because it doesn’t include +the ATLMFC library, which ms_metadata.cpp depends on.

    +
    +
    +

    1.3.4. Building and Using the IL Display Program#

    +

    For educational and debugging purposes, the front end comes with a utility +named edgcpdisp that reads a file containing the IL produced when the front +end compiles one or more source files and displays it in a human-readable form. +(In order to use this facility, of course, the front end must be configured to +write an IL file, i.e., IL_SHOULD_BE_WRITTEN_TO_FILE must be set to TRUE in +defines.h or in src/Makefile.)

    +

    Because the IL file written by the front end is essentially a binary dump of +the IL data structures, it is necessary for the front end and edgcpdisp to +be built on the same platform and using the same configuration options. (Many +of the IL data structures contain fields that are present only in certain +configurations.)

    +

    In an environment with a Unix-like make utility, edgcpdisp is +automatically built (with a configuration that correctly matches that of +the front end) when make is run for the default target in either the +top-level or src/directory. It can also be built separately in the +src/ directory by specifying edgcpdisp as the target.

    +

    If make is not available, edgcpdisp can be built after the front end is +built (as described in the preceding section) in the src/directory by +compiling a subset of the source files with STANDALONE_IL_DISPLAY set to +TRUE. For example, on a Windows platform using the Microsoft C++ compiler, the +command would be (all on one line):

    +
    cl /TP /Feedgcpdisp.exe -DSTANDALONE_IL_DISPLAY const_ints.c  debug.c      \
    +   error.c fixed_pt.c float_pt.c host_envir.c  il.c il_display.c il_read.c \
    +   il_to_str.c il_walk.c  mem_manage.c target.c types.c fe_init.c
    +
    +
    +

    Displaying the IL for a source file x.cpp can be accomplished with the +following commands:

    +
    edgcpfe --output x.cil x.cpp
    +edgcpdisp x.cil
    +
    +
    +

    (In configurations that do IL lowering, x.cil will contain the lowered IL. +To view the unlowered IL, see the --no_il_lowering front-end command-line +option described in the next chapter.)

    +

    The format of the output is partially controlled by the configuration macro +ALTERNATIVE_IL_FILE_FORMAT. When that macro is set to TRUE, each entry +is given a unique numeric identifier, resulting in output like the +following:

    +
    ...
    +file-scope type#6
    +source_corresp:
    +  name:                  file-scope id-name#17: "type_info"
    +...
    +
    +
    +

    When ALTERNATIVE_IL_FILE_FORMAT is FALSE, the entries are +distinguished by a hexadecimal representation of the entry’s address:

    +
    ...
    +file-scope type@a0013ee68
    +source_corresp:
    +  name:                  file-scope id-name@a0013f050: "type_info"
    +...
    +
    +
    +

    It is not necessary to use the edgcpdisp to get a human-readable +display of the IL. When it is built with the configuration macro +NEED_IL_DISPLAY set to TRUE, the front end will put out the IL display +on stdout (using the hexadecimal-address format) when the +--il_display command-line option is specified. (The IL need not be +written to a file in this case.)

    +
    +
    +
    +

    1.4. Driving the Front End#

    +

    For many applications, it is useful to invoke the front end through another +“driver” program. One such driver is the bin/eccp script that is part of +every release. Another is the edgcc program that can be downloaded +separately from the EDG download site.

    +
    +

    1.4.1. The eccp script#

    +

    The bin/ directory contains a (Bourne) shell script eccp that +allows the front end to be used much like most Unix-hosted compilers. It +invokes the front end – which must be configured with the C-generating back +end – with various default options, and then compiles any generated C files +through a “native” C compiler (e.g., the GNU gcc compiler) and a native +linker. The script accepts Unix-like compiler options (such as -c, +-o, -O, -g, -I, -L, and -l) and also passes through +most of the options handled by the front end proper (see Command Line).

    +

    The script can be moved anywhere, but it normally looks for various components +(the front end, the prelinker, etc.) under a directory designated by the +environment variable EDG_BASE. The eccp script can be edited to set a +default substitute value for the EDG_BASE variable. Normally, the value of +EDG_BASE is the top level directory of a fully-built release tree (although +the src/ and lib_src/ directories are not used by eccp). eccp +will start by setting various environment variables by executing a script +$EDG_BASE/edg_eccp_config. Sample scripts for various platforms are +provided in the sample_edg_eccp_config/ directory. Two environment +variables commonly customized in the edg_eccp_config script are +EDG_DEFAULT_DEFINES (to add options like -D__unix__) and +EDG_C_TO_OBJ_COMPILER (to establish which “native” compiler to use; e.g., +gcc).

    +

    eccp may also invoke the prelinker (util/edg_prelink) to automatically +instantiate templates (and, with some front end configurations, inline +functions that need an out-of-line copy). See +Automatic Instantiation for notes on this process. The script will +also run util/edg_munch if needed, and filter linker errors through +util/edg_decode.

    +

    See “Utility Programs” for more information on the utility programs +edg_prelink, edg_munch, and edg_decode used by the eccp script.

    +
    +
    +

    1.4.2. The edgcc Driver for Windows#

    +

    A Windows program implementing a subset of eccp‘s functionality can be +downloaded from the EDG download site. The file to download is +nt_util.zip. In addition to source code for the driver program edgcc, +it also contains source code for a Windows-hosted prelinker (pl_nm) and +munch-like program (munch_nm).

    +

    The plain text file src/msinfo.txt contains additional notes for +running the front end in the Windows environment.

    +
    +
    +
    +

    1.5. Configuring and Building the Run-Time Support Library#

    +

    Source code for a sample run-time support library is provided in the +lib_src/ directory. This library is meant to be built using the front end +(i.e., a compiler incorporating the EDG front end). The library is useful for +demonstration and debugging purposes. However, it is normally not suitable for +production compilers because it is written in portable C++ that cannot take +advantage of more efficient platform-specific mechanisms (e.g., to implement +exception handling).

    +

    Similarly to the front end, the library can be configured through macro +definitions placed in lib_src/defines.h. Typically, however, few or no +macros need to be defined because the --building_runtime option to the +front end (used to build this library) causes most or all required macros +to be predeclared.

    +

    The macros that might need manual configuration are documented in +lib_src/config.h.

    +

    When using multiple target configurations, a version of the run-time support +library must be built for each target configuration and installed in the +appropriate lib_target/ directory. See lib_src/Makefile for +directions to build target-specific versions of the library.

    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/c_gen_be/index.html b/dev/doc/c_gen_be/index.html new file mode 100644 index 0000000..0fcbf61 --- /dev/null +++ b/dev/doc/c_gen_be/index.html @@ -0,0 +1,728 @@ + + + + + 23. C-Generating Back End - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    23. C-Generating Back End#

    +

    c_gen_be.c contains code to translate the intermediate language to C; +c_gen_be.h contains the associated declarations. This is a fake “back end” +that is useful as a way of testing the front end in the absence of a real back +end, as a portability aid, and as an example of how to traverse the +intermediate code (which may be helpful to those writing back ends).

    +
    +

    23.1. Function#

    +
    +

    23.1.1. Generated C Code#

    +

    The C code generated can be either ANSI C or old-style K&R C, depending on the +setting of the configuration flag C_GEN_BE_GENERATES_ANSI_C.

    +

    The output contains #line directives that relate the generated code back to +the original source lines that generated it. The #line directives do not +ascend monotonically through the line numbers of the source file; they jump +around as the code generation jumps around. However, since the C-generating +back end tends to process all declarations of entities of one kind in a sweep +through those entities in source order, the output tends to have all the types +in source order, then all the variables in source order, etc.

    +

    Long output lines are broken (between tokens) to avoid unduly stressing C +compilers that must process the generated code.

    +

    Since the generated code is intended to be fed into a C compiler, rather than +read by a human, it is not very readable. The readability can be improved +(slightly) by turning on debugging (e.g., -d0 on the command line); that +will cause the C-generating back end to generate annotation comments and +indentation. Unreferenced entities, which ordinarily are not put out at all, +are generated inside #if 0/#endif delimiters in this mode.

    +
    +
    +

    23.1.2. Transformations#

    +

    For the most part, what the C-generating back end does is just writing out the +C code that corresponds directly to the IL. Since the IL has the same concepts +and constructs as the C language, the processing is pretty straightforward. +However, there are a few complicating transformations.

    +

    The following transformations on names are done:

    +
      +
    • +
      Names that match C reserved words, or words that are likely to mean +something to the underlying C compiler (e.g., unix), are given a prefix +of “__x”.
      +
      +
    • +
    • +
      Names with no linkage (e.g., local variables) are given a prefix that is +the source sequence (line) number and column number of the name’s +declaration, to make sure they do not conflict with similar names from +elsewhere in the program (e.g., “i” is output as “__28_7_i”).
      +
      +
    • +
    • +
      Unnamed entities are given generated names of the form “__Tnnnnnn”, +with nnnnnn generated from the IL entry address.
      +
      +
    • +
    • +
      The “this” parameter, passed through from C++, is given the name +“this”.
      +
      +
    • +
    • +
      Function-local and prototype-scope types are given names formed by +concatenating the original name, “__”, the (mangled) function name, +“__”, and “Lnn”, where nn is a number identifying the +function, prototype, or block scope scope of which the type is a +member. (Renaming is needed because such types are promoted out of +functions; more on this below.)
      +
      +
    • +
    • +
      When generating K&R C, file-scope static variables are given a suffix +formed from the name of the module and the date and time of compilation. +This suffix is needed because initialized file-scope static variables must +be made external to avoid some pcc limitations on declaring static +variables more than once. The suffix helps to ensure that the now-external +name does not conflict with like-named static and external variables from +other compilation units.
      +
      +
    • +
    +

    Another set of transformations is necessitated by the fact that IL lowering +generates “C” IL that actually contains some minor extensions. These +“extensions” are things that a real back end would probably take in its stride +(i.e., it wouldn’t see these cases as being different than normal cases), but +which must be rewritten if standard C code must be generated:

    +
      +
    • +
      Dynamic initializations for declarations can appear in mid-block, after +executable statements have appeared. (These are generated as executable +code. Because of this, “const” type qualifiers are suppressed on +variables initialized dynamically and on all struct members.)
      +
      +
    • +
    • +
      Structs and unions can have no members at all, and aggregate constants used +in initializers can contain empty lists of constants (”{}”). (The +struct/union definition will include a dummy field, and the initialization +puts a zero into that field.)
      +
      +
    • +
    • +
      Enumerations having no enumerator constants are put out as the +corresponding integral type.
      +
      +
    • +
    • +
      The eok_bassign operator is used to do assignment of arrays (e.g., in +generated copy constructors). (A memcpy is generated.)
      +
      +
    • +
    • +
      Prototyped parameter variables may be unnamed. (A name is generated.)
      +
      +
    • +
    • +
      Variables can be indicated to be initialized to zero (the initk_zero +initialization kind). This is used to differentiate real definitions of +external variables from tentative definitions (a distinction that is hazy +in C), and for local aggregate variables that are partially initialized. +(For static variables, the initialization to zero is preserved in the +generated C; for automatic variables, a memset is generated.)
      +
      +
    • +
    • +
      String literals in C++ are const. IL lowering leaves them const, +even though string literals in C are not const. (This does not require +a transformation in the generated C code: the string literals are put out +as such, and the C compiler sees them as non-const, which works out +okay.)
      +
      +
    • +
    +

    When generating K&R C, some transformations are needed to erase ANSI C features +that do not exist in K&R C:

    +
      +
    • +
      Prototyped functions are put out as old-style unprototyped functions.
      +
      +
    • +
    • +
      Type qualifiers (”const” and “volatile”) are not put out.
      +
      +
    • +
    • +
      Enumerations are put out as integral types, and enumeration constants are +put out as integral constants.
      +
      +
    • +
    • +
      “signed” is never put out. “signed char” is put out as “char”, +and “signed int” is not used for the base type of a bit field.
      +
      +
    • +
    • +
      “long double” is put out as “double”.
      +
      +
    • +
    • +
      The suffixes “U” on integral constants and “F” and “L” on +floating constants are not put out; a cast is used instead.
      +
      +
    • +
    • +
      Union initializations are rendered as executable code.
      +
      +
    • +
    • +
      Initializations of automatic aggregates are rendered as executable code.
      +
      +
    • +
    • +
      Bit fields in unions are put out as normal fields.
      +
      +
    • +
    • +
      Signed bit fields are simulated by adding code to sign-extend and truncate +the bit fields on each access.
      +
      +
    • +
    • +
      Second and third operands of “?” of type void are rewritten.
      +
      +
    • +
    • +
      extern void variables are put out with type char.
      +
      +
    • +
    • +
      Labels are given a prefix of “__L_” to accommodate the fact that pcc +does not maintain a separate name space for labels.
      +
      +
    • +
    +

    The following transformations also deal with features missing in K&R C, but +these transformations are done even when generating ANSI C to avoid some +features that might not be implemented (well) in C compilers:

    +
      +
    • +
      Rvalue field selections (e.g., “f(x).i”) are rewritten as lvalue field +selections by using a temporary.
      +
      +
      struct A { int i; };
      +extern struct A f();
      +void m() {
      +  j = f().i;  /* Rewritten as "j = (Tnnnn = f(), Tnnnn.i)" */
      +}
      +
      +
      +
    • +
    • +
      Wide string constants are stored in generated static variables and the +variables are used in place of the constants at each reference.
      +
      +
    • +
    • +
      Character arrays initialized with string constants not containing a +trailing null character are rendered in “exploded” form, e.g., something +like
      +
      +
      int a[4] = "abcd";
      +
      +
      +
      +
      is rendered as
      +
      +
      int a[4] = {'a', 'b', 'c', 'd'};
      +
      +
      +
    • +
    +

    The following transformations are necessary to deal with ordering problems +(i.e., they’re necessary because of the order in which the C-generating back +end outputs entities):

    +
      +
    • +
      Local types of functions are generated at file scope. This avoids problems +with extern declarations written inside functions (the extern entity is on +the file-scope list, but it may refer to local types of the function).
      +
      +
      void f() {
      +  struct A { int i; };
      +  extern void g(struct A);
      +}
      +
      +
      +
      +
      is rewritten as
      +
      +
      struct A { int i; };
      +extern void g(struct A);
      +void f() {}
      +
      +
      +
    • +
    • +
      Types in the prototype scope of a function are promoted out of the +prototype scope. This is because each function and variable is put out +twice, once as a declaration and once as a definition. Without this +promotion, the declaration and definition would be incompatible because the +two copies of the prototype scope types would be considered to be distinct +types.
      +
      +
      void f(struct A { int i; } p) {}
      +
      +
      +
      +
      is rewritten as
      +
      +
      struct A { int i; };
      +void f(struct A);
      +void f(struct A p) {}
      +
      +
      +
      +
      Prototype scopes that are not part of a function or variable definition are +not processed in this way. When generating K&R C, such unprocessed +function types are put out unprototyped, which eliminates the types defined +in the prototype scope. When generating ANSI C, such unprocessed function +types are put out prototyped, and if any structs, unions, or enums are +defined in the prototype scope they are put out inline.
      +

      +
      When a pointer type containing a prototype scope needs to be put out (i.e., +as the type of a constant or in a cast), the type (and cast) is suppressed, +because the conversion must have been implicit in the source program – +it’s not possible to name the types defined in a prototype scope outside of +that scope.
      +
      +
    • +
    +

    When virtual functions with covariant return types appear in the source +program, IL lowering rewrites them in a way that uses wrapper functions. That +is, when an overriding virtual function returns a pointer to a derived class, +and the overridden virtual function returns a pointer to a base, a wrapper +function is generated that calls the overriding function but returns a pointer +appropriate for the overridden function. Such functions have a body that is +simply a return of an enk_result_of_overriding_function node cast to the +proper pointer-to-base-class type. The C-generating back end expands these +wrapper functions by generating the body of the overriding function again, with +the added cast inserted over the expression at each return statement. Note +that the “obvious” implementation technique of replacing the +enk_result_of_overriding_function node by a call of the overriding function +(i.e., implementing these as actual wrapper functions) will not work if the +functions have variable-length argument lists. The same technique is used for +alternate entry points for constructors in the IA64-ABI, but only if the +routine has a variable-length argument list.

    +
    +
    +

    23.1.3. Configuration#

    +

    Although the generated C code is generally portable, there are some +configuration issues that must be attended to.

    +

    The most obvious is to make sure that the sizes and alignments of basic types +defined in targ_def.h match those assumed by the target C compiler.

    +

    Block operations (e.g., memcpy) are generated in either the BSD form or the +System V/ANSI form under control of the __BSD__ configuration option, so +make sure its setting matches the library of the target C compiler.

    +

    If the target C compiler has some way of indicating that a function is inline, +the code in dump_routine_decl should probably be changed to output that +construct.

    +

    Long output lines are wrapped to avoid overly long lines. You can alter the +maximum size by adjusting MAX_OUTPUT_LINE_SIZE. The default is fairly +modest (a few hundred characters).

    +

    If the target C compiler has particular bugs or shortcomings, you may want to +add code to work around them. There is existing code for the Sun, Microsoft, +and gcc C compilers.

    +

    The C-generating back end can emit #pragma directives for IL pragma +entries, but only in a somewhat limited way. For pragmas bound to an entity, +the pragma is emitted right before the declaration of the entity. However, +pragmas not bound to an entity are emitted at the beginning of the scope +containing them, and therefore they may not be where expected. That makes that +kind of pragma suitable only in cases where the exact position of the pragma is +not very significant, e.g., for global-effect pragmas and those that associate +attributes with entities by naming the entities.

    +
    +
    +
    +

    23.2. Operation#

    +

    The code can be compiled either as a subroutine back_end that is called in +the same program as the front end, or as a main program. In either case, +c_gen_be is called to do the C generation. It begins at il_header and +walks through the intermediate language tree, generating C and writing it to a +file with a .int.c suffix. First, it dumps the source correspondence +information (dump_source_file_correspondence_info) and some other header +code (dump_header_code). Then, for the file scope level, it

    +
      +
    • +
      calls dump_scope_constants to dump code for constants on the file-scope +list. This has marginal utility, but dumps class member constants (an +extension) promoted to the file scope by IL lowering. They are put out as +enum declarations.
      +
      +
    • +
    • +
      calls dump_scope_types to dump declarations for all named types – +i.e., typedefs and tags. The tags are output twice: as incomplete +declarations on a first pass, and as complete declarations on the second, +to avoid forward-reference problems. Local and prototype-scope types are +also output here (at the file scope) to avoid some ordering problems.
      +
      +
    • +
    • +
      calls dump_scope_routines to dump routine headers (no bodies).
      +
      +
    • +
    • +
      calls dump_scope_variables twice. The first time dumps variables +without initializers, and tentative declarations for those with +initializers. The second time dumps only the initialized variables, this +time with initializers. This is to avoid forward-reference problems.
      +
      +
    • +
    • +
      calls dump_scope_routines to dump routines with bodies.
      +
      +
    • +
    +

    When ONE_INSTANTIATION_PER_OBJECT is enabled, each instantiation is put +out as a separate object file. There is still only one IL tree, but it is +marked so that the C-generating back end can sweep through it several times +and put out a different C file (a “slice”) each time, each C file +containing one instantiated entity (function or static data member) plus +exactly the set of other entities needed by that entity. The information +on which entities to include on each sweep is provided by the +per-instantiation “needed” flags, which are a bit vector attached to the +source correspondence entry (see Needed Flags). Each slice is +assigned one bit in that bit vector, and if the bit is 1 the associated +entity is needed in the slice. On beginning the generation of the C file +for a slice, the C-generating back end sets the global variable +needed_flag_bit_number to the bit number for the slice, and then goes +through the normal processing to generate C for everything in the IL tree. +The normal test of the “needed” flag, used to exclude things that aren’t +needed, in this mode tests the proper bit in the bit vector, and therefore +excludes all entities that are not in the slice. In addition, when a +variable or function with a definition is encountered, if the variable or +function is not assigned to the current slice (as indicated by the +instantiation_needed_bit_number field in the variable or routine +entry), the variable or function is put out as a declaration instead of a +definition.

    +

    The lower-level routines are as follows:

    +

    dump_type_decl generates a type declaration. It calls

    +
      +
    • +
      dump_enum_definition,
      +
      +
    • +
    • +
      dump_struct_union_definition, or
      +
      +
    • +
    • +
      dump_typedef_decl.
      +
      +
    • +
    +

    Types are written out by dump_type and +dump_general_declaration_using_type. They use routines from +il_to_str.c to produce the output for the type. dump_enum_definition +puts out enum definitions, and dump_struct_union_definition puts out +struct/union definitions.

    +

    dump_variable_decl generates a variable declaration. For a variable with +an initializer, it calls dump_initializer. There’s some fairly complicated +processing under that routine to turn constant aggregate initialization into +executable code. Among other things, it involves writing initialization +assignments to an auxiliary file while processing declarations, then copying +the initialization code to the right place after all the declarations have been +processed. Because initialized static variables are put out twice (on two +calls of dump_variable_decl), they are made external when generating K&R C, +so their names are modified (by dump_variable_name) to avoid name conflicts +with like-named static and external variables in other compilation units.

    +

    Code generated for file-scope initializations (of unions when generating K&R C) +is placed in a separate routine (with a name beginning with “__cgi__”) that +needs to be called at program start-up time. If the compilation contains a +main program, or an initialization routine generated by IL lowering (with a +prefix of “__sti__”), a call to the C-generating back end initialization +routine is inserted there. Otherwise, if the compilation is of C++ source, the +C-generating back end generates an initialization routine of the same form as +that generated by IL lowering (”__sti__” prefix), along with the variables +needed to alert the link phase to the presence of the initialization routine. +If the compilation is of C source, a message is issued to ask the user to +include an appropriate “-i” option elsewhere to request invocation of the +initialization code.

    +

    dump_routine_decl generates a routine declaration. For a routine with a +definition, it calls dump_routine_definition. That in turn calls +dump_func_definition_type to dump the parameters (prototyped or old-style).

    +

    dump_statement is called to generate code for statements.

    +

    The statements and expressions of functions are pre-scanned before code for the +routine is generated, to generate declarations for any temporaries that will be +needed in the generated code. Specifically, temporaries are generated for +rvalue field selections and wide string constants.

    +

    Expressions are dumped by calling dump_expr. It outputs the expression by +walking the tree. It puts in explicit parentheses where necessary to guarantee +the grouping of operators. Taking the address of a function or array must also +be handled carefully, and is done by dump_ampersand.

    +

    Since pcc doesn’t allow signed bit fields, operations on such fields are +surrounded by references to macros to sign-extend them or truncate them for +storing.

    +

    dump_constant dumps out a literal constant or address constant using the +IL-to-string routines in il_to_str.c.

    +

    Actual output of generated code is handled by the following routines:

    +
      +
    • +
      m_write_ch,
      +
      +
    • +
    • +
      write_ch,
      +
      +
    • +
    • +
      m_write_str,
      +
      +
    • +
    • +
      write_str,
      +
      +
    • +
    • +
      m_write_tok_ch,
      +
      +
    • +
    • +
      write_tok_ch,
      +
      +
    • +
    • +
      m_write_tok_str,
      +
      +
    • +
    • +
      write_tok_str,
      +
      +
    • +
    • +
      write_unsigned_num, and
      +
      +
    • +
    • +
      write_num.
      +
      +
    • +
    +

    The “m_” versions are macros; the others are not. One can choose between +them based on the need for speed and/or a single evaluation of the argument. +The “tok_” routines always write a full token (or several); that allows the +output line to be broken before or after the output if the line is too long.

    +

    set_output_position is called to establish the source position of an entity +about to be generated. If necessary, it generates a #line directive or the +right number of empty lines to adjust the output position (see +write_line_directive).

    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/class_decl/index.html b/dev/doc/class_decl/index.html new file mode 100644 index 0000000..f253c2b --- /dev/null +++ b/dev/doc/class_decl/index.html @@ -0,0 +1,2236 @@ + + + + + 11. Class Declarations - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    11. Class Declarations#

    +

    All class, struct, and union declarations are scanned in decl_spec.c, and +their definitions, including the declarations of class members, are handled +through a set of routines, most of which are found in class_decl.c. The +layout of classes is handled in layout.c. Associated declarations are in +class_decl.h and layout.h.

    +

    Declarations of structs and unions in C mode are, for the most part, precisely +compatible with C++ declarations; they just make use of a small subset of the +syntactic options.

    +

    C++/CLI managed class add both a number of variant class kinds (collectively +called “managed classes”) and a number of variant member kinds (e.g., events). +These are also mostly implemented in class_decl.c.

    +

    C++11 lambda expressions implicitly define a closure class type. While the +top-level class declaration parsing routines (class_specifier and +scan_class_definition) are not applicable for parsing lambdas, some other +important routines in this area are reused (see Lambdas).

    +

    Similarly, C++/CLI delegate definitions implicitly define a ref class type, +which reuses some important routines supporting the ordinary definitions of +class types, but not the routines that parse such definitions.

    +
    +

    11.1. Overview#

    +
    +

    11.1.1. Class Declarations#

    +

    class_specifier (in decl_spec.c) is called from decl_specifiers +when a class, struct, or union keyword is encountered. [1] In +Microsoft mode, this is also done with the __interface keyword, and in +C++/CLI mode with the “keywords” ref class, ref struct, value +class, value struct, interface class, and interface struct. A +tag name may be present, and if it is declares_something is returned +TRUE. A definition may be present, and if it is defines_something is +returned TRUE. In every case, even when there is an error, a pointer to a +tk_class, tk_struct, or tk_union type entry is returned in +type_ptr.

    +

    The processing of class declarations consists of several steps. The tag name +(if present) is scanned and looked up in the symbol table (see +scan_tag_name). A declaration may be the declaration of a new class, a +reference to an existing class, or the completion of a declaration whereby an +incomplete class is fully defined; it may also be a specialization of a class +template. If this is a brand new class, the type entry is allocated for it; +otherwise, the old one is fetched from the symbol entry.

    +

    If the declaration does not actually define a class, that’s about all that +needs to be done. The type is returned to the caller and declaration +processing continues.

    +
    +
    +

    11.1.2. Class Definitions#

    +

    If a class declaration is a class definition – that is, if the class body is +present – then scan_class_definition is called from class_specifier +(it is also called from other places like f_instantiate_template_class to +create an instance of a template class and instantiate_class_template to do +prototype instantiation of the class template). The creation of a class +definition is tracked using type a_class_def_state; this is true for +ordinary definitions appearing in the source, but also for definitions +generated for, e.g., lambda expressions (i.e., closure types). This structure +records all kinds properties of the definition (e.g., the current accessibility +or whether a member has been seen that requires a nontrivial constructor) and +is passed around to many routines that implement class member declarations.

    +

    Most of the tasks performed by scan_class_definition are done in C++ mode +only:

    +
      +
    • +
      The base class specifiers (if any) are scanned and recorded.
      +
      +
    • +
    • +
      The scope stack is pushed for the class (and the scope stack entry is made +to point to the a_class_def_state structure for the definition).
      +
      +
    • +
    • +
      A loop is entered to scan class members. In ordinary C this means scanning +the declarations of fields. In C++ it means scanning all kinds of member +declarations.
      +
      +
    • +
    • +
      At the top of the loop (in C++ only) an optional access control specifier +is scanned.
      +
      +
    • +
    • +
      When using appears (or there is only a qualified name and no +declaration specifiers), a using declaration (or access declaration) is +scanned.
      +
      +
    • +
    • +
      When template appears template_declaration_or_directive is called +to process a member template.
      +
      +
    • +
    • +
      Otherwise, class_member_declaration is called:
      +
      +
        +
      • +
        A structure of type a_member_decl_info tracks properties of the +declaration. This structure includes a field decl_state of type +a_decl_parse_state (which is the kind of structure used for general +declaration processing).
        +
        +
      • +
      • +
        decl_specifiers (in decl_spec.c) is called to scan the +declaration specifiers.
        +
        +
      • +
      • +
        When there is no declarator following,
        +
        +
          +
        • +
          if it is a friend class declaration, decl_friend_class is called +and declarator processing is skipped.
          +
          +
        • +
        • +
          if it is a nested class, struct, union, or enum +declaration, declarator processing is skipped.
          +
          +
        • +
        • +
          if it is a nested anonymous union declaration, declarator processing is +entered (even though the call to declarator itself is skipped) +since the rest of the processing is done in +decl_nonstatic_data_member.
          +
          +
        • +
        +
      • +
      • +
        A loop is entered to scan a declarator list. In cases where only a +single declarator is permitted, the loop will be exited at the +appropriate point.
        +
        +
      • +
      • +
        declarator (in declarator.c) is called to scan a single +declarator. If default arguments are encountered when a parameter list +for a member function is scanned, they will be cached away to be +rescanned later.
        +
        +
      • +
      • +
        Based on the combined information returned from decl_specifiers and +declarator, one of the following is done:
        +
        +
          +
        • +
          decl_member_function is called to process a member function +declaration (static or nonstatic, virtual or nonvirtual). If the +function body is present, the tokens are cached so that they can +scanned later (see prescan_function_definition). If there is no +function body, a pure specifier (”= 0”) is checked for (see +scan_pure_specifier).
          +
          +
        • +
        • +
          decl_friend_function is called to process a friend function (member +or nonmember). If the function body is present, the tokens are cached +so that they can scanned later (see prescan_function_definition).
          +
          +
        • +
        • +
          decl_member_function_template is called to process a member +function template.
          +
          +
        • +
        • +
          decl_typedef is called to process a typedef declaration.
          +
          +
        • +
        • +
          decl_nonstd_member_constant is called to process a member constant +declaration (an extension).
          +
          +
        • +
        • +
          decl_static_data_member is called if the keyword static was +used in a non-function declaration.
          +
          +
        • +
        • +
          decl_nonstatic_data_member is called to do processing for ordinary +fields.
          +
          +
        • +
        +
      • +
      • +
        At the bottom of the declarator loop, continue looking for declarators if +the next token is a comma.
        +
        +
      • +
      +
    • +
    • +
      At the bottom of the loop, continue looking for member declarations unless +a right brace (or end of file) is encountered.
      +
      +
    • +
    • +
      Once the member declarations have been processed, further error checking is +done, and in addition:
      +
      +
        +
      • +
        In case the class was declared before the current definition, +move_to_end_of_types_list is called to move the type entry for the +class to the end of the scope types list. (It will have been initially +put onto the list in class_specifier.)
        +
        +
      • +
      • +
        set_virtual_function_numbers is called to do the remaining processing +for virtual functions – in typical implementations, the virtual function +number in a routine entry corresponds to its position in the virtual +function table.
        +
        +
      • +
      • +
        check_special_member_functions is called to determine whether a +compiler-generated default constructor, copy constructor, and assignment +operator is needed and, if so, to generate the declarations. (The bodies +are generated if and when the function is referenced.)
        +
        +
      • +
      • +
        do_class_layout is called to allocate space for base classes and +nonstatic data members, as well as for whatever information is needed +(e.g., pointers) to support accessing virtual base classes and calling +virtual functions.
        +
        +
      • +
      • +
        project_base_class_conversion_functions is called to add projection +symbols for inherited conversion functions to the class symbol +supplement’s conversion_list.
        +
        +
      • +
      • +
        report_virtual_function_ambiguities is called to issue diagnostics on +unresolved ambiguities in virtual function declarations.
        +
        +
      • +
      • +
        check_abstract_class is called to mark a class with pure virtual +functions as “abstract.”
        +
        +
      • +
      +
    • +
    • +
      The scope stack is popped, and the closing right brace of the class +definition is bypassed.
      +
      +
    • +
    • +
      For non-nested classes delayed_scan_fixup_for_class is called to rescan +member function default argument declarations and inline member function +definitions.
      +
      +
    • +
    +

    Many of these “class definition completion” tasks are initiated from the +complete_class_definition function. This function is also called for class +types that don’t appear using ordinary class definition syntax in the source +code (for example, closure types for lambda expressions; see Lambdas).

    +

    Ideally, all properties of a class should be known once the definition has been +seen. Unfortunately, that is not always the case. In particular, the C++11 +notion of whether a class type is a “literal type” cannot always be determined +until it is known whether it has a constexpr constructor, which in turn +sometimes requires waiting until all the field initializers have been scanned +(and for template classes that can be arbitrarily delayed). Whether a class +type is a literal type is therefore tracked by two flags in the class symbol +supplement [2] (known_to_be_a_literal_type and +known_not_to_be_a_literal_type), which can be determined “on demand” by a +call to set_literal_type_flag or, more generally, is_literal_type.

    +
    +
    +

    11.1.3. C++/CLI Managed Class Definitions#

    +

    Managed class definitions are parsed using the same framework as standard class +definitions. However, C++/CLI adds many new kinds of members, several of which +are implemented with new top-level mechanisms.

    +

    Several “field-like” managed member kinds rely on “context-sensitive +keywords”, i.e., specific identifiers (event, initonly, +literal, and property) that are keywords only if the rest of the +declaration would not otherwise be valid. The function +check_for_cli_modifier looks ahead through the token stream for such +keywords, and records their presence in the a_decl_parse_state +structure for the current declaration. If the keywords event or +property were found, the member declaration is handled using the +special-purpose function scan_cli_property_or_event_head, after which +the front end proceeds with the next declaration. The other two keywords +(initonly and literal) are consumed by the regular call of +decl_specifiers (which is passed the a_decl_parse_state structure +indicating that these identifiers should be treated as keywords).

    +

    Delegate definitions appearing as member declarations also rely on a +context-sensitive keyword delegate. That case is identified by the +function check_for_cli_delegate_definition, and is then handled by +scan_and_record_cli_delegate_definition.

    +

    Properties and events are represented as fields (a_field) if they are +nonstatic or as static data members (a_variable) if they are static. These +representations are created by calls to decl_nonstatic_data_member or +decl_static_data_member respectively, which is done by the function +decl_property_or_event_member.

    +

    Property and event definitions may include a brace-enclosed list of accessor +declarations (such properties/events are called nontrivial). Accessors are a +special kind of member function (i.e., their a_routine entry has a +special_kind field that is not sfk_none) of the parent class of the +property or event: The braces are for grouping purposes only and do not +introduce a new scope. Accessors declarations are handled as separate member +declarations in the main loop of scan_class_definition; not as part of the +call to scan_cli_property_or_event_head. However, a copy of the +a_member_decl_info structure recorded for the property/event declaration +itself is kept around while scanning the accessors (accessible via the +pe_info field of the current a_class_def_state structure). This is +needed because the exact nature of the property/event may depend on the storage +class specified on the first accessor: If no storage class was specified on the +property/event declaration itself, but the first accessor is declared static, +then the property/event should be treated as static. Hence for a nontrivial +property or events, the call to decl_property_or_event_member is delayed +until parsing of the subsequent accessor has started: At that point a lookahead +for a static specifier (using function static_member_next) is performed +if needed to determine the static/nonstatic nature of the property or event.

    +

    Literal fields (i.e., fields declared with the context-sensitive keyword +literal) are recorded in decl_literal_field: The result is an IL entry +of type a_constant, not a_field (i.e., “literal field” is somewhat of a +misnomer). initonly members, on the other hand, are just treated as +slightly special cases in decl_nonstatic_data_member and +decl_static_data_member.

    +

    Conversion functions and other operators can be static members of managed +classes; such members must have one more explicit parameter than their +nonstatic counterparts. The constraints on those parameters are checked in the +function check_operator_function_params.

    +
    +
    +
    +

    11.2. Names#

    +
    +

    11.2.1. Name Scope#

    +

    When a class is declared with a tag name, an sk_class_or_struct or +sk_union symbol is created to represent the use of the name. Since an +elaborated class specifier appearing in the source may refer to an existing +class, its name must be looked up in the symbol table. Finding a tag name in +the current or a containing scope is handled by scan_tag_name.

    +

    This is not a simple lookup, however. An interesting case occurs when a tag +name has already been declared in an outer scope: a reference to the same name +in an inner scope may or may not be a reference to the same entity. For +instance,

    +
    struct S { int i; };
    +void f() { struct S s; }
    +void g() { struct S { /* ... */ } s; }
    +
    +
    +

    In this example, the S in function f refers to the S defined in the +file scope, whereas the one in function g refers to another S, one +local to the function scope. The difference is that the declaration in g +is a definition and so eclipses the name from the file scope, whereas in f +there no redefinition of S. For this reason scan_tag_name must take +into account whether the class is being defined in the current declaration in +deciding whether to reuse a class defined in a containing scope. A further +complexity is revealed by another example:

    +
    struct S { int i; };
    +void f() { struct S; struct S *p; struct S { } s; }
    +
    +
    +

    Here the first declaration of S in function f, referred to as a +“vacuous declaration” of S because it does not define a class and is not +used in the definition of any other object, has the effect of introducing an +incomplete class S into the routine scope and thereby eclipsing the file +scope S. [3] scan_tag_name also deals with this kind of case.

    +

    When no tag symbol is found, there is still the question of what scope a new +symbol is to be declared in. This too is determined in scan_tag_name; the +answer is returned to the caller by effective_decl_level. In most cases it +is simply the current scope (given in decl_scope_level [4]). However, +in C++ a non-defining initial use of a class name in a function prototype scope +or a class scope is treated as declaring that name in the innermost containing +scope that is not the scope of a function prototype or a class. For example,

    +
    int f(struct S *p) { return (p == 0); }
    +struct S { /* ... */ } s;
    +
    +
    +

    Here (and contrary to the interpretation in ordinary C mode) there is only one +S; the second reference defines the struct to which the first is a kind +of forward reference. Thus scan_tag_name would return the file scope as +the effective_decl_level for S in its initial declaration. Similar +treatment is accorded declarations in classes:

    +
    class A {
    +  class B;
    +  class C *pc;
    +  class D {
    +    class E *pe;
    +  };
    +};
    +
    +
    +

    Here class B is a vacuous declaration (it anticipates a definition of a +nested class B later in the definition of A), whereas class C is a +forward reference to a file scope declaration of C. Similarly, class E +anticipates a file scope declaration as well, even though the file scope is not +the immediately containing scope of class D.

    +

    The tag name can be a qualified name, not only in a reference (e.g., a +friend declaration or the declaration of another entity using an elaborated +type specifier) but also in a definition.

    +
      +
    • +
      It can be a class-qualified name for a “delayed definition” of a nested +class. For example,
      +
      +
      class A {
      +  struct S;
      +  /* ... */
      +};
      +struct A::S { /* ... */ }
      +
      +
      +
      +
      Here scan_tag_name returns a symbol locator specifying the qualified +name; the parent class scope is then reactivated in +scan_class_definition before the body of the class definition is +scanned.
      +
      +
    • +
    • +
      It can also be a namespace-qualified name – most interestingly when a +class declared in a namespace is then defined outside the namespace. (It +is a requirement that the scope in which the definition occurs enclose the +scope in which original declaration occurs.) For example,
      +
      +
      namespace N {
      +  struct S;
      +  /* ... */
      +};
      +struct N::S { /* ... */ }
      +
      +
      +
      +
      scan_tag_name returns a symbol locator specifying the qualified name, +and class_specifier pushes a namespace-extension scope before calling +scan_class_definition.
      +
      +
    • +
    +
    +
    +

    11.2.2. Tagless Classes#

    +

    When classes are declared with no tag name, though obviously no symbol is +needed for lookup on a subsequent reference, one is needed to store +information about the class (see below). Creating such a symbol, which is +not actually added to the symbol table, is done by +make_unnamed_tag_symbol.

    +

    There is a way by which a tagless class can acquire a name retroactively – +when its definition appears within a typedef declaration. Here is an +example,

    +
    typedef struct { /* ... */ } S;
    +
    +
    +

    in which case the tagless struct comes to acquire the name S. This +cannot be anticipated during the processing done by scan_class_definition. +Rather, the situation is detected only after the class definition has been +scanned, in decl_typedef. In general, this means the name is assigned “for +linkage purposes”, which means the name field in the type’s +source-correspondence is updated. Additionally in cfront mode, +relink_unnamed_tag_symbol is called to add the symbol for the unnamed class +to the symbol table after turning it into a symbol of the specified name.

    +
    +
    +

    11.2.3. C++/CLI Accessor Names#

    +

    The names of accessor functions of properties and events (get, set, +add, remove, and raise) are not directly visible in the class of +which they are members (although accessors are members of that class in all +other ways; e.g., they have a this handle). Instead, referring to them +directly requires qualification with the name of the property or event. For +example

    +
    ref struct RS {
    +  int get();  // (1)
    +  property int p[int] {
    +    int get(int);  // (2) Use p::get
    +  }
    +  property int p[double] {
    +    int get(double);  // (3) Use p::get
    +  }
    +  property int q {
    +    int get(int);  // (4) Use q::get
    +  }
    +};
    +
    +
    +

    The accessors marked (2) and (3) form an overload set. The accessors marked +(1) and (4) are not part of overload sets. (See also Delegates (C++/CLI mode).)

    +

    The symbol for an CLI accessor is not linked under the symbol header used for +normal lookups of the accessor’s name. For example, a get accessor for a +property is not linked on the list of the symbol header normally associated +with the identifier get, and hence looking up the identifier get in the +usual way will never find an accessor. Instead, a special symbol header is +synthesized by combining the accessor name and its parent event or property; +see get_property_or_event_accessor_symbol_header for details. (See also +C++/CLI Member Functions for additional notes on accessor functions and their +representation, as well as Properties and Events (Microsoft and C++/CLI modes) for related remarks about +properties and events.)

    +
    +
    +
    +

    11.3. Type, Scope, and Symbol#

    +

    Processing a class declaration involves forming a potentially extensive and +complex description of the class. There are three principal data structures +that serve as repositories for this information: a symbol entry, a type entry, +and an IL scope entry. The information that must be passed on to the back end +(including the IL lowering phase, if applicable) is stored in the type and +scope entries; information that is only of use in front end processing (e.g., +for error detection) is recorded in the symbol.

    +

    Detailed descriptions of these data structures are provided in the files +il_def.h and symbol_tbl.h; introductions painted with a broader brush +may be found in the Intermediate Language and Symbol Table chapters.

    +

    One thing that might be a bit confusing is that both the symbols and type +entries for classes have supplements, entities of type +a_class_symbol_supplement and a_class_type_supplement, respectively.

    +

    Moving among the symbol, type, and scope entries that represent a class is +fairly straightforward:

    +
      +
    • +
      The assoc_type field of the IL scope entries points to the associated +class type.
      +
      +
    • +
    • +
      The assoc_scope field of the class type supplement points to the +corresponding IL scope entry.
      +
      +
    • +
    • +
      In the type entry the source_corresp.assoc_info field is a pointer to +the class’s symbol entry. [5]
      +
      +
    • +
    • +
      The symbol points to the type entry by means of the type field.
      +
      +
    • +
    +

    To make it a bit easier to get from source language categories to the data +structures that represent them, here (from a slightly different slant) is yet +another description of how the symbol, type, and scope divide up the task of +summarizing a class declaration:

    +
      +
    • +
      Nonstatic data members (“fields”) are recorded on a linked list of +a_field that is accessed from the type entry.
      +
      +
    • +
    • +
      Static data members are represented by a_variable entries; a list of +them appears on the scope entry.
      +
      +
    • +
    • +
      Member functions appear on a linked list of a_routine entries which is +also accessed from the scope entry. Static and nonstatic member functions +are intermingled on this list; they can be distinguished by the presence or +absence of an implicit this parameter type in the associated routine +type.
      +
      +
    • +
    • +
      Member function templates are represented by sk_function_template +symbols. (They also appear in the IL, but only very limited information is +available there: see the linked list of a_template pointed to from the +scope entry for the class.) Instances of member function templates, like +ordinary member functions, appear on the routines list of the class +scope entry.
      +
      +
    • +
    • +
      As far as the IL is concerned, constructors, destructors, overloaded +operator routines, and user-defined conversion routines are just like any +other member function. They can be identified by the +special_function_kind value in the routine entry (e.g., for generating +their names). To facilitate front-end processing, however, the symbol’s +class supplement contains pointers to the symbols for the constructor(s), +the destructor, and the assignment operator routine(s).
      +
      +
    • +
    • +
      Member types (including type entries for nested classes) and member +constants also appear on lists hanging off the scope entry.
      +
      +
    • +
    • +
      Member class templates are represented by sk_class_template symbols. +(They also appear in the IL, but only very limited information is available +there: see the linked list of a_template pointed to from the scope +entry for the class.) Instances of member class templates, like ordinary +nested classes, appear on the types list of the class scope entry.
      +
      +
    • +
    • +
      Friendship is represented by a reference to the befriending class in the +routine entry for the friend function (or in the type entry when friendship +is conferred on an entire class).
      +
      +
    • +
    • +
      Derivation is represented by a list of a_base_class entries that is +pointed to from the class type supplement of the derived class. All base +classes (direct, indirect, virtual) appear on this list. The specific ways +the class is derived are given by the a_base_class_derivation entry +associated with each base class; and there may be more than one such entry +for a given base class if it is virtual.
      +
      +
    • +
    • +
      Inherited names are represented by sk_projection symbols. The +projection symbol identifies both the fundamental symbol and the base class +entry with which that instance of the symbol is associated.
      +
      +
    • +
    • +
      Names brought into a derived class from a base class by a +using-declaration (or an access declaration) appear in the symbol table +as projection symbols for which is_using_decl is TRUE. Such +declarations are also recorded in the IL by entries of type +a_using_decl, pointed to from the scope entry.
      +
      +
    • +
    • +
      Accessibility is recorded in IL entries (for front-end use and symbolic +debug purposes only), in projection symbols (which can end up marked +“inaccessible”), and in base class derivation entries. But since +accessibility is generally dynamic, it must usually be computed (e.g., see +access_to_end_of_path and have_access_to_symbol in +symbol_tbl.c).
      +
      +
    • +
    +
    +
    +

    11.4. Base Classes#

    +

    Once the tag symbol and type entry have been created for a class definition, +scan_class_definition calls scan_base_specifier_list to scan any base +classes that may have been specified. It goes through the comma-separated list +of base classes one by one, creating for each (and for each of the indirect +base classes derived through it) an entry of type a_base_class that is +added to the base_classes list of the class type supplement. When all base +classes have been added, wrapup_base_classes is called to establish certain +properties (like the preferred derivation path of virtual bases) that cannot in +general be determined by looking at a single derivation.

    +
    +

    11.4.1. Base Class List#

    +

    The list of base classes associated with any derived class contains a base +class entry for each of its base classes – not just for those from which it is +directly derived. The order of the list is significant: depth-first +left-to-right, following the source code order of declarations. Base classes +contain a direct flag to distinguish direct from indirect base classes; +there is also an is_virtual flag. Consider this example:

    +
    class V { /* ... */ };
    +class A : virtual V { /* ... */ };
    +class B : virtual V { /* ... */ };
    +class C : public B { /* ... */ };
    +class D : public C, public A { /* ... */ };
    +
    +
    +

    Here the base classes list for class D will contain the following entries; +note that the virtual base class appears only once in the list:

    +
      +
    • +
      Indirect virtual base class V
      +
      +
    • +
    • +
      Indirect base class B
      +
      +
    • +
    • +
      Direct base class C
      +
      +
    • +
    • +
      Direct base class A
      +
      +
    • +
    +

    Base class entries are not shared between classes because they contain +information uniquely identifying the relation of a base class to its derived +class. Thus, in the previous example, class C also has its own base +classes list, namely:

    +
      +
    • +
      Indirect virtual base class V
      +
      +
    • +
    • +
      Direct base class B
      +
      +
    • +
    +

    Despite some overlap of information, new copies of the base class entries of +C are made for the base classes list of D.

    +

    In scan_base_specifier_list, for each base specifier in the source the +optional access-specifier and optional virtual keyword are scanned, the +base class name is scanned, and error checking is performed. If the same base +class name appears twice in the base specifier list, an error is issued. +However, if the name of a direct base class is identical to that of an indirect +base class already on the list, no error is reported at this time; rather, both +base classes are marked as ambiguous. This is an example of such a case:

    +
    class A { /* ... */ };
    +class B : public A { /* ... */ };
    +class C : public B, public A { /* ... */ };
    +
    +
    +

    The base classes list for C will contain:

    +
      +
    • +
      Indirect base class A (marked ambiguous)
      +
      +
    • +
    • +
      Direct base class B
      +
      +
    • +
    • +
      Direct base class A (marked ambiguous)
      +
      +
    • +
    +

    Only later, if, say, a qualified name using A appeared within a member +function of C, would the base class ambiguity be reported.

    +

    Creating the base classes list is done by scan_base_specifier_list, which +adds direct base classes, and add_indirect_base_classes, which in recording +indirect base classes calls itself recursively as required. Both routines call +fixup_virtual_base_class when a virtual base class is encountered more than +once among the direct and indirect base classes.

    +
    +
    +

    11.4.2. Derivation Path#

    +

    Each base class entry contains a derivation field, which points to one +or more entries of type a_base_class_derivation. (Nonvirtual base +classes will have only one such entry, but virtual bases may have more.) +Each base class derivation entry points to a linked list of one or more +entities of type a_derivation_step. Such a list is referred to as a +“derivation path” because it records the derivation of the derived class +from the base class: it is the path from a derived class back up its base +class tree to the required base class. Here is a simple example:

    +
    class A { /* ... */ };
    +class B : public A { /* ... */ };
    +class C : public B { /* ... */ };
    +
    +
    +

    The derivation path from derived class C to direct base class B is +=>B, whereas the path to indirect base class A is =>B=>A. (The notation => +can be thought of as a cast from a derived to a direct base class.)

    +

    The first step on a derivation path is either a direct base class, as in the +examples above, or a virtual base class. In the latter case, the paths to the +virtual base class (there may be more than one) are elided and may be found by +examining its base class derivation entries. For example:

    +
    class X { /* ... */ };
    +class A : public X { /* ... */ };
    +class B : virtual public A { /* ... */ };
    +class C : virtual public A { /* ... */ };
    +class D : private B, public C { /* ... */ };
    +
    +
    +

    Here the derivation path for X in D is represented as =>A=>X, whereas +A itself has two derivation paths, =>B=>A and =>C=>A, which are in effect +implicit in the derivation for X.

    +

    Base class ambiguity can be seen as a case in which there are two distinct +paths to nonvirtual base class entries that refer to the same class. Returning +to a previous example,

    +
    class A { /* ... */ };
    +class B : public A { /* ... */ };
    +class C : public B, public A { /* ... */ };
    +
    +
    +

    there are two base class entries for A in class C, with derivation +paths of =>B=>A and =>A.

    +

    add_indirect_base_class takes an existing base class entry and creates a +new one based on it, but to do this it needs a new derivation path as well. +copy_and_extend_path creates a new path based on the derivation path of the +original base class entry.

    +

    For cases in which it is necessary to compare two derivation paths, +congruent_paths returns TRUE if two paths refer, step for step, to the same +classes.

    +
    +
    +

    11.4.3. Virtual Base Class#

    +

    When two or more base classes of the same type are specified virtual, they +share the same base class entry. Its position in the base classes list will be +that of first appearance in the depth-first left-to-right traversal of the base +classes. However, each appearance in the derivation graph is recorded with a +separate derivation entry, and each derivation entry gives a unique derivation +path.

    +

    set_preferred_base_class_derivation is called to identify the “preferred” +path of a virtual base class – tantamount to the sequence of casts that +affords the greatest “normal” accessibility (i.e., without special treatment +for casts in the context of member or friend functions). For example,

    +
    class A { /* ... */ };
    +class B : virtual public A { /* ... */ };
    +class C : virtual public A { /* ... */ };
    +class D : private B, public C { /* ... */ };
    +
    +
    +

    Class D is derived from virtual base class A via two paths, BA and CA. +Therefore A‘s base class entry points to a list of two base class +derivation entries, one for each path. Since the path through C gives +greater accessibility, the base class derivation entry that points to CA is the +one marked “preferred”. (When several entries afford equally good access, a +direct base class is preferred over an indirect, and an indirect base class +with no virtual base classes in its derivation is preferred over one that has +virtual base classes in its derivation.)

    +
    +
    +

    11.4.4. Virtual Functions#

    +

    A final task performed by scan_base_specifier_list and its subroutines is +to accumulate virtual function information for its base classes.

    +

    When a function in a derived class “overrides” a virtual function from one of +its base classes, that information is recorded for later use: [6] A list of +entries of type an_overriding_virtual_function is pointed to from the base +class entry to identify the virtual functions that are members of that class +and that are overridden in some other class derived from it. This information +must be propagated as base classes are copied. Here is an example to make this +a bit clearer:

    +
    class A { virtual void f(); };
    +class B : public A { void f(); };
    +class C : public B { };
    +
    +
    +

    A::f() is a virtual function of the base class A that is overridden +by B::f() in the derived class B. The +overriding_virtual_functions field of the base class entry for A in +B points to an entry that identifies A::f() as the primary +function and B::f() as the overriding function. When C is +derived from B, this information is passed along. At the time the base +class entry for A is created in C, the virtual function override +information is copied from the base class entry for A in B, with an +additional piece of information – a pointer to the base class entry for +B in C. [7]

    +

    The virtual function override list is sorted on the basis of the virtual +function number in the routine entry of the primary function. It can be that +more than one overriding virtual function entry for a given primary function +ends up on the overriding virtual function list – and it needn’t be illegal. +Consider the following example:

    +
    class A { virtual void f(); };
    +class B : virtual public A { void f(); };
    +class C : virtual public B { void f(); };
    +class D : public B, public C { };
    +
    +
    +

    Within both B and C there are an overriding virtual function entries +for base class A specifying that primary function A::f() is overridden, +in the one instance by B::f() and in the other by C::f(). Within D +there is also a base class entry for A, and both the overriding by +B::f() and the overriding by C::f() are recorded in its list; both +overriding function entries will refer to the same primary function, +A::f(). As written above, this example is illegal. But the diagnostic +cannot be issued until the definition of D is complete (see +report_virtual_function_ambiguities), since a declaration D::f() would +override both B::f() and C::f(), making the ambiguity moot and the +program legal.

    +

    copy_virtual_function_override_list copies the overriding virtual function +for a base class from one class to another derived from it, calling +insert_in_virtual_function_override_list to place the copy in the proper +sorted location in the new list.

    +
    +
    +

    11.4.5. C++/CLI Derivations#

    +

    C++/CLI managed classes can derive from base classes in two different ways: +They can “inherit” from one ref class and they can “implement” any number of +interface classes. If the definition of a managed class (other than +System::Object) does not specify a base class explicitly, it inherits +System::ValueType if it is a value class, or it derives virtually from +System::Object otherwise (hence, all managed classes ultimately derive from +a virtual base class System::Object). See add_implicit_cli_bases.

    +

    “Implementing an interface” is modeled as virtual derivation. Inheriting from +a ref class other than System::Object corresponds to regular (i.e., +nonvirtual) derivation.

    +

    Some ref classes must implicitly directly derive from (i.e., “implement”) the +System::IDisposable interface according to a set of rules known as the “CLI +dispose pattern” (see implement_dispose_pattern_if_needed). However, this +cannot be determined until after the complete class definition has been seen: +This is therefore a unique situation where a (virtual) base class is added +after members have been seen. When this is done, wrapup_base_classes must +be called a second time.

    +

    Some generated managed classes implicitly inherit specific ref classes (by +calling add_cli_system_base_class): delegate classes inherit +System::MulticastDelegate and boxed enum types inherit System::Enum.

    +

    Generic parameters are modeled using proxy (managed) class types called +“constraint types”. A type constraint specifying a type C on a parameter +modeled by a constraint type P is modeled by adding C as a base class of P. +Note that Microsoft compilers permit “sealed” classes [8] to be specified as +type constraints, which means that in this context a sealed class can be +derived from (and in that case, the deriving constraint type is marked as +sealed also).

    +
    +
    +
    +

    11.5. Fields#

    +
    +

    11.5.1. Declarations#

    +

    scan_nonstatic_data_member is called from class_member_declaration to +process the declarations of what in ordinary C are called “fields” and in C++ +are “nonstatic data members”. It handles parsing of bit field widths and +C++11-style initializers (see below), and calls decl_nonstatic_data_member +to create the actual IL entry (type a_field) and associated symbol (if any) +as well as to do some error checking and set various flags. [9]

    +

    Field symbols point to their corresponding IL entry and also to a field symbol +supplement that carries some additional (mostly C++-specific) information.

    +

    Processing is straightforward for ordinary fields. There are several special +cases that warrant a little more explanation, however.

    +
      +
    • +
      For bit-fields scan_fs_constant_expression is called to scan the size +specified after the colon. It scans the constant value. This constant is +then used by decl_nonstatic_data_member to perform error checking, and, in +a few unusual cases, to modify the field’s type to accommodate the +bit-field (e.g., when a signed integer kind was specified but the bit-field +is too small for a sign bit).
      +
      +
    • +
    • +
      For unnamed fields a field entry is created and added to the IL tree (the +field entry is needed when set_field_size_and_offset is called), and a +symbol is created for it (see unnamed_field_symbol in +symbol_tbl.c). The space allocated by the unnamed field is represented +as a gap left in the layout of the class.
      +
      +
    • +
    • +
      Anonymous union “parent fields” have no names, but they do have an +associated symbol and a field entry in the IL. In addition, +check_anonymous_union_symbols is called both to do error checking and +to promote the symbols for the fields of the anonymous union into the name +scope of the class of which the anonymous union is a member field. This +produces an inconsistency between the IL representation, which is that of +any nested union, and the symbol table representation, where the names of +the fields of the anonymous union are treated as though they were declared +in the containing class – for example, the parent class of the promoted +sk_field symbol is the containing class, but the IL field entries to +which it points continues to be represented as a member of the nested +anonymous union.
      +
      +
    • +
    +

    In addition to actually doing error checking, decl_nonstatic_data_member +also sets some flags in the symbol to facilitate error checking and other +processing at a later time. For instance, if the field’s type is a reference +type, any_ref_member is set in the class symbol supplement; the setting can +then be checked to determine whether the compiler can generate a default +constructor.

    +
    +
    +

    11.5.2. Offset and Alignment#

    +

    The front end is configurable to use either of two models for assigning offsets +to fields. Either a class is laid out so that the fields are allocated exactly +in the order in which they are declared, or else they are grouped by access, +with first the public fields allocated in order of declaration, then the +protected and finally the private fields.

    +

    Processing for both models is done by set_offsets_for_fields, called from +do_class_layout in layout.c. For each field it calls +set_field_size_and_offset, which takes as input offset values left over +from the previous allocation and uses them to allocate the current field. The +maximum alignment required for the structure as a whole is also tracked. The +computations are done in increment_field_offsets, which does overflow +checking on all calculations.

    +

    By default, fields are assigned offsets in declaration order; the other +model is activated by setting +TARG_FIELD_ALLOC_SEQUENCE_EQUALS_DECL_SEQUENCE to 0. However, at +this time only the default allocation model is supported by the IL lowering +pass.

    +
    +
    +

    11.5.3. Field Initializers#

    +

    C++11 allows a field initializer (also known as a DMI – default member +initializer – or, previously, an NSDMI – non-static data member +initializer) to be specified on a field declaration. For example:

    +
    struct S {
    +  int i = init_val;
    +  static int init_val;
    +};
    +
    +
    +

    The initializer must be parsed in the context of the completed class (which, +e.g., means a field initializer can make use of a member that is declared at a +point that is lexically after the initializer). To achieve this, +scan_nonstatic_data_member caches the initializer for later parsing. In +the case of nontemplate classes, this later parsing is handled by recording a +fixup entry (by calling record_inclass_initializer_fixup) which is later +processed by a call to inclass_initializer_fixup (when the class is +completed), and that in turn calls field_initializer (in decl_inits.c) +to actually parse and record the initializer. For template classes, the +initializers are not parsed until they’re needed. If a field initializer of a +template class must be accessed by the front end, it must call +instantiate_field_initializer_if_needed prior to examining the IL for that +initializer (recorded in a_field::initializer). In the template case also +field_initializer is the routine that performs the actual parsing of the +initializer.

    +

    Field initializers are subject to various error checks. One of the more subtle +checks in this context is for circular dependencies: The initializer for a +field may depend on that field’s value in various indirect ways. The front end +will diagnose this if the circularity affects compile-time evaluation +(particularly, when dealing with constexpr constructors).

    +
    +
    +
    +

    11.6. Static Data Members#

    +

    decl_static_data_member is called to process declarations of static data +members. It creates a variable entry (typically with sc_extern storage +class – it will later be changed to sc_unspecified if it is defined in the +current translation unit) and appends it to the variables list of the IL +scope entry for the current class. It also creates a symbol entry of kind +sk_static_data_member and enters it into the symbol table.

    +

    When a static data member of integral type is declared as const-qualified +and an initializer appears in the in-class declaration, it is usable as a +member constant. The initializer expression is scanned by +scan_member_constant_initializer_expression, and the variable is flagged +with is_member_constant set to TRUE.

    +

    Definitions of static data members, with optional initializer, are handled as +part of normal declaration processing, where define_static_data_member is +called from function_definition. Aside from setting a few flags, little +needs to be done except some error checking.

    +
    +

    11.6.1. C++/CLI Static Data Members#

    +

    Static data members of C++/CLI managed classes can have an initializer when +they’re first declared in the class, and that declaration is then considered to +be a definition. Unlike standard static data members, there are no type +restrictions for this in-class initialization to be permitted and any +initializer that would be allowed in namespace scope can be specified.

    +

    Furthermore, such initializers are by default not processed until the complete +class definition has been seen [10]. This parallels the standard treatment +of in-class function definitions and in-class default arguments. However, if +the value of the static data member is needed to evaluate a +constant-expression, the initializer is processed at that point (i.e., early; +see ensure_inclass_static_member_constant_initializer_is_scanned).

    +
    +
    +
    +

    11.7. Member Functions#

    +

    decl_member_function is called to complete processing a member function +declaration, but the work has already been started by function_declarator, +which needs to recognize member function declarations for two reasons:

    +
      +
    • +
      Default arguments in parameter declarations are not passed to +expression-scanning routines immediately; rather, the tokens are cached and +scanned only once the entire class declaration has been completed.
      +
      +
    • +
    • +
      After the parameters have been scanned, an optional const or +volatile qualifier may be present on nonstatic member functions. And +whether the qualifier is there or not, the type of the implicit this +parameter is determined in function_declarator and the routine type +supplement for the member function’s routine type entry is updated +accordingly.
      +
      +
    • +
    +

    Consequently, even before decl_member_function is called, quite a bit of +processing has been done on member functions. What remains is to create a +symbol entry and a routine entry for the member function, add the symbol to the +symbol table, and append the routine entry to the routines list of the IL +scope entry for the current class. Some special processing is required for +overloaded functions, for virtual functions, for constructors and destructors, +for user-defined conversions, and for operator functions. The field +special_kind of a_routine entries identifies special member functions +(like constructors, destructors, operators, C++/CLI accessors, etc.); it is set +to sfk_none for ordinary member functions (and non-member functions).

    +
    +

    11.7.1. Static vs. Nonstatic#

    +

    As noted above, a nonstatic member function receives special treatment in +function_declarator: the implicit_this_param_type field of the routine +type supplement is updated with a pointer to the (optionally qualified) class +of which the function is a member. In a static member function this pointer +remains NULL. This is the only way static and nonstatic member functions are +distinguished in the IL. routine_type_is_nonstatic_member_function is a +macro that is available to test the field.

    +
    +
    +

    11.7.2. Overloading#

    +

    Function overloading is a matter for name lookup only – that a function is +overloaded is not explicitly represented in the IL. The general technique for +supporting function name overloading with sk_overloaded_function symbols is +discussed in detail in the chapter on the Symbol Table.

    +

    Entering a new member function symbol in a way that takes overloading into +account is handled by symbol_for_member_function. One of the subroutines +it calls is member_function_redecl_sym, which checks for type +compatibility, recognizing when the type of the implicit this parameter +should be ignored and when it must be taken into account.

    +

    In addition to sk_member_function symbols, the overload set may include +sk_projection symbols representing using-declarations and +sk_function_template symbols representing member function templates.

    +
    +
    +

    11.7.3. Virtual Functions#

    +

    A member function may be explicitly declared virtual, or it may be a +virtual function implicitly, because of having the same name and type as a +virtual function from a base class. In either case, for every member function +it is necessary to go through all the base classes and look for functions with +the same name and type. Then, if the original function is virtual for either +reason, not only must it be so marked, but it is also necessary to record the +fact that a virtual function from a base class is overridden by a function from +a derived class. This, as already described in another context, is done with +entries of type an_overriding_virtual_function.

    +

    decl_member_function calls check_for_virtual_override to accomplish all +this. The latter does the search through the base classes for overridden +virtual functions, and when it finds one it calls +record_virtual_function_override to add an entry to the +overriding_virtual_functions list in the base class. When an entry that +refers to the same primary function is already there (as a result of an +override by an inherited function), that entry is updated to record the +override by the current class’s member. When more than one such entry is on +the list, the extras are removed, since the ambiguity is resolved by the +current declaration.

    +

    After all declarations of the current class have been processed, +scan_class_definition calls set_virtual_function_numbers to assign +sequential numbers to nonoverriding virtual functions declared in the current +class. (Overriding virtual functions will have already been assigned the +number of the associated base class function.)

    +

    Then it calls report_virtual_function_ambiguities, which makes another pass +over the base classes to look for ambiguous virtual function overriding – it +issues errors when such ambiguities, caused by merging overriding virtual +function lists from several base classes, are not resolved by a member function +declaration in the current class.

    +
    +
    +

    11.7.4. Default Arguments#

    +

    Default arguments specified for parameter declarations in member function +declarations require special handling, because the expressions must not be +scanned until all the member declarations in the class have been scanned. +Parameter declarations are scanned in function_declaration. When a default +argument is encountered in a member function declaration that is part of a +class definition, prescan_default_arg_expr is called to cache the tokens +that make up the expression; the cache resides in an entry of type +a_def_arg_expr_fixup, which is kept on a list pointed to by an entry of +type a_routine_fixup that is accessed from the class symbol supplement. +When the class’s member declarations are complete, that list is revisited and +the default argument expression is rescanned (see +delayed_scan_of_default_arg_expr, which is called from +delayed_scan_fixup_for_class).

    +
    +
    +

    11.7.5. Inline Definitions#

    +

    When a member function body appears within a class definition, it is handled +somewhat like default argument expressions: prescan_function_definition is +called to cache the tokens that comprise the function body (the cache resides +in an entry of type a_routine_fixup), and when the class definition is +complete, delayed_scan_fixup_for_class calls scan_function_body (in +func_def.c) to process the function body retroactively. (For constructors +that are defined inline, the constructor initializer list is included among the +cached tokens, and ctor_initializer (in decl_inits.c) is later called +to scan it.)

    +

    A somewhat special case occurs when inline definitions and default argument +expressions appear within a nested class: the language definition requires that +a reference to a name in the enclosing class be found even if that name is +declared after the nested class definition is complete. For instance,

    +
    struct Outer {
    +  struct Inner {
    +    static int f() { return i; }
    +  };
    +  static int i;
    +};
    +
    +
    +

    Since a call to Inner::f() should return the current value of Outer::i, +the body of Inner::f() cannot be processed until all the members of +Outer have been seen. Therefore the delayed scan fixup list for a nested +class is not rescanned until its outermost containing class has been completely +scanned. Only then does scan_class_definition call +delayed_scan_fixup_for_class, which in turn calls itself recursively for +nested classes before processing the tokens cached for the members of the class +passed to it.

    +
    +
    +

    11.7.6. User-Defined Conversions#

    +

    When decl_member_function is called for a user-defined conversion, it +creates an entry of type a_conversion_list_entry to record the existence of +the conversion routine in the class symbol supplement for the current class. +The entry simply points to the symbol for the user-defined conversion; all such +routines for a given class are accumulated on a linked list.

    +

    Since conversion functions are functions that convert an object of the current +class to a specified result type, the list that is created can serve as a list, +for a given source type, of all the target types for which a user-defined +conversion exists. This kind of list can be useful in selecting the +appropriate implicit cast during expression processing.

    +

    User-defined conversion functions are inherited, so after all member +declarations have been seen, the list is augmented by projection symbols for +inherited conversion functions that result in types that are not already +present in the list (see project_base_class_conversion_functions which goes +through the conversion lists for each of the direct base classes of the current +class looking for unrepresented result types).

    +
    +
    +

    11.7.7. Compiler-Generated Functions#

    +

    A default constructor or a copy constructor is created by the compiler when it +is required in a class but was not explicitly declared by the user. Likewise a +compiler-generated destructor may be needed, or an assignment operator which +effectively copies an object of a given class onto another object of the same +class. Even if one of these functions is needed, only a declaration is +generated at first, not a function body. The body is generated only when there +is an actual invocation of the function. The functions will be declared as +extern inline member functions, just as if they had been explicitly defined in +the class definition.

    +

    After all member declarations have been scanned, +check_special_member_functions is called. For each compiler-generated +function determined to be needed, it calls generate_special_function, which +creates a routine type entry and calls decl_member_function to create the +symbol and the routine entry.

    +

    reference_to_implicitly_invoked_function is called when a +compiler-generated function is implicitly invoked. If the function has no +body, define_special_member_function (in func_def.c) is called, which +in turn calls make_default_constructor_body, +make_default_destructor_body, or make_default_assignment_body. The +compiler-generated assignment function is created only when a simple struct +copy is insufficient, i.e., when memberwise copying must be done explicitly.

    +

    Trivial default constructors present a special problem. They are “trivial” +because calling them has no actual effect, so an obvious optimization is to +eliminate them. When the symbol supplement for a class has a NULL +constructor pointer, that means the implicitly declared default constructor +for the class (always present in principle) is trivial and can generally be +ignored. There is an exception, however, when the definition of a trivial +default constructor would be ill-formed: then, even though no call is put out +in the IL, a diagnostic must still be issued. Here’s an example:

    +
    class A {
    +  const int i;
    +};
    +A var;
    +
    +
    +

    Since class A is not a “POD-struct”, var is default-initialized, which +means the default constructor A::A() is supposed to be called, and calling +an implicitly-declared constructor normally triggers its definition. The call +can be optimized away since it has no effect, but the definition would be +ill-formed (because A::i is const-qualified). So to preserve the +behavior as if A::A() were called, its declaration is saved in the symbol +(see trivial_default_constructor in the class symbol supplement) and its +definition is generated at the point of implicit reference by a call to +reference_to_trivial_default_constructor in symbol_ref.c.

    +
    +
    +

    11.7.8. C++/CLI Member Functions#

    +

    C++/CLI adds several variations for member function declarations in managed +classes.

    +

    Syntactically, a static constructor is like a default constructor (i.e., with +no parameters) declared with the storage class static. The two can +coexist, but they don’t create an overload set. In expression contexts, +default construction always refers to the nonstatic constructor kind. In +declaration contexts, the static constructor is only found if the declaration +includes static (which is communicated to the lookup functions with the +flag IDL_IS_STATIC_DECL). Static constructors are the only members that +can be defined outside their parent class with an explicit storage class +specifier (and such definitions must include that static specifier).

    +

    Managed classes can contain finalizers: Their handling is completely parallel +to that of destructors. The syntax uses “!X” instead of “~X”.

    +

    User-declared accessor functions for properties and events are explained in +C++/CLI Managed Class Definitions. For trivial properties and events (which don’t +include user-declared accessors), accessors are generated by calls to +generate_trivial_accessor. Whether generated or user-declared, the +a_routine for an accessor function points to the +a_property_or_event_descr entry associated with the corresponding event or +property.

    +

    The member function modifiers sealed, abstract, and override are +accepted in both ordinary Microsoft mode and in C++/CLI mode. They can appear +after the optional const and/or volatile at the end of a nonstatic member +function declarator (see scan_microsoft_function_modifiers), but in C++/CLI +override is not optional for derived class members that override a member +in a base ref class. The modifier new is also accepted at this grammatical +location to indicated that a function does not implicitly override a virtual +base member with the same name and type.

    +

    A virtual member function can also specify specific base members it overrides +using a specifier like “= B::m, C::n” where B and C are the base +classes or interfaces whose respective members m and n are +overridden/implemented. This is called “named overriding” (in contrast to +“implicit overriding”).

    +

    Named overriding and the requirements of the override and new modifiers +are mostly handled in check_for_virtual_override and its helper functions. +These features add considerable complexity to that function.

    +
    +
    +
    +

    11.8. Member Function Templates#

    +

    scan_class_definition calls template_declaration_or_directive (in +templates.c) when a member declaration begins with the keyword +template. When the declaration designates a function template, this +results in a call to class_member_template_declaration, which in turn calls +class_member_declaration. Once processing by decl_specifiers and +declarator has been done, decl_member_function_template is called to +create the sk_function_template symbol. A routine entry is also created, +but (as with nonmember template functions) it is not added to the IL. Rather, +it is attached to the template symbol supplement and is for front-end use only.

    +
    +
    +

    11.9. Member Constant Extension#

    +

    As an extension to C++ the EDG front end allows “member constant” declarations. +[11] Member constants may be of any scalar type. For integers such a +declaration is similar to declaring a constant name in an enum declaration. +For example, instead of this:

    +
    class A {
    +  enum { MAX = 100 };
    +  int array[MAX];
    +};
    +
    +
    +

    the program may declare and use a member constant:

    +
    class A {
    +  const int MAX = 100;
    +  int array[MAX];
    +};
    +
    +
    +

    Qualified-name references to member constants (e.g., to A::MAX) are also +permitted, subject to the same access and ambiguity constraints imposed on any +class member.

    +

    class_member_declaration calls decl_nonstd_member_constant to process +such a declaration. It adds to the IL an entry of type a_constant (it is +appended to the constants list of the IL scope associated with the current +class), and it enters an sk_constant symbol that points to it. Note that a +member constant is not equivalent to an initialized const static data +member, which is represented as a variable in the IL.

    +
    +
    +

    11.10. Friend Declarations#

    +

    A friend declaration involves (1) a class which gives friend access to +nonmembers and (2) the routine or class to which that access is given; and so +one may refer to the former as the befriending class and the latter as the +befriended routine or class.

    +

    The class type supplement of the befriending class contains pointers +(friend_routines and friend_classes) to linked lists of entries +identifying the routines and classes to which friendship is given. This +corresponds to the way in which a friend declaration actually appears in the +source.

    +

    In addition, the befriending-befriended relationship is represented the other +way around as well, with the befriending class also recorded in the befriended +routine or class. Specifically, routine entries have a pointer to a list of +entries that point to classes; the linked list identifies the befriending +classes, those that afford friend access to the specified routine. A +similar befriending_classes field can be found in the type supplement for a +befriended class.

    +

    decl_friend_function is called by class_member_declaration to process a +friend function declaration. For a member function +member_function_redecl_sym is called to get the symbol; otherwise, +decl_routine in decls.c is called (where, if this is the first +declaration of the function, the symbol will be created in the appropriate +non-class scope). Once the symbol is retrieved, the current class is recorded +as a befriending class in the routine entry.

    +

    decl_friend_class is called to process a friend class declaration. +This is just a matter of recording the current class as a befriending class in +the type supplement of the befriended class.

    +

    A class- or namespace-qualified friend declaration must refer to a +previously declared entity, but it may be that the first declaration of an +entity is an unqualified friend declaration. The lookup for an +unqualified friend declaration begins in the innermost enclosing +nonclass scope and continues to (but no farther than) the innermost +enclosing namespace scope, and if it is not found a declaration is +“injected” into the innermost enclosing nonclass scope. [12] For +instance:

    +
    namespace N {
    +  class S {
    +    friend void f();
    +    /* ... */
    +  };
    +  void f() { /* ... */ }   // Same "f" as declared a friend by N::S
    +}
    +
    +
    +

    This approach is taken even when the specified name is visible in a scope +enclosing the innermost namespace scope – in the above example, f would be +injected into namespace N even if a ::f were visible.

    +
    +
    +

    11.11. Using Declarations and Access Declarations#

    +

    A using-declaration inside a class definition is processed by +member_using_declaration, which is also called when +scan_class_definition encounters a declaration that is a class-qualified +name followed by a semicolon, interpreted to be an old-style access declaration +of an inherited member. member_using_declaration performs error checking +and causes a projection symbol to be created to reserve the name in the current +class. The flag is_using_decl is set in the projection symbol, since this +is not an ordinary kind of projection and is subject to somewhat different +rules for computing accessibility; [13] it can also be added to an overload +set if it refers to an inherited member function. In addition, the declaration +is recorded in the IL by adding an entry of type a_using_decl to the scope +associated with this class, in case a symbolic debugger would need the +information (see make_using_decl indecls.c).

    +
    +
    +

    11.12. Delegates (C++/CLI mode)#

    +

    A C++/CLI delegate is a managed function object (i.e., a “callable” object) +that encapsulates an invocation list. A delegate type is introduced by a +delegate definition, which looks like a typedef for a function type where the +keyword typedef is replaced by a context-sensitive keyword delegate. +The front end represents a delegate type as a mostly ordinary ref class type +synthesized from the signature provided in the definition. For example, a +definition like

    +
    delegate void D(System::Object^);
    +
    +
    +

    causes the front end to synthesize (in create_cli_delegate_definition) +a ref class called D, implementing the interface +System::MulticastDelegate with (among others) a member function called +Invoke with the signature of the delegate definition (to which “calls” +of delegate objects are dispatched), a constructor, and static member +operators + and - (to add or remove targets from the encapsulated +invocation list).

    +
    +
    +

    11.13. Properties and Events (Microsoft and C++/CLI modes)#

    +

    Microsoft C++ includes a notion of “property” members for (otherwise +standard) class types. Syntactically, this is a field declared with an +attribute of the form __declspec(property(get=func_name1, +put=func_name2)). The result is not really a field: No storage +is allocated for it, but every “read” operation on the pseudo-field is +mapped to a call of func_name1 and every “write” operation is mapped to a +call of func_name2 (either operation name may be omitted from the +attribute to create a read-only or write-only property). The IL +representation of this kind of property members uses a_field entries, +which point to entries of type a_property_or_event_descr, and those +entries in turn record the name of the specified get and/or put functions. +func_name1 and func_name2 are looked up at every point that requires +their use, which may not always yield consistent results. Therefore, the +rewriting of property-field accesses is done right away in the front end +proper (and not, for example, in a later lowering pass since the symbol +table might have changed by then).

    +

    C++/CLI provides a similar notion of properties for managed class types, but +instead of indicating the “accessor functions” (named get and set in +this case) by name in an attribute, they are part of the property definition +syntax. For example:

    +
    ref struct RS {
    +  property int p { int get(); void set(int); }
    +};
    +
    +
    +

    The IL representation is similar to that of the first kind of property (i.e., +the non-C++/CLI variant described above), but since the accessor functions are +independent from the point of use in this case, the corresponding a_routine +entries are pointed to directly from the a_property_or_event_descr entry +and vice versa. Also, since C++/CLI properties can be static or nonstatic, +their representation can be entries of type a_field and a_variable (the +latter corresponding to a pseudo-static-data-member).

    +

    C++/CLI properties can be “indexed” to model a sort of “array field” (but +unlike regular fields, indexed properties can be truly multidimensional). +Furthermore, such indexed properties can be overloaded:

    +
    ref class RC {
    +  property double ip[double, int] {
    +    double get(double, int);
    +    set(double, int, double);
    +  }
    +  property float ip[float, int] {
    +    float get(float, int);
    +  }
    +};
    +
    +
    +

    Because of this possibility, the symbol representing a property in a class has +a kind sk_property_set, which reflects that it potentially represents a set +of properties (unlike function symbols, there is no separate symbol kind for +single properties and overloaded sets). sk_property_set symbols point to a +structure of type a_property_set_symbol_supplement, which in turn points +both to the associated pseudo-data-members (sk_field or +sk_static_data_member) and to the overload sets formed by their get and +set accessors respectively.

    +

    Indexed properties can have the name default: Applying a subscript to such +a property’s parent object amounts to a use of such a property (this has some +similarity to the more traditional operator[]). If any such +default-indexed properties are present in a class, the corresponding +sk_property_symbol is pointed to from the class’ symbol supplement.

    +

    C++/CLI has a notion of “event” members. These are similar to C++/CLI +properties, but they cannot be indexed, must have handle-to-delegate type, and +they allow only three operations: +=, -=, and “call”. An event +definition can declare up to three accessors (matching the aforementioned three +operations) called add, remove, and raise, or it can be “trivial” +(in which case those accessors are generated by the front end). Since events +cannot be indexed, they cannot be overloaded, and no separate symbol kind is +needed for them: They’re simply associated with the sk_field or +sk_static_data_member symbol for their pseudo-data-member.

    +
    +
    +

    11.14. Class Object Layout#

    +

    Laying out the storage for a class means computing the overall size of an +object of that type and assigning to each of its components an offset +representing its position in the object. Nonstatic data members are +represented by entries of type a_field, each of which has an offset +value that represents the byte offset from the beginning of the object and a +offset_bit_remainder value (nonzero for bit fields only) that represents +the additional bits that must be taken into consideration if the field is not +aligned on a byte boundary. Base classes have an offset field that +contains the byte offset from the beginning of storage for the class as a whole +to the beginning of storage for the base class’s data section; for virtual base +classes there is also a pointer_offset field, which is the offset of the +pointer to the data section. The class type supplement also has a +virtual_function_info_offset field. All these offset values together make +up the abstraction we refer to as the class’s layout.

    +
    +

    11.14.1. Object Layout Models#

    +

    The front end provides by default two distinct object models: a “classic” model +based on the original cfront implementation and a more modern “IA-64” model +based on specifications drafted by a group of vendors for the 64-bit Itanium +Architecture of Intel. At the time of this writing, the latter specifications +can be found at:

    +
    +
    +

    The implementation of both models can be found in layout.c. Where +convenient, the same routines are used to implement the two models (e.g., there +is only one do_class_layout function).

    +

    The front end can also be configured to implement small variations of both the +cfront-like and IA-64 models. For the cfront-like model, increased +compatibility with the original cfront implementation can be achieved by +setting CFRONT_OBJECT_CODE_COMPATIBILITY to TRUE (this involves routines +whose names start with cfc_). Similarly, by setting +DEFAULT_EMULATE_GNU_ABI_BUGS to TRUE, improved compatibility is achieved +with the default IA-64-based ABI implemented by GNU C++ 3.2 (and this involves +routines in layout.c whose names start with the gnu_ prefix).

    +
    +
    +

    11.14.2. General Layout Steps#

    +

    All classes are laid out in the same general way, following this pattern (in +the sequence indicated):

    +
      +
    • +
      First, in the IA-64 model, storage is reserved for the so-called primary +base class (if it exists) or for a pointer to a virtual table (if the +class is polymorphic without having a primary base):
      +
      +
        +
      • +
        There is no primary base class concept in the cfront-like object model.
        +
        +
      • +
      • +
        The primary base class shares a “virtual pointer” at offset zero with the +complete class. Usually, the primary base class is a nonvirtual direct +base class, but it can also be indirect and/or virtual in less common +situations. If none of the base classes are polymorphic, the derived +class has no primary base class. The primary base class is also pointed +to from the class type supplement (by the field primary_base_class).
        +
        +
      • +
      • +
        No storage is allocated for non-primary virtual bases of the primary base +class at this point.
        +
        +
      • +
      +
    • +
    • +
      Next, storage is allocated for all the remaining direct base classes +(which implicitly includes storage for nonvirtual indirect base +classes as well):
      +
      +
        +
      • +
        In the cfront-like model, when the direct base class is also virtual, +only enough space is set aside for a pointer to the actual storage, +which appears later. In the IA-64 model, no such pointer is used and +– unless it is also the primary base – the direct virtual base is +allocated later on.
        +
        +
      • +
      • +
        In the case of a nonvirtual direct base class, enough storage is set +aside for its own primary base class (if any), its nonvirtual base +classes, its virtual base class pointers (in the cfront-like model), its +own fields, and its virtual function information, but no space is +allocated for its virtual base classes.
        +
        +
      • +
      • +
        In the cfront-like model, nonvirtual direct base classes that are empty +(no own or inherited nonstatic data members and no virtual functions or +direct or indirect virtual base classes) are allocated in a separate pass +when targ_optimize_empty_base_class_layout is TRUE. In the IA-64 +model, direct empty bases are allocated in the same pass as nonempty +bases. (See The Empty Base Class Layout Optimization).
        +
        +
      • +
      +
    • +
    • +
      Next, storage is reserved for the class’s own fields.
      +
      +
    • +
    • +
      Next, in the cfront-like model, storage for virtual function information +(typically, a pointer to a virtual function table).
      +
      +
    • +
    • +
      Finally, storage for its virtual base classes, with space enough in each +case for its own primary and nonvirtual base classes, virtual base class +pointers (cfront-like model only), fields, and virtual function +information.
      +
      +
    • +
    +

    The storage and alignment for all the items but the last are recorded in the +class’s type supplement as size_without_virtual_base_classes and +alignment_without_virtual_base_classes; the size and alignment +fields of the type entry itself record the values for the entire object. +Except in an incomplete type, both size values will be at least 1.

    +

    This general sequence is implemented by do_class_layout, which is called by +scan_class_definition once all the members have been scanned. +do_class_layout calls several subroutines:

    +
      +
    • +
      set_offsets_for_nonvirtual_base_classes to assign the offsets for +nonvirtual base classes;
      +
      +
    • +
    • +
      set_offsets_for_fields to set the offset and +offset_bit_remainder values of each field;
      +
      +
    • +
    • +
      set_offset_for_virtual_function_info to record the position at which +(typically) the virtual function table pointer will be found;
      +
      +
    • +
    • +
      set_offsets_for_virtual_base_classes to lay out the part of the class +object where the data sections of virtual bases classes are kept; and
      +
      +
    • +
    • +
      set_offsets_for_indirect_base_classes to record the offsets of indirect +nonvirtual base classes (this phase is really just a fixup pass – no new +storage is reserved).
      +
      +
    • +
    +
    +
    +

    11.14.3. The Empty Base Class Layout Optimization#

    +

    The C++ language specifications allow an implementation to allocate an empty +base subobject at the same location as another subobject provided this does not +cause two objects or subobjects of the same type to be allocated at the same +address. For example:

    +
    struct E {};
    +struct A: E { char c; };
    +struct B: E { E e; };
    +
    +
    +

    In A, the base class E can be allocated at the same offset as the field +c, but in B the optimization cannot be applied because two subobjects +of the same type (the field and the base) would occupy the same address.

    +

    In the cfront-like model, the front end implements this optimization when +targ_optimize_empty_base_class_layout is TRUE and most of the required work +is performed in set_offsets_for_empty_nonvirtual_base_classes. The +cfront-like optimization heuristic uses a two-pass algorithm:

    +
      +
    • +
      First the direct nonvirtual nonempty direct base classes are allocated as +usual; i.e. empty base classes are skipped.
      +
      +
    • +
    • +
      Next, an additional pass is made in +set_offsets_for_empty_nonvirtual_base_classes to place the direct +nonvirtual empty base classes. The first offset to be attempted is the +origin of the object (i.e., zero). If a situation is detected that +would cause two subobjects with the same type to be allocated at the +same offset, a new offset is sought after the next allocated base (if +one is available). This is repeated for every empty base – without +backtracking the offset – until there are no more empty bases.
      +
      Another example illustrates how the second pass is a single pass (i.e., +the offset if not backtracked):
      +
      +
      struct E1 {}; // Empty
      +struct E2: E1 {}; // Empty
      +struct E3 {};
      +struct B { E1 e; } // Not empty
      +struct D: E1, E2, E3, B { char c; };
      +// Layout:
      +//   B : this+0. (a nonempty base is allocated in the first pass)
      +//   E1: after B because at this+0 it conflicts with B::e.
      +//   E2: at least one byte farther than direct base E1 because else
      +//          E2::E1 conflicts with base E1.
      +//   E3: same offset as E2 since there is no type conflict; there is,
      +//       however, no backing up to the offset of direct base E1.
      +//   c : same offset as E2 and E3.
      +
      +
      +
      +
      The optimization can only be applied to empty base classes and not to empty +(nonstatic) data members. Hence, B cannot be considered empty in this +last example.
      +
      +
    • +
    +

    In the IA-64 model, empty base classes are allocated in the same pass as other +direct nonvirtual base classes. In this case the heuristic is different: If +the base can be allocated at offset zero without causing a conflict with a +subobject that has already been allocated there, then that is where the empty +base class is allocated. Otherwise, it is allocated at the next available +offset. Every time a base class is allocated (whether empty or not), +base_subobject_conflict is called: If a conflict is detected, the +allocation is retried at the next alignment boundary. This process is repeated +until there is no conflict. A similar process is needed for the first field +(to avoid having an empty base of a field end up at the same offset as an empty +base of the complete class).

    +

    The IA-64 model also handles the concept of a nearly-empty base class: This +is a virtual base class whose storage requirement is limited to a virtual table +pointer and (optionally) its own virtual base classes. Such a class can be +selected as a primary base class, in which case it is allocated at offset zero.

    +
    +
    +
    +

    11.15. Deferred Class Fixup#

    +

    As mentioned above, default arguments, inline member function bodies, and field +initializers are not processed until the entire class definition has been seen; +and when the class is a nested class, the processing is deferred until the +definition of the outermost containing class has been completed.

    +

    However, it gets even more complicated when templates are involved. Consider +this example:

    +
    template <class T> class A {
    +  void f(T* = new T) { ... }
    +};
    +class B {
    +  A<B> x;
    +} b;
    +
    +
    +

    Here, the instantiation of A<B> is kicked off before the definition of +B has finished, but the default argument expression for A<B>::f(B*) +requires that B be complete.

    +

    To accommodate cases like this, the default argument and inline function body +processing is deferred until all pending class definitions have completed. +(The definition of B is pending when the definition of A<B> is +finished, so the fixup for the latter is deferred.)

    +

    scan_class_definition calls +process_deferred_class_fixups_and_instantiations, and if global variable +pending_class_definitions is zero, +process_deferred_instantiation_requests (in templates.c) and +process_deferred_class_fixups are called.

    +

    The latter calls delayed_scan_fixup_for_class, which scans the token caches +saved for default arguments and function bodies. First it pushes a class +reactivation scope. Then, for default arguments it pushes a function prototype +scope and calls delayed_scan_of_default_arg_expr (or, for class template +instances, delayed_scan_for_function_template_default_args). For function +bodies it calls scan_function_body – except that the scanning of inline +member function bodies inside a class template instance is further deferred +until the member function has actually been referenced.

    +

    A similar mechanism is also used to delay processing of in-class initializers +for nonstatic data members in C++11 mode and of static data members of C++/CLI +managed classes; see record_inclass_initializer_fixup and +inclass_initializer_fixup_for_class.

    +
    +
    +

    11.16. Class Linkage#

    +

    Like functions and variables, a class has linkage recorded in the +source_corresp.name_linkage field of its type entry. Ordinarily (i.e., +except in cfront-compatibility mode), when a class is first created, it is +given external linkage by default, except for local classes (which have no +linkage) and classes declared inside an unnamed namespace (which have internal +linkage). This setting in turn determines the linkage and storage class +applied to class members.

    +

    In cfront mode, however, when a class is first created, it is given internal +linkage by default, and, since the class and its members are supposed to have +the same linkage, its members also have internal linkage (and correspondingly a +storage class of static). These are provisional settings, however, since +the presence of a non-inline member function or a static data member requires a +class to become externally linked. Moreover, if a class is referenced in a +declaration of an externally linked entity, it needs to have external linkage. +Thus, at the end of translation unit processing check_class_linkage is +called (in cfront-compatibility mode only) to make a pass over all the classes +defined in the translation unit and, where appropriate, to fix up the linkage +and storage class of classes and their members.

    +
    +
    +

    11.17. Lambdas#

    +

    A C++11 lambda expression is essentially a shortcut to define a “function +object” class and initialize a temporary object of that class. For example:

    +
    int f(int x) {
    +  auto f_impl = [x]()->int { return x*2; };
    +  return f_impl();
    +}
    +
    +
    +

    is largely equivalent to:

    +
    int f(int x) {
    +  class _Closure {
    +    int x;
    +  public:
    +    int operator()() const { return x*2; };
    +  };
    +  _Closure f_impl = (_Closure){ x };
    +  return f_impl();
    +}
    +
    +
    +

    The implementation of lambdas in the front end exploits this equivalence: When +expression processing encounters the beginning of a lambda expression, it hands +over the task of parsing the construct to scan_lambda (see +Scanning Operations). This routine calls make_closure_class, pushes +an associated class scope on the stack (after captures have been scanned – see +below), and records a synthetic a_class_def_state structure to go along +with the class definition scope. This allows the lambda to be parsed much as +if it were an in-class definition of a member function.

    +

    scan_lambda also creates the a_lambda entry and records it in the scope +stack entry for the closure class. That allows, e.g., expression and statement +processing to be aware of the lambda context. The convenience function +get_current_lambda is also useful for this purpose. The type entry for the +closure class does not itself directly point to the associated lambda (due to +memory region constraints), but its class type supplement has a flag indicating +that it is a lambda closure class type (rather than a user-defined class type).

    +
    +

    11.17.1. Explicit and Implicit Captures#

    +

    The C++11 lambda syntax allows for the optional specification of an implicit +capture mode and explicitly captured local variables and expressions (the +latter are often referred to as “init-captures”). scan_lambda_capture_list +parses this construct and records it in the a_lambda entry. Explicitly +captured variables are recorded with a call to add_lambda_capture and +explicitly captured expressions are handled by a call to scan_init_capture. +The fields associated with these explicit captures are added by a call to +decl_lambda_capture_fields (after the closure class definition scope has +been pushed and after the optional lambda declarator has been processed).

    +

    If an implicit capture mode has been specified (using the “[= … ]” +or “[& … ]” forms of the lambda capture list), +add_lambda_capture is also the routine that records the capture (it also +creates the associated field in the implicit capture case). However, in such +cases we get there via lambda_capture_for_variable, which is called from +the expression scanning routines while parsing the lambda body (ultimately, via +scan_identifier–see Scanning Identifiers).

    +
    +
    +

    11.17.2. The “Lambda Declarator”#

    +

    The syntax to describe lambda parameters, return type, and mutability is +optional and, when present, it differs from the ordinary member function +declaration syntax. Still, the function scan_lambda_declarator is much +simplified by reusing function_declarator. (function_declarator is +also used when parsing ordinary functions/operators, and is aware of the +enclosing class definition environment.) Similarly, +decl_call_operator_for_lambda – which creates the operator() member of +the closure class – mostly relies on decl_member_function and +decl_member_function_template.

    +

    For generic lambdas (a C++14 feature), the lambda declarator corresponds to the +declarator of a function template, where the template parameters are created +implicitly from the use of auto as a parameter type. For example:

    +
    [](auto p) { return p*2; }
    +
    +
    +

    creates a closure class with an operator() that is a member template +corresponding to:

    +
    template<typename _T> auto operator()(_T p) { return p*2; }
    +
    +
    +

    The front end implements this by prescanning the lambda declarator to record +information about auto parameters. If there are any such parameters, +set_up_generic_lambda_declarator_scan then proceeds to set up a member +function template declaration environment. decl_specifiers also uses the +information gathered during the prescan to map occurrences of auto in +the parameter list to the appropriate template parameter type (see +process_generic_lambda_param_type).

    +

    a_func_info_block has been augmented with a pointer to the associated +a_lambda when applicable, and some lambda-specific behaviors of +function_declarator (e.g., mutable as a function qualifier instead of +cv-qualifiers) make use of it.

    +

    If no return type is specified explicitly for the lambda, the return type is +temporarily set to the unknown type (tk_unknown). +scan_return_expression is aware of this arrangement, and it will update the +return type if appropriate. After the lambda body has been scanned +scan_lambda sets the return type to void if no return statement was +seen (through check_implicit_lambda_return_type, which also performs other +language-mandated checks if the return type was implicitly determined by a +return statement).

    +
    +
    +

    11.17.3. Scanning the Lambda Body#

    +

    The lambda body is parsed by scan_function_body as would the body of a +member function of a user-defined class type (or via +function_prototype_instantiation, in the case of a generic lambda). There +are however a few subtle differences involved for the lambda case.

    +

    First, scan_function_body is called while the class scope is still active. +This is needed so that closure fields associated with implicit captures can be +generated. So the option SFB_NO_CLASS_REACTIVATION is passed to +scan_function_body to avoid reactivating the scope of the not-yet-completed +closure class.

    +

    Second, if IL lowering is enabled, the function body is not lowered when the +associated function scope is popped. Instead, that lowering is triggered by a +call from scan_lambda to finish_function_processing_for_memory_region. +This is a consequence of the previous observation: Lowering of the member +function cannot happen when the associated member function is popped because +the parent (closure) class hasn’t been completed yet.

    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/code_style/index.html b/dev/doc/code_style/index.html new file mode 100644 index 0000000..2589b71 --- /dev/null +++ b/dev/doc/code_style/index.html @@ -0,0 +1,894 @@ + + + + + 25. Coding Style Guide - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    25. Coding Style Guide#

    +
    +

    25.1. General Whitespace Rules#

    +
      +
    • Maximum line length is 79 characters.

    • +
    • Indentation is by 2 spaces.

    • +
    • Editors should be set to use an 8 space tab width.

    • +
    +
    +
    +

    25.2. General Line Wrapping#

    +
    +

    25.2.1. General Condition Rules#

    +

    Conditions that cause the line length to exceed 79 characters are wrapped via a +line break following an operator. The continuation is left aligned with the +opening paren:

    +
    if (/* something very long */ &&
    +    /* something else */) {
    +  /* etc... */
    +}  /* if */
    +
    +if ((a || b) &&
    +    (/* something very long */ ||
    +     /* something else */)) {
    +  /* etc... */
    +}  /* if */
    +
    +if ((a || b) && (/* something very long */ ||
    +                 /* something else */)) {
    +  /* etc... */
    +}  /* if */
    +
    +
    +
    +
    +

    25.2.2. General Statement Rules#

    +

    Expressions that cause the line length to exceed 79 characters are wrapped via +a line break following an operator. The continuation is right-aligned:

    +
    int x = /* something very long */ &&
    +                        /* something else (right-aligned to column 79) */;
    +
    +
    +
    +
    +
    +

    25.3. General Line Breaks#

    +

    Line breaks are prioritized as follows:

    +
      +
    • 1 line for a conditional preprocessor directives (e.g., #if, #ifdef, etc.) +unless adding whitespace would break a visual “grouping” (e.g., conditional +inclusion of a header in a list of headers, conditionally enabling a single +statement in a function, etc.).

    • +
    • 1 line for a namespace declaration and its associated closing comments.

    • +
    • 2 lines for a function definition.

    • +
    • 1 line for a function, variable, or type declaration.

    • +
    +
    +
    +

    25.4. Naming Convention#

    +

    The EDG naming convention can be broadly described as “snake case” (with an +exception for templates). In snake case, names are composed of lower case +letters and underscores.

    +

    For types, the naming convention additionally adds a “a_/an_” +prefixed to the typename. For instance, what (in many projects) would be +spelled struct thing is called struct a_thing.

    +
    +
    +

    25.5. Writing a Variable#

    +

    Variables appearing in “global” (these technically shouldn’t exist as +there’s a conditional “edg” namespace around all file contents) or +namespace scope are indented using tabs in older files which make use of +tabs and the equivalent +(8) spaces in newer files. The type is not indented, the name is indented by +2 tabs, and a comment should be added at 3 tabs:

    +
    a_variable_type_name
    +        my_variable;
    +                /* A descriptive comment. */
    +
    +
    +

    If a variable type or name ends before the next tab stop, the lines should be +collapsed:

    +
    a_variable_type_name
    +        x;      /* A descriptive comment. */
    +int     my_variable;
    +                /* A descriptive comment. */
    +int     x;      /* A descriptive comment. */
    +
    +
    +
    +
    +

    25.6. Writing a Function#

    +
    +

    25.6.1. Parameter Alignment#

    +

    Functions declarations that fit within a single line should do so:

    +
    void foo(int a, int b, int c);
    +
    +
    +

    If a function declaration does not fit on a single line, it should be broken up +with the parameters broken up into two left-aligned columns, one column of +parameter types, and one column of parameter names:

    +
    void foo(a_variable_type        thing,
    +         an_other_variable_type other_thing,
    +         a_thingy               thingy);
    +
    +
    +
    +
    +

    25.6.2. Wrapping Function Declarations#

    +

    Particularly for function definitions with lots of qualifiers and long names +(member functions are particularly guilty), simply wrapping the parameters can +be insufficient. In these cases, there are two accepted techniques for keeping +the function within the required line length.

    +

    If the function has qualifiers like static and inline these can be +moved to the preceding line along with the return type:

    +
    static inline void
    +very_long_long_long_long_foo(a_variable_type        thing,
    +                             a_nother_variable_type other_thing,
    +                             a_thingy               thingy);
    +
    +
    +

    If this is still insufficient, the parameters can be moved to a new line and +right-aligned:

    +
    void very_long_long_long_long_long_foo(
    +                                    a_variable_type        thing,
    +                                    a_nother_variable_type other_thing,
    +                                    a_thingy               thingy);
    +
    +
    +
    +
    +

    25.6.3. Documentation#

    +

    In a function definition, a comment should be added after the closing paren but +before the opening curly brace. This comment should describe all of the +parameters, the return value, and any actions it takes, and the closing +} of the function should be followed by a comment giving the name +of the function, separated from the } by two spaces:

    +
    a_boolean foo(int num_l_parens, int num_r_parens)
    +/*
    +Given the number of left parens (num_l_parens) and the number of right
    +parens (num_r_parens), display the values and return TRUE if the
    +numbers are equivalent; otherwise, return FALSE.
    +*/
    +{
    +  printf("lparens=%d, rparens= %d\n", num_l_parens, num_r_parens);
    +  return num_l_parens == num_r_parens;
    +}  /* foo */
    +
    +
    +

    This also applies to void functions that use output parameters:

    +
    void foo(a_boolean *result, int num_l_parens, int num_r_parens)
    +/*
    +Given the number of left parens (num_l_parens) and the number of right
    +parens (num_r_parens), assign *result to TRUE if the numbers are equivalent;
    +otherwise, assign *result to FALSE.
    +*/
    +{
    +  *result = (num_l_parens == num_r_parens);
    +}  /* foo */
    +
    +
    +
    +
    +

    25.6.4. Return Value#

    +

    If a function requires a variable to hold the result, it should be the first +variable in the function, and it should be named “result”:

    +
    int foo()
    +/*
    +A descriptive comment.
    +*/
    +{
    +  int result;
    +
    +  /* etc... */
    +  return result;
    +}  /* foo */
    +
    +
    +
    +
    +

    25.6.5. Variable Grouping#

    +

    Variables should be grouped into blocks with their types and names aligned. +The first block of variables should have a trailing newline, and any following +blocks should use a preceding newline:

    +
    int foo()
    +/*
    +A descriptive comment.
    +*/
    +{
    +  int       result;
    +  a_boolean temp_state;
    +
    +  /* etc... */
    +
    +  a_state_catcher secondary_state;
    +  a_boolean       state_catcher_used = FALSE;
    +  /* etc... */
    +  return result;
    +}  /* foo */
    +
    +
    +
    +
    +
    +

    25.7. Writing a Lambda#

    +

    Lambdas are a case that’s a mix of variable and function rules. Lambda +parameters – similar to function parameters – should be broken up into two +left-aligned columns, one column of parameter types, and one column of +parameter names:

    +
    auto x = [](int num_l_parens,
    +            int num_r_parens) -> a_boolean {
    +  return num_l_parens == num_r_parens;
    +};
    +
    +
    +

    Unlike functions, lambdas do not require a documentation comment, or a closing +comment. For this reason, lambdas should be reserved for fairly trivial +operations.

    +

    If a lambda appears in a block of other variables, the lambda should follow the +name alignment of the variables in the same block, e.g.,

    +
    a_long_type_name y = /* etc... */;
    +auto             x = [](int num_l_parens,
    +                        int num_r_parens) -> a_boolean {
    +  return num_l_parens == num_r_parens;
    +};
    +
    +
    +
    +
    +

    25.8. Writing a Class#

    +

    Classes should be preceded by a descriptive comment, and terminated by a +closing comment giving the class name and separated from the ; by two +spaces:

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  /* etc... */
    +};  /* foo */
    +
    +
    +
    +

    25.8.1. Data Members#

    +

    Data members should be written at the end of the class. In terms of +indentation, data members are indented similarly to variables in global & +namespace scope, with the exception that the type is always indented by two +spaces:

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  /* etc... */
    +private:
    +  a_variable_type_name
    +                my_var_a;
    +                        /* A descriptive comment. */
    +  a_variable_type_name
    +                b;      /* A descriptive comment. */
    +  int           my_var_c;
    +                        /* A descriptive comment. */
    +  int           d;      /* A descriptive comment. */
    +};  /* foo */
    +
    +
    +
    +
    +

    25.8.2. Member Functions#

    +

    Member functions (including special member functions like constructors and +destructors) that do not exceed 1 line can be written inline:

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  void bar()
    +    { this->x += 1; }
    +private:
    +  int           x;      /* A descriptive comment. */
    +};  /* foo */
    +
    +
    +

    If the member function is empty it should be spelled “{}” (no space):

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  void foo()
    +    {}
    +};  /* foo */
    +
    +
    +

    Member functions that exceed 1 line should be written out-of-line:

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  void complex_bar();
    +private:
    +  int           x;      /* A descriptive comment. */
    +};  /* foo */
    +
    +
    +void foo::complex_bar()
    +/*
    +A descriptive comment about complex_bar.
    +*/
    +{
    +  /* etc... */
    +};  /* foo::complex_bar */
    +
    +
    +

    Additionally see Writing a Function as those rules also apply to member +functions.

    +
    +
    +

    25.8.3. Member Initializer#

    +

    If initializing using a passed value, the data members and parameters +should have names that differ (e.g., for a data member x, x_val can +be an appropriate parameter name).

    +

    Additionally, the introducing colon and all member initializers should be +indented two spaces, e.g.,

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  void foo()
    +    : x(1), y(2), z(3)
    +    {}
    +  inline void foo(int x_val, int y_val, int z_val);
    +  int           x;      /* A descriptive comment. */
    +  int           y;      /* A descriptive comment. */
    +  int           z;      /* A descriptive comment. */
    +};  /* foo */
    +
    +
    +void foo::foo(int x_val, int y_val, int z_val)
    +/*
    +A descriptive comment about foo::foo.
    +*/
    +  : x(x_val + 100), y(y_val + 1000),
    +    z(z_val + 10000)
    +{
    +  /* etc... */
    +};  /* foo::foo */
    +
    +
    +
    +
    +
    +

    25.9. Statements#

    +
    +

    25.9.1. for Statements#

    +
    +

    25.9.1.1. C-style#

    +

    “C-style” for loops should be formatted with their contents indented by 2 +spaces, and a closing comment (with two preceding spaces):

    +
    for (int x = 0; x < 10; ++x) {
    +  /* etc... */
    +}  /* for */
    +
    +
    +

    If the condition of the for loop causes the line length to exceed 79 +characters, it should be broken up at the semicolons:

    +
    for (int long_variable = 0;
    +     long_variable < another_long_variable;
    +     ++long_variable) {
    +  /* etc... */
    +}  /* for */
    +
    +
    +
    +
    +

    25.9.1.2. Range-based#

    +

    Range-based for loops should be formatted as “C-style” for loops +are, with the exception that, if the condition cause the line length to +exceed 79 characters, it should be broken at the colon and right aligned:

    +
    for (a_long_type &&x :
    +         some_container) {
    +  /* etc... */
    +}  /* for */
    +
    +
    +
    +
    +
    +

    25.9.2. if Statements#

    +

    if statements should be formatted with their contents indented by 2 +spaces. else and else if clauses should be preceded and followed by +braces, aligned with the if, and the closing brace aligned with the +if and followed by an if comment (with two preceding spaces):

    +
    if (argument) {
    +  /* something */
    +} else if (other_argument) {
    +  /* something else */
    +} else {
    +  /* default action */
    +}  /* if */
    +
    +
    +
    +
    +

    25.9.3. switch Statements#

    +

    switch statements should be formatted with their case labels indented +by 2 spaces, the contents further indented by two spaces, and the closing +brace annotated with a comment (with two preceding spaces). The opening +brace of a scoping block within a case can be immediately followed on the +same line by the first statement of the block, and its closing brace should +have no comment. If one case intentionally omits the usual closing +break statement and flows into the next, the intent should be +documented by use of the FALLTHROUGH macro. When the cases of a +switch statement are intended to cover all the enumerators of an +enumeration, the default_is_unexpected macro should be used to trigger +compiler diagnostics if an enumerator is added and not explicitly handled +by the switch:

    +
    switch (argument) {
    +  case a:
    +    { int y = 10;
    +
    +      x += y;
    +    }
    +    FALLTHROUGH
    +  case b:
    +    x += 1;
    +    break;
    +  case c:
    +    /* no-op */
    +    break;
    +  default_is_unexpected();
    +}  /* switch */
    +
    +
    +
    +
    +

    25.9.4. while Statements#

    +
    +

    25.9.4.1. Pre-condition#

    +

    “Pre-condition” while statements should be formatted with their contents +indented by 2 spaces, and a closing comment (with two preceding spaces):

    +
    while (argument) {
    +  /* etc... */
    +}  /* while */
    +
    +
    +
    +
    +

    25.9.4.2. Post-condition#

    +

    “Post-condition” (i.e., do) while statements should similarly be +formatted with their contents indented by 2 spaces. However, unlike +“pre-condition” while statements, no closing comment is required:

    +
    do {
    +  /* etc... */
    +} while (argument);
    +
    +
    +
    +
    +
    +
    +

    25.10. Preprocessor Directives#

    +
    +

    25.10.1. #if and #endif#

    +

    #if should have its closing #endif commented with the condition used +(preceded by a single space):

    +
    #if MACRO_IS_ENABLED
    +/* etc... */
    +#endif /* MACRO_IS_ENABLED */
    +
    +
    +

    If the condition is complicated, the closing comment can be abbreviated:

    +
    #if MACRO_IS_ENABLED && (OTHER_MACRO_IS_ENABLED || \
    +                         OTHER_OTHER_MACRO_IS_ENABLED)
    +/* etc... */
    +#endif /* MACRO_IS_ENABLED && (OTHER_MACRO...) */
    +
    +
    +
    +
    +

    25.10.2. #else#

    +

    If an #if makes use of an #else a comment should express the negated +condition (preceded by a single space):

    +
    #if MACRO_IS_ENABLED
    +/* etc... */
    +#else /* !MACRO_IS_ENABLED */
    +/* etc... */
    +#endif /* MACRO_IS_ENABLED */
    +
    +
    +
    +
    +

    25.10.3. #elif#

    +

    If an #if makes use of an #elif, no change to comments is performed:

    +
    #if MACRO_IS_ENABLED
    +/* etc... */
    +#elif OTHER_MACRO_IS_ENABLED
    +/* etc... */
    +#endif /* MACRO_IS_ENABLED */
    +
    +
    +
    +
    +
    +

    25.11. Templates#

    +

    Templates follow the rules of the respective thing being templated, with +the exception that the name for templates declaring a type should not +follow the normal naming convention. For class and alias templates, no +a_ or an_ qualifier is used, instead an uppercase letter starts the +name (e.g., Dyn_array).

    +
    +

    25.11.1. Template Parameters#

    +

    Template parameters, like template declarations, have their own naming +convention. They should be named a_/an_ followed by a capital +letter, and then a descriptive name, e.g.,

    +
    template<typename an_Elem>
    +struct My_template;
    +
    +
    +

    If multiple template parameters need to be denoted as the “1st, 2nd, 3rd, +etc.” version of a parameter, capital letters can be used to denote this, +e.g.,

    +
    template<typename a_Type_A, typename a_Type_B>
    +struct Thingy_helper;
    +
    +
    +
    +
    +
    +

    25.12. Special Cases#

    +
    +

    25.12.1. Pointer & Reference Types#

    +

    The rule for pointer and reference types is that the pointer or ref qualifier +accompanies the name being typed (for purposes of a function, consider the +return type the “type” of the function) e.g.,

    +
    void foo(int *result, const thingy &a)
    +/*
    +A descriptive comment.
    +*/
    +{
    +  int &c = a.value;
    +
    +  *result = c;
    +}  /* foo */
    +
    +
    +a_thingy *alloc_thingy();
    +
    +
    +
    +
    +

    25.12.2. Empty Loop Bodies#

    +

    Empty compound statements (e.g., function bodies and loop bodies) should be +spelled “{}” (no space) and follow the looping statement on the same line, +e.g.,

    +
    for (x = 0; x < y; x *= 2) {}
    +
    +while (try_op(x)) {}
    +
    +
    +
    +
    +

    25.12.3. Annotating Function Arguments#

    +

    When a function is called with an argument of a fixed value (e.g., a +TRUE or FALSE value for a “flag” argument) the argument should be +annotated with a comment naming the associated parameter, e.g.,

    +
    int chars = count_characters(str, /*include_whitespace=*/FALSE);
    +
    +
    +

    When NULL is passed, it should either follow the same convention or +be cast to the parameter’s type, e.g.,

    +
    some_func(one_thing, /*associated_thing=*/NULL);
    +other_func(something_else, (a_foo*)NULL);
    +
    +
    +
    +
    +

    25.12.4. Wrapping Function Calls#

    +

    Function calls that cause the line length to exceed 79 characters can be +handled one of two ways.

    +

    If the function call is initializing a variable, and would otherwise fit on the +line, it can be moved down a line and right aligned:

    +
    int x =
    +     my_very_long_function(a, b, c, d, e, f, g, h);
    +
    +
    +

    Otherwise, the function call should be wrapped on the arguments, aligning +continuation lines with the “(” of the function call; if there is a +single argument that cannot fit between the “(” column and the right +margin, the call should be broken after the “(” and all continuation lines +aligned with the position resulting from right-justifying the longest +argument. The exact style for wrapping the arguments is not specified, but +in general developers should, in the interest of compact code, flow as many +arguments together as will fit on each line:

    +
    int x = my_very_long_function(a, b, c, d, e, f,
    +                              g, h);
    +
    +
    +

    If arguments have some logical relation, e.g., for an area function, these +arguments can be grouped to emphasize the relation instead of flowing for +maximal compactness:

    +
    compute_area_of_points(x1, y1, z1,
    +                       x2, y2, z2);
    +
    +
    +

    In cases where the arguments are annotated with embedded comments, it may be +desirable to distribute them across multiple lines for clarity and neatness, +e.g.,

    +
    f(a, b, c, d, /*is_foo_bar=*/FALSE,
    +  /*needs_more_squirrels=*/VERY_FALSE);
    +
    +
    +

    instead of:

    +
    f(a, b, c, d, /*is_foo_bar=*/FALSE, /*needs_more_squirrels=*/VERY_FALSE);
    +
    +
    +
    +
    +

    25.12.5. Wrapping Array Subscripts#

    +

    Array subscripts that cause the line length to exceed 79 characters are +wrapped like a function call whose argument cannot fit: the line is broken +after the “[” and the continuation is right-aligned to column 79, including +the closing “]” and any punctuation that follows it:

    +
    pkdp = pragma_description_for_pragma_kind[
    +                  /* something very long (right-aligned to column 79) */];
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/cp_gen_be/index.html b/dev/doc/cp_gen_be/index.html new file mode 100644 index 0000000..aa59b92 --- /dev/null +++ b/dev/doc/cp_gen_be/index.html @@ -0,0 +1,615 @@ + + + + + 24. C++-Generating Back End - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    24. C++-Generating Back End#

    +

    The C++-generating back end is a “back end” that turns C or C++ intermediate +language back into source text in C or C++. It is designed for +source-to-source-transformation applications, i.e., processors that read in +source code, make some modifications to its meaning (e.g., adding profiling +code), and then write it out as modified.

    +

    The C++-generating back end handles C++, ANSI/ISO C, and K&R C [1]. The +output is in the same language as the input, and means the same thing, but +is not expected to be identical. At the very least, comments are +eliminated and preprocessing is done, which means #include files are +merged in, macros are expanded, and #ifs and the like are processed. +The output will match the input exactly with regard to entity names and +source line numbers (the latter by use of #line directives, if +necessary), and in the order of declarations and statements in the source. +In short, it should be possible to compile the output file with a C or C++ +compiler, execute it to get the same results as the original program, and +debug it using the original source text.

    +

    The source code for the C++-generating back end is in cp_gen_be.c; +cp_gen_be.h contains the associated declarations.

    +
    +

    24.1. Source Sequence Lists#

    +

    The C++-generating back end requires the source sequence list, which is a +construct that lists all declarations and statements of the source program in +the order of their appearance. It is optional, and must be enabled by the +configuration flag GENERATE_SOURCE_SEQUENCE_LISTS. The source sequence +list stands alongside the “normal” tree-structured intermediate language, as a +sort of table of contents for the IL tree. That is, for a program fragment +that declares variable i, function f, and variable j, the source +sequence list would be a list of three entries, pointing to the IL entries for +i, f, and j, and the tree-structured information under those +entries would provide full information on the entities.

    +

    The list is conceptually a single list that runs through the whole compilation +unit, though in actuality it is implemented by a somewhat more complicated data +structure that snakes between the file scope memory region and the function +scope memory regions. That is, however, merely the low-level representation +dictated by the restrictions on pointers between memory regions, and is hidden +by access functions, e.g., adv_to_signif_source_sequence_entry.

    +

    Some entities in the source program may be declared or defined more than once. +For example, a function can be declared and then later defined. For such +cases, one of the occurrences (the definition if there is one) is selected as +the primary declaration, and the source sequence entry for that declaration +points directly at the IL entry for the entity. For all the other +declarations, the source sequence entry on the list points to a source sequence +secondary declaration entry, which points to the IL entry for the entity and +also gives information about that particular declaration, e.g., the source +position and the specific type used (which may differ from that of the +definition by use of typedefs, array bounds, etc.).

    +

    The C++-generating back end operates by traversing the list and generating code +for each construct it encounters. A program is considered to be made up of an +alternation of declarative regions and executable regions.

    +

    In declarative regions, the C++-generating back end steps through the +entries on the source sequence list, each of which points to a declared +entity, and generates declarations. Source sequence entries for class, +struct, union, and enum types that are declared as part of some other +declaration (e.g., “struct A {int i;} x;”), called non-autonomous +declarations, are skipped over without generating a declaration for the +type, but the type is marked to be put out when encountered while putting +out the type of the containing entity (e.g., “x” above). All other +declarative source sequence entries are processed immediately.

    +

    In executable regions, the C++-generating back end steps through the source +sequence entries (a flat list) and the IL statement entries (a tree) in tandem, +and generates code for the statements.

    +
    +
    +

    24.2. Declarations#

    +

    The top-level routine for declaration processing is gen_declaration. It +calls routines like

    +
      +
    • +
      gen_variable_decl,
      +
      +
    • +
    • +
      gen_routine_decl,
      +
      +
    • +
    • +
      gen_namespace,
      +
      +
    • +
    • +
      gen_type_decl,
      +
      +
    • +
    • +
      gen_template,
      +
      +
    • +
    • +
      gen_using_directive_or_declaration, and
      +
      +
    • +
    • +
      gen_instantiation_directive.
      +
      +
    • +
    +

    gen_type_decl breaks the various type-declaration cases down as calls to

    +
      +
    • +
      gen_class_definition,
      +
      +
    • +
    • +
      gen_enum_definition, or
      +
      +
    • +
    • +
      gen_typedef_decl.
      +
      +
    • +
    +

    gen_declaration_using_type and gen_type output types in general, by +calling routines in il_to_str.c.

    +

    gen_secondary_decl handles secondary declaration source sequence entries.

    +

    gen_initializer handles initializers on variables. It calls +gen_dynamic_init to handle dynamic initialization.

    +

    gen_class_definition uses normal declaration routines like +gen_routine_decl to put out code for the class members, and also the +following, which handle special kinds of members:

    +
      +
    • +
      gen_field_decl,
      +
      +
    • +
    • +
      gen_member_constant_decl, and
      +
      +
    • +
    • +
      gen_using_declaration.
      +
      +
    • +
    +

    gen_type_decl, gen_variable_decl and gen_routine_decl include +special code to deal with declarations within class definitions. In +particular, they deal with friend declarations.

    +
    +
    +

    24.3. Executable Code#

    +

    The top-level routine for executable code processing is gen_statement. +Most statements are straightforward, but the following routines handle the more +complicated cases:

    +
      +
    • +
      gen_block_statement,
      +
      +
    • +
    • +
      gen_try_block_statement,
      +
      +
    • +
    • +
      gen_switch_statement, and
      +
      +
    • +
    • +
      gen_for_statement.
      +
      +
    • +
    +

    Expressions are handled by gen_expr, with some more complicated cases +handled by:

    +
      +
    • +
      gen_new_delete and
      +
      +
    • +
    • +
      gen_temp_init
      +
      +
    • +
    +

    The expression routines always add parentheses around expressions if there is +any chance of precedence confusion.

    +
    +
    +

    24.4. Constants#

    +

    Constants are put out by gen_constant, which calls routines in +il_to_str.c to do the actual output.

    +

    gen_initializer_constant handles initializer constants, which include +aggregate constants, ck_dynamic_init constants, and cases where a reference +is initialized from a constant, as well as the usual kinds of constants.

    +
    +
    +

    24.5. Templates and Macros#

    +

    Templates and macros are strange cases in the IL. Both are macro-like, in +that the source provides a prototype that is expanded by the front end on +each use of the construct. That means that template and macro references +are largely invisible in the IL – one sees only the expanded form and +little evidence that it came from a template or macro reference.

    +

    It is nevertheless desirable to be able to put out the template and macro +definitions in some way so that template instantiation and symbolic debugging +can be done on the generated code. To accommodate this need, the IL optionally +contains entries for templates and macros. These contain normalized textual +representations of the template or macro (e.g., a string like “#define x(a) +a+1”). The C++-generating back just puts those out verbatim. (The macro +entries are all put out at the end of the output file, so they won’t affect the +already-macro-expanded code that is put out, but they will still be available +for symbolic debuggers.) Note that macro entries are also used for #undef +directives. See gen_template and gen_macro.

    +
    +
    +

    24.6. Source Output#

    +

    The effective position for source output is set by calling +set_output_position. That will result in generation of #line +directives as necessary, but not until some text is actually output, at which +point adjust_output_position is called. Note that while line number +correspondence is maintained in the output, there is no attempt to maintain +column number correspondence, or even to do appropriate indentation.

    +

    Actual text output is done through

    +
      +
    • +
      write_ch,
      +
      +
    • +
    • +
      m_write_ch,
      +
      +
    • +
    • +
      write_space,
      +
      +
    • +
    • +
      m_write_space,
      +
      +
    • +
    • +
      write_tok_ch,
      +
      +
    • +
    • +
      m_write_tok_ch,
      +
      +
    • +
    • +
      write_tok_str,
      +
      +
    • +
    • +
      m_write_tok_str,
      +
      +
    • +
    • +
      write_unsigned_num, and
      +
      +
    • +
    • +
      write_num,
      +
      +
    • +
    +

    The names that begin with “m_” are macros and are intended for those cases +where speed is important. The others are functions. The names that include +“_tok_” are used to write complete tokens or sequences of tokens; the +low-level routines are given permission to break long output lines before or +after such text to avoid overly-long lines.

    +
    +
    +

    24.7. Troublesome Cases#

    +
    +

    24.7.1. Names#

    +

    Names are, in general, put out exactly as they appear in the IL. In some +cases, unnamed entities are given generated names. Members of classes are in +general put out as qualified names (e.g., A::x), but sometimes special care +is required:

    +
      +
    • +
      The declaration of a member within its class must not use a qualified name. +To handle this, a name context stack is maintained (see +push_name_context and pop_name_context), tracking the current +scope. When immediately within a class definition, the class qualifier for +that class is suppressed. The same thing is done for namespaces.
      +
      +
    • +
    • +
      A call of a virtual function with a qualified name suppresses the +virtual-ness of the function, so a qualified name must be used only if that +behavior is desired.
      +
      +
    • +
    • +
      In references to nonstatic members of classes (data or function), the +choice of name can have an effect on access control (e.g., for protected +members) and can disambiguate an otherwise ambiguous member name. +gen_simple_field_selection and gen_bound_function handle such +references for data and function cases, and call +optimized_expr_for_selection to determine the class to be used in +naming the member (that’s done by examining any implicit casts used in the +member selection).
      +
      +
    • +
    • +
      Sometimes, a prefix “::” or an elaborated type specifier (e.g., class +X) must be used to distinguish one name from another. One would think +that always generating those would be the appropriate (and easy) thing to +do. It turns out, however, that various compilers have bugs in that area, +and won’t accept some valid code generated in that mechanical way. As a +consequence, the C++-generating back end uses the hidden-name information +developed by the front end to generate prefix “::”, qualified names in +general, and elaborated type specifiers only when they are required. See +alloc_hidden_name_fixup et al. This processing has an additional +benefit: it handles external variables and functions that are declared +extern within a function. References to such entities must not use a +“::” prefix, because although the entity named is external, and thus in +some sense in the global scope, the name used for it is declared local to +the function.
      +
      +
    • +
    +

    See

    +
      +
    • +
      gen_name,
      +
      +
    • +
    • +
      gen_unqualified_name,
      +
      +
    • +
    • +
      gen_decl_name,
      +
      +
    • +
    • +
      gen_class_qualifier, and
      +
      +
    • +
    • +
      gen_namespace_qualifier.
      +
      +
    • +
    +
    +
    +

    24.7.2. References#

    +

    Reference types, or rather uses of entities with such types, require some +special attention. In expressions, eok_reference_to and +eok_ref_indirect occur in order to make explicit the indirection implicit +in the uses of the reference types; these operators are simply ignored when +generating the expressions.

    +

    More subtle is the fact that certain kinds of constants implicitly contain an +“address-of” operation. The ordinary processing of these by form_constant +adds an & to the output before writing the constant’s value; this & +must be suppressed when the constant has a reference type (or, more generally, +is used in an lvalue context). This special processing is provided by +handle_lvalue_constant_node.

    +
    +
    +

    24.7.3. Prototype Scopes#

    +

    Prototype scopes (scopes associated with a prototyped function declarator, in +C) cause a particular set of headaches, because while such types cannot be +named outside of the prototype scope, they do nevertheless show up in the types +of objects outside those scopes. For example:

    +
    void f(struct A {int i;} *p);
    +void g(enum E {e1});
    +main() {
    +  f(0);   /* Really f((struct A *)0) */
    +  g(1);   /* Really g((enum E)1) */
    +  return 0;
    +}
    +
    +
    +

    The C++-generating back end deals with these by noting such cases and +suppressing the explicit casts in those cases. The conversion is then once +again implicit in the output program.

    +

    See is_implicitly_cast_integral_constant.

    +
    +
    +

    24.7.4. Rewritten Property References#

    +

    References to Microsoft properties are rewritten by the front end. Something +like “p+1”, referring to a property p, might have been rewritten as +“call the get accessor function for p, add 1to it, and store the +resulting value by calling the set accessor for p.” The C++-generating back +end recovers the original source form. This is based on a field in expression +nodes called rewritten_property_reference_kind, which is set by the front +end to special values to identify certain key nodes in the expansion. See +gen_prop_event_or_op_synth_call. Event references are similarly +reconstituted.

    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/decls/index.html b/dev/doc/decls/index.html new file mode 100644 index 0000000..5c7ec21 --- /dev/null +++ b/dev/doc/decls/index.html @@ -0,0 +1,1394 @@ + + + + + 10. Declarations - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    10. Declarations#

    +

    Declaration scanning is shared among a number of files. What is specific to +class member declarations is found in class_decl.c and is discussed in the +next chapter. The remainder of declaration processing is found in decls.c, +which contains the top level routines and a number of utility functions; +decl_spec.c, which handles declaration specifiers; declarator.c, which +scans declarators; func_def.c, which contains the code to process function +definitions; and decl_inits.c, which contains the code to scan +initializers. decls.h, decl_spec.h, declarator.h, func_def.h, +and decl_inits.h contain associated declarations. In addition, code for +disambiguating C++ declarations and expressions is found in disambig.c, +with associated declarations in disambig.h.

    +
    +

    10.1. Overview#

    +

    The top level routine in declaration scanning, and in fact in the overall +compilation process, is translation_unit, which scans a series of +declarations and stops at end of file. The routine it calls is +scan_nonmember_declaration (via the older declaration interface), which +is also called for local declarations that appear within functions or blocks +(including old-style parameter declarations). (The only declarations that do +not pass through declaration are class member declarations and new-style +parameter declarations.)

    +

    Since a typical declaration looks like this:

    +
    +
    +
    decl-specifiers declarator-list ;
    +
    +
    +

    two principal elements in the structure of scan_nonmember_declaration are

    +
      +
    • +
      a call to decl_specifiers, which scans the type specifier, storage +class keyword, and so forth; and
      +
      +
    • +
    • +
      a loop to handle a comma-separated list of declarators with successive +calls to declarator.
      +
      +
    • +
    +

    There are many details, including a lot of error checking and some special +cases. But in general, after the return from declarator, one of several +routines is called (though not called directly from declaration) to do +additional processing:

    +
      +
    • +
      When a function body is present function_definition is called and the +loop is exited.
      +
      +
    • +
    • +
      decl_variable is called for declarations of variables.
      +
      +
    • +
    • +
      decl_routine is called for declarations of non-member functions without +bodies (it is also called via function_definition when a body is +present).
      +
      +
    • +
    • +
      decl_typedef is called for typedef declarations.
      +
      +
    • +
    • +
      decl_parameter is called for old-style parameter list declarations.
      +
      +
    • +
    • +
      define_static_data_member is called for C++ static data member +definitions.
      +
      +
    • +
    +

    Finally, if an initializer is present in a variable or static data member +declaration, it is scanned by a call to initializer; in cases where default +initialization may be required, def_initializer is called.

    +

    Other sorts of declarations are handled by the following (via +check_special_declaration_form):

    +
      +
    • +
      template_directive_or_declaration is called for template declarations, +template instantiation directives, and template specializations (in other +words, declarations that begin with the keyword template).
      +
      +
    • +
    • +
      namespace_declaration is called for namespace and namespace alias +declarations.
      +
      +
    • +
    • +
      nonmember_using_declaration is called for all using-declarations +except those appearing in a class definition.
      +
      +
    • +
    • +
      using_directive is called for using-directives.
      +
      +
    • +
    • +
      asm_declaration is called for declarations that begin with the keyword +asm.
      +
      +
    • +
    • +
      alias_declaration is called for C++11-style alias declarations.
      +
      +
    • +
    • +
      scan_and_record_cli_delegate_definition is called for C++/CLI delegate +definitions.
      +
      +
    • +
    +
    +

    10.1.1. Declaration Parse State#

    +

    The outline above just lists a few of the many functions involved in parsing +declarations, and many of those functions need to share various bits of state. +The principal structure tracking this state through this process have type +a_decl_parse_state. This keeps track of types (declared type, effective +type, etc.), positions (start of declaration, declarator, certain specifier +keywords, etc.), additional declarative attributes (GNU, Microsoft, etc.), and +so forth.

    +

    For declarations involving a declarator, the declared entity’s symbol, once +available, is pointed to by dps->sym where dps is a pointer to the +declaration parse state for that declaration.

    +

    In most cases the declaration parse state is initialized using the +init_decl_parse_state macro, but when multiple comma-separated declarators +are handled, the state is recycled for each secondary declarator by calling +start_secondary_declarator (which preserves and even restores state +associated with the common declaration specifiers).

    +

    a_decl_parse_state includes a field of type an_init_state to describe +the processing of any initializer associated with the declaration (although +an_init_state variables can also exist independent of a specific +declaration; see also Init Components and Init States).

    +

    The a_decl_parse_state stucture also maintains a list of “actions” +(pointers to functions accepting a pointer to that state) that should be run at +the end of a declaration; this can be useful when a local declaration element +is encountered that cannot be checked until the declaration has been more or +less completely processed. New actions can be registered by calls to +add_end_of_parse_action (they are eventually run by a call to +run_end_of_parse_actions).

    +

    The a_decl_parse_state structure is not only used by declarations handled +by scan_nonmember_declaration, but also for class member declarations, +parameter declarations, and even when parsing type names in contexts such as +casts and template arguments (through function type_name_full), which isn’t +really declaration parsing at all.

    +
    +
    +

    10.1.2. Declarations from C++/CLI Assembly Metadata#

    +

    In C++/CLI mode, the front end is able to import assembly metadata files. This +is achieved by first transforming the metadata into equivalent C++/CLI source +code, and then parsing that code. Whether metadata is imported implicitly +(because it is the core library file), explicitly through a “preusing” +command-line toption, or explicitly through a #using directive, the root +function doing the importing is import_metadata (in preproc.c). This +function sequences the following operations:

    +
      +
    • +
      It prepares a file for importing by calling make_cli_metadata_file and +import_metadata_file.
      +
      +
    • +
    • +
      If all went well, it calls generate_top_level_metadata_code, which +creates a string containing C++/CLI source representing the +declarations – but not the definitions – of the top-level entities +(which are managed class types) in the metadata file. The actual work +for this is done by the “metadata reader” implemented in +ms_metadata.cpp (a C++ file meant to be compiled only in a +Microsoft environment).
      +
      +
    • +
    • +
      Finally, the generated string is passed to +scan_top_level_metadata_declarations, which (much like +translation_unit) repeatedly calls declaration to internalize the +generated code.
      +
      +
    • +
    +

    The definitions of the generated entities [1] aren’t imported until (and +unless) they are needed. When that happens, a process somewhat similar to that +of import_metadata is performed by get_definition_of_class, but this +time routines to process definitions are called instead of declaration: +scan_cli_generic_class_definition_from_assembly_import for generic entities +(including generic delegates), +scan_cli_delegate_definition_from_assembly_import for non-generic delegate +definitions, and scan_class_definition for other non-generic class type +definition. +An imported assembly is assigned a number (the “assembly index”) and that +number is recorded in the IL representation of class and enum types loaded from +the assembly. +While processing code generated from metadata (top-level or needed +definitions), the global variable scanning_generated_code_from_metadata is +TRUE. This is used, for example, to suppress certain diagnostics that do not +apply to code generated from metadata.

    +
    +
    +
    +

    10.2. Linkage Specifications#

    +

    In C++ the first thing declaration must check for is the token extern +followed by a string literal (e.g., extern "C"). This introduces a linkage +specification, which may control a single declaration or a brace-enclosed block +of declarations. In either case linkage_specification is called. It sets +global variable def_external_linkage to describe the kind of linkage that +is to be the default for subsequent declarations, and then it calls +declaration again.

    +
    +
    +

    10.3. Declarations vs. Expressions#

    +

    Inside a function body it is sometimes difficult to determine whether something +is a declaration or an executable statement. In C the presence of a +declaration specifier keyword or a type name is sufficient to disambiguate the +cases, but in C++ it can be more complicated. Similar disambiguation problems +appear in other contexts as well. Here are some examples.

    +
      +
    • +
      a statement vs. a declaration:
      +
      +
      typedef int I;
      +I(i);              // declaration (= I i);
      +I(i)++;            // cast i to I, then increment
      +
      +
      +
    • +
    • +
      with operator new, a parenthesized type vs. a placement expression:
      +
      +
      new (int(1.5)) A   // placement
      +new (int(*  ))     // type
      +
      +
      +
    • +
    • +
      a parenthesized initializer vs. a parameter declaration
      +
      +
      struct A { /* ... */ };
      +A a(int(1));   // declare variable a (initialized by
      +               //    calling A::A() with arg 1)
      +A f(int(i));   // declare function f to take an integer
      +               //    argument and return an A
      +
      +
      +
    • +
    +

    The function is_decl_not_expr is called in cases where disambiguation is +required. This may in turn use the routines prescan_declaration, +prescan_decl_specifiers, prescan_declarator, and +prescan_function_declarator. In general, if a sequence of tokens looks +like a declaration, then it is a declaration, even if it could also be an +expression. The technique requires looking ahead as many tokens as necessary +to confirm or disprove the assumption that the token sequence is a declaration; +tokens are cached so that they can be rescanned by the caller.

    +

    Thus, in statement processing, when is_decl_not_expr returns TRUE the +tokens are scanned as a declaration (declaration is called); otherwise, the +tokens are scanned assuming that they constitute a statement.

    +
    +
    +

    10.4. Declaration Scanning#

    +
    +

    10.4.1. Declaration Specifiers#

    +

    The principal part of the code for processing declaration specifiers appears in +decl_spec.c.

    +

    decl_specifiers scans a list of type specifiers, type qualifiers, and/or +storage class specifiers, and returns (through a a_decl_parse_state object) +a pointer to a type tree. It is passed a vector of input flags (telling it +that a storage class specifier is allowed, that the declaration is of a class +member, etc.) and it returns additional information about the results of the +scan (reporting that inline was scanned, that an explicit type specifier +was present, etc.) via the a_decl_parse_state object that was passed in.

    +

    The specifiers are scanned in a loop. The simple ones are handled directly. +When enum is seen, enum_specifier is called. When class, +struct, or union is scanned, class_specifier is called; the +processing entailed in scanning a class definition (see +scan_class_definition in class_decl.c) is described in the chapter on +Class Declarations.

    +

    A typedef name may appear as a type specifier, as may a class name in C++. +Therefore, to tell whether an identifier (including a qualified name) is a type +name or a declarator, a call is made to curr_type_symbol; it returns a +symbol pointer when the identifier is a type name and NULL otherwise. Since +class name can also be a constructor name under some conditions, that case is +also checked for by is_constructor_decl.

    +

    The loop continues until it reaches something it does not recognize as a +declaration specifier. Then the accumulated information is combined to create +a type entry (see combine_type_specifiers and add_type_qualifiers, and +the output flags are set. When no type is explicitly specified, a default type +is returned; ordinarily it is int, but when the declarator is recognized to +be a constructor, the default is a reference to the class type, and for +destructors it is void.

    +

    decl_specifiers is also called to scan a set of type qualifiers only, e.g., +as part of scanning a pointer-declarator. For such cases +a_type_qualifier_set is always returned independently of the type (even +though in the usual case it is also part of the returned type). (See also +collect_type_qualifiers in declarator.c.)

    +

    The details of an enum declaration are handled by enum_specifier. +First it calls scan_tag_name (which is also called from +class_specifier) to look up the (optional) tag name and return a symbol. +When a brace-enclosed declaration follows the tag name, enum_specifier +scans the list of enumeration constant declarations, calling +scan_integral_constant_expression when a value is specified. Each +declaration is turned into a constant entry with the proper value, and all of +the constant entries are linked together under the type entry for the +enumerated type. The size of the enumerated type is also determined from the +value. [2] Note that in C++, unlike C, the types of the enumeration and its +constants are always the same.

    +
    +
    +

    10.4.2. Declarators#

    +

    Most of the code for scanning declarators is found in declarator.c.

    +

    declarator scans a declarator. It can scan either a real declarator or an +abstract declarator. It receives as input (via the a_decl_parse_state +object tracking that declaration) the type from an associated specifiers list, +and combines that type with the type information in the declarator. It also +returns a symbol locator for the name declared in the middle of the declarator. +For an abstract declarator, it returns an error locator. It takes as input a +vector of flags to direct its processing, and it returns a vector of output +flags to report results to the caller (again via the a_decl_parse_state +object).

    +

    declarator is the top-level interface and calls r_declarator, which is +recursive. Declarator processing has three parts:

    +
      +
    • +
      pointer_declarator is called to handle pointer modifiers (*) and in +C++ references (&) and pointer-to-member syntax. There can be more +than one such modifier, and each can be accompanied by one or more type +qualifiers. These are combined with the type returned by +decl_specifiers; the routines invoked to construct the new types are +make_pointer_type, make_reference_type, +make_rvalue_reference_type, and pointer_to_member_type.
      +
      +
    • +
    • +
      The middle section is either an identifier (or the place where one would +be, for an abstract declarator) or a nested declarator enclosed in +parentheses. The left parenthesis is ambiguous in an abstract declarator, +so the routine looks one token past it to disambiguate the function +declarator case from the nested declarator case. The declarator +identifier, scanned by scan_real_declarator_id, may be a simple +identifier, a qualified name, [3] a destructor name, or a token sequence +representing an overloaded operator or a user-defined conversion (such as +operator+ or operator int).
      +
      +
    • +
    • +
      The third section consists of zero or more function or array declarators, +for which calls are made to function_declarator or +array_declarator.
      +
      +
        +
      • +
        function_declarator scans the parameter list (an old-style id list, a +prototype parameter list, or void) and builds a function type. For a +top-level function type some additional information is returned in a +block called func_info, which is returned to the caller to assist +with later function processing; most notably, this includes a list of the +identifier names in an old-style id list. If the function declarator is +a prototype, and if any tags are declared in the prototype, a prototype +scope is created.
        +
        +
      • +
      • +
        array_declarator scans constant and nonconstant array dimensions (the +latter for variable length arrays in C mode and type names in new +expressions in C++).
        +
        +
      • +
      +
      +
      The processing for VLA declarations has several twists. In the ordinary +case in which a VLA declaration appears at function or block scope, a VLA +dimension entry is created and an stmk_set_vla_size statment is put +out. If the VLA declaration appears in a function prototype, then the +dimension expression may be unspecified (i.e., the[*] syntax is +accepted); this is not permitted, however, when the function prototype +belongs to a function definition, but this check is delayed till +scan_function_body. If the dimension expression is specified in a +function prototype scope, a fixup entry is created and processing is +completed in scan_function_body: once the routine’s IL scope has been +created, the VLA dimension entry can be allocated and any references to +parameter variables can be properly incorporated into the VLA dimension +expression.
      +
      +
    • +
    +

    The type information from the three sections is combined into a single type +tree. The routine that combines derived types is add_to_derived_type_list; +aside from the purely mechanical task of joining types, it also does error +checking, and calls set_type_size once all the parts of a derived type have +come together.

    +

    Information about the declarator-id is returned from declarator in a +symbol locator.

    +
    +
    +

    10.4.3. C++/CLI Type Constructs#

    +

    C++/CLI adds several type composition mechanisms: handles, tracking references, +interior pointers, pin pointers, CLI arrays, and delegates. It also adds new +class type and enum type variations.

    +

    The C++/CLI core library (which is always imported, and is usually +mscorlib.dll) defines a number of special “value class types” (e.g., +System::Int32) that map onto fundamental types (like int). When the +type scanned by decl_specifiers is such a special class type, it is +immediately replaced by the corresponding fundamental type (by a call to +fundamental_type_from_system_type). However, if a handle to a fundamental +type with a corresponding value class type is formed, the fundamental type is +replaced by the class type (through a call to boxed_type_for, which in turn +calls system_type_from_fundamental_type). Handles to enumeration type are +handled similarly: A C++/CLI value class type is created that “boxes” the +enumeration (see make_boxed_enum_type), and the handle is to that class +type.

    +

    Syntactically, handles and tracking references are like pointers and references +that use different declarator operators (”^” and “%” respectively). +They have different semantics and constraints, however. Many of the basic +constraints on their underlying types are checked in +f_check_cli_type_pointed_to.

    +

    Like handles and tracking references, C++/CLI interior pointers and pin +pointers are represented using tk_pointer entries. However, the syntax to +express interior pointers and pin pointers uses template-like angle brackets +(e.g., cli::pin_ptr<X>) instead of declarator operators. The front end +implements support for that syntax by predefining special alias templates +cli::pin_ptr and cli::interior_ptr (see +make_symbol_for_cli_interior_ptr and make_symbol_for_cli_pin_ptr) that +rely on internal __declspec attributes to form the aliased tk_pointer +type.

    +

    CLI arrays are instances of a ref class template cli::array<T, Rank = 1> +(see make_symbol_for_cli_array). Instances of this template have the flag +is_cli_array set (in their class type supplement); this simplifies, among +other things, the implementation of the function is_cli_array_type). CLI +arrays can mostly only be used via handles-to-CLI-arrays (see +check_invalid_use_of_special_cli_class_type).

    +

    A delegate is a special kind of generated reference class type that +encapsulates an “invocation list” (see Delegates (C++/CLI mode) for details). +Like CLI arrays, they can mostly only be used via handles-to-delegates.

    +

    C++/CLI function declarators can include a trailing “parameter array” (with +syntax like “void f(double, ...cli::array<double> ^p)”, where the type must +be a handle to a one-dimensional CLI array). They are akin to traditional C +variadic function arguments (“varargs”), but they are type-safe and limited to +accepting a variadic list of arguments that are all of the same type. A +parameter array is represented with a single a_param_type entry whose +is_cli_param_array flag is TRUE.

    +
    +
    +

    10.4.4. Completing the Declaration#

    +

    Once the declaration specifiers and the declarator have been scanned, it +remains to put the type and other declarative information together and generate +IL and symbol representations for the objects declared.

    +

    If typedef was seen among the declaration specifiers, decl_typedef is +called. It enters a tk_typeref type entry into the IL and an sk_type +symbol in the symbol table. In C++ it has some extra processing when the type +passed in to it is that of a tagless class or enum: the typedef name is +transferred to the class or enum type entry, and in cfront-compatibility mode +the symbol for the class is modified accordingly.

    +

    define_static_data_member is called to process the definition of a static +data member. The IL entry and symbol were created at the original point of +declaration.

    +

    Variables and routines are entered by calling decl_variable or +decl_routine, which are similarly organized functions made fairly +complicated by the need to check the declaration’s compatibility with previous +declarations of the same entity.

    +
      +
    • +
      id_linkage is used to determine whether the declared name has linkage, +and if so, to what (see find_linked_symbol, which returns a symbol if +there is a previous use in scope).
      +
      +
    • +
    • +
      qualified_name_redecl_sym is called instead of id_linkage if the +declarator is a namespace-qualified name (e.g., a friend declaration or a +namespace member definition that appears outside the scope of the namespace +to which it belongs); it also calls find_linked_symbol.
      +
      +
    • +
    • +
      find_linked_symbol not only calls the appropriate lookup routine; it +also deals with function overloading and function template specializations +(see matching_template_function in templates.c).
      +
      +
    • +
    • +
      create_external_symbol_for_linked_entity is called to find any previous +external variable or routine of the same name, even if the previous name +has since gone out of scope; it also checks that the old and new types are +compatible. decl_variable and decl_routine use this information to +decide whether to create a new variable or routine entry or instead to +reuse or complete a previous declaration.
      +
      +
    • +
    +

    “Block-extern” variables and routines have linkage and are always entered at +the file scope or namespace scope in the intermediate language, but their +symbols belong to the current scope in the symbol table (except in pcc +mode, where they are entered at the file scope in the symbol table too). When +a friend declaration introduces a new routine, its symbol is entered in the +innermost enclosing nonclass scope, and the associated routine entry is entered +in the innermost enclosing namespace scope.

    +

    In addition to deciding whether an existing symbol and IL entry can be reused +or new ones need to be created, decl_variable and decl_routine are also +responsible for checking type compatibility, storage class, and name-linkage, +and they call the routines that record cross-reference and source-sequence +information.

    +

    Functions with bodies need additional processing. function_definition +finishes the scanning of a function definition started by declaration. If +there is an old-style parameter list, the declarations are scanned through a +series of calls to declaration. Next, it calls decl_routine (for +normal functions) or define_member_function (for member functions) to +retrieve or create the function’s symbol and routine entry.

    +

    Then, scan_function_body is called. First, the scope stack is fixed up – +if the routine is a member function defined outside the class body, the scope +of the class of which it is a member is reactivated, or, if it is a namespace +member appearing outside the scope of the namespace, a namespace extension +scope is pushed – after which the routine’s own function scope is pushed.

    +

    Function parameter processing is completed within the function scope, so that +parameter variables will be entered into the symbol table correctly. A pass is +made over the linked list of a_param_type entries recorded in the function +type and the linked list of a_param_id entries created from scanning the +parameter declarations (the two lists should be in sync; the latter knows the +name of the parameter, the former only the type), and decl_parameter is +called to create the parameter variable entries.

    +

    When support for variable length arrays is enabled, a fixup is performed on any +VLA declarations that appeared in the function prototype. If the VLA dimension +expression referred to a parameter, a dummy variable is replaced with the +“real” parameter variable that has just been created. Then, the dimension +expression is copied from the file-scope memory region to the function-scope +memory region, and an entry of type a_vla_dimension is created to record it +in the IL.

    +

    If it is a constructor that is being defined, ctor_intializer is called to +scan the constructor initializer list and to enter implicit ctor-initializers; +similar processing is done for a destructor with a call to +dtor_initializer. If this definition appears in the midst of statement +processing (either because it is an inline member function of a local class or +a template instantiation), it is necessary to save the structured statement +stack and start a brand new one (see new_struct_stmt_stack). Then +compound_statement can finally be called to scan the body of the function; +the resulting statement tree is recorded in the assoc_block field of the +function’s scope entry. Before returning, scan_function_body restores the +structured statement stack and pops the various scopes off the scope stack.

    +
    +
    +
    +

    10.5. Initialization#

    +

    Initialization is a broad topic in C and C++. It includes:

    +
      +
    • +
      Setting the initial value of a variable as part of its declaration (the +traditional C notion of initialization)
      +
      +
    • +
    • +
      Initializing members and bases of a class as part of the execution of a +constructor
      +
      +
    • +
    • +
      Initializing a temporary variable as part of a cast or C99-style compound +literal
      +
      +
    • +
    • +
      Passing arguments in a function call (parameter variables are initialized +with argument values)
      +
      +
    • +
    +

    Furthermore, “default” initialization actions may be required even in the +absence of an explicit source construct, and the binding of references, while +treated as a form of initialization, involves a number of rules of its own. +Also, C++17 structured bindings are sometimes “aliases” for expressions and +those are represented as variables with a special kind of “initializer” +(although arguably those do not correspond to actual initialization).

    +

    Source file decl_inits.c is primarily concerned with declaration contexts: +Initializing variables and initializing members of classes as part of +constructor definitions (i.e., the first two bullets). It also includes the +structural handling of aggregate initialization (the traditional brace-enclosed +initializers), and that handling is also used in non-declaration contexts; +particularly, in C99-style compound literals and in various C++11-style list +initialization contexts.

    +
    +

    10.5.1. IL Representation#

    +

    The special case of a variable with static storage duration initialized with a +true constant is represented by associating the a_constant entry directly +with the a_variable entry (via the an_initializer entry embedded in the +variable entry). C++17 structured bindings for array elements and structure +fields are represented as variables with a special kind of “binding” +initializer pointing to the aliased expression (also via the an_initializer +entry). In all other cases, initialization involves a dynamic element and an +entry of type a_dynamic_init is used to represent it (see +Dynamic Initialization).

    +

    In addition, even for entities that are not initialized (or whose +initialization is “trivial”), a dynamic init entry may nonetheless be generated +to represent the eventual destruction of that entity (assuming that entity has +a nontrivial destructor).

    +
    +
    +

    10.5.2. Init Components and Init States#

    +

    It is frequently convenient in the front end to separate the parsing of an +initializer from its actual binding to a target entity. When this is done, the +parsing phase produces an “init component” (type an_init_component, defined +in expr.h). Such a component can represent either

    +
      +
    • +
      an expression, or
      +
      +
    • +
    • +
      a C99-style aggregate member designator, or
      +
      +
    • +
    • +
      a brace-enclosed list of init components.
      +
      +
    • +
    +

    (A fourth kind of “placeholder” init component exists. It represents a +point at which the parsing of a large aggregate initializer has been +suspended for later continuation. This is transparent to the routines +processing initializers because they don’t access the next pointer of +init components directly and instead use macros – like next_elem – that +automatically resume parsing when reaching one of these placeholder +entries.)

    +

    An init component that represents an expression ultimately points to an object +of type an_operand (see Operand Data Structure), as well as other information +needed for the second (“binding”) phase of initializer processing.

    +

    decl_inits.c relies on two functions from expr.c to scan init +components: scan_braced_init_list for list initializers (which in +general will return the top component of a tree representing the braced +structure), and scan_full_initializer_expr_as_component (which will +return a simple expression component). Sometimes, initializers must be +“prescanned” (to deduce the type of a C++11-style auto declaration): +The two aforementioned functions will retrieve the prescanned init +components from a cache if needed. Eventually, +free_init_component_list must be called on the top-level component +produced for every initializer.

    +

    The binding of an initializer as represented by an init component to its target +entity is generally handled by a call to convert_initializer, except for +aggregate initialization where the structure of the initializer is mapped to +that of the target type using a variety of functions (see +Aggregate Initializers) which eventually call the expr.c function +convert_initializer for the non-aggregate “leaf” elements of the aggregate +initializer.

    +

    Initializer processing shares a fair amount of information across calls to a +large number of functions. To facilitate this, the information is recorded in +a structure of type an_init_state. This is both an “input” and an “output” +device: Some fields are used to pass information down the initializer +processing functions, while others are used to return results. In particular, +some input fields inhibit the generation of IL entries +(check_validity_only) and/or the emission of diagnostics +(no_diagnostics): This is needed to handle overload resolution and template +deduction (which requires “tentative” initialization in C++11).

    +

    A declaration parse state block (a_decl_parse_state) embeds an init state +for initialization directly associated with a declaration (variable +initializers, particularly), and in that case, the embedded init state also +contains a pointer back to the associated declaration parse state block.

    +
    +
    +

    10.5.3. Variable Initializers#

    +

    Variable initializers (including initializers for static data members) are +scanned and processed by calling initializer in decl_inits.c. After +checking for errors independently of the initializer itself, and if necessary +deducing the type of the variable from the type of the initializer +(prescan_initializer_for_auto_type_deduction), the function distinguishes +four syntactic cases:

    +
      +
    1. +
      parenthesized initializers (a C++ feature; e.g., “T x(3);”),
      +
      +
    2. +
    3. +
      direct list initializers (a C++11 feature; e.g., “T x{3};”),
      +
      +
    4. +
    5. +
      traditional list initializers (e.g., “T x = {3};”), and
      +
      +
    6. +
    7. +
      simple initializers (e.g., “T x = 3;”).
      +
      +
    8. +
    +

    Parenthesized initializers for class types and for template-dependent types are +the only variations that do not use init components as an intermediate +representation of the initializer: Instead, these cases are handled by calls to +scan_class_parenthesized_initializer and +scan_dependent_type_parenthesized_initializer, respectively. The remaining +parenthesized cases (i.e., those that cannot involve a constructor and +therefore must allow for only a single parenthesized expression) are handled by +expr_direct_init_object.

    +

    Both the C++11-style direct list initialization syntax and the more traditional +list initialization syntax are handled by calls to brace_init_variable, +except that the initialization of a C++/CLI array using traditional list +initialization syntax uses a dedicated routine +aggr_init_cli_array_with_alloc. brace_init_variable calls +braced_initializer

    +

    Finally, initializations of the form “T x = expr” are handled by +expr_init_aggr_variable (for variables of class or array types) and +expr_init_scalar_variable (for scalar variables).

    +

    Structured bindings to array elements and to fields are technically not +variables (they are aliased to components of the unnamed “container” variable +for the binding), but they are represented though a_variable entries in the +front end. These entries have an initk_binding initializer kind and point +to the aliased expression. The routines +record_struct_binding_expr_for_array_element and +record_struct_binding_expr_for_field (both in expr.c) handle this +pseudo-initializers.

    +
    +

    10.5.3.1. Auto type deduction#

    +

    Some modes allow the keyword auto to be used as a type specifier. In such +cases, the actual type must be deduced from the initializer using rules similar +to those for function template argument deduction. This presents an ordering +challenge: The expression handling routines called by initializer must know +the type of the entity being initialized (e.g., to determine appropriate +conversions), but that type is not known until the initializer has been +determined. To address this, the initializer for entities declared with the +auto type specifier is prescanned (routine +prescan_initializer_for_auto_type_deduction in expr.c): That process +deduces the actual type of auto (using the same machinery as that used for +calls of function templates) and records the prescanned init component in the +a_decl_parse_state entity for the current declaration. The routines called +by initializer to scan init components are aware of this record and will +use it instead of actually scanning tokens when appropriate.

    +

    The same mechanism is also used to support the auto type specifier in +new-expressions (scan_new_operator in expr.c) and in +declarations of static const data members with in-class initializers +(decl_static_data_member in class_decl.c).

    +
    +
    +

    10.5.3.2. Default Initialization#

    +

    C++ entities of class type that are declared without an explicit initializer +are “default-initialized” – which means calling the class’s default +constructor (or, for an array, calling the default constructor for each +element):

    +
    struct A { A(); /* ... */ } a;    // a is default-initialized by A::A()
    +
    +
    +

    The routine def_initializer is called for declarations without +initializers, and it generates the default initialization if appropriate. +Default initialization is done only for variables and static data members that +are defined in the current translation unit, and not all classes are subject to +default initialization in the same way:

    +
      +
    1. +
      “POD” structs and unions (roughly, C-style structs: no non-public +members, no user-defined constructor, destructor, or assignment operator, +no base classes, no virtual functions, etc.) are never +default-initialized:
      +
      +
      struct A { int i; };     // POD
      +A a1;                    // a1 goes uninitialized
      +const A a2;              // error -- no explicit initializer
      +
      +
      +
    2. +
    3. +
      Non-POD classes with an implicitly-declared trivial default constructor +(i.e., classes for which each base class or nonstatic data member of +class type, if any, will in turn be initialized with its own trivial +default constructor) are default-initialized only when the object is +non-const:
      +
      +
      struct B { private: int i; };    // implicit trivial B::B()
      +B b1;                            // b1 is default-initialized
      +const B b2;                      // error -- no explicit initializer
      +
      +
      +
    4. +
    5. +
      Classes with an implicitly-declared nontrivial default constructor are +likewise default-initialized only when the object is non-const:
      +
      +
      struct C { int i; virtual void f(); }; // implicit nontrivial C::C()
      +C c1;                                  // c1 is default-initialized
      +const C c2;                            // error -- no explicit initializer
      +
      +
      +
    6. +
    7. +
      Classes with at least one user-declared constructor are default +initialized whether or not the object is const:
      +
      +
    8. +
    +
    +
    struct D { int i; D(); };   // user-declared D::D()
    +D d1;                       // d1 is default-initialized
    +const D d2;                 // d2 is default-initialized
    +
    +
    +
    +

    A further distinction is made between the second and third groups (classes with +trivial vs. nontrivial implicitly declared default constructor): b1 and +c1 differ in how their default initialization is implemented. A call to +the nontrivial default constructor C::C() is actually added to the IL (it +needs to deal with the virtual function info for class C), but the trivial +default constructor B::B() need not actually be called, since calling it +would have no effect. Its definition is generated in case there might be +compile-time side-effects (see reference_to_trivial_default_constructor in +symbol_ref.c), but the IL for a trivial default constructor does not appear +in the IL.

    +
    +
    +
    +

    10.5.4. Aggregate Initializers#

    +

    An aggregate type is an array type or a class type that has no user-provided +constructors. When an entity of such a type is initialized with a +braced-enclosed construct, the front end traverses the initializer structure +and the destination type’s structure mapping one onto the other. The result is +an aggregate constant (ck_aggregate), which may contain elements that are +not actually constants (i.e., ck_dynamic_init “constants”). Four cases are +distinguished:

    +
      +
    • +
      aggregate class types: handled by aggr_init_class, with help from +aggr_init_field_designator to handle C99- and GNU-style designators, +and from aggr_init_class_remainder_if_needed to represent nontrivial +initializations (in C++) of fields that have no explicit initializer.
      +
      +
    • +
    • +
      array types: handled by aggr_init_array, with help from +aggr_init_array_designator to handle designators, and from +aggr_init_array_remainder_if_needed to represent nontrivial +initializations (in C++) of array elements that have no explicit +initializer.
      +
      +
    • +
    • +
      template-dependent types: handled by aggr_init_generic_element; since +the structure of the destination type is not known in that case, the +structure of the resulting constant is entirely determined by the +brace-structure of the initializer.
      +
      +
    • +
    • +
      C++/CLI array types: handled by aggr_init_cli_array with help from +aggr_init_cli_array_level (which deals with the special rules for +deducing CLI array dimensions from the initializer when applicable).
      +
      +
    • +
    +

    The cases can be composed (e.g., an aggregate struct can contain an array of +aggregate structs), which is handled through recursion: aggr_init_element +handles the dispatching of the recursion based on the subaggregate object’s +type. Leaf entities (i.e., entities whose initialization doesn’t fall into one +of the cases above) are handled by aggr_init_simple_element. Cleanup +actions needed in case of an exception occurring during the initialization of a +leaf entity – including default initialization – is handled by calls to +record_partial_aggregate_cleanup_destruction.

    +

    The complete handling of a top-level aggregate initialization is initiated +either by a call to braced_initializer (for the initialization of variables +and static data members, compound literals, and constructor-initializers), or +by a call to prep_aggr_initializer (for all other expression contexts).

    +

    While “aggregate initializer” mainly deals with the initialization of an entity +of aggregate type with a brace-enclosed construct, it also includes the +initialization of a character array with a string literal. This can happen at +the top-level (e.g., “char str[] = "text”;”) or at a subaggregate level +(e.g., “X x = { 1, 2, "three" };”). A central routine for this aspect of +initialization is try_string_literal_init.

    +
    +
    +

    10.5.5. Constructor Initializers#

    +

    Constructor initializers can be written explicitly in the source:

    +
    struct A {
    +  int i, j;
    +  A() : i(1), j{2}  // Constructor initializers with parenthesized
    +    {}              // and braced syntax, respectively.
    +};
    +
    +
    +

    They can also be generated implicitly by the front end for class members and +base classes that must be initialized and are not explicitly initialized in the +source. (This includes, as an extreme case, constructor routines that are +front-end-generated; any needed constructor-initializers would have to be +implicit).

    +

    ctor_initializer builds the proper list of constructor-initializer entries +and attaches it to a constructor routine entry. It is called with a flag that +indicates whether or not it should attempt to scan the source construct (if +not, it just generates a default list without looking at the source).

    +

    The list generated is in the “right” order, that is, the order in which +initialization should be done, which is not necessarily the order in which the +explicit constructor-initializer clauses were written. The list contains three +parts, tracked by the a_ctor_init_block data structure: direct base +entries, virtual base entries, and field entries. Each initialization is +represented in the IL with an entry of type a_constructor_init (which in +turn points to a dynamic init entry).

    +

    The explicit clauses are scanned by calling scan_mem_initializer, which +ultimately calls

    +
      +
    • +
      scan_parenthesized_mem_init_args for parenthesized initializers (often +in turn calling scan_dependent_type_parenthesized_initializer for +template-dependent entities, scan_class_parenthesized_initializer for +class type entities initialized through a constructor call, or +expr_direct_init_object for other initializations not involving a +constructor).
      +
      +
    • +
    • +
      braced_initializer for C++11-style braced initializers.
      +
      +
    • +
    +

    Once any explicit clauses have been scanned, default initializers are generated +for any base classes and members that require them. In addition, in C++11 +mode, implicit constructor initializer entries may be generated for fields with +“field initializers” (see also Field Initializers): Such entries do not decribe +the initialization directly, but defer to the initializer recorded in the +a_field entry by setting the use_field_initializer flag to TRUE.

    +
    +
    +

    10.5.6. Destructor-initializers#

    +

    The destructor-initializers list attached to a destructor indicates any +destructions required for base classes and members of the destructor’s class. +The list is in the order in which the destructions should be done, i.e., the +reverse of the order of the list on the corresponding constructor.

    +

    Unlike in the constructor case, there is no source form for the +destructor-initializers, and therefore all the entries on the list are +front-end generated.

    +
    +
    +
    +

    10.6. Type Names in Expressions#

    +

    When a type name appears in an expression, routines that are used in +declaration processing are invoked to scan the type name.

    +

    type_name is called to scan a type that appears in a cast expression or as +an argument to sizeof. It calls [4] decl_specifiers and, for +abstractor declarators only, declarator. It returns a pointer to a type.

    +

    new_type_name is called to scan a C++ new-type-name or a parenthesized +type-name that may appear in a new expression. Only abstract declarators +are allowed, but a nonconstant bound expression is permitted for the first +array dimension.

    +
    +
    +

    10.7. asm Declarations#

    +

    asm_declaration is called when an asm keyword is encountered. A +parenthesized string literal is scanned and recorded in an entity of kind +an_asm_entry. The asm-string is not parsed or validated by the front +end – it is simply passed as-is to the back end.

    +

    In Microsoft and GNU modes, some syntax variations are accepted, and in GNU +modes, this can involve some limited validation checks.

    +
    +
    +

    10.8. Namespaces#

    +
    +

    10.8.1. Namespace Declarations#

    +

    namespace_declaration is called to process original namespace definitions, +namespace extensions, and declarations of namespace aliases.

    +

    When a namespace is originally declared, an entry of type a_namespace is +created and an sk_namespace symbol is entered in the symbol table. Then, +an sck_namespace scope is pushed, and declarations inside the namespace are +represented by symbols that are entered on the active symbol list of a given +symbol header; when the scope is popped the symbols are moved from the active +list to the inactive list. However, that namespace can be reopened again, in +which case it is an sck_namespace_extension scope that is pushed onto the +scope stack. It points to the same IL scope as the original sck_namespace +scope, but symbols that are entered within this scope are added directly to the +inactive list. This affects how name lookup is done inside a namespace +extension definition – see the Symbol Table chapter.

    +

    For both original and extending namespace definitions, once the appropriate +scope has been pushed, a loop is executed to make a series of calls to +declaration until the closing } of the namespace definition is +encountered. Then the sck_namespace or sck_namespace_extension scope +is popped off the scope stack.

    +

    Unnamed namespace definitions are a special case. For an original unnamed +namespace definition, an sck_namespace scope is immediately pushed and then +popped, a using-directive is simulated, and then an +sck_namespace_extension scope is opened. [5] In other words, an +original unnamed namespace definition that is written like this

    +
    namespace {
    +  int i;
    +}
    +
    +
    +

    is represented internally as if it were

    +
    +
    +
    namespace <unnamed> { }
    +
    using namespace <unnamed>;
    +
    namespace <unnamed> {
    +
    +
    int i;
    +
    +
    }
    +
    +
    +

    namespace_declaration also handles declarations of namespace aliases, for +which a namespace IL entry and a namespace symbol are also created. However, +in this case the namespace IL entry has its is_namespace_alias flag set to +TRUE and points not to an associated IL scope but to the namespace entry it +stands for.

    +
    +
    +

    10.8.2. Using-Directives#

    +

    A using-directive is processed by using_directive, which looks up the +namespace name and calls make_using_directive to create and enter an entry +of type a_using_decl and to “activate” the using directive in the current +scope (see add_active_using_directive in scope_stk.c). The effect of a +using-directive on the lookup algorithm is discussed in the Symbol Table +chapter.

    +
    +
    +

    10.8.3. Using-Declarations#

    +

    A using-declaration that appears in a scope other than that of a class +definition is processed by nonmember_using_declaration. [6] First it +looks up and validates the namespace-qualified or globally qualified name. +Then it enters an sk_namespace_projection symbol to represent the name +pulled into the current scope by the using-declaration.

    +

    When a using-declaration specifies the name of an overloaded function, each +member of the overload set will have its own projection symbol. An overload +set in the current scope may end up with a mix of sk_routine symbols +(declarations from the current scope) and sk_namespace_projection symbols +(referring to declarations from another scope). +conflicts_with_previous_function_decl is called to determine if a function +specified by a using-declaration is not distinguishable, for purposes of +overloading, from functions actually declared in the current scope.

    +

    An IL entry is created to represent the using-declaration (see +make_using_decl); it is available to back ends from the using_decls +list pointed to from the current scope.

    +
    +
    +
    +

    10.9. Standard Attributes, GNU Attributes, and __declspec Attributes#

    +

    In declarative contexts, the processing for standard attributes (delimited by +double square brackets) is very similar to that for GNU attributes +(”__attribute((...))”) and Microsoft __declspec(...) attributes. The +main difference (other than the delimiting tokens) is that standard attributes +have strict “appertaining rules” whereas nonstandard (GNU and Microsoft +__declspec) attributes can be placed more loosely. The standard rules are +basically that an attribute applies to the construct immediately preceding it, +except for “prefix attributes” which apply to all the entities denoted by the +declarators of the prefixed declaration. With nonstandard attributes, the +entity modified by an attribute depends on the attribute. For example:

    +
    [[noreturn]] int [[X]] f [[ nothrow ]] () [[Y]], g();    // (1)
    +#define A __attribute
    +A((noreturn)) int A((nothrow)) f() A((pure)), g();       // (2)
    +
    +
    +

    In (1), the noreturn attribute applies to the functions f and g, +and any attribute in that location would apply to those entities. The unknown +attribute X (in (1)) applies to int, nothrow applies to f, and +Y applies to the function type associated with the function declarator that +precedes it. (There are currently no standard attributes that could appear in +the locations indicated by X and Y, but the language specification does +anticipate their appertainance.)

    +

    While in (2) the noreturn attribute applies as in (1), the nothrow +attribute applies to the type of f (a function type) and the pure +attribute applies to f itself. Furthermore, the locations of the +nothrow and pure attributes can be interchanged with no change of +meaning.

    +

    The principal routines for parsing and applying attributes are described in +detail Pragmas and Attributes. For attributes that apply to +declarations, the attribute application “callback” functions can rely on the +assoc_info field of the attribute entry pointing to the +a_decl_parse_state structure for that declaration.

    +
    +
    +

    10.10. Microsoft Attributes#

    +

    In Microsoft mode, Microsoft attributes delimited by single brackets are +accepted. Attributes may, in general, be specified where a declaration is +accepted. In particular, they are accepted in namespace scopes, class scopes, +and in function parameter lists. Attributes have the form:

    +
    [attribute_name]
    +[attribute_name(args)]
    +
    +
    +

    When the bracket that begins an attribute is encountered, +scan_microsoft_attributes is used to scan the attributes and create the IL +entries used to represent them. A list of attributes is returned. This list +is later passed to one of the following routines that either add the attributes +to the IL or issue the appropriate diagnostics if the attributes appear in +invalid locations:

    +
    apply_microsoft_attributes
    +verify_standalone_attributes
    +dispose_of_unapplied_attributes
    +
    +
    +

    The attribute scanning routines use an attribute description data structure to +describe the attributes that should be recognized and to describe the argument +lists expected by those attributes. When the +RECOGNIZE_MICROSOFT_ATTRIBUTES macro is TRUE, the front end supplies +attribute descriptions for the documented Microsoft attributes. When +SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING is TRUE, the Microsoft attributes +are recognized in the sense that no “unrecognized attribute” warning is issued, +but they are otherwise treated as unrecognized attributes (see below).

    +

    Each attribute is represented by an entry of type an_ms_attribute. The +entry contains a string representation of the attribute. In addition, a +structured representation is also created for recognized attributes. In the +structured representation, each attribute has a list of associated argument +values. The argument values are checked to verify that they match the kind of +value expected for a given argument (e.g., for a boolean parameter the value +must be true or false). When processing an unrecognized attribute, no semantic +checking of argument values is performed and no checking is done to verify that +a given attribute is used in an acceptable location.

    +

    Attribute processing results in a list of attribute IL entries, and a flag +in the source correspondence that indicates that attributes apply to a +given entity (see the Intermediate Language chapter for more +information). The source correspondence flag is only available when the +structured attribute representation is being used. Beyond the error +checking described above, no additional semantic processing of attributes +is performed. For example, no code insertion is performed for the COM +attributes.

    +

    C++/CLI makes use of the same attribute syntax. Currently, however, no +C++/CLI-specific attributes are recognized (and as a consequence no associated +semantics are implemented).

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/err_msgs/index.html b/dev/doc/err_msgs/index.html new file mode 100644 index 0000000..655543d --- /dev/null +++ b/dev/doc/err_msgs/index.html @@ -0,0 +1,23323 @@ + + + + + 19. Error Messages - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    19. Error Messages#

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    0001

    +
    last_line_incomplete:
    +
    last line of file ends without a newline
    +
    +

    0002

    +
    last_line_backslash:
    +
    last line of file ends with a backslash
    +
    +

    0003

    +
    include_recursion:
    +
    #include file “xxxx” includes itself
    +
    +

    0004

    +
    out_of_memory:
    +
    out of memory
    +
    +

    0006

    +
    comment_unclosed_at_eof:
    +
    comment unclosed at end of file
    +
    +

    0007

    +
    bad_token:
    +
    unrecognized token
    +
    +

    0008

    +
    unclosed_string:
    +
    missing closing quote
    +
    +

    0009

    +
    nested_comment:
    +
    nested comment is not allowed
    +
    +

    0010

    +
    bad_use_of_sharp:
    +
    “#” not expected here
    +
    +

    0011

    +
    bad_pp_directive_keyword:
    +
    unrecognized preprocessing directive
    +
    +

    0012

    +
    end_of_flush:
    +
    parsing restarts here after previous syntax error
    +
    +

    0013

    +
    exp_file_name:
    +
    expected a file name
    +
    +

    0014

    +
    extra_text_in_pp_directive:
    +
    extra text after expected end of preprocessing directive
    +
    +

    0017

    +
    exp_rbracket:
    +
    expected a “]”
    +
    +

    0018

    +
    exp_rparen:
    +
    expected a “)”
    +
    +

    0019

    +
    extra_chars_on_number:
    +
    extra text after expected end of number
    +
    +

    0020

    +
    undefined_identifier:
    +
    identifier “xxxx” is undefined
    +
    +

    0021

    +
    useless_type_qualifiers:
    +
    type qualifiers are meaningless in this declaration
    +
    +

    0022

    +
    bad_hex_digit:
    +
    invalid hexadecimal number
    +
    +

    0023

    +
    integer_too_large:
    +
    integer constant is too large
    +
    +

    0024

    +
    bad_octal_digit:
    +
    invalid octal digit
    +
    +

    0025

    +
    zero_length_string:
    +
    quoted string should contain at least one character
    +
    +

    0026

    +
    too_many_characters:
    +
    too many characters in character constant
    +
    +

    0027

    +
    bad_character_value:
    +
    character value is out of range
    +
    +

    0028

    +
    expr_not_constant:
    +
    expression must have a constant value
    +
    +

    0029

    +
    exp_primary_expr:
    +
    expected an expression
    +
    +

    0030

    +
    bad_float_value:
    +
    floating constant is out of range
    +
    +

    0031

    +
    expr_not_integral:
    +
    expression must have integral type
    +
    +

    0032

    +
    expr_not_arithmetic:
    +
    expression must have arithmetic type
    +
    +

    0033

    +
    exp_line_number:
    +
    expected a line number
    +
    +

    0034

    +
    bad_line_number:
    +
    invalid line number
    +
    +

    0035

    +
    error_directive:
    +
    #error directive: xxxx
    +
    +

    0036

    +
    missing_pp_if:
    +
    the #if for this directive is missing
    +
    +

    0037

    +
    missing_endif:
    +
    the #endif for this directive is missing
    +
    +

    0038

    +
    pp_else_already_appeared:
    +
    directive is not allowed – an #else has already appeared
    +
    +

    0039

    +
    divide_by_zero:
    +
    division by zero
    +
    +

    0040

    +
    exp_identifier:
    +
    expected an identifier
    +
    +

    0041

    +
    expr_not_scalar:
    +
    expression must have arithmetic or pointer type
    +
    +

    0042

    +
    incompatible_operands:
    +
    operand types are incompatible (“type” and “type”)
    +
    +

    0044

    +
    expr_not_pointer:
    +
    expression must have pointer type
    +
    +

    0045

    +
    cannot_undef_predef_macro:
    +
    #undef may not be used on this predefined name
    +
    +

    0046

    +
    cannot_redef_predef_macro:
    +
    “entity” is predefined; attempted redefinition ignored
    +
    +

    0047

    +
    bad_macro_redef:
    +
    incompatible redefinition of macro “entity” (declared at line +xxxx)
    +
    +

    0049

    +
    duplicate_macro_param_name:
    +
    duplicate macro parameter name
    +
    +

    0050

    +
    paste_cannot_be_first:
    +
    “##” may not be first in a macro definition
    +
    +

    0051

    +
    paste_cannot_be_last:
    +
    “##” may not be last in a macro definition
    +
    +

    0052

    +
    exp_macro_param:
    +
    expected a macro parameter name
    +
    +

    0053

    +
    exp_colon:
    +
    expected a “:”
    +
    +

    0054

    +
    too_few_macro_args:
    +
    too few arguments in invocation of entity-kind “entity”
    +
    +

    0055

    +
    too_many_macro_args:
    +
    too many arguments in invocation of entity-kind “entity”
    +
    +

    0056

    +
    sizeof_function:
    +
    operand of sizeof may not be a function
    +
    +

    0057

    +
    bad_constant_operator:
    +
    this operator is not allowed in a constant expression
    +
    +

    0058

    +
    bad_pp_operator:
    +
    this operator is not allowed in a preprocessing expression
    +
    +

    0059

    +
    bad_constant_function_call:
    +
    function call is not allowed in a constant expression
    +
    +

    0060

    +
    bad_integral_operator:
    +
    this operator is not allowed in an integral constant expression
    +
    +

    0061

    +
    integer_overflow:
    +
    integer operation result is out of range
    +
    +

    0062

    +
    negative_shift_count:
    +
    shift count is negative
    +
    +

    0063

    +
    shift_count_too_large:
    +
    shift count is too large
    +
    +

    0064

    +
    useless_decl:
    +
    declaration does not declare anything
    +
    +

    0065

    +
    exp_semicolon:
    +
    expected a “;”
    +
    +

    0066

    +
    enum_value_out_of_int_range:
    +
    enumeration value is out of “int” range
    +
    +

    0067

    +
    exp_rbrace:
    +
    expected a “}”
    +
    +

    0068

    +
    integer_sign_change:
    +
    integer conversion resulted in a change of sign
    +
    +

    0069

    +
    integer_truncated:
    +
    integer conversion resulted in truncation
    +
    +

    0070

    +
    incomplete_type_not_allowed:
    +
    incomplete type “type” is not allowed
    +
    +

    0071

    +
    sizeof_bit_field:
    +
    operand of sizeof may not be a bit field
    +
    +

    0075

    +
    bad_indirection_operand:
    +
    operand of “*” must be a pointer but has type “type”
    +
    +

    0076

    +
    empty_macro_argument:
    +
    argument to macro is empty
    +
    +

    0077

    +
    missing_decl_specifiers:
    +
    this declaration has no storage class or type specifier
    +
    +

    0078

    +
    initializer_in_param:
    +
    a parameter declaration may not have an initializer
    +
    +

    0079

    +
    exp_type_specifier:
    +
    expected a type specifier
    +
    +

    0080

    +
    storage_class_not_allowed:
    +
    a storage class may not be specified here
    +
    +

    0081

    +
    mult_storage_classes:
    +
    more than one storage class may not be specified
    +
    +

    0082

    +
    storage_class_not_first:
    +
    storage class is not first
    +
    +

    0083

    +
    dupl_type_qualifier:
    +
    type qualifier specified more than once
    +
    +

    0084

    +
    bad_combination_of_type_specifiers:
    +
    invalid combination of type specifiers
    +
    +

    0085

    +
    bad_param_storage_class:
    +
    invalid storage class for a parameter
    +
    +

    0086

    +
    bad_function_storage_class:
    +
    invalid storage class for a function
    +
    +

    0087

    +
    type_specifier_not_allowed:
    +
    a type specifier may not be used here
    +
    +

    0088

    +
    array_of_function:
    +
    array of functions is not allowed
    +
    +

    0089

    +
    array_of_void:
    +
    array of void is not allowed
    +
    +

    0090

    +
    function_returning_function:
    +
    function returning function is not allowed
    +
    +

    0091

    +
    function_returning_array:
    +
    function returning array is not allowed
    +
    +

    0092

    +
    param_id_list_needs_function_def:
    +
    identifier-list parameters may only be used in a function definition
    +
    +

    0093

    +
    function_type_must_come_from_declarator:
    +
    function type may not come from a typedef
    +
    +

    0094

    +
    array_size_must_be_positive:
    +
    the size of an array must be greater than zero
    +
    +

    0095

    +
    array_size_too_large:
    +
    array is too large
    +
    +

    0096

    +
    empty_translation_unit:
    +
    a translation unit must contain at least one declaration
    +
    +

    0097

    +
    bad_function_return_type:
    +
    a function may not return a value of this type
    +
    +

    0098

    +
    bad_array_element_type:
    +
    an array may not have elements of this type
    +
    +

    0099

    +
    decl_should_be_of_param:
    +
    a declaration here must declare a parameter
    +
    +

    0100

    +
    dupl_param_name:
    +
    duplicate parameter name
    +
    +

    0101

    +
    id_already_declared:
    +
    “xxxx” has already been declared in the current scope
    +
    +

    0102

    +
    nonstd_forward_decl_enum:
    +
    forward declaration of enum type is nonstandard
    +
    +

    0103

    +
    class_too_large:
    +
    class is too large
    +
    +

    0104

    +
    struct_too_large:
    +
    struct or union is too large
    +
    +

    0105

    +
    bad_bit_field_size:
    +
    invalid size for bit field
    +
    +

    0106

    +
    bad_bit_field_type:
    +
    invalid type for a bit field
    +
    +

    0107

    +
    zero_length_bit_field_must_be_unnamed:
    +
    zero-length bit field must be unnamed
    +
    +

    0108

    +
    signed_one_bit_field:
    +
    signed bit field of length 1
    +
    +

    0109

    +
    expr_not_ptr_to_function:
    +
    expression preceding parentheses of apparent call must have +(pointer-to-) function type
    +
    +

    0110

    +
    exp_definition_of_tag:
    +
    expected either a definition or a tag name
    +
    +

    0111

    +
    code_is_unreachable:
    +
    statement is unreachable
    +
    +

    0112

    +
    exp_while:
    +
    expected “while”
    +
    +

    0114

    +
    never_defined:
    +
    entity-kind “entity” was referenced but not defined
    +
    +

    0115

    +
    continue_must_be_in_loop:
    +
    a continue statement may only be used within a loop
    +
    +

    0116

    +
    break_must_be_in_loop_or_switch:
    +
    a break statement may only be used within a loop or switch
    +
    +

    0117

    +
    no_value_returned_in_non_void_function:
    +
    non-void entity-kind “entity” should return a value
    +
    +

    0118

    +
    value_returned_in_void_function:
    +
    a void function may not return a value
    +
    +

    0119

    +
    cast_to_bad_type:
    +
    cast to type “type” is not allowed
    +
    +

    0120

    +
    bad_return_value_type:
    +
    return value type does not match the function type
    +
    +

    0121

    +
    case_label_must_be_in_switch:
    +
    a case label may only be used within a switch
    +
    +

    0122

    +
    default_label_must_be_in_switch:
    +
    a default label may only be used within a switch
    +
    +

    0124

    +
    default_label_appears_more_than_once:
    +
    default label has already appeared in this switch
    +
    +

    0125

    +
    exp_lparen:
    +
    expected a “(”
    +
    +

    0126

    +
    expr_not_an_lvalue:
    +
    expression must be an lvalue
    +
    +

    0127

    +
    exp_statement:
    +
    expected a statement
    +
    +

    0128

    +
    loop_not_reachable:
    +
    loop is not reachable
    +
    +

    0129

    +
    block_scope_function_must_be_extern:
    +
    a block-scope function may only have extern storage class
    +
    +

    0130

    +
    exp_lbrace:
    +
    expected a “{”
    +
    +

    0131

    +
    expr_not_ptr_to_class:
    +
    expression must have pointer-to-class type but it has type “type”
    +
    +

    0132

    +
    expr_not_ptr_to_struct_or_union:
    +
    expression must have pointer-to-struct-or-union type but it has type +“type”
    +
    +

    0133

    +
    exp_member_name:
    +
    expected a member name
    +
    +

    0134

    +
    exp_field_name:
    +
    expected a field name
    +
    +

    0135

    +
    not_a_member:
    +
    entity-kind “entity” has no member “xxxx”
    +
    +

    0136

    +
    not_a_field:
    +
    entity-kind “entity” has no field “xxxx”
    +
    +

    0137

    +
    expr_not_a_modifiable_lvalue:
    +
    expression must be a modifiable lvalue
    +
    +

    0138

    +
    address_of_register_variable:
    +
    taking the address of a register variable is not allowed
    +
    +

    0139

    +
    address_of_bit_field:
    +
    taking the address of a bit field is not allowed
    +
    +

    0140

    +
    too_many_arguments:
    +
    too many arguments in function call
    +
    +

    0141

    +
    all_proto_params_must_be_named:
    +
    unnamed prototyped parameters not allowed when body is present
    +
    +

    0142

    +
    expr_not_pointer_to_object:
    +
    expression must have pointer-to-object type but it has type “type”
    +
    +

    0143

    +
    program_too_large:
    +
    program too large or complicated to compile
    +
    +

    0144

    +
    bad_initializer_type:
    +
    a value of type “type” cannot be used to initialize an entity of +type “type”
    +
    +

    0145

    +
    cannot_initialize:
    +
    entity-kind “entity” may not be initialized
    +
    +

    0146

    +
    too_many_initializer_values:
    +
    too many initializer values
    +
    +

    0147

    +
    not_compatible_with_previous_decl:
    +
    declaration is incompatible with entity-kind “entity” (declared +at line xxxx)
    +
    +

    0148

    +
    already_initialized:
    +
    entity-kind “entity” has already been initialized
    +
    +

    0149

    +
    bad_file_scope_storage_class:
    +
    a global-scope declaration may not have this storage class
    +
    +

    0150

    +
    type_cannot_be_param_name:
    +
    a type name may not be redeclared as a parameter
    +
    +

    0151

    +
    typedef_cannot_be_param_name:
    +
    a typedef name may not be redeclared as a parameter
    +
    +

    0152

    +
    non_zero_int_conv_to_pointer:
    +
    conversion of nonzero integer to pointer
    +
    +

    0153

    +
    expr_not_class:
    +
    expression must have class type but it has type “type”
    +
    +

    0154

    +
    expr_not_struct_or_union:
    +
    expression must have struct or union type but it has type “type”
    +
    +

    0155

    +
    old_fashioned_assignment_operator:
    +
    old-fashioned assignment operator
    +
    +

    0156

    +
    old_fashioned_initializer:
    +
    old-fashioned initializer
    +
    +

    0157

    +
    expr_not_integral_constant:
    +
    expression must be an integral constant expression
    +
    +

    0158

    +
    expr_not_an_lvalue_or_function_designator:
    +
    expression must be an lvalue or a function designator
    +
    +

    0159

    +
    decl_incompatible_with_previous_use:
    +
    declaration is incompatible with previous “entity” (declared at +line xxxx)
    +
    +

    0160

    +
    external_name_clash:
    +
    external name conflicts with external name of entity-kind +“entity” (declared at line xxxx)
    +
    +

    0161

    +
    unrecognized_pragma:
    +
    unrecognized #pragma
    +
    +

    0163

    +
    cannot_open_temp_file_reason:
    +
    could not open temporary file “xxxx”: xxxx
    +
    +

    0165

    +
    too_few_arguments:
    +
    too few arguments in function call
    +
    +

    0166

    +
    bad_float_constant:
    +
    invalid floating constant
    +
    +

    0167

    +
    incompatible_param:
    +
    argument of type “type” is incompatible with parameter of type +“type”
    +
    +

    0168

    +
    function_type_not_allowed:
    +
    a function type is not allowed here
    +
    +

    0169

    +
    exp_declaration:
    +
    expected a declaration
    +
    +

    0170

    +
    pointer_outside_base_object:
    +
    pointer points outside of underlying object
    +
    +

    0171

    +
    bad_cast:
    +
    invalid type conversion
    +
    +

    0172

    +
    linkage_conflict:
    +
    external/internal linkage conflict with previous declaration at line +xxxx
    +
    +

    0173

    +
    float_to_integer_conversion:
    +
    floating-point value does not fit in required integral type
    +
    +

    0174

    +
    expr_has_no_effect:
    +
    expression has no effect
    +
    +

    0175

    +
    subscript_out_of_range:
    +
    subscript out of range
    +
    +

    0177

    +
    declared_but_not_referenced:
    +
    entity-kind “entity” was declared but never referenced
    +
    +

    0178

    +
    pcc_address_of_array:
    +
    “&” applied to an array has no effect
    +
    +

    0179

    +
    mod_by_zero:
    +
    right operand of “%” is zero
    +
    +

    0180

    +
    old_style_incompatible_param:
    +
    argument is incompatible with formal parameter
    +
    +

    0181

    +
    printf_arg_mismatch:
    +
    argument is incompatible with corresponding format string conversion +(expected type “type” but argument has type “type”)
    +
    +

    0182

    +
    empty_include_search_path:
    +
    could not open source file “xxxx” (no directories in search list)
    +
    +

    0183

    +
    cast_not_integral:
    +
    type of cast must be integral
    +
    +

    0184

    +
    cast_not_scalar:
    +
    type of cast must be arithmetic or pointer
    +
    +

    0185

    +
    initialization_not_reachable:
    +
    dynamic initialization in unreachable code
    +
    +

    0186

    +
    unsigned_compare_with_zero:
    +
    pointless comparison of unsigned integer with zero
    +
    +

    0187

    +
    assign_where_compare_meant:
    +
    use of “=” where “==” may have been intended
    +
    +

    0188

    +
    mixed_enum_type:
    +
    enumerated type mixed with another type
    +
    +

    0189

    +
    file_write_error:
    +
    error while writing xxxx file
    +
    +

    0190

    +
    bad_il_file:
    +
    invalid intermediate language file
    +
    +

    0191

    +
    cast_to_qualified_type:
    +
    type qualifier is meaningless on cast type
    +
    +

    0192

    +
    unrecognized_char_escape:
    +
    unrecognized character escape sequence
    +
    +

    0193

    +
    undefined_preproc_id:
    +
    zero used for undefined preprocessing identifier “xxxx”
    +
    +

    0194

    +
    exp_asm_string:
    +
    expected an asm string
    +
    +

    0195

    +
    asm_func_must_be_prototyped:
    +
    an asm function must be prototyped
    +
    +

    0196

    +
    bad_asm_func_ellipsis:
    +
    an asm function may not have an ellipsis
    +
    +

    0219

    +
    file_delete_error_reason:
    +
    error while deleting file “xxxx”: xxxx
    +
    +

    0220

    +
    integer_to_float_conversion:
    +
    integral value does not fit in required floating-point type
    +
    +

    0221

    +
    float_to_float_conversion:
    +
    floating-point value does not fit in required floating-point type
    +
    +

    0222

    +
    bad_float_operation_result:
    +
    floating-point operation result is out of range
    +
    +

    0223

    +
    implicit_func_decl:
    +
    function “xxxx” declared implicitly
    +
    +

    0224

    +
    too_few_printf_args:
    +
    the format string requires additional arguments
    +
    +

    0225

    +
    too_many_printf_args:
    +
    the format string ends before this argument
    +
    +

    0226

    +
    bad_printf_format_string:
    +
    invalid format string conversion
    +
    +

    0227

    +
    macro_recursion:
    +
    macro recursion
    +
    +

    0228

    +
    nonstd_extra_comma:
    +
    trailing comma is nonstandard
    +
    +

    0229

    +
    enum_bit_field_too_small:
    +
    bit field cannot contain all values of the enumerated type
    +
    +

    0230

    +
    nonstd_bit_field_type:
    +
    nonstandard type for a bit field
    +
    +

    0231

    +
    decl_in_prototype_scope:
    +
    declaration is not visible outside of function
    +
    +

    0232

    +
    decl_of_void_ignored:
    +
    old-fashioned typedef of “void” ignored
    +
    +

    0233

    +
    old_fashioned_field_selection:
    +
    left operand is not a struct or union containing this field
    +
    +

    0234

    +
    old_fashioned_ptr_field_selection:
    +
    pointer does not point to struct or union containing this field
    +
    +

    0235

    +
    var_retained_incomp_type:
    +
    variable “xxxx” was declared with a never-completed type
    +
    +

    0236

    +
    boolean_controlling_expr_is_constant:
    +
    controlling expression is constant
    +
    +

    0237

    +
    switch_selector_expr_is_constant:
    +
    selector expression is constant
    +
    +

    0238

    +
    bad_param_specifier:
    +
    invalid specifier on a parameter
    +
    +

    0239

    +
    bad_specifier_outside_class_decl:
    +
    invalid specifier outside a class declaration
    +
    +

    0240

    +
    dupl_decl_specifier:
    +
    duplicate specifier in declaration
    +
    +

    0241

    +
    base_class_not_allowed_for_union:
    +
    a union is not allowed to have a base class
    +
    +

    0242

    +
    access_already_specified:
    +
    multiple access control specifiers are not allowed
    +
    +

    0243

    +
    missing_class_definition:
    +
    class or struct definition is missing
    +
    +

    0244

    +
    name_not_member_of_class_or_base_classes:
    +
    qualified name is not a member of class “type” or its base classes
    +
    +

    0245

    +
    member_ref_requires_object:
    +
    a nonstatic member reference must be relative to a specific object
    +
    +

    0246

    +
    nonstatic_member_def_not_allowed:
    +
    a nonstatic data member may not be defined outside its class
    +
    +

    0247

    +
    already_defined:
    +
    entity-kind “entity” has already been defined
    +
    +

    0248

    +
    pointer_to_reference:
    +
    pointer to reference is not allowed
    +
    +

    0249

    +
    reference_to_reference:
    +
    reference to reference is not allowed
    +
    +

    0250

    +
    reference_to_void:
    +
    reference to void is not allowed
    +
    +

    0251

    +
    array_of_reference:
    +
    array of reference is not allowed
    +
    +

    0252

    +
    missing_initializer_on_reference:
    +
    reference entity-kind “entity” requires an initializer
    +
    +

    0253

    +
    exp_comma:
    +
    expected a “,”
    +
    +

    0254

    +
    type_identifier_not_allowed:
    +
    type name is not allowed
    +
    +

    0255

    +
    type_definition_not_allowed:
    +
    type definition is not allowed
    +
    +

    0256

    +
    bad_type_name_redeclaration:
    +
    invalid redeclaration of type name “entity” (declared at line +xxxx)
    +
    +

    0257

    +
    missing_initializer_on_const:
    +
    const entity-kind “entity” requires an initializer
    +
    +

    0258

    +
    this_used_incorrectly:
    +
    “this” may only be used inside a nonstatic member function
    +
    +

    0259

    +
    constant_value_not_known:
    +
    constant value is not known
    +
    +

    0260

    +
    missing_type_specifier:
    +
    explicit type is missing (“int” assumed)
    +
    +

    0261

    +
    missing_access_specifier:
    +
    access control not specified (“xxxx” by default)
    +
    +

    0262

    +
    not_a_class_or_struct_name:
    +
    not a class or struct name
    +
    +

    0263

    +
    dupl_base_class_name:
    +
    duplicate base class name
    +
    +

    0264

    +
    bad_base_class:
    +
    invalid base class
    +
    +

    0265

    +
    no_access_to_name:
    +
    entity-kind “entity” (declared at line xxxx) is inaccessible
    +
    +

    0266

    +
    ambiguous_name:
    +
    “entity” is ambiguous
    +
    +

    0267

    +
    old_style_parameter_list:
    +
    old-style parameter list (anachronism)
    +
    +

    0268

    +
    declaration_after_statements:
    +
    declaration may not appear after executable statement in block
    +
    +

    0269

    +
    inaccessible_base_class:
    +
    conversion to inaccessible base class “type” is not allowed
    +
    +

    0274

    +
    improperly_terminated_macro_call:
    +
    improperly terminated macro invocation
    +
    +

    0276

    +
    id_must_be_class_or_namespace_name:
    +
    name followed by “::” must be a class or namespace name
    +
    +

    0277

    +
    bad_friend_decl:
    +
    invalid friend declaration
    +
    +

    0278

    +
    value_returned_in_constructor:
    +
    a constructor or destructor may not return a value
    +
    +

    0279

    +
    bad_destructor_decl:
    +
    invalid destructor declaration
    +
    +

    0280

    +
    class_and_member_name_conflict:
    +
    declaration of a member with the same name as its class
    +
    +

    0281

    +
    global_qualifier_not_allowed:
    +
    global-scope qualifier (leading “::”) is not allowed
    +
    +

    0282

    +
    name_not_found_in_file_scope:
    +
    the global scope has no “xxxx”
    +
    +

    0283

    +
    qualified_name_not_allowed:
    +
    qualified name is not allowed
    +
    +

    0284

    +
    null_reference:
    +
    NULL reference is not allowed
    +
    +

    0285

    +
    brace_initialization_not_allowed:
    +
    initialization with “{…}” is not allowed for object of type +“type”
    +
    +

    0286

    +
    ambiguous_base_class:
    +
    base class “type” is ambiguous
    +
    +

    0287

    +
    ambiguous_derived_class:
    +
    derived class “type” contains more than one instance of class +“type”
    +
    +

    0288

    +
    derived_class_from_virtual_base:
    +
    cannot convert pointer to base class “type” to pointer to derived +class “type” – base class is virtual
    +
    +

    0289

    +
    no_matching_constructor:
    +
    no instance of constructor “entity” matches the argument list
    +
    +

    0290

    +
    ambiguous_copy_constructor:
    +
    copy constructor for class “type” is ambiguous
    +
    +

    0291

    +
    no_default_constructor:
    +
    no default constructor exists for class “type”
    +
    +

    0292

    +
    not_a_field_or_base_class:
    +
    “xxxx” is not a nonstatic data member or base class of class +“type”
    +
    +

    0293

    +
    indirect_nonvirtual_base_class_not_allowed:
    +
    indirect nonvirtual base class is not allowed
    +
    +

    0294

    +
    bad_union_field:
    +
    invalid union member – class “type” has a disallowed member +function
    +
    +

    0296

    +
    bad_rvalue_array:
    +
    invalid use of non-lvalue array
    +
    +

    0297

    +
    exp_operator:
    +
    expected an operator
    +
    +

    0298

    +
    inherited_member_not_allowed:
    +
    inherited member is not allowed
    +
    +

    0299

    +
    indeterminate_overloaded_function:
    +
    cannot determine which instance of entity-kind “entity” is +intended
    +
    +

    0300

    +
    bound_function_must_be_called:
    +
    a pointer to a bound function may only be used to call the function
    +
    +

    0301

    +
    duplicate_typedef:
    +
    typedef name has already been declared (with same type)
    +
    +

    0304

    +
    no_matching_function:
    +
    no instance of entity-kind “entity” matches the argument list
    +
    +

    0305

    +
    type_def_not_allowed_in_func_type_decl:
    +
    type definition is not allowed in function return type declaration
    +
    +

    0306

    +
    default_arg_not_at_end:
    +
    default argument not at end of parameter list
    +
    +

    0307

    +
    default_arg_already_defined:
    +
    redefinition of default argument
    +
    +

    0308

    +
    ambiguous_overloaded_function:
    +
    more than one instance of entity-kind “entity” matches the +argument list:
    +
    +

    0309

    +
    ambiguous_constructor:
    +
    more than one instance of constructor “entity” matches the +argument list:
    +
    +

    0310

    +
    bad_default_arg_type:
    +
    default argument of type “type” is incompatible with parameter of +type “type”
    +
    +

    0311

    +
    return_type_cannot_distinguish_functions:
    +
    cannot overload functions distinguished by return type alone
    +
    +

    0312

    +
    no_user_defined_conversion:
    +
    no suitable user-defined conversion from “type” to “type”exists
    +
    +

    0314

    +
    virtual_static_not_allowed:
    +
    only nonstatic member functions may be virtual
    +
    +

    0315

    +
    unqual_function_with_qual_object:
    +
    the object has type qualifiers that are not compatible with the +member function
    +
    +

    0316

    +
    too_many_virtual_functions:
    +
    program too large to compile (too many virtual functions)
    +
    +

    0317

    +
    bad_return_type_on_virtual_function_override:
    +
    return type is not identical to nor covariant with return type +“type” of overridden virtual function “entity”
    +
    +

    0318

    +
    ambiguous_virtual_function_override:
    +
    override of virtual entity-kind “entity” is ambiguous
    +
    +

    0319

    +
    pure_specifier_on_nonvirtual_function:
    +
    pure specifier (”= 0”) allowed only on virtual functions
    +
    +

    0320

    +
    bad_pure_specifier:
    +
    badly-formed pure specifier (only “= 0” is allowed)
    +
    +

    0321

    +
    bad_data_member_initialization:
    +
    data member initializer is not allowed
    +
    +

    0322

    +
    abstract_class_object_not_allowed:
    +
    object of abstract class type “type” is not allowed:
    +
    +

    0323

    +
    function_returning_abstract_class:
    +
    function returning abstract class “type” is not allowed:
    +
    +

    0324

    +
    duplicate_friend_decl:
    +
    duplicate friend declaration
    +
    +

    0325

    +
    inline_and_nonfunction:
    +
    inline specifier allowed on function declarations only
    +
    +

    0326

    +
    inline_not_allowed:
    +
    “inline” is not allowed
    +
    +

    0327

    +
    bad_storage_class_with_inline:
    +
    invalid storage class for an inline function
    +
    +

    0328

    +
    bad_member_storage_class:
    +
    invalid storage class for a class member
    +
    +

    0329

    +
    local_class_function_def_missing:
    +
    local class member entity-kind “entity” requires a definition
    +
    +

    0330

    +
    inaccessible_special_function:
    +
    entity-kind “entity” (declared at line xxxx) is inaccessible
    +
    +

    0332

    +
    missing_const_copy_constructor:
    +
    class “type” has no copy constructor to copy a const object
    +
    +

    0333

    +
    definition_of_implicitly_declared_function:
    +
    defining an implicitly declared member function is not allowed
    +
    +

    0334

    +
    no_suitable_copy_constructor:
    +
    class “type” has no suitable copy constructor
    +
    +

    0335

    +
    linkage_specifier_not_allowed:
    +
    linkage specification is not allowed
    +
    +

    0336

    +
    bad_linkage_specifier:
    +
    unknown external linkage specification
    +
    +

    0337

    +
    incompatible_linkage_specifier:
    +
    linkage specification is incompatible with previous “entity”(declared at line xxxx)
    +
    +

    0338

    +
    overloaded_function_linkage:
    +
    more than one instance of overloaded function “entity” has “C” +linkage
    +
    +

    0339

    +
    ambiguous_default_constructor:
    +
    class “type” has more than one default constructor
    +
    +

    0340

    +
    temp_used_for_ref_init:
    +
    value copied to temporary, reference to temporary used
    +
    +

    0341

    +
    nonmember_operator_not_allowed:
    +
    “operator*xxxx*“ must be a member function
    +
    +

    0342

    +
    static_member_operator_not_allowed:
    +
    operator may not be a static member function
    +
    +

    0343

    +
    too_many_args_for_conversion:
    +
    no arguments allowed on user-defined conversion
    +
    +

    0344

    +
    too_many_args_for_operator:
    +
    too many parameters for this operator function
    +
    +

    0345

    +
    too_few_args_for_operator:
    +
    too few parameters for this operator function
    +
    +

    0346

    +
    no_params_with_class_type:
    +
    nonmember operator requires a parameter with class type
    +
    +

    0347

    +
    default_arg_expr_not_allowed:
    +
    default argument is not allowed
    +
    +

    0348

    +
    ambiguous_user_defined_conversion:
    +
    more than one user-defined conversion from “type” to “type”applies:
    +
    +

    0349

    +
    no_matching_operator_function:
    +
    no operator “xxxx” matches these operands
    +
    +

    0350

    +
    ambiguous_operator_function:
    +
    more than one operator “xxxx” matches these operands:
    +
    +

    0351

    +
    bad_arg_type_for_operator_new:
    +
    first parameter of allocation function must be of type “size_t”
    +
    +

    0352

    +
    bad_return_type_for_op_new:
    +
    allocation function requires “void *” return type
    +
    +

    0353

    +
    bad_return_type_for_op_delete:
    +
    deallocation function requires “void” return type
    +
    +

    0354

    +
    bad_first_arg_type_for_operator_delete:
    +
    first parameter of deallocation function must be of type “void *”
    +
    +

    0356

    +
    type_must_be_object_type:
    +
    type must be an object type
    +
    +

    0357

    +
    base_class_already_initialized:
    +
    base class “type” has already been initialized
    +
    +

    0358

    +
    base_class_init_anachronism:
    +
    base class name required – “type” assumed (anachronism)
    +
    +

    0359

    +
    member_already_initialized:
    +
    entity-kind “entity” has already been initialized
    +
    +

    0360

    +
    missing_base_class_or_member_name:
    +
    name of member or base class is missing
    +
    +

    0361

    +
    assignment_to_this:
    +
    assignment to “this” (anachronism)
    +
    +

    0362

    +
    overload_anachronism:
    +
    “overload” keyword used (anachronism)
    +
    +

    0363

    +
    anon_union_member_access:
    +
    invalid anonymous union – nonpublic member is not allowed
    +
    +

    0364

    +
    anon_union_member_function:
    +
    invalid anonymous union – member function is not allowed
    +
    +

    0365

    +
    anon_union_storage_class:
    +
    anonymous union at global or namespace scope must be declared static
    +
    +

    0366

    +
    missing_initializer_on_fields:
    +
    entity-kind “entity” provides no initializer for:
    +
    +

    0367

    +
    cannot_initialize_fields:
    +
    implicitly generated constructor for class “type” cannot +initialize:
    +
    +

    0368

    +
    no_ctor_but_const_or_ref_member:
    +
    entity-kind “entity” defines no constructor to initialize the +following:
    +
    +

    0369

    +
    var_with_uninitialized_member:
    +
    entity-kind “entity” has an uninitialized const or reference +member
    +
    +

    0370

    +
    var_with_uninitialized_field:
    +
    entity-kind “entity” has an uninitialized const field
    +
    +

    0371

    +
    missing_const_assignment_operator:
    +
    class “type” has no assignment operator to copy a const object
    +
    +

    0372

    +
    no_suitable_assignment_operator:
    +
    class “type” has no suitable assignment operator
    +
    +

    0373

    +
    ambiguous_assignment_operator:
    +
    ambiguous assignment operator for class “type”
    +
    +

    0375

    +
    missing_typedef_name:
    +
    declaration requires a typedef name
    +
    +

    0377

    +
    virtual_not_allowed:
    +
    “virtual” is not allowed
    +
    +

    0378

    +
    static_not_allowed:
    +
    “static” is not allowed
    +
    +

    0379

    +
    bound_function_cast_anachronism:
    +
    cast of bound function to normal function pointer (anachronism)
    +
    +

    0380

    +
    expr_not_ptr_to_member:
    +
    expression must have pointer-to-member type
    +
    +

    0381

    +
    extra_semicolon:
    +
    extra “;” ignored
    +
    +

    0382

    +
    nonstd_const_member:
    +
    in-class initializer for nonstatic member is nonstandard
    +
    +

    0384

    +
    no_matching_new_function:
    +
    no instance of overloaded “entity” matches the argument list
    +
    +

    0386

    +
    no_match_for_addr_of_overloaded_function:
    +
    no instance of entity-kind “entity” matches the required type
    +
    +

    0387

    +
    delete_count_anachronism:
    +
    delete array size expression used (anachronism)
    +
    +

    0389

    +
    cast_to_abstract_class:
    +
    a cast to abstract class “type” is not allowed:
    +
    +

    0390

    +
    bad_use_of_main:
    +
    function “main” may not be called or have its address taken
    +
    +

    0391

    +
    initializer_not_allowed_on_array_new:
    +
    a new-initializer may not be specified for an array
    +
    +

    0392

    +
    member_function_redecl_outside_class:
    +
    member function “entity” may not be redeclared outside its class
    +
    +

    0394

    +
    ref_to_nested_function_var:
    +
    reference to local variable of enclosing function is not allowed
    +
    +

    0395

    +
    single_arg_postfix_incr_decr_anachronism:
    +
    single-argument function used for postfix “xxxx” (anachronism)
    +
    +

    0397

    +
    bad_default_assignment:
    +
    implicitly generated assignment operator cannot copy:
    +
    +

    0398

    +
    nonstd_array_cast:
    +
    cast to array type is nonstandard (treated as cast to “type”)
    +
    +

    0399

    +
    class_with_op_new_but_no_op_delete:
    +
    entity-kind “entity” has an operator new*xxxx*() but no default +operator delete*xxxx*()
    +
    +

    0400

    +
    class_with_op_delete_but_no_op_new:
    +
    entity-kind “entity” has a default operator delete*xxxx*() but +no operator new*xxxx*()
    +
    +

    0401

    +
    base_class_with_nonvirtual_dtor:
    +
    destructor for base class “entity” (declared at line xxxx) is +not virtual
    +
    +

    0403

    +
    member_function_redeclaration:
    +
    invalid redeclaration of member entity-kind “entity” (declared at +line xxxx)
    +
    +

    0404

    +
    inline_main:
    +
    function “main” may not be declared inline
    +
    +

    0405

    +
    class_and_member_function_name_conflict:
    +
    member function with the same name as its class must be a constructor
    +
    +

    0406

    +
    nested_class_anachronism:
    +
    using nested entity-kind “entity” (anachronism)
    +
    +

    0407

    +
    too_many_params_for_destructor:
    +
    a destructor may not have parameters
    +
    +

    0408

    +
    bad_constructor_param:
    +
    copy constructor for class “type” may not have a parameter of +type “type”
    +
    +

    0409

    +
    incomplete_function_return_type:
    +
    entity-kind “entity” returns incomplete type “type”
    +
    +

    0410

    +
    protected_access_problem:
    +
    protected entity-kind “entity” (declared at line xxxx) is not +accessible through a “type” pointer or object
    +
    +

    0411

    +
    param_not_allowed:
    +
    a parameter is not allowed
    +
    +

    0412

    +
    asm_decl_not_allowed:
    +
    an “asm” declaration is not allowed here
    +
    +

    0413

    +
    no_conversion_function:
    +
    no suitable conversion function from “type” to “type” exists
    +
    +

    0414

    +
    delete_of_incomplete_class:
    +
    delete of pointer to incomplete class
    +
    +

    0415

    +
    no_constructor_for_conversion:
    +
    no suitable constructor exists to convert from “type” to +“type”
    +
    +

    0416

    +
    ambiguous_constructor_for_conversion:
    +
    more than one constructor applies to convert from “type” to +“type”:
    +
    +

    0417

    +
    ambiguous_conversion_function:
    +
    more than one conversion function from “type” to “type”applies:
    +
    +

    0418

    +
    ambiguous_conversion_to_builtin:
    +
    more than one conversion function from “type” to a built-in type +applies:
    +
    +

    0424

    +
    addr_of_constructor_or_destructor:
    +
    a constructor or destructor may not have its address taken
    +
    +

    0426

    +
    nonconst_ref_init_anachronism:
    +
    temporary used for initial value of reference to non-const +(anachronism)
    +
    +

    0427

    +
    qualifier_in_member_declaration:
    +
    qualified name is not allowed in member declaration
    +
    +

    0428

    +
    mixed_enum_type_anachronism:
    +
    enumerated type mixed with another type (anachronism)
    +
    +

    0429

    +
    new_array_size_must_be_nonnegative:
    +
    the size of an array in “new” must be non-negative
    +
    +

    0430

    +
    return_ref_init_requires_temp:
    +
    returning reference to local temporary
    +
    +

    0432

    +
    enum_not_allowed:
    +
    “enum” declaration is not allowed
    +
    +

    0433

    +
    qualifier_dropped_in_ref_init:
    +
    qualifiers dropped in binding reference of type “type” to +initializer of type “type”
    +
    +

    0434

    +
    bad_nonconst_ref_init:
    +
    a reference of type “type” (not const-qualified) cannot be +initialized with a value of type “type”
    +
    +

    0435

    +
    delete_of_function_pointer:
    +
    a pointer to function may not be deleted
    +
    +

    0436

    +
    bad_conversion_function_decl:
    +
    conversion function must be a nonstatic member function
    +
    +

    0437

    +
    bad_template_declaration_scope:
    +
    a template declaration is not allowed here
    +
    +

    0438

    +
    exp_lt:
    +
    expected a “<”
    +
    +

    0439

    +
    exp_gt:
    +
    expected a “>”
    +
    +

    0440

    +
    missing_template_param:
    +
    template parameter declaration is missing
    +
    +

    0441

    +
    missing_template_arg_list:
    +
    argument list for entity-kind “entity” is missing
    +
    +

    0442

    +
    too_few_template_args:
    +
    too few arguments for entity-kind “entity”
    +
    +

    0443

    +
    too_many_template_args:
    +
    too many arguments for entity-kind “entity”
    +
    +

    0445

    +
    not_used_in_template_function_params:
    +
    entity-kind “entity” is not used in declaring the parameter types +of entity-kind “entity”
    +
    +

    0446

    +
    cfront_multiple_nested_types:
    +
    two nested types have the same name: “entity” and “entity”(declared at line xxxx) (cfront compatibility)
    +
    +

    0447

    +
    cfront_global_defined_after_nested_type:
    +
    global “entity” was declared after nested “entity” (declared +at line xxxx) (cfront compatibility)
    +
    +

    0449

    +
    ambiguous_ptr_to_overloaded_function:
    +
    more than one instance of entity-kind “entity” matches the +required type
    +
    +

    0450

    +
    nonstd_long_long:
    +
    the type “long long” is nonstandard
    +
    +

    0451

    +
    nonstd_friend_decl:
    +
    omission of “xxxx” is nonstandard
    +
    +

    0452

    +
    return_type_on_conversion_function:
    +
    return type may not be specified on a conversion function
    +
    +

    0456

    +
    runaway_recursive_instantiation:
    +
    excessive recursion at instantiation of entity-kind “entity”
    +
    +

    0457

    +
    bad_template_declaration:
    +
    “xxxx” is not a function or static data member
    +
    +

    0458

    +
    bad_nontype_template_arg:
    +
    argument of type “type” is incompatible with template parameter +of type “type”
    +
    +

    0459

    +
    init_needing_temp_not_allowed:
    +
    initialization requiring a temporary or conversion is not allowed
    +
    +

    0460

    +
    decl_hides_function_parameter:
    +
    declaration of “xxxx” hides function parameter
    +
    +

    0461

    +
    nonconst_ref_init_from_rvalue:
    +
    initial value of reference to non-const must be an lvalue
    +
    +

    0463

    +
    template_not_allowed:
    +
    “template” is not allowed
    +
    +

    0464

    +
    not_a_class_template:
    +
    “type” is not a class template
    +
    +

    0466

    +
    function_template_named_main:
    +
    “main” is not a valid name for a function template
    +
    +

    0467

    +
    union_nonunion_mismatch:
    +
    invalid reference to entity-kind “entity” (union/nonunion +mismatch)
    +
    +

    0468

    +
    local_type_in_template_arg:
    +
    a template argument may not reference a local type
    +
    +

    0469

    +
    tag_kind_incompatible_with_declaration:
    +
    tag kind of xxxx is incompatible with declaration of entity-kind +“entity” (declared at line xxxx)
    +
    +

    0470

    +
    name_not_tag_in_file_scope:
    +
    the global scope has no tag named “xxxx”
    +
    +

    0471

    +
    not_a_tag_member:
    +
    entity-kind “entity” has no tag member named “xxxx”
    +
    +

    0472

    +
    ptr_to_member_typedef:
    +
    member function typedef (allowed for cfront compatibility)
    +
    +

    0473

    +
    bad_use_of_member_function_typedef:
    +
    entity-kind “entity” may be used only in pointer-to-member +declaration
    +
    +

    0475

    +
    nonexternal_entity_in_template_arg:
    +
    a template argument may not reference a non-external entity
    +
    +

    0476

    +
    id_must_be_class_or_type_name:
    +
    name followed by “::~” must be a class name or a type name
    +
    +

    0478

    +
    destructor_type_mismatch:
    +
    type used as destructor name does not match type “type”
    +
    +

    0479

    +
    called_function_redeclared_inline:
    +
    entity-kind “entity” redeclared “inline” after being called
    +
    +

    0481

    +
    bad_storage_class_on_template_decl:
    +
    invalid storage class for a template declaration
    +
    +

    0482

    +
    no_access_to_type_cfront_mode:
    +
    entity-kind “entity” (declared at line xxxx) is an +inaccessible type (allowed for cfront compatibility)
    +
    +

    0484

    +
    invalid_instantiation_argument:
    +
    invalid explicit instantiation declaration
    +
    +

    0485

    +
    not_instantiatable_entity:
    +
    entity-kind “entity” is not an entity that can be instantiated
    +
    +

    0486

    +
    compiler_generated_function_cannot_be_instantiated:
    +
    compiler generated entity-kind “entity” cannot be explicitly +instantiated
    +
    +

    0487

    +
    inline_function_cannot_be_instantiated:
    +
    inline entity-kind “entity” cannot be explicitly instantiated
    +
    +

    0489

    +
    instantiation_requested_no_definition_supplied:
    +
    entity-kind “entity” cannot be instantiated – no template +definition was supplied
    +
    +

    0490

    +
    instantiation_requested_and_specialized:
    +
    entity-kind “entity” cannot be instantiated – it has been +explicitly specialized
    +
    +

    0493

    +
    no_match_for_type_of_overloaded_function:
    +
    no instance of entity-kind “entity” matches the specified type
    +
    +

    0494

    +
    nonstd_void_param_list:
    +
    declaring a void parameter list with a typedef is nonstandard
    +
    +

    0495

    +
    cfront_name_lookup_bug:
    +
    global entity-kind “entity” used instead of entity-kind +“entity” (cfront compatibility)
    +
    +

    0496

    +
    redeclaration_of_template_param_name:
    +
    template parameter “xxxx” may not be redeclared in this scope
    +
    +

    0497

    +
    decl_hides_template_parameter:
    +
    declaration of “xxxx” hides template parameter
    +
    +

    0498

    +
    must_be_prototype_instantiation:
    +
    template argument list must match the parameter list
    +
    +

    0500

    +
    bad_extra_arg_for_postfix_operator:
    +
    extra parameter of postfix “operator*xxxx*“ must be of type “int”
    +
    +

    0501

    +
    function_type_required:
    +
    an operator name must be declared as a function
    +
    +

    0502

    +
    operator_name_not_allowed:
    +
    operator name is not allowed
    +
    +

    0503

    +
    bad_scope_for_specialization:
    +
    entity-kind “entity” cannot be specialized in the current scope
    +
    +

    0504

    +
    nonstd_member_function_address:
    +
    nonstandard form for taking the address of a member function
    +
    +

    0505

    +
    too_few_template_params:
    +
    too few template parameters – does not match previous declaration +(declared at line xxxx)
    +
    +

    0506

    +
    too_many_template_params:
    +
    too many template parameters – does not match previous declaration +(declared at line xxxx)
    +
    +

    0507

    +
    template_operator_delete:
    +
    function template for operator delete(void *) is not allowed
    +
    +

    0508

    +
    class_template_same_name_as_templ_param:
    +
    class template and template parameter may not have the same name
    +
    +

    0510

    +
    unnamed_type_in_template_arg:
    +
    a template argument may not reference an unnamed type
    +
    +

    0511

    +
    enum_type_not_allowed:
    +
    this operation on an enumerated type requires an applicable +user-defined operator function
    +
    +

    0512

    +
    qualified_reference_type:
    +
    type qualifier on a reference type is not allowed
    +
    +

    0513

    +
    incompatible_assignment_operands:
    +
    a value of type “type” cannot be assigned to an entity of type +“type”
    +
    +

    0514

    +
    unsigned_compare_with_negative:
    +
    pointless comparison of unsigned integer with a negative constant
    +
    +

    0515

    +
    converting_to_incomplete_class:
    +
    cannot convert to incomplete class “type”
    +
    +

    0516

    +
    missing_initializer_on_unnamed_const:
    +
    const object requires an initializer
    +
    +

    0517

    +
    unnamed_object_with_uninitialized_field:
    +
    object has an uninitialized const or reference member
    +
    +

    0518

    +
    nonstd_pp_directive:
    +
    nonstandard preprocessing directive
    +
    +

    0519

    +
    unexpected_template_arg_list:
    +
    entity-kind “entity” may not have a template argument list
    +
    +

    0520

    +
    missing_initializer_list:
    +
    initialization with “{…}” expected for aggregate object
    +
    +

    0521

    +
    incompatible_ptr_to_member_selection_operands:
    +
    pointer-to-member selection class types are incompatible (“type”and “type”)
    +
    +

    0522

    +
    self_friendship:
    +
    pointless friend declaration
    +
    +

    0523

    +
    period_used_as_qualifier:
    +
    “.” used in place of “::” to form a qualified name
    +
    +

    0524

    +
    const_function_anachronism:
    +
    non-const function called for const object (anachronism)
    +
    +

    0525

    +
    dependent_stmt_is_declaration:
    +
    a dependent statement may not be a declaration
    +
    +

    0526

    +
    void_param_not_allowed:
    +
    a parameter may not have void type
    +
    +

    0529

    +
    bad_templ_arg_expr_operator:
    +
    this operator is not allowed in a template argument expression
    +
    +

    0530

    +
    missing_handler:
    +
    try block requires at least one handler
    +
    +

    0531

    +
    missing_exception_declaration:
    +
    handler requires an exception declaration
    +
    +

    0532

    +
    masked_by_default_handler:
    +
    handler is masked by default handler
    +
    +

    0533

    +
    masked_by_handler:
    +
    handler is potentially masked by previous handler for type “type”
    +
    +

    0534

    +
    local_type_used_in_exception:
    +
    use of a local type to specify an exception
    +
    +

    0535

    +
    redundant_exception_specification_type:
    +
    redundant type in exception specification
    +
    +

    0536

    +
    incompatible_exception_specification:
    +
    exception specification is incompatible with that of previous +entity-kind “entity” (declared at line xxxx):
    +
    +

    0540

    +
    no_exception_support:
    +
    support for exception handling is disabled
    +
    +

    0541

    +
    omitted_exception_specification:
    +
    allowing all exceptions is incompatible with previous entity-kind +“entity” (declared at line xxxx)
    +
    +

    0542

    +
    cannot_create_instantiation_request_file:
    +
    could not create instantiation request file “xxxx”
    +
    +

    0543

    +
    non_arith_operation_in_templ_arg:
    +
    non-arithmetic operation not allowed in nontype template argument
    +
    +

    0544

    +
    local_type_in_nonlocal_var:
    +
    use of a local type to declare a nonlocal variable
    +
    +

    0545

    +
    local_type_in_function:
    +
    use of a local type to declare a function
    +
    +

    0546

    +
    branch_past_initialization:
    +
    transfer of control bypasses initialization of:
    +
    +

    0548

    +
    branch_into_handler:
    +
    transfer of control into an exception handler
    +
    +

    0549

    +
    used_before_set:
    +
    entity-kind “entity” is used before its value is set
    +
    +

    0550

    +
    set_but_not_used:
    +
    entity-kind “entity” was set but never used
    +
    +

    0551

    +
    bad_scope_for_definition:
    +
    entity-kind “entity” cannot be defined in the current scope
    +
    +

    0552

    +
    exception_specification_not_allowed:
    +
    exception specification is not allowed
    +
    +

    0553

    +
    template_and_instance_linkage_conflict:
    +
    external/internal linkage conflict for entity-kind “entity”(declared at line xxxx)
    +
    +

    0554

    +
    conversion_function_not_usable:
    +
    entity-kind “entity” will not be called for implicit or explicit +conversions
    +
    +

    0555

    +
    tag_kind_incompatible_with_template_parameter:
    +
    tag kind of xxxx is incompatible with template parameter of type +“type”
    +
    +

    0556

    +
    template_operator_new:
    +
    function template for operator new(size_t) is not allowed
    +
    +

    0558

    +
    bad_member_type_in_ptr_to_member:
    +
    pointer to member of type “type” is not allowed
    +
    +

    0559

    +
    ellipsis_on_operator_function:
    +
    ellipsis is not allowed in operator function parameter list
    +
    +

    0560

    +
    unimplemented_keyword:
    +
    “entity” is reserved for future use as a keyword
    +
    +

    0561

    +
    cl_invalid_macro_definition:
    +
    invalid macro definition: xxxx
    +
    +

    0562

    +
    cl_invalid_macro_undefinition:
    +
    invalid macro undefinition: xxxx
    +
    +

    0565

    +
    cl_il_file_must_be_specified:
    +
    IL file name must be specified if input is
    +
    +

    0570

    +
    cl_error_in_debug_option_argument:
    +
    error in debug option argument
    +
    +

    0571

    +
    cl_invalid_option:
    +
    invalid option: xxxx
    +
    +

    0572

    +
    cl_back_end_requires_il_file:
    +
    back end requires name of IL file
    +
    +

    0573

    +
    cl_could_not_open_il_file:
    +
    could not open IL file xxxx
    +
    +

    0574

    +
    cl_invalid_number:
    +
    invalid number: xxxx
    +
    +

    0575

    +
    cl_incorrect_host_id:
    +
    incorrect host CPU id
    +
    +

    0576

    +
    cl_invalid_instantiation_mode:
    +
    invalid instantiation mode: xxxx
    +
    +

    0578

    +
    cl_invalid_error_limit:
    +
    invalid error limit: xxxx
    +
    +

    0585

    +
    cl_vtbl_option_only_in_cplusplus:
    +
    virtual function tables can only be suppressed when compiling C++
    +
    +

    0586

    +
    cl_anachronism_option_only_in_cplusplus:
    +
    anachronism option can be used only when compiling C++
    +
    +

    0587

    +
    cl_instantiation_option_only_in_cplusplus:
    +
    instantiation mode option can be used only when compiling C++
    +
    +

    0588

    +
    cl_auto_instantiation_option_only_in_cplusplus:
    +
    automatic instantiation mode can be used only when compiling C++
    +
    +

    0589

    +
    cl_implicit_inclusion_option_only_in_cplusplus:
    +
    implicit template inclusion mode can be used only when compiling C++
    +
    +

    0590

    +
    cl_exceptions_option_only_in_cplusplus:
    +
    exception handling option can be used only when compiling C++
    +
    +

    0591

    +
    cl_strict_mode_incompatible_with_pcc:
    +
    strict mode is incompatible with K&R mode
    +
    +

    0592

    +
    cl_strict_mode_incompatible_with_cfront:
    +
    strict mode is incompatible with cfront mode
    +
    +

    0593

    +
    cl_missing_source_file_name:
    +
    missing source file name
    +
    +

    0594

    +
    cl_output_file_incompatible_with_multiple_inputs:
    +
    output files may not be specified when compiling several input files
    +
    +

    0595

    +
    cl_too_many_arguments:
    +
    too many arguments on command line
    +
    +

    0596

    +
    cl_no_output_file_needed:
    +
    an output file was specified, but none is needed
    +
    +

    0597

    +
    cl_il_display_requires_il_file_name:
    +
    IL display requires name of IL file
    +
    +

    0598

    +
    void_template_parameter:
    +
    a template parameter may not have void type
    +
    +

    0599

    +
    too_many_unused_instantiations:
    +
    excessive recursive instantiation of entity-kind “entity” due to +instantiate-all mode
    +
    +

    0600

    +
    cl_strict_mode_incompatible_with_anachronisms:
    +
    strict mode is incompatible with allowing anachronisms
    +
    +

    0601

    +
    void_throw:
    +
    a throw expression may not have void type
    +
    +

    0602

    +
    cl_tim_local_conflicts_with_auto_instantiation:
    +
    local instantiation mode is incompatible with automatic instantiation
    +
    +

    0603

    +
    abstract_class_param_type:
    +
    parameter of abstract class type “type” is not allowed:
    +
    +

    0604

    +
    array_of_abstract_class:
    +
    array of abstract class “type” is not allowed:
    +
    +

    0605

    +
    float_template_parameter:
    +
    floating-point template parameter is nonstandard
    +
    +

    0606

    +
    pragma_must_precede_declaration:
    +
    this pragma must immediately precede a declaration
    +
    +

    0607

    +
    pragma_must_precede_statement:
    +
    this pragma must immediately precede a statement
    +
    +

    0608

    +
    pragma_must_precede_decl_or_stmt:
    +
    this pragma must immediately precede a declaration or statement
    +
    +

    0609

    +
    pragma_may_not_be_used_here:
    +
    this kind of pragma may not be used here
    +
    +

    0611

    +
    partial_override:
    +
    overloaded virtual function “entity” is only partially overridden +in entity-kind “entity”
    +
    +

    0612

    +
    specialization_of_called_inline_template_function:
    +
    specific definition of inline template function must precede its +first use
    +
    +

    0613

    +
    cl_invalid_error_tag:
    +
    invalid error tag in diagnostic control option: xxxx
    +
    +

    0614

    +
    cl_invalid_error_number:
    +
    invalid error number in diagnostic control option: xxxx
    +
    +

    0617

    +
    ptr_to_member_cast_to_ptr_to_function:
    +
    pointer-to-member-function cast to pointer to function
    +
    +

    0618

    +
    no_named_fields:
    +
    struct or union declares no named members
    +
    +

    0619

    +
    nonstd_unnamed_field:
    +
    nonstandard unnamed field
    +
    +

    0620

    +
    nonstd_unnamed_member:
    +
    nonstandard unnamed member
    +
    +

    0624

    +
    not_a_type_name:
    +
    “xxxx” is not a type name
    +
    +

    0625

    +
    cannot_open_pch_input_file_reason:
    +
    cannot open precompiled header input file “xxxx”: xxxx
    +
    +

    0626

    +
    invalid_pch_file:
    +
    precompiled header file “xxxx” is either invalid or not generated +by this version of the compiler
    +
    +

    0627

    +
    pch_curr_directory_changed:
    +
    precompiled header file “xxxx” was not generated in this directory
    +
    +

    0628

    +
    pch_header_files_have_changed:
    +
    header files used to generate precompiled header file “xxxx” have +changed
    +
    +

    0629

    +
    pch_cmd_line_option_mismatch:
    +
    the command line options do not match those used when precompiled +header file “xxxx” was created
    +
    +

    0630

    +
    pch_file_prefix_mismatch:
    +
    the initial sequence of preprocessing directives is not compatible +with those of precompiled header file “xxxx”
    +
    +

    0631

    +
    unable_to_get_mapped_memory:
    +
    unable to obtain mapped memory
    +
    +

    0632

    +
    using_pch:
    +
    “xxxx“: using precompiled header file “xxxx“
    +
    +

    0633

    +
    creating_pch:
    +
    “xxxx“: creating precompiled header file “xxxx“
    +
    +

    0634

    +
    memory_mismatch:
    +
    memory usage conflict with precompiled header file “xxxx”
    +
    +

    0635

    +
    cl_invalid_pch_size:
    +
    invalid PCH memory size: xxxx
    +
    +

    0636

    +
    cl_pch_must_be_first:
    +
    PCH options must appear first in the command line
    +
    +

    0637

    +
    out_of_memory_during_pch_allocation:
    +
    insufficient memory for PCH memory allocation
    +
    +

    0638

    +
    cl_pch_incompatible_with_multiple_inputs:
    +
    precompiled header files may not be used when compiling several input +files
    +
    +

    0639

    +
    not_enough_preallocated_memory:
    +
    insufficient preallocated memory for generation of precompiled header +file (xxxx bytes required)
    +
    +

    0640

    +
    program_entity_too_large_for_pch:
    +
    very large entity in program prevents generation of precompiled +header file
    +
    +

    0641

    +
    cannot_chdir:
    +
    “xxxx” is not a valid directory
    +
    +

    0642

    +
    cannot_build_temp_file_name:
    +
    cannot build temporary file name
    +
    +

    0643

    +
    restrict_not_allowed:
    +
    “restrict” is not allowed
    +
    +

    0644

    +
    restrict_pointer_to_function:
    +
    a pointer or reference to function type may not be qualified by +“restrict”
    +
    +

    0646

    +
    calling_convention_not_allowed:
    +
    a calling convention modifier may not be specified here
    +
    +

    0647

    +
    conflicting_calling_conventions:
    +
    conflicting calling convention modifiers
    +
    +

    0648

    +
    cl_strict_mode_incompatible_with_microsoft:
    +
    strict mode is incompatible with Microsoft mode
    +
    +

    0649

    +
    cl_cfront_incompatible_with_microsoft:
    +
    cfront mode is incompatible with Microsoft mode
    +
    +

    0650

    +
    calling_convention_ignored:
    +
    calling convention specified here is ignored
    +
    +

    0651

    +
    calling_convention_may_not_precede_nested_declarator:
    +
    a calling convention may not be followed by a nested declarator
    +
    +

    0652

    +
    calling_convention_ignored_for_type:
    +
    calling convention is ignored for this type
    +
    +

    0654

    +
    decl_modifiers_incompatible_with_previous_decl:
    +
    declaration modifiers are incompatible with previous declaration
    +
    +

    0655

    +
    decl_modifiers_invalid_for_this_decl:
    +
    the modifier “xxxx” is not allowed on this declaration
    +
    +

    0656

    +
    branch_into_try_block:
    +
    transfer of control into a try block
    +
    +

    0657

    +
    incompatible_inline_specifier_on_specific_decl:
    +
    inline specification is incompatible with previous “entity”(declared at line xxxx)
    +
    +

    0658

    +
    template_missing_closing_brace:
    +
    closing brace of template definition not found
    +
    +

    0659

    +
    cl_wchar_t_option_only_in_cplusplus:
    +
    wchar_t keyword option can be used only when compiling C++
    +
    +

    0660

    +
    bad_pack_alignment:
    +
    invalid packing alignment value
    +
    +

    0661

    +
    exp_int_constant:
    +
    expected an integer constant
    +
    +

    0662

    +
    call_of_pure_virtual:
    +
    call of pure virtual function
    +
    +

    0663

    +
    bad_ident_string:
    +
    invalid source file identifier string
    +
    +

    0664

    +
    template_friend_definition_not_allowed:
    +
    a class template cannot be defined in a friend declaration
    +
    +

    0665

    +
    asm_not_allowed:
    +
    “asm” is not allowed
    +
    +

    0666

    +
    bad_asm_function_def:
    +
    “asm” must be used with a function definition
    +
    +

    0667

    +
    nonstd_asm_function:
    +
    “asm” function is nonstandard
    +
    +

    0668

    +
    nonstd_ellipsis_only_param:
    +
    ellipsis with no explicit parameters is nonstandard
    +
    +

    0669

    +
    nonstd_address_of_ellipsis:
    +
    “&…” is nonstandard
    +
    +

    0670

    +
    bad_address_of_ellipsis:
    +
    invalid use of “&…”
    +
    +

    0672

    +
    const_volatile_ref_init_anachronism:
    +
    temporary used for initial value of reference to const volatile +(anachronism)
    +
    +

    0673

    +
    bad_const_volatile_ref_init:
    +
    a reference of type “type” cannot be initialized with a value of +type “type”
    +
    +

    0674

    +
    const_volatile_ref_init_from_rvalue:
    +
    initial value of reference to const volatile must be an lvalue
    +
    +

    0675

    +
    cl_SVR4_C_option_only_in_ansi_C:
    +
    SVR4 C compatibility option can be used only when compiling ANSI C
    +
    +

    0676

    +
    using_out_of_scope_declaration:
    +
    using out-of-scope declaration of entity-kind “entity” (declared +at line xxxx)
    +
    +

    0677

    +
    cl_strict_mode_incompatible_with_SVR4:
    +
    strict mode is incompatible with SVR4 C mode
    +
    +

    0678

    +
    cannot_inline_call:
    +
    call of entity-kind “entity” (declared at line xxxx) cannot +be inlined
    +
    +

    0679

    +
    cannot_inline:
    +
    entity-kind “entity” cannot be inlined
    +
    +

    0680

    +
    cl_invalid_pch_directory:
    +
    invalid PCH directory: xxxx
    +
    +

    0681

    +
    exp_except_or_finally:
    +
    expected __except or __finally
    +
    +

    0682

    +
    leave_must_be_in_try:
    +
    a __leave statement may only be used within a __try
    +
    +

    0688

    +
    not_found_on_pack_alignment_stack:
    +
    “xxxx” not found on pack alignment stack
    +
    +

    0689

    +
    empty_pack_alignment_stack:
    +
    empty pack alignment stack
    +
    +

    0690

    +
    cl_rtti_option_only_in_cplusplus:
    +
    RTTI option can be used only when compiling C++
    +
    +

    0691

    +
    inaccessible_elided_cctor:
    +
    entity-kind “entity” (declared at line xxxx), required for +copy that was eliminated, is inaccessible
    +
    +

    0692

    +
    uncallable_elided_cctor:
    +
    entity-kind “entity”, required for copy that was eliminated, is +not callable because reference parameter cannot be bound to rvalue
    +
    +

    0693

    +
    typeid_needs_typeinfo:
    +
    <typeinfo> must be included before typeid is used
    +
    +

    0694

    +
    cannot_cast_away_const:
    +
    xxxx cannot cast away const or other type qualifiers
    +
    +

    0695

    +
    bad_dynamic_cast_type:
    +
    the type in a dynamic_cast must be a pointer or reference to a +complete class type, or void *
    +
    +

    0696

    +
    bad_ptr_dynamic_cast_operand:
    +
    the operand of a pointer dynamic_cast must be a pointer to a complete +class type
    +
    +

    0697

    +
    bad_ref_dynamic_cast_operand:
    +
    the operand of a reference dynamic_cast must be an lvalue of a +complete class type
    +
    +

    0698

    +
    dynamic_cast_operand_must_be_polymorphic:
    +
    the operand of a runtime dynamic_cast must have a polymorphic class +type
    +
    +

    0699

    +
    cl_bool_option_only_in_cplusplus:
    +
    bool option can be used only when compiling C++
    +
    +

    0701

    +
    array_type_not_allowed:
    +
    an array type is not allowed here
    +
    +

    0702

    +
    exp_assign:
    +
    expected an “=”
    +
    +

    0704

    +
    redeclaration_of_condition_decl_name:
    +
    “xxxx”, declared in condition, may not be redeclared in this scope
    +
    +

    0705

    +
    default_template_arg_not_allowed:
    +
    default template arguments are not allowed for function templates
    +
    +

    0706

    +
    exp_comma_or_gt:
    +
    expected a “,” or “>”
    +
    +

    0707

    +
    missing_template_param_list:
    +
    expected a template parameter list
    +
    +

    0708

    +
    incr_of_bool_deprecated:
    +
    incrementing a bool value is deprecated
    +
    +

    0709

    +
    bool_type_not_allowed:
    +
    bool type is not allowed
    +
    +

    0710

    +
    base_class_offset_too_large:
    +
    offset of base class “entity” within class “entity” is too +large
    +
    +

    0711

    +
    expr_not_bool:
    +
    expression must have bool type (or be convertible to bool)
    +
    +

    0712

    +
    cl_array_new_and_delete_option_only_in_cplusplus:
    +
    array new and delete option can be used only when compiling C++
    +
    +

    0713

    +
    based_requires_variable_name:
    +
    entity-kind “entity” is not a variable name
    +
    +

    0714

    +
    based_not_allowed_here:
    +
    __based modifier is not allowed here
    +
    +

    0715

    +
    based_not_followed_by_star:
    +
    __based does not precede a pointer operator, __based ignored
    +
    +

    0716

    +
    based_var_must_be_ptr:
    +
    variable in __based modifier must have pointer type
    +
    +

    0717

    +
    bad_const_cast_type:
    +
    the type in a const_cast must be a pointer, reference, or pointer to +member to an object type
    +
    +

    0718

    +
    bad_const_cast:
    +
    a const_cast can only adjust type qualifiers; it cannot change the +underlying type
    +
    +

    0719

    +
    mutable_not_allowed:
    +
    mutable is not allowed
    +
    +

    0720

    +
    cannot_change_access:
    +
    redeclaration of entity-kind “entity” is not allowed to alter its +access
    +
    +

    0722

    +
    probable_inadvertent_lbracket_digraph:
    +
    use of alternative token “<:” appears to be unintended
    +
    +

    0723

    +
    probable_inadvertent_sharp_digraph:
    +
    use of alternative token “%:” appears to be unintended
    +
    +

    0724

    +
    namespace_def_not_allowed:
    +
    namespace definition is not allowed
    +
    +

    0725

    +
    missing_namespace_name:
    +
    name must be a namespace name
    +
    +

    0726

    +
    namespace_alias_def_not_allowed:
    +
    namespace alias definition is not allowed
    +
    +

    0727

    +
    namespace_qualified_name_required:
    +
    namespace-qualified name is required
    +
    +

    0728

    +
    namespace_name_not_allowed:
    +
    a namespace name is not allowed
    +
    +

    0729

    +
    bad_combination_of_dll_attributes:
    +
    invalid combination of DLL attributes
    +
    +

    0730

    +
    sym_not_a_class_template:
    +
    entity-kind “entity” is not a class template
    +
    +

    0731

    +
    array_of_incomplete_type:
    +
    array with incomplete element type is nonstandard
    +
    +

    0732

    +
    allocation_operator_in_namespace:
    +
    allocation operator may not be declared in a namespace
    +
    +

    0733

    +
    deallocation_operator_in_namespace:
    +
    deallocation operator may not be declared in a namespace
    +
    +

    0734

    +
    conflicts_with_using_decl:
    +
    entity-kind “entity” conflicts with using-declaration of +entity-kind “entity”
    +
    +

    0735

    +
    using_decl_conflicts_with_prev_decl:
    +
    using-declaration of entity-kind “entity” conflicts with +entity-kind “entity” (declared at line xxxx)
    +
    +

    0736

    +
    cl_namespaces_option_only_in_cplusplus:
    +
    namespaces option can be used only when compiling C++
    +
    +

    0737

    +
    useless_using_declaration:
    +
    using-declaration ignored – it refers to the current namespace
    +
    +

    0738

    +
    class_qualified_name_required:
    +
    a class-qualified name is required
    +
    +

    0742

    +
    not_an_actual_member:
    +
    entity-kind “entity” has no actual member “xxxx”
    +
    +

    0744

    +
    mem_attrib_incompatible:
    +
    incompatible memory attributes specified
    +
    +

    0745

    +
    mem_attrib_ignored:
    +
    memory attribute ignored
    +
    +

    0746

    +
    mem_attrib_may_not_precede_nested_declarator:
    +
    memory attribute may not be followed by a nested declarator
    +
    +

    0747

    +
    dupl_mem_attrib:
    +
    memory attribute specified more than once
    +
    +

    0748

    +
    dupl_calling_convention:
    +
    calling convention specified more than once
    +
    +

    0749

    +
    type_qualifier_not_allowed:
    +
    a type qualifier is not allowed
    +
    +

    0750

    +
    template_instance_already_used:
    +
    entity-kind “entity” (declared at line xxxx) was used before +its template was declared
    +
    +

    0751

    +
    static_nonstatic_with_same_param_types:
    +
    static and nonstatic member functions with same parameter types +cannot be overloaded
    +
    +

    0752

    +
    no_prior_declaration:
    +
    no prior declaration of entity-kind “entity”
    +
    +

    0753

    +
    template_id_not_allowed:
    +
    a template-id is not allowed
    +
    +

    0754

    +
    class_qualified_name_not_allowed:
    +
    a class-qualified name is not allowed
    +
    +

    0755

    +
    bad_scope_for_redeclaration:
    +
    entity-kind “entity” may not be redeclared in the current scope
    +
    +

    0756

    +
    qualifier_in_namespace_member_decl:
    +
    qualified name is not allowed in namespace member declaration
    +
    +

    0757

    +
    sym_not_a_type_name:
    +
    entity-kind “entity” is not a type name
    +
    +

    0758

    +
    explicit_instantiation_not_in_namespace_scope:
    +
    explicit instantiation is not allowed in the current scope
    +
    +

    0759

    +
    bad_scope_for_explicit_instantiation:
    +
    entity-kind “entity” cannot be explicitly instantiated in the +current scope
    +
    +

    0760

    +
    multiple_explicit_instantiations:
    +
    entity-kind “entity” explicitly instantiated more than once
    +
    +

    0761

    +
    typename_not_in_template:
    +
    typename may only be used within a template
    +
    +

    0762

    +
    cl_special_subscript_cost_option_only_in_cplusplus:
    +
    special_subscript_cost option can be used only when compiling C++
    +
    +

    0763

    +
    cl_typename_option_only_in_cplusplus:
    +
    typename option can be used only when compiling C++
    +
    +

    0764

    +
    cl_implicit_typename_option_only_in_cplusplus:
    +
    implicit typename option can be used only when compiling C++
    +
    +

    0765

    +
    nonstd_character_at_start_of_macro_def:
    +
    nonstandard character at start of object-like macro definition
    +
    +

    0766

    +
    exception_spec_override_incompat:
    +
    exception specification for virtual entity-kind “entity” is +incompatible with that of overridden entity-kind “entity”
    +
    +

    0767

    +
    pointer_conversion_loses_bits:
    +
    conversion from pointer to smaller integer
    +
    +

    0768

    +
    generated_exception_spec_override_incompat:
    +
    exception specification for implicitly declared virtual entity-kind +“entity” is incompatible with that of overridden entity-kind +“entity”
    +
    +

    0769

    +
    implicit_call_of_ambiguous_name:
    +
    “entity”, implicitly called from entity-kind “entity”, is +ambiguous
    +
    +

    0770

    +
    cl_explicit_option_only_in_cplusplus:
    +
    option “explicit” can be used only when compiling C++
    +
    +

    0771

    +
    explicit_not_allowed:
    +
    “explicit” is not allowed
    +
    +

    0772

    +
    conflicts_with_predeclared_type_info:
    +
    declaration conflicts with “xxxx” (reserved class name)
    +
    +

    0773

    +
    array_member_initialization:
    +
    only “()” is allowed as initializer for array entity-kind “entity”
    +
    +

    0774

    +
    virtual_function_template:
    +
    “virtual” is not allowed in a function template declaration
    +
    +

    0775

    +
    anon_union_class_member_template:
    +
    invalid anonymous union – class member template is not allowed
    +
    +

    0776

    +
    template_depth_mismatch:
    +
    template nesting depth does not match the previous declaration of +entity-kind “entity”
    +
    +

    0777

    +
    multiple_template_decls_not_allowed:
    +
    this declaration cannot have multiple “template <…>” clauses
    +
    +

    0778

    +
    cl_old_for_init_option_only_in_cplusplus:
    +
    option to control the for-init scope can be used only when compiling +C++
    +
    +

    0779

    +
    redeclaration_of_for_init_decl_name:
    +
    “xxxx”, declared in for-loop initialization, may not be +redeclared in this scope
    +
    +

    0780

    +
    hidden_by_old_for_init:
    +
    reference is to entity-kind “entity” (declared at line xxxx) +– under old for-init scoping rules it would have been entity-kind +“entity” (declared at line xxxx)
    +
    +

    0781

    +
    cl_for_init_diff_warning_option_only_in_cplusplus:
    +
    option to control warnings on for-init differences can be used only +when compiling C++
    +
    +

    0782

    +
    unnamed_class_virtual_function_def_missing:
    +
    definition of virtual entity-kind “entity” is required here
    +
    +

    0783

    +
    svr4_token_pasting_comment:
    +
    empty comment interpreted as token-pasting operator “##”
    +
    +

    0784

    +
    storage_class_in_friend_decl:
    +
    a storage class is not allowed in a friend declaration
    +
    +

    0785

    +
    templ_param_list_not_allowed:
    +
    template parameter list for “entity” is not allowed in this +declaration
    +
    +

    0786

    +
    bad_member_template_sym:
    +
    entity-kind “entity” is not a valid class member template
    +
    +

    0787

    +
    bad_member_template_decl:
    +
    not a valid member class or function template declaration
    +
    +

    0788

    +
    specialization_follows_param_list:
    +
    a template declaration containing a template parameter list may not +be followed by an explicit specialization declaration
    +
    +

    0789

    +
    specialization_of_referenced_template:
    +
    explicit specialization of entity-kind “entity” must precede the +first use of entity-kind “entity”
    +
    +

    0790

    +
    explicit_specialization_not_in_namespace_scope:
    +
    explicit specialization is not allowed in the current scope
    +
    +

    0791

    +
    partial_specialization_not_allowed:
    +
    partial specialization of entity-kind “entity” is not allowed
    +
    +

    0792

    +
    entity_cannot_be_specialized:
    +
    entity-kind “entity” is not an entity that can be explicitly +specialized
    +
    +

    0793

    +
    specialization_of_referenced_entity:
    +
    explicit specialization of entity-kind “entity” must precede its +first use
    +
    +

    0794

    +
    template_param_in_elab_type:
    +
    template parameter “xxxx” may not be used in an elaborated type +specifier
    +
    +

    0795

    +
    old_specialization_not_allowed:
    +
    specializing entity-kind “entity” requires “template<>” syntax
    +
    +

    0798

    +
    cl_old_specializations_option_only_in_cplusplus:
    +
    option “old_specializations” can be used only when compiling C++
    +
    +

    0799

    +
    nonstd_old_specialization:
    +
    specializing entity-kind “entity” without “template<>” syntax is +nonstandard
    +
    +

    0800

    +
    bad_linkage_for_decl:
    +
    this declaration may not have extern “C” linkage
    +
    +

    0801

    +
    not_a_template_name:
    +
    “xxxx” is not a class or function template name in the current +scope
    +
    +

    0802

    +
    nonstd_default_arg_on_function_template_redecl:
    +
    specifying a default argument when redeclaring an unreferenced +function template is nonstandard
    +
    +

    0803

    +
    default_arg_on_function_template_not_allowed:
    +
    specifying a default argument when redeclaring an already referenced +function template is not allowed
    +
    +

    0804

    +
    pm_derived_class_from_virtual_base:
    +
    cannot convert pointer to member of base class “type” to pointer +to member of derived class “type” – base class is virtual
    +
    +

    0805

    +
    bad_exception_specification_for_specialization:
    +
    exception specification is incompatible with that of entity-kind +“entity” (declared at line xxxx):
    +
    +

    0806

    +
    omitted_exception_specification_on_specialization:
    +
    allowing all exceptions is incompatible with entity-kind “entity”(declared at line xxxx)
    +
    +

    0807

    +
    unexpected_end_of_default_arg:
    +
    unexpected end of default argument expression
    +
    +

    0808

    +
    default_init_of_reference:
    +
    default-initialization of reference is not allowed
    +
    +

    0809

    +
    uninitialized_field_with_const_member:
    +
    uninitialized entity-kind “entity” has a const member
    +
    +

    0810

    +
    uninitialized_base_class_with_const_member:
    +
    uninitialized base class “type” has a const member
    +
    +

    0811

    +
    missing_default_constructor_on_const:
    +
    const entity-kind “entity” requires an initializer – class +“type” has no user-provided default constructor
    +
    +

    0812

    +
    missing_default_constructor_on_unnamed_const:
    +
    const object requires an initializer – class “type” has no +user-provided default constructor
    +
    +

    0813

    +
    cl_impl_extern_c_conv_option_only_in_cplusplus:
    +
    option “implicit_extern_c_type_conversion” can be used only when +compiling C++
    +
    +

    0814

    +
    cl_strict_mode_incompatible_with_long_preserving:
    +
    strict mode is incompatible with long preserving rules
    +
    +

    0815

    +
    useless_type_qualifier_on_return_type:
    +
    type qualifier on return type is meaningless
    +
    +

    0816

    +
    type_qualifier_on_void_return_type:
    +
    in a function definition a type qualifier on a “void” return type is +not allowed
    +
    +

    0817

    +
    static_data_member_not_allowed:
    +
    static data member declaration is not allowed in this class
    +
    +

    0818

    +
    invalid_declaration:
    +
    template instantiation resulted in an invalid function declaration
    +
    +

    0819

    +
    ellipsis_not_allowed:
    +
    “…” is not allowed
    +
    +

    0820

    +
    cl_extern_inline_option_only_in_cplusplus:
    +
    option “extern_inline” can be used only when compiling C++
    +
    +

    0821

    +
    extern_inline_never_defined:
    +
    extern inline entity-kind “entity” was referenced but not defined
    +
    +

    0822

    +
    invalid_destructor_name:
    +
    invalid destructor name for type “type”
    +
    +

    0824

    +
    ambiguous_destructor:
    +
    destructor reference is ambiguous – both entity-kind “entity”and entity-kind “entity” could be used
    +
    +

    0825

    +
    virtual_inline_never_defined:
    +
    virtual inline entity-kind “entity” was never defined
    +
    +

    0826

    +
    unreferenced_function_param:
    +
    entity-kind “entity” was never referenced
    +
    +

    0827

    +
    union_already_initialized:
    +
    only one member of a union may be specified in a constructor +initializer list
    +
    +

    0828

    +
    no_array_new_and_delete_support:
    +
    support for “new[]” and “delete[]” is disabled
    +
    +

    0829

    +
    double_for_long_double:
    +
    “double” used for “long double” in generated C code
    +
    +

    0830

    +
    no_corresponding_delete:
    +
    entity-kind “entity” has no corresponding operator delete*xxxx*(to be called if an exception is thrown during initialization of an +allocated object)
    +
    +

    0831

    +
    useless_placement_delete:
    +
    support for placement delete is disabled
    +
    +

    0832

    +
    no_appropriate_delete:
    +
    no appropriate operator delete is visible
    +
    +

    0833

    +
    ptr_or_ref_to_incomplete_type:
    +
    pointer or reference to incomplete type “type” is not allowed
    +
    +

    0834

    +
    bad_partial_specialization:
    +
    invalid partial specialization – entity-kind “entity” is already +fully specialized
    +
    +

    0835

    +
    incompatible_exception_specs:
    +
    incompatible exception specifications
    +
    +

    0836

    +
    returning_ref_to_local_variable:
    +
    returning reference to local variable
    +
    +

    0837

    +
    nonstd_implicit_int:
    +
    omission of explicit type is nonstandard (“int” assumed)
    +
    +

    0838

    +
    ambiguous_partial_spec:
    +
    more than one partial specialization matches the template argument +list of entity-kind “entity”
    +
    +

    0840

    +
    partial_spec_is_primary_template:
    +
    a template argument list is not allowed in a declaration of a primary +template
    +
    +

    0841

    +
    default_not_allowed_on_partial_spec:
    +
    partial specializations may not have default template arguments
    +
    +

    0842

    +
    not_used_in_partial_spec_arg_list:
    +
    entity-kind “entity” is not used in or cannot be deduced from the +template argument list of entity-kind “entity”
    +
    +

    0844

    +
    partial_spec_arg_depends_on_templ_param:
    +
    the template argument list of the partial specialization includes a +nontype argument whose type depends on a template parameter
    +
    +

    0845

    +
    partial_spec_after_instantiation:
    +
    this partial specialization would have been used to instantiate +entity-kind “entity”
    +
    +

    0846

    +
    partial_spec_after_instantiation_ambiguous:
    +
    this partial specialization would have made the instantiation of +entity-kind “entity” ambiguous
    +
    +

    0847

    +
    expr_not_integral_or_enum:
    +
    expression must have integral or enum type
    +
    +

    0848

    +
    expr_not_arithmetic_or_enum:
    +
    expression must have arithmetic or enum type
    +
    +

    0849

    +
    expr_not_arithmetic_or_enum_or_pointer:
    +
    expression must have arithmetic, enum, or pointer type
    +
    +

    0850

    +
    cast_not_integral_or_enum:
    +
    type of cast must be integral or enum
    +
    +

    0851

    +
    cast_not_arithmetic_or_enum_or_pointer:
    +
    type of cast must be arithmetic, enum, or pointer
    +
    +

    0852

    +
    expr_not_object_pointer:
    +
    expression must be a pointer to a complete object type
    +
    +

    0855

    +
    different_return_type_on_virtual_function_override:
    +
    return type is not identical to return type “type” of overridden +virtual function “entity”
    +
    +

    0856

    +
    cl_guiding_decls_option_only_in_cplusplus:
    +
    option “guiding_decls” can be used only when compiling C++
    +
    +

    0857

    +
    member_partial_spec_not_in_namespace:
    +
    a partial specialization of a class template must be declared in the +namespace of which it is a member
    +
    +

    0858

    +
    pure_virtual_function:
    +
    entity-kind “entity” is a pure virtual function
    +
    +

    0859

    +
    no_overrider_for_pure_virtual_function:
    +
    pure virtual entity-kind “entity” has no overrider
    +
    +

    0860

    +
    decl_modifiers_ignored:
    +
    __declspec attributes ignored
    +
    +

    0861

    +
    invalid_char:
    +
    invalid character in input line
    +
    +

    0862

    +
    incomplete_return_type:
    +
    function returns incomplete type “type”
    +
    +

    0863

    +
    local_pragma_pack:
    +
    effect of this “#pragma pack” directive is local to entity-kind +“entity”
    +
    +

    0864

    +
    not_a_template:
    +
    xxxx is not a template
    +
    +

    0865

    +
    friend_partial_specialization:
    +
    a friend declaration may not declare a partial specialization
    +
    +

    0866

    +
    exception_specification_ignored:
    +
    exception specification ignored
    +
    +

    0867

    +
    unexpected_type_for_size_t:
    +
    declaration of “size_t” does not match the expected type “type”
    +
    +

    0868

    +
    exp_gt_not_shift_right:
    +
    space required between adjacent “>” delimiters of nested template +argument lists (“>>” is the right shift operator)
    +
    +

    0869

    +
    bad_multibyte_char_locale:
    +
    could not set locale “xxxx” to allow processing of multibyte +characters
    +
    +

    0870

    +
    bad_multibyte_char:
    +
    invalid multibyte character sequence
    +
    +

    0871

    +
    bad_type_from_instantiation:
    +
    template instantiation resulted in unexpected function type of +“type” (the meaning of a name may have changed since the template +declaration – the type of the template is “type”)
    +
    +

    0872

    +
    ambiguous_guiding_decl:
    +
    ambiguous guiding declaration – more than one function template +“entity” matches type “type”
    +
    +

    0873

    +
    non_integral_operation_in_templ_arg:
    +
    non-integral operation not allowed in nontype template argument
    +
    +

    0874

    +
    cl_embedded_cplusplus_option_only_in_cplusplus:
    +
    option “embedded_c++” can be used only when compiling C++
    +
    +

    0875

    +
    templates_in_embedded_cplusplus:
    +
    Embedded C++ does not support templates
    +
    +

    0876

    +
    exceptions_in_embedded_cplusplus:
    +
    Embedded C++ does not support exception handling
    +
    +

    0877

    +
    namespaces_in_embedded_cplusplus:
    +
    Embedded C++ does not support namespaces
    +
    +

    0878

    +
    rtti_in_embedded_cplusplus:
    +
    Embedded C++ does not support run-time type information
    +
    +

    0879

    +
    new_cast_in_embedded_cplusplus:
    +
    Embedded C++ does not support the new cast syntax
    +
    +

    0880

    +
    using_decl_in_embedded_cplusplus:
    +
    Embedded C++ does not support using-declarations
    +
    +

    0881

    +
    mutable_in_embedded_cplusplus:
    +
    Embedded C++ does not support “mutable”
    +
    +

    0882

    +
    multiple_inheritance_in_embedded_cplusplus:
    +
    Embedded C++ does not support multiple or virtual inheritance
    +
    +

    0883

    +
    cl_invalid_microsoft_version:
    +
    invalid Microsoft version number: xxxx
    +
    +

    0884

    +
    inheritance_kind_already_set:
    +
    pointer-to-member representation “xxxx” has already been set for +entity-kind “entity”
    +
    +

    0885

    +
    bad_constructor_type:
    +
    “type” cannot be used to designate constructor for “type”
    +
    +

    0886

    +
    bad_suffix:
    +
    invalid suffix on integral constant
    +
    +

    0887

    +
    uuidof_requires_uuid_class_type:
    +
    operand of __uuidof must have a class or enum type for which +__declspec(uuid(”…”)) has been specified
    +
    +

    0888

    +
    bad_uuid_string:
    +
    invalid GUID string in __declspec(uuid(”…”))
    +
    +

    0889

    +
    cl_vla_option_only_in_C:
    +
    option “vla” can be used only when compiling C
    +
    +

    0890

    +
    vla_with_unspecified_bound_not_allowed:
    +
    variable length array with unspecified bound is not allowed
    +
    +

    0891

    +
    explicit_template_args_not_allowed:
    +
    an explicit template argument list is not allowed on this declaration
    +
    +

    0892

    +
    variably_modified_type_not_allowed:
    +
    an entity with linkage cannot have a type involving a variable length +array
    +
    +

    0893

    +
    vla_is_not_auto:
    +
    a variable length array cannot have static storage duration
    +
    +

    0894

    +
    sym_not_a_template:
    +
    entity-kind “entity” is not a template
    +
    +

    0896

    +
    expected_template_arg:
    +
    expected a template argument
    +
    +

    0898

    +
    no_params_with_class_or_enum_type:
    +
    nonmember operator requires a parameter with class or enum type
    +
    +

    0899

    +
    cl_enum_overloading_option_only_in_cplusplus:
    +
    option “enum_overloading” can be used only when compiling C++
    +
    +

    0901

    +
    destructor_qualifier_type_mismatch:
    +
    qualifier of destructor name “type” does not match type “type”
    +
    +

    0902

    +
    type_qualifier_ignored:
    +
    type qualifier ignored
    +
    +

    0903

    +
    cl_nonstandard_qualifier_deduction_option_only_in_cplusplus:
    +
    option “nonstd_qualifier_deduction” can be used only when compiling +C++
    +
    +

    0904

    +
    cannot_define_dllimport_function:
    +
    a function declared “dllimport” may not be defined
    +
    +

    0905

    +
    bad_declspec_property:
    +
    incorrect property specification; correct form is +__declspec(property(get=name1,put=name2))
    +
    +

    0906

    +
    dupl_get_or_put:
    +
    property has already been specified
    +
    +

    0907

    +
    declspec_property_not_allowed:
    +
    __declspec(property) is not allowed on this declaration
    +
    +

    0908

    +
    no_get_property:
    +
    member is declared with __declspec(property), but no “get” function +was specified
    +
    +

    0909

    +
    get_property_function_missing:
    +
    the __declspec(property) “get” function “xxxx” is missing
    +
    +

    0910

    +
    no_put_property:
    +
    member is declared with __declspec(property), but no “put” function +was specified
    +
    +

    0911

    +
    put_property_function_missing:
    +
    the __declspec(property) “put” function “xxxx” is missing
    +
    +

    0912

    +
    dual_lookup_ambiguous_name:
    +
    ambiguous class member reference – entity-kind “entity”(declared at line xxxx) used in preference to entity-kind +“entity” (declared at line xxxx)
    +
    +

    0916

    +
    pm_virtual_base_from_derived_class:
    +
    cannot convert pointer to member of derived class “type” to +pointer to member of base class “type” – base class is virtual
    +
    +

    0917

    +
    cl_invalid_instantiation_directory:
    +
    invalid directory for instantiation files: xxxx
    +
    +

    0918

    +
    cl_one_instantiation_per_object_option_only_in_cplusplus:
    +
    option “one_instantiation_per_object” can be used only when compiling +C++
    +
    +

    0921

    +
    cl_ii_file_name_incompatible_with_multiple_inputs:
    +
    an instantiation information file name may not be specified when +compiling several input files
    +
    +

    0922

    +
    cl_one_instantiation_per_object_incompatible_with_multiple_inputs:
    +
    option “one_instantiation_per_object” may not be used when compiling +several input files
    +
    +

    0923

    +
    cl_ambiguous_option:
    +
    more than one command line option matches the abbreviation +“–xxxx“:
    +
    +

    0925

    +
    cv_qualified_function_type:
    +
    type qualifiers on function types are ignored
    +
    +

    0927

    +
    cl_late_tiebreaker_option_only_in_cplusplus:
    +
    late/early tiebreaker option can be used only when compiling C++
    +
    +

    0928

    +
    bad_va_start:
    +
    incorrect use of va_start
    +
    +

    0929

    +
    bad_va_arg:
    +
    incorrect use of va_arg
    +
    +

    0930

    +
    bad_va_end:
    +
    incorrect use of va_end
    +
    +

    0931

    +
    cl_pending_instantiations_option_only_in_cplusplus:
    +
    pending instantiations option can be used only when compiling C++
    +
    +

    0932

    +
    cl_invalid_import_directory:
    +
    invalid directory for #import files: xxxx
    +
    +

    0933

    +
    cl_import_only_in_microsoft:
    +
    an import directory can be specified only in Microsoft mode
    +
    +

    0934

    +
    ref_not_allowed_in_union:
    +
    a member with reference type is not allowed in a union
    +
    +

    0935

    +
    typedef_not_allowed:
    +
    “typedef” may not be specified here
    +
    +

    0936

    +
    redecl_changes_access:
    +
    redeclaration of entity-kind “entity” alters its access
    +
    +

    0937

    +
    qualified_name_required:
    +
    a class or namespace qualified name is required
    +
    +

    0938

    +
    implicit_int_on_main:
    +
    return type “int” omitted in declaration of function “main”
    +
    +

    0939

    +
    invalid_inheritance_kind_for_class:
    +
    pointer-to-member representation “xxxx” is too restrictive for +entity-kind “entity”
    +
    +

    0940

    +
    implicit_return_from_non_void_function:
    +
    missing return statement at end of non-void entity-kind “entity”
    +
    +

    0941

    +
    duplicate_using_decl:
    +
    duplicate using-declaration of “entity” ignored
    +
    +

    0942

    +
    unsigned_enum_bit_field_with_signed_enumerator:
    +
    enum bit fields are always unsigned, but enum “type” includes +negative enumerator
    +
    +

    0943

    +
    cl_class_name_injection_option_only_in_cplusplus:
    +
    option “class_name_injection” can be used only when compiling C++
    +
    +

    0944

    +
    cl_arg_dependent_lookup_option_only_in_cplusplus:
    +
    option “arg_dep_lookup” can be used only when compiling C++
    +
    +

    0945

    +
    cl_friend_injection_option_only_in_cplusplus:
    +
    option “friend_injection” can be used only when compiling C++
    +
    +

    0946

    +
    invalid_name_after_template:
    +
    name following “template” must be a template
    +
    +

    0948

    +
    local_class_friend_requires_prior_decl:
    +
    nonstandard local-class friend declaration – no prior declaration in +the enclosing scope
    +
    +

    0949

    +
    nonstd_default_arg:
    +
    specifying a default argument on this declaration is nonstandard
    +
    +

    0950

    +
    cl_nonstd_using_decl_option_only_in_cplusplus:
    +
    option “nonstd_using_decl” can be used only when compiling C++
    +
    +

    0951

    +
    bad_return_type_on_main:
    +
    return type of function “main” must be “int”
    +
    +

    0952

    +
    template_parameter_has_class_type:
    +
    a nontype template parameter may not have class type
    +
    +

    0953

    +
    default_arg_on_member_decl:
    +
    a default template argument cannot be specified on the definition of +a member of a class template outside the template
    +
    +

    0954

    +
    return_from_ctor_function_try_block_handler:
    +
    a return statement is not allowed in a handler of a function try +block of a constructor
    +
    +

    0955

    +
    no_ordinary_and_extended_designators:
    +
    ordinary and extended designators cannot be combined in an +initializer designation
    +
    +

    0956

    +
    no_negative_designator_range:
    +
    the second subscript must not be smaller than the first
    +
    +

    0958

    +
    cl_extended_designators_option_only_in_C:
    +
    option “extended_designators” can be used only when compiling C
    +
    +

    0959

    +
    extra_bits_ignored:
    +
    declared size for bit field is larger than the size of the bit field +type; truncated to xxxx bits
    +
    +

    0960

    +
    constructor_type_mismatch:
    +
    type used as constructor name does not match type “type”
    +
    +

    0961

    +
    type_with_no_linkage_in_var_with_linkage:
    +
    use of a type with no linkage to declare a variable with linkage
    +
    +

    0962

    +
    type_with_no_linkage_in_function:
    +
    use of a type with no linkage to declare a function
    +
    +

    0963

    +
    return_type_on_constructor:
    +
    return type may not be specified on a constructor
    +
    +

    0964

    +
    return_type_on_destructor:
    +
    return type may not be specified on a destructor
    +
    +

    0965

    +
    malformed_universal_character:
    +
    incorrectly formed universal character name
    +
    +

    0966

    +
    invalid_UCN:
    +
    universal character name specifies an invalid character
    +
    +

    0967

    +
    UCN_names_basic_char:
    +
    a universal character name cannot designate a character in the basic +character set
    +
    +

    0968

    +
    invalid_identifier_UCN:
    +
    this universal character is not allowed in an identifier
    +
    +

    0969

    +
    VA_ARGS_not_allowed:
    +
    the identifier __VA_ARGS__ can only appear in the replacement lists +of variadic macros
    +
    +

    0970

    +
    friend_qualification_ignored:
    +
    the qualifier on this friend declaration is ignored
    +
    +

    0971

    +
    no_range_designator_with_dynamic_init:
    +
    array range designators cannot be applied to dynamic initializers
    +
    +

    0972

    +
    property_name_not_allowed:
    +
    property name cannot appear here
    +
    +

    0973

    +
    inline_qualifier_ignored:
    +
    “inline” used as a function qualifier is ignored
    +
    +

    0974

    +
    cl_compound_literals_option_only_in_C:
    +
    option “compound_literals” can be used only when compiling C
    +
    +

    0975

    +
    vla_not_allowed:
    +
    a variable-length array type is not allowed
    +
    +

    0976

    +
    bad_integral_compound_literal:
    +
    a compound literal is not allowed in an integral constant expression
    +
    +

    0977

    +
    bad_compound_literal_type:
    +
    a compound literal of type “type” is not allowed
    +
    +

    0978

    +
    friend_template_in_local_class:
    +
    a template friend declaration cannot be declared in a local class
    +
    +

    0979

    +
    ambiguous_question_operator:
    +
    ambiguous “?” operation: second operand of type “type” can be +converted to third operand type “type”, and vice versa
    +
    +

    0980

    +
    bad_call_of_class_object:
    +
    call of an object of a class type without appropriate operator() or +conversion functions to pointer-to-function type
    +
    +

    0982

    +
    ambiguous_class_call:
    +
    there is more than one way an object of type “type” can be called +for the argument list:
    +
    +

    0983

    +
    similar_typedef:
    +
    typedef name has already been declared (with similar type)
    +
    +

    0984

    +
    no_internal_linkage_for_new_or_delete:
    +
    operator new and operator delete cannot be given internal linkage
    +
    +

    0985

    +
    no_mutable_allowed_on_anonymous_union:
    +
    storage class “mutable” is not allowed for anonymous unions
    +
    +

    0986

    +
    bad_pch_file:
    +
    invalid precompiled header file
    +
    +

    0987

    +
    abstract_class_catch_type:
    +
    abstract class type “type” is not allowed as catch type:
    +
    +

    0988

    +
    bad_qualified_function_type:
    +
    a qualified function type cannot be used to declare a nonmember +function or a static member function
    +
    +

    0989

    +
    bad_qualified_function_type_parameter:
    +
    a qualified function type cannot be used to declare a parameter
    +
    +

    0990

    +
    ptr_or_ref_to_qualified_function_type:
    +
    cannot create a pointer or reference to qualified function type
    +
    +

    0991

    +
    nonstd_braces:
    +
    extra braces are nonstandard
    +
    +

    0992

    +
    bad_cmd_line_macro:
    +
    invalid macro definition: xxxx
    +
    +

    0993

    +
    nonstandard_ptr_minus_ptr:
    +
    subtraction of pointer types “type” and “type” is nonstandard
    +
    +

    0994

    +
    empty_template_param_list:
    +
    an empty template parameter list is not allowed in a template +template parameter declaration
    +
    +

    0995

    +
    exp_class:
    +
    expected “class”
    +
    +

    0996

    +
    struct_not_allowed:
    +
    the “struct” keyword may not be used when declaring a template +template parameter
    +
    +

    0997

    +
    virtual_function_decl_hidden:
    +
    entity-kind “entity” is hidden by “entity” – virtual +function override intended?
    +
    +

    0998

    +
    no_qualified_friend_definition:
    +
    a qualified name is not allowed for a friend declaration that is a +function definition
    +
    +

    0999

    +
    not_compatible_with_templ_templ_param:
    +
    entity-kind “entity” is not compatible with entity-kind +“entity”
    +
    +

    1000

    +
    storage_class_requires_function_or_variable:
    +
    a storage class may not be specified here
    +
    +

    1001

    +
    member_using_must_be_visible_in_direct_base:
    +
    class member designated by a using-declaration must be visible in a +direct base class
    +
    +

    1003

    +
    cl_sun_incompatible_with_cfront:
    +
    Sun mode is incompatible with cfront mode
    +
    +

    1004

    +
    cl_strict_mode_incompatible_with_sun:
    +
    strict mode is incompatible with Sun mode
    +
    +

    1005

    +
    cl_sun_mode_only_in_cplusplus:
    +
    Sun mode is only allowed when compiling C++
    +
    +

    1006

    +
    template_template_param_same_name_as_templ_param:
    +
    a template template parameter cannot have the same name as one of its +template parameters
    +
    +

    1007

    +
    recursive_def_arg_instantiation:
    +
    recursive instantiation of default argument
    +
    +

    1009

    +
    bad_template_name:
    +
    entity-kind “entity” is not an entity that can be defined
    +
    +

    1010

    +
    destructor_name_must_be_qualified:
    +
    destructor name must be qualified
    +
    +

    1011

    +
    no_typename_in_friend_class_decl:
    +
    friend class name may not be introduced with “typename”
    +
    +

    1012

    +
    no_ctor_or_dtor_using_declaration:
    +
    a using-declaration may not name a constructor or destructor
    +
    +

    1013

    +
    friend_is_nonreal_template:
    +
    a qualified friend template declaration must refer to a specific +previously declared template
    +
    +

    1014

    +
    bad_class_template_decl:
    +
    invalid specifier in class template declaration
    +
    +

    1015

    +
    simple_incompatible_param:
    +
    argument is incompatible with formal parameter
    +
    +

    1016

    +
    cl_dep_name_option_only_in_cplusplus:
    +
    option “dep_name” can be used only when compiling C++
    +
    +

    1017

    +
    op_arrow_loop:
    +
    loop in sequence of “operator->” functions starting at class +“type”
    +
    +

    1018

    +
    not_a_member_class:
    +
    entity-kind “entity” has no member class “xxxx”
    +
    +

    1019

    +
    name_not_class_in_file_scope:
    +
    the global scope has no class named “xxxx”
    +
    +

    1020

    +
    recursive_inst_of_templ_default_arg:
    +
    recursive instantiation of template default argument
    +
    +

    1021

    +
    no_access_or_using_decl_in_union:
    +
    access declarations and using-declarations cannot appear in unions
    +
    +

    1022

    +
    not_class_member:
    +
    “entity” is not a class member
    +
    +

    1023

    +
    nonstd_const_member_decl_not_allowed:
    +
    nonstandard member constant declaration is not allowed
    +
    +

    1024

    +
    cl_ignore_std_option_only_in_cplusplus:
    +
    option “ignore_std” can be used only when compiling C++
    +
    +

    1025

    +
    cl_parse_nonclass_templates_option_only_in_cplusplus:
    +
    option “parse_templates” can be used only when compiling C++
    +
    +

    1026

    +
    cl_dep_name_requires_parse_nonclass_templates:
    +
    option “dep_name” cannot be used with “no_parse_templates”
    +
    +

    1027

    +
    cl_incompatible_language_modes:
    +
    language modes specified are incompatible
    +
    +

    1028

    +
    invalid_nested_class_redecl:
    +
    invalid redeclaration of nested class
    +
    +

    1029

    +
    flexible_array_member_not_allowed:
    +
    type containing an unknown-size array is not allowed
    +
    +

    1030

    +
    static_variable_in_inline_function:
    +
    a variable with static storage duration cannot be defined within an +inline function
    +
    +

    1031

    +
    bad_linkage_of_ref_within_inline_function:
    +
    an entity with internal linkage cannot be referenced within an inline +function with external linkage
    +
    +

    1032

    +
    type_generic_function_mismatch:
    +
    argument type “type” does not match this type-generic function +macro
    +
    +

    1034

    +
    friend_cannot_add_default_arguments:
    +
    friend declaration cannot add default arguments to previous +declaration
    +
    +

    1035

    +
    cannot_be_declared_in_scope:
    +
    entity-kind “entity” cannot be declared in this scope
    +
    +

    1036

    +
    id_can_only_appear_in_function:
    +
    the reserved identifier “xxxx” may only be used inside a function
    +
    +

    1037

    +
    invalid_identifier_start_UCN:
    +
    this universal character cannot begin an identifier
    +
    +

    1038

    +
    exp_string_literal:
    +
    expected a string literal
    +
    +

    1039

    +
    unrecognized_stdc_pragma:
    +
    unrecognized STDC pragma
    +
    +

    1040

    +
    bad_stdc_pragma_arg:
    +
    expected “ON”, “OFF”, or “DEFAULT”
    +
    +

    1041

    +
    stdc_pragma_not_allowed_here:
    +
    a STDC pragma may only appear between declarations in the global +scope or before any statements or declarations in a block scope
    +
    +

    1042

    +
    bad_va_copy:
    +
    incorrect use of va_copy
    +
    +

    1043

    +
    only_applies_to_float_types:
    +
    xxxx can only be used with floating-point types
    +
    +

    1044

    +
    complex_type_not_allowed:
    +
    complex type is not allowed
    +
    +

    1045

    +
    invalid_designator_kind:
    +
    invalid designator kind
    +
    +

    1046

    +
    inexact_fp_conversion:
    +
    floating-point value cannot be represented exactly
    +
    +

    1047

    +
    bad_complex_operation_result:
    +
    complex floating-point operation result is out of range
    +
    +

    1048

    +
    real_imaginary_conversion:
    +
    conversion between real and imaginary yields zero
    +
    +

    1049

    +
    cannot_initialize_flexible_array_member:
    +
    an initializer cannot be specified for a flexible array member
    +
    +

    1050

    +
    imaginary_times_assign:
    +
    imaginary *= imaginary sets the left-hand operand to zero
    +
    +

    1051

    +
    undeclared_parameter:
    +
    standard requires that entity-kind “entity” be given a type by a +subsequent declaration (“int” assumed)
    +
    +

    1052

    +
    inline_never_defined:
    +
    a definition is required for inline entity-kind “entity”
    +
    +

    1053

    +
    conversion_to_pointer_loses_bits:
    +
    conversion from integer to smaller pointer
    +
    +

    1054

    +
    missing_floating_point_type:
    +
    a floating-point type must be included in the type specifier for a +_Complex or _Imaginary type
    +
    +

    1055

    +
    type_decl_in_anon_union:
    +
    types cannot be declared in anonymous unions
    +
    +

    1056

    +
    returning_ptr_to_local_variable:
    +
    returning pointer to local variable
    +
    +

    1057

    +
    returning_ptr_to_local_temp:
    +
    returning pointer to local temporary
    +
    +

    1058

    +
    cl_export_template_option_only_in_cplusplus:
    +
    option “export” can be used only when compiling C++
    +
    +

    1059

    +
    cl_export_template_requires_dep_name:
    +
    option “export” cannot be used with “no_dep_name”
    +
    +

    1060

    +
    cl_export_template_requires_no_implicit_include:
    +
    option “export” cannot be used with “implicit_include”
    +
    +

    1061

    +
    corresp_decl_incompatible:
    +
    declaration of entity-kind “entity” is incompatible with a +declaration in another translation unit
    +
    +

    1062

    +
    corresp_decl_at:
    +
    the other declaration is at line xxxx
    +
    +

    1065

    +
    field_cannot_involve_vla_type:
    +
    a field declaration cannot have a type involving a variable length +array
    +
    +

    1066

    +
    entity_differs_in_other_trans_unit:
    +
    declaration of entity-kind “entity” had a different meaning +during compilation of “xxxx”
    +
    +

    1067

    +
    exp_template:
    +
    expected “template”
    +
    +

    1068

    +
    export_on_instantiation:
    +
    “export” cannot be used on an explicit instantiation
    +
    +

    1069

    +
    bad_decl_for_export:
    +
    “export” cannot be used on this declaration
    +
    +

    1070

    +
    exported_in_unnamed_namespace:
    +
    a member of an unnamed namespace cannot be declared “export”
    +
    +

    1071

    +
    export_after_definition:
    +
    a template cannot be declared “export” after it has been defined
    +
    +

    1072

    +
    labeled_declaration:
    +
    a declaration cannot have a label
    +
    +

    1073

    +
    no_export_support:
    +
    support for exported templates is disabled
    +
    +

    1075

    +
    entity_defined_in_other_trans_unit:
    +
    entity-kind “entity” already defined during compilation of +“xxxx”
    +
    +

    1076

    +
    entity_defined_twice:
    +
    entity-kind “entity” already defined in another translation unit
    +
    +

    1077

    +
    based_var_cannot_be_local:
    +
    a nonstatic local variable may not be used in a __based specification
    +
    +

    1078

    +
    cl_list_make_dependencies_incompatible_with_multiple_trans_units:
    +
    the option to list makefile dependencies may not be specified when +compiling more than one translation unit
    +
    +

    1080

    +
    cl_pp_output_incompatible_with_multiple_trans_units:
    +
    the option to generate preprocessed output may not be specified when +compiling more than one translation unit
    +
    +

    1081

    +
    field_name_conflicts_with_class:
    +
    a field with the same name as its class cannot be declared in a class +with a user-declared constructor
    +
    +

    1082

    +
    cl_implicit_include_incompatible_with_multiple_trans_units:
    +
    “implicit_include” cannot be used when compiling more than one +translation unit
    +
    +

    1083

    +
    corrupted_export_template_file:
    +
    exported template file “xxxx” is corrupted
    +
    +

    1084

    +
    exported_instantiation_and_specialized:
    +
    entity-kind “entity” cannot be instantiated – it has been +explicitly specialized in the translation unit containing the +exported definition
    +
    +

    1086

    +
    unqual_named_function_with_qual_object:
    +
    the object has type qualifiers that are not compatible with the +member entity-kind “entity”
    +
    +

    1087

    +
    no_matching_function_due_to_selector:
    +
    no instance of entity-kind “entity” matches the argument list and +object (the object has type qualifiers that prevent a match)
    +
    +

    1088

    +
    mode_incompatible_with_type:
    +
    an attribute specifies a mode incompatible with “type”
    +
    +

    1089

    +
    no_type_of_specified_width:
    +
    there is no type with the width specified
    +
    +

    1090

    +
    bad_attribute_alignment:
    +
    invalid alignment value specified by attribute
    +
    +

    1091

    +
    attribute_does_not_apply_to_type:
    +
    invalid attribute for “type”
    +
    +

    1094

    +
    arguments_provided_for_attribute:
    +
    attribute “xxxx” does not take arguments
    +
    +

    1096

    +
    exp_attribute_name:
    +
    expected an attribute name
    +
    +

    1097

    +
    unrecognized_attribute:
    +
    unknown attribute “xxxx”
    +
    +

    1098

    +
    attribute_not_allowed:
    +
    attributes may not appear here
    +
    +

    1099

    +
    invalid_argument_to_attribute:
    +
    invalid argument to attribute “xxxx”
    +
    +

    1101

    +
    assigned_goto_requires_void_ptr:
    +
    in “goto *expr”, expr must have type “void *”
    +
    +

    1102

    +
    nonstd_assigned_goto:
    +
    “goto *expr” is nonstandard
    +
    +

    1103

    +
    nonstd_address_of_label:
    +
    taking the address of a label is nonstandard
    +
    +

    1104

    +
    cl_duplicate_file_name:
    +
    file name specified more than once: xxxx
    +
    +

    1105

    +
    warning_directive:
    +
    #warning directive: xxxx
    +
    +

    1107

    +
    transparent_type_is_not_union:
    +
    the “transparent_union” attribute only applies to unions, and +“type” is not a union
    +
    +

    1108

    +
    transparent_attribute_ignored:
    +
    the “transparent_union” attribute is ignored on incomplete types
    +
    +

    1109

    +
    union_cannot_be_transparent_sym:
    +
    “type” cannot be transparent because entity-kind “entity”does not have the same size as the first field
    +
    +

    1110

    +
    union_cannot_be_transparent:
    +
    “type” cannot be transparent because it has a field of type +“type” which is not the same size as the first field
    +
    +

    1112

    +
    attribute_does_not_apply_to_local_variable:
    +
    attribute “xxxx” does not apply to local variables
    +
    +

    1113

    +
    attributes_in_rout_defn:
    +
    attributes are not permitted in a function definition
    +
    +

    1115

    +
    invalid_case_range:
    +
    the second constant in a case range must be larger than the first
    +
    +

    1116

    +
    asm_name_in_rout_defn:
    +
    an asm name is not permitted in a function definition
    +
    +

    1117

    +
    asm_name_in_typedef:
    +
    an asm name is ignored in a typedef
    +
    +

    1118

    +
    bad_reg_name:
    +
    unknown register name “xxxx“
    +
    +

    1120

    +
    bad_asm_constraint_modifier:
    +
    unknown asm constraint modifier ‘xxxx‘
    +
    +

    1121

    +
    bad_asm_constraint_letter:
    +
    unknown asm constraint letter ‘xxxx‘
    +
    +

    1122

    +
    missing_constraint_letter:
    +
    asm operand has no constraint letter
    +
    +

    1123

    +
    asm_output_must_have_output_mod:
    +
    an asm output operand must have one of the ‘=’ or ‘+’ modifiers
    +
    +

    1124

    +
    asm_input_must_not_have_output_mod:
    +
    an asm input operand may not have the ‘=’ or ‘+’ modifiers
    +
    +

    1127

    +
    register_used_twice:
    +
    register “xxxx“ used more than once
    +
    +

    1128

    +
    register_used_and_clobbered:
    +
    register “xxxx“ is both used and clobbered
    +
    +

    1129

    +
    register_clobbered_twice:
    +
    register “xxxx“ clobbered more than once
    +
    +

    1130

    +
    fixed_register_used:
    +
    register “xxxx“ has a fixed purpose and may not be used in an asm +statement
    +
    +

    1131

    +
    fixed_register_clobbered:
    +
    register “xxxx“ has a fixed purpose and may not be clobbered in +an asm statement
    +
    +

    1132

    +
    empty_clobbers_list:
    +
    an empty clobbers list must be omitted entirely
    +
    +

    1133

    +
    exp_asm_operand:
    +
    expected an asm operand
    +
    +

    1134

    +
    exp_asm_clobber:
    +
    expected a register to clobber
    +
    +

    1135

    +
    format_rout_not_varargs:
    +
    “format” attribute requires an ellipsis parameter or parameter pack
    +
    +

    1136

    +
    subst_arg_is_not_variable:
    +
    first substitution argument is not the first variable argument
    +
    +

    1137

    +
    fmt_arg_does_not_exist:
    +
    format argument index is greater than number of parameters
    +
    +

    1138

    +
    fmt_arg_is_not_string:
    +
    format argument does not have string type
    +
    +

    1139

    +
    template_not_in_template:
    +
    the “template” keyword used for syntactic disambiguation may only be +used within a template
    +
    +

    1142

    +
    attr_requires_func_type:
    +
    attribute “xxxx” does not apply to non-function type “type”
    +
    +

    1143

    +
    nonobject_pointer_arithmetic:
    +
    arithmetic on pointer to void or function type
    +
    +

    1144

    +
    invalid_storage_class_in_for_init:
    +
    storage class must be auto or register
    +
    +

    1145

    +
    va_arg_would_have_been_promoted:
    +
    “type” would have been promoted to “type” when passed through +the ellipsis parameter; use the latter type instead
    +
    +

    1146

    +
    not_a_base_class_member:
    +
    “xxxx” is not a base class member
    +
    +

    1147

    +
    super_after_scope:
    +
    __super cannot appear after “::”
    +
    +

    1148

    +
    super_not_in_class:
    +
    __super may only be used in a class scope
    +
    +

    1149

    +
    unqualified_super:
    +
    __super must be followed by “::”
    +
    +

    1151

    +
    mangled_name_too_long:
    +
    mangled name is too long
    +
    +

    1152

    +
    aliased_name_undeclared:
    +
    declaration aliased to undefined entity “xxxx”
    +
    +

    1153

    +
    aliased_name_bad_kind:
    +
    declaration does not match its alias entity-kind “entity”
    +
    +

    1154

    +
    alias_cannot_have_definition:
    +
    entity declared as alias cannot have definition
    +
    +

    1155

    +
    vla_size_ignored:
    +
    variable-length array field type will be treated as zero-length array +field type
    +
    +

    1156

    +
    gcc_lvalue_cast_ignored:
    +
    nonstandard cast on lvalue ignored
    +
    +

    1157

    +
    cl_invalid_flag_name:
    +
    unrecognized flag name: xxxx
    +
    +

    1158

    +
    qualified_void_return_type:
    +
    void return type cannot be qualified
    +
    +

    1159

    +
    auto_ignored:
    +
    the auto specifier is ignored here (invalid in standard C/C++)
    +
    +

    1160

    +
    alignment_reduction_ignored:
    +
    a reduction in alignment without the “packed” attribute is ignored
    +
    +

    1161

    +
    corresp_member_template_is_different_kind:
    +
    a member template corresponding to “entity” is declared as a +template of a different kind in another translation unit
    +
    +

    1162

    +
    excess_initializers_ignored:
    +
    excess initializers are ignored
    +
    +

    1163

    +
    va_start_requires_ellipsis_function:
    +
    va_start can appear only in a function with an ellipsis parameter
    +
    +

    1164

    +
    cl_short_enums_requires_gcc_mode:
    +
    the “short_enums” option is only valid in GNU C and GNU C++ modes
    +
    +

    1165

    +
    bad_export_info_file:
    +
    invalid export information file “xxxx” at line number xxxx
    +
    +

    1166

    +
    statement_expression_in_function_only:
    +
    statement expressions are only allowed in block scope
    +
    +

    1168

    +
    asm_name_on_auto_variable:
    +
    an asm name is ignored on a non-register automatic variable
    +
    +

    1170

    +
    unrecognized_upc_pragma:
    +
    unrecognized UPC pragma
    +
    +

    1171

    +
    mismatched_shared_block_size:
    +
    shared block size does not match one previously specified
    +
    +

    1172

    +
    ambiguous_block_size_spec:
    +
    bracketed expression is assumed to be a block size specification +rather than an array dimension
    +
    +

    1173

    +
    shared_block_size_must_be_positive:
    +
    the block size of a shared array must be greater than zero
    +
    +

    1174

    +
    multiple_block_sizes:
    +
    multiple block sizes not allowed
    +
    +

    1175

    +
    nonshared_strict_relaxed:
    +
    strict or relaxed requires shared
    +
    +

    1176

    +
    threads_constant_not_allowed:
    +
    THREADS not allowed in this context
    +
    +

    1177

    +
    shared_block_size_too_large:
    +
    block size specified exceeds the maximum value of xxxx
    +
    +

    1178

    +
    function_returning_shared:
    +
    function returning shared is not allowed
    +
    +

    1180

    +
    shared_nonthreads_dim:
    +
    one dimension of an array of a shared type must be a multiple of +THREADS when the number of threads is nonconstant
    +
    +

    1181

    +
    shared_inside_struct:
    +
    shared type inside a struct or union is not allowed
    +
    +

    1182

    +
    shared_parameter:
    +
    parameters may not have shared types
    +
    +

    1183

    +
    threads_dimension_requires_definite_block_size:
    +
    a dynamic THREADS dimension requires a definite block size
    +
    +

    1184

    +
    bad_shared_storage_class:
    +
    shared variables must be static or extern
    +
    +

    1185

    +
    nonshared_blocksizeof:
    +
    argument of upc_blocksizeof is a pointer to a shared type (not shared +type itself)
    +
    +

    1186

    +
    nested_upc_forall:
    +
    affinity expression ignored in nested upc_forall
    +
    +

    1187

    +
    exit_forall:
    +
    branching into or out of a upc_forall loop is not allowed
    +
    +

    1188

    +
    bad_affinity:
    +
    affinity expression must have a shared type or point to a shared type
    +
    +

    1189

    +
    shared_affinity_type:
    +
    affinity has shared type (not pointer to shared)
    +
    +

    1190

    +
    upc_shared_void_comparison:
    +
    shared void* types can only be compared for equality
    +
    +

    1191

    +
    cl_upc_requires_ansi_c_dialect:
    +
    UPC mode is incompatible with C++ and K&R modes
    +
    +

    1192

    +
    null_char_ignored:
    +
    null (zero) character in input line ignored
    +
    +

    1193

    +
    null_char_in_string:
    +
    null (zero) character in string or character constant
    +
    +

    1194

    +
    null_char_in_header_name:
    +
    null (zero) character in header name
    +
    +

    1195

    +
    for_init_hides_declaration:
    +
    declaration in for-initializer hides a declaration in the surrounding +scope
    +
    +

    1196

    +
    for_init_hidden_declaration:
    +
    the hidden declaration is at line xxxx
    +
    +

    1197

    +
    prototype_lost:
    +
    the prototype declaration of entity-kind “entity” (declared at +line xxxx) is ignored after this unprototyped redeclaration
    +
    +

    1199

    +
    bad_linkage_for_redefine_extname:
    +
    entity-kind “entity” (declared at line xxxx) must have +external C linkage
    +
    +

    1200

    +
    declaration_hides_for_init:
    +
    variable declaration hides declaration in for-initializer
    +
    +

    1201

    +
    typedef_in_elab_type:
    +
    typedef “xxxx” may not be used in an elaborated type specifier
    +
    +

    1202

    +
    call_of_zero:
    +
    call of zero constant ignored
    +
    +

    1203

    +
    handler_redeclares_parameter:
    +
    parameter “xxxx” may not be redeclared in a catch clause of +function try block
    +
    +

    1204

    +
    specialization_out_of_namespace:
    +
    the initial explicit specialization of entity-kind “entity” must +be declared in the namespace containing the template
    +
    +

    1205

    +
    cc_clobber_ignored:
    +
    “cc” clobber ignored
    +
    +

    1206

    +
    invalid_token_after_template:
    +
    “template” must be followed by an identifier
    +
    +

    1207

    +
    mythread_constant_not_allowed:
    +
    MYTHREAD not allowed in this context
    +
    +

    1208

    +
    bad_upc_shared_pointer_layout_qualifier:
    +
    layout qualifier cannot qualify pointer to shared
    +
    +

    1209

    +
    bad_upc_shared_array_layout_qualifier:
    +
    layout qualifier cannot qualify an incomplete array
    +
    +

    1210

    +
    decl_hides_catch_parameter:
    +
    declaration of “xxxx” hides handler parameter
    +
    +

    1211

    +
    nonstd_ignored_array_cast:
    +
    nonstandard cast to array type ignored
    +
    +

    1212

    +
    invalid_pragma_operator:
    +
    this pragma cannot be used in a _Pragma operator (a #pragma directive +must be used)
    +
    +

    1213

    +
    field_uses_tail_padding:
    +
    field uses tail padding of a base class
    +
    +

    1214

    +
    gnu_may_use_bit_padding:
    +
    GNU C++ compilers may use bit field padding
    +
    +

    1215

    +
    deprecated_entity:
    +
    entity-kind “entity” was declared deprecated
    +
    +

    1216

    +
    field_with_asm_name_not_allowed:
    +
    an asm name is not allowed on a nonstatic member declaration
    +
    +

    1217

    +
    unrecognized_format_function_type:
    +
    unrecognized format function type “xxxx” ignored
    +
    +

    1218

    +
    base_uses_tail_padding:
    +
    base class “entity” uses tail padding of base class “entity”
    +
    +

    1219

    +
    bad_variable_for_init_priority:
    +
    the “init_priority” attribute can only be used for definitions of +static data members and namespace scope variables of class types
    +
    +

    1220

    +
    init_priority_reserved:
    +
    requested initialization priority is reserved for internal use
    +
    +

    1221

    +
    hidden_anonymous_union_field:
    +
    this anonymous union/struct field is hidden by entity-kind +“entity” (declared at line xxxx)
    +
    +

    1222

    +
    invalid_error_number:
    +
    invalid error number
    +
    +

    1223

    +
    invalid_error_tag:
    +
    invalid error tag
    +
    +

    1224

    +
    exp_error_argument:
    +
    expected an error number or error tag
    +
    +

    1225

    +
    size_affected_by_tail_padding:
    +
    size of class is affected by tail padding
    +
    +

    1226

    +
    nonlocal_label_reference:
    +
    labels can be referenced only in function definitions
    +
    +

    1227

    +
    branch_into_statement_expr:
    +
    transfer of control into a statement expression is not allowed
    +
    +

    1229

    +
    bad_statement_in_statement_expr:
    +
    this statement is not allowed inside of a statement expression
    +
    +

    1230

    +
    class_def_in_statement_expr:
    +
    a class that is not trivially copyable cannot be defined inside a +statement expression
    +
    +

    1232

    +
    dyn_local_static_in_statement_expr:
    +
    a dynamically-initialized local static variable is not allowed inside +of a statement expression
    +
    +

    1233

    +
    vla_in_statement_expr:
    +
    a variable-length array is not allowed inside of a statement +expression
    +
    +

    1234

    +
    statement_expr_in_default_arg:
    +
    a statement expression is not allowed inside of a default argument
    +
    +

    1235

    +
    ptr_func_ptr_data_conv:
    +
    nonstandard conversion between pointer to function and pointer to data
    +
    +

    1236

    +
    interface_cannot_have_virtual_base:
    +
    interface types cannot have virtual base classes
    +
    +

    1237

    +
    interface_cannot_have_private_or_protected:
    +
    interface types cannot specify “private” or “protected”
    +
    +

    1238

    +
    interface_must_derive_from_interface:
    +
    interface types can only derive from other interface types
    +
    +

    1239

    +
    type_is_interface:
    +
    “type” is an interface type
    +
    +

    1240

    +
    interface_cannot_have_typedef:
    +
    interface types cannot have typedef members
    +
    +

    1241

    +
    interface_cannot_have_ctor_or_dtor:
    +
    interface types cannot have user-declared constructors or destructors
    +
    +

    1242

    +
    interface_cannot_have_operator:
    +
    interface types cannot have user-declared member operators
    +
    +

    1243

    +
    interface_cannot_be_local:
    +
    interface types cannot be declared in functions
    +
    +

    1245

    +
    interface_cannot_have_data_member:
    +
    interface types cannot have data members
    +
    +

    1246

    +
    interface_cannot_have_friend:
    +
    interface types cannot contain friend declarations
    +
    +

    1248

    +
    interface_cannot_be_nested_class:
    +
    interface types cannot be nested class types
    +
    +

    1249

    +
    interface_cannot_have_member_templates:
    +
    interface types cannot have member templates
    +
    +

    1250

    +
    interface_cannot_have_static_members:
    +
    interface types cannot have static member functions
    +
    +

    1251

    +
    invalid_microsoft_pragma_operator:
    +
    this pragma cannot be used in a __pragma operator (a #pragma +directive must be used)
    +
    +

    1252

    +
    qualifier_must_be_base_class:
    +
    qualifier must be base class of “type”
    +
    +

    1253

    +
    invalid_selective_overrider_declaration:
    +
    declaration must correspond to a pure virtual member function in the +indicated base class
    +
    +

    1254

    +
    integer_overflow_class_internal:
    +
    integer overflow in internal computation due to size or complexity of +“type”
    +
    +

    1255

    +
    integer_overflow_internal:
    +
    integer overflow in internal computation
    +
    +

    1256

    +
    invalid_type_for_w64:
    +
    __w64 can only be specified on int, long, and pointer types
    +
    +

    1257

    +
    ilp64_will_narrow:
    +
    potentially narrowing conversion when compiled in an environment +where int, long, or pointer types are 64 bits wide
    +
    +

    1258

    +
    value_of_pragma_pack_show:
    +
    current value of pragma pack is xxxx
    +
    +

    1259

    +
    pragma_pack_show_args_ignored:
    +
    arguments for pragma pack(show) are ignored
    +
    +

    1262

    +
    multiple_declspec_align:
    +
    earlier __declspec(align(…)) ignored
    +
    +

    1263

    +
    exp_ms_attr_enum_value:
    +
    expected an argument value for the “xxxx” attribute parameter
    +
    +

    1264

    +
    invalid_ms_attr_enum_value:
    +
    invalid argument value for the “xxxx” attribute parameter
    +
    +

    1265

    +
    exp_ms_attr_bool_value:
    +
    expected a boolean value for the “xxxx” attribute parameter
    +
    +

    1266

    +
    positional_after_named:
    +
    a positional argument cannot follow a named argument in an attribute
    +
    +

    1267

    +
    invalid_ms_attr_name:
    +
    attribute “xxxx” has no parameter named “xxxx”
    +
    +

    1268

    +
    exp_ms_attr_arg_list:
    +
    expected an argument list for the “xxxx” attribute
    +
    +

    1269

    +
    exp_comma_or_rbracket:
    +
    expected a “,” or “]”
    +
    +

    1270

    +
    duplicate_ms_attr_arg:
    +
    attribute argument “xxxx” has already been given a value
    +
    +

    1271

    +
    cannot_assign_to_ms_attr:
    +
    a value cannot be assigned to the “xxxx” attribute
    +
    +

    1272

    +
    ptr_incomplete_throw:
    +
    a throw expression may not have pointer-to-incomplete type
    +
    +

    1273

    +
    alignof_incomplete_type:
    +
    alignment-of operator applied to incomplete type
    +
    +

    1274

    +
    invalid_use_of_standalone_ms_attr:
    +
    “xxxx” may only be used as a standalone attribute
    +
    +

    1275

    +
    invalid_use_of_ms_attr:
    +
    “xxxx” attribute cannot be used here
    +
    +

    1277

    +
    ms_attr_not_allowed:
    +
    attributes are not allowed here
    +
    +

    1278

    +
    invalid_ms_attr_uuid_value:
    +
    invalid argument value for the “xxxx” attribute parameter
    +
    +

    1279

    +
    too_many_ms_attr_args:
    +
    too many attribute arguments
    +
    +

    1280

    +
    conv_from_inaccessible_base_class:
    +
    conversion from inaccessible base class “type” is not allowed
    +
    +

    1281

    +
    cl_export_template_requires_distinct_templ_sigs:
    +
    option “export” requires distinct template signatures
    +
    +

    1282

    +
    mixed_string_concatenation:
    +
    string literals with different character kinds cannot be concatenated
    +
    +

    1283

    +
    no_gnu_virtual_base_gap:
    +
    GNU layout bug not emulated because it places virtual base +“entity” outside “entity” object boundaries
    +
    +

    1284

    +
    gnu_virtual_base_gap:
    +
    virtual base “entity” placed outside “entity” object +boundaries
    +
    +

    1285

    +
    nonstd_qualifier_in_namespace_member_decl:
    +
    nonstandard qualified name in namespace member declaration
    +
    +

    1286

    +
    declspec_align_reduction_ignored:
    +
    reduction in alignment ignored
    +
    +

    1287

    +
    const_ignored:
    +
    const qualifier ignored
    +
    +

    1289

    +
    invalid_asm_qualifiers:
    +
    invalid GNU asm qualifiers
    +
    +

    1290

    +
    non_pod_passed_to_ellipsis:
    +
    a class type that is not trivially copyable passed through ellipsis
    +
    +

    1291

    +
    non_pod_va_arg:
    +
    a class type that cannot be trivially copied cannot be fetched by +va_arg
    +
    +

    1292

    +
    nonstd_fixed_point_suffix:
    +
    the ‘u’ or ‘U’ suffix must appear before the ‘l’ or ‘L’ suffix in a +fixed-point literal
    +
    +

    1293

    +
    cl_fixed_point_option_only_in_C:
    +
    option “fixed_point” can be used only when compiling C
    +
    +

    1294

    +
    integer_may_not_fit_in_fixed_point_result:
    +
    integer operand may cause fixed-point overflow
    +
    +

    1295

    +
    bad_fixed_point_value:
    +
    fixed-point constant is out of range
    +
    +

    1296

    +
    inexact_fxp_conversion:
    +
    fixed-point value cannot be represented exactly
    +
    +

    1297

    +
    c99_constant_in_unsigned_long_long_range:
    +
    constant is too large for long long; given unsigned long long type +(nonstandard)
    +
    +

    1298

    +
    bad_upc_shared_void_pointer_layout_qualifier:
    +
    layout qualifier cannot qualify pointer to shared void
    +
    +

    1299

    +
    duplicate_threads_dim:
    +
    duplicate THREADS in multidimensional array type
    +
    +

    1300

    +
    bad_strong_using_scope:
    +
    a strong using-directive may only appear in a namespace scope
    +
    +

    1301

    +
    probable_guiding_friend:
    +
    entity-kind “entity” declares a non-template function – add <> +to refer to a template instance
    +
    +

    1302

    +
    operation_may_not_fit_in_fixed_point_result:
    +
    operation may cause fixed-point overflow
    +
    +

    1303

    +
    expr_not_integral_or_enum_or_fixed_point:
    +
    expression must have integral, enum, or fixed-point type
    +
    +

    1304

    +
    expr_not_integral_or_fixed_point:
    +
    expression must have integral or fixed-point type
    +
    +

    1305

    +
    noreturn_function_does_return:
    +
    function declared with “noreturn” does return
    +
    +

    1306

    +
    asm_name_conflict:
    +
    asm name ignored because it conflicts with a previous declaration
    +
    +

    1307

    +
    duplicate_typedef_in_class:
    +
    class member typedef may not be redeclared
    +
    +

    1308

    +
    taking_address_of_temporary:
    +
    taking the address of a temporary
    +
    +

    1309

    +
    attribute_ignored_on_incomplete_class_decl:
    +
    attributes are ignored on a class declaration that is not also a +definition
    +
    +

    1310

    +
    implicit_fixed_point_to_floating_point_conversion:
    +
    fixed-point value implicitly converted to floating-point type
    +
    +

    1311

    +
    no_classification_for_fixed_point_type:
    +
    fixed-point types have no classification
    +
    +

    1312

    +
    fixed_template_parameter:
    +
    a template parameter may not have fixed-point type
    +
    +

    1313

    +
    hex_fp_constant:
    +
    hexadecimal floating-point constants are not allowed
    +
    +

    1314

    +
    cl_named_address_spaces_option_only_in_C:
    +
    option “named_address_spaces” can be used only when compiling C
    +
    +

    1315

    +
    float_to_fixed_conversion:
    +
    floating-point value does not fit in required fixed-point type
    +
    +

    1316

    +
    inexact_fixed_conversion:
    +
    value cannot be converted to fixed-point value exactly
    +
    +

    1317

    +
    fixed_sign_change:
    +
    fixed-point conversion resulted in a change of sign
    +
    +

    1318

    +
    integer_to_fixed_conversion:
    +
    integer value does not fit in required fixed-point type
    +
    +

    1319

    +
    bad_fixed_operation_result:
    +
    fixed-point operation result is out of range
    +
    +

    1320

    +
    multiple_named_address_spaces:
    +
    multiple named address spaces
    +
    +

    1321

    +
    bad_storage_class_for_named_address_space_variable:
    +
    variable with automatic storage duration cannot be stored in a named +address space
    +
    +

    1322

    +
    type_with_named_address_space_not_allowed:
    +
    type cannot be qualified with named address space
    +
    +

    1323

    +
    named_address_space_on_function_type:
    +
    function type cannot be qualified with named address space
    +
    +

    1324

    +
    field_type_cannot_be_qualified_with_named_address_space:
    +
    field type cannot be qualified with named address space
    +
    +

    1325

    +
    fixed_to_float_conversion:
    +
    fixed-point value does not fit in required floating-point type
    +
    +

    1326

    +
    fixed_to_integer_conversion:
    +
    fixed-point value does not fit in required integer type
    +
    +

    1327

    +
    fixed_to_fixed_conversion:
    +
    value does not fit in required fixed-point type
    +
    +

    1328

    +
    cl_named_registers_option_only_in_C:
    +
    option “named_registers” can be used only when compiling C
    +
    +

    1329

    +
    named_register_not_allowed:
    +
    a named-register storage class is not allowed here
    +
    +

    1330

    +
    register_storage_class_conflict:
    +
    entity-kind “entity” (declared at line xxxx) redeclared with +incompatible named-register storage class
    +
    +

    1331

    +
    aliased_variable_cannot_have_register_storage_class:
    +
    named-register storage class cannot be specified for aliased variable
    +
    +

    1332

    +
    register_in_use:
    +
    named-register storage specifier is already in use
    +
    +

    1333

    +
    embedded_c_option_incompatible_with_individual_feature_options:
    +
    option “embedded_c” cannot be combined with options to control +individual Embedded C features
    +
    +

    1334

    +
    cl_invalid_edg_base_directory:
    +
    invalid EDG_BASE directory: xxxx
    +
    +

    1336

    +
    bad_predef_macro_line:
    +
    invalid predefined macro entry at line xxxx: xxxx
    +
    +

    1337

    +
    bad_macro_mode_name:
    +
    invalid macro mode name “xxxx”
    +
    +

    1338

    +
    bad_predef_macro_redef:
    +
    incompatible redefinition of predefined macro “xxxx”
    +
    +

    1339

    +
    missing_named_register_storage_class:
    +
    redeclaration of entity-kind “entity” (declared at line xxxx) +is missing a named-register storage class
    +
    +

    1340

    +
    register_too_small:
    +
    named register is too small for the type of the variable
    +
    +

    1341

    +
    no_named_register_for_array:
    +
    arrays cannot be declared with named-register storage class
    +
    +

    1342

    +
    enum_const_cast:
    +
    const_cast to enum type is nonstandard
    +
    +

    1343

    +
    cl_embedded_c_option_only_in_C:
    +
    option “embedded_c” can be used only when compiling C
    +
    +

    1344

    +
    named_address_space_not_allowed:
    +
    a named address space qualifier is not allowed here
    +
    +

    1345

    +
    bad_initializer_for_array_with_unspecified_bound:
    +
    an empty initializer is invalid for an array with unspecified bound
    +
    +

    1346

    +
    incomplete_class_return_type:
    +
    function returns incomplete class type “type”
    +
    +

    1347

    +
    out_of_class_initializer_ignored:
    +
    entity-kind “entity” has already been initialized; the +out-of-class initializer will be ignored
    +
    +

    1348

    +
    local_variable_hidden:
    +
    declaration hides entity-kind “entity” (declared at line xxxx)
    +
    +

    1349

    +
    named_address_space_for_parameter:
    +
    a parameter cannot be allocated in a named address space
    +
    +

    1350

    +
    bad_float_or_fixed_suffix:
    +
    invalid suffix on fixed-point or floating-point constant
    +
    +

    1351

    +
    register_in_address_space:
    +
    a register variable cannot be allocated in a named address space
    +
    +

    1352

    +
    bad_stdc_fx_overflow_pragma_arg:
    +
    expected “SAT” or “DEFAULT”
    +
    +

    1353

    +
    no_corresponding_member_delete:
    +
    entity-kind “entity” has no corresponding member operator +delete*xxxx* (to be called if an exception is thrown during +initialization of an allocated object)
    +
    +

    1354

    +
    dll_thread_conflict:
    +
    a thread-local variable cannot be declared with “dllimport” or +“dllexport”
    +
    +

    1355

    +
    function_returning_named_address_space:
    +
    a function return type cannot be qualified with a named address space
    +
    +

    1356

    +
    cannot_initialize_destructible_flexible_array:
    +
    an initializer cannot be specified for a flexible array member whose +elements have a nontrivial destructor
    +
    +

    1357

    +
    cannot_initialize_indirect_flexible_array:
    +
    an initializer cannot be specified for an indirect flexible array +member
    +
    +

    1358

    +
    cl_invalid_gnu_version:
    +
    invalid GNU version number: xxxx
    +
    +

    1359

    +
    attribute_after_parenthesized_initializer:
    +
    variable attributes appearing after a parenthesized initializer are +ignored
    +
    +

    1360

    +
    gcc_use_of_cast_as_lvalue:
    +
    the result of this cast cannot be used as an lvalue
    +
    +

    1361

    +
    unsigned_fixed_point_negation:
    +
    negation of an unsigned fixed-point value
    +
    +

    1364

    +
    register_name_on_nonregister:
    +
    register names can only be used for register variables
    +
    +

    1365

    +
    void_named_register:
    +
    named-register variables cannot have void type
    +
    +

    1367

    +
    parameter_with_link_scope_specifier:
    +
    parameters cannot have link scope specifiers
    +
    +

    1368

    +
    multiple_link_scope_specifiers:
    +
    multiple link scope specifiers
    +
    +

    1369

    +
    link_scope_requires_external_linkage:
    +
    link scope specifiers can only appear on functions and variables with +external linkage
    +
    +

    1370

    +
    link_scope_relaxation:
    +
    a redeclaration cannot weaken a link scope
    +
    +

    1371

    +
    invalid_link_scope:
    +
    link scope specifier not allowed on this declaration
    +
    +

    1372

    +
    nonstd_qualifier_in_global_scope_decl:
    +
    nonstandard qualified name in global scope declaration
    +
    +

    1373

    +
    impl_narrowing_64_bit_int:
    +
    implicit conversion of a 64-bit integral type to a smaller integral +type (potential portability problem)
    +
    +

    1374

    +
    expl_narrowing_64_bit_int:
    +
    explicit conversion of a 64-bit integral type to a smaller integral +type (potential portability problem)
    +
    +

    1375

    +
    pointer_conversion_to_same_size_int:
    +
    conversion from pointer to same-sized integral type (potential +portability problem)
    +
    +

    1377

    +
    friend_specifier_ignored:
    +
    friend specifier is not allowed in a class definition; friend +specifier is ignored
    +
    +

    1378

    +
    cannot_use_thread_local_storage:
    +
    only static and extern variables can use thread-local storage
    +
    +

    1379

    +
    multiple_thread_local_storage_specifiers:
    +
    multiple thread-local storage specifiers
    +
    +

    1380

    +
    virtual_function_never_defined:
    +
    virtual entity-kind “entity” was not defined (and cannot be +defined elsewhere because it is a member of an unnamed namespace)
    +
    +

    1381

    +
    stray_carriage_return:
    +
    carriage return character in source line outside of comment or +character/string literal
    +
    +

    1382

    +
    expr_not_fixed_point:
    +
    expression must have fixed-point type
    +
    +

    1383

    +
    invalid_access_specifier:
    +
    invalid use of access specifier is ignored
    +
    +

    1384

    +
    ptr_conv_to_bool:
    +
    pointer converted to bool
    +
    +

    1385

    +
    ptr_to_member_conv_to_bool:
    +
    pointer-to-member converted to bool
    +
    +

    1386

    +
    storage_specifier_ignored:
    +
    storage specifier ignored
    +
    +

    1387

    +
    dll_interface_ignored_on_class_template:
    +
    dllexport and dllimport are ignored on class templates
    +
    +

    1388

    +
    base_class_has_different_dll_interface:
    +
    base class dllexport/dllimport specification differs from that of the +derived class
    +
    +

    1389

    +
    redeclaration_adds_dll_interface:
    +
    redeclaration cannot add dllexport/dllimport to “entity”(declared at line xxxx)
    +
    +

    1390

    +
    dll_interface_conflict_dllexport_assumed:
    +
    dllexport/dllimport conflict with “entity” (declared at line +xxxx); dllexport assumed
    +
    +

    1391

    +
    dllimport_defined:
    +
    cannot define dllimport entity
    +
    +

    1392

    +
    dll_interface_requires_external_linkage:
    +
    dllexport/dllimport requires external linkage
    +
    +

    1393

    +
    class_and_member_have_dll_interface:
    +
    a member of a class declared with dllexport/dllimport cannot itself +be declared with such a specifier
    +
    +

    1394

    +
    field_without_dll_interface:
    +
    field of class type without a DLL interface used in a class with a +DLL interface
    +
    +

    1395

    +
    microsoft_parenthesized_member:
    +
    parenthesized member declaration is nonstandard
    +
    +

    1396

    +
    white_space_inside_splice:
    +
    white space between backslash and newline in line splice ignored
    +
    +

    1397

    +
    dll_interface_conflict_none_assumed:
    +
    dllexport/dllimport conflict with “entity” (declared at line +xxxx); dllimport/dllexport dropped
    +
    +

    1398

    +
    bad_nonstd_anonymous_union_field:
    +
    invalid member for anonymous member class – class “type” has a +disallowed member function
    +
    +

    1399

    +
    nonstd_reinterpret_cast:
    +
    nonstandard reinterpret_cast
    +
    +

    1400

    +
    positional_format_specifier_zero:
    +
    positional format specifier cannot be zero
    +
    +

    1401

    +
    nonlocal_vla_not_allowed:
    +
    a local class cannot reference a variable-length array type from an +enclosing function
    +
    +

    1402

    +
    class_and_inherited_member_instance_have_dll_interface:
    +
    member entity-kind “entity” (declared at line xxxx) already +has an explicit dllexport/dllimport specifier
    +
    +

    1403

    +
    vla_in_return_type:
    +
    a variable-length array is not allowed in a function return type
    +
    +

    1404

    +
    ptr_to_member_of_vla_type:
    +
    variable-length array type is not allowed in pointer to member of +type “type”
    +
    +

    1405

    +
    statement_expr_with_vla_type:
    +
    the result of a statement expression cannot have a type involving a +variable-length array
    +
    +

    1406

    +
    trigraph_ignored:
    +
    support for trigraphs is disabled
    +
    +

    1407

    +
    attribute_requires_external_linkage:
    +
    the “xxxx” attribute can only appear on functions and variables +with external linkage
    +
    +

    1408

    +
    cl_strict_mode_incompatible_with_ignore_std:
    +
    strict mode is incompatible with treating namespace std as an alias +for the global namespace
    +
    +

    1414

    +
    invalid_symbolic_asm_operand_name:
    +
    invalid symbolic operand name “xxxx”
    +
    +

    1415

    +
    match_limit_for_symbolic_asm_operand:
    +
    a symbolic match constraint must refer to one of the first ten +operands
    +
    +

    1416

    +
    if_exists_not_allowed:
    +
    use of __if_exists is not supported in this context
    +
    +

    1417

    +
    if_exists_not_closed:
    +
    __if_exists block not closed in the same scope in which it was opened
    +
    +

    1418

    +
    bad_init_for_thread_local:
    +
    thread-local variable cannot be dynamically initialized
    +
    +

    1419

    +
    unaligned_qualifier_dropped:
    +
    conversion drops “__unaligned” qualifier
    +
    +

    1420

    +
    insufficient_enum_range:
    +
    some enumerator values cannot be represented by the integral type +underlying the enum type
    +
    +

    1421

    +
    friend_class_template_default_arg_not_allowed:
    +
    default argument is not allowed on a friend class template declaration
    +
    +

    1422

    +
    multi_char_literal:
    +
    multicharacter character literal (potential portability problem)
    +
    +

    1423

    +
    exp_class_type:
    +
    expected a class, struct, or union type
    +
    +

    1424

    +
    offsetof_nonfield:
    +
    second operand of offsetof must be a field
    +
    +

    1425

    +
    offsetof_bit_field:
    +
    second operand of offsetof may not be a bit field
    +
    +

    1426

    +
    offsetof_virtual_base_member:
    +
    cannot apply offsetof to a member of a virtual base
    +
    +

    1427

    +
    offset_in_non_POD_nonstandard:
    +
    offsetof applied to a type other than a standard-layout class
    +
    +

    1428

    +
    default_arg_on_member_friend:
    +
    default arguments are not allowed on a friend declaration of a member +function
    +
    +

    1429

    +
    default_arg_requires_friend_to_be_definition:
    +
    default arguments are not allowed on friend declarations that are not +definitions
    +
    +

    1430

    +
    redeclaration_of_friend_with_default_args:
    +
    redeclaration of entity-kind “entity” (declared at line xxxx) +previously declared as a friend with default arguments is not allowed
    +
    +

    1431

    +
    bad_qualifier_for_nested_class_decl:
    +
    invalid qualifier for “type” (a derived class is not allowed here)
    +
    +

    1432

    +
    bad_qualifier_for_delayed_class_definition:
    +
    invalid qualifier for definition of class “type”
    +
    +

    1433

    +
    no_prior_push_macro:
    +
    no prior push_macro for “xxxx”
    +
    +

    1434

    +
    wide_string_not_allowed:
    +
    wide string literal not allowed
    +
    +

    1436

    +
    feature_requires_c:
    +
    “xxxx” is only allowed in C
    +
    +

    1437

    +
    microsoft_ptr_width_must_follow_star:
    +
    __ptr32 and __ptr64 must follow a “*”
    +
    +

    1438

    +
    microsoft_ptr_width_conflict:
    +
    __ptr32 and __ptr64 cannot both apply
    +
    +

    1439

    +
    name_must_be_prototype_instantiation:
    +
    template argument list of “xxxx” must match the parameter list
    +
    +

    1440

    +
    incomplete_class_type:
    +
    an incomplete class type is not allowed
    +
    +

    1441

    +
    complex_integral_type:
    +
    complex integral types are not supported
    +
    +

    1442

    +
    real_and_imag_require_complex_argument:
    +
    __real and __imag can only be applied to complex values
    +
    +

    1443

    +
    real_and_imag_applied_to_real_value:
    +
    __real/__imag applied to real value
    +
    +

    1444

    +
    deprecated_entity_with_custom_message:
    +
    entity-kind “entity” was declared deprecated (“xxxx”)
    +
    +

    1446

    +
    dll_interface_in_unnamed_namespace:
    +
    dllimport/dllexport applied to a member of an unnamed namespace
    +
    +

    1447

    +
    thiscall_requires_nonstatic_member:
    +
    __thiscall can only appear on nonstatic member function declarations
    +
    +

    1448

    +
    vararg_thiscall:
    +
    __thiscall not allowed on function with ellipsis parameter
    +
    +

    1449

    +
    specialization_of_referenced_entity_pos:
    +
    explicit specialization of entity-kind “entity” must precede its +first use (at line xxxx)
    +
    +

    1450

    +
    sealed_base_class:
    +
    a sealed class type cannot be used as a base class
    +
    +

    1451

    +
    duplicate_class_modifier:
    +
    duplicate class modifier
    +
    +

    1452

    +
    function_modifiers_abstract_and_sealed:
    +
    a member function cannot have both the “abstract” and “sealed” +modifiers
    +
    +

    1453

    +
    pure_specifier_on_sealed_member:
    +
    a sealed member cannot be pure virtual
    +
    +

    1454

    +
    function_modifier_requires_virtual_function:
    +
    nonvirtual function cannot be declared with “abstract” or “sealed” +modifier
    +
    +

    1455

    +
    override_member_does_not_override:
    +
    member function declared with “override” does not override a base +class member
    +
    +

    1456

    +
    override_of_sealed_function:
    +
    cannot override sealed entity-kind “entity” (declared at line +xxxx)
    +
    +

    1457

    +
    type_is_declared_abstract:
    +
    entity-kind “entity” (declared at line xxxx) was declared +with the class modifier “abstract”
    +
    +

    1534

    +
    duplicate_function_modifier:
    +
    duplicate function modifier
    +
    +

    1535

    +
    no_char16_t_representation:
    +
    invalid character for char16_t literal
    +
    +

    1537

    +
    cl_unrecognized_calling_convention:
    +
    unrecognized calling convention xxxx, must be one of:
    +
    +

    1541

    +
    enum_base_type_must_be_integral:
    +
    underlying type of enum type must be an integral type
    +
    +

    1542

    +
    enum_base_type_too_limited:
    +
    some enumerator constants cannot be represented by “type”
    +
    +

    1543

    +
    feature_not_allowed_in_current_mode:
    +
    “xxxx” not allowed in current mode
    +
    +

    1544

    +
    cl_type_traits_helpers_option_only_in_cplusplus:
    +
    type traits helpers option can be used only when compiling C++
    +
    +

    1545

    +
    gnu_sentinel_attribute_requires_ellipsis:
    +
    attribute “sentinel” requires an ellipsis parameter
    +
    +

    1546

    +
    invalid_gnu_sentinel_argument:
    +
    argument must be a constant null pointer value
    +
    +

    1547

    +
    no_gnu_sentinel_argument:
    +
    insufficient number of arguments for sentinel value
    +
    +

    1548

    +
    gnu_sentinel_must_be_ellipsis_argument:
    +
    sentinel argument must correspond to an ellipsis parameter
    +
    +

    1549

    +
    implementation_key_outside_mapping_region:
    +
    __declspec(implementation_key(…) can appear only between #pragma +start_map_region and #pragma stop_map_region
    +
    +

    1550

    +
    start_map_region_ignored:
    +
    #pragma start_map_region already active: pragma ignored
    +
    +

    1551

    +
    stop_map_region_ignored:
    +
    no #pragma start_map_region is currently active: pragma ignored
    +
    +

    1552

    +
    var_used_as_destructor:
    +
    entity-kind “entity” cannot be used to name a destructor (a type +name is required)
    +
    +

    1553

    +
    empty_wide_character:
    +
    nonstandard empty wide character literal treated as L’0’
    +
    +

    1554

    +
    invalid_typename_specifier:
    +
    “typename” may not be specified here
    +
    +

    1555

    +
    no_default_delete_in_virtual_dtor:
    +
    a non-placement operator delete must be visible in a class with a +virtual destructor
    +
    +

    1556

    +
    name_linkage_mismatch_for_variable:
    +
    name linkage conflicts with previous declaration of entity-kind +“entity” (declared at line xxxx)
    +
    +

    1557

    +
    alias_loop:
    +
    alias creates cycle of aliased entities
    +
    +

    1559

    +
    register_mapped_variable_cannot_have_initializer:
    +
    a variable with static storage duration allocated in a specific +register cannot be declared with an initializer
    +
    +

    1560

    +
    register_mapped_variable_must_be_POD:
    +
    a variable allocated in a specific register must be trivially copyable
    +
    +

    1561

    +
    predef_macro_redefined:
    +
    predefined meaning of “entity” discarded
    +
    +

    1563

    +
    designator_for_non_POD:
    +
    class type not suitable for use with designators
    +
    +

    1565

    +
    nonstandard_anonymous_union_qualifier:
    +
    anonymous union qualifier is nonstandard
    +
    +

    1566

    +
    anonymous_union_qualifier_ignored:
    +
    anonymous union qualifier is ignored
    +
    +

    1568

    +
    struct_declspec_ignored_in_C_mode:
    +
    __declspec(xxxx) ignored (it has no meaning for a C struct)
    +
    +

    1569

    +
    nonstandard_secondary_decl_specifiers:
    +
    specifiers after comma between declarations are nonstandard
    +
    +

    1570

    +
    secondary_specifier_ignored:
    +
    nonstandard specifier ignored
    +
    +

    1571

    +
    enum_attribute_ignored:
    +
    attributes are ignored on an enum declaration that is not also a +definition
    +
    +

    1572

    +
    reference_declared_mutable:
    +
    declaring a reference with “mutable” is nonstandard
    +
    +

    1573

    +
    array_condition_always_true:
    +
    a condition declaration for an array is always true
    +
    +

    1574

    +
    static_assert:
    +
    static assertion failed with “xxxx”
    +
    +

    1575

    +
    gnu_visibility_conflict:
    +
    visibility attribute ignored because it conflicts with a previous +declaration
    +
    +

    1576

    +
    pcc_field_ambiguity:
    +
    field name resolves to more than one offset – see “entity”(declared at line xxxx) and “entity” (declared at line +xxxx)
    +
    +

    1577

    +
    not_a_field_name:
    +
    “xxxx” is not a field name
    +
    +

    1578

    +
    case_label_conflict:
    +
    case label value has already appeared in this switch at line xxxx
    +
    +

    1579

    +
    member_cannot_have_internal_linkage:
    +
    a member function cannot have internal linkage
    +
    +

    1580

    +
    builtin_function_hidden:
    +
    declaration hides built-in entity-kind “entity”
    +
    +

    1581

    +
    builtin_function_overloaded:
    +
    declaration overloads built-in entity-kind “entity”
    +
    +

    1582

    +
    cl_list_macros_incompatible_with_multiple_trans_units:
    +
    the option to list macro definitions may not be specified when +compiling more than one translation unit
    +
    +

    1583

    +
    lparen_after_function:
    +
    unexpected parenthesis after declaration of entity-kind “entity”(malformed parameter list or invalid initializer?)
    +
    +

    1584

    +
    nonstandard_parenthesized_string_initializer:
    +
    parentheses around a string initializer are nonstandard
    +
    +

    1586

    +
    auto_variable_in_own_initializer:
    +
    a variable declared with an auto type specifier cannot appear in its +own initializer
    +
    +

    1587

    +
    cannot_deduce_auto_type:
    +
    cannot deduce “auto” type
    +
    +

    1588

    +
    auto_brace_initialization_not_allowed:
    +
    initialization with “{…}” is not allowed for “auto” type
    +
    +

    1589

    +
    auto_type_in_array_type:
    +
    “auto” type cannot appear in top-level array type
    +
    +

    1590

    +
    auto_type_in_function_type:
    +
    “auto” type cannot appear in top-level function type
    +
    +

    1591

    +
    invalid_member_constant_type:
    +
    a member of type “type” cannot have an in-class initializer
    +
    +

    1592

    +
    member_constant_not_const:
    +
    a member with an in-class initializer must be const
    +
    +

    1593

    +
    auto_type_requires_initializer:
    +
    cannot deduce “auto” type (initializer required)
    +
    +

    1594

    +
    inconsistent_deduction_of_auto:
    +
    “auto” type is “type” for this entity, but was previously implied +to be “type”
    +
    +

    1595

    +
    bad_constructor_decl:
    +
    invalid constructor declaration
    +
    +

    1596

    +
    bad_type_qualifier:
    +
    invalid use of a type qualifier
    +
    +

    1597

    +
    abstract_or_sealed_on_union:
    +
    a union cannot be abstract or sealed
    +
    +

    1598

    +
    auto_not_allowed_here:
    +
    “auto” is not allowed here
    +
    +

    1599

    +
    unfinished_base_class:
    +
    definition of base class type not completed yet
    +
    +

    1600

    +
    static_extern_template:
    +
    “extern template” cannot refer to a specialization of static +entity-kind “entity” (declared at line xxxx)
    +
    +

    1601

    +
    extern_template_follows_instantiation:
    +
    “extern template” cannot follow explicit instantiation of +entity-kind “entity”
    +
    +

    1602

    +
    bad_declspec_restrict_return:
    +
    __declspec(restrict) requires a function returning a pointer type
    +
    +

    1603

    +
    cl_report_gnu_extensions_requires_gnu_mode:
    +
    the “report_gnu_extensions” option is only valid in GNU C and GNU C++ +modes
    +
    +

    1604

    +
    vla_is_nonstandard:
    +
    variable-length array types are nonstandard
    +
    +

    1605

    +
    designator_is_nonstandard:
    +
    designators are nonstandard
    +
    +

    1606

    +
    extended_designator_is_gnu_extension:
    +
    this designator syntax is a GNU extension
    +
    +

    1607

    +
    compound_literal_is_nonstandard:
    +
    compound literals are nonstandard
    +
    +

    1608

    +
    statement_expression_is_gnu_extension:
    +
    statement expressions are a GNU extension
    +
    +

    1609

    +
    asm_name_after_definition:
    +
    asm name ignored for previously defined entity
    +
    +

    1610

    +
    attribute_is_gnu_extension:
    +
    attributes are a GNU extension
    +
    +

    1611

    +
    asm_operand_spec_is_gnu_extension:
    +
    extended asm syntax is a GNU feature
    +
    +

    1612

    +
    volatile_asm_is_gnu_extension:
    +
    volatile asm declarations are a GNU extension
    +
    +

    1613

    +
    asm_name_is_gnu_extension:
    +
    asm name specifiers are a GNU extension
    +
    +

    1614

    +
    gnu_restrict_is_nonstandard:
    +
    the “__restrict” qualifier is nonstandard
    +
    +

    1615

    +
    typeof_is_gnu_extension:
    +
    “typeof” is a GNU extension
    +
    +

    1616

    +
    typedef_modification_is_nonstandard:
    +
    modifying the size or signedness of a typedef is nonstandard
    +
    +

    1617

    +
    zero_length_array_is_gnu_extension:
    +
    zero-length arrays are a GNU extension
    +
    +

    1618

    +
    flexible_array_is_nonstandard:
    +
    flexible array members are nonstandard
    +
    +

    1619

    +
    nonnull_on_nonpointer:
    +
    attribute “nonnull” references nonpointer parameter
    +
    +

    1620

    +
    nonnull_parameter_number_too_large:
    +
    argument for attribute “nonnull” is larger than number of parameters
    +
    +

    1621

    +
    no_pointer_parameters:
    +
    no parameter has pointer type
    +
    +

    1622

    +
    null_argument_for_nonnull_parameter:
    +
    null argument provided for parameter marked with attribute “nonnull”
    +
    +

    1623

    +
    access_prevents_dtor_generation:
    +
    the destructor for “type” has been suppressed because the +destructor for “type” is inaccessible
    +
    +

    1624

    +
    suppressed_dtor_needed:
    +
    the suppressed destructor for “type” is needed
    +
    +

    1625

    +
    inline_gnu_noinline_conflict:
    +
    routine is both “inline” and “noinline”
    +
    +

    1626

    +
    invalid_cleanup_routine:
    +
    invalid cleanup routine
    +
    +

    1627

    +
    attribute_cleanup_requires_automatic_storage:
    +
    attribute “cleanup” requires automatic storage duration
    +
    +

    1628

    +
    attribute_cleanup_for_parameter:
    +
    attribute “cleanup” does not apply to parameters
    +
    +

    1629

    +
    bad_type_for_cleanup_routine:
    +
    cleanup routine has invalid type
    +
    +

    1630

    +
    nonstandard_conversion_for_cleanup:
    +
    call of cleanup routine requires suspect conversion
    +
    +

    1631

    +
    microsoft_ptr_signedness_must_follow_star:
    +
    __sptr and __uptr must follow a “*”
    +
    +

    1632

    +
    microsoft_ptr_signedness_conflict:
    +
    __sptr and __uptr cannot both be specified
    +
    +

    1633

    +
    microsoft_ptr_sign_extension:
    +
    widening pointer conversion from “type” to “type” extends +sign bit
    +
    +

    1634

    +
    microsoft_ptr_signedness_on_ptr_to_member:
    +
    __sptr and __uptr don’t apply to pointer-to-member types
    +
    +

    1635

    +
    const_mbr_suppresses_copy_asgn_decl:
    +
    the declaration of the copy assignment operator for “type” has +been suppressed because entity-kind “entity” is const
    +
    +

    1636

    +
    ref_mbr_suppresses_copy_asgn_decl:
    +
    the declaration of the copy assignment operator for “type” has +been suppressed because entity-kind “entity” has reference type
    +
    +

    1637

    +
    subobj_copy_asgn_decl_suppressed:
    +
    the declaration of the copy assignment operator for “type” has +been suppressed because that of “type” was suppressed
    +
    +

    1638

    +
    ambig_suppresses_copy_asgn_decl:
    +
    the declaration of the copy assignment operator for “type” has +been suppressed because that of “type” is ambiguous
    +
    +

    1639

    +
    access_suppresses_copy_asgn_decl:
    +
    the declaration of the copy assignment operator for “type” has +been suppressed because that of “type” is inaccessible
    +
    +

    1640

    +
    subobj_copy_ctor_decl_suppressed:
    +
    the declaration of the copy constructor for “type” has been +suppressed because that of “type” was suppressed
    +
    +

    1641

    +
    ambig_suppresses_copy_ctor_decl:
    +
    the declaration of the copy constructor for “type” has been +suppressed because that of “type” is ambiguous
    +
    +

    1642

    +
    access_suppresses_copy_ctor_decl:
    +
    the declaration of the copy constructor for “type” has been +suppressed because that of “type” is inaccessible
    +
    +

    1643

    +
    inaccessible_dtor_not_invoked:
    +
    the destructor for “type” will not be called because it is +inaccessible and the destructor for “type” was suppressed
    +
    +

    1644

    +
    file_ends_with_unterminated_type_definition:
    +
    definition at end of file not followed by a semicolon or a declarator
    +
    +

    1645

    +
    bad_type_for_gnu_sync_function:
    +
    first argument must be a pointer to integer or enum type
    +
    +

    1646

    +
    invalid_gnu_sync_size:
    +
    synchronized operations are valid only on objects of size 1, 2, 4, or +8
    +
    +

    1647

    +
    extra_arguments_ignored:
    +
    extra arguments ignored
    +
    +

    1648

    +
    equals_assumed_in_cmd_line_macro_def:
    +
    ‘=’ assumed following macro name “xxxx” in command-line definition
    +
    +

    1649

    +
    white_space_required_after_macro_name:
    +
    white space is required between the macro name “xxxx” and its +replacement text
    +
    +

    1650

    +
    call_result_should_be_used:
    +
    result of call is not used
    +
    +

    1651

    +
    warn_unused_result_with_void_return:
    +
    attribute “warn_unused_result” is ignored for void return type
    +
    +

    1653

    +
    dll_interface_ignored_on_qualified_declaration:
    +
    dllimport/dllexport is ignored on redeclaration using a qualified name
    +
    +

    1654

    +
    leading_character_ignored_in_char_literal:
    +
    too many characters in character literal – extra leading characters +ignored
    +
    +

    1655

    +
    first_inline_after_definition:
    +
    entity-kind “entity” cannot be declared inline after its +definition at line xxxx
    +
    +

    1658

    +
    type_with_no_linkage_in_template_arg:
    +
    a template argument may not reference a type with no name linkage
    +
    +

    1659

    +
    virtual_ignored:
    +
    “virtual” is ignored here
    +
    +

    1660

    +
    vla_type_in_template_arg:
    +
    a template argument may not reference a variable-length array type
    +
    +

    1661

    +
    UCN_names_surrogate_code_point:
    +
    a universal character name cannot designate a surrogate code point
    +
    +

    1662

    +
    include_next_in_primary_source_file:
    +
    #include_next cannot be used in the primary source file
    +
    +

    1663

    +
    bad_template_member_definition:
    +
    “entity” cannot be specified in a template member definition – +“entity” assumed instead
    +
    +

    1664

    +
    local_function_attribute_ignored:
    +
    attribute “xxxx” is ignored on local function declaration
    +
    +

    1665

    +
    concat_yields_invalid_token:
    +
    concatenation with “xxxx” in entity-kind “entity” does not +create a valid token
    +
    +

    1666

    +
    ambiguous_injected_template_name:
    +
    “entity” is ambiguous (entity-kind “entity” assumed)
    +
    +

    1667

    +
    function_qualifier_on_static_member:
    +
    a type qualifier is not allowed on a static member function
    +
    +

    1668

    +
    function_qualifier_on_ctor_or_dtor:
    +
    a type qualifier is not allowed on a constructor or destructor
    +
    +

    1669

    +
    function_qualifier_on_new_or_delete:
    +
    a type qualifier is not allowed on operator new or operator delete
    +
    +

    1670

    +
    function_qualifier_on_nonmember:
    +
    a type qualifier is not allowed on a nonmember function
    +
    +

    1671

    +
    assume_expression_discarded:
    +
    argument to xxxx has side-effects but is unevaluated
    +
    +

    1672

    +
    cl_unrecognized_unicode_source_kind:
    +
    unrecognized Unicode source kind (must be one of UTF-8, UTF-16, +UTF-16LE, UTF-16BE): xxxx
    +
    +

    1673

    +
    bad_unicode_char_in_pp_output:
    +
    Unicode character with hex value xxxx not representable in +preprocessing output
    +
    +

    1674

    +
    ctor_dtor_priority_reserved:
    +
    requested constructor/destructor priority is reserved for internal use
    +
    +

    1675

    +
    unrecognized_gcc_pragma:
    +
    unrecognized GCC pragma
    +
    +

    1676

    +
    unrecognized_gcc_visibility_pragma:
    +
    unrecognized GCC visibility pragma directive
    +
    +

    1677

    +
    unrecognized_visibility:
    +
    unrecognized visibility kind
    +
    +

    1678

    +
    ELF_visibility_pop_mismatch:
    +
    visibility pragma was still active
    +
    +

    1679

    +
    ELF_visibility_stack_empty:
    +
    no matching visibility push
    +
    +

    1680

    +
    typeid_of_incomplete_type:
    +
    typeid of incomplete type
    +
    +

    1682

    +
    array_size_one_assumed:
    +
    array entity-kind “entity” assumed to have one element
    +
    +

    1683

    +
    vector_size_attribute_requires_integral_floating_or_enum_type:
    +
    vector_size attribute requires an arithmetic or enum type
    +
    +

    1684

    +
    vector_size_too_large:
    +
    vector size is too large
    +
    +

    1685

    +
    vector_size_must_be_power_of_two:
    +
    the number of elements in a vector must be a power of two
    +
    +

    1686

    +
    vector_size_must_be_multiple_of_element_size:
    +
    vector size must be a multiple of the element size
    +
    +

    1687

    +
    mixed_vector_scalar_operation:
    +
    mixed vector-scalar operation not allowed
    +
    +

    1688

    +
    vectors_must_have_same_size:
    +
    operation requires two vectors of the same size
    +
    +

    1689

    +
    dependent_vector_size:
    +
    template-dependent vector size is not allowed
    +
    +

    1692

    +
    vector_size_attribute_on_complex_type:
    +
    vector_size attribute is not allowed with a complex element type
    +
    +

    1694

    +
    vector_element_type_mismatch:
    +
    vector operation requires identical element types
    +
    +

    1695

    +
    vector_operation_requires_integer_vector:
    +
    vector operation does not apply to vector with non-integral type
    +
    +

    1696

    +
    cannot_open_file:
    +
    cannot open xxxx file “xxxx”
    +
    +

    1697

    +
    cannot_open_file_reason:
    +
    cannot open xxxx file “xxxx”: xxxx
    +
    +

    1703

    +
    file_write_error_errno:
    +
    error while writing xxxx file: xxxx
    +
    +

    1712

    +
    il_output:
    +
    IL output
    +
    +

    1713

    +
    restrict_qualifier_dropped:
    +
    conversion drops “__restrict” qualifier
    +
    +

    1714

    +
    unable_to_get_mapped_memory_reason:
    +
    unable to obtain mapped memory for “xxxx”: xxxx
    +
    +

    1715

    +
    restrict_qualifier_ignored:
    +
    restrict qualifier is ignored
    +
    +

    1717

    +
    nonstandard_array_with_flexible_array_element:
    +
    array of elements containing a flexible array member is nonstandard
    +
    +

    1718

    +
    vector_template_parameter:
    +
    a template parameter may not have a vector type
    +
    +

    1719

    +
    out_of_order_ctor_init:
    +
    the initialization of entity-kind “entity” will be done before +that of entity-kind “entity”
    +
    +

    1721

    +
    inheritance_kind_ignored_on_enum:
    +
    inheritance kind is ignored on an enum specifier
    +
    +

    1723

    +
    extended_modifier_ignored_on_enum:
    +
    modifier is ignored on an enum specifier
    +
    +

    1724

    +
    non_unicode_char_in_ident:
    +
    identifier character cannot be represented in Unicode
    +
    +

    1725

    +
    non_unicode_char_in_header:
    +
    header name contains characters that cannot be represented in Unicode
    +
    +

    1726

    +
    invalid_locale:
    +
    “xxxx” is not a valid locale name
    +
    +

    1727

    +
    nonstd_template_void_param_list:
    +
    declaring a void parameter list with a template parameter is +nonstandard
    +
    +

    1728

    +
    cl_lambdas_option_only_in_cplusplus:
    +
    lambdas option can be used only when compiling C++
    +
    +

    1729

    +
    capture_mode_matches_default:
    +
    explicit capture matches default
    +
    +

    1730

    +
    not_a_variable:
    +
    entity-kind “entity” is not a variable
    +
    +

    1731

    +
    capture_of_static_duration_variable:
    +
    a variable with static storage duration cannot be captured in a lambda
    +
    +

    1732

    +
    cannot_capture_this_by_reference:
    +
    “this” cannot be captured by reference
    +
    +

    1733

    +
    this_in_lambda:
    +
    “this” cannot be used inside the body of this lambda
    +
    +

    1734

    +
    anon_union_ref_in_lambda:
    +
    a member of an outer-scope anonymous union cannot be referenced +inside the body of a lambda
    +
    +

    1735

    +
    not_captured_local_var_in_lambda:
    +
    an enclosing-function local variable cannot be referenced in a lambda +body unless it is in the capture list
    +
    +

    1736

    +
    bad_local_var_in_lambda:
    +
    invalid reference to an outer-scope local variable in a lambda body
    +
    +

    1737

    +
    captured_local_var_not_in_innermost_function:
    +
    a local variable outside the current function scope cannot be captured
    +
    +

    1738

    +
    not_captured_this_in_lambda:
    +
    the enclosing-function “this” cannot be referenced in a lambda body +unless it is in the capture list
    +
    +

    1740

    +
    captured_var_type_not_copyable:
    +
    lambda captured variable of type “type” cannot be copied to +closure class field of type “type”
    +
    +

    1741

    +
    cl_invalid_template_directory:
    +
    invalid template directory: xxxx
    +
    +

    1749

    +
    enum_value_out_of_underlying_range:
    +
    enumeration value is outside the range of its underlying type +(“type”)
    +
    +

    1750

    +
    not_a_line_splice:
    +
    “" followed by white space is not a line splice
    +
    +

    1751

    +
    dynamic_cast_without_rtti:
    +
    this dynamic_cast cannot be done without runtime type information, +which is disabled
    +
    +

    1752

    +
    ambiguous_cast_selects_direct_base:
    +
    conversion to “type” is ambiguous; direct base selected
    +
    +

    1753

    +
    requested_size_too_large:
    +
    an internal buffer would be too large
    +
    +

    1754

    +
    exception_handler_used:
    +
    C++ exception handler used, but exception handling semantics have not +been specified
    +
    +

    1755

    +
    type_qualifier_ignored_on_constructor:
    +
    type qualifier ignored on constructor
    +
    +

    1756

    +
    lambda_capture_involves_variable_length_array:
    +
    a variable captured by a lambda cannot have a type involving a +variable-length array
    +
    +

    1757

    +
    incompatible_vectors_conversion:
    +
    conversion between incompatible vector types
    +
    +

    1758

    +
    missing_lambda_body:
    +
    expected a “{” introducing a lambda body
    +
    +

    1759

    +
    cl_rvalue_references_option_only_in_cplusplus:
    +
    rvalue references option can be used only when compiling C++
    +
    +

    1760

    +
    type_qualifier_on_lambda:
    +
    a type qualifier is not allowed on a lambda
    +
    +

    1761

    +
    more_than_one_capture:
    +
    a name cannot appear more than once in a capture-list
    +
    +

    1762

    +
    explicit_template_args_ignored:
    +
    explicit template arguments ignored
    +
    +

    1763

    +
    bad_constant_lambda:
    +
    a lambda is not allowed in a constant expression
    +
    +

    1764

    +
    class_type_required:
    +
    “type” is not a class type
    +
    +

    1765

    +
    delete_of_array_type:
    +
    “delete” applied to a pointer-to-array type treated as delete[]
    +
    +

    1766

    +
    delete_of_array_type_nonstandard:
    +
    “delete” applied to a pointer-to-array type is nonstandard; treated +as delete[]
    +
    +

    1767

    +
    function_does_not_match_arguments:
    +
    entity-kind “entity” cannot be called with the given argument list
    +
    +

    1768

    +
    rvalue_reference_bound_to_lvalue:
    +
    an rvalue reference cannot be bound to an lvalue
    +
    +

    1769

    +
    rvalue_ref_template_parameter:
    +
    a nontype template parameter cannot have rvalue reference type
    +
    +

    1770

    +
    type_qualifiers_ignored_on_reference:
    +
    type qualifiers are ignored (underlying type is a reference)
    +
    +

    1771

    +
    decl_with_local_type_but_not_defined:
    +
    entity-kind “entity”, declared using a local type, must be +defined in this translation unit
    +
    +

    1772

    +
    decl_with_no_linkage_type_but_not_defined:
    +
    entity-kind “entity”, declared using a type with no linkage, must +be defined in this translation unit
    +
    +

    1773

    +
    bad_rvalue_ref_dynamic_cast_operand:
    +
    the operand of an rvalue reference dynamic_cast must have a complete +class type
    +
    +

    1774

    +
    invalid_function_to_be_defaulted:
    +
    “= default” can only appear on default constructors, copy/move +constructors, copy/move assignment operators, and destructors
    +
    +

    1775

    +
    deleted_function_definition_must_be_first_declaration:
    +
    “= delete” can only appear on the first declaration of a function
    +
    +

    1776

    +
    deleted_function:
    +
    entity-kind “entity” (declared at line xxxx) cannot be +referenced – it is a deleted function
    +
    +

    1777

    +
    bad_unevaluated_lambda:
    +
    a lambda is not allowed in an unevaluated expression
    +
    +

    1778

    +
    bad_function_for_gnu_va_arg_pack:
    +
    __builtin_va_arg_pack/__builtin_va_arg_pack_len can appear only in +an inline function with an ellipsis parameter
    +
    +

    1779

    +
    function_defaulted_in_friend_decl:
    +
    “= default” cannot be specified on a friend declaration
    +
    +

    1780

    +
    exp_cpp_keyword:
    +
    expected a C++ keyword
    +
    +

    1782

    +
    nonconstant_offsetof:
    +
    offset is not constant
    +
    +

    1783

    +
    unrecognized_microsoft_comment_pragma_type:
    +
    unrecognized #pragma comment type “xxxx”
    +
    +

    1784

    +
    cl_auto_type_option_only_in_cplusplus:
    +
    option to control whether “auto” is a type specifier can be used only +when compiling C++
    +
    +

    1785

    +
    cl_auto_storage_option_only_in_cplusplus:
    +
    option to control whether “auto” is a storage class can be used only +when compiling C++
    +
    +

    1786

    +
    cl_auto_cannot_be_disabled:
    +
    the type specifier and storage class specifier meanings of “auto” +cannot both be disabled
    +
    +

    1787

    +
    bad_pragma_comment_string:
    +
    invalid string in #pragma comment
    +
    +

    1788

    +
    deleted_function_overrides_nondeleted_function:
    +
    deleted function overrides nondeleted entity-kind “entity”
    +
    +

    1789

    +
    nondeleted_function_overrides_deleted_function:
    +
    nondeleted function overrides deleted entity-kind “entity”
    +
    +

    1790

    +
    deleted_default_constructor:
    +
    the default constructor of “type” cannot be referenced – it is a +deleted function
    +
    +

    1791

    +
    rvalue_reference_catch_type:
    +
    an rvalue reference is not allowed as a catch type
    +
    +

    1792

    +
    default_args_incompatible:
    +
    default arguments of entity-kind “entity” is incompatible with a +declaration in another translation unit
    +
    +

    1793

    +
    default_arg_differs_in_other_trans_unit:
    +
    default arguments of entity-kind “entity” were different during +compilation of “xxxx”
    +
    +

    1795

    +
    initializers_incompatible:
    +
    initializer for entity-kind “entity” is different in another +translation unit
    +
    +

    1796

    +
    initializer_differs_in_other_trans_unit:
    +
    initializer for entity-kind “entity” was different during +compilation of “xxxx”
    +
    +

    1797

    +
    designator_for_template_dependent_type:
    +
    a designator into a template-dependent type is not allowed
    +
    +

    1798

    +
    invalid_pragma_conform_kind:
    +
    unrecognized conformance kind
    +
    +

    1799

    +
    exp_on_or_off:
    +
    expected “on” or “off”
    +
    +

    1800

    +
    forScope_stack_empty:
    +
    #pragma conform(forScope) stack is empty
    +
    +

    1801

    +
    no_matching_forScope_stack_entry:
    +
    no previous #pragma conform(forScope) entry matches “xxxx”
    +
    +

    1802

    +
    show_pragma_conform_forScope_is_nonstandard:
    +
    forScope behavior is nonstandard
    +
    +

    1803

    +
    show_pragma_conform_forScope_is_standard:
    +
    forScope behavior is standard
    +
    +

    1804

    +
    deleted_main:
    +
    function “main” cannot be deleted
    +
    +

    1805

    +
    useless_type_qualifiers_in_type_name:
    +
    type qualifiers are meaningless here
    +
    +

    1806

    +
    invalid_assignment_operator_to_be_defaulted:
    +
    invalid type for defaulted assignment operator
    +
    +

    1807

    +
    function_template_cannot_be_defaulted:
    +
    function templates cannot be defaulted
    +
    +

    1808

    +
    invalid_constructor_to_be_defaulted:
    +
    invalid type for defaulted constructor
    +
    +

    1809

    +
    call_requires_one_argument:
    +
    function call requires one argument
    +
    +

    1810

    +
    call_requires_floating_point_argument:
    +
    function call requires a real floating-point argument
    +
    +

    1811

    +
    copy_ctor_with_default_arg_cannot_be_defaulted:
    +
    a copy constructor with a default argument cannot be defaulted
    +
    +

    1812

    +
    predeclared_function_cannot_be_deleted:
    +
    a predeclared function cannot be deleted
    +
    +

    1813

    +
    empty_then_statement:
    +
    empty dependent statement in if-statement
    +
    +

    1814

    +
    empty_else_statement:
    +
    empty dependent statement in “else” clause of if-statement
    +
    +

    1815

    +
    deleted_elided_cctor:
    +
    entity-kind “entity” (declared at line xxxx), required for +copy that was eliminated, cannot be referenced – it is a deleted +function
    +
    +

    1816

    +
    main_first_param_not_int:
    +
    nonstandard first parameter “type” of “main”, expected “int”
    +
    +

    1817

    +
    main_wrong_num_params:
    +
    nonstandard number of parameters for “main”, expected zero or two +parameters
    +
    +

    1818

    +
    main_second_param_wrong_type:
    +
    nonstandard second parameter “type” of “main”, expected “char +*[]” or “char **”
    +
    +

    1819

    +
    incl_dir_both_sys_and_nonsys:
    +
    “xxxx” was specified as both a system and non-system include +directory – the non-system entry will be ignored
    +
    +

    1820

    +
    cl_rvalue_ctor_is_copy_ctor_option_only_in_cplusplus:
    +
    option to control move constructors and move assignment operators can +be used only when compiling C++
    +
    +

    1823

    +
    trailing_return_type_requires_auto:
    +
    a trailing return type requires the “auto” type specifier
    +
    +

    1824

    +
    trailing_return_type_in_nested_declarator:
    +
    a trailing return type cannot appear in a nested declarator
    +
    +

    1825

    +
    trailing_return_type_function_without_simple_auto:
    +
    a function declarator with a trailing return type must be preceded by +a simple “auto” type specifier
    +
    +

    1826

    +
    missing_trailing_return_type:
    +
    “auto” function requires a trailing return type
    +
    +

    1827

    +
    pure_virtual_member_template:
    +
    a member template cannot have a pure specifier
    +
    +

    1828

    +
    excess_characters_in_literal_ignored:
    +
    string literal too long – excess characters ignored
    +
    +

    1830

    +
    nullptr_conv_to_bool:
    +
    std::nullptr_t converted to bool
    +
    +

    1833

    +
    invalid_empty_attribute_arg_list:
    +
    attribute “xxxx” does not allow an empty argument list
    +
    +

    1834

    +
    attr_twice_in_group:
    +
    attribute appears more than once
    +
    +

    1835

    +
    wrong_entity_for_attribute:
    +
    attribute “xxxx” does not apply here
    +
    +

    1836

    +
    attr_disallows_bit_field:
    +
    attribute “xxxx” does not apply to bit fields
    +
    +

    1837

    +
    attr_requires_bit_field:
    +
    attribute “xxxx” requires a bit field
    +
    +

    1838

    +
    attr_disallows_member_function:
    +
    attribute “xxxx” does not apply to member functions
    +
    +

    1839

    +
    attr_requires_member_function:
    +
    attribute “xxxx” requires a member function
    +
    +

    1840

    +
    attr_disallows_virtual_function:
    +
    attribute “xxxx” does not apply to virtual functions
    +
    +

    1841

    +
    attr_requires_virtual_function:
    +
    attribute “xxxx” requires a virtual function
    +
    +

    1842

    +
    attr_disallows_pure_virtual_function:
    +
    attribute “xxxx” does not apply to pure virtual functions
    +
    +

    1843

    +
    attr_requires_pure_virtual_function:
    +
    attribute “xxxx” requires a pure virtual function
    +
    +

    1844

    +
    attr_disallows_register_storage:
    +
    attribute “xxxx” does not apply to register variables
    +
    +

    1845

    +
    attr_requires_register_storage:
    +
    attribute “xxxx” requires a register variable
    +
    +

    1846

    +
    attr_must_also_appear_in_first_declaration:
    +
    attribute “xxxx” did not appear on original declaration
    +
    +

    1847

    +
    invalid_attribute_location:
    +
    attributes are not allowed here
    +
    +

    1848

    +
    attr_must_appear_in_class_definition:
    +
    attribute “xxxx” must appear in a class definition
    +
    +

    1849

    +
    pure_final_virtual:
    +
    “final” applied to a pure virtual function
    +
    +

    1850

    +
    override_of_final_function:
    +
    cannot override “final” entity-kind “entity” (declared at line +xxxx)
    +
    +

    1851

    +
    undefined_static_function_treated_as_extern:
    +
    static entity-kind “entity” treated as extern because it was +referenced but not defined
    +
    +

    1852

    +
    cl_gnu_c89_inlining_option_only_in_C:
    +
    option to enable GNU-C89-style inlining can be used only when +compiling C
    +
    +

    1853

    +
    first_decl_not_gnu_inline:
    +
    function was previously declared without the “gnu_inline” attribute
    +
    +

    1854

    +
    gnu_inline_requires_inline:
    +
    the “gnu_inline” attribute is ignored on non-inline functions
    +
    +

    1855

    +
    carries_dependency_not_on_first_decl:
    +
    entity-kind “entity” previously declared without the +carries_dependency attribute
    +
    +

    1856

    +
    bad_array_member_initialization:
    +
    invalid initializer for array entity-kind “entity”
    +
    +

    1857

    +
    cl_must_specify_cpp11_mode:
    +
    must specify C++11 or C++14 mode when building runtime library
    +
    +

    1858

    +
    attr_disallows_function_type:
    +
    attribute “xxxx” does not apply to function types
    +
    +

    1859

    +
    attr_requires_function_type:
    +
    attribute “xxxx” requires a function type
    +
    +

    1860

    +
    attribute_ignored_on_nonstatic_member_function:
    +
    attribute “xxxx” does not apply to nonstatic member functions
    +
    +

    1861

    +
    attr_disallows_automatic_storage:
    +
    attribute “xxxx” does not apply to automatic variables
    +
    +

    1862

    +
    attr_requires_automatic_storage:
    +
    attribute “xxxx” requires an automatic variable
    +
    +

    1863

    +
    attr_disallows_external_linkage:
    +
    attribute “xxxx” does not apply to a variable or function with +external linkage
    +
    +

    1864

    +
    attr_requires_local_variable:
    +
    attribute “xxxx” requires a local variable
    +
    +

    1865

    +
    attributes_ignored:
    +
    attributes ignored here
    +
    +

    1866

    +
    unattached_attribute:
    +
    attribute does not apply to any entity
    +
    +

    1867

    +
    bad_attribute_template_substitution:
    +
    bad attribute argument substitution
    +
    +

    1868

    +
    bad_tls_model_attr_arg:
    +
    the argument of the “tls_model” attribute must be “global-dynamic”, +“local-dynamic”, “initial-exec”, or “local-exec”
    +
    +

    1869

    +
    inconsistent_tls_model_attr_arg:
    +
    the declaration at line xxxx specified a different “tls_model” +argument
    +
    +

    1870

    +
    attr_disallows_inline:
    +
    attribute “xxxx” does not apply to inline functions
    +
    +

    1871

    +
    attr_requires_inline:
    +
    attribute “xxxx” requires a inline function
    +
    +

    1872

    +
    include_kind_mismatch:
    +
    both file names in an include_alias pragma must use the same +delimiter characters
    +
    +

    1873

    +
    signed_unsigned_comparison:
    +
    comparison between signed and unsigned operands
    +
    +

    1874

    +
    attribute_ignored_on_unnamed_type:
    +
    attribute “xxxx” ignored on unnamed type
    +
    +

    1875

    +
    attribute_ignored_on_nondefinition:
    +
    attribute “xxxx” ignored because no definition follows
    +
    +

    1876

    +
    incompatible_thread_locality:
    +
    thread locality is incompatible with a previous declaration of +entity-kind “entity” (declared at line xxxx)
    +
    +

    1877

    +
    no_implicit_capture_on_enclosing_lambda:
    +
    this enclosing-function local variable cannot be referenced in this +lambda body because an enclosing lambda does not allow implicit +captures
    +
    +

    1878

    +
    unbalanced_attribute_argument:
    +
    this attribute argument contains unmatched parentheses, brackets, or +braces
    +
    +

    1879

    +
    invalid_builtin_fpclassify_args:
    +
    a call to __builtin_fpclassify requires five integral arguments +followed by one floating-point argument
    +
    +

    1880

    +
    bad_final_builtin_fpclassify_arg:
    +
    the last argument in a call to __builtin_fpclassify must have a real +floating-point type
    +
    +

    1881

    +
    invalid_alignment_reducing_attr:
    +
    alignment cannot be set to less than the default alignment
    +
    +

    1882

    +
    attribute_on_explicit_instantiation:
    +
    attributes are not allowed on explicit instantiations
    +
    +

    1883

    +
    attr_disallows_definition:
    +
    attribute “xxxx” does not apply to a definition
    +
    +

    1884

    +
    attr_requires_definition:
    +
    attribute “xxxx” requires a definition
    +
    +

    1885

    +
    friend_attribute_requires_definition:
    +
    standard attributes cannot appear on friend declarations that are not +definitions
    +
    +

    1886

    +
    inconsistent_alignment:
    +
    specified alignment (xxxx) is different from alignment (xxxx) +specified on a previous declaration
    +
    +

    1887

    +
    variable_align_attr_not_on_definition:
    +
    alignment attribute must also appear on definition at line xxxx
    +
    +

    1888

    +
    alias_used_in_type:
    +
    entity-kind “entity” may not be used in the type-id of the +alias-declaration
    +
    +

    1890

    +
    transparent_union_cannot_have_floating_first_field:
    +
    “type” cannot be transparent because its first field has a +floating-point type
    +
    +

    1891

    +
    transparent_union_cannot_have_bit_field_first:
    +
    “type” cannot be transparent because its first field is a bit +field
    +
    +

    1892

    +
    missing_override_attr_in_base_check_class:
    +
    virtual function of a “base_check” class overrides a base class +member but lacks the “override” attribute
    +
    +

    1893

    +
    hiding_attr_on_nonhiding_member:
    +
    “hiding” attribute specified on a declaration that does not hide a +base class declaration
    +
    +

    1894

    +
    hiding_attr_on_unhidden_member:
    +
    “hiding” attribute specified on a declaration referred to by the +using-declaration at line xxxx
    +
    +

    1895

    +
    hiding_attr_required:
    +
    attribute “hiding” is required on a declaration (in a “base_check” +class) that hides entity-kind “entity” (declared at line xxxx)
    +
    +

    1896

    +
    undefined_decl_using_local_type:
    +
    entity-kind “entity” is not defined in this translation unit but +depends on a local type
    +
    +

    1897

    +
    undefined_decl_using_no_linkage_type:
    +
    entity-kind “entity” is not defined in this translation unit but +depends on a type with no linkage
    +
    +

    1898

    +
    missing_attribute_in_other_translation_unit:
    +
    attribute “xxxx” is missing in another translation unit
    +
    +

    1899

    +
    conflicting_attribute_in_other_translation_unit:
    +
    attribute “xxxx” conflicts with another translation unit
    +
    +

    1900

    +
    cl_nonstd_gnu_keywords_requires_gnu_mode:
    +
    the “nonstd_gnu_keywords” option is only valid in GNU C and GNU C++ +modes
    +
    +

    1901

    +
    const_var_in_C_const_expr:
    +
    use of a const variable in a constant expression is nonstandard in C
    +
    +

    1902

    +
    cannot_init_auto_flexible_array_member:
    +
    an initializer cannot be specified for a flexible array member with +automatic storage duration
    +
    +

    1904

    +
    final_base_class:
    +
    a “final” class type cannot be used as a base class
    +
    +

    1905

    +
    export_removed:
    +
    exported templates are no longer in the standard C++ language
    +
    +

    1906

    +
    template_dependent_designator:
    +
    a template-dependent designator is not allowed
    +
    +

    1907

    +
    offsetof_ref_field:
    +
    second operand of offsetof may not be a field with reference type
    +
    +

    1908

    +
    cl_long_lifetime_temps_incompat_with_newer_features:
    +
    long lifetime temporaries are incompatible with other requested newer +language features
    +
    +

    1909

    +
    wide_deprecation_string:
    +
    wide character string literal will not be quoted in diagnostics
    +
    +

    1910

    +
    missing_attribute_arguments:
    +
    missing arguments for attribute “xxxx”
    +
    +

    1911

    +
    sfinae_requires_newer_abi_version:
    +
    options “c++11” and “c++11_sfinae” require a different compiler +configuration
    +
    +

    1912

    +
    template_param_pack_not_at_end:
    +
    template parameter pack not at end of parameter list
    +
    +

    1913

    +
    parameter_pack_decl_not_allowed:
    +
    a parameter pack declaration is not allowed here
    +
    +

    1914

    +
    param_pack_cannot_have_default:
    +
    a parameter pack cannot have a default
    +
    +

    1915

    +
    cl_cppcli_only_in_microsoft_cplusplus:
    +
    C++/CLI can be enabled only in Microsoft C++ mode
    +
    +

    1916

    +
    reserved_enumerator_name:
    +
    “value__” cannot be used as the name of an enumerator constant (it +is a reserved name in this context)
    +
    +

    1917

    +
    cppcli_enumerator_requires_explicit_value:
    +
    an explicit enumerator value is required in an enum type with boolean +underlying type
    +
    +

    1919

    +
    pack_not_expanded:
    +
    parameter pack “xxxx” was referenced but not expanded
    +
    +

    1920

    +
    expansion_contains_no_packs:
    +
    pack expansion does not make use of any argument packs
    +
    +

    1921

    +
    pack_length_mismatch:
    +
    pack “xxxx” does not have the same number of elements as +“xxxx”
    +
    +

    1923

    +
    vector_size_attribute_on_enum_type:
    +
    vector_size attribute is not allowed with an enum type
    +
    +

    1924

    +
    virtual_static_property:
    +
    a property cannot be both static and virtual
    +
    +

    1925

    +
    trivial_indexed_property:
    +
    an indexed property cannot be trivial
    +
    +

    1926

    +
    invalid_property_accessor_decl:
    +
    this declaration cannot appear in a property definition
    +
    +

    1927

    +
    qualified_cli_accessor:
    +
    a qualified function type cannot be used to declare an accessor +function
    +
    +

    1928

    +
    ellipsis_cli_accessor:
    +
    an accessor function cannot have an ellipsis parameter
    +
    +

    1929

    +
    property_get_already_declared:
    +
    a “get” accessor was already declared for this property at line +xxxx
    +
    +

    1930

    +
    property_set_already_declared:
    +
    a “set” accessor was already declared for this property at line +xxxx
    +
    +

    1931

    +
    property_get_cannot_have_parameter:
    +
    a “get” accessor cannot have a parameter
    +
    +

    1932

    +
    bad_property_get_return:
    +
    return type of “get” accessor does not match property type
    +
    +

    1933

    +
    bad_property_set_return:
    +
    return type of “set” accessor must be void
    +
    +

    1934

    +
    empty_property_indices:
    +
    a property cannot declare an empty list of indices
    +
    +

    1935

    +
    void_property_index_type:
    +
    a property index cannot have type void
    +
    +

    1936

    +
    property_set_index_type_mismatch:
    +
    index type does not match the corresponding parameter in the “set” +accessor
    +
    +

    1937

    +
    property_get_index_type_mismatch:
    +
    index type does not match the corresponding parameter in the “get” +accessor
    +
    +

    1938

    +
    property_set_index_type_missing:
    +
    index type is missing in the “set” accessor
    +
    +

    1939

    +
    property_get_index_type_missing:
    +
    index type is missing in the “get” accessor
    +
    +

    1940

    +
    property_set_missing_value_parameter:
    +
    “set” accessor is missing its value parameter
    +
    +

    1941

    +
    extra_property_accessor_parameters:
    +
    accessor function has too many parameters
    +
    +

    1942

    +
    property_set_value_parameter_mismatch:
    +
    the last parameter of the “set” accessor does not match the property +type
    +
    +

    1943

    +
    cppcli_not_enabled:
    +
    “xxxx” requires C++/CLI mode
    +
    +

    1944

    +
    win32_api_error:
    +
    error in Win32 API “xxxx“: xxxx
    +
    +

    1945

    +
    using_not_at_file_scope:
    +
    #using may only be used at global scope
    +
    +

    1947

    +
    member_name_reserved_by_property:
    +
    member name “xxxx” is reserved by entity-kind “entity”(declared at line xxxx)
    +
    +

    1948

    +
    exp_lbracket:
    +
    expected a “[”
    +
    +

    1949

    +
    cl_microsoft_version_insufficient_for_cppcli:
    +
    C++/CLI mode requires microsoft_version >= 1600
    +
    +

    1950

    +
    static_default_indexed_property:
    +
    a default-indexed property cannot be static
    +
    +

    1951

    +
    virtual_static_property_accessor:
    +
    a property accessor cannot be both static and virtual
    +
    +

    1952

    +
    visibility_specifier_on_nested_type:
    +
    a top-level visibility specifier cannot appear on a nested type +declaration
    +
    +

    1953

    +
    visibility_specifier_requires_definition:
    +
    a top-level visibility specifier requires a type definition
    +
    +

    1954

    +
    trivial_reference_property:
    +
    a trivial property cannot have a reference type
    +
    +

    1955

    +
    trivial_const_or_volatile_property:
    +
    a trivial property cannot have a const or volatile type
    +
    +

    1956

    +
    incompatible_enum_kinds:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared as a different kind of enum type
    +
    +

    1957

    +
    lambda_captures_managed_class_type:
    +
    a variable captured by a lambda cannot have a managed class type
    +
    +

    1958

    +
    covariant_override_in_managed_class:
    +
    virtual function overriding with a covariant return type is not +allowed in a managed class
    +
    +

    1959

    +
    array_of_handle:
    +
    array of handles is not allowed
    +
    +

    1960

    +
    handle_to_array:
    +
    handle to array is not allowed
    +
    +

    1961

    +
    handle_to_function:
    +
    handle to function is not allowed
    +
    +

    1962

    +
    handle_to_void:
    +
    handle to void is not allowed
    +
    +

    1963

    +
    handle_to_address_type:
    +
    handle to handle, pointer, or reference is not allowed
    +
    +

    1964

    +
    tracking_reference_to_function:
    +
    tracking reference to function is not allowed
    +
    +

    1966

    +
    field_cannot_be_tracking_reference:
    +
    a field cannot be a tracking reference
    +
    +

    1967

    +
    invalid_ref_tracking_ref_combination:
    +
    a tracking reference cannot be combined with an ordinary reference in +this way
    +
    +

    1968

    +
    static_storage_variable_with_ref_class_type:
    +
    a variable with static storage duration cannot have a ref class type
    +
    +

    1969

    +
    unnamed_cli_managed_class_type:
    +
    a managed class cannot be unnamed
    +
    +

    1970

    +
    local_cli_managed_class_type:
    +
    a managed class cannot be local
    +
    +

    1971

    +
    conflicting_cli_class_type_kinds:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared as a different kind of class
    +
    +

    1972

    +
    conflicting_cli_class_template_kinds:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared as a different kind of class template
    +
    +

    1973

    +
    literal_requires_managed_class:
    +
    literal data members can only be members of managed classes
    +
    +

    1974

    +
    literal_without_initializer:
    +
    a literal data member must be initialized
    +
    +

    1975

    +
    invalid_literal_type:
    +
    a literal data member of type “type” is not allowed
    +
    +

    1976

    +
    literal_const_has_no_effect:
    +
    const has no effect on a literal data member
    +
    +

    1977

    +
    initonly_requires_managed_class:
    +
    initonly data members can only be members of managed classes
    +
    +

    1978

    +
    initonly_const_has_no_effect:
    +
    const has no effect on an initonly data member
    +
    +

    1979

    +
    cli_get_accessor_missing:
    +
    entity-kind “entity” (declared at line xxxx) has no “get” +accessor
    +
    +

    1980

    +
    cli_set_accessor_missing:
    +
    entity-kind “entity” (declared at line xxxx) has no “set” +accessor
    +
    +

    1981

    +
    static_constructor_with_params:
    +
    a static constructor cannot have parameters
    +
    +

    1982

    +
    static_constructor_member_template:
    +
    a static constructor cannot be a member template
    +
    +

    1983

    +
    compound_lvalue_as_asm_operand:
    +
    a compound lvalue is not allowed as an asm output operand
    +
    +

    1984

    +
    property_requires_managed_class:
    +
    properties can only be members of managed classes
    +
    +

    1985

    +
    qualifier_not_allowed_on_managed_member_function:
    +
    a type qualifier is not allowed on a member function of a managed +class
    +
    +

    1986

    +
    pointer_to_ref_or_interface_class:
    +
    an ordinary pointer to a C++/CLI ref class or interface class is not +allowed
    +
    +

    1987

    +
    reference_to_ref_or_interface_class:
    +
    an ordinary reference to a C++/CLI ref class or interface class is +not allowed
    +
    +

    1988

    +
    override_name_must_be_a_base_class_member_function:
    +
    override specifier does not name a base class member function
    +
    +

    1989

    +
    override_name_nonvirtual:
    +
    override specifier designates a nonvirtual member entity-kind +“entity” (declared at line xxxx)
    +
    +

    1990

    +
    multiple_overrides:
    +
    member function overrides entity-kind “entity” (declared at line +xxxx) which is already overridden by entity-kind “entity”(declared at line xxxx)
    +
    +

    1991

    +
    multiple_visibility_specifiers:
    +
    at most one visibility specifier is allowed
    +
    +

    1992

    +
    invalid_delegate_type:
    +
    type “type” used for delegate definition is not a function type
    +
    +

    1993

    +
    delegate_requires_managed_class:
    +
    delegate member types can only be members of managed classes
    +
    +

    1994

    +
    tracking_reference_to_delegate:
    +
    a tracking reference to a delegate type is not allowed
    +
    +

    1995

    +
    bad_use_of_delegate_type:
    +
    a delegate type is not allowed here
    +
    +

    1996

    +
    empty_pack_expansion:
    +
    this pack expansion produced an empty list of expressions, and an +expression is needed here
    +
    +

    1997

    +
    virtual_static_event:
    +
    an event cannot be both static and virtual
    +
    +

    1998

    +
    event_requires_managed_class:
    +
    events can only be members of managed classes
    +
    +

    1999

    +
    invalid_event_accessor_decl:
    +
    this declaration cannot appear in an event definition
    +
    +

    2000

    +
    invalid_event_type:
    +
    event type must be a handle-to-delegate type
    +
    +

    2001

    +
    event_add_already_declared:
    +
    an “add” accessor was already declared for this event at line xxxx
    +
    +

    2002

    +
    event_remove_already_declared:
    +
    a “remove” accessor was already declared for this event at line +xxxx
    +
    +

    2003

    +
    event_raise_already_declared:
    +
    a “raise” accessor was already declared for this event at line +xxxx
    +
    +

    2004

    +
    virtual_static_event_accessor:
    +
    an event accessor cannot be both static and virtual
    +
    +

    2005

    +
    bad_event_add_or_remove_return:
    +
    return type of “add” and “remove” accessors must be void
    +
    +

    2006

    +
    event_accessor_missing_value_parameter:
    +
    event accessor is missing its value parameter
    +
    +

    2007

    +
    extra_event_accessor_parameters:
    +
    accessor function has too many parameters
    +
    +

    2008

    +
    event_accessor_value_parameter_mismatch:
    +
    the type “type” of the parameter of the event accessor does not +match the event type (“type”)
    +
    +

    2009

    +
    event_raise_type_mismatch:
    +
    the type of the “raise” accessor does not match the event’s delegate +invocation type
    +
    +

    2010

    +
    missing_add_or_remove_accessor:
    +
    an event definition must include both “add” and “remove” accessors
    +
    +

    2011

    +
    static_conversion_function_must_have_one_parameter:
    +
    a static conversion function must accept exactly one argument
    +
    +

    2012

    +
    bad_parameter_type_for_static_member_operator:
    +
    static operator must have a parameter type T, T&, T%, or T^ with T = +“type”
    +
    +

    2013

    +
    sizeof_operand_not_parameter_pack:
    +
    the operand of sizeof… must be a parameter pack name
    +
    +

    2014

    +
    sizeof_pack_in_non_variadic_context:
    +
    the sizeof… operator can be used only in a variadic template
    +
    +

    2015

    +
    event_name_not_allowed:
    +
    event name cannot appear here
    +
    +

    2016

    +
    handle_to_standard_class_type:
    +
    a handle to a non-managed class is not allowed
    +
    +

    2017

    +
    handle_to_unscoped_enum_type:
    +
    a handle to an unscoped enum type is not allowed
    +
    +

    2018

    +
    property_attribute_in_managed_class:
    +
    “property” attribute not allowed in managed class
    +
    +

    2019

    +
    pure_virtual_definition:
    +
    a pure specifier (”= 0”) followed by a definition is nonstandard
    +
    +

    2020

    +
    managed_nullptr_not_allowed:
    +
    the managed nullptr type cannot be used here
    +
    +

    2021

    +
    addr_of_ref_class:
    +
    the “&” operator cannot be used to take the address of an object with +a ref class type
    +
    +

    2022

    +
    array_of_managed_class:
    +
    array of managed class is not allowed
    +
    +

    2023

    +
    static_storage_variable_with_handle_or_tracking_ref_type:
    +
    a variable with static storage duration cannot have a handle or +tracking reference type
    +
    +

    2024

    +
    lambda_captures_handle_or_tracking_ref:
    +
    a variable captured by a lambda cannot be a handle or tracking +reference
    +
    +

    2025

    +
    invalid_param_array_type:
    +
    a C++/CLI parameter array requires a handle to a one-dimensional +cli::array type
    +
    +

    2026

    +
    cannot_import_metadata:
    +
    could not import metadata from file “xxxx”
    +
    +

    2027

    +
    namespace_cli_cannot_be_extended:
    +
    the cli namespace cannot be extended
    +
    +

    2028

    +
    cli_array_invalid_element_type:
    +
    the element type of a cli::array must be a handle or value type
    +
    +

    2029

    +
    cli_array_invalid_number_of_dimensions:
    +
    invalid number of dimensions for cli::array type
    +
    +

    2030

    +
    invalid_type_pointed_to_for_interior_ptr_or_pin_ptr:
    +
    a cli::interior_ptr/cli::pin_ptr must point to a standard class, a +value class, an integer, a handle, or a standard pointer
    +
    +

    2031

    +
    type_cannot_be_class_member:
    +
    “type” cannot be a class member
    +
    +

    2032

    +
    pin_ptr_param_not_allowed:
    +
    a parameter of type cli::pin_ptr is not allowed
    +
    +

    2033

    +
    bad_finalizer_decl:
    +
    invalid finalizer declaration
    +
    +

    2034

    +
    too_many_params_for_finalizer:
    +
    a finalizer may not have parameters
    +
    +

    2035

    +
    function_qualifier_on_finalizer:
    +
    a type qualifier is not allowed on a finalizer
    +
    +

    2036

    +
    return_type_on_finalizer:
    +
    a return type may not be specified on a finalizer
    +
    +

    2037

    +
    no_finalizer_using_declaration:
    +
    a using-declaration may not name a finalizer
    +
    +

    2038

    +
    finalizer_name_must_be_qualified:
    +
    a finalizer name must be qualified
    +
    +

    2039

    +
    finalizer_qualifier_type_mismatch:
    +
    qualifier of finalizer name “type” does not match type “type”
    +
    +

    2040

    +
    var_used_as_finalizer:
    +
    entity-kind “entity” cannot be used to name a finalizer (a type +name is required)
    +
    +

    2041

    +
    invalid_finalizer_name:
    +
    invalid finalizer name for type “type”
    +
    +

    2042

    +
    ambiguous_finalizer:
    +
    finalizer reference is ambiguous – both entity-kind “entity” and +entity-kind “entity” could be used
    +
    +

    2043

    +
    finalizer_requires_reference_type:
    +
    a finalizer can only be a member of a ref class
    +
    +

    2045

    +
    finalizer_type_mismatch:
    +
    type used as finalizer name does not match type “type”
    +
    +

    2046

    +
    finalizer_does_not_exist:
    +
    a finalizer does not exist for this type
    +
    +

    2047

    +
    handle_of_non_managed:
    +
    the “%” operator can be used only on an object with a managed class +type
    +
    +

    2048

    +
    ptr_handle_or_ref_to_interior_ptr:
    +
    a pointer, handle, or reference to a cli::interior_ptr is not allowed
    +
    +

    2049

    +
    ptr_handle_or_ref_to_pin_ptr:
    +
    a pointer, handle, or reference to a cli::pin_ptr is not allowed
    +
    +

    2050

    +
    ptr_or_ref_to_cli_array:
    +
    a pointer or reference to a C++/CLI array is not allowed
    +
    +

    2051

    +
    bad_use_of_cli_array_type:
    +
    a C++/CLI array type is not allowed here
    +
    +

    2052

    +
    invalid_ref_class_base:
    +
    a C++/CLI ref class can only derive from another ref class or from +interface classes
    +
    +

    2053

    +
    invalid_value_class_base:
    +
    a C++/CLI value class can only derive from interface classes
    +
    +

    2054

    +
    invalid_interface_class_base:
    +
    a C++/CLI interface class can only derive from interface classes
    +
    +

    2055

    +
    ref_class_has_multiple_ref_bases:
    +
    a ref class can have at most one direct ref base class (“type” is +already such a base)
    +
    +

    2056

    +
    managed_base_for_standard_class:
    +
    a standard class cannot derive from a managed class
    +
    +

    2057

    +
    virtual_base_for_managed_class:
    +
    a managed class cannot have a virtual base
    +
    +

    2058

    +
    managed_class_type_cannot_have_private_or_protected_base:
    +
    a managed class cannot have a “private” or “protected” base
    +
    +

    2059

    +
    override_requires_virtual:
    +
    the “override” modifier requires a virtual function declaration with +an explicit “virtual” keyword
    +
    +

    2060

    +
    abstract_requires_virtual:
    +
    the “abstract” modifier requires a virtual function declaration with +an explicit “virtual” keyword
    +
    +

    2061

    +
    sealed_requires_virtual:
    +
    the “sealed” modifier requires a virtual function declaration with an +explicit “virtual” keyword
    +
    +

    2062

    +
    named_override_requires_virtual:
    +
    a named override specifier requires a virtual function declaration +with an explicit “virtual” keyword
    +
    +

    2063

    +
    pin_ptr_return_type_not_allowed:
    +
    a cli::pin_ptr return type is not allowed
    +
    +

    2064

    +
    cppcli_attribute_only:
    +
    attribute “xxxx” applies in C++/CLI mode only
    +
    +

    2065

    +
    normal_ref_bound_to_gc_lvalue:
    +
    a simple (non-tracking) reference cannot be bound to an entity on the +managed heap
    +
    +

    2067

    +
    cli_entity_not_loaded:
    +
    “xxxx“ not loaded from default assemblies
    +
    +

    2068

    +
    list_initializer_nonstandard_in_current_mode:
    +
    list initialization syntax is a C++11 feature
    +
    +

    2069

    +
    sizeof_ref_or_interface_class:
    +
    operand of sizeof may not be a ref class type or interface class type
    +
    +

    2070

    +
    cli_array_invalid_number_of_subscripts:
    +
    invalid number of subscripts for this cli::array type
    +
    +

    2071

    +
    ptr_to_member_of_managed_class:
    +
    a pointer-to-member is not valid for a managed class
    +
    +

    2072

    +
    private_virtual_member_function_not_sealed:
    +
    private virtual member function of managed class is not “sealed”
    +
    +

    2073

    +
    modifier_not_allowed_on_destructor:
    +
    modifier is not allowed on a destructor
    +
    +

    2074

    +
    modifier_not_allowed_on_finalizer:
    +
    modifier is not allowed on a finalizer
    +
    +

    2075

    +
    virtual_has_no_effect:
    +
    “virtual” has no effect on a destructor of a managed class
    +
    +

    2076

    +
    new_or_override_required:
    +
    “new” or “override” is required because this declaration matches +entity-kind “entity” (declared at line xxxx)
    +
    +

    2077

    +
    new_or_virtual_required:
    +
    “new” or “virtual” is required because this declaration matches +entity-kind “entity” (declared at line xxxx)
    +
    +

    2078

    +
    override_for_interface_member:
    +
    “new” or “override” are not valid here because the matching +entity-kind “entity” (declared at line xxxx) is a member of +an interface
    +
    +

    2079

    +
    new_requires_matching_base_member:
    +
    “new” modifier without a matching base ref class member
    +
    +

    2080

    +
    overriding_reduces_accessibility_in_managed_type:
    +
    entity-kind “entity” (declared at line xxxx) overridden with +reduced access
    +
    +

    2081

    +
    bad_tracking_ref_init:
    +
    a reference of type “type” cannot be initialized with a value of +type “type”
    +
    +

    2082

    +
    copy_constructor_in_value_class_type:
    +
    a copy constructor cannot be declared in a value class
    +
    +

    2083

    +
    default_constructor_in_value_class_type:
    +
    a default constructor cannot be declared in a value class
    +
    +

    2084

    +
    destructor_in_value_class_type:
    +
    a destructor cannot be declared in a value class
    +
    +

    2085

    +
    assignment_in_value_class_type:
    +
    an assignment operator cannot be declared in a value class
    +
    +

    2086

    +
    nonvalue_class_type_cannot_be_value_class_member:
    +
    non-value class “type” cannot be the type of a member of a value +class
    +
    +

    2087

    +
    cppcli_requires_newer_abi_version:
    +
    option “cppcli” requires a different compiler configuration
    +
    +

    2088

    +
    managed_member_exception_spec:
    +
    exception specifications are not allowed on member functions of +managed classes
    +
    +

    2089

    +
    managed_class_cannot_have_friend:
    +
    a managed class cannot declare a friend
    +
    +

    2092

    +
    local_class_in_managed_member_function:
    +
    a local class definition is not allowed in a member function of a +managed class
    +
    +

    2093

    +
    local_lambda_in_managed_member_function:
    +
    a local lambda is not allowed in a member function of a managed class
    +
    +

    2094

    +
    cli_interface_member_function_definition:
    +
    a member function of a C++/CLI interface class type cannot have a +definition
    +
    +

    2095

    +
    missing_get_and_set_accessors:
    +
    a property definition must include at least one accessor (“get” or +“set”)
    +
    +

    2096

    +
    subscript_mechanism_conflict:
    +
    default-indexed property conflicts with entity-kind “entity”(declared at line xxxx)
    +
    +

    2097

    +
    unusable_pack:
    +
    entity-kind “entity” cannot be used because it follows a +parameter pack and cannot be deduced from the parameters of +entity-kind “entity”
    +
    +

    2098

    +
    excess_pack_expansion:
    +
    this pack expansion produced more than one expression, and a single +expression is needed here
    +
    +

    2099

    +
    cli_enum_base_has_no_system_counterpart:
    +
    type must correspond to System::Boolean, System::Byte, System::SByte, +System::Int16, System::UInt16, System::Int32, System::UInt32, +System::Int64, or System::UInt64
    +
    +

    2100

    +
    bad_call_of_handle:
    +
    call of an object of a handle type without appropriate operator() or +conversion functions to pointer-to-function type
    +
    +

    2101

    +
    abstract_declarator_pack_is_nested:
    +
    an unnamed parameter pack declaration cannot be parenthesized
    +
    +

    2102

    +
    cl_variadic_templates_only_in_cplusplus:
    +
    variadic templates can be enabled only when compiling C++
    +
    +

    2103

    +
    conflicting_properties:
    +
    property definition conflicts with entity-kind “entity” (declared +at line xxxx)
    +
    +

    2106

    +
    generic_param_cannot_have_default:
    +
    a generic parameter cannot have a default
    +
    +

    2107

    +
    bad_param_kind_for_generic:
    +
    a generic can only have type parameters
    +
    +

    2108

    +
    for_each_missing_function:
    +
    to be used with “for each” statements, type “type” must provide +nonstatic member function “xxxx”
    +
    +

    2109

    +
    for_each_static_function:
    +
    “for each” cannot use member entity-kind “entity” because it is +static
    +
    +

    2110

    +
    for_each_no_matching_overload:
    +
    in this “for each” statement, no instance of “entity” is callable +with an empty argument list
    +
    +

    2111

    +
    for_each_invalid_return_type_for_move_next:
    +
    “for each” cannot use member function “MoveNext” because the return +type is invalid
    +
    +

    2112

    +
    for_each_incompatible_type:
    +
    a “for each” statement cannot operate on an expression of type +“type”
    +
    +

    2113

    +
    for_each_missing_field:
    +
    to be used with “for each” statements, type “type” must provide a +non-indexed property “xxxx”
    +
    +

    2115

    +
    for_each_getenumerator_return_type_invalid:
    +
    in this “for each” statement, “type” is not a valid enumerator +(returned by “GetEnumerator” of “type”)
    +
    +

    2116

    +
    exp_in:
    +
    expected “in”
    +
    +

    2117

    +
    no_suitable_synthesis_assignment_operator:
    +
    class “type” has no suitable assignment operator (after operator +synthesis)
    +
    +

    2118

    +
    not_a_generic_param:
    +
    “xxxx” is not a generic parameter
    +
    +

    2119

    +
    not_generic_param_of_curr_decl:
    +
    “xxxx” is not a generic parameter of the innermost generic +parameter list
    +
    +

    2120

    +
    invalid_constraint:
    +
    invalid generic constraint
    +
    +

    2121

    +
    invalid_event_use:
    +
    invalid use of event member (only subscription, unsubscription, and +invocation are allowed)
    +
    +

    2122

    +
    event_without_raise_invoked:
    +
    invoking an event with no “raise” accessor is invalid
    +
    +

    2123

    +
    bad_event_compound_assignment:
    +
    only “+=” and “-=” are valid for events
    +
    +

    2124

    +
    typeid_of_managed_type:
    +
    typeid of a managed type is not allowed
    +
    +

    2125

    +
    cli_typeid_of_managed_pointer:
    +
    typeid of a managed pointer type is not allowed
    +
    +

    2126

    +
    name_before_typeid_not_type:
    +
    name followed by “::typeid” must be a type name
    +
    +

    2127

    +
    reserved_dispose:
    +
    a member “xxxx” of this type is reserved within a managed class +– destructor intended?
    +
    +

    2128

    +
    reserved_finalize:
    +
    a member “xxxx” of this type is reserved within a managed class +– finalizer intended?
    +
    +

    2129

    +
    invalid_idisposable_dispose:
    +
    System::IDisposable::Dispose is missing or invalid
    +
    +

    2130

    +
    invalid_object_finalize:
    +
    System::Object::Finalize is missing or invalid
    +
    +

    2131

    +
    finalize_does_not_override_object_finalize:
    +
    entity-kind “entity” does not override System::Object::Finalize
    +
    +

    2132

    +
    bad_handle_dynamic_cast_operand:
    +
    the operand of a handle dynamic_cast must be a handle to a complete +class type
    +
    +

    2133

    +
    bad_tracking_ref_dynamic_cast_operand:
    +
    the operand of a tracking-reference dynamic_cast must be an lvalue of +a complete class type
    +
    +

    2134

    +
    bad_cli_dynamic_cast_type:
    +
    the type in a dynamic_cast to a handle or tracking reference type +must refer to a complete class
    +
    +

    2135

    +
    cast_interior_ptr_to_ptr:
    +
    an interior pointer cannot be cast to a native pointer
    +
    +

    2136

    +
    cppcli_explicit_conversion_only_in_ref_and_value_classes:
    +
    explicit conversion operators can only be declared in ref and value +class types
    +
    +

    2137

    +
    cppcli_explicit_conversion_is_virtual:
    +
    explicit conversion operator cannot be virtual
    +
    +

    2138

    +
    expr_not_arithmetic_or_unscoped_enum:
    +
    expression must have arithmetic or unscoped enum type
    +
    +

    2139

    +
    expr_not_arithmetic_or_unscoped_enum_or_pointer:
    +
    expression must have arithmetic, unscoped enum, or pointer type
    +
    +

    2140

    +
    expr_not_integral_or_unscoped_enum:
    +
    expression must have integral or unscoped enum type
    +
    +

    2141

    +
    expr_not_integral_or_unscoped_enum_or_fixed_point:
    +
    expression must have integral, unscoped enum, or fixed-point type
    +
    +

    2142

    +
    scoped_enum_operation_type_mismatch:
    +
    a built-in binary operator applied to a scoped enumeration requires +two operands of the same type
    +
    +

    2143

    +
    invalid_gcnew_type:
    +
    gcnew cannot allocate an entity of type “type”
    +
    +

    2144

    +
    gcnew_used_with_placement_syntax:
    +
    placement syntax cannot be used with gcnew
    +
    +

    2145

    +
    new_used_on_unsuitable_value_type:
    +
    new can only be used with simple value types
    +
    +

    2146

    +
    new_used_on_managed_class_type:
    +
    new cannot be used on a managed class (gcnew should be used instead)
    +
    +

    2147

    +
    new_used_on_handle_or_tracking_reference_type:
    +
    new cannot be used on a handle type
    +
    +

    2148

    +
    cli_array_must_have_new_or_array_init:
    +
    gcnew for a C++/CLI array must have a new initializer or an array +initializer
    +
    +

    2149

    +
    gcnew_bad_type_used_with_array_init:
    +
    an array initializer can only be used to initialize a C++/CLI array +type
    +
    +

    2150

    +
    gcnew_used_with_auto_syntax:
    +
    gcnew does not allow auto
    +
    +

    2151

    +
    too_many_array_bounds:
    +
    too many array bounds
    +
    +

    2152

    +
    too_few_array_bounds:
    +
    too few array bounds
    +
    +

    2153

    +
    too_few_generic_args:
    +
    too few arguments for entity-kind “entity”
    +
    +

    2154

    +
    too_many_generic_args:
    +
    too many arguments for entity-kind “entity”
    +
    +

    2156

    +
    no_matching_arity:
    +
    no declaration of entity-kind “entity” accepts the number of +generic arguments supplied
    +
    +

    2157

    +
    bad_function_for_delegate:
    +
    invalid delegate initializer – must be a function
    +
    +

    2158

    +
    ambiguous_function_for_delegate:
    +
    invalid delegate initializer – more than one function matches the +delegate type
    +
    +

    2159

    +
    mismatched_function_for_delegate:
    +
    invalid delegate initializer – function does not match the delegate +type
    +
    +

    2160

    +
    missing_delegate_object:
    +
    invalid delegate initializer – an object is needed in addition to a +function
    +
    +

    2161

    +
    nonmanaged_function_for_delegate:
    +
    invalid delegate initializer – function is not a member of a managed +class
    +
    +

    2162

    +
    superfluous_delegate_object:
    +
    invalid delegate initializer – object is not needed for the +specified function
    +
    +

    2163

    +
    incompatible_delegate_object:
    +
    invalid delegate initializer – object has type “type” but type +“type” is expected
    +
    +

    2164

    +
    address_of_managed_member_function:
    +
    taking the address of a member function of a managed class is not +allowed
    +
    +

    2165

    +
    bad_delegate_init_list:
    +
    invalid delegate initializer – expected either +“(<function-address>)” or “(<object-handle>, <member-address>)”
    +
    +

    2166

    +
    interface_not_implemented:
    +
    class fails to implement interface member entity-kind “entity”(declared at line xxxx)
    +
    +

    2167

    +
    gcnew_of_native_array:
    +
    gcnew cannot be used to allocate a native array
    +
    +

    2168

    +
    cli_interface_cannot_have_assignment:
    +
    a C++/CLI interface class cannot declare an assignment operator
    +
    +

    2169

    +
    sealed_cli_interface:
    +
    a C++/CLI interface class cannot be sealed
    +
    +

    2171

    +
    destructor_or_finalizer_with_named_override:
    +
    a destructor or finalizer declaration cannot include a named override +specifier
    +
    +

    2172

    +
    override_name_is_destructor_or_finalizer:
    +
    an override specifier cannot designate a destructor or finalizer
    +
    +

    2173

    +
    named_override_requires_managed_type:
    +
    a named override specifier is allowed only in a managed class
    +
    +

    2174

    +
    named_override_type_mismatch:
    +
    no member designated by the named override specifier matches the type +of this member
    +
    +

    2175

    +
    static_constructor_with_named_override:
    +
    a static constructor declaration cannot include a named override +specifier
    +
    +

    2176

    +
    unnamed_scoped_enum:
    +
    a scoped enum type must have a name
    +
    +

    2177

    +
    branch_into_finally:
    +
    transfer of control into a finally block is not allowed
    +
    +

    2178

    +
    return_from_finally:
    +
    return statement inside a finally block is not allowed
    +
    +

    2179

    +
    missing_finally:
    +
    try block requires at least one handler or finally clause
    +
    +

    2180

    +
    managed_object_not_thrown_by_handle:
    +
    a managed object must be thrown by handle
    +
    +

    2181

    +
    managed_object_not_caught_by_handle:
    +
    a managed object must be caught by handle
    +
    +

    2182

    +
    break_cannot_be_in_finally_block:
    +
    a break statement cannot be used in a finally block
    +
    +

    2183

    +
    continue_cannot_be_in_finally_block:
    +
    a continue statement cannot be used in a finally block
    +
    +

    2184

    +
    no_overloaded_subscript_with_offsetof:
    +
    builtin offsetof cannot be used when subscripting is overloaded
    +
    +

    2185

    +
    duplicate_constraint:
    +
    duplicate constraint
    +
    +

    2186

    +
    multiple_class_constraints:
    +
    more than one class constraint: “type” and “type”
    +
    +

    2187

    +
    multiple_constraint_clauses:
    +
    more than one constraint clause for entity-kind “entity”
    +
    +

    2188

    +
    initonly_static_data_member_not_initialized:
    +
    initonly static data members must have an initializer or be +initialized in a static constructor
    +
    +

    2189

    +
    gnu_attr_on_template_redecl:
    +
    GNU attributes on a template redeclaration have no effect
    +
    +

    2190

    +
    gnu_attr_on_template_redecl_but_original_kept:
    +
    GNU attributes on a template redeclaration have no effect (the +attributes of the original declaration at line xxxx apply instead)
    +
    +

    2191

    +
    cli_param_array_must_be_last_parameter:
    +
    a C++/CLI parameter array must be the last parameter
    +
    +

    2192

    +
    default_arg_used_in_param_array_function:
    +
    a function with a C++/CLI parameter array cannot have default +arguments
    +
    +

    2193

    +
    ellipsis_after_param_array:
    +
    a C++/CLI parameter array cannot be followed by an ellipsis parameter
    +
    +

    2194

    +
    parameter_array_on_operator_function:
    +
    a C++/CLI parameter array is not allowed in an operator function +parameter list
    +
    +

    2195

    +
    microsoft_inline_not_allowed_here:
    +
    __inline and __forceinline are not allowed here
    +
    +

    2196

    +
    data_member_with_interface_type:
    +
    a data member cannot have a C++/CLI interface class type
    +
    +

    2197

    +
    variable_with_interface_type:
    +
    a variable cannot have a C++/CLI interface class type
    +
    +

    2198

    +
    parameter_with_interface_type:
    +
    a parameter cannot have a C++/CLI interface class type
    +
    +

    2199

    +
    return_type_is_interface:
    +
    a function return type cannot be a C++/CLI interface class type
    +
    +

    2200

    +
    array_of_generic_param:
    +
    an array of generic parameter type is not allowed
    +
    +

    2201

    +
    ptr_handle_or_ref_to_generic_param:
    +
    a pointer, handle, or reference to a generic parameter type is not +allowed
    +
    +

    2202

    +
    ref_class_initonly_field:
    +
    an initonly field cannot have a ref class type
    +
    +

    2203

    +
    ref_bound_to_initonly_field:
    +
    a reference cannot be bound to an initonly field
    +
    +

    2204

    +
    address_of_initonly_field:
    +
    taking the address of an initonly field is not allowed
    +
    +

    2205

    +
    modification_of_initonly_field:
    +
    an initonly field can only be modified by the instance constructor of +its containing class
    +
    +

    2206

    +
    modification_of_static_initonly_field:
    +
    a static initonly field can only be modified by the static +constructor of its containing class
    +
    +

    2207

    +
    member_function_call_on_initonly_field:
    +
    member function will be invoked on a copy of the initonly field
    +
    +

    2208

    +
    expr_not_pointer_nor_handle:
    +
    expression must have pointer or handle type but it has type “type”
    +
    +

    2209

    +
    move_ctor_or_assign_copy_of_lvalue:
    +
    a move constructor or move assignment operator is used to copy an +lvalue here, which may destroy the source object
    +
    +

    2210

    +
    generic_selection_with_points_to:
    +
    member selection on a C++/CLI generic entity must use the “->” +syntax, not “.”
    +
    +

    2211

    +
    invalid_specific_ref_class_base:
    +
    a ref class type cannot derive from “type”
    +
    +

    2212

    +
    generic_class_must_be_managed:
    +
    a generic class must be managed (i.e., a ref class, a value class, or +an interface class)
    +
    +

    2213

    +
    sealed_constraint:
    +
    a sealed class cannot be used as a constraint
    +
    +

    2214

    +
    dynamic_cast_to_value_generic:
    +
    the type in a dynamic_cast cannot be a generic type that might be a +value type
    +
    +

    2215

    +
    UCN_names_invalid_code_point:
    +
    a universal character name must designate a valid code point
    +
    +

    2216

    +
    override_with_constraint_mismatch:
    +
    generic constraints do not match those of entity-kind “entity”(declared at line xxxx)
    +
    +

    2217

    +
    bad_argument_for_underlying_type:
    +
    __underlying_type only applies to enum types
    +
    +

    2218

    +
    too_many_cast_operands:
    +
    expected only one operand expression for this cast
    +
    +

    2219

    +
    bad_unicode_char_in_string:
    +
    Unicode character with hex value xxxx not representable in the +system default code page
    +
    +

    2220

    +
    conv_of_pm_to_func_ptr:
    +
    nonstandard conversion of bound pointer-to-member to a function +pointer
    +
    +

    2221

    +
    deprecated_access_specifier:
    +
    access specifier xxxx is deprecated – use xxxx instead
    +
    +

    2222

    +
    static_accessor_in_nonstatic_property_or_event:
    +
    a static accessor function is not permitted in a nonstatic property +or event definition
    +
    +

    2223

    +
    both_ref_and_value_constraints:
    +
    “type” has both a value class and ref class constraint
    +
    +

    2224

    +
    circular_constraints:
    +
    “type” and “type” involve circular naked type constraints
    +
    +

    2225

    +
    invalid_type_constraint:
    +
    “type” is not a valid type constraint
    +
    +

    2226

    +
    pch_file_incomplete:
    +
    precompiled header file “xxxx” not used (because it is incomplete)
    +
    +

    2227

    +
    invalid_generic_arg:
    +
    “type” is not a valid generic argument
    +
    +

    2228

    +
    bad_assembly_info_attribute:
    +
    assembly_info attribute applied to an invalid type
    +
    +

    2229

    +
    ref_class_not_satisfied:
    +
    “type” does not satisfy the ref class constraint of generic +parameter “type”
    +
    +

    2230

    +
    value_class_not_satisfied:
    +
    “type” does not satisfy the value class constraint of generic +parameter “type”
    +
    +

    2231

    +
    gcnew_and_abstract:
    +
    “type” does not satisfy the gcnew constraint of generic parameter +“type” because it is abstract
    +
    +

    2232

    +
    gcnew_and_no_ctor:
    +
    “type” does not satisfy the gcnew constraint of generic parameter +“type” because it does not have a public default constructor
    +
    +

    2233

    +
    gcnew_and_no_gcnew:
    +
    generic parameter “type” does not satisfy the gcnew constraint of +generic parameter “type” because it does not have the gcnew +constraint
    +
    +

    2234

    +
    type_not_satisfied:
    +
    “type” does not satisfy the “type” type constraint of generic +parameter “type”
    +
    +

    2235

    +
    constraint_mismatch:
    +
    constraint on generic parameter “type” differs from previous +declaration (at line xxxx)
    +
    +

    2236

    +
    standard_array_member_in_managed_class:
    +
    a member of a managed class cannot be a standard array
    +
    +

    2237

    +
    handle_member_in_standard_class:
    +
    a member of a non-managed class cannot be a handle
    +
    +

    2238

    +
    tracking_reference_member_in_standard_class:
    +
    a member of a non-managed class cannot be a tracking reference
    +
    +

    2239

    +
    reinterpret_cast_of_handle:
    +
    unsafe reinterpret_cast of handle
    +
    +

    2240

    +
    generic_type_in_template_arg:
    +
    a template argument may not reference a generic type parameter
    +
    +

    2241

    +
    comma_operator_in_cli_subscript:
    +
    an expression list is not allowed in this subscript operation (use +parentheses around a top-level comma operator)
    +
    +

    2242

    +
    expr_not_pointer_or_array_handle:
    +
    expression must have pointer-to-object or handle-to-C++/CLI-array +type but it has type “type”
    +
    +

    2243

    +
    unrecognized_ms_attr:
    +
    unrecognized attribute
    +
    +

    2244

    +
    standard_class_member_in_managed_class:
    +
    a member of a managed class cannot be of a non-managed class type
    +
    +

    2245

    +
    ref_or_interface_class_member_in_standard_class:
    +
    a member of a non-managed class cannot have a ref class type or +interface class type
    +
    +

    2247

    +
    template_delegate:
    +
    a delegate may not be declared as a template
    +
    +

    2248

    +
    invalid_generic_specialization:
    +
    a generic cannot be explicitly specialized
    +
    +

    2249

    +
    generic_in_template:
    +
    a generic cannot be declared in a class template
    +
    +

    2250

    +
    template_in_generic:
    +
    a template cannot be declared in a generic class
    +
    +

    2251

    +
    static_literal_field:
    +
    a literal field cannot be declared “static”
    +
    +

    2252

    +
    nonstandard_long_float:
    +
    “long float” is a nonstandard extension – use “double” instead
    +
    +

    2253

    +
    standard_class_nested_in_managed_class:
    +
    a standard class cannot be nested in a managed class
    +
    +

    2254

    +
    clrcall_requires_cppcli:
    +
    __clrcall is valid only in C++/CLI mode
    +
    +

    2255

    +
    vararg_clrcall:
    +
    __clrcall not allowed on function with ellipsis parameter
    +
    +

    2256

    +
    bad_use_of_function_modifier:
    +
    “xxxx” is not allowed here
    +
    +

    2257

    +
    override_with_trivial_property_or_event:
    +
    a trivial property or event cannot be used to override entity-kind +“entity” (declared at line xxxx)
    +
    +

    2258

    +
    exp_id_in_for_each_decl:
    +
    expected an iterator variable name
    +
    +

    2259

    +
    missing_notequal_on_for_each_type:
    +
    the iterator type in this “for each” statement is “type”, which +is not a pointer type or an iterator-like class type
    +
    +

    2260

    +
    missing_incr_on_for_each_type:
    +
    the iterator type in this “for each” statement is “type”, which +is not a pointer type or an iterator-like class type
    +
    +

    2261

    +
    missing_indirect_on_for_each_type:
    +
    the iterator type in this “for each” statement is “type”, which +is not a pointer type or an iterator-like class type
    +
    +

    2262

    +
    no_packing_of_non_POD_field:
    +
    packing attribute on the parent type is ignored for this field of +class type “type” that is not standard-layout
    +
    +

    2263

    +
    nonpublic_implicit_interface_match:
    +
    entity-kind “entity” (declared at line xxxx) not implemented +because this declaration is not public and has no named override +specifier
    +
    +

    2264

    +
    missing_gnu_inline_attr_on_redeclaration:
    +
    this declaration is missing the gnu_inline attribute specified in the +previous declaration at line xxxx
    +
    +

    2265

    +
    managed_member_function_cannot_have_ellipsis_parameter:
    +
    a member function of a managed class cannot have an ellipsis parameter
    +
    +

    2266

    +
    invalid_prev_decl_iterator:
    +
    previously-declared entity-kind “entity” invalid as iterator of +“for each” statement
    +
    +

    2267

    +
    generic_parameter_requires_clrcall:
    +
    calling convention ignored because the function type involves a +generic parameter; __clrcall used instead
    +
    +

    2268

    +
    generic_parameter_does_not_permit_varargs:
    +
    a function type involving a generic parameter cannot have an ellipsis +parameter
    +
    +

    2269

    +
    virtual_required_for_base_override:
    +
    “virtual” is required to override the matching entity-kind +“entity” (declared at line xxxx)
    +
    +

    2270

    +
    virtual_required_for_interface_implementation:
    +
    “virtual” is required to implement the matching entity-kind +“entity” (declared at line xxxx)
    +
    +

    2271

    +
    initonly_volatile_not_allowed:
    +
    an initonly data member cannot be volatile
    +
    +

    2272

    +
    member_name_reserved_by_cli_operator:
    +
    a member “xxxx” of this type is reserved within a managed class +– C++/CLI operators must be declared using the keyword “operator”
    +
    +

    2273

    +
    tracking_ref_to_constant:
    +
    a tracking reference to non-const cannot be bound to a constant
    +
    +

    2274

    +
    attributes_with_no_decl:
    +
    attributes ignored here because they do not apply to a declared entity
    +
    +

    2275

    +
    tracking_reference_to_system_string:
    +
    a tracking reference to System::String is not allowed
    +
    +

    2276

    +
    use_of_generic_class_with_pending_constraint:
    +
    invalid use of a generic class “type” with pending constraints +(probably caused by an invalid metadata file)
    +
    +

    2277

    +
    invalid_entity_for_pending_constraint:
    +
    a pending constraint clause is only allowed for generic class +declarations (but not generic class definitions)
    +
    +

    2278

    +
    invalid_empty_initializer_list:
    +
    empty initializer list not allowed here
    +
    +

    2279

    +
    template_in_managed_class:
    +
    a template cannot be declared in a managed class
    +
    +

    2280

    +
    bad_generic_declaration_scope:
    +
    a generic declaration is not allowed here
    +
    +

    2281

    +
    interface_cannot_have_member_generics:
    +
    interface types cannot have member generics
    +
    +

    2282

    +
    character_not_latin_1:
    +
    Unicode character not Latin-1, truncated to low-order byte
    +
    +

    2283

    +
    range_based_for_missing_function:
    +
    to be used with range-based “for” statements, type “type” must +provide function “xxxx”
    +
    +

    2284

    +
    missing_notequal_on_range_based_for_type:
    +
    the iterator type in this range-based “for” statement is “type”, +which is not a pointer type or an iterator-like class type
    +
    +

    2285

    +
    missing_incr_on_range_based_for_type:
    +
    the iterator type in this range-based “for” statement is “type”, +which is not a pointer type or an iterator-like class type
    +
    +

    2286

    +
    missing_indirect_on_range_based_for_type:
    +
    the iterator type in this range-based “for” statement is “type”, +which is not a pointer type or an iterator-like class type
    +
    +

    2287

    +
    range_based_for_incomplete_array_type:
    +
    a range-based “for” statement cannot operate on an array of unknown +size or incomplete type “type”
    +
    +

    2288

    +
    begin_end_type_mismatch_in_range_based_for:
    +
    return types for “begin” and “end” functions used in a range-based +“for” statement must be the same (“begin” return type is “type”, +“end” return type is “type”)
    +
    +

    2289

    +
    inaccessible_elided_dtor:
    +
    entity-kind “entity” (declared at line xxxx), required to +destroy temporary that was eliminated, is inaccessible
    +
    +

    2290

    +
    range_based_for_no_matching_overload:
    +
    in this range-based “for” statement, no instance of “entity”matches the argument list
    +
    +

    2291

    +
    range_based_for_undefined_identifier:
    +
    this range-based “for” statement requires a suitable “xxxx”function and none was found
    +
    +

    2292

    +
    for_each_undefined_identifier:
    +
    this “for each” statement requires a suitable “xxxx” function and +none was found
    +
    +

    2293

    +
    class_metadata_not_representable:
    +
    “type” has a metadata representation not representable using +C++/CLI
    +
    +

    2294

    +
    exp_ellipsis:
    +
    expected “…”
    +
    +

    2295

    +
    implements_requires_interface:
    +
    “type” in __implements list is not an interface
    +
    +

    2296

    +
    implements_must_precede_virtual_functions:
    +
    an __implements list must precede virtual function declarations
    +
    +

    2297

    +
    missing_implements_list:
    +
    “type” specified “__implements …” in its list of bases, but is +missing a matching __implements list
    +
    +

    2298

    +
    unused_dereference_of_ref_class:
    +
    the result of dereferencing a handle to a ref or interface class type +must be used
    +
    +

    2300

    +
    exp_rparen_and_pragma_ignored:
    +
    expected a “)”; pragma ignored
    +
    +

    2301

    +
    using_or_access_declaration_in_managed_class:
    +
    a using-declaration or access declaration cannot appear in a managed +class
    +
    +

    2302

    +
    skipped_inaccessible_function:
    +
    Note: entity-kind “entity” (declared at line xxxx) could have +been called but was not considered because it is inaccessible
    +
    +

    2303

    +
    cli_abstract_member_function_definition:
    +
    an abstract member function of a C++/CLI managed class cannot have a +definition
    +
    +

    2304

    +
    nonstatic_addressof_operator_in_managed_class:
    +
    declaring this unary “operator*” can change the meaning of +dereferencing a handle (use static member operators to explicitly +indicate applicable types)
    +
    +

    2319

    +
    interface_nonstatic_data_member:
    +
    an interface class cannot contain a nonstatic data member
    +
    +

    2320

    +
    pragma_gcc_system_header_in_primary_file:
    +
    #pragma GCC system_header cannot be used in the primary source file
    +
    +

    2321

    +
    too_large_to_inline:
    +
    entity-kind “entity” is too large to be inlined
    +
    +

    2323

    +
    cl_gen_move_operations_option_only_in_cplusplus:
    +
    option to control move operations can be used only when compiling C++
    +
    +

    2324

    +
    cl_gen_move_operations_and_rvalue_ctor_is_copy_ctor:
    +
    move operations cannot be generated when rvalue constructors are copy +constructors
    +
    +

    2325

    +
    cl_move_operations_require_rvalue_references:
    +
    option to control move operations cannot be used when rvalue +references are disabled
    +
    +

    2326

    +
    final_managed_class:
    +
    “final” cannot be used for managed classes (use “sealed” instead)
    +
    +

    2327

    +
    cast_to_cli_interface_class:
    +
    a cast to CLI interface class “type” is not allowed – cast to +handle intended?
    +
    +

    2328

    +
    new_of_cli_interface_class:
    +
    cannot create an object of a CLI interface class
    +
    +

    2329

    +
    enum_type_replacement:
    +
    this declaration hides the nonstandard declaration of entity-kind +“entity” (declared at line xxxx) because the underlying types +are incompatible
    +
    +

    2330

    +
    known_comparison_with_null:
    +
    pointer comparison result is constant, because operand can never be +null
    +
    +

    2331

    +
    value_init_of_incomplete:
    +
    an object of the incomplete type “type” cannot be +value-initialized
    +
    +

    2332

    +
    value_init_of_reference:
    +
    a reference cannot be value-initialized
    +
    +

    2333

    +
    exp_lparen_or_brace:
    +
    expected a “(” or a “{”
    +
    +

    2334

    +
    explicit_ctor_in_copy_list_init:
    +
    copy-list-initialization cannot use a constructor marked “explicit”
    +
    +

    2335

    +
    ptr_to_member_of_type_void:
    +
    pointer to member of type void is not allowed
    +
    +

    2336

    +
    ptr_to_member_of_reference_type:
    +
    pointer to member of reference type is not allowed
    +
    +

    2337

    +
    ptr_to_member_of_handle_type:
    +
    pointer to member of handle type is not allowed
    +
    +

    2338

    +
    braced_init_list_not_allowed:
    +
    a brace-enclosed list is not allowed here
    +
    +

    2339

    +
    arrow_star_operator_in_managed_class:
    +
    an operator->* member is not allowed in a managed class
    +
    +

    2340

    +
    bad_assembly_index:
    +
    assembly metadata refers to non-existent assembly
    +
    +

    2341

    +
    attribute_conflict:
    +
    attribute “xxxx” conflicts with earlier attribute “xxxx”
    +
    +

    2342

    +
    incompatible_enum_base_types:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared with a different base type
    +
    +

    2343

    +
    invalid_scoped_enum_elaboration:
    +
    “enum class” and “enum struct” cannot be used here (use plain “enum” +instead)
    +
    +

    2344

    +
    extra_braces_on_simple_init:
    +
    only one level of braces is allowed on an initializer for an object +of type “type”
    +
    +

    2345

    +
    not_an_enum_type_name:
    +
    entity-kind “entity” (declared at line xxxx) cannot be used +as an enum type name
    +
    +

    2347

    +
    auto_new_with_braced_init:
    +
    a braced-initializer cannot be used with “new auto”
    +
    +

    2348

    +
    missing_initializer_list_ctor:
    +
    the definition of std::initializer_list does not contain the expected +constructor
    +
    +

    2349

    +
    variable_hides_entity:
    +
    declaration hides entity-kind “entity” (declared at line xxxx)
    +
    +

    2350

    +
    invalid_std_initializer_list_parameter_list:
    +
    invalid template parameter list for std::initializer_list (it should +be one ordinary type parameter with no default)
    +
    +

    2351

    +
    braced_list_passed_to_ellipsis:
    +
    a brace-enclosed list cannot be passed for an ellipsis parameter
    +
    +

    2352

    +
    initializer_list_not_included:
    +
    an #include <initializer_list> is needed prior to a use of +std::initializer_list, including an implicit use
    +
    +

    2353

    +
    inline_on_alias:
    +
    the “inline” keyword cannot be used on a namespace alias declaration
    +
    +

    2354

    +
    prev_ns_not_inline:
    +
    the previous declaration of entity-kind “entity” was not declared +inline
    +
    +

    2355

    +
    prev_ns_inline:
    +
    entity-kind “entity” was previously declared inline
    +
    +

    2356

    +
    first_arg_must_be_integer_constant:
    +
    the first argument must be an integer constant
    +
    +

    2357

    +
    designator_requires_aggregate_type:
    +
    a designator cannot be used with a non-aggregate type “type”
    +
    +

    2358

    +
    indirect_anon_union_designator:
    +
    a designator for an anonymous union member can only appear within +braces corresponding to that anonymous union
    +
    +

    2359

    +
    cl_func_prototype_tags_option_only_in_C:
    +
    function prototype tags can only be enabled when compiling C
    +
    +

    2360

    +
    cannot_elide_braces:
    +
    braces cannot be omitted for this subobject initializer
    +
    +

    2361

    +
    narrowing_conversion:
    +
    invalid narrowing conversion from “type” to “type”
    +
    +

    2362

    +
    constant_narrowing_conversion:
    +
    invalid narrowing conversion from “type” to “type”: constant +value does not fit in destination type
    +
    +

    2363

    +
    cast_to_incomplete_array_type:
    +
    cast to incomplete array type “type” is not allowed
    +
    +

    2364

    +
    constant_narrowing_conversion_to_float:
    +
    invalid narrowing conversion from “type” to “type”: constant +value cannot be represented exactly in destination type
    +
    +

    2365

    +
    braced_init_in_paren_init:
    +
    a parenthesized initializer for a non-class entity must be an +expression, not a brace-enclosed list
    +
    +

    2366

    +
    braced_list_for_implicit_lambda_type:
    +
    a brace-enclosed list does not provide a return type for this lambda
    +
    +

    2367

    +
    invalid_explicit_exception_specification:
    +
    the declared exception specification is incompatible with the +generated one
    +
    +

    2368

    +
    scoped_enum_nonstandard_in_current_mode:
    +
    scoped enum types are a C++11 feature
    +
    +

    2369

    +
    value_init_of_function:
    +
    a function type cannot be value-initialized
    +
    +

    2370

    +
    list_init_of_incomplete:
    +
    list-initialization of an object type “type” is not allowed +because the type is incomplete
    +
    +

    2371

    +
    std_initializer_list_has_dtor:
    +
    std::initializer_list has a destructor, and is not supposed to – +library is misconfigured
    +
    +

    2372

    +
    explicit_enum_base_nonstandard_in_current_mode:
    +
    explicit enum base types are a C++11 feature
    +
    +

    2373

    +
    unconvertible_con_expr:
    +
    this constant expression has type “type” instead of the required +“type” type
    +
    +

    2374

    +
    new_of_initializer_list:
    +
    a “new” of an std::initializer_list object is unlikely to work as +expected because the underlying array will be destroyed at the end of +the full expression
    +
    +

    2377

    +
    defined_always_false:
    +
    “defined” is always false in a macro expansion in Microsoft mode
    +
    +

    2378

    +
    init_list_element_type_not_complete_object:
    +
    “type” cannot be the element type of an initializer list because +it is not a complete object type
    +
    +

    2379

    +
    invalid_default_arg:
    +
    mismatched delimiters in default argument expression
    +
    +

    2380

    +
    conv_of_unbound_pm_to_func_ptr:
    +
    nonstandard conversion of pointer-to-member to a function pointer
    +
    +

    2381

    +
    dynamic_exception_specifications_deprecated:
    +
    dynamic exception specifications are deprecated
    +
    +

    2382

    +
    bad_scope_for_partial_spec:
    +
    entity-kind “entity” cannot be partially specialized in the +current scope
    +
    +

    2383

    +
    previous_constexpr_decl_conflict:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared constexpr
    +
    +

    2384

    +
    previous_nonconstexpr_decl_conflict:
    +
    entity-kind “entity” (declared at line xxxx) was previously +not declared constexpr
    +
    +

    2385

    +
    constexpr_variable_decl_must_be_definition:
    +
    missing initializer for constexpr variable
    +
    +

    2386

    +
    invalid_constexpr:
    +
    “constexpr” is not valid here
    +
    +

    2387

    +
    invalid_constexpr_body:
    +
    a constexpr function must contain exactly one return statement
    +
    +

    2388

    +
    invalid_statement_in_constexpr_function:
    +
    statement may not appear in a constexpr function
    +
    +

    2389

    +
    invalid_statement_in_constexpr_constructor:
    +
    statement may not appear in a constexpr constructor
    +
    +

    2390

    +
    constexpr_virtual_combination:
    +
    a function cannot be both constexpr and virtual in this mode
    +
    +

    2391

    +
    nonliteral_return_type_in_constexpr_function:
    +
    a constexpr function cannot have a nonliteral return type “type”
    +
    +

    2392

    +
    nonliteral_param_type_in_constexpr_function:
    +
    a constexpr function cannot have a parameter of nonliteral type +“type”
    +
    +

    2393

    +
    unsequenced_use_of_variable:
    +
    unsequenced uses of entity-kind “entity” in expression may +produce undefined results
    +
    +

    2394

    +
    3rd_arg_of_assume_aligned_must_be_integral:
    +
    the optional third argument of a call to __builtin_assumed_aligned +must have integral type
    +
    +

    2395

    +
    constexpr_destructor:
    +
    a destructor cannot be constexpr
    +
    +

    2396

    +
    invalid_mmap_address:
    +
    address supplied for mmap must be aligned on a page boundary: xxxx
    +
    +

    2397

    +
    constexpr_constructor_with_function_try_block:
    +
    the body of a constexpr constructor cannot be a function try block
    +
    +

    2398

    +
    missing_initializer_on_fields_with_constexpr_ctor:
    +
    constexpr entity-kind “entity” provides no initializer for:
    +
    +

    2400

    +
    default_ctor_call_not_constant:
    +
    calling the default constructor for “type” does not produce a +constant value
    +
    +

    2401

    +
    default_ctor_not_constexpr:
    +
    the default constructor for “type” is not constexpr
    +
    +

    2402

    +
    constexpr_variable_must_have_literal_type:
    +
    a constexpr variable must have a literal type or a reference type
    +
    +

    2403

    +
    constexpr_ctor_with_virtual_base:
    +
    a constructor for a class with virtual bases cannot be constexpr
    +
    +

    2404

    +
    bad_cpp11_constant_function_call:
    +
    function call must have a constant value in a constant expression
    +
    +

    2405

    +
    constexpr_main:
    +
    function “main” may not be declared constexpr
    +
    +

    2407

    +
    tag_defined_in_constexpr_body:
    +
    a class or enum type definition cannot appear in a constexpr function +or constructor body
    +
    +

    2408

    +
    only_gnu_attributes_here:
    +
    only GNU-style attributes are permitted here
    +
    +

    2409

    +
    auto_used_two_ways:
    +
    nonstandard use of “auto” to both deduce the type from an initializer +and to announce a trailing return type
    +
    +

    2410

    +
    nonstd_qualified_void_param_list:
    +
    declaring a void parameter list with a qualified void type is +nonstandard
    +
    +

    2411

    +
    qualifier_ignored_on_local_declaration:
    +
    the qualifier on this local declaration is ignored
    +
    +

    2412

    +
    bad_conv_constant_expr_type:
    +
    this constant expression has type “type” instead of the required +xxxx type
    +
    +

    2413

    +
    bad_argument_for_bases:
    +
    an instantiation of __bases or __direct_bases requires a class type
    +
    +

    2414

    +
    bad_prototype_argument_for_bases:
    +
    the argument of __bases and __direct_bases must be a type template +parameter
    +
    +

    2415

    +
    bases_not_in_template:
    +
    xxxx can only be used in template contexts
    +
    +

    2416

    +
    constexpr_return_not_constant:
    +
    constexpr function return is non-constant
    +
    +

    2417

    +
    nonconstexpr_call_in_mem_initializer:
    +
    constexpr constructor calls non-constexpr entity-kind “entity”
    +
    +

    2418

    +
    nonconstant_field_initializer_in_mem_initializer:
    +
    constructor cannot be constexpr because the initializer of +entity-kind “entity” is not a constant expression
    +
    +

    2419

    +
    nonconstant_mem_init_for_constexpr_ctor:
    +
    non-constant initializer for constexpr constructor
    +
    +

    2420

    +
    generated_default_constructor_used_in_field_initializer:
    +
    the generated default constructor for “type” cannot be used in an +initializer for its own data member
    +
    +

    2421

    +
    recursive_initializer_instantiation:
    +
    instantiation of initializer of entity-kind “entity” depends on +its own value
    +
    +

    2422

    +
    defaulted_default_ctor_cannot_be_constexpr:
    +
    defaulted default constructor cannot be constexpr because the +corresponding implicitly declared default constructor would not be +constexpr
    +
    +

    2424

    +
    bad_binary_digit:
    +
    invalid binary number
    +
    +

    2425

    +
    multiple_union_field_initializers:
    +
    a union can have at most one field initializer – entity-kind +“entity” (declared at line xxxx) also has an initializer
    +
    +

    2427

    +
    union_constexpr_constructor_initializes_no_field:
    +
    constexpr constructor of a union must initialize one of its fields
    +
    +

    2428

    +
    constexpr_constructor_initializes_no_variant_field:
    +
    constexpr constructor fails to initialize an anonymous union (defined +at line xxxx)
    +
    +

    2429

    +
    constexpr_static_data_member_without_initializer:
    +
    a constexpr static data member declaration requires an in-class +initializer
    +
    +

    2430

    +
    cl_max_constexpr_option_only_in_cplusplus:
    +
    maximum constexpr depth/count options can be used only when compiling +C++
    +
    +

    2431

    +
    excessive_constexpr_complexity:
    +
    expression not folded to a constant due to excessive constexpr +function call complexity
    +
    +

    2432

    +
    cl_unrestricted_unions_option_only_in_cplusplus:
    +
    unrestricted union options can be used only when compiling C++
    +
    +

    2433

    +
    constexpr_ctor_does_not_initialize_base:
    +
    constexpr constructor must initialize direct base class “type”
    +
    +

    2434

    +
    field_initializer_list:
    +
    creation of an std::initializer_list object in a field initializer is +unlikely to work as expected because the underlying array will be +destroyed at the end of the full expression
    +
    +

    2435

    +
    this_not_constant:
    +
    “this” cannot be used in a constant expression
    +
    +

    2437

    +
    constexpr_explicit_instantiation:
    +
    “constexpr” is not allowed on an explicit instantiation directive
    +
    +

    2438

    +
    generated_default_ctor_exception_spec_circularity:
    +
    cannot determine the exception specification of the default +constructor due to a circular dependency
    +
    +

    2439

    +
    anon_union_at_decl_position:
    +
    anonymous union defined at line xxxx
    +
    +

    2440

    +
    unbounded_constexpr_ctor_init_recursion:
    +
    this constructor uses the initializer of entity-kind “entity”(declared at line xxxx), which would result in unbounded recursion
    +
    +

    2442

    +
    block_extern_initializer_not_allowed:
    +
    an initializer is not allowed on a local declaration of an extern +variable
    +
    +

    2443

    +
    local_named_register_initializer_not_allowed:
    +
    an initializer is not allowed on a local declaration of a named +register variable
    +
    +

    2445

    +
    cl_unrestricted_unions_in_microsoft_mode:
    +
    unrestricted unions cannot be enabled in Microsoft mode
    +
    +

    2446

    +
    delegation_loop:
    +
    constructor delegates directly or indirectly to itself
    +
    +

    2447

    +
    delegation_init_and_mem_init:
    +
    a delegating constructor cannot have other mem-initializers
    +
    +

    2448

    +
    ref_qualifier_not_allowed:
    +
    a ref-qualifier is not allowed here
    +
    +

    2449

    +
    same_param_types_with_and_without_ref_qualifiers:
    +
    overloading two member functions with the same parameter types +requires that they both have ref-qualifiers or both lack +ref-qualifiers
    +
    +

    2450

    +
    bad_raw_string_delim_char:
    +
    invalid character in raw string delimiter
    +
    +

    2451

    +
    missing_raw_string_delim_lparen:
    +
    parenthesis terminating raw string delimiter not found within 16 +characters – raw string indicator ignored
    +
    +

    2452

    +
    missing_raw_string_delimiter:
    +
    ending delimiter for raw string not found
    +
    +

    2453

    +
    pack_not_last_arg:
    +
    a parameter pack must be the final template argument in a partial +specialization
    +
    +

    2454

    +
    pm_call_obj_not_lvalue:
    +
    a pointer-to-member function with type “type” can only be used +with an lvalue object
    +
    +

    2455

    +
    pm_call_obj_not_rvalue:
    +
    a pointer-to-member function with type “type” can only be used +with an rvalue object
    +
    +

    2456

    +
    defaulted_copy_ctor_cannot_have_const_parameter:
    +
    the parameter of this defaulted copy-constructor cannot be const +because a base or member copy constructor parameter is non-const
    +
    +

    2457

    +
    defaulted_assignment_cannot_have_const_parameter:
    +
    the parameter of this defaulted assignment operator cannot be const +because a base or member copy assignment parameter is non-const
    +
    +

    2458

    +
    empty_anonymous_union:
    +
    an anonymous union must contain at least one nonstatic data member
    +
    +

    2459

    +
    delegating_constructor_requires_newer_abi_version:
    +
    option “delegating_constructors” requires a different compiler +configuration
    +
    +

    2460

    +
    alignment_reduction_unconditionally_ignored:
    +
    a reduction in alignment is ignored
    +
    +

    2461

    +
    bad_rvalue_ref_const_cast_operand:
    +
    the operand of a const_cast to an rvalue reference type cannot be a +non-class prvalue
    +
    +

    2462

    +
    expr_not_a_glvalue:
    +
    expression must be an lvalue or xvalue
    +
    +

    2463

    +
    lossy_conversion:
    +
    conversion may change the value
    +
    +

    2464

    +
    deprecated_string_conv:
    +
    conversion from a string literal to “char *” is deprecated
    +
    +

    2465

    +
    deprecated_string_conv_gen:
    +
    conversion from a string literal to pointer-to-character (non-const) +is deprecated
    +
    +

    2466

    +
    override_and_final_is_cpp11:
    +
    “override” and “final” are C++11 features
    +
    +

    2467

    +
    rvalue_reference_in_exception_specification:
    +
    rvalue references are not allowed as exception specification types
    +
    +

    2468

    +
    attr_disallows_handler_param:
    +
    attribute “xxxx” does not apply to handler parameters
    +
    +

    2469

    +
    attr_requires_handler_param:
    +
    attribute “xxxx” requires a handler parameter
    +
    +

    2470

    +
    wrong_entity_for_alignas:
    +
    alignas does not apply here
    +
    +

    2471

    +
    std_alignof_with_expr_arg:
    +
    the standard “alignof” operator does not accept an expression +argument (use a type instead)
    +
    +

    2472

    +
    bad_qualifier_for_member_enum_decl:
    +
    invalid qualifier for “type” (a derived class is not allowed here)
    +
    +

    2473

    +
    always_inline_requires_inline:
    +
    the “always_inline” attribute is ignored on non-inline functions
    +
    +

    2474

    +
    inheriting_ctor_not_from_direct_base:
    +
    inheriting constructors must be inherited from a direct base class
    +
    +

    2476

    +
    exp_asm_label:
    +
    expected a label
    +
    +

    2477

    +
    missing_label_operand_number:
    +
    expected an operand number after “%”
    +
    +

    2478

    +
    label_operand_number_out_of_range:
    +
    operand number for “%” does not refer to a valid label argument
    +
    +

    2479

    +
    wide_string_invalid_in_asm:
    +
    a wide string is invalid in an “asm” statement
    +
    +

    2480

    +
    attribute_is_nonstandard:
    +
    attribute is nonstandard
    +
    +

    2481

    +
    decltype_is_not_base_class:
    +
    not a base class of class “type”
    +
    +

    2482

    +
    bad_user_defined_suffix:
    +
    non-identifier character in user-defined literal suffix
    +
    +

    2483

    +
    multichar_ud_lit:
    +
    a multicharacter literal cannot be part of a user-defined literal
    +
    +

    2484

    +
    ud_string_suffix_mismatch:
    +
    user-defined literal suffix does not match the earlier “xxxx”
    +
    +

    2485

    +
    invalid_literal_operator_id:
    +
    invalid literal operator name
    +
    +

    2486

    +
    literal_operator_not_found:
    +
    user-defined literal operator not found
    +
    +

    2487

    +
    ambig_literal_operator:
    +
    ambiguous literal operators and/or literal operator template:
    +
    +

    2488

    +
    udl_cannot_be_class_member:
    +
    a literal operator cannot be a member of a class
    +
    +

    2489

    +
    extern_c_literal_operator:
    +
    a literal operator cannot have extern “C” name linkage
    +
    +

    2490

    +
    no_parameter_for_literal_operator:
    +
    at least one parameter expected for a literal operator
    +
    +

    2491

    +
    too_many_parameters_for_literal_operator:
    +
    too many parameters for this literal operator
    +
    +

    2492

    +
    invalid_parameter_type_for_literal_operator:
    +
    invalid parameter type “type” for literal operator
    +
    +

    2493

    +
    invalid_integer_parameter_for_literal_operator:
    +
    invalid integer parameter type (“type”) for literal operator; +expected a character type or unsigned long long
    +
    +

    2494

    +
    invalid_float_parameter_for_literal_operator:
    +
    invalid floating-point parameter type (“type”) for literal +operator; expected long double
    +
    +

    2495

    +
    pointer_to_nonconst_for_literal_operator:
    +
    invalid first parameter type (“type”) for literal operator; +pointer to non-const type is not allowed
    +
    +

    2496

    +
    invalid_second_parameter_type_for_literal_operator:
    +
    invalid second parameter type (“type”) for literal operator; must +be size_t
    +
    +

    2497

    +
    invalid_pointer_parameter_for_literal_operator:
    +
    invalid pointer parameter type (“type”) for literal operator; +expected a pointer to a character type
    +
    +

    2498

    +
    ellipsis_parameter_for_literal_operator:
    +
    a literal operator cannot have an ellipsis parameter
    +
    +

    2499

    +
    invalid_parameter_for_literal_operator_template:
    +
    a literal operator template cannot have any parameters
    +
    +

    2500

    +
    invalid_template_parameter_for_literal_operator_template:
    +
    a literal operator template must have a template parameter list +equivalent to “<char …>”
    +
    +

    2501

    +
    thread_local_not_allowed:
    +
    thread-local storage class is not valid here
    +
    +

    2502

    +
    thread_local_follows_non_thread_local:
    +
    thread-local declaration follows non-thread-local declaration +(declared at line xxxx)
    +
    +

    2503

    +
    non_thread_local_follows_thread_local:
    +
    non-thread-local declaration follows thread-local declaration +(declared at line xxxx)
    +
    +

    2504

    +
    default_arg_for_literal_operator:
    +
    a literal operator cannot have default arguments
    +
    +

    2505

    +
    attribute_ignored_for_thread_local:
    +
    attribute is ignored for thread-local variables
    +
    +

    2506

    +
    lit_suffix_no_underscore:
    +
    a user-provided literal suffix must begin with “_”
    +
    +

    2507

    +
    rvalue_references_is_cpp11:
    +
    rvalue references are a C++11 feature
    +
    +

    2508

    +
    lambdas_is_cpp11:
    +
    lambda expressions are a C++11 feature
    +
    +

    2509

    +
    std_attributes_is_cpp11:
    +
    standard attribute syntax is a C++11 feature
    +
    +

    2510

    +
    delegating_constructor_is_cpp11:
    +
    delegating constructors are a C++11 feature
    +
    +

    2511

    +
    inheriting_constructor_is_cpp11:
    +
    inheriting constructors are a C++11 feature
    +
    +

    2512

    +
    field_initializers_is_cpp11:
    +
    field initializers are a C++11 feature
    +
    +

    2513

    +
    deleted_functions_is_cpp11:
    +
    deleted functions are a C++11 feature
    +
    +

    2514

    +
    defaulted_functions_is_cpp11:
    +
    defaulted functions are a C++11 feature
    +
    +

    2515

    +
    storage_class_not_allowed_in_specialization:
    +
    a storage class is not allowed in an explicit specialization
    +
    +

    2517

    +
    specialization_of_unscoped_enum:
    +
    an unscoped enumeration must be opaque in order to be specialized
    +
    +

    2518

    +
    nonmember_enum_template:
    +
    an enumeration template declaration must refer to a previously +declared member of a class template
    +
    +

    2519

    +
    operand_must_be_vector:
    +
    expected a vector operand
    +
    +

    2520

    +
    incompatible_shuffle_source_operands:
    +
    shuffle source operands have incompatible types “type” and +“type”
    +
    +

    2521

    +
    nonintegral_shuffle_mask:
    +
    shuffle mask (type “type”) is not a vector of integers
    +
    +

    2522

    +
    incompatible_shuffle_mask:
    +
    shuffle mask (type “type”) has a length different from the source +operand (type “type”)
    +
    +

    2523

    +
    bad_size_for_static_address_init:
    +
    static initialization with an address value requires a destination of +the same size as the address
    +
    +

    2524

    +
    feature_test_macro_req_id:
    +
    the argument to a feature-test macro must be a simple identifier
    +
    +

    2525

    +
    has_include_next_in_primary_source_file:
    +
    __has_include_next cannot be used in the primary source file
    +
    +

    2526

    +
    absolute_file_name_in_has_include_next:
    +
    absolute file name used in __has_include_next
    +
    +

    2527

    +
    attr_not_applied_to_function_type:
    +
    attribute “xxxx” must be applied to a function type
    +
    +

    2529

    +
    bad_c11_noreturn:
    +
    _Noreturn is not allowed here
    +
    +

    2530

    +
    operand_must_be_real_floating_value:
    +
    expected an operand of real floating-point type (not “type”)
    +
    +

    2531

    +
    incompatible_builtin_complex_types:
    +
    __builtin_complex requires operands of compatible types (unlike +“type” and “type”)
    +
    +

    2532

    +
    default_association_appears_more_than_once:
    +
    a default association already appeared in this _Generic selection
    +
    +

    2533

    +
    variably_modified_type_not_allowed_here:
    +
    a type involving a variable length array is not allowed here
    +
    +

    2534

    +
    duplicate_type_in_c11_generic:
    +
    duplicate association type (“type”) in _Generic selection
    +
    +

    2535

    +
    no_match_in_c11_generic:
    +
    no association matches the selector type “type”
    +
    +

    2536

    +
    incompatible_ifunc_resolver_type:
    +
    the type of entity-kind “entity” (“type”) is incompatible +with an ifunc resolver type
    +
    +

    2537

    +
    ifunc_cant_be_alias:
    +
    a function cannot have both ifunc and alias attributes
    +
    +

    2538

    +
    ifunc_cant_be_weak:
    +
    a function cannot have both ifunc and weak attributes
    +
    +

    2539

    +
    call_requires_string_literal:
    +
    call requires a string literal operand
    +
    +

    2540

    +
    duplicate_inheriting_constructor:
    +
    duplicate inheriting constructor declaration (previous at line +xxxx)
    +
    +

    2541

    +
    modified_decltype_auto_type:
    +
    “decltype(auto)” must be a placeholder for the complete type of the +variable (not for a component of that type)
    +
    +

    2542

    +
    decltype_auto_not_allowed_here:
    +
    decltype(auto) is not allowed here
    +
    +

    2543

    +
    decltype_auto_type_requires_initializer:
    +
    cannot deduce “decltype(auto)” (initializer required)
    +
    +

    2544

    +
    cannot_deduce_decltype_auto_type:
    +
    cannot deduce “decltype(auto)” type
    +
    +

    2545

    +
    thread_local_must_include_static_or_extern:
    +
    a block-scope thread-local declaration must include static or extern
    +
    +

    2546

    +
    deduced_return_type_conflict:
    +
    deduced return type “type” conflicts with previously deduced type +“type”
    +
    +

    2547

    +
    use_of_undefined_function_with_deduced_return_type:
    +
    cannot deduce the return type of entity-kind “entity” (declared +at line xxxx); it has not been defined
    +
    +

    2548

    +
    virtual_function_cannot_have_deduced_return_type:
    +
    a virtual function cannot have a deduced return type
    +
    +

    2549

    +
    keyword_dropped:
    +
    entity-kind “entity” will be treated as a context-sensitive +keyword from this point
    +
    +

    2550

    +
    global_ns_has_no_actual_member:
    +
    the global namespace has no actual member “xxxx”
    +
    +

    2551

    +
    different_enum_comparison:
    +
    comparison between two different enum types (“type” and +“type”)
    +
    +

    2552

    +
    unrecognized_target_attribute:
    +
    target attribute not recognized
    +
    +

    2553

    +
    gnu_mv_default_missing:
    +
    missing “default” target function
    +
    +

    2554

    +
    gnu_mv_only_one_arch:
    +
    only one arch= target may be specified
    +
    +

    2555

    +
    generic_class_cannot_be_custom_attribute:
    +
    a generic class cannot be a custom attribute
    +
    +

    2556

    +
    invalid_ms_attribute_target:
    +
    invalid attribute target “xxxx”
    +
    +

    2557

    +
    ambiguous_ms_attribute:
    +
    ambiguous attribute – both “type” and “type” could be used
    +
    +

    2558

    +
    cli_attribute_inaccessible_field:
    +
    a named attribute argument can only reference a public nonstatic +read/write field or scalar property
    +
    +

    2559

    +
    cli_attribute_invalid_field:
    +
    a named attribute argument can only reference a nonstatic field or +scalar property of an attribute parameter type
    +
    +

    2560

    +
    cli_attribute_invalid_argument:
    +
    invalid attribute argument – expression must be a constant of an +attribute parameter type
    +
    +

    2561

    +
    cli_typeid_of_generic_param_in_attribute:
    +
    an attribute argument cannot use generic type parameters
    +
    +

    2562

    +
    invalid_use_of_standalone_custom_ms_attr:
    +
    “type” may only be used as a standalone attribute
    +
    +

    2563

    +
    field_target_on_nontrivial_property_or_event:
    +
    the ‘field’ attribute target cannot be used on a non-trivial +property/event
    +
    +

    2564

    +
    invalid_attribute_target_for_standalone_ms_attr:
    +
    invalid attribute target for a standalone attribute
    +
    +

    2565

    +
    invalid_attribute_target_for_ms_attr:
    +
    invalid attribute target for this context
    +
    +

    2566

    +
    invalid_use_of_custom_ms_attr:
    +
    “type” attribute cannot be used here
    +
    +

    2567

    +
    cli_param_array_attribute_deprecated:
    +
    “type” is deprecated; use ‘…’ to specify a parameter array
    +
    +

    2568

    +
    namespace_default_cannot_be_extended:
    +
    the default namespace cannot be extended
    +
    +

    2569

    +
    cppcx_box_invalid_type:
    +
    the boxed type must be a value class or enum
    +
    +

    2570

    +
    tracking_reference_to_value_class:
    +
    tracking reference to value class is not allowed
    +
    +

    2571

    +
    handle_to_value_class:
    +
    handle to value class is not allowed
    +
    +

    2572

    +
    tracking_reference_to_enum:
    +
    tracking reference to enum is not allowed
    +
    +

    2573

    +
    handle_to_enum:
    +
    handle to enum is not allowed
    +
    +

    2574

    +
    cppcx_public_native_type:
    +
    a public native type is not allowed
    +
    +

    2575

    +
    public_nested_type_in_cppcx_type:
    +
    a public nested type is not allowed
    +
    +

    2576

    +
    cppcx_generic_type_not_allowed:
    +
    generic types are not permitted in C++/CX
    +
    +

    2577

    +
    cppcx_generic_method_not_allowed:
    +
    generic methods are not permitted in C++/CX
    +
    +

    2578

    +
    cppcx_generic_constraints_not_allowed:
    +
    generic constraints are not allowed
    +
    +

    2579

    +
    nonpublic_data_member_in_public_cppcx_value_type:
    +
    non-public data members are not allowed in public C++/CX value types
    +
    +

    2580

    +
    public_nondata_member_in_public_cppcx_value_type:
    +
    public non-data members are not allowed in public C++/CX value types
    +
    +

    2581

    +
    cppcx_public_value_class_constructor:
    +
    constructors are not allowed in public C++/CX value types
    +
    +

    2582

    +
    bad_cppcx_event_add_return:
    +
    the return type of the “add” accessor must be +Windows::Foundation::EventRegistrationToken
    +
    +

    2583

    +
    bad_cppcx_event_remove_return:
    +
    the return type of the “remove” accessor must be void
    +
    +

    2584

    +
    bad_cppcx_event_remove_parameter:
    +
    the parameter type of the “remove” accessor must be +Windows::Foundation::EventRegistrationToken
    +
    +

    2585

    +
    cppcx_handle_or_ref_to_generic_param:
    +
    a handle or reference to a generic parameter type is not allowed
    +
    +

    2586

    +
    public_data_member_in_public_non_value_type:
    +
    public data members are not allowed in non-value types
    +
    +

    2587

    +
    cl_cppcx_only_in_microsoft_cplusplus:
    +
    C++/CX can be enabled only in Microsoft C++ mode
    +
    +

    2588

    +
    cl_cppcx_and_cppcli:
    +
    C++/CLI and C++/CX modes cannot be combined
    +
    +

    2589

    +
    cppcx_not_enabled:
    +
    “xxxx” requires C++/CX mode
    +
    +

    2590

    +
    cl_microsoft_version_insufficient_for_cppcx:
    +
    C++/CX mode requires microsoft_version >= 1600
    +
    +

    2591

    +
    literal_fields_disallowed_in_cppcx_mode:
    +
    Literal fields are not allowed in C++/CX
    +
    +

    2592

    +
    normal_ref_bound_to_cppcx_lvalue:
    +
    a standard reference cannot be bound to a C++/CX type
    +
    +

    2593

    +
    cppcx_enum_base_has_no_platform_counterpart:
    +
    type must correspond to Platform::Boolean, default::uint8, +default::int8, default::int16, default::uint16, default::int32, +default::uint32, default::int64, or default::uint64
    +
    +

    2594

    +
    event_in_cppcx_value_type:
    +
    a C++/CX value type cannot have events
    +
    +

    2595

    +
    bad_cppcx_dynamic_cast_type:
    +
    a dynamic_cast to a handle type must refer to a complete class type
    +
    +

    2596

    +
    cppcx_array_only_one_dimension_allowed:
    +
    Platform::Array can only be one-dimensional
    +
    +

    2597

    +
    cppcx_tracking_reference_on_standard_class_type:
    +
    tracking reference to standard class type is not allowed
    +
    +

    2598

    +
    cppcx_value_type_deriving_from_interface:
    +
    a C++/CX value type cannot inherit from an interface
    +
    +

    2599

    +
    cppcx_value_type_contains_virtual_function:
    +
    a C++/CX value type cannot contain virtual functions
    +
    +

    2600

    +
    partial_class_incorrect_type_or_location:
    +
    “partial” can only be applied to “ref class” or “ref struct” at +global scope or namespace scope
    +
    +

    2601

    +
    cppcx_invalid_array_property_set_value_parameter:
    +
    the parameter of the “set” accessor must be of type “const +Platform::Array<T>^”
    +
    +

    2602

    +
    cppcx_public_global_type:
    +
    the definition of a public C++/CX type is not allowed at global scope
    +
    +

    2603

    +
    cppcx_public_indexed_property:
    +
    an indexed property with a public “get” or “set” accessor is not +allowed
    +
    +

    2604

    +
    cppcx_public_nested_delegate:
    +
    a public nested delegate type is not allowed
    +
    +

    2605

    +
    cppcx_bad_delegate_init_list:
    +
    invalid delegate initializer – expected either “(<function-address +or functor-object> [, Platform::CallbackContext])” or “(<object +handle>, <member-address> [, Platform::CallbackContext [, bool]])”
    +
    +

    2606

    +
    cppcx_invalid_delegate_object:
    +
    invalid delegate initializer – object must be a handle to a managed +class
    +
    +

    2607

    +
    cppcx_non_const_array_parameter:
    +
    C++/CX does not support ‘in/out’ arrays – use “const +Platform::Array<T>^” for ‘in’ and “Platform::WriteOnlyArray<T>^” or +“Platform::Array<T>^*” for ‘out’ on public APIs
    +
    +

    2608

    +
    missing_target_attribute:
    +
    missing “target” attribute for entity-kind “entity” (declared at +line xxxx)
    +
    +

    2609

    +
    no_matching_target_attribute:
    +
    no declared member function matches “target” attributes for +entity-kind “entity”
    +
    +

    2610

    +
    invalid_base_for_ms_attributes:
    +
    Microsoft attributes in this location are only permitted for +interface types
    +
    +

    2611

    +
    resolver_routine_required:
    +
    GNU function multiversion resolver routine required
    +
    +

    2612

    +
    enum_in_managed_class_missing_definition:
    +
    an enum type declared in a managed class must include a definition
    +
    +

    2613

    +
    decltype_qualified_declared_name:
    +
    a decltype-qualified name is nonstandard in this declaration context
    +
    +

    2614

    +
    final_modifier_requires_virtual_function:
    +
    nonvirtual function cannot be declared with “final” modifier
    +
    +

    2615

    +
    target_on_special_function:
    +
    “target” attribute on special function is not supported
    +
    +

    2616

    +
    target_string_must_be_narrow:
    +
    must be a narrow string literal
    +
    +

    2617

    +
    target_unmatched_parens:
    +
    unmatched parentheses
    +
    +

    2618

    +
    gcc_pragma_nothing_to_pop:
    +
    no corresponding “push_options”
    +
    +

    2619

    +
    pragma_inside_function:
    +
    this pragma is not allowed inside a function
    +
    +

    2620

    +
    inline_new_or_delete_operator:
    +
    declaring a new or delete operator “inline” is nonstandard
    +
    +

    2621

    +
    pack_expansion_for_field_mem_init:
    +
    a mem-initializer for a data member cannot be a pack expansion
    +
    +

    2622

    +
    generic_lambda_cannot_capture:
    +
    generic lambda expressions cannot have capture defaults in this mode
    +
    +

    2623

    +
    friend_with_def_arg_must_be_definition:
    +
    a default template argument in a friend declaration may only be +specified in a definition
    +
    +

    2624

    +
    friend_with_def_arg_must_be_only_decl:
    +
    a friend template declaration with a default template argument must +be the only declaration (first declared at line xxxx)
    +
    +

    2625

    +
    non_autonomous_opaque_enum_decl:
    +
    an opaque enum declaration cannot be part of another declaration
    +
    +

    2626

    +
    nonstd_opaque_enum_decl_in_type_id:
    +
    an opaque enum declaration is nonstandard in this context
    +
    +

    2627

    +
    extended_friends_is_cpp11:
    +
    extended friend syntax is a C++11 feature
    +
    +

    2628

    +
    digit_separators_not_enabled:
    +
    digit separators not enabled, apostrophe begins a character literal
    +
    +

    2629

    +
    bad_digit_separator_pos:
    +
    digit separator cannot appear here
    +
    +

    2630

    +
    constexpr_ignored_on_microsoft_nonstatic_member:
    +
    “constexpr” is ignored here in Microsoft mode
    +
    +

    2631

    +
    bad_gnu_stmt_return:
    +
    invalid expression for statement expression result
    +
    +

    2632

    +
    macro_not_udl_suffix:
    +
    identifier is a macro and not a literal suffix
    +
    +

    2633

    +
    cannot_call_named_member_on_lvalue:
    +
    entity-kind “entity” (declared at line xxxx) cannot be called +on an lvalue
    +
    +

    2634

    +
    cannot_call_named_member_on_rvalue:
    +
    entity-kind “entity” (declared at line xxxx) cannot be called +on an rvalue
    +
    +

    2635

    +
    cannot_call_member_on_lvalue:
    +
    member function cannot be called on an lvalue
    +
    +

    2636

    +
    cannot_call_member_on_rvalue:
    +
    member function cannot be called on an rvalue
    +
    +

    2637

    +
    templ_param_list_too_long:
    +
    the template parameter list is too long
    +
    +

    2638

    +
    bad_alias_templ_redecl:
    +
    alias template type “type” is incompatible with the previous type +of “type” in the redeclaration of entity-kind “entity”(declared at line xxxx)
    +
    +

    2639

    +
    field_initializer_is_not_constant:
    +
    the field initializer for entity-kind “entity” (declared at line +xxxx) is not a constant expression
    +
    +

    2640

    +
    constraint_number_mismatch:
    +
    the number of operand constraints must be the same in each constraint +string
    +
    +

    2641

    +
    too_many_constraints:
    +
    the constraint string contains too many alternative constraints; not +all constraints were checked
    +
    +

    2643

    +
    decltype_auto_cannot_be_qualified:
    +
    decltype(auto) cannot have added type qualifiers
    +
    +

    2644

    +
    bad_init_capture_capture:
    +
    init-capture “entity” (declared at line xxxx) cannot be +captured here
    +
    +

    2645

    +
    invalid_nontype_template_argument:
    +
    invalid nontype template argument of type “type”
    +
    +

    2646

    +
    abi_tag_ignored_in_C_mode:
    +
    the abi_tag attribute is ignored (it has no meaning in C mode)
    +
    +

    2647

    +
    abi_tag_redefinition:
    +
    redeclaration adds abi_tag attribute “xxxx“
    +
    +

    2648

    +
    abi_tag_ignored:
    +
    abi_tag attribute is ignored (superseded by later abi_tag attribute)
    +
    +

    2649

    +
    no_abi_tag_on_declaration:
    +
    previous declaration of entity-kind “entity” (declared at line +xxxx) had no abi_tag attribute
    +
    +

    2651

    +
    abi_tag_ignored_on_specialization:
    +
    abi_tag attribute is ignored on specialization
    +
    +

    2652

    +
    decltype_auto_return_must_be_standalone:
    +
    decltype(auto) cannot appear under a pointer, reference, or +pointer-to-member construct
    +
    +

    2653

    +
    exp_class_or_typename:
    +
    expected “class” or “typename”
    +
    +

    2654

    +
    placement_new_refers_to_non_placement_delete:
    +
    placement “new” expression refers to non-placement entity-kind +“entity” (declared at line xxxx)
    +
    +

    2655

    +
    cl_must_specify_cpp14_mode:
    +
    must specify C++14 mode when building runtime library
    +
    +

    2659

    +
    constexpr_not_const:
    +
    constexpr non-static member function will not be implicitly ‘const’ +in C++14
    +
    +

    2660

    +
    nonliteral_var_in_constexpr_function:
    +
    variable type “type” in constexpr function is not a literal type
    +
    +

    2661

    +
    nonautomatic_var_in_constexpr_function:
    +
    variable in constexpr function does not have automatic storage +duration
    +
    +

    2662

    +
    uninitialized_var_in_constexpr_function:
    +
    variable in constexpr function is uninitialized
    +
    +

    2663

    +
    auto_direct_list_init_requires_singleton:
    +
    braced initialization of a variable declared with a placeholder type +but without “=” requires exactly one element inside the braces
    +
    +

    2664

    +
    cl_invalid_target:
    +
    no “xxxx“ –target configuration exists
    +
    +

    2665

    +
    attribute_not_supported_in_x86_64:
    +
    attribute is supported only in 32-bit x86 configurations
    +
    +

    2666

    +
    cl_missing_argument:
    +
    “xxxx“ requires an argument
    +
    +

    2667

    +
    special_member_coroutine:
    +
    a constructor or destructor cannot be a coroutine
    +
    +

    2668

    +
    main_coroutine:
    +
    entity-kind “entity” cannot be a coroutine
    +
    +

    2669

    +
    yield_in_catch:
    +
    co_yield expressions are not permitted in a catch clause
    +
    +

    2674

    +
    special_class_template_not_found:
    +
    class template “xxxx” not found
    +
    +

    2675

    +
    typename_needed:
    +
    use the “typename” keyword to treat entity-kind “entity” as a +type in a dependent context
    +
    +

    2676

    +
    shufflevector_index_out_of_range:
    +
    argument value must be less than the sum of the vector elements
    +
    +

    2677

    +
    not_a_type_member:
    +
    “type” has no member “xxxx”
    +
    +

    2678

    +
    braced_list_for_implicit_return_type:
    +
    a brace-enclosed list does not provide a return type
    +
    +

    2679

    +
    await_not_allowed_outside_function_scope:
    +
    a co_await expression must appear in a function scope
    +
    +

    2680

    +
    await_not_allowed_in_catch_clause:
    +
    a co_await expression is not allowed inside a catch clause
    +
    +

    2681

    +
    coroutine_with_ellipsis_parameter:
    +
    a coroutine cannot have an ellipsis parameter
    +
    +

    2682

    +
    cl_relaxed_constexpr_requires_bool:
    +
    enabling C++14-style constexpr requires support for “bool”
    +
    +

    2683

    +
    constexpr_function_undefined:
    +
    constexpr entity-kind “entity” (declared at line xxxx) is not +defined
    +
    +

    2684

    +
    constexpr_call_not_interpretable:
    +
    this call cannot be evaluated because the target function +entity-kind “entity” (declared at line xxxx) is not constexpr +or not completely defined yet
    +
    +

    2687

    +
    anon_union_alias_member_template:
    +
    invalid anonymous union – alias member template is not allowed
    +
    +

    2688

    +
    utf8_char_lit_too_long:
    +
    a UTF-8 character literal value cannot occupy more than one code unit
    +
    +

    2689

    +
    variable_not_constant_valued:
    +
    the value of entity-kind “entity” (declared at line xxxx) +cannot be used as a constant
    +
    +

    2690

    +
    variable_not_constant_addressed:
    +
    a pointer or reference to entity-kind “entity” (declared at line +xxxx) cannot be used as a constant
    +
    +

    2691

    +
    constexpr_non_array_subscript:
    +
    nonzero subscript for non-array object
    +
    +

    2692

    +
    constexpr_out_of_bounds_array_access:
    +
    cannot access position n in array of n elements
    +
    +

    2693

    +
    constexpr_called_from:
    +
    called from:
    +
    +

    2694

    +
    constexpr_union_field_inactive:
    +
    invalid access to inactive entity-kind “entity” of union +(entity-kind “entity” is active)
    +
    +

    2695

    +
    constexpr_goto:
    +
    ‘goto’ cannot be executed in constexpr contexts
    +
    +

    2696

    +
    constexpr_missing_return_value:
    +
    missing return value
    +
    +

    2697

    +
    constexpr_null_callee:
    +
    callee is null
    +
    +

    2698

    +
    constexpr_null_dereference:
    +
    attempt to dereference a null pointer
    +
    +

    2699

    +
    constexpr_access_one_past_array_end:
    +
    attempt to access storage one position past the end of an array of +n elements
    +
    +

    2700

    +
    constexpr_access_to_expired_storage:
    +
    attempt to access expired storage
    +
    +

    2701

    +
    constexpr_access_to_runtime_storage:
    +
    attempt to access run-time storage
    +
    +

    2703

    +
    constexpr_call_to_nonconstexpr_function:
    +
    cannot call non-constexpr entity-kind “entity” (declared at line +xxxx)
    +
    +

    2704

    +
    constexpr_vla:
    +
    cannot use variable-length array during constexpr evaluation
    +
    +

    2705

    +
    constexpr_negative_shift:
    +
    cannot perform a negative shift
    +
    +

    2706

    +
    constexpr_shift_excess:
    +
    shift amount (n) too large
    +
    +

    2707

    +
    constexpr_integer_overflow:
    +
    value exceeds range of “type”
    +
    +

    2708

    +
    constexpr_fp_error:
    +
    floating-point error
    +
    +

    2709

    +
    constexpr_null_ptr_to_member_data:
    +
    attempt to dereference a null pointer-to-member (data member)
    +
    +

    2710

    +
    comparison_of_pointers_to_void_and_function:
    +
    comparing a pointer to void and a pointer to a function is nonstandard
    +
    +

    2711

    +
    ms_metadata_init_failed:
    +
    metadata initialization failed
    +
    +

    2712

    +
    constexpr_bad_derived_class_cast:
    +
    invalid base-to-derived cast (actual derived class type is “type”)
    +
    +

    2713

    +
    constexpr_invalid_pm_access:
    +
    invalid access to entity-kind “entity” in object of complete type +“type”
    +
    +

    2714

    +
    bad_gnu_auto_type:
    +
    “xxxx” not allowed here
    +
    +

    2715

    +
    gnu_auto_type_with_secondary_declarator:
    +
    “xxxx” does not permit multiple declarators
    +
    +

    2716

    +
    auto_type_brace_initialization_not_allowed:
    +
    initialization with “{…}” is not allowed for “xxxx”
    +
    +

    2717

    +
    modified_auto_type:
    +
    “xxxx” must be a placeholder for the complete type of the +variable (not for a component of that type)
    +
    +

    2718

    +
    gnu_auto_type_without_initializer:
    +
    a variable declared with “xxxx” requires an initializer
    +
    +

    2719

    +
    constant_must_be_positive:
    +
    integer constant must be greater than or equal to zero
    +
    +

    2720

    +
    type_must_be_integral:
    +
    type must be an integral type
    +
    +

    2721

    +
    constexpr_expression_cannot_be_interpreted:
    +
    expression cannot be interpreted
    +
    +

    2722

    +
    constexpr_statement_cannot_be_interpreted:
    +
    statement cannot be interpreted
    +
    +

    2723

    +
    constexpr_interpreter_address:
    +
    invalid use of address of interpreter storage
    +
    +

    2724

    +
    constexpr_invalid_constant_kind:
    +
    invalid constant kind for constant-expression
    +
    +

    2725

    +
    constexpr_type_too_large:
    +
    type “type” too large for constant-expression evaluation
    +
    +

    2726

    +
    constexpr_type_invalid:
    +
    invalid type “type” for constant-expression evaluation
    +
    +

    2727

    +
    constexpr_invalid_type_conversion:
    +
    conversion from “type” to “type” is invalid in +constant-expression evaluation
    +
    +

    2728

    +
    constexpr_fp_conversion_failed:
    +
    floating-point conversion failed
    +
    +

    2730

    +
    deduced_return_types_is_cpp14:
    +
    deduced return types are a C++14 feature
    +
    +

    2731

    +
    constexpr_ctor_with_dtor:
    +
    cannot evaluate a constructor with an associated destructor
    +
    +

    2732

    +
    constexpr_missing_initializer_for_field:
    +
    entity-kind “entity” not initialized during constexpr evaluation
    +
    +

    2733

    +
    constexpr_invalid_pdiff:
    +
    invalid pointer difference in constexpr evaluation
    +
    +

    2734

    +
    constexpr_non_array_pointer_arithmetic:
    +
    invalid arithmetic on non-array pointer
    +
    +

    2735

    +
    constexpr_pointer_ahead_of_array:
    +
    cannot set pointer before the first array element
    +
    +

    2736

    +
    coroutine_with_deduced_return_type:
    +
    a coroutine with a deduced return type is invalid
    +
    +

    2737

    +
    await_in_unevaluated_operand:
    +
    expression not allowed in unevaluated context
    +
    +

    2740

    +
    return_in_coroutine:
    +
    “return” is not permitted in a coroutine (use “co_return” instead)
    +
    +

    2741

    +
    invalid_co_return:
    +
    “co_return” is only allowed in coroutines
    +
    +

    2742

    +
    constexpr_fp_values_not_comparable:
    +
    floating-point values cannot be compared
    +
    +

    2743

    +
    constexpr_pointers_not_comparable:
    +
    pointer values cannot be compared because they do not point into the +same complete object or they point to subobjects with different +accessibility
    +
    +

    2744

    +
    ignoring_attribute_on_non_inline_namespace:
    +
    ignoring abi_tag attribute on non-inline namespace
    +
    +

    2745

    +
    ignoring_attribute_on_anonymous_namespace:
    +
    ignoring abi_tag attribute on anonymous namespace
    +
    +

    2746

    +
    complex_template_parameter:
    +
    complex or imaginary template parameter type is nonstandard
    +
    +

    2747

    +
    yield_outside_of_function:
    +
    co_yield expression is not permitted outside a function scope
    +
    +

    2748

    +
    thread_local_ignored:
    +
    ignoring thread-local indication on anonymous union
    +
    +

    2751

    +
    object_not_initialized:
    +
    access to uninitialized object
    +
    +

    2752

    +
    constexpr_volatile_fetch:
    +
    attempt to read from volatile storage
    +
    +

    2753

    +
    constexpr_no_active_union_field:
    +
    invalid access to inactive entity-kind “entity” of union (no +field is active)
    +
    +

    2754

    +
    label_in_constexpr_function:
    +
    label definitions cannot appear in constexpr functions
    +
    +

    2755

    +
    constexpr_equality_past_the_end_address:
    +
    cannot compare a pointer past the end of an array with a pointer to +another complete object
    +
    +

    2756

    +
    variable_templ_function_type:
    +
    function type “type” is an invalid type for a variable template +instantiation
    +
    +

    2757

    +
    incomplete_var_type:
    +
    variable cannot have incomplete type “type”
    +
    +

    2758

    +
    field_subobject_not_initialized:
    +
    access to uninitialized subobject (entity-kind “entity”)
    +
    +

    2759

    +
    base_subobject_not_initialized:
    +
    access to uninitialized subobject (base class “type”)
    +
    +

    2760

    +
    constexpr_vacuous_dtor_call:
    +
    a pseudo-destructor call is not permitted in a constant-expression
    +
    +

    2761

    +
    constexpr_modifying_const_storage:
    +
    attempt to modify const storage
    +
    +

    2764

    +
    constexpr_access_past_object:
    +
    attempt to access storage one position past an object treated as an +array of one element
    +
    +

    2765

    +
    constexpr_reinterpret_cast:
    +
    cannot use reinterpret_cast in constant-expression evaluation
    +
    +

    2766

    +
    constexpr_invalid_null_ptr_operation:
    +
    operation not allowed on null pointer
    +
    +

    2767

    +
    star_this_not_constant_valued:
    +
    the value of *this cannot be used as a constant
    +
    +

    2768

    +
    inline_on_nested_namespace:
    +
    the “inline” keyword cannot be used on a nested namespace declaration
    +
    +

    2769

    +
    carries_dependency_ignored:
    +
    the “carries_dependency” attribute is ignored
    +
    +

    2770

    +
    event_interface_cannot_have_definition:
    +
    an “__event __interface” cannot have a definition here
    +
    +

    2771

    +
    invalid_event_handler_type:
    +
    an event handler must have a void or integral return type
    +
    +

    2772

    +
    event_interface_must_be_previously_defined:
    +
    an “__event __interface” must have been previously defined
    +
    +

    2773

    +
    too_many_template_arguments:
    +
    too many template arguments for entity-kind “entity”
    +
    +

    2774

    +
    enumerator_already_declared:
    +
    enumerator already declared (see entity-kind “entity” (declared +at line xxxx))
    +
    +

    2775

    +
    microsoft_version_doesnt_support_cpp14_mode:
    +
    the version of Microsoft being emulated must be at least 1903 to use +“–ms_c++14”
    +
    +

    2776

    +
    microsoft_version_doesnt_support_cpplatest_mode:
    +
    the version of Microsoft being emulated must be at least 1903 to use +“–ms_c++latest”
    +
    +

    2777

    +
    c11_atomic_array_or_function_type:
    +
    type “type” cannot be _Atomic because it is an array or function +type
    +
    +

    2778

    +
    c11_atomic_specifier_with_qualified_type:
    +
    the _Atomic(…) specifier cannot be applied to qualified type +“type”
    +
    +

    2779

    +
    access_to_member_of_c11_atomic_object:
    +
    access to member of _Atomic object
    +
    +

    2780

    +
    c11_atomic_bit_field:
    +
    a bit field cannot have an _Atomic type
    +
    +

    2782

    +
    nonconstexpr_mem_init_ctor_for_constexpr_ctor:
    +
    constexpr constructor calls non-constexpr constructor for subobject +initialization
    +
    +

    2783

    +
    terse_static_assert_not_enabled:
    +
    expected a comma (the one-argument version of static_assert is not +enabled in this mode)
    +
    +

    2784

    +
    terse_static_assert:
    +
    static assertion failed
    +
    +

    2785

    +
    conflicting_nullability:
    +
    at most one of the qualifiers _Nullable, _Nonnull, and +_Null_unspecified can modify a type
    +
    +

    2786

    +
    invalid_type_for_nullability:
    +
    nullability qualifiers are only permitted on pointer and +pointer-to-member types
    +
    +

    2787

    +
    vector_length_too_large:
    +
    vector length is too large
    +
    +

    2788

    +
    invalid_vector_element_type:
    +
    vector element type must be integral, enum, or real floating-point +type
    +
    +

    2789

    +
    builtin_needs_128_bit_integers:
    +
    builtin function is not available because 128-bit integers are not +supported
    +
    +

    2790

    +
    builtin_needs_vector_types:
    +
    builtin function is not available because vector types are not +supported
    +
    +

    2791

    +
    must_introduce_attribute:
    +
    two consecutive left square brackets always introduce an attribute +list but an attribute list cannot appear here
    +
    +

    2792

    +
    invalid_target_attribute:
    +
    unrecognized “target” attribute disqualifies this routine from being +used by resolver routine
    +
    +

    2793

    +
    vector_type_required:
    +
    “type” is not a vector type
    +
    +

    2794

    +
    vector_types_differ_in_length:
    +
    vector types “type” and “type” must have the same length
    +
    +

    2795

    +
    member_special_after_class_definition:
    +
    added default arguments cannot result in declaring a default or copy +constructor
    +
    +

    2796

    +
    template_arg_cannot_point_to_subobject:
    +
    a nontype template argument of reference type must bind to a function +or to a complete object
    +
    +

    2797

    +
    type_not_allowed_here:
    +
    “type” not allowed here
    +
    +

    2798

    +
    register_keyword_disallowed:
    +
    use of the “register” storage class specifier is not allowed
    +
    +

    2799

    +
    register_keyword_deprecated:
    +
    use of the “register” storage class specifier is deprecated
    +
    +

    2800

    +
    incr_of_bool_not_allowed:
    +
    incrementing a bool value is not allowed
    +
    +

    2801

    +
    redeclaration_of_range_iterator:
    +
    “xxxx”, declared as iterator of range-based “for” statement, may +not be redeclared in this scope
    +
    +

    2802

    +
    namespace_not_allowed:
    +
    an attribute namespace may not be used here (because a “using” prefix +was specified)
    +
    +

    2803

    +
    attribute_namespace_unrecognized:
    +
    attribute namespace “xxxx” is unrecognized
    +
    +

    2804

    +
    default_member_init_for_value_class:
    +
    a default member initializer is not permitted in a value class
    +
    +

    2805

    +
    cl_implicit_noexcept_requires_noexcept_support:
    +
    “–implicit_noexcept” requires a mode that enables noexcept
    +
    +

    2806

    +
    constexpr_virtual_base:
    +
    cannot fold operation involving virtual base class (“type”)
    +
    +

    2807

    +
    initializer_not_constant:
    +
    initialization is not constant
    +
    +

    2808

    +
    constexpr_incomplete_type:
    +
    cannot evaluate value of incomplete “type”
    +
    +

    2809

    +
    nodiscard_routine:
    +
    ignoring return value from routine declared with “nodiscard” attribute
    +
    +

    2810

    +
    nodiscard_return_type:
    +
    ignoring return value type with “nodiscard” attribute
    +
    +

    2811

    +
    nodiscard_doesnt_apply:
    +
    the “nodiscard” attribute does not apply to destructors or routines +with void return type
    +
    +

    2812

    +
    fallthrough_applies_to_null_statement:
    +
    the “fallthrough” attribute only applies to null statements
    +
    +

    2813

    +
    fallthrough_not_in_switch:
    +
    the “fallthrough” attribute may only appear in an enclosing switch +statement
    +
    +

    2814

    +
    fallthrough_must_precede_switch_case:
    +
    fallthrough statement must precede switch case label or default
    +
    +

    2815

    +
    constexpr_expiring_temporary:
    +
    reference or pointer to temporary with limited lifetime
    +
    +

    2816

    +
    address_of_nontrue_enable_if_function:
    +
    cannot take the address of a function with an “enable_if” attribute +whose condition is not unconditionally true
    +
    +

    2817

    +
    nonconstant_enable_if_attr:
    +
    “enable_if” attributes with conditions that are not constant values +are not currently supported
    +
    +

    2818

    +
    attribute_declared_here:
    +
    attribute was declared here
    +
    +

    2819

    +
    has_include_not_in_if:
    +
    __has_include cannot appear outside #if
    +
    +

    2820

    +
    coclass_base_requirements_not_met:
    +
    could not add CComCoClass base class
    +
    +

    2821

    +
    constexpr_string_not_null_terminated:
    +
    not a null-terminated string
    +
    +

    2822

    +
    non_scalar_vacuous_dtor_call:
    +
    non-scalar type “type” cannot be used in a pseudo-destructor call
    +
    +

    2823

    +
    constexpr_weak_address:
    +
    address of “weak” entity-kind “entity” is not constant
    +
    +

    2824

    +
    excessive_rescan_depth:
    +
    too many recursive substitutions of function template signatures
    +
    +

    2825

    +
    invalid_struct_binding_specifier:
    +
    invalid specifier for structured binding declaration
    +
    +

    2826

    +
    invalid_struct_binding_syntax:
    +
    invalid structured binding syntax
    +
    +

    2827

    +
    missing_initializer:
    +
    missing initializer
    +
    +

    2828

    +
    invalid_struct_binding_type:
    +
    type “type” has no components to bind to
    +
    +

    2829

    +
    too_many_struct_bindings:
    +
    too many identifiers
    +
    +

    2830

    +
    missing_bindings:
    +
    there are more elements than there are binding names
    +
    +

    2831

    +
    missing_std_tuple_element:
    +
    “std::tuple_element” not defined
    +
    +

    2832

    +
    missing_std_tuple_element_instance:
    +
    cannot instantiate “std::tuple_element” for <xxxx, “type”>
    +
    +

    2833

    +
    failed_tuple_container_member_get:
    +
    cannot call member function “get<xxxx>()” for type “type”
    +
    +

    2834

    +
    tuple_get_no_matching_overload:
    +
    no instance of “entity” matches the argument list
    +
    +

    2835

    +
    struct_binding_undefined_identifier:
    +
    this structured binding requires a suitable “xxxx” function and +none was found
    +
    +

    2836

    +
    struct_binding_inline:
    +
    a structured binding cannot be declared “inline”
    +
    +

    2837

    +
    struct_binding_constexpr:
    +
    a structured binding cannot be declared “constexpr”
    +
    +

    2838

    +
    struct_binding_storage_class:
    +
    a structured binding cannot declare an explicit storage class
    +
    +

    2839

    +
    invalid_tuple_size:
    +
    std::tuple_size<”type”>::value is not a valid integral +constant-expression
    +
    +

    2840

    +
    condition_does_not_declare_a_variable:
    +
    a condition declaration must declare a variable
    +
    +

    2841

    +
    condition_decl_must_have_initializer:
    +
    a condition declaration must include an initializer
    +
    +

    2842

    +
    parenthesized_init_not_allowed:
    +
    a parenthesized initializer is not permitted for a condition +declaration
    +
    +

    2843

    +
    condition_with_multiple_declarators:
    +
    a condition declaration can only declare one variable
    +
    +

    2844

    +
    struct_binding_lambda:
    +
    structured binding cannot bind to closure type
    +
    +

    2845

    +
    struct_binding_private_member:
    +
    cannot bind to non-public entity-kind “entity”
    +
    +

    2846

    +
    struct_binding_incomplete_type:
    +
    cannot bind to incomplete type “type”
    +
    +

    2847

    +
    invalid_init_statement:
    +
    this declaration is not valid here
    +
    +

    2848

    +
    constexpr_function_with_function_try_block:
    +
    the body of a constexpr function cannot be a function try block
    +
    +

    2849

    +
    branch_into_constexpr_if:
    +
    transfer of control into a constexpr if block is not allowed
    +
    +

    2850

    +
    lambda_capture_structured_binding:
    +
    structured binding cannot be captured
    +
    +

    2851

    +
    microsoft_version_doesnt_support_cpp17_mode:
    +
    the version of Microsoft being emulated must be at least 1911 to use +“–ms_c++17”
    +
    +

    2852

    +
    attempt_to_read_past_end_of_object:
    +
    attempt to read past the end of the object
    +
    +

    2853

    +
    constexpr_lambdas_not_enabled:
    +
    constexpr lambdas are not enabled in this mode
    +
    +

    2854

    +
    lambda_not_constant_expr:
    +
    a constant expression cannot contain a lambda expression
    +
    +

    2855

    +
    template_argument_index_out_of_bounds:
    +
    value exceeds number of template arguments
    +
    +

    2856

    +
    fold_expression_operator_mismatch:
    +
    second operator in binary fold expression does not match first
    +
    +

    2857

    +
    invalid_fold_expression_operator:
    +
    invalid fold expression operator
    +
    +

    2858

    +
    two_packs_in_fold_expression:
    +
    a binary fold expression cannot apply to two parameter packs
    +
    +

    2859

    +
    invalid_empty_fold_expression:
    +
    empty expansion not valid for this fold expression
    +
    +

    2860

    +
    inline_nonstatic_data_mem:
    +
    a nonstatic data member cannot be declared as inline
    +
    +

    2861

    +
    no_pack_in_fold_expression:
    +
    fold expression does not refer to a parameter pack
    +
    +

    2862

    +
    same_param_types_with_different_exception_specifications:
    +
    two functions with the same parameter types but different exception +specifications cannot be overloaded
    +
    +

    2863

    +
    dynamic_exc_spec_not_permitted:
    +
    dynamic exception specifications are not permitted in this mode
    +
    +

    2865

    +
    invalid_noexcept_specifier_operand:
    +
    invalid operand for noexcept specifier
    +
    +

    2866

    +
    lambda_in_noexcept_specifier:
    +
    lambda expression cannot appear in noexcept specifier of a template
    +
    +

    2867

    +
    inaccessible_rvalue_dtor:
    +
    entity-kind “entity” (declared at line xxxx) is inaccessible
    +
    +

    2868

    +
    bad_enum_template_decl:
    +
    invalid specifier in enum template declaration
    +
    +

    2869

    +
    no_float80:
    +
    80-bit floating-point types are not supported in this configuration
    +
    +

    2870

    +
    no_float128:
    +
    128-bit floating-point types are not supported in this configuration
    +
    +

    2871

    +
    invalid_enumerator_value:
    +
    invalid enumerator value
    +
    +

    2872

    +
    must_be_atomic_qualified_type:
    +
    must be an _Atomic qualified type
    +
    +

    2873

    +
    element_type_incomplete:
    +
    type of array element must be complete
    +
    +

    2874

    +
    always_inline_suppressed:
    +
    the always_inline attribute has been suppressed for this function
    +
    +

    2875

    +
    negative_value:
    +
    a negative value is not permitted here
    +
    +

    2876

    +
    integer_pack_element_for_type:
    +
    an integer pack element cannot match entity-kind “entity”
    +
    +

    2877

    +
    integer_pack_element_for_template:
    +
    an integer pack element cannot match entity-kind “entity”
    +
    +

    2878

    +
    unexpected_designator:
    +
    unexpected designator
    +
    +

    2879

    +
    cannot_evaluate_builtin_offsetof:
    +
    cannot evaluate __builtin_offsetof
    +
    +

    2880

    +
    deduction_guide_def:
    +
    deduction guide “type” cannot be defined
    +
    +

    2881

    +
    bad_deduction_guide_scope:
    +
    deduction guide must be declared in the same scope as entity-kind +“entity”
    +
    +

    2882

    +
    invalid_specifier_for_deduction_guide:
    +
    invalid specifier for deduction guide declaration (only “explicit” is +permitted)
    +
    +

    2883

    +
    constexpr_mutable_field_load:
    +
    mutable entity-kind “entity” of a constant cannot be accessed in +a constant expression
    +
    +

    2884

    +
    member_function_modifier_on_static_member:
    +
    function modifier does not apply to static member declaration
    +
    +

    2885

    +
    overloadable_attribute_requires_prototype:
    +
    the “overloadable” attribute requires a prototyped function +declaration
    +
    +

    2886

    +
    cannot_deduce_auto_templ_param:
    +
    cannot deduce “auto” template parameter type “type” from +“type”
    +
    +

    2887

    +
    modified_class_template_placeholder:
    +
    class template name must be a placeholder for the complete type being +initialized (not for a component of that type)
    +
    +

    2888

    +
    alias_declaration_is_cpp11:
    +
    alias declarations are a C++11 feature
    +
    +

    2889

    +
    alias_template_is_cpp11:
    +
    alias templates are a C++11 feature
    +
    +

    2890

    +
    bad_deduction_guide_return_type:
    +
    the return type must directly designate a specialization of the +associated class template
    +
    +

    2891

    +
    explicit_deduction_guide_in_copy_list_init:
    +
    copy-list-initialization cannot use “explicit” entity-kind +“entity”
    +
    +

    2893

    +
    invalid_udl_value:
    +
    Invalid value for user-defined literal operator
    +
    +

    2894

    +
    has_cpp_attrib_not_in_if:
    +
    xxxx cannot appear outside of preprocessor directives
    +
    +

    2895

    +
    bad_deduction_guide_access:
    +
    deduction guide must be declared with the same accessibility as +entity-kind “entity”
    +
    +

    2896

    +
    lambda_not_allowed_here:
    +
    a lambda is not permitted in this context
    +
    +

    2897

    +
    align_not_equivalent:
    +
    specified alignment is not equivalent to previous declaration
    +
    +

    2898

    +
    no_alignment_on_definition:
    +
    no alignment specified on definition; previous declaration had +specified an alignment
    +
    +

    2899

    +
    builtin_needs_128_bit_floats:
    +
    builtin function is not available because 128-bit floating-point +types are not supported
    +
    +

    2900

    +
    constexpr_shift_negative_value:
    +
    left-shifting a negative value has undefined behavior
    +
    +

    2901

    +
    no_array_designators_in_cpp_mode:
    +
    array designators are nonstandard in C++
    +
    +

    2902

    +
    no_chained_designators_in_cpp_mode:
    +
    chained designators are nonstandard in C++
    +
    +

    2903

    +
    no_mixed_init_in_cpp_mode:
    +
    mixing designated and non-designated initializers is nonstandard in +C++
    +
    +

    2904

    +
    no_out_of_order_init_in_cpp_mode:
    +
    out-of-order initializers are nonstandard in C++
    +
    +

    2905

    +
    invalid_string_literal_operator_template:
    +
    a string literal operator template must have a template parameter +list equivalent to “<typename T, T …>”
    +
    +

    2906

    +
    duplicate_designator:
    +
    duplicate designator is not allowed
    +
    +

    2907

    +
    likely_unlikely_conflict:
    +
    attribute conflicts with previous likely/unlikely attribute
    +
    +

    2908

    +
    implicit_copy_this_capture_deprecated:
    +
    the implicit by-copy capture of “this” is deprecated
    +
    +

    2909

    +
    empty_lambda_template_param_list:
    +
    an empty template parameter list is not allowed in a lambda expression
    +
    +

    2910

    +
    microsoft_version_doesnt_support_cpp20_mode:
    +
    the version of Microsoft being emulated must be at least 1920 to use +“–ms_c++20”
    +
    +

    2911

    +
    bad_stdc_pragma_arg_for_mode:
    +
    STDC pragma argument not accepted in this mode
    +
    +

    2912

    +
    if_constexpr_is_cpp17:
    +
    constexpr if statements are a C++17 feature
    +
    +

    2913

    +
    no_pack_expansion_in_designator:
    +
    pack expansion is not allowed in a designated initializer list
    +
    +

    2914

    +
    no_designator_value:
    +
    field designator has no value
    +
    +

    2915

    +
    multiple_union_field_initializers_empty:
    +
    a union can have at most one field initializer
    +
    +

    2916

    +
    bad_ordering_type:
    +
    no valid std::xxxx type found (<compare> must be included)
    +
    +

    2917

    +
    invalid_spaceship_types:
    +
    invalid types (“type” and “type”) for built-in operator<=>
    +
    +

    2918

    +
    fold_expressions_nonstandard:
    +
    fold expressions are nonstandard in this mode
    +
    +

    2919

    +
    selection_initializer_nonstandard:
    +
    C++17-style initializer is nonstandard in this mode
    +
    +

    2920

    +
    star_this_capture_nonstandard:
    +
    capturing *this is nonstandard in this mode
    +
    +

    2921

    +
    using_attribute_nonstandard:
    +
    C++17-style “using” attribute prefix is nonstandard in this mode
    +
    +

    2922

    +
    nested_namespace_nonstandard:
    +
    C++17-style nested namespaces are nonstandard in this mode
    +
    +

    2923

    +
    constexpr_and_consteval_specifiers:
    +
    only one of “constexpr”, “consteval”, and “constinit” can appear on a +declaration
    +
    +

    2924

    +
    consteval_virtual_combination:
    +
    a function cannot be both consteval and virtual in this mode
    +
    +

    2925

    +
    consteval_explicit_instantiation:
    +
    “consteval” is not allowed on an explicit instantiation directive
    +
    +

    2926

    +
    invalid_consteval:
    +
    “consteval” is not valid here
    +
    +

    2927

    +
    consteval_destructor:
    +
    a destructor cannot be consteval
    +
    +

    2928

    +
    consteval_ctor_with_virtual_base:
    +
    a constructor for a class with virtual bases cannot be consteval
    +
    +

    2929

    +
    consteval_variable:
    +
    “consteval” is not permitted on the declaration of a variable or +static data member
    +
    +

    2930

    +
    previous_consteval_decl_conflict:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared consteval
    +
    +

    2931

    +
    previous_nonconsteval_decl_conflict:
    +
    entity-kind “entity” (declared at line xxxx) was previously +not declared consteval
    +
    +

    2932

    +
    consteval_main:
    +
    function “main” may not be declared consteval
    +
    +

    2933

    +
    consteval_call_nonconstant:
    +
    call to consteval entity-kind “entity” did not produce a valid +constant expression
    +
    +

    2934

    +
    address_of_consteval_function:
    +
    address of consteval entity-kind “entity” in constant expression +result
    +
    +

    2935

    +
    consteval_overrides_nonconsteval:
    +
    consteval member cannot override non-consteval entity-kind +“entity”
    +
    +

    2936

    +
    nonconsteval_overrides_consteval:
    +
    non-consteval member cannot override consteval entity-kind +“entity”
    +
    +

    2938

    +
    constexpr_invalid_dynamic_cast:
    +
    dynamic_cast to subobject of type “type” is invalid (most-derived +type is “type”)
    +
    +

    2939

    +
    VA_OPT_not_allowed:
    +
    the identifier __VA_OPT__ can only appear in the replacement lists +of variadic macros
    +
    +

    2940

    +
    nested_VA_OPT:
    +
    __VA_OPT__ cannot appear in a __VA_OPT__ operand
    +
    +

    2941

    +
    unclosed_VA_OPT:
    +
    missing closing parenthesis for __VA_OPT__
    +
    +

    2942

    +
    missing_VA_OPT_paren:
    +
    __VA_OPT__ must be followed by “(”
    +
    +

    2943

    +
    paste_cannot_be_first_in_VA_OPT:
    +
    “##” may not be first in a __VA_OPT__ operand
    +
    +

    2944

    +
    paste_cannot_be_last_in_VA_OPT:
    +
    “##” may not be last in a __VA_OPT__ operand
    +
    +

    2945

    +
    nested_inline_namespace_nonstandard:
    +
    C++20-style nested inline namespaces are nonstandard in this mode
    +
    +

    2946

    +
    derived_class_too_far:
    +
    cannot convert pointer to base class “type” to pointer to derived +class “type” – attempt to point beyond the most-derived object
    +
    +

    2948

    +
    invalid_variable_main:
    +
    “main” cannot be used as a global variable name or given C language +linkage
    +
    +

    2949

    +
    linkage_main:
    +
    function “main” cannot be declared in a linkage-specification
    +
    +

    2950

    +
    struct_binding_in_condition:
    +
    structured binding is not allowed in a condition
    +
    +

    2951

    +
    missing_attr_namespace:
    +
    an attribute namespace identifier is required before “::”
    +
    +

    2952

    +
    multiple_attr_namespaces:
    +
    only one attribute namespace is allowed
    +
    +

    2953

    +
    bad_return:
    +
    “return” not allowed here
    +
    +

    2954

    +
    struct_binding_with_multiple_declarators:
    +
    a structured binding cannot be combined with other declarators
    +
    +

    2955

    +
    branch_out_of_constant:
    +
    cannot branch out of a constant-evaluation context
    +
    +

    2956

    +
    struct_binding_template:
    +
    structured binding templates are not permitted
    +
    +

    2957

    +
    braced_init_in_parens:
    +
    a parenthesized initializer must be an expression, not a +brace-enclosed list
    +
    +

    2958

    +
    cannot_deduce_class_template_arguments:
    +
    cannot deduce class template arguments
    +
    +

    2959

    +
    consteval_new_or_delete_operator:
    +
    a new or delete operator cannot be declared “consteval”
    +
    +

    2960

    +
    address_of_consteval_function_leaked:
    +
    the address of a consteval function cannot be used here
    +
    +

    2961

    +
    alignof_function_type:
    +
    the alignment of a function type (“type”) is nonstandard
    +
    +

    2962

    +
    alignof_incomplete_array:
    +
    the alignment of an array of unspecified bound is nonstandard in C
    +
    +

    2963

    +
    cannot_be_common_internal_linkage:
    +
    a variable cannot have both “common” and “internal_linkage” attributes
    +
    +

    2964

    +
    internal_linkage_not_on_prior_declaration:
    +
    the “internal_linkage” attribute did not appear on a prior declaration
    +
    +

    2965

    +
    no_class_template_guide:
    +
    no viable template argument deduction candidate found for +entity-kind “entity”
    +
    +

    2966

    +
    fully_qualified_constructor_call:
    +
    a fully qualified constructor call is not allowed
    +
    +

    2967

    +
    bad_scope_for_defaulted_comparison:
    +
    a defaulted comparison operator must be a member or a friend of the +class it applies to
    +
    +

    2968

    +
    bad_param_type_for_defaulted_comparison:
    +
    bad type “type” for parameter of defaulted comparison operator +(must be “reference to const X” where X is the enclosing class type)
    +
    +

    2969

    +
    return_type_of_default_comparison_must_be_bool:
    +
    return type of defaulted comparison operator must be “bool”
    +
    +

    2970

    +
    nonconst_defaulted_member_comparison:
    +
    a defaulted member comparison operator must be “const”
    +
    +

    2972

    +
    no_return_value_and_return_void:
    +
    a coroutine’s promise type “type” cannot have both “return_void” +and “return_value” set
    +
    +

    2973

    +
    return_value_at:
    +
    “return_value” declared at line xxxx
    +
    +

    2974

    +
    return_void_at:
    +
    “return_void” declared at line xxxx
    +
    +

    2975

    +
    implicit_co_return_with_no_return_void:
    +
    missing co_return statement while “type” has no “return_void” at +end of entity-kind “entity”
    +
    +

    2976

    +
    no_nothrow_global_new_for_coroutine:
    +
    no nothrow variant of the global “operator new” found for coroutine +state allocation
    +
    +

    2977

    +
    no_viable_delete_for_coroutine:
    +
    no viable “operator delete” found for coroutine state deallocation
    +
    +

    2978

    +
    no_constexpr_coroutine:
    +
    a constexpr function cannot be a coroutine
    +
    +

    2979

    +
    await_operand_not_a_class:
    +
    the operand to this xxxx expression resolves to non-class +“type”
    +
    +

    2980

    +
    await_not_allowed_in_static_initializer:
    +
    a co_await expression is not allowed in a static initializer
    +
    +

    2981

    +
    final_suspend_cannot_throw:
    +
    the co_await expression calling entity-kind “entity” must be +non-throwing
    +
    +

    2982

    +
    excessive_comparison_rewrites:
    +
    too many recursive comparison rewrite operations
    +
    +

    2983

    +
    invalid_placeholder_for_defaulted_spaceship_return:
    +
    a deducible return type for a default operator<=> must be “auto”
    +
    +

    2984

    +
    constexpr_implied_source_nonconstant:
    +
    implicit copy of non-constant source
    +
    +

    2985

    +
    struct_binding_restricted_storage_class:
    +
    a structured binding cannot declare an explicit storage class other +than static or thread_local
    +
    +

    2986

    +
    defaulted_comparison_for_property:
    +
    defaulted comparison operators are not supported for nontrivial +Microsoft property fields
    +
    +

    2987

    +
    invalid_std_comparison_type:
    +
    standard comparison type (“type”) must be a class type with a +single nonstatic data member of integral type
    +
    +

    2988

    +
    invalid_std_comparison_value:
    +
    no constexpr static data member “xxxx” found in “type”
    +
    +

    2989

    +
    constexpr_alloc_too_large:
    +
    number of elements (n) too large for dynamic allocation
    +
    +

    2990

    +
    constexpr_allocation_too_large:
    +
    constexpr dynamic allocation request too large
    +
    +

    2991

    +
    constexpr_bad_deallocation:
    +
    deallocation of storage that was not dynamically allocated
    +
    +

    2992

    +
    constexpr_bad_deallocation_size:
    +
    deallocation size (n) does not correspond to size allocated +(n)
    +
    +

    2993

    +
    constexpr_allocation_pos:
    +
    allocation occurred here
    +
    +

    2994

    +
    constexpr_bad_deallocation_type:
    +
    deallocation type (“type”) does not correspond to allocation type +(“type”)
    +
    +

    2995

    +
    constexpr_leftover_allocations:
    +
    some dynamic allocations (total number = n) were not deallocated
    +
    +

    2996

    +
    constexpr_invalid_intrinsic_signature:
    +
    intrinsic entity-kind “entity” declared with unexpected signature +(type “type”)
    +
    +

    2997

    +
    constexpr_begin_report:
    +
    >> output from std::__report_constexpr_value
    +
    +

    2998

    +
    constexpr_end_report:
    +
    >> end output from std::__report_constexpr_value
    +
    +

    2999

    +
    constexpr_dependent_array_size:
    +
    cannot use array with dependent array size in constexpr evaluation
    +
    +

    3000

    +
    nodiscard_routine_with_reason:
    +
    ignoring return value from routine declared with “nodiscard” +attribute (“xxxx”)
    +
    +

    3001

    +
    nodiscard_return_type_with_reason:
    +
    ignoring return value type with “nodiscard” attribute (“xxxx”)
    +
    +

    3002

    +
    nodiscard_constructor:
    +
    constructor used to create discarded object has “nodiscard” attribute
    +
    +

    3003

    +
    nodiscard_constructor_with_reason:
    +
    constructor used to create discarded object has “nodiscard” attribute +(“xxxx”)
    +
    +

    3004

    +
    nodiscard_object_type:
    +
    type of discarded object has “nodiscard” attribute
    +
    +

    3005

    +
    nodiscard_object_type_with_reason:
    +
    type of discarded object has “nodiscard” attribute (“xxxx”)
    +
    +

    3006

    +
    vacuous_destructor_not_called:
    +
    a pseudo-destructor reference can only be used for a +pseudo-destructor call
    +
    +

    3007

    +
    constexpr_explicit_dtor_call:
    +
    an explicit destructor call is not permitted in a constant-expression
    +
    +

    3008

    +
    comma_operator_in_array_subscript_deprecated:
    +
    an unparenthesized comma operator in an array subscript expression is +deprecated
    +
    +

    3009

    +
    constexpr_alloc_too_small:
    +
    number of dynamically-allocated elements (n) too small for +initializer
    +
    +

    3011

    +
    volatile_ass_deprecated:
    +
    use of the result of an assignment to a volatile scalar object is +deprecated
    +
    +

    3012

    +
    volatile_op_ass_deprecated:
    +
    a volatile destination type for a compound assignment expression is +deprecated
    +
    +

    3013

    +
    volatile_func_param_deprecated:
    +
    a volatile function parameter is deprecated
    +
    +

    3014

    +
    volatile_return_type_deprecated:
    +
    a volatile return type is deprecated
    +
    +

    3015

    +
    volatile_str_bind_deprecated:
    +
    use of a volatile qualifier on a structured binding is deprecated
    +
    +

    3016

    +
    ext_vector_type_invalid_size:
    +
    the “ext_vector_type” argument must be between 1 and 2047
    +
    +

    3017

    +
    ext_vector_type_not_in_typedef:
    +
    the “ext_vector_type” attribute may appear only in a typedef
    +
    +

    3018

    +
    ext_vector_type_requires_integral_floating_type:
    +
    the “ext_vector_type” attribute applies only to integer or +floating-point types
    +
    +

    3019

    +
    feature_test_macro_ignored:
    +
    this feature-test macro is ignored (and returns 0) in the current +compilation mode
    +
    +

    3020

    +
    constexpr_multiple_union_initializers:
    +
    cannot evaluate an aggregate initializer with multiple elements for a +union
    +
    +

    3021

    +
    cmp_operator_does_not_return_bool:
    +
    entity-kind “entity” (declared at line xxxx) selected for +operator rewrite does not return type bool
    +
    +

    3022

    +
    constexpr_class_specific_new:
    +
    a new-expression calling a class-specific allocation function cannot +be constant-evaluated
    +
    +

    3023

    +
    constexpr_placement_new:
    +
    a placement new-expression cannot be constant-evaluated
    +
    +

    3024

    +
    constexpr_nonvirtual_subobject_delete:
    +
    deleting through a subobject pointer requires a virtual destructor
    +
    +

    3026

    +
    invalid_intaddr_address:
    +
    operand of __INTADDR__ must be offset from null pointer
    +
    +

    3027

    +
    ambiguous_c11_generic:
    +
    _Generic construct matches multiple types
    +
    +

    3028

    +
    ambiguous_c11_generic_previous_match:
    +
    the other match is “type”
    +
    +

    3029

    +
    availability_attribute_ignored:
    +
    the “availability” attribute used here is ignored
    +
    +

    3030

    +
    init_stmt_in_range_for_nonstandard:
    +
    C++20-style initializer statement in a range-based “for” statement is +nonstandard in this mode
    +
    +

    3031

    +
    co_await_on_non_range_based_for:
    +
    co_await can only apply to a range-based “for” statement
    +
    +

    3032

    +
    cannot_deduce_type_in_range_based_for:
    +
    cannot deduce type of range in range-based “for” statement
    +
    +

    3033

    +
    inline_variables_nonstandard:
    +
    inline variables are a C++17 feature
    +
    +

    3034

    +
    destroying_delete_wrong_type:
    +
    destroying operator delete requires “type” as first parameter
    +
    +

    3035

    +
    destroying_delete_with_extra_params:
    +
    a destroying operator delete cannot have parameters other than +std::size_t and std::align_val_t
    +
    +

    3036

    +
    cl_relaxed_abstract_checking_only_in_cplusplus:
    +
    relaxed abstract class options can be used only when compiling C++
    +
    +

    3037

    +
    invalid_start_of_requires_clause_expr:
    +
    invalid start of expression in requires clause
    +
    +

    3038

    +
    cast_in_requires_clause:
    +
    a cast expression in a requires-clause must be parenthesized
    +
    +

    3039

    +
    invalid_operator_in_requires_clause:
    +
    this operator cannot appear at the top level (without parentheses) in +a requires-clause
    +
    +

    3040

    +
    nonbool_atomic_constraint:
    +
    atomic constraint must have type bool
    +
    +

    3041

    +
    atomic_constraint_substitution_failed:
    +
    atomic constraint failed substitution
    +
    +

    3042

    +
    atomic_constraint_evaluation_failed:
    +
    atomic constraint not constant
    +
    +

    3043

    +
    atomic_constraint_false:
    +
    atomic constraint evaluates to false
    +
    +

    3044

    +
    template_constraint_not_satisfied:
    +
    template constraint not satisfied
    +
    +

    3045

    +
    bad_scope_for_concept:
    +
    concept definition cannot appear in this scope
    +
    +

    3046

    +
    invalid_concept_redecl:
    +
    invalid redeclaration of entity-kind “entity” (declared at line +xxxx)
    +
    +

    3047

    +
    concept_arg_list_substitution_failed:
    +
    substitution of arguments “<templ-args>” for concept-id failed
    +
    +

    3048

    +
    concept_failed:
    +
    concept is false for arguments “<templ-args>”
    +
    +

    3049

    +
    trailing_requires_clause_not_on_template:
    +
    a requires-clause is not allowed here (not a templated function)
    +
    +

    3051

    +
    requires_incompatible_with_previous_decl:
    +
    requires-clause incompatible with entity-kind “entity” (declared +at line xxxx)
    +
    +

    3052

    +
    expected_an_attribute:
    +
    expected an attribute
    +
    +

    3054

    +
    exp_type_name:
    +
    expected a type name
    +
    +

    3055

    +
    requires_expr_ellipsis_param:
    +
    an ellipsis parameter is not permitted in a requires-expression
    +
    +

    3056

    +
    unnamed_require_expr_param:
    +
    unnamed parameter in requires-expression has no effect
    +
    +

    3057

    +
    exp_concept_name:
    +
    expected a concept name
    +
    +

    3058

    +
    is_constant_evaluated_in_constant_expression:
    +
    call to xxxx appearing in a constant expression always produces +“true”
    +
    +

    3059

    +
    is_constant_evaluated_in_consteval_context:
    +
    call to xxxx appearing in a consteval context always produces +“true”
    +
    +

    3060

    +
    is_constant_evaluated_in_nonconstexpr_context:
    +
    call to xxxx appearing in a non-constexpr function always +produces “false”
    +
    +

    3061

    +
    type_constraint_failed:
    +
    type constraint failed for “type”
    +
    +

    3062

    +
    cl_export_template_option_incompatible_with_modules:
    +
    option “export” cannot be used in modes where C++ modules are enabled
    +
    +

    3063

    +
    glb_mod_fgmt_decl_must_come_first:
    +
    a global module fragment declaration must precede any other +declaration
    +
    +

    3064

    +
    module_decl_only_after_glb_mod:
    +
    a module declaration can only be preceded by a global module fragment
    +
    +

    3065

    +
    pvt_mod_fgmt_only_after_module:
    +
    a private module fragment must be preceded by a module declaration
    +
    +

    3066

    +
    cannot_export_fgmt:
    +
    a xxxx module fragment cannot be exported
    +
    +

    3067

    +
    more_than_one_module_decl:
    +
    cannot declare more than one module
    +
    +

    3068

    +
    more_than_one_fgmt_decl:
    +
    cannot declare more than one xxxx module fragment
    +
    +

    3069

    +
    module_req_primary_name:
    +
    a module must be declared with a non-empty name
    +
    +

    3070

    +
    header_not_importable:
    +
    “xxxx” is not an importable header
    +
    +

    3071

    +
    cannot_import_module_with_no_name:
    +
    cannot import a module with no name
    +
    +

    3072

    +
    module_cannot_depend_on_itself:
    +
    a module cannot have an interface dependency on itself
    +
    +

    3073

    +
    module_already_imported:
    +
    module “module name” has already been imported
    +
    +

    3075

    +
    module_file_not_found:
    +
    could not find module file for module “xxxx”
    +
    +

    3076

    +
    cannot_import_module:
    +
    could not import module file “xxxx”
    +
    +

    3079

    +
    unknown_ifc_partition:
    +
    unknown partition name “xxxx”
    +
    +

    3085

    +
    types_must_have_same_size:
    +
    the type of the second operand “type” must have the same size as +“type”
    +
    +

    3086

    +
    type_must_be_trivially_copyable:
    +
    type must be trivially copyable
    +
    +

    3087

    +
    unsupported_type_for_bit_cast:
    +
    type “type” is currently not supported for constexpr evaluation +of __builtin_bit_cast
    +
    +

    3088

    +
    bitfields_not_allowed:
    +
    class types with bitfields “type” are not currently supported for +constexpr evaluation of __builtin_bit_cast
    +
    +

    3089

    +
    reference_type_not_allowed:
    +
    non-static data member of reference type “type” prevents +constexpr evaluation of __builtin_bit_cast
    +
    +

    3090

    +
    volatile_type_not_allowed:
    +
    a volatile type “type” prevents constexpr evaluation of +__builtin_bit_cast
    +
    +

    3091

    +
    invalid_bit_cast_type:
    +
    a union, pointer, or pointer-to-member type “type” prevents +constexpr evaluation of __builtin_bit_cast
    +
    +

    3093

    +
    deleted_inh_def_constructor:
    +
    the sub-object construction of “type” for inheriting constructors +cannot be performed – the associated constructor is deleted
    +
    +

    3094

    +
    promise_type_returns_return_void:
    +
    entity-kind “entity” must return void
    +
    +

    3095

    +
    invalid_start_of_member_declaration:
    +
    invalid start of member declaration
    +
    +

    3096

    +
    exp_auto:
    +
    expected “auto”
    +
    +

    3097

    +
    operator_not_allowed_after_new:
    +
    this operator is not allowed at this point; parenthesize the +preceding new-expression
    +
    +

    3098

    +
    invalid_use_of_concept:
    +
    invalid use of concept
    +
    +

    3099

    +
    rvalue_defaulted_member_comparison:
    +
    a defaulted member comparison operator cannot be “&&”-qualified
    +
    +

    3100

    +
    constexpr_comparison_calls_nonconstexpr_function:
    +
    default constexpr comparison function calls non-constexpr function +entity-kind “entity” (declared at line xxxx)
    +
    +

    3101

    +
    invalid_constexpr_memcmp:
    +
    constexpr memory comparison is only supported for integer or +array-of-integer objects
    +
    +

    3102

    +
    constraint_concept_template:
    +
    a concept template cannot have associated constraints
    +
    +

    3103

    +
    export_not_allowed:
    +
    “export” is not allowed
    +
    +

    3104

    +
    export_class_members:
    +
    exporting individual class members is not allowed
    +
    +

    3105

    +
    export_must_introduce_name:
    +
    an exported declaration must introduce a name
    +
    +

    3106

    +
    export_cannot_contain_export:
    +
    an export declaration cannot contain an export declaration (previous +declaration at line xxxx)
    +
    +

    3107

    +
    export_cannot_contain_import:
    +
    an export declaration cannot contain a module import declaration
    +
    +

    3108

    +
    export_only_in_modules:
    +
    an export declaration can only appear in a module interface unit
    +
    +

    3109

    +
    export_internal_linkage:
    +
    an export declaration cannot export a name with internal linkage
    +
    +

    3112

    +
    empty_requires_expression:
    +
    a requires-expression must specify at least one requirement
    +
    +

    3113

    +
    invalid_constinit:
    +
    “constinit” is not valid here
    +
    +

    3114

    +
    constinit_variable_storage:
    +
    “constinit” is only valid for declarations of variables with static +or thread storage duration
    +
    +

    3115

    +
    constinit_variable_has_dynamic_init:
    +
    constinit variable requires dynamic initialization
    +
    +

    3116

    +
    missing_constinit:
    +
    variable was previously declared with “constinit” at line xxxx
    +
    +

    3117

    +
    use_of_non_prototype_func_declarator:
    +
    use of non-prototype function declarator
    +
    +

    3118

    +
    cannot_be_const_qualified:
    +
    argument cannot have a const-qualified type
    +
    +

    3119

    +
    ptr_to_mem_of_incomplete_class:
    +
    a pointer-to-member of an incomplete type “type” is not allowed
    +
    +

    3120

    +
    pack_init_capture_not_enabled:
    +
    pack expansion in init-capture not enabled in this mode
    +
    +

    3121

    +
    pack_init_capture_is_cpp20:
    +
    pack expansion in init-capture is a C++20 feature
    +
    +

    3122

    +
    comparison_defaulted_in_class_must_be_first_decl:
    +
    a comparison operator defaulted in a class definition must be the +first declaration of that comparison operator (entity-kind +“entity” (declared at line xxxx))
    +
    +

    3123

    +
    pack_init_capture_in_non_variadic_context:
    +
    a pack expansion in an init-capture can be used only in a variadic +template
    +
    +

    3124

    +
    type_constraint_requires_type_concept:
    +
    type constraint uses entity-kind “entity” (declared at line +xxxx) that is not a type concept (i.e., a concept template whose +first parameter is a type parameter)
    +
    +

    3125

    +
    placeholder_type_failed_constraint:
    +
    the deduced placeholder type “type” failed the type constraint
    +
    +

    3126

    +
    ineligible_default_constructor:
    +
    default constructor for “type” is not eligible
    +
    +

    3127

    +
    ambiguous_destructor_constraints:
    +
    destructor for “type” is ambiguous because of unordered +constraints
    +
    +

    3128

    +
    failed_destructor_constraints:
    +
    destructor for “type” is ineligible because of failed constraints
    +
    +

    3129

    +
    destructor_position:
    +
    ambiguous destructor candidate
    +
    +

    3130

    +
    trailing_requires_on_virtual_func:
    +
    a virtual function cannot have a trailing requires clause
    +
    +

    3131

    +
    function_ineligible:
    +
    entity-kind “entity” (declared at line xxxx) does not satisfy +its constraints
    +
    +

    3132

    +
    bad_decltype_qualifier:
    +
    result of decltype qualifier “type” is not a class or enumeration
    +
    +

    3133

    +
    cpp20_reversed_comparison_ambiguity:
    +
    comparison is ambiguous in standard C++20 because the implied +comparison operator with reversed parameters is an equally good match +– this is usually caused by a missing “const” qualifier on the +comparison operator; see “entity” (declared at line xxxx)
    +
    +

    3134

    +
    invalid_concept_id:
    +
    invalid concept-id
    +
    +

    3135

    +
    requires_clause_arg_list_substitution_failed:
    +
    substitution of arguments “<templ-args>” for requires-clause +failed
    +
    +

    3136

    +
    ineligible_member_function:
    +
    constraints for entity-kind “entity” (declared at line xxxx) +are not satisfied
    +
    +

    3137

    +
    var_with_virtual_bases_in_constexpr_function:
    +
    variable type “type” in constexpr function has virtual base +classes
    +
    +

    3138

    +
    constexpr_object_with_virtual_base:
    +
    a constant expression cannot allocate a virtual base subobject (for +type “type”)
    +
    +

    3139

    +
    template_parameter_has_nonstructural_class_type:
    +
    a template parameter of class type must be of structural class type
    +
    +

    3140

    +
    utf8_lit_no_ulit:
    +
    support for UTF-8 literals requires u-literal support.
    +
    +

    3141

    +
    duplicate_module_map:
    +
    module file mapping for “xxxx“ specified more than once
    +
    +

    3142

    +
    duplicate_header_unit_map:
    +
    header unit mapping for “xxxx“ specified more than once
    +
    +

    3143

    +
    missing_header_unit_map:
    +
    no mapping specified for “xxxx“
    +
    +

    3145

    +
    cannot_find_header_for_import:
    +
    cannot find header “xxxx“ to import
    +
    +

    3146

    +
    multiple_module_matches:
    +
    more than one file in the module file list matches “xxxx“
    +
    +

    3147

    +
    module_file_mismatch:
    +
    module file found for “xxxx“ is for a different module
    +
    +

    3149

    +
    module_read_error:
    +
    unable to read module file
    +
    +

    3150

    +
    builtin_needs_char8_t:
    +
    builtin function is not available because the char8_t type is not +supported with the current options
    +
    +

    3152

    +
    nonstandard_use_of_explicit_default_constructor:
    +
    nonstandard use of explicit constructor “entity” (declared at +line xxxx) for default aggregate element initialization
    +
    +

    3153

    +
    constexpr_memcpy_operand_not_object:
    +
    source or destination of memcpy-like intrinsic does not point to an +object
    +
    +

    3154

    +
    constexpr_memcpy_distinct_types:
    +
    memcpy-like intrinsic attempts to copy representationally-distinct +types “type” and “type”
    +
    +

    3155

    +
    constexpr_memcpy_nontrivial_type:
    +
    memcpy-like intrinsic attempts to copy nontrivially-copyable type +“type”
    +
    +

    3156

    +
    constexpr_memcpy_partial_object:
    +
    memcpy-like intrinsic attempts to copy partial object
    +
    +

    3157

    +
    constexpr_memcpy_overflow:
    +
    memcpy-like intrinsic attempts to copy past array boundary
    +
    +

    3158

    +
    constexpr_memcpy_overlap:
    +
    memcpy-like intrinsic attempts to copy overlapping byte ranges (using +corresponding memmove operation instead)
    +
    +

    3159

    +
    nondefining_friend_requires_clause:
    +
    a friend declaration with a trailing-requires-clause must be a +definition
    +
    +

    3160

    +
    type_not_scalar:
    +
    expression must have arithmetic or pointer type but has type +“type”
    +
    +

    3161

    +
    type_not_arithmetic_or_enum_or_pointer:
    +
    expression must have arithmetic, enum, or pointer type but has type +“type”
    +
    +

    3162

    +
    type_not_arithmetic_or_unscoped_enum_or_pointer:
    +
    expression must have arithmetic, unscoped enum, or pointer type but +has type “type”
    +
    +

    3163

    +
    type_not_pointer:
    +
    expression must have pointer type but it has type “type”
    +
    +

    3164

    +
    member_access_requires_pointer:
    +
    operator -> or ->* applied to “type” instead of to a pointer type
    +
    +

    3166

    +
    cannot_interpret_target_bits:
    +
    cannot interpret bit layout for this compilation target
    +
    +

    3167

    +
    ifc_no_corresponding_operator:
    +
    no corresponding operator for IFC operator “xxxx”
    +
    +

    3168

    +
    ifc_no_corresponding_calling_conv:
    +
    no corresponding calling convention for IFC calling convention +“xxxx”
    +
    +

    3169

    +
    module_file_contains_unsupported_constructs:
    +
    module “module name” contains unsupported constructs
    +
    +

    3170

    +
    unhandled_ifc_construct:
    +
    unsupported IFC construct: “xxxx”
    +
    +

    3171

    +
    is_signed_no_longer_a_keyword:
    +
    __is_signed is no longer a keyword from this point
    +
    +

    3172

    +
    dim_not_const_unsigned_int:
    +
    an array dimension must have a constant unsigned integer value
    +
    +

    3174

    +
    modules_not_enabled:
    +
    modules are not enabled in this mode
    +
    +

    3175

    +
    import_name_not_allowed:
    +
    “import” is not allowed in a module name
    +
    +

    3176

    +
    module_name_not_allowed:
    +
    “module” is not allowed in a module name
    +
    +

    3179

    +
    not_an_enum_type:
    +
    entity-kind “entity” is not an enum type
    +
    +

    3180

    +
    using_enum_conflicts:
    +
    enumerator “entity” conflicts with entity-kind “entity”
    +
    +

    3181

    +
    using_enum_redecl:
    +
    enumerator “entity” has already been declared in this scope at +line xxxx
    +
    +

    3182

    +
    empty_throw_specification_not_cpp20:
    +
    the “throw()” specification is not part of C++20 and later
    +
    +

    3183

    +
    multiple_header_map_matches:
    +
    more than entry in the header unit map matches “xxxx“
    +
    +

    3184

    +
    exp_push_pop:
    +
    #pragma diagnostic must have either ‘push’ or ‘pop’ argument
    +
    +

    3185

    +
    no_corresponding_push:
    +
    no ‘#pragma diagnostic push’ was found to match this ‘diagnostic pop’
    +
    +

    3186

    +
    macro_in_pp_directive:
    +
    “xxxx” cannot be a macro when used in an import or module +directive
    +
    +

    3187

    +
    not_global_namespace:
    +
    this directive can only appear in the global namespace scope
    +
    +

    3188

    +
    export_not_at_namespace_scope:
    +
    an “export” declaration can appear only at global or namespace scope
    +
    +

    3189

    +
    identifier_not_keyword:
    +
    “xxxx” is parsed as an identifier rather than a keyword because +the tokens that follow it do not match those of a preprocessor +directive
    +
    +

    3190

    +
    apparent_module_pp_directive:
    +
    this appears to be the start of a preprocessor directive, but the +lack of a ‘;’ followed immediately by a newline prevents that
    +
    +

    3191

    +
    module_directive_in_macro:
    +
    this appears to be a modules preprocessing directive, but such +directives cannot appear within a macro expansion
    +
    +

    3192

    +
    module_directive_in_if:
    +
    a “module” directive cannot appear within the scope of conditional +inclusion (e.g., #if, #else, #elseif, etc.)
    +
    +

    3193

    +
    import_skipped:
    +
    the import of “xxxx” has been skipped
    +
    +

    3194

    +
    bad_gro_on_alloc_fail:
    +
    promise type “type” must declare +get_return_object_on_allocation_failure as a static member function +requiring no arguments
    +
    +

    3195

    +
    expl_spec_alias_template:
    +
    an alias template cannot be explicitly specialized
    +
    +

    3196

    +
    matching_lbrace:
    +
    to match this “{”
    +
    +

    3197

    +
    macro_invocation:
    +
    in this macro invocation
    +
    +

    3198

    +
    call_with_unusable_argument_conversion:
    +
    call requires an ambiguous argument conversion
    +
    +

    3199

    +
    named_module_source_conflict:
    +
    declaration owned by module xxxx conflicts with entity-kind +“entity” (declared at line xxxx)
    +
    +

    3200

    +
    global_module_source_conflict:
    +
    declaration owned by global module conflicts with entity-kind +“entity” (declared at line xxxx) owned by a named module
    +
    +

    3201

    +
    bad_malloc_attribute:
    +
    the first argument to a “malloc” attribute must be a function
    +
    +

    3202

    +
    cannot_capture_var:
    +
    cannot capture “entity” (declared at line xxxx)
    +
    +

    3203

    +
    cannot_capture_this:
    +
    cannot capture “this”
    +
    +

    3204

    +
    already_in_consteval_context:
    +
    already in consteval context
    +
    +

    3205

    +
    if_consteval_requires_braced_dependent_statement:
    +
    “if consteval” and “if not consteval” require braced dependent +statements
    +
    +

    3206

    +
    if_consteval_in_nonconstexpr_function:
    +
    “if consteval” and “if not consteval” are meaningless in a +non-constexpr function
    +
    +

    3207

    +
    branch_into_if_consteval:
    +
    transfer of control into an “if consteval” or “if not consteval” +statement is not allowed
    +
    +

    3208

    +
    constexpr_local_static:
    +
    constant-evaluation cannot go through the declaration of a variable +with static or thread storage duration
    +
    +

    3209

    +
    mutable_qualifier_on_explicit_this_lambda:
    +
    the mutable qualifier is not allowed on a lambda with an explicit +“this” parameter
    +
    +

    3210

    +
    static_with_explicit_this:
    +
    a member function declared with “static” cannot have an explicit +“this” parameter
    +
    +

    3211

    +
    explicit_this_param_must_be_first:
    +
    an explicit “this” parameter must be the first declared parameter
    +
    +

    3212

    +
    bad_this:
    +
    “this” is not allowed here
    +
    +

    3214

    +
    explicit_this_needs_this:
    +
    an explicit “this” function requires a selector operand
    +
    +

    3215

    +
    if_consteval_nonstandard:
    +
    “if consteval” and “if not consteval” are not standard in this mode
    +
    +

    3216

    +
    lambda_without_parameters_nonstandard:
    +
    omitting “()” in a lambda declarator is nonstandard in this mode
    +
    +

    3217

    +
    lambda_without_parameters_requires_clause:
    +
    a trailing-requires-clause is not permitted when the lambda parameter +list is omitted
    +
    +

    3218

    +
    invalid_ifc_partition:
    +
    module “module name” invalid partition requested
    +
    +

    3219

    +
    undefined_ifc_partition:
    +
    module “module name” undefined partition (believed to be +“xxxx”) requested
    +
    +

    3222

    +
    invalid_overflowing_ifc_position:
    +
    module “module name” file position n (relative position +n) requested for partition “xxxx” - which overflows the end +of its partition
    +
    +

    3223

    +
    invalid_misaligned_ifc_position:
    +
    module “module name” file position n (relative position +n) requested for partition “xxxx” - which is misaligned with +its partitions elements
    +
    +

    3224

    +
    invalid_ifc_position_backtrace_field:
    +
    from subfield “xxxx” (relative position to node n)
    +
    +

    3225

    +
    invalid_ifc_position_backtrace_pos:
    +
    from partition “xxxx” element n (file position n, +relative position n)
    +
    +

    3226

    +
    nonstandard_lambda_attributes:
    +
    attributes on lambdas are a C++23 feature
    +
    +

    3227

    +
    confusable_identifier:
    +
    identifier “xxxx” could be confused with a visually-similar one +appearing at line xxxx
    +
    +

    3228

    +
    suspicious_comment_formatting:
    +
    this comment contains suspicious Unicode formatting control characters
    +
    +

    3229

    +
    suspicious_string_formatting:
    +
    this string contains Unicode formatting control characters that could +result in unexpected runtime behavior
    +
    +

    3230

    +
    suppressed_module_warning_diag:
    +
    n suppressed warning was encountered while processing module +“module name”
    +
    +

    3231

    +
    suppressed_module_warnings_diag:
    +
    n suppressed warnings were encountered while processing module +“module name”
    +
    +

    3232

    +
    suppressed_module_error_diag:
    +
    n suppressed error was encountered while processing module +“module name”
    +
    +

    3233

    +
    suppressed_module_errors_diag:
    +
    n suppressed errors were encountered while processing module +“module name”
    +
    +

    3236

    +
    virtual_with_explicit_this:
    +
    a virtual member function cannot have an explicit “this” parameter
    +
    +

    3237

    +
    address_of_unqualified_explicit_this_function:
    +
    taking the address of an explicit “this” function requires a +qualified name
    +
    +

    3238

    +
    implicit_address_of_explicit_this_function:
    +
    forming the address of an explicit “this” function requires the “&” +operator
    +
    +

    3239

    +
    string_literal_cannot_initialize_flexible_array_member:
    +
    a string literal cannot be used to initialize a flexible array member
    +
    +

    3246

    +
    ifc_missing_function_definition:
    +
    the IFC representation of the definition of function “xxxx” is +missing
    +
    +

    3247

    +
    member_function_modifier_on_template:
    +
    function modifier does not apply to member template declaration
    +
    +

    3248

    +
    constexpr_too_many_nested_anonymous_types:
    +
    member selection involves too many nested anonymous types
    +
    +

    3249

    +
    no_common_type:
    +
    there is no common type between the operands
    +
    +

    3250

    +
    exp_pointer_to_member:
    +
    expected a pointer-to-member
    +
    +

    3251

    +
    lone_flexible_array_member:
    +
    a flexible array member cannot be declared in an otherwise-empty type
    +
    +

    3252

    +
    missing_gnu_srcloc_type:
    +
    expected “std::source_location::__impl” to be defined to a class +with only the data members “_M_function_name”, “_M_file_name”, +“_M_column”, “_M_line”
    +
    +

    3253

    +
    srcloc_column_bounds:
    +
    given column number is too large for “std::source_location” +implementation
    +
    +

    3254

    +
    srcloc_line_bounds:
    +
    given line number is too large for “std::source_location” +implementation
    +
    +

    3255

    +
    utf16_char_lit_too_long:
    +
    a UTF-16 character constant cannot occupy more than one code unit; +value truncated
    +
    +

    3256

    +
    both_arguments_must_have_same_type:
    +
    both arguments must have the same type
    +
    +

    3257

    +
    invalid_type_for_builtin:
    +
    type “type” is invalid as an argument for this builtin
    +
    +

    3258

    +
    constexpr_called_from_rout:
    +
    called from entity-kind “entity” (declared at line xxxx):
    +
    +

    3259

    +
    qualified_unnamed_bit_field_type:
    +
    a qualified type is nonstandard for anonymous bit fields
    +
    +

    3260

    +
    bad_vector_conditional_size:
    +
    the element type of the vector condition (“type”) must have the +same size as the element type of the result (“type”)
    +
    +

    3261

    +
    bad_vector_float_operand_size:
    +
    the floating-point vector operand type (“type”) has no matching +integer vector type
    +
    +

    3262

    +
    mangling_for_requires:
    +
    mangling for “requires” expressions is not yet implemented
    +
    +

    3263

    +
    unavailable_attr:
    +
    because of an “unavailable” attribute
    +
    +

    3264

    +
    duplicate_asm_qualifier:
    +
    duplicate ‘asm’ qualifier
    +
    +

    3265

    +
    incomplete_enum_bit_field_or_bad_opaque_enum:
    +
    either a bit field with an incomplete enum type or an opaque +enumeration with an invalid base type
    +
    +

    3266

    +
    ifc_partition_mismatch:
    +
    attempted to construct an element from IFC partition “xxxx” using +an index into IFC partition “xxxx”
    +
    +

    3267

    +
    ifc_partition_bad_entry_size:
    +
    the partition “xxxx” specified its entry size as n when nwas expected
    +
    +

    3268

    +
    ifc_requirement_failure:
    +
    an unexpected IFC requirement was encountered while processing +module “module name”
    +
    +

    3269

    +
    ifc_requirement_failure_fill_in:
    +
    condition failed at line n in xxxx: “xxxx”
    +
    +

    3270

    +
    circular_constraint:
    +
    atomic constraint depends on itself
    +
    +

    3271

    +
    noreturn_with_return_type:
    +
    “noreturn” function has non-void return type
    +
    +

    3272

    +
    ifc_bad_function_param_name:
    +
    a correction has been made by dropping the parameter “xxxx” (at +relative index n)
    +
    +

    3273

    +
    default_arg_on_member_template_def:
    +
    a default template argument cannot be specified on the definition of +a member template outside its class
    +
    +

    3274

    +
    ifc_bad_identifier:
    +
    invalid IFC identifier name “xxxx” encountered during entity +reconstruction
    +
    +

    3276

    +
    invalid_ifc_sort_value:
    +
    module “module name” invalid sort value
    +
    +

    3277

    +
    ifc_function_template_parse_failure:
    +
    a function template loaded from an IFC module was incorrectly parsed +as entity-kind “entity” (declared at line xxxx)
    +
    +

    3278

    +
    ifc_entity_ref_failure:
    +
    failed to load an IFC entity reference in module “module name”
    +
    +

    3279

    +
    ifc_entity_ref_failure_info:
    +
    from partition “xxxx” element n (file position n, +relative position n)
    +
    +

    3280

    +
    no_chained_designators_with_destructor:
    +
    chained designators are not permitted for a class type with a +nontrivial destructor
    +
    +

    3281

    +
    explicit_specialization_friend:
    +
    an explicit specialization declaration may not be a friend declaration
    +
    +

    3282

    +
    std_float128_not_supported:
    +
    the std::float128_t type is not supported; std::float64_t will be +used instead
    +
    +

    3284

    +
    alias_template_deduction_guide:
    +
    a deduction guide may not be declared for alias template “entity”
    +
    +

    3285

    +
    unavailable_entity:
    +
    entity-kind “entity” was declared declared unavailable
    +
    +

    3286

    +
    unavailable_entity_with_custom_message:
    +
    entity-kind “entity” was declared unavailable (“xxxx”)
    +
    +

    3287

    +
    deprecated_attr:
    +
    because of a “deprecated” attribute
    +
    +

    3288

    +
    explicit_lambda_template_parameters_is_cpp20:
    +
    explicit lambda template parameters are a C++20 feature
    +
    +

    3289

    +
    c23_noreturn_deprecated:
    +
    the use of “_Noreturn” has been obsoleted in C23; use “[[noreturn]]” +instead
    +
    +

    3290

    +
    c23_alignof_deprecated:
    +
    the use of “_Alignof” has been obsoleted in C23; use “alignof” instead
    +
    +

    3291

    +
    c23_alignas_deprecated:
    +
    the use of “_Alignas” has been obsoleted in C23; use “alignas” instead
    +
    +

    3292

    +
    c23_bool_deprecated:
    +
    the use of “_Bool” has been obsoleted in C23; use “bool” instead
    +
    +

    3293

    +
    c23_static_assert_deprecated:
    +
    the use of “_Static_assert” has been obsoleted in C23; use +“static_assert” instead
    +
    +

    3294

    +
    c23_thread_local_deprecated:
    +
    the use of “_Thread_local” has been obsoleted in C23; use +“thread_local” instead
    +
    +

    3295

    +
    ms_ifc_unavailable:
    +
    Microsoft mode must be enabled to use the module file “xxxx” (a +Microsoft Visual Studio IFC module)
    +
    +

    3296

    +
    file_for_module_not_found:
    +
    could not open module file “xxxx”
    +
    +

    3297

    +
    found_from_module_map:
    +
    found in the module map for module “xxxx”
    +
    +

    3298

    +
    found_from_header_unit_map:
    +
    found in the header unit map for “xxxx”
    +
    +

    3299

    +
    cl_invalid_output_mode:
    +
    unrecognized output mode (must be one of text, sarif): xxxx
    +
    +

    3300

    +
    cl_c23_typeof_option_only_in_C:
    +
    option “c23_typeof” can be used only when compiling C
    +
    +

    3301

    +
    cl_invalid_clang_version:
    +
    invalid clang version number: xxxx
    +
    +

    3305

    +
    constexpr_flexible_array_initializer:
    +
    cannot evaluate an initializer for a flexible array member
    +
    +

    3306

    +
    nonstandard_bit_field_initializer:
    +
    a default bit-field initializer is a C++20 feature
    +
    +

    3307

    +
    ifc_too_many_template_args:
    +
    too many arguments in template argument list in module “module +name”
    +
    +

    3308

    +
    ifc_too_many_template_args_info:
    +
    detected for the template argument represented by “xxxx” element +n (file position n, relative position n)
    +
    +

    3309

    +
    ifc_too_few_template_args:
    +
    too few arguments in template argument list in module “module +name”
    +
    +

    3310

    +
    ifc_too_few_template_args_info:
    +
    detected while processing the template argument list represented by +“xxxx” element n (file position n, relative position +n)
    +
    +

    3311

    +
    nonstandard_conversion_from_scoped_enum:
    +
    conversion from scoped enumeration type “type” is nonstandard
    +
    +

    3312

    +
    constexpr_allocation_mismatch:
    +
    deallocation does not match allocation kind (one is for an array and +the other not)
    +
    +

    3313

    +
    constexpr_address_unknown:
    +
    comparison involves unknown address (e.g., the address of a weak +variable)
    +
    +

    3314

    +
    bad_argument_to_make_signed:
    +
    __make_signed is only compatible with non-bool integer and enum types
    +
    +

    3315

    +
    bad_argument_to_make_unsigned:
    +
    __make_unsigned is only compatible with non-bool integer and enum +types
    +
    +

    3316

    +
    intrinsic_name_released:
    +
    the intrinsic name “xxxx” will be treated as an ordinary +identifier from here
    +
    +

    3317

    +
    array_subobject_not_initialized:
    +
    access to uninitialized subobject at index n
    +
    +

    3318

    +
    ifc_line_number_overflow:
    +
    IFC line number (n) overflows maximum allowed value (n) +module “module name”
    +
    +

    3319

    +
    invalid_unrepresentable_ifc_position:
    +
    module “module name” requested element n of partition +“xxxx”, this file position exceeds the maximum representable value
    +
    +

    3320

    +
    wrong_number_of_arguments:
    +
    wrong number of arguments
    +
    +

    3321

    +
    candidate_failed_constraint:
    +
    constraint on candidate entity-kind “entity” not satisfied
    +
    +

    3322

    +
    candidate_wrong_param_count:
    +
    number of parameters of entity-kind “entity” does not match the +call
    +
    +

    3323

    +
    candidate_expl_templ_arg_subst_failed:
    +
    substituting explicit template arguments “<templ-args>” for +entity-kind “entity” failed
    +
    +

    3324

    +
    impl_deleted_move_candidate_ignored:
    +
    entity-kind “entity” is an implicitly “= delete” move function +and thus ignored during overload resolution
    +
    +

    3325

    +
    arg_for_empty_param_pack:
    +
    entity-kind “entity” does not match because argument #*n* is +provided for an empty parameter pack
    +
    +

    3326

    +
    nonviable_because_arg_mismatch:
    +
    entity-kind “entity” does not match because argument #*n* does +not match parameter
    +
    +

    3327

    +
    deduction_failed:
    +
    candidate entity-kind “entity” failed deduction
    +
    +

    3328

    +
    builtin_operator_nonviable_because_arg_mismatch:
    +
    built-in operator*xxxx* does not match because argument #*n* does +not match parameter
    +
    +

    3329

    +
    integral_operand:
    +
    <integral>
    +
    +

    3330

    +
    promoted_integral_operand:
    +
    <promoted integral>
    +
    +

    3331

    +
    ptrdiff_t_operand:
    +
    <ptrdiff_t>
    +
    +

    3332

    +
    enum_operand:
    +
    <enum>
    +
    +

    3333

    +
    scoped_enum_operand:
    +
    <scoped enum>
    +
    +

    3334

    +
    arith_operand:
    +
    <arithmetic>
    +
    +

    3335

    +
    promoted_arith_operand:
    +
    <promoted arithmetic>
    +
    +

    3336

    +
    nonbool_arith_operand:
    +
    <non-bool arithmetic>
    +
    +

    3337

    +
    pointer_operand:
    +
    <pointer>
    +
    +

    3338

    +
    nullptr_operand:
    +
    <nullptr>
    +
    +

    3339

    +
    handle_operand:
    +
    <handle>
    +
    +

    3340

    +
    handle_to_cli_array_operand:
    +
    <handle to CLI array>
    +
    +

    3341

    +
    pointer_to_object_operand:
    +
    <pointer to object>
    +
    +

    3342

    +
    pointer_to_function_operand:
    +
    <pointer to function>
    +
    +

    3343

    +
    ptr_to_member_operand:
    +
    <pointer-to-member>
    +
    +

    3344

    +
    bool_operand:
    +
    <bool>
    +
    +

    3345

    +
    bool_equivalent_operand:
    +
    <bool-like>
    +
    +

    3346

    +
    class_operand:
    +
    <class>
    +
    +

    3347

    +
    auto_cast_is_cpp23:
    +
    auto(<expr>) and auto{<expr>} are a C++23 feature
    +
    +

    3348

    +
    anon_union_using_declaration:
    +
    invalid anonymous union – using declaration is not allowed
    +
    +

    3349

    +
    ifc_file_incompatibility:
    +
    IFC file “xxxx” cannot be processed
    +
    +

    3350

    +
    unsupported_ifc_file_version_info:
    +
    IFC version n.*n* is not supported
    +
    +

    3351

    +
    unsupported_ifc_file_arch_info:
    +
    IFC architecture “xxxx” is incompatible with the current target +architecture
    +
    +

    3352

    +
    unknown_ifc_partition_conversion:
    +
    module “module name” requests index n of an unsupported +partition corresponding to “xxxx”
    +
    +

    3353

    +
    param_cannot_be_completed:
    +
    parameter number n of entity-kind “entity” has type +“type” which cannot be completed
    +
    +

    3354

    +
    param_is_incomplete:
    +
    parameter number n of entity-kind “entity” has incomplete +type “type”
    +
    +

    3355

    +
    param_is_abstract:
    +
    parameter number n of entity-kind “entity” has abstract type +“type”
    +
    +

    3356

    +
    struct_bindings_is_cpp17:
    +
    structured bindings are a C++17 feature
    +
    +

    3357

    +
    capturing_struct_bindings_is_cpp20:
    +
    capturing structured bindings is a C++20 feature
    +
    +

    3358

    +
    bad_splicer_operand:
    +
    operand of splicer has type “type” instead of std::meta::info
    +
    +

    3359

    +
    not_a_type_reflection:
    +
    operand (reflection for reflection-description) is not the +reflection of a type
    +
    +

    3360

    +
    nonconstant_splicer_operand:
    +
    nonconstant operand of splicer
    +
    +

    3361

    +
    bad_std_string_view:
    +
    use of “type” instead of std::string_view (= +std::basic_string_view<char>)
    +
    +

    3362

    +
    inconsistent_std_string_view:
    +
    std::string_view used here is inconsistent with use in other +intrinsics
    +
    +

    3363

    +
    invalid_std_string_view_for_reflection:
    +
    definition of std::string_view does not match assumptions of +reflection (no base classes and data members for pointer and length)
    +
    +

    3364

    +
    constexpr_reflection_not_of_constant:
    +
    reflection is not that of a constant value
    +
    +

    3368

    +
    bad_reflection_kind_for_expression_splice:
    +
    bad reflection (reflection-description) for expression splice
    +
    +

    3369

    +
    already_defined_with_pos:
    +
    entity-kind “entity” has already been defined (previous +definition at line xxxx)
    +
    +

    3371

    +
    incompatible_std_meta_value_of_type:
    +
    extract of type “type” is not compatible with the given +reflection (entity with type “type”)
    +
    +

    3372

    +
    reflection_of_overloaded_set:
    +
    reflecting an overload set is not currently permitted
    +
    +

    3373

    +
    intrinsic_requires_template_instance:
    +
    this intrinsic requires a reflection for a template instance
    +
    +

    3374

    +
    invalid_reflection_equality:
    +
    incompatible types “type” and “type” for operator
    +
    +

    3375

    +
    invalid_reflection_for_intrinsic:
    +
    invalid reflection for intrinsic metafunction
    +
    +

    3376

    +
    nonmember_reflection_for_intrinsic:
    +
    intrinsic metafunction requires a reflection for a class member
    +
    +

    3377

    +
    union_base:
    +
    a class cannot not derive from a union
    +
    +

    3378

    +
    base_with_flexible_array:
    +
    cannot derive from a class with a flexible array member
    +
    +

    3379

    +
    null_reflection:
    +
    null reflection
    +
    +

    3380

    +
    namespace_alias:
    +
    namespace alias
    +
    +

    3381

    +
    unspecified_reflection:
    +
    reflection (details unavailable)
    +
    +

    3382

    +
    std_meta_substitute_bad_arg_reflection:
    +
    bad reflection (reflection-description) for template argument in +std::meta::substitute
    +
    +

    3383

    +
    std_meta_substitute_failed:
    +
    call to std::meta::substitute (for reflection-description) failed
    +
    +

    3384

    +
    expired_reflection_value:
    +
    reflection value refers to inactive entity
    +
    +

    3385

    +
    cannot_splice_general_expression:
    +
    an expression splice must splice a constant value, a variable, or a +function
    +
    +

    3386

    +
    cannot_splice_member_access:
    +
    a member access splice must splice a data member or a member function
    +
    +

    3387

    +
    splice_is_not_a_member_of_class:
    +
    member entity-kind “entity” (declared at line xxxx) is not a +direct or indirect member of “type”
    +
    +

    3388

    +
    unicode_name_not_found:
    +
    the name “xxxx” does not designate a known Unicode character
    +
    +

    3389

    +
    unterminated_unicode_name:
    +
    unterminated named Unicode character escape
    +
    +

    3390

    +
    invalid_char_in_unicode_name:
    +
    character cannot appear in a Unicode name
    +
    +

    3391

    +
    empty_unicode_name:
    +
    empty named Unicode character escape
    +
    +

    3392

    +
    exp_lsplice:
    +
    expected a “[:”
    +
    +

    3393

    +
    exp_rsplice:
    +
    expected a “:]”
    +
    +

    3394

    +
    lambda_mutable_and_static:
    +
    a lambda expression cannot be both “mutable” and “static”
    +
    +

    3395

    +
    static_lambda_nonstandard:
    +
    a “static” lambda expression is nonstandard
    +
    +

    3396

    +
    static_lambda_with_capture:
    +
    a “static” lambda expression must have an empty capture specification
    +
    +

    3399

    +
    ifc_creation_failure:
    +
    an IFC file could not be produced for the current translation unit
    +
    +

    3400

    +
    unsupported_il_to_ifc:
    +
    one or more entities cannot currently be written to an IFC file
    +
    +

    3401

    +
    nonstandard_explicit_bool:
    +
    ‘explicit(bool)’ is a C++20 feature
    +
    +

    3402

    +
    bad_type_for_atomic_fetch:
    +
    first argument must be a pointer to integer, enum, or supported +floating-point type
    +
    +

    3403

    +
    module_use_in_multi_tu_mode:
    +
    C++ modules cannot be used when compiling multiple translation units
    +
    +

    3404

    +
    module_use_with_export_template:
    +
    C++ modules cannot be used with the pre-C++11 “export” feature
    +
    +

    3405

    +
    ifc_unsupported_token:
    +
    the IFC token “xxxx” is not supported
    +
    +

    3406

    +
    pass_object_size_not_in_function_decl:
    +
    the “pass_object_size” attribute is only valid on parameters of +function declarations
    +
    +

    3407

    +
    attr_arg_out_of_small_integer_range:
    +
    the argument of the “xxxx” attribute n must be a value +between 0 and n
    +
    +

    3408

    +
    ref_qualifier_ignored:
    +
    a ref-qualifier here is ignored
    +
    +

    3409

    +
    invalid_neon_vector_element_type:
    +
    invalid NEON vector element type “type”
    +
    +

    3410

    +
    invalid_neon_polyvector_element_type:
    +
    invalid NEON polyvector element type “type”
    +
    +

    3411

    +
    invalid_scalable_vector_element_type:
    +
    invalid scalable vector element type “type”
    +
    +

    3412

    +
    invalid_scalable_vector_tuple_elements:
    +
    invalid number of tuple elements for scalable vector type
    +
    +

    3413

    +
    invalid_neon_vector_size:
    +
    a NEON vector or polyvector must be either 64 or 128 bits wide
    +
    +

    3414

    +
    sizeless_type_not_allowed:
    +
    sizeless type “type” is not allowed
    +
    +

    3415

    +
    value_init_of_sizeless_type:
    +
    an object of the sizeless type “type” cannot be value-initialized
    +
    +

    3416

    +
    ifc_unexpected_null_scope_member:
    +
    unexpected null declaration index found as part of scope n
    +
    +

    3417

    +
    cl_unnamed_module_map:
    +
    a module name must be specified for the module file map referencing +the file “xxxx”
    +
    +

    3418

    +
    ifc_partition_missing_element:
    +
    a null index value was received where a node in the IFC partition +“xxxx” was expected
    +
    +

    3419

    +
    void_template_variable:
    +
    entity-kind “entity” (declared at line xxxx) cannot have type +“type”
    +
    +

    3420

    +
    ref_qualifier_nonstandard:
    +
    a ref-qualifier is nonstandard in this mode
    +
    +

    3421

    +
    range_based_for_nonstandard:
    +
    a range-based “for” statement is nonstandard in this mode
    +
    +

    3422

    +
    auto_type_nonstandard:
    +
    “auto” as a type specifier is nonstandard in this mode
    +
    +

    3423

    +
    cannot_import_module_bad_checksum:
    +
    could not import module file “xxxx” due to file corruption
    +
    +

    3425

    +
    extraneous_injected_member_tokens:
    +
    extraneous tokens injected after member declaration
    +
    +

    3426

    +
    bad_injection_scope:
    +
    bad injection scope (reflection-description)
    +
    +

    3427

    +
    expected_string_view_value:
    +
    expected a value of type std::string_view but got “type”
    +
    +

    3428

    +
    extraneous_injected_statement_tokens:
    +
    extraneous tokens injected after statement
    +
    +

    3429

    +
    extraneous_injected_declaration_tokens:
    +
    extraneous tokens injected after declaration
    +
    +

    3430

    +
    tuple_index_overflow:
    +
    tuple index value (n) overflow
    +
    +

    3431

    +
    constexpr_begin_report_tokens:
    +
    >> output from std::meta::__report_tokens
    +
    +

    3432

    +
    constexpr_end_report_tokens:
    +
    >> end output from std::meta::__report_tokens
    +
    +

    3433

    +
    constexpr_no_current_parameters:
    +
    not in a context with parameter variables
    +
    +

    3434

    +
    empty_delimited_escape:
    +
    a delimited escape sequence must have at least one character
    +
    +

    3435

    +
    unterminated_delimited_escape:
    +
    unterminated delimited escape sequence
    +
    +

    3436

    +
    constant_addresses_local_variable:
    +
    constant contains address of a local variable
    +
    +

    3437

    +
    struct_binding_consteval:
    +
    a structured binding cannot be declared “consteval”
    +
    +

    3438

    +
    module_import_conflict:
    +
    “entity” conflicts with the imported declaration entity-kind +“entity” (declared at line xxxx)
    +
    +

    3439

    +
    char_too_wide_for_rep:
    +
    character cannot be represented in the specified character type
    +
    +

    3440

    +
    annotation_after_using:
    +
    an annotation cannot appear in the context of a “using” attribute +prefix
    +
    +

    3441

    +
    annotation_must_have_literal_type:
    +
    type “type” of annotation is not a literal type
    +
    +

    3442

    +
    ext_vector_type_requires_bool_integral_floating_type:
    +
    the “ext_vector_type” attribute applies only to bool, integer, or +floating-point types
    +
    +

    3443

    +
    multiple_union_designators:
    +
    multiple designators into the same union are not permitted
    +
    +

    3444

    +
    debug_show_location:
    +
    test message
    +
    +

    3445

    +
    microsoft_version_doesnt_support_cpp23_mode:
    +
    the version of Microsoft being emulated must be at least 1943 to use +“–ms_c++23”
    +
    +

    3446

    +
    cl_invalid_cwd:
    +
    invalid current working directory: xxxx
    +
    +

    3447

    +
    cleanup_attribute_in_constexpr_function:
    +
    “cleanup” attribute within a constexpr function is not currently +supported
    +
    +

    3448

    +
    assume_statement_applies_to_null_statements:
    +
    the “assume” attribute can only apply to a null statement
    +
    +

    3449

    +
    assumption_failed:
    +
    assumption failed
    +
    +

    3450

    +
    variable_templates_is_cpp14:
    +
    variable templates are a C++14 feature
    +
    +

    3451

    +
    address_of_function_with_pass_object_size_attr:
    +
    cannot take the address of a function with a parameter declared with +the “pass_object_size” attribute
    +
    +

    3452

    +
    all_arguments_must_have_same_type:
    +
    all arguments must have the same type
    +
    +

    3453

    +
    comparison_details:
    +
    the final comparison was xxxx xxxx xxxx
    +
    +

    3454

    +
    too_many_arguments_provided_for_attribute:
    +
    too many arguments for attribute “xxxx”
    +
    +

    3455

    +
    constexpr_bad_mantissa_string:
    +
    mantissa string does not contain a valid number
    +
    +

    3456

    +
    constexpr_float_error:
    +
    floating-point error during constant evaluation
    +
    +

    3457

    +
    inheriting_ctor_ignored_for_copy:
    +
    inheriting constructor entity-kind “entity” ignored for +copy/move-like operation
    +
    +

    3458

    +
    cannot_get_file_size:
    +
    cannot determine size of file xxxx
    +
    +

    3459

    +
    cannot_read_file:
    +
    cannot read xxxx
    +
    +

    3461

    +
    unrec_embed_param:
    +
    unrecognized parameter name
    +
    +

    3462

    +
    dupl_embed_param:
    +
    parameter specified more than once
    +
    +

    3463

    +
    has_embed_not_in_if:
    +
    __has_embed cannot appear outside #if
    +
    +

    3464

    +
    setlocale_lc_numeric_failed:
    +
    could not set LC_NUMERIC locale to C
    +
    +

    3465

    +
    elifdef_not_enabled:
    +
    elifdef and elifndef are not enabled in this mode and are ignored in +text being skipped
    +
    +

    3466

    +
    nonstandard_alias_declaration_context:
    +
    an alias declaration is nonstandard in this context
    +
    +

    3467

    +
    out_of_order_field_allocation_nonstandard:
    +
    the target ABI may allocate nonstatic members in an order not +matching their declaration order, which is nonstandard in C++23 and +later
    +
    +

    3470

    +
    module_unit_export_unexpected:
    +
    the module declaration cannot be exported from this translation unit +unless creating a module interface file
    +
    +

    3471

    +
    module_unit_export_expected:
    +
    the module declaration must be exported from this translation unit to +create a module interface file
    +
    +

    3472

    +
    cannot_write_module_none_declared:
    +
    module file generation was requested but no module was declared in +the translation unit
    +
    +

    3473

    +
    candidate_constraints_failed:
    +
    substituting “<templ-args>” for entity-kind “entity” failed +constraints
    +
    +

    3474

    +
    concept_not_satisfied:
    +
    entity-kind “entity” not satisfied for “<templ-args>”
    +
    +

    3475

    +
    bad_embed_initializer:
    +
    the #embed expansion is too long to initialize an entity of type +“type”
    +
    +

    3476

    +
    bad_defined_pp_op:
    +
    the “defined” operator is not permitted here
    +
    +

    3477

    +
    ptr_to_mem_to_non_member:
    +
    entity-kind “entity” is not a member of “type”
    +
    +

    3478

    +
    embed_narrowing:
    +
    narrowing conversion to signed character in #embed data
    +
    +

    3479

    +
    invalid_vector_of_bool_operator:
    +
    operator is not permitted for “vector of bool” types
    +
    +

    3480

    +
    constexpr_object_too_large:
    +
    object too large for constant-evaluation
    +
    +

    3481

    +
    self_referencing_temporary_object:
    +
    self-referencing temporary object
    +
    +

    3482

    +
    lambda_cannot_refer_to_local_entity_here:
    +
    a lambda cannot refer to a local variable or init-capture in this +context
    +
    +

    3483

    +
    parameter_capture_conflict:
    +
    a lambda parameter cannot hide an explicit capture
    +
    +

    3484

    +
    template_parameter_capture_conflict:
    +
    a lambda template parameter cannot hide an explicit capture
    +
    +

    3485

    +
    insufficient_address_space:
    +
    insufficient address space exists to process this translation unit
    +
    +

    3486

    +
    undetermined_type:
    +
    <undetermined type>
    +
    +

    3487

    +
    undetermined_constant:
    +
    <undetermined constant>
    +
    +

    3488

    +
    undetermined_template:
    +
    <undetermined template>
    +
    +

    3489

    +
    bad_flt_config:
    +
    the configured size of xxxx is too small for the specified number +of mantissa + exponent bits
    +
    +

    3490

    +
    expression:
    +
    expression
    +
    +

    3491

    +
    quoted_expression:
    +
    <expression>
    +
    +

    3492

    +
    unnamed:
    +
    unnamed
    +
    +

    3493

    +
    quoted_unnamed:
    +
    <unnamed>
    +
    +

    3494

    +
    error_type:
    +
    <error-type>
    +
    +

    3495

    +
    unknown_type:
    +
    <unknown-type>
    +
    +

    3496

    +
    something:
    +
    <something>
    +
    +

    3497

    +
    null_type:
    +
    <null-type>
    +
    +

    3498

    +
    no_init:
    +
    <no-init>
    +
    +

    3499

    +
    zero_init:
    +
    <zero-init>
    +
    +

    3500

    +
    bitwise_copy_of:
    +
    bitwise copy of:
    +
    +

    3501

    +
    bitwise_copy:
    +
    <bitwise-copy>
    +
    +

    3502

    +
    class_result_via_ctor:
    +
    class result via ctor:
    +
    +

    3503

    +
    constructor_call:
    +
    <constructor-call>
    +
    +

    3504

    +
    null_expression:
    +
    <NULL expression>
    +
    +

    3505

    +
    quoted_error:
    +
    <error>
    +
    +

    3506

    +
    null_routine:
    +
    <NULL routine>
    +
    +

    3507

    +
    quoted_default:
    +
    <default>
    +
    +

    3508

    +
    parameter_number:
    +
    parameter #
    +
    +

    3509

    +
    one_level_up:
    +
    (one level up)
    +
    +

    3510

    +
    levels_up:
    +
    levels up
    +
    +

    3511

    +
    dynamic_init:
    +
    dynamic-init:
    +
    +

    3512

    +
    error_constant:
    +
    <error-constant>
    +
    +

    3513

    +
    stack_offset_of:
    +
    stack-offset-of:
    +
    +

    3514

    +
    implicit_element:
    +
    <implicit element>
    +
    +

    3515

    +
    repetitions_of:
    +
    repetitions of
    +
    +

    3516

    +
    type_code_integer:
    +
    integer
    +
    +

    3517

    +
    type_code_enum:
    +
    enum
    +
    +

    3518

    +
    type_code_scoped_enum:
    +
    scoped enum
    +
    +

    3519

    +
    type_code_arithmetic:
    +
    arithmetic
    +
    +

    3520

    +
    type_code_non_bool_arithmetic:
    +
    non-bool arithmetic
    +
    +

    3521

    +
    type_code_pointer:
    +
    pointer
    +
    +

    3522

    +
    type_code_nullptr_type:
    +
    nullptr type
    +
    +

    3523

    +
    type_code_handle:
    +
    handle
    +
    +

    3524

    +
    type_code_handle_to_CLI_array:
    +
    handle-to-CLI-array
    +
    +

    3525

    +
    type_code_pointer_to_object:
    +
    pointer-to-object
    +
    +

    3526

    +
    type_code_pointer_to_function:
    +
    pointer-to-function
    +
    +

    3527

    +
    type_code_pointer_to_member:
    +
    pointer-to-member
    +
    +

    3528

    +
    type_code_bool:
    +
    bool
    +
    +

    3529

    +
    type_code_bool_equivalent:
    +
    bool-equivalent
    +
    +

    3530

    +
    type_code_class:
    +
    class
    +
    +

    3531

    +
    volatile_inc_deprecated:
    +
    a volatile operand to an increment expression is deprecated
    +
    +

    3532

    +
    volatile_dec_deprecated:
    +
    a volatile operand to a decrement expression is deprecated
    +
    +

    3533

    +
    indeterminate_not_on_first_decl:
    +
    entity-kind “entity” previously declared without the +“indeterminate” attribute
    +
    +

    3534

    +
    default_constructor_is_explicit:
    +
    the default constructor for “type” is explicit
    +
    +

    3535

    +
    ifc_definition_load_failure:
    +
    failed to load the definition of entity-kind “entity” in module +“module name”
    +
    +

    3536

    +
    ifc_initializer_load_failure:
    +
    failed to load the initializer for entity-kind “entity” in +module “module name”
    +
    +

    3537

    +
    base_class_of_class_type_with_typedef_name:
    +
    a class with a typedef name for linkage purposes cannot have a base +class
    +
    +

    3538

    +
    member_function_of_class_type_with_typedef_name:
    +
    a class with a typedef name for linkage purposes cannot have a member +function
    +
    +

    3539

    +
    member_type_of_class_type_with_typedef_name:
    +
    a class with a typedef name for linkage purposes cannot have a nested +type, other than an enumeration type or a non-closure class type
    +
    +

    3540

    +
    lambda_in_class_type_with_typedef_name:
    +
    a class with a typedef name for linkage purposes cannot contain a +lambda expression
    +
    +

    3541

    +
    field_init_in_class_type_with_typedef_name:
    +
    a class with a typedef name for linkage purposes cannot have a +nonstatic data member with a default member initializer
    +
    +

    3542

    +
    static_data_member_not_allowed_in_unnamed_class:
    +
    a static data member declaration is not allowed in an unnamed class
    +
    +

    3543

    +
    initializer_addresses_dllimport_variable:
    +
    initializer result addresses a dllimport variable
    +
    +

    3544

    +
    cannot_be_specialized:
    +
    template with “no_specializations” attribute cannot be specialized
    +
    +

    3545

    +
    static_dimension_nonstandard:
    +
    “static” is nonstandard here
    +
    +

    3546

    +
    enum_previously_declared_without_explicit_base:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared without an explicit enum base
    +
    +

    3547

    +
    missing_typename:
    +
    missing “typename” is nonstandard here
    +
    +

    3548

    +
    abbreviated_deduction_guide:
    +
    abbreviated function template syntax is nonstandard for deduction +guides
    +
    +

    3549

    +
    explicit_this_is_cpp23:
    +
    explicit “this” parameters are a C++23 feature
    +
    +

    3550

    +
    array_designator_for_deduced_context:
    +
    array designators are not supported in template deduction contexts
    +
    +

    3551

    +
    second_argument_wrong_shape:
    +
    the second argument must be an integer type with the same shape (a +scalar or vector type) as the first argument
    +
    +

    3552

    +
    vector_of_boolean_required:
    +
    argument must be a vector of boolean types
    +
    +

    3553

    +
    pointer_to_scalar_required:
    +
    argument must be a pointer to a scalar type
    +
    +

    3554

    +
    incorrect_masked_type:
    +
    incorrect argument type (should be “type”)
    +
    +

    3555

    +
    vector_type_with_size_is_required:
    +
    a vector type (with the same number of elements as the first +argument) is required
    +
    +

    3556

    +
    struct_binding_packs_is_cpp26:
    +
    structured binding packs are a C++26 feature
    +
    +

    3557

    +
    non_template_structured_binding_pack:
    +
    a structured binding pack can only be declared inside a template
    +
    +

    3558

    +
    multiple_structured_binding_packs:
    +
    cannot declare multiple packs in a structured binding declaration
    +
    +

    3559

    +
    cl_cpp26_requires_parse_nonclass_templates:
    +
    The “–no_parse_templates” option cannot be used in C++26 mode
    +
    +

    3560

    +
    type_pack_element_cannot_match:
    +
    a type pack element cannot match entity-kind “entity”
    +
    +

    3561

    +
    c23_old_style_param_id:
    +
    identifier-only parameters can only be used in old-style function +definitions, which are nonstandard since C23
    +
    +

    3562

    +
    cl_require_func_prototypes_option_only_in_C:
    +
    option “no_require_func_prototypes” can be used only when compiling C
    +
    +

    3563

    +
    address_of_overload_set_implicit_obj_member_selected:
    +
    overload resolution for an address-of-overload-set call may not +select implicit-object member entity-kind “entity” (declared at +line xxxx)
    +
    +

    3564

    +
    pack_indexing_is_cpp26:
    +
    pack indexing is a C++26 feature
    +
    +

    3565

    +
    pack_index_out_of_bounds:
    +
    pack index exceeds number of pack elements
    +
    +

    3566

    +
    alias_ctad_is_cpp20:
    +
    class template argument deduction for alias templates is a C++20 +feature
    +
    +

    3567

    +
    bitint_width_too_large:
    +
    _BitInt(n) is invalid; the maximum integer width is n
    +
    +

    3568

    +
    signed_bitint_width_too_small:
    +
    _BitInt(n) is invalid; the minimum signed _BitInt width is n
    +
    +

    3569

    +
    unsigned_bitint_width_too_small:
    +
    unsigned _BitInt(n) is invalid; the minimum unsigned _BitInt +width is n
    +
    +

    3570

    +
    bitint_enum_base_not_allowed:
    +
    _BitInt types cannot be the underlying type of an enumeration type
    +
    +

    3571

    +
    deduction_guide_redeclaration:
    +
    redeclaration of deduction guide “type” (previous declaration at +line xxxx)
    +
    +

    3572

    +
    create_pch_file_not_created:
    +
    precompiled header file “xxxx” was not created
    +
    +

    3576

    +
    non_c_like_typedef_for_linkage:
    +
    anonymous non-C-like type given name for linkage purposes by typedef +or alias declaration
    +
    +

    3577

    +
    non_c_like_because_of_base_class:
    +
    type is not C-like because of this base class
    +
    +

    3578

    +
    non_c_like_because_of_default_member_init:
    +
    type is not C-like because of this default member initializer
    +
    +

    3579

    +
    non_c_like_because_of_friend:
    +
    type is not C-like because of this friend declaration
    +
    +

    3580

    +
    non_c_like_because_of_member:
    +
    type is not C-like because of this member declaration
    +
    +

    3581

    +
    non_c_like_because_of_lambda:
    +
    type is not C-like because of this lambda expression
    +
    +

    3582

    +
    enum_qualifier_is_cpp11:
    +
    an enum-type name qualifier is a C++11 feature
    +
    +

    3583

    +
    unrestricted_unions_is_cpp11:
    +
    unrestricted unions are a C++11 feature
    +
    +

    3584

    +
    pack_expansion_for_non_pack_alias_param:
    +
    a pack expansion cannot be used as an argument for non-pack +entity-kind “entity” of entity-kind “entity”
    +
    +

    3585

    +
    uniterable_reflection_range:
    +
    the range passed to the metafunction cannot be iterated
    +
    +

    3587

    +
    interpreter_message_remark:
    +
    xxxx xxxx
    +
    +

    3588

    +
    interpreter_message_warning:
    +
    xxxx xxxx
    +
    +

    3589

    +
    interpreter_message_error:
    +
    xxxx xxxx
    +
    +

    3590

    +
    constexpr_diag_arg_count:
    +
    a call to “__builtin_constexpr_diag” requires three arguments
    +
    +

    3591

    +
    constexpr_diag_bad_level:
    +
    the first argument in a call to “__builtin_constexpr_diag” must be 0 +(remark), 1 (warning), 2 (error), 16 (remark at caller), 17 (warning +at caller), or 18 (error at caller)
    +
    +

    3592

    +
    constexpr_diag_bad_string:
    +
    a string literal or an object with the representation of +std::string_view is required for the tag and the message in a call to +“__builtin_constexpr_diag”
    +
    +

    3593

    +
    constexpr_diag_bad_tag:
    +
    the tag in a call to “__builtin_constexpr_diag” may contain only +letters, digits, and underscores
    +
    +

    3594

    +
    cl_invalid_constexpr_diag_tag:
    +
    invalid tag in constexpr diagnostic control option: xxxx
    +
    +

    3595

    +
    token_sequence_needs_double_caret:
    +
    a token sequence must be introduced by “^^”
    +
    +

    3596

    +
    exp_interpolator:
    +
    expected an interpolator (”[”, “[:”, “{”, “val”, or “str”)
    +
    +

    3597

    +
    interpolated_id_is_not_identifier:
    +
    “xxxx” does not spell an identifier
    +
    +

    3598

    +
    interpolated_operand_is_not_token_sequence:
    +
    the operand of a “{…}” interpolator is not a token sequence
    +
    +

    3599

    +
    tag_redefined_differently:
    +
    this declaration of entity-kind “entity” does not declare the +same type as the declaration at line xxxx
    +
    +

    3600

    +
    bad_gcc_unroll_pragma_value:
    +
    the argument of “#pragma GCC unroll” must be a non-negative integral +constant less than 65535
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/exceptions/index.html b/dev/doc/exceptions/index.html new file mode 100644 index 0000000..419ca03 --- /dev/null +++ b/dev/doc/exceptions/index.html @@ -0,0 +1,802 @@ + + + + + 14. Exception Handling - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    14. Exception Handling#

    +

    The high-level representation of exception handling in the IL closely follows +the C++ language specification. The data structures involved are defined in +il_def.h, and the routines to manage declarations and other support are in +decls.c, statements.c, and expr.c.

    +

    A global variable, exceptions_enabled, controls whether exception +processing is done. An error is issued if the flag is FALSE and the source +program attempts to use a syntactic feature that pertains to exception +handling. The default value of the exceptions_enabled flag is configurable +(see DEFAULT_EXCEPTIONS_ENABLED in lang_feat.h). The value may be +toggled by a command-line option (-x), except that its value may be TRUE +only in C++ mode and only when cfront-compatibility mode has not been selected.

    +

    Any actual implementation of exception handling will require a tradeoff between +portability and efficiency. The high-level representation of exception +handling (that is, the representation of the “unlowered” IL) is not explicit +about a number of details that an actual implementation will have to deal with, +notably finding the right handler, copying the throw object to the right +handler parameter, and calling the right set of destructors at the right time. +Therefore, though a portable implementation of exception handling is provided +(see lower_eh.c and routines provided for run-time support), back ends may +choose to replace it with an implementation adapted to the specific support +available on the target platform. IL lowering can instead be configured to do +partial lowering or no lowering of exception handling features.

    +

    This chapter describes the high-level support for exceptions and then +summarizes the main features of the portable implementation.

    +
    +

    14.1. Exception Specifications#

    +

    An exception specification that appears on a function declaration is +represented by an entry of type an_exception_specification. The +function refers to it by means of the exception_specification field of +its routine type supplement. When the function is declared with no +exception specification (meaning that any exception might be thrown), the +exception_specification pointer will be NULL. A dynamic throw +specification entry itself has a pointer to a linked list of entries of +type a_throw_spec_type_entry, each of which indicates a type of +exception that will be thrown from the given routine; that pointer is NULL +to indicate that no exceptions will be thrown. A noexcept specifier +points to a constant representing its operand or NULL if there is no such +operand.

    +

    scan_exception_specification, which is called from function_declarator, +scans an exception specification and allocates a throw specification entry +and its associated list of types, if any. Subsequently (i.e., after the +routine entry has been identified) the exception specification is either added +to the routine type supplement or checked against a prior declaration (see +check_exception_specification).

    +

    The used_in_exception flag is set for any type that appears in an exception +specification (as well as for any type that is the type of a throw +expression or appears in the exception declaration of a handler). Some +implementations of exception handling may use this flag in generating special +code for run-time type identification. In addition, if such a type is (or +“contains”) a class or enumeration type, that class or enumeration type must be +externally linked. See set_used_in_exception_or_rtti_flag (in +types.c).

    +
    +
    +

    14.2. try Blocks#

    +

    A try block is represented in the IL by a statement of kind +stmk_try_block, which points to a compound statement block and a linked +list of handlers. The latter are entries of type a_handler; each points to +a (possibly unnamed) parameter (the local variable to which the throw +object will be copied when the handler is invoked) and to an stmk_block +statement, the body of the handler; for a default handler (i.e., the +catch(...) case) the parameter pointer in the handler entry is NULL.

    +

    A try block is scanned by try_block_statement (in statements.c). +First compound_statement is called to scan the part of the try block +that precedes the first handler declaration. Then handler_declaration (in +decls.c) is called for each catch clause.

    +

    handler_declaration scans the exception declaration (calling +decl_specifiers and, if a named parameter is present, declarator). +Except for the default handler case, it creates a variable entry to +represent the parameter, whether it is explicitly declared or not. It also +does various checks to assure that the parameter’s type is valid (e.g., that it +is not an incomplete type) and calls set_used_in_exception_or_rtti_flag; +then it calls type_masks_handler_param_type (in types.c), to assure +that it is not masked by a previous handler declaration in the same try +block.

    +

    Finally, compound_statement is called to scan the handler’s body. Special +checking is done to assure that no label defined within the handler is +referenced by a goto from outside the handler.

    +

    in C++/CLI mode, there may be a “finally” block at the end, either in +addition to or in place of the catch clauses. It provides code that is +always executed when the try block is exited, whether normally, via a +goto or return, or via a thrown exception.

    +
    +
    +

    14.3. throw Expressions#

    +

    A throw expression is scanned by scan_throw_operator (in expr.c). +An enk_throw expression node is produced, which points to a dynamic +initialization entry that describes the object to be thrown (or rather, how to +copy it to the space for the object allocated by the run-time). +set_used_in_exception_or_rtti_flag is called for the type. A “rethrow”, +where no throw object is specified (i.e., throw;), is represented by an +enk_throw expression with a NULL pointer.

    +
    +
    +

    14.4. Portable Implementation#

    +

    One exception handling implementation provided in this release is a portable +implementation that provides complete EH support while requiring few changes to +existing back ends. Because this is a portable implementation there is a +significant impact on the performance of the generated code when exception +handling is enabled.

    +
    +

    14.4.1. A walk-through of an EH example#

    +

    What follows is a rather contrived example that provides an overview of how the +compiled code and the run-time system cooperate in throwing and handling +exceptions. It is intended as an introduction, with a more detailed discussion +of some of its features in subsequent sections.

    +

    Here is the example (with the numbers to the right corresponding to the text +that follows):

    +
    #include <stdio.h>
    +struct A { ~A() { } };
    +struct B : public A { };
    +struct C { };
    +void f(int i) throw(A) {                       // 2, 3, 4
    +  A  a1;                                       // 5
    +  if (i==0) throw a1;                          // 6
    +  B  b1;
    +  if (i==1) throw b1;
    +  C  c1;
    +  if (i==2) throw c1;
    +}
    +int main() {
    +  for (int i = 0; i < 3; ++i) {
    +    printf("i=%0d\n", i);
    +    try {                                      // 1
    +      f(i);
    +    }
    +    catch (A a) { printf("Caught an A\n"); }   // 7, 8
    +    catch (...) { printf("Caught something else\n"); }
    +  }  /* for */                                 // 9
    +}
    +
    +
    +
      +
    1. Each time the for loop in main is executed and control enters +the try block, prologue code is executed, which includes pushing an +entry onto the “EH stack” to record that a try block has been +entered. (The EH stack is the principal data structure used to track the +dynamic context in which exception handling events occur.)

    2. +
    3. Each time f is called, prologue code for the function pushes another +entry onto the EH stack to record that a function with exception +specifications has been entered. This entry provides the run-time system +with a list of the types that may be thrown from f.

    4. +
    5. Moreover, since f contains objects (namely, automatic variables with +destructors) that may need to be cleaned up if an exception is thrown +during its execution, an additional entry is pushed onto the EH stack +for object cleanup. [1] The array it points to is updated each time +an object that is eligible for clean-up is constructed.

    6. +
    7. The first clean-up region of f is entered, and global variable +__eh_curr_region is updated accordingly. This routine has three such +regions – the region in which no objects require clean-up, the region in +which a1 requires clean-up, and the region in which both a1 and +b1 require clean-up. [2]

    8. +
    9. When a1 is constructed, the second clean-up region is entered. The +address of a1 is entered in the “object address table”.

    10. +
    11. The processing for the original source expression “throw a1” +involves three steps:

      +
        +
      • +
        __throw_setup is called to record information about a1 (most +importantly, its type) and to return a pointer to a piece of storage +into which it may be copied. [3]
        +
        +
      • +
      • +
        The compiled code makes a copy of a1 to pass to +__throw. Note that if class A had a copy constructor, the +generated code would include a call of __exception_started prior +to making the copy of a1.
        +
        +
      • +
      • +
        __throw is called. First it walks the EH stack to identify the +action that is required – in this case, it locates a handler that +can catch an A object. It then makes a second pass through the +EH stack to do the appropriate clean-up, which in this case involves +calling the destructor for a1 and popping a couple of entries +off the EH stack. The actions performed by __throw may entail a +good deal more complexity, as described in greater detail later.
        +
        +
      • +
      +
    12. +
    13. After the clean-up is complete, control transfers back to the try +block in main, and specifically to the first handler (since it is +the one that catches an A object), and then “Caught an A” is +printed out.

    14. +
    15. The epilogue code of the handler involves a call to +__free_thrown_object, to deallocate the storage into which a1 +was copied.

    16. +
    17. As the try block is exited, the EH stack entry for the current +try block is popped, restoring the state to what it was originally, +before the try block was entered.

    18. +
    +

    On the second iteration of the for loop in main, the same sequence of +events takes place, except for two things. First, in function fb1 is +also constructed, so that the third clean-up region is entered and the address +of b1 is recorded in the object address table (along with that of a1); +that means that two objects are eligible for clean-up when an exception occurs. +Second, __throw must take into account that A is an accessible base +class of B in locating the handler that can catch b1.

    +

    Finally, on the third iteration of the loop, __throw detects a violation of +the exception specification for function f – c1 is the thrown object +this time, but C is not on the list of types that the function is allowed +to throw. As a result, unexpected is called, which results in a call to +terminate.

    +
    +
    +

    14.4.2. Run-Time Support#

    +
    +

    14.4.2.1. The EH Stack#

    +

    A principal data structure used in coordinating the compiled code and the +run-time is the “EH stack”. It maintains information about the dynamic context +in which exception handling events occur. The EH stack is a linked list of +structures, and a new entry is pushed onto the stack each time a try block +is entered, each time a function with an exception specification is entered, +and each time a function is entered for which some kind of object clean-up must +be done if an exception is thrown.

    +
    +
    +

    14.4.2.2. Code generated for a try block#

    +

    When a try block is entered, a try block entry is pushed onto the EH +stack. The try block entry contains

    +
      +
    • +
      a setjmp buffer that will be used for transfer of control back to the +try block when an exception is thrown;
      +
      +
    • +
    • +
      a list of the catch clauses associated with the try block;
      +
      +
    • +
    • +
      other status information used to record the current state of the try +block.
      +
      +
    • +
    +

    The state information in the try block is initialized so that the run-time +knows that the try section of the block (as opposed to one of the handlers) +is currently being executed. When generating code for exception cleanup it is +sometimes necessary for the front end to generate try blocks that do not +appear in the original program. These are known as “internal” try blocks +and are distinguished from normal try blocks by the fact that the pointer +to the list of catch clauses is null.

    +
    +
    +

    14.4.2.3. Prologue code for a function with an exception specification#

    +

    When a function with an exception specification is entered, a throw +specification entry is pushed onto the EH stack. This entry provides a list of +the types that may be thrown (directly or indirectly) by the function. It is +removed from the EH stack when the function returns.

    +
    +
    +

    14.4.2.4. Prologue code for a function that may need clean-up if an exception is thrown#

    +

    When a function constructs objects that may need to be cleaned up in the event +of an exception, its prologue code pushes a function clean-up entry onto the EH +stack. Note that a given function may push both a throw specification +entry and a function clean-up entry.

    +

    A function clean-up entry will be pushed on the stack if the function creates +any automatic objects (including temporaries) of classes with destructors; one +is also generated when an object may be dynamically allocated using operator +new and the front end is configured to generate the operator new call +outside the constructor.

    +

    The function clean-up entry contains

    +
      +
    • +
      a pointer to an array of region entries that are used to describe the +clean-up regions within the function
      +
      +
    • +
    • +
      a pointer to an array table that provides additional information for +certain region entries
      +
      +
    • +
    • +
      a pointer to an object address table used to determine the address of +objects referenced by the region and array tables
      +
      +
    • +
    +

    A region is associated with a specific sequence of clean-up actions that would +be required should an exception occur. A new region is typically started +whenever a destructable object comes into or goes out of scope.

    +

    The global variable __eh_curr_region records the region number currently +being executed. It is saved each time a new function entry or try block is +pushed on the stack and restored when the entry is popped.

    +

    The region entries contain the information needed to identify the object to be +cleaned up and the kind of clean-up action required. The run-time must be able +to determine the address of each object for which some kind of clean-up must be +done. Ideally this would be done by putting stack offsets in the region +entries. This can’t be done in the portable implementation, and so instead the +region entries contain an index into the object address table. The object +address table is allocated on the stack because its contents vary with each +invocation of the function. As each region is entered, the appropriate entry +in the object address table is filled in with the address of the object to be +cleaned up. The address of the object address table is recorded in the +function entry on the EH stack.

    +

    The region entries have been designed to be as compact as possible. Some +unusual circumstances require additional information not normally available in +the region entry. The additional information is needed when the region entry +describes an array or when the region entry describes a new allocation of a +class object whose operator delete function is of the two-operand variety. +In these cases the region entry contains an index into an array supplement and +the array supplement pointer is stored in the function entry on the EH stack.

    +
    +
    +

    14.4.2.5. Throwing an exception (generated code)#

    +

    When an exception is thrown, the run-time routine __throw_setup is called +to provide information to the run-time system about the object being thrown and +to allocate space into which the thrown object may be copied. A pointer to +this space is returned to the caller (i.e., the compiled code), which is +responsible for actually making the copy of the object. If copying the object +requires calling a copy constructor, __exception_started is called after +the evaluation of the object to be thrown, but before the copy constructor is +called. Once the object has been copied the run-time routine __throw is +called to complete the throw processing. If the thrown object requires +destruction, __throw_setup_dtor is called instead of __throw_setup. If +the thrown object is a multi-level pointer, __throw_setup_ptr is called +instead of __throw_setup.

    +
    +
    +

    14.4.2.6. Throwing an exception (__throw_setup)#

    +

    When __throw_setup is called, an entry is pushed onto the throw stack +(which is distinct from the EH stack). The throw stack contains information +about each of the thrown objects and is needed because throws may be nested +(i.e., a throw may occur while in a handler reached as the result of an earlier +throw). __throw_setup records the information provided by the caller in +the throw stack entry. This includes information about the type of the thrown +object.

    +

    The run-time system requires information about the types of objects that are +thrown and caught and also for types used in exception specifications. The +term “typeinfo” is used to refer to this type description information. +[4] It is not necessarily possible to generate only one typeinfo record +for a given type. [5] Consequently it must be possible to determine that +two typeinfo records refer to the same type. This is done by having each +typeinfo point to a “unique ID object”. The unique ID objects are +generated as tentative definitions to avoid potential multiple definition +problems. Two typeinfo records refer to the same type if they point to the +same unique ID object. The typeinfo information includes a list of the +base classes of the type. The base class list includes all direct base classes +as well as all virtual base classes, whether direct or indirect.

    +

    When checking exception specifications and looking for a catch clause that +can catch the thrown object, it is necessary to determine whether a given type +is a base class (and an accessible one) of the thrown type. This is done by +traversing the typeinfo base class list. The base class list includes +information about accessibility and ambiguity, which allows the runtime to +ignore non-public and ambiguous base classes.

    +

    In front end versions preceding 2.29, the runtime routine __throw_alloc was +called instead of __throw_setup. It had a similar function and a similar +interface, with one additional parameter, which (when non-NULL) was a string +indicating the accessibility for each base class, computed by the front end at +the point of the throw. This changed because the C++ language changed: As of +March 1995, the rules for throw were changed to allow catching only public +base classes, which eliminates the need for determining any special +accessibility at the point of throw.

    +
    +
    +

    14.4.2.7. Marking the initiation of the exception (__exception_started)#

    +

    An exception is considered “uncaught” after the expression in the throw +statement has been evaluated. If a copy constructor must be called to copy the +thrown object into the temporary copy used by the EH runtime, the copy +constructor must be called while the exception is considered uncaught. In +other words, if an exception is thrown during the evaluation of the expression +in the throw, that exception is handled normally. If, however, an exception is +thrown from a copy constructor called to copy an object to the temporary used +by the EH runtime (and control is transferred out of the copy constructor +because of the exception) terminate() must be called instead.

    +

    __exception_started is called to mark the point at which an exception is +considered uncaught. When the copy of the thrown object can be made without +calling a copy constructor __exception_started is not called, and the +exception is considered uncaught at the point at which __throw is called.

    +
    +
    +

    14.4.2.8. Throwing an exception (__throw)#

    +

    After the compiled code copies the thrown object into the space designated by +__throw_setup, it issues a call to __throw to complete the processing.

    +

    __throw makes two passes through the try stack. The first pass +determines what should occur as a result of the throw – transferring to a +specific handler, calling unexpected because an exception specification was +violated, or calling terminate (for any of several reasons). Once the end +result of the throw has been determined, a second pass is made through the EH +stack entries to perform any clean-up actions that are required.

    +

    During the first pass through the EH stack +check_exception_type_specifications is called for each try block entry +and each throw specification entry. Only try blocks that are executing +the try portion of the block (as opposed to a handler) are eligible to be +the destination of a throw. try blocks that are currently in handlers +are simply ignored. The search is terminated when a matching catch clause +is found or a violated exception specification is detected. When it is a +matching catch clause that is found, a pointer to the thrown object is +passed to the routine so that it may be adjusted for any derived-to-base-class +conversions that may be needed. If the matching catch clause is associated +with an internal try block, the search of the EH stack continues to +determine if a normal try block can be found. The search for a normal +try block that with a matching handler is used to determine whether +terminate() should be called.

    +

    According to the standard it is implementation-defined whether the stack is +unwound before terminate() is called. The runtime can be configured to +select either of the possible behaviors by setting the +UNWIND_STACK_BEFORE_CALLING_TERMINATE configuration flag. If this flag is +not set, terminate() would be called now if no matching handler was found.

    +

    In the second pass only the function clean-up entries are processed. The +function cleanup is called for each such entry. cleanup processes the +region entries associated with the function starting with the region number +specified by the caller. Each region entry contains a “flags” field that +controls how the region information is interpreted.

    +
      +
    • +
      If the “conditional flag” bit is set, the region entry describes an object +that is conditionally constructed and must only be destroyed if a variable, +whose address is determined from the next element in the region array, +indicates the object was actually constructed.
      +
      +
    • +
    • +
      If the “new allocation” bit is set, the region entry describes an object +allocated by new that must be deleted during clean-up. In this case +the function pointer in the region entry that normally points to the +destructor instead points to the delete routine to be called.
      +
      +
    • +
    • +
      If the “VLA” bit is set, the region entry describes a variable length +array, whose size is determined from the next element in the region array.
      +
      +
    • +
    +

    One of the fields in the region entry is the region number of the next entry to +be processed. The end of the region list is designated by a reserved value in +the next entry field.

    +

    If an exception occurs while constructing or destructing an array, the clean-up +operation must destroy the remaining portion of the partially constructed (or +destructed) array. To accomplish this there is a special kind of EH stack +entry that is only used by vec_new and vec_delete. When this entry is +encountered during the clean-up pass, __cleanup_vec_new_or_delete is called +to the required clean-up.

    +

    After all of the function clean-up entries have been processed, __throw +determines whether there are any clean-up actions required by the try block +associated with the handler to which control is to be transferred. If so, +cleanup is called to do the required clean-up operations.

    +

    Only after all the clean-up operations have been completed is the action +performed that was determined by the first pass through the EH stack:

    +
      +
    • +
      If an exception specification was violated, unexpected is called.
      +
      +
    • +
    • +
      If no handler was found, terminate() is called (when the +UNWIND_STACK_BEFORE_CALLING_TERMINATE configuration flag is set).
      +
      +
    • +
    • +
      Otherwise, control is transferred to the handler. Global variable +__catch_clause_number is set to the sequence number of the catch +clause to which control is to be transferred, and another global variable, +__caught_object_address, is set to the address of the object to be used +to initialize the handler parameter. The state information in the try +block entry is updated to indicate that a handler is now being executed. +Finally, longjmp is used to branch back to the appropriate try +block.
      +
      +
    • +
    +
    +
    +

    14.4.2.9. In the handler#

    +

    The try block code uses __catch_clause_number to select the appropriate +handler, and then the handler parameter is initialized using +__caught_object_address: If the handler parameter is a reference, it is +initialized by setting a pointer to the global variable; otherwise, the object +pointed to by __caught_object_address is used to initialize the handler +parameter. __exception_caught is called after the handler parameter has +been initialized. This marks the end of the period during which an exception +is considered uncaught. __exception_caught is not called by the catch +clause associated with an internal try block. Instead, an internal try block +exits by calling __internal_rethrow, which calls __exception_caught +before performing the rethrow.

    +
    +
    +

    14.4.2.10. A rethrow from the handler#

    +

    A rethrow (a throw with no operand) may be executed anywhere within the +dynamic context of a handler. This has the effect of doing a nested throw of +the object on top of the throw stack. Note that it rethrows the thrown object +and not the caught object (the two can be different if a derived-to-base +conversion occurred or if the object was caught using ellipsis).

    +

    The handling of rethrow is almost identical to the handling of a normal throw. +The only difference is that the thrown object is not copied. The throw stack +entry for the rethrow points to the copy of the thrown object made when the +original throw was done.

    +
    +
    +

    14.4.2.11. At the end of a handler#

    +

    At the end of each handler __free_throw_object is called to pop entries off +of the throw stack, call the destructor for the thrown object, and to free the +space used for copies of the thrown objects associated with the throw stack +entries being cleared.

    +
    +
    +

    14.4.2.12. Run-Time storage management#

    +

    The exception handling run-time dynamically allocates information used for book +keeping (e.g., throw stack entries) and for making copies of thrown objects. +The memory is allocated and freed using a stack discipline. The run-time +includes a static buffer that is used for this dynamically allocated memory. +If the static buffer is exhausted, additional memory is allocated using +malloc. If the run-time is unable to allocate the memory needed to handle +an exception, terminate is called.

    +
    +
    +
    +
    +

    14.5. Non-Portable Implementation#

    +

    The non-portable implementation would be more properly described as “turning +off parts of the portable implementation so that a back end can do something +better.” EDG does not provide a complete non-portable implementation (in IL +lowering and the runtime), but our customers should be able to write one using +the information provided by the front end.

    +

    The portable implementation is also known as the full-lowering implementation, +because it lowers everything related to exception handling to C, leaving +nothing related to exception handling in the IL. It is enabled by setting +DO_FULL_PORTABLE_EH_LOWERING to TRUE.

    +

    The next step down from that is the partial-lowering implementation, which is +enabled by setting GENERATE_EH_TABLES to TRUE. In that mode, the data +tables of the portable scheme are still generated, but the executable code is +rendered as exception-handling operations, so that a back end can choose a +different approach (e.g., not using setjmp, not maintaining a separate EH +stack).

    +

    The final step down is the no-lowering implementation, which is enabled by +having both DO_FULL_PORTABLE_EH_LOWERING and GENERATE_EH_TABLES FALSE. +In that mode, the data tables are not generated either, but the object lifetime +information is preserved so that the back end can use it to generate its own +version of the cleanup tables.

    +

    See the IL Lowering chapter for details on the constructs +preserved and lowered under each alternative.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/expr/index.html b/dev/doc/expr/index.html new file mode 100644 index 0000000..3d4ce52 --- /dev/null +++ b/dev/doc/expr/index.html @@ -0,0 +1,3150 @@ + + + + + 9. Expression Scanning - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    9. Expression Scanning#

    +

    expr.c and expr.h contain the code and associated declarations to scan +expressions. exprutil.c and exprutil.h contain utilities related to +expression scanning, for processing other than the actual syntax analysis. +overload.c and overload.h contain code to do overload resolution and +conversions.

    +

    The expression routines function as an expression-scanning utility for the rest +of the front end. They provide a set of simple interface routines that are +called to scan various kinds of expressions:

    +
      +
    • +
      scan_integer_expression scans an integral expression, e.g., the +selector expression for a switch statement.
      +
      +
    • +
    • +
      scan_void_expression scans a “void” expression, one whose value is +thrown away, e.g., an expression statement or the incrementing expression +in a for statement.
      +
      +
    • +
    • +
      scan_default_arg_expr scans a default argument expression.
      +
      +
    • +
    • +
      scan_template_argument_constant_expression scans a nontype argument of +a template reference.
      +
      +
    • +
    • +
      scan_return_expression scans the expression in a return statement.
      +
      +
    • +
    • +
      scan_case_label_constant scans a constant expression for a switch case.
      +
      +
    • +
    • +
      scan_constant_dimension_expression scans a constant array bound.
      +
      +
    • +
    • +
      scan_pp_expression scans a preprocessing expression, e.g., an +expression in an #if.
      +
      +
    • +
    • +
      scan_integral_constant_expression scans an integral constant +expression.
      +
      +
    • +
    • +
      scan_constant_initializer_expression scans an initializer that is +required to be a constant.
      +
      +
    • +
    • +
      scan_member_constant_initializer_expression scans an initializer for a +member constant (integral or enum) in C++.
      +
      +
    • +
    • +
      scan_full_initializer_expr_as_componentscans an initializer that need +not be a constant.
      +
      +
    • +
    • +
      scan_class_initializer_expression scans an initializer for a class.
      +
      +
    • +
    • +
      scan_class_parenthesized_initializer scans a parenthesized initializer +for a class.
      +
      +
    • +
    • +
      scan_boolean_controlling_expression scans a scalar expression that +controls a conditional statement (if, while, do while, and +for).
      +
      +
    • +
    +

    Each of these routines has roughly the same structure. scan_expr_full is +called to do the actual expression scanning. This produces a result of type +an_operand, which is checked for kind, converted to a required type (if +there is one), and then converted to the form required on return from the +interface routine, usually an expression node or a constant.

    +

    Some other utility expression routines with a different type of interface:

    +
      +
    • +
      scan_ctor_arguments is called to scan a parenthesized list of +expressions that acts as the argument list for a constructor call, for +example
      +
      +
      struct A {
      +  A(int, int);
      +};
      +A aa(1, j+1);  // scan_ctor_arguments is called
      +
      +
      +
    • +
    • +
      try_to_convert_class_operand_to_builtin_type is called to convert an +expression of a class type to a builtin type, as when such an expression +appears as the conditional expression in an if statement or the like.
      +
      +
    • +
    • +
      scan_braced_init_list scans a complete braced-enclosed initializer as +in the C++11 “initializer lists” feature. convert_initializer is used +to convert initializers, in particular brace-enclosed initializers, to the +type of the entity being initialized.
      +
      +
    • +
    • +
      find_default_constructor finds a default constructor capable of +initializing an object of a given class type.
      +
      +
    • +
    • +
      find_copy_constructor finds a copy constructor capable of copying an +object of a given class type with a given cv-qualification.
      +
      +
    • +
    • +
      find_copy_assignment_operator is similar for an operator= function.
      +
      +
    • +
    +
    +

    9.1. scan_expr_full#

    +

    scan_expr_full actually handles all expression scanning. It is called with +a set of option flags that configure its processing for various types of +expressions. It scans through the tokens of an expression, builds an +expression tree for the expression scanned, and returns an argument of type +an_operand to describe the expression scanned.

    +

    Its arguments are as follows:

    +
    + + + + + + + + + + + + + + + +
    +
    result
    +
    +
    +
    The result (of type an_operand) of this level of expression +scanning.
    +
    +
    +
    prec_level
    +
    +
    +
    The operator precedence level at which to terminate the scanning. +Expression scanning continues while the next operator precedence is +higher than this (or equal, with right-associative operators).
    +
    +
    +
    expression_kind
    +
    +
    +
    The kind of expression that is expected: ek_pp for a preprocessing +expression, ek_integral_constant for an integral constant +expression, ek_init_constant for a constant initializer expression +(not used in C++, except for nontype template arguments and some C++11 +expressions), ek_normal for a normal expression, or ek_sizeof +for the operand of sizeof. For the three constant expression +cases, some operators are restricted, some operand types are +restricted, and values of variables (etc.) may not be loaded. (See +the section on constant expressions.)
    +
    +
    +
    local_options
    +
    +
    +
    A bit-set of option switches that apply to just this level of +expression scanning (i.e., they do not apply to subexpressions scanned +within this expression scan). The switches control whether the comma +operator is allowed, whether the expression is being scanned as the +immediate operand of a cast, etc.
    +
    +
    +
    +

    Note that typically scan_expr_full is called through the macro +scan_expr.

    +
    +
    +

    9.2. Parsing Technique#

    +

    scan_expr_full scans an expression using a modified version of recursive +descent. The technique is “modified” in that it includes an operator +precedence level (higher precedences, numerically, bind more tightly). This +modification avoids the many levels of subroutine calls inherent in the +traditional recursive descent method. In the modified method, there is +approximately one subroutine call per leaf operand. Basically, +scan_expr_full will scan an expression up to either something it does not +understand (presumably something that follows the end of the expression), or up +to an operator that has lower precedence than the level being scanned (or equal +precedence when left-associative).

    +

    The precedence check is done by the routine token_ends_expr. One special +case: when inside a template argument list, “>” is treated as the closing +bracket for the argument list rather than the “greater than” operator.

    +

    For example, the expression 1+2*3-4 is parsed as follows:

    +
      +
    1. scan_expr_full is called with level 0. It takes the 1, then +looks at the operator +. The current level (0) is less than the +level of + (12), so scan_expr_full takes the + and calls +itself with level 12.

    2. +
    3. scan_expr_full (called with level 12) takes the 2, then looks at +the operator *. The current level (12) is less than the level of +* (13), so scan_expr_full takes the * and calls itself +with level 13.

    4. +
    5. scan_expr_full (called with level 13) takes the 3, then looks at +the operator -. The current level (13) is greater than the level of +- (12), so scan_expr_full returns the constant expression for +3.

    6. +
    7. Back in scan_expr_full (level 12, step 2 above), 2*3 is +assembled (by computing the constant result). scan_expr_full then +looks at the operator -. The current level (12) is equal to the +level of -, and - is left-associative, so scan_expr_full +returns the constant expression for 2*3 (i.e., 6).

    8. +
    9. Back in scan_expr_full (level 0, step 1), 1+(2*3) is assembled +(by computing the constant result). scan_ \expr_full then looks at +the operator -. The current level (0) is less than the level of +- (12), so scan_expr_full takes the - and calls itself with +level 12.

    10. +
    11. scan_expr_full (called with level 12) takes the 4, then looks at +the next token of input, which is something unrecognized, and returns +the constant expression for 4.

    12. +
    13. Back in scan_expr_full (level 0, step 5), (1+(2*3))-4 is +assembled (by computing the constant result). scan_expr_full then +looks at the next token of input, which is something unrecognized, and +returns the constant expression for (1+(2*3))-4 (i.e., 3).

    14. +
    +
    +
    +

    9.3. scan_expr_full Processing#

    +

    The processing within scan_expr_full is only slightly more complicated than +the description above. There are two major sections: In the first, a leaf +operand (identifier or constant), a prefix operator followed by an expression, +or an expression in parentheses (or a cast) is scanned. In the second section, +there is a loop with the above-described precedence level test at the top. So +long as the next thing in the input (whether it is a postfix operator, +subscript, function argument list, or binary operator) has an appropriate +precedence, it will be taken and added to the current expression. The loop +stops on the first thing that is not recognized or has a lower precedence. A +loop is required for expressions containing equal-precedence left-associative +operators, like 1+2*3*4+5: the *3 and *4 would be accumulated on +successive iterations of the loop in one call of scan_expr_full.

    +
    +
    +

    9.4. Scanning Identifiers#

    +

    When scan_expr_full scans an identifier, it calls scan_identifier, +which builds an operand for identifiers for enumeration constants, variables, +functions, etc. Odd C++ “names” like operator+ are also handled by +scan_identifier. The appropriate routines are called to turn them into +pseudo-identifier tokens, and thereafter the handling is the same as for other +names.

    +

    In constant expressions, variables are only allowed if they can legitimately be +part of a constant expression.

    +

    For undefined identifiers in C mode, scan_identifier enters the identifier +as an undefined identifier; shortly, the identifier will turn out to be either +truly undefined (in which case an error is generated) or will turn out to be +the name of an implicitly-declared function (in which case +decl_default_function in decls.c will be called to declare it as such).

    +

    In C++, nonstatic data members and nonstatic member functions are processed as +if preceded by “this->” (see make_this_pointer_operand). If the +identifier is a type identifier and it is followed by a left parenthesis, +scan_functional_notation_type_conversion is called to scan a type cast.

    +

    Also in C++, special considerations are made for uses of identifiers in local +classes (which can only use entities from the enclosing function in very +limited ways) and in local lambdas (which have similarities to local classes, +with the added wrinkle that references to enclosing local variables must be +interpreted as uses of fields of the associated closure class, and these fields +may have to be created as a result of these references). See +bad_nested_function_variable_ref and +make_selection_for_captured_variable.

    +
    +
    +

    9.5. Scanning Constants#

    +

    When scan_expr_full scans a constant, it calls make_constant_operand to +build the appropriate operand. Floating constants are allowed in integral +constant expressions only as the immediate operand of a cast (see +local_options, above). For string literals, +make_string_constant_operand is called instead. It produces an lvalue for +the array of characters; except in unusual cases (e.g., when the string is used +to initialize a character array), this is changed to a pointer to the string +(by conv_array_operand_to_pointer_operand).

    +
    +
    +

    9.6. Scanning Operations#

    +

    Processing for operators is done by lower-level routines. The routines are +called when the operator token has been scanned, so for non-unary operators, +this means after the left operand expression has been scanned. Most of these +routines have a structure similar to the following, which describes a generic +binary operation routine:

    +
      +
    • +
      A check is made to see if the operator is allowed in the present type of +expression (some operators, for example, are disallowed in some kinds of +constant expressions).
      +
      +
    • +
    • +
      The right operand is scanned by calling scan_expr_full with appropriate +switches.
      +
      +
    • +
    • +
      In C++ mode if either of the operands has a class type, +check_for_operator_overloading is called to see if operator overloading +applies. If it does, an appropriate operator function call is generated. +If not, the remaining steps are done.
      +
      +
    • +
    • +
      The left operand (passed in) is converted from a glvalue to a prvalue. In +cases where the left operand is supposed to be an lvalue, that is checked, +and using_lvalue or modifying_lvalue (depending on how the lvalue +is used) is called.
      +
      +
    • +
    • +
      The type of the left operand is checked.
      +
      +
    • +
    • +
      The right operand is converted from a glvalue to a prvalue.
      +
      +
    • +
    • +
      The type of the right operand is checked.
      +
      +
    • +
    • +
      The types of the operands are checked to see if they are compatible with +one another and with the operation. This sometimes selects a subcase of +the operation (e.g., pointer addition instead of integer addition).
      +
      +
        +
      • +
        For arithmetic operations, determine_arithmetic_conversions is called +to determine the usual arithmetic conversions and +change_binary_operand_types is called to promote the operand types as +necessary.
        +
        +
      • +
      • +
        For pointer operands, check_compatibility_of_pointer_operands is +called to check the operand types and do implicit type changes.
        +
        +
      • +
      • +
        For pointers to members, +check_ptr_to_member_operands_for_compatibility is called to do a +similar check.
        +
        +
      • +
      +
    • +
    • +
      which_binary_operator is called to select the proper intermediate +language operator for the operation on this type of operands.
      +
      +
    • +
    • +
      do_binary_operation is called to produce the result operand, either by +folding an operation on constants (by calling binary_operation in +folding.c, but not when not-evaluated), or by building an expression +tree.
      +
      +
    • +
    • +
      The start position of the expression is recorded in the result operand.
      +
      +
    • +
    +

    The prefix ++ and -- operators are scanned by +scan_prefix_incr_decr.

    +

    The unary operator & is scanned by scan_ampersand_operator. It usually +calls take_address_of_lvalue to produce the prvalue address result. In +pcc mode, it issues a warning for taking the address of an array, and calls +conv_array_operand_to_pointer_operand to produce address-of-array-element +instead of the ANSI address-of-array. If the operand is the qualified name of +a class member, a pointer-to-member constant is created. In C++/CLI, & +applied to an lvalue that might be on the CLR heap (as determined by +is_gc_lvalue_expr) produces an interior_ptr result.

    +

    The C++/CLI unary operator % is scanned by +scan_handle_address_operator. It produces an eok_handle_to or +eok_box operator. The result is a handle.

    +

    The unary operator * is scanned by scan_indirection_operator, producing +an lvalue or function designator as a result.

    +

    scan_arith_prefix_operator is called to scan the prefix operators +, +-, ~, and !. The unary version of the code in +do_binary_operation (fold if constant by calling unary_operation in +folding.c, else build expression node) is included directly here, since +these are all of the normal unary operators.

    +

    The sizeof operator is scanned by scan_sizeof_operator, which calls +is_decl_not_expr to decide whether or not the argument is a type name. If +it is, type_name is called to scan the type. If the argument is not a +type, it is scanned as a not-evaluated expression. The size of the type is +taken from the type entry in either case.

    +

    scan_alignof_operator is used to scan the __ALIGNOF__ construct (an +extension; similar to sizeof, but returns the alignment for a type instead +of its size).

    +

    scan_intaddr_operator is used to scan the __INTADDR__ construct (used +in the offsetof macro to scan an address expression and cast it to integral +type).

    +

    scan_noexcept_operator scans the C++11 noexcept operator.

    +

    scan_typeid scans the typeid operator. It produces an expression node +of kind enk_typeid.

    +

    scan_dynamic_cast_operator scans the dynamic_cast operator. Cases that +require runtime type determination are rendered as eok_dynamic_cast +expression nodes (or eok_ref_dynamic_cast, for casts to reference types); +the other cases are turned into ordinary casts.

    +

    scan_static_cast_operator scans static_cast.

    +

    scan_safe_cast_operator scans the C++/CLI safe_cast. It’s essentially +the same as static_cast except that it allows additional runtime-checked +cases, which are found by process_runtime_checked_safe_cast.

    +

    scan_reinterpret_cast_operator scans reinterpret_cast.

    +

    scan_const_cast_operator scans const_cast.

    +

    scan_new_operator is used to scan the new operator. The new +operation is rendered as an enk_new_delete operator tagged as a “new”, +whose supplement describes the operator new function to call plus +(optionally) some kind of initialization of the space allocated (for example, a +constructor call). For the C++/CLI gcnew, an enk_gcnew is used, and +the supplement for that includes additional information, including an +initializer. For a gcnew of a C++/CLI array, the supplement contains both +information about the array bounds (either as explicitly provided, or deduced +from the number of elements in the initializer), and an aggregate initializer +for the array elements (the latter is scanned by scan_cli_array_init). For +delegate initializers, scan_delegate_initializer scans the initializer, +which requires hand-coded checking because the delegate class doesn’t have +constructors that accurately cover the allowed initializers.

    +

    scan_delete_operator is used to scan the delete operator. The +delete operation is rendered as an enk_new_delete operator tagged as a +“delete”, whose supplement describes the operator delete function to call +plus (optionally) a destructor to call on the space being deallocated.

    +

    A left parenthesis can indicate a cast, a nested expression, or a C++17 fold +expression. scan_cast_or_expr is called for all cases. It uses +is_decl_not_expr to decide whether or not the thing following the left +parenthesis is a type name. If it is, type_name is called to scan the +type, cast_type_pre_check to check the legality of the type, and +do_cast to check and process the cast. For casts to void, an explicit +cast-to-void expression node is placed on top of the expression, as a special +marker for simplify_void_operand, but no simplification is done at this +point. In pcc mode, certain casts of lvalues leave an lvalue as the result +(see still_an_lvalue). If what is inside the parentheses is not a type, +scan_expr_full is called to scan a nested expression or the first term of a +fold expression. If it turns out to be a fold expression (or the left +parenthesis was followed by an ellipsis, which also implies a fold expression), +scan_fold_expression is called to scan the fold expression in either +generic form (during the prototype instantiation of the enclosing template) or +expanded form (during real instantiations).

    +

    The postfix ++ and -- operators are scanned by +scan_postfix_incr_decr.

    +

    Subscripting is scanned by scan_subscript_operator. The subscript is +represented by an eok_subscript operator. Constant subscripts are checked +for legality by valid_node_if_subscript or by the constant-folding +routines. When the first operand is a C++/CLI array, the contents of the [ +… ] are scanned as an expression list (no top-level comma operator is +allowed), and an eok_cli_subscript operator is used. Default indexed +properties, indexed properties, and operator[] functions can all be used to +implement the subscripting operation. Property rewrites are considered both +for the entire subscripted operation and for the first operand if it can be +converted to something subscriptable.

    +

    Function calls are scanned by scan_function_call. The function name is +entered as a default function if it is undefined (in C89 mode). The argument +list is scanned, and each argument is cast or default-promoted (see +prep_argument_operand and arg_default_promote_operand) appropriately. +The arguments are checked against the applicable function prototype or, if the +called function has an old-style declaration with a body, against the declared +old-style parameters. If the called function was declared with the pragma +__printf_args or the pragma __scanf_args, and the format string is a +constant, check_printf_scanf_arg is called for each argument following the +format string. It checks that the type of the argument matches the type of the +corresponding formatting specifier, and issues a warning if not. +assemble_function_call and make_function_call are called to put +together the actual function call. If the function is a virtual function, a +different expression operator is used; the virtual call is suppressed if the +function was named with a qualified name or if the proper function to call can +be determined statically. If the function is an overloaded function, +scan_call_arguments just builds a list of entries of type +an_arg_list_elem that describe the arguments scanned. No checking can be +done on them until the specific function to be called is identified in overload +resolution.

    +

    The operators -> and . are scanned by +scan_field_selection_operator. After the right operand (a member name) is +scanned, the processing breaks apart into several cases:

    +
      +
    • +
      For nonstatic data members (C fields), do_field_selection_operation is +called; it in turn calls fold_field_selection to fold field selection +relative to a constant address to produce another constant address. The +expression operator generated is eok_dot_field or +eok_points_to_field.
      +
      +
    • +
    • +
      For nonstatic member functions, do_member_function_selection is called. +It produces an operand for a bound function, i.e., a function bound to a +selector object.
      +
      +
    • +
    • +
      For static data members and static member functions, +combine_unneeded_selector_with_operand is called, and it generates an +eok_dot_static or eok_points_to_static operation.
      +
      +
    • +
    +

    For nonstatic members, cast_pointer_for_field_selection is called to cast +the left operand pointer to a base class if necessary.

    +

    The operators ->* and .* are scanned by +scan_ptr_to_member_operator. For member function cases, the result is a +bound member function. For data member cases, an eok_pm_field or +eok_pm_points_to_field operation is generated.

    +

    The operators *, /, and % are scanned by scan_mult_operator.

    +

    The operators + and - are scanned by scan_add_operator.

    +

    The operators >> and << are scanned by scan_shift_operator.

    +

    The operators >, <, <=, and >= are scanned by +scan_rel_operator, and the operators == and != are scanned by +scan_eq_operator.

    +

    The operators &, ^, and | are scanned by scan_bit_operator.

    +

    The operators && and || are scanned by scan_logical_operator, and +the operator ? (and the associated :) is scanned by +scan_conditional_operator. When these operators have constant operands for +the boolean controlling expressions, some operands will be scanned as +not-evaluated expressions, and the result tree is (conditionally) simplified +accordingly.

    +

    The operator “,” is scanned by scan_comma_operator. Note that the +comma operator is not allowed at the top level in initializer expressions and +in argument lists, because it means something else in those contexts; see the +local_options parameter of scan_expr_full.

    +

    scan_simple_assignment_operator scans the operator =. It calls +prep_assignment_operand to check and convert the right operand in most +cases. Assignment to “this” is recognized as a special case and +allowed with a warning.

    +

    scan_compound_assignment_operator scans compound assignment operators +(+=, -=, et al.).

    +

    Lambda expressions are scanned by scan_lambda_expression. The actual +parsing is handed to scan_lambda in class_decl.c, and +scan_lambda_expression constructs the required temporary initialization +from the resulting a_lambda entry. (See also Scanning Identifiers for +special measures needed when parsing identifiers in a lambda body.)

    +
    +
    +

    9.7. Operand Data Structure#

    +

    Throughout the expression routines (and nowhere else), all the information +about an operand is maintained in an entry called an_operand. The operand +contains the type of the operand, its “kind” (indicating the way in which the +operand is represented, i.e., as a constant or an expression tree), its “state” +(none, glvalue, prvalue, or function designator), and its source position. +Variables of type an_operand are typically stack-based variables within the +expression routines. They are never allocated in the intermediate language +memory region.

    +

    An lvalue is an object in memory; an rvalue is a value, with no associated +memory location. The distinction between lvalues and rvalues is very important +in the C language. [1] Names of variables start out as lvalues, and if +their values are used, they are implicitly converted to rvalues. C++11 adds +xvalues, which are eXpiring values produced by certain rvalue reference +operations. They share an operand state with lvalues, since the two are very +similar (they have addresses, possibly cv-qualified types, dynamic type, object +identity). They can be distinguished with the is_an_lvalue() and +is_an_xvalue() tests. Lvalues and xvalues are collectively known as +glvalues. The things formerly known as rvalues in C and in pre-C++11 C++ are +now known in C++11 as prvalues, and prvalues and xvalues collectively are now +known as rvalues.

    +

    The expression scanning routines attempt to model the C++11 concept of “value +categories” exactly, and the an_operand entry plays a part in that. [2] +It is always clear from the operand whether an expression is currently an +lvalue, xvalue, or prvalue, and the transformation from glvalue to prvalue is +done deliberately and when appropriate (see conv_glvalue_to_prvalue).

    +

    For functions, the equivalent of an lvalue is a function designator, and +there is a representation for those in an_operand.

    +

    In the C++ language definition, the term “lvalue” includes C’s function +designator as well as C’s lvalue, but in this implementation and this +documentation we use the term with the narrower C meaning.

    +

    When the operand representation is an expression, the operand points to an +expression tree in an intermediate language memory region. When the operand +representation is a constant, however, the constant is contained directly in +the operand (it is not allocated). This allows the expression routines to scan +constant expressions and fold them to constant results without allocating and +throwing away useless intermediate constant entries.

    +

    When an operand represents a bound function, that is, a C++ member function +with an associated object, the operand has the bound_function flag set. A +second operand is used to describe the associated object. There’s no direct +link between the two; the expression routines must carry around two operand +entries.

    +

    When expressions appear in a comma-separated list, such as an argument list, +the operands on the list are often represented as entries of type +an_arg_list_elem. Such entries can represent either an expression (in +an_operand form), or a brace-enclosed list, the latter being needed for the +C++11 “initializer lists” feature.

    +

    The C++/CLI ECMA standard mentions the concept of a “gc-lvalue,” and defines +conversions between normal lvalues and gc-lvalues. It turns out those concepts +are not needed, at least not in the suggested way, and no added kind of lvalue +is needed in an_operand entries. The important principle is that the +language must never allow the address of something that might be on the CLR +heap to be placed in a normal pointer where the garbage collector cannot find +it. So, whenever the address of something that might be in the CLR heap is +taken, the address must be placed in an interior_ptr or a pin_ptr, both +which are visible to the garbage collector. The functions +is_gc_lvalue_expr and is_gc_lvalue_operand test for lvalues that might +be in the CLR heap; if they return TRUE, the address of such an entity is made +an interior_ptr.

    +
    +
    +

    9.8. Primitive Operations on Operands#

    +

    Many routines exist to do primitive operations on operands. Routines that +perform initialization are

    +
      +
    • +
      set_operand_kind and
      +
      +
    • +
    • +
      clear_operand.
      +
      +
    • +
    +

    Constructors for the various kinds of operands are

    +
      +
    • +
      make_constant_operand,
      +
      +
    • +
    • +
      make_string_constant_operand,
      +
      +
    • +
    • +
      make_integer_constant_operand,
      +
      +
    • +
    • +
      make_expression_operand,
      +
      +
    • +
    • +
      make_glvalue_expression_operand,
      +
      +
    • +
    • +
      make_indefinite_function_operand,
      +
      +
    • +
    • +
      make_sym_for_ptr_to_member_operand,
      +
      +
    • +
    • +
      make_lvalue_variable_operand,
      +
      +
    • +
    • +
      make_ptr_to_member_constant_operand,
      +
      +
    • +
    • +
      make_function_designator_operand, and
      +
      +
    • +
    • +
      make_field_operand.
      +
      +
    • +
    +

    Routines that create operands for one- and two-operand expressions are

    +
      +
    • +
      build_unary_result_operand and
      +
      +
    • +
    • +
      build_binary_result_operand.
      +
      +
    • +
    +

    Error operands are created for parts of expressions containing errors by

    +
      +
    • +
      make_error_operand,
      +
      +
    • +
    • +
      conv_to_error_operand,
      +
      +
    • +
    • +
      error_in_operand, and
      +
      +
    • +
    • +
      error_and_make_error_operand,
      +
      +
    • +
    +

    which differ in whether or not they issue errors, and where. +make_node_from_operand converts an operand to an equivalent expression +tree.

    +
    +
    +

    9.9. Checking Operands#

    +

    op_is_zero_constant tests for a zero operand. There is also a set of +check_... routines, which are called to verify that an operand has certain +attributes, and if not, issue an error and change the operand to an error +operand:

    +
      +
    • +
      check_modifiable_lvalue_operand,
      +
      +
    • +
    • +
      check_integral_operand,
      +
      +
    • +
    • +
      check_integral_or_enum_operand,
      +
      +
    • +
    • +
      check_integral_or_enum_or_fixed_point_operand,
      +
      +
    • +
    • +
      check_arithmetic_operand,
      +
      +
    • +
    • +
      check_pointer_operand,
      +
      +
    • +
    • +
      check_object_pointer_operand,
      +
      +
    • +
    • +
      check_function_pointer_operand,
      +
      +
    • +
    • +
      check_scalar_operand.
      +
      +
    • +
    +

    check_boolean_controlling_expression checks that an expression controlling +a conditional is a scalar expression, and in C++ modes that don’t disable the +bool keyword, it converts the expression to bool.

    +
    +
    +

    9.10. Transformations on Operands#

    +

    Several routines handle transformations on expressions defined by the standard:

    +
      +
    • +
      conv_glvalue_to_prvalue changes a glvalue to a prvalue. Several +special cases are handled. Type qualifiers on the glvalue type are removed +to make the prvalue type. Most of the work for expression cases is handled +by conv_glvalue_expr_to_prvalue. conv_glvalue_to_prvalue calls +using_lvalue to do the error check for using the element just past the +end of an array; it also generates an error if it is called to convert a +glvalue in a constant expression.
      +
      +
    • +
    • +
      conv_array_operand_to_pointer_operand changes an array to a pointer to +the first element of the array.
      +
      +
    • +
    • +
      conv_function_designator_to_ptr_to_function changes a function +designator to a pointer to the function.
      +
      +
    • +
    +

    do_operand_transformations is a convenient way to request the preceding +three transformations. It can do any or all of them.

    +

    Note that in C++ operand transformations often cannot be done until one knows +the way in which an expression will be used. In an expression like arr + +xx, for example, with arr an array, one cannot convert the array to a +pointer until one has ruled out the possibility that this operation is an +overloaded use of operator “+” with a function for which the first +parameter is a reference to an array. In C, the transformations can often be +done earlier, but for ease of handling they are delayed as in C++.

    +
      +
    • +
      promote_operand handles the integral promotions (C standard, 6.3.1.1); +these are done only where explicitly called for.
      +
      +
    • +
    • +
      determine_arithmetic_conversions handles the usual arithmetic +conversions (C standard, 6.3.1.8). In pcc mode, the promotions are +unsigned preserving (e.g., unsigned char is promoted to unsigned +int), and all float operations are forced to double. To +determine integral promotion types type_after_integral_promotions (in +types.c) is called; a special case involving bit-fields is handled by +type_after_bit_field_integral_promotion.
      +
      +
    • +
    • +
      arg_default_promote_operand does the default argument promotions on an +operand (C standard, 6.5.2.2).
      +
      +
    • +
    • +
      take_address_of_lvalue converts an lvalue to a prvalue pointer to the +object. This is the & operator for objects. It checks for taking the +address of a bit field or a register variable. +take_reference_to_operand does the similar operation for a reference +binding.
      +
      +
    • +
    +

    When fixed-point types (an Embedded C extension described in ISO/IEC TR 18037) +are enabled, transformations of fixed-point operands are also performed as +needed. For example, in arithmetic operations involving both a fixed-point and +a floating-point operand the fixed-point operand is converted to a +floating-point type. However, unlike most other mixed-type operations, +operations involving a mix of fixed-point and integer operands do not cause the +conversion of the operands to a common type.

    +
    +
    +

    9.11. The Expression Stack#

    +

    While expressions are being scanned, the expression routines maintain an +expression stack. This stack snakes through local stack frames (i.e., it is +not allocated via malloc). The expression stack contains information on +the kind of expression being scanned, whether or not the expression is being +evaluated (e.g., the operand of a sizeof is not evaluated), and some other +minor information.

    +

    There is a new stack entry for each major kind of expression scanned, but not +for each level in the expression. That is, if one started on a normal +expression, an entry would be placed on the stack; no new entries would be +added for parentheses or grouped operators in the expression; but if a sizeof +expression, or an integral constant expression in an array size in a type in a +cast, is reached, a new entry would be placed on the top of the stack.

    +

    See push_expr_stack and pop_expr_stack.

    +
    +
    +

    9.12. Expression Lists and Initializer Lists#

    +

    The C++ language, as of the C++11 revision, uses lists of expressions in two +contexts:

    +
      +
    • +
      argument lists of function calls (syntax term expression-list), for +example “f(x, 2)”, and
      +
      +
    • +
    • +
      initializer lists (syntax term initializer-list), for example +initializers of variables as in “A a{x, 2};”.
      +
      +
    • +
    +

    Those contexts at first glance might seem to have little in common other than +the fact that they involve lists of expressions. However, the standard ties +the use of variadic template pack expansions and the use of brace-enclosed +initializer lists to those expression-list contexts, and in some cases +initializer lists become argument lists for constructor calls. So, in the end, +it becomes appropriate and desirable to represent both kinds of expression +lists with the same data structure and to process them with many of the same +routines.

    +

    The data structure used is an_init_component, which can represent

    +
      +
    • +
      an expression, e.g., “x”, in an_operand form, or
      +
      +
    • +
    • +
      a braced-enclosed list, e.g., “{1, 2, 3}”, as a pointer to a list of +init-component entries, or
      +
      +
    • +
    • +
      a designator, e.g., an array element designation like “[1]=” in an +aggregate initializer, or
      +
      +
    • +
    • +
      a continuation state to resume parsing when parsing of an initializer list +was suspended (see below).
      +
      +
    • +
    +

    In initializer processing, e.g., in decl_inits.c and expression routines +that interface with that, the name an_init_component is used. In routines +that are more related to argument lists and overload resolution, on the other +hand, the name an_arg_list_elem is used instead. It’s a typedef to the +same type, but it reflects a slightly different view of what the structure +represents. In practice, the line between the two is a bit fuzzy, and +especially with some lower-level routines the naming has to choose one or the +other name and is therefore somewhat arbitrary. Probably the main thing to +remember is that both names are used for the same data structure, with the +expression routines using the an_arg_list_elem name somewhat more often, +and the initializer routines using an_init_component exclusively. About +the only real difference that can be pointed out is that an argument list +referred to via an_arg_list_elem will never have a designator on the list.

    +

    Init-component entries are linked together into lists and trees. Something +like “{1, {2, 3, 4}}”, for example, creates a braced-init-list component +pointing to a list of two entries, the second of which is a braced-init-list +component pointing to a list of three expression components.

    +

    The essence of the initializer lists feature in the language is that the same +notation can be used for initializations that are ultimately interpreted in +many different ways. Therefore, the handling of initializer lists inherently +involves a two-step process: first, parsing the source into a tree of +init-component entries, and then interpreting those entries by context as +describing calls and initializations of various kinds. At the simplest level, +the initializer processing calls scan_braced_init_list first to scan an +entire braced-init-list, and then convert_initializer to convert it to the +type of the entity being initialized. The real work in scanning +braced-init-lists is done by parse_braced_init_list_full and its +subroutines.

    +

    In some cases the front end will process a very long braced initializer list in +parts to avoid tying up too much memory in init-component entries (which are +transient front end structures). It does this by suspending and resuming the +parsing of the initializer (repeatedly if needed) and using placeholder +init-component entries (of kind ick_continued) that point to some state +information sufficient to resume parsing later on. This is fairly transparent +to the routines processing init-component entries, but requires that those +routines use macros like next_elem and is_last_elem rather than +directly access the next pointers of init-component entries. This is only +possible for traditional aggregate initializers, but it is a worthwhile +optimization because occasionally programs contain initializers with thousands +or even millions of elements.

    +

    So some expression routines deal with an init-component (or list or tree of +them) as the “source” for an initialization. And some routines will scan an +expression or braced-init-list in init-component form to do lookahead, and then +place the init-component entry in an initializer cache, later to be fetched +out of there as if it had been freshly scanned from source. That’s used, for +example, for declarations with “auto” type; an expression is scanned so its +type can be used for the auto type deduction, and the expression is then +put into the initializer cache so it will be picked up at the appropriate time +later.

    +

    Because expression components are scanned at one point and then revisited later +for processing, some of the context information for them must be saved along +with the init-component entries. In particular, because it’s not known at the +time of scan where the full-expression boundaries will fall, each expression is +scanned in its own invented lifetime, and is “bundled” with that lifetime in +the init-component. When the expression is removed from the list later for +additional processing, the lifetime is reactivated or subsumed into an existing +lifetime. Likewise, the cross reference entries associated with an expression +are detached from the current expression and saved in the init-component, and +then reactivated when the expression is processed further. This allows things +like tracking of whether a variable is ultimately used as an lvalue or rvalue. +(See scan_expr_as_init_component for the bundling code, and +extract_operand_from_expression_component and +unbundle_init_component_expressions for the unbundling.)

    +

    The processing when a braced-init-list meets a destination type is handled by +convert_initializer (callable from outside the expression routines) and +prep_list_initializer (callable only from within the expression routines). +The latter does the real work. It has some significant subroutines:

    +
      +
    • +
      make_initializer_list_object makes an object of type +std::initializer_list<T> from a braced-init-list, which involves a call +to a constructor of initializer_list passing an array containing the +element values.
      +
      +
    • +
    • +
      value_initialization handles value-initialization, which is usually the +result when the braced-init-list is an empty list, “{}”.
      +
      +
    • +
    • +
      check_narrowing_conversion checks for the “narrowing” conversions, +issuing appropriate diagnostics.
      +
      +
    • +
    +

    prep_list_initializer operates in one of three modes:

    +
      +
    1. Producing an_operand result. This is the usual mode for internal calls +in the expression routines.

    2. +
    3. Guided by an_init_state, producing either a dynamic init entry or a +constant as a result. This is the usual mode for calls that come from +initializer processing by way of convert_initializer. This mode can +be modified to produce no diagnostics or generate no IL, which is used +for SFINAE analysis.

    4. +
    5. Doing overload resolution analysis, producing a result in an entry of +type an_arg_match_summary. That is used when evaluating arguments in +overload resolution, and in that mode no errors are issued, no IL is +generated, and the source init-components are not modified (in other +words, it’s purely exploratory).

    6. +
    +

    All processing for aggregates, i.e., arrays and aggregate classes, is done by +code in decl_inits.c. prep_list_initializer calls +prep_aggr_initializer to handle aggregate initialization from a +braced-init-list, and the initializer processing routines will call back into +the expression routines as necessary. In certain cases, processing will hop +back and forth between the two areas repeatedly. In those cases, the +an_init_state structure is used to convey information across the +transitions, e.g., to record something that expression processing knows so that +as the transfer or control goes to the decl_inits.c routines and back into +expression processing that information is still known.

    +

    The expression routines have to be quite careful about whether they are dealing +with a single expression or (a member of) an expression list, and that is made +easier by using different structures to represent those, i.e., an_operand +for a single expression, and an_arg_list_elem for (a member of) an +expression list. There are some rare cases in the C++11 language where a +brace-enclosed list is allowed in a context where a single expression is +allowed, and in those cases an_operand of kind ok_braced_init_list is +constructed, which points to an init-component list. That allows a lot of the +existing routines to accept a braced-init-list in some limited cases. To give +one example, the assignment operators allow a braced-init-list as their second +operand, even though that’s not an expression list context. So, if a +braced-init-list is present, it is scanned as an operand (see +scan_braced_init_list_as_operand) and passed around in that form to the +usual routines. When it gets to the operator-overloading routine +check_for_operator_overloading, that routine is prepared to unpack that +operand and use the braced-init-list in overload resolution. There are also +some cases when rescanning expressions (see below) where a braced-init-list +operand is constructed so that a braced-init-list can be returned through an +interface that is designed for single operand expressions.

    +

    The an_arg_operand data structure, which in the past was used for operands +in argument lists, is now reserved for a few cases where a single +non-expression-list expression needs to be returned to a caller outside the +expression routines, specifically for nontype template arguments values.

    +

    In most cases, there is no direct IL representation for initializer lists, +because when a braced-init-list meets a destination type it is converted to +some expression form that is no longer a braced-init-list. (For example, it +might become a dynamic init for a constructor call, or a nonconstant aggregate +dynamic init.) However, in prototype instantiations of templates there may be +braced-init-lists that have not met a real destination type and therefore +cannot be interpreted yet, and those must remain in braced-init-list form. For +those, the enk_braced_init_list expression node kind is used. It points to +a list of expressions, some of which may themselves be enk_braced_init_list +nodes.

    +
    +
    +

    9.13. Constant Expressions#

    +

    Constant expression processing has two fairly different modes:

    +
      +
    1. In C mode, and in C++ mode prior to C++11, each constituent of an +expression is checked immediately to see whether it is allowed in a +constant expression. An error is issued if not. So, for example, the +appearance of a throw operator in a constant expression draws an +immediate error. Class-typed values are never allowed, and neither are +user-defined conversions. This mode is referred to as the “traditional +constant expression” mode (see, for example, +curr_expr_kind_is_traditional_const).

    2. +
    3. In C++11 (roughly, when constexpr_enabled is TRUE), what matters is +whether the expression overall folds to a constant, regardless of the +constituents of the expression. So, for example, “1 ? 2 : i” is a +valid C++11 constant expression: the reference to “i” is not +evaluated and does not rule out a constant expression. Class-typed +constant values (of “literal” type) are allowed, and so are user-defined +conversions using constexpr functions. This mode is referred to as +the constexpr mode. (A variation of that mode, known as “relaxed +constexpr mode”, is enabled in C++14 mode. See also +Folding and constexpr.)

    4. +
    +

    In both modes, references to constant-valued variables and operations on +constant operands are folded as soon as they can be, [3] and a constant +value is passed up to the next level, so the basic processing is very much the +same. The main differences are:

    +
      +
    • +
      In traditional constant expressions, many operator-scan routines check +immediately on entry whether the operator they handle is valid, and issue +an error if not. In C++11 constant expressions, the check is done by +calling operator_not_allowed_in_cpp11_constant_expr (or +construct_not_allowed_in_cpp11_constant_expr), which issues no error in +unevaluated parts of expressions.
      +
      +
    • +
    • +
      Various routines that handle looking for user-defined conversions (e.g., +check_user_defined_conversions_for_cast) allow user-defined conversions +when constexpr_enabled is TRUE.
      +
      +
    • +
    • +
      Calls, including constructor calls, can be folded to constants. This is +done by first building the normal IL for the call and then, if the function +or constructor involved is constexpr, seeing whether the call can be +folded to a constant. This is done by expr_fold_constexpr_call and +expr_fold_constexpr_ctor. Implicit calls, like conversion function +calls, can also be folded to constants. If backing expressions are being +recorded, the original IL for the call is recorded as the backing +expression for the result constant.
      +
      +
    • +
    • +
      Both modes require tracking, in non-constant expressions, of whether the +expression makes use of anything not allowed in a constant expression. +[4] In traditional constant expressions, the kinds of expressions ruled +out are tracked at the an_operand level (see the +ruled_out_expr_kinds set and the rule_out_expr_kinds routine), and +for specific kinds of constant expressions (e.g., integral constant +expressions). In C++11 constant expressions, a single boolean flag called +constant_expr_ruled_out is maintained in the expression stack, and +there’s effectively only one kind of constant expression. (Note, however, +that in C++11 mode some kinds of expressions are scanned as traditional +constant expressions, e.g., preprocessor expressions and nontype template +argument address expressions, because the C++11 language rules still impose +many restrictions on the kinds of operators that can be used in them.)
      +
      In certain contexts, the rules about what is ruled out are relaxed +slightly. Specifically, in contexts that will later be subject to +parameter substitution in constexpr call evaluation, a use of the value +of a parameter variable does not rule the expression out as a potential +constant expression (because in a real evaluation, the parameter might have +a constant value). Those contexts (the return expression of a +constexpr function, the mem-initializers of a constexpr +constructor, and the field initializers of a literal class) are identified +by in_potential_constant_constexpr_context.
      +
      When init-components are used, expression processing is often done in two +steps: first, the expression is scanned into an init-component, and then +the init-component is converted to the final required type. In those +cases, the constant_expr_ruled_out flag is copied from the expression +stack into the init-component, and then back from the init-component to the +expression stack when the conversion processing is started.
      +
      +
    • +
    • +
      In several contexts, the C++11 standard calls for a “converted constant +expression” of a given type (for example, an array bound is a converted +constant expression of type size_t). This is implemented by +process_converted_constant_expression. The required type can be a +specific type, like size_t, or a general category of types, like +integral types. In traditional constant expressions, that routine just +scans a constant expression and converts it as necessary, not allowing +user-defined conversions. In C++11 mode, it allows user-defined +conversions but imposes a restriction on the types of implicit conversions +allowed at the end (e.g., not “narrowing” conversions). The C++11 rules +are therefore broader overall but more restrictive in certain cases. The +set of allowed implicit conversions is defined by +impl_converted_constant_expr_conversion_possible.
      +
      +
    • +
    • +
      constexpr calls and constructions in constant expressions produce a +constant result directly, i.e., not a temporary initialized by a constant, +but other temporaries (e.g., a temporary needed to bind “const int &” +to an integer constant 2) are created as usual. Processing within +folding fetches the value out of the temporary if appropriate, or creates a +special compile-time temporary using a ck_address/abk_temporary +constant that holds the necessary constant value. Operations that cannot +be converted to those forms are left as initialization of a temporary, +which is considered non-constant.
      +
      +
    • +
    +
    +
    +

    9.14. Rescanning Expressions#

    +

    The C++11 standard introduced some new rules for template deduction (see +WG21 paper N2634). +When a function template is considered in overload resolution, part of the +process is “template deduction,” which is an attempt to find values for the +template parameters of that template that will specify a template instance +that is a viable function for the call. The deduction rules require that +any expressions that appear in the template type be valid after +substitution of the deduced template arguments for the template parameters. +Whereas in older versions of the standard “valid” was defined by a specific +list of requirements, and only relatively simple expressions were allowed, +the C++11 rules now allow arbitrarily complex expressions inside +unevaluated contexts (e.g., sizeof and decltype), and “valid” is +defined by the normal semantic rules of the language, except that access +checking is not done. So, for example:

    +
    template <class T> auto f(T p1, T p2) -> decltype(p1 + p2) {
    +  return p1 + p2;
    +};
    +struct A {
    +  const A & operator +(const A&);
    +};
    +A a1, a2;
    +int main() {
    +  f(a1, a2);
    +}
    +
    +
    +

    Here, the call is valid only if the expression “p1+p2” is valid, which is +true only if there is a valid meaning for the “+” operator, possibly found +by doing overload resolution as in this case. Any error detected during this +process should cause only a failure of deduction for that template, and not a +hard error. (This idea is summarized in the acronym that is often used to +refer to this non-error-producing deduction process, SFINAE, which stands for +Substitution Failure Is Not An Error.)

    +

    To implement this, the Front End is capable of “rescanning” expressions to redo +the semantic checking on them. An expression saved during the initial scan of +a template is copied, with substitution of template argument values for +template parameters, and is then passed through the normal +expression-processing routines in order to do everything that would have been +done to that expression after scanning it from source tokens. A key part of +the infrastructure for performing that is that almost all operator-scanning +routines have an rcblock parameter, which can be used to pass in a rescan +control block. When that parameter is non-NULL, it gives information about the +expression to be rescanned, the template arguments and template parameters, and +some options. The operator scan function tests rcblock each time it is +about to get something from source tokens, and when rcblock is non-null it +instead uses the previously-scanned IL expression to produce the same +information in the same form. That information then passes through the parts +of the operator routine that handle semantic checking, implicit conversions and +transformations, etc., undergoing exactly the processing it would have received +if scanned from source.

    +

    Because IL expressions don’t contain all the information that was available +when the expression was originally scanned, additional information (in the form +of an_expr_rescan_info_entry) is saved whenever an expression is scanned in +a context that might later be subject to a rescan (essentially, in function +template headers). That rescan information includes a copy of the +an_operand entry that represented the IL expression, and a bit of +additional information like the operator source position.

    +

    When deduction is being done, if expr_is_rescannable is true for an +expression, it is passed to rescan_expr_with_substitution_internal, which +determines the operator-scanning function that corresponds to the top operator +of the expression (see operator_token_for_expr_rescan) and then calls that +operator-scanning function. The scanning function will then do substitution +and rescanning on its operands (see make_rescan_operands), followed by the +semantic checking and processing it usually does, before returning an operand +back to its caller, which will continue through the rescan process. If an +error occurs, the error flag in the rescan control block is set, and once the +processing returns to the top level the deduction fails.

    +

    The expression rescanning code co-exists with the older code that handled +SFINAE processing for many years before this change, e.g., routines like +copy_template_param_expr. Those routines are still used when new-style +SFINAE is turned off (see cpp0x_sfinae_enabled), and also for parts of +expressions that aren’t rescannable.

    +

    For braced-init-lists, a copy of the original list in init-component form is +saved in the rescan info operand (see +save_rescan_info_for_braced_init_list). On the rescan, that list is +rescanned. As with all rescans, the source of the rescan is mined for +source-like information, and a lot of other information is ignored. That +means, for rescanned braced-init-lists, that the original list is not modified +or really “used” – it’s a guide for the rescan as opposed to a source of +expression operands to be used directly.

    +

    Making rescanning work requires some special coding conventions in +expression-processing routines:

    +
      +
    1. The error-reporting routines cannot be called directly. Instead the +corresponding routines beginning with “expr_” must called. So, for +example, instead of “pos_error” one must call +“expr_pos_error”. This allows the interception of error calls so +that they set a flag in the expression stack instead of issuing an +error.

    2. +
    3. Code that checks access must be conditional on +expr_access_checking_should_be_done(). Note that it’s usually +necessary to avoid the access checks altogether rather than doing them +and getting to the point where an error would be issued, in order that +complete and correct IL is generated.

    4. +
    5. Calls out to utility routines in other parts of the front end must not +generate errors (unless those errors come from handling something +outside of the expression; for example, it’s okay to issue an error out +of a template instantiation that is kicked off by the expression +processing). If those utility routines might generate errors, they must +have parameters that can be used to get an error return instead of +having an error issued. For an example, see binary_operation in +folding.c and its error_detected parameter.

    6. +
    7. Scanning routines for added operators must have an rcblock +parameter, to indicate the rescan. Within such routines, all processing +that deals with source tokens must have a rescan alternative that pick +up the information from the expression being rescanned. As a general +guideline, beware of using curr_token, pos_curr_token, +end_pos_curr_token, locator_for_curr_id, +const_for_curr_token, curr_construct_ end_position, +error_position, and the error-reporting routines that use an implied +position.

      +

      Near the end of the scanning routine, call +record_operator_position_in_rescan_info to record the operator +position in the rescan information for the expression.

      +

      The scanning routine should be added to +operator_token_for_expr_rescan and +rescan_expr_with_substitution_internal so it will be rescannable. If +an operator scanning routine is not added to those routines, it will not +be rescannable, and if it comes up in a deduction context the deduction +will simply fail. That may be acceptable for certain kinds of +operators.

      +
    8. +
    9. Note that none of these restrictions are necessary for features used +only in C mode, but may be desirable anyway to allow the option of using +that feature in C++ mode at some later date.

    10. +
    +
    +
    +

    9.15. Void Expressions#

    +

    When a void expression has been scanned, either by scan_void_expression or +as the first operand in scan_comma_operator, simplify_void_operand is +called to trim off any parts of the expression that have no effect. This +trimming is done very conservatively, however. Top-level casts to void are +removed. Other kinds of trimming could be done, but they are not in the +interest of preserving the source expression. simplify_void_operand issues +a warning for expressions that have no overall effect. (See +node_has_side_effects.)

    +

    Expressions that are explicitly cast to void are not processed as void +expressions at the time of the cast; a cast-to-void node is placed on top of +the expression, and the expression is handed up. If the node makes it up to +the top level, it is simplified and the cast-to-void node is removed. Casts to +void can remain in the final intermediate language, but only in rare cases +(such as

    +
    i>0 ? (void)f(1) : (void)g(2)
    +
    +
    +

    as a statement).

    +
    +
    +

    9.16. Type Conversions#

    +

    Type conversions happen implicitly (in assignments and initializations) and +explicitly (in casts). Either way, they are done under control of the +expression routines. And they must be: in C++, conversions involve not just +the type of an expression, but whether it is and stays an lvalue or an rvalue, +and whether or not other implicit transformations may be done. The data +structure that can express these concepts is an_operand, and it exists only +within expr.c, exprutil.c, and overload.c.

    +

    To scan and process an expression correctly, one needs to know what will +ultimately be done with it, specifically what type it will be converted to. +Therefore, in all cases involving conversion, all necessary information about +the destination is passed into the expression routines, and they take care of +the conversion. By the time the expression is returned to the caller, it has +the correct type.

    +

    The routines that control these conversions have names beginning with +“prep_”:

    +
      +
    • +
      prep_conversion_operand deals with the general assignment or +initialization case.
      +
      +
    • +
    • +
      prep_initializer_operand deals with initialization. Its interesting +special case is initialization of references.
      +
      +
    • +
    • +
      prep_elision_initializer_operand deals with initialization of entities +with class types that have constructors, where it may be possible to avoid +a copy constructor call.
      +
      +
    • +
    • +
      prep_argument_operand deals with initialization when it applies to +arguments. Its interesting special case is generating copy constructor +calls for class values passed by value.
      +
      +
    • +
    • +
      prep_return_by_cctor_operand deals with expressions in return +statements (also considered an initialization case), specifically in +routines that return class values by calling a copy constructor. A dynamic +initialization entry describing the initializing operation is built and +returned to the caller.
      +
      +
    • +
    • +
      prep_assignment_operand deals with the right-side expressions in +assignments.
      +
      +
    • +
    +

    In general, these routines do their work in two parts:

    +
      +
    • +
      They determine whether or not the source operand can be converted to the +destination type, and if so, how. This is done by calling +conversion_possible.
      +
      +
    • +
    • +
      If the conversion is valid, they do it, by calling convert_operand.
      +
      +
    • +
    +

    conversion_possible uses impl_conversion_possible (from types.c) to +see if a standard conversion if available to do the conversion); if not, it +calls user_defined_conversion_possible to see if a user-defined conversion +can be done.

    +

    user_defined_conversion_possible calls conversion_to_class_possible to +check for constructors and conversion_from_class_possible to check for +conversion functions that might be applicable.

    +

    convert_operand calls cast_operand for simple conversions, and +user_convert_operand for user-defined conversions.

    +

    cast_operand and cast_node are called to change the type of an +operand or expression node. (cast_operand is actually just a wrapper +on top of cast_operand_full, which does the real work.) The caller of +those routines must have already determined that the conversion is valid. +If the cast is implicit and if it does not change the type of an operand, +that operand is usually left alone. (An exception are casts on bit fields, +because a bit-field access that has no cast on it has slightly different +properties – especially with respect to promotion – from the same access +with a cast on top.)

    +

    If the operand is a constant, type_change_constant is called to fold the +conversion.

    +

    If the operand is an expression, add_cast_to_node is called to add a cast +to the expression tree. For casting a pointer-to-class to a +pointer-to-related-class it calls add_base_class_casts or +add_derived_class_casts, and for the similar cases involving pointers to +members, it calls add_pm_base_class_casts or +add_pm_derived_class_casts.

    +

    The routines that scan explicit casts use several lower-level routines:

    +
      +
    • +
      check_user_defined_conversions_for_cast looks to see if a cast performs +any user-defined conversions, and if so applies them.
      +
      +
    • +
    • +
      set_up_for_cast_to_reference does some checking and setup in the cases +where the cast is to a reference type.
      +
      +
    • +
    • +
      cast_operand_for_reference_cast is like cast_operand, but for cases +where the operand is being cast to a reference type (including an rvalue +reference type).
      +
      +
    • +
    • +
      generic_cast_operand performs a cast when either the source operand or +the destination type involves something template-dependent in a prototype +instantiation. In such cases, it’s not generally possible to know what the +cast does, and we just want to put a generic representation of it in the +IL.
      +
      +
    • +
    +

    In C++/CLI, string literals start out as standard C++ string constants, and are +converted to C++/CLI strings if the context requires it. So, for example, if a +standard string literal is passed as an argument to a function that takes a +parameter of type “System::String^”, the string will be converted to +a C++/CLI string. This is done by setting the constant type to “handle to +System::String” without setting the implicit_cast flag. There is no +conversion of the characters in the string to Unicode (or in any other way), in +spite of what the ECMA standard seems to require. Wide string literals can +also be converted to C++/CLI strings in this way, and in that case the string +contents are treated as Unicode (as they always are in Microsoft mode, and +therefore in C++/CLI mode; but still no conversion is done). Having C++/CLI +strings represented as constants is a little strange, since ultimately they +have to result in creation of a class object on the heap, and use of its – +non-constant – address. However, MSVC treats such strings as constants, so +representing them that way makes it easier to emulate MSVC’s behavior. See +literal_type_convertible_to_cli_string, +is_literal_convertible_to_cli_string, and +convert_operand_to_handle_to_cli_string.

    +

    C++/CLI also allows boxing and unboxing conversions, i.e., between a value of a +value type and (a handle to) a boxed value in the CLR heap. Boxing can be +either an implicit conversion or a cast; unboxing is always done explicitly by +a cast. Operands having fundamental types will be implicitly converted to a +boxed value in cases where a class is required, e.g., in an example like +“(3).toString()”, or when they are implicitly converted to an appropriate +handle type. Significant routines for boxing and unboxing are +is_boxable_type, add_box_to_expression, add_unbox_to_expression, +box_value_type_operand, and unbox_after_indirection_if_required.

    +
    +
    +

    9.17. Temporaries#

    +

    create_expr_temporary creates an enk_temp_init node that defines a +expression temporary. It hangs a dynamic initialization entry under that node +and, if the temporary will require a destructor call, puts the destructor +information in the dynamic initialization entry.

    +

    alloc_dtor_dynamic_init is the routine that actually allocates the dynamic +initialization entry for the temporary. If the temporary is within the +expression in a return statement in a routine that returns its value via a copy +constructor, the destructor routine is recorded in the dynamic initialization +entry, but the destructor routine is not marked as referenced. This is because +the topmost initialization in the return expression should not indicate a +destructor (the caller does the destruction), but one cannot know at the time +the dynamic initialization entry is created whether or not it will end up being +the topmost one. Therefore, all entries are given destructors, but the +destructor routines are not marked as referenced. Each such dynamic +initialization is placed on a fixup list. After the entire expression is +processed, the destructor indication is cleared in the topmost initialization, +and fix_up_dynamic_init_dtors is called to revisit the dynamic +initialization entries and mark the (remaining) destructors as referenced.

    +

    temp_init_from_operand creates a temporary variable and initializes it from +a given operand value.

    +

    convert_operand_into_temp creates a temporary variable and initializes it +from a given operand value where there might be type conversion involved.

    +

    Note that the temporary closure object resulting from a lambda expression is +not represented with an enk_temp_init node; the enk_lambda node itself +represents the temporary (it points to an associated dynamic initialization +entry).

    +
    +
    +

    9.18. Copy Constructor Elision#

    +

    In cases where a class entity is being initialized, it is often possible to +avoid calling a copy constructor:

    +
    struct A { A(int) {...}};
    +A xx = 1;         // A::A(int)
    +
    +
    +

    The constructor in that case can be used to directly initialize the variable +xx. It’s not necessary to initialize a temporary with that constructor and +then copy the temporary to xx using a copy constructor. The process of +avoiding the unnecessary copy constructor call is called copy constructor +elision.

    +

    determine_dynamic_init_for_class_init is the routine that checks for the +possibility of copy constructor elision. It attempts to find a constructor or +other routine that can do the initialization directly. Failing that, it +returns a copy constructor.

    +

    If a copy constructor call is elided, the copy constructor must still exist. +To confirm its existence and accessibility handle_elided_copy_constructor +is called.

    +
    +
    +

    9.19. Selector Operands#

    +

    A function call like

    +
    p->f(xx);
    +
    +
    +

    is processed by (1) scanning p->f and generating a pair of operands (one +for the object, one for the function) bound together, then (2) processing the +call. Between the first step and the second, the selector operand for the +object is carried around alongside of the (primary) operand for the function.

    +

    If the function being called is a nonstatic member function (which would be the +usual case), the selector must sometimes become a pointer to an object rather +than an lvalue or rvalue for the object. conv_operand_to_object_pointer +does that transformation.

    +

    conv_selector_to_object_pointer also does that transformation but has a +flag indicating whether or not the object has been turned into a pointer, so +that the transformation is not done more than once.

    +

    conv_object_pointer_to_lvalue does the transformation in the other +direction.

    +

    It is noteworthy that the addresses of class prvalues can be taken. The +language does not allow the addresses of other kinds of prvalues to be taken. +However, the addresses of class objects are needed in order to do copy +constructor calls, member function calls, and base/derived class casts. The +language hints that all class prvalues might really be temporary variables of +class type, and that therefore it is possible to take their addresses. +Accordingly, the front end generates temporaries for class prvalues, including +cases when functions return class values. The routine +conv_class_prvalue_operand_to_object_pointer can turn an expression for a +class prvalue back into a pointer to the class object, usually by finding the +enk_temp_init node that defines the temporary and flipping the +address/value flag in that node back to “address.”

    +
    +
    +

    9.20. Overloaded Function Calls#

    +

    Overloaded function calls can be explicit calls or they can be implicit in +contexts that involve user-defined conversions (constructors or conversion +functions). In either case, the process of overload resolution must be done. +It involves considering an argument list and a set of overloaded functions, +selecting the function that best matches the argument list, then adjusting the +types of the arguments so that they are appropriate arguments for the function +selected.

    +

    The argument list is represented as a list of entries of type +an_arg_list_elem, with each entry containing either an expression in +an_operand form or a brace-enclosed list.

    +

    Each function in the overload set is considered in turn to see how well it +matches the argument list. If all of the arguments can be made to match the +function parameters, the function is added to a candidate functions list (see +type a_candidate_function). Under that entry is a list of entries that +describes how well each argument matches the function’s corresponding formal +parameter.

    +

    After all the functions are considered, select_best_candidate_functions is +called to select the function(s) with the best argument matches. For each +argument, it forms the set of functions that match best on that argument; then +the intersection of those best-match sets is formed. If the intersection has +just one function, it is the best-matching function. However, it must still be +compared to all the other functions to verify that the chosen function is +better in some argument position than each of the other functions (though not +necessarily on the same argument position for each function). After the +candidate functions list has been trimmed to a list of best-matching functions,

    +
      +
    • +
      If there are no functions on the list, an error is issued: no function is +appropriate.
      +
      +
    • +
    • +
      If there is more than one function on the list, an error is issued: several +functions are appropriate, so the call is ambiguous.
      +
      +
    • +
    • +
      If there is exactly one function on the list, that is the function to call. +The arguments are converted to the proper parameter types and the call is +generated.
      +
      +
    • +
    +

    compare_arg_match_levels compares two argument match summaries and +determines which of the two is a better match. Often, this is just a matter of +comparing the match levels. However, one of the overload resolution rules says +that if one match is a subsequence of the other (for certain cases), the +shorter sequence is the better match; this is the routine that implements that +rule. When comparing two matches at the same level, it looks to see if either +one is a subsequence of the other, and if so, the shorter sequence is called a +better match. The functions compare_argument_tiebreakers and +compare_standard_conversions are called to do most of the work.

    +

    There are several tie-breakers that will select one function over another when +the argument matches are equally good for the two functions. See +compare_candidate_functions.

    +

    If function templates are involved in the overload resolution, the candidate +functions set is built more or less as described above. After an initial check +that the number of arguments matches the number of parameters, +function_template_call_argument_deduction is called to do template +parameter deduction for the call. If deduction is possible, it returns a list +of template argument values and a routine type with the template argument +values substituted for the corresponding template parameters. This routine +type (which is a normal routine type containing no template parameters) is then +used for the rest of the overload resolution process. If the function name was +accompanied by a set of explicit template arguments (e.g., f<int>(1)), the +explicit template argument list is passed to the deduction routines and those +template parameters are not deduced. +function_template_call_argument_deduction calls matches_template_type +to do the actual deduction. After the list of candidate functions has been +built, select_best_candidate_functions considers the template candidates +alongside the non-template functions. If a template function is chosen as the +best function, find_template_function is called to build the instance of +the function, and the template function routine is then used as the result of +the overload resolution.

    +

    When template-dependent name lookup is enabled, some special processing is +done. If, in a prototype instantiation, the argument list contains an +expression of template-dependent type, overload resolution cannot be done. A +special “unknown dependent function” indication is returned to the caller. If, +in a prototype instantiation, the argument list contains no dependent +expressions, the call is a “non-dependent call” according to the standard. +Overload resolution is done, and the function selected is recorded (in +association with the token sequence number of the position of the call or +overloaded operator) by calling record_nondependent_call. Then, in a real +instantiation of the template, get_nondependent_call_info is called to +retrieve the information, if any, recorded for a given call. If there is +information associated with the call, the call is non-dependent and the +function previously determined by overload resolution is used again (overload +resolution is not done).

    +

    There are several things that are done during the processing of a +non-overloaded call that cannot be done at that point during the processing of +an overloaded function call, because it’s not known which specific function +will be called. Once overload resolution has been done, those things are done +by overloaded_function_catch_up:

    +
      +
    • +
      Check access to the function if it is a class member.
      +
      +
    • +
    • +
      Record reference information for the function called.
      +
      +
    • +
    • +
      Check that the return type of the function is not incomplete.
      +
      +
    • +
    +

    The casting of the arguments to the proper types is also a “catch-up” function.

    +

    select_overloaded_function is the top-level routine for overload +resolution. To find the best match it calls try_overloaded_function_match, +which first calls determine_arg_match_level to see how well the arguments +match (for the selector object, it uses selector_match_with_this_param +instead) and then calls select_best_candidate_functions to pick the best +function from the list of viable functions.

    +

    set_up_overload_set_traversal, next_symbol_in_overload_set, +set_up_overload_symbol_list_traversal, and +next_symbol_in_overload_symbol_list are used to set up and traverse +overload sets (the first two for normal sets, and the second two for sets +introduced by symbol lists, e.g., argument-dependent lookup or conversion +functions).

    +

    determine_arg_match_level implements the argument matching rules of the +language. An argument can match at any of the following levels:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    aml_exact
    +
    +
    +
    Exact match or trivial conversions.
    +
    +
    +
    aml_promotion
    +
    +
    +
    Match with promotions.
    +
    +
    +
    aml_std_conversion
    +
    +
    +
    Match with standard conversions.
    +
    +
    +
    aml_boxing_conversion
    +
    +
    +
    Match with boxing conversion (C++/CLI only)
    +
    +
    +
    aml_user_conversion
    +
    +
    +
    Match with user-defined conversions.
    +
    +
    +
    aml_ellipsis
    +
    +
    +
    Match with ellipsis.
    +
    +
    +
    aml_error
    +
    +
    +
    Match with error type (not in ARM).
    +
    +
    +
    aml_none
    +
    +
    +
    No match.
    +
    +
    +
    +

    C++/CLI adds a few additional complexities:

    +
      +
    • +
      Parameter arrays, where zero of more arguments at the end of the argument +list can be bundled together into a CLI array of values passed to a final +parameter with a parameter array type. Such a match is worse than other +matches except for an ellipsis match. Parameter arrays are also handled +when template type deduction is done.
      +
      +
    • +
    • +
      Overload sets are formed using hide-by-sig lookup. +use_hide_by_sig_lookup is called on a function symbol to see whether +hide-by-sig lookup applies (it only applies to members of managed classes), +and to build a list, attached to the symbol, of the symbols that should be +in the overload set for that symbol. The overload set traversal routines +set_up_overload_set_traversal and next_symbol_in_overload_set +determine whether the symbol requires hide-by-sig lookup, and traverse the +hide-by-sig list if so, skipping any inaccessible functions. Since +hide-by-sig applies only to member functions, it never has to co-exist with +argument-dependent lookup.
      +
      +
    • +
    +
    +
    +

    9.21. User-defined Conversions#

    +

    conversion_to_class_possible looks for a constructor or conversion function +that will convert an expression to a particular class type, and +conversion_from_class_possible looks for a conversion function that will +convert an expression from a class type to a specific other type or to a +built-in type from a given set. These use try_overloaded_function_match +for the constructor cases, and try_conversion_function_match_full for the +conversion function cases.

    +

    Conversion functions that return reference types are a little tricky in that +their results are lvalues or xvalues, but that falls out more or less naturally +from the fact that operand transformations (like glvalue to prvalue) are put +off as long as possible. When the result of a conversion is to be bound to a +reference, the kind of reference (lvalue reference or rvalue reference) +constrains the choice of suitable conversion functions.

    +

    C++/CLI adds static conversion functions. Those can convert to a class in +addition to from a class, and can also convert to/from a handle to a class or +tracking reference to a class. Therefore, places that look for conversion +functions must also look in the destination class for conversion functions, and +in the base classes of the source type, and must also consider handles to be +class-like as both source and destination types of a conversion, because the +classes underlying those handle types may have static conversion functions. +See try_static_conversion_function_match and +cli_handle_user_defined_conversion_possible.

    +
    +
    +

    9.22. Operator Overloading#

    +

    check_for_operator_overloading looks for operator overloading +possibilities. It is called only when one or more of the operands of an +operator has a class or enum type [5]. It considers three ways of +processing the operands:

    +
      +
    1. As arguments of an operator member function.

    2. +
    3. As arguments of an operator function that is not a member function.

    4. +
    5. As operands of the built-in version of the operator, with the operands +converted from the class types to acceptable built-in types by use of +conversion functions. This is not tried for operators that have a +built-in meaning for classes (”,”, “->”, “=”, and unary +“&”).

    6. +
    +

    As with overload resolution for function calls, the overloaded operator +resolution process considers each of the alternatives (functions and built-in +operator) in turn and builds a list of candidate functions. After all the +alternatives have been examined, the best one is selected (or an error is +issued). The operands are then adjusted to match the function or built-in +operator that was selected.

    +

    try_overloaded_function_match is called (possibly several times) to +determine how well the operator functions match the operands. +opname_member_function_symbol is used to find the applicable member +functions (if any), and nonmember_operator_function_lookup is used to find +the applicable nonmember functions (if any); special processing is done for +those if the operand types come from namespaces.

    +

    try_conversions_for_builtin_operator is called to try to find conversions +that will allow use of the built-in version of the operator. Its subroutines +– operand_type_pattern_for_operator, try_builtin_operands_match, and +try_pointer_builtin_operands_match – do the necessary investigation.

    +

    C++/CLI adds some additional issues:

    +
      +
    • +
      When the first operand is a handle, it is overloadable much as if it had +the underlying class type. An expression like “h+x” can be treated as +“h->operator+(x)”.
      +
      +
    • +
    • +
      When either operand is a handle, it may be possible to use a static +conversion function to convert the operand to a fundamental type for which +there is a builtin version of the operator, much as is done for class +operands.
      +
      +
    • +
    • +
      Static operator functions can apply. They don’t have a “this” +parameter, so the first operand matches the first parameter, and the +second operand (if there is one) the second parameter. “a+b” could +become “X::operator+(a,b)”. These are also searched for in the +class of the second operand, if there is one and it has class type.
      +
      +
    • +
    • +
      Operator synthesis can be done. If a class does not have an +“operator+=”, for example, the combination of an “operator+” and an +“operator=” can be used.
      +
      +
    • +
    • +
      In certain cases, string literals can act as if they are handles to +System::String, which then makes them overloadable.
      +
      +
    • +
    +
    +
    +

    9.23. Address of Overloaded Function#

    +

    When an overloaded function appears in an expression, it is represented an as +indefinite function operand, which is basically just an operand that points to +the overloaded function symbol.

    +

    When such an operand is subjected to the function-to-pointer transformation, +the operand stays an indefinite function, but changes from a function +designator to a prvalue pointer.

    +

    When such an operand shows up in a conversion where the destination type is a +function pointer, find_addr_of_overloaded_function_match is called to find +out which (if any) of the specific functions matches the required function +pointer. The operand is then converted to the specific function pointer in +cast_operand_full; overloaded_function_catch_up is called to do +whatever would have been done had it been known all along which specific +function was intended.

    +

    If the overload set includes one or more template functions, the resolution +algorithm is as follows:

    +
      +
    1. If there is an exact match in the set of non-function-templates, it is +selected (if there is more than one, the pointer use is ambiguous); +otherwise,

    2. +
    3. If there is a template function from which a function can be generated +that will match exactly, it is selected (if there is more than one, the +pointer use is ambiguous); otherwise,

    4. +
    5. If there is a non-exact match in the set of non-function-templates, it is +selected (this can only happen with pointers to member functions, where +an implicit conversion from base to derived is allowed).

    6. +
    +

    matching_template_function is called to attempt to find a match under rule +(2).

    +
    +
    +

    9.24. Range-based for statement#

    +

    The C++11 range-based for statement is checked and assembled by +check_range_based_for_statement. It determines which of the three +“patterns” is applicable for the statement and calls +check_range_based_for_array_case, check_range_based_for_member_case, or +check_range_based_for_default_case as necessary to perform the necessary +semantic checks and generate the IL.

    +

    The range-based-for statement takes the form:

    +
    +
    +
    for ( for-range-declaration : expression ) statement
    +
    +
    +

    and is defined to be equivalent to:

    +
    +
    +
    {
    +
    +
    auto && __range = (expression);
    +
    for ( auto __begin = begin-expr,
    +
    +
    +
    +
    __end = end-expr;
    +
    +
    __begin != __end;
    +
    ++__begin ) {
    +
    +
    for-range-declaration = *__begin;
    +
    statement
    +
    +
    }
    +
    +
    }
    +
    +
    +

    Lower level routines for handling variable initializer expressions, member +lookup, overload resolution, etc. are shared (where applicable) with the +for-each statement handling described below (together the range-based for +and for-each statements are referred internally as “enhanced for” +statements).

    +
    +
    +

    9.25. For-each Statement#

    +

    The C++/CLI for-each statement is checked and assembled by +check_for_each_statement. There are four “patterns” for the for-each +statement (the STL pattern, the CLI collection pattern, the CLI array pattern, +and the native array pattern). check_for_each_statement determines the +pattern matched by a given loop, and calls the right one of four routines, each +charged with checking one of the patterns and building the IL.

    +

    The for-each statement is defined in terms of a rewrite for each of the +patterns. For example, a for-each loop that matches the native array pattern +is rewritten from

    +
    +
    +
    for each (T t in c) statement
    +
    +
    +

    to

    +
    +
    +
    { C &cref = c;
    +
    +
    I *cend = &cref[0]+c_num_elements;`
    +
    I *i = cref;
    +
    for (; i != cend; ++i) {
    +
    +
    T t = static_cast<T>(*i);
    +
    statement
    +
    +
    }
    +
    +
    }
    +
    +
    +

    The IL for this case contains variables and associated scopes for the iterator +variable and the added temporary variables, initializer expressions for each of +those, and additional expressions for the loop != and ++ expressions. +Those are relatively simple in this case, but in other cases and other patterns +the generated expressions can be complex, and developing them may involve +member lookup, overload resolution, operator overloading, or user-defined +conversions. The front end’s goal is to provide IL that completely describes +the actions needed to implement the loop, while at the same time retaining the +parts in a high-enough-level form that source-analysis programs can discern the +original loop variables and expressions.

    +
    +
    +

    9.26. Properties#

    +

    Microsoft mode has properties, which are data members of classes that are +implemented by accessor functions, e.g., one to get the current value of the +property, and one to set the current value of the property. Properties come in +two kinds:

    +
      +
    • +
      Old-style properties, indicated by the __declspec(property(… )) +attribute. The accessor functions are only loosely associated with the +property, by being named in the attribute.
      +
      +
    • +
    • +
      New-style properties in C++/CLI, which begin with the “property” +context-dependent keyword. The accessor functions are declared as part of +the property declaration, in a form that looks vaguely like a nested class.
      +
      +
    • +
    +

    In both cases, the IL has a description of the property declaration, in +something close to the source form (that information is held in +an_property_or_event_descr entry). However, also in both cases, references +to the properties are expanded by expression processing, so they are not +retained in source form. A bit of source code like “p+=1” +might be expanded into a series of calls something like “call the get accessor +for p, call operator+ on the fetched value and 1, and call the put +accessor to store the computed value.” The generated IL contains some tags on +various nodes in the expansion that help source-analysis code recover the +original meaning, though in a cumbersome way.

    +

    Property references cannot be rewritten immediately. They have to be carried +around for a short while in expression processing until it becomes clear from +the context how the property is being used, i.e., a “get” or a “set”. Before +they are rewritten, property references are carried around as an_operand +entries of kind ok_property_ref. The operand can include a list of +subscripts that is part of the property reference. Once the context is +established, the property reference is rewritten; that’s handled by +rewrite_property_reference. As hinted at above, some rewrites are more +complicated than a simple “get” or “set”, and might involve a “get”, some +operation on the fetched value, possibly surrounded by conversions, and finally +a “set”. That happens for compound assignment operators and for pre- and +post-increment and -decrement operators. In such cases, the operand is cloned +(see clone_operand), so that it will only be evaluated once, and +rewrite_property_reference is called twice, once for the “get” and once for +the “set”.

    +

    C++/CLI events are very similar to the new-style properties, in representation +and in the fact that references are expanded by the front end.

    +
    +
    +

    9.27. C++/CLI Generics#

    +

    Expression processing for C++/CLI generics, meaning handling of expressions +during the scanning of a generic definition, mostly falls out of normal +expression processing. During the generic definition, the parameters of the +generic (represented as template parameters) are given values that are +generated class types that reflect the constraints on the generic parameters. +So, for example, if a generic parameter is constrained to derive from an +interface I, the generated class type will be such that it will be possible to +look up members of I in the class and find them in a base class that is I. +That makes most operations work without special handling. Also, for many +cases, the template parameter’s value is a handle to the constraint class type, +so that operations like assignment work because they become handle assignments +instead of class assignments (where it might not be possible to know whether +the class will have an appropriate operator= at runtime). There are a few +special cases with casting, where a generic parameter might or might not be a +value class type, or might or might not effectively be a handle at runtime. +Casts are rejected if they might be invalid because they treat a value type as +a handle, or vice-versa. Also, casts are rejected if it can be shown at +compile time that the source value type can never satisfy the constraints of +the destination type.

    +
    +
    +

    9.28. Reference Information#

    +

    To track references to identifiers, ref_entry is called for each identifier +reference in an expression. The information provided is used to write +cross-reference information (when requested) and to set the referenced, used, +modified, and address-taken flags in variable and routine entries. For some +identifiers, the kind of reference is known immediately, so +record_symbol_reference is called to record the information. For others, +the kind of reference is dependent on the expression context, and therefore it +is not known immediately. For such cases, an entry called a_ref_entry is +allocated and placed on a list of such entries for the current expression. +When the reference kind becomes known, the kind in the entry is updated (see +change_ref_kinds). At the end of the expression, +flush_ref_entries_list is called. It scans the entries on the list, calls +record_symbol_reference to record the (now fully determined) reference, and +then frees the entries.

    +
    +
    +

    9.29. Diagnostic output#

    +

    Diagnostic output in the expression-processing routines must be handled +specially in order that it be possible to suppress diagnostics when rescanning +an expression during template deduction. For that reason, what would normally +be simply a call of a diagnostic-output routine must be slightly more +complicated in the expression-processing source files. For the simpler +diagnostics, there are direct expr_ equivalents:

    +
      +
    • +
      For pos_error, use expr_pos_error.
      +
      +
    • +
    • +
      For pos_warning, use expr_pos_warning.
      +
      +
    • +
    • +
      For pos_diagnostic, use expr_pos_diagnostic.
      +
      +
    • +
    • +
      For syntax_error, use expr_syntax_error.
      +
      +
    • +
    +

    Other diagnostic calls should be enclosed in a test of +expr_error_should_be_issued or expr_diagnostic_should_be_issued, as +appropriate.

    +

    Any access-checking code must be conditioned on +expr_access_checking_should_be_done. It’s not enough to simply surround +access-error diagnostic calls with a suppression test; when template deduction +is being done, it must be as if no access checking is even attempted, and the +flow of control must continue as if the error were not present.

    +
    +

    9.29.1. Folding of Constant Operations#

    +

    There are four main files involved in folding constant operations:

    +
      +
    • +
      const_ints.c contains the code for low-level integer operations, with +const_ints.h containing associated declarations.
      +
      +
    • +
    • +
      fixed_pt.c contains the code for low-level fixed-point operations, with +fixed_pt.h containing associated declarations.
      +
      +
    • +
    • +
      float_pt.c contains the code for low-level floating-point operations, +with float_pt.h containing associated declarations.
      +
      +
    • +
    • +
      folding.c contains the higher-level code that handles folding of +constant operations and of type conversions on constants. folding.h +contains associated declarations. Code for folding of constexpr calls +and operations is also here.
      +
      +
    • +
    +
    +
    +
    +

    9.30. Low-level Integer Routines#

    +

    const_ints.c contains the routines that manipulate low-level integers. Any +integer literal constant in the source program and any operation on constant +integers implied by the source program are ultimately handled by the routines +here. For the most part, the low-level integer form can be viewed as a +representation for target machine integers on the host machine, although it is +also used for some things (like array dimensions) that are only arguably target +machine constants.

    +

    The point of these routines is to collect all the code that operates on target +integers in one place, so that it can be modified if necessary, and so that the +rest of the front end does not need to deal with the subtleties of signed and +unsigned representations, overflow, etc.

    +

    There are two different possible representations for integer values (type +an_integer_value):

    +
      +
    • +
      If there is some host integer type that is big enough to hold any target +integer (the usual case), an integer value is simply represented as a host +integer. Operations on that representation are done using the host C +operators, with extra overflow checking. If the host C compiler supports +long long, that type can be used as the representation type.
      +
      +
    • +
    • +
      Otherwise (for example, in a cross-compiler for a 64-bit target running on +a 32-bit host), an integer value is represented as a struct containing +an array of small integers (of type an_int_value_part). Operations on +that representation are simulated in software.
      +
      +
    • +
    +

    (See configuration constant INTEGER_VALUE_REPR_IS_A_HOST_INTEGER.)

    +

    The an_integer_value representation may be used to represent signed or +unsigned quantities. It is not self-identifying in that regard, i.e., the +representation does not contain an indication of the signedness of the value. +Therefore, in cases where signedness is significant, (e.g., multiplication), +the caller must pass in a separate argument indicating the signedness to be +used for the integer value. For values that can be represented in both the +signed and unsigned forms, the representation in the two forms is the same. +That allows small constants to be used as either signed or unsigned quantities +as the need arises.

    +

    The const_ints.c routines deal with integer values as single-sized +entities, the size being large enough to hold any of the target integer types. +The routines check for overflow relative to that representation, but they know +nothing of different integer types and their sizes.

    +

    Most routines in const_ints.c operate on values in the an_integer_value +form. For convenience, some routines are provided that operate on the IL +a_constant form, but it’s a circumspect use of that form: as far as the +routines are concerned, a_constant is a structure that only contains +an_integer_value (in the variant integer_value field) and a type (in +the type field) that can be passed to int_constant_is_signed to +determine the signedness of the value. No other fields of the constant need be +defined.

    +

    The routines that are used to translate between a_host_large_integer (some +large built-in host integral type) and the an_integer_value form are

    +
      +
    • +
      set_integer_value,
      +
      +
    • +
    • +
      set_unsigned_integer_value,
      +
      +
    • +
    • +
      value_of_integer_constant, and
      +
      +
    • +
    • +
      unsigned_value_of_integer_constant.
      +
      +
    • +
    +

    Routines used to get attributes of integer values are

    +
      +
    • +
      get_integer_size_and_alignment and
      +
      +
    • +
    • +
      int_constant_is_signed.
      +
      +
    • +
    +

    Utility routines used to determine the magnitude of an integer value, create a +bit mask, and sign-extend a value are

    +
      +
    • +
      bits_required_to_represent_integer_constant,
      +
      +
    • +
    • +
      make_integer_value_mask, and
      +
      +
    • +
    • +
      sign_extend_integer_value.
      +
      +
    • +
    +

    Routines used to format integer values in decimal string form are

    +
      +
    • +
      str_for_integer_constant.
      +
      +
    • +
    +

    Routines used to compare integer values (including some comparisons against the +limits of integers of given kinds) are

    +
      +
    • +
      cmp_integer_values,
      +
      +
    • +
    • +
      cmp_integer_constants,
      +
      +
    • +
    • +
      cmplit_integer_value,
      +
      +
    • +
    • +
      cmpulit_integer_value,
      +
      +
    • +
    • +
      in_range_for_integer_kind,
      +
      +
    • +
    • +
      le_max_value_for_integer_kind, and
      +
      +
    • +
    • +
      is_max_value_for_integer_kind.
      +
      +
    • +
    +

    On these, the two values being compared may have independent signedness. The +lit routines do comparison against a_host_large_integer or +a_host_large_unsigned value, typically a small constant.

    +

    Routines used to perform arithmetic and logical operations are

    +
      +
    • +
      add_integer_values,
      +
      +
    • +
    • +
      subtract_integer_values,
      +
      +
    • +
    • +
      multiply_integer_values,
      +
      +
    • +
    • +
      divide_integer_values,
      +
      +
    • +
    • +
      remainder_integer_values,
      +
      +
    • +
    • +
      and_integer_values,
      +
      +
    • +
    • +
      or_integer_values,
      +
      +
    • +
    • +
      xor_integer_values,
      +
      +
    • +
    • +
      shift_left_integer_values,
      +
      +
    • +
    • +
      shift_right_integer_values, and
      +
      +
    • +
    • +
      complement_integer_values.
      +
      +
    • +
    +

    On these, the two operands must have the same signedness (except that there are +versions of the add and subtract routines for the independent-signedness +cases). The result of the operation overwrites the first operand.

    +

    For some kinds of values, it’s just too much of a nuisance to use the integer +value routines, so the front end converts such values to +a_host_large_integer or a_host_large_unsigned (which are typically +signed and unsigned long, or signed and unsigned long long) and +operates on them in that form. The values handled that way are:

    +
      +
    • +
      Sizes of objects, including arrays (conceptually of type size_t on the +target).
      +
      +
    • +
    • +
      Offsets relative to objects (conceptually of type ptrdiff_t on the +target).
      +
      +
    • +
    • +
      Single characters (but not a character constant containing one or more +characters).
      +
      +
    • +
    • +
      Single wchar_t values.
      +
      +
    • +
    +

    Note that the target size_t and ptrdiff_t are allowed to be bigger than +the host a_host_large_integer; the use of a_host_large_integer +representation just restricts the possible constant values of that type that +the front end can deal with. The conversions into the host types are done with +overflow checking, so the front end will issue errors for values larger than +those it can accommodate.

    +
    +
    +

    9.31. Low-level Fixed-point Routines#

    +

    The routines in fixed_pt.c manipulate the internal repreentation of +fixed-point constants on the host machine. As with the integer routines, they +are collected in one place so that they can be changed more easily and so that +the front end at large need know nothing about the fixed-point representation.

    +

    They implement very low-level operations on the internal form of fixed-point +constants. Some of the standard product versions of these routines (e.g., for +conversion of a decimal text form of a fixed-point constant to internal form) +are not always accurate to the last significant bit: They are best viewed as +prototype routines for testing purposes, to be replaced by real routines for +the production version.

    +

    The main routines (or macros) in fixed_pt.c are the following:

    +
      +
    • +
      cmp_fixed_point_constants
      +
      +
    • +
    • +
      fxp_init_value
      +
      +
    • +
    • +
      fxp_value_is_zero
      +
      +
    • +
    • +
      fxp_string_to_fixed_point
      +
      +
    • +
    • +
      fxp_hex_string_to_fixed_point
      +
      +
    • +
    • +
      conv_fixed_point_to_fixed_point
      +
      +
    • +
    • +
      conv_integer_to_fixed_point
      +
      +
    • +
    • +
      conv_fixed_point_to_integer
      +
      +
    • +
    • +
      conv_float_to_fixed_point
      +
      +
    • +
    • +
      conv_fixed_point_to_float
      +
      +
    • +
    • +
      fxp_to_string
      +
      +
    • +
    • +
      fxp_add
      +
      +
    • +
    • +
      fxp_subtract
      +
      +
    • +
    • +
      fxp_multiply
      +
      +
    • +
    • +
      fxp_divide
      +
      +
    • +
    • +
      fxp_compare
      +
      +
    • +
    • +
      fxp_hash
      +
      +
    • +
    +
    +
    +

    9.32. Low-level Floating-point Routines#

    +

    The routines in float_pt.c manipulate target floating-point constants on +the host machine. As with the integer routines, they are collected in one +place so that they can be changed more easily and so that the front end at +large need know nothing about the floating-point representation.

    +

    They implement very low-level operations on the internal form of floating-point +constants. When USE_HOST_FP_CONVERSION_ROUTINES is TRUE (the default), +binary to decimal conversions are performed using standard UNIX conversion +routines provided by the host. When USE_HOST_FP_CONVERSION_ROUTINES is +FALSE, internal routines (in floating.c) are used to perform these +conversions. Arithmetic operations are performed without range checking; +therefore, they are best viewed as prototype routines for testing purposes, to +be replaced by real routines for the production version.

    +

    In cases where the target configuration supports floating-point types that are +not supported by the host compiler (e.g., __float128 and __float80 on +Windows), the Berkeley SoftFloat library can be used to perform +arithmetic operations on the host. This configuration can be selected by +setting the USE_SOFTFLOAT configuration macro to TRUE. In such +configurations, the USE_HOST_FP_CONVERSION routines is automatically set to +FALSE to enable a software-only floating-point configuration. Note that +such configurations are inherently slower than those that use floating-point +hardware. See the SoftFloat web site for licensing information.

    +

    The main routines in float_pt.c are the following:

    +
      +
    • +
      fp_change_kind
      +
      +
    • +
    • +
      fp_string_to_float
      +
      +
    • +
    • +
      fp_hex_string_to_float
      +
      +
    • +
    • +
      fp_to_string
      +
      +
    • +
    • +
      fp_long_to_float
      +
      +
    • +
    • +
      fp_unsigned_long_to_float
      +
      +
    • +
    • +
      fp_to_host_large_integer
      +
      +
    • +
    • +
      fp_to_host_large_unsigned
      +
      +
    • +
    • +
      fp_is_zero_constant
      +
      +
    • +
    • +
      fp_add
      +
      +
    • +
    • +
      fp_subtract
      +
      +
    • +
    • +
      fp_multiply
      +
      +
    • +
    • +
      fp_divide
      +
      +
    • +
    • +
      fp_compare
      +
      +
    • +
    • +
      fp_hash
      +
      +
    • +
    +
    +
    +

    9.33. Constant Folding#

    +

    The routines in folding.c do folding of constant operations and type +conversions on constants.

    +

    This folding is done in target machine arithmetic. For integers, routines in +const_ints.c do the actual operations on the generic integer value, but the +routines here add a layer that understands specific integer types, and does +overflow checking, masking, and sign extension according to the size and +signedness of the integer type. For fixed-point and floating operations, +target-specific code in fixed_pt.c and float_pt.c does the actual +operations. For pointer operations, the constants are either address constants +(a base symbol plus a byte offset) or integer constants cast to a pointer type +(the most common of these is NULL/0). The routines get_pointer_offset +and set_pointer_offset are used to extract and set the offsets in both +those cases.

    +

    The folding routines detect errors and warnings and call the error routines to +report them. When they are called in nonconstant contexts (like executable +statements), errors are downgraded to warnings, and the operation is left +unfolded, to be tried at runtime.

    +

    If the folding routines are unable to fold an operation to a constant (because +of some attribute of the operands, not because of an error), they return a flag +did_not_fold set to TRUE, which tells the caller to leave the operation +unfolded. For example, the pointer difference of pointers to different static +objects is a constant, but one that is unknowable until link time. +did_not_fold would be returned TRUE for that case (and no error or warning +would be indicated). The folding routines also record the unfolded expression +in constants resulting from the folding.

    +

    unary_operation and binary_operation are the top-level routines for +operations on constants. They take as input an operator and one or two +constants, and produce a constant (or an error indication) as output. The +operations are done with all necessary checking for overflows, etc. The +routines called by unary_operation to do the actual folding are

    +
      +
    • +
      do_inegate,
      +
      +
    • +
    • +
      do_fxnegate,
      +
      +
    • +
    • +
      do_fnegate,
      +
      +
    • +
    • +
      do_xnegate,
      +
      +
    • +
    • +
      do_complement, and
      +
      +
    • +
    • +
      do_not,
      +
      +
    • +
    +

    and those called by binary_operation are:

    +
      +
    • +
      do_iadd,
      +
      +
    • +
    • +
      do_isubtract,
      +
      +
    • +
    • +
      do_imultiply,
      +
      +
    • +
    • +
      do_idivide,
      +
      +
    • +
    • +
      do_remainder,
      +
      +
    • +
    • +
      do_shiftr,
      +
      +
    • +
    • +
      do_shiftl,
      +
      +
    • +
    • +
      do_icompare,
      +
      +
    • +
    • +
      do_and,
      +
      +
    • +
    • +
      do_or, and
      +
      +
    • +
    • +
      do_xor
      +
      +
    • +
    +

    for integers;

    +
      +
    • +
      do_land and
      +
      +
    • +
    • +
      do_lor
      +
      +
    • +
    +

    for scalars;

    +
      +
    • +
      do_fxadd,
      +
      +
    • +
    • +
      do_fxsubtract,
      +
      +
    • +
    • +
      do_fxmultiply,
      +
      +
    • +
    • +
      do_fxdivide, and
      +
      +
    • +
    • +
      do_fxcompare
      +
      +
    • +
    +

    for fixed-point;

    +
      +
    • +
      do_fadd,
      +
      +
    • +
    • +
      do_fsubtract,
      +
      +
    • +
    • +
      do_fmultiply,
      +
      +
    • +
    • +
      do_fdivide, and
      +
      +
    • +
    • +
      do_fcompare
      +
      +
    • +
    +

    for floating-point;

    +
      +
    • +
      do_xadd,
      +
      +
    • +
    • +
      do_xsubtract,
      +
      +
    • +
    • +
      do_xmultiply,
      +
      +
    • +
    • +
      do_xdivide,
      +
      +
    • +
    • +
      do_jmultiply,
      +
      +
    • +
    • +
      do_jdivide, and
      +
      +
    • +
    • +
      do_xcompare
      +
      +
    • +
    +

    for complex and imaginary;

    +
      +
    • +
      do_padd,
      +
      +
    • +
    • +
      do_pdiff, and
      +
      +
    • +
    • +
      do_pcompare
      +
      +
    • +
    +

    for pointers; and

    +
      +
    • +
      do_pmcompare
      +
      +
    • +
    +

    for pointers to members.

    +

    Actual shifting is performed by do_shift, which calls check_shift_count +for error checking. The shifting is implemented with the integer size and +sign-extension appropriate for the target.

    +

    When pointer addition or subtraction is folded, the resulting constant, if an +address constant, is checked to see if the offset lies within the base object. +Offsets beyond the end of the object and negative offsets are flagged with a +warning (most often, this is due to a constant subscript out of bounds). This +is checked by valid_address_constant.

    +

    In ordinary constant folding, valid_address_constant will allow the +position just past the end of an object without a warning, since it does not +know whether the address of that position is required (which is allowed by ANSI +C) or the value (which is an error). The routine using_lvalue calls +valid_address_constant again to check for the error once it is known that +it is the value that is being accessed.

    +

    type_change_constant_full changes the type of a constant to something else. +It’s usually called through the simpler interface type_change_constant. It +has subroutines

    +
      +
    • +
      conv_integer_to_integer,
      +
      +
    • +
    • +
      conv_integer_to_float,
      +
      +
    • +
    • +
      conv_float_to_integer,
      +
      +
    • +
    • +
      conv_float_to_float,
      +
      +
    • +
    • +
      conv_pointer_to_whatever,
      +
      +
    • +
    • +
      conv_integer_to_pointer,
      +
      +
    • +
    • +
      conv_ptr_to_member_to_ptr_to_member, and
      +
      +
    • +
    • +
      conv_integer_to_ptr_to_member.
      +
      +
    • +
    +

    with the obvious functions. Warnings about truncation and hidden changes of +sign are issued (the latter are suppressed if the type change was the result of +an explicit cast or if the operand was a non-decimal constant).

    +

    Casts of pointers to classes to pointers to base or derived classes are handled +by

    +
      +
    • +
      fold_base_class_cast and
      +
      +
    • +
    • +
      fold_derived_class_cast.
      +
      +
    • +
    +

    The similar cases for pointers to members are handled by

    +
      +
    • +
      fold_pm_base_class_cast and
      +
      +
    • +
    • +
      fold_pm_derived_class_cast.
      +
      +
    • +
    +

    fold_field_selection is called to fold a field selection relative to a +constant address. Because of the unusual second operand (a field rather than a +constant), binary_operation could not be used for this case. If the field +is a bit field, fold_field_selection returns a did_not_fold flag.

    +

    constant_glvalue_address and its companion routine +constant_prvalue_pointer examine expression trees to determine if they +represent constant addresses, computing and returning the appropriate constant +value on the fly.

    +
    +
    +

    9.34. Folding and constexpr#

    +

    C++11 and C++14 permit calls to constexpr functions and constructors in +constant-expressions. To implement this, the front end includes an IL +interpreter implemented in the source file interpret.c. The start of that +file contains extensive comments describing the overall structure of the +interpreter. The global variable relaxed_constexpr_enabled is TRUE +when the C++14 version of the constexpr feature is enabled. This enables +the interpretation of expressions, like assignments, with side-effects (valid +in C++14, but not C++11). It also removes C++11 structural constraints for +constexpr functions and constructors (e.g., it allows multiple statements +in definitions).

    +

    To avoid burdening the IL or the rest of the front end, the interpreter does +not record state information in the IL or other front end structures. Instead, +it maintains its own data structures linked to the IL through efficient hash +tables. It does, however, use front end types to represent integral and +floating-point values. Other kinds of values (e.g., addresses) are represented +using interpreter-specific structures.

    +

    The interpreter can fold calls to constexpr functions and constructors, but +it can also more generally fold expressions and dynamic initializations.

    +

    The entry points into the interpreter are interpret_expr,interpret_dynamic_init,interpret_constexpr_call, and +interpret_constexpr_ctor. These functions return a boolean value +indicating whether interpretation succeeded (TRUE) or failed (FALSE). +Interpretation can fail because it encountered an operation not permitted +during constexpr evaluation (e.g., a virtual function call), including +operations with undefined behavior (e.g., attempting to fetch a value from +uninitialized storage). It can also fail when the cost of interpretation +becomes too high. The parameters limiting that cost can be set through the +command-line options --max_depth_constexpr_call and +--max_cost_constexpr_call. If interpretation fails, the interpreter also +returns a diagnostic description indicating the reason for the failure (that +description can be emitted as part of the diagnostic if a constant was +required).

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/ext_intf/index.html b/dev/doc/ext_intf/index.html new file mode 100644 index 0000000..ec7ec05 --- /dev/null +++ b/dev/doc/ext_intf/index.html @@ -0,0 +1,8972 @@ + + + + + 2. External Interface - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    2. External Interface#

    +

    Bear in mind that this information applies to the standard product. If any +local modifications are made, the documentation given to users must be adjusted +accordingly.

    +
    +

    2.1. Command Line#

    +

    The front end is invoked by a command of the form

    +
    +

    edgcpfe [options] ifile

    +
    +

    to compile the single input file ifile. If - (hyphen) is specified +for ifile, the front end reads from stdin. [1] No particular +file name suffix is required on input files.

    +

    Command line options may be specified using either single character option +codes (e.g., -o) or keyword options (e.g., --output). A single +character option specification consists of a hyphen followed by one or more +option characters (e.g., -Ab). If an option requires an argument, the +argument may immediately follow the option letter, or may be separated from the +option letter by white space. A keyword option specification consists of two +hyphens followed by the option keyword (e.g., --strict). Keyword options +may be abbreviated by specifying as many of the leading characters of the +option name as are needed to uniquely identify an option name (for example, the +--wchar_t_keyword option may be abbreviated as --wc). If an option +requires an argument, the argument may be separated from the keyword by white +space, or the keyword may be immediately followed by =argument. When +the second form is used there may not be any white space on either side of the +equals sign.

    +

    If the configuration flag COMPILE_MULTIPLE_SOURCE_FILES is defined as TRUE, +a list of files may appear for ifile. If a list of files is specified, +options that specify a compilation output file (--output, --list, and +--xref) may not be used, and the name of each source file is written to the +error output file as the compilation of that file begins.

    +

    When one of the preprocessing-only modes is specified (see below), the +--output option can be used to specify the preprocessing output file. If +--output is not specified, preprocessing output is written to stdout. +Preprocessing output has trigraphs and line splices processed (and thus they do +not appear in their original form).

    +

    When compilation (rather than just preprocessing) is done, the output (if any) +from the compilation is written to a file selected by the back end; see the +documentation of the back end for further information. For versions of the +front end that generate an intermediate language file, the --output option +can be used to specify the IL output file.

    +

    The options are described in the following subsections (organized by +category).

    +
    +

    2.1.1. Language Dialect Options#

    +

    The following options select among various C and C++ dialects.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --anachronisms
    +
    --no_anachronisms
    +
    +
    +
    Enable or disable anachronisms in C++ mode. The default for this +option is specified by DEFAULT_ALLOW_ANACHRONISMS. This option is +valid only in C++ mode.
    +
    +
    +
    --c
    +
    -m
    +
    +
    +
    Enable compilation of C rather than C++.
    +
    +
    +
    --c89
    +
    +
    +
    Enable the compilation of the C89 version of C.
    +
    +
    +
    --c99
    +
    --no_c99
    +
    +
    +
    Enable or disable compilation of the C99 version of C. In either +case, C rather than C++ is compiled.
    +
    +
    +
    --c11
    +
    +
    +
    Enable language features added in the C11 standard. This option +cannot be combined with options enabling or requiring a C++ mode.
    +
    +
    +
    --c18
    +
    --c17
    +
    +
    +
    Enable support for C18 (which is only a minor “bug fix” change from +C11). This option cannot be combined with options enabling or +requiring a C++ mode.
    +
    +
    +
    --c23
    +
    +
    +
    Enable language features added in drafts of the anticipated C23 +standard. This option cannot be combined with options enabling or +requiring a C++ mode.
    +
    +
    +
    --old_c
    +
    -K
    +
    +
    +
    Enable K&R/pcc mode, which approximates the behavior of the standard +UNIX pcc. ANSI/ISO C features that do not conflict with K&R/pcc +features are still supported in this mode.
    +
    +
    +
    --c++
    +
    -p
    +
    +
    +
    Enable compilation of C++. This is the default.
    +
    +
    +
    --c++03
    +
    +
    +
    Enable compilation of C++ as specified by the ISO/IEC 14882:2003 +standard by explicitly disabling all C++11 features, regardless of +their configured default values (but individual C++11 features can be +enabled on the command line). This option implicitly enables C++ mode +and can be combined with the options enabling strict ANSI/ISO +conformance, as well as other emulation modes (e.g., --microsoft, +--g++).
    +
    +
    +
    --c++11
    +
    --no_c++11
    +
    --c++0x
    +
    --no_c++0x
    +
    +
    +
    Enable or disable extensions added in the C++11 standard. This option +is only valid in C++ mode and can be combined with the options +enabling strict ANSI/ISO conformance.
    +
    +
    +
    --c++14
    +
    +
    +
    Enable language features added in the C++14 standard. This option +cannot be combined with options enabling or requiring a C mode.
    +
    +
    +
    --c++17
    +
    +
    +
    Enable language features added in the C++17 standard. This option +cannot be combined with options enabling or requiring a C mode.
    +
    +
    +
    --c++20
    +
    +
    +
    Enable language features added in the C++20 standard. This option +cannot be combined with options enabling or requiring a C mode.
    +
    +
    +
    --c++23
    +
    +
    +
    Enable language features added in the C++23 standard. This option +cannot be combined with options enabling or requiring a C mode.
    +
    +
    +
    --c++26
    +
    +
    +
    Enable language features added in drafts of the anticipated C++26 +standard. This option cannot be combined with options enabling or +requiring a C mode.
    +
    +
    +
    --cfront_2.1
    +
    -b
    +
    +
    +
    Enable compilation of C++ with compatibility with cfront version 2.1. +This causes the compiler to accept language constructs that, while not +part of the C++ language definition, are accepted by the AT&T C++ +Language System (cfront) release 2.1. This option also enables +acceptance of anachronisms.
    +
    +
    +
    --cfront_3.0
    +
    +
    +
    Enable compilation of C++ with compatibility with cfront version 3.0. +This causes the compiler to accept language constructs that, while not +part of the C++ language definition, are accepted by the AT&T C++ +Language System (cfront) release 3.0. This option also enables +acceptance of anachronisms.
    +
    +
    +
    --c++cli
    +
    --no_c++cli
    +
    --cppcli
    +
    --no_cppcli
    +
    --clr
    +
    +
    +
    Enable or disable compilation of C++/CLI source. This option implies +Microsoft C++ mode; it cannot be combined with options that are +contrary to such a mode (e.g., forcing strict mode) or with the option +--microsoft_version with a value less than 1600.
    +
    +
    +
    --c++cx
    +
    --no_c++cx
    +
    --cppcx
    +
    --no_cppcx
    +
    +
    +
    Enable or disable compilation of C++/CX source. This option implies +Microsoft C++ mode; it cannot be combined with options that are +contrary to such a mode (e.g., forcing strict mode) or with the option +--microsoft_version with a value less than 1600. Support for this +mode is preliminary and will be improved in future versions of the +front end.
    +
    +
    +
    --clang
    +
    --no_clang
    +
    +
    +
    Enable or disable clang C or C++ language compatibility features. +This option also enables the GNU C or C++ language compatibility +features. It is only recognized when GNU_EXTENSIONS_ALLOWED is +TRUE. As of this writing, the only effect of clang mode apart from +enabling GNU emulation is to enable the feature-test macros like +__has_feature.
    +
    +
    +
    --clang_version version-number
    +

    +
    +
    +
    The version of the clang compiler that should be emulated. Version +x.y.z of the clang compiler is encoded as x*10000+y*100+z (e.g., +version 3.4.1 is emulated with the option “--clang_version +30401”).
    +
    +
    +
    --embedded_c
    +
    --no_embedded_c
    +
    +
    +
    Enable or disable support for all Embedded C language extensions +(fixed-point types, named address space qualifiers, and named-register +storage class specifiers). These options are not available with C++ +modes.
    +
    +
    +
    --embedded_c++
    +
    +
    +
    Enable the diagnosis of noncompliance with the “Embedded C++” subset +(from which templates, exceptions, namespaces, new-style casts, RTTI, +multiple inheritance, virtual base classes, and mutable are +excluded).
    +
    +
    +
    --g++
    +
    --no_g++
    +
    +
    +
    Enable or disable GNU C++ language compatibility features. This +option also specifies that the source language being compiled is C++. +It is only recognized when GNU_EXTENSIONS_ALLOWED is TRUE.
    +
    +
    +
    --gcc
    +
    --no_gcc
    +
    +
    +
    Enable or disable GNU C language compatibility features. This option +also specifies that the source language being compiled is C. It is +only recognized when GNU_EXTENSIONS_ALLOWED is TRUE.
    +
    +
    +
    --gnu_version version-number
    +

    +
    +
    +
    The version of the GNU compiler that should be emulated in any of the +GNU (C or C++) modes. Version x.y.z of the GNU compiler is encoded as +x*10000+y*100+z (e.g., version 3.4.1 is emulated with the option +“--gnu_version 30401”).
    +
    +
    +
    --microsoft
    +
    --microsoft_16
    +
    --no_microsoft
    +
    +
    +
    Enable or disable Microsoft emulation mode. These options may only be +used if MICROSOFT_EXTENSIONS_ALLOWED is TRUE. --microsoft +enables 32-bit mode. --microsoft_16 enables 16-bit mode (i.e., +support for near and far; the option is accepted only if +NEAR_AND_FAR_ALLOWED is TRUE). The default values are supplied by +DEFAULT_MICROSOFT_MODE and DEFAULT_NEAR_AND_FAR_ENABLED. In +Microsoft emulation mode, language features that are not recognized by +the Microsoft compiler are disabled by default. In most cases these +features can then be enabled through use of other command line options +(for example, --bool). Microsoft bugs mode is also enabled when +DEFAULT_MICROSOFT_BUGS is TRUE.
    +
    +
    +
    --microsoft_version version-number
    +
    +
    +
    The version of the Microsoft compiler that should be emulated in +Microsoft mode. This enables or disables particular Microsoft mode +features when the acceptance of those features varies between versions +of the Microsoft compiler. The value specified is the value of the +predefined macro _MSC_VER supplied by the version of the Microsoft +compiler to be emulated. For example, 1100 is the value that +corresponds to Visual C++ version 5.0. This option also enables +Microsoft mode, but it does not imply either 16-bit or 32-bit mode +(i.e., it uses whatever value has already been specified, or the +default value if none has been explicitly specified).
    +
    +
    +
    --microsoft_build_number build-number
    +
    +
    +
    The “build number” of the Microsoft compiler that should be emulated +in Microsoft mode (this option also enables Microsoft mode). This +value is used to set the value of the predeclared macro +_MSC_FULL_VER (which is a concatenation of the microsoft version +number and the build number; e.g., with “--microsoft_version 1600 +--microsoft_build_number 30507” _MSC_FULL_VER is defined to +expand to 160030507). The default build number is 99999.
    +
    +
    +
    --microsoft_bugs
    +
    --no_microsoft_bugs
    +
    +
    +
    Enable or disable recognition of certain Microsoft bugs. These +options also enable Microsoft mode. Microsoft bugs mode is +automatically enabled when Microsoft mode is used and +DEFAULT_MICROSOFT_BUGS is TRUE.
    +
    +
    +
    --ms_await
    +
    +
    +
    Emulate the Microsoft Visual Studio /await command-line switch +that enables a pre-C++20 version of coroutines.
    +
    +
    +
    --ms_await_strict
    +
    +
    +
    Emulate the Microsoft Visual Studio /await:strict command-line +switch that enables a pre-C++20 version of coroutines.
    +
    +
    +
    --ms_c11
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c11 command-line switch +by enabling the same set of C11 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1927 for this +option to have an effect.
    +
    +
    +
    --ms_c17
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c17 command-line switch +by enabling the same set of C17 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1928 for this +option to have an effect.
    +
    +
    +
    --ms_c23
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c23 command-line switch +by enabling the same set of C23 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1935 for this +option to have an effect.
    +
    +
    +
    --ms_c++14
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c++14 command-line switch +by enabling the same set of C++14 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1903 to use this +option.
    +
    +
    +
    --ms_c++17
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c++17 command-line switch +by enabling the same set of C++17 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1911 to use this +option.
    +
    +
    +
    --ms_c++20
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c++20 command-line switch +by enabling the same set of C++20 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1920 to use this +option.
    +
    +
    +
    --ms_c++23
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c++23 command-line switch +by enabling the same set of C++23 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1943 to use this +option.
    +
    +
    +
    --ms_c++latest
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c++latest command-line +switch by enabling the same set of C++ options as are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro.
    +
    +
    +
    --ms_compatibility
    +
    --no_ms_compatibility
    +
    +
    +
    Enable or disable certain Microsoft compatibility options (as defined +by the clang-fms-compatibility option). Unlike the +--microsoft option (i.e., Microsoft emulation mode), this +command-line option can be combined with other emulation modes (e.g., +--clang). Specifying --ms_compatibility implies +--ms_extensions. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro.
    +
    +
    +
    --ms_std_preprocessor
    +
    --no_ms_std_preprocessor
    +
    +
    +
    Enable or disable a mode in which the behavior of the preprocessor in +Microsoft emulation mode conforms with the C and C++ Standards; when +disabled, the preprocessor emulates the behavior of the traditional +Microsoft preprocessor.
    +
    +
    +
    --ms_stdc
    +
    --no_ms_stdc
    +
    +
    +
    Emulate the /Zc:__STDC__ option of Microsoft’s Visual Studio by +setting the value of the __STDC__ macro to the value 1 or +leaving the macro undefined respectively. Implicitly enables +Microsoft emulation mode.
    +
    +
    +
    --ms_cplusplus_std_value
    +
    --no_ms_cplusplus_std_value
    +

    +
    +
    +
    Emulate the /Zc:__cplusplus[-] option of Microsoft’s Visual Studio +by either setting the value of the __cplusplus macro to the value +implied by the C++ standard currently being implemented or leaving it +as the default value of 199711L used by Visual Studio. Implicitly +enables Microsoft emulation mode.
    +
    +
    +
    --ms_extensions
    +
    --no_ms_extensions
    +
    +
    +
    Enable or disable certain Microsoft extensions (as defined by the +clang-fms-extensions option). Unlike the --microsoft +option (i.e., Microsoft emulation mode), this command-line option can +be combined with other emulation modes (e.g., --clang). If not +specified explicitly with the --microsoft_version command-line +option, microsoft_version is set to the value of the +DEFAULT_MICROSOFT_VERSION macro.
    +
    +
    +
    --ms_permissive
    +
    --no_ms_permissive
    +
    +
    +
    Enable or disable “permissive” mode during Microsoft emulation. These +command-line options control emulation of the Visual Studio +/permissive[-] command-line options and can be used in C, C++, +C++/CLI, or C++/CX modes. The default value is controlled by the +DEFAULT_MS_PERMISSIVE configuration macro. Specifying one of +these command-line options also implicitly enables Microsoft emulation +mode.
    +
    +
    +
    --nonstd_gnu_keywords
    +
    --no_nonstd_gnu_keywords
    +

    +
    +
    +
    In GNU modes, --no_nonstd_gnu_keywords disables GNU-specific +keywords that do not start with underscores (notably: typeof); the +option has no effect in other modes. --nonstd_gnu_keywords is +only accepted in GNU modes and enables any keywords that were disabled +by a prior occurrence of --no_nonstd_gnu_keywords.
    +
    +
    +
    --no_strict_gnu
    +
    --strict_gnu
    +
    +
    +
    For every version of the C and C++ ISO standards, the GNU and Clang +compilers support both the language as defined by ISO (with +-std=c* command-line options) as well as the language with certain +incompatible compiler-specific extensions (with -std=gnu*). +Specifying --strict_gnu on the command-line causes the front end +to emulate the -std=c* behavior of the selected GNU/Clang +compiler, while specifying --no_strict_gnu emulates the +-std=gnu* behavior. When these options are not specified, the +front end implicitly emulates the -std=c* behavior whenever any +--c* or --c++* command-line options are specified (e.g., +--c++11 mimics -std=c++11); otherwise the -std=gnu* +behavior is emulated.
    +
    +
    +
    --strict_warnings or -a
    +
    --strict or -A
    +
    +
    +
    Enable strict ANSI/ISO mode, which provides diagnostic messages when +nonstandard features are used, and disables features that conflict +with ANSI/ISO C or C++. This is compatible with both C and C++ mode. +It is not compatible with pcc mode. ANSI/ISO violations can be issued +as either warnings or errors depending on which command line option is +used. The -A and --strict options cause errors to be issued +whereas the -a and --strict_warnings options produce warnings. +(Note that nonstandard types, functions, etc., that might be +predeclared by various compilers will not be declared by the front end +in this mode, so any references to these names will be diagnosed as +errors, regardless of which of these options is specified.) The error +threshold is set so that the requested diagnostics will be listed.
    +
    +
    +
    --stricter_template_checking
    +
    +
    +
    If a selected dialect weakens the type checking performed in a +template, adding this option makes it stricter again (although not +always as strict as what is done in strict ANSI/ISO mode).
    +
    +
    +
    --sun
    +
    --no_sun
    +
    +
    +
    Enable or disable Sun CC (version 5.x) language compatibility +features. This option can only be used in C++ mode, and cannot be +combined with options to enable strict ANSI mode, or compatibility +with cfront, Microsoft, or GNU. It is only recognized when +SUN_EXTENSIONS_ALLOWED is TRUE.
    +
    +
    +
    --svr4
    +
    --no_svr4
    +
    +
    +
    Enable or disable recognition of SVR4 C compatibility features. The +default value is supplied by DEFAULT_SVR4_C_MODE. This option +also specifies that the source language being compiled is ANSI C.
    +
    +
    +
    --upc
    +
    --no_upc
    +
    +
    +
    Enable or disable UPC (Unified Parallel C) extensions.
    +
    +
    +
    --upc_threads n
    +
    +
    +
    Specify a fixed number of UPC threads (this is the value of the +THREADS identifier).
    +
    +
    +
    --upc_strict
    +
    --upc_relaxed
    +
    +
    +
    Specify the default UPC access method for objects of shared types.
    +
    +
    +
    +
    +
    +

    2.1.2. Input/output Options#

    +

    The following options control the kind of input read or output produced or the +location of such input or output.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --unicode_source_kind kind
    +

    +
    +
    +
    Source input files that do not begin with a byte order mark indicating +the kind of Unicode encoding are assumed to use the Unicode encoding +indicated by kind. Possible values of kind are UTF-8, +UTF-16, UTF-16LE (little-endian), UTF-16BE (big-endian), +and none (to indicate that the source file is not Unicode).
    +
    +
    +
    --gen_c_file_name file-name
    +

    +
    +
    +
    When using the C-generating back end or the C++-generating back end, +this option specifies the file name to be used for the generated +output.
    +
    +
    +
    --dependencies
    +
    -M
    +
    +
    +
    Do preprocessing only. Instead of the normal preprocessing output, +generate on the preprocessing output file a list of dependency lines +suitable for input to the UNIX make program. Note that when +implicit inclusion of templates is enabled, the output may indicate +false (but safe) dependencies unless --no_preproc_only is also +used.
    +
    +
    +
    --error_output efile
    +
    +
    +
    Redirect the output that would normally go to the error output +file (i.e., diagnostic messages) to the file efile. This option +is useful on systems where output redirection of files is not well +supported. If used, this option should probably be specified +first in the command line, since otherwise any command-line errors +for options preceding the --error_output would be written to +stderr before redirection.
    +
    +
    +
    --list lfile
    +
    -Llfile
    +
    +
    +
    Generate raw listing information in the file lfile. This +information is likely to be used to generate a formatted listing. +The raw listing file contains raw source lines, information on +transitions into and out of include files, and diagnostics +generated by the front end. Each line of the listing file begins +with a key character that identifies the type of line, as follows:
    +
    +
    +
    N:

    a normal line of source; the rest of the line is the text of the +line.

    +
    +
    X:

    the expanded form of a normal line of source; the rest of the +line is the text of the line. This line appears following the N +line, and only if the line contains non-trivial modifications +(comments are considered trivial modifications; macro expansions, +line splices, and trigraphs are considered non-trivial +modifications). Comments are replaced by a single space in the +expanded-form line.

    +
    +
    S:

    a line of source skipped by an #if or the like; the rest of the +line is text. Note that the #else, #elif, or #endif that ends a +skip is marked with an N.

    +
    +
    L:

    an indication of a change in source position. The line has a +format similar to the # line-identifying directive output by cpp, +that is to say

    +
    +

    L line-number "file-name" key

    +
    +

    where key is 1 for entry into an include file, 2 for exit from an +include file, and omitted otherwise. The first line in the raw +listing file is always an L line identifying the primary input +file. L lines are also output for #line directives (key is +omitted). L lines indicate the source position of the following +source line in the raw listing file.

    +
    +
    R, W, E, or C:

    an indication of a diagnostic (R for remark, W for +warning, E for error, and C for catastrophic error). The +line has the form

    +
    +

    S "file-name" line-number column-number +message-text

    +
    +

    where S is R, W, E, or C, as explained +above. Errors at the end of file indicate the last line of the +primary source file and a column number of zero. Command-line +errors are catastrophes with an empty file name ("") and a +line and column number of zero. Internal errors are catastrophes +with position information as usual, and message-text beginning +with (internal error). When a diagnostic displays a list (e.g., +all the contending routines when there is ambiguity on an +overloaded call), the initial diagnostic line is followed by one +or more lines with the same overall format (code letter, file +name, line number, column number, and message text), but in which +the code letter is the lower case version of the code letter in +the initial line. The source position in such lines is the same +as that in the corresponding initial line.

    +
    +
    +
    +
    --list_macros
    +
    +
    +
    Do preprocessing only. Instead of the normal preprocessing output, +generate on the preprocessing output file a list of all the macros in +effect after processing the source file, including predefined and +command-line macros along with their definitions.
    +
    +
    +
    --no_line_commands
    +
    -P
    +
    +
    +
    Do preprocessing only. Write preprocessed text to the preprocessing +output file, with comments removed and without line control +information.
    +
    +
    +
    --old_line_commands
    +
    +
    +
    When generating source output (e.g., with the C-generating back end), +put out #line directives in the form used by the Reiser cpp, i.e., +“# nnn” instead of “#line nnn”.
    +
    +
    +
    --output ofile
    +
    -o ofile
    +
    +
    +
    Specify the output file of the compilation, i.e., the preprocessing or +intermediate language output file.
    +
    +
    +
    --xref xfile
    +
    -Xxfile
    +
    +
    +
    Generate cross-reference information in the file xfile. For each +reference to an identifier in the source program, a line of the form
    +
    +
    +

    symbol-id name ref-code file-name line-number column-number

    +
    +
    +
    is written, where ref-code is D for definition, d for +declaration (that is, a declaration that is not a definition), T +for a full template instantiation, t for a partial template +instantiation (i.e., an instantiation of the template declaration, but +not of its definition), M for modification, A for address +taken, U for used, C for changed (but actually meaning “used +and modified in a single operation,” such as an increment), R for +any other kind of reference, or E for an error in which the kind +of reference is indeterminate. symbol-id is a unique decimal number +for the symbol. The fields of the above line are separated by tab +characters.
    +
    +
    +
    --create_header_unit file
    +
    +
    +
    Write an EDG IFC header unit file +representing the current translation unit to file.
    +
    +
    +
    --create_module_interface file
    +

    +
    +
    +
    Write an EDG IFC module file for a module interface unit to file.
    +
    +
    +
    --create_module_internal_partition file
    +

    +
    +
    +
    Write an EDG IFC module file for a module implementation unit to +file.
    +
    +
    +
    --module_interface
    +
    +
    +
    Write an EDG IFC module file for a module interface unit in the +current working directory. The filename is derived from the parsed +module declaration.
    +
    +
    +
    --module_internal_partition
    +

    +
    +
    +
    Write an EDG IFC module file for a module implementation unit in the +current working directory. The filename is derived from the parsed +module declaration.
    +
    +
    +
    +
    +
    +

    2.1.3. Preprocessor Options#

    +

    The following options control the behavior of the preprocessor.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --comments
    +
    -C
    +
    +
    +
    Keep comments in the preprocessed output. This should be specified +after either --preprocess or --no_line_commands; it does not +of itself request preprocessing output.
    +
    +
    +
    --define_macro name [ ( parm-list ) ] [ = def ]
    +
    -D name [ ( parm-list ) ] [ = def ]
    +

    +
    +
    +
    Define macro name as def. If “= def “ is omitted, +define name as 1. Function-style macros can be defined by +appending a macro parameter list to name.
    +
    +
    +
    --embed_directory dir
    +
    +
    +
    Add dir to the list of directories searched for #embeds. The +process by which files named in #embed directives are found is similar +to that used for #include. See Finding Include Files.
    +
    +
    +
    --import_dir dir-name
    +
    +
    +
    Specify the directory in which the files to be included by #import +directives are to be found. These files must have been generated +previously by the Microsoft compiler. This option is valid only in +Microsoft mode.
    +
    +
    +
    --incl_suffixes str
    +
    +
    +
    Specifies the list of suffixes to be used when searching for an +include file whose name was specified without a suffix. The +argument is a colon-separated list of suffixes (e.g., +"h:hpp::"). If a null suffix is to be allowed, it must be +included in the suffix list. The default is specified by the +configuation flag DEFAULT_INCLUDE_FILE_SUFFIX_LIST.
    +
    +
    +
    --include_directory dir
    +
    --sys_include dir
    +
    -Idir
    +
    +
    +
    Add dir to the list of directories searched for #includes. +See Finding Include Files.
    +
    +
    +
    --modules_directory dir
    +

    +
    +
    +
    Add dir to the list of directories searched for module files when +processing an import directive. The current working directory is +automatically added to the start of this list. If the +EDG_MODULES_PATH environment variable is set, that path is added +to the end of the list. See Finding Module Files.
    +
    +
    +
    --ms_header_unit header_path=module_file
    +
    --header_unit header_path=module_file
    +

    +
    +
    +
    Add module_file to the header unit map, corresponding to +header_path. When importing a header unit, if the resolved path +to the header matches header_path, then module_file is used as +the match. See Finding Module Files.
    +
    +
    +
    --ms_header_unit_angle header_path=module_file
    +
    --ms_header_unit_quote header_path=module_file
    +

    +
    +
    +
    Add module_file, corresponding to header_path, to a header +unit map selected by the form in which header_path is written, +<...> and "...", respectively. Unlike –ms_header_unit, +header_path is not resolved immediately but will be resolved on +demand. (See Finding Include Files.) If the resolved path to +the header for the header unit matches the resolved header_path, +module_file is used as the match. See Finding Module Files.
    +
    +
    +
    --ms_mod_file_map [ module_name= ] file
    +

    +
    +
    +
    If module_name is omitted, file will be examined to determine +if the module it represents matches the module named in the +import directive. Otherwise, an import of module_name will +resolve to file without examining its contents. See +Finding Module Files.
    +
    +
    +
    --ms_translate_include
    +
    --no_ms_translate_include
    +

    +
    +
    +
    Enable or disable the automatic translation of #include +directives into import directives when a header has a mapping +to a module file in a header unit map (see --ms_header_unit, +--ms_header_unit_angle, and --ms_header_unit_quote +regarding how such mappings are specified.)
    +
    +
    +
    --old_style_preprocessing
    +

    +
    +
    +
    Forces pcc style preprocessing when compiling in ANSI C or C++ mode. +This may be used when compiling an ANSI C or C++ program on a system +in which the system header files require pcc style preprocessing.
    +
    +
    +
    --preinclude_macros filename
    +
    --preinclude filename
    +
    +
    +
    Include the source code of the indicated file at the beginning of the +compilation. This can be used to establish standard macro +definitions, etc. The file name is searched for in the directories on +the include search list. When the preinclude_macros variant is +used, only the preprocessing directives from the file are evaluated. +All of the actual code is discarded. The effect of this option is +that any macro definitions from the specified file will be in effect +when the primary source file is compiled. All of the macro-only files +are processed before any of the normal preincludes. Within each +group, the files are processed in the order in which they were +specified.
    +
    +
    +
    --preprocess
    +
    -E
    +
    +
    +
    Do preprocessing only. Write preprocessed text to the preprocessing +output file, with comments removed and with line control information.
    +
    +
    +
    --no_preproc_only
    +
    +
    +
    May be used in conjunction with the options that normally cause the +front end to do preprocessing only (e.g., --preprocess, etc.) to +specify that a full compilation should be done (not just +preprocessing). When used with the implicit inclusion option, this +makes it possible to generate a preprocessed output file that includes +any implicitly included files.
    +
    +
    +
    --stdc_zero_in_system_headers
    +
    --no_stdc_zero_in_system_headers
    +

    +
    +
    +
    Enable or disable special processing of the __STDC__ macro +when referenced from system headers. When this feature is +enabled, __STDC__ has the value zero in system header files +(files found in directories specified using the --sys_include +option) and one otherwise. This feature is provided to emulate +the behavior of gcc in certain configurations. The default is +specified by DEFAULT_STDC_ZERO_IN_SYSTEM_HEADERS. If the flag +is not TRUE by default, the GNU mode default is specified by the +DEFAULT_GNU_STDC_ZERO_IN_SYSTEM_HEADERS macro.
    +
    +
    +
    --trace_includes
    +
    -H
    +
    +
    +
    Output a list of the names of files #included to the error +output file. The source file is compiled normally (i.e., it is not +just preprocessed) unless another option that causes preprocessing +only is specified.
    +
    +
    +
    --undefine_macro name
    +
    -Uname
    +
    +
    +
    Remove any initial definition of the macro name. +--undefine_macro options are processed after all +--define_macro options in the command line have been +processed.
    +
    +
    +
    --check_concatenations
    +
    --no_check_concatenations
    +

    +
    +
    +
    Specifies whether or not the front end will issue a diagnostic if a +concatenation operator ## in a macro expansion fails to produce a +valid preprocessor token as required by the C and C++ Standards.
    +
    +
    +
    --no_token_separators_in_pp_output
    +

    +
    +
    +
    Used in connection with options that generate preprocessing output, +suppresses the extra spaces the front end inserts in the text of macro +expansions to ensure that tokens that should not be combined remain +separate tokens. This can be used to prevent the insertion of +extraneous spaces when the front end is used as a preprocessor for +text that is not C or C++.
    +
    +
    +
    +
    +
    +

    2.1.4. Diagnostic Options#

    +

    The following options control when or how diagnostics are emitted.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --add_match_notes
    +
    --no_add_match_notes
    +
    +
    +
    Enable or disable diagnostic notes that +provide further details for a failure to match candidates in an +overload set.
    +
    +
    +
    --brief_diagnostics
    +
    --no_brief_diagnostics
    +

    +
    +
    +
    Enable or disable a mode in which a shorter form of the diagnostic +output is used. When enabled, the original source line is not +displayed and the error message text is not wrapped when too long to +fit on a single line.
    +
    +
    +
    --colors
    +
    --no_colors
    +
    +
    +
    Enable or disable colorization of diagnostic messages. The default +behavior is controlled by the DEFAULT_ENABLE_COLORIZED_DIAGNOSTICS +configuration macro (which defaults to TRUE). Colorized +diagnostics are disabled when not writing to a terminal, and are also +disabled when the NOCOLOR environment variable is set, the +TERM environment variable is unset, or the EDG_COLORS +environment variable is set to an empty string.
    +
    +
    +
    --constexpr_diag_suppress tag, tag,…
    +
    --constexpr_diag_remark tag, tag,…
    +
    --constexpr_diag_warning tag, tag,…
    +
    --constexpr_diag_error tag, tag,…
    +
    +
    +
    Override the severity of the diagnostics that calls of +__builtin_constexpr_diag request with any of the specified tags. +A tag is shown in brackets at the end of the diagnostic it names, and +may contain only letters, digits, and underscores. When more than +one of these options names a given tag, the last one on the command +line takes effect.
    +
    +
    +
    --context_limit number
    +

    +
    +
    +
    Set the context limit to number. The context limit is the maximum +number of template instantiation context entries to be displayed as +part of a diagnostic message. The default is specified by the +DEFAULT_CONTEXT_LIMIT macro. If the number of context entries +exceeds the limit, the first and last N context entries are displayed, +where N is half of the context limit. A value of zero is used to +indicate that there is no limit.
    +
    +
    +
    --diag_suppress tag, tag,…
    +
    --diag_remark tag, tag,…
    +
    --diag_warning tag, tag,…
    +
    --diag_error tag, tag,…
    +
    +
    +
    Override the normal error severity of the specified diagnostic +messages. The message(s) may be specified using a mnemonic error tag +or using an error number. The error tag names and error numbers are +listed in the Error Messages appendix.
    +
    +
    +
    --diag_once tag, tag,…
    +
    +
    +
    Causes the specified diagnostic to be issued only once as a warning or +remark. The message(s) may be specified using a mnemonic error tag or +using an error number. The error tag names and error numbers are +listed in the Error Messages appendix.
    +
    +
    +
    --display_error_number
    +
    --no_display_error_number
    +

    +
    +
    +
    Enable or disable the display of an error message number in any +diagnostic messages that are generated. The option may be used to +determine the error number to be used when overriding the severity of +a diagnostic message. The configuration macro +DEFAULT_DISPLAY_ERROR_NUMBER specifies the default behavior.
    +
    +
    +
    --error_limit number
    +
    -e number
    +
    +
    +
    Set the error limit to number. The front end will abandon +compilation after this number of errors (remarks and warnings are +not counted toward the limit). By default, the limit is 100.
    +
    +
    +
    --for_init_diff_warning
    +
    --no_for_init_diff_warning
    +

    +
    +
    +
    Enable or disable a warning that is issued when programs compiled +under the new for-init scoping rules would have had different behavior +under the old rules. The diagnostic is only put out when the new +rules are used. DEFAULT_WARNING_ON_FOR_INIT_DIFFERENCE specifies +the default behavior. This option is valid only in C++ mode.
    +
    +
    +
    --lossy_conversion_warning
    +
    --no_lossy_conversion_warning
    +

    +
    +
    +
    Enable or disable a warning that is issued when conversion of an +arithmetic value to a different type might result in lost data because +the target type cannot represent all the values of the source type.
    +
    +
    +
    --macro_positions_in_diagnostics
    +
    --no_macro_positions_in_diagnostics
    +

    +
    +
    +
    Enable or disable display of extra information for diagnostics that +refer to text in macro expansions. These options may only be used if +FULLY_RESOLVED_MACRO_POSITIONS is TRUE. The additional +information includes the original source line from which the text +identified by the message was copied into the macro expansion (i.e., a +macro definition or an argument in the top-level macro invocation), as +well as the chain of macro invocations that led to the expanded text +designated by the diagnostic (if MACRO_INVOCATION_TREE_IN_IL is +TRUE). The default value is given by +DEFAULT_MACRO_POSITIONS_IN_DIAGNOSTICS.
    +
    +
    +
    --module_import_diagnostics
    +
    --no_module_import_diagnostics
    +

    +
    +
    +
    Enable or disable the issuing of diagnostics while importing entities +from module files.
    +
    +
    +
    --output_mode mode
    +
    +
    +
    Set the front end diagnostic output mode to mode. Valid modes +are text for traditional command line diagnostic output and +sarif for SARIF (Static Analysis Results Interchange Format) +output (see www.sarif.info).
    +
    +
    +
    --promote_warnings
    +
    -W
    +
    +
    +
    Issue all warnings as if they were discretionary errors.``
    +
    +
    +
    --remarks
    +
    -r
    +
    +
    +
    Issue remarks, which are diagnostic messages even milder than +warnings.
    +
    +
    +
    --report_gnu_extensions
    +

    +
    +
    +
    Warn about the use of certain GNU extensions outside system header +files. Only valid in GNU C or C++ mode.
    +
    +
    +
    --template_typedefs_in_diagnostics
    +
    --no_template_typedefs_in_diagnostics
    +

    +
    +
    +
    Disable or enable, respectively, the replacement of typedefs +declared in template classes with their underlying type. +Diagnostic messages are often more useful when such typedefs are +replaced. The default behavior is specified by the +DEFAULT_TEMPLATE_TYPEDEFS_IN_DIAGNOSTICS macro.
    +
    +
    +
    --timing
    +
    -#
    +
    +
    +
    Generate compilation timing information. This option causes the +compiler to display the amount of CPU time and elapsed time used by +each phase of the compilation and a total for the entire compilation.
    +
    +
    +
    --top_templates number
    +
    +
    +
    At the end of the compilation, write to the error output file a report +of the templates that were substituted the most. number specifies +how many templates to report; if it is zero, every template that has a +nonzero number of substitutions is reported.
    +
    +
    +
    --no_use_before_set_warnings
    +
    -j
    +
    +
    +
    Suppress warnings on local automatic variables that are used before +their values are set. The front end’s algorithm for detecting such +uses is conservative and is likely to miss some cases that an +optimizer with sophisticated flow analysis could detect; thus, an +implementation might choose to suppress the warnings from the front +end when optimization has been requested but to permit them when the +optimizer is not being run.
    +
    +
    +
    --no_warnings
    +
    -w
    +
    +
    +
    Suppress warnings. Errors are still issued.
    +
    +
    +
    --wrap_diagnostics
    +
    --no_wrap_diagnostics
    +
    +
    +
    Enable or disable a mode in which the error message text is not +wrapped when too long to fit on a single line.
    +
    +
    +
    +
    +
    +

    2.1.5. Individual Language Features#

    +

    The following options enable or disable specific language syntax. (Options +that affect the meaning of existing constructs are listed in +Alternative Language Behaviors.)

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --alternative_tokens
    +
    --no_alternative_tokens
    +

    +
    +
    +
    Enable or disable recognition of alternative tokens. This controls +recognition of the digraph tokens in C and C++, and controls +recognition of the operator keywords (e.g., and, bitand, etc.) +in C++. The default behavior is specified by the +DEFAULT_ALTERNATIVE_TOKENS_ALLOWED configuration constant.
    +
    +
    +
    --array_new_and_delete
    +
    --no_array_new_and_delete
    +

    +
    +
    +
    Enable or disable support for array new and delete. The default +behavior is specified by the configuration constant +DEFAULT_ARRAY_NEW_AND_DELETE_ENABLED. This option is valid only +in C++ mode. The front end can be configured to define a +preprocessing variable when array new and delete are enabled. This +preprocessing variable may then be used by the standard header files +to decide whether to include the declarations for the array new/delete +functions.
    +
    +
    +
    --auto_storage
    +
    --no_auto_storage
    +
    +
    +
    Enable or disable the traditional meaning of auto as a storage +class specifier (only valid in C++ mode). (If disabled, then auto +must be a type specifier.). The default behavior is specified by the +DEFAULT_AUTO_STORAGE_CLASS_SPECIFIER_ENABLED configuration +constant.
    +
    +
    +
    --auto_type
    +
    --no_auto_type
    +
    +
    +
    Enable or disable auto as a type specifier where the actual type +is deduced from an initializer (only valid in C++ mode). This is a +C++11 feature. If enabled, the traditional meaning of auto as a +storage class specifier is disabled (which matches C++11), unless the +option --auto_storage is also supplied. The default behavior is +specified by the DEFAULT_AUTO_TYPE_SPECIFIER_ENABLED configuration +constant.
    +
    +
    +
    --bit_precise_integers
    +
    --no_bit_precise_integers
    +
    +
    +
    Enable or disable support for C23-style _BitInt types.
    +
    +
    +
    --bool
    +
    --no_bool
    +
    +
    +
    Enable or disable recognition of bool. The default value is +supplied by DEFAULT_BOOL_IS_KEYWORD. This option is valid only in +C++ mode. The front end can be configured to define a preprocessing +variable when bool is recognized. This preprocessing variable may +then be used by header files to determine whether a typedef should be +supplied to define bool.
    +
    +
    +
    --c23_typeof
    +
    --no_c23_typeof
    +
    +
    +
    Enable or disable support for the C23 typeof and +typeof_unqual operators, regardless of the current C language +level. This option is valid only in C mode.
    +
    +
    +
    --c++11_sfinae
    +
    --no_c++11_sfinae
    +
    +
    +
    Enable or disable template deduction in the style dictated by the +C++11 standard, i.e., where general expressions are allowed in +deduction contexts and they undergo the full usual semantic +checking. This type of deduction is necessary to get the full +power of the decltype feature in return types. (“SFINAE” is +an acronym for “Substitution Failure Is Not An Error”, which is +the guiding principle for template deduction, and by extension a +name for the process of deduction.)
    +
    +
    +
    --c++11_sfinae_ignore_access
    +
    --no_c++11_sfinae_ignore_access
    +

    +
    +
    +
    When new-style SFINAE is enabled, these options control whether or not +access errors cause deduction failures. The positive option indicates +that access checking should not be done during template deduction, and +therefore that access errors cannot cause a deduction failure; this +was the status quo ante when the new-style SFINAE rules were proposed. +The “no” version of the option indicates that access checking +should be done during template deduction, and therefore that access +errors cause a deduction failure; this is the revised direction chosen +by the standards committee.
    +
    +
    +
    --char8_t
    +
    --no_char8_t
    +

    +
    +
    +
    Enable or disable support for the char8_t keyword and type (a +C++20 feature). Enabled by default in C++20 mode.
    +
    +
    +
    --compound_literals
    +
    --no_compound_literals
    +
    +
    +
    Enable or disable support for “compound literals” (a C99 feature).
    +
    +
    +
    --concepts
    +
    --no_concepts
    +

    +
    +
    +
    Enable or disable support for concepts (a C++20 feature).
    +
    +
    +
    --delegating_constructors
    +
    --no_delegating_constructors
    +

    +
    +
    +
    Enable or disable delegating constructors (a C++11 feature).
    +
    +
    +
    --deprecated_string_conv
    +
    --no_deprecated_string_conv
    +

    +
    +
    +
    Enable or disable the deprecated conversion from a string literal to +char *. Meaningful only when string literals are const.
    +
    +
    +
    --designators
    +
    --no_designators
    +
    +
    +
    Enable or disable support for designators (a C99 feature). These +options are not available in C++ mode.
    +
    +
    +
    --digit_separators
    +
    --no_digit_separators
    +
    +
    +
    Enable or disable support for digit separators (a C++14 feature). +When this feature is enabled, an apostrophe can appear between the +digits of a numeric literal and is ignored, e.g., 123'456'789.
    +
    +
    +
    --extended_designators
    +
    --no_extended_designators
    +

    +
    +
    +
    Enable or disable support for “extended designators,” an extension +accepted only in C mode to emulate the behavior of certain other C +compilers when it comes to designators in aggregate initializers.
    +
    +
    +
    --dollar
    +
    -$
    +
    +
    +
    Accept dollar signs in identifiers. The default value of this option +is specified in a configuration file.
    +
    +
    +
    --exceptions--no_exceptions
    +
    -x
    +
    +
    +
    Enable or disable support for exception handling. -x is +equivalent to --exceptions. The default behavior is specified by +the configuration constant DEFAULT_EXCEPTIONS_ENABLED. This +option is valid only in C++ mode.
    +
    +
    +
    --exc_spec_in_func_type
    +
    --no_exc_spec_in_func_type
    +
    +
    +
    Enable or disable exceptions being part of a function type (enabled by +default in C++17 modes and disabled by default otherwise).
    +
    +
    +
    --explicit
    +
    --no_explicit
    +
    +
    +
    Enable or disable support for the explicit specifier on +constructor declarations. The default behavior is specified by the +configuration constant DEFAULT_EXPLICIT_KEYWORD_ENABLED. This +option is valid only in C++ mode.
    +
    +
    +
    --export
    +
    --no_export
    +
    +
    +
    Enable or disable recognition of exported templates. The default +value is supplied by DEFAULT_EXPORT_TEMPLATE_ALLOWED. This option +is valid only in C++ mode. This option requires that dependent name +processing be done, and cannot be used with implicit inclusion of +template definitions.
    +
    +
    +
    --extern_inline
    +
    --no_extern_inline
    +
    +
    +
    Enable or disable support for inline functions with external +linkage in C++. When inline functions are allowed to have +external linkage (as required by the standard), then extern and +inline are compatible specifiers on a nonmember function +declaration; the default linkage when inline appears alone is +external (that is, inline means extern inline on nonmember +functions); and an inline member function takes on the linkage of +its class (which is usually external). However, when inline +functions have only internal linkage (as specified in the ARM), then +extern and inline are incompatible; the default linkage when +inline appears alone is internal (that is, inline means +static inline on nonmember functions); and inline member +functions have internal linkage no matter what the linkage of their +class.
    +
    +
    +
    --fixed_point
    +
    --no_fixed_point
    +
    +
    +
    Enable or disable support for Embedded C fixed-point types. (Not +available in C++ modes.)
    +
    +
    +
    --lambdas
    +
    --no_lambdas
    +
    +
    +
    Enable or disable support for C++11 lambdas. (Only available in C++ +modes.)
    +
    +
    +
    --long_long
    +
    +
    +
    Permit the use of long long in strict mode in dialects in which it +is non-standard.
    +
    +
    +
    --modules
    +
    --no_modules
    +
    +
    +
    Enable or disable support for modules. Modules are currently +experimental and will be enabled by default in future releases in the +applicable modes. The front end does not currently generate modules +files of its own and can only consume module files produced by +Microsoft Visual Studio version 16.8. This support is incomplete and +compatibility will change in future releases.
    +

    +
    +
    +
    --multibyte_chars
    +
    --no_multibyte_chars
    +
    +
    +
    Enable or disable processing for multibyte character sequences in +comments, string literals, and character constants. The default +behavior is specified by +DEFAULT_MULTIBYTE_CHARS_IN_SOURCE_ALLOWED. Multibyte encodings +are used for character sets like the Japanese SJIS.
    +
    +
    +
    --named_address_spaces
    +
    --no_named_address_spaces
    +

    +
    +
    +
    Enable or disable support for Embedded C named address space +qualifiers. (Not available in C++ modes.)
    +
    +
    +
    --named_registers
    +
    --no_named_registers
    +
    +
    +
    Enable or disable support for Embedded C named-register storage class +specifiers. (Not available in C++ modes.)
    +
    +
    +
    --namespaces
    +
    --no_namespaces
    +
    +
    +
    Enable or disable support for namespaces. The default behavior is +specified by the configuration constant +DEFAULT_NAMESPACES_ENABLED. This option is valid only in C++ +mode.
    +
    +
    +
    --nonstd_using_decl
    +
    --no_nonstd_using_decl
    +

    +
    +
    +
    In C++, controls whether a nonmember using-declaration that specifies +an unqualified name is allowed.
    +
    +
    +
    --nullptr
    +
    --no_nullptr
    +
    +
    +
    Enable or disable support for the C++11/C23 nullptr keyword.
    +
    +
    +
    --old_specializations
    +
    --no_old_specializations
    +

    +
    +
    +
    Enable or disable acceptance of old-style template specializations +(i.e., specializations that do not use the template<> syntax). +Default behavior is specified by +DEFAULT_OLD_SPECIALIZATIONS_ALLOWED. This option is valid only in +C++ mode.
    +
    +
    +
    --relaxed_abstract_checking
    +
    --no_relaxed_abstract_checking
    +

    +
    +
    +
    Enable or disable a mode in which checking for the use abstract class +types as function parameter or return types is performed only when the +function is defined or called. Traditionally this checking has been +performed on non-defining function declarations as well, and this +behavior can be preserved via the second option.
    +
    +
    +
    --restrict
    +
    --no_restrict
    +
    +
    +
    Enable or disable recognition of the restrict keyword.
    +
    +
    +
    --rtti
    +
    --no_rtti
    +
    +
    +
    Enable or disable support for RTTI (runtime type information) +features: dynamic_cast, typeid. The default behavior is +specified by the configuration constant DEFAULT_RTTI_ENABLED. +This option is valid only in C++ mode.
    +
    +
    +
    --rvalue_ctor_is_copy_ctor
    +
    --rvalue_ctor_is_not_copy_ctor
    +

    +
    +
    +
    Determines whether an rvalue (or “move”) constructor is treated as a +copy constructor (the default) or not. If rvalue constructors are +treated as copy constructors, a user-declared rvalue constructor will +inhibit the implicit generation of a traditional copy constructor.
    +
    +
    +
    --rvalue_refs
    +
    --no_rvalue_refs
    +
    +
    +
    Enable or disable support for rvalue references. (Only valid in C++ +mode.)
    +
    +
    +
    --sun_linker_scope
    +
    --no_sun_linker_scope
    +

    +
    +
    +
    Enable or disable support for Sun CC 5.5 link scope specifiers +(__global, __symbolic, and __hidden). The default setting +is supplied by DEFAULT_SUN_LINKER_SCOPE_ALLOWED.
    +
    +
    +
    --thread_local_storage
    +
    --no_thread_local_storage
    +

    +
    +
    +
    Enable or disable the C++11 thread_local specifier (and, if so +configured, the __thread specifier) to indicate that variables +should be stored in thread-local storage. By default, the +__thread specifier is enabled in Sun mode and in GNU mode when +gnu_version >= 30400.
    +
    +
    +
    --trigraphs
    +
    --no_trigraphs
    +

    +
    +
    +
    Enable or disable recognition of trigraphs. The default behavior is +specified by the DEFAULT_TRIGRAPHS_ALLOWED configuration constant.
    +
    +
    +
    --typename
    +
    --no_typename
    +
    +
    +
    Enable or disable recognition of typename. The default value is +supplied by DEFAULT_TYPENAME_ENABLED. This option is valid only +in C++ mode.
    +
    +
    +
    --type_traits_helpers
    +
    --no_type_traits_helpers
    +

    +
    +
    +
    Enable or disable support for type traits helpers (like __is_union +and __has_virtual_destructor; intended to ease the implementation +of ISO/IEC TR 19768). Only valid in C++. Type traits helpers are +enabled in all C++ modes by default, except in GNU and Sun C++ modes.
    +
    +
    +
    --uliterals
    +
    --no_uliterals
    +
    +
    +
    Enable or disable recognition of U-literals (string literals of the +forms U"..." and u"...", and character literals of the forms +U'...' and u'...'). In C++ mode, this also enables or +disables the C++11 char16_t and char32_t keywords.
    +
    +
    +
    --unrestricted_unions
    +
    --no_unrestricted_unions
    +

    +
    +
    +
    Enable or disable C++11-style “unrestricted unions” (i.e., unions with +data members that have nontrivial initialization and/or destruction +semantics). This option can currently not be enabled in Microsoft +mode.
    +
    +
    +
    --user_defined_literals
    +
    --no_user_defined_literals
    +

    +
    +
    +
    Enable or disable C++11-style “user-defined literals,” i.e., +literals with a suffix designating an operator function that is to +be called to produce the value of the literal, e.g., 12.34_km, +which calls operator ""_km(12.34).
    +
    +
    +
    --utf8_char_literals
    +
    --no_utf8_char_literals
    +

    +
    +
    +
    Enable or disable C++17-style UTF-8 character literals (e.g., +u8'a'). Enabled by default in C++17 mode as well as when +microsoft_version >= 1900.
    +
    +
    +
    --variadic_macros
    +
    --no_variadic_macros
    +
    +
    +
    Enable or disable support for variadic macros (a C99 feature that is +also available in C++ mode).
    +
    +
    +
    --extended_variadic_macros
    +
    --no_extended_variadic_macros
    +

    +
    +
    +
    Enable or disable support for “extended variadic macros,” an extension +that emulates the behavior of certain other C compilers when it comes +to variadic macros.
    +
    +
    +
    --variadic_templates
    +
    --no_variadic_templates
    +

    +
    +
    +
    Enable or disable support for “variadic templates,” a C++11 feature +that allows declaration of templates with a variable number of +arguments. The default value is dependent on the major language mode +and on DEFAULT_VARIADIC_TEMPLATES_ENABLED. This option is valid +only in C++ modes.
    +
    +
    +
    --vla
    +
    --no_vla
    +
    +
    +
    Enable or disable support for “variable length arrays,” a C99 feature +and an extension in some other modes that allows the declaration and +use of arrays of automatic storage duration with dimensions that are +fixed at run time. These options are available only if +VLA_ALLOWED is configured to TRUE.
    +
    +
    +
    --wchar_t_keyword
    +
    --no_wchar_t_keyword
    +
    +
    +
    Enable or disable recognition of wchar_t as a keyword. The +default value is supplied by DEFAULT_WCHAR_T_IS_KEYWORD. This +option is valid only in C++ mode. The front end can be configured to +define a preprocessing variable when wchar_t is recognized as a +keyword. This preprocessing variable may then be used by the standard +header files to determine whether a typedef should be supplied to +define wchar_t.
    +
    +
    +
    +
    +
    +

    2.1.6. Alternative Language Behaviors#

    +

    The following options affect the meaning of various language constructs.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --aligned_new
    +
    --no_aligned_new
    +

    +
    +
    +
    Enable or disable calling special allocation and deallocation +functions for types with more stringent alignment requirements than +the fundamental types (enabled by default in C++17 modes and disabled +otherwise).
    +
    +
    +
    --arg_dep_lookup
    +
    --no_arg_dep_lookup
    +

    +
    +
    +
    In C++, controls whether argument dependent lookup of unqualified +function names is performed
    +
    +
    +
    --base_assign_op_is_default
    +
    --no_base_assign_op_is_default
    +

    +
    +
    +
    Enable or disable the anachronism of accepting a copy assignment +operator that has an input parameter that is a reference to a base +class as a default copy assignment operator for the derived class. +This option is enabled by default in cfront compatibility mode.
    +
    +
    +
    --class_name_injection
    +
    --no_class_name_injection
    +

    +
    +
    +
    In C++, controls whether the name of a class is injected into the +scope of the class (as required by the standard) or is not injected +(as was true in earlier versions of the C++ language).
    +
    +
    +
    --const_string_literals
    +
    --no_const_string_literals
    +

    +
    +
    +
    Control whether C++ string literals and wide string literals are const +(as required by the standard) or non-const (as was true in earlier +versions of the C++ language).
    +
    +
    +
    --default_calling_convention calling-convention
    +

    +
    +
    +
    The calling convention that should be assumed for functions that are +declared without an explicit calling convention. This option may only +be used if MICROSOFT_EXTENSIONS_ALLOWED is TRUE. +calling-convention must be one of __cdecl, __fastcall, +__stdcall, and __thiscall.
    +
    +
    +
    --default_nocommon_tentative_definitions
    +
    --default_common_tentative_definitions
    +

    +
    +
    +
    Control whether tentative definitions are placed in “common” storage. +These options are only available in configurations with +GNU_EXTENSIONS_ALLOWED set to TRUE. The default can be overridden +for specific variables with the GNU attributes common and +nocommon.
    +
    +
    +
    --defer_parse_function_templates
    +
    --no_defer_parse_function_templates
    +

    +
    +
    +
    Enable or disable deferral of prototype instantiations until the +first actual instantiation of a function. This is used to permit +the compilation of programs that contain definitions of unusable +function templates. It is enabled by default in g++ mode when +gnu_version is >= 30400 (but not when using the C++-generating +back end).
    +
    +
    +
    --dep_name
    +
    --no_dep_name
    +
    +
    +
    Enable or disable dependent name processing; i.e., the special lookup +of names used in templates as required by the C++ standard. The +default value is supplied by DEFAULT_DEPENDENT_NAME_PROCESSING. +This option is valid only in C++ mode and --dep_name cannot be +combined with --no_parse_templates.
    +
    +
    +
    --distinct_template_signatures
    +
    --no_distinct_template_signatures
    +

    +
    +
    +
    Control whether the signatures for template functions can match those +for non-template functions when the functions appear in different +compilation units. (This option is available only on versions that do +name mangling on the names of external entities.) The default is +--distinct_template_signatures, under which a normal function +cannot be used to satisfy the need for a template instance; e.g., a +function “void f(int)” could not be used to satisfy the need for +an instantiation of a template “void f(T)” with T set to +int. --no_distinct_template_signatures provides the older +language behavior, under which a non-template function can match a +template function. Also controls whether function templates may have +template parameters that are not used in the function signature of the +function template.
    +
    +
    +
    --enum_overloading
    +
    --no_enum_overloading
    +
    +
    +
    Enable or disable support for using operator functions to overload +builtin operations on enum-typed operands.
    +
    +
    +
    --far_data_pointers
    +
    --near_data_pointers
    +
    --far_code_pointers
    +
    --near_code_pointers
    +
    +
    +
    Set the default size for pointers when support for near and +far is enabled (e.g., in Microsoft 16-bit mode). Ignored in other +modes.
    +
    +
    +
    --friend_injection
    +
    --no_friend_injection
    +

    +
    +
    +
    In C++, controls whether the name of a class or function that is +declared only in friend declarations is visible when using the normal +lookup mechanisms. When friend names are injected, they are visible +to such lookups. When friend names are not injected (as required by +the standard), function names are visible only when using +argument-dependent lookup, and class names are never visible.
    +
    +
    +
    --func_prototype_tags
    +
    --no_func_prototype_tags
    +
    +
    +
    in C, controls whether tag types first +declared in a function prototype belong to the function prototype +scope (standard C behavior) or to a surrounding scope (default +Microsoft C behavior).
    +
    +
    +
    --gcc89_inlining
    +
    +
    +
    Use the GNU C89 semantics of inline in C99 mode. (Not valid in +C++ modes.)
    +
    +
    +
    --gen_move_operations
    +
    --no_gen_move_operations
    +

    +
    +
    +
    Enable or disable the generation of move constructors and move +assignment operators according to standard C++11 rules.
    +
    +
    +
    --guiding_decls
    +
    --no_guiding_decls
    +
    +
    +
    Enable or disable recognition of “guiding declarations” of template +functions. A guiding declaration is a function declaration that +matches an instance of a function template but has no explicit +definition (since its definition derives from the function template). +For example:
    +
    +
    +
    template <class T> void f(T) { ... }
    +void f(int);
    +
    +
    +
    +
    +
    When regarded as a guiding declaration, f(int) is an instance of +the template; otherwise, it is an independent function for which a +definition must be supplied. If --no_guiding_decls is combined +with --old_specializations, a specialization of a non-member +template function is not recognized – it is treated as a definition +of an independent function. Default behavior is specified by +DEFAULT_GUIDING_DECLS_ALLOWED. This option is valid only in C++ +mode.
    +
    +
    +
    --ignore_std
    +
    +
    +
    Enable a g++ compatibility feature that makes the std +namespace a synonym for the global namespace.
    +
    +
    +
    --implicit_extern_c_type_conversion
    +
    --no_implicit_extern_c_type_conversion
    +

    +
    +
    +
    Enable or disable an extension to permit implicit type conversion in +C++ between a pointer to an extern "C" function and a pointer to +an extern "C++" function. This extension is allowed in +environments where C and C++ functions share the same calling +conventions: IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE +must be set for it to be available. (It is useful for cfront +compatibility when DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT +is TRUE – in standard C++ the linkage specification is part of the +function type, with the consequence that otherwise identical function +types, one declared extern "C" and the other declared extern +"C++", are viewed as distinct.)
    +
    +
    +
    --implicit_noexcept
    +
    --no_implicit_noexcept
    +

    +
    +
    +
    Enable or disable the implicit generation of exception specifications +for user-declared destructors and deallocation functions in C++11 +mode. (In strict C++11 mode, it is enabled by default, whereas in +other C++11 modes it is disabled by default.)
    +
    +
    +
    --implicit_typename
    +
    --no_implicit_typename
    +

    +
    +
    +
    Enable or disable implicit determination, from context, whether a +template parameter dependent name is a type or nontype. The default +value is supplied by DEFAULT_IMPLICIT_TYPENAME_ENABLED. This +option is valid only in C++ mode.
    +
    +
    +
    --late_tiebreaker
    +
    --early_tiebreaker
    +
    +
    +
    Select the way that tie-breakers (e.g., cv-qualifier differences) +apply in overload resolution. In “early” tie-breaker processing, the +tie-breakers are considered at the same time as other measures of the +goodness of the match of an argument value and the corresponding +parameter type (this is the standard approach). In “late” tiebreaker +processing, tie-breakers are ignored during the initial comparison, +and considered only if two functions are otherwise equally good on all +arguments; the tie-breakers can then be used to choose one function +over another.
    +
    +
    +
    --long_lifetime_temps
    +
    --short_lifetime_temps
    +

    +
    +
    +
    Select the lifetime for temporaries: “short” means to end of full +expression; “long” means to the earliest of end of scope, end of +switch clause, or the next label. “short” is standard C++, and “long” +is what cfront uses (the cfront compatibility modes select “long” by +default).
    +
    +
    +
    --long_preserving_rules
    +
    --no_long_preserving_rules
    +

    +
    +
    +
    Enable or disable the K&R usual arithmetic conversion rules with +respect to long. This means the rules of K&R I, Appendix A, 6.6, +not the rules used by the pcc compiler. The significant difference is +in the handling of “long op unsigned int” when int and +long are the same size. The ANSI/ISO/pcc rules say the result is +unsigned long, but K&R I says the result is long (unsigned +long did not exist in K&R I).
    +
    +
    +
    --max_depth_constexpr_call= n
    +
    --max_cost_constexpr_call= n
    +

    +
    +
    +
    Specify the maximum depth of recursion or the maximum “cost” for +folding a top-level constexpr call (function or constructor). In +C++11 modes, the “cost” is the number of calls expanded from a single +top-level call. In C++14 modes, the “cost” is a combination of the +number of calls interpreted and the number of loop iterations +performed during the interpretation of a top-level call.
    +
    +
    +
    --ms_rvalue_cast
    +
    --no_ms_rvalue_cast
    +

    +
    +
    +
    Explicitly disable or enable treating a cast of an lvalue to its own +type as that same lvalue. (--ms_rvalue_cast corresponds to +standard behavior, but Microsoft compilers traditionally behaved +otherwise.) Implies Microsoft mode.
    +
    +
    +
    --ms_strict_ternary
    +
    --no_ms_strict_ternary
    +

    +
    +
    +
    Enable or disable strict standard-conforming behavior of the +conditional ternary operator (?:) in Microsoft mode. It is disabled +by default in Microsoft mode, unless Microsoft permissive mode is +disabled (see --no_ms_permissive). Implies Microsoft mode.
    +
    +
    +
    --nonconst_ref_anachronism
    +
    --no_nonconst_ref_anachronism
    +

    +
    +
    +
    Enable or disable the anachronism of allowing a reference to nonconst +to bind to a class rvalue of the right type. This anachronism is also +enabled by the --anachronisms option and the cfront-compatibility +options.
    +
    +
    +
    --nonstd_anonymous_unions
    +
    --no_nonstd_anonymous_unions
    +

    +
    +
    +
    Enable or disable extensions to the C++ anonymous union feature +(including of anonymous “structs” or “classes”). This option can also +be used in C modes. Enabled by default in GNU and Microsoft modes, +and disabled by default in strict modes.
    +
    +
    +
    --nonstd_default_arg_deduction
    +
    --no_nonstd_default_arg_deduction
    +

    +
    +
    +
    Controls whether default arguments are retained as part of deduced +function types. The C++ standard requires that default arguments not +be part of deduced function types.
    +
    +
    +
    --nonstd_instantiation_lookup
    +
    --no_nonstd_instantiation_lookup
    +

    +
    +
    +
    Controls whether the lookup of names during template instantiation +should, instead of the normal lookup rules, use rules that were part +of the C++98 working paper for some time during the development of the +standard. In this mode, names are looked up in both the namespace of +the template definition and in the namespace in which a template +entity was first referenced in a way that would require an +instantiation.
    +
    +
    +
    --nonstd_qualifier_deduction
    +
    --no_nonstd_qualifier_deduction
    +

    +
    +
    +
    Controls whether nonstandard template argument deduction should be +performed in the qualifier portion of a qualified name. With this +feature enabled, a template argument for the template parameter T +can de deduced in contexts like A<T>::B or T::B. The standard +deduction mechanism treats these as nondeduced contexts that use the +values of template parameters that were either explicitly specified or +deduced elsewhere.
    +
    +
    +
    --old_id_chars
    +
    --no_old_id_chars
    +
    +
    +
    Controls whether the set of extended characters accepted in C++ +identifiers should be those specified by pre-C++23 C++ standards or by +Unicode Standard Annex #44. The latter is the default in all C++ +modes, because the C++ Standard Committee adopted the Unicode +specification of identifier characters both for C++23 and +retroactively for earlier standards.
    +
    +
    +
    --old_for_init
    +
    --new_for_init
    +
    +
    +
    Control the scope of a declaration in a for-init-statement. The +old (cfront-compatible) scoping rules mean the declaration is in the +scope to which the for statement itself belongs; the new +(standard-conforming) rules in effect wrap the entire for +statement in its own implicitly generated scope. The default behavior +is specified by configuration constant +DEFAULT_USE_NONSTANDARD_FOR_INIT_SCOPE. This option is valid only +in C++ mode.
    +
    +
    +
    --pack_alignment n
    +
    +
    +
    Set the default alignment for packing classes and structs to n, a +power-of-2 value within the range defined by +TARG_MINIMUM_PACK_ALIGNMENT and TARG_MAXIMUM_PACK_ALIGNMENT. +The argument n is the default maximum alignment for nonstatic data +members; it can be overridden by a #pragma pack directive. This +option is allowed only when USER_CONTROL_OF_STRUCT_PACKING is +TRUE.
    +
    +
    +
    --parse_templates
    +
    --no_parse_templates
    +

    +
    +
    +
    Enable or disable the parsing of nonclass templates in their generic +form (i.e., even if they are not really instantiated). It is done by +default if dependent name processing is enabled. This option is valid +only in C++ mode.
    +
    +
    +
    --preserve_lvalues_with_same_type_casts
    +
    --no_preserve_lvalues_with_same_type_casts
    +

    +
    +
    +
    Explicitly enable or disable treating a cast of an lvalue to its own +type as that same lvalue (whereas both C and C++ specify that such +casts result in rvalues). Enabled by default in Microsoft and Sun +modes.
    +
    +
    +
    --require_func_prototypes
    +
    --no_require_func_prototypes
    +
    +
    +
    In C, controls whether old-style non-prototype function declarators +are recognized. If not, something like “int f();” is equivalent +to “int f(void);”. The default is that non-prototype function +declarators are not recognized in C23 mode, while they are recognized +in earlier C modes.
    +
    +
    +
    --short_enums
    +
    --no_short_enums
    +
    +
    +
    Enable or disable a mode in which all enumeration types are “packed” +(meaning that the underlying type of the enumeration is chosen to be +the smallest integer that will accommodate the enumerator constants). +Only valid in GNU C compatibility mode.
    +
    +
    +
    --signed_bit_fields
    +

    +
    +
    +
    Make bit fields declared with a plain integer type (e.g., short or +int, but not signed short or unsigned int) signed.
    +
    +
    +
    --signed_chars
    +
    -s
    +
    +
    +
    Make plain char signed. The default signedness for char is +selected at the time of installation of the front end (information on +this appears in a later section of this document). When plain +char is signed, the macro __SIGNED_CHARS__ is defined by the +front end.
    +
    +
    +
    --special_subscript_cost
    +
    --no_special_subscript_cost
    +

    +
    +
    +
    Enable or disable a special nonstandard weighting of the conversion to +the integral operand of the [] operator in overload resolution. +This is a compatibility feature that may be useful with some existing +code. The special cost is enabled by default in cfront 3.0 mode. +With this feature enabled, the following code compiles without error:
    +
    +
    +
    struct A {
    +  A();
    +  operator int *();
    +  int operator[](unsigned);
    +};
    +void main() {
    +  A a;
    +  a[0]; // Ambiguous, but allowed with
    +        // this option operator[]
    +        // is chosen
    +}
    +
    +
    +
    +
    +
    As of July 1996, the above is again acceptable, if ptrdiff_t is +configured as long. Using a parameter of type ptrdiff_t +(instead of unsignedint) is recommended for portability.
    +
    +
    +
    --no_stdarg_builtin
    +
    +
    +
    Disable special treatment of the <stdarg.h> header. When enabled, +the <stdarg.h> header is treated as a built-in, and references to +its macros (va_start et al) are passed through as such in +generated C or C++ code. The default value is supplied by +DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE. This option +cannot be used when the feature is disabled by default.
    +
    +
    +
    --unsigned_bit_fields
    +

    +
    +
    +
    Make bit fields declared with a plain integer type (e.g., short or +int, but not signed short or unsigned int) unsigned.
    +
    +
    +
    --unsigned_chars
    +
    -u
    +
    +
    +
    Make plain char unsigned. The default signedness for char is +selected at the time of installation of the front end (information on +this appears in a later section of this document).
    +
    +
    +
    --using_std
    +
    --no_using_std
    +
    +
    +
    Enable or disable implicit use of the std namespace when standard +header files are included. The default behavior is specified by the +configuration constant DEFAULT_IMPLICIT_USING_STD. This option is +valid only in C++ mode. Note that this does not do the equivalent +of putting a “using namespace std;” in the program to allow old +programs to be compiled with new header files; it has a special and +localized meaning related to the EDG versions of certain header files, +and is unlikely to be of much use to end-users of the Front End.
    +
    +
    +
    +
    +
    +

    2.1.7. Template Instantiation Options#

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --auto_instantiation
    +
    --no_auto_instantiation
    +
    -T
    +
    +
    +
    Enable or disable automatic instantiation of templates. The +-T option is equivalent to --auto_instantiation. The +default behavior is specified by the configuration flag +DEFAULT_AUTOMATIC_INSTANTIATION_MODE. See +Template Instantiation. This option is valid only in C++ +mode.
    +
    +
    +
    --definition_list_file file_name
    +

    +
    +
    +
    This option specifies the name of the template definition list file +passed between the front end and the prelinker. This file is a +temporary file and does not remain after the compilation is complete. +This option is supplied for use by the driver program that invokes the +front end and is not intended to be used by end-users.
    +
    +
    +
    --exported_template_file file-name
    +

    +
    +
    +
    This option specifies the name to be used for the exported template +file used for processing of exported templates. This option is +supplied for use by the driver program that invokes the front end and +is not intended to be used by end-users.
    +
    +
    +
    --ii_file file-name
    +
    +
    +
    This option specifies the name to be used for the template +instantiation request file used in automatic instantiation mode. This +option is supplied for use by the driver program that invokes the +front end and is not intended to be used by end-users.
    +
    +
    +
    --implicit_include
    +
    --no_implicit_include
    +
    -B
    +
    +
    +
    Enable or disable implicit inclusion of source files as a method +of finding definitions of template entities to be instantiated. +-B is equivalent to --implicit_include. The default +behavior is specified by the configuration flag +DEFAULT_IMPLICIT_TEMPLATE_INCLUSION_MODE. See +Template Instantiation. This option is valid only in C++ +mode.
    +
    +
    +
    --instantiate mode
    +
    -tmode
    +
    +
    +
    Control instantiation of external template entities. External +template entities are external (i.e., noninline and nonstatic) +template functions, variables, and template static data members. The +instantiation mode determines the template entities for which code +should be generated based on the template definition):
    +
    +
    +
    none

    Instantiate no template entities. This is the default.

    +
    +
    used

    Instantiate only the template entities that are used in this +compilation.

    +
    +
    all

    Instantiate all template entities whether or not they are used.

    +
    +
    local

    Instantiate only the template entities that are used in this +compilation and force those entities to be local to this +compilation.

    +
    +
    +
    +
    See Template Instantiation. This option is valid only in +C++ mode.
    +
    +
    +
    --instantiation_dir dir-name
    +

    +
    +
    +
    When --one_instantiation_per_object is used, this option can be +used to specify a directory into which the generated object files (or +C files, if the C-generating back end if being used) should be put. +The eccp script always specifies this option when invoking the +front end, with the default of Template.dir if the option is not +specified by the user.
    +
    +
    +
    --one_instantiation_per_object
    +

    +
    +
    +
    Put out each template instantiation in this compilation (function, +variable, or static data member) in a separate object file. The +primary object file contains everything else in the compilation, i.e., +everything that isn’t an instantiation. Having each instantiation in +a separate object file is very useful when creating libraries, because +it allows the user of the library to pull in only the instantiations +that are needed. That can be essential if two different libraries +include some of the same instantiations. This option is valid only in +C++ mode, and only if the configuration constant +ONE_INSTANTIATION_PER_OBJECT is TRUE.
    +
    +
    +
    --pending_instantiations= n
    +

    +
    +
    +
    Specifies the maximum number of instantiations of a given template +that may be in process of being instantiated at a given time. This is +used to detect runaway recursive instantiations. If n is zero, +there is no limit. The default is specified by the configuration +parameter DEFAULT_MAX_PENDING_INSTANTIATIONS.
    +
    +
    +
    --suppress_instantiation_flags
    +

    +
    +
    +
    When automatic instantiation is being used, this option suppresses the +generation of the special symbols used by the prelinker to do +automatic instantiation processing. This option is for use by the +driver and prelinker and should not be used directly by users. This +option is used by to implement the driver option that removes the +instantiation flags from object files once the prelinking step has +completed.
    +
    +
    +
    --template_directory dir
    +

    +
    +
    +
    Specifies a directory name to be placed on the exported template +search path. The directories are used to find the definitions of +exported templates and are searched in the order in which they are +specified on the command-line. The current directory is always the +first entry on the search path.
    +
    +
    +
    --template_info_file file-name
    +

    +
    +
    +
    This option specifies the name to be used for the template +instantiation information file used in automatic instantiation mode. +This option is supplied for use by the driver program that invokes the +front end and is not intended to be used by end-users.
    +
    +
    +
    +
    +
    +

    2.1.8. Code Generation Options#

    +

    The following options control the IL produced, the C-generating back end, or +the C++-generating back end.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --no_code_gen
    +
    -n
    +
    +
    +
    Do syntax-checking only, i.e., do not run the back end.
    +
    +
    +
    --force_vtbl
    +
    +
    +
    Force definition of virtual function tables in cases where the +heuristic used by the front end to decide on definition of virtual +function tables provides no guidance. See --suppress_vtbl. This +option is valid only in C++ mode.
    +
    +
    +
    --no_il_lowering
    +
    -N
    +
    +
    +
    On versions that include IL lowering and that write an intermediate +language file, suppress both IL lowering and the back end, and write +an unlowered (i.e., C++ rather than C) IL file. Probably not of +interest to end users.
    +
    +
    +
    --inline_statement_limit size
    +

    +
    +
    +
    When inlining is enabled, sets the maximum size (in number of lowered +statements) for a routine to be inlinable. A value of zero allows an +inlined routine to be any size. Only available when +MINIMAL_INLINING is configured to be TRUE.
    +
    +
    +
    --inlining
    +
    --no_inlining
    +
    +
    +
    Enable or disable minimal inlining of function calls. These options +are available only when MINIMAL_INLINING is configured to be TRUE. +The default is to do inlining when the C-generating back end is used.
    +
    +
    +
    --keep_restrict_in_signatures
    +
    --no_keep_restrict_in_signatures
    +
    +
    +
    In most modern configurations, top-level parameter type qualifiers +are removed from function types. In such configurations, this +option overrides or preserves that behavior for the restrict +qualifier; i.e., when the option is enabled, the mangled name of a +function will reflect the presence of top-level restrict parameter +type qualifiers.
    +
    +
    +
    --module_init name1,name2,…
    +
    -iname1,name2,…
    +
    +
    +
    When generating C output for testing (see c_gen_be in an +Appendix), when compiling in C mode, and if the current compilation +contains a main program, force calling of the file-scope +initialization routines in the indicated compiled units. This is +needed only when there are file-scope union initializations in +translation units that do not contain a main program. A message will +be issued during compilation of such units, indicating the need for +the --module_init option. All necessary names must be specified +in one --module_init option; a second --module_init will +overwrite the original list, not add to it. This option is not needed +when object code is generated by a back end other than the +C-generating back end, nor is it needed when the C-generating back end +is configured to generate ANSI C. This option is not needed in C++ +mode, because C++ has a language mechanism for getting initialization +code executed at program start-up.
    +
    +
    +
    --gen_c_clang_version version-number
    +

    +
    +
    +
    When using the C- or C++-generating back end to produce code that +is to be compiled with the clang compiler, this specifies the +version of the compiler being used (e.g., 150000 for version +15.0). This option is supplied for use by the driver program that +invokes the front end and is not intended to be used by end-users.
    +
    +
    +
    --gen_c_gnu_version version-number
    +

    +
    +
    +
    When using the C- or C++-generating back end to produce code that +is to be compiled with the gcc compiler, this specifies the +version of the compiler being used (e.g., 140100 for version +14.1.0). This option is supplied for use by the driver program +that invokes the front end and is not intended to be used by +end-users.
    +
    +
    +
    --gen_c_msvc_version version-number
    +

    +
    +
    +
    When using the C- or C++-generating back end to produce code that +is to be compiled with the Microsoft compiler, this specifies the +version of the compiler being used (e.g., 1932 for Visual Studio +2022 Update 2). (This option is identical to the earlier +--msvc_target_version option, which continues to be accepted.) +This option is supplied for use by the driver program that invokes +the front end and is not intended to be used by end-users.
    +
    +
    +
    --remove_unneeded_entities
    +
    --no_remove_unneeded_entities
    +

    +
    +
    +
    Enable or disable an optimization to prune the IL tree of types, +variables, routines, and related IL entries that are not “really +needed.” (Something may be referenced but unneeded if it is referenced +only by something that is itself unneeded; certain entities, such as +global variables and routines defined in the translation unit, are +always considered to be needed.) The positive form of the option is +available only when MAINTAIN_NEEDED_FLAGS is TRUE.
    +
    +
    +
    --suppress_vtbl
    +
    -V
    +
    +
    +
    Suppress definition of virtual function tables in cases where the +heuristic used by the front end to decide on definition of virtual +function tables provides no guidance. The virtual function table for +a class is defined in a compilation if the compilation contains a +definition of the first non-inline non-pure virtual function of the +class. For classes that contain no such function, the default +behavior is to define the virtual function table (but to define it as +a local static entity). The option --suppress_vtbl suppresses the +definition of the virtual function tables for such classes, and +--force_vtbl forces the definition of the virtual function table +for such classes. --force_vtbl differs from the default behavior +in that it does not force the definition to be local. This option is +valid only in C++ mode.
    +
    +
    +
    --target target-config-name
    +

    +
    +
    +
    For configurations that support multiple targets, specifies that the +target configuration named target-config-name should be used for the +compilation. If no --target option is specified, the default +target configuration (which may or may not be the legacy +configuration) is used.
    +
    +
    +
    +
    +
    +

    2.1.9. Precompiled Header Options#

    +

    The following options control how precompiled header files are generated and +used.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --pch
    +
    +
    +
    Automatically use and/or create a precompiled header file – for +details, see Precompiled Headers. If +--use_pch or --create_pch (manual PCH mode) appears on the +command line following this option, its effect is erased.
    +
    +
    +
    --create_pch file-name
    +
    +
    +
    If other conditions are satisfied (see +Precompiled Headers), create a precompiled header file with +the specified name. If --pch (automatic PCH mode) or +--use_pch appears on the command line following this option, +its effect is erased.
    +
    +
    +
    --use_pch file-name
    +
    +
    +
    Use a precompiled header file of the specified name as part of the +current compilation. If --pch (automatic PCH mode) or +--create_pch appears on the command line following this option, +its effect is erased.
    +
    +
    +
    --pch_dir directory-name
    +
    +
    +
    The directory in which to search for and/or create a precompiled +header file. This option may be used with automatic PCH mode +(--pch) or with manual PCH mode (--create_pch or +--use_pch).
    +
    +
    +
    --pch_messages
    +
    --no_pch_messages
    +
    +
    +
    Enable or disable the display of a message indicating that a +precompiled header file was created or used in the current +compilation.
    +
    +
    +
    --pch_verbose
    +
    +
    +
    In automatic PCH mode, for each precompiled header file that cannot be +used for the current compilation, a message is displayed giving the +reason that the file cannot be used.
    +
    +
    +
    --pch_mem size
    +
    +
    +
    The number of 1024-byte units of preallocated memory in which to save +precompiled-header state (only if USE_MMAP_FOR_MEMORY_REGIONS is +FALSE).
    +
    +
    +
    +
    +
    +

    2.1.10. C++/CLI Options#

    +
    + + + + + + + + + + + + + + + + + + +
    +
    --mscorlib_file_name file-name
    +
    +
    +
    Use the given assembly metadata file instead of mscorlib.dll to +import system types.
    +
    +
    +
    --preusing file-name
    +
    +
    +
    Import the given assembly metadata file prior to processing the input +source (but after importing mscorlib.dll or the file specified +with the --mscorlib_file_name option).
    +
    +
    +
    --using_directory directory-name
    +

    +
    +
    +
    Add the given directory to the search path used when searching for +assembly metadata files.
    +
    +
    +
    --using_framework_directory
    +
    --no_using_framework_directory
    +

    +
    +
    +
    Do or do not implicitly include the installation directory of the +Microsoft .NET runtime in the search path used when searching for +assembly metadata files. The default is to include that directory.
    +
    +
    +
    --vcmeta_directory directory-name
    +

    +
    +
    +
    Search for the vcmeta.dll file in the specified directory. If +omitted, vcmeta.dll is searched for in the same directory as the +module that contains the front end.
    +
    +
    +
    +
    +
    +

    2.1.11. Front End Debugging Options#

    +
    + + + + + + + + + + + + + + + +
    +
    --dbn
    +
    --dbname=n
    +
    -dn
    +
    -dname=n
    +
    +
    +
    Set the debug output level in the front end, which controls the +output of flow-tracing and similar information to the debug output +file (stderr). --dbn sets the debug level to n (in +the range 1-5) for the entire execution of the compiler (higher +values generate more voluminous debugging output). One can +control the debug output more precisely by specifying a routine +name and the debug level desired upon entry to that routine, as in +--dbname=n. Regardless of the previous setting +of the debug level, it will be changed to the indicated value on +entry to the indicated routine; on exit, it will be restored to +its former value. One can also use += or -= in place of += in that option to increase or decrease the debug level +relative to its current value. The former value is also restored +on exit from the routine in those cases. Ordinarily, a message is +written to debug output whenever the debug level is changed (i.e., +both on entry and exit in the above cases). If that is not +desirable, a ! (implying “not”) can be appended to the level +number in the command-line option, to indicate that the +level-change messages should not be produced for that request. +Several routine names can be specified, and/or several requests +can be made, by separating them with commas, as in the following:
    +
    +
    +

    --db fe_init,fe_wrapup+=2,get_token=3

    +
    +
    +
    -d-name1,-name2,…
    +
    +
    +
    Enable the named “debug flags”, which will enable debug output +associated with the flag. For example, -d-dump_layout produces +output related to the class type layout process.
    +
    +
    +
    -d#name1,#name2,…
    +
    +
    +
    Disable the named “debug flags”.
    +
    +
    +
    --db_name=name
    +
    +
    +
    Enable debug output for source entities with the given name. Not all +debug output takes this option into account; i.e., even with this +option some debug output not associated with the given name may be +produced. When simultaneously compiling multiple translation units, +entities in all translation units are considered by default. The +given name can be restricted to entities in the primary translation +units by preceding it with [] or to entities in a secondary +translation unit by preceding it with [file] where +file is the name of the secondary source file. For example,
    +
    +
    +

    -d-trans_corresp --db_name=[x.cpp]A::f

    +
    +
    +
    will output debugging information about cross-translation-unit +correspondences for a member A::f declared in a secondary +translation unit defined by source file x.cpp.
    +
    +
    +
    +
    +
    +

    2.1.12. Miscellaneous Options#

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --version
    +
    -v
    +
    +
    +
    Display the version number of the front end, and the Edison Design +Group copyright.
    +
    +
    +
    --building_runtime
    +
    +
    +
    Used to indicate that the EDG runtime library is being compiled. This +causes additional macros to be predefined that are used to pass target +configuration information from the front end to the runtime.
    +
    +
    +
    --edg_base_dir
    +
    +
    +
    The name of the directory in which to find files needed by the front +end at execution time. This option is supplied for use by the driver +program that invokes the front end and is not intended to be used by +end-users.
    +
    +
    +
    --dump_command_options
    +
    +
    +
    Display the complete set of --name +command-line options recognized by the front end in a format that is +compatible with, e.g., the bash shell’s complete command to allow the +shell’s completion facility to be used with front end options.
    +
    +
    +
    --dump_configuration
    +
    +
    +
    Display the complete set of configuration +macros with which the front end was built. The output (to the error +output file) can be captured and used as the contents of the +defines.h file to recreate that configuration. This option is +available only in executables built with DEBUG set to TRUE.
    +
    +
    +
    --dump_legacy_as_target target-config-name
    +
    +
    +
    Displays the legacy configuration in such a manner that the +configuration can be used to specify a new target configuration named +target-config-name. For customers who have multiple versions of the +front end (each configured for a specific target), this option can be +used to generate a separate target configuration for each of the +legacy configurations, and the output combined to form a single +configuration where the target can be specified at run-time (via the +--target option). This option is available only in executables +built with DEBUG set to TRUE. The output is directed to the error +output file.
    +
    +
    +
    --incognito
    +
    --no_incognito
    +
    +
    +
    Enable or disable the suppression of implicitly-defined +EDG-specific macros such as __EDG__ and __EDG_VERSION__. +Suppressing these macros facilitates compilation of code that +incorrectly configures itself via conditional compilation when it +detects that the compiler is based on the EDG front end. The +default behavior of the front end is determined by the value of +the configuration macro DEFAULT_INCOGNITO.
    +
    +
    +
    --il_display
    +
    +
    +
    Displays the IL in a human-readable form. This is +the same output that would be generated by writing the IL to a file +and displaying it with the edgcpdisp utility. The IL that is +displayed is lowered IL (if the configuration does lowering) unless +the --no_il_lowering command-line option is also specified.
    +
    +
    +
    --mmap_address address
    +
    +
    +
    Specify the fixed address to be used in calls to mmap. Valid +addresses are specific to the host operating system (and +architecture), and may change from invocation to invocation +(depending, say on which shared libraries are loaded). The address +chosen should be aligned to the page size of the host. The use of a +fixed address for mmap is useful in cases where pre-compiled +header files are used (to ensure that the same address space is +available from one invocation of the front end to another). This +option is available only in executables built with +USE_FIXED_ADDRESS_FOR_MMAP set to TRUE.
    +
    +
    +
    --check_unicode_security
    +
    --no_check_unicode_security
    +
    +
    +
    Enable or disable checking of comments, string literals, and +identifiers for Unicode patterns that could be used to disguise +malicious source code by making it appear innocuous; suspicious +patterns are reported as warnings. Checking is only applicable to +UTF-encoded Unicode source and header files. These options are +available only in executables built with +UNICODE_VULNERABILITY_CHECKING_SUPPORTED set to TRUE.
    +
    +
    +
    --module_import_diagnostics
    +
    --no_module_import_diagnostics
    +
    +
    +
    Enable or disable the issuing of diagnostic messages during the import +of entities from a module. The option can be used to reduce verbosity +and condense diagnostics that do not relate to the source file being +compiled. The default setting is specified by the +DEFAULT_MODULE_IMPORT_DIAG_ENABLED configuration macro.
    +
    +
    +
    --wdir directory-name
    +
    +
    +
    Specify the directory to use in expanding relative path names. All +relative paths are expanded after command-line processing is complete, +so that any --wdir options preceding the final one have no effect.
    +
    +
    +
    +
    +
    +
    +

    2.2. Environment Variables#

    +

    The environment variable USR_INCLUDE can be set to a directory to be used +instead of /usr/include on the standard include file search list. (Of +course, this has no effect if the front end has been configured to have an +empty “standard list” of include files.)

    +

    When the front end is built with the __MICROSOFT_OS__ flag set, the +environment variable TMP is used to specify the directory to be used for +temporary files. If TMP is not set, and when __MICROSOFT_OS__ is not +set, the environment variable TMPDIR is used to indicate a directory to be +used for temporary files. If TMPDIR is not set, a default temporary +directory (often, /usr/tmp) is used. (Note: at the present time, the front +end only uses temporary files when generating an intermediate language file for +immediate use by a back end called in the same program, and in the C-generating +back end.)

    +
    +
    +

    2.3. Diagnostic Messages#

    +

    Diagnostic messages have an associated severity, as follows:

    +
      +
    • +
      Catastrophic errors indicate problems of such severity that the compilation +cannot continue. For example: command-line errors, internal errors, and +missing include files. If multiple source files are being compiled, any +source files after the current one will not be compiled.
      +
      +
    • +
    • +
      Errors indicate violations of the syntax or semantic rules of the C or C++ +language. Compilation continues, but object code is not generated.
      +
      +
    • +
    • +
      Warnings indicate something valid but questionable. Compilation continues +and object code is generated (if no errors are detected).
      +
      +
    • +
    • +
      Remarks indicate something that is valid and probably intended, but which a +careful programmer may want to check. These diagnostics are not issued by +default. Compilation continues and object code is generated (if no errors +are detected).
      +
      +
    • +
    +

    Diagnostics are written to the error output file with a form like the +following:

    +
    "test.c", line 5: a break statement may only be used within a loop
    +          or switch
    +    break;
    +    ^
    +
    +
    +

    Diagnostics are normally written to stderr, but the front end can be +configured to use stdout by setting the DIRECT_ERROR_OUTPUT_TO_STDOUT +configuration macro. When this flag is set, messages are directed to +stdout, except when doing preprocessing only. Errors during command-line +processing are always directed to stderr.

    +

    Diagnostic messages can optionally be “colorized”. Colorization is enabled +when the colorize_diagnostics global variable is TRUE. To support +colorization of diagnostics, diagnostics are annotated when the +annotate_diagnostics global variable is TRUE. In that case, annotation +sequences are inserted into the diagnostic message itself to identify pieces of +the diagnostic that might later be highlighted in some fashion. These two +character annotations take the form of an “escape” character +(DIAG_ANNOTATION_INDICATOR) followed by an a_diagnostic_annotation_kind +enumerator. When colorization is enabled, format_output_line replaces the +annotations with Select Graphic Rendition (SGR) codes that, on most terminal +emulators, can be used to highlight text in various ways. The SGR codes used +for colorization default to a string specified by DEFAULT_EDG_COLORS which +can be overridden by the EDG_COLORS environment variable (if set). The +string consists of a colon-separated list of elements, where each element +specifies a string that maps to an a_diagnostic_annotation_kind value +followed by an “=” and the SGR string to use when highlighting text of that +kind. For example:

    +
    "error=01;31:warning=01;35:note=01;36:locus=01:quote=01:range1=32"
    +
    +
    +

    A customer can use the annotations in a diagnostic to display the annotated +pieces in any fashion they desire (e.g., when a GUI is available).

    +

    Note that the message identifies the file and line involved, and that the +source line itself (with position indicated by the ^) follows the message. +If there are several diagnostics in one source line, each diagnostic will have +the form above, with the result that the text of the source line will be +displayed several times, with an appropriate position each time.

    +

    Long messages are wrapped to additional lines when necessary.

    +

    A configuration flag controls whether or not the string “error:” appears, +i.e., the front end can be configured so that the severity string is omitted +when the severity is “error”.

    +

    A command line option may be used to request a shorter form of the diagnostic +output in which the original source line is not displayed and the error message +text is not wrapped when too long to fit on a single line.

    +

    A command line option may be used to request that the error number be included +in the diagnostic message. When displayed, the error number also indicates +whether the error may have its severity overridden on the command line. If the +severity may be overridden, the error number will include the suffix “-D” +(for “discretionary”); otherwise no suffix will be present.

    +
    "Test_name.c", line 7: error #64-D: declaration does not declare anything
    +  struct {};
    +  ^
    +"Test_name.c", line 9: error #77: this declaration has no storage class or
    +          type specifier
    +  xxxxx;
    +  ^
    +
    +
    +

    Because an error is determined to be discretionary based on the error severity +associated with a specific context, a given error may be discretionary in some +cases and not in others.

    +

    For some messages, a list of entities is useful; they are listed following the +initial error message:

    +
    "test.c", line 4: error: more than one instance of overloaded function "f"
    +          matches the argument list:
    +            function "f(int)"
    +            function "f(float)"
    +            argument types are: (double)
    +    f(1.5);
    +    ^
    +
    +
    +

    In some cases, some additional context information is provided; specifically, +such context information is useful when the front end issues a diagnostic while +doing a template instantiation or while generating a constructor, destructor, +or assignment operator function. For example:

    +
    "test.c", line 7: error: "A::A()" is inaccessible
    +  B x;
    +     ^
    +          detected during implicit generation of "B::B()" at line 7
    +
    +
    +

    Without the context information, it is very hard to figure out what the error +refers to.

    +

    If the front end is configured with FULLY_RESOLVED_MACRO_POSITIONS (and, +optionally, MACRO_INVOCATION_TREE_IN_IL) set to TRUE, messages referring to +text occurring inside a macro expansion may provide additional information. +This additional information gives the source location from which the text was +copied into the macro expansion (i.e., from a macro definition or one of the +arguments in the top-level macro invocation), as well as possibly the chain of +macro invocations leading to the expanded text to which the diagnostic refers. +If the front end is configured to permit the display of this information, it +can also be enabled or disabled by the command-line option +--[no_]macro_positions_in_diagnostics. The information is presented in a +form like the following:

    +
    "test.c", line 1: error: identifier "val" is undefined
    +   #define incr(x) (x)+=val
    +                        ^
    +  in expansion of macro "incr" at "test.c", line 2,
    +  in expansion of macro "next_val" at "test.c", line 4:
    +   return next_val(i);
    +          ^
    +
    +
    +
    +
    +

    2.4. Termination Messages#

    +

    When the front end is installed without the USING_DRIVER option (see +information on configuration later in this document), it writes sign-off +messages to the error output file. For example, one of the following forms of +message

    +
    n errors detected in the compilation of "ifile".
    +1 catastrophic error detected in the compilation of "ifile".
    +n errors and 1 catastrophic error detected in the compilation of "ifile".
    +
    +
    +

    is written to indicate the detection of errors in the compilation. No message +is written if no errors were detected. The following message

    +
    Error limit reached.
    +
    +
    +

    is written when the count of errors reaches the error limit (see the -e +option, above); compilation is then terminated. The message

    +
    Compilation terminated.
    +
    +
    +

    is written at the end of a compilation that was prematurely terminated because +of a catastrophic error. The message

    +
    Compilation aborted.
    +
    +
    +

    is written at the end of a compilation that was prematurely terminated because +of an internal error. Such an error indicates an internal problem in the +compiler and should be reported to those responsible for its maintenance.

    +
    +
    +

    2.5. Response to Signals#

    +

    Except in multi-threaded builds, the signals SIGINT (caused by a user +interrupt, like ^C) and SIGTERM (caused by a kill command) are +trapped by the front end and cause abnormal termination. When +MULTIPLE_THREAD_COMPILATION is TRUE, it’s expected that the customer +application will install handlers as appropriate and no signal handling is +performed by the front end.

    +
    +
    +

    2.6. Exit Status#

    +

    On completion, the front end returns with a code indicating the +highest-severity diagnostic detected: 4 if there was a catastrophic error, 2 if +there were any errors, or 0 if there were any warnings or remarks or if there +were no diagnostics of any kind.

    +

    If multiple source files are compiled, the exit status indicates the +highest-severity diagnostic detected in the entire compilation.

    +
    +
    +

    2.7. Finding Include Files#

    +

    A file name specified in a #include directive is searched for in a set of +directories specified by command-line options and environment variables. If +the file name specified does not include a suffix, a set of suffixes is used +when searching for the file.

    +

    Files whose names are not absolute pathnames and that are enclosed in "..." +will be searched for in the following directories, in the order listed:

    +
      +
    1. The directory containing the current input file (the primary source file +or the file containing the #include); [2]

    2. +
    3. any directories specified in --include_directory options (in the +order in which they were listed on the command line);

    4. +
    5. any directories on the standard list (this list is selected at the time +of installation of the front end; often, it is just the one directory +/usr/include or a similar system include directory for C++).

    6. +
    +

    For file names enclosed in <...>, only the directories that are specified +using the --include_directory option and those on the standard list are +searched. If the directory name is specified as “-”, e.g., “-I-”, the +option indicates the point in the list of --include_directory options at +which the search for file names enclosed in <...> should begin. That is, +the search for <...> names should only consider directories named in +--include_directory options following the -I-, and the directories of +item 3 above. -I- also removes the directory containing the current input +file (item 1 above) from the search path for file names enclosed in "...".

    +

    An include directory specified with the --sys_include option is considered +a “system” include directory. Warnings are suppressed when processing files +found in system include directories. If a default include directory has been +specified using the USR_INCLUDE configuration flag or environment variable, +it is considered a system include directory.

    +

    If the file name has no suffix it will be searched for by appending each of a +set of include file suffixes. When searching in a given directory all of the +suffixes are tried in that directory before moving on to the next search +directory. The default set of suffixes is specified by the +DEFAULT_INCLUDE_FILE_SUFFIX_LIST configuration parameter. The default can +be overridden using the --incl_suffixes command-line option. A null file +suffix cannot be used unless it is present in the suffix list (i.e., the front +end will always attempt to add a suffix from the suffix list when the file name +has no suffix).

    +
    +
    +

    2.8. Finding Module Files#

    +

    An import directive can specify either a module unit or a header unit, and +the process of finding these differ. A header unit import names the header +identically to the equivalent #include directive (a file name enclosed in +<...> or "..."), while a module unit is imported by its name and not +the name of the file containing the module unit.

    +

    An import directive that specifies a header unit first finds the named +header using the process for finding #include files. See +Finding Include Files. If the header is found, the corresponding module file +is found by the following search, in the listed order:

    +
      +
    1. Using the direct mappings provided by --ms_header_unit.

    2. +
    3. Using the unresolved mappings provided by --ms_header_unit_angle (if +the header file name is specified via <...>) or by +--ms_header_unit_quote (if the header file name is specified via +"..."). If a match is found here, that match is added to the map +for --ms_header_unit.

    4. +
    +

    An import directive that specifies a module unit will search for the module +file, in the order listed:

    +
      +
    1. Any direct mappings from that module name to a module file as specified +by --ms_mod_file_map

    2. +
    3. Any files listed without a direct map by --ms_mod_file_map, examining +those files to determine if the module each represents matches the module +being imported

    4. +
    5. Files in the directory containing the current input file (the primary +source file or the file containing the import)

    6. +
    7. Files in any directories specified by--modules_directory (in the +order in which they were listed on the command line)

    8. +
    9. Files in the directory specified by the EDG_MODULES_PATH environment +variable, if it’s set.

    10. +
    +
    +
    +

    2.9. C++ Dialect Accepted#

    +

    In strict C++ mode, the front end accepts the complete C++ language as defined +by the ISO/IEC 14882:2003 standard, including export templates (if the front +end’s configuration allows them). In nonstrict C++ mode (which is the default +in common configurations), a small set of features – particularly, export +templates – are not supported, but some minor extensions commonly available on +other compilers are accepted.

    +

    The front end accepts the complete C++17 language as defined by the ISO/IEC +14882:2017 standard (enabled through the command-line option --c++17). The +front end also fully supports the earlier C++14, C++11, and (as noted above) +C++98/03 versions of the language. The front end supports most of the features +of the C++20 language as defined by the 14882:2020 standard (enabled through +the command-line option --c++20). The C++20 features that are not accepted +yet are described below.

    +

    Extensive compatibility modes are also available for the Microsoft Visual C++ +compilers, the GNU C++ (“GCC”) compilers, and the clang C++ compiler. A more +basic Sun C++ compatibility mode is also implemented. Only one emulation mode +may be active at a time (but --ms_extensions or --ms_compatibility may +be enabled in non-Microsoft emulation modes).

    +

    The front end also has a cfront compatibility mode, which duplicates a number +of “features” and bugs of cfront 2.1 and 3.0.x. Complete compatibility is not +guaranteed or intended – the mode is there to allow programmers who have +unwittingly used cfront features to continue to compile their existing code. +In particular, if a program gets an error when compiled by cfront, the EDG +front end may produce a different error or no error at all.

    +

    Command-line options are available to enable and disable anachronisms, to +control strict standard-conformance checking, and to adjust the severity of +certain diagnostics.

    +
    +

    2.9.1. C++20 Implementation Status#

    +

    Most of the new features and changes in the C++20 standard are accepted by +the front end. Details about the specific changes (e.g., the first version +of the front end to support the feature, and the standard committee papers +that introduced the feature) can be found on the EDG website.

    +

    The following C++20 features are not yet supported (our web site has links with +further details):

    +
      +
    • +
      Concepts are supported, but some of the most recent changes to the feature +are not yet supported:
      +
      +
        +
      • +
        Partial ordering of rewritten operator candidates resulting from +constrained templates
        +
        +
      • +
      • +
        Clarify declaration matching and partial ordering requiring substitution +into constraints
        +
        +
      • +
      +
    • +
    • +
      When are constexpr member functions defined? (core issue 1581). This +is not yet implemented because of concerns about potential code breakage.
      +
      +
    • +
    • +
      Modules. (There is partial support for importing Microsoft modules. See +the release notes for more information.)
      +
      +
    • +
    +
    +
    +

    2.9.2. C++23 and C++26 Implementation Status#

    +

    Some of the new features and changes in the C++23 and draft C++26 standard are +accepted by the front end. Details about the specific changes (e.g., the first +version of the front end to support the feature, and the standard committee +papers that introduced the feature) can be found on the EDG website.

    +
    +
    +

    2.9.3. “Default” C++ Mode#

    +

    The following extensions are accepted default C++ mode. Most of these are also +accepted in any other C++ mode that does not diagnose strict ANSI violations as +errors (exceptions are explicitly noted).

    +
      +
    • +
      A friend declaration for a class may omit the class keyword:
      +
      +
      class B;
      +class A {
      +  friend B;  // Should be "friend class B"
      +};
      +
      +
      +
    • +
    • +
      Constants of scalar type may be defined within classes (this is an old +form; the modern form uses an initialized static data member):
      +
      +
      class A {
      +  const int size = 10;
      +  int a[size];
      +};
      +
      +
      +
    • +
    • +
      In the declaration of a class member, a qualified name may be used:
      +
      +
      struct A {
      +  int A::f();  // Should be int f();
      +};
      +
      +
      +
    • +
    • +
      If ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE, an extension is +supported to allow an anonymous union to be introduced into a containing +class by a typedef name – it needn’t be declared directly, as with a +true anonymous union. For example:
      +
      +
      typedef union {
      +  int i, j;
      +} U;           // U identifies a reusable anonymous union.
      +class A {
      +  U;           // Okay -- references to A::i and A::j are allowed.
      +};
      +
      +
      +
      +
      In addition, the extension also permits “anonymous classes” and “anonymous +structs,” as long as they have no C++ features (e.g., no static data +members or member functions and no nonpublic members) and have no nested +types other than other anonymous classes, structs, or unions. For +instance,
      +
      +
      struct A {
      +  struct {
      +    int i, j;
      +  };           // Okay -- references to A::i and A::j are allowed.
      +};
      +
      +
      +
    • +
    • +
      If recognition of the restrict keyword is enabled, the C99 restrict +feature is supported in a form extended for C++, which allows restrict +as a type qualifier for reference and pointer-to-member types and for +nonstatic member functions. The set of C++ extensions is described in +J16/92-0057.
      +
      +
    • +
    • +
      If IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE is TRUE, implicit +type conversion between a pointer to an extern "C" function and a +pointer to an extern "C++" function is permitted. Here’s an example:
      +
      +
      extern "C" void f();     // f's type has extern "C" linkage
      +void (*pf)()             // pf points to an extern "C++" function
      +             = &f;       // error unless implicit conversion is allowed
      +
      +
      +
      +
      This extension is allowed in environments where C and C++ functions share +the same calling conventions (though it is pointless unless +DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT is TRUE). When +DEFAULT_IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_ALLOWED is set, it is +enabled by default; it can also be enabled in cfront-compatibility mode or +with command-line option --implicit_extern_c_type_conversion.
      +
      +
    • +
    • +
      A “?” operator whose second and third operands are string literals or +wide string literals can be implicitly converted to “char *” or +“wchar_t *”. (Recall that in C++ string literals are const. There +is a deprecated implicit conversion that allows conversion of a string +literal to “char *”, dropping the const. That conversion, however, +applies only to simple string literals. Allowing it for the result of a +“?” operation is an extension.)
      +
      +
      char *p = x ? "abc" : "def";
      +
      +
      +
    • +
    • +
      Default arguments may be specified for function parameters other than those +of a top-level function declaration (e.g., they are accepted on typedef +declarations and on pointer-to-function and pointer-to-member-function +declarations).
      +
      +
    • +
    • +
      Nonstatic local variables of an enclosing function can be referenced in a +non-evaluated expression (e.g., a sizeof expression) inside a local +class. A warning is issued.
      +
      +
    • +
    • +
      In default C++ mode (but not other non-C++11 modes), the friend class +syntax is extended to allow nonclass types as well as class types expressed +through a typedef or without an elaborated type name. For example:
      +
      +
      typedef struct S ST;
      +class C {
      +  friend S;             // Okay (requires S to be in scope).
      +  friend ST;            // Okay (same as "friend S;").
      +  friend int;           // Okay (no effect).
      +  friend S const;       // Error: cv-qualifiers cannot appear directly.
      +};
      +
      +
      +
    • +
    • +
      In default C++ mode, mixed string literal concatenations are accepted. +(This is a feature carried over from C99 and also available in GNU modes. +It is not enabled in other non-C++11 modes.)
      +
      +
      wchar_t *str = "a" L"b";  // Okay, same as L"ab".
      +
      +
      +
    • +
    • +
      In default C++ mode, variadic macros are accepted. (This is a feature +carried over from C99 and also available in GNU modes. It is not by +default enabled in other non-C++11 modes.)
      +
      +
    • +
    • +
      In default C++ mode, empty macro arguments are accepted (a feature carried +over from C99).
      +
      +
    • +
    • +
      A trailing comma in the definition of an enumeration type is silently +accepted (a feature carried over from C99):
      +
      +
      enum E { e, };
      +
      +
      +
    • +
    +

    Except where noted, all of the extensions described in the C dialect section +are also allowed in C++ mode.

    +
    +
    +

    2.9.4. GNU C++ Mode#

    +

    The front end can be built to accept GNU extensions. In GNU C++ mode, a large +number of extensions and bugs are closely emulated. This feature enables the +front end to compile many large and complex projects that were developed using +the GNU tool chain; this includes major open-source projects.

    +

    Support for this emulation is ongoing: New GNU C++ features are added as +needed, with priority given to features used in system headers.

    +

    Because the GNU compiler frequently changes behavior between releases, the +front end provides an option (--gnu_version) to specify a specific version +of GCC to emulate. Generally speaking, features and bugs are emulated to +exactly match each known version of GCC, but occasionally the emulation is +approximate and in such cases the front end is often a little more permissive +than GCC on the principle that it is more important to accept source that GCC +accepts than to diagnose every case that GCC diagnoses. The front end does +not, however, attempt to emulate every GCC command-line option; in particular, +GCC options to be extra-permissive are not emulated (however, the severity of +specific error diagnostics can sometimes be decreased to accept constructs that +are not by-default allowed in GNU emulation mode).

    +

    Some GNU features are only emulated when specific configuration options are +enabled. For example, support for complex floating-point types is only +available when the front end is configured to support C99 extensions.

    +

    A few GCC extensions there are likely not going to be supported in the +foreseeable future:

    +
      +
    • +
      The forward declaration of function parameters (so they can participate in +variable-length array parameters).
      +
      +
    • +
    • +
      GNU-style complex integral types (complex floating-point types are +supported)
      +
      +
    • +
    • +
      Nested functions
      +
      +
    • +
    • +
      Local structs with variable-length array fields. Such fields are treated +(with a warning) as zero-length arrays in GNU C mode, which is a useful +approximation in some circumstances, but not generally equivalent to the +GNU feature.
      +
      +
    • +
    +
    +
    +

    2.9.5. Microsoft C++ Mode#

    +

    The front end also extensively emulates the Microsoft Visual C++ compilers. As +is the case with GNU modes, an option (--microsoft_version) is available to +select a specific version of Microsoft’s compiler to emulate.

    +

    Although Microsoft C++ and C modes generally emulate both extensions/features +and bugs, the emulation of a certain class of bugs (considered more severe) can +be controlled separately (using the --no_microsoft_bugs/--microsoft_bugs +options).

    +

    Microsoft C++ mode can be combined with certain other language options to +enable a larger superset of the language accepted by the Microsoft compiler.

    +

    In addition to full Microsoft emulation mode, two subsets of Microsoft +emulation are available: --ms_extensions, and --ms_compatibility, +corresponding to clang’s -fms-extensions and -fms-compatibility +command-line options, respectively. These command-line options allow a certain +degree of Microsoft emulation while the primary emulation mode is something +else (e.g., --clang).

    +

    Support for Microsoft C++ emulation is ongoing: New features are added as +needed, with priority given to features used in system headers.

    +
    +
    +

    2.9.6. Microsoft C++/CLI Mode#

    +

    The front end implements the language extensions known as “C++/CLI” that +simplifies writing C++-like programs for Microsoft’s “.NET” environment. These +extensions are formally described through the ECMA-372 standard, but where the +Microsoft compiler deviates from the standard, the front end follows the +Microsoft compiler rather than the standard.

    +

    Almost all C++/CLI features are implemented in the front end. This includes +various managed class kinds and the special members (e.g., properties) that +they can contain, delegates, handles and tracking references, gcnew, +generics, importing of assemblies, hide-by-sig lookup rules, string literal +rules, and so forth. A notable exception is Microsoft-style attributes +(delimited by square brackets): The front end can parse them, but does not +currently implement their semantics.

    +

    An earlier attempt at integrating C++ and .NET was known as “Managed C++”: The +front end does not support those earlier Microsoft compiler features (which +have since been deprecated by Microsoft).

    +
    +
    +

    2.9.7. Extensions Accepted in Sun Compatibility Mode#

    +

    The front end provides a “Sun Compatibility” mode. This mode automatically +selects a set of command-line options that provides the greatest compatibility +with the Sun CC 5.x compiler. It also enables certain extensions that are +accepted by the Sun compiler. Note that this mode is provided to enable the +front end to compile code such as commonly used Sun header files, and is not +intended to provide complete compatibility with the Sun compiler.

    +

    Sun compatibility mode currently corresponds to the following combination of +options:

    +
    --no_guiding_decls
    +--extern_inline
    +--nonstd_using_decl
    +
    +
    +

    These settings can explicitly be overridden using more command-line options.

    +

    The following extensions are accepted in Sun compatibility mode:

    +
      +
    • +
      The Sun-specific link scope specifiers __global, __symbolic, and +__hidden can be recognized. In modes that recognize these keywords, +the pragmas “#pragma disable_ldscope” and “#pragma enable_ldscope” +can be used to temporarily allow these keywords as normal identifiers. For +example:
      +
      +
      __global int i;       // Accepted in some Sun modes.
      +#pragma disable_ldscope
      +int __global;         // Okay: Keyword (temporarily) deactivated.
      +#pragma enable_ldscope
      +struct __global;      // Error: __global is a keyword.
      +
      +
      +
    • +
    • +
      The __thread specifier can be used to indicate that a variable should +be placed in thread-local storage.
      +
      +
    • +
    • +
      In Sun mode, a non-tag from one scope hides a tag from another scope when +both are visible as a result of a using-directive.
      +
      +
      template <class T> struct B { };
      +namespace N {
      +  typedef B<char> A;
      +}
      +using namespace N;
      +class A;typedef A C;   // Sun mode uses typedef N::A instead of ambiguity
      +
      +
      +
    • +
    • +
      A reference to an undeclared function template is accepted when the +reference appears in the definition of a class template.
      +
      +
      template <class T> struct A {
      +  friend void f<>(T&);  // Accepted in Sun mode
      +};
      +
      +
      +
    • +
    • +
      When a friend class is declared with an unqualified name, the lookup of +that name is not restricted to the nearest enclosing namespace scope.
      +
      +
      struct S;
      +namespace N {
      +  class C {
      +    friend struct S;  // ::S in Sun and Microsoft modes
      +  };
      +                      // (N::S otherwise)
      +}
      +
      +
      +
    • +
    • +
      The typename keyword is ignored in most contexts.
      +
      +
      // The Sun compiler does recognize typename in a template parameter list
      +template <typename T> class C {
      +  // Illegal uses of typename that are accepted by the Sun compiler
      +  typename T t;
      +  typename typename T typename typename x;
      +};
      +
      +
      +
    • +
    • +
      A default argument may be specified in the definition of a member function +of a class template declared outside of the class.
      +
      +
      template <class T> struct A {
      +  void f(int);
      +};
      +template <class T> void A<T>::f(int = 0) { }
      +
      +
      +
    • +
    • +
      A template argument list may appear following a constructor name in +constructor definition that appears outside of the class definition:
      +
      +
      template <class T> struct A {
      +  A();
      +};
      +template <class T> A<T>::A<T>(){}
      +
      +
      +
    • +
    • +
      Template parameters are (incorrectly) visible in class template +specializations and specializations of members of class templates.
      +
      +
      template <class T> struct A {
      +  void f();
      +};
      +template <> struct A<int> {
      +  T t;  // T should not be visible here
      +};
      +template <> void A<char>::f() {
      +  T t;  // T should not be visible here
      +}
      +
      +
      +
    • +
    • +
      The explicit instantiation of a class does not cause the instantiation of +its inline members.
      +
      +
      +
      template <class T> struct A {
      +  void f() {
      +    g();
      +  } // Not instantiated in Sun mode
      +};
      +template class A<int>;
      +
      +
      +
      +
    • +
    • +
      An extern inline function that is referenced but not defined is +permitted (with a warning).
      +
      +
    • +
    • +
      Default arguments are retained as part of deduced function types.
      +
      +
    • +
    • +
      When searching for a header file specified using the <...> syntax, the +front end searches for the specified header file name and also for a +version with the suffix .SUNWCCh appended (e.g., stddef.h.SUNWCCh).
      +
      +
    • +
    • +
      The std namespace is predeclared.
      +
      +
    • +
    • +
      A reference to a nonstatic data member may be written without an object +(not even an implicit this->) inside a sizeof:
      +
      +
      typedef struct _X {
      +  char A[512];
      +} X;
      +static unsigned int foo() {
      +  return sizeof(X::A);
      +}
      +
      +
      +
    • +
    • +
      A storage class may appear in a declaration that also has a “direct” +linkage specification – e.g.,
      +
      +
      extern "s" static void f();
      +
      +
      +
      +
      is treated as equivalent to
      +
      +
      extern "C" { static void f(); }
      +
      +
      +
    • +
    +
    +
    +

    2.9.8. Anachronisms Accepted#

    +

    The following anachronisms are accepted when anachronisms are enabled:

    +
      +
    • +
      overload is allowed in function declarations. It is accepted and +ignored.
      +
      +
    • +
    • +
      Definitions are not required for static data members that can be +initialized using default initialization. The anachronism does not apply +to static data members of template classes; they must always be defined.
      +
      +
    • +
    • +
      The number of elements in an array may be specified in an array delete +operation. The value is ignored.
      +
      +
    • +
    • +
      A single operator++() and operator--() function can be used to +overload both prefix and postfix operations.
      +
      +
    • +
    • +
      The base class name may be omitted in a base class initializer if there is +only one immediate base class.
      +
      +
    • +
    • +
      Assignment to this in constructors and destructors is allowed. This is +allowed only if anachronisms are enabled and the “assignment to this” +configuration parameter is enabled.
      +
      +
    • +
    • +
      A bound function pointer (a pointer to a member function for a given +object) can be cast to a pointer to a function.
      +
      +
    • +
    • +
      A nested class name may be used as a nonnested class name provided no other +class of that name has been declared. The anachronism is not applied to +template classes.
      +
      +
    • +
    • +
      A reference to a non-const type may be initialized from a value of a +different type. A temporary is created, it is initialized from the +(converted) initial value, and the reference is set to the temporary.
      +
      +
    • +
    • +
      A reference to a non-const class type may be initialized from an rvalue of +the class type or a derived class thereof. No (additional) temporary is +used.
      +
      +
    • +
    • +
      A function with old-style parameter declarations is allowed and may +participate in function overloading as though it were prototyped. Default +argument promotion is not applied to parameter types of such functions when +the check for compatibility is done, so that the following declares the +overloading of two functions named f:
      +
      +
      int f(int);
      +int f(x) char x; { return x; }
      +
      +
      +
      +
      It will be noted that in C this code is legal but has a different +meaning: a tentative declaration of f is followed by its definition.
      +
      +
    • +
    • +
      When --nonconst_ref_anachronism is enabled, a reference to a nonconst +class can be bound to a class rvalue of the same type or a derived type +thereof.
      +
      +
      struct A {
      +  A(int);
      +  A operator=(A&);
      +  A operator+(const A&);
      +};
      +main () {
      +  A b(1);
      +  b = A(1) + A(2);   // Allowed as anachronism
      +}
      +
      +
      +
    • +
    +
    +
    +

    2.9.9. Extensions Accepted in Cfront 2.1 Compatibility Mode#

    +

    The following extensions are accepted in cfront 2.1 compatibility mode in +addition to the extensions listed in the 2.1/3.0 section following (i.e., these +are things that were corrected in the 3.0 release of cfront):

    +
      +
    • +
      The dependent statement of an if, while, do-while, or +for is not considered to define a scope. The dependent statement may +not be a declaration. Any objects constructed within the dependent +statement are destroyed at exit from the dependent statement.
      +
      +
    • +
    • +
      Implicit conversion from integral types to enumeration types is allowed.
      +
      +
    • +
    • +
      A non-const member function may be called for a const object. A +warning is issued.
      +
      +
    • +
    • +
      A const void * value may be implicitly converted to a void * value, +e.g., when passed as an argument.
      +
      +
    • +
    • +
      When, in determining the level of argument match for overloading, a +reference parameter is initialized from an argument that requires a +non-class standard conversion, the conversion counts as a user-defined +conversion. (This is an outright bug, which unfortunately happens to be +exploited in the NIH class libraries.)
      +
      +
    • +
    • +
      When a builtin operator is considered alongside overloaded operators in +overload resolution, the match of an operand of a builtin type against the +builtin type required by the builtin operator is considered a standard +conversion in all cases (e.g., even when the type is exactly right without +conversion).
      +
      +
    • +
    • +
      A reference to a non-const type may be initialized from a value that is +a const-qualified version of the same type, but only if the value is +the result of selecting a member from a const class object or a pointer +to such an object.
      +
      +
    • +
    • +
      The cfront 2.1 “transitional model” for nested type support is simulated. +In the transitional model a nested type is promoted to the file scope +unless a type of the same name already exists at the file scope. It is an +error to have two nested classes of the same name that need to be promoted +to file scope or to define a type at file scope after the declaration of a +nested class of the same name. This “feature” actually restricts the +source language accepted by the compiler. This is necessary because of the +effect this feature has on the name mangling of functions that use nested +types in their signature. This feature does not apply to template classes +and is only enabled when the configuration switch +CFRONT_2_1_OBJECT_CODE_COMPATIBILITY is TRUE.
      +
      +
    • +
    • +
      A cast to an array type is allowed; it is treated like a cast to a pointer +to the array element type. A warning is issued.
      +
      +
    • +
    • +
      When an array is selected from a class, the type qualifiers on the class +object (if any) are not preserved in the selected array. (In the normal +mode, any type qualifiers on the object are preserved in the element type +of the resultant array.)
      +
      +
    • +
    • +
      An identifier in a function is allowed to have the same name as a parameter +of the function. A warning is issued.
      +
      +
    • +
    • +
      An expression of type void may be supplied on the return statement in a +function with a void return type. A warning is issued.
      +
      +
    • +
    • +
      Cfront has a bug that causes a global identifier to be found when a member +of a class or one of its base classes should actually be found. This bug +is emulated in cfront compatibility mode but can be disabled by setting the +parameter CFRONT_GLOBAL_VS_MEMBER_NAME_LOOKUP_BUG to FALSE. A +warning is issued when, because of this feature, a nonstandard lookup is +performed.
      +

      +
      The following conditions must be satisfied for the nonstandard lookup to be +performed:
      +
      +
        +
      • +
        A member in a base class must have the same name as an identifier at the +global scope. The member may be a function, static data member, or +nonstatic data member. Member type names don’t apply because a nested +type will be promoted to the global scope by cfront which disallows a +later declaration of a type with the same name at the global scope.
        +
        +
      • +
      • +
        The declaration of the global scope name must occur between the +declaration of the derived class and the declaration of an out-of-line +constructor or destructor. The global scope name must be a type name.
        +
        +
      • +
      • +
        No other member function definition – even one for an unrelated class +– may appear between the destructor and the offending reference. +This has the effect that the nonstandard lookup applies to only one +class at any given point in time. For example:
        +
        +
        struct B {
        +  void func(const char*);
        +};
        +struct D : public B {
        +public:
        +  D();
        +  void Init(const char* );
        +};
        +struct func {
        +  func( const char* msg);
        +};
        +D::D(){}
        +void D::Init(const char* t){
        +  // Should call B::func --  calls func::func instead.
        +  new func(t);
        +}
        +
        +
        +
      • +
      +
      +
      The global scope name must be present in a base class (B::func in this +example) for the nonstandard lookup to occur. Even if the derived class +were to have a member named func, it is still the presence of +B::func that determines how the lookup will be performed.
      +
      +
    • +
    • +
      A parameter of type “const void *” is allowed on operator delete; +it is treated as equivalent to “void *”.
      +
      +
    • +
    • +
      A period (”.”) may be used for qualification where “::” should be +used. Only “::” may be used as a global qualifier. Except for the +global qualifier, the two kinds of qualifier operators may not be mixed in +a given name (i.e., you may say A::B::C or A.B.C but not A::B.C +or A.B::C). A period may not be used in a vacuous destructor reference +nor in a qualifier that follows a template reference such as A<T>::B.
      +
      +
    • +
    • +
      Cfront 2.1 does not correctly look up names in friend functions that are +inside class definitions. In this example function f should refer to the +functions and variables (e.g., f1 and a1) from the class +declaration. Instead, the global definitions are used.
      +
      +
      int a1;
      +int e1;
      +void f1();
      +class A {
      +  int a1;
      +  void f1();
      +  friend void f()  {
      +    int i1 = a1;   // cfront uses global a1
      +    f1();          // cfront uses global f1
      +  }
      +};
      +
      +
      +
      +
      Only the innermost class scope is (incorrectly) skipped by cfront +as illustrated in the following example.
      +
      +
      int a1;
      +int b1;
      +struct A {
      +  static int a1;
      +  class B {
      +    static int b1;
      +    friend void f() {
      +      int i1 = a1;  // cfront uses A::a1
      +      int j1 = b1;  // cfront uses global b1
      +    }
      +  };
      +};
      +
      +
      +
    • +
    • +
      operator= may be declared as a nonmember function. (This is flagged as +an anachronism by cfront 2.1)
      +
      +
    • +
    • +
      A type qualifier is allowed (but ignored) on the declaration of a +constructor or destructor. For example:
      +
      +
      class A {
      +  A() const;   // No error in cfront 2.1 mode
      +};
      +
      +
      +
    • +
    • +
      The preprocessing symbol c_plusplus is defined in addition to the +standard __cplusplus.
      +
      +
    • +
    +
    +
    +

    2.9.10. Extensions Accepted in Cfront 2.1 and 3.0 Compatibility Mode#

    +

    The following extensions are accepted in both cfront 2.1 and cfront 3.0 +compatibility mode (i.e., these are features or problems that exist in both +cfront 2.1 and 3.0):

    +
      +
    • +
      Type qualifiers on the this parameter may be dropped in contexts +such as this example:
      +
      +
      struct A {
      +  void f() const;
      +};
      +void (A::*fp)() = &A::f;
      +
      +
      +
      +
      This is actually a safe operation. A pointer to a const function may +be put into a pointer to non-const, because a call using the pointer is +permitted to modify the object and the function pointed to will actually +not modify the object. The opposite assignment would not be safe.
      +
      +
    • +
    • +
      Conversion operators specifying conversion to void are allowed.
      +
      +
    • +
    • +
      A nonstandard friend declaration may introduce a new type. A friend +declaration that omits the elaborated type specifier is allowed in default +mode, but in cfront mode the declaration is also allowed to introduce a new +type name.
      +
      +
      struct A {
      +   friend B;
      +};
      +
      +
      +
    • +
    • +
      The third operand of the ? operator is a conditional expression instead +of an assignment expression as it is in the modern language.
      +
      +
    • +
    • +
      A reference to a pointer type may be initialized from a pointer value +without use of a temporary even when the reference pointer type has +additional type qualifiers above those present in the pointer value. For +example,
      +
      +
      int *p;
      +const int *&r = p;  // No temporary used
      +
      +
      +
    • +
    • +
      A reference may be initialized with a null.
      +
      +
    • +
    • +
      Because cfront does not check the accessibility of types, access errors for +types are issued as warnings instead of errors.
      +
      +
    • +
    • +
      When matching arguments of an overloaded function, a const variable +with value zero is not considered to be a null pointer constant. In +general, in overload resolution a null pointer constant must be spelled +“0” to be considered a null pointer constant (e.g., '\0' is not +considered a null pointer constant).
      +
      +
    • +
    • +
      Inside the definition of a class type, the qualifier in the declarator for +a member declaration is dropped if that qualifier names the class being +defined.
      +
      +
      struct S {
      +  void S::f(); // No warning in cfront mode
      +};
      +
      +
      +
    • +
    • +
      An alternate form of declaring pointer-to-member-function variables is +supported, namely:
      +
      +
      struct A {
      +  void f(int);
      +  static void sf(int);
      +  typedef void A::T3(int);  // nonstd typedef decl
      +  typedef void T2(int);     // std typedef
      +};
      +typedef void A::T(int);   // nonstd typedef decl
      +T* pmf = &A::f;           // nonstd ptr-to-member decl
      +A::T2* pf = A::sf;        // std ptr to static mem decl
      +A::T3* pmf2 = &A::f;      // nonstd ptr-to-member decl
      +
      +
      +
      +
      where T is construed to name a routine type for a nonstatic member +function of class A that takes an int argument and returns +void; the use of such types is restricted to nonstandard +pointer-to-member declarations. The declarations of T and pmf in +combination are equivalent to a single standard pointer-to-member +declaration:
      +
      +
      void (A::* pmf)(int) = &A::f;
      +
      +
      +
      +
      A nonstandard pointer-to-member declaration that appears outside of a class +declaration, such as the declaration of T, is normally invalid and +would cause an error to be issued. However, for declarations that appear +within a class declaration, such as A::T3, this feature changes the +meaning of a valid declaration. cfront version 2.1 accepts declarations, +such as T, even when A is an incomplete type; so this case is also +excepted.
      +
      +
    • +
    • +
      Protected member access checking is not done when the address of a +protected member is taken. For example:
      +
      +
      class B { protected: int i; };
      +class D : public B { void mf(); };
      +void D::mf() {
      +  int B::* pmi1 = &B::i;  // error, OK in cfront mode
      +  int D::* pmi2 = &D::i;  // OK
      +}
      +
      +
      +
      +
      Note that protected member access checking for other operations (i.e., +everything except taking a pointer-to-member address) is done in the normal +manner.
      +
      +
    • +
    • +
      The destructor of a derived class may implicitly call the private +destructor of a base class. In default mode this is an error but in cfront +mode it is reduced to a warning. For example:
      +
      +
      class A {
      +  ~A();
      +};
      +class B : public A {
      +  ~B();
      +};
      +B::~B(){}      // Error except in cfront mode
      +
      +
      +
    • +
    • +
      When disambiguation requires deciding whether something is a parameter +declaration or an argument expression, the pattern type-name-or-keyword(identifier… ) is treated as an argument. For example:
      +
      +
      class A {
      +  A();
      +};
      +double d;
      +A x(int(d));
      +A(x2);
      +
      +
      +
      +
      By default int(d) is interpreted as a parameter declaration (with +redundant parentheses), and so x is a function; but in +cfront-compatibility mode int(d) is an argument and x is a +variable.
      +
      The declaration A(x2); is also misinterpreted by cfront. It should be +interpreted as the declaration of an object named x2, but in cfront +mode is interpreted as a function style cast of x2 to the type A.
      +
      Similarly, the declaration
      +
      +
      int xyz(int());
      +
      +
      +
      +
      declares a function named xyz, that takes a parameter of type “function +taking no arguments and returning an int.” In cfront mode this is +interpreted as a declaration of an object that is initialized with the +value int() (which evaluates to zero).
      +
      +
    • +
    • +
      A named bit-field may have a size of zero. The declaration is treated as +though no name had been declared.
      +
      +
    • +
    • +
      Plain bit fields (i.e., bit fields declared with a type of int) are +always unsigned.
      +
      +
    • +
    • +
      The name given in an elaborated type specifier is permitted to be a +typedef name that is the synonym for a class name, e.g.,
      +
      +
      typedef class A T;
      +class T *pa;   // No error in cfront mode
      +
      +
      +
    • +
    • +
      No warning is issued on duplicate size and sign specifiers.
      +
      +
      short short int i;    // No warning in cfront mode
      +
      +
      +
    • +
    • +
      An extra comma is allowed after the last argument in an argument list, as +for example in
      +
      +
      f(1, 2, );
      +
      +
      +
    • +
    • +
      A constant pointer-to-member-function may be cast to a pointer-to-function. +A warning is issued.
      +
      +
      struct A {
      +  int f();
      +};
      +main () {
      +  int (*p)();
      +  p = (int (*)())A::f;  // Okay, with warning
      +}
      +
      +
      +
    • +
    • +
      Arguments of class types that allow bitwise copy construction but also have +destructors are passed by value (i.e., like C structures), and the +destructor is not called on the “copy.” In normal mode, the class object is +copied into a temporary, the address of the temporary is passed as the +argument, and the destructor is called on the temporary after the call +returns. Note that because the argument is passed differently (by value +instead of by address), code like this compiled in cfront mode is not +calling-sequence compatible with the same code compiled in normal mode. In +practice, this is not much of a problem, since classes that allow bitwise +copying usually do not have destructors.
      +
      +
    • +
    • +
      A union member may be declared to have the type of a class for which the +user has defined an assignment operator (as long as the class has no +constructor or destructor). A warning is issued.
      +
      +
    • +
    • +
      When an unnamed class appears in a typedef declaration, the typedef +name may appear as the class name in an elaborated type specifier.
      +
      +
      typedef struct {
      + int i, j;
      +} S;
      +struct S x;     // No error in cfront mode
      +
      +
      +
    • +
    • +
      Two member functions may be declared with the same parameter types when one +is static and the other is nonstatic with a function qualifier.
      +
      +
      class A {
      +  void f(int) const;
      +  static void f(int);     // No error in cfront mode
      +};
      +
      +
      +
    • +
    • +
      The scope of a variable declared in the for-init-statement is the scope +to which the for statement belongs.
      +
      +
      int f(int i) {
      +  for (int j = 0; j < i; ++j) { /* ... */ }
      +  return j;     // No error in cfront mode
      +}
      +
      +
      +
    • +
    • +
      Function types differing only in that one is declared extern "C" and +the other extern "C++" can be treated as identical:
      +
      +
      typedef void (*PF)();
      +extern "C" typedef void (*PCF)();
      +void f(PF);
      +void f(PCF);
      +
      +
      +
      +
      When DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT is FALSE, PF and +PCF are considered identical and void f(PCF) is treated as a +compatible redeclaration of f. (By contrast, in standard C++``PF`` and +PCF are different and incompatible types – PF is a pointer to an +extern "C++" function whereas PCF is a pointer to an extern "C" +function – and the two declarations of f create an overload set.)
      +

      +
      However, even if DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT is TRUE, +it is possible to set +IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE to TRUE as well, so +that in cfront-compatibility mode an implicit type conversion will always +be done between a pointer to an extern "C" function and a pointer to an +extern "C++``”`` function.
      +
      +
    • +
    • +
      Functions declared inline have internal linkage.
      +
      +
    • +
    • +
      enum types are regarded as integral types.
      +
      +
    • +
    • +
      An uninitialized const object of non-POD class type is allowed even if +its default constructor is implicitly declared:
      +
      +
      struct A { virtual void f(); int i; };
      +const A a;
      +
      +
      +
    • +
    • +
      A function parameter type is allowed to involve a pointer or reference to +array of unknown bounds.
      +
      +
    • +
    • +
      If the user declares an operator= function in a class, but not one that +can serve as the default operator=, and bitwise assignment could be +done on the class, a default operator= is not generated; only the +user-written operator= functions are considered for assignments (and +therefore bitwise assignment is not done).
      +
      +
    • +
    • +
      A member function declaration whose return type is omitted (and thus +implicitly int) and whose name is found to be that of a type is +accepted if it takes no parameters:
      +
      +
      typedef int I;
      +struct S {
      +  I();    // Accepted in cfront mode (declares "int S::I()")
      +  I(int); // Not accepted
      +};
      +
      +
      +
    • +
    • +
      Default arguments are retained as part of deduced function types.
      +
      +
    • +
    +
    +
    +
    +

    2.10. C Dialect Accepted#

    +

    The front end accepts the ANSI/ISO C language as defined by ANSI/ISO +9899:1990. In C99 mode, it accepts the ANSI/ISO C language defined by +ISO/IEC 9899:1999 as modified by Technical Corrigenda 1 through 3. In C11 +mode, it accepts the C language defined by ISO/IEC 9899:2011 and in C18 +mode the language defined by ISO/IEC 9899:2018 (which only differs from C11 +in minor ways). In C23 mode, many of the features of the latest standard +have been implemented. See the EDG web site for up-to-date information about +feature implementation.

    +

    When Embedded C extensions are enabled, the front end can accept the constructs +described in ISO/IEC TR 18037 (fixed-point types, named address space +qualifiers, and named-register storage class specifiers).

    +

    The front end extensively emulates the C modes of the Microsoft, GNU, and clang +compilers. See GNU C++ Mode. As with C++ mode, only one emulation mode may +be in effect for a given compilation. The --ms_extensions and +--ms_compatibility options can be used to emulate certain Microsoft +behaviors irrespective of the emulation mode.

    +

    There is no Sun C mode corresponding to Sun C++ mode, however.

    +

    The special comments recognized by the UNIX lint program – +/*ARGSUSED*/, /*VARARGS*/ (with or without a count of non-varying +arguments), and /*NOTREACHED*/ – are also recognized by the front end.

    +

    When Unified Parallel C (UPC) mode is enabled, it also accepts the core +language extensions described in version 1.0 of the UPC Language +Specifications).

    +
    +

    2.10.1. C99 Features Available in Other Modes#

    +

    Certain C language features were added in the C99 version of the ISO C standard +and are supported in C99 mode. For a full list of those features, see ISO/IEC +9899:1999. A few features are noteworthy, however, because they are +implementation-specific or because they can be enabled in older C modes or +(when indicated) in C++ mode:

    +
      +
    • +
      The options --variadic_macros, --no_variadic_macros, +--extended_variadic_macros and --no_extended_variadic_macros +control whether macros taking a variable number of arguments are +recognized. Configuration flags are available to select the default +setting of these options; these are also available in C++ mode.
      +
      Ordinary variadic macros (as included in C99) are illustrated by the +following example:
      +
      +
      #define OVM(x, ...) x(__VA_ARGS__)
      +void f() { OVM(printf, "%s %d\n", "Three args for ", 1); }
      +/* Expands to: printf("%s %d\n", "Three args for ", 1) */
      +
      +
      +
      +
      During expansion the special identifier __VA_ARGS__ will be replaced by +the trailing arguments of the macro invocation. If variadic macros are +enabled, this special identifier can appear only in the replacement list of +variadic macros.
      +
      Extended variadic macros (as implemented by certain pre-C99 compilers) use +a slightly different syntax and allow the name of the variadic parameter to +be chosen (instead of .../__VA_ARGS__):
      +
      +
      #define EVM(x, args...) x(args)
      +void f() { EVM(printf, "%s %d\n", "Three args for ", 1); }
      +/* Same expansion as previous example. */
      +
      +
      +
      +
      In addition, enabling extended variadic macros adds a special behavior to +the token pasting operator ## when it is followed by an empty or omitted +macro argument: A preceding comma (possibly followed by white space) is +erased. Hence,
      +
      +
      #define EVM2(fmt, args) printf(fmt , ## args)
      +EVM2("Hello World\n")
      +
      +
      +
      +
      expands to printf("Hello World\n") and the extraneous comma is erased.
      +
      +
    • +
    • +
      If the LONG_LONG_ALLOWED switch is TRUE,
      +
      +
        +
      • +
        the long long and unsigned long long types are accepted;
        +
        +
      • +
      • +
        integer constants suffixed by LL are given the type long long, +and those suffixed by ULL are given the type unsigned long long +(any of the suffix letters may be written in lower case);
        +
        +
      • +
      • +
        the specifier %lld is recognized in printf and scanf +formatting strings; and
        +
        +
      • +
      • +
        the long long types are accommodated in the usual arithmetic +conversions.
        +
        +
      • +
      +
    • +
    • +
      restrict may be used as a type qualifier for object pointer types and +function parameter arrays that decay to pointers. Its presence is recorded +in the IL so that back ends can perform optimizations that would otherwise +be prevented because of possible aliasing. The keyword is enabled by +--restrict; this is also available in C++.
      +
      +
    • +
    • +
      If VLA_ALLOWED is TRUE, variable length arrays (VLAs) are supported. +VLA types may appear only in the declaration of an identifier that belongs +to a block or function-prototype scope. For example:
      +
      +
      void addscalar(int n, int m, double a[n][m], double x) {
      +  int i, j;
      +  for (i=0; i<n; i++)
      +    for (j=0; j<m, j++)
      +      a[i][j] += x;
      +        /* a refers to a VLA with n*m elements. */
      +}
      +double A[4][8];
      +void f() {
      +  addscalar(4, 8, A, 3.14);
      +}
      +
      +
      +
      +
      See also command line options --vla and --no_vla.
      +
      +
    • +
    • +
      When DESIGNATED_INITIALIZER_ENABLING_POSSIBLE is TRUE, designators may +be accepted in initializers for aggregates. Designators are not allowed in +C++ mode, however. The global variables designators_allowed and +extended_designators_allowed are controlled by configuration flags and +command line options. In turn they control which variety (if any) of +designators is recognized. See also command line options +--designators, --no_designators, --extended_designators and +--no_extended_designators.
      +
      When designators_allowed is TRUE, designators of the forms .x and +[k] are accepted. They can be concatenated to reach nested aggregate +elements. For example:
      +
      +
      struct X { double a; int b[10] } x
      +                        = { .b = { 1, [5] = 2 }, .b[3] = 1, .a = 42.0 };
      +
      +
      +
      +
      In addition, when extended_designators_allowed is TRUE, designators of +the form x: and [m ...  n] are accepted and the assignment (=) +token becomes optional after array element designators. Field designators +of the form x: cannot immediately be followed by an assignment token +(=) or another designator. Examples:
      +
      +
      struct X { double a; int b[10] } x
      +                        = { b: { 1, [5 ... 9] = 2 }, .b[7] 1, a: 42.0 };
      +struct Y y = { b:[3] /* Error */ = 7, a: = /* Error */ 42.0 };
      +
      +
      +
      +
      Designators permit multiple initializations of the same subobject: only the +last value is retained, but side-effects of prior initializing expressions +do occur.
      +
      +
    • +
    • +
      Compound literals are supported in expressions. For example,
      +
      +
      int *p = (int []){1, 2, 3};
      +
      +
      +
      +
      creates an unnamed lvalue of type int[3] initialized as indicated. +p is initialized to point to that array. Compound literals are not +allowed in C++ mode.
      +
      +
    • +
    • +
      The __generic pseudo-macro is implemented. This is an EDG extension +used to support the type-generic math header <tgmath.h>. The form of +the macro reference is:
      +
      +
      __generic(x, y, z, func_d, func_f, func_l, func_cd, func_cf, func_cl)
      +
      +
      +
      +
      where x and the optional y and z are the arguments with which a +type-generic function is called, and the remaining 6 arguments are the +names of functions from which is selected the actual function to be called. +The suffixes with which the function names are supplied here correspond to +function parameter types of double, float, long double, +double _Complex, float _Complex, and long double _Complex, +respectively. The order is fixed. Function names may be omitted. For +example, <tgmath.h> may have the following macros defined:
      +
      +
      #define sin(x)  __generic(x,,,  sin, sinf, sinl, csin, csinf,csinl)(x)
      +#define fmax(x,y) __generic(x, y,,fmax, fmaxf, fmaxl,,,)(x, y)
      +#define conjg(x)  __generic(x,,,  ,,, conjg, conjgf, conjgl)(x)
      +
      +
      +
      +
      Note that sin and conjg take only one argument, that fmax has +no forms that accept complex arguments, and that conjg has no forms +that accept real arguments.
      +
      There is also a __genericfx pseudo-macro that provides a similar +capability for fixed-point types. The form of the macro reference is:
      +
      +
      __genericfx(x, fnc_hr, fnc_uhr, fnc_r, fnc_ur, fnc_lr, fnc_ulr,
      +              fnc_hk, fnc_uhk, fnc_k, fnc_uk, fnc_lk, fnc_ulk)
      +
      +
      +
      +
      where x is as above and the remaining 12 arguments are the names of +functions, with the suffixes corresponding to function parameter types of +short_Fract, unsignedshort_Fract, _Fract, +unsigned_Fract, long_Fract, unsignedlong_Fract, short_Accum, unsignedshort_Accum, +_Accum, unsigned _Accum, long_Accum, unsignedlong_Accum, respectively.
      +
      +
    • +
    • +
      The keywords __I__, __NAN__, and __INFINITY__ are defined as, +respectively, a float _Imaginary i, a float Not-a-Number, and a float +positive Infinity. These are intended to be used by library writers to +implement the C99 macros I, NAN, and INFINITY. __NAN__ and +__INFINITY__ are also available in all modes, not just C99 mode.
      +
      +
    • +
    • +
      A trailing array member of unspecified length in a struct type is called a +flexible array member. Such members are a standard feature in C99. In +default C99 mode (but not in strict C99 mode) trailing struct members can +also have a type containing a flexible array member. For example:
      +
      +
      struct F {
      +  int i;
      +  int f[];  // OK in default and strict C99 modes
      +};
      +struct X {
      +  F x;  // OK in default C99 mode (but not in strict mode)
      +};
      +
      +
      +
    • +
    +
    +
    +

    2.10.2. ANSI C Extensions#

    +

    The following extensions are accepted (these are flagged if the -A or +-a option is specified):

    +
      +
    • +
      A translation unit (input file) can contain no declarations.
      +
      +
    • +
    • +
      Comment text can appear at the ends of preprocessing directives.
      +
      +
    • +
    • +
      __ALIGNOF__ (or __alignof__) is similar to sizeof, but returns +the alignment requirement value for a type, or 1 if there is no +alignment requirement. It may be followed by a type or expression in +parentheses:
      +
      +
      +

      __ALIGNOF__(type)        __alignof__(type)

      +

      __ALIGNOF__(expression)  __alignof__(expression)

      +
      +
      +
      The expression in the second form is not evaluated.
      +
      +
    • +
    • +
      __INTADDR__(expression) scans the enclosed expression as a +constant expression, and converts it to an integer constant (it is used in +the offsetof macro).
      +
      +
    • +
    • +
      A number of “type traits pseudo-functions” (taking one or more type +names) are accepted: __has_nothrow_assign, +__has_nothrow_constructor, __has_nothrow_copy, +__has_nothrow_move_assign, __has_trivial_assign, +__has_trivial_constructor, __has_trivial_copy, +__has_trivial_destructor, __has_trivial_move_assign, +__has_trivial_move_constructor, __has_virtual_destructor, +__is_abstract, __is_base_of, __is_class, +__is_constructible, __is_convertible_to, __is_destructible, +__is_empty, __is_enum, __is_literal_type, +__is_nothrow_assignable, __is_nothrow_constructible, +__is_nothrow_destructible, __is_pod, __is_polymorphic, +__is_standard_layout, __is_trivial, +__is_trivially_assignable, __is_trivially_constructible, +__is_trivially_copyable, __is_trivially_destructible, and +__is_union.
      +
      +
      double x[__is_union(union U)];  // Okay.
      +
      +
      +
      +
      These are silently accepted even in strict modes. They ease the +implementation C++11 metaprogramming templates (many of which were first +introduced by ISO/IEC TR 19768).
      +
      +
    • +
    • +
      Bit fields may have base types that are enums or integral types +besides int and unsigned int. This matches A.6.5.8 in the ANSI +Common Extensions appendix.
      +
      +
    • +
    • +
      If the ADDR_OF_BIT_FIELD_ALLOWED flag is TRUE, the address of a bit +field may be taken if the bit field has the same size and alignment as one +of the integral types. A warning is issued.
      +
      +
    • +
    • +
      The last member of a struct may have an incomplete array type. It may +not be the only member of the struct (otherwise, the struct would have zero +size).
      +
      +
    • +
    • +
      A file-scope array may have an incomplete struct, union, or +enum type as its element type. The type must be completed before the +array is subscripted (if it is), and by the end of the compilation if the +array is not extern. In C++, an incomplete class is also allowed.
      +
      +
    • +
    • +
      Static functions may be declared in function and block scopes. Their +declarations are moved to the file scope.
      +
      +
    • +
    • +
      enum tags may be incomplete: one may define the tag name and resolve it +(by specifying the brace-enclosed list) later.
      +
      +
    • +
    • +
      The values of enumeration constants may be given by expressions that +evaluate to unsigned quantities that fit in the unsigned int range but +not in the int range. A warning is issued for suspicious cases.
      +
      +
      /* When ints are 32 bits: */
      +enum a {w = -2147483648};  /* No warning */
      +enum b {x = 0x80000000};   /* No warning */
      +enum c {y = 0x80000001};   /* No warning */
      +enum d {z = 2147483649};   /* Warning */
      +
      +
      +
    • +
    • +
      An extra comma is allowed at the end of an enum list. A remark is +issued except in pcc mode.
      +
      +
    • +
    • +
      The final semicolon preceding the closing } of a struct or union +specifier may be omitted. A warning is issued except in pcc mode.
      +
      +
    • +
    • +
      A label definition may be immediately followed by a right brace. +(Normally, a statement must follow a label definition.) A warning is +issued.
      +
      +
    • +
    • +
      An empty declaration (a semicolon with nothing before it) is allowed. A +remark is issued.
      +
      +
    • +
    • +
      An initializer expression that is a single value and is used to initialize +an entire static array, struct, or union need not be enclosed in braces. +ANSI C requires the braces.
      +
      +
    • +
    • +
      In an initializer, a pointer constant value may be cast to an integral type +if the integral type is big enough to contain it.
      +
      +
    • +
    • +
      The address of a variable with register storage class may be taken. A +warning is issued.
      +
      +
    • +
    • +
      In an integral constant expression, an integer constant may be cast to a +pointer type and then back to an integral type.
      +
      +
    • +
    • +
      long float is accepted as a synonym for double.
      +
      +
    • +
    • +
      If PTR_TO_INCOMP_ARRAY_ARITHMETIC_ALLOWED is TRUE, pointers to +incomplete arrays may be used in pointer addition, subtraction, and +subscripting:
      +
      +
      int (*p)[];
      +...
      +q = p[0];
      +
      +
      +
      +
      A warning is issued if the value added or subtracted is anything other than +a constant zero. Since the type pointed to by the pointer has zero size, +the value added to or subtracted from the pointer is multiplied by zero and +therefore has no effect on the result.
      +
      +
    • +
    • +
      Benign redeclarations of typedef names are allowed. That is, a typedef +name may be redeclared in the same scope as the same type. A warning is +issued.
      +
      +
    • +
    • +
      Dollar signs can be accepted in identifiers through use of a command line +option or by setting a configuration parameter. The default is to not +allow dollar signs in identifiers.
      +
      +
    • +
    • +
      Numbers are scanned according to the syntax for numbers rather than the +pp-number syntax. Thus, 0x123e+1 is scanned as three tokens +instead of one invalid token. (If the -A or -a option is +specified, of course, the pp-number syntax is used.)
      +
      +
    • +
    • +
      Assignment and pointer difference are allowed between pointers to types +that are interchangeable but not identical, for example, unsigned char +* and char *. This includes pointers to same-sized integral types +(e.g., typically, int * and long *). A warning is issued except in +pcc mode. Assignment of a string constant to a pointer to any kind of +character is allowed without a warning.
      +
      +
    • +
    • +
      Assignment of pointer types is allowed in cases where the destination type +has added type qualifiers that are not at the top level (e.g., int ** +to const int **). Comparisons and pointer difference of such pairs of +pointer types are also allowed. A warning is issued.
      +
      +
    • +
    • +
      In operations on pointers, a pointer to void is always implicitly +converted to another type if necessary, and a null pointer constant is +always implicitly converted to a null pointer of the right type if +necessary. In ANSI C, some operators allow such things, and others +(generally, where it does not make sense) do not allow them.
      +
      +
    • +
    • +
      Pointers to different function types may be assigned or compared for +equality (==) or inequality (!=) without an explicit type cast. A +warning is issued. This extension is not allowed in C++ mode.
      +
      +
    • +
    • +
      A pointer to void may be implicitly converted to or from a pointer to a +function type.
      +
      +
    • +
    • +
      If the ATT_PREPROCESSING_EXTENSIONS_ALLOWED switch is TRUE, the +#assert preprocessing extensions of AT&T System V release 4 are +allowed. These allow definition and testing of predicate names. Such +names are in a name space distinct from all other names, including macro +names. A predicate name is given a definition by a preprocessing directive +of the form
      +
      +
      +
      +
      #assert name
      +
      #assert name(token-sequence)
      +
      +
      +
      +
      which defines the predicate name. In the first form, the predicate +is not given a value. In the second form, it is given the value +token-sequence. Such a predicate can be tested in a #if +expression, as follows:
      +
      +
      +
      +
      #name(token-sequence)
      +
      +
      +
      +
      which has the value 1 if a #assert of that name with that +token-sequence has appeared, and 0 otherwise. A given predicate may be +given more than one value at a given time.
      +
      +
      +
      A predicate may be deleted by a preprocessing directive of the form
      +
      +
      +
      +
      #unassert name
      +
      #unassert name(token-sequence)
      +
      +
      +
      +
      The first form removes all definitions of the indicated predicate name; the +second form removes just the indicated definition, leaving any others there +may be.
      +
      +
    • +
    • +
      GNU line directive flags are accepted on #line directives. The system +header flag is recognized, and the associated code is treated as if found +in a system include directory.
      +
      +
    • +
    • +
      asm statements and declarations are accepted. This is disabled in +strict ANSI C mode (-A or -a and -m options) since it conflicts +with the ANSI C standard for something like
      +
      +
      asm("xyz");
      +
      +
      +
      +
      which ANSI C interprets as a call of an implicitly-defined function asm +and which by default the front end interprets as an asm statement.
      +
      +
    • +
    • +
      When ASM_FUNCTION_ALLOWED is TRUE, asm functions are accepted, and +__asm is recognized as a synonym for asm. An asm function body +is represented in the IL by an uninterpreted null-terminated string +containing the text that appears in the source (including the text of +source comments when INCLUDE_COMMENTS_IN_ASM_FUNC_BODY is TRUE). An +asm function must be declared with no storage class, with a prototyped +parameter list, and with no omitted parameters:
      +
      +
      asm void f(int,int) {
      +  ...
      +}
      +
      +
      +
      +
      If asm functions are recognized and the C-generating back end is used, +it is required that ANSI-C be generated, not K&R C, because the asm +function must be put out with a prototyped parameter list.
      +
      +
    • +
    • +
      If ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE, an extension is +supported to allow constructs similar to C++ anonymous unions, including +the following:
      +
      +
        +
      • +
        not only anonymous unions but also anonymous structs are allowed – that +is, their members are promoted to the scope of the containing struct and +looked up like ordinary members;
        +
        +
      • +
      • +
        they can be introduced into the containing struct by a typedef name +– they needn’t be declared directly, as with true anonymous unions; and
        +
        +
      • +
      • +
        a tag may be declared (C mode only).
        +
        +
      • +
      +
      +
      Among the restrictions: the extension only applies to constructs within +structs.
      +
      +
    • +
    • +
      If DEFAULT_ADDRESS_OF_ELLIPSIS_ALLOWED is TRUE, the expression &... +is accepted in the body of a function in which an ellipsis appears in the +parameter list. It is needed to support some versions of macro +va_start in stdarg.h.
      +
      +
    • +
    • +
      If DEFAULT_ALLOW_ELLIPSIS_ONLY_PARAM_IN_C_MODE is TRUE, an ellipsis may +appear by itself in the parameter list of a function declaration – e.g., +f(...). A diagnostic is issued in strict ANSI C mode.
      +
      +
    • +
    • +
      External entities declared in other scopes are visible. A warning is +issued.
      +
      +
      void f1(void) { extern void f(); }
      +void f2() {
      +  f(); /* Using out of scope declaration */
      +}
      +
      +
      +
    • +
    • +
      A non-lvalue array expression is converted to a pointer to the first +element of the array when it is subscripted or similarly used.
      +
      +
    • +
    • +
      The nonstandard preprocessing directive #include_next is supported. +This is a variant of the #include directive. It searches for the named +file only in the directories on the search path that follow the directory +in which the current source file (the one containing the #include_next +directive) is found. (This is an extension found in the GNU C compiler.)
      +
      +
    • +
    • +
      The nonstandard preprocessing directive #warning is supported. It is +similar to the #error directive, but results in a warning instead of a +catastrophic error when processed. This directive is not recognized in +strict mode. (This is an extension found in GNU C compilers.)
      +
      +
    • +
    +

    In the following areas considered “undefined behavior” by the ANSI C standard, +the front end does the following:

    +
      +
    • +
      Adjacent wide and non-wide string literals are not concatenated unless +wchar_t and char are the same type. (In C++ mode, when wchar_t +is a keyword, adjacent wide and non-wide string literals are never +concatenated.)
      +
      +
    • +
    • +
      In character and string escapes, if the character following the \ has +no special meaning, the value of the escape is the character itself. Thus +"\s" == "s". A warning is issued.
      +
      +
    • +
    • +
      A struct that has no named fields but at least one unnamed field is +accepted by default, but a diagnostic (a warning or error) is issued in +strict ANSI C mode.
      +
      +
    • +
    +
    +
    +

    2.10.3. K&R/pcc Mode#

    +

    When pcc mode is specified, the front end accepts the traditional C +language defined by The C Programming Language, first edition, by +Kernighan and Ritchie (K&R), Prentice-Hall, 1978. In addition, it provides +almost complete compatibility with the Reiser cpp and Johnson pcc +widely used as part of UNIX systems; since there is no documentation of the +exact behavior of those programs, complete compatibility cannot be +guaranteed.

    +

    In general, when compiling in pcc mode, the front end attempts to interpret +a source program that is valid to pcc in the same way that pcc would. +However, ANSI features that do not conflict with this behavior are not +disabled.

    +

    In some cases where pcc allows a highly questionable construct, the front +end will accept it but give a warning, where pcc would be silent (for +example: 0x, a degenerate hexadecimal number, is accepted as zero).

    +

    The known cases where the front end is not compatible with pcc are the +following:

    +
      +
    • +
      Token pasting is not done outside of macro expansions (i.e., in the primary +source line) when two tokens are separated only by a comment. That is, +a/**/b is not considered to be ab. The pcc behavior in that +case can be gotten by preprocessing to a text file and then compiling that +file.
      +

      +
      The textual output from preprocessing is also equivalent but not identical: +the blank lines and white space will not be exactly the same.
      +
      +
    • +
    • +
      pcc will consider the result of a ?: operator to be an lvalue if +the first operand is constant and the second and third operands are +compatible lvalues. This front end will not.
      +
      +
    • +
    • +
      pcc mis-parses the third operand of a ?: operator in a way that +some programs exploit:
      +
      +
      i ? j : k += l
      +
      +
      +
      +
      is parsed by pcc as
      +
      +
      i ? j : (k += l)
      +
      +
      +
      +
      which is not correct, since the precedence of += is lower than the +precedence of ?:. This front end will generate an error for that case.
      +
      +
    • +
    • +
      lint recognizes the keywords for its special comments anywhere in a +comment, regardless of whether or not they are preceded by other text in +the comment. The front end only recognizes the keywords when they are the +first identifier following an optional initial series of blanks and/or +horizontal tabs. lint also recognizes only a single digit of the +VARARGS count; the front end will accumulate as many digits as appear.
      +
      +
    • +
    +

    The differences in pcc mode relative to the default ANSI mode are as +follows:

    +
      +
    • +
      The keywords signed, const, and volatile are disabled, to avoid +problems with items declared with those names in old-style code. Those +keywords were ANSI C inventions. The other non-K&R keywords (enum and +void) are judged to have existed already in code and are not disabled.
      +
      +
    • +
    • +
      Declarations of the form
      +
      +
      typedef some-type void;
      +
      +
      +
      +
      are ignored.
      +
      +
    • +
    • +
      Assignment is allowed between pointers and integers, and between +incompatible pointer types, without an explicit cast. A warning is issued.
      +
      +
    • +
    • +
      A field selection of the form p->field is allowed even if +p does not point to a struct or union that contains field. +p must be a pointer or an integer. Likewise, x.field is +allowed even if x is not a struct or union that contains +field. x must be an lvalue. For both cases, all definitions of +field as a field must have the same offset within their struct or +union.
      +
      +
    • +
    • +
      If the configuration flag TARG_NO_ERROR_ON_INTEGER_OVERFLOW is TRUE, +overflows detected while folding signed integer operations on constants +will cause warnings rather than errors. Usually this should be set to +match the desired target machine behavior on integer operations in C.
      +
      +
    • +
    • +
      If the configuration flag SAME_REPR_INTS_INTERCHANGEABLE_IN_IL is TRUE, +integral types with the same representation (size, signedness, and +alignment) will be considered identical and may be used interchangeably. +For example, this means that int and long will be interchangeable +if they have the same size.
      +
      +
    • +
    • +
      A warning will be issued for a & applied to an array. The type of such +an operation is “address of array element” rather than “address of array”.
      +
      +
    • +
    • +
      For the shift operators << and >>, the usual arithmetic conversions +are done, the right operand is converted to int, and the result type is +the type of the left operand. In ANSI C, the integral promotions are done +on the two operands, and the result type is the type of the left operand. +The effect of this difference is that, in pcc mode, a long shift +count will force the shift to be done as long.
      +
      +
    • +
    • +
      When preprocessing output is generated, the line-identifying directives +will have the pcc form instead of the ANSI form.
      +
      +
    • +
    • +
      String literals will not be shared. Identical string literals will cause +multiple copies of the string to be allocated.
      +
      +
    • +
    • +
      sizeof may be applied to bit fields; the size is that of the underlying +type (e.g., unsigned int).
      +
      +
    • +
    • +
      lvalues cast to a type of the same size remain lvalues, except when they +involve a floating-point conversion.
      +
      +
    • +
    • +
      When a function parameter list begins with a typedef identifier, the +parameter list is considered prototyped only if the typedef identifier +is followed by something other than a comma or right parenthesis:
      +
      +
      typedef int t;
      +int f(t) {}     /* Old-style list */
      +int g(t x) {}   /* Prototyped list, parameter x of type t */
      +
      +
      +
      +
      That is, function parameters are allowed to have the same names as +typedefs. In the normal ANSI mode, of course, any parameter list +that begins with a typedef identifier is considered prototyped, so the +first example above would give an error.
      +
      +
    • +
    • +
      The names of functions and of external variables are always entered at the +file scope.
      +
      +
    • +
    • +
      A function declared static, used, and never defined is treated as if +its storage class were extern.
      +
      +
    • +
    • +
      A file-scope array that has an unspecified storage class and remains +incomplete at the end of the compilation will be treated as if its storage +class is extern (in ANSI mode, the number of elements is changed to 1, +and the storage class remains unspecified).
      +
      +
    • +
    • +
      The empty declaration
      +
      +
      +
      +
      struct x;
      +
      +
      +
      +
      will not hide an outer-scope declaration of the same tag.
      +
      +
    • +
    • +
      In a declaration of a member of a struct or union, no diagnostic is +issued for omitting the declarator list; nevertheless, such a declaration +has no effect on the layout. For example,
      +
      +
      struct s {char a; int; char b[2];} v;    /* sizeof(v) is 3 */
      +
      +
      +
    • +
    • +
      enums are always given type int. In ANSI mode, and depending on +the configuration flag enum_types_can_be_smaller_than_int, smaller +integral types will be used if possible.
      +
      +
    • +
    • +
      No warning is generated for a storage specifier appearing in other than the +first position in a list of specifiers (as in int static).
      +
      +
    • +
    • +
      short, long, and unsigned are treated as “adjectives” in type +specifiers, and they may be used to modify a typedef type.
      +
      +
    • +
    • +
      A “plain” char is considered to be the same as either signed char +or unsigned char, depending on the installation default and +command-line options. In ANSI C, “plain” char is a third type distinct +from both signed char and unsigned char.
      +
      +
    • +
    • +
      Free-standing tag declarations are allowed in the parameter declaration +list for a function with old-style parameters.
      +
      +
    • +
    • +
      float function parameters are promoted to double function +parameters.
      +
      +
    • +
    • +
      float functions are promoted to double functions.
      +
      +
    • +
    • +
      Declaration specifiers are allowed to be completely omitted in declarations +(ANSI C allows this only for function declarations). Thus
      +
      +
      i;
      +
      +
      +
      +
      declares i as an int variable. A warning is issued.
      +
      +
    • +
    • +
      The = preceding an initializer may be omitted. A warning is issued. +See K&R first edition, Appendix A, section 17 (anachronisms). This is +accepted only if C_ANACHRONISMS_ALLOWED is TRUE.
      +
      +
    • +
    • +
      All float operations are done as double.
      +
      +
    • +
    • +
      __STDC__ is left undefined.
      +
      +
    • +
    • +
      Extra spaces to prevent pasting of adjacent confusable tokens are not +generated in textual preprocessing output.
      +
      +
    • +
    • +
      The first directory searched for include files is the directory containing +the file containing the #include instead of the directory containing +the primary source file.
      +
      +
    • +
    • +
      Trigraphs are not recognized.
      +
      +
    • +
    • +
      Comments are deleted entirely (instead of being replaced by one space) in +preprocessing output.
      +
      +
    • +
    • +
      0x is accepted as a hexadecimal 0, with a warning.
      +
      +
    • +
    • +
      1E+ is accepted as a floating-point constant with an exponent of 0, +with a warning.
      +
      +
    • +
    • +
      The compound assignment operators may be written as two tokens (e.g., ++= may be written + =).
      +
      +
    • +
    • +
      The compound assignment operators may be written in their old-fashioned +reversed forms (e.g., -= may be written =-). A warning is issued. +This is described in K&R first edition, Appendix A, section 17 +(anachronisms). This is accepted only if C_ANACHRONISMS_ALLOWED is +TRUE.
      +
      +
    • +
    • +
      The digits 8 and 9 are allowed in octal constants.
      +
      +
    • +
    • +
      A warning rather than an error is issued for integer constants that are +larger than can be accommodated in an unsigned long. The value is +truncated to an acceptable number of low-order bits.
      +
      +
    • +
    • +
      The types of large integer constants are determined according to the K&R +rules (they won’t be unsigned in some cases where ANSI C would define +them that way). Integer constants with apparent values larger than +LONG_MAX are typed as long and are also marked as “non-arithmetic”, +which suppresses some warnings when using them.
      +
      +
    • +
    • +
      The escape \a (alert) is not recognized in character and string +constants.
      +
      +
    • +
    • +
      Macro expansion is done differently. Arguments to macros are not +macro-expanded before being inserted into the expansion of the macro. Any +macro invocations in the argument text are expanded when the macro +expansion is rescanned. With this method, macro recursion is possible and +is checked for.
      +
      +
    • +
    • +
      Token pasting inside macro expansions is done differently. End-of-token +markers are not maintained, so tokens that abut after macro substitution +may be parsed as a single token.
      +
      +
    • +
    • +
      Macro parameter names inside character and string constants are recognized +and substituted for.
      +
      +
    • +
    • +
      Macro invocations having too many arguments are flagged with a warning +rather than an error. The extra arguments are ignored.
      +
      +
    • +
    • +
      Macro invocations having too few arguments are flagged with a warning +rather than an error. A null string is used as the value of the missing +parameters.
      +
      +
    • +
    • +
      Extra #elses (after the first has appeared in an #if block) are +ignored, with a warning.
      +
      +
    • +
    • +
      Expressions in a switch statement are cast to int; this differs +from the ANSI C definition in that a long expression is (possibly) +truncated.
      +
      +
    • +
    • +
      The promotion rules for integers are different: unsigned char and +unsigned short are promoted to unsigned int.
      +
      +
    • +
    • +
      An identifier in a function is allowed to have the same name as a parameter +of the function. A warning is issued.
      +
      +
    • +
    +
    +
    +

    2.10.4. Extensions Accepted in SVR4 Compatibility Mode#

    +

    The following extensions are accepted in SVR4 C compatibility mode:

    +
      +
    • +
      Macro invocations having too many arguments are flagged with a warning +rather than an error. The extra arguments are ignored.
      +
      +
    • +
    • +
      Macro invocations having too few arguments are flagged with a warning +rather than an error. A null string is used as the value of the missing +parameters.
      +
      +
    • +
    • +
      The sequence /**/ in a macro definition is treated as equivalent to the +token-pasting operator ##.
      +
      +
    • +
    • +
      lvalues cast to a type of the same size remain lvalues, except when they +involve a floating-point conversion.
      +
      +
    • +
    • +
      Assignment is allowed between pointers and integers, and between +incompatible pointer types, without an explicit cast. A warning is issued.
      +
      +
    • +
    • +
      A field selection of the form p->field is allowed even if +p does not point to a struct or union that contains field. +p must be a pointer. Likewise, x.field is allowed even +if x is not a struct or union that contains field. x +must be an lvalue. For both cases, all definitions of field as a +field must have the same offset within their struct or union.
      +
      +
    • +
    • +
      In an integral constant expression, an integer constant may be cast to a +pointer type and then back to an integral type.
      +
      +
    • +
    • +
      Incompatible external object declarations are allowed if the object types +share the same underlying representation.
      +
      +
    • +
    • +
      Certain incompatible function declarations are allowed. A warning is +issued.
      +
      +
      typedef unsigned int size_t;
      +extern size_t strlen(const char *);
      +extern int strlen();  /* Warning */
      +
      +
      +
    • +
    +
    +
    +
    +

    2.11. Namespace Support#

    +

    Namespaces are enabled by default (see DEFAULT_NAMESPACES_ENABLED) except +in the cfront modes. The command-line options --namespaces and +--no_namespaces can be used to enable or disable the features.

    +

    When doing name lookup in a template instantiation, some names must be found in +the context of the template definition while others may also be found in the +context of the template instantiation. The front end implements two different +instantiation lookup algorithms: the one mandated by the standard (referred to +as “dependent name lookup”), and the one that existed before dependent name +lookup was implemented.

    +

    Dependent name lookup is done in strict mode (unless explicitly disabled by +another command-line option) or when dependent name processing is enabled by +either a configuration flag or command-line option.

    +
    +

    2.11.1. Dependent Name Processing#

    +

    When doing dependent name lookup, the front end implements the instantiation +name lookup rules specified in the standard. This processing requires that +nonclass prototype instantiations be done. This in turn requires that the code +be written using the typename and template keywords as required by the +standard.

    +
    +
    +

    2.11.2. Lookup Using the Referencing Context#

    +

    When not using dependent name lookup, the front end uses a name lookup +algorithm that approximates the two-phase lookup rule of the standard, but does +so in such a way that is more compatible with existing code and existing +compilers.

    +

    When a name is looked up as part of a template instantiation but is not found +in the local context of the instantiation, it is looked up in a synthesized +instantiation context that includes both names from the context of the template +definition and names from the context of the instantiation. Here’s an example:

    +
    namespace N {
    +  int g(int);
    +  int x = 0;
    +  template <class T> struct A {
    +    T f(T t) { return g(t); }
    +    T f() { return x; }
    +  };
    +}
    +namespace M {
    +  int x = 99;
    +  double g(double);
    +  N::A<int> ai;
    +  int i = ai.f(0);      // N::A<int>::f(int) calls N::g(int)
    +  int i2 = ai.f();      // N::A<int>::f() returns 0 (= N::x)
    +  N::A<double> ad;
    +  double d = ad.f(0);   // N::A<double>::f(double) calls M::g(double)
    +  double d2 = ad.f();   // N::A<double>::f() also returns 0 (= N::x)
    +}
    +
    +
    +

    The lookup of names in template instantiations does not conform to the rules in +the standard in the following respects:

    +
      +
    • +
      Although only names from the template definition context are considered for +names that are not functions, the lookup is not limited to those names +visible at the point at which the template was defined.
      +
      +
    • +
    • +
      Functions from the context in which the template was referenced are +considered for all function calls in the template. Functions from the +referencing context should only be visible for “dependent” function calls.
      +
      +
    • +
    +

    For details of the algorithm implemented, see the Symbol Table +chapter (in particular the Instantiation Context Lookup section).

    +
    +
    +

    2.11.3. Argument Dependent Lookup#

    +

    When argument-dependent lookup is enabled, functions made visible using +argument-dependent lookup overload with those made visible by normal lookup. +The standard requires that this overloading occur even when the name found by +normal lookup is a block extern declaration. The front end does this +overloading, but in default mode, argument-dependent lookup is suppressed when +the normal lookup finds a block extern.

    +

    This means a program can have different behavior, depending on whether it is +compiled with or without argument-dependent lookup, even if the program makes +no use of namespaces. For example:

    +
    struct A { };
    +A operator+(A, double);
    +void f() {
    +  A a1;
    +  A operator+(A, int);
    +  a1 + 1.0;     // calls operator+(A, double) with arg-dependent
    +                // lookup enabled but otherwise calls
    +                // operator+(A, int);
    +}
    +
    +
    +
    +
    +

    2.11.4. Runtime Support#

    +

    The headers and runtime provided with the EDG front end support two different +versions (i.e., with and without namespaces) under control of +__EDG_RUNTIME_USES_NAMESPACES, a preprocessing option defined by the front +end.

    +
    +
    +
    +

    2.12. Template Instantiation#

    +

    The C++ language includes the concept of templates. A template is a +description of a class or function that is a model for a family of related +classes or functions. [3] For example, one can write a template for a +Stack class, and then use a stack of integers, a stack of floats, and a +stack of some user-defined type. In the source, these might be written +Stack<int>, Stack<float>, and Stack<X>. From a single source +description of the template for a stack, the compiler can create +instantiations of the template for each of the types required.

    +

    The instantiation of a class template is always done as soon as it is needed in +a compilation. However, the instantiations of template functions, template +variables, member functions of template classes, and static data members of +template classes (hereafter referred to as template entities) are not +necessarily done immediately, for several reasons:

    +
      +
    • +
      One would like to end up with only one copy of each instantiated entity +across all the object files that make up a program. (This of course +applies to entities with external linkage.)
      +
      +
    • +
    • +
      The language allows one to write a specialization of a template entity, +i.e., a specific version to be used in place of a version generated from +the template for a specific data type. (One could, for example, write a +version of Stack<int>, or of just Stack<int>::push, that replaces +the template-generated version; often, such a specialization provides a +more efficient representation for a particular data type.) Since the +compiler cannot know, when compiling a reference to a template entity, if a +specialization for that entity will be provided in another compilation, it +cannot do the instantiation automatically in any source file that +references it. (The modern C++ language requires that a specialization be +declared in every compilation in which it is used, but for compatibility +with existing code and older compilers the EDG front end does not require +that in some modes. See the command-line option +--no_distinct_template_signatures.)
      +
      +
    • +
    • +
      C++ templates can be exported (i.e., declared with the keyword +export). Such templates can be used in a translation unit that does +not contain the definition of the template to instantiate. The +instantiation of such a template must be delayed until the template +definition has been found.
      +
      +
    • +
    • +
      The language also dictates that template functions that are not referenced +should not be compiled, that, in fact, such functions might contain +semantic errors that would prevent them from being compiled. Therefore, a +reference to a template class should not automatically instantiate all the +member functions of that class.
      +
      +
    • +
    +

    (It should be noted that certain template entities are always instantiated when +used, e.g., inline functions.)

    +

    From these requirements, one can see that if the compiler is responsible for +doing all the instantiations automatically, it can only do so on a program-wide +basis. That is, the compiler cannot make decisions about instantiation of +template entities until it has seen all the source files that make up a +complete program.

    +

    The EDG C++ front end provides an instantiation mechanism that does automatic +instantiation at link time. For cases where the programmer wants more explicit +control over instantiation, the front end also provides instantiation modes and +instantiation pragmas, which can be used to exert fine-grained control over the +instantiation process.

    +
    +

    2.12.1. Automatic Instantiation#

    +

    The goal of an automatic instantiation mode is to provide painless +instantiation. The programmer should be able to compile source files to object +code, then link them and run the resulting program, and never have to worry +about how the necessary instantiations get done.

    +

    In practice, this is hard for a compiler to do, and different compilers use +different automatic instantiation schemes with different strengths and +weaknesses:

    +
      +
    • +
      AT&T/USL/Novell/SCO’s cfront product saves information about each file it +compiles in a special directory called ptrepository. It instantiates +nothing during normal compilations. At link time, it looks for entities +that are referenced but not defined, and whose mangled names indicate that +they are template entities. For each such entity, it consults the +ptrepository information to find the file containing the source for the +entity, and it does a compilation of the source to generate an object file +containing object code for that entity. This object code for instantiated +objects is then combined with the “normal” object code in the link step.
      +

      +
      The programmer using cfront must follow a particular coding +convention: all templates must be declared in “.h” files, and for +each such file there must be a corresponding “.C” file containing +the associated definitions. The compiler is never told about the +“.C” files explicitly; one does not, for example, compile them in +the normal way. The link step looks for them when and if it needs +them, and does so by taking the “.h” file name and replacing its +suffix. [4]
      +

      +
      This scheme has the disadvantage that it does a separate compilation for +each instantiated function (or, at best, one compilation for all the member +functions of one class). Even though the function itself is often quite +small, it must be compiled along with the declarations for the types on +which the instantiation is based, and those declarations can easily run +into many thousands of lines. For large systems, these compilations can +take a very long time. The link step tries to be smart about recompiling +instantiations only when necessary, but because it keeps no fine-grained +dependency information, it is often forced to “recompile the world” for a +minor change in a “.h” file. In addition, cfront has no way of +ensuring that preprocessing symbols are set correctly when it does these +instantiation compilations, if preprocessing symbols are set other than on +the command line.
      +
      +
    • +
    • +
      Borland’s C++ compiler instantiates everything referenced in a compilation, +then uses a special linker to remove duplicate definitions of instantiated +functions.
      +

      +
      The programmer using Borland’s compiler must make sure that every +compilation sees all the source code it needs to instantiate all the +template entities referenced in that compilation. That is, one cannot +refer to a template entity in a source file if a definition for that entity +is not included by that source file. In practice, this means that either +all the definition code is put directly in the “.h” files, or that each +“.h” file includes an associated “.C” (actually, “.CPP”) file.
      +

      +
      This scheme is straightforward, and works well for small programs. For +large systems, however, it tends to produce very large object files, +because each object file must contain object code (and symbolic debugging +information) for each template entity it references.
      +
      +
    • +
    +

    EDG’s approach is a little different. It requires that, for each instantiation +of a non-exported template, there is some (normal, top-level, +explicitly-compiled) source file that contains the definition of the template +entity, a reference that causes the instantiation, and the declarations of any +types required for the instantiation. [5] This requirement can be met in +various ways:

    +
      +
    • +
      The Borland convention: each “.h” file that declares a template entity +also contains either the definition of the entity or includes another file +containing the definition.
      +
      +
    • +
    • +
      Implicit inclusion: when the compiler sees a template declaration in a +“.h” file and discovers a need to instantiate that entity, it is +given permission to go off looking for an associated definition file +having the same base name and a different suffix, and it implicitly +includes that file at the end of the compilation. This method allows +most programs written using the cfront convention to be compiled with +EDG’s approach. See Implicit Inclusion.
      +
      +
    • +
    • +
      The ad hoc approach: the programmer makes sure that the files that define +template entities also have the definitions of all the available types, and +adds code or pragmas in those files to request instantiation of the +entities there.
      +
      +
    • +
    +

    Exported templates are also supported by the EDG automatic instantiation +method, but they require additional mechanisms explained further on.

    +

    The EDG automatic instantiation method works as follows for non-exported +templates: [6]

    +
      +
    1. +
      The first time the source files of a program are compiled, no template +entities are instantiated. However, template information files (with, by +default, a “.ti” suffix) are generated and contain information about +things that could have been instantiated in each compilation [7].
      +
      +
    2. +
    3. +
      When the object files are linked together, a program called the +prelinker is run. It examines the object files, looking for +references and definitions of template entities, and for the added +information about entities that could be instantiated.
      +
      +
    4. +
    5. +
      If the prelinker finds a reference to a template entity for which there +is no definition anywhere in the set of object files, it looks for a file +that indicates that it could instantiate that template entity. When it +finds such a file, it assigns the instantiation to it. The set of +instantiations assigned to a given file is recorded in an associated +instantiation request file (with, by default, a “.ii” suffix).
      +
      +
    6. +
    7. +
      The prelinker then executes the compiler again to recompile each file for +which the instantiation request file was changed. The original +compilation command-line options (saved in the template information file) +are used for the recompilation.
      +
      +
    8. +
    9. +
      When the compiler compiles a file, it reads the instantiation request +file for that file and obeys the requests therein. It produces a new +object file containing the requested template entities (and all the other +things that were already in the object file). The compiler also receives +a definition list file, which lists all the instantiations for which +definitions already exist in the set of object files. If during the +compilation the compiler has the opportunity to instantiate a referenced +entity that is not on that list, it goes ahead and does the instantiation. +It passes back to the prelinker (in the definition list file) a list of +the instantiations that it has “adopted” in this way, so the prelinker can +assign them to the file. This adoption process allows rapid instantiation +and assignment of instantiations referenced from new instantiations, and +reduces the need to recompile a given file more than once during the +prelinking process.
      +
      +
    10. +
    11. +
      The prelinker repeats steps 3-5 until there are no more instantiations to +be adjusted.
      +
      +
    12. +
    13. +
      The object files are linked together.
      +
      +
    14. +
    +

    Once the program has been linked correctly, the instantiation request files +contain a complete set of instantiation assignments. From then on, whenever +source files are recompiled, the compiler will consult the instantiation +request files and do the indicated instantiations as it does the normal +compilations. That means that, except in cases where the set of required +instantiations changes, the prelink step from then on will find that all the +necessary instantiations are present in the object files and no instantiation +assignment adjustments need be done. That’s true even if the entire program is +recompiled.

    +

    If the programmer provides a specialization of a template entity somewhere in +the program, the specialization will be seen as a definition by the prelinker. +Since that definition satisfies whatever references there might be to that +entity, the prelinker will see no need to request an instantiation of the +entity. If the programmer adds a specialization to a program that has +previously been compiled, the prelinker will notice that too and remove the +assignment of the instantiation from the proper instantiation request file.

    +

    The instantiation request files should not, in general, require any manual +intervention. One exception: if a definition is changed in such a way that +some instantiation no longer compiles (it gets errors), and at the same time a +specialization is added in another file, and the first file is being recompiled +before the specialization file and is getting errors, the instantiation request +file for the file getting the errors must be deleted manually to allow the +prelinker to regenerate it.

    +

    If the prelinker changes an instantiation assignment, it will issue a message +like

    +
    C++ prelinker: A<int>::f() assigned to file test.o
    +C++ prelinker: executing: /edg/bin/eccp -c test.c
    +
    +
    +

    The automatic instantiation scheme can coexist with partial explicit control of +instantiation by the programmer through the use of pragmas or command-line +specification of the instantiation mode. See the following sections.

    +

    Instantiations are normally generated as part of the object file of the +translation unit in which the instantiations are performed. But when “one +instantiation per object” mode is specified, each instantiation is placed in +its own object file. One-instantiation-per-object mode is useful when +generating libraries that need to include copies of the instances referenced +from the library. If each instance is not placed in its own object file, it +may be impossible to link the library with another library containing some of +the same instances. Without this feature it is necessary to create each +individual instantiation object file using the manual instantiation mechanism.

    +

    The automatic instantiation mode can be configured out altogether by setting +the configuration flag AUTOMATIC_TEMPLATE_INSTANTIATION to FALSE. It can +be turned on or off using the --auto_instantiation and +--no_auto_instantiation command-line options. If automatic instantiation +is turned off, the template information file is not generated.

    +
    +
    +

    2.12.2. Instantiation Modes#

    +

    Normally, when a file is compiled, no template entities are instantiated +(except those assigned to the file by automatic instantiation). The overall +instantiation mode can, however, be changed by a command line option:

    +
    + + + + + + + + + + + + + + + +
    +
    -tnone
    +
    +
    +
    Do not automatically create instantiations of any template entities. +This is the default. It is also the usually appropriate mode when +automatic instantiation is done.
    +
    +
    +
    -tused
    +
    +
    +
    Instantiate those template entities that were used in the compilation. +This will include all static data members for which there are template +definitions.
    +
    +
    +
    -tall
    +
    +
    +
    Instantiate all template entities declared or referenced in the +compilation unit. For each fully instantiated template class, all of +its member functions and static data members will be instantiated +whether or not they were used. Nonmember template functions will be +instantiated even if the only reference was a declaration.
    +
    +
    +
    -tlocal
    +
    +
    +
    Similar to -tused except that the functions are given internal +linkage. This is intended to provide a very simple mechanism for +those getting started with templates. The compiler will instantiate +the functions that are used in each compilation unit as local +functions, and the program will link and run correctly (barring +problems due to multiple copies of local static variables.) However, +one may end up with many copies of the instantiated functions, so this +is not suitable for production use. -tlocal can not be used in +conjunction with automatic template instantiation. If automatic +instantiation is enabled by default, it will be disabled by the +-tlocal option. If automatic instantiation is not enabled by +default, use of -tlocal and -T is an error.
    +
    +
    +
    +

    In the case where the eccp script is given a single file to compile and +link, e.g.,

    +
    eccp t.c
    +
    +
    +

    the compiler knows that all instantiations will have to be done in the single +source file. Therefore, it uses the -tused mode and suppresses automatic +instantiation.

    +
    +
    +

    2.12.3. Instantiation #pragma Directives#

    +

    Instantiation pragmas can be used to control the instantiation of specific +template entities or sets of template entities. There are three instantiation +pragmas:

    +
      +
    • +
      The instantiate pragma causes a specified entity to be instantiated.
      +
      +
    • +
    • +
      The do_not_instantiate pragma suppresses the instantiation of a +specified entity. It is typically used to suppress the instantiation of an +entity for which a specific definition will be supplied.
      +
      +
    • +
    • +
      The can_instantiate pragma indicates that a specified entity can be +instantiated in the current compilation, but need not be; it is used in +conjunction with automatic instantiation, to indicate potential sites for +instantiation if the template entity turns out to be required. [8]
      +
      +
    • +
    +

    The argument to the instantiation pragma may be:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    a template class name
    +
    +
    +
    A<int>
    +
    +
    +
    a template class declaration
    +
    +
    +
    class A<int>
    +
    +
    +
    a member function name
    +
    +
    +
    A<int>::f
    +
    +
    +
    a static data member name
    +
    +
    +
    A<int>::i
    +
    +
    +
    a static data member decl.
    +
    +
    +
    int A<int>::i
    +
    +
    +
    a member function declaration
    +
    +
    +
    void A<int>::f(int, char)
    +
    +
    +
    a template function declaration
    +
    +
    +
    char* f(int, float)
    +
    +
    +
    a template variable name
    +
    +
    +
    x<int>
    +
    +
    +
    +

    A pragma in which the argument is a template class name (e.g., A<int> or +class A<int>) is equivalent to repeating the pragma for each member +function and static data member declared in the class. When instantiating an +entire class a given member function or static data member may be excluded +using the do_not_instantiate pragma. For example,

    +
    #pragma instantiate A<int>
    +#pragma do_not_instantiate A<int>::f
    +
    +
    +

    The template definition of a template entity must be present in the compilation +for an instantiation to occur. If an instantiation is explicitly requested by +use of the instantiate pragma and no template definition is available or a +specific definition is provided, an error is issued.

    +
    template <class T> void f1(T);  // No body provided
    +template <class T> void g1(T);  // No body provided
    +void f1(int) {}  // Specific definition
    +void main(){
    +  int i;
    +  double  d;
    +  f1(i);
    +  f1(d);
    +  g1(i);
    +  g1(d);
    +}
    +#pragma instantiate void f1(int)  // error - specific definition
    +#pragma instantiate void g1(int)  // error - no body provided
    +
    +
    +

    f1(double) and g1(double) will not be instantiated (because no bodies +were supplied) but no errors will be produced during the compilation (if no +bodies are supplied at link time, a linker error will be produced).

    +

    A member function name (e.g., A<int>::f) can only be used as a pragma +argument if it refers to a single user defined member function (i.e., not an +overloaded function). Compiler-generated functions are not considered, so a +name may refer to a user defined constructor even if a compiler-generated copy +constructor of the same name exists. Overloaded member functions can be +instantiated by providing the complete member function declaration, as in

    +
    #pragma instantiate char* A<int>::f(int, char*)
    +
    +
    +

    The argument to an instantiation pragma may not be a compiler-generated +function, an inline function, or a pure virtual function.

    +
    +
    +

    2.12.4. Implicit Inclusion#

    +

    When implicit inclusion is enabled, the front end is given permission to assume +that if it needs a definition to instantiate a template entity declared in a +“.h” file it can implicitly include the corresponding “.C” file to get +the source code for the definition. For example, if a template entity +ABC::f is declared in file xyz.h, and an instantiation of ABC::f is +required in a compilation but no definition of ABC::f appears in the source +code processed by the compilation, the compiler will look to see if a file +xyz.C exists, and if so it will process it as if it were included at the +end of the main source file.

    +

    To find the template definition file for a given template entity the front end +needs to know the path name specified in the original include of the file in +which the template was declared and whether the file was included using the +system include syntax (e.g., #include <file.h>). This information is not +available for preprocessed source containing #line directives. +Consequently, the front end will not attempt implicit inclusion for source code +containing #line directives.

    +

    The file to be implicitly included is found by replacing the file suffix with +each of the suffixes specified in the instantiation file suffix list. The +normal include search path mechanism is then used to look for the file to be +implicitly included.

    +

    DEFAULT_INSTANTIATION_FILE_SUFFIX_LIST defines the set of definition-file +suffixes tried. By default, the list is “.c”, “.C”, “.cpp”, +“.CPP”, “.cxx”, “.CXX”, and “.cc”.

    +

    Implicit inclusion works well alongside automatic instantiation, but the two +are independent. They can be enabled or disabled independently, and implicit +inclusion is still useful when automatic instantiation is not done.

    +

    The implicit inclusion mode can be configured out altogether by setting the +configuration flag INSTANTIATION_BY_IMPLICIT_INCLUSION to FALSE. It can be +turned on or off using the --implicit_include and --no_implicit_include +command-line options.

    +

    Implicit inclusions are only performed during the normal compilation of a file, +(i.e., not when doing only preprocessing). A common means of investigating +certain kinds of problems is to produce a preprocessed source file that can be +inspected. When using implicit inclusion it is sometimes desirable for the +preprocessed source file to include any implicitly included files. This may be +done using the --no_preproc_only command line option. This causes the +preprocessed output to be generated as part of a normal compilation. When +implicit inclusion is being used, the implicitly included files will appear as +part of the preprocessed output in the precise location at which they were +included in the compilation.

    +
    +
    +

    2.12.5. Exported Templates#

    +

    Exported templates are templates declared with the keyword export. +Exporting a class template is equivalent to exporting each of its static data +members and each of its non-inline member functions. An exported template is +special because its definition does not need to be present in a translation +unit that uses that template. In other words, the definition of an exported +(non-class) template does not need to be explicitly or implicitly included in a +translation unit that instantiates that template. For example, the following +is a valid C++ program consisting of two separate translation units:

    +
    // File 1:
    +#include <stdio.h>
    +static void trace() { printf("File 1\n"); }
    +
    +export template<class T> T const& min(T const&, T const&);
    +int main() {
    +  trace();
    +  return min(2, 3);
    +}
    +
    +
    +
    // File 2:
    +#include <stdio.h>
    +static void trace() { printf("File 2\n"); }
    +
    +export template<class T> T const& min(T const &a, T const &b) {
    +  trace();
    +  return a<b? a: b;
    +}
    +
    +
    +

    Note that these two files are separate translation units: one is not included +in the other. That allows the two functions trace() to coexist (with +internal linkage).

    +

    Support for exported templates can be enabled using the --export +command-line option (it is enabled by default in strict ANSI mode; -A or +--strict). For example, the program above could be built as follows using +the eccp script:

    +
    eccp --export -c file_1.c
    +eccp --export -c file_2.c
    +eccp file_1.o file_2.o
    +
    +
    +
    +

    2.12.5.1. Finding the exported template definition#

    +

    The automatic instantiation of exported templates is somewhat similar (from a +user’s perspective) to that of regular (included) templates. However, an +instantiation of an exported template involves at least two translation units: +one which requires the instantiation, and one which contains the template +definition.

    +

    When a file containing definitions of exported templates is compiled, a file +with a “.et” suffix is created and some extra information is included in +the associated “.ti” file. The “.et” files are used later by the front +end to find the translation unit that defines a given exported template.

    +

    When a file that potentially makes use of exported templates is compiled, the +compiler must be told where to look for “.et” files for exported templates +used by a given translation unit. By default, the compiler looks in the +current directory. Other directories may be specified with the +--template_directory option. Strictly speaking, the “.et” files are +only really needed when it comes time to generate an instantiation. This means +that code using exported templates can be compiled without having the +definitions of those templates available. Those definitions must be available +by the time prelinking is done (or when explicit instantiation is done).

    +

    The “.et” files only inform the front end about the location of exported +template definitions; they do not actually contain those definitions. The +sources containing the exported template definitions must therefore be made +available at the time of instantiation (usually, when prelinking is done). In +particular, the export facility is not a mechanism for avoiding the +publication of template definitions in source form.

    +
    +
    +

    2.12.5.2. Secondary translation units#

    +

    An instantiation of an exported template can be triggered by the prelinker, by +an explicit instantiation directive, or by the -tused command-line option. +In each case, the translation unit that contains the initial point of +instantiation will be processed as the primary translation unit. Based on +information it finds in the “.et” files, the front end will then load and +parse the translation unit containing the definition of the template to +instantiate. This is a secondary translation unit. The simultaneous +processing of the primary and secondary translation units enables the front end +to create instantiations of the exported templates (which can include entities +from both translation units). This process may reveal the need for additional +instantiations of exported templates, which in turn can cause additional +secondary translation units to be loaded [9].

    +

    When secondary translation units are processed, the declarations they contain +are checked for consistency. This process may report errors that would +otherwise not be caught. Many these errors are so-called “ODR violations” (ODR +stands for “one-definition rule”). For example:

    +
    // File 1:
    +struct X {
    +  int x;
    +};
    +int main() {
    +  return min(2, 3);
    +}
    +
    +// File 2:
    +struct X {
    +  unsigned x;  // Error: X::x declared differently in File 1
    +};
    +export template<class T> T const& min(T const &a, T const &b) {
    +  return a<b? a: b;
    +}
    +
    +
    +

    If there are no errors, the instantiations are generated in the output +associated with the primary translation unit (or in separate associated files +in one-instantiation-per-object mode). This may also require that entities +with internal linkage in secondary translation units be “externalized” so they +can be accessed from the instantiations in the primary translation unit.

    +
    +
    +

    2.12.5.3. Libraries with exported templates#

    +

    Typically a (non-export) library consists of an include directory and a lib +directory. The include directory contains the header files required by users +of the library and the lib directory contains the object code libraries that +client programs must use when linking programs.

    +

    With exported templates, users of the library must also have access to the +source code of the exported templates and the information contained in the +associated “.et” files. This information should be placed in a directory +that is distributed along with the include and lib directories: This is the +export directory. It must be specified using the --template_directory +option when compiling client programs.

    +

    The recommended procedure to build the export directory is as follows:

    +
      +
    1. +
      For each “.et” file in the original source directory, copy the +associated source file to the export directory.
      +
      +
    2. +
    3. +
      Concatenate all of the “.et” files into a single “.et” file +(e.g., mylib.et) in the export directory. The individual “.et” +files could be copied to the export directory, but having all of the +“.et” information in one file will make use of the library more +efficient.
      +
      +
    4. +
    5. +
      Create an export_info file in the export directory. The +export_info file specifies the include search paths to be used when +recompiling files in the export directory. If no export_info file is +provided, the include search path used when compiling the client program +that uses the library will also be used to recompile the library exported +template files.
      +
      +
    6. +
    +

    The export_info file consists of a series of lines of the form

    +
    include=x
    +
    +
    +

    or

    +
    sys_include=x
    +
    +
    +

    where x is a path name to be placed on the include search path. The +directories are searched in the order in which they are encountered in the +export_info file. The file can also contain comments – which begin with a +“#” – and blank lines. Spaces are ignored but tabs are not currently +permitted. For example:

    +
    # The include directories to be used for the xyz library
    +include = /disk1/xyz/include
    +sys_include = /disk2/abc/include
    +include=/disk3/jkl/include
    +
    +
    +

    The include search path specified for a client program is ignored by the front +end when it processes the source in the export library, except when no +export_info file is provided. Command-line macro definitions specified for +a client program are also ignored by the front end when processing a source +file from the export libary; the command-line macros specified when the +corresponding “.et” file was produced do apply. All other compilation +options (other than the include search path and command-line macro definitions) +used when recompiling the exported templates will be used to compile the client +program.

    +

    When a library is installed on a new system, it is likely that the +export_info file will need to be adapted to reflect the location of the +required headers on that system.

    +
    +
    +
    +
    +

    2.13. Extern Inline Functions#

    +

    Depending on the way in which the front end is configured, out-of-line copies +of extern inline functions are either implemented using static functions, or +are instantiated using a mechanism like the template instantiation mechanism. +Note that out-of-line copies of inline functions are only required in cases +where the function cannot be inlined, or when the address of the function is +taken (whether explicitly by the user, by implicitly generated functions, or by +compiler-generated data structures such as virtual function tables or exception +handling tables).

    +

    When static functions are used, local static variables of the functions are +promoted to global variables with specially encoded names, so that even though +there may be multiple copies of the code, there is only one copy of such global +variables. This mechanism does not strictly conform to the standard because +the address of an extern inline function is not constant across translation +units.

    +

    When the instantiation mechanism is used, the address of an extern inline +function is constant across translation units, but at the cost of requiring the +use of one of the template instantiation mechanisms, even for programs that +don’t use templates. Definitions of extern inline functions can be provided +either through use of the automatic instantiation mechanism or by use of the +-tused or -tall instantiation modes. There is no mechanism to manually +control the definition of extern inline function bodies.

    +
    +
    +

    2.14. Predefined Macros#

    +

    The front end defines a number of preprocessing macros. Many of them are only +defined under certain circumstances. This section describes the macros that +are provided and the circumstances under which they are defined. In addition, +a table of predefined macro definitions may be processed when the compiler is +invoked. This may be used for any kind of predefined macro, but in particular +is used to define the macros that gcc and g++ define when using gcc and g++ +modes. The format of the file and other information is described in +Predefined Macro Definition File.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    __STDC__
    +
    +
    +
    Defined in ANSI C mode and in C++ mode. In C++ mode the value may be +redefined. Not defined in Microsoft compatibility mode.
    +
    +
    +
    __DATE__
    +
    +
    +
    Defined in all modes to the date of the compilation in the form “Mmm +dd yyyy”.
    +
    +
    +
    __TIME__
    +
    +
    +
    Defined in all modes to the time of the compilation in the form +“hh:mm:ss”.
    +
    +
    +
    __FILE__
    +
    +
    +
    Defined in all modes to the name of the current source file.
    +
    +
    +
    __LINE__
    +
    +
    +
    Defined in all modes to the current source line number within the +current source file.
    +
    +
    +
    __cplusplus
    +
    +
    +
    Defined in C++ modes. In general, the value is 201103L if C++11 +features are enabled and either 1 or 199711L otherwise, but +which of those three values is chosen depends on the emulation +(compiler and version).
    +
    +
    +
    c_plusplus
    +
    +
    +
    Defined in cfront mode.
    +
    +
    +
    __cplusplus_cli
    +
    +
    +
    Defined in C++/CLI mode with the value 200406l.
    +
    +
    +
    __STDC_VERSION__
    +
    +
    +
    Defined in ANSI C mode with the value 199409L. The name of this +macro, and its value, are specified in Normative Addendum 1 of the ISO +C90 Standard. In C99 mode, defined with the value 199901L.
    +
    +
    +
    __STDC_HOSTED__
    +
    +
    +
    Defined in C99 and C++11 modes with the value specified by the +STDC_HOSTED configuration macro.
    +
    +
    +
    __STDC_IEC_559__
    +
    +
    +
    Defined in C99 mode if the configuration macro STDC_IEC_559 is +TRUE.
    +
    +
    +
    __STDC_IEC_559_COMPLEX__
    +

    +
    +
    +
    Defined in C99 mode if the configuration macro
    +
    +
    STDC_IEC_559_COMPLEX is TRUE.
    +
    +
    +
    +
    __STDC_ISO_10646__
    +
    +
    +
    Defined in C99 mode if the configuration macro STDC_ISO_10646 is +TRUE. The value is specified by the STDC_ISO_10646_VALUE macro.
    +
    +
    +
    __STDC_MB_MIGHT_NEQ_WC__
    +
    +
    +
    Defined in C99 mode if the configuration macro +STDC_MB_MIGHT_NEQ_WC is TRUE.
    +
    +
    +
    __SIGNED_CHARS__
    +
    +
    +
    Defined when plain char is signed. This is used in the +<limits.h> header file to get the proper definitions of +CHAR_MAX and CHAR_MIN.
    +
    +
    +
    __FUNCTION__
    +
    +
    +
    Defined in all modes to the name of the current function. An error is +issued if it is used outside of a function. An EDG, GNU, and +Microsoft extension. (Depending on the current mode, this identifier +behaves as a variable or as a string literal; never as a preprocessor +macro.)
    +
    +
    +
    __func__
    +
    +
    +
    Same as __FUNCTION__ in C99, C++11, and GNU modes. (This +identifier behaves as a variable; not as a preprocessor macro.)
    +
    +
    +
    __PRETTY_FUNCTION__
    +
    +
    +
    Defined in all modes to the name of the current function. This +includes the return type and parameter types of the function. An +error is issued if it is used outside of a function. An EDG and GNU +extension. (Depending on the current mode, this identifier behaves as +a variable or as a string literal; never as a preprocessor macro.)
    +
    +
    +
    __FUNCSIG__
    +
    +
    +
    Same as __PRETTY_FUNCTION__ in Microsoft mode. (This identifier +behaves as a string literal; not as a preprocessor macro.)
    +
    +
    +
    __FUNCDNAME__
    +
    +
    +
    Defined to the “decorated” name of the current function (i.e., its +mangled name) in Microsoft mode. (This identifier behaves as a string +literal; not as a preprocessor macro.)
    +
    +
    +
    __BASE_FILE__
    +
    +
    +
    Defined in all modes. Similar to __FILE__ but indicates the +primary source file rather than the current one (i.e., when the +current file is an included file).
    +
    +
    +
    _WCHAR_T
    +
    +
    +
    Defined in C++ mode when wchar_t is a keyword. The name of this +macro and whether it is predefined are specified by configuration +options. _WCHAR_T is the default.
    +
    +
    +
    _WCHAR_T_DEFINED
    +
    +
    +
    Defined in Microsoft C++ mode when wchar_t is a keyword.
    +
    +
    +
    _NATIVE_WCHAR_T_DEFINED
    +

    +
    +
    +
    Defined in Microsoft C++ mode when wchar_t is a keyword (Microsoft +version 1300 and above).
    +
    +
    +
    _BOOL
    +
    +
    +
    Defined in C++ mode when bool is a keyword. The name of this +macro and whether it is predefined are specified by configuration +options. _BOOL is the default.
    +
    +
    +
    __BOOL_DEFINED
    +
    +
    +
    Defined in Microsoft C++ mode when bool is a keyword.
    +
    +
    +
    __ARRAY_OPERATORS
    +
    +
    +
    Defined in C++ mode when array new and delete are enabled. The name +of this macro and whether it is predefined are specified by +configuration options. __ARRAY_OPERATORS is the default.
    +
    +
    +
    __EXCEPTIONS
    +
    +
    +
    Defined in C++ mode when exception handling is enabled. The name of +this macro and whether it is predefined are specified by configuration +options. __EXCEPTIONS is the default.
    +
    +
    +
    __RTTI
    +
    +
    +
    Defined in C++ mode when RTTI is enabled. The name of this macro and +whether it is predefined are specified by configuration options. +__RTTI is the default.
    +
    +
    +
    __PLACEMENT_DELETE
    +
    +
    +
    Defined in C++ mode when placement delete is enabled. The name of +this macro and whether it is predefined are specified by configuration +options. __PLACEMENT_DELETE is the default. Placement delete is +enabled when ABI_CHANGES_FOR_PLACEMENT_DELETE is TRUE and +exception handling is enabled.
    +
    +
    +
    __NO_LONG_LONG
    +
    +
    +
    Defined in all modes when the long long type is not supported. +The name of this macro and whether it is predefined are specified by +configuration options. __NO_LONG_LONG is the default.
    +
    +
    +
    __EDG_RUNTIME_USES_NAMESPACES
    +

    +
    +
    +
    Defined in C++ mode when the configuration flag +RUNTIME_USES_NAMESPACES is TRUE. The name of this macro and +whether it is predefined are specified by configuration options. +__EDG_RUNTIME_USES_NAMESPACES is the default.
    +
    +
    +
    __EDG_IMPLICIT_USING_STD
    +

    +
    +
    +
    Defined in C++ mode when the configuration flag +RUNTIME_USES_NAMESPACES is TRUE and when implicit_using_std +has been set to TRUE, either by a command line option or by the +configuration flag DEFAULT_IMPLICIT_USING_STD, indicating that the +standard header files should implicitly do a using-directive on the +std namespace. The name of this macro and whether it is +predefined are specified by configuration options. +__EDG_IMPLICIT_USING_STD is the default.
    +
    +
    +
    __EDG_TYPE_TRAITS_ENABLED
    +

    +
    +
    +
    Defined in non-Microsoft modes when type traits pseudo-functions (to +ease the implementation of ISO/IEC TR 19768; e.g., “__is_union”) +are enabled. The name of this predefined macro is specified by a +configuration option. __EDG_TYPE_TRAITS_ENABLED is the default.
    +
    +
    +
    __EDG__
    +
    +
    +
    Always defined.
    +
    +
    +
    __EDG_VERSION__
    +
    +
    +
    Defined to an integral value that represents the version number of the +front end. For example. version 2.30 is represented as 230.
    +
    +
    +
    __EDG_IA64_ABI
    +
    +
    +
    Defined as 1 when using a front end configured to use the IA-64 ABI.
    +
    +
    +
    __embedded_cplusplus
    +
    +
    +
    Defined as 1 in Embedded C++ mode.
    +
    +
    +
    _CHAR_UNSIGNED
    +
    +
    +
    Defined in Microsoft mode when char is unsigned.
    +
    +
    +
    _MSC_VER
    +
    +
    +
    Defined in Microsoft mode to the version number of the Microsoft +compiler that is to be emulated. For example, 1100 is the value that +corresponds to Visual C++ version 5.0.
    +
    +
    +
    _MSC_BUILD
    +
    +
    +
    Defined in Microsoft mode to the value of microsoft_build_number.
    +
    +
    +
    _M_CEE
    +
    +
    +
    Defined in Microsoft mode when C++/CLI mode is in effect (e.g., when +--cppcli is specified).
    +
    +
    +
    _MSC_EXTENSIONS
    +
    +
    +
    Defined in Microsoft mode.
    +
    +
    +
    _WIN32
    +
    +
    +
    Defined (unconditionally) in Microsoft mode.
    +
    +
    +
    _WIN64
    +
    +
    +
    Defined in Microsoft mode when targ_supports_x86_64 is TRUE.
    +
    +
    +
    _INTEGRAL_MAX_BITS
    +
    +
    +
    Defined in Microsoft mode to the number of bits in the largest +integral type that is supported. The value depends on the way in +which the front end was configured.
    +
    +
    +
    _CPPRTTI
    +
    +
    +
    Defined in Microsoft mode C++ when RTTI is enabled.
    +
    +
    +
    __GNUC__
    +
    +
    +
    Defined in GNU mode to the value specified by the GCC_VERSION +configuration macro.
    +
    +
    +
    __GNUC_MINOR__
    +
    +
    +
    Defined in GNU mode to the value specified by the +GCC_MINOR_VERSION configuration macro.
    +
    +
    +
    __VERSION__
    +
    +
    +
    Defined in GNU mode to the value specified by the +GCC_VERSION_STRING configuration macro.
    +
    +
    +
    __PRAGMA_REDEFINE_EXTNAME
    +

    +
    +
    +
    Defined if all modes when the configuration flag +REDEFINE_EXTNAME_PRAGMA_ENABLED is TRUE.
    +
    +
    +
    __upc__
    +
    +
    +
    Defined when UPC extensions are enabled.
    +
    +
    +
    __COUNTER__
    +
    +
    +
    Defined in Microsoft mode. Returns an integer value, starting with +zero and incremented each time the macro is used.
    +
    +
    +
    __TIMESTAMP__
    +
    +
    +
    Defined in Microsoft mode. Returns a string literal containing the +modification date and time of the source file in which it is +specified.
    +
    +
    +
    __EDG_IA64_ABI
    +
    +
    +
    Defined in C++ mode when using the IA-64 ABI. The name of this +predefined macro is specified by a configuration option. +__EDG_IA64_ABI is the default.
    +
    +
    +
    __EDG_IA64_ABI_USE_INT_STATIC_INIT_GUARD
    +
    +
    +
    Defined in C++ mode when using the IA-64 ABI when guard variables are +int-sized (i.e., in the ARM EABI). The name of this predefined +macro is specified by a configuration option. +__EDG_IA64_ABI_USE_INT_STATIC_INIT_GUARD is the default.
    +
    +
    +
    __EDG_IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS
    +
    +
    +
    Defined in C++ mode when using the IA-64 ABI when constructors and +destructors return the this pointer (i.e., in the ARM EABI). The +name of this predefined macro is specified by a configuration option. +__EDG_IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS is the default.
    +
    +
    +
    __EDG_SIZE_TYPE__
    +
    +
    +
    Defined to be the type of size_t.
    +
    __EDG_PTRDIFF_TYPE__
    +
    +
    Defined to be the type of ptrdiff_t.
    +
    +
    +
    +
    __CHAR16_T_AND_CHAR32_T
    +

    +
    +
    +
    Defined in C++ mode when char16_t and char32_t are keywords. +The name of this macro and whether it is predefined are specified by +configuration options. __CHAR16_T_AND_CHAR32_T is the default.
    +
    +
    +
    __CHAR16_TYPE__
    +
    +
    +
    Defined in GNU mode as the underlying type for char16_t (GNU +version 40400 and above).
    +
    +
    +
    __CHAR32_TYPE__
    +
    +
    +
    Defined in GNU mode as the underlying type for char32_t (GNU +version 40400 and above).
    +
    +
    +
    __VARIADIC_TEMPLATES
    +

    +
    +
    +
    Defined in C++ mode when variadic templates are supported. The name +of this macro and whether it is predefined are specified by +configuration options. __VARIADIC_TEMPLATES is the default.
    +
    +
    +
    __STDCPP_THREADS__
    +
    +
    +
    Defined in C++ mode when the implementation supports multiple threads +(i.e., when IMPLEMENTATION_SUPPORTS_MULTIPLE_THREADS is TRUE +and the global variable std_thread_local_storage_specifier_enabled +is TRUE).
    +
    +
    +
    +
    +
    +

    2.15. Pragmas#

    +

    #pragma directives are used within the source program to request certain +kinds of special processing. The #pragma directive is part of the standard +C and C++ languages, but the meaning of any pragma is implementation-defined.

    +
    +

    2.15.1. Instantiation Pragmas#

    +

    The following are described in detail in the template instantiation section of +this chapter:

    +
    #pragma instantiate
    +#pragma do_not_instantiate
    +#pragma can_instantiate
    +
    +
    +
    +
    +

    2.15.2. Precompiled Header Pragmas#

    +

    The following are described in the section on precompiled header processing:

    +
    #pragma hdrstop
    +#pragma no_pch
    +
    +
    +
    +
    +

    2.15.3. Once Pragma#

    +

    The front end also recognizes #pragma once, which, when placed at the +beginning of a header file, indicates that the file is written in such a way +that including it several times has the same effect as including it once. +Thus, if the front end sees #pragma once at the start of a header file, it +will skip over it if the file is #included again.

    +

    A typical idiom is to place an #ifndef guard around the body of the file, +with a #define of the guard variable after the #ifndef:

    +
    +
    +
    #pragma once           // optional
    +
    #ifndef FILE_H
    +
    #define FILE_H
    +
    ... body of the header file ...
    +
    #endif
    +
    +
    +

    The #pragma once is marked as optional in this example, because the front +end recognizes the #ifndef idiom and does the optimization even in its +absence. #pragma once is accepted for compatibility with other compilers +and to allow the programmer to use other guard-code idioms.

    +
    +
    +

    2.15.4. Diagnostic Pragmas#

    +

    The following pragmas may be used to control the error severity used when a +given diagnostic message is issued.

    +
    #pragma diag_suppress
    +#pragma diag_remark
    +#pragma diag_warning
    +#pragma diag_error
    +#pragma diag_default
    +#pragma diag_once
    +
    +
    +

    These are similar in function to the equivalent command-line options. Uses of +these pragmas have the following form:

    +
    +
    +
    #pragma diag_xxx [=] error_number_or_tag, error_number_or_tag …
    +
    +
    +

    The diagnostic affected is specified using either an error number or an error +tag name. The “=” is optional. Any diagnostic may be overridden to be an +error, but only diagnostics with a severity of discretionary error or below may +have their severity reduced to a warning or below, or be suppressed. The +diag_default pragma is used to return the severity of a diagnostic to the +one that was in effect before any pragmas were issued (i.e., the normal +severity of the message as modified by any command-line options). The +following example suppresses the “pointless friend declaration” warning on the +declaration of class A:

    +
    #pragma diag_suppress 522
    +class A { friend class A; };
    +#pragma diag_default 522
    +class B { friend class B; };
    +
    +
    +

    The diag_once pragma causes the specified diagnostics to be issued only +once as a warning or remark.

    +
    +
    +

    2.15.5. Pack Pragma#

    +

    When USER_CONTROL_OF_STRUCT_PACKING is TRUE, #pragma pack is +recognized. It is used to specify the maximum alignment allowed for nonstatic +data members of structs and classes, even if that alignment is less than the +alignment dictated by the member’s type.

    +

    The basic syntax is:

    +
    +
    +
    #pragma pack(n)
    +
    #pragma pack()
    +
    +
    +

    where argument n, a power-of-2 value within the range defined by +TARG_MINIMUM_PACK_ALIGNMENT and TARG_MAXIMUM_PACK_ALIGNMENT, is the new +packing alignment that is to go into effect for subsequent declarations, until +another #pragma pack is seen. The second form cancels the effect of a +preceding #pragma pack(n) and either restores the default packing +alignment specified by the --pack_alignment command-line option or, if the +option was not used, disables the packing of structs and classes.

    +

    An enhanced syntax (intended to be compatible with the similar facility offered +by Microsoft C/C++ compilers) is also supported in which keywords push and +pop can be used to manage a stack of packing alignment values – for +instance:

    +
    #pragma pack (push, xxx, 16)
    +  /* Packing alignment set to 16. */
    +#include "xxx.h"
    +#pragma pack (pop, xxx)
    +  /* Packing alignment reset to what it was prior to the
    +     above #pragma pack directive, even if the included header
    +     left some unrelated pragma pack entries on the stack. */
    +
    +
    +

    which has the effect saving the current packing alignment value and +establishing a new one, processing the include file (which may leave the +packing alignment with an unknown setting), and restoring the original value. +Finally, the form

    +
    #pragma pack(show)
    +
    +
    +

    causes the front end to emit a warning describing the current setting of the +maximum member alignment (if any).

    +

    In C++ a #pragma pack directive has “local” effect when it appears inside a +function template, an instantiation of a class template, or the body of a +member function or friend function that is defined within a class definition. +When such a context is entered, the current pack alignment state is saved, so +that it can be restored when the context is exited. For example,

    +
    template <class T> class A {
    +  :
    +#pragma pack(1)
    +  :
    +};
    +#pragma pack(4)
    +main() {
    +  A<int> a;                     // #pragma pack(1) is local to A<int>
    +  struct S { char c; int i; };  // sizeof(S) == 8, not 5
    +}
    +
    +
    +

    Moreover, within an instantiation of a class or function template, the default +pack alignment is that which is in effect at the point of the template’s +definition, not at the point of its instantiation. Here is an example:

    +
    #pragma pack(1)
    +template <class T> int f(T) {
    +  struct S { char c; int i; };   // default pack alignment is 1 for each
    +  return sizeof(S);              //   instance of f<T>
    +}
    +#pragma pack(4)
    +main() {
    +  int i = f(0);                  // i = 5, not 8
    +}
    +
    +
    +

    These rules apply to inline-defined member functions, too, because their bodies +are also scanned “out of order” relative to the textual order of the source +program (i.e., not till all the class members have been declared).

    +
    #pragma pack(4)
    +struct A {
    +  int f() {
    +#pragma pack(1)                   // #pragma pack(1) is local to A::f
    +    struct S { char c; int i; };  // sizeof(S) is 5
    +  }
    +  int g() {
    +    struct S { char c; int i; };  // sizeof(S) is 8
    +  }
    +#pragma pack(1)
    +  int h() {
    +    struct S { char c; int i; };  // sizeof(S) is 5
    +  }
    +};
    +
    +
    +

    When IDENT_DIRECTIVE_AND_PRAGMA is TRUE, #pragma ident is recognized, +as is #ident:

    +
    #pragma ident "string"
    +#ident "string"
    +
    +
    +

    Both are implemented by recording the string in a pragma entry and passing it +to the back end.

    +

    When PRAGMA_WEAK_ALLOWED is TRUE, #pragma weak is recognized. Its form +is:

    +
    +
    +
    #pragma weak name1 [ = name2 ]
    +
    +
    +

    where name1 is the name to be given “weak binding” and is a synonym for +name2 if the latter is specified. The entire argument string is recorded +in the pragma entry and passed to the back end.

    +
    +
    +

    2.15.6. Microsoft Pragmas#

    +

    The following pragmas are accepted in Microsoft mode:

    +
    #pragma push_macro("identifier")
    +#pragma pop_macro("identifier")
    +#pragma include_alias("a_long_file_name.h", "short.h")
    +
    +
    +

    In addition, when NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is TRUE, +the setlocale pragma is accepted:

    +
    #pragma setlocale("locale name")
    +
    +
    +

    The pack pragma is also accepted by the Microsoft compiler, but its +acceptance by the front end is controlled by a separate configuration flag, not +by whether or not Microsoft mode is being used.

    +
    +
    +

    2.15.7. IL Display Pragma#

    +

    As a debugging aid, in configurations where NEED_IL_DISPLAY is TRUE, +the il_display pragma can be used to display the underlying IL for the IL +entity that the pragma is attached to. The il_display pragma is a +pbk_next_construct pragma that attaches to the subsequent declaration or +statement and displays the IL associated with that entity. Note that the IL +displayed represents the IL at the current point in the compilation and may not +accurately reflect the eventual IL. This can be useful for displaying source +location information. For example:

    +
    struct A { int x, y; };
    +void f(int i) {
    +#pragma il_display
    +  A a = { 1, 2 };
    +#pragma il_display
    +  i++;
    +}
    +
    +
    +
    +
    +
    +

    2.16. Precompiled Headers#

    +

    It is often desirable to avoid recompiling a set of header files, +especially when they introduce many lines of code and the primary source +files that #include them are relatively small. The EDG front end +provides a mechanism for, in effect, taking a snapshot of the state of the +compilation at a particular point and writing it to a disk file before +completing the compilation; then, when recompiling the same source file or +compiling another file with the same set of header files, it can recognize +the “snapshot point,” verify that the corresponding precompiled header +(“PCH”) file is reusable, and read it back in. Under the right +circumstances, this can produce a dramatic improvement in compilation time; +the trade-off is that PCH files can take a lot of disk space. Because of +potential memory conflicts between threads, precompiled header processing +is disabled in multi-threaded configurations. In particular, a PCH file +cannot be created if MULTIPLE_THREAD_COMPILATION is TRUE and, because +the configurations must match, a PCH file by a single-threaded +configuration cannot be used.

    +
    +

    2.16.1. Automatic Precompiled Header Processing#

    +

    When --pch appears on the command line, automatic precompiled header +processing is enabled. This means the front end will automatically look for a +qualifying precompiled header file to read in and/or will create one for use on +a subsequent compilation.

    +

    The PCH file will contain a snapshot of all the code preceding the “header +stop” point. The header stop point is typically the first token in the primary +source file that does not belong to a preprocessing directive, but it can also +be specified directly by #pragma hdrstop (see below) if that comes first. +For example:

    +
    #include "xxx.h"
    +#include "yyy.h"
    +int i;
    +
    +
    +

    The header stop point is int (the first non-preprocessor token) and the PCH +file will contain a snapshot reflecting the inclusion of xxx.h and +yyy.h. If the first non-preprocessor token or the #pragma hdrstop +appears within a #if block, the header stop point is the outermost +enclosing #if. To illustrate, here’s a more complicated example:

    +
    #include "xxx.h"
    +#ifndef YYY_H
    +#define YYY_H 1
    +#include "yyy.h"
    +#endif
    +#if TEST
    +int i;
    +#endif
    +
    +
    +

    Here, the first token that does not belong to a preprocessing directive is +again int, but the header stop point is the start of the #if block +containing it. The PCH file will reflect the inclusion of xxx.h and +conditionally the definition of YYY_H and inclusion of yyy.h; it will +not contain the state produced by #if TEST.

    +

    A PCH file will be produced only if the header stop point and the code +preceding it (mainly, the header files themselves) meet certain requirements:

    +
      +
    • +
      The header stop point must appear at file scope – it may not be within an +unclosed scope established by a header file. For example, a PCH file will +not be created in this case:
      +
      +
      // xxx.h
      +class A {
      +
      +// xxx.C
      +#include "xxx.h"
      +int i; };
      +
      +
      +
    • +
    • +
      The header stop point may not be inside a declaration started within a +header file, nor (in C++) may it be part of a declaration list of a linkage +specification. For example, in the following case the header stop point is +int, but since it is not the start of a new declaration, no PCH file +will be created:
      +
      +
      // yyy.h
      +static
      +
      +// yyy.C
      +#include "yyy.h"
      +int i;
      +
      +
      +
    • +
    • +
      Similarly, the header stop point may not be inside a #if block or a +#define started within a header file.
      +
      +
    • +
    • +
      The processing preceding the header stop must not have produced any errors. +(Note: warnings and other diagnostics will not be reproduced when the PCH +file is reused.)
      +
      +
    • +
    • +
      No references to predefined macros __DATE__ or __TIME__ may have +appeared.
      +
      +
    • +
    • +
      No use of the #line preprocessing directive may have appeared.
      +
      +
    • +
    • +
      #pragma no_pch (see below) must not have appeared.
      +
      +
    • +
    • +
      The code preceding the header stop point must have introduced a sufficient +number of declarations to justify the overhead associated with precompiled +headers. This is configurable – see PCH_DECL_SEQ_THRESHOLD.
      +
      +
    • +
    +

    When the host system does not support memory mapping, so that everything to be +saved in the precompiled header file is assigned to preallocated memory (i.e., +when USE_MMAP_FOR_MEMORY_REGIONS is FALSE), two additional restrictions +apply:

    +
      +
    • +
      The total memory needed at the header stop point cannot exceed the size of +the block of preallocated memory.
      +
      +
    • +
    • +
      No single program entity saved can exceed HOST_ALLOCATION_INCREMENT, +the preallocation unit.
      +
      +
    • +
    +

    When a precompiled header file is produced, it contains, in addition to the +snapshot of the compiler state, some information that can be checked to +determine under what circumstances it can be reused. This includes:

    +
      +
    • +
      The compiler version, including the date and time the compiler was built.
      +
      +
    • +
    • +
      The current directory (i.e., the directory in which the compilation is +occurring).
      +
      +
    • +
    • +
      The command line options.
      +
      +
    • +
    • +
      The initial sequence of preprocessing directives from the primary source +file, including #include directives.
      +
      +
    • +
    • +
      The date and time of the header files specified in #include directives.
      +
      +
    • +
    +

    This information comprises the PCH “prefix.” The prefix information of a given +source file can be compared to the prefix information of a PCH file to +determine whether the latter is applicable to the current compilation.

    +

    As an illustration, consider two source files:

    +
    // a.C
    +#include "xxx.h"
    +...               // Start of code
    +
    +// b.C
    +#include "xxx.h"
    +...               // Start of code
    +
    +
    +

    When a.C is compiled with --pch, a precompiled header file named +a.pch is created. Then, when b.C is compiled (or when a.C is +recompiled), the prefix section of a.pch is read in for comparison with the +current source file. If the command line options are identical, if xxx.h +has not been modified, and so forth, then, instead of opening xxx.h and +processing it line by line, the front end reads in the rest of a.pch and +thereby establishes the state for the rest of the compilation.

    +

    It may be that more than one PCH file is applicable to a given compilation. If +so, the largest (i.e., the one representing the most preprocessing directives +from the primary source file) is used. For instance, consider a primary source +file that begins with:

    +
    #include "xxx.h"
    +#include "yyy.h"
    +#include "zzz.h"
    +
    +
    +

    If there is one PCH file for xxx.h and a second for xxx.h and +yyy.h, the latter will be selected (assuming both are applicable to the +current compilation). Moreover, after the PCH file for the first two headers +is read in and the third is compiled, a new PCH file for all three headers may +be created.

    +

    When a precompiled header file is created, it takes the name of the primary +source file, with the suffix replaced by an implementation-specified suffix +(see PCH_FILE_SUFFIX, which is set to pch by default). Unless +--pch_dir is specified (see below), it is created in the directory of the +primary source file.

    +

    When a precompiled header file is created or used, a message such as

    +
    "test.C": creating precompiled header file "test.pch"
    +
    +
    +

    is issued. The user may suppress the message by using the command-line option +--no_pch_messages.

    +

    When the --pch_verbose option is used the front end will display a message +for each precompiled header file that is considered that cannot be used giving +the reason that it cannot be used.

    +

    In automatic mode (i.e., when --pch is used) the front end will deem a +precompiled header file obsolete and delete it under the following +circumstances:

    +
      +
    • +
      if the precompiled header file is based on at least one out-of-date header +file but is otherwise applicable for the current compilation; or
      +
      +
    • +
    • +
      if the precompiled header file has the same base name as the source file +being compiled (e.g., xxx.pch and xxx.C) but is not applicable for +the current compilation (e.g., because of different command-line options).
      +
      +
    • +
    +

    This handles some common cases; other PCH file clean-up must be dealt with by +other means (e.g., by the user).

    +

    Support for precompiled header processing is not available when multiple source +files are specified in a single compilation: an error will be issued and the +compilation aborted if the command line includes a request for precompiled +header processing and specifies more than one primary source file.

    +
    +
    +

    2.16.2. Manual Precompiled Header Processing#

    +

    Command-line option --create_pch file-name specifies that a precompiled +header file of the specified name should be created.

    +

    Command-line option --use_pch file-name specifies that the indicated +precompiled header file should be used for this compilation; if it is invalid +(i.e., if its prefix does not match the prefix for the current primary source +file), a warning will be issued and the PCH file will not be used.

    +

    When either of these options is used in conjunction with --pch_dir, the +indicated file name (which may be a path name) is tacked on to the directory +name, unless the file name is an absolute path name.

    +

    The --create_pch, --use_pch, and --pch options may not be used +together. If more than one of these options is specified, only the last one +will apply. Nevertheless, most of the description of automatic PCH processing +applies to one or the other of these modes – header stop points are determined +the same way, PCH file applicability is determined the same way, and so forth.

    +
    +
    +

    2.16.3. Other Ways for Users to Control Precompiled Headers#

    +

    There are several ways in which the user can control and/or tune how +precompiled headers are created and used.

    +
      +
    • +
      #pragma hdrstop may be inserted in the primary source file at a point +prior to the first token that does not belong to a preprocessing directive. +It enables the user to specify where the set of header files subject to +precompilation ends. For example,
      +
      +
      #include "xxx.h"
      +#include "yyy.h"
      +#pragma hdrstop
      +#include "zzz.h"
      +
      +
      +
      +
      Here, the precompiled header file will include processing state for +xxx.h and yyy.h but not zzz.h. (This is useful if the user +decides that the information added by what follows the #pragma hdrstop +does not justify the creation of another PCH file.)
      +
      +
    • +
    • +
      #pragma no_pch may be used to suppress precompiled header processing +for a given source file.
      +
      +
    • +
    • +
      Command-line option --pch_dir directory-name is used to specify the +directory in which to search for and/or create a PCH file.
      +
      +
    • +
    +

    Moreover, when the host system does not support memory mapping and preallocated +memory is used instead (i.e., when USE_MMAP_FOR_MEMORY_REGIONS is FALSE) +then one of the command-line options --pch, --create_pch, or +--use_pch, if it appears at all, must be the first option on the command +line; and in addition:

    +
      +
    • +
      Command-line option --pch_mem size may be used to change the size +of the preallocated block of memory from its default value. The +argument size is the number of 1024-byte units. (--pch_mem must +also be among the first options on the command line.)
      +
      +
    • +
    +
    +
    +

    2.16.4. Performance Issues#

    +

    The relative overhead incurred in writing out and reading back in a precompiled +header file is quite small for reasonably large header files. (An +implementation can adjust PCH_DECL_SEQ_THRESHOLD to avoid creating +precompiled header files with too little information in them.)

    +

    In general, it doesn’t cost much to write a precompiled header file out even if +it does not end up being used, and if it is used it almost always produces a +significant speedup in compilation. The problem is that the precompiled header +files can be quite large (from a minimum of about 250K bytes to several +megabytes or more), and so one probably doesn’t want many of them sitting +around.

    +

    Thus, despite the faster recompilations, precompiled header processing is not +likely to be justified for an arbitrary set of files with nonuniform initial +sequences of preprocessing directives. Rather, the greatest benefit occurs +when a number of source files can share the same PCH file. The more sharing, +the less disk space is consumed. With sharing, the disadvantage of large +precompiled header files can be minimized, without giving up the advantage of a +significant speedup in compilation times.

    +

    Consequently, to take full advantage of header file precompilation, users +should expect to reorder the #include sections of their source files and/or +to group #include directives within a commonly used header file.

    +

    The EDG front end source provides an example of how this can be done. A common +idiom is this:

    +
    #include "fe_common.h"
    +#pragma hdrstop
    +#include ...
    +
    +
    +

    where fe_common.h pulls in, directly and indirectly, a few dozen header +files; the #pragma hdrstop is inserted to get better sharing with fewer PCH +files. The PCH file produced for fe_common.h is a bit over a megabyte in +size. Another idiom, used by the source files involved in declaration +processing, is this:

    +
    #include "fe_common.h"
    +#include "decl_hdrs.h"
    +#pragma hdrstop
    +#include ...
    +
    +
    +

    decl_hdrs.h pulls in another dozen header files, and a second, somewhat +larger, PCH file is created. In all, the fifty-odd source files of the EDG +front end share just six precompiled header files. If disk space were at a +premium, one could decide to make fe_common.h pull in all the header +files used – then, a single PCH file could be used in building the EDG +front end.

    +

    Different environments and different projects will have different needs, but in +general, users should be aware that making the best use of the precompiled +header support will require some experimentation and probably some minor +changes to source code.

    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/genindex/index.html b/dev/doc/genindex/index.html new file mode 100644 index 0000000..7da1977 --- /dev/null +++ b/dev/doc/genindex/index.html @@ -0,0 +1,88 @@ + + + + + Index - CPFE 7.0 documentation + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    +
    + + +

    Index

    + +
    + +
    + + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/il/index.html b/dev/doc/il/index.html new file mode 100644 index 0000000..d646921 --- /dev/null +++ b/dev/doc/il/index.html @@ -0,0 +1,4283 @@ + + + + + 4. Intermediate Language - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    4. Intermediate Language#

    +

    The Intermediate Language is the output of the front end. It is a +representation of the source program that is passed to the back end, and +from which the back end can perform analyses, make transformations, and/or +generate object code.

    +

    The intermediate language is a “high-level” intermediate language, that is, a +representation that is close in spirit to the original source language, rather +than a “low-level” intermediate language that is close to any typical computer +architecture. That fits the EDG philosophy of the function of a front end, +i.e., that a front end should determine the meaning of a source program and +produce an intermediate language representation of the source program that:

    +
      +
    • +
      accurately represents the meaning of the program;
      +
      +
    • +
    • +
      does not destroy information;
      +
      +
    • +
    • +
      does not add constraints that are not present in the source program; and
      +
      +
    • +
    • +
      makes explicit any implicit or overloaded operations in the source program, +so that the back end does not have to have a deep understanding of the +source language and does not have to search or interpret the intermediate +language. It follows from this that the front end does not do +optimization, does not rewrite source constructs in “simpler” forms, and +does not use a machine-dependent representation. It also follows that +ambiguity and overloading resolution are completely handled by the front +end and a back end need do nothing to deal with them. The intermediate +language is a tree-structured in-memory data structure. Both declarative +and executable constructs are represented in tree form, and in fact all +declarative and executable information at all levels is tied together into +one tree. Having a pointer to the root of this tree gives one all the +information necessary to generate object code for the source program. (In +other words, the intermediate language data structure is the only +information that needs to be passed from the front end to the back end. +There is no additional hidden information.) The source code definitions of +the intermediate language tables are in the file il_def.h. However, +some introductory information is necessary before one dives into that file.
      +
      +
    • +
    +
    +

    4.1. Memory Management#

    +

    Memory management may seem like a strange place to begin an overview of the +intermediate language. However, an understanding of the memory management +structure is necessary to get a feeling for the overall shape of the +intermediate language tree.

    +
    +

    4.1.1. Memory Regions#

    +

    It was decided early in the design of the front end that the intermediate +language would be an in-memory data structure. That is, it exists in +directly-addressable memory and can be examined without recourse to special +access routines. This is beneficial from the point of view of compilation +speed and ease of programming. However, it could be problematic from the point +of view of memory use, especially when processing extremely large source files. +To deal with that problem, it was decided that the intermediate language should +be set up so that the parts of the tree associated with different top-level +functions are placed in separate blocks of memory that need not all be in +memory at the same time. A top-level function is any function that is not a +lambda defined in a function scope, or the instantiation of a generic lambda +defined in a function scope. Functions that are not top-level are placed in +the memory region of the enclosing function. During the processing of a single +function, the intermediate language for that function (and for other functions +in the same memory region) and for the global declarations visible to that +function must be in memory. The intermediate language for all other functions, +however, is not needed at that time, and can be written out to a file or +otherwise removed from the active address space. As a result, a large source +program looks more like a sequence of reasonably-sized functions and uses +memory accordingly.

    +

    These blocks of memory are called “memory regions”. There is a memory region +for the file scope intermediate language and one for the intermediate language +of each top-level function of the source program.

    +

    The memory region scheme is a two-level scheme: there is a file scope memory +region which is always in memory, and a set of function scope memory regions of +which only one is guaranteed to be in memory at a given time. C++ lambdas +defined in function scopes are handled by placing them in the same memory +region as the enclosing function. Member functions of local classes in C++, +while somewhat similar to lambdas, are treated (with some careful allocation of +entities) as top-level functions and have their own memory regions.

    +
    +
    +

    4.1.2. Memory Regions and Pointers#

    +

    The memory management structure has an effect on pointers in the intermediate +language. Clearly, a pointer to an entry in a function scope memory region is +valid only if the associated memory region is actually in memory. Rather than +requiring dynamic checking of pointer legality, we decided to make a rule about +how pointers may be used. Specifically, entries within a function scope memory +region may only be pointed to from within that memory region. Entries in the +file scope memory region may, of course, be pointed to from anywhere, since +they are always in memory.

    +

    This rule has some consequences. The most important one is that anything that +must be referenced from more than one memory region must be allocated in the +file scope memory region. Specifically, since functions may be called from +many other functions, they must have some representation in the file scope +memory region. Of course, since the whole point of the function scope memory +regions is to avoid having everything in memory at one time, it wouldn’t make +sense to put the entire routine into the file scope memory region. What’s done +instead is to put the description of the interface to the routine (i.e., what’s +needed to call it) in the file scope memory region, and the description of the +implementation of the routine (i.e., what’s needed to execute it) in the +function scope memory region. Similarly, local static variables of functions +must be allocated in the file scope memory region because they are potentially +referenced from member functions of classes local to the function.

    +

    A second consequence is that anything referenced from the file scope memory +region must also be allocated in the file scope memory region. [1] This +second consequence becomes significant when combined with another intermediate +language decision, that of placing all entities with external visibility at the +file scope. [2] Placing the declaration of an external entity at the file +scope means placing all of the entities it references in the file scope memory +region, and that means placing all the entities they reference in the file +scope memory region. The practical consequence of all that is that all types +must be allocated in the file scope memory region, since it is not possible to +know at the time they are allocated whether or not they will be used as part of +the type of some external entity. In C++, that means in particular that all +classes are allocated in the file scope memory region (except for the bodies of +member functions). Likewise, all namespaces are allocated in the file scope +memory region except for the bodies of namespace member functions.

    +

    It is important to bear in mind that the file scope memory region is not the +same thing as the file scope. They are similar but not identical. The file +scope is a language concept: it is the outermost scope in a C or C++ program. +The file scope memory region is a memory management concept referring to a +block of memory whose contents must always be accessible. All entities in the +file scope are allocated in the file scope memory region, but some entities +allocated in the file scope memory region are function-scope entities, some are +function-scope entities moved to the file scope because they are externally +visible, and some are class or namespace members allocated in the file scope +memory region because all classes and namespaces are allocated there.

    +
    +
    +
    +

    4.2. Intermediate Language Files#

    +

    The intermediate language and memory management scheme are set up to allow but +not require the use of files to save the intermediate language. The front +end’s connection to a back end can be configured in a number of ways:

    +
      +
    • +
      The entire intermediate language tree can be passed in memory to the back +end. This is fastest but uses the most memory.
      +
      +
    • +
    • +
      The intermediate language can be written to a file on a +per-top-level-function basis and read back in on a per-top-level-function +basis in the back end. (Only one file is used, but the intermediate +language for each function is written separately and the memory involved is +reclaimed immediately.) This is slowest but uses the least memory.
      +
      +
    • +
    • +
      The intermediate language can be processed on a per–top-level-function +basis in some other way, then thrown away. For example, the intermediate +language can be translated to another intermediate language used by the +back end, and the original intermediate language can be discarded.
      +
      +
    • +
    +
    +
    +

    4.3. C versus C++ Intermediate language#

    +

    The intermediate language generated for C++ is a superset of the intermediate +language generated for C.

    +

    For the sake of customers that have an existing C back end, EDG provides a +optional and separate “IL lowering” pass that translates the C++ intermediate +language into the C intermediate language. Note that although the process is +called “lowering,” the resulting C intermediate language is still “high-level”; +it’s just not as high-level as it was. Also note that the IL lowering process +does some implementation of C++ features (e.g., virtual function tables, name +mangling, pointers-to-members, constructor and destructor wrapper code) which +are just abstractions in the unlowered IL. Clearly, a back end has the most +latitude in generating code for C++ if it starts with the unlowered C++ IL, but +it also has quite a bit more work to do. On the other hand, an extra pass over +the intermediate language takes time, so a configuration that uses the IL +lowering pass will not be as fast as one that does not use it.

    +

    The IL lowering pass is useful because

    +
      +
    1. it allows customers to get a C++ compiler going in minimal time;

    2. +
    3. if the features implemented by IL lowering require some minor changes, +the changes can be made in IL lowering, which is relatively small, rather +than in the front end as a whole, which is quite large; and

    4. +
    5. if a customer wants to attach a back end to the unlowered IL (either +initially or for an improved release of a compiler), the IL lowering code +serves as a guide to the tasks that must be done.

    6. +
    +

    The description of the intermediate language in this chapter is for the +unlowered IL. All C++-specific features are rewritten or removed by the IL +lowering, which means that some of the description in this chapter is of no +interest to a back end that uses the lowered IL. If there is some question +about whether or not a feature would remain in the lowered IL, the description +will indicate what effect IL lowering has.

    +

    There is no way at present to compile the C++ front end so that the IL that it +generates includes only the C IL definitions. Even though IL lowering will +eliminate uses of non-C features, the C++-specific fields and enumeration +values are still present in the source code. Back ends should ignore those +fields (they are not necessarily cleared) and should expect to get IL that is +valid C when one considers (only) the fields that C uses.

    +

    One catch: Dynamic initialization of entities in the middle of blocks is left +in its original form. This is not “incorrect” C IL, but is something that does +not come up in C(89) programs. It was judged that back ends would be capable +of dealing with the stmk_init statements even if they appear after other +executable statements in a block, and the alternative was to make lowering of +initialization of aggregates to constants quite messy.

    +

    Similarly, the initialization statement attached to an stmk_for is always a +simple stmk_expr in C, but in C IL generated by IL lowering, it can be an +arbitrary statement.

    +
    +
    +

    4.4. C99 and the Intermediate Language#

    +

    The ANSI/ISO C standard was updated in 1999, and the resulting version of C +is referred to as C99. The C/C++ front end supports C99 (as well as later +versions). In some cases, the IL has been extended to support newly-added +features of C99.

    +

    The IL extensions for C99 and later revisions are enabled by the macro +C99_IL_EXTENSIONS_SUPPORTED. If that macro is set to FALSE, C99 and +later modes can still be enabled, but all features that require the IL +extensions are disabled. Note, in particular, that if your interest is +only in supporting C++, or only C89, turning off these features will make +it slightly easier to write a back end, because you will have to implement +fewer IL constructs.

    +

    There is a lowering phase for C99, which rewrites many of the extensions into +standard C89 IL. This lowering phase is enabled by the macro +DO_IL_LOWERING.

    +

    See C99 features for a detailed list of C99 IL constructs. That list +summarizes the lowering done for each construct; there is more detail in the IL +Lowering chapter of this document.

    +
    +
    +

    4.5. C++/CLI and the Intermediate Language#

    +

    The front end supports the Microsoft C++/CLI language, a set of extensions to +C++ to allow programmers to interface to Microsoft’s .NET, which is a +heap-based garbage-collected environment in the style of Java or C#. There is +an ECMA standard for the C++/CLI language (ECMA 372), but the real standard is +the MSVC compiler, as it diverges from the ECMA document in significant ways.

    +

    The C++/CLI extensions involve new types, new expression operators, new member +function kinds, new declarations, and new statements. Those are covered in +detail in the appropriate sections of this document. The data structures and +code for those features are included when MICROSOFT_EXTENSIONS_ALLOWED is +TRUE; there is no separate macro for C++/CLI to control their inclusion. The +features are enabled only when cppcli_enabled is TRUE, and there is a macro +CPPCLI_ENABLING_POSSIBLE that when FALSE (the default) prevents the C++/CLI +features from being enabled. So if you do not want to support C++/CLI, leave +CPPCLI_ENABLING_POSSIBLE set to FALSE and you will never see any of its +features in the IL.

    +

    Note that C++/CLI is supported only when the front end is hosted on Windows. +Also note that C++/CLI is Microsoft’s second version of a C++ interface for +.NET; there was a previous set of extensions called “Managed C++”. The front +end does not support those features (and Microsoft is moving away from +supporting them as well).

    +
    +
    +

    4.6. Memory Region Processing Order#

    +

    When a file is compiled, the processing order of memory regions will look like:

    +
      +
    • +
      Start file scope memory region (1).
      +
      +
        +
      • +
        Start function scope memory region (2).
        +
        +
      • +
      • +
        End function scope memory region (2).
        +
        +
      • +
      • +
        Start function scope memory region (3).
        +
        +
      • +
      • +
        End function scope memory region (3).
        +
        +
      • +
      • +
        Etc.
        +
        +
      • +
      +
    • +
    • +
      End file scope memory region (1).
      +
      +
    • +
    +

    When IL lowering is done, it is done as each memory region is ended. When IL +files are written, they are written as each memory region is ended (after IL +lowering, if any).

    +

    When the front end instantiates functions or generates routines (like +constructors), there can be brief periods when multiple function scope memory +regions are active. The function scope memory region for the instantiated or +generated routine is started and ended while the primary function scope memory +region is still active. If this process kicks off instantiation or generation +of other routines, there can be many active function scope memory regions.

    +
    +
    +

    4.7. General Information#

    +

    Each major type of entity in the C/C++ language has a corresponding +intermediate language entry. For example: a_constant, a_type, +a_variable, a_routine, a_label, a_statement, and +an_expr_node. Each entry kind has a fixed size except for the entries +representing strings (used for literal strings and names), which have a +variable length. The IL entries are not self-labeling; one must know the kind +of thing pointed to to make sense of a pointer.

    +

    The intermediate language is high-level, meaning that the entities in it +correspond fairly closely to C and C++ language constructs. For example, all +of the C and C++ expression operators are present in their original forms. +There is no remapping of complex operators (like “?”) to lower-level +operations. Statements are kept in their original structured form, and not +flattened to ifs and gotos.

    +

    Since the structure of the intermediate language corresponds so closely to the +original C or C++ form, it implies no ordering of evaluation that was not in +the original program. Timing of side effects for post-increment operations, +for example, which must be completed by the next sequence point, is not +specified explicitly. It is up to the back end to adhere to the C and C++ +language rules when generating object code for such constructs.

    +

    By convention, there can be multiple pointers to any given declarative entity +(for example, many places can point to the constant entry for 1), but only +a single pointer to any executable entity (each use of 1 in an expression +requires a distinct expression node pointing to the common constant entry for +1).

    +

    The intermediate language tables are designed to keep memory requirements +reasonably low. There are several cases where enum values are stored as +a_bytes (which means as chars of some kind), in order to ensure +that only one byte is used for those rather than whatever the host C compiler +might choose for an enum. An example of such a type is +a_constant_repr_kind. This has the unfortunate side effect that explicit +casts are often required when dealing with values of these types. There are +also several cases where, in a union that has one case that is larger than all +the others, the extra information for the unusual case is broken out as a +separate supplement that is pointed to from the union (e.g., +a_routine_type_supplement).

    +

    As mentioned, all of the intermediate language is tree-structured. The +expression i+1 is a tree with a + expression node pointing to two +expression nodes representing i and 1; the statement

    +
    if (i) i=1; else i=2;
    +
    +
    +

    is a tree with an if statement node pointing to two statement nodes for +i=1 and i=2; and the declaration

    +
    int *m[5];
    +
    +
    +

    is a variable node for m pointing to a tree defining the type “array of +pointer to int”. All the statements of a function are bundled into one +tree which is pointed to by the function definition, and all the type, +variable, and function definitions for a given scope are on a list pointed to +by the header for the scope. At the top of the entire tree for a compilation +there is a header that points to the entry for the outermost scope. Beginning +there, one can get to all of the functions and therefore all of the functions’ +scopes; one can also get to all of the classes and therefore all of the +classes’ scopes. In other words, beginning at the IL header one can reach the +entire IL tree for the compilation.

    +
    +
    +

    4.8. The IL Header#

    +

    The top of the intermediate language tree is il_header, which contains +several important pointers:

    +
      +
    • +
      A pointer to the scope entry defining the primary scope of the compilation. +This is the root of the IL tree proper.
      +
      +
    • +
    • +
      A pointer to the top of a tree of entries describing the source files from +which the source program came.
      +
      +
    • +
    • +
      A pointer to the scope_region_entry array, which gives pointers to the +scope entries that are the top of the IL tree in each of the function scope +memory regions.
      +
      +
    • +
    • +
      A pointer to the function_def_table array, which gives the pointers to +the scope entries and memory region numbers for a given function +definition.
      +
      +
    • +
    +
    +
    +

    4.9. Source File Information#

    +

    The source file information structure describes the primary source input file +and the include files of the compilation, and the relationship between them. +It is a structure distinct from the IL tree proper because the file structure +of a program need not have any relationship to its syntactic structure. An +include file, for example, could include half of a routine, or the end of one +routine and the start of another. (This is of course not typical, but it’s +possible.) Within the IL tree proper, a source line’s position is given by a +sequence number, which is the ordinal position of the source line in the +sequence of lines read by the front end, starting at the beginning of the +primary source file and switching into include files when directed to by +#include directives. The sequence number is compact and unambiguous for +internal use, and can be translated easily to a file name and line number for +external use by referring to the source line information structure. The +routine conv_seq_to_file_and_line in il.c does that translation.

    +
    +
    +

    4.10. Source Correspondence Information#

    +

    Constructs that declare constants, types, variables, routines, fields, labels, +namespaces, templates, template parameters, and macros have information on the +associated source name and the source location of the declaration. This +information is given by the source_corresp field, which is a struct of +type a_source_correspondence. A source location is specified by an entry +of type a_source_position, which consists of a sequence number and a column +number. The column number is the 1-origined column number in the original +source line (not the logical source line that results after processing +trigraphs and line splices). Tab characters count as one column, so the +“column number” may not match the apparent display position on a terminal or +printer. If multibyte characters appear, including characters that come from +files in formats such as UTF-16, they count as a single column. The node for +statements has a source location as well, but (to save space) it contains only +a sequence number and no column number (see, however, the configuration flag +FULL_SOURCE_POS_IN_IL_STATEMENT).

    +

    Aside from a pointer to the name string and the source position, the source +correspondence information contains an assoc_info pointer. This is +intended to be used by the front end and other components to store a pointer to +information maintained locally about the entity. However, the information does +not survive into the next pass. In the front end, the pointer points back to +an associated symbol entry. That pointer is no longer valid once the front end +is finished (since the space for symbol entries may have been released), but +the pointer can be set in the back end as desired.

    +

    Compiler-generated entities have no source correspondence information +(since they do not appear in the program source). Their source +correspondence name pointer is NULL.

    +

    The source correspondence information also contains the name_linkage field, +which indicates the kind of linkage the entity has (e.g., is it externally +visible? Should C++ name mangling be done on it?), an access field (which +indicates the access for class members in C++), a parent_scope pointer to +the containing scope, and a referenced field.

    +

    When IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS is TRUE, the name string +in the source correspondence entry can contain multibyte character +sequences (e.g., UTF-8 when UNICODE_SOURCE_SUPPORTED is TRUE). When it +is FALSE, multibyte characters will be represented as \mXXXX or +\MXXXXXXXX escape sequences. When a universal-character-name +(e.g., \u00d6) appears in a name, the name string will contain the`` +u``XXXX or \UXXXXXXXX escape sequence, except that when +UNICODE_SOURCE_SUPPORTED and +IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS are both TRUE the UCN value +will be represented directly. IL lowering can do some limited rewriting of +such escape sequences; see REWRITE_UCN_ESCAPE_CHAR_IN_LOWERING. Note +that these flags do not control whether or not multibyte characters are +allowed in identifiers, only how they are represented; see +MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED.

    +
    +

    4.10.1. referenced and needed Flags#

    +

    The referenced flag in a source correspondence entry indicates whether an +entity is referenced. All entities that have no source correspondence have +referenced set to TRUE. For named entities, referenced is TRUE if the +entity is referenced in the intermediate language. The reference can be +implicit: in a case like

    +
    struct s {int a;} v;
    +
    +
    +

    the struct type is referenced, but not through the name s.

    +

    The referenced flag is set correctly but simplistically. More precise +information is available in the needed flag (and, in classes and routines, +the definition_needed flag). These are optional and are selected by the +configuration switch MAINTAIN_NEEDED_FLAGS. When present, they indicate +whether or not an entity is “really” needed, and whether the definition of a +class is really needed, or merely its declaration. This is determined by +marking as needed all externally-defined functions and variables, and all the +things they reference, and all the things those things reference, etc.

    +

    Depending on the setting of DEFAULT_REMOVE_UNNEEDED_ENTITIES, possibly as +overridden by a command-line option, unneeded entities and unneeded class +definitions will be removed from the IL tree. This process, however, does not +remove all unneeded entities, because some end up being required for IL +consistency even though they are not “needed.” One example: if a class and its +definition are needed, all the members of the class must be kept in the IL even +though some of the members may not be “needed” (in the sense of being +referenced directly or indirectly from an externally defined routine or +variable). The IL after removal of unneeded entities will be self-consistent, +in that a back end that does not use the needed flags will find nothing +surprising. If a back end uses the needed flag, it should also pay +attention to the class definition_needed flag or it may find some apparent +inconsistencies in the IL tree.

    +

    The setting of the “needed” flags and the removal of unneeded IL entries work +both with and without IL lowering. When IL lowering is done, the setting is +done after lowering, so that the flags reflect the lowered code.

    +

    When ONE_INSTANTIATION_PER_OBJECT is TRUE, a more complicated set of +“needed” flags is maintained. In that mode, each instantiation is put out as a +separate object file. There is still only one IL tree, but it is marked so +that a back end can sweep through it several times and put out a different +“slice” each time, each slice containing one instantiated entity (function, +variable, or static data member) plus exactly the set of other entities needed +by that entity. This is done via a set of per-instantiation “needed” flags, +represented as a bit vector implemented as a linked list of entries of type +a_per_instantiation_needed_flags_entry attached to the +per_instantiation_needed_flags field of the source correspondence. Each +slice is assigned one bit in that bit vector, and if the bit is 1 the +associated entity is needed in the slice.

    +

    See the Needed Flags section.

    +
    +
    +

    4.10.2. Source positions#

    +

    Source position information is recorded in the IL in various ways. The +decl_position field in the source correspondence indicates the source +position of the primary declaration of an entity. When an entity has more than +one declaration, decl_position corresponds to the defining declaration or, +if there is no defining declaration, the first declaration. When +GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, source positions on declarations +other than the primary declaration are recorded in the source-sequence list – +see decl_position in a_src_seq_secondary_decl. As noted previously, +position information is also recorded in a_statement; in addition, source +position information is recorded in other IL entries that have no source +correspondence field, e.g., a_base_class, a_using_decl, +an_instantiation_directive, a_static_assertion, and a_pragma.

    +

    In applications for which additional source position information is needed, +EXTRA_SOURCE_POSITIONS_IN_IL can be configured to TRUE. Note, however, +that this information can take a lot of extra space, so the feature is disabled +by default.

    +

    When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, source range information +(beginning and ending source positions of various syntactic constructs) is +supplied. Each source correspondence has a pointer to +a_decl_position_supplement, which includes the source range of the complete +identifier (including namespace and class qualifiers, if present), as well as +the source range of the declaration-specifiers and the declarator. For +instance, the source position information for this declaration of foo is +indicated:

    +
    inline void A::foo(A *pa) { /* ... */ }
    +               ^                    decl_position
    +            ^^^^^^                  identifier_range
    +^^^^^^^^^^^                         specifiers_range
    +            ^^^^^^^^^^^^^           declarator_range
    +
    +
    +

    Moreover, though the param-type entry for parameter pa has no source +correspondence entry, it does have a pointer to a_decl_position_supplement, +which records its source range information:

    +
    inline void A::foo(A *pa) { /* ... */ }
    +                      ^^            identifier_range
    +                   ^                specifiers_range
    +                     ^^^            declarator_range
    +
    +
    +

    Source range information is supplied for a_base_class and +a_constructor_init, as well as for the initializer construct of explicitly +initialized variables. Moreover, when GENERATE_SOURCE_SEQUENCE_LISTS is +TRUE, pointers to a_decl_position_supplement also appear in +a_src_seq_secondary_decl entries; this provides source range information on +declarations that are not the primary declaration of an entity (e.g., +friend declarations).

    +

    Source range information is also provided for expression nodes when +EXTRA_SOURCE_POSITIONS_IN_IL is TRUE. The source positions of the start +and end of the expression, along with the source position of the operator (if +present) are recorded.

    +
    +
    +

    4.10.3. Name Linkage#

    +

    The name_linkage field of the source correspondence structure indicates the +kind of linkage the name of an entity (routine, variable, class or enumeration +type, or class member) has:

    +
      +
    • +
      External linkage, used in C mode and for extern "C" entities in C++ +mode, indicates that the name is visible outside its compilation unit.
      +
      +
    • +
    • +
      C++ external linkage, for normal entities in C++ mode, indicates that the +name is visible outside its compilation unit. The name may be subjected to +some kind of name mangling.
      +
      +
    • +
    • +
      Internal linkage indicates that the entity name is visible throughout its +compilation unit (e.g., a file-scope static variable).
      +
      +
    • +
    • +
      No linkage indicates that the entity name has no connection to other +entities with the same name (e.g., a local variable).
      +
      +
    • +
    +

    From a C perspective, the name linkage information seems to be redundant, in +that it would seem that one could decide the name linkage on the basis of a +variable or routine’s storage class. In C++, however, class names (i.e., +types) have linkage, and in some compatibility modes if a class is used in the +type of an external entity, it acquires external linkage, and its static data +members and member functions also get external linkage. It gets to be very +complicated to try to encode the storage class (including whether or not it can +be changed on subsequent declarations) and the name linkage in just the storage +class field.

    +

    In addition, the routine_name_linkage field in the routine type supplement +is significant. The linkage specification in a routine type declaration can +correspond to the routine’s calling convention – for example, when extern +"C++" and extern "C" imply distinct calling conventions or an +implementation-defined linkage specification has its own calling convention. +Among other things, this means that in C++ otherwise identical functions are +distinguished for purposes of overloading based on the linkages associated with +their parameter types:

    +
    typedef void (*PF)();             // Pointer to an extern "C++" function
    +extern "C" typedef void (*PFC)()  // Pointer to an extern "C" function
    +void f(PF);
    +void f(PFC);                      // Overloads f
    +
    +
    +

    Note, moreover, that the linkage specification of a function’s name need not +be identical to the linkage specification of its type. The former might +affect how its external name is generated and the latter might affect its +calling convention.

    +
    +
    +
    +

    4.11. Access Control#

    +

    Access control information appears in several places:

    +
      +
    • +
      The access field of a_source_correspondence, which appears in most +declarative entities.
      +
      +
    • +
    • +
      using-declarations and access declarations in classes, which may adjust +the accessibility of inherited members.
      +
      +
    • +
    • +
      Base class entries, which indicate the kind of derivation from the base +class to the derived class.
      +
      +
    • +
    • +
      Lists of the friend classes and friend functions of a class. These are +also available in reversed form as befriending lists for classes and +functions, which indicate the classes which have named the befriended class +or function as a friend.
      +
      +
    • +
    +

    This information is useful to the back end only for generating symbolic +debugging information. The necessary access control checks will have been done +by the front end, and access control does not have an effect on code +generation.

    +

    Only class members are subject to access control. All other entities (and all +entities in C) will have access of as_public.

    +
    +
    +

    4.12. The Scope Entry#

    +

    Each scope in the source program is represented by a scope entry in the IL +(type a_scope). There are scope entries for:

    +
      +
    • +
      the file scope;
      +
      +
    • +
    • +
      each function definition scope;
      +
      +
    • +
    • +
      each block within a function;
      +
      +
    • +
    • +
      each “prototype” scope (for function prototypes in function declarations);
      +
      +
    • +
    • +
      each class, struct, and union type (when the type has a body);
      +
      +
    • +
    • +
      each namespace (in C++); and
      +
      +
    • +
    • +
      each condition (tested initialized variable in C++, e.g., in an “if” +statement).
      +
      +
    • +
    +

    The scope entry for the file scope is pointed to from il_header; it +contains lists of the file-scope entities in the compilation. In particular, +it points to a list of the functions in the compilation. Each function is +represented by an a_routine entry. A function without a body (i.e., an +extern function) has just a routine entry. For a function with a body, the +field assoc_scope in the routine entry gives the region number for the +memory region containing the function, which allows one to get a pointer to the +scope entry for the function scope. That scope entry points to the statements +for the function, and to lists of its parameter definitions and of local +constants, types, variables, labels, and block scopes.

    +

    One can see that the scope entry is the most important entry in terms of the +overall structure of the IL tree, in that it groups entities together into a +scope and also points down to the subscopes. Conversely, many IL entries point +back to their containing scope via the parent_scope field of their source +correspondence entry. (The scope entries themselves also contain a parent +pointer to their enclosing scope; this parent pointer is null for the file +scope.)

    +

    A scope entry points to lists of the entities that are defined in the scope: +constants, types, variables, routines, sub-scopes, etc. The lists may be used +or not depending on the type of scope:

    +
      +
    • +
      File scope (allocated in the file scope memory region):
      +
      +
        +
      • +
        types: used for tags (class, struct, union, and enum) and +typedefs. Top-level class definitions appear here.
        +
        +
      • +
      • +
        variables: used for static and external variables at the file scope.
        +
        +
      • +
      • +
        routines: used for functions both with and without definitions +(bodies).
        +
        +
      • +
      • +
        dynamic initializations: used for variables that have dynamic +initializations (eliminated by IL lowering).
        +
        +
      • +
      +
    • +
    • +
      Function or block scope (allocated in a function scope memory region):
      +
      +
        +
      • +
        types: used for tags (class, struct, union, and enum) and +typedefs that are local to the function or block. This pointer is +unusual in that it will point to a list of entries allocated in the file +scope memory region. Local classes appear here.
        +
        +
      • +
      • +
        variables: used for local static variables (one list; this pointer is +unusual in that it will point to a list of entries allocated in the file +scope memory region) and automatic/register variables (another list).
        +
        +
      • +
      • +
        scopes: for subscopes (blocks that have declarations). Note that every +{ } has an associated block statement, but a block statement only has +an associated scope if it contains local declarations.
        +
        +
      • +
      +
    • +
    • +
      Function prototype scope (allocated in the file scope memory region):
      +
      +
        +
      • +
        types: used for tags (class, struct, union, and enum) and +typedefs that are local to the prototype scope.
        +
        +
      • +
      +
      +
      Used only in C, not C++. Function prototype scopes are used to contain +types defined in prototyped parameter lists. When the function type is +part of a function declaration (i.e., there is no body), there’s nowhere +else to put the types. When the function type is part of a definition, the +prototype scope is effectively part of the function scope, but it must be +kept separate so that it can be available in the file scope memory region +as part of the information on the interface to the function.
      +
      +
    • +
    • +
      Class scope (allocated in the file scope memory region):
      +
      +
        +
      • +
        constants: used for class constants (an extension).
        +
        +
      • +
      • +
        types: used for tags (class, struct, union, and enum) and +typedefs. Nested types appear here.
        +
        +
      • +
      • +
        variables: used for static data members of the class.
        +
        +
      • +
      • +
        routines: used for member functions of the class. This includes all +member functions: static and non-static, virtual and non-virtual, inline +and non-inline, constructors, destructors, operator functions, and +conversion functions. Friend functions are not listed here (see the +friend and befriending lists under the class type and routine entries).
        +
        +
      • +
      +
    • +
    • +
      Namespace scope (allocated in the file scope memory region):
      +
      +
        +
      • +
        types: used for tags (class, struct, union, and enum) and +typedefs. Type members of the namespace appear here.
        +
        +
      • +
      • +
        variables: used for variable members of the namespace.
        +
        +
      • +
      • +
        routines: used for function members of the namespace.
        +
        +
      • +
      • +
        namespaces: used for nested namespaces.
        +
        +
      • +
      +
    • +
    +

    The entries appear on the lists in the order of declaration in the source +program, with the exception that tags and routines appear at the point where +the full definition occurs, not where the first forward reference appears. +Unreferenced entities do appear on the lists.

    +

    Not all intermediate language entities appear directly on the lists. An entity +appears on a list if:

    +
      +
    • +
      it is named in the source program; or
      +
      +
    • +
    • +
      it is a tag (class, struct, union, or enum); or
      +
      +
    • +
    • +
      it is a front-end-generated temporary variable or parameter.
      +
      +
    • +
    +

    Note that enumerated constants appear as part of the definition of the enum +tag and not ever on a constants list.

    +

    The type lists will also contain “placeholder typerefs,” which are +tk_typeref types with no name and no type qualifiers which provide +information about corresponding positions in different type lists. These are +useful to IL lowering in promoting types out of classes and namespaces. See +the section on placeholder typerefs in the IL lowering chapter of this +document.

    +

    For function scopes, the scope entry contains additional information:

    +
      +
    • +
      A pointer to the routine entry (in the file scope memory region).
      +
      +
    • +
    • +
      A list of parameter variables, and (for a nonstatic member function) a +“this” parameter variable.
      +
      +
    • +
    • +
      For constructors and destructors, a list of a_constructor_init entries +indicating initialization or destruction to be done.
      +
      +
    • +
    • +
      Labels within the function.
      +
      +
    • +
    • +
      A list of entries for computing the bounds of variable length array types.
      +
      +
    • +
    +
    +
    +

    4.13. Types#

    +

    a_type describes a type, which can be void, an integral or enumeration +type, a real, complex, or imaginary floating-point type, a fixed-point type, a +pointer, a reference, std::nullptr_t (the type of the nullptr keyword +in C++), an array, a GNU vector type, a class or struct, a union, a +function type, a pointer-to-member type, a typeref, or a fully generic +template-dependent type. Some of these type kinds – including fixed-point and +vector types – are optional (i.e., available only in specific configurations).

    +

    void, std::nullptr_t, the fixed-point types, and the floating types are +self-contained. Integer types and enumeration types point to a supplement +entry of type an_integer_type_supplement (conveniently accessed with the +macro integer_type_supp). Enumeration types are basically integer types, +with an additional pointer to either a list of a_constant entries that +define the members of the enumeration (for unscoped enumeration types), or a +scope entry (for scoped enumeration types; the scope entry then points to the +list of enumerator constants). The entries representing the enumerator +constants may, e.g., be of interest to a back end for generating symbol +debugging information.

    +

    The integral, fixed-point, and floating types are provided in a fixed set of +sizes, e.g., float, double, and long double for floating. The +sizes of the types can be configured easily, but they remain essentially +symbolic. That is, int remains int and not “integral type of size 4”.

    +

    A special type kind is used to represent “template parameters” in a broad +sense. This includes normal template parameters, but also otherwise unknown +template-dependent types like typename T::X where T is a template +parameter. This general concept “template parameter type” is also used to +represent the auto type specifier in modes that support it. The general +type kind for template-dependent types is tk_template_param.

    +

    The other kinds of types are derived types – they point to one or more other +types, and are used to build up type trees. For example, the type entry for +int can be pointed to by an array type entry to build an array of int. +A pointer type entry could be put on top of that to make a pointer to array of +int.

    +

    Derived types are built up from their constituent types in the obvious way:

    +
      +
    • +
      Array types point to the element type and indicate the number of elements.
      +
      +
    • +
    • +
      Function types point to the return type. Parameters of prototyped cases +(and of the types of defined unprototyped functions) are represented by a +list of a_param_type entries (pointed to indirectly by the type entry +via an entry of type a_routine_type_supplement).
      +
      +
    • +
    • +
      Pointer and reference types point to the underlying type. Pointers and +references are represented as variants of a common type kind.
      +
      +
    • +
    • +
      Pointer-to-member types point to the class type and the underlying type.
      +
      +
    • +
    • +
      class, struct, and union types point to a list of a_field +entries that define the members. There is a class type supplement that +provides a great deal of additional information, especially in C++. (See +below.)
      +
      +
    • +
    • +
      typedefs, type qualifiers (e.g., const and volatile), type operators such +as decltype, and various other types are represented by an entry called a +typeref, described in more detail in a subsection below.
      +
      +
    • +
    +

    Simple types are shared. For example, there would only be one type entry for +the type int, and it would be pointed to in all cases where it is needed. +There is also sharing of pointer types, reference types, pointer-to-member +types, and qualified types: the based types list pointer in a type entry points +to a list of types based on the type (e.g., pointer-to the type); when a based +type is created, it is placed on the list and can thereafter be found and +reused.

    +

    Types include information indicating their size and alignment (but beware of +typerefs, which normally have no size or alignment of their own [3], +and function types, which have no size or alignment). The sizes and alignments +are set by routines in types.c and class_decl.c and are taken on faith +in the rest of the front end. Incomplete types have size zero and have the +flag incomplete set to TRUE. Other types (including classes that contain +no nonstatic data members) normally have sizes greater than zero (some C and +C++ dialects treat some completely defined types as having size 0).

    +

    When support for near and far is enabled (e.g., in 16-bit Microsoft +mode), the near and far memory attributes are encoded as type +qualifiers. A qualifier appears only if it is not the default. For example, +if the source specifies far and the default in that context is far, no +qualifier is added. Back ends that need to know about memory attributes can +check the size of individual pointers (i.e., does the pointer have the size of +a far pointer) or use the function is_far_type (e.g., to determine the +calling method for function types). The memory attributes appear only when +il_header.near_and_far_enabled is TRUE; see also NEAR_AND_FAR_ALLOWED.

    +

    When support for named address spaces is enabled (a feature of Embedded C), +named address spaces are also encoded as type qualifiers. Unlike other +qualifiers, named address spaces are not encoded as a bit vector (e.g., a bit +per address space) but as a small integer indicating which address space is +selected (zero represents “no specific address space” which is sometimes +referred to as “the generic address space”). This small integer can be used as +an index in the array named_address_spaces; this array is defined in +targ_def.h and can be configured to describe the address spaces of a +particular target.

    +

    Variable length array types are a special case, because the number of elements +in the array is computed at run time, and so the dimension is represented as an +expression. However, the type itself cannot point to the dimension expression, +since the former belongs to the file-scope memory region and the latter to a +function-scope memory region. Instead, the flag has_assoc_vla_dimension is +set in the type entry, and the dimension expression is stored in an entry of +type a_vla_dimension, which appears on a linked list pointed to by the +routine’s IL scope entry (see find_vla_dimension in il.c). When the +bound of a VLA is unspecified (e.g., because it was declared with the [*] +syntax), is_vla will be TRUE but has_assoc_vla_dimension will be FALSE.

    +
    +

    4.13.1. Typerefs#

    +

    Typerefs are used to record additional information for existing types:

    +
      +
    • +
      typedefs giving a name for a type,
      +
      +
    • +
    • +
      type qualifiers such as const and volatile,
      +
      +
    • +
    • +
      typeof (a GNU extension) and decltype (a C++11 feature) constructs,
      +
      +
    • +
    • +
      specializations of alias templates,
      +
      +
    • +
    • +
      type splices (a C++26 feature),
      +
      +
    • +
    • +
      type-returning traits,
      +
      +
    • +
    • +
      type-transforming attributes,
      +
      +
    • +
    • +
      dependent type pack index specifiers, and
      +
      +
    • +
    • +
      (when configured with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE) +lexical information such as nested name qualifiers and alternative template +arguments.
      +
      +
    • +
    +

    Typeref type entries point to a typeref type supplement containing additional +information such as template argument lists, nested name qualifiers, and +operands of type operators.

    +

    For qualified pointer types, the typeref indicating the qualifier is on the +type of the pointer type: for int *const q the type is a const typeref +pointing to a pointer type entry, which points to an entry for int. +(By comparison, const int *q produces a pointer type entry pointing to +a const typeref, which points to an entry for int.)

    +

    It is often necessary for code that deals with types to access the target of a +typeref or chain of typerefs. Various convenience functions are provided for +this purpose, including skip_typerefs, skip_typerefs_not_typedefs, +skip_lexical_typerefs, etc.

    +
    +
    +

    4.13.2. Class Types#

    +

    Class types are class, struct, and union types [4]. Their +associated type entry always points to a class type supplement (conveniently +accessed with the macro class_type_supp), which carries additional +information especially relevant to C++.

    +

    In C, a struct or union type is relatively simple, and is defined by a +list of a_field entries. Each entry defines one field (member) of the +struct or union. The offset of a field is given as the combination of +a byte offset (the offset field) and a bit offset (the +offset_bit_remainder field). The latter is nonzero only for bit fields +(i.e., when is_bit_field is TRUE); a bit field also has a nonzero +bit_size, and its type (an integral type) is significant only as an +indication of the base type specified in the source program. Enum types and +integral types smaller than int can appear as the base type for a bit +field. A separate flag bit_field_is_signed indicates whether or not the +bit field is signed. Unnamed fields in the source program, which affect the +offsets of the fields that follow them (i.e., they introduce gaps), also appear +in the list of fields for the struct.

    +

    An associated scope is defined for a struct or union in C even though +the C language doesn’t really associate a scope with those constructs. The +scope is used only to represent the parent of the type’s fields. The type does +have a class type supplement, but that’s mostly necessary so that the pointer +to the associated scope can be recorded; the rest of the class type supplement +is irrelevant in C.

    +

    In C++, the fields are the nonstatic data members of the class, and the class +type supplement gives additional information about the class:

    +
      +
    • +
      A list of the base classes of the class (both direct and indirect).
      +
      +
    • +
    • +
      A list of the using-declarations (and access adjustments, from access +declarations), of friend classes and functions, and of classes that have +befriended the class. These are of interest to a back end only for +generating symbolic debugging information. Note that the friendship +information is available in normal and reversed forms: the “befriending” +information is backwards from the source form – it appears on the class +that is befriended, not the one that granted the friendship with a +friend declaration.
      +
      +
    • +
    • +
      A scope entry for the class, which contains the definitions of the static +data members (as variables) and member functions (as routines) of the +class. The scope is present only if the class has been defined.
      +
      +
    • +
    +

    The nonstatic data members are listed in declaration order, which (with the +default class allocation scheme) is the same as allocation order. Members of +base classes are not listed in the derived classes, even though they are in +some sense present by inheritance.

    +
    +

    4.13.2.1. Base Class Entries#

    +

    A base class entry describes a specific base class of a specific derived class. +It’s more than just the type of a base class – it describes how that class +type relates to the derived class:

    +
      +
    • +
      Where the storage for the base class appears in the derived class.
      +
      +
    • +
    • +
      The derivation path from the derived class to the base class; for virtual +base classes there may be more than one such path.
      +
      +
    • +
    • +
      The type of derivation, e.g., is the base class a virtual base class?
      +
      +
    • +
    • +
      The list of virtual functions of the base class that are overridden in the +derived class. (This information is useful for generating virtual function +tables.)
      +
      +
    • +
    +

    Base class entries are used for indirect base classes (i.e., base classes of +base classes) as well as for direct base classes.

    +

    The base classes list for a given class lists all of the base classes of the +class all the way down, in depth-first left-to-right order (i.e., an indirect +base class precedes the direct base class derived from it; not coincidentally, +this is the order defined by the language as initialization order.) A +nonvirtual base class can appear more than once on the list – it is marked as +ambiguous – but a virtual base class will appear only once, though it may have +more than one derivation path.

    +

    Base class entries are used in the IL wherever it is necessary to provide an +unambiguous specification of a base class instance.

    +
    +
    +

    4.13.2.2. Class Scopes#

    +

    If a class is defined, its class type supplement will point to a scope entry +that defines the contents of the class (except the nonstatic data members, +which are provided by the field list of the class type). The class scope will +contain:

    +
      +
    • +
      Constants, for class constants (an extension).
      +
      +
    • +
    • +
      Types, for types defined within the class (including nested classes).
      +
      +
    • +
    • +
      Variables, for static data members and instances of variable templates.
      +
      +
    • +
    • +
      Routines, for member functions, including static and non-static, virtual +and non-virtual, inline and non-inline, constructors, destructors, operator +functions, and conversion functions, but not friend functions. The routine +entries indicate any special attributes of each function, but the routine +list is just a list in declaration order. It’s not broken into sections or +indexed in any way. The only way to find all virtual functions, for +example, is to go through the list and examine each routine to see if it is +virtual.
      +
      +
    • +
    +
    +
    +

    4.13.2.3. Class Member Declaration Lists#

    +

    The lists described above group the members of a class by category, and none of +them accounts for constructs like a static_assert declaration, which +declares nothing. When MAINTAIN_CLASS_MEMBER_LIST is configured to TRUE, +the class type supplement of every defined class also points to the +member_declarations list, which has one an_il_entity_list_entry per +declaration that appeared in the body of the class, in the order in which the +declarations appeared. For example, the list built for

    +
    struct S {
    +  static_assert(sizeof(int) == 4);
    +  int a, b;
    +  template <class T> void f(T);
    +  friend void g();
    +  enum E { e1, e2 };
    +};
    +
    +
    +

    identifies, in order, a static assertion, a field (a), a field (b), a +template, a routine, and a type.

    +

    Note that:

    +
      +
    • +
      A friend declaration that appears in the body is included even though the +entity it declares is not a member of the class.
      +
      +
    • +
    • +
      Entities that are not explicitly declared in the body are not included: +that is the case for members that the front end generates (e.g., an +implicitly-declared default constructor) and for template instantiations +that are triggered while the body is being processed. A member that is +explicitly defaulted or deleted is declared, and is therefore included.
      +
      +
    • +
    • +
      An anonymous union is represented by the entry for its type; no entry is +created for the unnamed field through which the members of the union are +accessed (that field can be reached through the +anonymous_union_field pointer of the class type supplement).
      +
      +
    • +
    • +
      The closure class of a lambda expression that appears in the body (e.g., +in a default member initializer) is not included; that class is reached +through the a_lambda entry for the expression.
      +
      +
    • +
    • +
      An enumerator is not included because the declaration of its enumeration +type is; the enumerators can be reached through that type.
      +
      +
    • +
    • +
      A member template is represented by the entry for its template, not by an +entry for the prototype instantiation of the templated entity (see +Templates).
      +
      +
    • +
    • +
      A using-declaration that names an overload set (or, with using +enum, an enumeration) produces several a_using_decl entries but only +one entry on the list.
      +
      +
    • +
    • +
      An entity that is declared more than once in the body is represented by one +entry per declaration. For example, a nested class that is first declared +and later defined in the same body appears twice.
      +
      +
    • +
    +

    The list of an instantiated class template specialization describes the +declarations of the instantiated body.

    +
    +
    +

    4.13.2.4. Class Layout#

    +

    Class layout is done by routines in layout.c, and the decisions made are +recorded in the IL in the form of offsets, sizes, and alignments. The class +layout can be configured in various ways, or can be replaced in its entirety. +Class layout decides on:

    +
      +
    • +
      Offsets of nonstatic data members (fields) within the class.
      +
      +
    • +
    • +
      Offsets of base classes within the class. For virtual base classes, +offsets of the information that allows access to the virtual base classes +(typically, a pointer to the virtual base class).
      +
      +
    • +
    • +
      Offsets of virtual function information (typically, a pointer to a virtual +function table).
      +
      +
    • +
    • +
      Ordering of base classes and members, and insertion of necessary alignment +between them.
      +
      +
    • +
    +

    Virtual function table pointers and virtual base class pointers can be shared +with base classes. That is, space for such pointers need not be allocated in a +derived class if they are present in a base class; the derived class can use +the pointer in the base class.

    +

    There are many configuration macros that control class layout. See +targ_def.h.

    +
    +
    +

    4.13.2.5. C++/CLI Types#

    +

    In addition to the standard types, C++/CLI has

    +
      +
    • +
      handle and tracking reference types, which are represented as +tk_pointer types, but aren’t considered to be standard pointers or +standard references;
      +
      +
    • +
    • +
      interior_ptr and pin_ptr types, which are variants of standard +pointer types with certain added attributes and restrictions (they only +appear as the types of local variables, parameters, or return types);
      +
      +
    • +
    • +
      managed class types (refstruct, refclass, valueclass, interfaceclass), which are represented like standard +class types, with a value in the cli_class_type_kind field that +indicates the kind of managed class;
      +
      +
    • +
    • +
      enumclass types, which are similar to C++11 scoped enum types and +similarly represented;
      +
      +
    • +
    • +
      CLI array types, which are represented as managed class types tagged with +the is_cli_array field; and
      +
      +
    • +
    • +
      delegate types, which are represented as managed class types tagged with +the is_delegate_class field.
      +
      +
    • +
    +

    Fundamental types usually have corresponding value class types (e.g., int +corresponds to the System::Int32 value class type). In general, types +written in the source in either form are converted to the fundamental type +version. In cases where a managed type is required, the fundamental type is +converted to the value class, so for example “int ^” becomes “handle to +System::Int32” as soon as it is created. Otherwise, conversions between +the two kinds of types are always indicated explicitly. In particular, in +expressions a conversion from one form to the other will be indicated +explicitly, e.g., with a box or unbox operator.

    +
    +
    +
    +
    +

    4.14. Namespaces#

    +

    Namespaces are represented by entries of type a_namespace. Such an entry +is used for a namespace definition, in which case it points to a scope entry +that describes the contents of the namespace, and also for a namespace alias, +in which case it points to another namespace entry.

    +

    Entries of type a_using_decl describe using-directives and +using-declarations that appear in the source program. This +information is not needed for code generation, but may be useful in the +generation of symbolic debug information or for source-to-source +translation.

    +
    +
    +

    4.15. Constants#

    +

    a_constant describes a target machine constant, which can be an integer, a +string, a fixed-point constant, a floating-point constant, a complex or +imaginary constant, an address, or a pointer-to-member. Nontype template +parameters and the UPC identifiers THREADS and MYTHREAD are also +represented using a_constant entries. The constants are kept in target +form, and should not be manipulated without using the target-specific routines +for that purpose. Fixed-point constants are stored as a_fixed_point_values. Floating-point constants are stored as an_internal_float_value. String +constants are stored as a string of bytes in the target character set with an +associated length (to avoid any question about extra or missing null characters +in the string). The text of string constants is always allocated in the file +scope memory region to avoid some memory region problems.

    +

    Integers are usually maintained in a host large integer +(a_host_large_integer/a_host_large_unsigned) regardless of the size +or signedness of their actual integral type. They are always properly +masked and sign extended. If a host large integer is insufficiently large, +the front end can be configured to use a more general (but computationally +less efficient) representation of integer values (see the configuration +macro INTEGER_VALUE_REPR_IS_A_HOST_INTEGER). In either case, +an_integer_value is the type to use internally to represent an integer +constant.

    +

    Constants are also used as initial values of variables. When those variables +are aggregates (arrays or classes), some special kinds of constant entries are +used to represent aggregates of constants and repetition of constants within +those aggregates. Such constants are acting more as a structuring entity than +as simple constants; it’s just convenient to use the a_constant entry for +that function as well. Getting even farther afield, there is even a constant +kind (ck_dynamic_init) that indicates an element in an aggregate constant +that is in fact not a constant at all, and must be computed at run time and +placed at that position in the aggregate. The structure of the aggregate +constant will match the structure of the variable being initialized. For +example, the initial value for a variable whose type is “array of 4 structures +containing 2 integer fields” will be an aggregate constant containing a list of +four constants, each of those an aggregate constant containing a list of two +integer constants. Aggregate constants need not fully initialize an aggregate +(i.e., there may be fewer constants than there are members of the aggregate); +any members not explicitly initialized are implicitly initialized to zero (even +when the variable being initialized is non-static).

    +

    Most constants, specifically those used in expressions, are shared and reused, +so that only one constant 0, for example, need be allocated. Constants +used as constant initial values, however, are (and must be) unshared. [5] +Since the aggregating kinds of constant entries are only used in initial +values, it follows that they are always unshared. In pcc mode, string +constants are considered writable and are not shared.

    +

    In some cases, a program may include a cast of a constant value to another +type, and the result (clearly constant) may be unrepresentable in any of the +normal forms. An example is an integer constant cast to a pointer type. For +these situations, the a_constant entry has the implicit_cast field. +When set, it indicates that the value of the overall constant is to be the +constant value cast to the type indicated by the type field. The back end +must determine the exact value to be used.

    +

    Address constants are used to refer to the addresses of variables, +functions, string literals, etc. The offset in address constants is +expressed in bytes and is not scaled by the size of the object pointed to +(unlike in the C and C++ languages). Address constants are only used for +addresses that are truly constant, not, for example, for the addresses of +auto variables. Note, however, that the constant value may not be +known until link time, i.e., it might not be a compile-time constant.

    +

    Pointer-to-member constants represent the location of a particular data member +or member function of a class within an arbitrary instance of that class, i.e., +what is written in source as something like &A::xx (with xx a nonstatic +member of A). They are defined in a high-level form rather than (for +example) as an offset within the class, to leave it to IL lowering or the back +end to choose an implementation for pointers to members.

    +

    Wide character constants are represented as integral constants. Wide string +literals are represented as string constants. There are routines in +literals.c that do the necessary packing.

    +

    When character or string literals contain a universal-character-name (e.g., +\u00d6), the UCN value is converted from Unicode to the appropriate +character value or multibyte character sequence and stored in the string.

    +

    In C++/CLI, string literals start out as standard C++ string constants, and are +converted to C++/CLI strings if the context requires it. So, for example, if a +standard string literal is passed as an argument to a function that takes a +parameter of type “System::String^”, the string will be converted to +a C++/CLI string. This is done by setting the constant type to “handle to +System::String” without setting the implicit_cast flag. There is no +conversion of the characters in the string to Unicode (or in any other way), in +spite of what the ECMA standard seems to require. Wide string literals can +also be converted to C++/CLI strings in this way, and in that case the string +contents are treated as Unicode (as they always are in Microsoft mode, and +therefore in C++/CLI mode; but still no conversion is done). Having C++/CLI +strings represented as constants is a little strange, since ultimately they +have to result in creation of a class object on the heap, and use of its – +non-constant – address; however, MSVC treats such strings as constants, so +emulating the Microsoft compiler is easier when they are represented as +constants. It is left to back ends to transform these constants into +executable code as needed.

    +

    The front end generally attempts to fold constant-expressions into a single +a_constant node. The expression that led to the constant is also recorded +in the expr field in the a_constant entry. If this field is nonnull, +it points to the expression tree which produced the constant when folded; the +resulting constant is not shareable.

    +
    +
    +

    4.16. Variables#

    +

    a_variable describes a variable, parameter, static data member, instance of +a variable template, temporary, or structured binding. It indicates the type +and storage class. The storage class can be sc_auto, sc_register, +sc_static, sc_extern (meaning a reference to an external variable +defined in another compilation), or sc_unspecified (meaning a definition of +a variable visible to other compilations). The storage class is standardized +during declaration processing. Parameter variables can only have storage +classes of sc_auto or sc_register. File-scope and namespace scope +variables, instances of variable templates, and static data members can only +have storage classes of sc_static, sc_extern, or sc_unspecified. +Function- and block-local variables can only have storage classes of +sc_auto, sc_register, or sc_static.

    +

    Variables declared with a named-register storage class (an Embedded C +extension) have storage class sc_unspecified (not sc_register) but also +have the flag has_named_register_storage_class set to TRUE. The register +is described using a small integer stored in the variant field +asm_name_or_reg.id, which can be used to index the array +named_register_storage_classes. This array is defined in targ_def.h +and can be customized to describe the named-register storage classes available +on a particular target.

    +

    If the variable has an initial value, the field init_kind indicates whether +the variable should be statically initialized to a constant value (simple or +aggregate) or dynamically initialized to a constant or non-constant value +(simple or aggregate). In the dynamic initialization case, the variable points +to a dynamic initialization entry that indicates the initialization to be done. +(More on this below.) Note that static initialization is never used for +non-static local variables, even ones initialized with a constant value: static +initialization initializes the entity once, at program startup time, whereas an +automatic local variable must be initialized each time the function is invoked +and the variable declaration is reached. Structured bindings (a C++17 feature) +that refer to array elements or to fields are represented as variables, but +they are really aliases for simple expressions referring to parts of the +associated (unnamed) container variable. These bindings have an +initk_binding initializer kind and point to the aliased expression via +initializer.binding. Structured bindings that bind to a +std::tuple-like container are ordinary reference variables with +initk_dynamic initializers.

    +

    An uninitialized static variable is considered to be implicitly initialized to +zero. There is also an initk_zero initialization kind, which can be used +to explicitly initialize a variable to zero, statically or dynamically. On an +external variable, such initialization has the added function of indicating +that the variable is a true definition rather than a tentative definition.

    +

    If the address of the variable has been taken anywhere (implicitly by +conversion of an array to a pointer or in binding of a reference, or explicitly +by use of the & operator), the flag address_taken will be set.

    +

    If a variable is a local static variable of a function, +referenced_non_locally is TRUE if the variable is referenced from a +different function, specifically from a member function of a local class. This +may have an effect on aliasing analysis.

    +

    Local static variables create a memory-region difficulty: the variable entry +must be allocated in the file scope memory region, because the variable can be +referenced from the bodies of member functions of local classes. Dynamic +initialization of the variable, however, can be based on an expression +referencing a local (nonstatic) variable of the function, and therefore the +dynamic initialization must be allocated in the function scope memory region. +The a_local_static_variable_init entry solves this problem. When a local +static variable has initialization that must be allocated in the function scope +memory region, the variable init_kind is set to initk_function_local. +This is an indication that the variable is initialized, but details of the +initialization are not available in the file scope. In the function or block +scope in which the variable is defined, there will be +a_local_static_variable_init entry on the local_static_variable_inits +list of the scope. That entry will point to the variable, and give the +initialization details. Conceptually, the initialization information in the +local initialization entry is part of the variable information (it provides the +true values for the init_kind and initializer fields of the variable); +it’s in a different place because of memory region issues. The routine +get_variable_initializer can be used to fetch the complete initializer +information for a variable. It will search for and retrieve the function-local +information when necessary. Local static variables with initial values that +are simple (non-aggregate) constants always use initk_static initialization +rather than the initk_function_local form. This is done so that the values +of integral constant variables can be retrieved as constants while compiling +local classes. initk_function_local is used for dynamic initialization and +for aggregate constant initialization.

    +

    Temporary variables are generated by IL lowering, for class temporaries and +when initializing references. Temporary variables are also generated for +anonymous unions; see Anonymous Unions for more information.

    +
    +
    +

    4.17. Dynamic Initialization#

    +

    A dynamic initialization entry (type a_dynamic_init) is used to represent +initializations that require the execution of code at runtime, i.e., that +cannot be done as static initializations to a constant.

    +

    The kind field of the entry indicates the kind of initialization to be +done:

    +
      +
    • +
      Initialization to a constant. Note that this is different than static +initialization to a constant, in that it gets done at a particular time and +possibly more than once. The constant here is unshared and may be an +aggregate (one that is completely constant).
      +
      +
    • +
    • +
      Initialization to an expression. An expression is evaluated and its value +is the initial value.
      +
      +
    • +
    • +
      Initialization by a constructor. A constructor routine is called to +initialize the entity.
      +
      +
    • +
    • +
      Initialization by a routine returning a class object. A routine is called +and the value it returns (by calling a copy constructor) initializes the +entity.
      +
      +
    • +
    +

    A dynamic initialization entry can also indicate a destructor that must be +called to destroy the entity initialized. [6] Such dynamic +initialization entries will be linked onto the destructions list of an +object lifetime entry. The destruction is to be done any time the region +of the object lifetime is exited, and IL lowering generates the appropriate +destructions. See Object Lifetimes.

    +

    A dynamic initialization entry indicates what the initialization is to +do, but it does not indicate where the initialization is to be done +(except if the entity being initialized is a complete variable), and it +does not indicate when the initialization is to be done. Dynamic +initialization entries are used in several cases, and the context in each +case provides the additional information needed:

    +
      +
    • +
      For initialization of file-scope variables, instances of variable +templates, or static data members, the variable points to the dynamic +initialization entry, and the dynamic_inits list from the scope entry +for the file scope indicates the order in which the initializations should +be performed. Variables from namespaces also appear on this same list, +since their initializations are intermixed with those of the file-scope +variables.
      +
      +
    • +
    • +
      For initialization of function and block variables, the variable points to +the dynamic initialization entry, and there is an stmk_init statement +in the executable code of the function that points to the same dynamic +initialization entry and indicates the point at which the initialization +should be done. An stmk_init statement can appear in the same block as +the variable declaration or in a nested block. If the variable is a local +static variable, the initialization is to be done only the first time the +stmk_init is reached, and corresponding end-of-program destruction must +be done only if the initialization was done. Note that if a local variable +uses dynamic initialization it must have an associated stmk_init +statement.
      +
      +
    • +
    • +
      For initialization of temporaries in the middle of expressions, an +enk_temp_init node points to a dynamic initialization entry that +indicates the initialization to be done.
      +
      +
    • +
    • +
      For initialization of storage allocated by new, an enk_new_delete +node points to a dynamic initialization entry that indicates the +initialization to be done. These dynamic initialization entries never +indicate destruction.
      +
      +
    • +
    • +
      For destruction of storage in a delete, an enk_new_delete node +points to a dynamic initialization entry that indicates the destruction to +be done. These dynamic initialization entries never indicate +initialization.
      +
      +
    • +
    • +
      For initialization of members in a constructor-initializer (either +user-written or front-end-generated), an entry of type +a_constructor_init indicates the member or base class to initialize and +points to a dynamic initialization entry to indicate what to do. The order +of the a_constructor_init entries gives the order in which the +initializations should be done. These dynamic initialization entries never +indicate destruction (except when exceptions are enabled, in which case the +destructions indicated are to be done if an exception is thrown before the +constructor completes).
      +
      +
    • +
    • +
      Similarly, for destruction of members in a destructor (which can only be +front-end-generated), an entry of type a_constructor_init indicates the +member or base class to destroy and points to a dynamic initialization +entry to indicate what to do. The order of the a_constructor_init +entries gives the order in which the destruction should be done (i.e., if +one looks at a constructor and destructor for a class, the entries on the +destructor will be in the reverse order of those on the constructor). +These dynamic initialization entries never indicate initialization.
      +
      +
    • +
    • +
      For non-static data member initializers (NSDMIs), more recently renamed +as default member initializers (DMIs), the field entry initializer +field points to a dynamic initialization entry giving the initializer. +If such an initialization is not overridden in a given constructor, the +a_constructor_init entry for the field will have +use_field_initializer TRUE to indicate that the initial value comes +from the field initializer.
      +
      +
    • +
    • +
      For dynamic initialization of entities within an aggregate, for example
      +
      +
      int i[3] = {1, 2, j+k};
      +
      +
      +
      +
      dynamic initialization entries at two levels are needed. The variable +i will point to a dynamic initialization entry that indicates the +overall initialization. Because the initialization is an aggregate +initialization containing a non-constant value, the dynamic initialization +will have the kind dik_nonconstant_aggregate and will point to a +ck_aggregate constant. That constant points to a list of the constants +in the aggregate, beginning with the constants 1 and 2. Following +that is another constant entry of kind ck_dynamic_init which indicates +“this position in the aggregate is not really a constant; here’s what needs +to be done to compute it” and points to another dynamic initialization +entry, this one of kind dik_expression and indicating that the value to +use for the initialization is the expression j+k.
      +

      +
      Within the aggregate constant list, ck_init_repeat constants are used +to repeat a particular ck_dynamic_init initialization a specified +number of times. This is needed to do constructor initialization of arrays +of classes.
      +

      +
      In this aggregate case, the top-level dynamic initialization entry serves +as more of an aggregating construct than as a specification of a dynamic +initialization. It shouldn’t come as much of a surprise, then, to learn +that to specify only destruction for an aggregate, one uses a top-level +dik_nonconstant_aggregate dynamic initialization entry as is done in +the initialization case, and the destruction is specified in the +lower-level dynamic initialization entry. The troublesome thing about this +form is that one cannot tell just by looking at the top-level dynamic +initialization whether the overall construct does initialization, +destruction, or both. One must find and examine the lower-level dynamic +initialization entry.
      +
      +
    • +
    • +
      For returns from routines that return a class by value, the stmk_return +statement points to a dynamic initialization that indicates the way to +create the class being passed back to the caller.
      +
      +
    • +
    • +
      For expressions that are operands of throw, the throw expression +node points to a dynamic initialization that indicates the way to copy the +value for use by the runtime.
      +
      +
    • +
    • +
      For parameters of catch clauses, the catch clause points to a dynamic +initialization that describes the way to initialize the parameter from the +runtime’s copy of the thrown object.
      +
      +
    • +
    +

    IL lowering rewrites all dynamic initializations that are not valid in C, and +therefore constructor and destructor calls and non-constant aggregates do not +appear in the lowered IL.

    +
    +
    +

    4.18. Object Lifetimes#

    +

    In C++, class types can have associated destructors, which are called to +destroy objects of the class type at the ends of their lifetimes. These calls +are implicit: the programmer does not write them, and the compiler generates +them in the appropriate places. For example, on a goto out of a block +containing a class variable, the destructor for the variable must be called. +If there are several possible ways to exit the block (e.g., flowing off the +end, gotos, exceptions), the destructor must be called in each case.

    +

    The IL does not make the needed destructor calls explicit (in fact, for +exception handling, the needed destructor calls would be done by the runtime, +so there’s no way to put them in the IL without dictating a particular +implementation of exception handling). Instead, it gives information about +needed destructions and the associated object lifetimes in such a way that a +back end can easily generate the required destructor calls. (IL lowering puts +in those calls, so a back end working from the lowered IL need not deal with +object lifetimes.)

    +

    The IL concept of an “object lifetime” is modeled on a source language concept, +the idea that an object’s lifetime (the time during which it has a meaningful +value) might be different than the lifetime of the storage for the object. +That is, the object is constructed, used, and destroyed, and then the storage +that contained the object might remain around for some time longer, but it no +longer contains meaningful information and is no longer an object.

    +

    It should be noted that from an IL point of view, the concept of object +lifetime is only applied to objects of class types having destructors. From a +strict language point of view, other kinds of objects do have object lifetimes, +but those object lifetimes are not very interesting because they always match +the lifetime of the object storage; more precisely, in the absence of a +destructor there is no way to tell the difference between an object whose +lifetime has ended and one that is still active, as long as the storage remains +allocated to the entity. Therefore there is no benefit in associating IL +object lifetimes with entities that do not need destruction, and there is a +benefit – space savings – in not doing so. Note that this means that IL for +C programs, which by definition involve no constructors, never includes object +lifetimes.

    +

    The IL entry an_object_lifetime represents and defines an object lifetime. +There are several kinds of object lifetimes, each associated with a certain +kind of entity in the IL: [7]

    +
      +
    • +
      A static object lifetime, which lasts until the termination of the program. +For packaging reasons, there is a global static object lifetime and +possibly several function static object lifetimes (one for each function +that contains destructible local static entities). Such lifetimes are +bound to the file scope and function scopes.
      +
      +
    • +
    • +
      A block object lifetime, which lasts until the termination of a function or +block scope. Such a lifetime is bound to a function or block scope. There +is also a variant of this kind of lifetime, referred to as a +block-after-label lifetime, that lasts from a label or (in +long-lifetime-temporaries mode) a switch case or default label to the end +of the scope. The block-after-label lifetime points to a statement that is +or contains a label or to a stmk_switch_case statement, respectively.
      +
      +
    • +
    • +
      A try-block object lifetime, which surrounds the execution of a try +statement and its associated catch clauses, and is bound to a +try-supplement.
      +
      +
    • +
    • +
      An expression temporary object lifetime, which lasts until the end of a +full expression, and is bound to an expression node of kind +enk_object_lifetime, or to a dynamic initialization entry.
      +
      +
    • +
    +

    Each dynamic initialization in the IL that requires end-of-lifetime destruction +is placed on the linked list of destructions attached to the proper object +lifetime entry. The destructions in a given lifetime are linked together by +the next_in_destruction_list pointer, in the order in which they should be +destroyed (that is, the reverse of the order of construction). The +destructions pointer in the object lifetime entry points to the first +initialization on the list (the last one constructed and the first one to be +destroyed).

    +

    Not all dynamic initializations are placed on a lifetime list. Initializations +of nonclass objects, or objects of class types that have no destructors, +clearly do not need to go on lifetime lists. Even initializations of objects +of class types with destructors are put on lifetime lists only if the +destruction of the object is automatic at the end of the lifetime, e.g., not +for new (the programmer controls the time of destruction) or return by +constructor (the destruction is done by the caller, not the subroutine).

    +

    Each object lifetime has a parent_lifetime pointer, and also a +parent_destruction_sublist pointer giving the position of the child +lifetime relative to the destructions in the parent. This makes a tree +structure that one can enter at some inner lifetime and follow upward. The +path upward from a given starting point is referred to as the “cleanup chain” +starting at that point. For example:

    +
    struct A { A(); ~A(); };
    +void () {        // Lifetime 1 associated with this block
    +  A x;
    +  A y;
    +  {              // Lifetime 2 associated with this block
    +    A xx;
    +    // Position R
    +    A yy;
    +  }
    +  A z;
    +}
    +
    +
    +

    Lifetime 1 has the destructions list (z, y, x) and lifetime 2 has the +destructions list (yy, xx). Lifetime 2’s parent_lifetime pointer +points to lifetime 1, and its parent_destruction_sublist pointer points to +the initialization entry for y.

    +

    One can see that if a return statement appeared at position R above, one +would want to destroy xx from the inner lifetime and y and x from +the outer lifetime. How would a back end figure that out? Well, as the back +end processes the IL, it would keep track of the latest +initialization-with-destruction encountered, i.e., the one for xx when at +position R. The pointer to that initialization defines the cleanup chain that +applies at position R. Starting with that initialization, the back end would +follow the next_in_destruction list to the end, generating destructions for +the entities on that list. Then, using the lifetime pointer in the last +dynamic initialization and the parent_lifetime pointer in the lifetime +pointed to, it would go to the parent lifetime, entering its destructions list +at the point indicated by parent_destruction_sublist. It would then +generate destructions for the entities on that list. The process would +continue upward through parent lifetimes until the lifetime for the function is +processed.

    +

    Generating destructions at a goto is almost as easy. The goto +statement has a common_lifetime field set by the front end. It indicates +the first object lifetime that the goto and the label have in common, that +is, the innermost object lifetime that appears on the cleanup chains for both +the goto and the label. The destructions for the goto are generated by +working upward through the cleanup chain, as for the return case, except +that processing stops when the common lifetime is reached (before generating +any destructions in that lifetime; if the goto is directly in the common +lifetime, then no destructions are generated).

    +

    When labels appear, and are followed by declarations for destructible objects, +a new block-after-label lifetime is begun at the label. This is necessary for +backwards gotos:

    +
    struct A { A(); ~A(); };
    +void () {     // Lifetime 1 begins
    +  A x;
    +L:;           // Lifetime 2 begins after label
    +  A y;
    +  if (i) goto L;
    +}
    +
    +
    +

    The destruction of x will be in lifetime 1, and the destruction of y +will be in lifetime 2. The goto is in lifetime 2, and the label is in +lifetime 1 (the parent of lifetime 2), so the common lifetime for the goto +is lifetime 1. The cleanup code at the goto therefore destroys y as it +exits lifetime 2, but it does not destroy x.

    +

    Switch case labels are treated like other labels and can begin new object +lifetimes if necessary. The labels generated for break and continue +statements do not ever begin new lifetimes.

    +

    Destructible temporaries are treated much the same way as destructible +variables, and their initializations are likewise placed on lifetime lists. In +its choice of which lifetime to use in each case, the front end represents its +decisions on the lifetimes of temporaries. For example, when a reference +variable is bound to a temporary, the C++ language dictates that the lifetime +of the temporary is extended to match the lifetime of the reference (e.g., for +a static reference the temporary lasts until the end of the program). The +front end would represent this in the IL by placing the temporary on the same +lifetime as the reference variable.

    +

    In the modern C++ language, normal temporaries last until the end of the full +expression within which they occur. In the front end, this is represented by +placing an expr-temporary lifetime around the full expression and placing the +destructions of any temporaries therein. In older dialects of C++, however, +including the dialect implemented by cfront, temporaries lasted until end of +scope. This mode is implemented by the EDG C++ front end in cfront +compatibility mode and when --long_lifetime_temps is specified. To be more +precise, in long-lifetime-temporaries mode temporaries survive until end of +scope or until a label, and they are limited to a single statement when the +statement is a conditional dependent statement, or to a full expression when +the expression is the tested expression in a conditional or loop statement, or +the initializer for a local static variable. Since long-lifetime temporaries +are destroyed at a label, when walking a cleanup chain and going from a +block-after-label lifetime to its parent one should ignore destructions for +temporaries until one reaches and exits from a block lifetime (all temporaries +in the block lifetime and any intervening block-after-label lifetimes were +destroyed at some label, and are no longer active). Because of the destruction +of temporaries at labels, in this mode block-after-label lifetimes are required +at some labels even when there are no destructible objects created after the +label.

    +

    In addition to its use in generating destructions on programmed exit from +lifetimes, the block object lifetime information is also intended to be useful +in generating the cleanup description information needed by the runtime support +for exception handling. With the default configuration, IL lowering will use +the object lifetime information to generate data structures that support EDG’s +implementation of exception handling. Those who wish to create a +higher-performance version of exception handling may find it useful to turn off +lowering of exception handling features and to use the object lifetime +information directly in the back end to generate the required cleanup +information. In either case, because the object lifetime information is used +to generate exception handling information, it includes some information beyond +what is required to generate cleanup on block exits:

    +
      +
    • +
      There is information about the mem-initializers (both user-written and +front-end-generated) in constructors, and about the similar +(front-end-generated) data structure in destructors.
      +
      +
    • +
    • +
      For each new that does allocation inline (rather than letting a +constructor do it), a dynamic initialization entry is generated to indicate +the freeing of the storage to be done if an exception is thrown before the +storage is fully initialized.
      +
      +
    • +
    • +
      For local static variables, a block object lifetime is placed around the +entire initialization and bound to the local static variable initialization +IL entry. Exiting this lifetime via an exception causes the runtime to +reset the state so that the local variable is marked as uninitialized. If +its declaration is encountered again on a subsequent call, the +initialization will be attempted anew.
      +
      +
    • +
    • +
      For aggregate classes or arrays initialized by a brace-enclosed list, +individual sub-initializations will indicate destructions to be done if an +exception is thrown before the complete aggregate is initialized. Once the +aggregate has been completely initialized, these destructions to undo +partial construction no longer apply.
      +
      +
    • +
    +

    One of the unfortunate consequences of using dynamic initialization entries to +represent destructions is that the contextual nature of dynamic initialization +entries (they don’t indicate the entity to be initialized; it’s implied by the +context) – which is an advantage when the entries are used to do +initializations – is somewhat of a disadvantage when the entries are used to +do destructions. Specifically, unless one saves some information in the +dynamic initialization entry at the time it is processed as an initialization, +it is very hard to know what to destroy when one processes it as a destruction. +However, it’s not hard to solve this problem from a practical point of view: +one just adds a field to the dynamic initialization entry to point to +back-end-specific information recorded at the time that the initialization is +processed, and that information is then available, and in just the right form, +when the destruction is processed. That’s the technique used by IL lowering.

    +
    +
    +

    4.19. Routines#

    +

    a_routine describes a function. It indicates the type and storage class. +The storage class can be sc_static, sc_extern (meaning a reference to a +function defined in another compilation), or sc_unspecified (meaning a +definition of a function visible to other compilations). The storage class is +standardized during declaration processing. A function with a body will have +storage class sc_unspecified or sc_static; a function without a body +will have storage class sc_extern.

    +

    The type of a function is always a function type, which describes the +external interface to the function: its return type, its parameter types, +etc. A nonstatic member function will also have an implicit “this” +parameter, with a type of const pointer-to (possibly qualified) class. +The parameter types might have associated default argument value +expressions, although that information is useful to a back end only for +generation of symbolic debugging information, since calls of the routine +will have the default argument values supplied.

    +

    The routine entry also indicates whether or not the routine is inline, virtual, +and/or front-end-generated. (The front end generates routines for constructors +and destructors, assignment operator functions, and, when IL lowering is done, +for global initialization and termination routines, runtime routines, and +wrappers for constructors with default arguments.) The special_kind field +indicates whether or not the function is a C++ special function such as a +constructor. If the special_kind indicates that the routine is an operator +function, opname_kind indicates the kind of operator function it is. The +special_kind is significant to a back end using the unlowered C++ +intermediate code in that wrapper code needs to be generated for constructors +and destructors. Other than that, special_kind and opname_kind are +mostly of interest for generating symbolic debugging information and mangled +names.

    +

    The routine entry points to a list of classes that have befriended the +function. Those classes will have the function on their friend lists.

    +

    If the function is a virtual function, the routine entry indicates a virtual +function number assigned to the routine. Typically, this will be used as the +function’s index into a virtual function table, but since the unlowered C++ IL +leaves virtual function access as an abstraction, it’s only a helpful +identifying number at that level.

    +

    If the function has a body, the routine entry indicates the function +definition number and the memory region that contains the function +definition. By indexing through il_header.function_def_table, one can +get to the scope entry for the function (in the proper function scope +memory region). That scope entry points to the statements and local +declarations of the function. It also points to variables for the +parameters of the function, including a “this” parameter variable if +necessary. The parameter and “this” variables will match the parameter +and “this” types in the function type. (In non-prototyped functions, the +function type parameters might be promoted versions of the parameter +variable types.) For parameters that are passed using a copy constructor +(indicated by a flag in the parameter type entry), a back end using the +unlowered C++ IL may have to expect to receive the address of the class +entity rather than its value, and to do implicit indirections on the +references to the parameter.

    +

    The address_taken flag in the routine entry will be set if the address of +the function has been taken. Merely calling the function does not cause the +address_taken flag to be set, even though the IL for a call refers to the +routine address.

    +

    An exception specification that appears on a function declaration is +represented by an entry of type an_exception_specification, referred to +by means of the exception_specification field of the routine type +supplement. When the function is declared with no exception specification +(meaning that any exception might be thrown) the +exception_specification pointer will be NULL. The exception +specification entry representing a dynamic exception specification has a +pointer to a linked list of entries of type +an_exception_specification_type, each of which indicates a type of +exception that will be thrown from the given routine; that pointer is NULL +to indicate that no exceptions will be thrown. An exception +specification representing a noexcept specification points to an entry +of type a_constant representing its operand (or NULL if no operand is +specified).

    +

    When ASM_FUNCTION_ALLOWED is TRUE, asm functions are recognized and +passed uninterpreted to the back end. They are represented in the IL like +ordinary functions, except that they have a storage class of sc_asm and the +function body (pointed to from the associated scope entry) is represented by an +stmk_asm statement. The asm entry to which the latter refers points is a +null-terminated string containing the text that appeared in the source; +comments are removed unless INCLUDE_COMMENTS_IN_ASM_FUNC_BODY is TRUE.

    +

    In order to save space in the a_routine structure, some (mostly +GNU-specific) fields with default values that are rarely changed are located in +the a_gnu_routine_supplement struct, which is pointed to by the +gnu_extra_info field. This supplement is only allocated when one of the +fields has a non-default value.

    +

    The GNU function multiversioning feature (available in GNU C++ modes where +gnu_version >= 40800), allows for declarations/definitions of multiple +routines with the same signature but with different target attributes. The +target attributes specify which CPU architecture is applicable for each of +the functions in the group. Internally, the entire group of functions is +represented by a “representative” function (whose is_representative field +is TRUE). All target-specific functions are have the +is_target_specific field set to TRUE and are queued on the +mv_info.representative.targeted_versions list. Although each of the +routines (both representative and target-specific) have associated symbols, +only the symbol for the representative routine is entered into the symbol +table. This feature is controlled by the GNU_FUNCTION_MULTIVERSIONING +configuration macro.

    +
    +
    +

    4.20. Constructors and Destructors#

    +

    Constructor and destructor routines must do additional processing beyond what +appears in the body of the routine. Since this processing surrounds the code +in the definition of the routine, it is called “wrapper” code.

    +

    Some of the wrapper code is implicit: there must be code that initializes +the information in the class used to access virtual base classes and +virtual functions (typically, virtual base class pointers and virtual +function table pointers). The wrapper code must also control whether or +not virtual base classes are initialized or destroyed (they should be for a +complete object, but not for a subobject). If a new or delete +operation can be folded into a constructor or destructor (a configuration +option, but always true if assignment to “this” is supported), the +wrapper code may have to provide for calling a new or delete +routine.

    +

    The wrapper code must also do any necessary initialization or destruction for +base classes and members. The required actions are described explicitly by a +list of a_constructor_init entries which indicate the initialization or +destruction to be done, in the correct order. If the source program contains +constructor-initializer clauses, they will appear on the list in the right +positions. For any base class or member that requires initialization and for +which the source does not provide an initializer, a default initializer is +generated. In a front-end-generated copy constructor, the default +“initialization” will in fact be a copy. In a destructor, there is no source +construct for indicating specific destruction for base classes and members, so +the list is always front-end-generated in its entirety. It is also in the +correct order, i.e., the reverse of the order in the corresponding constructor +list.

    +

    IL lowering modifies constructor and destructors to provide all the necessary +wrapper code.

    +

    Calls of “destructors” for classes that do not have them or for simple types, +as in

    +
    p->int::~int();
    +
    +
    +

    are rendered as eok_dot_vacuous_destructor_call or +eok_points_to_vacuous_destructor_call expression nodes in the IL. No +routine entry is created for the ersatz destructor. Such nodes are rewritten +as casts to void in IL lowering.

    +
    +
    +

    4.21. Labels#

    +

    a_label is a declarative entity that describes a label (user-written or +front-end-generated) in a function. It is pointed to by the goto and label +definition statements in the executable code of the function.

    +
    +
    +

    4.22. asm Statements#

    +

    An asm statement (or declaration, whichever way you care to look at them) +can appear in two contexts:

    +
      +
    • +
      Within the bodies of functions, where it is considered to be executable +code and is represented by an stmk_asm statement pointing to +an_asm_entry that gives the asm statement string.
      +
      +
    • +
    • +
      At file or namespace scope, where it is considered to be a declaration and +is represented as an_asm_entry on a list of such entries attached to +the file or namespace scope a_scope entry. If such asm +declarations are supposed to affect declarations that immediately follow +them, the back end must consider the source positions of variables, +routines, and asm entries and do a merge of those lists.
      +
      +
    • +
    +
    +
    +

    4.23. Statements#

    +

    a_statement describes a statement, which can be an expression, an if, a +while, a do-while, a for, a switch, a goto, a +break, a continue, a label definition, a return, a block (with or +without an associated scope), a try block, or a declaration statement.

    +

    The representation of switch statements (stmk_switch) matches the +language definition, but the case and default labels are represented +using a separate statement entry kind stmk_switch_case. Each +stmk_switch_case entry points to an entry of type a_switch_case_entry +(which describes the label’s value, among other things). An stmk_switch +statement points to a list of all switch case entries associated with that +statement (via an entry of type a_switch_stmt_descr). A list of switch +case entries in sorted order of label value is usually also available (this +list excludes the default case), but not if any of the cases is +template-dependent. break statements to transfer out of a switch +statement are stmk_goto statements pointing to a label entry whose +switch_break_label flag is TRUE.

    +

    The stmk_init statement indicates the point in a sequence of executable +statements where the dynamic initialization of a variable should be done. It +points to the same dynamic initialization entry that the variable does. This +is particularly useful in C++ where variables can be declared and initialized +in the middle of a block.

    +

    The stmk_block statement is used both for a simple compound statement and +for a block (i.e., a compound statement containing local declarations). The +a_block entry pointed to from the statement indicates whether or not the +block has an associated scope. In C++, a block statement is always generated +for the dependent statement of conditionals (e.g., if), even if no { } +are present. However, the block will not have an associated scope unless +something is actually declared inside the block.

    +

    The stmk_try_block statement is used to represent a try block. It +points to a compound statement block and a linked list of handlers. The latter +are entries of type a_handler; each points to a (possibly unnamed) +parameter (the local variable to which the thrown object will be copied when +the handler is invoked) and to an stmk_block statement, the body of the +handler; for a default handler (i.e., the catch(...) case) the parameter +pointer in the handler entry is NULL.

    +

    The stmk_decl statement is used to represent a declaration statement. This +could be the declaration of one or more variables and/or functions (using one +of more comma-separated declarators), one or more typedef types, a local class +or enum type, a using-declaration, etc.

    +

    The C++/CLI “for each” statement is represented by an stmk_for_each +statement. Its representation includes an indication of which “pattern” the +loop matches (the CLI collection pattern, the CLI array pattern, the STL +pattern, or the native array pattern), and for each of those patterns +expressions that give the worked-out expansion for the pieces of the loop, so +that a code-generating back end does not need to figure out the expansion.

    +

    When support for variable length arrays is enabled, two additional statements +may appear.

    +
      +
    • +
      An stmk_set_vla_size statement is associated with a VLA declaration and +indicates exactly where the dimension expression for a VLA should be +evaluated.
      +
      +
    • +
    • +
      An stmk_vla_decl statement will refer to a variable of variably +modified type or to a tk_typeref type to indicate the location of the +corresponding variable or typedef declaration. This is generally +important because a VLA type has run-time dependencies that need to be +honored. Moreover, when the variable referred by an stmk_vla_decl +statement has a VLA type (not just a type that “contains” a VLA type), the +stmk_vla_decl statement indicates the point at which the storage for +the variable should be allocated. Note that a single stmk_vla_decl +statement may be preceded by multiple stmk_set_vla_size statements if +the type associated with the stmk_vla_decl statement has multiple +variable-length dimensions. (See also Types and +Operation Expressions.) In C modes, expression statements with a single +node of kind enk_vla_dealloc (see also VLA Deallocation) may be +generated to indicate the point at which a variable of VLA type should be +deallocated (e.g., preceding a goto out of a scope containing a VLA +variable). Such deallocation constructs are generated only when +VLA_DEALLOCATIONS_IN_IL is TRUE.
      +
      +
    • +
    +

    Note that variable-length array types can also appear in sizeof +expressions. None of the above statement kinds are generated for those cases +since statements cannot in general appear within expressions. Instead, such +expressions result in enk_sizeof expression nodes. Back ends can find and +examine the a_vla_dimension entries associated with such nodes to evaluate +the result of the sizeof expression.

    +
    +
    +

    4.24. Source Sequence Lists#

    +

    When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, lists of +a_source_sequence_entry are generated, ordered strictly according to +the order in the source program. This is useful for applications that care +about the exact order of declarations, redeclarations, and definitions in +the source code, e.g., source analysis applications. Each list entry +represents a declaration, a statement, a macro, a pragma, a template, or a +template specialization that represents an instantiation (if either of the +deprecated configuration macros +CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or +NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE). +Those entities representing declarations and statements point to the +corresponding IL entry, and the latter have pointers back (fields +source_sequence_entry in a_source_correspondence and in +a_statement).

    +

    The lists appear in the IL via the source_sequence_list pointer in +a_scope entries for the file scope and for each function scope. (The +pointer will always be NULL for other scope kinds.) Source sequence entries +themselves have both forward and backward pointers to facilitate list traversal +and management.

    +

    Logically, there is a single source-sequence list in a translation unit. +Actually, however, a number of lists may be involved. The file-scope +source-sequence list is pointed to from the scope entry for the file scope, but +when a function definition appears, another list, pointed to from the scope +entry for the function, is produced. The logical successor of the +source-sequence entry for the function (which is in the file-scope list) is the +first entry on the function-scope list, and the logical successor of the last +entry on the function-scope list is the entry pointed to by the next +pointer of the function’s source-sequence entry.

    +

    The reason for representing the logically continuous source-sequence list by +many discontinuous lists is that source-sequence entries appear in different +memory regions, just as the IL entries they point to do. Thus, the entries on +the file-scope source-sequence list are allocated in the file-scope memory +region, but the entries on a function-scope source-sequence list are usually +allocated in the memory region of that particular function.

    +

    Some declarations within a function, however, create entities that are +allocated at file scope. This is the case for types, static variables, and +variables and functions declared extern. The source-sequence entries for +such entries must also be in the file-scope memory region, but that means they +cannot be on the same linked list with entries allocated in the function-scope +memory region. Therefore, additional side branches are used: entries of type +a_src_seq_sublist (“sublist headers”) establish such branches by pointing +to the head and tail of a list of file-scope source-sequence entries that are +logically within the source-sequence list of the function scope.

    +

    The sublist headers for a given function, as well as being pointed to by +entries (“sublist parents”) in the function-scope source-sequence list, are +also chained together; the head of the linked list is pointed to by +src_seq_sublist_list in the function’s scope entry, and its tail is pointed +to by last_src_seq_sublist in the corresponding scope stack entry.

    +

    Entries of type a_src_seq_end_of_construct are inserted into the +source-sequence list to mark the point at which certain constructs terminate +(the entries point back to the associated IL entry). This includes class and +enum definitions and statement blocks. Such entries are also used to mark the +end of a set of source sequence entries for constructs embedded in a variable +or function declaration. For example, in:

    +
    int x[sizeof(struct S { int i; })];
    +
    +
    +

    (which is accepted in some modes only), the source sequence list contains an +entry for the definition of variable x, followed by entries for the +definition of struct S, followed by an entry marking the end-of-construct +of variable x‘s definition. An end-of-construct marker is similarly used +to mark the appearance of the “while (...)” part of a do-while statement +(this is, e.g., significant to be able to record whether a pragma appeared +before the statement as a whole, or just before the while keyword).

    +

    When a declaration is not a definition (e.g., a function declaration with no +body or a variable declared extern), it is represented by an entity of type +a_src_seq_secondary_decl, which is pointed to by the source-sequence entry +and points in turn to the corresponding IL entry. Therefore, when an entity +has more than one declaration, multiple source-sequence entries are created, +but only the one that represents the definition points directly to the IL +entry; the others point to secondary declaration entries. If there is no +definition of the entity in the compilation, all of the source sequence entries +for that entity will be secondary declarations.

    +

    (Source sequence lists are not actually added to the IL tree until +pop_scope is called for a function scope or the file scope. During front +end processing, the source sequence lists as described above are assembled from +smaller lists that are managed on a per-scope basis; whenever a scope stack +entry is popped, its list is typically merged into the list of the immediately +enclosing scope. Moreover, the source sequence list describing a function +definition may temporarily be a simple linked list containing a mix of entries +from the memory regions of the function scope and the file scope; the +representation involving sublist headers, as described above, is produced by a +fixup pass when the function scope is popped.)

    +

    Many implementations will not need the kind of information provided by +source-sequence lists and will choose to avoid the processing overhead and +especially the memory overhead they introduce. By default, therefore, +GENERATE_SOURCE_SEQUENCE_LISTS (defined in host_envir.h) is set to +FALSE.

    +
    +
    +

    4.25. Expressions#

    +

    an_expr_node describes an expression node, which can be an operator node, a +reference to a constant, variable, or function, an initialization of a +temporary, or a few other things like new or delete.

    +

    Each expression node has a type, indicated by its type field.

    +

    The simplest expression nodes are leaf nodes. The most common leaf node kind +are:

    +
      +
    • +
      enk_variable refers to a variable.
      +
      +
    • +
    • +
      enk_routine refers to a function.
      +
      +
    • +
    • +
      enk_constant refers to a constant.
      +
      +
    • +
    • +
      enk_field refers to a field.
      +
      +
    • +
    +
    +

    4.25.1. Lvalues and Rvalues (Value Categories)#

    +

    Each expression node has an is_lvalue flag, which is TRUE if the node +represents an lvalue and FALSE if it represents an rvalue. (It is also TRUE +for what is called a function designator in C, which is simply called an lvalue +in C++.)

    +

    So, an enk_variable node with is_lvalue TRUE indicates an lvalue for +the variable, and the same node with is_lvalue FALSE indicates an rvalue +for the variable, i.e., the value of the variable. In the statement

    +
    i = j;
    +
    +
    +

    the left operand would have is_lvalue TRUE and the right operand would have +is_lvalue FALSE.

    +

    Similarly, an enk_routine with is_lvalue is TRUE indicates an lvalue +for the function (which has a function type), and one with is_lvalue FALSE +indicates an rvalue for the function (which is the address of the function, and +has pointer-to-function type).

    +

    enk_constant nodes are usually rvalues, representing the value of an +indicated constant. The one exception is that an enk_constant for a +string constant (ck_string) can be an lvalue for the string.

    +

    C++11 adds the concept of “xvalues,” which are eXpiring values produced by +certain rvalue reference operations. They are indicated by the is_xvalue +flag in the node being TRUE (is_lvalue and is_xvalue are never both +TRUE). Lvalues and xvalues are collectively called “glvalues.” The things that +were called “rvalues” in pre-C++11 C++ and in C are known in C++11 as +“prvalues,” and the term “rvalue” becomes a collective term for prvalues plus +xvalues. [8] In the IL, xvalues in general can be viewed as funny versions +of lvalues.

    +

    Glvalue nodes shouldn’t be considered to have values. They’re just a +description of an object in memory. Because they don’t have values, they also +can’t be considered to be constant or to have constant values, though some +lvalues will have constant addresses (see constant_glvalue_address).

    +

    When a glvalue with a cv-qualified type is converted to a prvalue, the type +qualifiers are dropped (except for class-typed prvalues in C++). In the IL, +this is reflected in the fact that the expression node for the prvalue will +have the unqualified type. When an lvalue with a function type is converted to +a prvalue, its type becomes pointer-to-function.

    +

    Clearing the is_lvalue flag in an expression node where initially the flag +would be expected to be TRUE indicates a fetch from memory. This is obvious on +the enk_variable node, but it also applies to many other nodes, such as +field selection and subscripting operators. Nodes that can be made to include +a fetch merely by clearing the is_lvalue flag (or, similarly, the +is_xvalue flag) are referred to as “rvalueable”. One can test for the +presence of an implicit fetch (also known as an lvalue-to-rvalue conversion) in +an expression node by calling node_includes_glvalue_to_prvalue_conv.

    +
    +
    +

    4.25.2. Operation Expressions#

    +

    Expression nodes of kind enk_operation are operations. They are the +non-leaf nodes of expression trees, the ones that apply an operator to a set of +operands, to do operations like i+j.

    +

    The operands of an operation are linked together as a list, and the operation +node points to the first expression on the list.

    +

    Most operations take a fixed number of operands. The various forms of calls +are exceptions and take a variable number of operands.

    +

    The operator kind (addition, assignment, call, etc.) is described by the +variant.operation.kind field, which is mostly independent of the type of +the operands. For example, an addition is described with kind eok_add +independently of the operand type. There are a few exceptions to this when the +semantics of the operation vary sufficiently from the generic case to warrant a +separate operator. For example, pointer arithmetic uses dedicated operators +eok_padd, eok_psubtract, and eok_pdiff instead of the generic +eok_add and eok_subtract. Where applicable, an additional field +variant.operation.type_kind describes the class of types an operation acts +on. For example, this will be tk_float for the multiplication of two +floating-point values, or tk_template_param for a multiplication involving +a template-dependent operand. For operations that don’t apply to a particular +type kind (e.g., eok_call), the type_kind field is set to +tk_unknown. The type_kind field is set automatically when calling +make_operator_node or set_node_operator (it is ultimately computed by +operation_type_kind).

    +

    In the case of scalar controlling expressions, the several different cases +(integer, float, and pointer) are reduced to a single case (integer) by +standardizing the expression. Specifically, for the expression of a +stmk_if, stmk_while, stmk_end_test_while, or stmk_for, and for +the controlling operands of the eok_not, eok_land, eok_lor, and +eok_question operators, the expression will always be either an integer +constant 0 or 1, or an expression whose top operator is defined to +yield a 0 or 1 result. Where necessary, a constant value will be +standardized (e.g., 5.3 will be changed to 1), or a != 0 operation +of the proper type (integer, float, or pointer) will be added to the top of the +expression.

    +

    The operands of an expression may be evaluated in any order consistent with +the C and C++ “as-if” rule. By default, parentheses are not directly +represented in the IL; their effect is simply reflected in the operands of +the operators in the expression tree or, in cases where they have semantic +implications, by flags in various IL entries (e.g., +an_expr_node::is_parenthesized). Applications that need to be aware of +source-level parentheses can set the PARENS_IN_IL configuration option; +see Parentheses.

    +

    In general, operator nodes that do not correspond directly to something that +appeared in the source, and were added by the front end, are marked by having +compiler_generated set to true.

    +
    +
    +

    4.25.3. Addressing operators#

    +

    There are several addressing operators (note that when we refer to eok_... +names we mean those under the enk_operation expression variant):

    +
      +
    • +
      eok_address_of is the “&” operator. Its operand is an lvalue, and +its result is a prvalue of pointer type that is the address of the lvalue.
      +
      +
    • +
    • +
      eok_indirect is the “*” operator. Its operand is a prvalue +pointer, and its result is an lvalue that is the object pointed to. It +is rvalueable.
      +
      +
    • +
    • +
      eok_array_to_pointer converts its operand, an array (lvalue, xvalue, or +prvalue), to a prvalue pointer to the first element of the array.
      +
      +
    • +
    +

    The “restrict” qualifier on pointers, originally introduced in C99, is a type +qualifier on pointer types that indicates that they can be considered to be +unaliased (nothing else in scope points at what they point at). The function +node_is_pointer_with_restrict_semantics can be used to test an expression +node that is a pointer (e.g., the operand of an eok_indirect operation) to +see whether it has the “restrict” semantics.

    +
    +
    +

    4.25.4. References#

    +

    References are not pointers, but they are treated as somewhat pointer-like in +the IL, with their own versions of the addressing operators:

    +
      +
    • +
      eok_reference_to is the reference version of “&”. Its operand is a +glvalue, and its result is a prvalue of reference type that is the +“address” of (reference to) the glvalue. Its operand can also be a class +prvalue, in which case its result is the “address” of the underlying class +object.
      +
      +
    • +
    • +
      eok_ref_indirect is the reference version of “*”. Its operand is a +prvalue with reference type, and its result is an lvalue that is the object +referenced. It is rvalueable.
      +
      +
    • +
    +

    These operators do not, of course, appear in the source code; they are added by +the front end where needed. No operations are allowed on references other than +the above, or storing a reference somewhere, or passing it as an argument.

    +

    An example: for something like

    +
    int i;
    +int &r = i;
    +r = r;
    +
    +
    +

    the left operand of the assignment is an eok_ref_indirect with +is_lvalue TRUE over an enk_variable for r with is_lvalue FALSE, +and the right operand is an eok_ref_indirect with is_lvalue FALSE over +an enk_variable for r with is_lvalue FALSE.

    +

    Note that reference type values are typically dealt with as prvalues, in the +same way that pointers are. In the example above, the enk_variable for +r is effectively fetching the pointer-like value stored in the reference +variable, so its is_lvalue flag is FALSE. An enk_variable node with +is_lvalue TRUE for a reference variable would mean an lvalue for the cell +containing the reference value, but there’s no real use for that in the C++ +language, since you can’t take the address of the cell nor can you change its +value after initialization.

    +

    Address constants with kind ck_address can have reference type when they +are used to initialize a reference-typed variable. They represent a constant +reference value.

    +

    Rvalue references (source form like “int&&r”) are similar to the +traditional “lvalue” references. eok_reference_to and eok_ref_indirect +can be used with them also, and ck_address constants can have rvalue +reference type. An rvalue reference is always bound to an rvalue (i.e., an +xvalue or prvalue). See Casts for information on casts to +rvalue reference types.

    +
    +
    +

    4.25.5. Field Selection#

    +

    There are several operators that implement field selection:

    +
      +
    • +
      eok_dot_field is the “.” operator. The left operand is a class +glvalue or prvalue, the right operand is an enk_field, and the result +is a glvalue or prvalue of the type of the selected field (with +cv-qualifier adjustment). When the left operand is an lvalue, the result +is an lvalue (rvalueable), and similarly for an xvalue. When the left +operand is a prvalue, the result is a prvalue.
      +
      +
    • +
    • +
      eok_points_to_field is the “->” operator. The left operand is a +prvalue pointer to class, the right operand is an enk_field, and the +result is an lvalue (rvalueable) of the type of the selected field (with +cv-qualifier adjustment).
      +
      +
    • +
    • +
      eok_pm_field is the “.*” operator. The left operand is a class +glvalue or prvalue, the right operand is a pointer to data member, and the +result is a glvalue or prvalue of the type of the pointed-to member (with +cv-qualifier adjustment). When the left operand is an lvalue, the result +is an lvalue (rvalueable), and similarly for an xvalue. When the left +operand is a prvalue, the result is a prvalue.
      +
      +
    • +
    • +
      eok_pm_points_to_field is the “->*” operator. The left operand is +a prvalue pointer to class, the right operand is a pointer to data member, +and the result is an lvalue (rvalueable) of the type of the pointed-to +member (with cv-qualifier adjustment).
      +
      +
    • +
    • +
      eok_dot_static is the “.” operator when the entity selected is +static. The first operand is a class glvalue or prvalue (and it is +evaluated) and the second operand is an enk_variable for a static data +member, an enk_routine for a static member function, or an +enk_constant identifying a member constant (e.g., an enumerator). The +result is the second operand.
      +
      +
    • +
    • +
      eok_points_to_static is the “->” operator when the entity selected +is static. The first operand is a prvalue pointer to class (and it is +evaluated) and the second operand is an enk_variable for a static data +member, an enk_routine for a static member function, or an +enk_constant identifying a member constant (e.g., an enumerator). The +result is the second operand.
      +
      +
    • +
    +

    Note that most of the selection operators are rvalueable in some cases, but the +static variants are not; for those, the lvalue-to-rvalue conversion, if there +is one, has to be indicated on the second operand, and not in the +eok_dot_static or eok_points_to_static operation itself.

    +

    Also note that there are no variants of the pointer-to-member selections for +pointer-to-member-function cases. Those can be used only in calls, and the two +operands of the selection are simply folded into the eok_pm_call. +Likewise, the “.” or “->” operation in a member function call is simply +folded into the call.

    +
    +
    +

    4.25.6. Subscripting#

    +

    eok_subscript is the array subscripting “[]” operator. One operand is +a prvalue pointer to the first element of the array, and the other is an +integral subscript value. The result is an lvalue (rvalueable) for the +specified element of the array. Usually, the pointer operand is first, but +that’s not actually a requirement of the language, and the operands can appear +in either order, as for the expression “1[a]”. See the +pointer_operand_is_second field, which indicates this unusual case, and the +macro subscript_or_padd_pointer_operand, which can be used to extract the +pointer operand. As you will note from the name of that macro, this is also an +issue for the pointer addition (eok_padd) operator.

    +
    +
    +

    4.25.7. Casts#

    +

    The eok_cast operator is used to indicate simple casts.

    +

    Casting a derived class pointer to a base class pointer is represented by an +eok_base_class_cast operator. Casting a base class pointer to a derived +class pointer uses an eok_derived_class_cast operator. These casts differ +from ordinary pointer casts in that they may add or subtract an offset to the +pointer, and they must preserve a NULL pointer. They can also be applied +directly to a class glvalue or prvalue, rather than a pointer to a class +object, or to a C++/CLI handle.

    +

    eok_pm_base_class_cast and eok_pm_derived_class_cast are the similar +casts for pointers-to-members. The same operators are used for +pointers-to-data-members and pointers-to-member-functions, even though the +implementations of those are likely to be different.

    +

    The anachronism of casting a bound pointer-to-member-function to a normal +pointer (which is similar to the processing done by an +eok_points_to_pm_call to determine the function to call) is rendered as an +eok_virtual_function_ptr operation.

    +

    In pcc mode and in some Microsoft and GNU C++ modes, certain casts to +like-sized types (like int to unsigned int) leave a result that is +still an lvalue. For these cases, the lvalue is cast to the appropriate type +using the eok_lvalue_cast operator. The result is still an lvalue.

    +

    The C++ dynamic_cast operator is rendered as an eok_dynamic_cast +(pointer or handle case) or eok_ref_dynamic_cast (reference case), but only +for cases that require runtime processing. The rest are rendered as ordinary +casts.

    +

    Casts to bool are rendered as an eok_bool_cast, which has the same +effect as a “!= 0” test.

    +

    The eok_lvalue_adjust operator adjusts the type of a glvalue. Its operand +is a glvalue, and its result is a glvalue for the same object but with a +different type.

    +

    The eok_class_rvalue_adjust operator adjusts the type of a class prvalue. +It is limited to adjusting the cv-qualifiers of the type. Its operand is a +class prvalue, and its result is the same value with a different type. When +LOWER_CLASS_RVALUE_ADJUST is TRUE, IL lowering will rewrite these +adjustments by taking the address of the class rvalue, casting the pointer to +the proper type, and indirecting to get back to a class object.

    +

    Casts to reference types are represented as glvalue-to-glvalue operations. The +simplest cases are represented by the eok_ref_cast operator. The node type +is the underlying type of the reference, e.g., the node for a cast (T &)x +has type T, not type T&. The operand is a glvalue, and the result is a +glvalue for the same object but with the type T. More complicated +reference casts that involve related-class adjustments are represented by +eok_base_class_cast and eok_derived_class_cast operators operating on +class glvalues. Nodes that represent a cast to a reference type are marked +with the is_reference_cast flag. If several nodes are required (e.g., +multiple casts to base classes) only the topmost node will be marked. Note +that eok_ref_cast nodes are rvalueable, and when the is_lvalue flag is +cleared to indicate the presence of an lvalue-to-rvalue conversion the node +type becomes the cv-unqualified type (for non-class lvalues) or pointer-to the +lvalue type (for function lvalues). That means, for a function type F, a +cast to F& with an included lvalue-to-rvalue conversion is represented by a +node with type F*.

    +

    Casts to rvalue reference types are similarly represented by eok_ref_cast, +eok_base_class_cast, and eok_derived_class_cast nodes. They are marked +with the is_rvalue_reference_cast flag in addition to the +is_reference_cast flag. Although in the C++ language such reference casts +take an rvalue as their operand, in the IL the operand is always converted to a +glvalue and then cast. The node or nodes that do the cast are then exactly the +same as those that would be used for an lvalue reference cast. The final +(topmost) cast node will always be an eok_ref_cast node, and it will have +is_lvalue FALSE to indicate the result is an rvalue (unless the result +needs to be converted back to an lvalue for some reason).

    +
    +
    +

    4.25.8. Assignments#

    +

    There are assignment operators for integral types, fixed-point types, floating +types, classes (bitwise copy, or C struct assignment), pointers, and +pointers-to-members.

    +

    There is also a block-copy assignment, eok_bassign, which is only generated +by IL lowering and inside front-end-generated assignment operator functions, +and is needed to do bitwise copies of arrays when copying classes. It is +unusual in that its second operand is in lvalue form and its result type is +void.

    +

    In C++, assignment operators can return lvalues instead of rvalues. Such cases +are indicated by the returns_lvalue_instead_of_usual_rvalue flag in the +expression node. The expression type matches the type of thing returned (i.e., +it matches the first operand’s type). The same flag is used for prefix ++ +and -- and the “?” and “,” operators when they return an lvalue. +When that flag is set, is_lvalue will also always be set as well (in other +words, they are not rvalueable).

    +
    +
    +

    4.25.9. Compound Assignments#

    +

    In cases where a compound assignment operator (e.g., +=) is applied to +operands of two different types, the right side operator will be cast as +necessary to the type of the operation (as it would be for other operators). +The left side operand (the destination, an lvalue), however, is left in its +original type, which is also the type of the entire expression. The back end +must provide a cast of the value of the left operand to the operation type +(generally the type of the right operand, but see below) before performing the +operation on the operands. For example: in i-=f (i an int, f a +float), the back end must provide the cast of i to float before +doing the subtraction; the operation type is float; the result type (and +the type of the expression node) is int.

    +

    As mentioned above, the operation type for the operation is generally the right +operand type. There are two exceptions in which the underlying type of the +left operand is the operation type: shift assignments (<<= and >>=) and +pointer += and -= (for those cases, the right operand is not cast to +the operation type). Fixed-point +=, -=, *=, and /= are yet +more complicated; the function compound_assignment_operation_type should be +called to determine the operation type for those (it also works for all the +simpler cases).

    +

    GNU vector cases are even weirder, as no attempt is made to bring the operands +to a common type.

    +
    +
    +

    4.25.10. Binary Conditional Operator#

    +

    In some configurations, the front end supports a GNU extension known as the +“binary conditional operator”. The operator has the form expr1?:expr2 (i.e., similar to the regular conditional operator, but with +an omitted middle operand). Such expressions result in the value of expr1 +if expr1 converted to a boolean is true, or the value of expr2 +otherwise. In the IL, this is represented by the usual eok_question +operator, but with the flag is_gnu_two_operand_question_mark set to TRUE. +The expression includes a synthesized second operand, which may use an +enk_reuse_value expression node to reuse the value of the first operand +without evaluating it a second time.

    +
    +
    +

    4.25.11. Calls#

    +

    The normal call is rendered as an eok_call operation. The first operand +gives the address of the routine to call, and the rest of the operands are the +arguments for the call.

    +

    For nonstatic member function calls, the operation is eok_dot_member_call +(for calls in the x.f() form) or eok_points_to_member_call (for calls +in the p->f() form). The first operand is the routine address (as a normal +pointer, not a pointer-to-member); the second operand is the selector object (a +class glvalue or prvalue for eok_dot_member_call, or a pointer to a class +object for eok_points_to_member_call). The remaining operands are the +arguments to the call. In either case, a call with virtual semantics is +indicated by the is_virtual_call flag in the expression node.

    +

    For pointer-to-member-function calls, the operation is eok_dot_pm_call (for +calls in the (x.*pmf)() form) or eok_points_to_pm_call (for calls in +the (p->*pmf)() form). The first operand is the pointer-to-member-function +(i.e., a value of pointer-to-member-function type, not a normal pointer type); +the second is the selector object (a class glvalue or prvalue for +eok_dot_pm_call, or a pointer to class for eok_points_to_pm_call); the +rest are the actual arguments, as above.

    +

    If a routine has default arguments, the front end will supply the default +expressions if no explicit arguments are provided. The back end need not do +any special handling.

    +

    If a parameter of class type must be passed by using a copy constructor, a call +of the copy constructor into a temporary will be generated on the calling side. +Somewhat arbitrarily, the enk_temp_init node for that is marked as an +lvalue.

    +

    For routines that return a class object via a copy constructor, the call will +always be immediately underneath a dik_call_returning_class_via_cctor +dynamic initialization entry. The entity being initialized by the dynamic +initialization entry should be taken as the destination for the copy +constructor call. (IL lowering makes this explicit.)

    +

    Note that uses of operator functions and conversion functions are rendered as +routine calls even through they use operator syntax or are implicit in the +source program. Constructor and destructor “calls” generally only show up in +dynamic initialization entries, and not as standard calls in expressions.

    +

    Inlining is considered to be a back end issue. The front end does not do +inlining of calls. IL lowering optionally offers a limited form of inlining, +but it’s intended only for those who have no better alternative.

    +
    +
    +

    4.25.12. Returns#

    +

    The stmk_return statement is used to represent all returns, whether +explicitly written by the programmer or generated by the front end. In +addition to the expected

    +
    return;
    +return expr;
    +
    +
    +

    (which are distinguished by a NULL or non-NULL expr pointer), there is also +a special form of return used for returns in routines that return a class value +by calling a copy constructor. For those, the stmk_return statement has a +pointer to a dynamic initialization entry, which indicates the initializing +operation to be done to return the class object. IL lowering implements this +by having the caller pass an extra argument that provides the address at which +the class object should be placed, and having the called routine call the copy +constructor using the implicit parameter as its destination address.

    +
    +
    +

    4.25.13. Pointers to Members#

    +

    Pointer-to-member types are represented as an abstraction in the unlowered C++ +intermediate language. It is up to IL lowering or a back end to translate them +into a particular implementation. Typically, pointers to data members are +implemented as a small integral offset (the offset of the member within the +class) and pointers to member functions are rendered as a structure (see the +ARM, 8.1.2.c).

    +

    Pointer-to-member types are represented by a tk_ptr_to_member type entry.

    +

    Pointer-to-member constants are represented by a constant entry of kind +ck_ptr_to_member. These represent source constructs like &A::x, +meaning some sort of representation of the location of x in a class object +of type A (not a pointer to that member in a specific object, but rather a +representation of how to find that member in an arbitrary entity of that +class).

    +

    Operands of pointer-to-member type can be assigned (eok_assign) and +compared (eok_eq and eok_ne). They can also be cast to base or derived +classes (eok_pm_base_class_cast and eok_pm_derived_class_cast).

    +
    +
    +

    4.25.14. Temporary Initialization#

    +

    The enk_temp_init node is used to introduce a temporary in the middle of an +expression. It points to a dynamic initialization entry and an expression. +The initialization indicated in the dynamic initialization entry is performed +on the temporary, and then the temporary is returned as the value of the +enk_temp_init node, as an lvalue, xvalue, or prvalue. Any destruction +indicated in the dynamic initialization entry must be done to the temporary at +the end of the object lifetime to which the dynamic initialization is bound.

    +
    +
    +

    4.25.15. Condition Declarations#

    +

    In if, while, for, and switch statements in C++, the expression +tested can be a condition declaration. For example:

    +
    if (float x = f()) { ... }
    +
    +
    +

    This is represented in the IL as an expression node of kind enk_condition. +The condition has its own associated scope, which contains just the one +variable, and which wraps around the statement. Note that the initializations +for conditions in loops are done each time around the loop; if destruction is +also required, it too must be done each time around the loop.

    +
    +
    +

    4.25.16. New and Delete#

    +

    A new operator allocates storage and optionally initializes it. It is +represented by an enk_new_delete expression node. The supplement to that +node provides information about the new routine to be called, the arguments +for that call, and optionally a dynamic initialization entry that describes any +initialization to be done. If the allocation fails (i.e., the new routine +returns NULL), the initialization is not done.

    +

    A delete operator deallocates storage after optionally calling a +destructor. It is represented by an enk_new_delete expression node. The +supplement to that node provides information about the delete routine to be +called, the pointer to the object to be deleted, and optionally a dynamic +initialization entry that describes destruction to be done.

    +

    In both the new and the delete cases, the routine indicated in the +new/delete supplement may be NULL to indicate that the allocation or +deallocation should be done by the constructor or destructor. The dynamic +initialization entry in those cases indicates the appropriate constructor +or destructor. This alternative is controlled by configuration options +NEW_CAN_BE_FOLDED_INTO_CTOR and DELETE_CAN_BE_FOLDED_INTO_DTOR, +which must be true if assignment to “this” (an anachronism) is +supported, because the constructor or destructor must have control of +allocation and deallocation in that case.

    +

    When a delete contains the count of array elements (an anachronism), the +expression between [] is scanned and thrown away; it does not appear in the +IL.

    +

    The C++/CLI gcnew operator is represented by an enk_gcnew expression +node. For CLI array cases, the supplment provides both the bound sizes +(whether explicitly specified or determined from the size of the initializer) +and an initializer aggregate for the element values.

    +
    +
    +

    4.25.17. Lambda Expression#

    +

    A lambda expression – which produces a temporary “closure object” of a +class type with an operator() member – is represented by an +enk_lambda expression node. Such a node points to a supplement entry +of type a_lambda and to an a_dynamic_init entry describing the +initialization and (if applicable) the destruction of the temporary +“closure object” resulting from the expression. The a_lambda entry +describes the static properties of the lambda expression, such as the local +variables it captures (and how they are captured), the closure type, +relevant source positions, etc.

    +
    +
    +

    4.25.18. Throw Expression#

    +

    A throw expression is represented by an enk_throw expression node. It +points to a supplement that points to a dynamic initialization entry that +describes the object to be thrown (or rather, how to make a copy of it, since a +copy is what’s actually thrown); the supplement pointer is NULL in the case of +a “rethrow”.

    +
    +
    +

    4.25.19. Sizeof#

    +

    When a sizeof operator cannot be evaluated at compile time (for instance, +when it is applied to a variable length array), an enk_sizeof expression +node is put out. Such nodes are also used to represent dependent sizeof +expressions in prototype instantiations.

    +
    +
    +

    4.25.20. typeid#

    +

    The typeid operator is represented by an enk_typeid expression node. +It points to the type whose type information is wanted. For cases that require +runtime type determination (e.g., typeid(*p) where p points to a +polymorphic class type), there is also a pointer to an expression whose dynamic +type is to be determined at runtime.

    +

    enk_typeid is also used for the C++/CLI X::typeid feature. That’s +indicated by the is_cli_typeid flag. The result value in that case is a +handle to a System::Type entry.

    +
    +
    +

    4.25.21. VLA Deallocation#

    +

    In C mode, the front end may generate enk_vla_dealloc nodes to indicate +where VLAs should be deallocated. Such nodes may also be created when lowering +C++ IL for VLAs (when DO_IL_LOWERING is TRUE). The nodes are eliminated +from the IL altogether (both in C and C++ modes) if +LOWER_VARIABLE_LENGTH_ARRAYS is TRUE; the nodes are translated to calls +into the run-time support library.

    +
    +
    +

    4.25.22. Parameters#

    +

    When an identifier in an expression refers to a parameter, the resulting IL is +an enk_variable node if the parameter is referenced in the body of a +function. However, it is possible to refer to parameters in expressions that +appear outside the function body. For example, in C++11, a function template +declaration might be as follows:

    +
    template<class T> auto f(T p)->decltype(*p);
    +
    +
    +

    Such uses always appear in unevaluated contexts and are represented with +enk_param_ref nodes, which, like enk_variable nodes, are rvalueable.

    +

    An enk_param_ref node doesn’t point directly to IL representing a +parameter (e.g., a_param_type entries) because such a pointer might +become invalid when, e.g., two function types are combined through +composite_routine_type. Instead, the parameter is represented by two +integers: The parameter position in its enclosing parameter list, and the +“level” of the parameter list relative to the point of reference (function +declarators may be nested and an inner declarator may refer to a parameter +of an enclosing declarator).

    +
    +
    +

    4.25.23. Fixed-point operations#

    +

    Operations on fixed-point values are represented using the usual expression +operators (eok_negate, eok_post_incr, eok_add, eok_divide, +eok_eq, eok_assign, etc.). For mixed-type arithmetic (i.e., operations +involving two different fixed-point types, or a fixed-point type and an integer +type), these operators are different from most of the other (more common) +operators in that their operands are not converted to a common type. For +example, when adding a short int to a long _Accum, the operator is +applied directly to the unconverted operands without “usual arithmetic +conversions.” A back end is then responsible for performing the operation with +maximum precision and converting the result to the result type indicated in the +operator expression node. This arrangement is necessary to meet the +requirements of the Embedded C extensions (ISO/IEC TR 18037).

    +

    Note that while mixed-type fixed-point arithmetic does not in general attempt +to convert the operands to a common type, a conversion from unsigned to signed +may be applied if one operand is signed and the other not. Furthermore, an +operation involving a fixed-point operand and a floating-point operand is a +floating-point operation: The fixed-point operand is converted to a +floating-point type.

    +
    +
    +

    4.25.24. Parentheses#

    +

    Parentheses are represented in the IL as expression operation nodes with an +operator of eok_parens. Those are not usually generated; PARENS_IN_IL +must be set to TRUE to request them. When that flag is TRUE, each pair of +parentheses in a source program expression is represented by an eok_parens +node in the IL for the expression. If EXTRA_SOURCE_POSITIONS_IN_IL is also +TRUE, those expression nodes will include position information on the opening +and closing parenthesis tokens.

    +

    eok_parens nodes are not used or allowed in versions that use IL lowering. +They are intended mostly for source-analysis applications. Note that enabling +PARENS_IN_IL should not be done without reason, because it complicates the +code that deals with expressions. Every bit of code that wants to check for a +specific operator in an expression may have to check for and strip parentheses +off the expression before doing the check. That can be done by calling +skip_parens, but it’s hard to always remember to do that. (This problem is +very similar to the skip_typerefs problem for types, and that is widely +known as a pain and a source of bugs.)

    +
    +
    +

    4.25.25. Fold Expressions#

    +

    A C++17 fold-expression like “(ps + ...  + 1)” where ps contains an +unexpanded parameter pack is represented in generic template contexts (i.e., +“prototype instantiations”) using an enk_fold node. The expansion of the +construct (in real template instantiations), however, uses the ordinary binary +operator representations. For example, if ps expands to a sequence of +integer parameter variables, the expanded representation will involve a tree of +enk_operation/eok_add nodes.

    +
    +
    +

    4.25.26. Boxing and Unboxing#

    +

    C++/CLI boxing and unboxing is implemented by several operators:

    +
      +
    • +
      eok_box takes an operand of a value type (e.g., int) and returns a +handle to a boxed version of the value on the CLR heap (e.g., handle to +System::Int32).
      +
      +
    • +
    • +
      eok_handle_to_box has the same runtime meaning as eok_box, but is +generated for source uses of the unary % operator applied to a value +class.
      +
      +
    • +
    • +
      eok_unbox takes an operand that is a handle to a boxed value class or +boxed enum and returns an lvalue (in place on the heap) or rvalue (copied) +for the contained value, depending on the is_lvalue flag.
      +
      +
    • +
    • +
      eok_unbox_lvalue is similar, but the operand is an lvalue for the value +class or boxed enum. It is always compiler-generated, e.g., on top of an +eok_indirect applied to a handle to a value class.
      +
      +
    • +
    +
    +
    +
    +

    4.26. Pragmas#

    +

    A #pragma directive may be represented in the IL by an entry of type +a_pragma, which appears on a linked list pointed to by the pragmas +field of an IL scope entry. It includes a pointer (see the entity field) +if it is specifically associated with a statement, routine, etc.; the entity +does not point back, but rather has its has_associated_pragma flag set, +since more than one pragma entry may be associated with a given IL entity. For +additional information, see Pragmas and Attributes.

    +
    +
    +

    4.27. Anonymous Unions#

    +

    Anonymous unions are unions that have no name, either for the union type or for +the singular instance of the union. The names of the members of the union are +promoted into the surrounding context. There are two kinds of anonymous +unions:

    +
      +
    • +
      Anonymous unions within classes, as in
      +
      +
      class A {
      +  union {
      +    int i;
      +    float j;
      +  };
      +} x;
      +
      +
      +
      +
      Here, the fields of the anonymous union are promoted into the surrounding +class, so one can refer to x.i.
      +
      +
    • +
    • +
      Anonymous unions as variables, as in
      +
      +
      union {
      +  int i;
      +  float j;
      +};
      +
      +
      +
      +
      Here, i can be used as if it were a variable. Such constructs can +appear at file and namespace scope and within function and block scopes.
      +
      +
    • +
    +

    For the first (field) case, the IL reflects the source form: class A will +contain an unnamed field whose type is an unnamed union, which in turn contains +the fields i and j. A reference like x.i appears as a selection of +i directly from x. By looking at the field for i, one can tell +that it is a member of an anonymous union, and infer the additional field +selection. (IL lowering adds the extra field selection.)

    +

    For the second (variable) case, there will be an unnamed variable whose type is +the unnamed union. A reference like i appears as a selection of i out +of the unnamed variable, so it is more explicit (and less like the source +program) than the field case.

    +
    +
    +

    4.28. Virtual Function Tables#

    +

    There are no “virtual function tables” per se in the unlowered IL. There is +only the information that is part of the definition of virtual functions in the +language:

    +
      +
    • +
      Functions are marked as being virtual, including when they are implicitly +virtual because they override a virtual function from a base class. +Virtual functions are assigned ordinal numbers within a class, which can be +used as their indexes into a virtual function table.
      +
      +
    • +
    • +
      Calls to virtual functions use a special operator, eok_virtual_call.
      +
      +
    • +
    • +
      Base class entries contain information on virtual function overrides, i.e., +on which virtual functions of a base class are overridden by virtual +functions in derived classes (either the one the base class entry is +attached to or some class on the derivation path between the base class and +that one).
      +
      +
    • +
    +

    One can generate a virtual function table for A in B by scanning the +member functions of A looking for virtual functions, along with the +override list for base class A of B. If a function in A does not +appear on the override list, the function from A goes into the virtual +function table. Otherwise, the function from the override list goes into the +virtual function table. More detail can be found in the code in IL lowering +that generates virtual function tables.

    +
    +
    +

    4.29. C99 features#

    +

    The C99 IL extensions over C89 are as follows:

    +
      +
    • +
      For variable-length arrays (VLAs), the front end generates two additional +statement kinds (stmk_set_vla_size and stmk_vla_decl) and +optionally one additional expression node kind (enk_vla_dealloc; see +VLA Deallocation). Types and variables are also marked as being VLAs +when appropriate. This feature can be enabled also in C89 and C++ modes +(by --vla), and is controlled by the macro VLA_ALLOWED (which is +set by default if C99_IL_EXTENSIONS_SUPPORTED is set). If +LOWER_VARIABLE_LENGTH_ARRAYS is TRUE, the VLA-specific constructs are +eliminated from the IL (this requires the run-time support library).
      +
      +
    • +
    • +
      For compound literals, an enk_temp_init node is generated. Such a node +generates a temporary, and is otherwise used only in C++ mode. This +feature can be enabled also in C89 mode (by --compound_literals), and +is controlled by the macro COMPOUND_LITERAL_ENABLING_POSSIBLE (which is +set by default if C99_IL_EXTENSIONS_SUPPORTED is set). C99 lowering +eliminates compound literals by rewriting them as initialized generated +variables.
      +
      +
    • +
    • +
      For designators in initializers, ck_designator constants are +generated in aggregate initializers. This feature can be enabled also +in C89 mode (by --designators), and is controlled by the macro +DESIGNATED_INITIALIZER_ENABLING_POSSIBLE (which is set by default +if C99_IL_EXTENSIONS_SUPPORTED is set). If +LOWER_DESIGNATED_INITIALIZERS is TRUE (which it is by default if +C99 lowering is done), designators are almost completely eliminated; +they remain only for initializations of members other than the first in +unions, which are not possible in C89.
      +
      +
    • +
    • +
      For _Bool, the type is represented as in C++ (the bool_type flag is +set in the integral type). C99 lowering eliminates _Bool by rewriting +the type as a typedef to the underlying integer type.
      +
      +
    • +
    • +
      For complex and imaginary types, there are new type kinds (tk_complex +and tk_imaginary), new constant kinds (ck_complex and +ck_imaginary), and some new operator kinds (e.g., eok_jfadd and +eok_jmultiply) and conversions. If LOWER_COMPLEX is TRUE, C99 +lowering rewrites complex types as structs and imaginary types as +floating-point types, rewrites the constants as aggregate or floating-point +constants, and rewrites the operators and conversions as runtime routine +calls.
      +
      +
    • +
    • +
      For flexible array members, the last member of a struct type may have an +array type with an unknown bound. No lowering is done.
      +
      +
    • +
    • +
      For non-constant expressions in aggregate initializers, the aggregate +constants contain ck_dynamic_init constants, as in C++. C99 lowering +rewrites those as executable code.
      +
      +
    • +
    • +
      For inline functions, the function is marked with the is_inline and +suppress_inline_body flags, as in C++. If MINIMAL_INLINING is +TRUE, C99 lowering replaces inline function calls with the expansions where +possible (as is done in C++).
      +
      +
    • +
    • +
      For longlong, there are two new integer kinds (ik_long_long +and ik_unsigned_long_long) and new constants of these kinds. This +feature can be enabled also in C89 mode and in C++ mode, and is controlled +by the macro LONG_LONG_ALLOWED (which is set by default if +C99_IL_EXTENSIONS_SUPPORTED is set). No lowering is done.
      +
      +
    • +
    • +
      For mixed statements and declarations, the statements and declarations +appear intermixed in the statement list of a compound statement, as in C++. +No lowering is done.
      +
      +
    • +
    +
    +
    +

    4.30. Entry Prefix#

    +

    Each IL entry is preceded by a prefix, which is not part of the IL entry proper +but contains information about the entry that is useful to tree walking +routines and the like:

    +
      +
    • +
      Is the entry allocated in the file-scope memory region?
      +
      +
    • +
    • +
      Has the entry been encountered yet on a tree walk of the IL?
      +
      +
    • +
    • +
      Has the entry been encountered yet by IL lowering?
      +
      +
    • +
    • +
      What entry number has been assigned to the entry (for the alternate IL file +format)?
      +
      +
    • +
    +

    This prefix is allocated in space preceding the beginning of the entry (that +is, one has to do special address arithmetic to get to the prefix; see the +macro il_entry_prefix_of). Some of the flags mentioned above are present +only when required by the front end configuration.

    +
    +
    +

    4.31. Orphans#

    +

    Type entries and static variables that are local to a function require some +special handling. All type entries and all static variables are allocated in +the file scope memory region. However, types and static variables that are +local to a function are placed on the types and static variables list of a +function or block scope. Those are unusual lists: the scope entry (in a +function scope memory region) points to a list that is entirely in the file +scope memory region. Yet, the entries pointed to are not really part of the +file scope. They might, in fact, not be referenced from anywhere except the +function scope memory region. Such entries are “orphaned” in the file scope: +their parents can be processed, written out, and removed from memory, but the +children remain in the file scope, unattached to the rest of the file scope IL +tree.

    +

    A similar problem occurs when an IL entry such as a type is allocated in the +file scope memory region because it might be shared. If the entity is +referenced only from function scope memory regions, it too will be an orphan.

    +

    Orphans are a problem if one wants to process the intermediate language on a +per-memory-region basis. One needs to be able to find all of the orphans when +processing the file scope memory region. There are two mechanisms that help +with this:

    +
      +
    • +
      il_header points to a list of entries of type +a_scope_orphaned_list_header. Each entry on this list holds a copy of +the local type and static variable list pointers for a function or block +scope that has such entries. The a_scope_orphaned_list_header entries +are allocated in the file scope memory region, so they can be used to find +all such lists if the function and block scopes are no longer in memory.
      +

      +
      See the routine add_scope_orphaned_il_lists.
      +
      +
    • +
    • +
      Each file-scope IL entry is preceded by space for a pointer. (This space +precedes the entry prefix.) The pointer is used to chain potential orphans +onto a list of entries of the same kind headed by an element of the global +array orphaned_file_scope_il_entries. Those lists can be traversed +after processing the file scope to find entries that might otherwise be +lost. Note that entries are placed on the list if they are potential +orphans, i.e., if they are allocated in the file scope memory region and +are referenced from a function scope memory region. Most of the entries on +the lists will not be orphans, but all orphans will appear on the list.
      +

      +
      See the routine add_orphaned_file_scope_il_entry.
      +
      +
    • +
    +

    All orphan processing is included only if needed. It is needed if IL lowering +is done or if an IL file is written.

    +
    +
    +

    4.32. Relationship of the IL and the Symbol Table#

    +

    The symbol table of the front end is not part of the intermediate language +structure and is not passed to the back end. It is really mostly a name lookup +mechanism, which one can use to look up a name to get to the associated +intermediate language entry. By the time a back end receives the IL, all +references to entries are simply pointers to the proper entries, and therefore +no name lookup mechanism is needed.

    +

    The symbol table also contains some information that is only needed in the +front end (for error checking or searching) and is not passed to the back end, +or information that has no IL representation (for example, symbol entries for +keywords).

    +

    The symbol table also always reflects the true C and C++ idea of name scoping, +which may not exactly match the IL representation. For example, if we have the +declaration extern int xx in two scopes, each declares a name xx whose +visibility is limited to the scope in which it is declared, but the object (an +integer variable) associated with the name exists over the entire program. +During the front end compilation process there would be two different symbol +entries for xx in two different scopes, but in the intermediate language +there would be only one variable entry for xx, and it would appear at the +file scope level. All references to either xx of the source program would +point to that one entity, and would not indicate which of the original xxs was referenced.

    +
    +
    +

    4.33. Templates#

    +

    The front end generates IL for instances of templates. For example, class +types are generated for instances of class templates and routines are +generated for instances of function templates. A back end can view a +template as a sort of powerful macro expanded by the front end, and can +deal with the generated IL for instances exactly as if the instances were +non-template classes and routines. A code generator need not, in general, +care that the source program contained templates.

    +

    Each template declaration or definition in the source program is +represented by an IL entry of type a_template. A list of those is +attached to the templates field of a_scope. A separate +a_template entry is included for each declaration or definition of a +given template (i.e., there can be more that one a_template entry +associated with a single template; if there is, the first such entry is the +canonical one, and is used when referring to the template itself as opposed +to a given declaration of the template). When the macro +ALL_TEMPLATE_INFO_IN_IL is set to TRUE, a_template entries are also +generated for member functions, static data members, and member classes +nested in class templates. If RECORD_TEMPLATE_STRINGS is TRUE, the +a_template entry contains a pointer to a null-terminated string that is +a textual representation of the template declaration or definition.

    +

    The generated IL for an instance generated from a template does preserve some +indications of the fact that the entity came from a template:

    +
      +
    • +
      The type entry variant for class/struct/union has an is_template_class +flag that is set for template classes. If the class is an instance of a +template, rather than a member of a class that is a template, the class +type supplement’s template_arg_list field gives the list of template +arguments for the template.
      +
      +
    • +
    • +
      The routine entry has an is_template_function flag that is set for +template functions. If the function is an instance of a template, rather +than a member of a class that is a template, the routine entry’s +template_arg_list field gives the list of template arguments for the +template.
      +
      +
    • +
    • +
      The variable entry has an is_variable_template flag that is set for +template variables and template static data members.
      +
      +
    • +
    • +
      The variable and routine entries have instantiation information flags.
      +
      +
    • +
    +

    Template argument lists are represented by a list of a_template_arg +entries. Each entry points to an argument value: an IL type for a type +template argument, an IL constant for a nontype template argument, or an +a_template entry for a template template argument.

    +

    More information about templates is available when the macro +ALL_TEMPLATE_INFO_IN_IL is set to TRUE. With that setting:

    +
      +
    • +
      The assoc_template field (in a class type supplement, routine, or +variable) points to the (canonical) a_template entry for the associated +template.
      +
      +
    • +
    • +
      A canonical_template field of a_template points the canonical +a_template entry for the associated template.
      +
      +
    • +
    • +
      A definition_template field of a_template is set in the canonical +entry to point to the a_template entry associated with the template +definition (if any). In other entries it is NULL.
      +
      +
    • +
    +

    When ALL_TEMPLATE_INFO_IN_IL is TRUE and, in addition, the variable +prototype_instantiations_in_il is TRUE, the IL tree includes IL for +templates themselves (as opposed to IL for instances of templates). This IL is +produced by doing a “prototype instantiation” of the template, which means +doing syntax and (partial) semantic analysis of the template definition without +the use of actual template argument values. Of necessity, such analysis is +incomplete; the meaning of certain constructs cannot be determined until the +actual template argument values are known. Therefore, the IL for prototype +instantiations can contain special generic operators and variants of other IL +constructs that do not appear in normal IL (e.g., eok_lvalue).

    +

    Prototype instantiations of classes are always done. Prototype instantiations +of functions are done when the variable nonclass_prototype_instantiations +is TRUE (see the command-line option --parse_templates). The variable +prototype_instantiations_in_il controls whether prototype instantiations +are preserved in the IL. If the flag is FALSE, the instantiations – if done +– are thrown away and not linked into the IL tree. If the flag is TRUE, the +prototype instantiations are done and preserved, and

    +
      +
    • +
      The a_template entry for each template poimts to IL for its prototype +instantiation: a class type for a class template, a routine for a function +template, or a variable for a variable template or static data member +template.
      +
      +
    • +
    • +
      The a_template entry points to an entry of type a_template_decl, +which provides information about the template header (source position, +parameter list). The information on parameters is given by a list of +entries of type a_template_parameter. (The pointer is NULL for +a_template entries for member functions, static data members and member +classes nested in class templates.)
      +
      +
    • +
    +

    Note that when prototype_instantiations_in_il is TRUE and +nonclass_prototype_instantiations is FALSE only class prototype +instantiations are included in the IL.

    +

    While the front end is processing templates, it is convenient for it to be able +to generate IL versions of entities (like class members) that are not “real,” +i.e., that exist only as part of some template abstraction that will never be +seen by the back end. For those cases, it is helpful to be able to represent +types and constants which are not known but which nevertheless have a certain +identity, e.g., they’re derived from template parameters of a current template. +The tk_template_param type and the ck_template_param constant are used +for those cases. Likewise, a special a_template entry is created to +represent the unknown value of a template template parameter inside a prototype +instantiation. These entities will appear in the IL tree only inside prototype +instantiations.

    +

    C++/CLI generics are represented as templates with an extra flag +(is_generic_definition in both class types and routines). They can also +have additional constraint information, provided by entries of type +a_generic_constraint and a_generic_constraint_clause.

    +
    +
    +

    4.34. Macros#

    +

    If RECORD_MACROS_IN_IL is set to TRUE, entries of type a_macro are +created and added to the macros list of the IL header. The entries +contain a textual version of the macro definition (e.g., a string like +“#define x(a) a+1”), except for predefined macros like __LINE__ and +__FILE__ whose replacement text varies from one invocation to the next. +The entries for these macros contain an empty (zero-length) text string +instead of a fixed definition. If a macro is redefined (to a different +string), there is another macro entry for the new definition. Macro +entries are also used to represent #undef directives.

    +

    The front end can also be configured to maintain detailed information regarding +macro invocations. For instance, it is possible to determine the original +source position of text that appears in the expansion of a macro invocation. +This extra position information can be used to produce more-detailed diagnostic +messages regarding such text, and source analysis tools can more accurately +identify the positions and ranges associated with declarations, expressions, +and statements. It is also possible to determine the chain of macro +invocations that led to a particular macro expansion or to obtain a macro +invocation tree (similar to a function call tree) for an entire translation +unit.

    +

    If FULLY_RESOLVED_MACRO_POSITIONS is TRUE, a_source_position has an +extra sequence/column pair, orig_seq and orig_column. For text +appearing directly in the source, both pairs will indicate the same position. +For text that occurs in a macro expansion, however, +orig_seq/orig_column will be the source position at which the text +originally appeared before being copied into the macro expansion – either in +the definition of some macro or in the argument list of the top-level macro +invocation. (Regardless of the value of FULLY_RESOLVED_MACRO_POSITIONS, +the seq/column pair for all positions in a macro expansion indicate the +initial position of the top-level macro invocation.)

    +

    If MACRO_INVOCATION_TREE_IN_IL is set to TRUE, a flattened macro +invocation tree is kept in the file scope memory region. Because +variably-sized data is awkward to represent in the IL, the list of macro +invocation records is broken into fixed-size blocks of type +a_macro_invocation_record_block, each containing +MACRO_INVOCATIONS_PER_BLOCK records, and these blocks are organized +into a binary tree to reduce the cost of accessing an arbitrary invocation +record.

    +

    There is one record in the tree (of type a_macro_invocation_record) for +each macro invocation that was performed. Each such record indicates the +parent invocation, the macro that was invoked, and the (original) source +position of the macro name that introduced the invocation. Furthermore, if +EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the record will contain the +(original) ending position of the macro invocation (the last character of the +name of an object-like macro or the closing parenthesis in the invocation of a +function-like macro).

    +

    In addition, when MACRO_INVOCATION_TREE_IN_IL is TRUE, +a_source_position contains the index of the macro invocation record in +whose expansion that position occurs (or NO_PARENT_MACRO_INVOCATION if the +position refers to text that appears directly in source code).

    +

    The macro_context field in a_source_position and +parent_macro_index in a_macro_invocation_record enable +reconstruction of the stack of macro invocations that resulted in the text +at that position. Each macro invocation record is uniquely identified by +an index value of type a_macro_invocation_index, so the macro +invocation stack can be traced simply by following the chain of +parent_macro_index values. (An invocation of macro C is considered +to be a child of an invocation of macro P if C’s invocation appears +in the argument list or the expansion of that invocation of P.)

    +

    For convenience in accessing macro invocation records by index, +il_def.h defines the macro set_macro_inv_record_ptr_to_index(root, index, mirp), which sets a pointer mirp of +type a_macro_invocation_record_ptr to the address of the record at the +specified index, given the tree root (which is found in +il_header.root_macro_invocation_record_block).

    +

    In addition to direct access into the tree by record index, it is possible to +scan the tree sequentially; the records are stored in the same order that the +invocations were performed during preprocessing. To facilitate reconstruction +of the invocation tree during such a traversal without the necessity of +maintaining a separate invocation stack, the array contains certain +“placeholder” records that do not denote macro invocations. Such records are +identified by a negative value (other than NO_PARENT_MACRO_INVOCATION) for +the parent invocation.

    +

    To understand the use of these placeholder records, consider two records +M and N reflecting successive macro invocations. If the parent +invocation of N is the same as that of M, the two invocations are +siblings and the transition from M to N implies no change to the +conceptual invocation stack. If the parent invocation of N is M +itself, then N is a child of M (i.e., invocation M is assumed to be +pushed onto the stack). Otherwise, a non-negative parent index in N is +assumed to be a single-level pop of the conceptual stack – that is, the +parent of N is the parent of M’s parent. In all these cases, the +invocation records for M and N will be at consecutive indices. If, on +the other hand, the parent of N is a more remote ancestor of M, a +placeholder record will be inserted between M and N with a negative +parent index whose absolute value is the number of invocations to pop from +the conceptual stack in order to restore that remote ancestor to the top of +the stack.

    +
    +
    +

    4.35. Attributes#

    +

    C++11 (“standard”), GNU, and Microsoft __declspec attributes are +represented in the IL by entries of type an_attribute. If such attributes +appear on a declaration, they are pointed to by the attributes field of the +corresponding entry’s source correspondence; otherwise, a dedicated attributes +field is used (e.g., in a_param_type). When +RECORD_UNRECOGNIZED_ATTRIBUTES is TRUE, unrecognized attributes are +recorded in the IL with kind ak_unrecognized (when the macro is FALSE, +unrecognized attributes are not recorded and a warning is issued). All +attributes specified in the same “group” point to an entry of type +an_attribute_group. Empty groups contain a pseudo-attribute of kind +ak_empty_attr (or more than one, for a GNU construct like +“__attribute((,,,))”).

    +

    If an attribute includes an argument list, the corresponding attribute entry +points to a list of an_attribute_arg entries. An empty argument list – as +in __attribute((nonnull())) – is represented with an argument entry of +kind aak_empty. Otherwise, the entries in the argument list represent a +constant (aak_constant), a type (aak_type) or an uninterpreted token +(aak_token or aak_raw_token). aak_token entries represent single +tokens that may be followed by other arguments separated by a comma. In +contrast, aak_raw_token entries represent one or more tokens including the +commas; a sequence of aak_raw_token entries is always followed by a +terminating aak_empty entry (used primarily to record the position of the +token that follows in the source – this is useful for diagnostic purposes). +If an unrecognized attribute is followed by a non-empty argument list, that +list consists of aak_raw_token entries (including entries for any commas in +the list). E.g., the unrecognized C++ attribute [[ unrecog(x, y) ]] has +three aak_raw_token argument entries for “x”, “,”, and “y” +(followed by a aak_empty entry).

    +

    Microsoft attributes (delimited by single brackets) are represented in the IL +by entries of type an_ms_attribute. Depending on the configuration of the +front end, a given Microsoft attribute may be either “recognized” or +“unrecognized”. All attributes include a string representation of the +attribute from the source. In addition, recognized attributes include an +argument list representing the arguments that were specified in the attribute +reference.

    +

    Microsoft attributes that apply to function parameters are pointed to by the +param type entry. All other attributes are pointed to by the ms_attributes +field of an IL scope entry. Attributes that apply to a particular entity +include a pointer (see the entity field) to that entity. The entity does +not point back, but rather has its has_associated_attribute flag in its +source correspondence set.

    +
    +
    +

    4.36. Properties#

    +

    Microsoft properties come in two kinds:

    +
      +
    • +
      Old-style properties indicated by the __declspec(property(… )) +attribute. The accessor functions are only loosely associated with the +property, by being named in the attribute.
      +
      +
    • +
    • +
      New-style properties in C++/CLI, which begin with the “property” +context-dependent keyword. The accessor functions are declared as part of +the property declaration, in a form that looks vaguely like a nested class.
      +
      +
    • +
    +

    In both cases, the IL has a description of the property declaration, so that is +retained in something close to the source form (that information is held in +a_property_or_event_descr entry). However, also in both cases, references +to the properties are expanded by the front end, so they are not retained in +source form. A bit of source code like “p+=1” might be +expanded into a series of calls something like “call the get accessor for +p, call operator+ on the fetched value and 1, and call the put accessor +to store the computed value.” The generated IL contains some tags on various +nodes in the expansion that help source-analysis code recover the original +meaning, though in a cumbersome way.

    +

    C++/CLI events are very similar to the new-style properties, in representation +and in the fact that references are expanded by the front end.

    +
    +
    +

    4.37. Microsoft __if_exists blocks#

    +

    Representing __if_exists (and __if_not_exists) blocks in the IL is +problematic because, although the Microsoft documentation describes the +contents of an __if_exists block as a statement, the Microsoft compiler +actually accepts any fragment of a statement or declaration in the block (as +does our front end in Microsoft mode).

    +

    The front end provides a mechanism that can represent __if_exists blocks +that appear in class definitions, and which surround complete declarations of +the class. When an __if_exists appears in a valid location in a class +definition, an IL entry (an_ms_if_exists) and source sequence entry are +created for the start and end of the block. __if_exists blocks in other +scopes are not represented in the IL (but are still included in the textual +representation of templates). If an __if_exists appears in an invalid +context in a class definition, an error is issued.

    +

    IL entries are only created for __if_exists blocks that appear in the +prototype instantiation of class templates and classes nested within class +templates. In non-template contexts, the __if_exists is simply evaluated +when it is encountered.

    +
    +
    +

    4.38. IL Use Within the Front End#

    +

    Some aspects of the IL are used only during the front end processing and are +not seen by back ends.

    +

    Most of the primary table types have a kind used to represent errors (e.g., an +error constant, an error expression). These are used to replace parts of the +IL tree that contain errors. Since the back end is not run if there are +errors, a back end will never see these kinds of entries.

    +

    There are also a few table kinds used for unknown entities (not known yet, but +not an error), for example the unknown type kind tk_unknown. These are +replaced by actual kinds by the time a back end sees the IL.

    +

    Constant expressions are generally folded to a single constant value and +the front end uses that folded value for its processing. In scanning +1+2, for example, the 1 and 2 will be folded into a constant +entry for 3, and that value will be used internally. The original +expression that was folded is generally preserved via the expr field of +a_constant.

    +
    +
    +

    4.39. How To Extend the IL#

    +

    Extending the intermediate language involves making a coordinated set of +changes in several files. Three kinds of changes are discussed below:

    +
      +
    • +
      adding a field to an existing IL entry (typically quite straightforward),
      +
      +
    • +
    • +
      adding a new operator kind (usually also straightforward), and
      +
      +
    • +
    • +
      adding a brand new IL entry (only a little more complicated).
      +
      +
    • +
    +

    Note, however, that what is covered is the typical case. There may be +additional complications. And, of course, nothing of a general nature can be +said about how a field or entity is set and used or how it interacts with other +parts of the IL.

    +
    +

    4.39.1. Adding a Field to an Existing IL Entry#

    +

    This is what you need to do to add a field f of type T to existing IL +entry E with an_il_entry_kind iek_e:

    +
    + + + + + + + + + + + + +
    +
    in il_def.h:
    +
    +
    +
    Add f to E.
    +
    +
    +
    in il_alloc.c:
    +
    +
    +
    Initialize field f in the routine that allocates E objects.
    +
    +
    +
    in il_display.c:
    +
    +
    +
    Add code to display the value of f. This will typically appear +in a function called disp_e, and the display will depend +on the type T. For example, disp_boolean will be called for +a flag, disp_ptr will be called if T is of type +pointer-to-IL-entry, and so forth.
    +
    +
    +
    +

    and in addition, if T is of type pointer-to-IL-entry:

    +
    + + + + + + +
    +
    in walk_entry.h:
    +
    +
    +
    In WALK_ENTRY_ROUTINE_NAME, there will be a case clause +for iek_e within the main switch statement. Here you +will usually need to add a call to walk_ptr or remap_ptr. +(The latter is typically used if f is a secondary reference to +the object it points to, but walk_ptr can be used in any +case.) There are some special cases to look out for, however. For +example, if f points to a linked list, instead of walk_ptr +call either walk_list (if *T uses a next pointer) +or walk_list_on_link_field.
    +
    +
    +
    +

    If f is an addition to the a_type entry, update traverse_type_tree +accordingly.

    +

    If f is an addition to the an_expr_node entry, update traverse_expr +accordingly.

    +

    If f is an addition to the a_statement entry, update +traverse_statement accordingly.

    +

    If f is an addition to the a_dynamic_init entry, update +traverse_dynamic_init accordingly.

    +

    If f is an addition to the a_constant entry in its function as the +description of an initializer, update traverse_constant accordingly.

    +
    +
    +

    4.39.2. Adding a New Operator#

    +

    Most expression nodes (an_expr_node) represent operations +(enk_operation) like additions, assignments, calls, casts, etc. Each of +these operation kinds is identified by an enumeration constant (eok_add, +eok_call, …). To add a new operation kind, it is not sufficient to add +another constant; the following updates are also required:

    +
    + + + + + + + + + + + + + + + +
    +
    in il_def.h:
    +
    +
    +
    Add a string constant to db_operator_names.
    +
    +
    +
    in il_display.c:
    +
    +
    +
    Add a case for the new operator in disp_expr_operator_name.
    +
    +
    +
    in cp_gen_be.c:
    +
    +
    +
    Update generated_precedence to cover the new operator.
    +
    +
    +
    in il.c:
    +
    +
    +
    Update lvalue_rvalue_test and operation_type_kind, and if the +operator has side effects, also operation_has_side_effects.
    +
    +
    +
    +

    Furthermore, if the operator may produce an lvalue (is_lvalue is TRUE) or +xvalue (is_xvalue is TRUE), additional functions must know about the new +operator kind:

    +
    + + + + + + + + + +
    +
    in il.c:
    +
    +
    +
    is_rvalueable_node, node_does_fetch, and +operator_takes_lvalue_operand.
    +
    +
    +
    in exprutil.c:
    +
    +
    +
    conv_prvalue_expr_to_glvalue, and (if is_rvalueable_node +indicates that the operator is not “rvalueable”) +conv_glvalue_expr_to_prvalue.
    +
    +
    +
    +

    Finally, if the operator is an addressing operator, a few other routines +require updating:

    +
    + + + + + + + + + +
    +
    in folding.c:
    +
    +
    +
    constant_glvalue_address and constant_prvalue_pointer.
    +
    +
    +
    in il_walk.c:
    +
    +
    +
    traverse_addressing_subtree.
    +
    +
    +
    +

    Adding a new expression node kind (new enk_...variant) is harder. That +requires looking at all code that handles expressions, in particular switch +statements that case out on the expression kind, and making appropriate +changes. If the new variant includes an embedded type, be sure to update +examine_expr_for_dependent_type.

    +
    +
    +

    4.39.3. Adding an IL Entry#

    +

    This is what you need to do to add an IL entry of struct type X, +where X is a name with the form a_xxx:

    +
    + + + + + + + + + + + + + + + + + + + + + +
    +
    in il_def.h:
    +
    +
    +
    Add the definition of X. Add iek_xxx to the enumeration +an_il_entry_kind. Update the initialization of +il_entry_kind_names and sizeof_il_entry.
    +
    +
    +
    in walk_entry.h:
    +
    +
    +
    Add a case clause for iek_xxx in +WALK_ENTRY_ROUTINE_NAME. Add calls to process orphans in +WALK_ORPHANED_ENTRY_ROUTINE_NAME.
    +
    +
    +
    in il_walk.c:
    +
    +
    +
    Add calls to process orphans in +remap_first_ptr_of_orphaned_file_scope_entry_array and in +remap_last_ptr_of_orphaned_file_scope_entry_array.
    +
    +
    +
    in il_alloc.c:
    +
    +
    +
    Add an alloc_xxx routine. If the entity should always be +allocated in the file scope memory region, call alloc_il; to use +the current memory region, call alloc_cil. (Do not use +alloc_fe for entities in the IL.) If the entity is a supplement to +some other entry (to keep down the size of the containing entry), the +space for the supplement should be allocated when the containing entry +kind is set to that variant. See examples in set_type_kind. In +such cases, you should also change the copy routine for the containing +entity so that it copies the supplement as well. See copy_type +and copy_node for examples. If you want to track the number of +entities of type X that are allocated and how much space they use, +define a static variable num_xxxes_allocated, initialize +it in il_alloc_init, register it in il_alloc_one_time_init in +case precompiled headers are used, increment it in alloc_xxx, +and display it by adding code to show_il_alloc_space_used.
    +
    +
    +
    in il_display.c:
    +
    +
    +
    Add a disp_xxx routine. Add a case clause for +iek_xxx in disp_entry. If the entity is a supplement, +add its kind to the list at the beginning of disp_entry (a +list of entity kinds for which the entity is displayed with the +containing entity), and put the call of disp_xxx in the +clause for the containing entity.
    +
    +
    +
    in il.c:
    +
    +
    +
    If the entry might be an orphan (allocated in the file-scope memory +region, pointed to from something in a function-scope memory region, +but not pointed to from anything in the file-scope memory region), add +the entry kind as a case in +f_possibly_add_orphaned_file_scope_il_entry.
    +
    +
    +
    +

    This is what is required in the general case, but there are potentially many +other issues to consider. For example, if X has a substructure of type +a_source_correspondence:

    +
    + + + + + + + + + +
    +
    in il_alloc.c:
    +
    +
    +
    Be sure alloc_xxx calls set_default_source_corresp. +Add a case clause for iek_xxx in +source_corresp_for_il_entry.
    +
    +
    +
    in il_display.c:
    +
    +
    +
    Add a case clause for iek_xxx in disp_ptr.
    +
    +
    +
    +

    If X is added to a_class_type_supplement, and the field is one that is +meaningful even if the class does not have a definition:

    +
    + + + + + + +
    +
    in il.c:
    +
    +
    +
    If you use “needed” flags (MAINTAIN_NEEDED_FLAGS is TRUE), modify +turn_class_definition_into_declaration to copy X when clearing +the class type supplement.
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/includes/index.html b/dev/doc/includes/index.html new file mode 100644 index 0000000..049226e --- /dev/null +++ b/dev/doc/includes/index.html @@ -0,0 +1,307 @@ + + + + + 20. ANSI C and C++ Include Files - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    20. ANSI C and C++ Include Files#

    +
    +

    20.1. Standard C++ Include Files#

    +

    The following include files are supplied with the front end:

    +
      +
    • +
      compare.stdh
      +
      +
    • +
    • +
      coroutine.stdh
      +
      +
    • +
    • +
      cxxabi.h
      +
      +
    • +
    • +
      exception.h
      +
      +
    • +
    • +
      exception.stdh
      +
      +
    • +
    • +
      initializer_list.stdh
      +
      +
    • +
    • +
      new.h
      +
      +
    • +
    • +
      new.stdh
      +
      +
    • +
    • +
      source_location.stdh
      +
      +
    • +
    • +
      stdexcept.h
      +
      +
    • +
    • +
      stdexcept.stdh
      +
      +
    • +
    • +
      stdfloat.stdh
      +
      +
    • +
    • +
      typeinfo.h
      +
      +
    • +
    • +
      typeinfo.stdh
      +
      +
    • +
    +

    The “. stdh” files are basically the same as the definitions in the C++ +standard. The standard specifies header names without a suffix (e.g., +<new>). The front end, by default, adds the stdh suffix when searching +for the header file. The “.h” versions are supplied so that older code +that uses header names like <new.h> will continue to work.

    +

    Not all of the header files for the libraries required by the C++ standard are +provided. In general, header files are only supplied for components of the +library for which an implementation is supplied with the front end.

    +

    The typeinfo.h header file contains the definition of the type_info +data structure used by the front end and the runtime library. The +type_info structure must not be changed unless corresponding changes are +also made in the front end and runtime.

    +

    The cxxabi.h header includes declarations of routines and data structures +specified by the IA-64 ABI.

    +
    +

    20.1.1. Namespaces and the Standard Header Files#

    +

    When front end configuration flag RUNTIME_USES_NAMESPACES is TRUE the front +end defines the preprocessing macro __EDG_RUNTIME_USES_NAMESPACES. This +flag is tested by the C++ header files to determine whether the runtime +declarations should appear in the global scope or in the std namespace. +The C++ header files also test the __EDG_IMPLICIT_USING_STD flag, which is +defined by the front end when the front end is configured to use namespace in +the runtime and when the --using_std option is specified when the front end +is invoked. This flag causes the header files to do a using namespace std +in any header file that contains declarations for entities in the std +namespace.

    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/index.html b/dev/doc/index.html new file mode 100644 index 0000000..c4b2bcc --- /dev/null +++ b/dev/doc/index.html @@ -0,0 +1,288 @@ + + + + + CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    C/C++ Front End Documentation#

    +
    +
    +
    +

    Introduction#

    +

    This document describes the function and internal structure of the Edison +Design Group C/C++ Front End. More precisely, it gives the general overview +necessary as an introduction to the study of the source code of the Front End. +The source code comments provide more detailed information, and that +information is not necessarily repeated here.

    +

    The front end accepts the C++ language as defined by the ISO/IEC 14882:2020 +standard, as well as a number of the features of the ISO/IEC 14882:2024 +standard. The front end can also be configured to accept earlier revisions of +the C++ standard (e.g., ISO/IEC 14882:2003). With the proper command-line +options, it alternatively accepts the C language of the ISO/IEC 9899:1990, +ISO/IEC 9899:1999, ISO/IEC 9899:2011, and ISO/IEC 9899:2018 standards, as well +as a number of features from the ISO/IEC 9899:2024 standard. Certain other +dialects of C++ and C are also accepted, including Microsoft, GNU and Clang +dialects. C++/CLI, the Microsoft extension to C++ in support of Microsoft’s +.NET environment (and formalized through the ECMA-372 standard), is also +implemented.

    +

    It is a single pass, including integrated preprocessing. (Preprocessing +alone – to a textual output file – can also be done, as in traditional +compilers with a separate preprocessor.) The syntax-analysis technique is +recursive descent, with a precedence modification to speed up the scanning +of expressions.

    +

    The front end does no optimization. Its goal is to produce a complete and +clean parsed form of the source program, and to diagnose errors. It does +complete error checking, produces clear error messages (including the position +of the error within the source line), and avoids cascading of errors. It also +tries to avoid seeming overly finicky to a knowledgeable C or C++ programmer.

    +

    The front end is written in a portable dialect of C++, using features from the +ISO/IEC 14882:2011 standard (i.e., it’s written using C++11 features). Host +and target computer characteristics (e.g., command-line interface, character +sets, integer sizes, floating-point representation) are carefully separated +from the main body of code so that they can be easily changed for rehosting or +retargeting. There is extensive debugging and assertion-checking code, which +can be included or excluded by conditional compilation options.

    +

    The output from the front end is a high-level tree-structured in-memory +intermediate language. This intermediate language contains full information on +declarations, statements, and expressions, all in tree form, and all with +source-correspondence information that simplifies the generation of symbolic +debugging information.

    +

    The intermediate language can, if desired, be written to a file, read back from +such a file, or displayed in human-readable form.

    +

    When it translates C programs to intermediate language, the front end uses only +the C subset of the intermediate language. When it translates C++ programs to +intermediate language, it uses the full intermediate language. However, an +optional IL lowering pass can be used translate the C++ intermediate language +constructs into C intermediate language constructs to reduce the work required +of back ends.

    +

    It is expected that the front end will be combined with an appropriate back end +that will generate object code from the intermediate language. A simple back +end is provided that generates C from the intermediate language, and another +that generates C++ from the intermediate language (the latter is intended for +source-to-source applications).

    +

    Also included: minimal runtime, a template prelinker, an IL display utility, a +name demangler, and prototype header files.

    +

    This document covers:

    +
      +
    • The external interface of the front end – the command-line options, +language dialect, intermediate language, and host/target configuration +issues. (Error messages are listed in an appendix.)

    • +
    • The design of the front end – its philosophy and an overview of the source +code.

    • +
    +

    Readers of this document should be familiar with the C++ language, with the C +language, and with the basics of compiler theory.

    +
    +
    +
    +

    Indices and tables#

    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/int_overview/index.html b/dev/doc/int_overview/index.html new file mode 100644 index 0000000..528b306 --- /dev/null +++ b/dev/doc/int_overview/index.html @@ -0,0 +1,2679 @@ + + + + + 3. Overview of Internal Structure - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    3. Overview of Internal Structure#

    +
    +

    3.1. Function of the Front End#

    +

    The front end reads source files written in C or C++, diagnoses any errors in +them, and produces an intermediate language tree that represents the source +program.

    +

    The source files are one primary source file (named on the command line) +and zero or more header files (specified by #include directives). If +COMPILE_MULTIPLE_SOURCE_FILES or COMPILE_MULTIPLE_TRANSLATION_UNITS +is TRUE, multiple source files may be specified on the command line.

    +

    The intermediate language tree is an in-memory representation of the source +program, from which a back end can generate object code. This intermediate +form is high-level (i.e., its constructs correspond closely to C or C++ +constructs). Implicit transformations in the source language are made explicit +in the intermediate language. Source-correspondence information is preserved +so that symbolic debugging information can be generated.

    +

    When it translates C programs to intermediate language, the front end uses only +the C subset of the intermediate language. When it translates C++ programs to +intermediate language, it uses the full intermediate language. However, an +optional IL lowering pass can be used translate the C++ intermediate language +constructs into C intermediate language constructs (this lowering is not +available for C++/CLI and C++/CX).

    +

    The front end does not do any optimizations. It does not transform the program +in other than trivial ways.

    +

    The front end would usually be run from a driver, which invokes the front end +and back end in order, and which validates and distributes the command-line +options. In such a case, the front end would write the intermediate language +information to a file, which would be read by the back end.

    +

    The front end incorporates the preprocessing function of the C and C++ +languages, and does them on the fly as it parses the source program. The front +end can also be run in a preprocessing-only mode, and will generate +preprocessing output as a separate preprocessor would. Comments can be kept or +removed in this process.

    +

    The front end can generate a file containing raw listing information to be used +to assemble a compilation listing. The raw listing file contains raw source +lines, information on transitions into and out of include files, and +diagnostics generated by the front end. A file containing cross-reference +information (information on each reference to an identifier in the source +program) can also be generated in a different file.

    +
    +
    +

    3.2. Guide to the Source Files#

    +

    Note that most source files have a .c file suffix, even though they contain +C++ code and must be compiled with a C++ compiler (with the C++11 dialect). +That naming convention is for historical reasons and for ease in delivering +patches against earlier versions of the front end. Symbolic links (e.g., with +a .cpp suffix) can be added if required by a build environment.

    +

    The source files are:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    attribute.h
    +
    +
    +
    Declarations related to attribute.c (scanning of attributes).
    +
    +
    +
    basics.h
    +
    +
    +
    Basic declarations for every compilation.
    +
    +
    +
    builtin_defs.h
    +
    +
    +
    Declarations related to GCC/clang/Microsoft builtin functions. This +header file is generated automatically by a tool that retrieves the +signatures of these builtin functions from various versions of GCC and +clang compilers (the Microsoft builtin function signatures are +manually input to this automated process).
    +
    +
    +
    builtin_kinds.h
    +
    +
    +
    Builtin function kinds (split from builtin_defs.h to improve +compilation times). This header file is generated automatically by a +tool that retrieves the signatures of these builtin functions from +various versions of GCC and clang compilers (the Microsoft builtin +function signatures are manually input to this automated process).
    +
    +
    +
    c_gen_be.h
    +
    +
    +
    Declarations related to c_gen_be.c (C-generating back end).
    +
    +
    +
    cfe_daemon_common.h
    +
    +
    +
    Declarations related to cfe_daemon.c exposed for utility programs.
    +
    +
    +
    checking.h
    +
    +
    +
    Fundamental declarations associated with assertion checking.
    +
    +
    +
    class_decl.h
    +
    +
    +
    Declarations related to class_decl.c (class declarations +scanning).
    +
    +
    +
    cmd_line.h
    +
    +
    +
    Declarations related to cmd_line.c (command-line parsing).
    +
    +
    +
    const_ints.h
    +
    +
    +
    Declarations related to the manipulation of the internal +representation of integer constants.
    +
    +
    +
    cp_gen_be.h
    +
    +
    +
    Declarations related to cp_gen_be.c (C++/C-generating back end).
    +
    +
    +
    debug.h
    +
    +
    +
    Declarations related to debug.c (debug output).
    +
    +
    +
    decl_inits.h
    +
    +
    +
    Declarations related to decl_inits.c (declaration initializers +scanning).
    +
    +
    +
    decl_spec.h
    +
    +
    +
    Declarations related to decl_spec.c (declaration specifiers +scanning).
    +
    +
    +
    declarator.h
    +
    +
    +
    Declarations related to declarator.c (declarator scanning).
    +
    +
    +
    decls.h
    +
    +
    +
    Declarations related to decls.c (declarations scanning).
    +
    +
    +
    def_arg.h
    +
    +
    +
    Declarations related to def_arg.c (default argument scanning).
    +
    +
    +
    defines.h
    +
    +
    +
    A place to put #defines to configure the front end; +defines.h is included at the beginning of every source file.
    +
    +
    +
    direct_allocator.h
    +
    +
    +
    Declaration and definition of the Direct_allocator template.
    +
    +
    +
    disambig.h
    +
    +
    +
    Declarations related to disambig.c (C++ expression-declaration +disambiguation).
    +
    +
    +
    error.h
    +
    +
    +
    Declarations related to error.c (error reporting).
    +
    +
    +
    err_codes.h
    +
    +
    +
    Definition of the enumeration of error codes. This file is generated +from the error_msg.txt file. See mk_errinfo.
    +
    +
    +
    err_data.h
    +
    +
    +
    Definition of the enumeration of error codes. This file is generated +from the error_msg.txt and error_tag.txt files. See +mk_errinfo.
    +
    +
    +
    expr.h
    +
    +
    +
    Declarations related to expr.c (expression scanning).
    +
    +
    +
    exprutil.h
    +
    +
    +
    Declarations related to exprutil.c (expression scanning +utilities). Also, the data structures used in expression scanning.
    +
    +
    +
    extasm.h
    +
    +
    +
    Declarations related to extasm.c (GNU C extended asm statement +scanning).
    +
    +
    +
    fe_init.h
    +
    +
    +
    Declarations related to fe_init.c (initialization).
    +
    +
    +
    fe_wrapup.h
    +
    +
    +
    Declarations related to fe_wrapup.c (termination).
    +
    +
    +
    fixed_pt.h
    +
    +
    +
    Declarations related to fixed_pt.c (manipulation of fixed-point +constants).
    +
    +
    +
    float_pt.h
    +
    +
    +
    Declarations related to float_pt.c (manipulation of floating-point +constants).
    +
    +
    +
    float_type.h
    +
    +
    +
    Definitions of floating-point conversion routines used when +USE_HOST_FP_CONVERSION_ROUTINES is FALSE. This header file is +included multiple times (once for each distinct floating-point type) +by floating.c.
    +
    +
    +
    floating.h
    +
    +
    +
    Declarations related to floating.c (software-based conversion of +floating-point values between binary and decimal).
    +
    +
    +
    folding.h
    +
    +
    +
    Declarations related to folding.c (folding of constant +operations).
    +
    +
    +
    func_def.h
    +
    +
    +
    Declarations related to func_def.c (processing for function +definitions).
    +
    +
    +
    header_util.h
    +
    +
    +
    General utility components (mostly templates) intended for use in both +headers and compilation units.
    +
    +
    +
    host_envir.h
    +
    +
    +
    Declarations related to host_envir.c (definition of the host +environment, including operating system dependencies). Also, many +host configuration switches.
    +
    +
    +
    host_util.h
    +
    +
    +
    Definitions of host environment functions that are used by both the +front end and utility programs such as the prelinker. When the front +end is compiled, these routines are included as part of +host_envir.c.
    +
    +
    +
    ifc_map.h
    +
    +
    +
    Automatically-generated type declarations and definitions for +interacting with the IFC modules format.
    +
    +
    +
    ifc_map_functions.h
    +
    +
    +
    Automatically-generated function declarations for interacting with the +IFC modules format.
    +
    +
    +
    ifc_modules_inst.h
    +
    +
    +
    Automatically-generated macro invocations to facilitate instantiations +in ifc_modules_templ.c.
    +
    +
    +
    ifc_modules_internal.h
    +
    +
    +
    Declarations related only to the internal +implementation files for IFC modules file support.
    +
    +
    +
    ifc_modules_spec.h
    +
    +
    +
    Automatically-generated macro invocations to facilitate explicit +specializations in ifc_modules_templ.c.
    +
    +
    +
    ifc_modules.h
    +
    +
    +
    Declarations related to IFC modules files.
    +
    +
    +
    il.h
    +
    +
    +
    Declarations related to il.c (intermediate language).
    +
    +
    +
    il_alloc.h
    +
    +
    +
    Declarations related to il_alloc.c (allocation of intermediate +language entities).
    +
    +
    +
    il_def.h
    +
    +
    +
    The definition of the intermediate language.
    +
    +
    +
    il_display.h
    +
    +
    +
    Declarations related to il_display.c (display of intermediate +language in human-readable form).
    +
    +
    +
    il_file.h
    +
    +
    +
    Declarations related to the structure of the intermediate language +file.
    +
    +
    +
    il_read.h
    +
    +
    +
    Declarations related to il_read.c (reading the intermediate +language file).
    +
    +
    +
    il_to_str.h
    +
    +
    +
    Declarations related to il_to_str.c (creating external string-form +representations for certain IL entries).
    +
    +
    +
    il_walk.h
    +
    +
    +
    Declarations related to il_walk.c (walking the intermediate +language tree).
    +
    +
    +
    il_write.h
    +
    +
    +
    Declarations related to il_write.c (writing the intermediate +language file).
    +
    +
    +
    inline.h
    +
    +
    +
    Declarations related to inline.c (minimal inlining for IL +lowering).
    +
    +
    +
    interpret.h
    +
    +
    +
    Declarations related to interpret.c (IL interpreter for +constexpr functions).
    +
    +
    +
    lang_feat.h
    +
    +
    +
    Declarations of configuration switches that affect the source language +accepted.
    +
    +
    +
    layout.h
    +
    +
    +
    Declarations related to layout.c (class object layout).
    +
    +
    +
    lexical.h
    +
    +
    +
    Declarations related to lexical.c (source input and lexical +scanning). Also, the definition of the data structures related to the +current input line.
    +
    +
    +
    lint.h
    +
    +
    +
    A place to put directives to silence the lint program.
    +
    +
    +
    literals.h
    +
    +
    +
    Declarations related to literals.c (conversion of literal +constants).
    +
    +
    +
    lookup.h
    +
    +
    +
    Declarations related to lookup.c (name lookup).
    +
    +
    +
    lower_c99.h
    +
    +
    +
    Declarations related to lower_c99.c (C99 IL lowering).
    +
    +
    +
    lower_eh.h
    +
    +
    +
    Declarations related to lower_eh.c (IL lowering of exceptions).
    +
    +
    +
    lower_il.h
    +
    +
    +
    Declarations related to lower_il.c (IL lowering).
    +
    +
    +
    lower_init.h
    +
    +
    +
    Declarations related to lower_init.c (IL lowering of +initializations).
    +
    +
    +
    lower_name.h
    +
    +
    +
    Declarations related to lower_name.c (name mangling for IL +lowering).
    +
    +
    +
    macro.h
    +
    +
    +
    Declarations related to macro.c (macro definition and invocation).
    +
    +
    +
    mem_manage.h
    +
    +
    +
    Declarations related to mem_manage.c (memory management).
    +
    +
    +
    mem_tables.h
    +
    +
    +
    Declarations related to the memory management data structure.
    +
    +
    +
    modules.h
    +
    +
    +
    Declarations related to the processing of module files.
    +
    +
    +
    ms_attrib.h
    +
    +
    +
    Declarations related to Microsoft attribute processing.
    +
    +
    +
    ms_metadata.h
    +
    +
    +
    Declarations related to ms_metadata.cpp (reading C++/CLI metadata +from assemblies).
    +
    +
    +
    overload.h
    +
    +
    +
    Declarations related to overload.c (overload resolution for +expression processing).
    +
    +
    +
    pch.h
    +
    +
    +
    Declarations related to pch.c (precompiled header processing).
    +
    +
    +
    pragma.h
    +
    +
    +
    Declarations related to pragma.c (processing of #pragma +directives).
    +
    +
    +
    preproc.h
    +
    +
    +
    Declarations related to preproc.c (preprocessing directives).
    +
    +
    +
    scope_stk.h
    +
    +
    +
    Declarations related to scope_stk.c (scope stack management).
    +
    +
    +
    src_seq.h
    +
    +
    +
    Declarations related to src_seq.c (source sequence list +management).
    +
    +
    +
    statements.h
    +
    +
    +
    Declarations related to statements.c (statement scanning). Also, +the definition of the statement stack.
    +
    +
    +
    symbol_ref.h
    +
    +
    +
    Declarations related to symbol_ref.c (symbol references).
    +
    +
    +
    symbol_tbl.h
    +
    +
    +
    Declarations related to symbol_tbl.c (symbol table). Also, the +definitions of the symbol table and the scope stack.
    +
    +
    +
    sys_predef.h
    +
    +
    +
    Declarations related to sys_predef.c (system-specific predefined +macros). Also declarations related to builtins (and the place to add +user-defined builtins).
    +
    +
    +
    targ_def.h
    +
    +
    +
    Declarations that define default target machine characteristics, and +target configuration switches.
    +
    +
    +
    target.h
    +
    +
    +
    Declarations of target configuration variables, initialized to default +values defined in targ_def.h.
    +
    +
    +
    target_cfg.h
    +
    +
    +
    Definitions of target-specific routines to set and dump target +configurations (included once for each target configuration).
    +
    +
    +
    target_map.h
    +
    +
    +
    Definition of various routines that map target-specific configuration +macros to global variables in some fashion (included multiple times).
    +
    +
    +
    templates.h
    +
    +
    +
    Declarations related to templates.c (class and function +templates).
    +
    +
    +
    trans_copy.h
    +
    +
    +
    Declarations related to trans_copy.c (copying of secondary +translation unit IL to primary IL).
    +
    +
    +
    trans_corresp.h
    +
    +
    +
    Declarations related to trans_corresp.c (establishment of +correspondences between translation units).
    +
    +
    +
    trans_unit.h
    +
    +
    +
    Declarations related to trans_unit.c (driver for translation-unit +processing).
    +
    +
    +
    types.h
    +
    +
    +
    Declarations related to types.c (utility routines dealing with +types).
    +
    +
    +
    util.h
    +
    +
    +
    General utility components. This contains a set of (mostly templated) +utilities that are used in place of those that would normally be found +in a C++ standard library. The declarations are conditionally +enclosed in the edg namespace (under control of the +USE_EDG_NAMESPACE configuration macro).
    +
    +
    +
    version.h
    +
    +
    +
    Definition of the current version number of the front end.
    +
    +
    +
    walk_entry.h
    +
    +
    +
    Routines used by il_walk.c to walk through IL entries.
    +
    +
    +
    attribute.c
    +
    +
    +
    Scanning of attributes.
    +
    +
    +
    c_gen_be.c
    +
    +
    +
    The C-generating back end (for use in place of a “real” back end; +generates C code which can be compiled by a native target compiler).
    +
    +
    +
    cp_gen_be.c
    +
    +
    +
    The C++/C-generating back end (for use in source-to-source +transformation).
    +
    +
    +
    cfe.c
    +
    +
    +
    The main program for the front end.
    +
    +
    +
    cfe_daemon.c
    +
    +
    +
    The main program for the front end when built as a daemon..
    +
    +
    +
    class_decl.c
    +
    +
    +
    Class declarations scanning.
    +
    +
    +
    cmd_line.c
    +
    +
    +
    Command-line processing.
    +
    +
    +
    const_ints.c
    +
    +
    +
    Manipulation of the internal representation of integer constants.
    +
    +
    +
    debug.c
    +
    +
    +
    Debug control routines.
    +
    +
    +
    decl_inits.c
    +
    +
    +
    Declaration initializers scanning.
    +
    +
    +
    decl_spec.c
    +
    +
    +
    Declaration specifiers scanning.
    +
    +
    +
    declarator.c
    +
    +
    +
    Declarator scanning.
    +
    +
    +
    decls.c
    +
    +
    +
    Declarations scanning.
    +
    +
    +
    def_arg.c
    +
    +
    +
    Default argument caching and rescanning.
    +
    +
    +
    disambig.c
    +
    +
    +
    C++ expression-declaration disambiguation.
    +
    +
    +
    error.c
    +
    +
    +
    Error reporting.
    +
    +
    +
    expr.c
    +
    +
    +
    Expression scanning.
    +
    +
    +
    exprutil.c
    +
    +
    +
    Utilities for expression scanning.
    +
    +
    +
    extasm.c
    +
    +
    +
    Scanning of GNU C extended asm statement.
    +
    +
    +
    fe_init.c
    +
    +
    +
    Overall initialization.
    +
    +
    +
    fe_wrapup.c
    +
    +
    +
    Overall termination.
    +
    +
    +
    fixed_pt.c
    +
    +
    +
    Manipulation of fixed-point constants: conversion to and from internal +form and conversions and operations on the internal form.
    +
    +
    +
    float_pt.c
    +
    +
    +
    Manipulation of floating-point constants: conversion to and from +internal form and conversions and operations on the internal form.
    +
    +
    +
    floating.c
    +
    +
    +
    Conversion of floating-point values between binary and decimal +formats. Used only when USE_HOST_FP_CONVERSION_ROUTINES is +FALSE.
    +
    +
    +
    folding.c
    +
    +
    +
    Folding of constant operations.
    +
    +
    +
    func_def.c
    +
    +
    +
    Processing for function definitions.
    +
    +
    +
    host_envir.c
    +
    +
    +
    Handling of host-environment dependencies (e.g., file name rules and +opening of files).
    +
    +
    +
    ifc_map_functions.c
    +
    +
    +
    Automatically-generated function definitions for interacting with the +IFC modules format (that do not fit into one of the more specific IFC +map functions files).
    +
    +
    +
    ifc_map_functions_acc.c
    +
    +
    +
    Automatically-generated accessor function definitions for interacting +with the IFC modules format.
    +
    +
    +
    ifc_map_functions_dbg.c
    +
    +
    +
    Automatically-generated debug functions for debugging objects of types +declared in ifc_map.h.
    +
    +
    +
    ifc_map_functions_mut.c
    +
    +
    +
    Automatically-generated mutator function definitions for interacting +with the IFC modules format.
    +
    +
    +
    ifc_map_functions_val.c
    +
    +
    +
    Automatically-generated validation function definitions for validating +objects of types declared in ifc_map.h.
    +
    +
    +
    ifc_modules.c
    +
    +
    +
    Handling of operations common to reading and writing IFC module files.
    +
    +
    +
    ifc_modules_read.c
    +
    +
    +
    Handling of reading IFC modules files.
    +
    +
    +
    ifc_modules_templ.c
    +
    +
    +
    Template definitions and explicit instantiations shared by +ifc_modules.c and the IFC map functions files.
    +
    +
    +
    ifc_modules_write.c
    +
    +
    +
    Handling of writing IFC modules files.
    +
    +
    +
    il.c
    +
    +
    +
    Low-level manipulation of intermediate language constructs.
    +
    +
    +
    il_alloc.c
    +
    +
    +
    Allocation and initialization of intermediate language constructs.
    +
    +
    +
    il_display.c
    +
    +
    +
    Display of the intermediate language in human-readable form.
    +
    +
    +
    il_read.c
    +
    +
    +
    Reading the intermediate language from a file.
    +
    +
    +
    il_to_str.c
    +
    +
    +
    Creating textual representations for certain IL entries +(e.g., constants, types).
    +
    +
    +
    il_walk.c
    +
    +
    +
    Walking the in-memory intermediate language tree.
    +
    +
    +
    il_write.c
    +
    +
    +
    Writing the intermediate language to a file.
    +
    +
    +
    inline.c
    +
    +
    +
    Minimal inlining of function calls for IL lowering.
    +
    +
    +
    interpret.c
    +
    +
    +
    IL interpreter for constexpr functions.
    +
    +
    +
    layout.c
    +
    +
    +
    Laying out class objects.
    +
    +
    +
    lexical.c
    +
    +
    +
    Source input and lexical scanning.
    +
    +
    +
    literals.c
    +
    +
    +
    Conversion of literal constants to internal form.
    +
    +
    +
    lookup.c
    +
    +
    +
    Name lookup.
    +
    +
    +
    lower_c99.c
    +
    +
    +
    IL lowering from C99 to C89.
    +
    +
    +
    lower_eh.c
    +
    +
    +
    IL lowering of exception handling constructs.
    +
    +
    +
    lower_il.c
    +
    +
    +
    Intermediate language lowering (C++ constructs are translated to C +constructs).
    +
    +
    +
    lower_init.c
    +
    +
    +
    IL lowering of initializations, new/delete, and +constructors/destructors.
    +
    +
    +
    lower_name.c
    +
    +
    +
    Name mangling for IL lowering.
    +
    +
    +
    macro.c
    +
    +
    +
    Definition of macros (#define directive) and invocation +(expansion) of macros.
    +
    +
    +
    mem_manage.c
    +
    +
    +
    Memory management (dynamic allocation of storage).
    +
    +
    +
    modules.c
    +
    +
    +
    Generic module file processing.
    +
    +
    +
    ms_attrib.c
    +
    +
    +
    Processing of Microsoft attributes.
    +
    +
    +
    ms_metadata.cpp
    +
    +
    +
    Processing of C++/CLI metadata from assemblies. Contains C++ source +code that can only be compiled on a Microsoft Windows platform.
    +
    +
    +
    overload.c
    +
    +
    +
    Overload resolution for expression processing.
    +
    +
    +
    pch.c
    +
    +
    +
    Precompiled header processing.
    +
    +
    +
    pragma.c
    +
    +
    +
    Processing of #pragma directives.
    +
    +
    +
    preproc.c
    +
    +
    +
    Preprocessing directives.
    +
    +
    +
    scope_stk.c
    +
    +
    +
    Management of the scope stack.
    +
    +
    +
    src_seq.c
    +
    +
    +
    Management of source sequence lists.
    +
    +
    +
    statements.c
    +
    +
    +
    Statements scanning.
    +
    +
    +
    symbol_ref.c
    +
    +
    +
    Processing for symbol references.
    +
    +
    +
    symbol_tbl.c
    +
    +
    +
    Symbol table entry and look up, maintenance of name scoping.
    +
    +
    +
    sys_predef.c
    +
    +
    +
    Definitions of system-specific predefined macros and assertions.
    +
    +
    +
    target.c
    +
    +
    +
    Target configuration support.
    +
    +
    +
    templates.c
    +
    +
    +
    Declaring and instantiating class and function templates.
    +
    +
    +
    trans_copy.c
    +
    +
    +
    Copying of secondary translation unit IL to the primary IL.
    +
    +
    +
    trans_corresp.c
    +
    +
    +
    Establishment of correspondences between externally-linked entities in +different translation units.
    +
    +
    +
    trans_unit.c
    +
    +
    +
    Driver for translation-unit processing.
    +
    +
    +
    types.c
    +
    +
    +
    Utility routines dealing with types.
    +
    +
    +
    unicode_name_fsm.c
    +
    +
    +
    Automatically-generated data file for a finite state machine that +recognizes Unicode character names.
    +
    +
    +
    error_msg.txt
    +
    +
    +
    Contains the definition of the error codes and error messages and is +used to generate err_codes.h and err_data.h. See +mk_errinfo.
    +
    +
    +
    error_tag.txt
    +
    +
    +
    May be used to provide additional error “tags” or aliases that may be +used to reference a given error message in certain command line +options. This is used to generate err_data.h. See +mk_errinfo.
    +
    +
    +
    +

    Note that in general the files are paired. A .h file containing +declarative information corresponds to a .c/.cpp file containing +executable code. The file name.h contains the declarations of the +data structures and externally-callable routines for the file name.c, and is, in effect, the definition of the external interface to that +source file.

    +

    There are also some .h files that contain configuration information and are +not paired with a .c file (e.g., targ_def.h).

    +

    In addition, there is a set of .h files that contain #includes of +other header files. Their purpose is to group header files – both to help +manage their often complicated interactions and to make better use of +compilation systems that perform header precompilation.

    +
    + + + + + + + + + + + + + + + + + + +
    +
    basic_hdrs.h
    +
    +
    +
    Header files devoted to configuration.
    +
    +
    +
    fe_common.h
    +
    +
    +
    Header files common to all .c files.
    +
    +
    +
    decl_hdrs.h
    +
    +
    +
    Header files used for declaration processing.
    +
    +
    +
    expr_hdrs.h
    +
    +
    +
    Header files used for expression processing.
    +
    +
    +
    lower_hdrs.h
    +
    +
    +
    Header files used for IL lowering.
    +
    +
    +
    +

    In rough numbers, the .h files together are about 320,000 lines, and the +.c files about 1,017,000 lines (including IL lowering, the IL display +utility, and the C- and C++-generating back ends). The utility programs are +another 15,000 lines, and the minimal runtime about 11,000 lines.

    +
    +
    +

    3.3. Coding Philosophy#

    +

    This section contains miscellaneous information on the coding style and +philosophy used in writing the front end, which may be useful to those who must +maintain it.

    +

    The configuration section of a previous chapter of this document contains some +important information of this type.

    +

    Code should conform to the C++11 standard and not have any dialect-specific +constructs [1]. The environment dialect switches __ANSIC__, +__SYSV__, and __BSD__ should used to control inclusion of header files +that are not available in all versions of C++. basics.h (which should be +included first in every compilation) takes care of the most common header files +and the most common library routines (it will remap them via macros if +necessary).

    +

    The size argument on calls of functions like memcpy should be wrapped in a +call of the function-like macro size_t_arg if the size is anything other +than a sizeof operator.

    +

    Code that is host-dependent should be written only in host_envir.c and +cmd_line.c.

    +

    Target-dependent code should not be written outside of const_ints.c, +fixed_pt.c and float_pt.c (which are heavily target-dependent) and +literals.c, folding.c, and layout.c (which have some +target-dependent aspects). In particular, be careful about doing anything with +integers without going through the routines in const_ints.c.

    +
    +

    3.3.1. External Names#

    +

    External routines should always be declared both where the body occurs and in +the corresponding .h file. The .h file should be included everywhere +the routine is referenced.

    +

    External variables should be declared in .h files with EXTERN as their +storage class. All .h files that contain external variables must be +included in fe_init.c; there, the macro EXTERN, which ordinarily is +mapped to extern, is mapped to a null string. This makes the same +declarations, when scanned in fe_init.c, external definitions instead of +external references. If an external variable should have an initial value, the +initialization should be included in the .h file, surrounded by #if +VAR_INITIALIZERS/#endif. In fe_init.c the initializer will be +included.

    +

    Of course, variables should be made static instead of external if it is +possible to localize them to a single source file.

    +

    All static variables (external, internal, and function-local) must be saved and +restored as necessary when precompiled headers are generated. The point at +which a precompiled header is written or read is outside of any declaration and +at the file scope (etc.); variables that never have interesting values at such +points need not be saved and restored. All others, however (and these cannot +be function-local), must be registered by calling +register_pch_saved_variables so that they will be written to the +precompiled header file and restored.

    +

    Likewise, variables that are translation-unit specific should be registered by +calling register_trans_unit_variable. See the Multiple Translation Units chapter.

    +
    +
    +

    3.3.2. Include Files#

    +

    Include files always include any other files on which they depend. They also +define a flag once they have been included, and will skip themselves if +included again. (For example, cmd_line.h defines CMD_LINE_H). +Therefore, one can include the files in any order and without regard for +whether or not they have been included by other include files. To improve +compilation speed, #includes can be surrounded by #ifndef +flag/#endif.

    +
    +
    +

    3.3.3. Debug Code#

    +

    Debug code is surrounded by #if DEBUG/#endif. In such code, one should +test the value of debug_level to control output of debug information. +debug_level is zero ordinarily, to indicate that no debug output should be +produced. Debug code should be set to come out at an appropriate level: 1 +is for output that comes out once per source line, 3 for output that comes +out once per token, and 5 for output one would hardly ever want to see. +2 and 4 lie in between those levels in the expected way. Choosing an +appropriate debug level is more of an art than a science. If in doubt, make a +guess at the best level, run the front end with that level of debug output, and +see if the new messages seem out of place in the overall debug output at that +level.

    +

    One can also use db_flag_is_set to determine whether specific output should +be generated. For example, calls of db_flag_is_set("vtbl") are used in IL +lowering to control debug output related to virtual function tables. By +specifying -d-vtbl on the command line, one can get that particular debug +output and nothing else. A particular “flag” is considered set if the string +of the db_flag_is_set call is specified in a command-line debug option, so +a new “flag” is added by adding a call of db_flag_is_set with some new +string; there is no central registry of debug “flags.”

    +

    A similar facility for tracing names is provided by the --db_name=xxxx +command-line option and the db_has_traced_name macro. This can be used to +control extra output about processing of entities with specific names. +db_trace provides a combination of the features of db_flag_is_set and +db_has_traced_name.

    +

    Debugging options that are specified with the -d command-line option can +also be specified using the db_opt pragma. The pragma can be used to +specify a certain debug level or to define a certain debug flag for a portion +of a source program that is being compiled. For example:

    +
    template <class T> void f() {
    +#pragma db_opt -nondep_call
    +  g();
    +#pragma db_opt #nondep_call
    +}
    +
    +
    +

    When a flag name is preceded by “#”, the flag is cleared if previously set.

    +

    Debugging options that are specified with the --db_name command-line option +can also be specified using the db_name pragma.

    +

    The variable db_active is TRUE if debug_level is non-zero or if there +is the potential for it becoming non-zero (i.e., if there is a list of debug +requests from the command line). This can be used to control processing that +may be needed when debug output is generated, but should not be done when no +debugging is requested.

    +

    Diagnostic messages should be written to f_error. This is normally set to +stderr, but in some modes is set to stdout, and can be redirected to a +file by use of a command-line option. Debug output should be written to +f_debug. This is set to f_error, but is a separate file variable to +allow it to be changed if desired.

    +

    Entries and exits of routines should have calls to db_enter and +db_exit. These provide flow tracing. The db_enter call looks like

    +
    +
    +
    db_enter(level, "routine-name");
    +
    +
    +

    The db_exit call has no arguments. These calls will cause an entry +message and an exit message when debug_level is equal to or greater +than the level specified. Note that the calls need not be surrounded by +#if DEBUG/#endif; db_enter and db_exit are actually macros, +and when DEBUG is 0, they are defined as null strings. When +DEBUG is non-zero, they expand to calls to debug_enter and +debug_exit. Those calls are surrounded by ifs testing +db_active so that the routine calls are only done when debug output is +actually being generated (or may be generated, when a list of +routine-related debug requests is specified on the command line).

    +

    It should be clear that for db_exit to work correctly one should have a +single exit point for each routine, and not have return statements in the +middle of routines.

    +

    Some routines do not have db_enter and db_exit calls for speed +reasons – even the overhead of two ifs would be visible. An example is +skip_white_space in lexical.c.

    +
    +
    +

    3.3.4. Checking Code#

    +

    Checking code performs dynamic consistency checking, e.g., verifying the entry +conditions for routines and the consistency of tables. Checking code is always +surrounded by #if CHECKING/#endif. When a problem is found, this code +calls

    +
    +
    +
    internal_error("routine-name: problem found");
    +
    +
    +

    which displays the argument string and causes abnormal termination of the front +end.

    +

    As a concrete example of checking code: all switch statements should +have a default clause; if the default clause does not correspond to any +legal possibility, it should be present as checking code, and should call +internal_error to indicate that a bad value appeared as the switch +selector. (See CHECK_SWITCH_DEFAULT_UNEXPECTED in basics.h and +default_is_unexpected in checking.h for macros that assist in +applying this rule.)

    +

    Several routines are provided as convenient ways to do consistency +checking. Calls of these routines need not be surrounded by #if +CHECKING/#endif; they are defined as macros that expand to nothing +when CHECKING is disabled. check_assertion can be used to check an +expression to make sure it is true. expect_error checks that +total_errors is nonzero at the point of invocation or that it becomes +nonzero before the end of the compilation. This is useful to ensure that +situations that are expected to lead to error diagnostics will indeed do so +(only the first invocation will be reported on failure). +check_assertion_or_expect_error combines the previous two routines: it +has no effect if either the given condition is TRUE, or if total_errors +is nonzero by the end of the compilation. unexpected_condition is used +when a piece of code is not expected to be reached (for example, the +default clause of a switch). Three versions of each of these routines are +provided: the version described above, a version with a _str suffix +that accepts a single string argument, and a version with a _str2 +suffix that accepts two strings. The string(s) are printed on error +termination to provide additional information about the cause of the error.

    +

    The consistency checks that are enabled by the CHECKING flag do not +significantly affect the performance of the front end. There are other +consistency checks whose execution does affect the performance of the front +end. These extra consistency checks are enabled by the EXPENSIVE_CHECKING +flag. These checks are not intended to be enabled when optimum performance is +required (e.g., in production versions of a product).

    +
    +
    +

    3.3.5. Conventions for Declarations#

    +

    The type a_boolean (defined by default as int) should be used for +true/false variables, along with the constants TRUE and FALSE. +These are defined in basics.h and thus are available everywhere. In +structs, a_byte_boolean is used for boolean fields when there is +just one of them. When there are several, bit fields of length one are +used, to save space. Obviously, these rules will not work on all host +machines, but they will work well enough on most.

    +

    Fields in structs are ordered to some extent to reduce the space wasted +in gaps for alignment. It’s assumed that pointers and large integers have +similar size and alignment requirements, and thus a sequence of them will leave +no gaps. When small fields appear, however, they are grouped together to avoid +the gaps one would expect from a series of short/long/short/long fields.

    +

    Bit fields are declared with the type a_bit_field. It is usually +unsigned int, but when compiling with a compiler that uses the Microsoft +bit-field layout algorithm it can be set to unsigned char to get better +packing of the bit fields.

    +

    The type a_byte should be used for small integer fields (i.e., fields +whose values lie in the range 0-127), rather than char or unsigned +char. enum types are often given a base type of a_byte so that +their size is explicitly controlled to save space in structs.

    +

    For each table type (whether or not it is part of the intermediate +language) there is an associated allocation routine and an associated +routine that will set the fields of the table to default values. (In some +cases, these two functions are provided by one routine.) When a table has a +variant section and an associated tag field, there is also a routine to set +the tag field and set the associated variant fields to default values. A +tag field should never be assigned directly; it should only be set by this +routine. Consistent use of the allocation, clear, and set-kind routines +ensures that no uninitialized fields will cause sporadic problems, and that +new fields can be easily added. In addition, it can be useful to add the +following snippet to defines.h :

    +
    #if UNION_AS_STRUCT
    +#define union struct
    +#endif
    +
    +
    +

    Setting UNION_AS_STRUCT in a testing build allocates each variant field +in its own storage. This often allows detection of cases where code +accesses an incorrect variant for a given IL entry.

    +

    The names of macros are written in upper case in the front end source when they +are object-like (e.g., manifest constants), but in lower case when they are +function-like. The names of types and enumerators are written in lower case.

    +

    The names of typedefed, class, and templated types always begin with +a_ or an_ (e.g., a_type, an_expr_node). Pointer type names +end in _ptr. The names of constants in enumerations always begin with +a prefix that hints at the enumeration type (e.g., enk_ for +an_expr_node_kind).

    +
    +
    +

    3.3.6. Storage Allocation#

    +

    Allocation of space is never done by calling malloc or the like directly. +For all table entries, as mentioned earlier, the associated allocation routine +should be called. It will allocate and clear the space, and will also make +sure that the space is allocated in the right area (e.g., intermediate language +constructs must be allocated in the right memory region). For any other +allocation cases, one of the routines in mem_manage.c should be called +instead. alloc_fe has an interface like malloc, and allocates storage +that need not survive the execution of the front end. alloc_general is +similar, and allocates storage that will survive into the back end if the back +end is called as part of the same program (this should not be used ordinarily).

    +

    One case to do carefully: all names that become part of the intermediate +language (file names, directory names, identifier names) should be allocated in +the file-scope intermediate language region, by calling alloc_il.

    +

    Space is never freed by calling free or related routines. Where tables are +reused, the front end maintains individual lists of available entries for each +type of table, and takes entries off those lists before allocating new ones. +Space can be released on a memory region basis, for example to free up all the +space used for a given function once the function has been processed. When the +front end is configured in such a way that it can be re-initialized (by setting +MAKE_FRONT_END_CALLABLE) the front end keeps a record of all memory +allocations and automatically frees the memory when the front end terminates.

    +

    In general, every reasonable attempt is made to not allocate tables unless they +are actually needed. The intermediate language, for example, will contain some +wasted space, but extremely little.

    +

    In order to avoid any fixed limits in the front end, the primary non-IL data +structures are designed so they can be dynamically allocated and expanded +(curr_source_line, scope_stack, etc.). An initial allocation is done +that should cover all expected uses; if more space is needed, the table is +reallocated with a larger size. That means that there is a danger inherent in +keeping around pointers into those data structures, because if the table moves, +all pointers to the table become obsolete. In the input line/macro area, such +pointers are necessary, and there is a pointer registration scheme that is used +to make sure that all pointers are updated if a reallocation occurs. In other +areas, pointers can be avoided relatively easily. A simple rule to remember is +that one should never make a local pointer into one of the primary stacks +(scope_stack, struct_stmt_stack); one should instead use an index value +into the stack, since an index is not invalidated by a reallocation of a table. +When memory is allocated that may later be resized, it must initially be +allocated using either alloc_resizable_buffer or realloc_buffer. It +may then be resized later by calling realloc_buffer.

    +

    One can get a summary of space use by having debug_level non-zero in +fe_wrapup. This can be requested by specifying -dfe_wrapup=1 on the +command line. A summary of symbol table and constant sharing efficiency is +also included.

    +
    +
    +

    3.3.7. Typerefs#

    +

    The a_type IL entry can have a tk_typeref kind; such entries +represent a type that is based on another type in some way. For example, a +typedef is represented by a typeref entry designating the type for +which it is a synonym. Similarly, cv-qualified types like const int are +represented by a const typeref pointing to the entry for the int +type. Additional uses for typerefs include type operators like +decltype, capturing the specific template arguments used when a +class or alias template specialization is referred to, and many others.

    +

    In general, typerefs do not have complete information about the type they +represent, such as the size and alignment. As a result, it is often +necessary to access the type on which a given typeref is based, and +various macros and functions are provided for that operation, such as +skip_typerefs, skip_lexical_typerefs, +skip_typerefs_not_typedefs, etc. It is a common source of bugs to +omit a call to one of these functions and operate on the typeref itself +instead of its underlying type.

    +

    See the Typerefs section in the Intermediate Language +chapter for further details.

    +
    +
    +

    3.3.8. Source Positions#

    +

    Source positions are represented as a structure of type a_source_position +(see basics.h). It contains a sequence number and a column number. The +sequence number is a unique number assigned in ascending order to each source +line as it is read. Unlike a file name and line number, the sequence number is +unambiguous. It’s also more compact, and can be converted to a file name and +line number for external use (this is done in error messages, for example).

    +

    The column number is a 1-origined character position in the original source +line. The character position is the logical character number in the line, not +simply a byte offset. This is significant if the source file contains +multibyte characters or is in a format such as UTF-16. Tab characters are +counted as a single column. The position of text within a macro expansion is +considered to be the first character of the macro name in the macro call in the +original source line that directly or indirectly generated the text.

    +

    If the front end is configured with FULLY_RESOLVED_MACRO_POSITIONS set to +TRUE, each source position contains an additional sequence/column number pair. +For text within a macro expansion, this additional position information gives +the location from which the associated text was copied into the macro +expansion, i.e., a macro definition or macro argument.

    +

    If MACRO_INVOCATION_TREE_IN_IL is configured to TRUE, each source position +referring to text within a macro expansion contains the index of the macro +invocation record that identifies the macro in whose expansion the text at that +position occurs. For text appearing directly in the source, this index will be +NO_PARENT_MACRO_INVOCATION.

    +

    A sequence number of zero is used to indicate an unknown position or a +“position” in initialization, in a predefined macro, or in the command-line. +The column number indicates which. See basics.h.

    +

    Importing assembly metadata in C++/CLI is a process that creates a string +containing C++ code that expresses that metadata and then parses the contents +of that string. Each import is associated with a particular sequence number, +and that number is assigned to the position of each token extracted from that +string (with a column number zero). For example, when compiling a C++/CLI +source file, sequence number one will usually correspond to mscorlib.dll.

    +
    +
    +

    3.3.9. Language Dialect#

    +

    The global variable C_dialect (in cmd_line.h) indicates the C +dialect to be accepted: the choices are C_dialect_cplusplus, +C_dialect_ANSI, and C_dialect_pcc. The macro C_mode() is +useful as a way of testing for C versus C++. cppNN_mode +(where NN is the year of the relevant C++ Standard, e.g., cpp03_mode, +cpp17_mode, etc.) is TRUE when the features of the corresponding +revision of the language should be accepted, and similarly cNN_mode for versions of the C language.

    +

    The global variable strict_ansi_mode is TRUE if use of features that +are not part of the selected C or C++ Standard should cause diagnostics. +strict_ansi_error_severity indicates the level of diagnostic (warning, +discretionary error, or error) that should be produced for such cases.

    +

    microsoft_mode indicates whether a Microsoft dialect (C, C++, C++/CLI, +or C++/CX) is in effect. In configurations that do not allow Microsoft +extensions (i.e., when MICROSOFT_EXTENSIONS_ALLOWED is FALSE), it is a +macro equivalent to FALSE. This allows many Microsoft-mode-specific bits +of code to be written without surrounding them with conditional compilation +directives testing MICROSOFT_EXTENSIONS_ALLOWED. cppcli_enabled +and cppcx_enabled similarly indicate that the Microsoft dialect is +C++/CLI or C++/CX, respectively (if TRUE, microsoft_mode is TRUE too, +and C_mode() is FALSE). Some C++/CLI- and C++/CX-specific code is +delimited by conditional compilation directives testing +MICROSOFT_EXTENSIONS_ALLOWED because it uses variables, data members, +or functions that are available only when that macro is TRUE. (The macro +CPPCLI_ENABLING_POSSIBLE is tested in a few places for code that deals +with the importing of assembly metadata, but it shouldn’t be used to +conditionalize other C++/CLI-specific code. In particular, the IL +extensions representing C++/CLI and C++/CX constructs are only conditioned +on MICROSOFT_EXTENSIONS_ALLOWED.)

    +

    gpp_mode and gcc_mode indicate that, respectively, GNU C++ or GNU C +emulation is in effect. In configurations where GNU_EXTENSIONS_ALLOWED is +FALSE, these are macros equivalent to FALSE.

    +

    clang_mode indicates that clang emulation is in effect. Because the +initial emulation of the clang C++ compiler in the front end was very close +to g++, clang_mode also implies that gpp_mode or gcc_mode will +be set. When it is necessary to distinguish between the GNU and clang +emulations, the macros gnu_version_is, gpp_version_is, +gcc_version_is, clang_version_is, clangcpp_version_is, and +clangc_version_is (see lang_feat.h) allow finer-grained +discrimination (including the compiler version to be emulated). (There are +also corresponding Microsoft-specific macros, ms_version_is, +mscpp_version_is, and msc_version_is.)

    +

    cfront_2_1_mode is TRUE if the cfront 2.1 dialect of C++ is to be compiled. +cfront_3_0_mode indicates the cfront 3.0 dialect. The macro +any_cfront_mode() tests for either of those being set to TRUE.

    +

    (There are other variables/macros that control dialect variations. The ones +mentioned here are among the more frequently used ones.)

    +
    +
    +

    3.3.10. Expression Processing#

    +

    See Rescanning Expressions for some additional coding rules that apply +only within the expression-processing routines.

    +
    +
    +
    +

    3.4. Recursive Descent Parsing#

    +

    “Recursive descent” is an ad-hoc syntax parsing technique. It works well for +languages (like C) where very little lookahead is required to resolve local +ambiguities, and where the language in which the compiler is written is +recursive (as is true for the front end).

    +

    The idea of recursive descent provides a framework and a discipline for parsing +a language, but it is implemented entirely by hand-crafted code. There is +nothing automatic about the parsing. Thus, there is more possibility for error +in developing a recursive-descent parser than there is in developing a +table-driven parser. However, if one writes carefully and tests thoroughly, +the end result is better with a recursive descent parser: faster parsing, +better error recovery, and a clearer compiler (because all of the logic related +to a particular construct appears in one place).

    +

    To implement recursive descent, one writes routines for each non-terminal +construct in the language syntax. For example, one writes a routine to scan an +expression, and one to scan a statement, and one to scan a declaration. The +internal structure of these routines looks a great deal like the syntax of the +constructs they implement. For example, if a declaration is defined as a list +of declaration specifiers followed by a declarator followed by a semicolon, the +routine that scans a declaration would call the routine to scan a list of +declaration specifiers, then the routine to scan a declarator, and then check +for and discard a semicolon. Where the language has recursive constructs, the +routines involved will call each other recursively.

    +

    The terminal tokens that are being parsed come from the lexical routines, +specifically from get_token. At any given moment, there is a current +token (curr_token). It is the next token of input, the one that +hasn’t yet been taken. If the token is an identifier or a literal +constant, there is additional information associated with it. See +lexical.h.

    +

    As the recursive descent routines parse the input tokens, they build up +information on what they have parsed, in the intermediate language trees and in +the symbol table. They also check for and recover from errors.

    +

    The scanning of expressions is one area where recursive descent is inefficient +for languages (like C) where the expression syntax has many levels. A naive +recursive descent implementation would provide a routine for each level of the +expression syntax, and thus scanning a simple expression would involve perhaps +a dozen subroutine calls. For this reason, the front end uses a modified +recursive descent technique to scan expressions. Internal calls to the +scan_expr routine (in expr.c) specify a precedence level, and the scan +routine can decide whether to call itself recursively or not based on the +relative precedences of adjacent operators. With this modification, the number +of calls is reduced to very nearly one per operator. See the description of +expr.c later in this document for more detail.

    +

    To reduce the possibilities for errors in writing the parsing routines, one +should not check for the start of constructs by checking directly for all the +possible first tokens in that construct. Such a list of tokens is inherently +error-prone. For constructs of this kind, there are functions that will +indicate whether or not the current token looks like the start of the construct +(see, for example, is_decl_start in decls.c). Such routines might +themselves call other is_xxx_start routines if the constructs can +themselves begin with other complex constructs.

    +

    Several utility routines in lexical.c are useful for recursive descent +parsing. required_token can be used to check for and discard a required +token, and to issue a specific error message if the token is not present. +loop_token is used to check (at the bottom of the loop implementing an +iterative syntactic construct) for the occurrence of a particular token. The +token is taken if found, but no error is given if the token is not found. +next_token is useful for doing a limited kind of lookahead: it will return +the kind of the token following the current token, without actually getting +that token (actually, it gets it and then puts it back). In many cases, that +one token is enough to allow a decision to be made at a fork in the syntax. +See, for example, the code that recognizes statement labels in statement in +statements.c.

    +

    Consult any of the popular books on compiler theory for a more detailed +overview of recursive descent.

    +
    +
    +

    3.5. Error Recovery#

    +

    When the front end discovers an error, it has several goals:

    +
      +
    • +
      To describe the error clearly and indicate its position (including the +position within the source line);
      +
      +
    • +
    • +
      to recover from the error without generating extra errors;
      +
      +
    • +
    • +
      to preserve as much information as possible about the valid parts of the +construct containing the error, so that detection of other errors is not +needlessly compromised.
      +
      +
    • +
    +

    (“Error” here of course refers to remarks and warnings as well.)

    +

    Describing an error clearly requires that one not only detect the error, but +detect it at an appropriate level, so that the front end can guess better at +what was intended. Sometimes this requires clever code at decision points in +recursive descent parsing, so that on invalid constructs one goes to the more +likely of two subcases. Within the { } for a struct, for example, we +have a series of member declarations separated by semicolons. If a semicolon +is missing, one should not fall out of the loop and leave the scanning of the +struct. In other situations, clearly invalid cases should be flagged at +the higher level, and none of the subcases should be entered. For example, at +the beginning of a statement or a declaration, if the first token is not a +valid start for that construct, an error message (“expected a statement” or +“expected a declaration”) is more informative than descending into any of the +subcases and letting them issue errors.

    +
    +

    3.5.1. Error Positions#

    +

    The position of an error is often just as important as the error text. The +front end tries to give useful error positions. This is aided by the fact that +column positions are maintained for each token. A global variable +error_position indicates the position of the beginning of the last language +construct scanned. It is set by get_token on scanning each token, and it +is also set by each medium-sized language construct (e.g., an expression, a +declarator). Most recursive descent routines save the position of the first +token of the construct they scan, and then set error_position to that +position on return. error_position is the default position for errors when +no explicit position is specified, and this protocol for setting it works well +in ensuring that the error positions are right. Some cases take extra work. +For example, in the expression routines, the position of the left operand and +right operand, and the position of the operator itself, are known for each +operation. If an error is due to a problem with one of the operands, the error +position used is the position of that operand. If the problem is with the +combination of those operands (as in adding a pointer and a float), the error +position used is the position of the operator.

    +

    The macro set_err_pos_to_curr_token is used when one is going forward in +scanning. It sets the error position to the position of the current token. +One would use it, for example, when looking for the = that indicates an +initializer in a declaration. The previous construct (a declarator) has been +scanned and checked, and its position is in error_position. Now, however, +we are going forward, and the = that may have ended the expression scan +should once again be the current construct. In practice, there are few cases +like this; they only come up for optional tokens in the middle of constructs. +required_token handles the change of error position in the more usual case +of a required token.

    +

    When an error refers back to something earlier in the source, it often makes +sense to give the position of the other location rather than the current +location. Variables declared but never used, for example (a warning), are +detected at the closing brace of functions. However, that position is much +less informative than the position of the declaration of the variable in +question, so that is used. Likewise, when a comment is unclosed at end of +file, it is more useful to indicate the position of the start of the comment +instead of the location of the end of file, where the error was detected.

    +
    +
    +

    3.5.2. Error Codes#

    +

    Error messages are mapped to values of the enumeration an_error_code (see +err_codes.h, along with err_data.h for the associated error message +text). For example, ec_exp_line_number represents the message “expected a +line number”. ec_no_error is first in the enumeration, and therefore has +the value zero. Thanks to it, one can return error codes of type +an_error_code, and test them in if statements (non-zero means an +error).

    +

    Errors with codes beginning ec_exp_ (and texts beginning “expected a …”) +are uniformly syntax errors – some expected token or construct was not found.

    +

    The severity of an error is determined by the error routine called (e.g., +error instead of warning) and not by the error code. In fact, there +are cases where the same error code is used as both a warning and an error. +The severity of certain diagnostic messages may be overridden using a command +line option. A diagnostic that is issued with a severity that is less than an +error (i.e., remark, warning, or discretionary error) may have its severity +changed, or may be suppressed completely.

    +

    Some error message texts have fill-ins, as in

    +
    +
    +
    could not open source file "name"
    +
    +
    +

    For these, variants of the error routines should be called. For the case +above, for example, str_error would be called. The fill-in string is +passed to the error routine as a null-terminated string, and replaces +%s where it appears in the error text string. See +Error Reporting for details on the kinds of fill-ins available.

    +
    +
    +

    3.5.3. Syntax Errors#

    +

    In terms of internal processing, one must distinguish syntax errors from +semantic errors. Syntax errors are discovered when the sequence of tokens +in the source program cannot be parsed according to the language syntax +(for example, i=j+;–there’s something missing between the + and +the ;). All other errors are semantic errors – things that can be +parsed but are still nonsensical (for example, use of an undefined +variable, or adding two structs). In error recovery, the important +distinction between the two is that for a syntax error one must decide how +to continue parsing, whereas for a semantic error everything is fine as far +as parsing and there’s no question about how to continue.

    +

    Syntax errors should always cause the calling of flush_tokens in +lexical.c, and semantic errors should never call it. The routine +syntax_error records the occurrence of an error, and then calls +flush_tokens, which is a convenient combination.

    +

    flush_tokens scans and throws again tokens until it finds one in the +stop tokens set, and then returns. Paired tokens are also considered: if +a ( is scanned while flushing tokens, for example, the corresponding +) will be sought before continuing the search for a stop token. There +are some other special cases; see the code in lexical.c.

    +

    The stop tokens set is an array indexed by token kind. Each element of the +array is non-zero if the corresponding token is currently in the stop tokens +set (and thus should halt a flush). As recursive descent routines scan +constructs, they add to the stop tokens set those terminal tokens they expect +to see in their constructs, and then remove those tokens once they are +encountered. The macros add_stop_token and remove_stop_token are +called to add and remove tokens from the set by incrementing and decrementing +the associated element of the array. Since syntactic constructs are nested +inside one another, having each recursive descent routine add the tokens it +recognizes produces a stop tokens set that will halt a flush at a token with +which one of the active routines feels it can continue.

    +

    At boundaries where the syntax changes dramatically, push_stop_token_stack +is called to establish a new set of stop token values. The old values are +restored later by calling pop_stop_token_stack. This is done, for example, +when entering the processing for preprocessing directives, whose syntax is +dramatically different than the context in which they are embedded.

    +

    Uses of add_stop_token and remove_stop_token must be very carefully +paired. A missing call of either would probably cause the associated token to +be handled incorrectly in error flushes for the rest of the compilation. +Skipping a remove_stop_token call is easy to do if one does a goto out +of an inner loop in a recursive descent routine (say, because there is an +error) and one skips over the point where the remove_stop_token is done. +The likelihood of such a problem is lessened by having debug_enter and +debug_exit verify (by means of a checksum) that the contents of +stop_token_array are the same on exit as they were on entry. This check is +only done when debugging is active, however, because it’s time-consuming. +Also, fe_wrapup verifies that all the counts have returned to zero by the +end of the compilation; that check is always done. In addition, when expensive +checking code is enabled, pop_stop_token_stack verifies that all of the +elements of the stop token set that is being discarded have been reset to zero.

    +

    If required_token does not find the token it expects, it adds that token to +the stop tokens set, and calls syntax_error. After flush_tokens +finishes, required_token checks again to see if the desired token has come +up, and if so, scans over it.

    +
    +
    +

    3.5.4. Error Entries#

    +

    For both syntax and semantic errors, another part of error recovery is +producing something sensible, in spite of the error, in the data structure that +represents the program. This task is eased by having special “error” entries +for all of the major table types. There are, for example, error constants, +error types, and error expression nodes. They are used to take the place of +any part of the program tree that cannot be built because of an error. In +general, the code tries to build as much of the complete tree as possible. An +error in one part of an expression, for example, need not mean that the entire +expression tree will be replaced by an error expression node. Throughout the +front end, code must be capable of dealing with error entries. The basic +philosophy is that an error entry is considered to be compatible with anything +else. No additional errors should be issued on encountering an error entry, +since it is assumed that some error was issued when the entry was created.

    +

    When syntax errors involve missing identifiers, special error symbols are +created. A different error symbol is created for each error case. All error +symbols point to the same special associated symbol header (see the +documentation of symbol_tbl.c).

    +

    When errors involve duplicate declarations of the same symbol, the second +symbol is entered anyway. Both symbols are in the symbol table, but because of +the symbol table structure, the later declaration will the one that is visible, +and it therefore effectively replaces the earlier declaration.

    +

    In general, scanning routines do not need to return indications of success or +failure, since they always return a tree representing the construct scanned. +Some routines must deal with unusual cases where there is no possible +representation for the thing scanned, and so they return an error parameter. +The caller must check it.

    +
    +
    +

    3.5.5. Intelligent Error Diagnosis#

    +

    The front end attempts to diagnose as many errors and warnings as possible. If +one uses header files with function prototypes for all external functions and +variables, it should be possible when writing in ANSI C or in C++ to do away +with lint, or at least to relegate it to use in unusual cases. That is the +goal of the front end: diagnose not only errors but also questionable +constructs such as those flagged by lint. However, since lint is run +on request and the front end must be run on each compilation, one must take +care that the errors are not overly pedantic. The front end tries to do this +by being selective about errors. It’s a good idea, for example, to warn about +value-less return statements in functions that should return a value. +However, in old-style C, before the keyword void existed, it was standard +practice to omit the type specifier altogether on a function that returned +nothing. The C language says such a function has type int, but the C +programmer usually thinks of such a function as having type void. So, in +the front end, a warning is issued for a value-less return in a function with +an explicit type, but not for one in a function with an implicit int type. +In pcc mode, a warning is never issued.

    +

    A similar issue comes up in expressions. An expression like 1/0 looks like +an error (division by zero), but should not necessarily cause a compilation +error. If it occurs in a context where it is not evaluated (such as +0&&1/0), it never causes an error; if it occurs in a context where it must +be evaluated at compile time (as in the size of an array), it causes an error; +and if it occurs elsewhere (i.e., in executable code), it causes a warning and +is left as-is to cause a fault (or not) at execution time.

    +

    Likewise, when a constant seems to be part of a bit-oriented operation (it is a +non-decimal constant, or it results from a bit-wise operator applied to +constant operands), the normal warnings about implicit sign changes when the +constant is changed from signed to unsigned or vice-versa are suppressed.

    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/lex_pp/index.html b/dev/doc/lex_pp/index.html new file mode 100644 index 0000000..a3314b7 --- /dev/null +++ b/dev/doc/lex_pp/index.html @@ -0,0 +1,2423 @@ + + + + + 7. Lexical Analysis and Preprocessing - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    7. Lexical Analysis and Preprocessing#

    +
    +

    7.1. Source Line Data Structure#

    +

    Before describing the routines involved in lexical analysis and preprocessing, +it is necessary to discuss the data structure that represents the current +source line. This data structure is used throughout the lexical routines, and +its form is dictated by the types of processing that must be done in the +lexical and macro routines. The routines and data structures described in this +section are defined in lexical.c and lexical.h.

    +
    +

    7.1.1. The Current Source Line#

    +

    A logical source line, in the ANSI C standard (2.1.2.2), is what results after +trigraphs have been replaced by the corresponding characters (e.g., ??= by +#) and line splices have been done (i.e., each line ending with a backslash +is spliced with the following line). The routine read_logical_source_line +does this processing, and the global array curr_source_line contains the +result. That is, in curr_source_line trigraphs have already been replaced, +and several physical source lines may have been spliced into one logical source +line. If any such transformations were made to produce the current source +line, the global variable orig_line_modif_list points at a list of entries +that describe all the transformations made, in a form such that

    +
      +
    • +
      the original source lines can be reconstructed from curr_source_line, +if that is necessary (e.g., for error-reporting purposes); and
      +
      +
    • +
    • +
      from a location within curr_source_line, one can determine the file +name, line number, and column from which that text came, for +error-reporting purposes.
      +
      +
    • +
    +
    +
    +

    7.1.2. Modifications to the Current Source Line#

    +

    When changes to the current logical source line are made because of +preprocessing, they are handled in a different way: curr_source_line is not +changed (much); instead, the global variable source_line_modif_list points +to a list of entries that indicate changes that have been made logically to +curr_source_line. Each of these changes is a deletion of some number of +characters at a given location, and an insertion of some number of characters +(possibly none) at that location. These entries represent changes due to +deletion of comments and replacement of macro invocations by the expansions of +those macros. (Comments need not be deleted, even logically, if preprocessing +output is not being produced. In pcc mode, comments are deleted entirely, +but in other modes they are replaced by one blank.)

    +

    The two sets of changes are handled differently, and one might ask why the +trigraphs and line splices are actually rendered in curr_source_line (with +instructions on undoing them), while the macro changes are not rendered (and +the instructions are for doing them rather than undoing them). The reason is +that the first set of changes is applicable at the character or intra-token +level, and the second set only applies at the inter-token level. It is a basic +goal of the lexical routines that the current position must be representable as +a single pointer, and that one be able to move forward efficiently in the input +by just incrementing that pointer. Trigraphs and line splices can occur within +tokens, and therefore if they were not rendered in curr_source_line one +would have to check for them in every case where one wants to move forward in +the input. The other modifications, on the other hand, can only occur between +tokens, and therefore they need not be expanded in the source line. They occur +between tokens, and special marker characters in the input stream are used to +indicate their presence. The marker characters cause the termination of +scanning of the previous token, followed (on the next call of get_token) by +interpretation of the marker character to decide where the input goes next. +This makes macro expansion efficient (the source line need not actually be +subjected to insertions and deletions) while preserving the ability to advance +through the input using just one pointer. It also preserves information that +allows one to construct either the original source line or the macro-expanded +line, and to know the origin of any particular part of the resultant line.

    +

    The modification entries can apply to the inserted text of other modifications, +so one can have modifications of modifications. Wherever a modification is +made, the original character (in curr_source_line or inserted text) is +replaced by a marker character (ATTENTION_MARKER) so that if that spot is +reached by sequential scanning from preceding text, one is cued to look at the +modification list to find the text that follows.

    +

    In extreme cases the data structure can get quite complex, with modifications +on modifications. In cases involving real-world macros, however, it remains +fairly simple.

    +

    ATTENTION_MARKER is a one-character lexical escape sequence. It has to be, +because a macro invocation can be as short as a single character, and the +ATTENTION_MARKER overwrites the beginning of the macro invocation. There +are also two-character lexical escape sequences, which begin with the +LE_ESCAPE character (which is zero). The second character of the escape +sequence is one of the following:

    +
      +
    • +
      LE_END_OF_LINE, which marks the end of the primary source line.
      +
      +
    • +
    • +
      LE_NEWLINE, which represents the newline character at the end of the +primary source line.
      +
      +
    • +
    • +
      LE_END_OF_INSERTION, which marks the end of the text inserted by a +source line modification.
      +
      +
    • +
    • +
      LE_END_OF_TOKEN, which separates tokens in macro text (see below).
      +
      +
    • +
    • +
      LE_INERT_MACRO, which indicates a macro name that should not be +expanded (see below).
      +
      +
    • +
    • +
      LE_NULL, which indicates a null (zero) character in the source line.
      +
      +
    • +
    +

    To ensure that the ATTENTION_MARKER and LE_ESCAPE characters are always +lexical escapes, rather than characters accidentally introduced into the +lexical data structure because of special characters in the input file, the +front end does two rewrites on input:

    +
      +
    • +
      The newline character at the ends of input lines is transformed into a +lexical escape sequence. This frees up the newline character to be used as +ATTENTION_MARKER.
      +
      +
    • +
    • +
      A null (zero) character in an input line is flagged with an error and +replaced by a space. In modes that allow null characters in the source +(e.g., gcc mode), the character is replaced by an LE_NULL escape +sequence (and an original line modification is created, so that column +numbers can be determined correctly).
      +
      +
    • +
    +

    The characters newline and null were selected for use as these reserved +characters because they are already special in the C language and in character +sets in general. No other pair of characters can be guaranteed not to occur in +source files, especially when international character encodings such as SJIS +are considered.

    +

    Note that because LE_ESCAPE is a zero character, the source line and +inserted text cannot be considered to be simple null-terminated strings. Also +note that the ATTENTION_MARKER and LE_ESCAPE characters will naturally +terminate the accumulation of the characters of a token.

    +

    The modification entries of both kinds are dynamically allocated, used, and +then freed when the next logical source line is about to be read. For each +kind, there is an available list (freed entries that are available for reuse), +an allocation routine, and a free routine. See

    +
      +
    • +
      add_orig_line_modif,
      +
      +
    • +
    • +
      free_orig_line_modif,
      +
      +
    • +
    • +
      add_source_line_modif,
      +
      +
    • +
    • +
      free_source_line_modif, and
      +
      +
    • +
    • +
      rem_source_line_modif.
      +
      +
    • +
    +

    The majority (75%?) of source lines have no modifications of any kind (not +counting comments), so the code in the lexical routines is optimized to deal +efficiently with that case.

    +

    Routines assoc_source_line_modif and nested_source_line_modif, along +with the associated macros go_into_insertion and leave_insertion, +handle the low-level tasks of determining where to go next in the input stream +based on the source modifications.

    +

    The current position in the input stream in given by curr_char_loc. +Ordinarily, it points to somewhere within curr_source_line, but when macros +are expanded it can point to somewhere in macro_buffer or to a +dynamically-allocated argument.

    +

    In the text of macro arguments and the replacement text for macros, the +individual characters have already been tokenized once. To ensure that the +tokenization is done the same way if and when it is done again, the text of +each token in source line modifications is followed by an LE_END_OF_TOKEN +lexical escape sequence. That escape sequence terminates the accumulation of +characters to make up a token, and is then ignored as part of the white-space +skip at the start of the next call of get_token. End-of-token sequences +are usually removed by gen_pp_output_for_curr_line, but an individual +end-of-token will be output as a blank if there is the possibility that two +adjacent tokens might be misparsed without one. See the discussion in +macro.c for further information.

    +

    In some obscure cases involving thwarted macro expansion, it is necessary to do +a true insertion into the source line, rather than the usual replacement of +some characters by some others. Fortunately, this only needs to be done at the +beginning of the line, so a simple mechanism suffices: a source line +modification with a NULL location is taken to be an insertion before the first +character of the line. Only one such insertion is allowed per line, and if one +exists, line_start_source_line_modif points to it.

    +

    curr_source_line and macro_buffer are actually dynamically-allocated +arrays, and can be expanded (by reallocation) as necessary. Therefore, there +is no limit to the length of source lines or of macros except that imposed by +available memory.

    +
    +
    +
    +

    7.2. Lexical Analysis#

    +

    “Lexical analysis” includes the reading of source lines and the breaking of +them into lexical tokens. It is also closely tied to preprocessor directives +and to macro processing, since they are invoked at the lexical level, and are +defined in terms of tokens. The source code for lexical processing is in +lexical.c, and associated declarations are in lexical.h.

    +
    +

    7.2.1. Getting Tokens#

    +

    The primary interface to the lexical routines is the routine get_token, +which fetches and returns the next token of input. When compiling C, these +tokens are the input for syntax analysis. When preprocessing only, the tokens +are fetched (by a loop in cpp_driver in preproc.c), and then discarded; +calling get_token repeatedly forces the reading of input lines and the +necessary preprocessing on each line, and each modified line is then written +out just before the next line is read. do_preprocessing_only and +generate_pp_output will be TRUE in that case. get_token is used in +both cases; in fact, it is used for all fetching of tokens in all contexts.

    +

    When get_token is called, it scans the next token of input and returns its +kind. The kind of token is also saved in curr_token. See the enumeration +a_token_kind, in lexical.h, for the list of token kinds (e.g., +tok_identifier, tok_lparen).

    +

    Much of the rest of the processing is dependent on several global switches, as +described in the following paragraphs. Most of these switches are defined in +preproc.h.

    +

    If fetch_pp_tokens is TRUE when get_token is called, a preprocessing +token (pp-token) is fetched instead of a regular token. Constants are not +converted (and numeric ones are returned as pp-numbers); adjacent string +literals are not concatenated; keywords are not recognized; and errors are not +issued for malformed tokens. Also, start_of_curr_token and +end_of_curr_token are set to point to the beginning and end of the current +token, and len_of_curr_token is set to its length.

    +

    If expand_macros is TRUE, preprocessing macros are expanded as they are +scanned. The caller sees only the tokens after expansion. If a macro name is +preceded by an LE_INERT_MACRO escape sequence, the macro is not expanded +and the identifier is returned to the caller with curr_token_is_inert_macro +set to TRUE.

    +

    When fetch_pp_tokens is FALSE, do_string_literal_concatenation controls +whether adjacent string literals are concatenated.

    +

    If in_preprocessing_directive is TRUE, the definition of white space is +changed to that for within preprocessing directives; i.e., keywords are not +recognized, and newline, #, and ## are recognized and returned as +tokens. However, if caching_pragma_tokens is TRUE, a pragma is being +recoded as a token cache, and this requires disabling some of the processing +that is normally done when in_preprocessing_directive is TRUE – +identifiers will be looked up and # and ## are not returned as tokens. +And if recognize_keywords_in_pragma is also set, keywords are looked up and +returned as keyword tokens rather than as identifier tokens. (This is required +for dealing with #pragma directives involving C or C++ constructs that must +be scanned by the compiler’s normal scanning routines; for instance, it is used +for processing the pragmas that control template instantiation.)

    +

    If in_pp_if_expression is TRUE (indicating that we are inside a +preprocessing #if expression), integer constants will get an implicit L +suffix, and undefined identifiers will be returned as the integer constant +0L.

    +

    If exp_header_name is TRUE, then "..." will be scanned as a header name +for an #include (tok_header_name). Other tokens will be processed +normally. exp_system_header_name is similar, for header names of the form +<...>.

    +

    If exp_digit_sequence is TRUE (indicating a string of decimal digits) then +the digits will be scanned as a tok_digit_sequence (used in the #line +directive). Other tokens will be processed normally.

    +

    For tokens that are literal constants, the struct const_for_curr_token is +set to the value of the constant (if fetch_pp_tokens is FALSE). This +global variable is also set for the literal portion of user-defined literals +(when user_defined_literals_enabled is TRUE), along with +ud_lit_op_sym_for_cur_token, which designates the symbol for the literal +operator or literal operator template chosen to produce the value of the +user-defined literal. When ud_lit_op_sym_for_curr_token designates a raw +literal operator or a literal operator template, const_for_curr_token is a +ck_string constant whose value is the actual spelling of the literal part of +the toke; otherwise, it is the value of that literal part.

    +

    For tokens that are identifiers, the corresponding symbol header is looked up +in the symbol table and locator_for_curr_id is set accordingly. For +user-defined literal tokens, locator_for_curr_id is set to designate the +literal-operator-id of the literal operator or literal operator template +denoted by the literal’s ud-suffix. It can be used later to refer to the +current definition of the identifier or operator (if there is one) or to enter +a new definition for the identifier or operator.

    +

    The routine get_token is basically one large switch statement that fans +out based on the current character of input. The various cases are:

    +
      +
    • +
      For operators and similar special-character tokens, get_token looks at +the next character or two and selects the appropriate token.
      +
      +
    • +
    • +
      For the lexical escape sequences (the ATTENTION_MARKER character or the +two-character LE_ESCAPE sequences), skip_white_space is called. These +characters are not all actually white space, but it simplifies processing +to let that routine handle them. All reads of new source lines are +requested by skip_white_space.
      +
      +
    • +
    • +
      For numbers, scan_number is called (it handles decimal, octal, and +hexadecimal integer literals, as well as decimal and hexadecimal +fixed-point and float literals). scan_number will determine the kind +of number, accumulate its characters, and, if appropriate, call the proper +conversion routine in literals.c to convert the literal constant string +to internal form in const_for_curr_token. It also handles recognition +of numeric user-defined literals and, when one is recognized, setting +ud_lit_op_sym_for_curr_token.
      +
      +
    • +
    • +
      For identifiers, the characters are accumulated and find_symbol is +called. This yields a list of symbols with the given name. The list is +then searched for a definition that is a macro or keyword. If the +identifier is a macro and if macro expansion is required, +macro_invocation (in macro.c) is called. Note that because this +look-up finds both macros and other uses of identifiers, a symbol only has +to be looked up once; it does not have to be looked up once to see whether +or not it is a macro, and then again later to see if it is something else.
      +
      +
    • +
    • +
      For quoted tokens (character constants and string literals, and the wide +versions thereof), an appropriate scanning routine is called, which in turn +calls accum_quoted_string. The latter accumulates the characters of +the string, checking for escapes and the like. When a string literal or +wide string literal is scanned outside of preprocessing mode, get_token +will call concat_adjacent_string_literals, which will check if the next +token is another string literal. If so, the adjacent strings will be +concatenated into a single string literal token. scan_char_constant +recognizes user-defined character literals and sets +ud_lit_op_sym_for_curr_token, as appropriate. In order to handle merging +of suffixes across concatenated string literals, the similar task for +user-defined string literals is handled by concat_adjacent_string_literals, +except when fetch_pp_tokens is TRUE; in that case, get_token performs the +requisite processing, as string literals are not concatenated in that mode.
      +
      +
    • +
    • +
      When a # appears as the first non-white-space character on a line, a +call to pp_directive (in preproc.c) is made to process a +preprocessing directive.
      +
      +
    • +
    +

    One very important requirement is that get_token be fast. About 30 percent +of total time time in the front end is likely to be spent in get_token and +its subordinate routines. Every effort has been made to make those routines +fast, and in particular, to avoid unnecessary subroutine calls. As an example, +simple white space (blanks and horizontal tabs) is skipped in get_token +itself, rather than incurring the overhead of calling skip_white_space.

    +

    The handling for pp-tokens and normal tokens differs in a number of ways, but +the most fundamental of those is the information returned to the caller. The +kind of token is returned in both cases. However, for identifiers and literal +constants, where additional information must be returned to precisely specify +the token, the returned value in the pp-token case is the actual characters of +the token, and in the normal token case it is something one step removed from +that: a symbol locator for identifiers, or a constant entry for constants. +This is useful, but it’s also necessary – when scanning normal tokens, and in +particular identifiers and literal constants, there are some cases where it is +necessary to skip forward to the next token to see if it has some effect on the +current one. For example, after scanning a string literal, one must look ahead +to see if the next token is another string literal, and if so, one concatenates +the two. Since the next token may be on another line, it’s clear that the +original string for the token in the current source line may be gone by the +time the next token is reached. Therefore, the locator or constant entry form +is necessary even inside of get_token.

    +
    +
    +

    7.2.2. Token Lookahead and Caching#

    +

    Sometimes syntactic analysis requires lookahead – it requires the fetching +of one or more tokens past the current position to discriminate between two +possible parses.

    +

    This comes up even in C, although the lookahead there is limited to a single +token. For example, when a statement begins with an identifier, one must look +past the identifier to see whether or not the next token is a “:” – if so, +the identifier is a label. (The routine next_token provides this +capability.)

    +

    In C++, lookahead is needed in many more contexts, and is not limited to +one-token lookahead. In addition, there are some language constructs that must +be saved in some lexical form when they appear, and then parsed later on the +basis of the saved information. The most obvious example is the bodies of +member functions declared inside a class: their name binding cannot be done +until the entire class declaration has been scanned, so the easiest +implementation is to save the member function bodies and then parse them when +the closing brace of the class is reached.

    +

    A construct called a token cache supports all these needs for lookahead, as +well as recording the tokens of template definitions and other syntactic +elements for delayed use. a_token_cache is a data structure that represents a +sequence of tokens. The tokens in a cache are represented by a list of shared +tokens (a_shared_token), each one describing an immutable token state (this +includes not just the token kind, but also any additional information required +to fully specify the token, e.g., a symbol locator for an identifier or a +constant entry for a literal constant). A similar data structure, +a_reusable_token_cache, is used for the tokens of a template definition or +delayed construct.

    +

    To build a nonreusable token cache, one declares a variable of type +a_token_cache. Then one reads through tokens in the usual way, calling +get_token to fetch each token, and then calls cache_curr_token before advancing +to the next. When enough lookahead or caching has been done, one can put all +the tokens in the token cache back on the front of the input stream by calling +rescan_cached_tokens.

    +

    get_token does not read directly from nonreusable token caches (although it +does do so with reusable token caches; see below). Instead, +rescan_cached_tokens adds the current token to the end of the cache and then +pushes the cached tokens in LIFO order onto the global +cached_token_rescan_stack (implemented as a stack instead of a list for +efficiency reasons), and finally calls get_token to fetch what was the first +token of the cache from the cached token rescan stack as the current token. As +long as the global rescan stack is non-empty, get_token will fetch a token from +the rescan stack (by calling get_token_from_cached_token_rescan_stack) instead +of scanning a new token from the current source line.

    +

    next_token is a simple user of the token caching facility; it caches the +current token, fetches the next and remembers its kind, then pushes the cache +back on the input stream to restore the original token (and also the next one, +behind it).

    +

    unget_token puts the current token back on the front of the input stream, +so that in effect afterwards there is no current token (although it doesn’t +actually go so far as to change curr_token). It is used in some unusual +error situations that want to fabricate and insert an identifier token where +one was missing in the source.

    +

    Two routines are available to cache sequences of tokens delimited by given +tokens:

    +
      +
    • cache_token_stream_until_matching_token

    • +
    • cache_token_stream_with_coalesce_flag

    • +
    +

    cache_token_stream_with_coalesce_flag is not intended to be called +directly. Instead, it is called by one of two interface routines:

    +
      +
    • cache_token_stream

    • +
    • cache_token_stream_coalesce_identifiers

    • +
    +

    cache_token_stream is used to cache tokens until one of a specified set of +stop tokens is found. This is used, for example, when caching the body of a +class or function template when all tokens up to a closing brace should be +cached. In such situations, the only special processing that is needed is to +keep track of paired delimiter tokens (e.g., {}, [], ()) so that, +for example, the closing brace of an inner block is not incorrectly taken as +the end of the template body.

    +

    When the stop token could appear within a template argument list, additional +processing must be done to determine whether a “<” that is encountered is +the start of a template argument list or simply a less than sign. In order to +determine this, the identifiers found while the tokens are cached must be +coalesced (the identifier coalescing process is described later in this +chapter). This special kind of token stream caching is done by calling +cache_token_stream_coalesce_identifiers. The process of coalescing an +identifier involves fetching some number of tokens. Because these tokens are +not fetched directly by cache_token_stream_coalesce_identifiers, a +mechanism is needed to get access to those tokens. +begin_caching_of_fetched_tokens is called to request that a cache of +fetched tokens be automatically constructed. Each new token returned by +get_token is added to a special cache. The token stream is then cached by +recording the starting token sequence number, getting each token, and +coalescing each identifier that is encountered until the stop token is found. +Once the starting and ending token sequence numbers are known, the tokens in +that range are extracted from the special cache. +end_caching_of_fetched_tokens is then used to indicate that the automatic +caching of tokens is no longer needed.

    +

    As noted above, token caches are also used to represent template definitions +and other syntactic constructs that require delayed processing. The tokens +that comprise the syntactic element are cached when it is scanned and are +rescanned later when needed. While other token caches are rescanned once and +discarded, reusable token caches may be rescanned over and over again. +Reusable token caches should be constructed by calling the factory function +shared_obj<a_token_cache> with reusable set to TRUE (this acts as a sanity +check to ensure the token cache is used in the intended way, but they are +otherwise built in exactly the same manner as other token caches). The +reusable token cache object (of type a_reusable_token_cache) is then +constructed from the result.

    +

    Various scenarios can cause multiple reusable token caches to be pending rescan +at a given time; calling rescan_reusable_cache pushes a reusable token cache +onto the global reusable_cache_stack. get_token first rescans tokens from the +(nonreusable) cached token rescan stack, as described above. When this stack +is exhausted it rescans tokens from the reusable cache at the top of the +reusable cache stack by calling get_token_from_reusable_cache_stack. When all +of the entries in a reusable cache have been scanned the cached token rescan +stack is restored and the entry is popped off of the reusable cache stack. +Token scanning then resumes with the next token on the cached token rescan +stack.

    +

    Reusable and nonreusable token caches may be freely intermixed; template +instantiations may occur while scanning tokens from a cache and a template +instantiation will usually create new caches, as needed, when doing +look-aheads, as described earlier.

    +
    +
    +

    7.2.3. Source Positions#

    +

    Each time a token is fetched, the global variable pos_curr_token is set to +the source position of the first character of the token. A source position +means a sequence number (which can be converted to a file name and line number) +and a column number from the original source line. The position is determined +by the macro macro_line_loc_to_source_pos. In the simplest and most common +case, a pointer to the starting character of the current token can be converted +easily to a source position by using the current sequence number and +determining the column number by taking the difference between the pointer and +the start of curr_source_line and applying an offset to convert the byte +offset into a logical column number using the macro logical_column_offset +(which can in some cases result in a call of f_logical_column_offset). In +more complicated cases, conv_line_loc_to_source_pos is called, and it uses +the information in both orig_line_modif_list and source_line_modif_list +to determine the source position. The source position of something in a +preprocessing modification is taken to be the position of the first character +of the original source line that contains the macro invocation that leads to +the given modification.

    +
    +
    +

    7.2.4. The Input Stack#

    +

    open_file_and_push_input_stack is called to enter both the primary source +file and #include files – by fe_init (in fe_init.c) and by +proc_include (in preproc.c), respectively – and it in turn calls +open_file_for_input and push_input_stack to do the work; when end of +file is reached, pop_input_stack is called.

    +

    open_file_for_input loops to try each possible include file directory when +attempting to open an include file; it also contains code for the (optional) +implicit inclusion feature of automatic template instantiation, permitting a +series of suffixes to be tried in each directory.

    +

    Together, the push/pop routines manage the input_stack, which contains +information about the current nesting of input files. To limit the number of +open files, they will reuse files once a few files have been opened (see +MAX_INCLUDE_FILES_OPEN_AT_ONCE). The storage for input_stack is +dynamically allocated and is reallocated larger as needed.

    +

    If the options requesting makefile information or a list of header files +were specified on the command line, do_preprocessing_only will be TRUE but +generate_pp_output will be FALSE. Either list_makefile_dependencies or +list_included_files will be TRUE. push_input_stack writes out the +appropriate information to the preprocessing output file.

    +

    The front end recognizes certain idioms used to allow an include file to be +included more than once with all of the includes after the first having no +effect. When one of these idioms is recognized the front end will ignore +subsequent attempts to include the file again. The front end recognizes two +commonly used mechanisms used to allow a file to be included multiple time: +placing the entire contents of a file inside a #ifndef or #ifdef, and +use of the #pragma once directive. A simple state machine is used to +determine whether subsequent includes of a given file may be suppressed. The +state information is maintained in the input stack entry. +suppress_subsequent_include_of_file is called for each file to be included. +If it returns TRUE then the call of push_input_stack is skipped and the +include is suppressed. See the comments that precede find_include_history +for additional information.

    +
    +
    +

    7.2.5. Skipping White Space#

    +

    skip_white_space is called to skip over any white space and get to the +start of the next token (some simple cases of white space are skipped in +get_token, for efficiency). Besides the usual white-space characters, it +also handles the skipping of comments, calling read_logical_source_line to +fetch the next line of input, and going into and leaving source modifications +upon encountering lexical escape sequences (e.g., ATTENTION_MARKER to go +into a modification, LE_ESCAPE/LE_END_OF_INSERTION to leave a +modification).

    +

    skip_white_space tracks the kind of white space it has skipped over +(comment/other) and sets global variable kind_of_white_space_skipped. This +information is useful in the macro processing routines, where white space can +be significant. Note that kind_of_white_space_skipped is not necessarily +set correctly if one calls get_token, since get_token does some +white-space skipping on its own.

    +

    When skip_white_space recognizes one of the lint comments

    +
    +
    +
    /*ARGSUSED*/,
    +
    /*NOTREACHED*/,
    +
    /*VARARGS*/, or
    +
    /*VARARGS n*/
    +
    +
    +

    add_curr_token_pseudo_pragma is called. It adds a pending pragma entry to +the current token pragma list. Later, the pending pragma entry is removed via +a call to extract_specific_pragmas, and processed (by setting global state +information or flags in IL entries). For ARGSUSED and VARARGS, that’s done in +record_lint_argsused_and_varargs_state. For NOTREACHED, it’s done in +check_lint_notreached_state.

    +
    +
    +

    7.2.6. Hanging Delete#

    +

    If global variable delete_source_from_loc is non-NULL, the text that +extends from that location in the current line to the position immediately +preceding curr_char_loc is to be deleted. This is referred to as a +“hanging delete”, and is used in deleting macro invocations. This flag is +necessary because the complete text of a macro invocation must be deleted (to +be replaced by the expansion of the macro), but the macro invocation may span +several lines, and the macro routines are not in control when ends of lines are +passed in skip_white_space. By setting this flag, the macro routines can +request that the text of a macro invocation be correctly deleted even if it +spills over onto additional lines. When the deletion is handled at line end, +delete_source_from_loc is updated to point to the start of the new source +line so that the hanging delete remains in effect.

    +
    +
    +

    7.2.7. Whitespace keywords#

    +

    C++/CLI has “whitespace keywords,” which are keywords made up of two words +separated by whitespace but considered a single keyword, for example “refclass”. These are scanned by scan_whitespace_keyword. One interesting +detail is that the characters that make up the token (which can be spread over +multiple lines because of the embedded whitespace) are replaced by a canonical +spelling of the keyword containing a single embedded space, the same way that a +macro is replaced in the input line by its expansion. That allows processing +that deals with tokens on the pp-token level to handle those whitespace keyword +tokens like any others, as a contiguous sequence of characters.

    +
    +
    +

    7.2.8. Textual Preprocessing Output#

    +

    When compiling C to intermediate language, there is no need to assemble the +actual logical source line that results after preprocessing. All that is +required is that the tokens of that line can be extracted. But when +preprocessing only is being done, the preprocessed line is output from +curr_source_line and the information in source_line_modif_list. [1] +gen_pp_output_for_curr_line assembles and puts out the effective line, +calling gen_pp_line_info to generate line-identification directives when +the file/line of the current line does not immediately follow that of the line +previously output. gen_pp_output_for_curr_line is called by +read_logical_source_line right before a new line is read; it is also called +when the input stack is pushed and popped for the starts and ends of input +files.

    +

    There are some special problems in producing the preprocessing output line when +preprocessing directives are passed to output. This must be done for certain +directives (like #pragma) that the preprocessor cannot process. If a +directive of that type contains a multi-line comment, the parts of the +directive preceding and following the comment must be written out on the same +line. In this case, the part preceding the comment will be written without a +terminating newline, and the part following the comment will be written later +on the end of that line.

    +
    +
    +

    7.2.9. Reading Logical Source Lines#

    +

    Aside from its primary function of reading the next logical source line and +processing trigraphs and line splices, read_logical_source_line also calls +gen_pp_output_for_curr_line to output the previous line (if needed), clears +the modification lists, and handles ends of files. It can be told to stay at +the end of a file (rather than popping out to the enclosing file) on end of +file, if that is desirable (as it is when scanning a comment that is unclosed +at end of file). On the ultimate end of file, it returns a special end-of-file +line (containing just an LE_END_OF_LINE lexical escape sequence) in +curr_source_line, and sets after_end_of_all_source.

    +

    If curr_source_line is too small, expand_curr_source_line is called to +reallocate it, and adjust_curr_source_line_structure_after_realloc (in +macro.c) is then called to walk through the data structure associated with +curr_source_line and change any pointers to curr_source_line to point +to the proper addresses within the new allocation for curr_source_line.

    +
    +
    +

    7.2.10. Multibyte characters in source code#

    +

    When MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED is TRUE, multibyte character +sequences are accepted in comments, string literals, character constants, +identifiers, and header names. Multibyte character sequences are not wide +characters (e.g., Unicode); they are sequences of one or more characters, +appearing in a string of characters of the usual char size, and +representing single logical characters. For example, in the Japanese SJIS +encoding, the sequence 82A9 (in hexadecimal) represents a single Kanji +character: the first character (82) is in a range that indicates it is the +first character of a two-character sequence. Typically, the characters in the +ASCII code set will be accepted as themselves in multibyte character encodings, +i.e., they will be sequences of length one. Since each character sequence in a +multibyte character string need not have the same length (and some encodings +have explicit shift-state-change characters), a multibyte character string can +be understood only by scanning it from beginning to end, advancing over one +logical character at a time.

    +

    Moreover, since characters after the first in a multibyte sequence can look +like simple ASCII characters, it is not generally okay to look for an ASCII +character by doing a simple strchr-type search. The lexical routines count +on being able to do this for only two characters: the zero/null character (this +is guaranteed by the C standard; characters after the first in a multibyte +character sequence are not allowed to be zero) and the newline character (this +is effectively guaranteed by the fact that one must be able to read files +containing multibyte character sequences and discern the ends of lines without +tracking the multibyte character state as each character is read). [2]

    +

    To advance over logical characters, one needs a routine that will determine the +length of the multibyte character sequence at a given location. This is done +by the macro mbc_length and routine f_mbc_length. In the usual +configuration, that routine is implemented by calling the standard C library +routine mblen. mbc_length and related routines are used to do special +processing in the following places:

    +
      +
    • +
      In read_logical_source_line, the line splice (”\”) and trigraph +(”?”) characters are ignored if they appear in the middle of a +multibyte character sequence.
      +
      +
    • +
    • +
      In skip_white_space, the closing character for a C-style comment +(”*”) is ignored if it appears in the middle of a multibyte character +sequence. (”//” end-of-line comments require no special handling, +because the end-of-line marker is rendered as a lexical escape +sequence,which cannot appear within a multibyte character sequence.)
      +
      +
    • +
    • +
      In accum_quoted_string, scan_char_literal, scan_string_literal, +conv_single_char, and conv_single_wide_char, the characters inside +quoted strings are scanned as multibyte characters as necessary. The +routine mbc_to_wide_char is used to convert a multibyte character +sequence in a wide string literal or wide character constant to the +appropriate wchar_t character. In the usual configuration, +mbc_to_wide_char is implemented by calling the C library routine +mbtowc.
      +
      +
    • +
    • +
      In get_token, the scanning for identifiers uses is_identifier_char +to recognize identifier characters beyond the basic character set. +make_canonical_identifier handles encoding the multibyte characters +appropriately in the name string for the identifier.
      +
      +
    • +
    +

    Note that not all source code is scanned as multibyte characters, because that +would take too much time. The special scanning is done only in the contexts +listed above. For the line-splice and trigraph cases, when the line-read +routine sees those characters it goes to the beginning of the line and steps +through the characters of the line to find out where the character falls in the +multibyte character sequences, but that processing is done only if a potential +line splice or trigraph appears. Note also that there are configuration +options to turn off the special processing for several of the special +characters, for cases where the encoding guarantees no confusion on the +particular character.

    +

    If the encoding has locking state-change characters (e.g., JIS), each C-style +comment and string is assumed to begin in the initial shift state. This +follows a requirement stated in 5.2.1.2 of the ANSI/ISO C standard

    +

    If UNICODE_SOURCE_SUPPORTED is TRUE, the multibyte encoding selected is the +UTF-8 encoding of Unicode. UTF-16 is also supported, in the little-endian or +big-endian format, and is converted immediately to UTF-8 on input. The type of +source code in a file can be specified by a byte order mark (BOM) at the start +of the file, or by way of the --unicode_source_kind command-line option. +There is also a macro DEFAULT_UNICODE_SOURCE_KIND that can be used to +establish the default for files without a byte order mark.

    +

    When UNICODE_SOURCE_SUPPORTED is set to TRUE, identifiers and file name +strings in the front end are represented in UTF-8. For file names, there is +the expectation that the standard system fopen will be able to deal with UTF-8 +file names. If that isn’t the case, some host-specific code may have to be +added to fopen_interface. (For Windows-hosted configurations, specific +code is provided which calls the _wfopen function.)

    +

    If UTF-8 identifier name strings are somehow undesirable (e.g., a back end or +linker can’t handle them), the macro +IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS can be set to FALSE, in which case +characters in identifiers outside of the basic character set will be rendered +in the \uxxxx or \Uxxxxxxxx form also used for UCNs. Note, +however, that the encoded form will come out in diagnostic messages that name +an entity in the source.

    +

    If DEFAULT_UNICODE_SOURCE_KIND is usk_none, source files without a byte +order mark are assumed to be encoded in ISO-8859-1 (otherwise known as +Latin-1), which matches the first 256 code points in Unicode. +(LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED should be set to a locale that +matches ISO-8859-1.) Such a mode (which is the default for Windows-hosted +versions) is a hybrid mode in which some files are Unicode and some are not, +and in which therefore a character like a u-umlaut would be encoded differently +depending on the kind of source file it appears in. Such characters in +non-Unicode files are converted to UTF-8 (or the identifier encoding \uxxxx) when they appear in identifiers and file names. In hybrid +configurations, characters in textual preprocessing output are always converted +to UTF-8 if DEFAULT_UNICODE_SOURCE_KIND is not usk_none, and to +ISO-8859-1 otherwise. Characters that cannot be represented in ISO-8859-1 in +the latter case are converted to “?”.

    +

    When UNICODE_SOURCE_SUPPORTED is TRUE, +NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE may be set to TRUE to +indicate that non-Unicode files are encoded in some character set other than +ISO-8859-1.This feature requires the ability to translate other character sets +to and from Unicode. Such a facility is provided in newer versions of the +Windows API (Microsoft version 1400 and above) so this feature is enabled when +the front end is built with EDG_WIN32 set to TRUE. In identifiers and file +names, native characters are translated to their UTF-8 equivalent. In wide +strings, native characters are translated to their Unicode equivalent. In +narrow strings, they are left in their original form.

    +

    When Microsoft extensions are enabled and EDG_WIN32 is TRUE, this feature +enables support for the Microsoft setlocale pragma, which specifies the +character encoding to be used for the translation to and from Unicode.

    +
    +
    +

    7.2.11. Raw Listing Output#

    +

    gen_raw_listing_output_for_curr_line is called to write source lines to +f_raw_listing when raw listing information is requested; it calls +gen_expanded_raw_listing_output_for_curr_line to write out the +macro-expanded form of the source line if the source line has some +modifications.

    +

    gen_rlisting_line_info writes information about transitions into and out of +include files; it is called by push_input_stack at beginnings of files and +by pop_input_stack at ends of files.

    +
    +
    +

    7.2.12. Inserting Text into the Token Stream#

    +

    insert_string_into_token_stream may be called to cause a string to be +scanned as tokens that are processed as part of the input stream either before +or after processing the current token. When scanning tokens from the string, +macros are optionally expanded and adjacent string literals are concatenated. +The string cannot contain preprocessing directives, and trigraphs are not +recognized.

    +

    This mechanism is used is used to internalize C++ code generated by the C++ +metadata reader (see Declarations from C++/CLI Assembly Metadata) in the functions +scan_top_level_metadata_declarations and get_definition_of_class.

    +
    +
    +

    7.2.13. Utility Routines#

    +

    There are several routines in lexical.c that are utility routines for +syntax analysis, and are not directly related to get_token:

    +
      +
    • +
      flush_tokens is called on the occurrence of a syntax error, and throws +away tokens (by calling get_token) until a token is found that seems an +appropriate place to restart. The current stop token set pointed to by +curr_stop_token_stack_entry contains the set of tokens on which to stop +the flush (it is maintained by the macros add_stop_token, +remove_stop_token, and the routines push_stop_token_stack and +pop_stop_token_stack). Recursive-descent routines place the tokens +they expect in the set of stop tokens; then, if an error occurs, the flush +will stop at a point that one of the recursive descent routines will +recognize. flush_tokens should not in general be called directly; +syntax_error should be called to report a syntax error, and it will +call flush_tokens.
      +
      +
    • +
    • +
      flush_until_matching_token is called by flush_tokens (and can be +called from elsewhere) to flush from an opening token such as a left +parenthesis to the matching closing token.
      +
      +
    • +
    • +
      loop_token is a utility routine that can be called at the bottom of a +loop for a repeated syntactic construct (e.g., a comma-separated list). It +tests for a particular token and takes it if it is found.
      +
      +
    • +
    • +
      required_token is a utility routine that should be called when a +particular token is required to appear next. It checks for that token, and +issues an error if the token is not found.
      +
      +
    • +
    • +
      next_token returns the next token after the current one, without +disturbing the current token. This is used in recursive descent parsing +routines to look ahead at the next token to decide between two paths +through the syntax.
      +
      +
    • +
    • +
      next_two_tokens is similar to next_token except that if the next +token matches a value supplied by the caller the token after the next token +is fetched and returned to the caller. This is used when scanning vacuous +destructor references in C++ where it is necessary to look for a tilde +following a :: to recognize a nonclass vacuous destructor reference +[3].
      +
      +
    • +
    • +
      push_lexical_state_stack and pop_lexical_state_stack are used to +enter and exit a new lexical context. These are used, for example, when +instantiating a template and when switching from fetching normal tokens to +scanning a preprocessing directive.
      +
      +
    • +
    +
    +
    +
    +

    7.3. Scanning Names in C++#

    +

    Unlike C, in which all names are simple identifiers, in C++ the names of +entities are often more complicated. Names may be preceded by one or more +qualifiers such as namespace and class qualifiers (e.g., A::B::i) and +global scope qualifiers (e.g., ::i); class qualifiers may include template +references (e.g., A<int>::i); and the name that follows these qualifiers +may be more complicated than a simple identifier: it may also be an operator +name (e.g., operator+), a conversion function name (e.g., operator +int), a (C++11) literal operator name (e.g., operator ""_km), or a +destructor name (e.g., ~A). An arbitrarily complex name is referred to as +a “generalized identifier”. The process of collecting the tokens of a +generalized identifier and replacing them with a single tok_identifier +pseudo-token is referred to as “coalescing” the generalized identifier. A +hierarchy of routines is provided that scan generalized identifiers:

    +
      +
    • +
      is_generalized_identifier_start determines whether the current token +begins a generalized identifier and, if so, scans the tokens that comprise +the generalized identifier and records its description in +locator_for_curr_id.
      +
      +
    • +
    • +
      coalesce_and_lookup_qualified_name calls +is_generalized_identifier_start and, if the generalized identifier +includes a qualifier, the name after the qualifier is looked up in the +scope specified by the qualifier. Names without qualifiers are not looked +up. [4]
      +
      +
    • +
    • +
      coalesce_and_lookup_generalized_identifier is used to scan and look up +a generalized identifier. It calls coalesce_and_lookup_qualified_name +and looks up the name if it does not include a qualifier. Names that +include qualifiers will have already been looked up by +coalesce_and_lookup_qualified_name.
      +
      +
    • +
    +

    The arguments to these routines include options used to specify the kinds of +names that may be accepted and, for the coalesce-and-look-up routines, a lookup +mode that specifies the type of name lookup to be performed. The options +parameter specifies a set of “generalized identifier” (GID) flags. The GID +flags specify several different types of information:

    +
      +
    • +
      The kinds of identifiers that should be recognized. For example, ~A +may be recognized as a destructor, or the tilde may be an operator.
      +
      +
    • +
    • +
      The kinds of identifiers that are allowed. For example, are qualified +names allowed in this context? Are operator names allowed? The difference +between constructs that are “recognized” and those that are “allowed” is +that constructs that are not recognized (i.e., ~D) are not considered +identifiers by is_generalized_identifier_start while constructs that +are not allowed are considered identifiers but cause errors to be issued +indicating that the particular type of identifier is not permitted in the +current context.
      +
      +
    • +
    +
    +

    7.3.1. Recognizing Generalized Identifiers#

    +

    is_generalized_identifier_start is the lowest-level generalized identifier +routine and does most of the work. As the name suggests, +is_generalized_identifier_start is used to determine whether the current +token is the beginning of a generalized identifier.

    +

    is_generalized_identifier_start is actually a macro that first checks +whether the current identifier has already been coalesced. If it has, the +macro immediately returns TRUE; otherwise it calls +f_is_generalized_identifier_start, which performs the rest of the +processing described here.

    +

    For these examples is_generalized_identifier_start returns TRUE and sets +the current token to tok_identifier:

    +
    +
    +
    i::iX::i
    +
    ::X::i
    +
    ::A::B::i
    +
    A<int>::i
    +
    A::operator =
    +
    A::operator int
    +
    A::operator ""_km // When user-defined literals are recognized
    +
    A::~A
    +
    NS::i
    +
    NS::A::i
    +
    operator =
    +
    operator int
    +
    operator ""_km    // When user-defined literals are recognized
    +
    ~A                // When destructors are recognized
    +
    A<int>
    +
    NS::A<int>
    +
    ~int              // When nonclass vacuous destructors are recognized
    +
    int::~int         // When nonclass vacuous destructors are recognized
    +
    A::anything else except *   // Error
    +
    +
    +

    For these examples FALSE is returned and current token is set to +tok_ptr_to_member:

    +
    +
    +
    X::*
    +
    A<int>::*   // Template reference will be coalesced
    +
    +
    +

    For these examples FALSE is returned and the current token is not changed:

    +
    +
    +
    ::new
    +
    ::delete
    +
    ~A          // When destructors are not recognized
    +
    anything else
    +
    +
    +

    Determining whether or not the current token is the start of an identifier may +involve scanning all of the tokens that comprise the identifier. Consequently, +all of the tokens that make up an identifier are scanned the first time that +is_generalized_identifer_start is called for a given identifier. The +information needed to describe the generalized identifier is recorded in the +symbol locator, and on subsequent calls the information from the locator is +used to return the appropriate value to the caller. When a sequence of tokens +is coalesced the original tokens are replaced with a single tok_identifier +or tok_ptr_to_member. The resulting token and related state information in +the locator is referred to as a “pseudo-token”. When +is_generalized_identifier_start determines that the thing being scanned is +an identifier, the current token is set to tok_identifier, the locator is +updated with a description of the identifier, and the return value of the +function is TRUE. The fields in the locator that are set are

    +
      +
    • +
      is_qualified_name
      +
      +
    • +
    • +
      is_global_qualified_name
      +
      +
    • +
    • +
      is_file_scope_qualified_name
      +
      +
    • +
    • +
      is_operator_name
      +
      +
    • +
    • +
      is_destructor_name
      +
      +
    • +
    • +
      is_udl_operator_name
      +
      +
    • +
    • +
      is_class_member
      +
      +
    • +
    • +
      parent
      +
      +
    • +
    • +
      has_been_coalesced
      +
      +
    • +
    • +
      is_vacuous_destructor_reference
      +
      +
    • +
    • +
      is_nonclass_destructor
      +
      +
    • +
    +

    When coalescing a qualified name such as A::xxx the result is a locator +whose symbol header points to the name xxx, and whose parent points to +the A. If A is a class, is_class_member is TRUE and +parent.class_type points to the type of A. If A is a namespace, +is_class_member is FALSE and parent.namespace_ptr points to the +namespace entry for A. The final identifier (xxx) is not looked up. +Instead, the information is preserved in the locator so that, if necessary, +xxx can be looked up by coalesce_and_lookup_qualified_name.

    +

    is_generalized_identifier_start coalesces template class references of the +form A::i, [5] A<T>, and A<T>::i (but not simply A) by +calling coalesce_template_id. These references must be coalesced to +determine whether the template reference is the beginning of a qualified name +(e.g., A<int, float>::i cannot be determined to be a qualified name until +the :: is seen.) The result of a template class reference is an incomplete +instantiation. A complete instantiation is only generated when it is required +for a name to be looked up. A complete instantiation will be generated for +references like A<T>::X::Y, because X must be looked up in A<T>. A +complete instantiation will not be generated (at least not here) for references +like A<T>::X. The complete instantiation is delayed until X needs to +be looked up (typically in coalesce_and_lookup_qualified_name.) A template +argument list may also follow a function template name or an overloaded +function name in which one of the members of the overload set is a function +template. This is known as “explicit specification of function template +arguments”. Unlike template class references, a template function reference +cannot be resolved to a given template instance when the template argument list +is scanned (because function templates can be overloaded). As a result, when a +function template argument list is scanned, a pointer to the list is retained +in the symbol locator, but the reference is not otherwise resolved at this +point.

    +

    The pointer operator used when declaring a pointer-to-member looks a lot like a +qualified name; the only difference is that the final identifier is replaced +with an asterisk (*). For example, a pointer-to-member operator may look +like A<int>::B::C::*. Because of this similarity pointer-to-member +operators are also coalesced by is_generalized_identifier_start even though +they are not considered identifiers. When a pointer-to-member operator is +coalesced the current token is set to tok_ptr_to_member, the +parent.class_type field of the locator points to the type specified in the +operator (e.g., A<int>::A::B::C in the previous example), and the return +value of the function is FALSE.

    +

    The operators ::new and ::delete look like qualified names but are +actually operators. When called for these operators, +is_generalized_identifier_start leaves the current token unchanged and +returns FALSE.

    +

    C++ allows a destructor to be called for classes that have no destructor and +for nonclass types. We refer to this kind of destructor call as a “vacuous +destructor” reference. A GID option is used to indicate whether a vacuous +destructor should be recognized and, if so, whether it must be a nonclass +destructor. Vacuous destructor references, which are only allowed in field +selection operations, differ from other generalized identifiers in several +important ways:

    +
      +
    • +
      the qualifier, if present, and the identifier that follows the tilde may be +a nonclass type.
      +
      +
    • +
    • +
      the nonclass type found may be a keyword that names a basic type (e.g., +int::~int).
      +
      +
    • +
    +

    When a vacuous destructor reference is coalesced, the parent.class_type +points to the type specified by the name after the ::~ because it must be +possible to record the type of the vacuous destructor reference for cases that +do not include a qualifier.

    +
    +
    +

    7.3.2. Coalesce-and-Look-Up Routines#

    +

    The coalesce-and-look-up routines are:

    +
      +
    • coalesce_and_lookup_qualified_name

    • +
    • coalesce_and_lookup_generalized_identifier

    • +
    +

    After is_generalized_identifier_start has determined that the current token +does in fact begin an identifier the coalesce-and-look-up routines are used to +do the appropriate kind of name lookup. The difference between the two +routines is that coalesce_and_lookup_qualified_name will only perform a +lookup of the final identifier of a qualified name while both qualified names +and names without qualifiers will be handled by +coalesce_and_lookup_generalized_identifier.

    +

    One of the arguments passed to these routines is an “identifier lookup mode”, +an enumeration that specifies the kind of lookup to be performed. The lookup +mode is translated into a set of “identifier lookup” (IDL) flags that are +passed to the symbol table lookup routines. An error is issued by +coalesce_and_lookup_qualified_name if the name lookup fails, except in +ilm_tentative_type mode. [6] In all other respects the various +identifier lookup modes are identical as far as the coalesce and lookup +routines are concerned. coalesce_and_lookup_generalized_identifier does +not issue an error if the lookup of an unqualified name fails.

    +
    +
    +

    7.3.3. Generalized Identifier Errors#

    +

    check_for_generalized_identifier_errors is called by the +coalesce-and-look-up routines and also by is_generalized_identifier_start +to ensure that the identifier that has been scanned meets the constraints +specified by the GID “allowed” flags. The error tests are done by comparing +the current GID options with the information in the locator. When one +generalized identifier routine calls another, it masks off the error flags so +that the errors are diagnosed only once by the highest-level routine.

    +

    check_for_template_declarator_errors is called by the coalesce-and-look-up +routines to verify that the declarator in a template declaration does actually +refer to a template entity that is permitted in a template declaration. These +checks are done to provide diagnostics that are more helpful than those that +would result if the identifier were simply returned to declarator.

    +
    +
    +

    7.3.4. Template References#

    +

    coalesce_template_id coalesces references to class and function templates. +The kind of reference to be coalesced is determined based on a symbol that is +provided. If the symbol refers to a function template or an overload set +containing one or more function templates, +coalesce_template_function_reference is called, otherwise +coalesce_template_class_reference is called to handle class template +references or to diagnose the improper use of a template argument list.

    +
    +

    7.3.4.1. Template Class References#

    +

    coalesce_template_class_reference coalesces template class references, such +as A<int, 1>, into identifiers for which the specific_symbol field of +the locator points to a specific instance of the template. A class template +name is usually, but not always, followed by a template argument list. The +argument list may be omitted in declarations of the class template,

    +
    template <class T> class A;
    +template <class T> class A { /* ... */ };
    +
    +
    +

    in which case the name refers to the class template (not to one of its +instances), and may also be omitted inside the definition of a class template +or in the definition of a member function or static data member of the class +template,

    +
    template <class T> class A {
    +  A*       a;    // Equivalent to A<T>*   a
    +  int A::* pma;  // Equivalent to A<T>::* pma
    +};
    +
    +
    +

    in which case the name refers to the current instance of the class template +(e.g., A<T>).

    +

    There are several contexts in which template class references must be +coalesced. Most calls of coalesce_template_class_reference are from +is_generalized_identifier_start and include a template argument list or are +part of a qualified name. coalesce_template_class_reference is also called +by coalesce_and_lookup_generalized_identifier, which scans simple class +template names such as A, and by scan_tag_name, which scans specific +definitions of a template classes such as class A<int> {}. Like the +generalized identifier routines, coalesce_template_class_reference accepts +a set of generalized identifier options as one of its arguments. The only +value actually used is GID_TEMPLATE_ARGS_OPTIONAL which specifies that the +template argument list may be omitted for a reference that is not within the +class template definition. As described above, the argument list may always be +omitted within the class template definition.

    +

    The template argument list, if present, is scanned by calling either +scan_template_argument_list or scan_unknown_template_arg_list:

    +
      +
    • +
      scan_unknown_template_arg_list is used when scanning the template +argument list associated with a “nonreal” template – a class template that +is a member of a proxy or nonreal class. A nonreal template is created in +contexts in which a member class template of a template parameter dependent +class is used. For example:
      +
      +
      template <class T> struct A {
      +  typename T::X<int> tx;
      +};
      +
      +
      +
      +
      In such cases, it is assumed that T::X is a template because there are +no cases in which a less than sign could immediately follow a type name, so +the “<” must indicate the beginning of a template argument list. When +scanning a nonreal template argument list there is no information available +about the number of template parameters, their types, etc. All of this +must be inferred by scanning the actual arguments. Consequently, no +attempt is made to determine whether the number of arguments, the types, +etc. are correct. The disambiguation routines are used to determine +whether a given argument is a type or nontype (see below for the use of +this function in scanning function template references.)
      +
      +
    • +
    • +
      scan_template_argument_list is used when scanning the template +arguments of “real” templates. Default values are provided for any omitted +arguments. If the type of a nontype parameter depends on another template +parameter, the type of the parameter is generated by rescanning a token +cache constructed when the template was defined. Similarly, if the type of +the default value, or the default value itself, involves a template +parameter, the default value is also generated by rescanning a token cache +constructed when the template was defined.
      +
      +
    • +
    +

    Both routines call scan_template_argument_constant_expression for nontype +arguments and type_name for type arguments. find_template_class is +called, once a complete template argument list has been created, to find the +type that corresponds to the particular set of arguments. If no such type +exists, find_template_class creates one. In either case the symbol +associated with the type is returned.

    +
    +
    +

    7.3.4.2. Function Template References#

    +

    coalesce_function_template_reference coalesces references to functions that +employ an explicit template argument list. Unlike class templates, function +templates may be overloaded; therefore an explicit template argument list does +not necessarily identify a specific template instance. The function type of +the instance is also needed to determine the actual instance that is being +referenced, but is not available when the template argument list is scanned, so +the argument list must be retained until some later point when the function +type is also available.

    +

    scan_unknown_template_arg_list is used to scan explicit template argument +lists because, in general, there is no template parameter list that can be used +to determine the kind of argument expected (type vs. nontype), or the type of +the argument (for nontype arguments). As with nonreal template argument lists, +the disambiguation routines are used to determine whether a given argument is a +type or nontype. type_name is used to scan arguments that are types. +scan_nontype_template_argument is used to scan nontype arguments. Function +template argument lists differ from those of class templates in that, for +function templates, the corresponding template parameter list is not available +when the template argument list is scanned. The presence of the template +parameter list for a class template makes it possible to convert nontype +arguments to the type of the corresponding template parameter (or to a special +nonreal type in the case of a nonreal argument list). For function templates, +such conversions cannot be done until the specific function template to be used +has been identified. Consequently, when a nontype argument is scanned it must +be retained in a form that permits the conversion to be done later. +scan_nontype_template_argument returns a pointer to an_arg_operand, a +data structure used by the expression scanning routines to represent an +expression. The constant_is_an_arg_operand field in the template argument +is set to indicate that the nontype argument is represented in this form.

    +
    +
    +

    7.3.4.3. Variable Template References#

    +

    coalesce_variable_template_reference coalesces references to variable +templates. scan_template_argument_list is used to scan the template +arguments. find_template_variable is used to produce a variable symbol for +the instantiation of the given variable template using the specified template +arguments.

    +
    +
    +
    +
    +

    7.4. Conversion of Literal Constants#

    +

    The source file literals.c contains the code to handle conversion of +literal constants to internal form. The external form is a string of +characters, a token, as accumulated by get_token and its subroutines; the +internal form is a structure of type a_constant, representing an integer, +fixed-point, float, character, or string constant.

    +

    conv_integer_literal converts decimal, octal, and hexadecimal integer +constants. Aside from computing the value of the constant, it also recognizes +the trailing L and U suffixes, and determines the type of the overall +constant (on the basis of its value and the suffixes). For pcc mode, the +rules for determining the type of a constant are modified slightly.

    +

    conv_fixed_point_literal converts fixed-point constants (an Embedded C +feature), calling fxp_string_to_fixed_point or +fxp_hex_string_to_fixed_point in fixed_pt.c to actually do the +conversion. It also recognizes the various suffixes (k, r, …), and +sets the type of the result accordingly.

    +

    conv_float_literal converts float constants, calling fp_string_to_float +or fp_hex_string_to_float_point in float_pt.c to actually do the +conversion. It also recognizes the L and F suffixes, and sets the type +of the result accordingly.

    +

    conv_char_literal converts character constants to an integer value. It +uses conv_single_char to fetch and convert each character. If there is +more than one character, they are assembled into one integer (with ordering +controlled by TARG_CHAR_CONSTANT_FIRST_CHAR_MOST_SIGNIFICANT).

    +

    conv_string_literal converts string literals. It receives a count of +effective characters in the string from its caller (as computed by +accum_quoted_string), so it can dynamically allocate the space for the +string before scanning it. It also uses conv_single_char to convert each +character of the string.

    +

    conv_single_char converts one character to an integer value. This includes +simple characters, escapes like \n, and octal and hexadecimal escapes. At +the moment, this routine assumes that the host and target character sets are +the same.

    +

    concat_string_literals concatenates several string literals (in constant +form in a token cache) into one string. This is used for the concatenation of +adjacent string literals.

    +
    +
    +

    7.5. Preprocessing Directives#

    +

    The source file preproc.c contains the code to handle preprocessing +directives (except for #define, which is handled in macro.c). +Associated declarations are in preproc.h.

    +

    The routine cpp_driver is the top-level routine when the front end is being +run as a C preprocessor, typically to produce a preprocessed output file. It +calls get_token repeatedly until end of source, with +do_preprocessing_only set to TRUE to indicate that preprocessing only – +and not compilation – is being done.

    +

    Normally, when preprocessing output is required, generate_pp_output is TRUE +as well. But cpp_driver is also called when preprocessing is being done to +generate a list of #include files or a list of makefile dependencies. +In those cases, generate_pp_output is FALSE, and either +list_included_files or list_makefile_dependencies is TRUE.

    +

    pp_directive is called (by get_token) when a # is encountered at +the beginning of a source line. It sets in_preprocessing_directive, +fetches the directive identifier and identifies it by calling +identify_dir_keyword (which uses a simple linear search), calls the +appropriate routine to process the directive (which may call +ignore_harmless_trailing_comment to ignore extra text at the end of the +directive), calls end_of_directive_processing (to check for any extra text +that is not harmless), and then resets in_preprocessing_directive. If a +syntax error is detected in a directive, some_error_in_curr_directive is +set; this suppresses the check for extra text at the end of the directive.

    +

    When the text of a preprocessing directive is not to be written to the +preprocessing output, do_not_put_curr_line_in_pp_output is set – initially +in pp_directive and on each subsequent line, because of multi-line +comments, in read_logical_source_line; the flag is checked by the output +routine, gen_pp_output_for_curr_line. In the rare case that the text of a +preprocessing directive should be passed to output (because some C compiler +should see the directive to handle it), pass_pp_directive_to_output is set +to TRUE while the directive is scanned.

    +

    Each preprocessing directive has an associated processing routine (for example, +proc_if handles the #if directive).

    +

    proc_pragma processes the #pragma directive. This is an area that +would be configured for specific versions. Unrecognized pragmas must be +ignored (no error should be generated). When preprocessing only, #pragma +directives are passed to output (see pass_directive_to_output).

    +

    proc_ident processes the #ident directive, although the “processing” it +does is to ignore it. When preprocessing only, #ident directives are +passed to output (see pass_directive_to_output).

    +

    proc_error passes the rest of the directive to an error reporting routine, +as a catastrophic error, which terminates the compilation.

    +

    proc_line scans a line number, treating it as a digit-sequence rather than +an integer constant; optionally, it also scans a file name, calling +copy_header_name to extract the file name from the header name token. It +puts this information into the input stack and calls routines in il.c to +remember the proper correspondence between source sequence numbers and file +name/line number pairs.

    +

    proc_include scans the file name (as a header name in one of two forms) and +then calls push_input_stack to request reading from that include file. It +calls copy_header_name to extract the file name from the header name token.

    +

    proc_undef scans an identifier, looks it up, and removes any macro +definition under that name. It will not remove predefined macros. (A +predefined macro has a source position with a sequence number of zero, and a +column number of SP_COL_PREDEFINED_MACRO.)

    +

    #if and related directives depend on the pp_if_stack, which is a stack +of entries describing active #if constructs. The current depth of the +stack is indicated by pp_if_stack_depth. Each #if that has not yet +been closed by a corresponding #endif appears on the stack. The stack +entry indicates whether or not the #else for the #if has already +appeared, and has the source position of the #if for use as the error +position if the corresponding #endif never appears. In ANSI C or C++ mode, +each #if is required to be ended in the file in which it was begun: to +implement this, the variable base_pp_if_stack_depth contains the value of +pp_if_stack_depth as of the beginning of the current source file. The part +of the stack between base_pp_if_stack_depth and pp_if_stack_depth is +considered the only active part of the stack at any given moment. #endifs encountered must be associated with #ifs in the active part of the +stack, and all of the #ifs in the active part of the stack must be closed +by the end of the source file (this is checked by +verify_that_all_pp_ifs_were_closed, which is called from +pop_input_stack). In pcc mode, the #ifs do not have to match up +within each file; they only have to come out right at the end of the +compilation.

    +

    The various if-directives are handled by proc_if, proc_ifdef (which +also handles #ifndef), proc_else, proc_elif, and proc_endif. +proc_if and proc_elif call scan_if_expr, which calls +scan_pp_expression (in expr.c) to scan the if-expression (there are +restrictions on what can appear in such an expression). All of the +if-processors call perform_if once they know whether or not the #if +should be executed; perform_if returns if the condition is TRUE, and calls +skip_to_endif if the condition is FALSE. The latter reads lines looking +for preprocessing directives, counts nesting of #ifs, and looks for an +#else or #endif that matches the current if.

    +

    A new preprocessing directive can be added by:

    +
      +
    • +
      Adding an enumeration constant to a_pp_directive_kind;
      +
      +
    • +
    • +
      adding a test for the directive keyword in identify_dir_keyword;
      +
      +
    • +
    • +
      adding a switch clause for the directive in pp_directive; and
      +
      +
    • +
    • +
      adding a routine proc_directive to process the directive. Note +that the routine must take all the tokens in the directive (up to the +tok_newline) before returning.
      +
      +
    • +
    +
    +

    7.5.1. AT&T Preprocessing Extensions#

    +

    When ATT_PREPROCESSING_EXTENSIONS_ALLOWED is defined some of the AT&T +System V release 4 extensions to the preprocessor are supported. In that case, +the #assert and #unassert directives are handled by proc_assert and +proc_unassert. The data structure built for assert predicates is a simple +one: assert_predicates points to a list of an_assert_predicate entries, +each of which gives a predicate name and a list of an_assert_value entries +giving the value or values for the predicate. Entry and lookup are done with a +simple linear search. The token sequences involved are processed into +character strings (containing the token characters with a blank after each +token, and ended with a null character). Such character strings then represent +the token sequences, and can be saved and compared. +scan_assert_predicate_reference is called from get_token on detection +of a # inside of an #if expression; it scans the reference and returns +1 or 0 depending on whether or not the predicate is defined with the indicated +token sequence. enter_assert_predicate can be called from fe_init.c to +enter predefined predicate names.

    +
    +
    +

    7.5.2. C++/CLI Assembly Import#

    +

    The front supports the C++/CLI #using directive to import the metadata of +an assembly. This is done in function proc_using. In C++/CLI mode, a +“core library assembly” (usually, mscorlib.dll) is imported before input +source is processed, as well as any assemblies specified with the +--preusing command-line option: Function process_preusings handles that +part (see also Declarations from C++/CLI Assembly Metadata and C++/CLI Initialization).

    +
    +
    +
    +

    7.6. Macro Processing#

    +

    macro.c contains the code to handle the #define preprocessing directive +and invocations of macros. macro.h contains associated declarations.

    +
    +

    7.6.1. Macro Definition Data Structure#

    +

    When a macro is defined, the symbol created for it points to an entry of type +a_macro_def (defined in symbol_tbl.h). The macro’s parameter list is +represented by a linked list of entries of type a_macro_param; these give +the names of the parameters (needed only to verify that, on a benign +redefinition of the macro, the parameter names are the same). The replacement +text of the macro is a sequence of sections, each of which indicates text that +should be placed in the macro expansion at that point. Each section begins +with a byte that identifies the kind of section, as follows:

    +
    + + + + + + + + + + + + + + + + + + +
    +
    rt_null (0)
    +
    +
    +
    marks the end of the replacement text.
    +
    +
    +
    rt_text
    +
    +
    +
    indicates raw text that is part of the macro replacement text. The +next three bytes contain the count of characters following.
    +
    +
    +
    rt_raw_argument
    +
    rt_right_raw_argument
    +
    +
    +
    indicate that the raw (non-macro-expanded) text of an argument is to +be inserted at this point. This results from use of the ## +operator, or from parameters scanned in pcc mode. The next three +bytes contain a number indicating the argument to be used (1 is the +first argument, 2 the second, etc.). rt_raw_argument is used for +a parameter to the left of ## and for all parameters in pcc mode, +and rt_right_raw_argument is used for a parameter to the right of +##.
    +
    +
    +
    rt_stringized_raw_argument
    +

    +
    +
    +
    indicates that the “stringized” text of an argument is to be inserted +at this point (this results from use of the # operator). The next +three bytes contain a number indicating the argument to be used.
    +
    +
    +
    rt_argument
    +
    +
    +
    indicates that the macro-expanded text of an argument is to be +inserted at this point. The next three bytes contain a number +indicating the argument to be used.
    +
    +
    +
    +

    The ## (paste) operator has no direct representation in the replacement +text; it just results in the two entities being placed next to each other. For +example,

    +
    #define x(a,b) a ## b
    +
    +
    +

    results in rt_raw_argument(1) followed by rt_right_raw_argument(2).

    +

    White space in the replacement text is standardized. Any white space preceding +or following the replacement text is removed, as is any white space preceding +or following a ##, and any white space following a #. All other white +space is replaced by a single space.

    +

    Each token in the raw text (except the last, and any token preceding a ##) +is followed by an LE_END_OF_TOKEN lexical escape sequence. The raw text +immediately following insertions of arguments (except immediately following a +##) also starts with an end-of-token marker, to terminate the last token of +the inserted argument text. The end-of-token markers ensure that the tokens +will be tokenized the same way each time. For example, one problem comes up in

    +
    #define z(a) ..##a
    +
    +
    +

    The value of z(.) should be three “.” tokens, not the one token +“...”. End-of-token markers are not used when in pcc mode, since cpp +does not operate on a token level.

    +

    Similar standardization of white space and insertion of end-of-token markers is +done when the raw form of macro arguments is accumulated. This standardization +(of replacement text and macro argument text) makes it easier to check for +benign redefinitions and to generate the stringized form of arguments.

    +
    +
    +

    7.6.2. The Macro Buffer#

    +

    The global variable macro_buffer points to a large character array used as +a work area during macro processing. During macro definition, it holds the +replacement text. During macro invocation, it holds the expansions of all +macro invocations in the current line. It is dynamically allocated, and can be +expanded as necessary by calling expand_macro_buffer. +expand_macro_buffer will, in turn, call +adjust_curr_source_line_structure_after_realloc to walk through the data +structure associated with curr_source_line and change pointers to +macro_buffer to reference addresses within the new allocation for +macro_buffer. adjust_curr_source_line_structure_after_realloc +automatically finds such pointers in global variables and the public data +structure, but it has no way of knowing about local pointer variables. +Therefore, routines that have such variables register them by calling +register_pointer_variable, so that they will be found and adjusted if +reallocation is done.

    +

    In order to reduce memory consumption when processing very complex and lengthy +macro expansions, the reallocation process for macro_buffer differs from +that of the other extensible buffers. While the other buffers are simply +reallocated, relying on the C runtime to copy the complete old contents to the +new allocation, expand_macro_buffer compacts the contents of +macro_buffer by explicitly allocating a new buffer, copying data to the new +allocation only if it might still be in use, and then freeing the old buffer. +First, each existing source line modification (see +Modifications to the Current Source Line) is processed to copy its inserted text. +Within that text, only the ATTENTION_MARKER is copied from each portion +that is marked for deletion by another source line modification. (The +ATTENTION_MARKERs must be copied in order to allow scanning for inert +macro names, as described in Macro Invocations.) As a result, the +original text of already-expanded macro invocations and the expanded text of +macro arguments will not occupy space in the new macro_buffer allocation.

    +

    Second, text that is in the process of being constructed at the end of the +macro_buffer is copied to the end of the data in the new allocation. Any +routines that build data structures incrementally, so that reallocation can +occur before the structure is complete (e.g., macro replacement text in +proc_define), must identify the beginning of such data using +begin_macro_buffer_region and its completion with +release_macro_buffer_region.

    +
    +
    +

    7.6.3. Macro Definitions#

    +

    Macro definitions (#define directive) are handled by proc_define. It +scans the macro identifier, and looks it up in the symbol table (predefined +macros may not be redefined, and normal macros may be redefined only if the new +parameters and text match the existing parameters and text – a “benign” +redefinition). If a “(” follows immediately (with no intervening white +space), the macro is function-like; its parameter names are accumulated as a +list. Otherwise, the macro is object-like. proc_define then scans the +replacement text and builds the replacement text string in macro_buffer. +It calls mdefn_get_token to fetch tokens of the body and remember whether +or not any white space preceded each. White space is standardized, +end-of-token markers are inserted (if in ANSI C or C++ mode), parameter names +are recognized, and # and ## are handled as described above.

    +

    If in pcc mode, the opening and closing quoting characters of character +constants and string literals are scanned as single-character tokens, and the +insides of the quoted strings are tokenized. This results in recognition (and +later replacement) of parameter names within strings, as cpp does it. +Invalid tokens are passed textually to the replacement text (this is necessary +always, not just for this case), and skipped white space is kept in its +original form, so the contents of the string will be accurately rendered in the +final expansion of the macro.

    +

    After the replacement text is accumulated, it is copied to +dynamically-allocated storage, and the macro definition is completed and +attached to the symbol. For a redefinition, the new parameter list and +replacement text are first compared textually against the old. If they match, +the new definition is thrown away.

    +
    +
    +

    7.6.4. Macro Invocations#

    +

    macro_invocation handles the scanning and replacement of macro invocations. +It is called by get_token when an identifier that is a macro name is +scanned.

    +

    The first thing that macro_invocation checks is whether or not the macro +name is “inert”. The standard says that when a macro’s name is generated in +its own expansion (directly or indirectly), it is forever after protected +against further expansion (it is inert). This is implemented by the +assoc_macro field in the a_source_line_modif entry. A macro invocation +is replaced by the macro’s expansion by creating a modification entry that +indicates the textual changes to be made to the source line or to a previous +modification. The assoc_macro field records the origin of any given +change, by pointing to the definition of the macro that generated the change. +Given a pointer to the name of a macro at the beginning of a possible macro +invocation, one can therefore determine whether it is in the main source line +or in a modification (or nested in several), and from that one can see whether +the macro name appears as part of its own expansion. If so, the macro name is +inert, and is left as an identifier. (Actually, it is replaced by an +LE_INERT_MACRO lexical escape followed by the macro name. Once a macro +name is preceded by an inert-macro escape, it is considered inert every time it +is scanned, regardless of the context.) In pcc mode, macros are not considered +to be inert, and recursion is checked for by counting the number of nested +invocations of a given macro.

    +

    If the macro name is not inert, processing for expansion continues. +delete_source_from_loc is set to point to the beginning of the macro +identifier. This begins a “hanging delete” which will be closed when the end +of the macro invocation is found. At that point, the text of the hanging +delete will be replaced by the macro expansion, this replacement being +indicated by a source line modification entry.

    +

    If the macro is object-like, no parameters need be scanned. However, there are +several special cases in object-like macros: For __FILE__ and __LINE__, +the proper expansion string is developed from the current position information +in the input stack; for defined, which is an operator allowed in #if +expressions but handled as a pseudo-macro, the routine +scan_defined_operator is called. It scans both forms of the defined +operator, and returns 0 or 1. Alternatively, if the identifier +defined is not followed by appropriate tokens, it is left as an identifier +(see the discussion of check_for_following_parenthesis below).

    +

    If the macro is function-like, check_for_following_parenthesis is called to +scan forward looking for a parenthesis that begins the argument list. If the +next token is not a parenthesis, then the macro name is left as an identifier. +However, this is complicated, because in skipping white space while looking for +a left parenthesis, we may have gone onto a new source line. We have to delete +the identifier before leaving the old source line, on the assumption that we +are scanning a macro invocation. If it turns out that the identifier is not +the start of a macro invocation, the identifier must be reinserted into the new +source line.

    +

    Note the field sequence_id in a_source_line_modif; it is an integer +sequence number indicating the sequence in which source line modifications were +added. This is useful in cases where modifications must be undone (as in +identifier un-deletion when a macro identifier is followed by something other +than a left parenthesis on the same line); one can find all entries with +sequence numbers greater than a certain number, and remove them.

    +

    If a left parenthesis is found, the argument list is scanned, and this +requires a new data structure. An entry of type a_macro_arg contains +the text of a single argument value. That text exists in two forms – as +“raw” text (not macro-expanded), and as “expanded” text. The +a_macro_arg entries are dynamically allocated, and freed when no longer +needed (see alloc_macro_arg, free_macro_arg, and the variable +avail_macro_args). The text of macro arguments is not kept in +macro_buffer.

    +

    Each macro argument is initially scanned in raw form. arg_get_token is +called, with macro expansion turned off, and the characters of each token, with +standardized white space and end-of-token markers, are placed in the array +pointed to by raw_text in the a_macro_arg entry (a +dynamically-allocated array, which can be reallocated as needed to expand it). +The scan stops when a comma or right parenthesis is found. A variable is used +to count the nesting of parentheses, so that non-zero-level commas and right +parentheses will not stop the scan.

    +

    After the raw form of the argument has been accumulated, the raw text is +temporarily re-inserted in the source line and is re-scanned with macro +expansion on. The standard says that this must be done as if this text forms +the rest of the source file (i.e., the macro expansion is done in isolation +from the text following the raw argument value). This is implemented by having +the source modification entry that re-inserts the raw text have the field +is_isolated_text TRUE. This will cause get_token and +skip_white_space, upon reaching the LE_END_OF_INSERTION lexical escape +sequence at the end of the raw text, to return tok_end_of_source instead of +continuing into the surrounding text. macro_invocation scans the entire +raw argument again, saving the text of the tokens scanned in the +expanded_text array in the macro argument entry, and stopping when it gets +tok_end_of_source. If any modifications of the raw text were done because +of macro expansions (this can be determined by sequence id), they are removed. +This restores the raw text to its original state. In pcc mode, and when the +definition of the macro does not use the parameter in a context that requires +expansion,only the raw form of each argument is needed, so the rescan is not +done.

    +

    In cases where the macro argument is the result of a previous macro expansion, +the rescan begins in the text inserted by the macro expansion modifications +rather than in the raw_text buffer. That ensures that the inertness test +can be done properly on macro names encountered in the rescanned source. Once +the rescan reaches the end of the insertions and would continue into the +primary source line, the input stream is switched to the tail of the +raw_text buffer. (raw_text is used instead of the primary source line +because macro arguments can be continued to subsequent source lines, and once +the next line is read the only copy of the raw argument text is in the +raw_text array; the previous source line is gone.)

    +

    This process is repeated for each argument. After all arguments are scanned +(or immediately for object-like macros), expansion is done. The length of the +expansion is first determined, and then the textual change is made, by building +up text in macro_buffer and placing a source line modification to delete +the characters of the macro invocation and insert the characters of the +expansion.

    +

    For the special cases of predefined macros, the replacement text is already +available as a simple null-terminated string. For these cases, determining the +length and building the replacement string are easily done.

    +

    For the other, more normal, cases, the length is determined and the expansion +string is built up by interpreting the sections of the replacement text in +order. For unexpanded uses of parameters, the raw_text is copied. For +macro-expanded uses of parameters, the expanded_text is copied. For +stringized parameters, stringized_arg is called; it copies the +raw_text, inserting the surrounding quotes and the additional backslashes +to protect quotes and backslashes in the string.

    +

    The source line modification is then inserted to perform the macro expansion.

    +

    When, in pcc mode, the expansion is for a top-level macro, +expand_top_level_pcc_macro is called to expand any macro calls within the +body of the macro. A complete string for the expanded version is constructed +in an auxiliary buffer (aux_buffer_for_pcc_macros) and then copied back +into macro_buffer, replacing the original expansion and any source line +modifications associated with it. Getting a fully-expanded string is necessary +to get pcc-like token pasting behavior across internal macro expansion +boundaries. A variant of this processing is also done in Microsoft mode.

    +

    macro_invocation then returns. It indicates to get_token whether or +not the inserted text should be rescanned. If macro_invocation already +knows what the next token should be, it returns it directly (*rescan = +FALSE), thus saving get_token the time and trouble of scanning the token +text again.

    +

    A utility debug routine print_markered_text is available for use in +printing out text strings that contain end-of-token markers and/or transitions +into or out of source modifications.

    +
    +
    +

    7.6.5. Macro Position Tracking#

    +

    When FULLY_RESOLVED_MACRO_POSITIONS is TRUE, the front end keeps track of +the original location of text that is copied into macro expansions – i.e., +either in a #define line or in an argument to a top-level macro invocation. +This “original position” information is reflected in the orig_seq and +orig_column fields of a_source_position.

    +

    The principal data structure used in tracking original position information +through the various manipulations performed during macro definition and +invocation is a_macro_text_map, which defines an extensible array of +a_macro_text_map_entry elements (both defined in lexical.h). Each of +the repositories of text associated with macro definition and invocation – +macro definitions, the raw and expanded forms of macro arguments, and source +line modifications – has an associated macro text map.

    +

    A macro text map provides an ordered sequence of correspondences between +offsets in the associated text buffer and the original source locations from +which that text was copied. Each map entry defines a region of the associated +text buffer, beginning at offset start_of_region and extending up to but +not including the start_of_region of the next entry. The text at offset +start_of_region originally came from the location given by +corresponding_source_pos, with a one-to-one correspondence of increasing +offsets and source column positions throughout the entry’s buffer region. +Because the entries are ordered by buffer offset, the original source position +for a given offset can be efficiently found using a binary search (the +requisite bsearch predicate is +compare_macro_text_map_entry_with_offset, defined in lexical.c).

    +

    It will be helpful to trace the overall flow of information through the +definition and invocation of a macro before covering the details of how it is +accomplished. When a #define is processed, proc_define builds a text +map by incrementally recording the source position and offset in the +replacement text for each token of the definition that will be copied to the +macro expansion. A similar process occurs as each macro argument is copied to +the corresponding raw and expanded text buffers. During the interpretation of +the replacement text by macro_invocation, as each section of text is copied +from the replacement text or macro argument, the corresponding entries from the +associated macro text map are copied, adjusting the offsets to reflect the +location of the text in the macro expansion (but leaving the original source +positions). Finally, when conv_line_loc_to_source_pos is called to compute +a source position for a given character location in the expanded text, the +macro text map in the source line modification is used to determine the +corresponding original source position.

    +

    There are two principal patterns for adding entries to a text map. The simpler +pattern is when a sequence of map entries is copied from one map to another, +adjusting the offsets from being relative to the start of the source buffer to +being relative to the start of the target buffer. This technique is used to +create the text map for the source line modification containing the macro +expansion by copying portions of the text maps for the macro definition +replacement text and macro arguments. The function that performs this +operation is clone_macro_text_map_entries, defined in macro.c.

    +

    The other pattern occurs when a text buffer is built incrementally by fetching +one token at a time and adding its text to a buffer. In this case, the map +entries are built to reflect either the source position of the token, if the +token is in source text, or a copy of the corresponding text map entry, if the +token comes from a source line modification (e.g., a macro argument in a macro +invocation appearing in the expansion of another macro invocation). This +technique is used to create the replacement text in a macro definition and for +both the raw and expanded text of macro arguments. It is also used when +processing a top-level macro invocation in pcc and Microsoft modes.

    +

    Facilitating this process are the struct a_text_map_position_tracker and +the functions init_text_map_position_tracker, +add_token_to_macro_text_map, and terminate_macro_text_map (all defined +in macro.c). As each token is added to the text buffer, +add_token_to_macro_text_map is called to determine whether a new entry is +required in the map for the new token: if the token is from the same source +line or source line modification as the preceding token and its offset within +the current buffer region is the same as the column offset from the region’s +corresponding source position, then no new map entry is needed. If a new map +entry is required, either the appropriate map entries from the previous token’s +source line modification are copied, using clone_macro_text_map_entries, or +(for tokens from the current source line) a new entry is added covering the +appropriate region of the current source line for the preceding token(s).

    +

    One complication in this processing occurs when macro_buffer is +reallocated, as described earlier. Because a_text_map_position_tracker +objects in use at the time macro_buffer is reallocated might contain the +offset of text in a source line modification’s inserted text that occurs after +a portion of deleted text, and because that deleted text might be compacted as +part of the reallocation process, it is necessary to keep track of all active +position tracker objects so their current offset values can be adjusted if +necessary.

    +

    This is done using the variable active_text_map_position_trackers (in +macro.c), which is the top of a stack of all trackers currently in use, and +the field num_active_position_trackers in a_source_line_modif. +Whenever a token scan under control of a text map position tracker enters the +inserted text of a source line modification, its +num_active_position_trackers is incremented, and it is decremented when the +scan leaves that source line modification.

    +

    Whenever macro_buffer is reallocated, all the entries in each source line +modification’s text map are examined and each offset adjusted, if necessary, to +compensate for the removal of deleted text. Furthermore, if the modification’s +num_active_position_trackers field is greater than zero, all the trackers +in the active_text_map_position_trackers stack are checked for references +to that source line modification and their offsets adjusted as needed.

    +

    The text maps for macro definitions and the raw and expanded text of macro +arguments are completely self-contained: each has its own array of text map +entries and is associated with the containing data structure for the duration +of the compilation. (The array of entries for a macro definition is of fixed +size and is allocated in front-end memory, so that it will be stored in a +precompiled header, while the arrays for macro arguments are extensible.) A +different scheme is used for the text maps in source line modifications, +however. The reason for this decision is that the text map for a source line +modification may well be very large, with thousands or tens of thousands of +entries, while source line modifications themselves are ephemeral, generally no +longer needed once processing of the current logical source line has been +completed. The same reasoning led to the use of macro_buffer for the +inserted text of source line modification, so the memory management for source +line modification text maps is patterned after that of macro_buffer. Just +as each modification’s inserted text is simply a subrange of the text in +macro_buffer, the entries created during macro expansion are built in a +single map, called macro_text_map and defined in macro.c, and each +modification’s text map simply refers to a subrange of them. Initialization +and truncation of macro_text_map is done in parallel with the corresponding +operations on macro_buffer.

    +
    +
    +

    7.6.6. Macro Invocation Tree#

    +

    Maintaining the macro invocation tree is selected by setting +MACRO_INVOCATION_TREE_IN_IL to TRUE. Each macro invocation is recorded in +an object of type a_macro_invocation_record (defined in il_def.h), +giving the parent invocation, if any; the macro invoked; and its starting +position (as well as its ending position, if EXTRA_SOURCE_POSITIONS_IN_IL +is set to TRUE). (The “parent invocation” refers to the macro invocation in +whose argument list or expansion this macro invocation occurred. For macro +invocations occurring in program text and not in a macro argument list, +parent_macro_index will have the value NO_PARENT_MACRO_INVOCATION.)

    +

    Each time macro_invocation is called to expand a macro, it calls +register_macro_invocation to add an entry to the list and obtain the index +of the newly-added entry. This index and the macro invocation stack depth at +that point are stored into the source line modification created to hold the +macro’s expanded text. These values are used by recursive calls of +macro_invocation (to expand macro arguments) and by calls resulting from +rescanning expanded text to maintain the chain of parent invocations when the +macro name comes from a source line modification rather than directly from +source text.

    +

    Because variable-length data is awkward to represent in the IL (and extensible +arrays are not possible in memory regions), the macro invocation records are +grouped into fixed-size blocks (a_macro_invocation_record_block, defined in +il_def.h). In the IL, these blocks are organized into a binary tree to +facilitate relatively-efficient random access by index. During front-end +processing, however, they are kept in a doubly-linked list: apart from +diagnostic output, which need not be terribly efficient, there is no need for +random access to the invocation records (and even diagnostic output will most +often refer to records near the end of the list, so long linear searches are +uncommon). It is more efficient to create the binary tree form once, after the +total number of records is known, than to balance the tree repeatedly while it +is being created.

    +

    The macro_invocation_record_blocks are reorganized into a binary tree and +the relevant fields of il_header are set at the end of the translation unit +by a call to copy_macro_invocation_tree_to_il (defined in macro.c).

    +

    An additional effect of setting MACRO_INVOCATION_TREE_IN_IL is that +a_source_position is extended to include the macro_context field. This +field reflects the macro invocation in whose expansion the source position +resides, i.e., it is logically simply a copy of the invocation_record field +of the containing source line modification. However, the special treatment +given to top-level macros in pcc and Microsoft mode, in which the expansion of +the macro is rescanned for expansion and the result is copied back into the +source line modification corresponding to the top-level macro invocation, means +that the subsidiary source line modifications are no longer available at the +time source positions are being computed.

    +

    To avoid this problem, the macro invocation index that will be stored by +macro_invocation into source line modifications is also kept in the +macro_context field of each text map entry created for that invocation. +This information is preserved when the text maps for the subsidiary source line +modifications are cloned into the top-level modification by +expand_top_level_pcc_macro. This additional information allows the +macro_context field in source positions to be set in the same way as the +original position information, by looking up the offset in the text map of the +top-level modification. (This is the reason that it is not permitted to set +MACRO_INVOCATION_TREE_IN_IL to TRUE without also setting +FULLY_RESOLVED_MACRO_POSITIONS to TRUE.)

    +
    +
    +
    +

    7.7. Unicode Version-Dependent Features#

    +

    The front end has three distinct features that depend on the definitions +and classifications of characters in the Unicode standard and thus might +need to be updated when new versions of Unicode are released. The following +subsections discuss each of these features and what is involved in a potential +update.

    +
    +

    7.7.1. Classification of Identifier Characters#

    +

    The front end must, of course, determine whether a given character can +appear in a C/C++ identifier in order to find the start and end of +identifier tokens during lexical analysis. There is also a distinction +between characters that can begin an identifier and those that can appear +only after the initial character; for example, '0' cannot be the first +character of an identifier but it is valid in the succeeding positions.

    +

    For single-byte character sets, this classification is done using boolean +arrays indexed by the character value; see the declarations of +is_id_char, is_id_char_no_mbc, and char_ends_id in +lexical.h and their initialization in lexical_one_time_init in +lexical.c for details.

    +

    The situation is more complicated for multi-byte characters, whether +appearing directly in the source or via a universal-character-name. For +C++23 (and, because the relevant paper was adopted as a defect report, for +previous versions as well) and C23, the determination is based on the +Unicode XID_Start and XID_Continue Derived Properties as specified +in www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt. +(Specific versions of this file can be found by replacing UCD/latest +with the version number, e.g., 15.1.0, in the URL.) Earlier versions of +the C and C++ standards used different methods to specify these +classifications, however, and the front end continues to support those +variants for backward compatibility.

    +

    The mechanism for achieving compatibility with multiple classification +schemes is the UCN_table array, defined in lexical.c. The elements +of the array are objects of the following struct:

    +
    typedef struct a_UCN_range {
    +  unsigned long start;  /* The first character in the range. */
    +  unsigned long end;    /* The last character in the range. */
    +  a_byte        dialects;
    +                        /* A bit set indicating the dialects for which this
    +                           range of characters is accepted.  See below for
    +                           the encoding masks. */
    +  a_byte        non_initial_dialects;
    +                        /* A bit set indicating the dialects for which this
    +                           range of characters is not permitted as the
    +                           first character of an identifier.  This uses the
    +                           same encoding as dialects. */
    +} a_UCN_range;
    +
    +
    +

    Characters tend to occur in groups, so to reduce the storage requirements +of the array, each element describes a contiguous range of characters, all +of which share the same treatment in all of the supported classification +schemes. The elements of the array are sorted in strictly-ascending order +of code point so that the array can be efficiently searched using a binary +search. The dialects and non_initial_dialects members are bit sets +with each bit representing a different language dialect, specifying how the +characters in the specified range are classified in the various +dialects. The C++23/C23 dialect is represented by the UAX44 bit (so +named because the XID_Start and XID_Continue properties are +described in Unicode Annex #44).

    +

    From the perspective of updating this table when new versions of Unicode +are published, the principal requirement of this table is that all members +of a given character range must be classified the same way in all of the +supported dialects. A change in the classification of a character in a new +Unicode version thus typically means that an existing range in the table +must be split, so that any characters before and/or after the character of +interest can maintain their previous values while that character’s +UAX44 bits reflect the new Unicode classification (maintaining the +previous values for all the other flags). As a specific example, the +DerivedCoreProperties.txt file for Unicode version 15.1.0 contained +(among others) the following changes from version 15.0.0:

    +
    +2EBF0..2EE5D  ; XID_Start # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
    +. . .
    ++2EBF0..2EE5D  ; XID_Continue # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
    +
    +
    +

    These changes indicate that the characters in the indicated range can now +appear both within identifiers and as the first character of an +identifier. These code points were previously contained within the range of +the following element of the UCN_table array:

    +
    { 0x2ebe1, 0x2f7ff,   _   |  _  | CPP11 |   _  ,   _   |   _   |   _   },
    +
    +
    +

    As a result, the range needed to be split in order to preserve the +classification of the characters before and after the new 15.1.0 range, +resulting in the following three elements to replace the existing one:

    +
    { 0x2ebe1, 0x2ebef,   _   |  _  | CPP11 |   _  ,   _   |   _   |   _   },
    +{ 0x2ebf0, 0x2ee5d,   _   |  _  | CPP11 | UAX44,   _   |   _   |   _   },
    +{ 0x2ee5e, 0x2f7ff,   _   |  _  | CPP11 |   _  ,   _   |   _   |   _   },
    +
    +
    +

    Note both the addition of the UAX44 flag in the initializer for +dialects and its absence in the initializer for +non_initial_dialects, since the latter specifies dialects for which the +characters are not permitted to start an identifier.

    +
    +
    +

    7.7.2. Detection of Source Code Unicode Vulnerabilities#

    +

    One potential avenue of source-level exploits relies on the fact that a +number of distinct Unicode characters have similar or identical glyphs. For +example, the Latin, Greek, and Cyrillic alphabets each have a character +whose visual appearance is “A”, even though the code points for those +characters are different. This permits the creation of programs with +vulnerabilities that cannot be detected by even a careful code review (by +hijacking overloaded function calls, for example).

    +

    Unicode provides a table, +www.unicode.org/Public/security/latest/confusables.txt, that +enumerates such potentially-confused characters (replace “latest” with the +version number to access the specification for a specific version). This +table is described in +www.unicode.org/reports/tr39/.

    +

    The front end incorporates this data as the array confusable_map, +defined in lexical.h, which is a lightly-massaged version of the +contents of confusables.txt. Each element of the array is an object of +the following struct:

    +
    struct a_confusable_map_elem {
    +  int src_char;         /* The numeric value of a Unicode code point whose
    +                           glyph could be confused with that of another
    +                           code point. */
    +  int prototype[MAX_PROTOTYPE_LENGTH];
    +                        /* The numeric values of the Unicode code points of
    +                           the prototype character(s) for src_char, as
    +                           defined in unicode.org/reports/tr39, "Unicode
    +                           Security Mechanisms", section 4. */
    +};  /* a_confusable_map_elem */
    +
    +
    +

    The elements are in strictly-ascending order of src_char, to facilitate +efficient searching using a binary search.

    +

    Although the entries in confusables.txt are not in the same order as +the elements of confusable_map, that does not present a significant +issue for updating the front end for new Unicode versions, as the mapping +from the Unicode data to the corresponding array initializer is +obvious. For example, a representative line of the version 15.1.0 file is:

    +
    2238 ;        002D 0307 ;     MA      #* ( ∸ → -̇ ) DOT MINUS → HYPHEN-MINUS, COMBINING DOT ABOVE     #
    +
    +
    +

    and the corresponding initializer element is:

    +
    { 0x02238, { 0x002D, 0x0307 } },
    +
    +
    +

    Thus, a simple diff of two versions of the confusables.txt file +provides sufficient information for any required updates.

    +

    Such updates are expected to be infrequent, in any event, as the base data +is not likely to change very much over time. If desired, the +edg-make-confusables-data script can be used with a given version of +confusables.txt to create the entire initializer for +confusable_map.

    +
    +
    +

    7.7.3. Named Unicode Escapes#

    +

    C++23 introduced the capability of incorporating a given Unicode character +into the source text by specifying its full name, using the syntax \N{character-name}. This feature requires the front end to be able to +distinguish valid character-names from invalid ones and to determine the +code point associated with each valid name.

    +

    Because Unicode defines tens of thousands of characters, with the average +name being over thirty characters in length, this task is necessarily +data-intensive. A naive straightforward approach, e.g., a sorted array of +character names and code points searched using a binary search, would +require around 1.5 megabytes of data and up to sixteen probes to match a +given character name, so it would be fairly inefficient in both data and +execution time.

    +

    The approach chosen for the front end implementation of this feature uses a +fairly straightforward finite state machine (FSM), with each state +representing the initial substring of characters in one or more character +names and each transition designating the state that would result for a +specific character following that initial substring in a valid Unicode +character name. There are a few simple optimizations to reduce the size of +the data containing the FSM; sequences of single-transition states are +compressed into a single state that matches a sequence of characters and +has a single transition on the final one, and the algorithmically-named +ranges for CJK and Tangut ideographs are also condensed into single states +matching the common prefix and specifying their respective ranges of code +points. Incorporating these optimizations, the storage required for the +state machine for the names in Unicode 15.1.0 is about 510 kilobytes, much +less than the naive implementation, and its performance is also much +better.

    +

    The data for the Unicode character names and code points comes from two +files: www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt and +www.unicode.org/Public/UCD/latest/ucd/NameAliases.txt. (The +files for specific versions can be found by substituting the version +number, e.g., 15.1.0, for UCD/latest in the URLs.)

    +

    The data for the state machine in the front end is contained in the array +unicode_name_fsm, defined in the file unicode_name_fsm.c. Because +this table cannot be edited by hand, there is a utility that produces that +file in its entirety, with no manual editing required. To run the utility, +download the two files above from the unicode.org web site and issue +the following command:

    +
    +

    process_unicode_names UnicodeData.txt NameAliases.txt output-file version date

    +
    +

    where output-file is any file name (it must be copied to +unicode_name_fsm.c if that file is not updated in situ); version is +the Unicode version number (e.g., 15.1.0); and date is the release +date of the Unicode version (e.g., 2023-08-28). (The latter two +command-line arguments are incorporated into the comments in the generated +source file.)

    +

    The source for the utility is found in the +dev_tools/cpp_tools/process_unicode_names subdirectory. Any changes +desired in the contents of unicode_name_fsm.c (such as updating the +copyright date) should be edited into the utility source in the +initializer for the header_text variable, since any manual edits in +unicode_name_fsm.c will be overwritten by the next run of the utility.

    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/lower_il/index.html b/dev/doc/lower_il/index.html new file mode 100644 index 0000000..d1febac --- /dev/null +++ b/dev/doc/lower_il/index.html @@ -0,0 +1,4531 @@ + + + + + 5. IL Lowering - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    5. IL Lowering#

    +

    When we started developing the C++ front end, one of the first design decisions +we had to make was what intermediate language it would generate.

    +

    We already had a C front end (supporting the C89 version of the language) and a +Fortran front end. The C front end generated an intermediate language that +looked a lot like C, and the Fortran front end generated an intermediate +language that looked a lot like Fortran. The two intermediate languages were +compatible in the sense that they had the same structure and could be combined +into an intermediate language that is the union of the two.

    +

    It seemed clear that the C++ intermediate language ought to be compatible with +the other two languages in that same sense, and that in fact it should be a +superset of the C intermediate language, since C++ is (almost) a superset of +C89. (When we talk about the C intermediate language or “C IL”, we generally +refer to the IL to represent C89 constructs, not to the extensions supporting +the current C99 standard and other dialects like GNU C.)

    +

    But how much of a superset? Since our IL philosophy for Fortran and C had been +to make “high-level” ILs that were very close to the source language, our +initial inclination was to make an intermediate language with lots of new C++ +features that would be the same sort of thing for C++. It seemed like the +obvious approach. When we analyzed that idea, and discussed it with customers, +however, we realized a few things:

    +
      +
    • +
      There’s a big semantic jump from C to C++. Some of the C++ features are +much more complicated than C or Fortran features. Implementing them in a +back end would add a lot of work, and requires a lot of knowledge of the +C++ language.
      +
      Since our corporate mission is to deliver front ends that take care of +all of the language issues and the attendant grief so that back ends +can just worry about code generation (and its attendant grief), it +didn’t seem that we would be doing our full job by generating the +high-level C++ IL.
      +
      +
    • +
    • +
      We had customers that had existing C back ends and were interested in +adding C++ with minimum development cost.
      +
      +
    • +
    +

    Okay then, what about generating an IL that’s very close to the C IL? After +all, because of USL’s cfront, people view C++ as a language that can be +translated into C, maybe even as a macro language on top of C. Well, there are +problems with that, too:

    +
      +
    • +
      It hides information that is useful in generating symbolic debugging +information. (This has historically been a weakness of cfront-based +compilers, forcing programmers to debug using the generated C code.)
      +
      +
    • +
    • +
      It makes it harder for a back end to use unconventional or aggressive code +generation techniques for C++ constructs.
      +
      +
    • +
    • +
      It makes the front end less suitable for use in source-analysis tools (they +want to analyze the C++ source, not some version of it translated into C).
      +
      +
    • +
    +

    We considered various levels of intermediate language between the full C++ and +full C extremes, and all were unsatisfactory in some way. Then David Callahan +of Tera Computer suggested that we do it both ways, that we generate a full C++ +IL and also supply a piece of software that translates that IL into the +existing C IL.

    +

    Thus was born IL lowering. The front end proper generates a true C++ IL, and +IL lowering translates that IL into C IL, which can then be fed into a C back +end or the C-generating back end we use for testing. It should be noted that +although “lowering” is what’s done, the output is still “high-level” – it’s +not as high-level as it was, but it’s still at the level of the intermediate +language for C89.

    +

    The IL lowering pass is optional. It need not be used if it’s not wanted. The +IL utilities work with both versions of the IL.

    +

    Since many C++ features go into IL lowering as abstractions and come out as C +code, IL lowering is actually choosing implementations of those features. The +implementations are at the same level as those in cfront. That is, they are +relatively “standard” implementations. As one would expect, the generated C +has some of the same complex unreadable quality that cfront output has, and the +same ridiculously complex expressions. The front end can even be configured to +produce constructs that are object-code compatible with cfront’s. +Alternatively, the front end can generate code compatible with the IA-64 +(Itanium) ABI.

    +

    IL lowering can also do inlining, though we firmly believe that that is +something that only a back end can really do properly. [1]

    +

    The IL lowering pass seems to solve the problems raised:

    +
      +
    • +
      Both the C++ and C forms are available for those who prefer one form or the +other. In fact, one can use both forms, e.g., one could generate symbolic +debugging information from the C++ form and object code from the C form.
      +
      +
    • +
    • +
      It allows customers to get a C++ compiler going in minimal time.
      +
      +
    • +
    • +
      If the features implemented by IL lowering require some minor changes, the +changes can be made in IL lowering, which is relatively small, rather than +in the front end as a whole, which is quite large.
      +
      +
    • +
    • +
      If a customer wants to attach a back end to the unlowered IL (either +initially or for an improved release of a compiler), the IL lowering code +serves as a guide to the tasks that must be done.
      +
      +
    • +
    +

    Even though IL lowering will rewrite uses of non-C89 features, the C++-specific +fields of the IL are still present in the IL entries. Back ends should not +count on those fields being cleared; rather, they should ignore them and +consider only the fields that C uses. Viewed that way, the lowered IL should +contain nothing that would not show up in a C intermediate language tree.

    +

    One catch: Dynamic initialization of entities in the middle of blocks is left +in its original form. This is not “incorrect” C IL, but is something that does +not come up in C89 programs. It was judged that back ends would be capable of +dealing with the stmk_init statements even if they appear after other +executable statements in a block, and the alternative was to make lowering of +initialization of aggregates to constants quite messy.

    +

    The code for IL lowering is in lower_il.c, and the associated declarations +are in lower_il.h. Name mangling code is in lower_name.c and +lower_name.h. Code for lowering initializations, new/delete, and +constructors/destructors is in lower_init.c and lower_init.h. Code for +lowering exception handling features is in lower_eh.c and lower_eh.h.

    +

    Certain higher-level constructs – like variable-length arrays and complex +floating-point types – from more recent C dialects (primarily C99, but also +GNU C) can also be lowered to C89-level IL. The code for this is done +primarily in lower_c99.c. See Lowering C Dialects for an overview +of the constructs in this category that can be lowered.

    +

    Finally, IL lowering can also ensure that boolean controlling expressions +(e.g., the expression controlling which way an if-statement goes) always +produce an integer value 0 or 1 (as opposed to “zero or nonzero” or “null or +nonnull”). This normalization – enabled by setting +LOWERING_NORMALIZES_BOOLEAN_CONTROLLING_EXPRESSIONS to TRUE – can occur in +all modes (C++, C89, etc.) and usually involves adding a “!= 0” comparison +to the controlling expression.

    +
    +

    5.1. ABI support#

    +

    The front end and IL lowering support two ABIs (Application Binary Interfaces). +An ABI is a set of conventions for the runtime environment, which prescribes +class layout, access to virtual functions, name mangling, etc. Code generated +by two compilers that are compatible with a given ABI should, in theory, be +able to interact properly, and with libraries that are compatible with that +ABI.

    +

    Up through version 3.0, the front end supported a single ABI and some minor +variants thereof. This ABI, referred to as the “cfront-like ABI,” is an +extended version of the original ABI used by cfront. The extensions were +invented by EDG, and therefore the ABI does not conform to any industry +standard, other than in its general compatibility with what was once a de +facto standard. The variants of the cfront-like ABI are:

    +
      +
    • +
      cfront 3.0.1 compatibility, selected by setting +CFRONT_3_0_OBJECT_CODE_COMPATIBILITY to TRUE.
      +
      +
    • +
    • +
      cfront 2.1 compatibility, selected by setting +CFRONT_2_1_OBJECT_CODE_COMPATIBILITY to TRUE.
      +
      +
    • +
    • +
      If neither of those variants is selected, the default ABI is cfront-like +with some minor quirks eliminated, principally with respect to allocation +of space for virtual base classes. This variant was originally intended as +the default and best ABI, but in practice it hasn’t been used very much, +and the IA-64 ABI (see below) is a better choice.
      +
      +
    • +
    +

    As of version 3.1, the front end also supports the IA-64 ABI, described by +https://itanium-cxx-abi.github.io/cxx-abi/abi.html. This is a modern ABI +originally designed for the Intel IA-64 (“Itanium”) architecture, but now an +industry standard widely used on other architectures as well. In particular, +the GNU g++ compiler uses the IA-64 ABI on many platforms. This ABI is +selected by setting IA64_ABI to TRUE. Note that the fully-lowered +implementation of exception handling provided by EDG works with the IA-64 ABI, +but does not conform to the spec, and that versions using the C-generating back +end do not fully conform because of some layout cases not easily represented in +C.

    +

    Note that the IA-64 ABI requires linker support in the form of a feature (often +called COMDAT) that allows different object files to contain (identical) +definitions of certain functions and variables. The linker discards the +duplicates, ending up with a single definition.

    +

    The ABI support in the front end changes from time to time as features are +added and bugs are fixed. The macro ABI_COMPATIBILITY_VERSION can be set +to a version number of the front end to keep the ABI frozen as it was at that +version. Source language features that require ABI changes made after that +version are disabled.

    +
    +
    +

    5.2. What Does C++ IL Lowering Do?#

    +

    IL lowering is called at the end of processing of each “top-level” scope (i.e., +once at the end of each top-level function, and once at the end of the file +scope). It rewrites any C++ IL constructs in the scope as semantically +equivalent C IL constructs. (A similar process occurs for C99 IL; see +Lowering C Dialects for details.)

    +

    IL Lowering is suppressed if there are errors in the source program, if the +dialect of C language being compiled doesn’t require it, if preprocessing only +is being done, or if syntax-checking only is being done.

    +
    +

    5.2.1. Name Mangling#

    +

    (Code for name mangling is in lower_name.c and lower_name.h.)

    +

    “Name mangling” means transforming the names of C++ entities so that the names +include information on aspects of the entity’s type and fully qualified name. +This is made necessary by the fact that the object code and C environments into +which a C++ program is translated typically contain fewer and simpler name +spaces than there are in the C++ language. Specifically:

    +
      +
    • +
      Overloaded function names are not allowed in C, and probably not in object +code.
      +
      +
    • +
    • +
      Classes have their own scopes in C++, but not in the generated C form. An +entity x from inside a class must not conflict with an entity x +from the file scope, for example.
      +
      +
    • +
    • +
      External names in C and (probably) in the object code form a completely +flat name space. The names of C++ entities with external linkage must be +projected onto that name space so that they do not conflict with one +another. A function f from a class A, for example, must not have +the same external name as a function f from class B.
      +
      +
    • +
    • +
      Some C++ “names” are not names in the conventional sense of the word +(they’re not strings of alphanumeric characters), e.g., operator=.
      +
      +
    • +
    +

    We can see that there are three problems here:

    +
      +
    • +
      Generating C code names that will not clash for non-external entities. +This is only a problem when generating C code.
      +
      +
    • +
    • +
      Generating external names that will not clash. This is a problem whether +the output is C or object code.
      +
      +
    • +
    • +
      Generating alphanumeric names for entities with strange “names” in C++. +This is a problem whether the output is C or object code, at least for +external names.
      +
      +
    • +
    +

    As it happens, the name mangling process solves all three problems. It also +solves the problem of generating hidden names for some behind-the-scenes +language support in such a way that they will match up across separate +compilations (e.g., virtual function table names).

    +

    Once name mangling has been done, the name linkage of C++ external entities is +changed to C external.

    +
    +

    5.2.1.1. Cfront-like ABI name mangling#

    +

    The cfront-like ABI name mangling algorithm is the same as the one used by +cfront, and also matches the description in 7.2.1c of the ARM (except for some +minor details). The reader is referred there for a complete description. +Here, we just hit the highlights and the things that differ from or are +extensions to that description.

    +

    Each type has a corresponding mangled encoding. For example, a class type +is represented as the class name preceded by the number of characters in +the class name, as in 5abcde for abcde. Simple types are encoded +as lower-case letters, as in i for int or f for float. +long long, wchar_t, and bool, which do not appear in the ARM, +are encoded as “L”, “w”, and “b”, respectively. The C++11 +types char16_t and char32_t are encoded as “g” and “k”, +respectively. A std::nullptr_t type is encoded as “n”, while the +C++/CLI __nullptr is encoded as “j”. (In some Microsoft modes, +there are distinct integral types named __int8, __int16, +__int32 and __int64. They are encoded as “m1”, “m2”, +“m4”, and “m8”, respectively.) 128-bit integers (in GNU +compatibility mode) are mangled with “m16” and “Um16” (signed and +unsigned, respectively). Type modifiers and declarators are encoded as +upper-case letters preceding the types they modify, as in U for +unsigned or P for pointer. In GNU C++ mode, complex types are encoded +with an “x” preceding the code for the corresponding real +floating-point type (e.g., “xf” for “_Complex float”). The long +double type is indicated by an “r” encoding. In addition to the type +declarators mentioned in the ARM (i.e., “P” for pointer, “R” for +reference, “A” for array, “F” for function, and “M” for +member), an “E” encoding has been added to indicate an rvalue +reference. For ref-qualified member function types, an optional “_R” +(for an lvalue req-qualifier) or “_E” (for an rvalue ref-qualifier) can +follow the “F” that indicates a function type. When C++/CLI is +enabled, the “Ht” encoding is used for tracking references, “Hh” is +used for handles, “Hi” is used for interior_ptr, and “Hp” is +used for pin_ptr. __underlying_type (enabled when type trait +helpers are enabled) is mangled as “o”. See +mangled_encoding_for_type.

    +

    Types specified using the C++11 keyword decltype are encoded in one of +three ways. When a decltype expression is either type-dependent or +value-dependent (i.e., it has some component that could be affected by the +C++11 SFINAE rules), it is said to be instantiation-dependent and it is +encoded using the character “y” or “Y” followed by a mangled +encoding of the expression (”y” is used when the expression is an +unparenthesized id-expression or a class member access; “Y” is used +otherwise). decltype expressions that are not instantiation-dependent +are encoded using the known underlying type or value (e.g., +decltype(sizeof(int)) is mangled using the mangled encoding for the +size_t type, i.e., “Ui” in a front end that is configured to use +unsigned int to represent size_t). In a manner similar to +decltype, typeof(type) is mangled using the encoding “t” +and typeof(expression) is mangled using the encoding “p”. The +“u” mangled encoding is also introduced in C++11 to represent the use +of auto as a type specifier when it appears in a new-expression that +is mangled because it appears in the context of an instantiation-dependent +expression (e.g., decltype(new auto(p1))). The letter “n” is used +to encode the type for nullptr (i.e., std::nullptr_t). The “q” +mangled encoding is used for the decltype(auto) notation.

    +

    When a function parameter is a C++11 function parameter pack, its type is +represented by the encoding “Dp” followed by the function parameter type.

    +

    Nested class types are encoded as a “Q” followed by a digit indicating the +depth of nesting, followed by a “_”, followed by the mangled-form names of +the class types in the fully-qualified name of the class, from outermost to +innermost:

    +
    class A {
    +  class B {  // Q2_1A1B
    +  };
    +};
    +
    +
    +

    The name of the nested class itself is mangled to the form described above with +a prefix __, which serves to make the class name distinct from all user +names. The same mangling technique is used for namespaces. In cases where the +mangled entity is specified in the source code as being in the global scope +(e.g., p->::X::y), and the entity is a selection or call operand, the +global scope indication is specified using the letter “G” as the first +qualifier in a qualified name; for example:

    +
    int g(int);
    +template <class T> auto f(T p1) -> decltype(::g(p1));
    +                                   // f__tm__2_i__FZ1Z_YOcl_2_4g__GI1IO
    +
    +
    +

    Local class names and scoped enumerators are encoded by following the name by +“__L” followed by a number (which has no special meaning; it uniquely +identifies the type within the function scope). This example (which requires +–c++11) shows a local class and its mangling within a function template:

    +
    template <typename T> void f(T) {}
    +void x() {
    +  struct A {} a;  // __12A__L1__x__Fv
    +  f(a);           // f__tm__15_12A__L1__x__Fv__FZ1Z_v
    +}
    +
    +
    +

    This form is used when encoding the local class name as a type. It’s not +actually necessary to mangle the name of the local class itself unless it’s +also a nested class. See mangled_type_name_full. This is not in the ARM, +and cfront does it slightly differently.

    +

    The “__L” indicator is also used in the names of entities promoted out of +functions. There, the “__L” appears between the name of the entity and the +mangled name of the function:

    +
    void *f() {
    +  struct A {};           // __12A__L1__f__Fv
    +  static struct A a;     // a__L0__f__Fv
    +  return &a;
    +}
    +
    +
    +

    The instance number (after the “__L”) serves to ensure that the mangled +name is unique (and is chosen so as to make it repeatable across translation +units in cases where the ODR requires it). Note that in configurations where +local types cannot be used in template arguments (i.e., other than –c++11 or +when microsoft_mode >= 1400) and therefore can’t appear in external names, the +mangled names may differ slightly from those listed above.

    +

    Unnamed namespace names are mangled as __N followed by a unique string. +The unique string is the “module id” generated by IL lowering from the source +file name and some other information, but from the perspective of name mangling +it is simply ignored. Such names appear only in contexts where their length is +given, so it’s easy to know how much to ignore.

    +

    Template classes have mangled names that encode the arguments of the template:

    +
    template<class T1, class T2> class abc {};
    +abc<int, int> x;
    +abc__tm__3_ii
    +           ^^--- Two template arguments of type int.
    +         ^------ Total length of template argument list string, including
    +                   the underscore.
    +     ^^--------- Fixed string, indicates "template".
    +^^^------------- The name of the class template.
    +
    +
    +

    When distinct mangling for templates is disabled, “tm” is replaced by +“pt” (which is what cfront uses).

    +

    The encoding for nontype template arguments encodes both the parameter type and +the actual argument value:

    +
    template<int I> class def {};
    +def<5> x;
    +def__tm__7_XCiL15
    +                ^-- Literal constant representation.
    +               ^--- Length of literal constant.
    +              ^---- "L" indicates literal constant, "c" indicates address
    +                       of variable, etc.
    +            ^^----- Type of template argument, with "const" added.
    +           ^------- "X" indicates beginning of constant argument.
    +
    +
    +

    Template argument packs are introduced by “__pk__”:

    +
    +
    template <class T, class ...U> int f();
    +int x = f<short, int, double>();
    +f__tm__12_s__pk__3_id__Fv_i <-- encoding for "f<short, int, double>()"
    +                          ^---- Return type (int).
    +                        ^------ Argument list (void).
    +                       ^------- Function.
    +                    ^---------- Second argument of the pack (double).
    +                   ^----------- First argument of the pack (int).
    +                 ^------------- Total length of template argument pack.
    +             ^^---------------- Beginning of a template argument pack.
    +          ^-------------------- First template argument type (short).
    +       ^^---------------------- Total length of template argument list.
    +   ^^-------------------------- Introduces template arguments.
    +^------------------------------ The name of the function template.
    +
    +
    +
    +

    Constants are encoded with the letter “C” followed by the type of the +constant and the encoding of the constant value (e.g., “CiL_2_59” +represents the integer constant 59). There are several different encodings +for different kinds of constants:

    +
      +
    • +
      Integer:
      +
      +
      L3n12  <-- encoding for "-12"
      +   ^^----- Literal value.
      +  ^------- "n" indicates negative.
      + ^-------- Length of the literal.
      +^--------- "L" indicates a number.
      +
      +
      +
      +
      This is compatible with cfront 3.0.1.
      +

      +
      The length of the literal uses an encoding compatible with cfront, i.e., +it’s either a single digit or two digits followed by an underscore (e.g., +“L10_1234567890”). This encoding has some ambiguity problems when the +template argument is followed by an underscore. Such cases did not come up +in the cfront world, but they do come up when template arguments are +applied to template functions (see paragraphs on distinct mangling for +templates, below). To deal with this, a new unambiguous mangling for +literal lengths has been introduced as of version 2.32. It has the length +enclosed in underscores in all cases (single- or multi-digit), e.g., +“L_1_2”. This form is used in the new contexts that didn’t come up for +cfront, and the old form continues to be used in the cfront contexts.
      +
      +
    • +
    • +
      Float:
      +
      +
      L4n1p5 <-- encoding for "-1.5"
      +   ^^^---- Literal value ("p" for decimal point).
      +  ^------- "n" indicates negative.
      + ^-------- Length of the literal.
      +^--------- "L" indicates a number.
      +
      +
      +
      +
      cfront 3.0.1 does not implement this, so we made it up. In actuality, the +literal form of the floating constant depends on the fp_to_string +routine, so the encoding is likely to be longer (for example, it’s likely +to include an exponent).
      +
      +
    • +
    • +
      Complex floating point literals are mangled like floating point literals +above except that both real and imaginary components are included:
      +
      +
      L_3_0d0_3_1d1 <-- encoding for "0.0+1.0i"
      +          ^^^---- Imaginary portion of complex number.
      +       ^^^------- Length of the imaginary portion of the number.
      +    ^^^---------- Real portion of complex number.
      + ^^^------------- Length of the real portion of the complex number.
      +^---------------- "L" indicates a number.
      +
      +
      +
    • +
    • +
      Address of variable or routine:
      +
      +
      4abcd <-- encoding for address of "abcd"
      + ^^^^---- Name of entity.
      +^-------- Length of the name.
      +
      +
      +
      +
      This is compatible with cfront 3.0.1.
      +
      +
    • +
    • +
      For pointers to data members, the offset value encoded as an integer:
      +
      +
      L212  <--- encoding for an offset of "12"
      +  ^^------ Literal value.
      + ^-------- Length of the literal.
      +^--------- "L" indicates a number.
      +
      +
      +
      +
      This is compatible with cfront 3.0.1.
      +
      +
    • +
    • +
      For pointers to member functions, the __mptr triplet of values (delta, +index, function or offset), encoded as follows:
      +
      +
      LM0_L2n1_1j
      +         ^^- Function name, or alternatively "0" if the pointer
      +               to member uses an offset (e.g., LM0_L11_0).
      +    ^^^^---- Index value, encoded as an integer.
      +  ^--------- Delta value.
      +^^---------- "LM" indicates a pointer to member function.
      +
      +
      +
      +
      This is compatible with cfront 3.0.1. Note that “0” is always used +for the offset, not the actual offset value. This follows cfront. The +idea seems to be that “0” is really a way of saying “there is no +function;” the offset value itself would not be of interest to a name +demangler.
      +
      +
    • +
    • +
      For strings, the type of the string is encoded. The character “S” +is used to indicate a string literal. The string L"xyz" is encoded +as “CA4_CwLS” (i.e., a string literal of type const wchar_t[4]).
      +
      +
    • +
    • +
      nullptr is encoded using the encoding for integers given above; the +type is always “n” (for std::nullptr_t), and the value is +always zero, so the entire mangled encoding for nullptr is always +“CnL_1_0”.
      +
      +
    • +
    +

    The fact that there are rules for mangling type names seems to suggest that +names of types are mangled. Strictly speaking, except for nested class names, +they are not. It is really only the names of variables and routines that need +to be mangled. The mangled form of type names does have a use, however: it is +used when building the mangled names of variables and routines, to represent +the types referenced by the entity (e.g., parameter types).

    +

    Unnamed (class/struct/union, enums, lambda closure) types are given a generated +name during mangling; that name is then used as described above (e.g., in +mangled names of variables and routines). The names generated for these +unnamed types are constructed so as to ensure that types subject to ODR +constraints across translation units are given the same name; other types are +given names guaranteed not to collide with similar constructs in other +translation units.

    +

    Unnamed class/struct/union and enums are given the name “__Ut” followed by +an instance number (within the namespace/class/function scope) which makes the +generated name unique within that scope. A mangled encoding of the type will +include its parent’s encoding as well.

    +

    Lambda closure types are a special kind of unnamed class type, and they are +mangled with a similar “__Ul” encoding that additionally gives information +about the lambda’s parameter types:

    +
    +
    __Ul1_Fif <-- [](int, float)->float {return 0.0;}(i, f);
    +      ^^^---- Lambda operator() function type (int, float).
    +    ^-------- Instance (within parent scope).
    +^^^^--------- "__Ul" indicates lambda.
    +
    +
    +
    +

    Lambdas defined in certain contexts, specifically some default arguments and +member initializers, are subject to ODR constraints and therefore must get +names that can be generated identically in different compilations. That’s +accomplished by making the default argument or member initializer a +“pseudo-parent scope” and encoding the closure type as a member of that +pseudo-scope.

    +

    Lambdas defined in default arguments (and subject to ODR constraints) are given +a name based on this encoding:

    +
    +
    __Ud1_2_Fv__L0__f__FiT1 <-- void f(int i=[]{return 0;}(),int k=0)
    +          ^^^^^^^^^^^^^---- Local to function f(int,int).
    +        ^^----------------- Lambda operator() function type.
    +      ^-------------------- Declared in trailing parameter 2.
    +    ^---------------------- Instance 1 (within parameter).
    +^^^^----------------------- "__Ud" indicates lambda in default arg.
    +
    +
    +
    +

    Lambdas in member initializers are given a name that is prefixed with +“__Um”:

    +
    +
    __Q3_10S__tm__2_i1x8__Um1_Fv < template <class T> int S<T>::x =
    +                                                       []{return 1;}();
    +                          ^^-- Lambda operator() function type.
    +                        ^----- Instance (within member initializer).
    +                    ^^^^------ "__Um" indicates lambda in initializer.
    +                   ^---------- Length of type name that follows.
    +^^^^^^^^^^^^^^^^^^^----------- Nested encoding for S<int>::x::.
    +
    +
    +
    +

    The following kinds of entity names (only) are mangled:

    +
      +
    • +
      Function names. Even non-member function names are mangled, to deal with +overloading. Names of functions with extern "C" linkage are not +mangled. See mangle_function_name.
      +
      Mangled function names have the function name followed by “__” followed +by “F” followed by the mangled description of the types of the +parameters of the function. If the function is a member function, the +mangled form of the class name precedes the “F”. If the member +function is static, an “S” also precedes the “F”. In cases where +the function has extern "C" linkage on the function type, a “K” +modifier immediately follows the “F” indication.
      +
      +
      int f(float);                   // f__Ff
      +class A {
      +  int f(float);                 // f__1AFf
      +  static int g(float);          // g__1ASFf
      +};
      +
      +
      +
      +
      Members of namespaces are mangled like member functions.
      +
      For the Microsoft extension that allows explicit specification of a virtual +function to be overridden, name mangling adds the class of the overridden +virtual function as O followed by the class type encoding, after the +class name. So, for example, a member D::f that explicitly overrides +B::f would be encoded as f__1DO1BFv.
      +
      +
    • +
    • +
      Special and operator function names, like constructors and operator=(). +The encoding is similar to that for normal functions, but a coded name is +used instead of the routine name:
      +
      +
      class A {
      +  int operator+(float);         // __pl__1AFf
      +  A(float);                     // __ct__1AFf
      +};
      +int operator+(A, float);        // __pl__F1Af
      +
      +
      +
      +
      The ARM contains a full list of the name encodings. Static constructors, +used in C++/CLI, are encoded with “__st__”; finalizers are encoded with +“__df__”. See mangled_operator_name.
      +
      +
    • +
    • +
      Static data member names. The mangled form is the member name followed by +“__” followed by the mangled form of the class name:
      +
      +
      class A {
      +  static int i;                 // i__1A
      +};
      +
      +
      +
      +
      This type of mangling is also used for variables that are members of +namespaces. Generally speaking, the names of variables at the file scope +don’t need to be mangled, but that’s not true for variable templates, or +for variables that may have implicit or explicit abi_tags. See +mangle_variable_name.
      +
      +
    • +
    • +
      Functions that are instances or specializations of templates. These +are mangled to include the template signature. This is controlled by +the variable distinct_template_signatures. Template parameters +(both type and nontype) are mangled as “ZnZ” or “Zn_mZ”, where n is the template parameter position +number (first is 1) and m is the template parameter depth (top level +is 1, which is assumed in the case where it is not specified). The +return type of the function is also included in the mangled name. +“__S” can appear either directly after the template name, to +indicate that the template is specialized, or after the template +argument list, to indicate that the instance is specialized.
      +
      +
      template <class T> struct A {
      +  template <class T2> void f(T2);
      +};
      +template <> template <class T2> void A<char>::f(T2) {}
      +template <> template<> void A<float>::f(int) {}
      +A<int> ai;
      +A<char> ac;
      +A<float> af;
      +int main(){
      +  ai.f(1); // f__tm__2_i__10A__tm__2_iFZ1_2Z_v
      +  ac.f(1); // f__S__tm__2_i__10A__tm__2_cFZ1_2Z_v
      +  af.f(1); // f__tm__2_i__S__10A__tm__2_fFZ1_2Z_v
      +}
      +
      +
      +
      +

      +
      The specialization indications are also placed in the names of parent +classes of functions and static data members generated from templates. A +“__S” following directly after the class itself indicates that the +class is specialized (and similarly for a class template), and a “__S” +after the template argument list of a class template indicates that the +instance is specialized.
      +
      +
      template <class T> struct A {
      +  void f();
      +  struct B {
      +    void bf(T);
      +  };
      +};
      +template <> struct A<short> {
      +  void f();
      +};
      +template <> struct A<int>::B {
      +  void bf(int);
      +};
      +A<short> as;
      +A<int>::B aib;
      +main () {
      +  as.f();         // f__13A__tm__2_s__SFv
      +  aib.bf(1);      // bf__Q2_10A__tm__2_i4B__SFi
      +}
      +
      +
      +
      +
      When a partial specialization of a class template appears, the mangled name +has two template argument lists. The first (which begins with +“__ps__”) gives the template arguments that appear on the declaration +of the partial specialization, and the second gives the arguments according +to the template parameters of the partial specialization.
      +
      +
      template <class T, class U> struct A {};
      +template <class T> struct A<T *, int> {
      +  void f();  // f__23A__ps__6_PZ1Zi__tm__2_iFv_v
      +             //      A  <T *, int>   <int>
      +};
      +
      +
      +
      +
      Where expressions appear in template signatures, they are mangled as in the +following example:
      +
      +
      Opl_2_Z1ZZ2ZO <-- "Z1 + Z2", Z1/Z2 indicating nontype template
      +                  parameters.
      +            ^---- "O" to end the operation encoding.
      +         ^^^----- Second operand.
      +      ^^^-------- First operand.
      +   ^^^----------- Count of operands (with bracketing underscores).
      + ^^-------------- Operation, using same encoding as for operator
      +                  function names.
      +^---------------- "O" for operation.
      +
      +
      +
      +
      The two or three letter operation encodings (e.g., “pl” in the example +above) are the same as the operator function encodings specified in the ARM +(without the leading double underscores).
      +
      The operands can be template parameters, constants (using the encoding +described for nontype template arguments, not including the initial +“X”), subexpressions (using the expression operation encoding described +above), mangled names (e.g., of variables or routines), or (in decltype +expressions) function parameter references.
      +

      +
      In addition to those operations specified in the ARM, the following +operation encodings have been added as EDG extensions:
      +
      +
      "ds" = .*
      +"dt" = .
      +"ps" = unary plus
      +"ng" = unary minus
      +"de" = * (indirection)
      +"ao" = & (address of)
      +"ppe" = prefix increment (pp indicates postfix increment)
      +"mme" = prefix decrement (mm indicates postfix decrement)
      +"tw" = throw
      +"rl" = __real
      +"im" = __imag
      +"mn" = GNU min operator (<?)
      +"mx" = GNU max operator (>?)
      +"sp" = ... (pack expansion)
      +"ht" = % (C++/CLI unary "%" operator which returns a handle)
      +"sb" = [] (C++/CLI array subscript -- has variable number of operands)
      +"gc" = gcnew (C++/CLI gcnew -- optional list of dimension expressions
      +       precedes a type operand)
      +"cp" = () (call operation with ADL suppressed -- has variable number of
      +       operands)
      +"il" = {} (brace-enclosed initializer list -- has variable number of
      +       initializers)
      +"tl" = T{} (cast of a brace-enclosed initializer list -- has a type
      +       followed by a variable number of initializers)
      +"nx" = noexcept
      +"li" = literal operator (for user-defined literals -- has zero or one
      +       operand and is followed immediately by a count and the ud-suffix
      +       for the literal operator, e.g., operator "" _miles would be
      +       "li6_miles")
      +
      +
      +
      +
      The following added operations differ from the standard operation encoding +in that they include an initial type before a single operand. The “cs” +encoding is used to encode both the old-style cast (where there is one +non-type operand) as well as the functional-notation cast (where there can +be zero or more non-type operands). The case where a functional-notation +cast is used with one argument is indistinguishable from the old-style cast +case:
      +
      +
      "sc" = static_cast
      +"dc" = dynamic_cast
      +"rc" = reinterpret_cast
      +"cc" = const_cast
      +"cs" = old-style (one argument) or functional-notation cast
      +"sf" = C++/CLI safe_cast
      +
      +
      +
      +
      The following operation differs in that it takes a single type argument:
      +
      +
      "ct" = C++/CLI ::typeid
      +
      +
      +
      +
      The following operations differ in that their source can specify either a +type or an expression:
      +
      +
      "sz" = sizeof
      +"af" = __ALIGNOF__
      +"uu" = __uuidof
      +"ty" = typeid
      +"sk" = sizeof...
      +
      +
      +
      +
      The mangled encodings for these cases are:
      +
      +
      OszZ1Z0O <-- "sizeof(Z1)", Z1 indicating a template parameter.
      +       ^---- "O" to end the operation encoding.
      +      ^----- Count of operands, 0 for type and "e" cases, 1 for "X".
      +   ^^^------ Encoding for type or "e" or "X" (for expression cases).
      + ^^--------- Operation ("sz" for sizeof, "af" for __ALIGNOF__,
      +             "uu" for __uuidof, or "ty" for typeid)
      +^----------- "O" for operation.
      +
      +
      +
      +
      There are three cases. When the operation takes a type, then the type +is encoded after the operation encoding and there are no operands. +Prior to version 4.2, an expression was indicated with an “e” in +place of the type (but no expression was contained in the mangled name +and the operand count was still zero). In version 4.2 and later, the +mangled expression is included (operand count is 1), and the type is +replaced with an “X” to indicate that an expression follows. | | The +new and delete operations (as well as new[] and +delete[]) are encoded thusly:
      +
      +
         v--------------vvvvvvvvvv----- These are optional.
      +Onwg_1_CiL_2_10Z1Z_1_CiL_1_0O <-- encoding for "::new (10) T (0)"
      +                            ^---- "O" to end the encoding.
      +                     ^^^^^^^----- Initializers (if any).  An optional
      +                                  "bi" indicates the use of a
      +                                  brace-enclosed initializer list.
      +                  ^^^------------ Optional initializer count (zero
      +                                  or more).  Omitted (along with
      +                                  initializers) if none were
      +                                  specified.
      +               ^^^--------------- Type of new operation.
      +       ^^^^^^^^------------------ Placement arguments (if any).
      +    ^^^-------------------------- Placement argument count (zero
      +                                  or more).
      +   ^----------------------------- "g" indicates global new.
      + ^^------------------------------ new operation (nw, nwa).
      +^-------------------------------- "O" for operation.
      +
      +   v----------- This is optional.
      +Odlg_1_I1IO <-- encoding for "::delete p1"
      +          ^---- "O" to end the operation encoding.
      +       ^^^----- Argument to delete.
      +    ^^^-------- Argument count (always one for delete).
      +   ^----------- "g" indicates global delete.
      + ^^------------ delete operation (dl, dla).
      +^-------------- "O" for operation.
      +
      +
      +
      +
      Builtin operations (i.e., vendor-specific extensions like Microsoft +__is_base_of) use the operation “bi”, and any operands that are +types are prefixed by “T”. The encoding “__dn” was added to +represent a destructor name (and is followed by a single type name). +See mangled_encoding_for_expression for details on the mangling of +expressions. | | Where arrays with sizes based on template parameters +appear, they are mangled as “A_mangled-expression_element-type” (the underscore following the “A” differentiates +this case from the usual known-size array case). | | A template +template parameter that is followed by a template argument list, e.g., +ttparam<x,y,x> in source code, is represented by the Z...Z +encoding, with the template argument list encoding inserted before the +closing Z, as in Z1__tm__4_Z2ZZ. | | References to function +parameters in decltype expressions (e.g., p in template +<class T> auto f(T p) -> decltype(p)) are mangled as such:
      +
      +
       v-vv----- These are optional.
      +IC1_2I <-- "const param#1 two levels up"
      +     ^---- Terminating non-digit character so parameter number won't run
      +           into an entity with an initial length.
      +   ^^----- Number of "levels up" for this parameter (0-based).  Omitted
      +           if zero.
      +  ^------- Parameter number (1-based) or 0 for "this".
      + ^-------- Optional cv-qualifiers.
      +^--------- "I" indicates parameter reference.
      +
      +
      +
    • +
    • +
      The implicit or explicit use of this in a mangled name is also +represented with the function parameter mangling given above (where the +parameter number is set to zero).
      +
      +
    • +
    • +
      Names of variables generated for virtual function tables. These have names +like
      +
      +
      +

      __vtbl__mangled-class-name

      +
      +
      +
      or
      +
      +
      +

      __vtbl__mangled-base-class-name__mangled-class-name

      +
      +
      +
      In the case of a virtual function table used during construction or +destruction of a subobject, there can be an additional mangled class name +on the end. See make_var_for_virtual_function_table.
      +
      +
    • +
    • +
      Names of variables generated to contain runtime type information. These +have names like
      +
      +
      +

      __T_type-encoding

      +
      +
      +
      and
      +
      +
      +

      __TID_type-encoding

      +
      +
      +
      See mangled_typeinfo_name and mangled_id_object_name.
      +
      +
    • +
    • +
      Names of wrapper routines generated to deal with covariant virtual function +return types. These are pointed to from virtual function tables and have +names of the form
      +
      +
      +

      __VFE__overridden-class__overriding-function

      +
      +
      +
      See mangle_wrapper_name.
      +
      +
    • +
    • +
      Names of static variables and functions made external, e.g., because they +are referenced from an instantiation and each instantiation is placed in a +separate object file. The form of the mangled names is
      +
      +
      +
      +
      __STV__variable-name__module-id
      +
      __STF__mangled-function-name__module-id
      +
      +
      +
      +
      where module-id is a unique name generated for the current compilation.
      +
      +
    • +
    • +
      The GNU ifunc attribute, when lowered, creates a variable through which +calls to the function are dispatched. The variable uses the __IFV__ +prefix:
      +
      +
      +

      __IFV__variable-name

      +
      +
    • +
    • +
      When GNU function multiversioning is used, a set of routines with the same +unmangled name are given unique mangled names based on their use. The +following prefixes are used to create these names:
      +
      +
      +
      + + + + + + + + + + + + +
      +
      __RES__mangled-function_name
      +
      +
      +
      resolver function
      +
      +
      +
      __IFC__mangled-function-name
      +
      +
      +
      ifunc function
      +
      +
      +
      __TGT__targets__identifier
      +
      +
      +
      target-specific function
      +
      +
      +
      +
      +
    • +
    • +
      For classes and function names with the GNU abi_tag attribute, the +“__ab” prefix is used (once for each string literal that is specified +in the abi_tag attribute list):
      +
      +
      +

      __ab<count><tag>

      +
      +
      +
      where <count> represents the number of characters in the <tag> string +literal.
      +
      +
    • +
    • +
      Structured binding container variables (at namespace scope) are given +mangled names based on the binding variable(s) they refer to. The +“__SBC__” prefix is used to identify this mangling. Each of the +binding variables, in order, are included in the container’s mangled name, +separated by “__”. A final “__” indicates the end of the +structured binding container mangled name. For example, +__SBC__x__y______1N indicates a structured binding container for +[x,y] in namespace N.
      +
      +
    • +
    +

    Once a mangled name has been generated, a compression step examines it to see +whether it can be shortened by compression. The compression approach is +simple-minded: the sequence “JnnnJ” means “repeat the sequence +beginning at offset nnn in the mangled name.” The offset is 0-origined. Only +sequences that begin with a length (e.g., 7ABCDEFG) are eligible to be +repeated in this way. Each “J” in the original mangled name is replaced by +“JJ” to avoid ambiguities. If compression is done, the mangled name is +given a prefix of “__CPRnnnn__”, where nnnn is the length of +the uncompressed form of the name.

    +
    +
    +

    5.2.1.2. IA-64 ABI name mangling#

    +

    In the IA-64 ABI, name mangling is done according to the ABI spec +(https://itanium-cxx-abi.github.io/cxx-abi/abi.html). We will not repeat that +description here.

    +

    There is no compression per se in the IA-64 ABI name mangling scheme. +Instead, entities that have appeared earlier in a mangled name can be +referenced again by way of a “substitution,” which is essentially the encoding +“S” followed by a number (base 36) indicating which of the preceding +entities is repeated. Entities of certain kinds (types, qualified name +prefixes, templates) are assigned numbers in their order of appearance in the +mangled name, and a later substitution can refer to such an entity by number. +Certain types and templates in the standard iostream header are assigned +predefined substitution codes so that they can be referenced cheaply. For the +implementation of substitutions, see add_substitution_if_available and +alloc_substitution. Note that one consequence of substitutions is that it +is impossible to reuse mangled names for entities as part of a larger mangled +name including that entity, because the substitution numbering in the reused +piece would be wrong for the overall mangled name.

    +

    Mangled names for entities local to a function are distinguished by a trailing +“discriminator,” a number that serves to distinguish like-named entities within +one function. Such entities are assigned discriminator numbers in the front +end, in strict order of appearance in the function. For example, the first +variable “i” in a function is assigned discriminator number zero, the next +one, etc. regardless of block scope nesting. These discriminator values are +recorded in the symbol table (rather than the IL) and IL lowering retrieves +them and includes them in mangled names.

    +

    Similarly, string literals within (certain) functions are numbered so that +mangled names can be generated for them. The C++ standard requires that if an +extern inline function is implemented by multiple copies, a string literal +that appears in the function has the same address in all copies. This is +implemented by assigning a sequence number to each string in functions that +might exist in multiple copies. Name mangling then uses that number to +generate a mangled name for the variable created to hold the string value.

    +

    For entities “externalized,” i.e., static variables or functions made external +because they must be referenced from multiple compilations (e.g., for exported +templates, or in one-instantiation-per-object mode), name mangling uses an +extension to the ABI spec. This is an encoding of the form

    +
    +

    B length module_id

    +
    +

    where module_id is a generated string describing the current compilation, +formed from the source file name and some other bits that help make it unique. +This encoding is used as a prefix on the <name> syntax term and is used to make +a local name unique when it is externalized.

    +

    For the Microsoft extension that allows explicit specification of a virtual +function to be overridden, name mangling adds the name of the overridden +virtual function as the encoding Q<nested-name> following the nested +name for the function, i.e., an <encoding> has an alternative of <function +name>Q<nested-name> <bare-function-type>. So, for example, a member +D::f that explicitly overrides B::f would be encoded as +_ZN1D1fEQN1B1fEv. This is an extension to the ABI spec.

    +

    Builtin operations in expressions (i.e., vendor-specific extensions like the +Microsoft __is_base_of) are encoded as a vendor-specific operator builtinXX, where XX is the number of the builtin operation. Any type operands are +encode as “TO” followed by the encoding for the type.

    +

    When C++/CLI is enabled, tracking references, interior_ptrs, pin_ptrs, and handles are mangled using the vendor extended type qualifier:

    +
    +

    <type> ::= U<source-name><type> # vendor extended type qualifier

    +
    +

    Tracking references use the encoding “8__trkref” for <source-name>, +interior_ptrs are encoded as “14__interior_ptr”, pin_ptrs +as “9__pin_ptr”, and handles are encoded as “8__handle”. C++/CLI +static constructors are encoded as “C8” and finalizers are “D7”. +__nullptr is encoded as “DN”; __underlying_type is encoded as +“Du”.

    +

    C++/CLI operators are generally mangled using the IA-64 ABI vendor extended +operator syntax:

    +
    +
    +
    <operator-name> ::= v<digit><source-name> # vendor extended +operator
    +
    +
    +

    The unary “%” operation (which produces a handle to its operand) uses the +“9clihandle” <source-name>; the array subscript operation (which has a +variable number of operands) is encoded with a <source-name> of +“12clisubscript”. Due to the limitation of a single digit in this +encoding, only 8 subscripts can be represented in the mangled name. The +::typeid operation is mangled as “9clitypeid”; safe_cast is +“12clisafe_cast”.

    +

    The vendor extended operator syntax isn’t flexible enough to support gcnew, +so an EDG-specific mangling (patterned after the mangling for new) is used:

    +
    +
    + + + + + + + + + + + + + + + +
    +
    ::= gc_<type>E
    +
    +
    +
    # gcnew <type>
    +
    +
    +
    ::= gc_<type><initializer>
    +
    +
    +
    # gcnew <typ>e {init}
    +
    +
    +
    ::= gc<expression>*_<type> E
    +
    +
    +
    # gcnew array<type>(dims)
    +
    +
    +
    ::= gc<expression>*_<type><initializer>
    +
    +
    +
    # gcnew array<type>(dims) {init}
    +
    +
    +
    +
    +

    The IA-64 ABI specification doesn’t specify how to mangle function names that +use the GNU multiversion feature. For these functions, the front end produces +mangled names similar to the names that GNU produces. More specifically, for +the resolver function and for target-specific functions, a suffix is appended +to the name (”.resolver” for resolver functions and a string that contains +a sorted list of the canonicalized target attributes for target-specific +functions). The mangling for an ifunc function is somewhat different: the +original name is mangled, then “.ifunc” is appended, then the name is +mangled again (with the signature of the lowered routine type). Note that +these GNU manglings contain periods which can cause problems in certain back +ends (e.g., C-generating back ends), so a configuration macro, +REPLACE_SPECIAL_CHARACTERS_IN_MANGLED_NAMES, is available to change the +periods into underscores. Note also that due to their non-standard nature, +these names cannot be demangled (either with or without the periods).

    +
    +
    +
    +

    5.2.2. Dynamic Initialization#

    +

    The a_dynamic_init entry, which describes a dynamic initialization, is used +both in C and C++. IL lowering rewrites cases that are not valid in C and +leaves the others. See lower_dynamic_init. Cases that must be rewritten +are:

    +
      +
    • +
      Initialization of a file-scope variable to a nonconstant value.
      +

      +
      See lower_file_scope_dynamic_inits.
      +

      +
      The initialization is rewritten as executable code in a file-scope +initialization routine (called __sti__module-id, or __tls_init +for initialization of objects with thread_local storage).
      +

      +
      The existence of the initialization routine is communicated to the +environment through creation of a file-scope static variable called +__link:
      +
      +
      void __sti__module_id() {...}
      +struct __linkl {
      +  struct __linkl *next;
      +  void           (*ctor)();
      +  void           (*dtor)();
      +};
      +static struct __linkl __link = {NULL, __sti__module_id, NULL};
      +
      +
      +
      +
      This is compatible with the cfront patch step. That tool or something +similar to it can find the __link variable and place it on a list of +entries to be consulted at program startup and termination. It is also +compatible with the alternative cfront munch tool, which looks for +routines with names beginning with __sti__ and __std__. Note that +the cfront approach allows the specification of a termination routine, but +that facility is not used by this front end (end-of-program destructions +are requested individually by calling a runtime routine, e.g., +__record_needed_destruction for the cfront-like ABI). This __link +variable is included in the program even if initialization is handled by +some fancier mechanism (see, for example, +USE_INIT_SECTION_IN_GENERATED_C for the C-generating back end), and +even in the IA-64 ABI, even though it may not be used in those cases.
      +

      +
      See make_code_to_invoke_file_scope_init_routine.
      +

      +
      When ONE_INSTANTIATION_PER_OBJECT is TRUE, each instantiation in a +compilation is put out as a separate object file. There is still only one +IL tree, but it is marked so that a back end can sweep through it several +times and put out a different “slice” each time, each slice containing one +instantiated entity (function, variable, or static data member) plus +exactly the set of other entities needed by that entity. This is done via +a set of per-instantiation “needed” flags. For slices that contain +variable template or static data member instantiations, the slice may +require file-scope initialization code. In these cases, multiple +file-scope initialization routines and multiple __link variables are +generated, each one marked to be included in the proper slice. Each +file-scope initialization is placed in the initialization routine for the +appropriate slice and any initialization for objects with thread_local +storage are put out in a __tls_init_N routine where the N indicates +the number of the slice).
      +
      +
    • +
    • +
      Initialization of a local static variable to a nonconstant value. The +initialization is rewritten as executable code, then surrounded by a +first-time test so that the initialization is done only once:
      +
      +
      void f() {
      +  static int i = j+k;
      +}
      +
      +
      +
      +
      is translated to (cfront-like ABI):
      +
      +
      static int temp;  // Implicitly initialized to zero
      +void f() {
      +  static int i;
      +  if (temp == 0) {
      +    temp = 1;
      +    i = j+k;
      +  }
      +}
      +
      +
      +
      +
      In the IA-64 ABI, the guard variable is set after the initialization. If +IA64_ABI_USE_GUARD_ACQUIRE_RELEASE is TRUE, the routines given in the +ABI spec are called, making the full (and potentially thread-safe) sequence
      +
      +
      static long long temp;  // Implicitly initialized to zero
      +void f() {
      +  static int i;
      +  if (temp == 0) {
      +    if (__cxa_guard_acquire(&temp)) {
      +      i = j+k;
      +      __cxa_guard_release(&temp);
      +    }
      +  }
      +}
      +
      +
      +
      +
      See add_first_time_test.
      +
      +
    • +
    • +
      Initialization by calling a routine that returns a class object via a copy +constructor. The initialization is rewritten as a call of the routine.
      +
      +
    • +
    • +
      Initialization using a constructor. The initialization is rewritten as a +call of the constructor.
      +

      +
      See add_constructor_call.
      +
      +
    • +
    • +
      Initialization to a nonconstant aggregate. The initialization is rewritten +as initialization to a constant aggregate combined with executable code to +initialize the nonconstant positions.
      +
      +
      void f() {
      +  int a[3] = {1, i+1, 3};
      +}
      +
      +
      +
      +
      is rewritten as
      +
      +
      void f() {
      +  int a[3] = {1, 0, 3};
      +  a[1] = i+1;
      +}
      +
      +
      +
      +
      See
      +
      +
        +
      • +
        lower_ck_dynamic_init
        +
        +
      • +
      • +
        lower_dynamic_init_aggregate_constant
        +
        +
      • +
      • +
        add_destructor_call
        +
        +
      • +
      +
    • +
    • +
      Any dynamic initialization requiring a destructor. The required destructor +call will be on a list of destructions to be done at the end of an object +lifetime. See Object Lifetimes.
      +

      +
      If the dynamic initialization is a valid C initialization except for the +requirement to call a destructor, it is left as-is; otherwise, it is +rewritten as described above.
      +

      +
      When a global or local static variable is constructed, and the variable +requires later destruction, this is recorded at runtime by calling the +routine __record_needed_destruction [2] (cfront-like ABI) or +__cxa_atexit (IA-64 ABI) The calls of that routine build a list of +entities to be destroyed at the time of program termination. If a +destruction requires only a destructor call, the data structure passed to +the runtime routine gives the address of the object and the address of the +destructor. Otherwise (for more complex cases, e.g., arrays), a routine is +generated containing the necessary destruction code, and the address of +that routine is passed in the data structure, along with a NULL object +pointer indicating the complex case.
      +

      +
      See record_needed_destruction.
      +
      +
    • +
    +

    In routines that return a class value by calling a copy constructor, the +stmk_return statement is unusual in that it points to a dynamic +initialization entry that describes the initializing operation to be done to +return a value. The destination of the initialization is taken to be the +address given by the implicit return value parameter added to the routine. The +caller passes in the address of a class object, and the code generated for the +return statement initializes that object before returning.

    +
    +
    +

    5.2.3. Main Program#

    +

    A call of the runtime routine _main is inserted at the start of the main +program. That routine invokes initialization code for file-scope variables, +and arranges things so that the corresponding termination code will be called +when the program terminates. See lower_scope, and the section on dynamic +initialization in this chapter.

    +
    +
    +

    5.2.4. Class Types#

    +

    The following processing is done on class types:

    +
      +
    • +
      If the class has virtual base classes, a copy of the class type is made +without the virtual base classes. This copy is given the name of the +original class prefixed with “__SO__”. This type is attached to the +original type through the type_as_subobject pointer. If the class has +no virtual base classes, the type-as-subobject is the same as the original +class type. See make_subobject_class_type.
      +
      +
    • +
    • +
      The field list of the class is augmented by adding generated fields for the +base classes of the class (using the type-as-subobject of the base classes +for the field types) and pointer to a virtual function table and (for the +cfront-like ABI) any required pointers to virtual base classes . This does +not change the size of the class – these entities were already part of the +class; they are just made explicit so they can be referenced as fields. +See prelower_class_type.
      +
      +
    • +
    • +
      If the class has virtual functions, a variable will be created for a +virtual function table for the class and for each base class of the class +as a subobject of the class. The declaration is created as an extern +declaration, and is turned into a definition (either external or static) +that is initialized if the virtual function table definition should be put +out. (See next section and make_vars_for_virtual_function_tables).
      +
      +
    • +
    • +
      If the class has virtual base classes, in the IA-64 ABI, information needed +to access virtual base classes and to call virtual functions in such bases +is determined and recorded. See +compute_vbase_and_vcall_offset_indices.
      +
      +
    • +
    • +
      The members of the class (local constants, local types including nested +classes, static data members, and member functions) are promoted out of the +class into the surrounding context. See promote_class_members and +do_scope_class_member_promotion.
      +
      +
    • +
    • +
      To support the anachronism that allows a static data member to be declared +but never defined, the storage class of static data members that are +externally visible and have no initial value is changed to sc_extern. +See lower_scope.
      +
      +
    • +
    +
    +
    +

    5.2.5. Virtual Function Tables#

    +

    Each class containing virtual functions has associated with it a virtual +function table. If it has base classes that also contain virtual functions, it +will also have associated with it an instance of each base class’s virtual +function table adjusted for use when that base class is a subobject within a +complete object of the derived class. So, associated with a class C we +might have a virtual function table for C as a complete object, one for +B as a subobject of a complete object of type C, and one for A as a +subobject of a complete object of type C.

    +

    In the cfront-like ABI, each of these virtual function tables is embodied in a +variable whose type is an array of entries of type

    +
    typedef void (*__vptp)();
    +struct __mptr {
    +  short d;
    +  short i;
    +  __vptp f;
    +};
    +
    +
    +

    d is the “delta” value to be added to the “this” pointer to adjust +it to point to the class in which the virtual function is defined; f +points to the virtual function. For a pure virtual function, the function +pointer points to the runtime routine __pure_virtual_called. In the +case of a deleted virtual function, a pointer to the runtime routine +__deleted_virtual_called is used for the function pointer.

    +

    Note that field i in the above is not used; it’s there for cfront +compatibility. cfront uses the same data structure for pointers to member +functions and virtual function table entries, even though a simpler structure +could have been used for virtual function tables.

    +

    In the IA-64 ABI, each of these virtual function tables is embodied in a +variable whose type is an array of entries of type ptrdiff_t, which is +used to encode function pointers, offsets, etc. There is no “delta” value. +Entries that require such an adjustment point to a thunk routine, which +adjusts the “this” pointer and then calls the proper routine. For a +pure virtual function, the function pointer points to the runtime routine +__cxa_pure_virtual; a deleted virtual function has its function pointer +initialized to the __cxa_deleted_virtual runtime routine.

    +

    Each entry defines one virtual function of the class. The routine entry for +the virtual function gives the virtual function number for the function, which +serves as the index into the virtual function table. In the cfront-like ABI, +the code generated uses entry [0] of the virtual function table to point to +the typeinfo for the class, and the first function is at entry [1]. In the +IA-64 ABI, the first function is at entry [0], but there are also negative +entries: [-1] points to the typeinfo for the class, [-2] gives the offset to +the beginning of the complete object , and [-3], [-4], etc., if needed, give +offsets to virtual base classes and offsets to be added to the “this” value +when calling virtual functions.

    +

    When an entity of a class type having virtual functions is initialized (by a +constructor), the virtual function table pointer in the class entity is set to +point to the virtual function table that is appropriate for that object (i.e., +the one that properly reflects whether the class entity is a complete object or +a subobject of some other class). Note that it’s the virtual function pointer +that is changed; the virtual function tables themselves are constant and are +not changed. They are not built up, on a per-routine basis or otherwise, for a +given entity. Rather, the proper complete table is chosen and a pointer to it +is put into the class entity. Many class entities can point to the same +virtual function table.

    +

    The variables for virtual function tables are externally visible (except for +classes with internal or no linkage), and they are shared between compilation +units to save space. For the sharing scheme to work correctly, exactly one +compilation unit must define the contents of each virtual function table. The +rest of the compilation units must put out the variable as an extern +declaration. What IL lowering does is to build every variable as an extern +declaration first, then change it to a definition (external or static) if the +virtual function table should be defined in the present compilation. The +heuristic used to decide whether or not a virtual function table definition +should be put out is the one described in ARM 10.8.1c: The virtual function +table for a class is put out if the compilation contains a definition for the +first non-inline virtual member function of the class. If the class contains +no non-inline virtual function, the virtual function table is defined as a +local static variable unless the --suppress_vtbl or --force_vtbl option +is specified on the command line. This same heuristic is used for the IA-64 +ABI [3], with the modification that virtual function tables that would be +put out as static are put out as COMDATs, so that the multiple copies can be +joined together by the linker.

    +

    To define a virtual function table, the variable is given a static initial +value that’s specified by a ck_aggregate constant. Each entry in the table +is defined appropriately. For a complete-object virtual function table, the +functions that go into the table are simply the virtual functions of the class +in the order of their virtual function numbers. For a virtual function table +for a subobject of class A in a complete object of class B, the member +functions of A are scanned looking for virtual functions, while at the same +time the override list for base class A of B is scanned. If a function +in A does not appear on the override list, the function from A goes +into the virtual function table. Otherwise, the function from the override +list goes into the virtual function table.

    +

    During the execution of constructors and destructors for base class subobjects, +virtual functions should act as if the complete object has the type of the +constructor or destructor class. That is, functions in classes further out +than the subobject class do not override during the subobject construction or +destruction. When virtual base classes are involved, this means that some +virtual function table instances need to be built to reflect three classes: a +class A (whose virtual function table this is) that is a subobject of a class B +(whose constructor is executing, and which therefore dictates overriding) that +is a subobject of a class C (which is the complete object type, and which +therefore dictates layout). This is necessary when there are virtual base +classes, and not otherwise, because the “delta” field in the virtual function +table is based on the offset between the objects for the classes of the +overridden and overriding functions, and that offset varies depending on the +type of the complete object.

    +

    In the IA-64 ABI, the normal (non-construction) virtual function table variable +for a class contains the primary virtual function table plus the virtual +function tables for the base classes of an object of that type, all +concatenated end-to-end in the single array. This is as required by the ABI +specification. For construction vtables, however, where the spec makes no such +requirement, each vtable is in a separate variable. In the cfront-like ABI, +every vtable is in a separate variable.

    +

    See

    +
      +
    • +
      make_vars_for_virtual_function_tables
      +
      +
    • +
    • +
      make_var_for_virtual_function_table
      +
      +
    • +
    • +
      define_one_virtual_function_table
      +
      +
    • +
    • +
      define_virtual_function_tables
      +
      +
    • +
    • +
      define_scope_virtual_function_tables
      +
      +
    • +
    • +
      add_vtbl_entry_init
      +
      +
    • +
    • +
      virtual_function_table_should_be_defined_here
      +
      +
    • +
    • +
      make_construction_vtbls
      +
      +
    • +
    +
    +
    +

    5.2.6. Covariant return types on virtual functions#

    +

    An overriding virtual function can return a pointer or reference to a +derived class where the overridden function returns a pointer or reference +to a base class. Such an overriding function is said to be covariant +with the overridden function. This requires special handling in IL +lowering because a call that appears (statically) to be to the overridden +function may in fact (dynamically) be a call to the overriding function, +and the value returned from the overriding function must undergo a +derived-to-base adjustment before it is returned to the caller. This is +implemented by adding wrapper functions: for each combination of an +overriding function and an overridden function, a wrapper is generated that +calls the overriding function, casts the returned value to the proper type, +and returns it. The virtual function table points to the wrapper function +from slots that need to call the overriding function but need the interface +of the overridden function.

    +

    This mechanism is also used more generally in the IA-64 ABI, for thunks +required for virtual function calls where a “this” adjustment is needed.

    +

    The IL representation for a wrapper function is a routine with

    +
      +
    • +
      overriding_function_for_wrapper and
      +
      +
    • +
    • +
      overridden_function_for_wrapper
      +
      +
    • +
    +

    set appropriately. In the case where a wrapper is being used for a covariant +return type adjustment, the wrapper body is simply a return of an +enk_result_of_overriding_function node cast to the proper +pointer-to-base-class. The enk_result_of_overriding_function node +represents the value returned from calling the overriding function with the +arguments passed to the wrapper.

    +

    This is controlled by the macro +ABI_CHANGES_FOR_COVARIANT_VIRTUAL_FUNC_RETURN.

    +

    While the IL representation is a wrapper function, the underlying +implementation need not be. In fact, for functions with variable-length +argument lists, a wrapper approach may not be feasible. Instead, a back end +can turn the wrapper routines into entry points of the overriding function, or +duplicate the body of the overriding function within each wrapper routine.

    +
    +
    +

    5.2.7. Namespaces#

    +

    The processing for namespaces is simply the promotion of the namespace members +out of the namespaces, with appropriate name mangling. See +do_namespace_member_promotion.

    +
    +
    +

    5.2.8. Routines#

    +

    The lowering for routines consists of making two kinds of implicit parameters +explicit:

    +
      +
    • +
      The implicit “this” parameter. This is present on nonstatic member +functions.
      +
      +
    • +
    • +
      The implicit parameter that provides the address into which a class value +should be returned, for functions returning a class by value. This +mechanism is not used for simple C-style structures, but is needed for more +complicated classes, because for those it must be possible to take the +address of a class value even if it is an rvalue, e.g., to cast to a base +class or call a member function. In this more complicated calling scheme, +the caller passes in the address of a temporary and the called routine +places the class value there on return.
      +
      +
    • +
    +

    Both the param_type_list in the routine type and the parameter variable +entries in the routine scope are updated to make the implicit parameters +explicit.

    +

    Parameters that are classes passed by value and requiring a copy constructor +require additional processing: Since classes that require a copy constructor +cannot be copied arbitrarily and cannot be moved, the caller actually does the +copy constructor call into a temporary and passes the address of the temporary +as the argument. The parameters on the receiving end must be changed to be +pointers to the class object, and all the references to the parameters must be +changed to add the extra indirection.

    +

    See lower_type and lower_scope.

    +
    +
    +

    5.2.9. Promotion of Local Entities to File Scope#

    +

    If the flag PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE is TRUE, local static +variables and local types of functions will be promoted out of those functions +into the file scope under some conditions. Such promotion is enabled when the +IL will be fed into the C-generating back end, and may be desirable in other +cases where the output is textual and block-structured in some way.

    +

    The problem addressed by this transformation is shown by the following example:

    +
    void f() {
    +  static int i;
    +  class A {
    +    void g() {
    +      i = 1;       // Reference to variable local to function f
    +    }
    +  };
    +}
    +
    +
    +

    The body of A::g will become a free-standing function at file scope and yet +will have to reference the variable i of f. Therefore i must be +promoted out of f into the file scope so that it will be put out in the +file scope in the generated C code.

    +

    This is not a problem for an ordinary back end, as the reference to i will +be made in object code form or within the flat name space of an +assembly-language program.

    +

    See

    +
      +
    • +
      local_entities_should_be_promoted
      +
      +
    • +
    • +
      promote_local_entities_to_file_scope
      +
      +
    • +
    +
    +
    +

    5.2.10. Constructor Wrapper Code#

    +

    Constructors are modified to add the “wrapper” code that is required.

    +

    The constructor-initializer list indicates all the initializations that must be +done for base classes and members. It is in the language-defined order for +initialization: virtual base classes, then non-virtual base classes, then +members. Each base class or member that requires initialization will appear on +the list, with a front-end-generated default initialization if there is no +user-written one in the source.

    +

    The modifications made are:

    +
      +
    • +
      In the cfront-like ABI, if the class has virtual base classes, a parameter +is added for each such class. These parameters are used to pass in the +addresses of the virtual base classes when the constructor is called (from +another constructor) to initialize a subobject; when the constructor is +called to initialize a complete object, the parameters are passed as NULL. +In the IA-64 ABI, a single parameter is always added, for the VTT (virtual +table table) pointer passed in. Again, NULL is passed in to indicate a +complete object.
      +
      +
    • +
    • +
      In the cfront-like ABI, code is added to set any virtual base class +pointers in the class. The virtual base class pointers in the base classes +are set by the constructor calls for the base classes and therefore need +not be set by code at this level.
      +
      +
    • +
    • +
      Code is added to call a constructor for each virtual base class that +appears on the constructor-initializer list if a complete object is being +initialized.
      +
      +
    • +
    • +
      Code is added to call a constructor for each non-virtual base class that +appears on the constructor-initializer list.
      +
      +
    • +
    • +
      Code is added to initialize each member that appears on the +constructor-initializer list.
      +
      +
    • +
    • +
      If the class has any virtual functions, code is added to set the virtual +function table pointers in the current class and all of its base classes +that have virtual functions.
      +
      +
    • +
    • +
      If allocation can be folded into the constructor (a configuration +option, but always true if assignment to “this” is supported), the +entire routine is surrounded by code that tests the incoming “this” +parameter, and if it is NULL calls an appropriate new routine to +allocate space, which is then initialized. If the constructor actually +contains an assignment to “this”, the new code is not inserted and +the wrapper code above is inserted after each assignment to “this” +instead of at the beginning of the routine.
      +
      +
    • +
    +

    If the class has any virtual functions that are overridden in such a way that +there is a virtual base class step between the class of the overridden function +and the class of the overriding function, special virtual function instances +are required during construction of the class as a subobject. A constructor +for such a class, when called for a subobject, expects to receive an array of +virtual function table pointers from its caller (the constructor for the +derived class). It uses these virtual function table instances when setting +virtual function table pointers, and it passes parts of the array to its own +subobject constructors. In the cfront-like ABI, the pointer to the array is +passed (and received, in the subobject constructor) by setting the so-called +“transfer pointer” (a virtual function table or virtual base class pointer in +the class object that is unset at that point and can be borrowed for this +purpose). In the IA-64 ABI, the pointer to the array is passed in via the +added VTT pointer parameter.

    +

    In the IA-64 ABI, constructors have multiple entry points. The entry for a +complete object has a “C1” encoding in its mangled name, and has no added +parameters. The entry for a subobject has “C2”, and has an added VTT +pointer parameter if the class has virtual bases. The IL lowering +implementation puts the real code for the constructor in one function, which is +the subobject constructor if the class has virtual bases and the complete +object constructor otherwise. The other constructor is referred to as the +alternate entry point. When the class has virtual bases and +HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS is TRUE, the construction of +virtual bases is performed in the complete constructor before invoking the +subobject constructor; otherwise the alternate entry is simply an entry point +that calls the primary routine. Calls from an entry point to the primary +routine can be inlined if appropriate, or a back end can implement the entry +point functions as actual entry points to a single routine. See +alternate_entry_point.

    +

    See

    +
      +
    • +
      lower_constructor_code
      +
      +
    • +
    • +
      add_constructor_params
      +
      +
    • +
    • +
      add_constructor_wrapper_code
      +
      +
    • +
    • +
      lower_ctor_init
      +
      +
    • +
    +
    +
    +

    5.2.11. Destructor Wrapper Code#

    +

    Destructors are modified to add the “wrapper” code that is required.

    +

    The constructor-initializer list indicates all the destructions that must be +done for base classes and members. It is in the language-defined order for +destruction, i.e., the reverse of the initialization order. Each base class or +member that requires destruction will appear on the list, with a +front-end-generated destruction (there is no way to explicitly write one in the +source program).

    +

    The modifications made are:

    +
      +
    • +
      A parameter of type int is added. This parameter is used by the caller +as a bit mask: the 0x2 bit of the parameter set to 1 indicates a +complete object, and the 0x1 bit set to 1 indicates that the +storage for the object should be freed.
      +
      +
    • +
    • +
      If the class has any virtual functions, code is added to set the virtual +function table pointer in the class and in all of its base classes, so that +virtual function calls executed during the destruction will not call +functions in further-derived classes.
      +
      +
    • +
    +

    The above code is added at the beginning of the routine. The rest of the +wrapper code is added at the end of the routine. To make sure the code at the +end is reached, all returns in the routine body are rewritten as +gotos to the epilogue code.

    +
      +
    • +
      Code is added to destroy each member that appears on the +constructor-initializer list.
      +
      +
    • +
    • +
      Code is added to destroy each non-virtual base class that appears on the +constructor-initializer list.
      +
      +
    • +
    • +
      Code is added to destroy each virtual base class that appears on the +constructor-initializer list if a complete object is being destroyed.
      +
      +
    • +
    • +
      A delete routine is called to free the storage if the proper bit in +the implicit parameter is set. The entire routine is also enclosed in +an if statement so it will do nothing if the “this” parameter +passed in is NULL. If an assignment to “this” was actually done in the +routine, this delete is protected by a test to see if the “this” +parameter is (still) non-NULL.
      +
      +
    • +
    +

    See Constructor Wrapper Code regarding special virtual function tables used +during subobject construction. Similar processing is also needed in +destructor wrappers for subobject destruction.

    +

    In the IA-64 ABI, destructors have multiple entry points. The entry for a +complete object has a “D1” encoding in its mangled name, and has no added +parameters. The entry for a subobject has “D2”, and has an added VTT +pointer parameter if the class has virtual bases. The entry to destroy and +free storage for a complete object has “D0” and no added parameters. The +IL lowering implementation puts the real code for the destructor in one +function, which is the subobject destructor if the class has virtual bases and +the complete object destructor otherwise. The other destructors are known as +alternate entry points. When the class has virtual bases and +HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS is TRUE, the destruction of +virtual bases is performed in the complete destructor after invoking the +subobject destructor; otherwise alternate entry points simply call the primary +routine (for the deleting destructor, the entry point also contains the +deallocation code). Calls from an entry point to the primary routine can be +inlined if appropriate, or a back end can implement the entry point functions +as actual entry points to a single routine. See alternate_entry_point.

    +

    See

    +
      +
    • +
      lower_destructor_code
      +
      +
    • +
    • +
      add_destructor_params
      +
      +
    • +
    • +
      lower_dtor_init
      +
      +
    • +
    • +
      lower_destructor_dynamic_init
      +
      +
    • +
    +
    +
    +

    5.2.12. Calls#

    +

    See lower_call.

    +

    Calls of constructors and destructors are altered to add the implicit +parameters described in the previous sections. Except for constructor and +destructor calls in wrapper code, constructor and destructor calls are for +complete objects.

    +

    See make_ctor_implied_arg_list and make_dtor_implied_arg_list.

    +

    Calls of “vacuous” destructors, as in

    +
    p->int::~int();
    +
    +
    +

    are changed from eok_vacuous_destructor_call or +eok_points_to_vacuous_destructor_call operations to a cast to void.

    +

    Virtual function calls are rewritten from

    +
    object->func(args ...)
    +
    +
    +

    to (cfront-like ABI)

    +
    ((vtbl_temp = (object->__vptr)+index),
    +  (object+vtbl_temp->d)->(vtbl_temp->f)(args ...))
    +
    +
    +

    (Omitting some casting for clarity.) In other words, vtbl_temp is +assigned the address of the proper virtual function table entry, the +“this” pointer is adjusted by the “delta” value in the entry, and the +function indicated in the entry is called. If object is not a reusable +expression, the first occurrence of object above is replaced by +(object_temp = object), and the second by object_temp.

    +

    For the IA-64 ABI, the code is

    +
    (object->__vptr[index])(object, additional_args ...)
    +
    +
    +

    (recall that any required “this” adjustment is handled by thunk +routines and therefore is not needed at the call site).

    +

    See lower_virtual_function_call.

    +

    A related case (though not a call) is lowering of eok_virtual_function_ptr, +the operator that implements the anachronism of casting a bound member function +pointer to a normal function pointer. It rewrites

    +
    (func-type *)(object->func)
    +
    +
    +

    to (cfront-like ABI)

    +
    (func-type *)((object->__vptr)+index)->f)
    +
    +
    +

    or (IA-64 ABI)

    +
    (func-type *)*(object->__vptr)+index
    +
    +
    +

    See lower_virtual_function_ptr.

    +
    +
    +

    5.2.13. Return Value Optimization#

    +

    Return value optimization applies to functions that return a value via a copy +constructor. It can be done when all return statements in the function +return the same nonstatic local variable. The optimization is to rewrite all +references to the local variable to refer instead to the return-value address +passed in by the caller, thus avoiding a copy constructor call on exit. For +example:

    +
    struct A {
    +  A(int);
    +  A(const A&);
    +};
    +A f() {
    +  A a(1);       // Constructed into temp passed by caller
    +  return a;     // No copy needed
    +}
    +
    +
    +

    The front end proper detects the possibility of doing the optimization, but the +transformation is done by IL lowering. There are several parts to the +optimization:

    +
      +
    • +
      References to the address of the local variable are rewritten as references +to the (pointer) value of the return-value address parameter.
      +
      +
    • +
    • +
      The local variable is marked as unreferenced, and any initialization on it +is turned into initialization of the object pointed to by the return-value +address parameter.
      +
      +
    • +
    • +
      Return statements are transformed into simple returns doing no copy +constructor call and returning no value.
      +
      +
    • +
    +
    +
    +

    5.2.14. Expression Temporaries#

    +

    enk_temp_init nodes are used to introduce class temporaries in the middle +of expressions. They indicate the initialization to be done on the temporary +and any destruction to be done once the temporary is no longer needed. The +temporary is implicit in the high-level IL; IL lowering allocates a variable +for the temporary and uses it in place of references to the enk_temp_init +node.

    +

    The initialization and destruction are indicated by a dynamic initialization +entry, which is rewritten in the usual way. See lower_expr_full.

    +

    One special problem: When class temporaries created under a conditional +operator (”?”, “&&”, or “||”) require destruction, the destruction +must be done only if the initialization was done. For each case like this, it +is necessary to create a temporary, initialize it to zero at the start of the +block containing the expression, set it to one if the initialization is done, +and test it on exit from the block to determine whether or not to do the +destruction. See add_dyn_init_cleanup, init_conditional_flag_var, +set_conditional_flag_var, add_conditional_flag_test.

    +
    +
    +

    5.2.15. New and Delete#

    +

    new and delete are represented as an enk_new_delete expression +node.

    +

    There are three main new cases (see lower_new):

    +
      +
    • +
      A simple new is translated to a call of the appropriate new +routine. If the allocated object must be initialized, the pointer returned +from the allocation is tested to ensure that it is non-NULL, and then the +initialization is done.
      +
      +
    • +
    • +
      A simple class new is often translated to a constructor call, passing a +NULL pointer as an indication that the constructor should do the +allocation. (This is enabled by NEW_CAN_BE_FOLDED_INTO_CTOR. When +that is FALSE, the new routine is called, and if the allocation succeeds +the constructor is called.)
      +
      +
    • +
    • +
      An array new is translated into a call of a runtime routine; see below.
      +
      +
    • +
    +

    There are three main delete cases (see lower_delete):

    +
      +
    • +
      A simple delete is translated into a call of the appropriate delete +routine. If the allocated object must be destroyed, the destructor is +called before the deallocation routine.
      +
      +
    • +
    • +
      A simple class delete is usually translated into a destructor call, +passing a flag indicating that the destructor should do the deallocation.
      +
      +
    • +
    • +
      An array delete is translated into a call of a runtime routine; see +below.
      +
      +
    • +
    +

    Calls of new and delete that allocate or free arrays of classes that +have constructors or destructors are specially handled. They are converted to +calls of:

    +
    +
    +
    cfront-like ABI:
    +
    +
    +
    +
    __vec_new(array, num_elems, elem_size, ctor_routine)
    +
    __vec_delete(array, num_elems, elem_size, dtor_routine, +free, 0)
    +
    +
    +
    +
    IA-64 ABI:
    +
    +
    +
    +
    __cxa_vec_new(num_elems, elem_size, padding, +ctor_routine, dtor_routine)
    +
    __cxa_vec_delete(array, elem_size, padding, +dtor_routine)
    +
    +
    +
    +

    where

    +
    + + + + + + + + + + + + + + + + + + + + + +
    +
    array
    +
    +
    +
    is the address of the first element of the array. For +__vec_new, it may be NULL to indicate that the space for the +array should be allocated. For __vec_delete, it may be NULL +to indicate that the routine should do nothing.
    +
    +
    +
    num_elems
    +
    +
    +
    is the number of elements in the array. For +__vec_delete, it may be -1 to indicate that the number of +elements given in the corresponding __vec_new should be used.
    +
    +
    +
    elem_size
    +
    +
    +
    is the size in bytes of each array element.
    +
    +
    +
    ctor_routine or dtor_routine
    +
    +
    +
    is the address of the constructor or destructor routine to call, or +NULL if no routine should be called.
    +
    +
    +
    free
    +
    +
    +
    is non-zero to indicate that the storage for the array should +be freed.
    +
    +
    +
    padding
    +
    +
    +
    is the size of the array prefix in which the number of elements is +recorded by the runtime.
    +
    +
    +
    +

    The final argument of the __vec_delete call is not used; it is present for +compatibility with cfront.

    +

    These routines are necessary in order to save the number of elements in the +array from the time of the new (where it is known) to the time of the +delete (where it is not available), and also to call the constructors and +destructors for all the array elements.

    +

    For the cfront-like ABI, when exception handling is enabled, and only for +classes that have destructors, __vec_new_eh is called instead of +__vec_new. It has an additional final parameter that is a pointer to the +destructor. This is used to destroy any constructed elements if an exception +is thrown while __vec_new_eh is initializing the array elements.

    +

    For the cfront-like ABI, when value-initialization is to be done for a class +that has a generated constructor, __vec_new_eh_zero is called. It has the +same parameter list as __vec_new_eh, but it zeroes the storage before +calling the constructor.

    +

    With array new and delete, it is possible to define class-specific

    +
      +
    • +
      operator new[] and
      +
      +
    • +
    • +
      operator delete[]
      +
      +
    • +
    +

    functions. When those are specified, different runtime routines are called:

    +
    +
    +
    cfront-like ABI:
    +
    +
    +
    +
    __array_new(num_elems, elem_size, ctor_routine,
    +
                +dtor_routine, new_routine, delete_routine, is_two_arg)
    +
    __array_delete(entity_node, num_elems, elem_size, dtor_routine,
    +
                  +delete_routine, is_two_arg)
    +
    +
    +
    +
    IA-64 ABI:
    +
    +
    +
    +
    __cxa_vec_new2(num_elems, elem_size, padding, ctor_routine,
    +
                  +dtor_routine, new_routine, delete_routine)
    +
    __cxa_vec_new3(num_elems, elem_size, padding, ctor_routine,
    +
                  +dtor_routine, new_routine, delete_routine)
    +
    __cxa_vec_delete(array, elem_size, padding, dtor_routine)
    +
    +
    +
    +

    Most of the parameters are as described above. The others are:

    +
    + + + + + + + + + + + + +
    +
    new_routine
    +
    +
    +
    is the address of the special operator new[] +routine, or NULL if the default routine should be used.
    +
    +
    +
    delete_routine
    +
    +
    +
    is the address of the special operator delete[] +routine, or NULL if the default routine should be used. Also NULL on +__array_new if exceptions are disabled.
    +
    +
    +
    is_two_arg
    +
    +
    +
    is 1 to indicate that the delete_routine takes +two arguments, 0 otherwise.
    +
    +
    +
    +

    These routines are used only if ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE is +TRUE. For the cfront-like ABI, if value-initialization is to be done, +__array_new_zero is called in place of __array_new. The IA-64 ABI +“new3” routine is used for the two-argument delete case.

    +

    For the cfront-like ABI, when ABI_CHANGES_FOR_PLACEMENT_DELETE is TRUE, it +is possible to do a placement new of an array type and later deallocate the +storage via the delete operator. For that case, a special runtime routine +is called to ensure that the array size is recorded:

    +
    +
    +
    __placement_array_new(entity_node, num_elems, size_elem, +ctor_routine, dtor_routine)
    +
    +
    +

    and the value of the global runtime variable __array_new_prefix_size is +added to the size of the allocation requested in the placement new to allocate +extra space to contain the array prefix. See +make_placement_array_new_call. If value-initialization is to be done, +__placement_array_new_zero is called in place of __placement_array_new.

    +

    See lower_array_new and lower_array_delete.

    +
    +
    +

    5.2.16. Constructors and Destructors for Arrays#

    +

    Construction or destruction of an entire (static or automatic) array is done by +calling runtime routines. For the cfront-like ABI, __vec_new or +__vec_delete are used (see previous section). The address of the array is +passed into __vec_new, thus suppressing allocation, and 0 for the flag +free is passed into __vec_delete, thus suppressing freeing of the +storage. For the IA-64 ABI, there are specific runtime routines for these +functions:

    +
    +
    +
    __cxa_vec_ctor(array, num_elems, elem_size, ctor_routine, +dtor_routine)
    +
    __cxa_vec_dtor(array, num_elems, elem_size, dtor_routine)
    +
    +
    +

    Copying of an entire array using a copy constructor is done in the cfront-like +ABI by calling __vec_cctor, passing the array address, the number of +elements, the element size, the address of the routine to call, and the source +array address. [4] In the IA-64 ABI, the runtime routine is +__cxa_vec_cctor.

    +

    If the constructor involved has default arguments, a wrapper routine is created +that requires no arguments other than the “this” parameter and calls the +constructor with the proper default arguments. The wrapper routine is then +passed to the runtime routine, which can call it like a normal constructor.

    +

    See

    +
      +
    • +
      add_array_constructor_call
      +
      +
    • +
    • +
      add_destructor_call
      +
      +
    • +
    • +
      default_version_of_routine
      +
      +
    • +
    • +
      make_vec_delete_call
      +
      +
    • +
    +
    +
    +

    5.2.17. Pointers to Members#

    +

    Pointer-to-member types (tk_ptr_to_member) are transformed as follows:

    +
      +
    • +
      Pointers to data members are converted to values of an integral type. The +integer contains a byte offset to the data member in the class. In the +cfront-like ABI, one is added to leave the zero value free to indicate a +NULL pointer to data member. In the IA-64 ABI, nothing is added, and -1 is +used for a NULL pointer to data member.
      +
      +
      struct A { int i; int j;};
      +int A::*pdm = &A::j;       // unsigned int pdm = 5(cfront) 4(IA-64)
      +int A::*pdmn = 0;          // unsigned int pdmn = 0(cfront) -1(IA-64)
      +
      +
      +
    • +
    • +
      Pointers to member functions are represented by structures with the form
      +
      +
        +
      • +
        cfront-like ABI:
        +
        +
      • +
      +
      typedef void (*__vptp)();
      +struct __mptr { short d; short i; __vptp f; };
      +
      +
      +
      +
      This is essentially the structure described in 8.1.2.c of the ARM. +d is the offset to be added to the “this” pointer; i is the +index into the virtual function table (or -1 for a nonvirtual function, +or 0 for a NULL pointer); f is the nonvirtual function pointer when +i is -1 or the offset to the virtual function table pointer +(appropriately cast) when i is greater than zero.
      +
      +
      struct A {int f(); virtual int g();};
      +int (A::*pmf)() = &A::f;       // struct __mptr pmf = {0, -1, &f__1AFv};
      +int (A::*pmg)() = &A::g;       // struct __mptr pmg = {0,  1, 0};
      +
      +
      +
        +
      • +
        IA-64 ABI:
        +
        +
      • +
      +
      typedef void (*__vptp)();
      +struct __mptr { __vptp f; ptrdiff_t d; };
      +
      +
      +
      +
      f is zero for a NULL pointer, is a pointer to a function for the +non-virtual case, and is the vtable offset in bytes plus one for the +virtual function case. d is the offset to be added to the “this” +pointer. When IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR is +TRUE, an alternate representation is used that works on architectures where +the low-order bit of a function address can be non-zero. In that +representation, f is zero for a NULL pointer (but you also have to +check that the low-order bit of d is zero), is a pointer to a function +for the non-virtual case, and is the vtable offset in bytes for the virtual +function case. d is the offset to be added to the “this” pointer, +shifted left one bit, and its low-order bit is one for the virtual function +case.
      +
      +
    • +
    +

    See lower_type.

    +

    Pointer-to-member constants (ck_ptr_to_member) are transformed to the above +forms. See lower_ptr_to_member_constant. The function case generates a +ck_aggregate constant. Such constants can only be used when the constant +appears as an initializer value; for other kinds of references (e.g., in an +assignment statement), the reference to the constant is changed to a reference +to a temporary variable that is initialized with the aggregate constant.

    +

    Assignment and comparison of pointers to data members are changed to integer +assignment and comparison operators. Assignment of pointers to member +functions is changed to structure assignment. Comparison of pointers to member +functions is changed to

    +
    +
    +
    cfront-like ABI:
    +
    +
    +
    (op1.i == op2.i) && (op1.i == 0 || (op1.d == op2.d && op1.f == op2.f))
    +
    +
    +
    +

    IA-64 ABI:

    +
    +
    (op1.f == op2.f) && (op1.f == 0 || op1.d == op2.d)
    +
    +
    +
    +

    IA-64 ABI alternate representation:

    +
    +
    (op1.f == op2.f) && ((op1.f == 0 && (((op1.d | op2.d) & 1) == 0))
    +                   || op1.d == op2.d)
    +
    +
    +
    +
    +

    (That is the code for ==; the code for != is similar.) If one of the +operands is a constant, the comparisons are done directly against the constant +values of the components of the constant, and unnecessary parts of the +expression above are omitted. A comparison against a null pointer to member +constant, for example, becomes simply

    +
    (op1.i == 0)
    +
    +
    +

    for the cfront-like ABI.

    +

    Casting a pointer to a data member to a base or derived class is changed to

    +
    +
    +
    cfront-like ABI:
    +
    +
    (pdm != 0) ? (pdm + offset) : 0
    +
    +
    +

    IA-64 ABI:

    +
    (pdm != -1) ? (pdm + offset) : -1
    +
    +
    +
    +

    Casting a pointer to a member function to a base or derived class is changed to

    +
    +
    +
    cfront-like ABI:
    +
    +
    (temp = pmf, (temp.i != 0) ? (temp.d += offset) : 0, temp)
    +
    +
    +

    IA-64 ABI:

    +
    (temp = pmf, (temp.f != 0) ? (temp.d += offset) : 0, temp)
    +
    +
    +

    IA-64 ABI alternate representation:

    +
    (temp = pmf, (temp.f != 0 || temp.d != 0)
    +                           ? (temp.d += offset) : 0, temp)
    +
    +
    +
    +

    The tricky issue in both cases is preserving a NULL pointer to member.

    +

    See lower_pm_related_class_cast.

    +

    Casts from one pointer-to-member-function type to another (not related) are +removed since both types will now have the same representation and since the +cast, left in, would be a cast to a structure type. Similar casts between +pointers to data members are casts from an integral type to the same integral +type and are left alone.

    +

    The eok_pm_points_to_field andeok_pm_field operators, which implement +the ->* and .* operators for pointers to data members, are rewritten:

    +
    p->*pdm
    +
    +
    +

    is lowered to

    +
    (member-type *)(((char *)p)+(pdm-1))
    +
    +
    +

    The IA-64 ABI version does not need the -1.

    +

    See lower_pm_field.

    +

    The eok_pm_call operator, which implements calls of functions identified by +a pointer to member, is rewritten:

    +
    object->pmf(args ...)
    +
    +
    +

    is lowered to (cfront-like ABI)

    +
    ((this_temp = (object_type *)((char *)object + pmf.d)),
    +                        // Adjust "this" pointer by delta from
    +                        //   pointer-to-member.
    + (func_temp = (function_type *)
    +                        // The computed function address gets cast to the
    +                        //   proper function type.
    +    ((pmf.i < 0) ?      // Check virtual/non-virtual pointer-to-member.
    +      pmf.f :           // Function address for non-virtual case.
    +                        // Virtual function case:
    +      ((vtbl_temp =     // Virtual function table entry address is address
    +                        //   of virtual function table + offset in table.
    +         *(__vtbl_entry **)((char *)this_temp +
    +                            (short)(pmf.f)) +
    +                        // Pointer to virtual function table is at offset
    +                        //   pmf.f in the object.
    +         pmf.i),        // + offset into table
    +       this_temp = (object_type *)
    +                     ((char *)this_temp + vtbl_temp->d),
    +                        // Adjust "this" pointer to get pointer to subobject
    +                        //   expected by the virtual function.
    +       vtbl_temp->f))), // Address of virtual function.
    + func_temp(             // Call using the function pointer computed.
    +                        // Arguments for the call:
    +   this_temp,           //   "this" pointer.
    +   args ...))           //   Additional arguments, if any.
    +
    +
    +

    If pmf is not a reusable expression, the first occurrence of pmf above +is replaced by (pmf_temp = pmf), and the rest by pmf_temp.

    +

    If the class and its base classes have no virtual functions, and the variable +pointer_to_member_call_optimization_allowed is TRUE (which does not conform +to the C++ standard), the following simpler version is used:

    +
    ((this_temp = (object_type *)((char *)object + pmf.d)),
    + eok_call((function_type *)pmf.f,
    +           this_temp,
    +           additional_args ...))
    +
    +
    +

    This seems slightly more complicated than is needed, but it makes sure that if +a reusable copy of pmf is needed, the temp for it is initialized before the +call is begun.

    +

    For the IA-64 ABI, the code is:

    +
    ((this_temp = (object_type *)((char *)object + pmf.d)),
    +                        // Adjust "this" pointer by delta
    +                        //   from pointer-to-member.
    + (func_temp = (function_type *)
    +                        // The computed function address gets cast to the
    +                        //   proper function type.
    +   ((pmf.f & 1) == 0) ? // Check virtual/non-virtual pointer-to-member.
    +      pmf.f :           // Function address for non-virtual case.
    +                        // Virtual function case:
    +      ((vtbl_temp =     // Virtual function table entry address is address
    +                        //   of virtual function table + offset in table.
    +         *(__vtbl_entry **)
    +           ((char *)this_temp +
    +                        // Pointer to virtual function table is at offset
    +                        //   zero in the object
    +            ((ptrdiff_t)pmf.f - 1)),
    +                        // + offset into table, dropping low-order bit.
    +       *vtbl_temp))),   // Address of virtual function.
    + func_temp(             // Call using the function pointer computed.
    +                        // Arguments for the call:
    +   this_temp,
    +           //   "this" pointer.
    +   additional_args ...)) //   Additional arguments, if any.
    +
    +
    +

    See lower_pm_call.

    +
    +
    +

    5.2.18. Operations Returning Lvalues#

    +

    Operations that return lvalues in C++ but not in C, i.e., assignment operators, +prefix ++ and --, and “?” and “,” operators, are rewritten in C +form. Often this involves duplication of expressions. This rewriting +operation is enabled or disabled by LOWER_LVALUE_RETURNING_OPERATIONS.

    +

    Lvalue-returning assignments are rewritten from

    +
    (c1 = c2)
    +
    +
    +

    to

    +
    ((c1 = c2), rcc2)
    +
    +
    +

    where rcc2 is a reusable copy of c2 (see +make_lvalue_reusable_copy). The comma operator is an lvalue-returning +operator, which is then further rewritten (see following).

    +

    Lvalue-returning “?” operators are rewritten from

    +
    ((g1 ? g2 : g3) = c2)
    +
    +
    +

    to

    +
    (g1 ? (g2 = c2) : (g3 = c2))
    +
    +
    +

    Lvalue-returning “,” operators are rewritten from

    +
    ((g1 , g2) = c2)
    +
    +
    +

    to

    +
    (g1 , (g2 = c2))
    +
    +
    +

    For both the “?” and the “,” cases, the operations in the rewritten +form are lvalue operations iff the “=” operation in the original is an +lvalue operation. The operation indicated as “=” can in fact be any +operation (e.g., simple or complex assignment, prefix ++ or --, field +selection). c2 isn’t present for unary operations.

    +
    + +
    +

    5.2.20. bool#

    +

    In modern C++, there is a bool type, and operations like “!=” return +bool instead of int. (C99 has a _Bool type, but the boolean +operation – like “!=” and “>” – produce int values.) The IL +representation of a boolean type is identical to an ordinary small integer +type, except that the variant field variant.integer.bool_type is TRUE. +That representation is therefore not lowered: A back end can just ignore the +bool_type field and treat a boolean type as the underlying integer type.

    +

    Several bool operations are rewritten by IL lowering:

    +
      +
    • +
      eok_bool_cast, which represents a cast to bool (or _Bool), is +rewritten as a “!= 0” test of the appropriate type. See +lower_bool_cast.
      +
      +
    • +
    • +
      An increment of a bool lvalue is rewritten to set the lvalue to 1 +(true). In the postincrement case, this involves saving the original +value, setting the lvalue to 1, and then returning the saved original +value. See lower_bool_increment.
      +
      +
    • +
    • +
      The return types of operations that yield a bool in C++ but an int +in C, e.g., “!=” and “&&”, are rewritten to yield an int. In +contexts where the result is tested directly, the type is simply changed; +where something else is done with the result (e.g., storing it in a +variable), a cast to the proper type is inserted. See +adjust_bool_operation_types.
      +
      +
    • +
    • +
      Compound assignment operators whose left-hand operand has type bool (or +_Bool) are rewritten to ensure that the result value is restricted to +0/1. See rewrite_compound_assignment.
      +
      +
    • +
    +
    +
    +

    5.2.21. Condition Declarations#

    +

    In if, while, for, and switch statements, the expression tested +can be a condition declaration. For example:

    +
    if (float x = f()) { ... }
    +
    +
    +

    This is represented in the IL as an expression node of kind enk_condition.

    +

    Loops and non-loops are handled somewhat differently by IL lowering. Non-loops +(if, switch) are rewritten as follows:

    +
    if (A x = y) { ... }
    +
    +
    +

    is transformed into

    +
    {  A x = y;  if (x) { ... }}
    +
    +
    +

    The test in the if actually uses the expression from the expr field of +the condition, which is the value of the declared variable converted to a +testable type if necessary.

    +

    Loops (while, for) are rewritten as follows:

    +
    for (w; A x = y; z) { ... }
    +
    +
    +

    or

    +
    while (A x = y) { ... }
    +
    +
    +

    is transformed into

    +
    {                                    {
    +   for (w;;) {                          while (1) {
    +     A x = y;                             A x = y;
    +     if (!x) {                            if (!x) {
    +       destroy x if necessary;              destroy x if necessary;
    +       goto break_label;                    goto break_label;
    +     }                                    }
    +     { ... } // Original statement        { ... } // Original statement
    +     z;      // Increment code
    +     destroy x if necessary;              destroy x if necessary;
    +  }                                    }
    +  break_label:;                        break_label:;
    +}                                   }
    +
    +
    +

    Again, the x in !x is the value of the declared variable converted to a +testable type if necessary. If the break_label exists already, it and the +block around the for/while are not added.

    +

    See lower_condition.

    +
    +
    +

    5.2.22. Anonymous Unions#

    +

    In the unlowered IL, field selections of fields of anonymous unions that are +embedded in classes elide the field selection(s) for the anonymous union(s). +For example:

    +
    class A {
    +  union {
    +    int i;
    +    float j;
    +  };
    +} x;
    +
    +
    +

    x.i appears as a selection of i directly out of x. IL lowering +adds the implied field selection through the unnamed union.

    +

    See adjust_field_selection_for_anonymous_union_references.

    +
    +
    +

    5.2.23. Automatic Template Instantiation#

    +

    When automatic template instantiation is enabled and +instantiation_flags_in_template_info_file is FALSE (an old mode not longer +much used), IL lowering helps the cause by getting certain information about +instantiations passed into the object file. The instantiation information is +recorded in the flags

    +
      +
    • +
      can_be_instantiated,
      +
      +
    • +
    • +
      do_not_instantiate, and
      +
      +
    • +
    • +
      instance_required
      +
      +
    • +
    +

    that appear in variable and routine entries.

    +

    IL lowering passes the values of these flags into the object code by generating +tentative definitions of global-scope variables that have names formed by +combining a prefix with the mangled name for the entity for which the flag is +being generated. The prefixes are

    +
      +
    • +
      __CBI__ for the can_be_instantiated flag,
      +
      +
    • +
    • +
      __DNI__ for the do_not_instantiate flag, and
      +
      +
    • +
    • +
      __TIR__ for the instance_required flag.
      +
      +
    • +
    +

    The routine make_instantiation_info_var is used to create these variables.

    +

    For template classes with virtual functions, where the decision on whether or +not to output a definition of the virtual function table is based on the +presence of a definition for the first non-inline virtual function of the +class, a reference to the virtual function table causes a __TIR__ for the +first virtual function to be generated (that requests a definition of the +function, and therefore of the virtual function table, somewhere in the +program). When a virtual function definition is generated, it references all +the virtual functions of the class, so __TIR__ variables are generated for +them (except for the first virtual function, to avoid the chicken-and-egg +problem of the first virtual function and the virtual function table each +forcing the other to be instantiated, with neither actually referenced from +anywhere).

    +

    The prelinker phase notices these names in the object files, and from them can +recover the associated instantiation information.

    +
    +
    +

    5.2.24. Guard Code on Variable Template and Template Static Data Member Initializations#

    +

    When TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE (in targ_def.h) is +TRUE, “guard” code is placed around initializations of instances of variable +templates and static data members of templates. Such guard code is necessary +if template instantiation resolution is done by instantiating everything and +then having the (specially-modified) linker discard duplicate copies of +instantiated routines. Dynamically-initialized template variables and static +data members of templates are a particular problem: because the initialization +code is generated in startup routines, and is undifferentiated from other code +in those routines, a flag is needed to indicate that initialization has already +been done. After any one instance of the code does initialization, all other +instances will do nothing.

    +

    The initialization guard code looks like (cfront-like ABI):

    +
    int guard_var;  // Implicitly initialized to 0
    +{
    +  if (guard_var == 0) {
    +    guard_var = 1;       // Initialization of static data member
    +  }
    +}
    +
    +
    +

    For the IA-64 ABI, the code sequence is the one generated by +add_first_time_test, which has either calls of __cxa_guard_acquire et +al. or is like the above but with the setting of the guard variable after the +initialization.

    +

    If the template variable or static data member is a specialization, its +initialization should take precedence over any other (non-specialization) +initializations. For that case, the guard variable is put out as a definition +with an initial value of -1. That disables the construction guard code for +all other instances.

    +

    Destruction is not a problem, since all destructions of static entities are put +on a list to be done at the end of program execution. The entry is only put on +the list exactly once when and if the initialization is done.

    +
    +
    +

    5.2.25. Runtime Type Information#

    +

    Runtime type information is needed for exception processing and for the RTTI +features of the C++ language. IL lowering generates special typeinfo +variables for each type that requires such information.

    +

    In the cfront-like ABI, note that the runtime typeinfo is not the same type +as the programmer-visible type_info; the runtime typeinfo contains a +type_info structure as a member, and has other information besides. The +typeinfo variables have mangled names of the form

    +
    +
    +
    __T_mangled-type-encoding
    +
    +
    +

    (except static typeinfo variables for non-class types, which are unnamed).

    +

    The variables are typeinfo structures (this is still for the cfront-like +ABI):

    +
    struct typeinfo {
    +  type_info       tinfo;      // User-visible type_info structure
    +  const char      *name;      // Null-terminated string for name
    +  char            *id;        // Id object pointer
    +  base_class_spec *bc;        // Array of base class information
    +};
    +
    +
    +

    Each pointer field is NULL if it is not applicable. In versions preceding +2.38, there was an additional field after id which contained a destructor +pointer. It was eliminated when the__throw_setup_dtor runtime routine +was added. In versions preceding 2.41, the name field was not const (it +was made const when const string literals were implemented).

    +

    In the IA-64 ABI, the type_info type visible to the user is the same as the +implementation type, and it has a number of derived classes that provide +additional information for pointer types, class types, etc. as described in +the ABI spec. typeinfo variables have mangled names beginning with +“_ZTI”.

    +

    If the type represented by a typeinfo variable is a polymorphic class, the +typeinfo variable is external if and only if the virtual function table +variable for the class is external, and the typeinfo variable is defined +(i.e., initialized) if and only if the virtual function table is defined. For +other cases (non-polymorphic classes and non-classes), the typeinfo +variable is always static and always defined.

    +

    In the IA-64 ABI, the typeinfo variable is made a COMDAT so that there will be +only one copy in the linked program even when the virtual function table +heuristic does not place the definition in a single file. Likewise, the name +string for a typeinfo variable is placed in a separate variable with a +predictable mangled name (beginning with “_ZTS”), which is made a COMDAT so +that all instances of the name are shared.

    +

    In the cfront-like ABI, when the typeinfo variable is static, and the +type is not an internally-linked class, it is possible that the same type +is represented by several typeinfo variables. [5] In those cases, +the object id pointer is used to indicate that those typeinfo entries +all correspond to the same type: the object id pointer is non-NULL and +points to an id object variable of type char whose name has the form

    +
    +

    __TID_mangled-type-encoding

    +
    +

    This variable is put out as a tentative definition and therefore there will be +only one copy of a given id object variable in the executable program. Two +typeinfo variables are considered to represent the same type if their id +object pointers are non-NULL and equal to one another.

    +

    In the cfront-like ABI, for classes that have base classes, the base class +array field points to a (static) variable initialized to an array of entries +with the following structure:

    +
    struct base_class_spec {
    +  typeinfo         *tinfo;  // typeinfo for base class
    +  short            offset;  // Offset of base class in derived class
    +  unsigned char flags;      // Flags
    +};
    +
    +
    +

    Only direct, virtual, and ambiguous base classes of the derived class +appear in the base class list. The flags byte contains a bit set: +0x01 indicates a virtual base class, 0x02 is set to mark the +last entry in the array, 0x04 indicates a public base class, 0x08 +indicates an ambiguous base class, and 0x10 indicates a direct base +class.

    +

    When ABI_CHANGES_FOR_RTTI is FALSE, an older form of the typeinfo entry +is generated, which is adequate for exception handling but not for RTTI. The +differences are as follows:

    +
      +
    • +
      The type_info and name fields are not present.
      +
      +
    • +
    • +
      typeinfo variables for nonclass types are put out as tentative +definitions and rely on default initialization to zero. Because of the +name mangling and the fact that the variable is external, there will be +only one copy of the typeinfo variable for any given nonclass type in +the executable program. No id object variable is needed.
      +
      +
    • +
    • +
      The public base class and ambiguous bits in the base class specification +are not set.
      +
      +
    • +
    +
    +

    5.2.25.1. The typeid operator#

    +

    The C++ typeid operator is represented by an expression node with kind +enk_typeid.

    +

    If the typeid node has a null expression pointer, the type is known +statically. IL lowering generates a typeinfo entry for the static type, +and replaces the typeid node with a field selection that computes the +address of the tinfo member of the typeinfo variable.

    +

    If the typeid node has a non-null expression pointer, the type (a +polymorphic class) must be determined at runtime.

    +

    In the cfront-like ABI, IL lowering replaces the typeid node with a runtime +routine call

    +
    __get_typeid((typeid_expr != NULL) ? vptr : NULL)
    +
    +
    +

    where typeid_expr is the typeid expression (or more precisely the +address indicated by that expression) and vptr is an expression for the +value of the virtual function table pointer for the class object pointed to. +If typeid_expr is not reusable, it will be assigned to a temporary and the +temporary will be used in the vptr expression. Note that when +typeid_expr is null, a null pointer is passed to __get_typeid; the +latter then throws bad_typeid.

    +

    In the IA-64 ABI, the code sequence is entirely inline:

    +
    (typeid_expr != NULL) ? (typeinfo*)(vptr[-1]) :
    +                        (__cxa_bad_typeid(), NULL)
    +
    +
    +
    +
    +

    5.2.25.2. The dynamic_cast operator#

    +

    A dynamic_cast is represented by an expression node with operator +eok_dynamic_cast. IL lowering rewrites that into

    +
    +

    cfront-like ABI:

    +
    +
    (src != NULL) ? __dynamic_cast    (src, vptr, desired_type, orig_src,
    +                                    static_type) :
    +                NULL
    +
    +
    +

    or

    +
    (src != NULL) ? __dynamic_cast_ref(src, vptr, desired_type, orig_src,
    +                                   static_type) :
    +                NULL
    +
    +
    +
    +

    IA-64 ABI:

    +
    +
    (src != NULL) ? __dynamic_cast    (src, static_type, desired_type, hint) :
    +                NULL
    +
    +
    +

    or

    +
    (temp =         __dynamic_cast     (src, static_type, desired_type, hint))
    +                     ? temp : __cxa_bad_cast()
    +
    +
    +
    +
    +

    The second form in each ABI is for a cast to a reference type. src is the +expression being cast (or its address, in the reference case); vptr is the +virtual function pointer for the class (note that it’s protected by the +null-pointer check); desired_type is a pointer to the typeinfo for the +desired class, or NULL for a dynamic cast to “void *”; orig_src is the +original source pointer in the dynamic cast (the value passed as the first +parameter may have been cast to a base class if the original class has no +virtual function pointer); and static_type points to the typeinfo for +the underlying class of the source pointer’s static type.

    +

    In the IA-64 ABI, a dynamic_cast to void * is done as inline code, by +extracting the offset-to-base from the [-2] entry in the virtual function table +and adding that to the object address.

    +

    Note that dynamic_casts that do not require runtime processing are +translated by the front end into simple casts or base class casts.

    +
    +
    +
    +

    5.2.26. Exceptions#

    +

    The lowering of exception handling (EH) features can be configured three +different ways:

    +
      +
    1. Full lowering: all exception handling features are reduced to C, and +no support for EH features is required in the back end. This solution +is easy to use and highly portable, but entails a fairly significant +overhead in execution cost (15-20%). This mode is required for the +C-generating back end, and is supported by the minimal runtime +provided by EDG. It is enabled by the configuration switch +DO_FULL_PORTABLE_EH_LOWERING.

    2. +
    3. Partial lowering: the data tables of the portable scheme are generated, +but they use stack offsets for variables (in the portable scheme, all +addresses are computed at runtime and stored in an object address table). +try, catch, and throw are preserved in the IL. Much of the +minimal runtime provided by EDG would still be applicable, but some +parts would require changes. This mode is enabled by the configuration +switch GENERATE_EH_TABLES.

    4. +
    5. No lowering: No data tables are generated; the object lifetime +information is preserved for use in generating tables in a back end. +try, catch, and throw are preserved in the IL. The back +end makes all decisions about the way in which EH features are +implemented. This mode is enabled by having both GENERATE_EH_TABLES +and DO_FULL_PORTABLE_EH_LOWERING set to FALSE.

    6. +
    +

    It should be noted that in all three schemes the statements and expressions +attached under EH constructs are lowered. Even in the partial/no lowering +schemes, lowering generates the code needed for things like copying thrown and +caught objects. Special expression nodes that represent (partially) lowered +exception handling constructs, of kind enk_lowered_eh_construct, are used +to represent the parts of those operations that remain for the back end to +define.

    +

    The portable implementation is the one that involves the most transformations +in IL lowering, and the other two schemes are essentially scaled-back versions +of the full-lowering scheme. Therefore, the description that follows covers +the processing for the full-lowering scheme and indicates differences in the +other schemes.

    +

    Exception handling imposes a nontrivial overhead in time and/or space on +programs, including those that do not make use of exceptions. Accordingly, +exception handling can be enabled or disabled by a command-line option, and +when it is disabled IL lowering will not generate the code or data structures +to support it.

    +

    The fully- and partially-lowered implementations do work with the IA-64 ABI, +but they are not compatible with the ABI spec. For a fully-comforming IA-64 +ABI implementation, it is necessary to do the EH implementation in the back +end.

    +
    +

    5.2.26.1. Maintaining Context#

    +

    When an exception is thrown, the stack is unwound to the catch point, and +destructible objects created in the stack frames removed from the stack must be +destroyed by the runtime. In order to be able to do that, the runtime must +have access to information about the stack frames and the destructible objects +therein. This information is provided by entries linked into an exception +handling stack. There are three kinds of stack entries:

    +
      +
    • +
      Entries representing a function. These are pushed on entry to a function +and popped on exit from that function, and they point to information about +the destructible objects in the function. No stack frame is needed for any +function that has no destructible objects and no try blocks.
      +
      +
    • +
    • +
      Entries for exception specifications of a function. These are pushed at +the beginning of each function having an exception-specification (i.e., a +list of the exception types that the function is permitted to throw), and +popped at the end of each such function. The stack frame points to an +array that describes the types that may be thrown.
      +
      +
    • +
    • +
      Entries for try blocks. These are pushed at the beginning of each +try block and popped on exit from each such block. The stack frame +provides space for a setjmp buffer, and a pointer to an array that +describes the types caught at each associated catch handler clause.
      +
      +
    • +
    +

    The code to push and pop stack frames is generated by

    +
      +
    • +
      push_eh_stack_frame and
      +
      +
    • +
    • +
      pop_eh_stack_frame.
      +
      +
    • +
    +

    The function and exception-specification stack frames are requested by +add_eh_function_prologue (which also handles epilogue code).

    +

    The function stack frame points to several data structures that describe the +destructible objects:

    +
      +
    • +
      The region table, which has entries that describe objects and the cleanup +to be done for them. See make_region_table_entry. The table is an +array, and an index into that array is called a cleanup region number. +Each entry contains a cleanup region number for a “next” entry in the +table, which makes it possible to link entries into lists of cleanup +actions. At any given point in a function, one can describe the sequence +of cleanup actions required on termination of that routine by indicating a +cleanup region number, i.e., the index number of the first entry of a +linked list of region table entries that enumerates the destructions and +deallocations to be done, in the order they are to be done. IL lowering +generates code to maintain the global variable __eh_curr_region +appropriately to indicate the set of cleanup actions necessary at each +point in each function. See assign_to_eh_curr_region.
      +
      +
    • +
    • +
      The array table, which provides additional information about destructible +objects that are arrays (for example, the array element size). See +make_array_table_entry.
      +
      +
    • +
    • +
      The object address table, which provides the addresses of destructible +objects. The region table identifies objects by indicating their index +numbers in the object address table. This extra level of indirection is +necessary to separate the static parts of the region table, which can be +used for all activations of a function, from the changeable part, which is +different for each activation. (When a function calls itself recursively, +for example, the exception stack entries for the various activations will +point to distinct copies of the object address table but to a common static +copy of the region table.) See object_addr_table_index.
      +
      +
    • +
    +

    The exception-specification stack frame indicates the types that may be thrown +by pointing to an array whose elements are exception type specifications. An +exception type specification is a structure defined as follows:

    +
    struct exception_type_specification {
    +  typeinfo      *tinfo;
    +  unsigned char flags;
    +  unsigned char *ptr_flags;
    +};
    +
    +
    +

    The tinfo pointer points to a typeinfo variable for a type. The +flags value is a bit set that indicates modifications of that type, e.g., +pointer-to the type. One of the bits is used to indicate the last entry in the +array. The ptr_flags field (added in version 2.41) is non-null for +multi-level pointer types. It points to an array of flags values, each one +describing the cv-qualifiers at one level of a multi-level pointer type. +Again, one of the bits is used to indicate the last entry in the array.

    +

    The try-block stack frame contains space for a setjmp buffer, and a pointer +to an array in which each entry represents a catch handler. The entries in the +array are exception type specification structures, each one describing the type +to be caught by the associated handler.

    +

    Note that local and global static variables are never handled in normal +exception cleanup. The required destructions for all static entities that have +been constructed are placed on a runtime list, and therefore the cleanup for +those entities need not and should not be described in the region tables.

    +

    In the partial-lowering scheme, the region table and array table are generated, +but the object address table is not used. Instead, the addresses of variables +in the region table and array table are given as stack offsets using +ck_stack_offset constants. Since there is no object address table, the +code that computes addresses and places them in the object address table is +unnecessary. No exception stack is maintained; instead, expression nodes with +subkinds leck_function_prologue and leck_function_epilogue are inserted +at the appropriate places to indicate to the back end that appropriate +maintenance should be done at those points, and to identify the variables for +the region table and array table. It is assumed that the back end will also +deal with the exception-specification, if any, for the function. In place of +assignments to __eh_curr_region, expression nodes with subkind +leck_cleanup_state are used to communicate the new region table entry +number to the back end at each place that changes it. typeinfo information +is still put out for all types involved in exception handling operations, but +there will be no references to those entries in the lowered code. They are +pointed to from the type entries, available for use by a back end.

    +

    In the no-lowering scheme, none of the tables are generated (including the +typeinfo entries). As in the partial-lowering scheme,

    +
      +
    • +
      leck_function_prologue,
      +
      +
    • +
    • +
      leck_function_epilogue, and
      +
      +
    • +
    • +
      leck_cleanup_state
      +
      +
    • +
    +

    nodes will be inserted. The latter have a pointer to a dynamic initialization +entry, rather than a region number, as the indication of the cleanup state to +be established at that point.

    +

    When INDICATE_CLEANUP_STATE_IN_UNREACHABLE_CODE is TRUE, cleanup state +instructions will be emitted even at the unreachable ends of blocks. This may +be desirable if the back end is using the cleanup state information to build a +table of cleanup address ranges rather than leaving them as some kind of +executable code. The instructions generated will have the special kind +leck_unreachable_cleanup_state.

    +
    +
    +

    5.2.26.2. Throwing an Exception#

    +

    The enk_throw expression node is rewritten either as

    +
    __rethrow();
    +
    +
    +

    for the rethrow case (throw with no operand), or as

    +
    ((temp = __throw_setup(&typeinfo, size, flags)),
    +         (initialization, __throw()))
    +
    +
    +

    for the normal case. typeinfo is the runtime type information variable for +the base type being thrown, size is the size in bytes of the object being +thrown, and flags is a bit set that indicates the relationship of the type +thrown to the typeinfo type – for example, that the type being thrown is a +pointer to the type indicated by the typeinfo variable. The +__throw_setup call allocates space for a copy of the thrown object; the +initialization code makes a copy of the thrown object in that allocated space; +and the __throw call actually does the throw (and does not return). If the +thrown object requires destruction, __throw_setup_dtor is called instead of +__throw_setup (this routine was added in version 2.38). +__throw_setup_dtor has an additional final parameter, which is the +destructor pointer. If the thrown object is a multi-level pointer, +__throw_setup_ptr is called instead of __throw_setup (this routine was +added in version 2.41). __throw_setup_ptr has a parameter in place of the +flags parameter, which is a pointer to an array of flag bytes that indicate the +cv-qualifiers at each level of the multi-level pointer type. In cases where +the thrown object is copied to the allocated space using a copy constructor, +and the copy is implicit, __exception_started is called before the copy +constructor call to tell the runtime to consider the copy constructor call as +“inside” the throw.

    +

    In front end versions preceding 2.29, and when ABI_CHANGES_FOR_RTTI is +FALSE, a runtime routine __throw_alloc is called instead of +__throw_setup. It has one additional argument: if the typeinfo +type is a class with base classes, the argument is a character string +containing the letter “Y” or “N” for each base class to indicate +whether the base class is accessible. Otherwise, it is a NULL pointer.

    +

    In the partial-lowering and no-lowering schemes, the enk_throw node is +preserved. The dynamic initialization that copies the thrown object is +lowered, using a node with subkind

    +
      +
    • +
      leck_thrown_object_address
      +
      +
    • +
    +

    to indicate the address in the runtime to which the thrown object should be +copied. A node with subkind leck_exception_started is used to mark the +point before a copy constructor call.

    +

    See lower_throw.

    +
    +
    +

    5.2.26.3. Catching an Exception#

    +

    The routine lower_try_block lowers the stmk_try_block statement to +generate code for a try and its associated catch clauses. The code +does roughly the following:

    +
      +
    • +
      Push a try-block entry on the exception stack. This entry points to an +array whose elements describe the types to be caught by each catch +handler. The index of an entry in the array is the number assigned to +identify the associated catch handler.
      +
      +
    • +
    • +
      Do a setjmp in an “if” surrounding the dependent statement of the +try. This records the address to be jumped back to in the event that +one of the catch handlers is to be executed. When the call to setjmp +returns (the first time), the try block is executed.
      +
      +
    • +
    • +
      For each catch handler, test the global variable +__catch_clause_number (which is set by the runtime before the transfer +back to this code) to see if it matches the number of the catch clause. If +so, copy the value of the caught object (whose address the runtime provides +in __caught_object_address) to the handler parameter (see +begin_catch_clause). Call __exception_caught to indicate to the +runtime that the exception is fully caught. Execute the dependent +statement of the catch, and, on exit, call __free_thrown_object +(see cleanup_on_exit_from_catch).
      +
      +
    • +
    • +
      At the end of the try block, whether reached from the try or from a +catch handler, pop the try-block entry off the exception stack.
      +
      +
    • +
    +

    Note three aspects of using setjmp to implement try:

    +
      +
    1. The size of the setjmp buffer must be configured to match the target +environment. See

      +
        +
      • +
        TARG_JMP_BUF_NUM_ELEMENTS,
        +
        +
      • +
      • +
        TARG_J _BUF_ELEMENT_INT_KIND.
        +
        +
      • +
      • +
        TARG_JMP_BUF_ELEMENTS_ARE_FLOAT, and
        +
        +
      • +
      • +
        TARG_JMP_BUF_ELEMENT_FLOAT_KIND
        +
        +
      • +
      +

      in targ_def.h.

      +
    2. +
    3. The setjmp is represented as a runtime routine call. This may +necessitate some sleight of hand from a back end if setjmp is not really +a runtime routine.

    4. +
    5. Some optimization may have to be suppressed for the region of the try +block. In C, on return from a setjmp only volatile variables are +guaranteed to be set correctly. The code generated by IL lowering, however, +assumes that all variables are set correctly, which means that variables +cannot be kept in registers over calls in any code in which exceptions might +be thrown. The contains_try_block flag in the routine entry is a +partial solution. See also the modified_within_try_block flag.

    6. +
    +

    In the partial-lowering and no-lowering schemes, the stmk_try_block +statement is preserved, with things under it lowered. The initializations of +catch parameters are lowered, with a node with subkind +leck_caught_object_address used to represent the address in the runtime +from which the caught object should be copied. (Note that the implicit +indirection inserted for reference parameters in the full-lowering approach is +not inserted in these modes; a back end can check the handler parameter type +and generate such an indirection if one is necessary.) A node of subkind +leck_exception_caught is used to indicate the point (after the +initialization, if any) where the exception is considered fully caught. On +exit from a try or catch (by flowing off the end or by goto or +return), a node of subkind leck_try_epilogue or leck_catch_epilogue +is inserted.

    +
    +
    +

    5.2.26.4. Unordered Evaluation#

    +

    The C and C++ language rules do not fully define the order of evaluation of +parts of expressions. For example, in “A(1) + A(2)” the evaluation of +A(1) could occur before or after the evaluation of A(2). When +destructible temporaries appear in such contexts, the order of construction and +destruction of the temporaries cannot be predicted from the language rules +alone, e.g., the temporary for A(1) could be constructed before or after +the temporary for A(2). Such temporaries are called “unordered” +temporaries, and the dynamic initialization entries for them are marked as +such. These temporaries cause a problem for a portable implementation, because +is it necessary when indicating the cleanup to be done at the point of +construction of A(1) or A(2) to indicate that the other temporary might +or might not already have been constructed. This is done by adding a +conditional flag for each temporary, which indicates whether or not the +construction has been done, and having the cleanup position in the cleanup +region table include destructions for both temporaries. The runtime then tests +the conditional flags to indicate whether the destructions should actually be +done. This method, of course, involves a time and space overhead, so the flag +DO_UNORDERED_EH_PROCESSING can be set to FALSE to switch it off. It can be +switched off if the back end will do the constructions in the canonical order +indicated by the IL, or if the next_in_destruction_list linkage of the +initializations is changed before IL lowering to match the order that will +actually be used by the back end, or if the back end will use some different +technique to accomplish the same result. Note that when using the C-generating +back end, the order in which temporaries are constructed depends on the C +compiler that will be used, so if one has detailed information about the order +in which it will evaluate expressions, one may be able to switch off this +processing. The unordered processing is turned off in the no-lowering scheme.

    +
    +
    +

    5.2.26.5. Placement Delete#

    +

    When a placement new is done, and there exists a corresponding +operatordelete function (one with the same parameter types as the +operatornew, ignoring the first parameter), if an exception is thrown +before the initialization associated with the new completes, the +operatordelete is called to deallocate the storage. This is +implemented by wrapping the code that performs the initialization inside an +internal try block. If an exception is thrown while executing the try +expression, the associated catch expression, a call of the delete routine, +is executed. In the fully-lowered scheme, this internal try block is +expanded into the same code sequence used for a statement-level try (but as +part of an expression). In the partial-lowering and no-lowering schemes, the +internal try is indicated by an expression node with subkind +leck_internal_try. See make_internal_try_expr.

    +
    +
    +
    +

    5.2.27. Lowering extern inline#

    +

    When LOWER_EXTERN_INLINE is TRUE, extern inline functions are processed +specially. In the cfront-like ABI, they are lowered to normal static inline +functions; this mainly involves just a change of the storage class in the +routine entry. In the IA-64 ABI, they are left external but put into a COMDAT +so that multiple copies are folded into one by the linker.

    +

    The code generated in LOWER_EXTERN_INLINE mode in the cfront-like ABI does +not quite conform to the standard, because it does not ensure that when the +address of an extern inline function is taken the address is the same +across different compilation units. Setting INSTANTIATE_EXTERN_INLINE to +TRUE (instead of setting LOWER_EXTERN_INLINE) provides standard-conforming +behavior: extern inline functions are treated like template instances, and +the template prelinker assigns the “instantiation” of the function to a single +file, thus ensuring that if its address is taken it is the same everywhere.

    +

    Two transformations that apply to all extern inline functions, whether +LOWER_EXTERN_INLINE is specified or not:

    +
      +
    • +
      For functions that have local static variables, the static variables are +promoted out of the function and made external (and given mangled names), +so that all copies of the function will refer to a common set of static +variables. If the static variables are initialized, the initialization +guard variables are also made external, with mangled names that begin with +__LSG__ (cfront-like ABI) or _ZGV (IA-64 ABI).
      +
      +
    • +
    • +
      If ASSIGN_STRING_LITERAL_SEQUENCE_NUMBERS is TRUE, similar processing +is done for string literals: they are moved into external variables with +mangled names so that every copy of the extern inline function gets the +same address for the same string literal. This is off by default in the +cfront-like ABI, even though it should be TRUE for full conformance to the +C++ standard, because it’s expensive way out of proportion to its benefit. +Not being able to count on a COMDAT-like mechanism, the cfront-like ABI +must put out the variables for the string literals as tentative definitions +(therefore uninitialized), and initialize them at each point of use. It’s +not at all pretty, especially in small inline functions, and it’s a feature +that hardly anyone ever counts on.
      +
      +
    • +
    +
    +
    +

    5.2.28. Inlining#

    +

    As an option, IL lowering can do inlining of function calls. That is, when it +encounters a call of a function declared inline, it can replace the call +with IL corresponding to the body of the function with the parameters replaced +by the corresponding arguments. When a function call occurs as a statement, +the statements of the function body are inserted in place of the call. When +the function call occurs within an expression, the body of the function is +rewritten as one large expression and that expression is inserted in the proper +place in the containing expression. It is not always possible to do this sort +of inlining: there are certain constructs (e.g., loops) that cannot be rendered +in expression form. Even when the inlining is done at the statement level, +there are certain constructs that are not practical to inline. Calls that +cannot be inlined are left in their original call form, and an out-of-line copy +of the function is used. A remark is issued.

    +

    Inlining of this style has some serious limitations. Aside from the +impossibility of inlining certain function bodies, there is also the problem +that inlining at this level is done without knowledge of the target +architecture, and therefore without the ability to know whether the inlined +version of a call is preferable to the original version. The inlined version +might be ridiculously large, or might be worse in some other way. Inlined +calls produce extremely convoluted expressions, which stress back ends and C +compilers.

    +

    In short, if you want inlining (and you do, for C++), you probably want to do +it some other way. The version EDG supplies is provided as a convenience for +those who use the C-generating back end and whose C compilers do not handle +inlining. It’s intended to give roughly the same functionality as cfront, and +EDG does not plan to enhance it in any substantial way.

    +

    The code to perform inlining is contained in inline.c, with the associated +declarations in inline.h. Inlining of function calls is enabled by the +configuration switch MINIMAL_INLINING. The default is to inline only when +using the C-generating back end.

    +

    Inlining is done on code that has already been lowered, which is to say on C +code. When the end of the lowering of a function’s body is reached, +set_up_routine_for_inlining is called to determine whether the routine can +be inlined. If so, the inlinable flag in the routine entry is set. Note +that this means that a routine call cannot be inlined until the full definition +of the function has been seen and lowered. Also note that lowering is not done +if any errors are detected, so inlining is always done using correct code. A +function is disqualified for inlining immediately if any of the following are +true:

    +
      +
    • +
      The function has local static variables.
      +
      +
    • +
    • +
      The function has local constants.
      +
      +
    • +
    • +
      The function has local types.
      +
      +
    • +
    • +
      The function has block scopes.
      +
      +
    • +
    • +
      The function includes pragmas.
      +
      +
    • +
    • +
      The function has an ellipsis in its parameter list.
      +
      +
    • +
    +

    A function that passes these tests is eligible to be inlined. When a call is +seen, do_inlining_of_call is invoked to do the expansion. The expansion is +done in three steps:

    +
      +
    1. set_up_variable_remapping_for_inlining makes temporary variables +for the parameters and local variables of the function, and generates +assignment code to initialize each parameter temporary with the +corresponding argument expression. If the argument is constant-valued +and the parameter is not modified in the function, no temporary is +needed; the constant will be used directly.

    2. +
    3. expand_statement_inline does the expansion of the function body. +It makes a copy of the statements and expressions of the function, +replacing references to the parameters and local variables with the +appropriate temporaries or constants. If the function call being +inlined appears at the statement level, the copy is made in statement +form. Otherwise, the function body is translated into expression +form as the copy is made. Expression statements are copied as +expressions; a sequence of statements is formed via comma operations; +and if statements are rendered as “?” operations. Loops cannot +be translated to expression form, and therefore can be inlined only in +the statement mode. gotos and labels generally preclude inlining +in both modes, but the special case of a goto to a label +immediately following it is allowed and eliminated. returns +are allowed only at the end of the function at the top level (or as +the last statement in a block that is the last statement in a block +… that is the last statement of the top-level block of the function). +Dynamic initialization of local variables is translated to +assignments, but aggregate initialization precludes inlining.

    4. +
    5. finish_variable_remapping_for_inlining adds the created temporaries +to the calling context scope, and then the statement sequence or +expression tree is inserted into the IL tree, replacing the original +call.

    6. +
    +

    Since the inlining operation is an attempt to inline the function, one that may +fail, the statement sequence or expression tree for the inlined call is built +off to the side, and attached to the IL tree only once the inlining operation +is completed successfully. Likewise, the temporaries created for parameters +and local variables are not entered into the scope of the call until the end of +the operation. If an inlining operation fails, the original call is left in +place and the routine is marked as requiring an out-of-line copy. (An +out-of-line copy is also required if the address of the routine was taken.) If +inlining of a call fails because of something that precludes all inlining of +the function, the inlinable flag of the routine is cleared so no further +attempts will be made. If the inlining operation failed only because of the +context (e.g., the function includes a loop and the call is inside an +expression), the inlinable flag is left TRUE.

    +

    As the function body is copied with substitution for the parameters and local +variables, new constant expressions may be created. That is, when a constant +argument is passed for an unmodified parameter, the references to the parameter +in the function body are replaced by the proper constant value. That may +produce operations whose operands are constant (e.g., p + 1 becomes 1 + +1, which can be simplified to 2).

    +

    This substitution and folding is done by +adjust_copied_expression_for_inlining, which is called from +copy_expr_tree as each node in the tree is copied. The list of remappings +to be done is built by set_up_variable_remapping_for_inlining and pointed +to by the static variable variable_remappings_for_inlining. +get_var_remapping_for_inlining consults the list to find the applicable +remapping for a variable.

    +

    More dramatic simplification is possible for short-circuiting operators like +“?” and for if statements (whether they are rewritten in expression +form or not). If the tested expression is constant, parts of the expression +tree or statement tree are discarded accordingly. For example, when parameter +p is replaced by 1,

    +
    p ? i : (j + 1)
    +
    +
    +

    becomes simply i, and

    +
    if (p > 0) i = 1; else i = 2;
    +
    +
    +

    becomes simply i = 1. This is handled by +copy_and_simplify_short_circuited_operation for the operator cases, and in +expand_statement_inline for the if statement.

    +

    Arguments can be considered to be constant even if they are not literally +constants. For example, the address of a local variable is not a compile-time +constant, but it is constant over the duration of a call, and therefore can be +considered constant-valued for purposes of parameter remapping.

    +

    The this parameter of constructors is given special treatment so that the +allocation sequence at the beginning of constructors will be eliminated when +the constructor is operating on a known variable. According to the normal +parameter rules, this in a constructor is modified within the function and +therefore a temporary must be used. However, we know how constructors work, +and if there is no assignment to this in the constructor we know the only +modification is one that will be eliminated when the constructor is called with +a non-null argument for this. In such cases, the this parameter is +remapped directly to a constant, and the allocation sequence is eliminated by +the normal short-circuit optimization.

    +
    +
    +

    5.2.29. Lowering thread_local#

    +

    The thread_local keyword was added in C++11 and the dynamic initialization +and destruction of objects with thread_local storage requires lowering +support.

    +

    If the back end has the capability to execute code at thread creation time, +then it is most efficient to set the configuration macro +USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES to FALSE in which +case lowering creates one or more initialization routines (depending on the +setting of SEPARATE_ROUTINES_FOR_FILE_SCOPE_DYNAMIC_INITS) for each +dynamically-initialized variable with thread_local storage in the +translation unit and sets il_header.thread_local_dynamic_init_routines to +point to the list (in the proper order). It is the responsibility of the back +end to ensure that this list of routines is invoked at thread creation time.

    +

    In most cases, however, the compiler won’t have the capability to execute code +at thread creation time, in which case +USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES should be set to +TRUE. In such configurations, each use of an object with thread_local +storage duration that may be dynamically initialized is re-written to invoke +the “wrapper” routine for the object (see lower_thread_local_variable). +Lowering creates a “wrapper” routine (see +thread_local_wrapper_for_variable) that invokes an “initialization” routine +(if one exists) and then returns a pointer to the thread_local object. +This ensures that each thread_local object is properly initialized (though +at considerable run-time cost). Mangled names for wrapper routines contain the +mangled name of the thread_local object along with a prefix ( _ZTW in +the IA-64 ABI and __TWR__ in the Cfront ABI).

    +

    Note that although “wrapper” routines are only required for dynamically +initialized thread_local variables, the lack of “wrapper” routines for +thread_local variables with external linkage that are not dynamically +initialized results in a non-compliant implementation (i.e., the standard +requires that all thread_local variables be initialized before the first +odr-use of any thread_local variable, but the use of a statically +initialized thread_local circumvented the initialization process). As a +result, the all_thread_locals_have_wrappers global variable was introduced +in 4.10, and when set to TRUE, results in standard compliant behavior. The +previous behavior matches g++’s behavior and is achieved by setting +all_thread_locals_have_wrappers to FALSE.

    +

    The “initialization” routines that wrappers call perform the actual +initialization for the thread_local objects (and incorporate a +thread_local guard variable to ensure the initialization is performed only +once per thread). When the back end supports weak references, +LAZY_INITIALIZATION_USES_WEAK_REFERENCES should be set to TRUE, in +which case each “initialization” routine is aliased to the __tls_init +routine that initializes that particular thread_local object. In cases +where a thread_local object is used in one translation unit and defined in +another, a reference to an initialization routine is created in the first +translation unit but there may or may not be a definition for the +initialization routine in the second routine (it will be aliased to the +__tls_init routine in that translation unit only if the thread_local +object is dynamically initialized). When weak references are used wrapper +routines need to allow for the case where an initialization routine is +NULL. For back ends that do not support weak references, a do-nothing +initialization routine is created for this case (see +make_null_thread_local_init_routine_for_variable). Mangled names for +initialization routines contain the mangled name of the thread_local object +along with a prefix (_ZTH in the IA-64 ABI and __THI__ in the Cfront +ABI).

    +

    The __tls_init routines themselves (or __tls_init_N in +one-instantiation-per-object mode) are created during the lowering of +file-scope dynamic initializations (see Dynamic Initialization).

    +

    In a manner similar to the handling of destructions of static entities, +destructions of file-scope objects with thread_local duration are +registered with the run-time library through calls to __cxa_thread_atexit +(for the IA-64 ABI) or __record_needed_thread_destruction (for the Cfront +ABI). The run-time library is then responsible for invoking these destructors +when the thread terminates (see record_needed_destruction).

    +
    +
    +

    5.2.30. Lowering ifunc#

    +

    The GNU ifunc attribute maps to the STT_GNU_IFUNC symbol type in the +ELF standard and is not available on many architectures. The STT_GNU_IFUNC +symbol type allows a routine’s symbol to be determined dynamically at load +time. At load time, the routine specified as the resolver (in the ifunc +attribute) is invoked (once) and returns a pointer to the routine that will be +used to resolve all instances of that symbol for that execution of the +executable. This provides a very low overhead mechanism to select one of a +family of functions (typically based on the underlying CPU architecture). +Here’s an example (with --gcc --gnu_version 40600):

    +
    int printf(const char *,...);
    +void target() {
    +  printf("Here\n");
    +}
    +static void (*resolver(void))(void) {
    +  return (void(*)(void))&target;
    +}
    +void source() __attribute__ ((ifunc ("resolver")));
    +int main() {
    +  source();   // Prints "Here"
    +}
    +
    +
    +

    For back ends that don’t support the STT_GNU_IFUNC symbol, an approximation +of the run-time behavior can be achieved by setting LOWER_IFUNC to +TRUE. In that case, lowering will convert the routine with the ifunc +attribute into a “wrapper” routine as such:

    +
    decltype(source) resolver_result = source;
    +source(args...) {
    +  if (resolver_result == source) {
    +    resolver_result = (decltype(source))resolver();
    +  }
    +  return *resolver_result(args...);
    +}
    +
    +
    +

    This has the effect of invoking the resolver only once (though at run time +rather than at load time). Invocations of source incur an extra function +call and indirection, but lowering re-writes references to source so they +are dispatched through the resolver variable whenever possible (in which case +the only overhead is an extra indirection).

    +

    Note that there are a few caveats:

    +
      +
    • +
      The re-writing of calls to avoid the wrapper routine only occurs once the +declaration with the ifunc attribute has been seen; any reference prior +to that point will be unlowered (and will hence invoke the wrapper). That +can be an issue if, for example, the declaration with the ifunc +attribute is only in a library’s implementation (and not in the shared +header file). In that case, code that is compiled with the shared header +file will contain references to the wrapper routine.
      +
      +
    • +
    • +
      Constants (i.e., ck_address/abk_routine) that refer to the +ifunc are not re-written in lowering, so they’ll always point to the +wrapper routine.
      +
      +
    • +
    +

    See lower_ifunc_routine and lower_ifunc_expr for more information.

    +
    +
    +

    5.2.31. Lowering GNU function multiversioning#

    +

    GNU supports function multiversioning in version 4.8.0 and later via the +target attribute in C++ mode. Detailed documentation is available here: +http://gcc.gnu.org/wiki/FunctionMultiVersioning. The target attribute +allows multiple versions of a function definition to be supplied, and the +choice of which version to call is determined at load time based on +characteristics of the machine where the program is running. The choice is +made by a compiler-generated (when lowering is enabled) “resolver” routine that +selects the best routine from the target-specific versions. The resolver +routine is executed once at load time (because it is associated with an +ifunc routine) to determine which target-specific routine to use for the +particular CPU. For back ends that don’t support ifunc, see +LOWER_IFUNC.

    +

    For example (assuming USE_X86_FUNCTION_MULTIVERSIONING is TRUE, with--gnu_version 40800):

    +
    __attribute__ ((target("default")))     int foo () { return 222; }
    +__attribute__ ((target("arch=corei7"))) int foo () { return 777; }
    +__attribute__ ((target("avx")))         int foo () { return 333; }
    +int main () {
    +  int (*fp)() = foo;
    +  return fp() != foo();
    +}
    +
    +
    +

    Would generate lowered pseudo-code like this:

    +
    int foo_default () { return 222; }  // "default" foo
    +int foo_corei7 () { return 777; }   // "corei7" foo
    +int foo_avx () { return 333; }      // "avx" foo
    +// Resolver function returns address of specific function
    +static (int *foo.resolver()) { // lowering-generated resolver function
    +  resolved_foo = // one of foo_default, foo_corei7, foo_avx
    +  return resolved_foo;
    +}
    +int foo.ifunc() __attribute__((ifunc("foo.resolver"));
    +int main () {
    +  int (*fp)() = foo.ifunc;    // &foo lowered to &foo.ifunc
    +                              // Dynamic loader invokes foo.resolver
    +                              // to select which specific foo.
    +                              // foo.ifunc is invoked once during
    +                              // startup.
    +  return fp() != foo.ifunc(); // call of foo is lowered to foo.ifunc
    +}
    +
    +
    +

    Note that at present, lowering is only performed when +USE_X86_FUNCTION_MULTIVERSIONING is TRUE (the rules that are used to determine +at run-time which of a set of target-specific functions are machine-specific +and only the x86 case is implemented).

    +

    See lower_mv_routine, lowered_mv_routine, and create_mv_resolver.

    +
    +
    +
    +

    5.3. How is IL Lowering Done?#

    +
    +

    5.3.1. Sequencing#

    +

    All the individual transformations done by IL lowering are relatively +straightforward. What makes the job of IL lowering so difficult is the fact +that it must operate under some very difficult sequencing constraints.

    +

    They come about because IL lowering must be done on a per-function basis, so +that individual memory regions can be lowered and then written to a file. That +means that when function scope memory regions are lowered, the file scope +entities that they reference are not yet lowered. And they cannot be: since +the file-scope entities are still active entities in the compilation, if they +were modified by IL lowering it would disturb the rest of the compilation.

    +

    To pick an example: to lower a virtual function call in a function scope, one +needs to be able to reference the virtual function pointer field in the class +entity. That field is added by IL lowering. But the class type is in the file +scope memory region, and therefore has not yet been lowered at the time the +virtual function call is lowered.

    +

    Another example: IL lowering changes reference types into pointer types. +However, mangled names of functions must be based on the original types, +including reference types. Therefore, mangled names must be generated before +reference types are changed to pointer types.

    +

    Another example: the variable that contains a virtual function table must be +available when constructors and destructors for classes are lowered. However, +it is not possible to know at that point in the compilation whether or not the +definition of the virtual function table should be put out. In fact, it’s not +possible to tell whether it should be internal or external. Therefore, virtual +function table variable definitions cannot be done at the time the variable +declarations are done.

    +

    In short, lots of processing that would be fairly straightforward if the entire +IL tree could be lowered at once becomes convoluted because some parts of the +tree have already been lowered, some haven’t, some cannot be yet, etc.

    +

    One technique that helps is the concept of “prelowering” classes. This is +processing that’s done as soon as possible on completed class definitions. It +does not modify the class, but it adds information that is needed to use the +class in lowering code:

    +
      +
    • +
      The type-as-subobject (a copy of the type with any virtual base classes +removed).
      +
      +
    • +
    • +
      The fields that make the base classes, virtual base class pointers, and +virtual function table pointer of the class explicit. (Note that this +change affects the field list of the type, which would seem to be a +modification; however, since the fields are not in the symbol table, they +cannot be found by the front end. It does mean that front end code should +not traverse the field list to visit all the fields. It should use the +symbol list instead.)
      +
      +
    • +
    • +
      Variables for virtual function tables. These are all created as extern +declarations, and they are changed to definitions or to static variables +later if that is appropriate.
      +
      +
    • +
    +

    See prelower_class_type.

    +

    Another technique is to not clear C++-specific fields when they are +lowered, where that’s possible. One example: the implicit “this” +parameter type in a routine type entry becomes an explicit first parameter +type when lowered. However, the pointer to the implicit type is not +cleared. That allows code that wants to see whether or not a function is a +nonstatic member function to fetch the “this” parameter type without having +to know whether or not the type has already been lowered. One consequence +of this technique is that back ends cannot count on having the C++-specific +fields cleared, and should therefore not look at them.

    +
    +
    +

    5.3.2. The IL Lowering Flag#

    +

    The IL lowering flag is a two-state flag that appears in the prefix that +precedes each IL entry. It is flipped from 0 to 1 when the associated entry is +visited during IL lowering. This allows IL lowering to know that it has +already processed a given entry and thereby avoid looping when there are cycles +in the IL graph.

    +

    This flag is similar to the il_walk_flag used by the IL walk routines, but +is kept separate so that IL lowering is not forced to visit all of the IL tree +even if it knows that certain parts cannot contain entries that will be +modified by lowering. It should be noted that even though every entry has a +flag, not all entries’ flags are maintained by IL lowering. For example, IL +lowering does not maintain the flag on expression nodes, because it knows that +it will visit each expression node exactly once.

    +

    Why not use the standard IL walk routines to do the traversal? The problem is +that the IL walk routines cannot co-exist with processing that changes the +structure of the IL tree. Since IL lowering can eliminate entries, move them +around, add entries, and swap entries, the IL walk routines could get into +loops, get lost, or process entries more than once. Therefore they are not +suitable, and IL lowering has its own IL traversal code.

    +
    +
    +

    5.3.3. Orphaned Entries#

    +

    Type entries and static variables that are local to a function require some +special handling. All type entries and all static variables are allocated in +the file scope memory region. However, types and static variables that are +local to a function are placed on the types and static variables list of a +function or block scope. Those are unusual lists: the function scope entries +(in a function scope memory region) point to lists that are entirely in the +file scope memory region. Yet, the entries pointed to are not really part of +the file scope. They might, in fact, not be referenced from anywhere except +the function scope memory region. Such entries are “orphaned” in the file +scope: their parents are processed, written out, and removed from memory, but +the children remain in the file scope, unattached to the rest of the file scope +IL tree.

    +

    There is special processing in the IL write, read, and walk routines to deal +with such orphans, but special handling is also required in IL lowering.

    +

    Such entries clearly must be lowered at some point. Do we lower them when the +function scope is lowered, or do we lower them when the file scope is lowered? +Well, lowering them with the function scope is impractical, since it’s hard to +tell which of the file-scope references are orphans and which are not. Even if +we know that a static variable, say, is an orphan, how much of its subtree do +we process? Is its type an orphan, or just a normal file-scope type?

    +

    So it’s easier not to do lowering on orphans. The processing then lowers +entries in the function scope, and leaves all those in the file scope alone. +Whenever a pointer hops into the file scope memory region, IL lowering leaves +that entry alone, regardless of whether or not it might be an orphan.

    +

    This solves one problem but creates another. If there truly are orphaned +entries, how will the IL lowering for the file scope find them to lower them? +The answer is that orphans or potential orphans are recorded on a special list, +using support routines and data structures provided by the IL support +components. When a pointer hops into the file scope memory region, the entry +pointed to is recorded as a potential orphan, and at the end of the lowering +for the file scope all the orphans are visited. If they turn out not to be +orphans, the IL lowering flag will indicate that they have already been visited +and they will not be processed again.

    +

    See lower_orphaned_entries.

    +
    +
    +

    5.3.4. Maintained Context#

    +

    While IL lowering works through a top-level scope, it maintains a stack that +shows the nesting of scopes for the present position (the spot for which +lowering is being done). This makes it easy to find the innermost enclosing +scope or the innermost enclosing function at any given moment, for example to +create a temporary in the innermost scope. The global variable +curr_context points to the top of the context stack.

    +
    +
    +

    5.3.5. Object Lifetimes#

    +

    The object lifetime entries in the IL provide information about regions of the +program on exit from which automatic destructions of class objects are done. +The destructions to be done appear in a list attached to the object lifetime +entry (in the form of dynamic initialization entries). IL lowering uses this +information to insert destructor calls on exit from those regions (whether by +flowing off the end of the region or branching out of it via a goto or the +like), and to build region table information for exception handling.

    +

    As IL lowering works through the IL, it keeps track of the current position in +cleanup terms, which is to say the latest initialization encountered that +requires automatic destruction. This is maintained in the +latest_initialization field of the current context. Given the pointer to +the latest initialization, gen_cleanup_actions and its subroutines can walk +up the cleanup chain, generating the appropriate destructions. In the case of +a return, the walk up the chain continues until the lifetime for the +function scope is reached. In the case of a goto, the cleanup continues +until the lifetime indicated in the goto statement is reached (that +lifetime is determined by the front end, and is the innermost lifetime that the +goto and the label have in common).

    +

    At the beginning of lowering of a block, the object lifetime for the block and +for any expression-temporary lifetimes immediately within it are processed. +This processing (which is performed by begin_object_lifetime) involves +allocating an entry of type a_destructible_entity_descr and attaching it to +each dynamic initialization on the lifetime destructions lists. These entries +are used to record information that will be needed when generating the +initialization and the later destruction. In particular, the position of the +entity (in initialization position form; see below) is determined and recorded +in the entry at the time of initialization. That position is then used when +generating the destruction code. The beginning-of-lifetime processing also +includes deciding whether the entity will require a conditional flag to +indicate that the construction has been done. If one is required, the variable +for it is created and code to initialize it to zero is inserted.

    +

    At the beginning of block-after-label lifetimes, similar processing is done, +but it takes a bit of effort to get it done at the right time, because there is +no explicit indication of a new lifetime on a statement that ushers in a +block-after-label lifetime. One must note, at the beginning of the previous +block or block-after-label lifetime, the next block-after-label lifetime in +sequence, and watch for the appearance of the associated statement during the +normal processing of statements. Also at labels (including switch case +labels), long lifetime temporaries must be destroyed (and when exceptions are +enabled, the region table is adjusted accordingly). (For this reason, +block-after-label lifetimes can begin at stmk_switch_case statements in +long-lifetime-temporaries mode.)

    +
    +
    +

    5.3.6. Initialization Positions#

    +

    an_init_pos_descr is used to contain a description of a position within an +initialization. As an aggregate initialization is processed, such a +description is maintained for the current position. The description can then +be turned into an expression that addresses the indicated position, which is +necessary when generating code to initialize pieces of aggregates:

    +
    int j;
    +void f() {
    +  struct {int i; int j;} k[2] = {{1, 1}, {j+1, 2}};
    +}
    +
    +
    +

    becomes

    +
    int j;
    +void f() {
    +  struct {int i; int j;} k[2] = {{1, 1}, {0, 2}};
    +  k[1].i = j+1;
    +}
    +
    +
    +
    +
    +

    5.3.7. Insert Locations#

    +

    Many transformations work by inserting new pieces of code into expressions or +statement lists. The insert location for such insertions is described by a +structure of type an_insert_location. It can describe an insert location +either within an expression or within a sequence of statements. The code +inserted is typically in units of “statements”, even when the insertion is +within expressions. That is, a lowering routine would assemble something like +temp = 1 and that construct would be inserted, either as a free-standing +expression statement, or as a clause in a comma operation added within an +expression. For the expression insertion case, for example,

    +
    i ? (void)A(i) : (void)0
    +
    +
    +

    might be modified by insertion of an assignment:

    +
    i ? (temp = 1, (void)A(i)) : (void)0
    +
    +
    +

    Since the insertion is done in statement units, the callers of the insert +routines need not in general be concerned about whether or not the insert +location is in an expression or a statement. The low-level routines do the +necessary adjustment, including rendering conditional tests as if +statements or “?” operators.

    +

    See

    +
      +
    • +
      insert_expr
      +
      +
    • +
    • +
      insert_statement
      +
      +
    • +
    • +
      insert_if_statement
      +
      +
    • +
    +
    +
    +

    5.3.8. Reusable Copies#

    +

    There are a few cases where an expression that is used once in the original IL +tree is used more than once in the lowered IL tree. Without special handling, +such cases might cause problems if the expression involved has side effects. +The routine make_reusable_copy solves the problem: given an expression +tree, it returns a distinct expression tree that produces the same value. If +the original tree has no side effects, it is simply copied. If it has side +effects, the original expression is modified to assign the expression value to +a temporary, and the new copy is simply a reference to the temporary.

    +

    Note that the new copy does not replace the original expression. The original +expression continues to be used in its original location, and the copy is used +for the second reference. Further copies can be made from either of the +expressions.

    +

    make_lvalue_reusable_copy does a similar operation for expressions that are +lvalues. It handles bit-field lvalues specially.

    +
    +
    +
    +

    5.4. Lowering C Dialects#

    +

    In some newer C modes like C99 or GNU C mode, some features create IL +constructs that are not used in IL for C89. In order to make things easier for +back ends, the front end includes a C lowering phase, which can rewrite many +(but not all) of these newer C constructs. Many (but not all) of the +additional IL features are enabled by C99_IL_EXTENSIONS_SUPPORTED. Most of +the code for this lowering is in lower_c99.c, with related declarations in +lower_c99.h.

    +
      +
    • +
      For compound literals, the generated enk_temp_init node is rewritten as +an initialized generated variable. See lower_c99_temp_init.
      +
      +
    • +
    • +
      Designated initializers are processed to produce a C89-style aggregate +initializer. This is done outside of the primary C99 lowering phase, and +is enabled by LOWER_DESIGNATED_INITIALIZERS. ck_designator +constants remain in the IL after this lowering for initializations of +members other than the first in unions, which are not expressible in C89 +IL. See lower_designated_initializers. Note that there are some +advantages to not doing this lowering and instead handling the designators +in a back end, notably that that can avoid some very large IL structures +for big sparsely-initialized arrays.
      +
      +
    • +
    • +
      The _Bool type is unchanged, but a C89 view of the IL does not consider +the bool_type flag and therefore sees the underlying integer. Compound +assignment operators whose left-hand operand has type _Bool are +rewritten to ensure that the result value is restricted to 0/1, via the +same routines that do this processing in C++ lowering; see +rewrite_compound_assignment. Boolean casts are also handled as in C++; +see bool.
      +
      +
    • +
    • +
      Complex types are rewritten as structs, imaginary types are rewritten as +floating-point types, complex constants are rewritten as aggregate +initializers, imaginary constants are rewritten as floating-point +constants, and operators and conversions on complex and imaginary types are +rewritten as runtime routine calls. This is controlled by +LOWER_COMPLEX. See lower_c99_nonreal_float_types, +lower_c99_complex_cast, and lower_c99_operator. Also see the file +c99_complex.c in the runtime library for descriptions and sample +implementations of the complex runtime routines. Note that a back end +could treat the runtime routines as intrinsics and generate machine +instructions directly for the calls. (Again, the C99-centric names are +historical: These routines also handle complex types appearing in GNU C +source.)
      +

      +
      For compound assignment operators, the operation is rewritten in terms +of the underlying operation, and the result is then converted and +stored in the destination variable (e.g., x += y is rewritten as +x = x + y). If the left side is an expression with side effects, +its address is evaluated and stored in a temporary, and the two +references to the left hand side (to fetch its value as as input to the +operation, and to store the result) are done by way of indirection +through the temporary. See rewrite_compound_assignment.
      +
      +
    • +
    • +
      If LOWER_FIXED_POINT is TRUE, fixed-point operations, types, and +constants are rewritten into standard C. Fixed-point types are lowered to +typedefs for appropriately-size integral types (see +lower_c99_fixed_point_types). Fixed-point constants are lowered to +integral constants (see lower_c99_fixed_point_constant). Fixed-point +operations and conversions are lowered to calls to runtime routines (see +lower_c99_fixed_point_operation, lower_c99_fixed_point_cast, +lower_c99_fixed_point_incr_decr, and rewrite_compound_assignment). +The runtime routines are not provided by EDG; they are available from +Dinkumware, Ltd. There is a long comment beginning with “Fixed-point +lowering:” in lower_c99.c that gives more details on the runtime +interface.
      +
      +
    • +
    • +
      When LOWER_VARIABLE_LENGTH_ARRAYS is TRUE variable-length arrays (VLAs) +are rewritten as pointers to storage allocated by the run-time library. +Storage for a VLA is allocated by a call to __vla_alloc, which is +produced by the lowering of certain stmk_vla_decl statements. The +storage is freed by calls to __vla_dealloc, which are the result of +lowering enk_vla_dealloc expression nodes (which may be produced +directly by the front end in C modes, or as the result of IL lowering in +C++ modes).
      +

      +
      A VLA type can be defined recursively to be either an array type with a +nonconstant bound, or a normal (constant-bound) array whose element is +a VLA type. The lowering process eventually replaces all VLA types and +pointer to VLA types by pointer types pointing to the underlying +(non-array) element type of the VLA type. For example, the type int +[3][n][4] is replaced by int* and the type +double*(*)[3][n][4] is replaced by double**. To avoid certain +subtle ordering problems, this type replacement is done in two stages. +First, all VLA types are collected on a linked list (see +record_vla_component_types_for_lowering) during the main C99 IL +lowering traversal (this is necessary because these types may only be +pointed to from an expression node, unlike, e.g., class types which are +listed on a scope’s type list). After the main tree traversal, the +actual replacement is done by a call to the function +lower_vla_types.
      +

      +
      The length of VLA types must in general be computed at run time. This +is achieved by evaluating the array bound expression and storing the +result in temporary helper variables. To further simplify the VLA size +computations in expressions, these variables are updated to hold a +total count of the number of (non-array) elements for a particular VLA +type component. For example, the type char[n][m] would produce two +variables, one holding the value m and the other holding the value +n*m. Once created, the IL entries for these variables can be +accessed through the a_vla_dimension entries of the associated VLA +type components. For VLA types appearing in explicit declarations +(variable declarations and typedef declarations), the front end adds +adds explicit stmk_set_vla_size statement indicating when the value +of these variables ought to be computed. However, in expression +contexts that introduce new VLA types (sizeof and cast expressions, +as well as compound literals) there are no such statements. Either +way, the bulk of the work to produce and compute these variables is +done in lower_vla_dimensions, which creates all the necessary +variables for an arbitrarily complex VLA type and returns an expression +that sets all the variables to their required values.
      +

      +
      With those variables available, the lowering of various array-related +operations (subscripting, pointer arithmetic, and run-time sizeof +expressions) is relatively straightforward. There is a long comment +near the beginning of lower_c99.c (conditioned on +LOWER_VARIABLE_LENGTH_ARRAYS) that gives more details on the + lowering of VLAs.
      +
      +
    • +
    • +
      Extended identifiers containing universal character names (\uxxxx), +whose name strings contain the \u etc., are rewritten as standard +identifiers if REWRITE_UCN_ESCAPE_CHAR_IN_LOWERING is TRUE. The +“\” character is changed to “_”. This is the same processing that +is done in C++ lowering.
      +
      +
    • +
    • +
      Non-constant expressions in aggregate initializers, i.e., those indicated +by ck_dynamic_init constants, are rewritten as executable code. This +is done via the same routines that do this processing in C++ lowering. See +lower_c99_stmk_init.
      +
      +
    • +
    • +
      Inline function calls are replaced by their expansions if +MINIMAL_INLINING is TRUE. This is done via the same routines that do +this processing in C++ lowering.
      +
      +
    • +
    • +
      Boolean controlling expressions are optionally normalized to always yield +an integer value of 0 or 1. This transformation occurs even in C89 mode +(and the same processing is done in C++ mode).
      +
      +
    • +
    +

    Some features are not lowered but use IL constructs that exist in IL produced +by lowering C++, which a back end is likely already to accept:

    +
      +
    • +
      For mixed statements and declarations, the statements and declarations +appear intermixed in the statement list of a compound statement.
      +
      +
    • +
    • +
      For longlong, there are two new integer kinds (ik_long_long +and ik_unsigned_long_long) and new constants of these kinds.
      +
      +
    • +
    +

    One feature is not lowered at all:

    +
      +
    • +
      For flexible array members, the last member of a struct type may have an +array type with an unknown bound. This probably does not require special +processing in a back end.
      +
      +
    • +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/modules/index.html b/dev/doc/modules/index.html new file mode 100644 index 0000000..0b57f07 --- /dev/null +++ b/dev/doc/modules/index.html @@ -0,0 +1,2085 @@ + + + + + 16. Modules - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    16. Modules#

    +

    The EDG modules implementation is based upon the Microsoft IFC specification.

    +

    The EDG front end has experimental support for both the IFC variant produced by +Microsoft’s Visual Studio compiler and an EDG variant produced by the EDG front +end.

    +
    +

    16.1. Roles#

    +

    To make the system work, every IFC type is understood in terms of a “role”. The +type’s role in effect defines what semantics it will be generated with.

    +

    The roles are as follows:

    +
      +
    • Simple Sort - Any kind of enumeration of named values +unrelated to an index.

    • +
    • Index Sort - A “sort” that encodes a simple sort and an +associated index (e.g., DeclIndex is the “Index Sort”, with a “Simple +Sort” DeclSort).

    • +
    • Bitfield - Any IFC type that encodes things using bit flags.

    • +
    • Raw Numeric - Any IFC type that is an integer with no +associated implicit interpretation (from a format perspective, it’s just a +“dumb” number).

    • +
    • Raw Bytes - Similar to Raw Numeric, anything that’s just a +raw byte array.

    • +
    • +
      Nodes
        +
      • Partition Node - An IFC Node that can be directly read +from a partition, for instance a DeclFunction.

      • +
      • Basic Node - An IFC Node that only appears as a +sub-node (doesn’t have a partition of its own), for instance, a +ModuleReference.

      • +
      • Header Node - Basically what it says, an IFC Node that’s +part of the header (FileHeader and Partition).

      • +
      +
      +
      +
    • +
    • Foreign Index - A special role for IFC types that represent +an Index in another module file.

    • +
    • Value Category - A role representing several levels of +discriminated values (conceptually similar to an IFC std::variant)

    • +
    +
    +

    16.1.1. Simple Sort#

    +

    Simple sorts are represented as an enum (sorted in alphabetical order):

    +
    enum an_ifc_access_sort {
    +  ifc_as_none,
    +  ifc_as_private,
    +  ifc_as_protected,
    +  ifc_as_public
    +};  /* an_ifc_access_sort */
    +
    +
    +

    Simple sorts can also be converted to a c-string of their respective EDG name +via a call to the respective str_for function. This can be useful for +debugging and diagnostic purposes.

    +
    +
    +

    16.1.2. Index Sort#

    +

    Index sorts are represented as an index type (a struct with a module binding, +an associated Simple Sort value, and the associated index +value):

    +
    enum an_ifc_decl_sort {
    +  ifc_ds_decl_alias,
    +  ifc_ds_decl_barren,
    +  ifc_ds_decl_bitfield,
    +  ifc_ds_decl_concept,
    +  ifc_ds_decl_constructor,
    +  ifc_ds_decl_deduction_guide,
    +  ifc_ds_decl_destructor,
    +  ifc_ds_decl_enumeration,
    +  ifc_ds_decl_enumerator,
    +  ifc_ds_decl_expansion,
    +  ifc_ds_decl_explicit_instantiation,
    +  ifc_ds_decl_explicit_specialization,
    +  ifc_ds_decl_field,
    +  /* snip */
    +};  /* an_ifc_decl_sort */
    +
    +/*
    +The universal representation for an IFC DeclIndex.
    +*/
    +struct an_ifc_decl_index {
    +  an_ifc_module*
    +                mod;
    +                        /* The associated module. */
    +  an_ifc_decl_sort
    +                sort;
    +                        /* The associated DeclSort value for this index. */
    +  uint32_t      value;
    +                        /* The index value into the associated partition of
    +                           "sort" for this index.  Represented as the
    +                            largest common underlying type. */
    +};  /* an_ifc_decl_index */
    +
    +
    +
    +
    +

    16.1.3. Bitfield#

    +

    Bitfields are represented as a bitfield type (a struct with a module binding +and the raw value pulled from the module file):

    +
    /*
    +The universal representation for an IFC FunctionTraitsBitfield.
    +*/
    +struct an_ifc_function_traits_bitfield {
    +  an_ifc_module*
    +                mod;
    +                        /* The associated module. */
    +  an_ifc_function_traits_bitfield_storage
    +                value;
    +                        /* The raw bit value obtained from the module.
    +                           Represented as the largest common underlying
    +                           type. */
    +};  /* an_ifc_function_traits_bitfield */
    +
    +
    +

    This is then paired with a (alphabetically sorted) set of bit queries.

    +
    enum an_ifc_function_traits_bitfield_query : uint32_t {
    +  ifc_ftb_constexpr     = 1 << 0,
    +  ifc_ftb_constrained   = 1 << 1,
    +  ifc_ftb_defaulted     = 1 << 2,
    +  ifc_ftb_deleted       = 1 << 3,
    +  ifc_ftb_explicit      = 1 << 4,
    +  ifc_ftb_hidden_friend = 1 << 5,
    +  ifc_ftb_immediate     = 1 << 6,
    +  ifc_ftb_inline        = 1 << 7,
    +  ifc_ftb_no_return     = 1 << 8,
    +  ifc_ftb_none          = 1 << 9,
    +  ifc_ftb_pure_virtual  = 1 << 10,
    +  ifc_ftb_virtual       = 1 << 11
    +};  /* an_ifc_function_traits_bitfield_query */
    +
    +
    +

    A bitmask can then before formed and tested on a bitfield like so:

    +
    an_ifc_function_traits_bitfield bitfield = ...;
    +
    +if (test_bitmask<ifc_ftb_immediate | ifc_ftb_explicit>(bitfield)) {
    +  /* matched bitfield & (ifc_ftb_immediate | ifc_ftb_explicit) */
    +} else {
    +  /* didn't match */
    +}  /* if */
    +
    +
    +
    +
    +

    16.1.4. Raw Numeric#

    +

    Raw numerics are represented as a raw numeric type (a struct with a module +binding and the raw value pulled from the module file, along with a convenience +conversion operator):

    +
    /*
    +The universal representation for an IFC Index.
    +*/
    +struct an_ifc_index {
    +  an_ifc_module*
    +                mod;
    +                        /* The associated module. */
    +  an_ifc_index_storage
    +                value;
    +                        /* The raw bit value obtained from the module.
    +                           Represented as the largest common underlying
    +                           type. */
    +
    +  inline operator an_ifc_index_storage() const
    +    { return this->value; }
    +};  /* an_ifc_index */
    +
    +
    +

    Thus, the value itself can be passed around safely without concern of changes +in the underlying type, and with access to the module, while being trivial to +work with as an unsigned number:

    +
    an_ifc_index power_idx = ...;
    +
    +if (power_idx > 9000) {
    +  /* panic */
    +}  /* if */
    +
    +
    +
    +
    +

    16.1.5. Raw Bytes#

    +

    Types generated from the raw bytes role are derived from +Byte Buffers.

    +
    /*
    +The universal representation of an IFC SHA256 node.
    +
    +The representation is declared as a derived struct of an_ifc_Byte_buffer
    +rather than simply an alias of the instantiation to improve the debugger
    +experience.
    +*/
    +struct an_ifc_sha256 : an_ifc_Byte_buffer<an_ifc_sha256_storage> {
    +  using storage_type = an_ifc_sha256_storage;
    +  using base_type = an_ifc_Byte_buffer<storage_type>;
    +  using base_type::an_ifc_Byte_buffer;
    +};  /* an_ifc_sha256 */
    +
    +
    +

    These types also include an additional table documenting the number of bytes +available (starting from a specific version). For example, if a type has +32 bytes starting with version 0.33, and that doubles to 64 bytes in 0.41 +the following table will be written:

    +
    |----------------|
    +| Version | Size |
    +|---------|------|
    +| 0.33    | 32   |
    +| 0.41    | 64   |
    +|---------|------|
    +
    +
    +
    +
    +

    16.1.6. Nodes#

    +

    The node roles (Partition Node, Basic Node, and +Header Node) are all very similar, differing only in their +construction.

    +

    The node types are – similarly to Raw Bytes types – derived +from Byte Buffers.

    +
    /*
    +The universal representation of an IFC DeclFunction node.
    +
    +The representation is declared as a derived struct of an_ifc_Byte_buffer
    +rather than simply an alias of the instantiation to improve the debugger
    +experience.
    +*/
    +struct an_ifc_decl_function :
    +                          an_ifc_Byte_buffer<an_ifc_decl_function_storage> {
    +  using storage_type = an_ifc_decl_function_storage;
    +  using base_type = an_ifc_Byte_buffer<storage_type>;
    +  using base_type::an_ifc_Byte_buffer;
    +};  /* an_ifc_decl_function */
    +
    +
    +

    Additionally, – again similarly to Raw Bytes types – node +types include a descriptive table to aid in development:

    +
    |------------------------------------------------------------|
    +|               DeclFunction - 0.33 (32 bytes)               |
    +|-------------|-----------------------------|---------|------|
    +| Name        | Type                        | Version | Size |
    +|-------------|-----------------------------|---------|------|
    +| name        | NameIndex                   | 0.33    | 4    |
    +| locus       | SourceLocation              | 0.33    | 8    |
    +| type        | TypeIndex                   | 0.33    | 4    |
    +| home_scope  | DeclIndex                   | 0.33    | 4    |
    +| chart       | ChartIndex                  | 0.33    | 4    |
    +| traits      | FunctionTraitsBitfield      | 0.33    | 2    |
    +| specifiers  | BasicSpecifiersBitfield     | 0.33    | 1    |
    +| access      | AccessSort                  | 0.33    | 1    |
    +| properties  | ReachablePropertiesBitfield | 0.33    | 1    |
    +| __padding__ | uint8_t[3]                  |         | 3    |
    +|-------------|-----------------------------|---------|------|
    +
    +|------------------------------------------------------------|
    +|               DeclFunction - 0.41 (32 bytes)               |
    +|-------------|-----------------------------|---------|------|
    +| Name        | Type                        | Version | Size |
    +|-------------|-----------------------------|---------|------|
    +| name        | NameIndex                   | 0.33    | 4    |
    +| locus       | SourceLocation              | 0.33    | 8    |
    +| type        | TypeIndex                   | 0.33    | 4    |
    +| home_scope  | DeclIndex                   | 0.41    | 4    |
    +| chart       | ChartIndex                  | 0.33    | 4    |
    +| traits      | FunctionTraitsBitfield      | 0.33    | 2    |
    +| specifiers  | BasicSpecifiersBitfield     | 0.33    | 1    |
    +| access      | AccessSort                  | 0.33    | 1    |
    +| properties  | ReachablePropertiesBitfield | 0.33    | 1    |
    +| __padding__ | uint8_t[3]                  |         | 3    |
    +|-------------|-----------------------------|---------|------|
    +| home_scope  | DeclIndex                   | 0.41    | TF   |
    +|-------------|-----------------------------|---------|------|
    +
    +
    +

    Here, the first table describes DeclFunction from IFC version 0.33 up until +0.41 (non-inclusive) as a 32 byte structure. Each of the structure’s fields are +listed with their name, return type, the interpretation version of the return +type, and the size of the field. Additionally, a __padding__ field is +listed specifying there are 3 bytes of unused (or unknown) data padding the end +of the structure (which would otherwise be 29 bytes).

    +

    The second table describes DeclFunction for IFC version 0.41+ +(inclusive). This table is very similar to the structure describing the +earlier version of DeclFunction. However, this table specifies that the +home_scope’s DeclIndex has an updated value interpretation, and in the +bottom row of the table sized “TF” that a tacit field is being used to +define (in this case redefine) home_scope (see Tacit Field for +more information on tacit fields).

    +

    The values of these fields can be retrieved via calling the get_ifc_X +function where X is the name of the field (for information on the inner +workings of these functions, see Nodes). For instance, to +retrieve the home_scope (independent of the IFC version and underlying +semantics) the following function can be used:

    +
    an_ifc_decl_function func_decl = /* ... */;
    +an_ifc_decl_index    home_scope = get_ifc_home_scope(func_decl);
    +
    +
    +

    The returned home_scope is pre-validated during the node’s +construction, and ready for usage (for more information, see +Validation).

    +
    +

    16.1.6.1. Partition Node#

    +

    To get a partition node, in effectively all front end code, construct_node +should be used (for information on exceptional cases, see +Skipping Validation). This looks something like:

    +
    Opt<an_ifc_decl_function> opt_idf;
    +
    +construct_node(&opt_idf, index);
    +
    +
    +

    This will load the appropriate value found at the given index, run validation +(if necessary), and (if validation is successful) store the node in the Opt +variable.

    +
    +
    +

    16.1.6.2. Basic Node#

    +

    Basic nodes are only obtainable from a get_ifc_X operation, and used to +represent nodes which are nested in other nodes. For instance, you might have:

    +
    an_ifc_decl_reference decl_ref = ...;
    +
    +an_ifc_module_reference module_reference = get_ifc_unit(decl_ref);
    +
    +
    +

    Here the returned an_ifc_module_reference is a basic node. Note that this +is not wrapped in an optional, as the an_ifc_module_reference being a +sub-node of an_ifc_decl_reference was validated when +an_ifc_decl_reference was constructed.

    +
    +
    +

    16.1.6.3. Header Node#

    +

    Header nodes rarely need new code written for them, there are only two at the +time of writing (and for the foreseeable future):

    +
      +
    • an_ifc_file_header

    • +
    • an_ifc_partition

    • +
    +

    To get a header node, the low level construct_node_from_module is used +directly. Similarly, since header nodes are lower level, validate functions +need called explicitly.

    +

    The flow for interaction with these nodes is typically something like the +following (if not in practice, conceptually):

    +
    Opt<an_ifc_file_header> get_module_header(an_ifc_module *mod)
    +{
    +  Opt<an_ifc_file_header> result;
    +  an_ifc_file_header      raw_result;
    +
    +  init_byte_buffer(4, mod->f_size - 4);
    +  raw_result = construct_node_from_module<an_ifc_file_header>(mod);
    +  if (validate(raw_result, /*parent=*/NULL)) {
    +    result = raw_result;
    +  }  /* if */
    +  return result;
    +}  /* get_module_header */
    +
    +
    +

    This is conceptually very similar to what construct_node is doing behind +the scenes.

    +
    +
    +
    +

    16.1.7. Foreign Index#

    +

    Currently in the IFC spec there’s a DeclSort::Reference structure:

    +
    + + + + + + + + + + + + + + +

    Field

    Type

    unit

    ModuleReference

    local_index

    DeclIndex

    +
    +

    The problem is that the local_index field uses a DeclIndex, but +that DeclIndex is valid in a completely different module. This has +caused issues for the front end in the past where the index is accidentally +being used in the current module’s code.

    +

    The “Foreign Index” role is used to replace the DeclIndex type with a +new DeclForeignIndex type. This new type is more akin to a +Raw Numeric than a Index Sort.

    +

    The front end thus represents this as the following node structure:

    +
    + + + + + + + + + + + + + + +

    Field

    Type

    unit

    ModuleReference

    local_index

    DeclForeignIndex

    +
    +

    The DeclForeignIndex type in C++ code looks as follows:

    +
    /*
    +The universal representation for an IFC DeclForeignIndex.
    +*/
    +struct an_ifc_decl_foreign_index {
    +  an_ifc_module*
    +                mod;
    +                        /* The associated module. */
    +  an_ifc_decl_foreign_index_storage
    +                value;
    +                        /* The raw bit value obtained from the module.
    +                           Represented as the largest common underlying
    +                           type. */
    +};  /* an_ifc_decl_foreign_index */
    +
    +
    +

    This allows the index value to be imported into the current module in a +type safe way that can’t be accidentally treated as a DeclIndex. Thus, +interacting with the DeclReference you get something like:

    +
    an_ifc_decl_reference decl_ref = ...;
    +
    +an_ifc_decl_foreign_index local_index = get_ifc_local_index(decl_ref);
    +process_ifc_decl(local_index); /* type error */
    +
    +
    +

    In terms of correct usage, foreign indexes are typically deserialized via an +associated Tacit Field which reconstructs them as the appropriate +Index Sort in the context of their respective module.

    +

    As an example consider the DeclReference type:

    +
    |-------------------------------------------------|
    +|         DeclReference - 0.33 (12 bytes)         |
    +|-------------|------------------|---------|------|
    +| Name        | Type             | Version | Size |
    +|-------------|------------------|---------|------|
    +| unit        | ModuleReference  | 0.33    | 8    |
    +| local_index | DeclForeignIndex | 0.33    | 4    |
    +|-------------|------------------|---------|------|
    +| index       | DeclIndex        | ANY     | TF   |
    +|-------------|------------------|---------|------|
    +
    +
    +

    Using the tacit field index, local_index can be retrieved in the +context of the associated unit (i.e., IFC module) transparently:

    +
    an_ifc_decl_reference ref = ...;
    +an_ifc_decl_index     idx = get_ifc_index(ref);
    +
    +
    +
    +
    +

    16.1.8. Value Category#

    +

    Value categories are roughly equivalent to a variant type. The categories have +a Simple Sort which describes which variant is valid. The +actual variants can be any role.

    +

    This allows for handling of nested hierarchies like IFC Operators where an +OperatorSort selects the interpretation of the variant value which may +be one of several different Simple Sorts.

    +
    +
    +
    +

    16.2. Versioning#

    +
    +

    16.2.1. Simple Sort#

    +

    The Simple Sort versioning system works by converting from a +“versioned sort” (i.e., enumeration) to a “universal sort” (i.e., enumeration). +Each IFC version gets its own unique, and appropriately sized enumeration, like +so:

    +
    enum an_ifc_decl_sort_0_33 : uint32_t {
    +  ifc_0_33_ds_decl_vendor_extension        = 0,
    +  ifc_0_33_ds_decl_enumerator              = 1,
    +  ifc_0_33_ds_decl_variable                = 2,
    +  ifc_0_33_ds_decl_parameter               = 3,
    +  ifc_0_33_ds_decl_field                   = 4,
    +  ifc_0_33_ds_decl_bitfield                = 5,
    +  ifc_0_33_ds_decl_scope                   = 6,
    +  ifc_0_33_ds_decl_enumeration             = 7,
    +  /* snip */
    +};  /* an_ifc_decl_sort_0_33 */
    +
    +enum an_ifc_decl_sort_0_41 : uint32_t {
    +  ifc_0_41_ds_decl_vendor_extension       = 0,
    +  ifc_0_41_ds_decl_enumerator             = 1,
    +  ifc_0_41_ds_decl_variable               = 2,
    +  ifc_0_41_ds_decl_parameter              = 3,
    +  ifc_0_41_ds_decl_field                  = 4,
    +  ifc_0_41_ds_decl_bitfield               = 5,
    +  ifc_0_41_ds_decl_scope                  = 6,
    +  ifc_0_41_ds_decl_enumeration            = 7,
    +  /* snip */
    +};  /* an_ifc_decl_sort_0_41 */
    +
    +
    +

    Note that these versioned enumerators do not follow the typical naming +convention. This is done to reduce the amount of possible completions editor +auto complete has for ifc_ds_ (and similar).

    +

    The universal sort representation by contrast takes all of the unique names, +from all the versioned sorts, and puts them in one enumeration:

    +
    enum an_ifc_decl_sort : uint32_t {
    +  ifc_ds_decl_alias,
    +  ifc_ds_decl_barren,
    +  ifc_ds_decl_bitfield,
    +  ifc_ds_decl_concept,
    +  ifc_ds_decl_constructor,
    +  ifc_ds_decl_deduction_guide,
    +  ifc_ds_decl_destructor,
    +  ifc_ds_decl_enumeration,
    +  ifc_ds_decl_enumerator,
    +  ifc_ds_decl_expansion,
    +  ifc_ds_decl_explicit_instantiation,
    +  ifc_ds_decl_explicit_specialization,
    +  ifc_ds_decl_field,
    +  /* snip */
    +};  /* an_ifc_decl_sort */
    +
    +
    +

    This enumeration is sorted alphabetically to make things easier to find and to +prevent the list from being “shuffled” when new IFC versions are adopted.

    +

    Functions are then added to convert between the versioned sort (read from the +module file) to the universal sort, they look something like this:

    +
    inline an_ifc_decl_sort to_universal_sort(an_ifc_decl_sort_0_33 versioned)
    +/*
    +Given the versioned representation of DeclSort, return the corresponding
    +universal representation.
    +*/
    +{
    +  an_ifc_decl_sort result;
    +
    +  switch (versioned) {
    +    case ifc_0_33_ds_decl_vendor_extension:
    +      result = ifc_ds_decl_vendor_extension;
    +      break;
    +    case ifc_0_33_ds_decl_enumerator:
    +      result = ifc_ds_decl_enumerator;
    +      break;
    +    case ifc_0_33_ds_decl_variable:
    +      result = ifc_ds_decl_variable;
    +      break;
    +  /* snip */
    +
    +
    +

    This allows for stability in all of our logic despite a number of possible +changes to the sort for a particular version (e.g., numbering changes, removal, +and addition). Effectively, sorts become unique on name rather than unique on +value.

    +
    +
    +

    16.2.2. Index Sort#

    +

    As an Index Sort is composed of a Simple Sort +and an index value, its versioning relies upon the versioning of the associated +Simple Sort (see Simple Sort).

    +
    +
    +

    16.2.3. Bitfield#

    +

    Bitfield versioning works very similarly to +Simple Sort.

    +

    There’s similarly a versioned bitfield enum for each version, of appropriate +size, using the values that are correct for that version:

    +
    enum an_ifc_basic_specifiers_bitfield_0_33 : uint8_t {
    +  ifc_0_33_bsb_cxx                        = 0,
    +  ifc_0_33_bsb_c                          = 1 << 0,
    +  ifc_0_33_bsb_internal                   = 1 << 1,
    +  ifc_0_33_bsb_vague                      = 1 << 2,
    +  ifc_0_33_bsb_external                   = 1 << 3,
    +  ifc_0_33_bsb_deprecated                 = 1 << 4,
    +  ifc_0_33_bsb_initialized_in_class       = 1 << 5,
    +  ifc_0_33_bsb_non_exported               = 1 << 6,
    +  ifc_0_33_bsb_is_member_of_global_module = 1 << 7
    +};  /* an_ifc_basic_specifiers_bitfield_0_33 */
    +
    +
    +

    Unlike sorts, it’s not super practical to try and normalize the representation +itself, so instead the value is captured with a module reference.

    +
    /*
    +The universal representation for an IFC BasicSpecifiersBitfield.
    +*/
    +struct an_ifc_basic_specifiers_bitfield {
    +        an_ifc_module*
    +                mod;
    +                        /* The associated module. */
    +        an_ifc_basic_specifiers_bitfield_storage
    +                value;
    +                        /* The raw bit value obtained from the module.
    +                           Represented as the largest common underlying
    +                           type. */
    +};  /* an_ifc_basic_specifiers_bitfield */
    +
    +
    +

    This is then paired with a universal query enum (similar to the universal sort) +that gives a unique bit value to each possible bitfield and a test_bitmask +function.

    +
    enum an_ifc_basic_specifiers_bitfield_query : uint32_t {
    +  ifc_bsb_c                          = 1 << 0,
    +  ifc_bsb_cxx                        = 1 << 1,
    +  ifc_bsb_deprecated                 = 1 << 2,
    +  ifc_bsb_external                   = 1 << 3,
    +  ifc_bsb_initialized_in_class       = 1 << 4,
    +  ifc_bsb_internal                   = 1 << 5,
    +  ifc_bsb_is_member_of_global_module = 1 << 6,
    +  ifc_bsb_non_exported               = 1 << 7,
    +  ifc_bsb_vague                      = 1 << 8
    +};  /* an_ifc_basic_specifiers_bitfield_query */
    +
    +
    +template<an_ifc_basic_specifiers_bitfield_query a_Query>
    +inline a_boolean test_bitmask(
    +                         const an_ifc_basic_specifiers_bitfield &universal)
    +/*
    +Given the universal representation of BasicSpecifiersBitfield, return TRUE
    +if the universal bitmask specified by a_Query matches; otherwise, return
    +FALSE.
    +*/
    +{
    +  a_boolean result;
    +
    +  uint8_t mask = to_bitmask_0_33(a_Query);
    +  uint8_t test_value = universal.value & mask;
    +
    +  result = test_value == mask;
    +  return result;
    +}  /* test_bitmask */
    +
    +
    +

    At a high level, these functions generate per-version branches. Each of these +branches calls a function that converts the universal query, into a version +specific query (i.e., bitmask) for respective version (in this case there’s +only one version of the bitfield, so there are no branches, just a call to +to_bitmask_0_33). These bitmask conversion functions look something like +the following:

    +
    uint8_t to_bitmask_0_33(an_ifc_basic_specifiers_bitfield_query query)
    +/*
    +Given the universal representation of a BasicSpecifiersBitfield bitmask,
    +return the corresponding IFC version 0.33 representation of the bitmask.
    +*/
    +{
    +  uint8_t result = 0;
    +
    +  if (query & ifc_bsb_cxx) {
    +    result |= ifc_bsb_0_33_cxx;
    +  }  /* if */
    +  if (query & ifc_bsb_c) {
    +    result |= ifc_bsb_0_33_c;
    +  }  /* if */
    +  /* snip */
    +
    +
    +

    The versioned specific bitmask is then tested against the version specific +value, returning the result.

    +

    This approach allows the front end to test “the same” bitmasks in a version +agnostic way, with a very small runtime performance overhead.

    +
    +

    16.2.3.1. Bitwidth Limitations#

    +

    As bitfield versioning relies upon native integer types, there are limitations +imposed, namely there are a limited number of expressible bitfield queries +across all versions of the IFC.

    +

    If this becomes a problem in the future, two approaches are noted as promising.

    +

    The first (and simplest) being, the removal of the ability to create a bitmask +by joining two queries (bit-or) in favor of two (effectively bit-and) +tests. This would allow a much larger number of bitfield queries to be +represented as the bitfield query would no longer require its own bit position.

    +

    The second option being, the usage of a “big integer” type with overloaded +operators in place of a native integer type. As the translation process is +realistically performed at compile time (either via language level guarantees +if the front end moves to C++14 and these functions are made constexpr, or via +the optimizer), while this approach may on the surface seem more expensive, at +runtime it would likely be more efficient than the former.

    +

    If this problem is encountered, existing usage will guide the resolution (the +formation and usage of bit-or joined queries has thus far been limited, and may +not be useful long term).

    +
    +
    +
    +

    16.2.4. Raw Values#

    +

    Raw Numeric and Raw Bytes values effectively +aren’t versioned. As raw values have no semantic meaning at the format level, +there’s “nothing to be done.”

    +
    +
    +

    16.2.5. Nodes#

    +

    Node versioning relies upon a number of “field +accessors” (i.e., get_ifc_X) that read from the underlying byte +representation (abstracted by Byte Buffers). These accessors +additionally, abstract away the exact location and representation of various +field values within the node, allowing for complex changes to the node +representation to be “normalized.”

    +

    These accessor functions look something like the following:

    +
    template<>
    +an_ifc_decl_index get_ifc_decl(
    +                              const an_ifc_parameterized_entity &universal)
    +/*
    +Given the universal representation of ParameterizedEntity, return the
    +universal representation of the field "decl".
    +*/
    +{
    +  an_ifc_decl_index result;
    +
    +  /* Ensure the decl field exists in the current module version. */
    +  check_assertion(has_ifc_decl(universal));
    +  if (is_at_least(universal.get_module(), 0, 41)) {
    +    /* version specific logic */
    +  } else {
    +    /* version specific logic */
    +  }  /* if */
    +  return result;
    +}  /* get_ifc_decl */
    +
    +
    +

    For every version where the retrieval logic is different, we end up with a +separate branch gated on the lower bound of the version range. Newer values are +always checked first, as it’s presumed newer IFC versions will be the common +case.

    +
    +

    16.2.5.1. Stages#

    +

    The exact logic in a given branch used to read a field value, is represented in +the generator as a sequence of “stages.” These stages are setup via a “stage +builder” for the specific IFC node version. The stage builder allocates a +result variable for every stage (and can also allocate some additional +variables with extra name information if necessary).

    +

    In most cases the stages and the associated logic are fairly trivial. As an +example, consider:

    +
    an_ifc_decl_index_0_41 stage_0;
    +an_ifc_decl_index      stage_1;
    +
    +/* Copy the field (ParameterizedEntity::decl - DeclIndex) into
    +   version-specific storage. */
    +static_assert(sizeof(stage_0) == 4,
    +              "stage_0 is not properly sized storage!");
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/0);
    +stage_1 = to_universal_index(universal.get_module(), stage_0);
    +result = stage_1;
    +
    +
    +

    Here the raw value is copied (via copy_ifc_field) from an offset into a +version specific variable (stage 0). Then, said version specific variable is +converted (via to_universal_index) into a universal representation (stage +1). Finally, the resulting value is assigned to the result return +variable.

    +

    This is a trivial case of data retrieval where the data is directly stored as +part of the node, and only needs converted to a universal representation. For +more information about this process, and additional similar cases, see +Field Deserialization.

    +

    Additionally, it’s important to note that in some cases, more complicated +processing is similarly implemented via stages (for a variety of reasons). For +more information on this process, and advanced uses of the stage builder, see +Tacit Field.

    +
    +
    +

    16.2.5.2. Field Presence Checking#

    +

    The presence of an accessor sometimes depends on the IFC version. In +contexts where this is not obvious has_ifc_X functions can be used to +check to see if the associated get_ifc_X is valid. These are fairly +simple calls that return TRUE when field X is relevant to the node for +the corresponding IFC version, and FALSE otherwise.

    +
    +
    +
    +

    16.2.6. Foreign Index#

    +

    Foreign Indexes, despite conceptually being an +Index Sort are versioned more like Raw +Numerics. This is done as foreign indexes have an +associated module which contains its own revision information. Thus, using the +current (referencing) module’s version information to convert the raw value to +a universal understanding would be unreliable at best.

    +
    +
    +

    16.2.7. Value Category#

    +

    Value Categories rely upon the fact that the +types they’re composed of are themselves versioned. Thus, while value +categories are versioned, they do not have any versioning rules specific to +them.

    +
    +
    +
    +

    16.3. Deserialization#

    +

    IFC deserialization is notable for intricacies introduced by supporting +optional memory mapped IFC reading and support for big-endian and little-endian +byte orders.

    +
    +

    16.3.1. Byte Buffers#

    +

    The an_ifc_Byte_buffer class template is the class that’s fundamentally +responsible for abstracting away the location of the in memory representation +of a given byte sequences taken from the IFC file.

    +

    The most notable use the byte buffer abstraction being for the representation +of Nodes but some other IFC roles, such as +Raw Bytes, also make use of byte buffers.

    +

    The byte buffer fulfills its duty of abstracting away the memory location for a +given byte sequence via a union. Said union contains either the bytes required +for storage, or a storage_ptr; this determination is made during construction +of the respective byte buffer.

    +
    +
    +

    16.3.2. Endianness Agnostic Reading#

    +

    Endianness agnostic reading requires considerations for cases that are +and aren’t memory mapped.

    +
    +
    +

    16.3.3. Without Memory Mapping#

    +

    When memory mapping isn’t enabled, the front end resorts to calls to +get_bytes for each field in each node.

    +

    Each call copies the appropriate number of bytes for the field into a +Byte Buffer, reversing the byte order for the bytes +stored in the field if the host and IFC endianness do not match.

    +

    For nodes that contain nested (i.e., Basic Node) node +structures, the internal node’s fields are copied individually rather than +copying the entire internal node as “one field.”

    +
    +
    +

    16.3.4. With Memory Mapping#

    +

    When memory mapping is enabled, if there is an endianness mismatch, the +non-memory mapped approach described above is used.

    +

    Otherwise, the front end will use only a pointer to the start of the node +(within the broader memory mapped memory region). This pointer is then stored +and dereferenced when retrieving data in place of copying bytes into the +Byte Buffer.

    +

    There is also support for a-typical cases where the front end, even when +operating with memory mapping and matching endianness, explicitly requests an +explicit copy of the data. In practice, this isn’t currently used by the front +end and may be removed in the future.

    +
    +
    +

    16.3.5. Field Deserialization#

    +

    Fields are deserialized from the associated Byte +Buffer for the corresponding node. This process makes use +of one of two copy_ifc_field field functions, and in some cases an adjusted +Byte Buffer pointer instead of a copy.

    +
    +
    +

    16.3.6. Implicit Bounds Copying#

    +

    Copying with implicit bounds occurs when the destination object type is exactly +equivalent size. These copies additionally include a static assert as a +functional “sanity check” to ensure the code generation tool is right about the +size of the destination object (not just in theory, but in practice).

    +
    an_ifc_keyword_sort_0_33 stage_0;
    +an_ifc_keyword_sort      stage_1;
    +
    +/* Copy the field (KeywordSyntax::value - KeywordSort) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_0) == 4,
    +              "stage_0 is not properly sized storage!");
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/8);
    +
    +
    +
    +
    +

    16.3.7. Explicit Bounds Copying#

    +

    Copying with explicit bounds occurs when the destination object type is a +buffer of at least equivalent size.

    +
    enum an_ifc_source_location_part : uint8_t {};
    +using an_ifc_source_location_storage = an_ifc_source_location_part[8];
    +#if USE_MMAP_FOR_MODULES
    +using an_ifc_source_location_bytes = const an_ifc_source_location_storage*;
    +#else /* !USE_MMAP_FOR_MODULES */
    +using an_ifc_source_location_bytes = an_ifc_source_location_storage;
    +#endif /* USE_MMAP_FOR_MODULES */
    +
    +an_ifc_source_location_bytes stage_0;
    +
    +/* Copy the field (KeywordSyntax::locus - SourceLocation) into universal
    +   storage. */
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/0,
    +               /*size=*/8);
    +
    +
    +
    +
    +

    16.3.8. Byte Buffer Adjustment#

    +

    Byte Buffers are adjusted in place of a copy when the front end is +operating in memory mapped mode, and the resulting value is a byte buffer based +type. This process allows the front end to avoid unnecessary copies in memory +mapped modes when working with subobjects.

    +
    enum an_ifc_source_location_part : uint8_t {};
    +using an_ifc_source_location_storage = an_ifc_source_location_part[8];
    +using an_ifc_source_location_bytes = const an_ifc_source_location_storage*;
    +
    +an_ifc_source_location_bytes stage_0;
    +
    +/* Update the universal storage pointer to the start of the field
    +   (KeywordSyntax::locus - SourceLocation). */
    +stage_0 = (an_ifc_source_location_bytes)((*universal.get_storage()) + 0);
    +
    +
    +

    This optimization is only performed when memory mapped mode is available as +otherwise it creates an unsafe implicit dependence. In said case, the value +retrieved from a node via a field accessor depends on the lifetime of the +owning node’s storage. In other words, without memory mapping, it’s possible +for the memory that owns the subobject to go out of scope.

    +
    +
    +

    16.3.9. Field Copying#

    +

    The respective implementation of both overloads of copy_ifc_field perform a +memcpy operation; this is an intentional choice over casting and +dereferencing the pointer.

    +

    This decision is also closely related to the usage of Byte Buffers +over dedicated structs representing each version (which have debugging benefits +over the chosen approach).

    +

    In the case of both decisions, the driving force behind this choice is +alignment. In the former case attempting to dereference an misaligned pointer +is undefined behavior. Thus, attempting to “avoiding the copy” via a +reinterpret_cast paired with a deference could lead to severe portability +issues, and – ironically – degraded performance. However, the memcpy +operation can be safely optimized and used, even for unaligned inputs. Thus, +the approach of usage a memcpy to copy data into known fixed size types +gives maximum performance without the associated portability concerns.

    +

    In the case of the latter decision specifically, the individual data members +within a struct will be padded differently on different host compilers, +operating systems, and different architectures (to comply with alignment +requirements). Thus, attempting to “overlay” a struct onto the underlying IFC +byte representation, results in similar severe portability issues.

    +
    +
    +

    16.3.10. Tacit Field#

    +

    A “tacit field” is a field that isn’t actually part of the official field list +for a node. Tacit fields are regularly used to expose information that’s +(indirectly) always present. For instance, a node might have no “home_scope” +field but the home scope can always be resolved via a different field.

    +

    As an example, consider the following made up node “FooDef” (which for +the sake of the hypothetical, pairs a declaration with a syntactic +definition):

    +
    + + + + + + + + + + + + + + +

    Field

    Type

    declaration

    DeclIndex

    definition

    SyntaxIndex

    +
    +

    Continuing with the hypothetical, in practice for “FooDef” nodes the +DeclIndex for declaration, when valid, always points to a node that has a +home_scope field. A tacit field exposes this invariant explicitly. From +the front end’s perspective, adding a tacit field for home_scope is +“as-if” the binary representation defined “FooDef” to be:

    +
    + + + + + + + + + + + + + + + + + +

    Field

    Type

    declaration

    DeclIndex

    definition

    SyntaxIndex

    home_scope

    DeclIndex

    +
    +

    This also exposes this invariant to the validator, which will then make sure +declaration points to a node with a home_scope field containing a valid +DeclIndex.

    +

    Not all tacit fields perform this sort of “proxy retrieval” operation, +effectively any invariant can be exposed and validated in this way.

    +
    +

    16.3.10.1. Impact on Versioning#

    +

    This conceptual breadth of functionality allows tacit fields play a large +role in supporting different IFC versions as well. Consider a later +revision of “FooDef” changes declaration so that the DeclIndex +sometimes points to a new intermediary node “FooProxyDecl”, which then +itself always points to a third node that has a home_scope.

    +

    Tacit fields allow this change to be “invisible” to existing logic. The +existing home_scope tacit field can be updated to follow the new rules +and properly retrieve the home_scope as one might expect. However, +tacit fields can also “replace” (or “override”) a field that’s explicitly +part of the binary node representation (i.e., “explicitly declared”) if +they share the same name.

    +

    In the context of this example, existing code might break – badly – when +it encounters the new intermediary “FooProxyDecl” node after a call to +the field accessor get_ifc_declaration(const an_ifc_foo_decl&). A new +declaration tacit field can be added that automatically “sees through” +the wrapper, “as-if” it was never added. The existing logic then goes back +to functioning as it did before, as from its perspective nothing changed.

    +

    Code that then needs to observe the new “FooProxyDecl” can then be +accounted for by adding additional tacit fields that either expose the +“true” value of declaration or information from “FooProxyDecl.”

    +

    The exact approach taken is situational, however, tacit fields are a powerful +tool for resolving versioning issues.

    +
    +
    +

    16.3.10.2. Tacit Field Implementation#

    +

    As noted in Nodes, field accessors work via “stages” +constructed from a “stage builder” in the code generation tool.

    +

    These can get exceptionally complicated in terms of implemented +code. Consider the following real example, taken verbatim from the front end:

    +
    template<>
    +an_ifc_decl_index get_ifc_home_scope(
    +                                   const an_ifc_decl_enumerator &universal)
    +/*
    +Given the universal representation of DeclEnumerator, return the universal
    +representation of the field "home_scope".
    +*/
    +{
    +  an_ifc_decl_index result;
    +
    +  /* Ensure the home_scope field exists in the current module version. */
    +  check_assertion(has_ifc_home_scope(universal));
    +  if (is_at_least(universal.get_module(), 0, 41)) {
    +    an_ifc_type_index_0_33 stage_0;
    +    an_ifc_type_index      stage_1;
    +    an_ifc_type_designated stage_2;
    +    an_ifc_decl_index_0_41 stage_3;
    +    an_ifc_decl_index      stage_4;
    +    a_boolean              stage_5;
    +    an_ifc_decl_index      stage_6;
    +
    +    /* Copy the field (DeclEnumerator::type - TypeIndex) into
    +       version-specific storage. */
    +    static_assert(sizeof(stage_0) == 4,
    +                  "stage_0 is not properly sized storage!");
    +    copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12);
    +    stage_1 = to_universal_index(universal.get_module(), stage_0);
    +    /* Use the obtained index to retrieve the appropriate instance of
    +       TypeDesignated (the type tag should have been prechecked by
    +       validation).  Then, retrieve and return the desired value held by
    +       the field decl. */
    +    construct_node_unchecked(&stage_2, stage_1);
    +    /* Copy the field (TypeDesignated::decl - DeclIndex) into
    +       version-specific storage. */
    +    static_assert(sizeof(stage_3) == 4,
    +                  "stage_3 is not properly sized storage!");
    +    copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0);
    +    stage_4 = to_universal_index(stage_2.get_module(), stage_3);
    +    if (stage_4.sort == ifc_ds_decl_specialization) {
    +      stage_5 = TRUE;
    +    } else {
    +      stage_5 = FALSE;
    +    }  /* if */
    +    if (stage_5) {
    +      an_ifc_decl_index          stage_6_0;
    +      an_ifc_decl_specialization stage_6_1;
    +      an_ifc_decl_index_0_41     stage_6_2;
    +      an_ifc_decl_index          stage_6_3;
    +
    +      stage_6_0 = stage_4;
    +      /* Use the obtained index to retrieve the appropriate instance of
    +         DeclSpecialization (the type tag should have been prechecked by
    +         validation).  Then, retrieve and return the desired value held by
    +         the field decl. */
    +      construct_node_unchecked(&stage_6_1, stage_6_0);
    +      /* Copy the field (DeclSpecialization::decl - DeclIndex) into
    +         version-specific storage. */
    +      static_assert(sizeof(stage_6_2) == 4,
    +                    "stage_6_2 is not properly sized storage!");
    +      copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4);
    +      stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2);
    +      stage_6 = stage_6_3;
    +    } else {
    +      an_ifc_decl_index stage_6_0;
    +
    +      stage_6_0 = stage_4;
    +      stage_6 = stage_6_0;
    +    }  /* if */
    +    result = stage_6;
    +  } else {
    +    an_ifc_type_index_0_33 stage_0;
    +    an_ifc_type_index      stage_1;
    +    an_ifc_type_designated stage_2;
    +    an_ifc_decl_index_0_33 stage_3;
    +    an_ifc_decl_index      stage_4;
    +
    +    /* Copy the field (DeclEnumerator::type - TypeIndex) into
    +       version-specific storage. */
    +    static_assert(sizeof(stage_0) == 4,
    +                  "stage_0 is not properly sized storage!");
    +    copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12);
    +    stage_1 = to_universal_index(universal.get_module(), stage_0);
    +    /* Use the obtained index to retrieve the appropriate instance of
    +       TypeDesignated (the type tag should have been prechecked by
    +       validation).  Then, retrieve and return the desired value held by
    +       the field decl. */
    +    construct_node_unchecked(&stage_2, stage_1);
    +    /* Copy the field (TypeDesignated::decl - DeclIndex) into
    +       version-specific storage. */
    +    static_assert(sizeof(stage_3) == 4,
    +                  "stage_3 is not properly sized storage!");
    +    copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0);
    +    stage_4 = to_universal_index(stage_2.get_module(), stage_3);
    +    result = stage_4;
    +  }  /* if */
    +  return result;
    +}  /* get_ifc_home_scope */
    +
    +
    +
    +
    16.3.10.2.1. Stage Breakdown#
    +

    This is an intimidating amount of logic, however it’s composed of bite sized +pieces of principled logic coming together. At a high level, there are two +cases here, one for IFC version 0.41+ and one for earlier supported versions of +the IFC.

    +

    Consider the “ earlier “ code (i.e., the code for supporting IFC versions +prior to 0.41, which will be known from this point as the 0.33+ code):

    +
    an_ifc_type_index_0_33 stage_0;
    +an_ifc_type_index      stage_1;
    +an_ifc_type_designated stage_2;
    +an_ifc_decl_index_0_33 stage_3;
    +an_ifc_decl_index      stage_4;
    +
    +/* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_0) == 4,
    +              "stage_0 is not properly sized storage!");
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12);
    +stage_1 = to_universal_index(universal.get_module(), stage_0);
    +/* Use the obtained index to retrieve the appropriate instance of
    +   TypeDesignated (the type tag should have been prechecked by validation).
    +   Then, retrieve and return the desired value held by the field decl. */
    +construct_node_unchecked(&stage_2, stage_1);
    +/* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_3) == 4,
    +              "stage_3 is not properly sized storage!");
    +copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0);
    +stage_4 = to_universal_index(stage_2.get_module(), stage_3);
    +result = stage_4;
    +
    +
    +

    The code generation tool represents this as in effect, a directly constructed +expression AST, simplifying a bit:

    +
    IFCRemoteDelegate(
    +  IFCDirectDelegate('type'),
    +  'Type',
    +  'TypeDesignated',
    +  'decl'
    +)
    +
    +
    +

    This is conceptually an “expression” representing the retrieval of the +value. The innermost operation IFCDirectDelegate is thus the first to be +evaluated.

    +

    While fully documenting the tacit field system within the code generation tool +is out of scope, for purposes of understanding, an IFCDirectDelegate simply +means “read the type field” from the node.

    +

    Similarly, IFCRemoteDelegate simply means “take the input value (the +type field value), it’s a Type(Index) that must point to a +TypeDesignated node, read said node’s decl field.”

    +

    The “stage builder” takes this expression and transforms it into a series of +“stages.”

    +
    +
    16.3.10.2.1.1. Stage 0#
    +

    Read the versioned value of the type field:

    +
    an_ifc_type_index_0_33 stage_0;
    +
    +/* snip */
    +/* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_0) == 4,
    +              "stage_0 is not properly sized storage!");
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12);
    +
    +
    +
    +
    +
    16.3.10.2.1.2. Stage 1#
    +

    Turn the versioned type field value into a universal value:

    +
    an_ifc_type_index_0_33 stage_0;
    +an_ifc_type_index      stage_1;
    +
    +/* snip */
    +stage_1 = to_universal_index(universal.get_module(), stage_0);
    +
    +
    +
    +
    +
    16.3.10.2.1.3. Stage 2#
    +

    Load the TypeDesignated node:

    +
    an_ifc_type_index      stage_1;
    +an_ifc_type_designated stage_2;
    +
    +/* Use the obtained index to retrieve the appropriate instance of
    +   TypeDesignated (the type tag should have been prechecked by validation).
    +   Then, retrieve and return the desired value held by the field decl. */
    +construct_node_unchecked(&stage_2, stage_1);
    +
    +
    +
    +
    +
    16.3.10.2.1.4. Stage 3#
    +

    Read the versioned value of the decl field from the TypeDesignated +node:

    +
    an_ifc_type_designated stage_2;
    +an_ifc_decl_index_0_33 stage_3;
    +
    +/* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_3) == 4,
    +              "stage_3 is not properly sized storage!");
    +copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0);
    +
    +
    +
    +
    +
    16.3.10.2.1.5. Stage 4#
    +

    Turn the versioned decl field value into a universal value:

    +
    an_ifc_decl_index_0_33 stage_3;
    +an_ifc_decl_index      stage_4;
    +
    +stage_4 = to_universal_index(stage_2.get_module(), stage_3);
    +result = stage_4;
    +
    +
    +
    +
    +
    16.3.10.2.1.6. Stage 5 (Wrap-up)#
    +

    Assign the result:

    +
    an_ifc_decl_index      stage_4;
    +
    +result = stage_4;
    +
    +
    +

    The stage builder facilitates the creation of these stages from the expression, +creating a metaphorical “data retrieval pipeline.” The usage of expression +nodes and this system of generating C++ stages from these nodes, allows tacit +fields to be quickly written via reusable building blocks.

    +

    Examination of the validation logic will reveal it’s very similar to the logic +generated for field data retrieval, however rather than returning a result, it +performs a number of checks to make sure the would-be result and everything +required in-between is validated as necessary.

    +
    +
    +
    +
    16.3.10.2.2. Advanced Stage Breakdown#
    +

    After establishing an understanding of the flow of the 0.33+ code, consider the +0.41+ code:

    +
    an_ifc_type_index_0_33 stage_0;
    +an_ifc_type_index      stage_1;
    +an_ifc_type_designated stage_2;
    +an_ifc_decl_index_0_41 stage_3;
    +an_ifc_decl_index      stage_4;
    +a_boolean              stage_5;
    +an_ifc_decl_index      stage_6;
    +
    +/* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_0) == 4,
    +              "stage_0 is not properly sized storage!");
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12);
    +stage_1 = to_universal_index(universal.get_module(), stage_0);
    +/* Use the obtained index to retrieve the appropriate instance of
    +   TypeDesignated (the type tag should have been prechecked by validation).
    +   Then, retrieve and return the desired value held by the field decl. */
    +construct_node_unchecked(&stage_2, stage_1);
    +/* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_3) == 4,
    +              "stage_3 is not properly sized storage!");
    +copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0);
    +stage_4 = to_universal_index(stage_2.get_module(), stage_3);
    +if (stage_4.sort == ifc_ds_decl_specialization) {
    +  stage_5 = TRUE;
    +} else {
    +  stage_5 = FALSE;
    +}  /* if */
    +if (stage_5) {
    +  an_ifc_decl_index          stage_6_0;
    +  an_ifc_decl_specialization stage_6_1;
    +  an_ifc_decl_index_0_41     stage_6_2;
    +  an_ifc_decl_index          stage_6_3;
    +
    +  stage_6_0 = stage_4;
    +  /* Use the obtained index to retrieve the appropriate instance of
    +     DeclSpecialization (the type tag should have been prechecked by
    +     validation).  Then, retrieve and return the desired value held by the
    +     field decl. */
    +  construct_node_unchecked(&stage_6_1, stage_6_0);
    +  /* Copy the field (DeclSpecialization::decl - DeclIndex) into
    +     version-specific storage. */
    +  static_assert(sizeof(stage_6_2) == 4,
    +                "stage_6_2 is not properly sized storage!");
    +  copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4);
    +  stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2);
    +  stage_6 = stage_6_3;
    +} else {
    +  an_ifc_decl_index stage_6_0;
    +
    +  stage_6_0 = stage_4;
    +  stage_6 = stage_6_0;
    +}  /* if */
    +result = stage_6;
    +
    +
    +

    Here stages 0 through 4 are identical to the 0.33+ code, however additional +stages have been added (i.e., the “pipeline” has been extended). Stage 6 is +particularly interesting as it works with substages.

    +

    To understand what’s going on here, consider the following simplified code from +the code generation tool:

    +
    existing_logic = IFCRemoteDelegate(
    +  IFCDirectDelegate('type'),
    +  'Type',
    +  'TypeDesignated',
    +  'decl'
    +)
    +source_value = IFCReusableResult(existing_logic)
    +
    +IFCConditionalDelegate(
    +  IFCTestSortMatch(
    +    source_value,
    +    'Decl',
    +    {'DeclSpecialization'}
    +  ),
    +  'DeclIndex',
    +  IFCRemoteDelegate(
    +    source_value,
    +    'Decl',
    +    'DeclSpecialization',
    +    'decl'
    +  ),
    +  source_value
    +)
    +
    +
    +

    The existing_logic, the associated IFCRemoteDelegate, and +IFCDirectDelegate were already covered, so those won’t be +revisited. However, IFCReusableResult, IFCTestSortMatch, and +IFCConditionalDelegate are new.

    +

    IFCReusableResult can be thought of like a lazily-evaluated, “memoization +instruction.” This allows reuse of the same value without reevaluation.

    +

    IFCTestSortMatch means “take the input value (the possibly memoized +TypeDesignated decl field value), evaluate true if its Decl(Sort) +value is DeclSpecialization; otherwise, evaluate false.”

    +

    IFCConditionalDelegate means “compute a DeclIndex value one of two +ways, if the input value (the test sort match) evaluates as true use the +first sub-expression, otherwise use the second.”

    +

    IFCConditionalDelegates are particularly notable as they allow logic +to have branched evaluation. When these branches are translated to C++ +code, these are implemented via substages (effectively stage builders that +inherent a prefix and their input from a parent stage builder’s stage).

    +

    Note how this all composes to allow the existing logic to be sanely extended. +Looking at what’s new, stage 5 is where things diverge.

    +
    +
    16.3.10.2.2.1. Stage 5#
    +

    The resulting DeclIndex is check to see if its sort is a +DeclSpecialization, storing the result as a boolean value:

    +
    an_ifc_decl_index      stage_4;
    +a_boolean              stage_5;
    +
    +if (stage_4.sort == ifc_ds_decl_specialization) {
    +  stage_5 = TRUE;
    +} else {
    +  stage_5 = FALSE;
    +}  /* if */
    +
    +
    +
    +
    +
    16.3.10.2.2.2. Stage 6 (Wrap-up)#
    +

    The previous result of the DeclSpecialization sort test is used, forking to +evaluate one of two sub-expressions before the result is assigned:

    +
    if (stage_5) {
    +  /* substage content */
    +} else {
    +  /* substage content */
    +}  /* if */
    +result = stage_6;
    +
    +
    +

    The first sub-expression (when a DeclSpecialization is used) unwraps +the decl field value from the DeclSpecialization node, storing the +result in stage 6:

    +
    an_ifc_decl_index          stage_6_0;
    +an_ifc_decl_specialization stage_6_1;
    +an_ifc_decl_index_0_41     stage_6_2;
    +an_ifc_decl_index          stage_6_3;
    +
    +stage_6_0 = stage_4;
    +/* Use the obtained index to retrieve the appropriate instance of
    +   DeclSpecialization (the type tag should have been prechecked by
    +   validation).  Then, retrieve and return the desired value held by the
    +   field decl. */
    +construct_node_unchecked(&stage_6_1, stage_6_0);
    +/* Copy the field (DeclSpecialization::decl - DeclIndex) into
    +   version-specific storage. */
    +static_assert(sizeof(stage_6_2) == 4,
    +              "stage_6_2 is not properly sized storage!");
    +copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4);
    +stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2);
    +stage_6 = stage_6_3;
    +
    +
    +

    The second sub-expression (when a DeclSpecializtion is not used) passes +through the value as a no-op:

    +
    an_ifc_decl_index stage_6_0;
    +
    +stage_6_0 = stage_4;
    +stage_6 = stage_6_0;
    +
    +
    +

    Note that even though the second sub-expression ends up being generated as an +effective no-op case with no special processing of its own, a substage +(stage_6_0) is initialized. There is no special meaning to this, it’s merely an +implementation detail that falls out from the semantics of the code generation +tool. This may be improved in future revisions, but it’s largely a visual +defect that gets cleaned up during optimization.

    +
    +
    +
    +
    +
    +

    16.3.11. Validation#

    +

    The IFC validation system is designed to check all data read from the IFC file +while being “out of the way”, performant, and extendable.

    +
    +

    16.3.11.1. Point of Validation#

    +

    Data is validated upon construction of a node, namely within the +construct_node function (via a call to the validate function +corresponding to the node). This validation covers all get_ifc_X return +values (and in the case of Tacit Field, any intermediate data).

    +

    The validation system leverages the stage builder (for more information +about stages in general, see Stages) system used to create +the get_ifc_X functions themselves. The stage builder knows how to +create not only the typical “data retrieval pipeline”, but one which +validates the intermediate steps, and the returned data.

    +

    The extent of the validation depends on the role associated with the type +being validated.

    +
    +
    16.3.11.1.1. Simple Sort#
    +

    Simple Sort validation ensures that the input value corresponds +to a valid simple sort value for the current IFC version and simple sort type.

    +
    +
    +
    16.3.11.1.2. Index Sort#
    +

    Index Sort validation first checks the associated +Simple Sort for validation issues, then ensures that the +requested element exists in the associated partition. This latter step can be +thought of as a sort of pointer validation, it doesn’t ensure the validity of +the data being pointed to, but it does ensure the pointer itself is valid.

    +
    +
    +
    16.3.11.1.3. Nodes#
    +

    Nodes sometimes appear within other nodes (for more +information, see Basic Node). In these cases, the validator +recurses into the sub-node and also ensures the validity of its fields. This +reduces the number of calls required to work with sub-nodes, and improves +diagnostics (by providing extra context to work with).

    +
    +
    +
    16.3.11.1.4. Value Categories#
    +

    Value Category validation similar to Index Sort +validation first checks the associated Simple Sort for +validation issues. The respective variant is then validated as necessary.

    +
    +
    +
    +

    16.3.11.2. Validation Cache#

    +

    The validation system is made more efficient by a bit-based caching mechanism.

    +

    Each partition position in the IFC has its validation status represented as two +bits that are part of a 32-bit integer. The higher 16 bits are used to +represent an “invalid” flag while the lower 16 bits are used to represent a +“validated” flag. The choice to represent “invalid” status instead of “valid” +status is deliberate to minimize the number of writes to the validation cache +for a valid IFC file.

    +

    These 32-bit integers are themselves part of an array that’s allocated +per-partition representing all elements in the partition. The cache thus has +both high locality and high space efficiency.

    +

    When a node is constructed via construct_node the validation cache is +checked, and if the node has already been validated, the cached validation +status will be reused rather than rerunning the validate function for the +node.

    +

    The caching process also provides – as an adverse affect – a guarantee that +validation diagnostics are only emitted once.

    +
    +
    +

    16.3.11.3. Skipping Validation#

    +

    In general, data validation should not be skipped. However, in some cases it’s +desirable to skip validation.

    +
    +
    16.3.11.3.1. Pre-checked Data#
    +

    construct_node_prechecked can be useful as an optimization in places where +it’s known – with certainty – that the node being constructed has previously +been validated.

    +

    Note that when CHECKING is enabled this function will check the validation +cache to ensure that the node being constructed truly was previously validated.

    +
    +
    +
    16.3.11.3.2. Unchecked Data#
    +

    construct_node_unchecked can be used as part of low level implementation +details that can safely ignored validation status (or code that takes special +care to ensure safe usage). It’s important to emphasize, this function truly +bypasses all checks, and thus can introduce unsafe data or crashes if used +improperly.

    +

    An example of a time this function is useful is the find_trait +function. Traits are found via a binary search, attempting to validate the data +during the search would significantly degrade performance, and might lead to a +large number of unnecessary diagnostics about data that’s never used. The usage +is made safe as after the search completes the final result (if any) is +validated.

    +
    +
    +
    +
    +

    16.3.12. Visitors#

    +

    The visitor system is designed to allow the use of get_ifc_X +functions on a given Index Sort value. As an example, +consider the following:

    +
    an_ifc_decl_index decl_idx = ...;
    +an_ifc_decl_index home_scope_idx = get_ifc_home_scope(decl_idx);
    +
    +
    +

    This is not a field accessor as described in the Nodes section. +Instead, this function will load the appropriate node for the index, and then +delegate to that node’s field accessor of the same name. It’s thus in essence, +equivalent to writing:

    +
    switch (decl_idx.sort) {
    +  case ifc_ds_decl_function:
    +    { an_ifc_decl_function universal;
    +
    +      construct_node_prechecked(&universal, decl_idx);
    +      home_scope_idx = get_ifc_home_scope(universal);
    +    }
    +    break;
    +}  /* switch */
    +
    +
    +

    Note that this has some limitations, namely, the sort has to point to a node +that has the given field name for the current IFC version, and the node has to +have been previously validated.

    +

    To accommodate these limitations additional visitors are exposed for the +corresponding has_ifc_X function (for more information, see: +Field Presence Checking) and for node validation.

    +

    Thus, in most cases the correct usage looks something like the following:

    +
    an_ifc_decl_index decl_idx = ...;
    +an_ifc_decl_index home_scope_idx;
    +
    +/* Check if a valid version of the node pointed to by this decl_idx would
    +   ever have a valid home_scope */
    +if (has_ifc_home_scope(decl_idx)) {
    +  /* Make sure we're working with a valid node */
    +  if (validate(decl_idx)) {
    +    /* Guaranteed retrieval of a valid home scope index. */
    +    home_scope_idx = get_ifc_home_scope(decl_idx);
    +  }  /* if */
    +}  /* if */
    +
    +
    +

    This is often just simplified to:

    +
    an_ifc_decl_index decl_idx = ...;
    +an_ifc_decl_index home_scope_idx;
    +
    +if (has_ifc_home_scope(decl_idx) && validate(decl_idx)) {
    +  home_scope_idx = get_ifc_home_scope(decl_idx);
    +}  /* if */
    +
    +
    +
    +

    16.3.12.1. Passthrough#

    +

    In the case of certain nodes, a reasonable answer can be obtained, but is not +implicitly present. For these cases, an “implicit dereference” is added to the +code generation tool. These allow visitors to recurse using the “dereferenced” +value.

    +

    As an example, consider the following:

    +
    # Implicit dereferencing on the DeclIndex.
    +'Decl': {
    +  # Implicitly dereference DeclReference via the get_ifc_index function.
    +  'DeclReference': 'get_ifc_index'
    +}
    +
    +
    +

    This is an implicit dereference on the Decl Index Sort, that +applies the requested traversal to the result of a DeclReference’s +get_ifc_index field accessor.

    +

    In generated code, this looks something like the following:

    +
    case ifc_ds_decl_reference:
    +  { an_ifc_decl_reference universal;
    +
    +    construct_node_prechecked(&universal, idx);
    +
    +    an_ifc_decl_index remote_idx = get_ifc_index(universal);
    +    result = get_ifc_home_scope(remote_idx);
    +  }
    +  break;
    +
    +
    +

    This notably also applies to the has_ifc_X function:

    +
    case ifc_ds_decl_reference:
    +  { Opt<an_ifc_decl_reference> opt_universal;
    +
    +    construct_node(&opt_universal, idx);
    +    if (opt_universal.has_value()) {
    +      an_ifc_decl_index remote_idx = get_ifc_index(*opt_universal);
    +
    +      if (has_ifc_home_scope(remote_idx)) {
    +        result = TRUE;
    +      }  /* if */
    +    }  /* if */
    +  }
    +  break;
    +
    +
    +

    Thus, in contrast to an Tacit Field, a visitor is much more lenient +form of data retrieval, often used both in instances of “may-have” as opposed +to instances of “must-have.”

    +
    +
    +

    16.3.12.2. Implicit Conversion#

    +

    Some visitors are additionally configured with implicit conversions. These +conversions allow the visitor to return one return type while the underlying +get_ifc_X field accessors return different types.

    +

    As an example, the IFC’s TextOffset can be represented as a +NameIndex. Thus, to allow for one get_ifc_name visitor, a conversion is +added.

    +
    +
    +

    16.3.12.3. Limited Scope#

    +

    As most fields don’t need exposed by visitors, generating every possible +visitor could get quite expensive (both for the code generation tool and for +build times). Thus, instead, the code generation tool requires desired visitors +to be explicitly listed.

    +

    For instance, to define a simple visitor to expose the home_scope DeclIndex:

    +
    # Add a visitor over the Decl index for get_ifc_home_scope returning
    +# an_ifc_decl_index with no conversions.
    +(
    +  'Decl',
    +  'home_scope',
    +  'an_ifc_decl_index',
    +  {}
    +)
    +
    +
    +

    In more advanced cases like the +aforementioned get_ifc_name visitor, +conversions are specified like so:

    +
    # Add a visitor over the Decl index for get_ifc_name returning
    +# an_ifc_name_index with a potential conversion from a an_ifc_text_offset
    +# to an_ifc_name_index.
    +(
    +  'Decl',
    +  'name',
    +  'an_ifc_name_index',
    +  {
    +    'conversions': {
    +      'an_ifc_text_offset': IFCTextOffsetToNameIndex()
    +    }
    +  }
    +)
    +
    +
    +
    +
    +
    +
    +

    16.4. Partition Kinds#

    +

    The generation tool manages a list of partition kinds known to said tool (and +thus the front end).

    +

    These partition kinds are exposed via the an_ifc_partition_kind enum with +an additional ifc_pk_none value written to represent invalid states.

    +

    The total number of IFC partition kinds known to the front end (not including +ifc_pk_none) can be retrieved via the IFC_PARTITION_COUNT macro.

    +

    A alphabetically sorted mapping of IFC partition kind names to +an_ifc_partition_kind values (not including ifc_pk_none) named +ifc_partition_map is also maintained to enable binary search based mapping +between a given IFC partition kind name and the corresponding front end value +used for its representation.

    +

    As this mapping is extensive (with the exception of ifc_pk_none) +ifc_partition_mapping[partition_kind - 1].name can be used to retrieve the +name of any an_ifc_partition_kind value in constant time.

    +

    Additionally, the associated relationships between partition kinds and other +roles is also captured by several utility functions.

    +
    +

    16.4.1. get_ifc_partition_kind#

    +

    Some operations require knowing the partition kind associated with a given node +type. The get_ifc_partition_kind<T> explicit template specializations +expose this information via template instantiation.

    +
    +
    +

    16.4.2. get_ifc_partition_element_size#

    +

    Some operations require knowing the expected element size for a given partition +at a given IFC version. The get_ifc_partition_element_size function +provides this functionality taking a module and partition kind and returning +the expected size.

    +
    +
    +

    16.4.3. has_partition_kind#

    +

    Some operations require knowing whether or not a given +Simple Sort value has an associated partition kind. The +has_partition_kind functions take a simple sort and return TRUE if the +sort has an associated partition kind, otherwise they return FALSE.

    +
    +
    +

    16.4.4. to/from_partition_kind#

    +

    Some operations require a transition from an Index +Sort’s Simple Sort to a partition sort or +vice versa.

    +

    The to_partition_kind functions take a Simple Sort and +convert the sort to an_ifc_partition_kind.

    +

    Conversely, the to_X sort functions take an_ifc_partition_kind and +convert it to the desired Simple Sort.

    +

    Note that in both cases, any conversion failures will result in a crash.

    +
    +
    +
    +

    16.5. Debugging#

    +
    +

    16.5.1. Nodes#

    +

    As noted in the Field Copying subsection, to provide a portable +implementation of IFC Deserialization, sacrifices +were made that negatively impact the debugger experience of working with IFC +Nodes.

    +

    To mitigate this issue, DEBUG builds of the front end include db_node +functions which can be invoked to get a pretty-printed summary of the node’s +contents from within the debugger.

    +

    Consider the following:

    +
    an_ifc_decl_alias foo = ...;
    +/* break point */
    +
    +
    +

    When debugging this code, the db_node(const an_ifc_decl_alias &universal) +function (in most cases invoked simply as db_node(foo)) can be used to +print the node contents.

    +

    This results in output similar to the following:

    +
    =============================== DeclAlias ================================
    +access: AccessSort::None
    +aliasee:
    +  sort: TypeSort::TypePointer
    +  value: 0
    +home_scope: NULL
    +locus:
    +  column: 22
    +  line: 2
    +name: 189
    +specifiers:
    +  - C
    +  - Cxx
    +  - IsMemberOfGlobalModule
    +type:
    +  sort: TypeSort::TypeFundamental
    +  value: 0
    +
    +
    +
    +
    +
    +

    16.6. Code Organization#

    +

    This system generates a lot of code, as a result, to keep the front end build +times down code has been carefully organized and separated to prevent any one +translation unit from having an excessive impact on the build time.

    +

    The code generated files currently include:

    +
      +
    • ifc_map.h - A forward declaration of all types so they can be used in +ifc_module.h without polluting ifc_module.h with a large number of +functions.

    • +
    • ifc_map_functions.h - The forward declarations of functions imported in +files that need access to low level IFC reading operations.

    • +
    • ifc_map_functions.c - The implementation of functions declared in +ifc_map_functions.h that do not have a more specific implementation file.

    • +
    • ifc_map_functions_acc.c - The implementation of all IFC field accessor +functions.

    • +
    • ifc_map_functions_dbg.c - The implementation of all IFC debug functions.

    • +
    • ifc_map_functions_val.c - The implementation of all IFC validation +functions.

    • +
    • ifc_modules_inst.h - A list of macros imported in ifc_modules_templ.c +to manage explicit template instantiations.

    • +
    • ifc_modules_spec.h - A list of macros imported in ifc_modules_templ.c +to manage explicit template specializations.

    • +
    +

    Note that Visitor implementations are currently +found in ifc_map_functions.c.

    +

    The portion of the front end that handles deserialization is primarily found in +ifc_modules_read.c. The portion of the front end that handles +serialization is primarily found in ifc_modules_write.c. Code that is +common between the two is found in ifc_modules_internal.h and +ifc_modules.c.

    +

    All supporting template definitions and instantiations (that used by a mix of +ifc_modules.c, ifc_modules_read.c, ifc_modules_write.c`, and the +ifc_map_functions*.c files) are isolated to ifc_modules_templ.c, +preventing multiple translation units from instantiating the same template.

    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/objects.inv b/dev/doc/objects.inv new file mode 100644 index 0000000..99cae49 Binary files /dev/null and b/dev/doc/objects.inv differ diff --git a/dev/doc/pragma/index.html b/dev/doc/pragma/index.html new file mode 100644 index 0000000..a825446 --- /dev/null +++ b/dev/doc/pragma/index.html @@ -0,0 +1,1147 @@ + + + + + 15. Pragmas and Attributes - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    15. Pragmas and Attributes#

    +

    Support for the processing of #pragma directives appears in several files +(including preproc.c, lexical.c, and il.c), but the principal +routines are in pragma.c. pragma.h and il_def.h contain +definitions of the data structures that are used.

    +

    Standard attributes, GNU attributes, and Microsoft __declspec attributes +are like pragmas in their semantic scope (i.e., a generic mechanism for small +language extensions), but unlike pragmas they fit in ordinary grammar-based +based front end processing. The principal routines for attribute processing +are in attribute.c (and attribute.h); the main data structures are in +il_def.h.

    +
    +

    15.1. Introduction to Pragma Processing#

    +

    Pragma processing differs from other front end processing in several ways. +Pragmas are scanned as part of the inter-token processing of the lexical +routines, yet the actual interpretation of the pragmas must be performed at a +suitable point in the syntactic and semantic processing of the front end. In +fact tokens may need to be scanned far in advance of when they are actually +used, and so pragmas may be encountered at the lexical level when it is +impossible for them to be fully processed. This occurs in scanning the bodies +of template definitions, in doing the lookahead to disambiguate declarations +and expressions, and so forth.

    +

    Moreover, it is clear that the “suitable point in syntactic and semantic +processing” where the pragma is interpreted will be different for different +pragmas. And some pragmas simply carry information for use by the back end and +do not affect front-end processing at all. Each pragma has special +requirements.

    +

    Pragmas are also unusual because, by definition, they are specific to a given +implementation. The mechanism that the EDG front end provides is intended to +make it relatively easy for customers to add pragmas and to customize how they +are processed, from how they are tokenized to how IL pragma entries are +generated. The handful of pragmas that are supplied by default with the EDG +front end can serve as prototypes for such customization.

    +

    A pivotal role in pragma processing is played by an entry of type +a_pending_pragma, a front-end-only repository of information about a +specific #pragma directive in the source. It is “pending” in that it is +awaiting interpretation, after which it is disposed of. Interpreting a pragma +may mean setting a flag in a symbol, causing a diagnostic to be suppressed, +creating an IL pragma entry to pass information on to the back end, and so +forth.

    +

    Pragma processing can be summarized as consisting of three steps:

    +
      +
    1. The #pragma directive that appears in the source code is identified and +recorded in a pending pragma entry. Although most pragmas are simply +recorded for later interpretation, “preprocessing immediate” pragmas are +dispatched immediately upon being recognized by the preprocessing +routines.

    2. +
    3. The pending pragma entry is “dispatched” – i.e., made available for +additional processing by being placed on a list where it can be found +later.

    4. +
    5. The pending pragma entry is interpreted, with its message transferred to +another form (e.g., a flag is set somewhere), and then it is disposed +of.

    6. +
    +

    Pragmas must be recognized to be processed, and once they have been recognized +much of the processing is table-driven. The key pieces of information about +every pragma are:

    +
      +
    • +
      The pragma kind – an element of the enumeration a_pragma_kind (defined +in il_def.h). Every pragma that is recognized corresponds to one +pragma kind.
      +
      +
    • +
    • +
      The pragma-id – the identifier string that follows the #pragma keyword +and that may be looked up in the array pragma_ids (defined in +il_def.h) to determine the pragma kind.
      +
      +
    • +
    • +
      The pragma kind description – a data structure of type +a_pragma_kind_description (defined in pragma.h and available to the +front end only) that summarizes the attributes and processing requirements +of a given pragma.
      +
      +
    • +
    +

    When the pragma has been recognized, much of the processing is governed by the +corresponding pragma kind description, which contains information such as how +(and whether) the pragma binds to an IL construct, whether the pragma is +intended to be processed by the front end or back end, and how tokens that +comprise the pragma should be passed from the point at which the pragma is +initially scanned to the point at which the pragma is semantically processed. +The pragma kind description also contains an optional processing function +pointer, which, if present, points to a function to be called to process this +kind of pragma.

    +

    pragma_description_for_pragma_kind is an array of pointers to pragma kind +descriptions that may be indexed by pragma kind. It is initialized in +pragma_init by a series of calls to add_pragma_kind_description.

    +
    +
    +

    15.2. Phase One: Recording Pragmas#

    +

    Pragma directives are initially scanned by the routine proc_pragma, which +is one of the preprocessing routines in preproc.c. As mentioned earlier, +the initial scanning of the pragma may occur far too early for the pragma to be +processed in any meaningful way. The most extreme example of this is a +template definition containing a pragma that must be reevaluated for each +instantiation generated from the template.

    +

    To accommodate this kind of use, the initial scanning of a pragma typically +consists simply of identifying the kind of pragma being scanned, and recording +the body of the pragma in a form in which it may easily be processed later. +Preprocessing immediate pragmas are the exception to this rule, and are +dispatched immediately upon being identified by the preprocessing routines.

    +

    Pragmas are expected to have the form

    +
    +

    #pragma identifier token1 token2 token3 …

    +
    +

    The pragma kind is determined by comparing the identifier with each the +elements of the array pragma_ids. Once the pragma kind has been +determined, the associated pragma kind description determines how the body of +the pragma is to be recorded. The body may be recorded as either a token cache +or a character string. Most pragmas will be recorded as token caches since +this is usually the easiest representation for the front end to use later. +Pragmas that are to be reemitted by the C or C++ generating back end must be +recorded as character strings.

    +

    When a pragma is recorded as a token cache, the pragma kind description +specifies how the lexical routines should tokenize the pragma body. +Specifically, it specifies whether macros should be expanded and whether the +recognition of certain preprocessing tokens (e.g., # and ##) should be +disabled. Typically both of these flags would be FALSE, but when scanning a +pragma containing what looks like a source language construct (as is the case +with the instantiation pragmas) these fields would be TRUE.

    +

    If the configuration parameter INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL is TRUE, +any pragma identifier that is not recognized is processed using the pragma kind +description associated with the pk_unrecognized pragma kind.

    +

    To record the pragma a pending pragma entry is allocated (see +alloc_pending_pragma in pragma.c), and the pragma representation (token +cache or text) is attached to it. A pragma is associated with a token that +immediately follows it in the source, so the newly created pending pragma entry +is appended to curr_token_pragmas, a list of pending pragma entries that +are associated with the current token (see add_to_curr_token_pragma_list).

    +

    Since the current token may be cached, the list of pending pragma entries +associated with it is cacheable, too (see add_pragma_entry_to_cache in +lexical.c). When a token is cached, the pragmas associated with it are +recorded in the cache as well, and when the token is retrieved from the cache +the associated pragmas are restored as the current_token_pragmas list. If +the cache from which the token was retrieved is a reusable cache, a copy of the +pragma list is made (instead of using the original list).

    +

    Pending pragma entries are also created to represent “pseudo pragmas”, +constructs that are processed by the front end like pragmas even though they +are not actually represented in the source code by a pragma directive. Thus, +lint comments are implemented as pseudo pragmas; e.g., when a /*ARGSUSED*/ +comment is encountered, the front end generates a pk_lint_argsused pragma +entry, and all subsequent processing is handled just like a pragma specified +using a #pragma directive.

    +
    +
    +

    15.3. Phase Two: Dispatching Pragmas#

    +

    The result of the initial scanning process is curr_token_pragmas, a list of +pending pragma entries that represent the pragmas immediately preceding the +current token. However, the pragma is not subject to further processing simply +as a consequence of being associated with the current token. For example, with

    +
    #pragma xyz
    +int a;
    +
    +
    +

    the xyz pragma is on the current token pragma list for int but is not +made available for additional processing until processing begins on the +construct that int introduces or else until the next token, a, is about +to fetched. This convention is followed to avoid processing the pending pragma +entry prematurely – we wouldn’t want to process pragma xyz if there is a +chance token int will end up in a token cache.

    +

    The pending pragma entries on the curr_token_pragmas list are dispatched +for additional processing either by select_curr_construct_pragmas or by +process_curr_token_pragmas. These routines do most of the middle phase +processing of pending pragma entries. How they differ and how they interact +can be explained in terms of pragma binding kinds.

    +

    Each pragma kind specifies one of three pragma binding kinds [1]; each +binding kind represents a different processing pathway; and each form of +processing implies a different form of dispatching.

    +
      +
    • +
      Pending pragma entries with a binding kind of pbk_immediate and +pbk_next_token are processed immediately at the point the current token +is consumed. Such pragmas may appear anywhere in the program, and though +they may be recorded in the IL, they are not bound to any particular IL +entity (the difference between pbk_immediate and pbk_next_token is +described below).
      +
      +
    • +
    • +
      Pending pragma entries with a binding kind of pbk_next_construct are +subject to processing during the processing of the given statement or +declaration. They must appear immediately before the first token of the +construct to which they will be bound. If they appear in the IL, they will +be bound to a particular IL entity.
      +
      +
    • +
    • +
      Pending pragma entries with a binding kind of pbk_other are not subject +to processing at any particular time – that is up to the implementation. +They may appear anywhere in the source program. They are dispatched onto a +list to wait for a processing function to check for them; if they are not +explicitly handled and removed, they simply remain there until the scope +they belong to is terminated.
      +
      +
    • +
    +
    +

    15.3.1. Bound Pragmas#

    +

    select_curr_construct_pragmas is called at the start of each new +declaration or statement. It is always called before advancing past the first +token of the construct; this is to ensure that it is called before +process_curr_token_pragmas is called. Its principal job is go through the +curr_token_pragmas list, removing each pbk_next_construct entry and +dispatching it to a list specifically reserved for pragmas bound to the current +construct, the curr_construct_pragmas list in the current scope stack +entry. The pragmas wait on the list to be processed sometime during the +processing of the current construct.

    +

    The pending pragma entries associated with the current construct will remain on +the list to which they are dispatched only for the life of the declaration or +statement. If the current construct cannot be bound to (this is the case, for +example, with the declaration of an unnamed enumeration or a break +statement), cannot_bind_to_curr_construct is called to issue diagnostics, +if appropriate, and clear the list. If, usually as a result of an error, the +processing of the pending pragma entries cannot be completed, +discard_curr_construct_pragmas is called to clear the list.

    +

    Normally, therefore, when select_curr_construct_pragmas is called, the list +it updates will have been cleared, since entries on the list for the previous +construct will already have been disposed of by the time the current construct +is dealt with. An exception is when a pragma precedes a label: such a pragma +is construed as applying not to the label but to the construct following, so it +must be preserved on the curr_construct_pragmas list as processing advances +past the label. In such situations pending pragma entries may accumulate, +e.g., for this case

    +
    #pragma some_pragma
    +l:
    +#pragma another_pragma
    +f();
    +
    +
    +

    both pragmas can end up bound to the call of function f.

    +

    Another job of select_curr_construct_pragmas, when source sequence entries +are being generated, is to add a source sequence entry for each pending pragma +entry on the curr_token_pragmas list. If an IL entry is subsequently +created for the pragma, it uses the source sequence entry; otherwise, the +source sequence entry is returned to an available list.

    +
    +
    +

    15.3.2. Unbound Pragmas#

    +

    process_curr_token_pragmas is called each time the current token is about +to be consumed and a new token is about to become the current token. Its job +is to handle pending pragma entries that remain on the curr_token_pragmas +list and then to clear that list before the next token is taken.

    +

    If it finds a pbk_immediate or pbk_next_token pragma on the list, it +initiates the completion of its processing. There is no dispatching of these +pragmas. They are processed immediately and automatically. In non-cached +contexts, pbk_immediate pragmas will have already been procesed when +process_curr_token_pragmas is called and will be ignored.

    +

    pbk_other pragmas are dispatched to a list of the pragmas that are +currently available for further processing in a given scope – see +pending_pragmas in a_scope_stack_entry. The pending pragma entry is +placed on the list of the current scope and is discarded when the current scope +terminates. Such a pragma simply waits on the list until some event removes it +to complete its processing; there is no default mechanism to trigger such +processing automatically.

    +

    Since select_curr_construct_pragmas will already have been called, there +should not be any pbk_next_construct entries remaining on the +curr_token_pragmas list. If there are, they must have appeared in the +source somewhere other than immediately before a declaration or statement. +process_curr_token_pragmas removes them from the list, optionally issuing a +diagnostic of the severity specified in the corresponding pragma kind +description.

    +

    If source sequence entries are being generated, process_curr_token_pragmas +will also add source sequence entries for each pending pragma entry that needs +one. If an IL entry is subsequently created for the pragma, it uses that +source sequence entry; otherwise, the source sequence entry is returned to an +available list.

    +
    +
    +
    +

    15.4. Phase Three: Interpreting Pragmas#

    +

    The pragma representations that result from the scanning of pragmas are called +“pending pragmas” because, having been created as repositories of uninterpreted +information about a specific pragma directive, they wait around for the right +moment for their processing to be completed. The completion can be described +as the “interpretation” of the pragma – its translation into another form so +that it will have the intended effect on subsequent compilation.

    +

    The different pragma binding kinds indicate, as noted above, different +processing pathways:

    +
      +
    • +
      Pending pragma entries with a binding kind of pbk_next_token are +processed automatically by process_curr_token_pragmas, at the point the +current token is consumed.
      +
      +
    • +
    • +
      Pending pragma entries with a binding kind of pbk_immediate are +processed immediately after they have been scanned. In cached contexts +they are also processed by process_curr_token_pragmas (in the same way +as pbk_next_token pragmas) each time the cache is rescanned.
      +
      +
    • +
    • +
      Pending pragma entries with a binding kind of pbk_next_construct are +subject to processing during the processing of the given statement or +declaration. Either they are processed as the result of an explicit action +involving a call to extract_specific_pragmas, or else the processing is +initiated automatically when (at an appropriate point, depending on the +construct they are associated with) process_curr_construct_pragmas is +called.
      +
      +
    • +
    • +
      Pending pragma entries with a binding kind of pbk_other are subject to +processing only as the result of an explicit action involving a call to +extract_specific_pragmas; otherwise they simply remain on the +pending_pragmas list of the current scope stack entry and their +processing is never completed.
      +
      +
    • +
    +

    process_curr_construct_pragmas is the routine that initiates automatic +processing for the pbk_next_construct pragmas associated with a given +declaration or statement. It traverses the list of them on the current scope +stack entry, making sure that each pragma binds to the sort of construct +(statement or declaration) that is currently being processed; it (optionally) +issues a diagnostic otherwise. If automatically_include_in_il (in the +corresponding pragma kind description) is TRUE, it calls +create_il_entry_for_pragma. If next_construct_processing_function is +non-NULL, it calls it do any additional processing that is required. It also +returns all the pending pragma entries to the available list.

    +

    If a pragma should be included in the IL, create_il_entry_for_pragma is +called; it calls add_pragma_to_il, which in turn calls alloc_pragma to +create the entry of type a_pragma and add_to_pragmas_list to add it to +the end of the pragmas list of the proper scope.

    +

    create_il_entry_for_pragma is called automatically – by +process_curr_token_pragmas for pbk_immediate pragmas and by +process_curr_construct_pragmas for pbk_next_construct pragmas – when +the automatically_include_in_il flag is set. It is also called +automatically by extract_specific_pragmas when that flag is set. It can be +called directly from pragma-processing code when automatic creation of IL +entries is undesirable.

    +

    The scope to which the IL pragma entry is attached is determined based on +several considerations. If a pbk_next_construct pragma is bound to a class +member, it belongs to the scope of the class; otherwise, if it is bound to an +IL entry allocated in the file-scope memory region, it belongs to the file +scope; otherwise, it belongs to the current (block or function) scope. A +pbk_immediate, pbk_next_token, or pbk_other pragma belongs to the +file scope if the global flag in the corresponding pragma kind description +is TRUE; otherwise it belongs to the current scope.

    +

    pbk_next_construct pragmas that are added to the IL have a pointer to the +IL entry with which they are associated (a statement, a variable, etc.), but +the latter has no pointer back to the pragma. Instead, the +has_associated_pragma flag (in a_source_correspondence and in +a_statement) is set, indicating that one or more pragmas is bound to it. +find_assoc_pragma may be called to locate the pragma entry (or entries) +associated with a given IL entry.

    +

    The automatic processing of pending pragma entries may also involve calling a +routine to do whatever special processing is required for the particular pragma +kind. The address of this routine, which must be declared with the appropriate +type (see a_next_construct_pragma_function, +an_immediate_pragma_function, and an_other_pragma_function) is recorded +in the pragma kind description. Here are some examples from pragmas supplied +by default by the EDG front end:

    +
      +
    • +
      instantiate_pragma is specified as the processing function for the +pbk_next_token pragma of kind pk_instantiate; it is called by +process_curr_token_pragmas when such pending pragma entries are +encountered; no IL entry is required.
      +
      +
    • +
    • +
      record_arg_pragma is the processing function for pragmas of kind +pk_printf_args and pk_scanf_args; it is called from +process_curr_construct_pragmas. Note that a symbol pointer is included +in the interface of the processing functions for pbk_next_construct +pragmas, and so record_arg_pragma is able to record the event for the +current routine.
      +
      +
    • +
    +

    The timing of the call to process_curr_construct_pragmas and therefore to +the corresponding processing function may be critical. The rules, in general, +are:

    +
      +
    • +
      for declarations, process_curr_construct_pragma is called at the point +the symbol is bound to its corresponding IL entry;
      +
      +
    • +
    • +
      for statements, it is called immediately after the statement entry is +created (but before other processing is done).
      +
      +
    • +
    +

    For reasons of timing and other considerations it is sometimes inappropriate to +use the automatic mechanisms that are provided. An alternative is to call +extract_specific_pragmas, which returns a pending pragma entry of a given +pragma kind, [2] and to do the required processing directly. For an example +of this style of pragma use see record_lint_argsused_and_varargs_state, +which is called only when a function is being defined: if +extract_specific_pragmas returns a pending pragma entry of the specified +kind, it sets a flag in the routine type supplement and, since the entry will +have been removed from the current construct pragma list, calls +free_pending_pragma_list to dispose of it.

    +

    extract_specific_pragmas is also called for pbk_other pragmas. In +fact, it is essential for completing the processing of such pragmas and should +be included in custom code to implement a specific pragma. Once this routine +has been called for a given pragma kind, the pending pragma entry returned is +no longer on the pending_pragmas list, so it cannot be found a second time. +Note also that the calling routine is responsible for freeing the pending +pragma entry.

    +
    +
    +

    15.5. How to Add A New Pragma#

    +

    The mechanisms provided to support #pragma directives have been designed +with extensibility in mind. This section is intended to provide some +additional guidance in adding new pragma kinds. In general, this is what you +will need to do to:

    +
      +
    • +
      Add a new entry to the enumeration a_pragma_kind in il_def.h, and +add an identifier string to the array pragma_ids.
      +
      +
    • +
    • +
      Decide on the binding kind for the pragma.
      +
      +
        +
      • +
        pbk_immediate is appropriate when the pragma’s effect is quite +independent of the context in which it appears in the source. It is +processed unconditionally immediately after the pragma is scanned. If +the pragma appears in a cached context, the pragma is also processed each +time the cache is rescanned.
        +
        +
      • +
      • +
        pbk_next_token is similar to pbk_immediate except that the pragma +is not processed until the next regular (non-preprocessing) token is +fetched and if the pragma appears in a cached context it is not processed +when it is first encountered but only each time the cache is rescanned.
        +
        +
      • +
      • +
        pbk_next_construct is appropriate when the pragma is meant to affect +the construct that immediately follows it in the source. Set one or both +of may_bind_to_decl or may_bind_to_statement depending on what +sort of construct it applies to. These pragmas are discarded (optionally +with a diagnostic) if they appear in front of the wrong kind of +construct.
        +
        +
      • +
      • +
        pbk_other is appropriate for maximum flexibility, though it requires +additional intervention by you, since the automated mechanisms are not +available.
        +
        +
      • +
      • +
        pbk_preproc_immediate is appropriate when the pragma must be +processed when encountered by the preprocessing routines and cannot be +deferred until the next nonpreprocessing token of the program is scanned. +No pending pragma entry is created for these pragmas and they cannot be +entered into the IL.
        +
        +
      • +
      +
    • +
    • +
      Create the pragma kind description by adding a call to +add_pragma_kind_description in pragma_init; the call should be made +using the interface function that is specific to the binding kind.
      +
      +
    • +
    • +
      If you want to store information – say, the value of a pragma argument +that will be used when the pragma is processed – you can add one or more +variant fields to a_pending_pragma. The switch statement in +alloc_pending_pragma (where the variant field, if any, is initialized) +should be updated to recognize the new pragma kind.
      +
      +
    • +
    • +
      If the pragma is to be entered in the IL and additional information is +needed in the IL entry, you should add variant fields to a_pragma +(defined in il_def.h) and initialize them in alloc_pragma (in +il_alloc.c).
      +
      +
    • +
    • +
      If the pragma is to be entered in the IL automatically, set +automatically_include_in_il when creating the pragma kind description +entry.
      +
      +
    • +
    • +
      If the pragma binding kind is pbk_immediate, pbk_next_token, or +pbk_next_construct, decide whether you want a processing function to be +called automatically. If so, be sure to include a pointer to it when +creating the pragma kind description entry.
      +

      +
      Even if you have specified a processing function, be sure that +automatically_include_in_il is FALSE if you want control over whether +the IL pragma entry should be created; if you do this, you can call +create_il_entry_for_pragma. If automatically_include_in_il is +TRUE, the IL pragma entry will already have been created before your +routine is called, but you will still be able to set any variant fields +that are specific to this pragma kind.
      +
      +
    • +
    • +
      If the pragma binding kind is pbk_other – or if it is +pbk_next_construct but you don’t want to use the automatic facility of +process_curr_construct_pragma – you will have to write code to call +extract_specific_pragmas and to do the required processing. Note that, +if automatically_include_in_il is set to TRUE, +extract_specific_pragmas will cause an IL pragma entry to be created; +if you want more control, be sure the flag is FALSE when you create the +pragma kind description entry.
      +
      +
    • +
    • +
      If your code uses extract_specific_pragmas, be sure to call +free_pending_pragma_list to dispose of the pending pragma entry (or +entries) returned to you.
      +
      +
    • +
    • +
      If your pragma processing function needs to deal with more than the pragma +identifier, decide whether your code requires the pragma to be represented +as a text string or as a token cache. If the former, set +record_pragma_text to TRUE when you create the pragma kind description +entry. However, if you choose to deal with tokens, the following +convention should be observed:
      +
      +
        +
      1. Call begin_rescan_of_pragma_tokens to find the appropriate token +cache for rescanning the tokens that comprise the pragma body; it also +pushes a sck_pragma scope. The first token you will see is the one +following the pragma identifier.

      2. +
      3. When you have finished scanning the tokens, call +wrapup_rescan_of_pragma_tokens to pop the sck_pragma scope and +check that all of the tokens were scanned from the cache; if the current +token is not the tok_end_of_source at the end of the pragma +directive, an “extra text in preprocessing directive” error will be +issued.

      4. +
      +
    • +
    • +
      You should set expand_macros to FALSE if you want to suppress macro +expansion while the pragma tokens are scanned. Furthermore, setting +processing_C_code when generating a token cache means keywords will be +recognized and adjacent string literals will be concatenated together.
      +
      +
    • +
    • +
      If you are simply passing the pragma on to the back end without processing +it in the front end, be sure that make_text_not_tokens is TRUE when you +create the pragma kind description entry – a pragma cannot be passed to +the back end in the form of a token cache.
      +
      +
    • +
    • +
      If you want a diagnostic issued when a pbk_next_construct pragma +appears in the wrong place in the source program or an unprocessed +pbk_other pragma is encountered when a scope is popped, set the +error_severity appropriately when you create the pragma kind +description entry; use es_none to suppress the diagnostic.
      +
      +
    • +
    +
    +
    +

    15.6. Introduction to Attributes#

    +

    Unlike pragmas, attributes are parsed like other ordinary language features. +This parsing is usually achieved with a call to scan_attributes, which +returns a list of attributes (an_attribute entries) in the order that they +were encountered. Each attribute entry represent a standard attribute, a GNU +attribute, or a Microsoft __declspec attribute [3]: The specific variant +is recorded in the family field (which can be af_std, af_gnu, or +af_ms_declspec). Whether a specific attribute family syntax is accepted is +determined by the global variables std_attributes_enabled, +gnu_attributes_enabled, and ms_declspec_attributes_enabled. The +parsing process also classifies attributes according to their kind +(ak_align, ak_nothrow, etc.) and their syntactic location +(al_prefix, al_declarator_id, etc.). As with pragmas, the front end +accepts attributes that it doesn’t recognize (these are assigned attribute kind +ak_unrecognized).

    +

    Attributes appear in “groups”. For example:

    +
    __attribute((align(4))) __attribute((pure,nothrow)) void f();
    +
    +
    +

    The an_attribute entry corresponding to the align attribute will point +to a first entry of type an_attribute_group, whereas the an_attribute +entries for pure and nothrow will both point to a second +an_attribute_group entry. Attribute groups can be empty (typically as the +result of macro expansion). To represent empty groups, an ak_empty +attribute is created (which then points to an ordinary entry of type +an_attribute_group). Attribute group entries do not carry information of +their own other than the position of delimiting tokens: Their principal +function is to indicate how attributes were grouped in the source code. The +“upside-down” arrangement of attributes vs. groups keeps all the attributes +associated with a given entity on a “flat” list, which simplifies traversing +them (the alternative would consist in having to traverse groups and within +each group traversing a list of attributes).

    +

    After attributes have been parsed, they are “attached” and “applied” to an +appropriate IL entity. This is usually done by calling attach_attributes.

    +

    Attaching an attribute means recording its entry in the IL by placing it on a +list pointed to by the IL entry of the entity to which the attribute applies. +Usually, the list is pointed to by the attributes field in +a_source_correspondence. Unrecognized attributes are recorded in the IL +only when the global variable record_unrecognized_attributes (initialized +with the configuration macro RECORD_UNRECOGNIZED_ATTRIBUTES) is TRUE. If +unrecognized attributes are not recorded in the IL, they elicit a warning.

    +

    Applying an attribute means that the validity of the attribute for its target +entity is checked (e.g., it is an error for a standard [[nothrow]] +attribute to be applied to a variable) and, possibly, that the IL entry for the +target entity is updated (e.g., the noreturn attribute causes the +does_not_return flag in the corresponding routine type supplement to be set +to TRUE). Applying an unrecognized or an empty attribute has no effect.

    +

    When simultaneously compiling multiple translation units, the attributes +attached to corresponding declarations are checked. By default, attributes +must match exactly, but alternative policies are possible for specific +attributes and contexts.

    +

    The parsing/classification of attributes, their application to IL entities, and +the checking of corresponding attributes across translation units (when +applicable) is at least in part table-driven.

    +
    +
    +

    15.7. Parsing Attributes#

    +

    As mentioned above, attributes are usually parsed by calling +scan_attributes. However, if only GNU attributes should be considered, +scan_gnu_attribute_groups is called instead. Both functions take an +argument of type an_attribute_location, which specifies the syntactic +context in which the call is made. For example, in the declaration

    +
    [[nothrow]] int __attribute((pure))
    +            f [[final]] () __attribute((deprecated));
    +
    +
    +

    the nothrow attribute is parsed as al_prefix, the pure attribute is +parsed as al_specifier, the final attribute is parsed as +al_declarator_id, and the deprecated attribute is parsed as +al_post_func. (I.e., the front end contains calls to scan_attributes +or scan_gnu_attribute_groups in various places, each call passing an +argument reflecting the current parsing context.)

    +

    In the case of standard attributes, strict appertaining rules allow the +syntactic context to unambiguously determine what entity the attribute applies +to. For example, standard al_prefix attributes apply to the variables, +functions, or typedefs being declared, while standard al_specifier +attributes apply to the type specified by the declaration specifiers.

    +

    In contrast, the syntactic location of GNU attributes does not unambiguously +determine the entity they apply to; instead, the affected entity depends on the +attribute kind. For example, in

    +
    __attribute((align(16))) int f1();
    +__attribute((vector_size(16))) int f2();
    +
    +
    +

    the align attribute modifies function f1, but the vector_size +attribute modifies type int. To deal with this, the front end reclassifies +some GNU attributes after they are parsed based on whether the attribute +transforms a type or not. This ensures that the attribute is applied to the +correct entity. For example, the vector_size attribute in the example +above is parsed as al_prefix, but then reclassified as al_specifier +(this is done in attach_specifier_attributes). A related example is

    +
    void f3() __attribute((warn_unused_result));
    +void f4() __attribute((pure));
    +
    +
    +

    These attributes are originally parsed with context al_post_func +(indicating they appear after a function declarator), which for a C++11 +attribute would imply that the attribute applies to the associated function +type. However, GNU attributes in this syntactic context can apply to the +function type (e.g., warn_unused_result) or to the function itself (e.g., +pure). In cases like these, the attributes are reclassified to +al_postfix (in scan_declarator_attributes) and the attribute +application function modifies the function or its type depending on the +attribute (and the same process applies to attributes after array declarators).

    +

    Microsoft __declspec attributes also lack strict appertaining rules, but +their treatment is simpler because there are no type-transforming +__declspec attributes and __declspec attributes can appear in fewer +syntactic locations (only al_prefix, al_specifier, and al_tag_name +contexts are valid, and the former two are usually equivalent). There are some +special cases, however. For example, the align attribute in

    +
    __declspec(align(16)) struct S { ... } x;
    +
    +
    +

    is equivalent to

    +
    struct __declspec(align(16)) S { ... } x;
    +
    +
    +

    and the front end handles this by recording the align attribute as an +al_tag_name attribute in such cases.

    +
    +

    15.7.1. Unscanning Attributes#

    +

    Sometimes, it is not clear at the time of parsing the attribute which context +the attributes will end up in. E.g., GNU attributes can appear after the left +parenthesis introducing function parameters and after the left parenthesis +introducing a nested declarator (see r_declarator in declarator.c). In +such circumstances, the attributes can be scanned (by calling +scan_attributes) with an assumed context, then “unscanned” (with +unscan_attributes), and then “rescanned” by calling scan_attributes +with the correct syntactic location. Note that the call to +unscan_attributes does not restore the tokens that made up the attributes; +it just stores the given attribute entries to be returned by the next call to +scan_attributes.

    +
    +
    +
    +

    15.8. Recognizing Attributes#

    +

    For an attribute to be recognized in the front end, it must have a description +in the array known_attr_table defined in attribute.c. The description +(type an_attr_descr) contains four fields:

    +
      +
    • +
      A string with the source form of the attribute name (e.g., “section”). +The optional leading and trailing underscores in the case of GNU attributes +should not be included in this string.
      +
      +
    • +
    • +
      A string encoding what kind of arguments (if any) the attribute takes. +This the “signature” of the attribute. The details of this encoding are +described in the definition of an_attr_descr in attribute.c. For +example, the code "(sn+)" would indicate that an argument list is +required and that it should contain one or more (narrow) string literals.
      +
      +
    • +
    • +
      A string encoding the general conditions (primarily, the mode) in which an +attribute should be accepted, and, in the case of standard attributes, the +attribute namespace for the attribute. This encoding too is described in +the definition of an_attr_descr in attribute.c. For example, +"g+(-39999)" indicates that the attribute should be accepted as a GNU +attribute in GNU C++ modes with gnu_version less than 40000, while +"c+[EDG]" specifies that the attribute should be accepted with standard +syntax and namespace-prefix EDG:: in modes that accept standard C++11 +attribute syntax.
      +
      +
    • +
    • +
      The attribute kind (e.g., ak_section) that should be assigned to the +attribute.
      +
      +
    • +
    +

    Note that there can be multiple entries for the same attribute kind. For +example, the nothrow attribute is accepted as a GNU attribute, as a +Microsoft __declspec attribute, and as a standard attribute, and therefore +(at the time of this writing) it has three description entries as follows:

    +
    ...
    +{ "nothrow", "", "1c+", ak_nothrow },
    +...
    +{ "nothrow", "", "gx", ak_nothrow },
    +...
    +{ "nothrow", "", "m+", ak_nothrow },
    +...
    +
    +
    +

    (the prefix “1” in "1c+" indicates that the attribute cannot be +repeated in an attribute group).

    +

    If an attribute name is recognized, but it does not meet other constraints, a +diagnostic is issued and the attribute is reclassified as ak_unrecognized +(by calling the macro make_attr_unrecognized). This recovery technique is +used throughout attribute processing: Rather than dropping an attribute +altogether, it is generally just reclassified by calling +make_attr_unrecognized.

    +
    +
    +

    15.9. Applying Attributes#

    +

    The application of attributes is highly dependent on the specific attribute +being applied, but some of the processing is also table-driven. Specifically, +the array known_attr_appl_table contains an entry of type +an_attr_appl_descr for every attribute kind. Each entry contains the +following fields:

    +
      +
    • +
      The attribute kind, included only for readability and consistency checking +(the array contents must match the enumeration an_attribute_kind).
      +
      +
    • +
    • +
      A string encoding which entity kinds an attribute applies to, and, +optionally, simple constraints for matching entities. The details of the +encoding are described in the definition of an_attr_appl_descr in +attribute.c. For example, "r|v" means the attribute applies to +routines and variables only, while "r|v:-a" means the same thing, but +requires the variable not to have automatic storage duration. (A failure +to meet these constraints causes the attribute to be reclassified as +ak_unrecognized.)
      +
      +
    • +
    • +
      A pointer to a callback function (of type an_attr_application_fn). If +this pointer is non-NULL and if the constraints in the previous field are +fullfilled, the indicated function is called with the attribute and the IL +entry it applies to (the “target entity”) passed in as arguments. The +callback function can check additional constraints on the target entity and +update the entry (and any other structures) as appropriate.
      +
      +
    • +
    +

    A few Microsoft __declspec attributes require special handling in the front +end. For example, the presence of a property(...) attribute is detected +soon after being scanned because it affects certain semantic checks performed +by the front end before the complete declaration has been parsed (and, +therefore, before the application callback function can be called).

    +
    +

    15.9.1. Type-Transforming Attributes#

    +

    Most attributes only modify relatively minor properties of the entities to +which they apply, and this modification is to the entity itself. For example, +the standard attribute [[final]] when applied to a class type X +prevents other classes from deriving from X; it does not create a new IL +entry. Some GNU attributes, however, can transform a type into a new type +requiring a distinct IL entry [4]. For example, the GNU attribute in:

    +
    float __attribute((vector_size(16))) vec;
    +
    +
    +

    transforms type float to a type “vector of float”. Such +type-transforming attributes are applied (and attached) using function +attach_type_attributes. It uses the array known_attr_appl_table much +like attach_attributes, but instead of making the resulting type entry +point directly to the attributes list, it adds a tk_typeref entry on top of +the resulting type for that purpose.

    +

    Because of the possibility of entity transformation, the callback functions +recorded in known_attr_appl_table must return an IL entry pointer that +represents the entity resulting from the application of the attribute to a +given entity. Except for type-transforming attributes, the returned IL entry +is the same entry as the one passed to the callback function.

    +
    +
    +
    +

    15.10. Attributes in Back Ends#

    +

    Most known attributes have an effect on IL fields that provides sufficient +information to a traditional code-generating back end. For example, the +nothrow attribute causes the never_throws flag in a_routine to be +set to TRUE. However, since attribute entries are also pointed to by affected +entities, it is not strictly necessary to add separate fields to IL entries. A +specific attribute can be found using the function find_attribute. For +example, the standard attribute carries_dependency is currently only +represented by its an_attribute entry.

    +

    The C-generating back end ignores most an_attribute entries. Instead, it +usually renders GNU attributes (when the target compiler is known to be a +version of GCC) based on other fields in the IL. However, for some attributes +that are only represented in the IL through their an_attribute entry, the +C-generating back end may emit a GNU attribute construct based on the presence +of the corresponding entry.

    +

    The C++-generating back end, on the other hand, renders attributes based only +on applicable an_attribute entries. To ensure that the rendered code is +close to the original form, attributes specified on a secondary declaration are +recorded twice in the IL (i.e., the entries are duplicated): Once on the list +pointed to by the source correspondence of the target entity, and once on a +list pointed by the associated a_src_seq_secondary_decl. Attributes on +primary declarations are recorded only once, but are marked as having appeared +on the primary declaration (flag on_primary_declaration in +an_attribute).

    +
    +
    +

    15.11. How to Add a New Attribute#

    +

    The framework described above make the addition of many common kinds of +attributes relatively simple:

    +
      +
    • +
      Add an ak_… attribute kind in il_def.h.
      +
      +
    • +
    • +
      Add one or more entries to the known_attr_table in attribute.c.
      +
      +
    • +
    • +
      Add an entry in the known_attr_appl_table in attribute.c.
      +
      +
    • +
    • +
      Write the callback function specified in the new known_attr_appl_table +entry (if such a callback is needed at all).
      +
      +
    • +
    • +
      If the attribute is not required to match exactly across translation units, +add one or more entries describing the correspondence handling to the +attr_corresp_table defined in attribute.c. (In some cases this may +involve adding additional functions or updating the code in +trans_corresp.c.)
      +
      +
    • +
    +

    (The attribute may require new IL entry fields or even new IL entry kinds. If +so, see How To Extend the IL.)

    +

    If attributes must be recognized in contexts that do not currently allow them, +additional calls to scan_attributes and attach_attributes must be added +to the front end (and, most likely, additional enumeration constants for +an_attribute_location). If the C++-generating back end is used, it will +also require a matching call to gen_attributes.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/runtime/index.html b/dev/doc/runtime/index.html new file mode 100644 index 0000000..7a4f3d7 --- /dev/null +++ b/dev/doc/runtime/index.html @@ -0,0 +1,477 @@ + + + + + 21. Runtime Library - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    21. Runtime Library#

    +

    The runtime library routines provide basic runtime support. The source for +these routines is in the lib_src directory of the release structure.

    +

    “Basic” runtime support means support for operations built in to the C++ +language, like new and delete, and for operations for which code is +generated by IL lowering, e.g., array initialization. (This includes code +generated by the lowering of C99 constructs.) It does not mean support for all +libraries required by the C++ standard, e.g., iostreams.

    +

    The front end supports two different runtime models. A configuration macro is +used to select the runtime model to be used. The models supported are the +IA-64 ABI and one that is an extension of the one used with cfront.

    +

    The IA-64 model is a complete implementation of the IA-64 ABI, except that the +exception handling implementation does not conform to the ABI (because +producing a conforming implementation of exception handling requires back end +support).

    +

    The cfront runtime model is generally compatible with the one used by +cfront version 3.0.2, and in fact the code generated by the front end in +cfront object code compatibility mode will work with the libraries +supplied with cfront (with one exception that is described below). +Another way of saying the same thing: The runtime library is an independent +implementation of the runtime interface defined by cfront.

    +

    One incompatibility between our runtime support library and the one provided +with cfront is the handling of static destructors. The cfront static +destruction mechanism does not conform to the C++ standard, which requires all +static objects, including local static objects, to be destroyed in the reverse +order of construction. The EDG static destruction mechanism relies on a new +data structure called the needed destructions list. If a cfront runtime +library is to be used, the dtor_list.o file from the EDG library must be +included when a program is linked. This may be done by explicitly including +dtor_list.o in the link command generated by the driver, or by adding +dtor_list.o to the library file containing the cfront libraries.

    +

    In the area of exception handling, there is no standard cfront runtime +model (because no version of cfront that supports exception handling was +released by USL), so the model is invented by EDG, drawing on some +published aspects of the implementation done by Hewlett-Packard.

    +

    The runtime routines should be considered to be a sample implementation of a +runtime library. They are believed to be complete and to work correctly, but +they might require adaptation to make them work correctly in a given +environment, or to make them compatible with other runtime libraries or +conventions on the target system. In particular, if runtime compatibility with +cfront is not required, there are probably better ways of doing some of these +things. Also, the target system may provide efficient support for things that +can only be done in a clumsy way in a portable runtime library, e.g., getting +start-up initialization code run automatically at the beginning of execution.

    +
    +

    21.1. The --building_runtime option#

    +

    Like the front end, the runtime contains a number of configuration flags. In +many cases, it is essential that the same values be used by both the front end +and the runtime with which the generated code will be linked. To help make +sure the runtime is configured properly the --building_runtime option +should be specified when compiling the runtime. This causes additional +preprocessing macros to be defined that pass the value of certain configuration +flags from the front end to the runtime. The following preprocessing macros +are defined when the --building_runtime option is used:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    __EDG_JMP_BUF_ELEMENT_TYPE
    +

    +
    +
    +
    The name of the integer or floating point type that is used as the +element type of the jmp_buf array used by setjmp.
    +
    +
    +
    __EDG_JMP_BUF_NUM_ELEMENTS
    +

    +
    +
    +
    The number of elements in the jmp_buf array used by setjmp.
    +
    +
    +
    __EDG_DELTA_TYPE
    +
    +
    +
    The name of the integer type that is used to represent the offset in a +virtual function table entry.
    +
    +
    +
    __EDG_VIRTUAL_FUNCTION_INDEX_TYPE
    +

    +
    +
    +
    The name of the integer type that is used to represent the index field +in a virtual function table entry.
    +
    +
    +
    __EDG_VAR_HANDLE_TYPE
    +

    +
    +
    +
    The name of the integer type that is used to represent a “handle” in +exception handling tables. Defined only when GENERATE_EH_TABLES +is TRUE.
    +
    +
    +
    __EDG_REGION_NUMBER_TYPE
    +

    +
    +
    +
    The type of a region number field in the exception handling tables. +Defined only when GENERATE_EH_TABLES is TRUE.
    +
    +
    +
    __EDG_ETS_FLAG_TYPE
    +

    +
    +
    +
    The type used to pass exception types flags to the runtime library. +Defined only when GENERATE_EH_TABLES is TRUE.
    +
    +
    +
    __EDG_NULL_EH_REGION_NUMBER
    +

    +
    +
    +
    The value used as the null region number value in the exception +handling tables. Defined only when GENERATE_EH_TABLES is TRUE.
    +
    +
    +
    __EDG_LOWER_VARIABLE_LENGTH_ARRAYS
    +

    +
    +
    +
    Indicates whether or not the front end is configured to lower +variable-length arrays. Set to the value of (VLA_ALLOWED && +LOWER_VARIABLE_LENGTH_ARRAYS) in the front end.
    +
    +
    +
    __EDG_IA64_ABI_USE_VARIANT_ARRAY_COOKIES
    +

    +
    +
    +
    Non-zero when the variant representation of array cookies is used in +the IA-64 ABI. Defined only when IA64_ABI is TRUE.
    +
    +
    +
    __EDG_ELEM_COUNT_PARAM_TYPE
    +

    +
    +
    +
    The type used to represent the number_of_elements argument in the +Cfront-like ABI. Defined only when IA64_ABI is FALSE.
    +
    +
    +
    __EDG_ABI_COMPATIBILITY_VERSION
    +

    +
    +
    +
    The value of ABI_COMPATIBILITY_VERSION used when the front end was +built.
    +
    +
    +
    __EDG_ABI_CHANGES_FOR_RTTI
    +

    +
    +
    +
    The value of ABI_CHANGES_FOR_RTTI used when the front end was +built.
    +
    +
    +
    __EDG_ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE
    +

    +
    +
    +
    The value of ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE used when the +front end was built.
    +
    +
    +
    __EDG_ABI_CHANGES_FOR_PLACEMENT_DELETE
    +

    +
    +
    +
    The value of ABI_CHANGES_FOR_PLACEMENT_DELETE used when the front +end was built.
    +
    +
    +
    __EDG_BSD
    +
    +
    +
    The value of the __BSD__ macro when the front end was built.
    +
    +
    +
    __EDG_SYSV
    +
    +
    +
    The value of the __SYSV__ macro when the front end was built.
    +
    +
    +
    __EDG_ANSIC
    +
    +
    +
    The value of the__ANSIC__ macro when the front end was built.
    +
    +
    +
    __EDG_CPP11_IL_EXTENSIONS_SUPPORTED
    +
    +
    +
    The value of CPP11_IL_EXTENSIONS_SUPPORTED when the front end was +built.
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/search/index.html b/dev/doc/search/index.html new file mode 100644 index 0000000..72b7789 --- /dev/null +++ b/dev/doc/search/index.html @@ -0,0 +1,112 @@ + + + + + Search - CPFE 7.0 documentation + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    +
    + +

    Search

    + + + + +

    + Searching for multiple words only shows matches that contain + all words. +

    + + +
    + + +
    +

    + + +
    + + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + + + + \ No newline at end of file diff --git a/dev/doc/searchindex.js b/dev/doc/searchindex.js new file mode 100644 index 0000000..75efebd --- /dev/null +++ b/dev/doc/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"alltitles":{"#elif":[[4,"elif"]],"#else":[[4,"else"]],"#if and #endif":[[4,"if-and-endif"]],"#pragma Directives":[[23,"pragma-directives"]],"A rethrow from the handler":[[8,"a-rethrow-from-the-handler"]],"A walk-through of an EH example":[[8,"a-walk-through-of-an-eh-example"]],"ABI support":[[16,"abi-support"]],"ANSI C Extensions":[[10,"ansi-c-extensions"]],"ANSI C and C++ Include Files":[[12,null]],"AT&T Preprocessing Extensions":[[15,"at-t-preprocessing-extensions"]],"Access Control":[[11,"access-control"],[21,"access-control"]],"Active, Inactive, and \u201cOther\u201d Symbols":[[21,"active-inactive-and-other-symbols"]],"Adding a Field to an Existing IL Entry":[[11,"adding-a-field-to-an-existing-il-entry"]],"Adding a New Operator":[[11,"adding-a-new-operator"]],"Adding an IL Entry":[[11,"adding-an-il-entry"]],"Address of Overloaded Function":[[9,"address-of-overloaded-function"]],"Addressing operators":[[11,"addressing-operators"]],"Administrative Functions":[[0,null]],"Advanced Concepts":[[24,"advanced-concepts"]],"Advanced Stage Breakdown":[[17,"advanced-stage-breakdown"]],"Aggregate Initializers":[[6,"aggregate-initializers"]],"Alias Templates":[[23,"alias-templates"],[23,"id13"]],"Alias templates":[[23,"id4"]],"Alternative Language Behaviors":[[10,"alternative-language-behaviors"]],"Anachronisms Accepted":[[10,"anachronisms-accepted"]],"Annotating Function Arguments":[[4,"annotating-function-arguments"]],"Anonymous Unions":[[11,"anonymous-unions"],[16,"anonymous-unions"]],"Applying Attributes":[[18,"applying-attributes"]],"Argument Dependent Lookup":[[10,"argument-dependent-lookup"]],"Argument-Dependent Lookup":[[21,"argument-dependent-lookup"]],"Asking Questions About Types":[[22,"asking-questions-about-types"]],"Assignments":[[11,"assignments"]],"At the end of a handler":[[8,"at-the-end-of-a-handler"]],"Attributes":[[11,"attributes"]],"Attributes in Back Ends":[[18,"attributes-in-back-ends"]],"Auto type deduction":[[6,"auto-type-deduction"]],"Automatic Instantiation":[[10,"automatic-instantiation"],[23,"automatic-instantiation"]],"Automatic Precompiled Header Processing":[[10,"automatic-precompiled-header-processing"]],"Automatic Template Instantiation":[[16,"automatic-template-instantiation"]],"Automatically Generated Definitions":[[23,"automatically-generated-definitions"]],"Base Class Entries":[[11,"base-class-entries"]],"Base Class List":[[3,"base-class-list"]],"Base Classes":[[3,"base-classes"]],"Basic Node":[[17,"basic-node"]],"Basic Organization":[[21,"basic-organization"]],"Binary Conditional Operator":[[11,"binary-conditional-operator"]],"Bitfield":[[17,"bitfield"],[17,"ifc-bitfield-versioning"]],"Bitwidth Limitations":[[17,"bitwidth-limitations"]],"Bound Pragmas":[[18,"bound-pragmas"]],"Boxing and Unboxing":[[11,"boxing-and-unboxing"]],"Building Support for C++/CLI and C++/CX Modes":[[1,"building-support-for-c-cli-and-c-cx-modes"]],"Building and Using the IL Display Program":[[1,"building-and-using-the-il-display-program"]],"Building the Front End":[[1,"building-the-front-end"]],"Building the Front End Only":[[1,"building-the-front-end-only"]],"Byte Buffer Adjustment":[[17,"byte-buffer-adjustment"]],"Byte Buffers":[[17,"byte-buffers"]],"C Dialect Accepted":[[10,"id3"]],"C mode out-of-scope declarations":[[21,"c-mode-out-of-scope-declarations"]],"C versus C++ Intermediate language":[[11,"c-versus-c-intermediate-language"]],"C++ Dialect Accepted":[[10,"c-dialect-accepted"]],"C++-Generating Back End":[[5,null]],"C++/CLI Accessor Names":[[3,"c-cli-accessor-names"]],"C++/CLI Assembly Import":[[15,"c-cli-assembly-import"]],"C++/CLI Derivations":[[3,"c-cli-derivations"]],"C++/CLI Generics":[[9,"c-cli-generics"],[23,"c-cli-generics"]],"C++/CLI Initialization":[[0,"c-cli-initialization"]],"C++/CLI Managed Class Definitions":[[3,"c-cli-managed-class-definitions"]],"C++/CLI Member Functions":[[3,"c-cli-member-functions"]],"C++/CLI Options":[[10,"c-cli-options"]],"C++/CLI Static Data Members":[[3,"c-cli-static-data-members"]],"C++/CLI Type Constructs":[[6,"c-cli-type-constructs"]],"C++/CLI Types":[[11,"c-cli-types"]],"C++/CLI and the Intermediate Language":[[11,"c-cli-and-the-intermediate-language"]],"C++20 Implementation Status":[[10,"c-20-implementation-status"]],"C++23 and C++26 Implementation Status":[[10,"c-23-and-c-26-implementation-status"]],"C-Generating Back End":[[2,null]],"C-style":[[4,"c-style"]],"C/C++ Front End Documentation":[[13,null]],"C99 Features Available in Other Modes":[[10,"c99-features-available-in-other-modes"]],"C99 and the Intermediate Language":[[11,"c99-and-the-intermediate-language"]],"C99 features":[[11,"c99-features"]],"Calls":[[11,"calls"],[16,"calls"]],"Canonical Entries":[[25,"canonical-entries"]],"Casts":[[11,"casts"]],"Catching an Exception":[[16,"catching-an-exception"]],"Cfront-like ABI name mangling":[[16,"cfront-like-abi-name-mangling"]],"Checking Code":[[14,"checking-code"]],"Checking Operands":[[9,"checking-operands"]],"Class Declarations":[[3,null],[3,"id1"]],"Class Definitions":[[3,"class-definitions"]],"Class Layout":[[11,"class-layout"]],"Class Linkage":[[3,"class-linkage"]],"Class Member Declaration Lists":[[11,"class-member-declaration-lists"]],"Class Member Projection Symbols":[[21,"class-member-projection-symbols"]],"Class Object Layout":[[3,"class-object-layout"]],"Class Scopes":[[11,"class-scopes"]],"Class Symbol Supplement":[[21,"class-symbol-supplement"]],"Class Templates":[[23,"class-templates"],[23,"id3"],[23,"id6"],[23,"id10"],[23,"id12"]],"Class Types":[[11,"class-types"],[16,"class-types"]],"Classes":[[21,"classes"]],"Classification of Identifier Characters":[[15,"classification-of-identifier-characters"]],"Classifying the Template Declaration":[[23,"classifying-the-template-declaration"]],"Coalesce-and-Look-Up Routines":[[15,"coalesce-and-look-up-routines"]],"Code Generation Options":[[10,"code-generation-options"]],"Code Organization":[[17,"code-organization"]],"Code generated for a try block":[[8,"code-generated-for-a-try-block"]],"Coding Philosophy":[[14,"coding-philosophy"]],"Coding Style Guide":[[4,null]],"Command Line":[[10,"command-line"]],"Command-line Parsing":[[0,"command-line-parsing"]],"Commonly-used Configuration Macros":[[1,"commonly-used-configuration-macros"]],"Compiler-Generated Functions":[[3,"compiler-generated-functions"]],"Completing the Declaration":[[6,"completing-the-declaration"]],"Completing the Function Template":[[23,"completing-the-function-template"]],"Compound Assignments":[[11,"compound-assignments"]],"Concepts":[[23,"concepts"]],"Condition Declarations":[[11,"condition-declarations"],[16,"condition-declarations"]],"Configuration":[[2,"configuration"]],"Configuring and Building the C++ Front End":[[1,null]],"Configuring and Building the Run-Time Support Library":[[1,"configuring-and-building-the-run-time-support-library"]],"Configuring the Front End":[[1,"configuring-the-front-end"]],"Connection With IL Scope Entries":[[21,"connection-with-il-scope-entries"]],"Constant Entries":[[22,"constant-entries"]],"Constant Expressions":[[9,"constant-expressions"]],"Constant Folding":[[9,"constant-folding"]],"Constants":[[5,"constants"],[11,"constants"]],"Constrained Templates":[[23,"constrained-templates"]],"Constructor Initializers":[[6,"constructor-initializers"]],"Constructor Wrapper Code":[[16,"constructor-wrapper-code"]],"Constructors and Destructors":[[11,"constructors-and-destructors"],[21,"constructors-and-destructors"]],"Constructors and Destructors for Arrays":[[16,"constructors-and-destructors-for-arrays"]],"Conventions for Declarations":[[14,"conventions-for-declarations"]],"Conversion of Literal Constants":[[15,"conversion-of-literal-constants"]],"Copy Constructor Elision":[[9,"copy-constructor-elision"]],"Copying Tested Binaries":[[24,"copying-tested-binaries"]],"Copying from Secondary Translation Units":[[25,"copying-from-secondary-translation-units"]],"Correspondence Checking":[[25,"correspondence-checking"]],"Covariant return types on virtual functions":[[16,"covariant-return-types-on-virtual-functions"]],"Creating a PCH File":[[0,"creating-a-pch-file"]],"Data Members":[[4,"data-members"]],"Data Structures":[[23,"data-structures"]],"Debug Code":[[14,"debug-code"]],"Debug Print Routines":[[22,"debug-print-routines"]],"Debug Routines":[[0,"debug-routines"]],"Debugging":[[17,"debugging"]],"Debugging Facilities":[[25,"debugging-facilities"]],"Declaration Parse State":[[6,"declaration-parse-state"]],"Declaration Scanning":[[6,"declaration-scanning"]],"Declaration Specifiers":[[6,"declaration-specifiers"]],"Declarations":[[3,"declarations"],[5,"declarations"],[6,null]],"Declarations from C++/CLI Assembly Metadata":[[6,"declarations-from-c-cli-assembly-metadata"]],"Declarations vs. Expressions":[[6,"declarations-vs-expressions"]],"Declarators":[[6,"declarators"]],"Default Arguments":[[3,"default-arguments"]],"Default Initialization":[[6,"default-initialization"]],"Deferred Class Fixup":[[3,"deferred-class-fixup"]],"Delegates (C++/CLI mode)":[[3,"delegates-c-cli-mode"]],"Dependent Name Processing":[[10,"dependent-name-processing"]],"Derivation Path":[[3,"derivation-path"]],"Deserialization":[[17,"deserialization"]],"Destructor Wrapper Code":[[16,"destructor-wrapper-code"]],"Destructor-initializers":[[6,"destructor-initializers"]],"Detection of Source Code Unicode Vulnerabilities":[[15,"detection-of-source-code-unicode-vulnerabilities"]],"Development Aids":[[1,"development-aids"]],"Diagnostic Messages":[[10,"diagnostic-messages"]],"Diagnostic Options":[[10,"diagnostic-options"]],"Diagnostic Pragmas":[[10,"diagnostic-pragmas"]],"Diagnostic output":[[9,"diagnostic-output"]],"Directories and Files in a Release":[[1,"directories-and-files-in-a-release"]],"Documentation":[[4,"documentation"]],"Driving the Front End":[[1,"driving-the-front-end"]],"Dynamic Initialization":[[11,"dynamic-initialization"],[16,"dynamic-initialization"]],"EDG Testing Framework":[[24,null]],"Empty Loop Bodies":[[4,"empty-loop-bodies"]],"Endianness Agnostic Reading":[[17,"endianness-agnostic-reading"]],"Entry Prefix":[[11,"entry-prefix"]],"Environment Variables":[[10,"environment-variables"]],"Error Codes":[[14,"error-codes"]],"Error Entries":[[14,"error-entries"]],"Error Messages":[[7,null]],"Error Positions":[[14,"error-positions"]],"Error Recovery":[[14,"error-recovery"]],"Error Reporting":[[0,"error-reporting"]],"Exception Handling":[[8,null]],"Exception Specifications":[[8,"exception-specifications"]],"Exceptions":[[16,"exceptions"]],"Executable Code":[[5,"executable-code"]],"Exit Status":[[10,"exit-status"]],"Expectation Inheritance":[[24,"expectation-inheritance"]],"Explicit Bounds Copying":[[17,"explicit-bounds-copying"]],"Explicit Instantiation Directives":[[23,"explicit-instantiation-directives"]],"Explicit Specializations":[[23,"explicit-specializations"]],"Explicit and Implicit Captures":[[3,"explicit-and-implicit-captures"]],"Exported Templates":[[10,"exported-templates"],[23,"exported-templates"]],"Expression Lists and Initializer Lists":[[9,"expression-lists-and-initializer-lists"]],"Expression Processing":[[14,"expression-processing"]],"Expression Scanning":[[9,null]],"Expression Temporaries":[[16,"expression-temporaries"]],"Expressions":[[11,"expressions"],[22,"expressions"]],"Extensions Accepted in Cfront 2.1 Compatibility Mode":[[10,"extensions-accepted-in-cfront-2-1-compatibility-mode"]],"Extensions Accepted in Cfront 2.1 and 3.0 Compatibility Mode":[[10,"extensions-accepted-in-cfront-2-1-and-3-0-compatibility-mode"]],"Extensions Accepted in SVR4 Compatibility Mode":[[10,"extensions-accepted-in-svr4-compatibility-mode"]],"Extensions Accepted in Sun Compatibility Mode":[[10,"extensions-accepted-in-sun-compatibility-mode"]],"Extern Inline Functions":[[10,"extern-inline-functions"]],"External Interface":[[10,null]],"External Names":[[14,"external-names"]],"Externalization of statics":[[25,"externalization-of-statics"]],"Failure Debug Mode":[[24,"failure-debug-mode"]],"Failure Limiting":[[24,"failure-limiting"]],"Field Copying":[[17,"field-copying"]],"Field Deserialization":[[17,"field-deserialization"]],"Field Initializers":[[3,"field-initializers"]],"Field Presence Checking":[[17,"field-presence-checking"]],"Field Selection":[[11,"field-selection"]],"Fields":[[3,"fields"]],"File Variables":[[0,"file-variables"]],"File-Loaded Filters":[[24,"file-loaded-filters"]],"Filter Reduction":[[24,"filter-reduction"]],"Filtering":[[24,"filtering"]],"Finding Corresponding Pairs":[[25,"finding-corresponding-pairs"]],"Finding Include Files":[[10,"finding-include-files"]],"Finding Module Files":[[10,"finding-module-files"]],"Finding the exported template definition":[[10,"finding-the-exported-template-definition"]],"Fixed-point operations":[[11,"fixed-point-operations"]],"Fold Expressions":[[11,"fold-expressions"]],"Folding and constexpr":[[9,"folding-and-constexpr"]],"Folding of Constant Operations":[[9,"folding-of-constant-operations"]],"For-each Statement":[[9,"for-each-statement"]],"Foreign Index":[[17,"foreign-index"],[17,"id5"]],"Friend Declarations":[[3,"friend-declarations"]],"Front End Behaviors":[[1,"front-end-behaviors"]],"Front End Debugging Options":[[10,"front-end-debugging-options"]],"Full Instantiation":[[23,"full-instantiation"]],"Function":[[2,"function"]],"Function Overloading":[[21,"function-overloading"]],"Function Template References":[[15,"function-template-references"]],"Function Templates":[[23,"function-templates"],[23,"id5"],[23,"id7"],[23,"id14"]],"Function Templates and Member Functions of Class Templates":[[23,"function-templates-and-member-functions-of-class-templates"]],"Function of the Front End":[[14,"function-of-the-front-end"]],"GNU C++ Mode":[[10,"gnu-c-mode"]],"General Condition Rules":[[4,"general-condition-rules"]],"General Information":[[11,"general-information"]],"General Layout Steps":[[3,"general-layout-steps"]],"General Line Breaks":[[4,"general-line-breaks"]],"General Line Wrapping":[[4,"general-line-wrapping"]],"General Statement Rules":[[4,"general-statement-rules"]],"General Whitespace Rules":[[4,"general-whitespace-rules"]],"Generalized Identifier Errors":[[15,"generalized-identifier-errors"]],"Generated C Code":[[2,"generated-c-code"]],"Generating Strings from IL Types and Constants":[[0,"generating-strings-from-il-types-and-constants"]],"Generating the Template Class":[[23,"generating-the-template-class"]],"Getting Information About Base Classes":[[22,"getting-information-about-base-classes"]],"Getting Tokens":[[15,"getting-tokens"]],"Guard Code on Variable Template and Template Static Data Member Initializations":[[16,"guard-code-on-variable-template-and-template-static-data-member-initializations"]],"Guide to the Source Files":[[14,"guide-to-the-source-files"]],"Hanging Delete":[[15,"hanging-delete"]],"Header Node":[[17,"header-node"]],"Hide-by-sig lookup":[[21,"hide-by-sig-lookup"]],"Host-dependent Routines":[[0,"host-dependent-routines"]],"How To Extend the IL":[[11,"how-to-extend-the-il"]],"How is IL Lowering Done?":[[16,"how-is-il-lowering-done"]],"How to Add A New Pragma":[[18,"how-to-add-a-new-pragma"]],"How to Add a New Attribute":[[18,"how-to-add-a-new-attribute"]],"IA-64 ABI name mangling":[[16,"ia-64-abi-name-mangling"]],"IL Display Pragma":[[10,"il-display-pragma"]],"IL Features":[[1,"il-features"]],"IL Lowering":[[16,null]],"IL Representation":[[6,"il-representation"]],"IL Use Within the Front End":[[11,"il-use-within-the-front-end"]],"Identifiers and Symbol Headers":[[21,"identifiers-and-symbol-headers"]],"Impact on Versioning":[[17,"impact-on-versioning"]],"Implementing Alternative Automatic Instantiation Mechanisms":[[23,"implementing-alternative-automatic-instantiation-mechanisms"]],"Implicit Bounds Copying":[[17,"implicit-bounds-copying"]],"Implicit Conversion":[[17,"implicit-conversion"]],"Implicit Inclusion":[[10,"implicit-inclusion"],[23,"implicit-inclusion"]],"Important Constrained-Template Functions":[[23,"important-constrained-template-functions"]],"In the handler":[[8,"in-the-handler"]],"Include Files":[[14,"include-files"]],"Index Sort":[[17,"index-sort"],[17,"ifc-index-sort-versioning"],[17,"id10"]],"Indices and tables":[[13,"indices-and-tables"]],"Individual Language Features":[[10,"individual-language-features"]],"Init Components and Init States":[[6,"init-components-and-init-states"]],"Initial Compilation":[[23,"initial-compilation"]],"Initialization":[[6,"initialization"]],"Initialization Positions":[[16,"initialization-positions"]],"Initialization and Wrapup":[[0,"initialization-and-wrapup"]],"Initialization, Termination, and Keeping Translation Units Separate":[[25,"initialization-termination-and-keeping-translation-units-separate"]],"Inline Definitions":[[3,"inline-definitions"]],"Inlining":[[16,"inlining"]],"Input/output Options":[[10,"input-output-options"]],"Insert Locations":[[16,"insert-locations"]],"Inserting Text into the Token Stream":[[15,"inserting-text-into-the-token-stream"]],"Instantiating Non-Template Inline Functions":[[23,"instantiating-non-template-inline-functions"]],"Instantiation #pragma Directives":[[10,"instantiation-pragma-directives"]],"Instantiation Context Lookup":[[21,"instantiation-context-lookup"]],"Instantiation Modes":[[10,"instantiation-modes"],[23,"instantiation-modes"]],"Instantiation Pragmas":[[10,"instantiation-pragmas"]],"Intelligent Error Diagnosis":[[14,"intelligent-error-diagnosis"]],"Intermediate Language":[[11,null]],"Intermediate Language Display":[[0,"intermediate-language-display"]],"Intermediate Language Files":[[11,"intermediate-language-files"]],"Intermediate Language Traversal":[[0,"intermediate-language-traversal"]],"Introduction":[[13,"introduction"]],"Introduction to Attributes":[[18,"introduction-to-attributes"]],"Introduction to Pragma Processing":[[18,"introduction-to-pragma-processing"]],"Iteration and Termination":[[23,"iteration-and-termination"]],"K&R/pcc Mode":[[10,"k-r-pcc-mode"]],"Labels":[[11,"labels"]],"Lambda Expression":[[11,"lambda-expression"]],"Lambdas":[[3,"lambdas"]],"Language Dialect":[[14,"language-dialect"]],"Language Dialect Options":[[10,"language-dialect-options"]],"Lexical Analysis":[[15,"lexical-analysis"]],"Lexical Analysis and Preprocessing":[[15,null]],"Libraries with exported templates":[[10,"libraries-with-exported-templates"]],"Limited Scope":[[17,"limited-scope"]],"Linkage Specifications":[[6,"linkage-specifications"]],"Lists of Entries":[[22,"lists-of-entries"]],"Live Feedback":[[24,"live-feedback"]],"Looking Up Class Members":[[21,"looking-up-class-members"]],"Looking Up Names in the Current Scope":[[21,"looking-up-names-in-the-current-scope"]],"Looking Up Names in the File Scope":[[21,"looking-up-names-in-the-file-scope"]],"Looking Up Namespace Members":[[21,"looking-up-namespace-members"]],"Looking for Class Member Projection Symbols":[[21,"looking-for-class-member-projection-symbols"]],"Lookup Options":[[21,"lookup-options"]],"Lookup Using the Referencing Context":[[10,"lookup-using-the-referencing-context"]],"Lookup of Entities Imported from C++/CLI Metadata":[[21,"lookup-of-entities-imported-from-c-cli-metadata"]],"Low-level Fixed-point Routines":[[9,"low-level-fixed-point-routines"]],"Low-level Floating-point Routines":[[9,"low-level-floating-point-routines"]],"Low-level Integer Routines":[[9,"low-level-integer-routines"]],"Lowering C Dialects":[[16,"lowering-c-dialects"]],"Lowering GNU function multiversioning":[[16,"lowering-gnu-function-multiversioning"]],"Lowering extern inline":[[16,"lowering-extern-inline"]],"Lowering ifunc":[[16,"lowering-ifunc"]],"Lowering thread_local":[[16,"lowering-thread-local"]],"Lvalues and Rvalues (Value Categories)":[[11,"lvalues-and-rvalues-value-categories"]],"Macro Definition Data Structure":[[15,"macro-definition-data-structure"]],"Macro Definitions":[[15,"macro-definitions"]],"Macro Invocation Tree":[[15,"macro-invocation-tree"]],"Macro Invocations":[[15,"macro-invocations"]],"Macro Position Tracking":[[15,"macro-position-tracking"]],"Macro Processing":[[15,"macro-processing"]],"Macros":[[11,"macros"]],"Main Program":[[16,"main-program"]],"Maintained Context":[[16,"maintained-context"]],"Maintaining Context":[[16,"maintaining-context"]],"Managing Instantiation of Functions, Variables, and Static Data Members":[[23,"managing-instantiation-of-functions-variables-and-static-data-members"]],"Manual Precompiled Header Processing":[[10,"manual-precompiled-header-processing"]],"Marking the initiation of the exception (__exception_started)":[[8,"marking-the-initiation-of-the-exception-exception-started"]],"Member Constant Extension":[[3,"member-constant-extension"]],"Member Function Templates":[[3,"member-function-templates"]],"Member Function of Class Templates":[[23,"member-function-of-class-templates"]],"Member Functions":[[3,"member-functions"],[4,"member-functions"]],"Member Initializer":[[4,"member-initializer"]],"Memory Management":[[0,"memory-management"],[11,"memory-management"]],"Memory Management Issues":[[0,"memory-management-issues"]],"Memory Region Processing Order":[[11,"memory-region-processing-order"]],"Memory Regions":[[11,"memory-regions"]],"Memory Regions and Intermediate Language":[[25,"memory-regions-and-intermediate-language"]],"Memory Regions and Pointers":[[11,"memory-regions-and-pointers"]],"Microsoft Attributes":[[6,"microsoft-attributes"]],"Microsoft C++ Mode":[[10,"microsoft-c-mode"]],"Microsoft C++/CLI Mode":[[10,"microsoft-c-cli-mode"]],"Microsoft Pragmas":[[10,"microsoft-pragmas"]],"Microsoft __if_exists blocks":[[11,"microsoft-if-exists-blocks"]],"Miscellaneous Options":[[10,"miscellaneous-options"]],"Modifications to the Current Source Line":[[15,"modifications-to-the-current-source-line"]],"Modifying Type Trees":[[22,"modifying-type-trees"]],"Modules":[[17,null]],"Multi-Configuration Support":[[24,"multi-configuration-support"]],"Multi-file Testing":[[24,"multi-file-testing"]],"Multibyte characters in source code":[[15,"multibyte-characters-in-source-code"]],"Multiple Translation Units":[[25,null]],"Name Linkage":[[11,"name-linkage"]],"Name Mangling":[[16,"name-mangling"]],"Name Scope":[[3,"name-scope"]],"Name Scopes":[[21,"name-scopes"]],"Named Unicode Escapes":[[15,"named-unicode-escapes"]],"Names":[[3,"names"],[5,"names"]],"Namespace Declarations":[[6,"namespace-declarations"]],"Namespace Projection Symbols":[[21,"namespace-projection-symbols"]],"Namespace Support":[[10,"namespace-support"]],"Namespace Symbols":[[21,"namespace-symbols"]],"Namespaces":[[6,"namespaces"],[11,"namespaces"],[16,"namespaces"]],"Namespaces and the Standard Header Files":[[12,"namespaces-and-the-standard-header-files"]],"Naming Convention":[[4,"naming-convention"]],"Needed Flags":[[0,"needed-flags"]],"Negative Filters":[[24,"negative-filters"]],"Nested Class Anachronism Lookup":[[21,"nested-class-anachronism-lookup"]],"New and Delete":[[11,"new-and-delete"],[16,"new-and-delete"]],"No Expectations Mode":[[24,"no-expectations-mode"]],"No Flakey Tests Mode":[[24,"no-flakey-tests-mode"]],"Nodes":[[17,"nodes"],[17,"ifc-node-versioning"],[17,"id11"],[17,"id13"]],"Non-Portable Implementation":[[8,"non-portable-implementation"]],"Nonreal and Proxy Class Lookup":[[21,"nonreal-and-proxy-class-lookup"]],"Nonreal and Proxy Class Members":[[21,"nonreal-and-proxy-class-members"]],"Object Layout Models":[[3,"object-layout-models"]],"Object Lifetimes":[[11,"object-lifetimes"],[16,"object-lifetimes"],[22,"object-lifetimes"]],"Offset and Alignment":[[3,"offset-and-alignment"]],"Once Pragma":[[10,"once-pragma"]],"One-instantiation-per-object mode":[[25,"one-instantiation-per-object-mode"]],"Operand Data Structure":[[9,"operand-data-structure"]],"Operation":[[2,"operation"]],"Operation Expressions":[[11,"operation-expressions"]],"Operations Returning Lvalues":[[16,"operations-returning-lvalues"]],"Operator Overloading":[[9,"operator-overloading"]],"Optional Components":[[1,"optional-components"]],"Ordering Dependencies":[[25,"ordering-dependencies"]],"Orphaned Entries":[[16,"orphaned-entries"],[22,"orphaned-entries"]],"Orphans":[[11,"orphans"]],"Other Declarative Entries":[[22,"other-declarative-entries"]],"Other Ways for Users to Control Precompiled Headers":[[10,"other-ways-for-users-to-control-precompiled-headers"]],"Overloaded Function Calls":[[9,"overloaded-function-calls"]],"Overloaded Operators":[[21,"overloaded-operators"]],"Overloading":[[3,"overloading"]],"Overview":[[3,"overview"],[6,"overview"],[23,"overview"],[23,"id2"]],"Overview of Internal Structure":[[14,null]],"Pack Pragma":[[10,"pack-pragma"]],"Parameter Alignment":[[4,"parameter-alignment"]],"Parameters":[[11,"parameters"]],"Parentheses":[[11,"parentheses"]],"Parsing Attributes":[[18,"parsing-attributes"]],"Parsing Technique":[[9,"parsing-technique"]],"Partial Instantiation":[[23,"partial-instantiation"]],"Partial Specializations":[[23,"partial-specializations"]],"Partition Kinds":[[17,"partition-kinds"]],"Partition Node":[[17,"partition-node"]],"Passthrough":[[17,"passthrough"]],"Performance Issues":[[10,"performance-issues"]],"Phase One: Recording Pragmas":[[18,"phase-one-recording-pragmas"]],"Phase Three: Interpreting Pragmas":[[18,"phase-three-interpreting-pragmas"]],"Phase Two: Dispatching Pragmas":[[18,"phase-two-dispatching-pragmas"]],"Placement Delete":[[16,"placement-delete"]],"Point of Validation":[[17,"point-of-validation"]],"Pointer & Reference Types":[[4,"pointer-reference-types"]],"Pointers to Members":[[11,"pointers-to-members"],[16,"pointers-to-members"]],"Portable Implementation":[[8,"portable-implementation"]],"Post-condition":[[4,"post-condition"]],"Pragmas":[[10,"pragmas"],[11,"pragmas"]],"Pragmas and Attributes":[[18,null]],"Pre-checked Data":[[17,"pre-checked-data"]],"Pre-condition":[[4,"pre-condition"]],"Precompiled Header Options":[[10,"precompiled-header-options"]],"Precompiled Header Pragmas":[[10,"precompiled-header-pragmas"]],"Precompiled Headers":[[0,"precompiled-headers"],[10,"precompiled-headers"]],"Predefined Macro Definition File":[[0,"predefined-macro-definition-file"]],"Predefined Macros":[[10,"predefined-macros"]],"Prefix and Header Stop Point":[[0,"prefix-and-header-stop-point"]],"Prelinker":[[23,"prelinker"]],"Preprocessing Directives":[[15,"preprocessing-directives"]],"Preprocessor Directives":[[4,"preprocessor-directives"]],"Preprocessor Options":[[10,"preprocessor-options"]],"Primitive Operations on Operands":[[9,"primitive-operations-on-operands"]],"Problem Reporting":[[24,"problem-reporting"]],"Prologue code for a function that may need clean-up if an exception is thrown":[[8,"prologue-code-for-a-function-that-may-need-clean-up-if-an-exception-is-thrown"]],"Prologue code for a function with an exception specification":[[8,"prologue-code-for-a-function-with-an-exception-specification"]],"Promotion of Local Entities to File Scope":[[16,"promotion-of-local-entities-to-file-scope"]],"Properties":[[9,"properties"],[11,"properties"]],"Properties and Events (Microsoft and C++/CLI modes)":[[3,"properties-and-events-microsoft-and-c-cli-modes"]],"Prototype Scopes":[[5,"prototype-scopes"]],"Range-based":[[4,"range-based"]],"Range-based for statement":[[9,"range-based-for-statement"]],"Raw Bytes":[[17,"raw-bytes"]],"Raw Listing Output":[[15,"raw-listing-output"]],"Raw Numeric":[[17,"raw-numeric"]],"Raw Values":[[17,"raw-values"]],"Re-record Mode":[[24,"re-record-mode"]],"Reading Logical Source Lines":[[15,"reading-logical-source-lines"]],"Reading the Intermediate Language from a File":[[0,"reading-the-intermediate-language-from-a-file"]],"Recognizing Attributes":[[18,"recognizing-attributes"]],"Recognizing Generalized Identifiers":[[15,"recognizing-generalized-identifiers"]],"Recompilation":[[23,"recompilation"]],"Recursive Descent Parsing":[[14,"recursive-descent-parsing"]],"Reference Information":[[9,"reference-information"]],"References":[[5,"references"],[11,"references"]],"Regress Mode":[[24,"regress-mode"]],"Related Class Casts":[[16,"related-class-casts"]],"Relationship of the IL and the Symbol Table":[[11,"relationship-of-the-il-and-the-symbol-table"]],"Replaceable Code":[[1,"replaceable-code"]],"Replay mode":[[24,"replay-mode"]],"Replaying Failed Test":[[24,"replaying-failed-test"]],"Replaying Mismatched":[[24,"replaying-mismatched"]],"Replaying Regressions":[[24,"replaying-regressions"]],"Replaying Subset of Failed Test":[[24,"replaying-subset-of-failed-test"]],"Replaying Unexpected":[[24,"replaying-unexpected"]],"Representation of constraints":[[23,"representation-of-constraints"]],"Rescanning Expressions":[[9,"rescanning-expressions"]],"Response to Signals":[[10,"response-to-signals"]],"Return Value":[[4,"return-value"]],"Return Value Optimization":[[16,"return-value-optimization"]],"Returns":[[11,"returns"]],"Reusable Copies":[[16,"reusable-copies"]],"Rewritten Property References":[[5,"rewritten-property-references"]],"Roles":[[17,"roles"]],"Routines":[[11,"routines"],[16,"routines"]],"Routines that Implement Language Concepts":[[22,"routines-that-implement-language-concepts"]],"Run-Time Support":[[8,"run-time-support"]],"Run-Time storage management":[[8,"run-time-storage-management"]],"Runtime Library":[[19,null]],"Runtime Support":[[10,"runtime-support"]],"Runtime Type Information":[[16,"runtime-type-information"]],"Scanning Constants":[[9,"scanning-constants"]],"Scanning Identifiers":[[9,"scanning-identifiers"]],"Scanning Names in C++":[[15,"scanning-names-in-c"]],"Scanning Operations":[[9,"scanning-operations"]],"Scanning the Lambda Body":[[3,"scanning-the-lambda-body"]],"Scope List":[[21,"scope-list"]],"Secondary translation units":[[10,"secondary-translation-units"]],"Selector Operands":[[9,"selector-operands"]],"Sequencing":[[16,"sequencing"]],"Setting Sizes and Alignments of Types":[[22,"setting-sizes-and-alignments-of-types"]],"Setup Requirements":[[24,"setup-requirements"]],"Simple Sort":[[17,"simple-sort"],[17,"ifc-simple-sort-versioning"],[17,"id9"]],"Single-file Testing":[[24,"single-file-testing"]],"Sizeof":[[11,"sizeof"]],"Skipping Validation":[[17,"skipping-validation"]],"Skipping White Space":[[15,"skipping-white-space"]],"Slow Lookup Processing (scope_stack_lookup)":[[21,"slow-lookup-processing-scope-stack-lookup"]],"Slow Test Reporting":[[24,"slow-test-reporting"]],"Source Correspondence Information":[[11,"source-correspondence-information"]],"Source File Information":[[11,"source-file-information"],[22,"source-file-information"]],"Source Line Data Structure":[[15,"source-line-data-structure"]],"Source Output":[[5,"source-output"]],"Source Positions":[[14,"source-positions"],[15,"source-positions"]],"Source Sequence Entries":[[22,"source-sequence-entries"]],"Source Sequence Lists":[[5,"source-sequence-lists"],[11,"source-sequence-lists"]],"Source positions":[[11,"source-positions"]],"Special Cases":[[4,"special-cases"],[21,"special-cases"]],"Special Filters":[[24,"special-filters"]],"Stage 0":[[17,"stage-0"]],"Stage 1":[[17,"stage-1"]],"Stage 2":[[17,"stage-2"]],"Stage 3":[[17,"stage-3"]],"Stage 4":[[17,"stage-4"]],"Stage 5":[[17,"stage-5"]],"Stage 5 (Wrap-up)":[[17,"stage-5-wrap-up"]],"Stage 6 (Wrap-up)":[[17,"stage-6-wrap-up"]],"Stage Breakdown":[[17,"stage-breakdown"]],"Stages":[[17,"stages"]],"Standard Attributes, GNU Attributes, and __declspec Attributes":[[6,"standard-attributes-gnu-attributes-and-declspec-attributes"]],"Standard C++ Include Files":[[12,"standard-c-include-files"]],"Statement Scanning":[[20,null]],"Statements":[[4,"statements"],[11,"statements"],[22,"statements"]],"Static Data Members":[[3,"static-data-members"]],"Static Data Members of Class Templates":[[23,"static-data-members-of-class-templates"]],"Static vs. Nonstatic":[[3,"static-vs-nonstatic"]],"Storage Allocation":[[14,"storage-allocation"],[22,"storage-allocation"]],"Subscripting":[[11,"subscripting"]],"Support for Source Language Dialects":[[1,"support-for-source-language-dialects"]],"Symbol Locator":[[21,"symbol-locator"]],"Symbol Lookup":[[21,"symbol-lookup"]],"Symbol Management":[[21,"symbol-management"]],"Symbol Table":[[21,null]],"Symbols and IL Entries":[[21,"symbols-and-il-entries"]],"Symbols and Symbol Headers":[[21,"symbols-and-symbol-headers"]],"Syntax Errors":[[14,"syntax-errors"]],"Synthesized Namespace Projection Symbols":[[21,"synthesized-namespace-projection-symbols"]],"Table Management":[[22,null]],"Tacit Field":[[17,"tacit-field"]],"Tacit Field Implementation":[[17,"tacit-field-implementation"]],"Tagless Classes":[[3,"tagless-classes"]],"Taking Apart Types":[[22,"taking-apart-types"]],"Target Platform Options":[[1,"target-platform-options"]],"Target-Specific Configuration":[[1,"target-specific-configuration"]],"Template Class References":[[15,"template-class-references"]],"Template Conversion Operators":[[21,"template-conversion-operators"]],"Template Declaration Information":[[23,"template-declaration-information"]],"Template Declarations":[[23,"template-declarations"]],"Template Instantiation":[[10,"template-instantiation"]],"Template Instantiation Options":[[10,"template-instantiation-options"]],"Template Parameter Clauses":[[23,"template-parameter-clauses"]],"Template Parameters":[[4,"template-parameters"]],"Template References":[[15,"template-references"]],"Template Symbols":[[21,"template-symbols"]],"Templates":[[4,"templates"],[11,"templates"],[23,null]],"Templates and Macros":[[5,"templates-and-macros"]],"Templates in the IL":[[23,"templates-in-the-il"]],"Temporaries":[[9,"temporaries"]],"Temporary Initialization":[[11,"temporary-initialization"]],"Termination Messages":[[10,"termination-messages"]],"Test Run Cleanup":[[24,"test-run-cleanup"]],"Test Run Status":[[24,"test-run-status"]],"Test Termination":[[24,"test-termination"]],"Testing Tools":[[24,"testing-tools"]],"Textual Preprocessing Output":[[15,"textual-preprocessing-output"]],"The --building_runtime option":[[19,"the-building-runtime-option"]],"The Active Symbol List":[[21,"the-active-symbol-list"]],"The Copy Address Pointer":[[25,"the-copy-address-pointer"]],"The Current Source Line":[[15,"the-current-source-line"]],"The EH Stack":[[8,"the-eh-stack"]],"The Empty Base Class Layout Optimization":[[3,"the-empty-base-class-layout-optimization"]],"The Expression Stack":[[9,"the-expression-stack"]],"The IL Header":[[11,"the-il-header"]],"The IL Lowering Flag":[[16,"the-il-lowering-flag"]],"The Inactive Symbol Lists":[[21,"the-inactive-symbol-lists"]],"The Input Stack":[[15,"the-input-stack"]],"The Macro Buffer":[[15,"the-macro-buffer"]],"The Scope Entry":[[11,"the-scope-entry"]],"The Template Information and Instantiation Request Files":[[23,"the-template-information-and-instantiation-request-files"]],"The defines.h File":[[1,"the-defines-h-file"]],"The dettarg Utility":[[1,"the-dettarg-utility"]],"The dynamic_cast operator":[[16,"the-dynamic-cast-operator"]],"The eccp script":[[1,"the-eccp-script"]],"The edgcc Driver for Windows":[[1,"the-edgcc-driver-for-windows"]],"The typeid operator":[[16,"the-typeid-operator"]],"The \u201cLambda Declarator\u201d":[[3,"the-lambda-declarator"]],"The \u201cOther\u201d Symbol List":[[21,"the-other-symbol-list"]],"Throw Expression":[[11,"throw-expression"]],"Throwing an Exception":[[16,"throwing-an-exception"]],"Throwing an exception (__throw)":[[8,"throwing-an-exception-throw"]],"Throwing an exception (__throw_setup)":[[8,"throwing-an-exception-throw-setup"]],"Throwing an exception (generated code)":[[8,"throwing-an-exception-generated-code"]],"Token Lookahead and Caching":[[15,"token-lookahead-and-caching"]],"Transformations":[[2,"transformations"]],"Transformations on Operands":[[9,"transformations-on-operands"]],"Translation Unit Correspondences":[[25,"translation-unit-correspondences"]],"Troublesome Cases":[[5,"troublesome-cases"]],"Type Conversions":[[9,"type-conversions"]],"Type Entries":[[22,"type-entries"]],"Type Names in Expressions":[[6,"type-names-in-expressions"]],"Type, Scope, and Symbol":[[3,"type-scope-and-symbol"]],"Type-Transforming Attributes":[[18,"type-transforming-attributes"]],"Typerefs":[[11,"typerefs"],[14,"typerefs"],[22,"typerefs"]],"Types":[[11,"types"],[22,"types"]],"Unbound Pragmas":[[18,"unbound-pragmas"]],"Unchecked Data":[[17,"unchecked-data"]],"Unicode Version-Dependent Features":[[15,"unicode-version-dependent-features"]],"Unordered Evaluation":[[16,"unordered-evaluation"]],"Unscanning Attributes":[[18,"unscanning-attributes"]],"User-Defined Conversions":[[3,"user-defined-conversions"],[21,"user-defined-conversions"]],"User-defined Conversions":[[9,"user-defined-conversions"]],"Using Declarations and Access Declarations":[[3,"using-declarations-and-access-declarations"]],"Using a PCH file":[[0,"using-a-pch-file"]],"Using the Top-Level Makefile":[[1,"using-the-top-level-makefile"]],"Using-Declarations":[[6,"using-declarations"]],"Using-Directives":[[6,"using-directives"]],"Utility Programs":[[26,null]],"Utility Routines":[[15,"utility-routines"]],"VLA Deallocation":[[11,"vla-deallocation"]],"Validation":[[17,"validation"]],"Validation Cache":[[17,"validation-cache"]],"Value Categories":[[17,"value-categories"]],"Value Category":[[17,"value-category"],[17,"id6"]],"Variable Grouping":[[4,"variable-grouping"]],"Variable Initializers":[[6,"variable-initializers"]],"Variable Template References":[[15,"variable-template-references"]],"Variable Templates":[[23,"variable-templates"],[23,"id8"],[23,"id11"]],"Variable Templates and Static Data Member Templates":[[23,"variable-templates-and-static-data-member-templates"]],"Variable Templates and Static Data Members of Class Templates":[[23,"variable-templates-and-static-data-members-of-class-templates"]],"Variables":[[11,"variables"]],"Variadic Templates":[[23,"variadic-templates"]],"Verbose Mode":[[24,"verbose-mode"]],"Versioning":[[17,"versioning"]],"Virtual Base Class":[[3,"virtual-base-class"]],"Virtual Function Tables":[[11,"virtual-function-tables"],[16,"virtual-function-tables"]],"Virtual Functions":[[3,"virtual-functions"],[3,"id13"]],"Visitors":[[17,"visitors"]],"Void Expressions":[[9,"void-expressions"]],"What Does C++ IL Lowering Do?":[[16,"what-does-c-il-lowering-do"]],"Whitespace keywords":[[15,"whitespace-keywords"]],"With Memory Mapping":[[17,"with-memory-mapping"]],"Without Memory Mapping":[[17,"without-memory-mapping"]],"Wrapping Array Subscripts":[[4,"wrapping-array-subscripts"]],"Wrapping Function Calls":[[4,"wrapping-function-calls"]],"Wrapping Function Declarations":[[4,"wrapping-function-declarations"]],"Writing a Class":[[4,"writing-a-class"]],"Writing a Function":[[4,"writing-a-function"]],"Writing a Lambda":[[4,"writing-a-lambda"]],"Writing a Test File":[[24,"writing-a-test-file"]],"Writing a Variable":[[4,"writing-a-variable"]],"Writing the Intermediate Language to a File":[[0,"writing-the-intermediate-language-to-a-file"]],"asm Declarations":[[6,"asm-declarations"]],"asm Statements":[[11,"asm-statements"]],"basics.h and Build Environment Configuration":[[1,"basics-h-and-build-environment-configuration"]],"bool":[[16,"bool"]],"edg-run-test":[[24,"edg-run-test"]],"edg_decode":[[26,"edg-decode"]],"edg_munch":[[26,"edg-munch"]],"edg_prelink":[[26,"edg-prelink"]],"edgy":[[24,"edgy"]],"for Statements":[[4,"for-statements"]],"get_ifc_partition_element_size":[[17,"get-ifc-partition-element-size"]],"get_ifc_partition_kind":[[17,"get-ifc-partition-kind"]],"has_partition_kind":[[17,"has-partition-kind"]],"if Statements":[[4,"if-statements"]],"lang_feat.h, host_envir.h, targ_def.h, and target.h":[[1,"lang-feat-h-host-envir-h-targ-def-h-and-target-h"]],"mk_errinfo":[[26,"mk-errinfo"]],"normal_id_lookup":[[21,"normal-id-lookup"]],"push_scope and pop_scope":[[21,"push-scope-and-pop-scope"]],"referenced and needed Flags":[[11,"referenced-and-needed-flags"]],"scan_expr_full":[[9,"scan-expr-full"]],"scan_expr_full Processing":[[9,"scan-expr-full-processing"]],"switch Statements":[[4,"switch-statements"]],"throw Expressions":[[8,"throw-expressions"]],"to/from_partition_kind":[[17,"to-from-partition-kind"]],"try Blocks":[[8,"try-blocks"]],"typeid":[[11,"typeid"]],"using-Directive Processing":[[21,"using-directive-processing"]],"while Statements":[[4,"while-statements"]],"\u201cDefault\u201d C++ Mode":[[10,"default-c-mode"]],"\u201cExtern\u201d Symbols":[[21,"extern-symbols"]]},"docnames":["admin","build","c_gen_be","class_decl","code_style","cp_gen_be","decls","err_msgs","exceptions","expr","ext_intf","il","includes","index","int_overview","lex_pp","lower_il","modules","pragma","runtime","statements","symbol_tbl","tables","templates","testing","trans_unit","utilities"],"envversion":{"sphinx":66,"sphinx.domains.c":3,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":9,"sphinx.domains.index":1,"sphinx.domains.javascript":3,"sphinx.domains.math":2,"sphinx.domains.python":4,"sphinx.domains.rst":2,"sphinx.domains.std":2},"filenames":["admin.rst","build.rst","c_gen_be.rst","class_decl.rst","code_style.rst","cp_gen_be.rst","decls.rst","err_msgs.rst","exceptions.rst","expr.rst","ext_intf.rst","il.rst","includes.rst","index.rst","int_overview.rst","lex_pp.rst","lower_il.rst","modules.rst","pragma.rst","runtime.rst","statements.rst","symbol_tbl.rst","tables.rst","templates.rst","testing.rst","trans_unit.rst","utilities.rst"],"indexentries":{},"objects":{},"objnames":{},"objtypes":{},"terms":{"002d":15,"0d":8,"0f":23,"0i":16,"0l":15,"0x":10,"0x002d":15,"0x01":16,"0x02":16,"0x02238":15,"0x0307":15,"0x04":16,"0x08":16,"0x1":16,"0x10":16,"0x123e":10,"0x2":16,"0x2ebe1":15,"0x2ebef":15,"0x2ebf0":15,"0x2ee5":15,"0x2ee5d":15,"0x2f7ff":15,"0x80000000":10,"0x80000001":10,"10k":0,"11_sfina":[7,10],"11_sfinae_ignore_access":10,"12clisafe_cast":16,"12clisubscript":16,"14__interior_ptr":16,"16be":[7,10],"16le":[7,10],"199409l":10,"199711l":10,"199901l":10,"1c":[16,18],"1e":10,"1st":4,"200406l":10,"201103l":10,"250k":10,"2ebf0":15,"2ee5d":15,"2nd":4,"34_km":10,"3rd":4,"3rd_arg_of_assume_aligned_must_be_integr":7,"4abcd":16,"5abcd":16,"64k":0,"7abcdefg":16,"82a9":15,"8__handl":16,"8__trkref":16,"9__pin_ptr":16,"9clihandl":16,"9clitypeid":16,"A":[0,1,2,3,4,5,6,9,10,11,13,14,15,16,17,19,20,21,22,23,24,25,26],"AT":10,"About":[9,15],"After":[0,1,3,6,8,9,14,15,16,17,18,21,23,25],"Again":[0,16,23],"All":[0,1,3,5,9,10,11,14,15,16,17,21,24,25],"An":[0,1,3,6,8,9,10,11,14,15,16,17,18,20,21,22,23,24,26],"And":[3,9,11,15,16,18,21,22,23],"Are":15,"As":[0,1,3,5,6,8,9,10,11,14,15,16,17,18,20,21,23,24],"At":[0,3,5,9,10,11,14,15,16,17,20,21,23],"Be":11,"Being":21,"Between":[0,9],"Both":[3,5,6,9,10,11,14,15,16,18,21,23,24],"But":[0,3,6,10,15,16,21,23],"By":[0,1,3,9,10,11,14,15,18,23,24,25,26],"Could":25,"Do":[10,11,23,26],"Doing":9,"Each":[0,1,2,3,6,8,9,10,11,14,15,16,17,18,20,21,22,23,25,26],"For":[0,1,2,3,4,5,6,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"From":[10,11,15,17],"Further":16,"Has":11,"Having":[1,9,10,11,22,23],"Here":[3,6,8,9,10,11,16,17,18,21,23,24],"How":25,"I":[0,1,6,9,10,16,18,23],"If":[0,1,2,3,4,6,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"In":[0,1,2,3,4,5,6,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,25,26],"Is":[9,10,11,16],"It":[0,1,2,3,5,6,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"Its":[0,3,6,9,10,11,13,18,20,26],"More":[5,11,13,16,21],"Most":[0,3,5,6,9,10,11,14,15,16,18,21,23,25,26],"No":[0,3,9,10,11,14,15,16,18,21,23,25],"Not":[0,1,3,9,10,11,12,16,17,25],"OFF":7,"ON":7,"Of":[10,11,14,24],"On":[0,2,3,8,9,10,11,15,16,21,23],"Or":[0,23],"Other":[0,6,9,11,15,23,25],"Same":[3,10],"Should":[10,11,24],"So":[0,3,9,11,14,16,21,23,25],"Some":[0,1,3,5,6,8,9,10,11,14,16,17,18,20,21,25,26],"Such":[0,2,3,6,9,10,11,14,15,16,18,20,21,22,23,25],"TO":16,"That":[0,2,3,5,6,9,10,11,14,15,16,20,21,23,25],"The":[0,2,4,5,6,7,10,12,13,14,17,18,20,22,24,26],"Their":[3,10,11,14,18,23],"Then":[0,2,3,6,8,9,10,11,15,16,17,21,23],"There":[0,2,3,6,9,10,11,13,14,15,16,17,18,20,21,22,23,24,25,26],"These":[0,1,2,3,5,6,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"They":[0,2,3,4,6,9,10,11,14,15,16,18,19,21,22,23,25],"This":[0,1,2,3,4,5,6,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"Those":[0,1,9,10,11,14,16,22],"To":[0,1,3,5,6,8,9,10,14,15,16,17,18,19,21,22,23,24,25,26],"Under":[9,10],"Up":16,"We":[0,15,16,21,23],"What":[3,6,8,11,21],"When":[0,1,2,3,4,5,6,8,9,10,11,12,13,14,15,16,17,18,20,21,22,23,24,25,26],"Where":[3,11,14,16,21],"Which":[15,21],"While":[0,3,6,9,11,15,16,17,21,23,25],"With":[0,6,10,11,13,14,16,23],"Would":16,"You":[0,2,18,24],"_":[7,15,16,24],"__":[2,16],"__12a__l1__f__fv":16,"__12a__l1__x__fv":16,"__28_7_i":2,"__ab":16,"__alignof__":[9,10,16],"__ansic__":[1,14,19],"__array_delet":16,"__array_new":16,"__array_new_prefix_s":16,"__array_new_zero":16,"__array_oper":10,"__asm":10,"__attribut":[1,6,11,18],"__attribute__":16,"__base":7,"__base_file__":10,"__begin":9,"__bool_defin":10,"__bsd__":[1,2,14,19],"__builtin_assumed_align":7,"__builtin_bit_cast":7,"__builtin_complex":7,"__builtin_constexpr_diag":[7,10],"__builtin_fpclassifi":7,"__builtin_offsetof":7,"__builtin_va_arg_pack":7,"__builtin_va_arg_pack_len":7,"__catch_clause_numb":[8,16],"__caught_object_address":[8,16],"__cbi__":[10,16,23],"__cbi__f__fi__tir__f__fi__dni__f__fi":23,"__cdecl":10,"__cgi__":2,"__char16_t_and_char32_t":10,"__char16_type__":10,"__char32_type__":10,"__char_bit__":0,"__cleanup_vec_new_or_delet":8,"__clrcall":7,"__counter__":10,"__cplusplus":10,"__cplusplus_c":10,"__cpr":16,"__ct__1aff":16,"__cxa_atexit":16,"__cxa_bad_cast":16,"__cxa_bad_typeid":16,"__cxa_deleted_virtu":16,"__cxa_guard_acquir":16,"__cxa_guard_releas":16,"__cxa_pure_virtu":16,"__cxa_thread_atexit":16,"__cxa_vec_cctor":16,"__cxa_vec_ctor":16,"__cxa_vec_delet":16,"__cxa_vec_dtor":16,"__cxa_vec_new":16,"__cxa_vec_new2":16,"__cxa_vec_new3":16,"__date__":[0,10],"__declspec":[1,3,7,9,11,18],"__deleted_virtual_cal":16,"__df__":16,"__direct_bas":7,"__dn":16,"__dni__":[16,23],"__dynamic_cast":16,"__dynamic_cast_ref":16,"__edg__":10,"__edg_abi_changes_for_array_new_and_delet":19,"__edg_abi_changes_for_placement_delet":19,"__edg_abi_changes_for_rtti":19,"__edg_abi_compatibility_vers":19,"__edg_ans":19,"__edg_bsd":19,"__edg_cpp11_il_extensions_support":19,"__edg_delta_typ":19,"__edg_elem_count_param_typ":19,"__edg_ets_flag_typ":19,"__edg_ia64_abi":10,"__edg_ia64_abi_use_int_static_init_guard":10,"__edg_ia64_abi_use_variant_array_cooki":19,"__edg_ia64_abi_variant_ctors_and_dtors_return_thi":10,"__edg_implicit_using_std":[10,12],"__edg_jmp_buf_element_typ":19,"__edg_jmp_buf_num_el":19,"__edg_lower_variable_length_array":19,"__edg_null_eh_region_numb":19,"__edg_ptrdiff_type__":10,"__edg_region_number_typ":19,"__edg_runtime_uses_namespac":[10,12],"__edg_size_type__":10,"__edg_sysv":19,"__edg_type_traits_en":10,"__edg_var_handle_typ":19,"__edg_version__":10,"__edg_virtual_function_index_typ":19,"__eh_curr_region":[8,16],"__embedded_cplusplus":10,"__end":9,"__event":7,"__except":[7,10],"__exception_caught":[8,16],"__exception_start":16,"__fastcal":10,"__file__":[10,11,15],"__final":7,"__float128":9,"__float80":9,"__forceinlin":7,"__free_throw_object":8,"__free_thrown_object":[8,16],"__func__":10,"__funcdname__":10,"__funcsig__":10,"__function__":10,"__gener":10,"__genericfx":10,"__get_typeid":16,"__global":10,"__gnuc__":10,"__gnuc_minor__":10,"__gnuc_patchlevel__":0,"__has_emb":7,"__has_featur":10,"__has_includ":7,"__has_include_next":7,"__has_nothrow_assign":10,"__has_nothrow_constructor":10,"__has_nothrow_copi":10,"__has_nothrow_move_assign":10,"__has_trivial_assign":10,"__has_trivial_constructor":10,"__has_trivial_copi":10,"__has_trivial_destructor":10,"__has_trivial_move_assign":10,"__has_trivial_move_constructor":10,"__has_virtual_destructor":10,"__have_builtin_setjmp__":0,"__hidden":10,"__i__":10,"__if_exist":7,"__if_not_exist":11,"__ifc__":16,"__ifv__":16,"__imag":[7,16],"__impl":7,"__implement":7,"__infinity__":10,"__inlin":7,"__int16":16,"__int32":16,"__int64":16,"__int8":16,"__intaddr__":[7,9,10],"__interfac":[3,7,11],"__internal_rethrow":8,"__is_abstract":10,"__is_base_of":[10,16],"__is_class":10,"__is_construct":10,"__is_convertible_to":10,"__is_destruct":10,"__is_empti":10,"__is_enum":10,"__is_gnu_or_microsoft_mod":0,"__is_literal_typ":10,"__is_nothrow_assign":10,"__is_nothrow_construct":10,"__is_nothrow_destruct":10,"__is_pod":10,"__is_polymorph":10,"__is_sign":7,"__is_standard_layout":10,"__is_trivi":10,"__is_trivially_assign":10,"__is_trivially_construct":10,"__is_trivially_copy":10,"__is_trivially_destruct":10,"__is_union":10,"__l":16,"__l_":2,"__leav":7,"__line__":[10,11,15],"__link":16,"__linkl":16,"__lsg__":16,"__make_sign":7,"__make_unsign":7,"__microsoft_os__":10,"__mptr":16,"__n":16,"__nan__":10,"__no_long_long":10,"__nullptr":16,"__padding__":17,"__pk__":16,"__pl__1aff":16,"__pl__f1af":16,"__placement_array_new":16,"__placement_array_new_zero":16,"__placement_delet":10,"__pragma":7,"__pragma_redefine_extnam":10,"__pretty_function__":10,"__printf_arg":9,"__ps__":16,"__ptr32":7,"__ptr64":7,"__pure_virtual_cal":16,"__q3_10s__tm__2_i1x8__um1_fv":16,"__rang":9,"__real":[7,16],"__record_needed_destruct":16,"__record_needed_thread_destruct":16,"__report_constexpr_valu":7,"__report_token":7,"__res__":16,"__restrict":7,"__rethrow":16,"__rtti":10,"__s":16,"__sbc__":16,"__sbc__x__y______1n":16,"__scanf_arg":9,"__signed_chars__":10,"__so__":16,"__sptr":7,"__st__":16,"__std__":[16,26],"__stdc__":10,"__stdc_hosted__":10,"__stdc_iec_559__":10,"__stdc_iec_559_complex__":10,"__stdc_iso_10646__":10,"__stdc_mb_might_neq_wc__":10,"__stdc_version__":10,"__stdcall":10,"__stdcpp_threads__":10,"__stf__":16,"__sti__":[2,16,26],"__sti__module_id":16,"__stv__":16,"__super":7,"__symbol":10,"__sysv__":[1,14,19],"__t":2,"__t_":16,"__tgt__":16,"__thi__":16,"__thiscal":[7,10],"__thread":10,"__throw":16,"__throw_alloc":[8,16],"__throw_setup":16,"__throw_setup_dtor":[8,16],"__throw_setup_ptr":[8,16],"__tid_":16,"__time__":[0,10],"__timestamp__":10,"__tir__":[16,23],"__tls_init":16,"__tls_init_":16,"__tls_init_n":16,"__tri":7,"__twr__":16,"__ud":16,"__ud1_2_fv__l0__f__fit1":16,"__ul":16,"__ul1_fif":16,"__um":16,"__unalign":7,"__underlying_typ":[7,16],"__upc__":10,"__uptr":7,"__ut":16,"__uuidof":[7,16],"__va_args__":[7,10],"__va_opt__":7,"__variadic_templ":10,"__vec_cctor":16,"__vec_delet":16,"__vec_new":16,"__vec_new_eh":16,"__vec_new_eh_zero":16,"__version__":10,"__vfe__":16,"__vla_alloc":16,"__vla_dealloc":16,"__vms__":1,"__vptp":16,"__vptr":16,"__vtbl__":16,"__vtbl_entri":16,"__w64":7,"__wint_type__":0,"__x":2,"_accum":[10,11],"_aligna":7,"_alignof":7,"_allow":1,"_atom":7,"_bitint":[7,10],"_bool":[7,10,11,16],"_buf_element_int_kind":16,"_char_unsign":10,"_closur":3,"_complex":[7,10,16],"_cpprtti":10,"_e":16,"_entry_of":25,"_f__fif":26,"_fract":10,"_gener":7,"_imaginari":[7,10],"_incl_path":1,"_init":25,"_integral_max_bit":10,"_km":[10,15],"_m_cee":10,"_m_column":7,"_m_file_nam":7,"_m_function_nam":7,"_m_ix86":1,"_m_line":7,"_m_x64":1,"_main":[16,26],"_mile":16,"_mode":14,"_msc_build":10,"_msc_extens":10,"_msc_full_ver":10,"_msc_ver":10,"_native_wchar_t_defin":10,"_nonnul":7,"_noreturn":7,"_null_unspecifi":7,"_nullabl":7,"_one_time_init":25,"_pragma":7,"_ptr":14,"_r":16,"_simpl":23,"_start":14,"_static_assert":7,"_str":14,"_str2":14,"_t":3,"_thread_loc":7,"_tok_":5,"_trans_unit_init":25,"_type":22,"_wchar_t":10,"_wchar_t_defin":10,"_wfopen":15,"_win32":10,"_win64":10,"_x":10,"_z":26,"_zgv":16,"_zn1d1feqn1b1fev":16,"_zth":16,"_zti":16,"_zts":16,"_ztw":16,"a0013ee68":1,"a0013f050":1,"a1":[6,8,9,10,23],"a2":[6,9,23],"a3":23,"a4":23,"a5":23,"a_":[4,11,14,16],"a__l0__f__fv":16,"a_base_class":[3,11,25],"a_base_class_deriv":3,"a_bit_field":14,"a_block":11,"a_boolean":[4,14,17,23],"a_byt":[11,14,15],"a_byte_boolean":14,"a_candidate_funct":9,"a_class_def_st":3,"a_class_symbol_suppl":[3,21],"a_class_type_suppl":[3,11],"a_confusable_map_elem":15,"a_const":[3,6,9,11,15,20,22],"a_constant_repr_kind":11,"a_constructor_init":[6,11],"a_control_flow_descr":20,"a_conversion_head":21,"a_conversion_list_entri":[3,21],"a_ctor_init_block":6,"a_decl_parse_st":[3,6],"a_decl_position_suppl":11,"a_def_arg_expr_fixup":3,"a_derivation_step":3,"a_destructible_entity_descr":16,"a_diagnostic_annotation_kind":10,"a_dynamic_init":[6,11,16],"a_field":[3,6,11],"a_fixed_point_valu":11,"a_foo":4,"a_for_loop":22,"a_func_info_block":[3,23],"a_generic_constraint":[11,23],"a_generic_constraint_claus":[11,23],"a_gnu_routine_suppl":11,"a_handl":[8,11],"a_hide_by_sig_list_entri":21,"a_host_large_integ":[9,11],"a_host_large_unsign":[9,11],"a_label":11,"a_lambda":[3,9,11],"a_local_static_variable_init":11,"a_long_file_nam":10,"a_long_typ":4,"a_long_type_nam":4,"a_macro":11,"a_macro_arg":15,"a_macro_def":[15,21],"a_macro_invocation_index":11,"a_macro_invocation_record":[11,15],"a_macro_invocation_record_block":[11,15],"a_macro_invocation_record_ptr":11,"a_macro_param":15,"a_macro_text_map":15,"a_macro_text_map_entri":15,"a_member_decl_info":3,"a_name_space_kind":21,"a_namespac":[6,11],"a_namespace_symbol_suppl":21,"a_next_construct_pragma_funct":18,"a_nother_variable_typ":4,"a_pack_expansion_descr_ptr":23,"a_pack_expansion_stack_entry_ptr":23,"a_param_id":6,"a_param_typ":[6,11,23],"a_pending_pragma":18,"a_per_instantiation_needed_flags_entri":[0,11],"a_pp_directive_kind":15,"a_pragma":[11,18],"a_pragma_kind":18,"a_pragma_kind_descript":18,"a_projection_descr":21,"a_property_or_event_descr":[3,11],"a_property_set_symbol_suppl":3,"a_queri":17,"a_ref_entri":9,"a_requires_claus":23,"a_reusable_token_cach":15,"a_routin":[3,11,18,23],"a_routine_fixup":3,"a_routine_type_suppl":11,"a_scop":[11,22],"a_scope_orphaned_list_head":[0,11,22],"a_scope_pointers_block":21,"a_scope_stack_entri":[18,21,22],"a_shared_token":15,"a_source_correspond":[1,11,18],"a_source_line_modif":15,"a_source_posit":[0,11,14,15],"a_source_sequence_entri":11,"a_src_seq_end_of_construct":11,"a_src_seq_secondary_decl":[11,18,22],"a_src_seq_sublist":11,"a_stat":[11,18],"a_state_catch":4,"a_static_assert":11,"a_switch_case_entri":[11,20],"a_switch_stmt_descr":[11,22],"a_symbol":21,"a_symbol_head":21,"a_symbol_list_entri":21,"a_symbol_loc":21,"a_symbol_reference_kind":21,"a_templ":[3,11,23],"a_template_arg":11,"a_template_cach":23,"a_template_decl":[11,23],"a_template_decl_info":23,"a_template_inst":23,"a_template_param":23,"a_template_param_type_suppl":23,"a_template_paramet":11,"a_template_symbol_suppl":[21,23,25],"a_text_map_position_track":15,"a_th":4,"a_thingi":4,"a_throw_spec_type_entri":8,"a_token_cach":15,"a_token_kind":[15,21],"a_trans_unit_corresp":25,"a_translation_unit":25,"a_typ":[11,14,22],"a_type_a":4,"a_type_b":4,"a_type_qualifier_set":[6,22],"a_type_tree_traversal_flag_set":22,"a_ucn_rang":15,"a_using_decl":[3,6,11],"a_vari":[3,6,11,21],"a_variable_typ":4,"a_variable_type_nam":4,"a_vla_dimens":[6,11,16],"aa":9,"aak_const":11,"aak_empti":11,"aak_raw_token":11,"aak_token":11,"aak_typ":11,"ab":10,"abandon":10,"abbrevi":[4,7,10,23],"abbreviated_deduction_guid":7,"abc":[0,10,16],"abc__tm__3_ii":16,"abcd":[2,16],"abi":[1,2,3,7,10,12,19,26],"abi_changes_for_array_new_and_delet":[16,19],"abi_changes_for_covariant_virtual_func_return":16,"abi_changes_for_placement_delet":[10,16,19],"abi_changes_for_rtti":[16,19,22],"abi_compatibility_vers":[16,19],"abi_tag":[7,16],"abi_tag_ignor":7,"abi_tag_ignored_in_c_mod":7,"abi_tag_ignored_on_speci":7,"abi_tag_redefinit":7,"abil":[0,15,16,17],"abk_routin":16,"abk_temporari":9,"abl":[5,6,8,10,11,15,16,18,21,23,24],"abnorm":[0,10,14],"abort":[0,10,24],"abov":[0,1,3,5,6,9,10,11,14,15,16,17,18,21,23,24,25],"absenc":[2,3,6,10,11,15,23,24],"absens":23,"absolut":[7,10,11],"absolute_file_name_in_has_include_next":7,"abstract":[1,3,6,7,10,11,16,17,22,23],"abstract_class_catch_typ":7,"abstract_class_object_not_allow":7,"abstract_class_param_typ":7,"abstract_declarator_pack_is_nest":7,"abstract_or_sealed_on_union":7,"abstract_requires_virtu":7,"abstractor":6,"abut":10,"ac":16,"accept":[0,1,3,4,5,6,7,9,11,13,14,15,16,18,21,22,23,24],"access":[2,5,6,7,8,9,10,14,15,16,17,22,23,24,25],"access_already_specifi":7,"access_control_error_report":21,"access_for_symbol":21,"access_prevents_dtor_gener":7,"access_suppresses_copy_asgn_decl":7,"access_suppresses_copy_ctor_decl":7,"access_to_end_of_path":[3,21],"access_to_member_of_c11_atomic_object":7,"accessor":[5,7,9,11,14,17,21],"accesssort":17,"accident":[15,17],"accommod":[0,1,2,3,5,9,10,17,18,22],"accompani":[4,6,9],"accomplish":[0,1,3,8,15,16,21,22,23],"accord":[3,6,8,9,10,11,14,15,16,18,20,21,25],"account":[3,8,10,11,17,21,24],"accum_quoted_str":15,"accumul":[0,3,6,9,10,15,18,24],"accur":[9,10,11,15,23],"achiev":[0,3,6,15,16,18],"acquir":[3,11,21],"acronym":[9,10],"across":[0,1,4,6,9,10,15,16,17,18,21,24,25],"act":[9,11,15,16,23],"action":[4,6,8,9,11,16,18,21,23,24],"activ":[3,6,7,10,11,14,15,16,20,23,25],"active_scope_lookup":21,"active_text_map_position_track":15,"actual":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"ad":[10,14],"adapt":[8,10,19,23,26],"add":[0,1,2,3,4,5,6,7,8,9,10,12,14,15,16,17,19,20,21,22,23,24,25,26],"add_active_using_direct":[6,21],"add_active_using_directive_to_scop":21,"add_active_using_directives_for_namespac":21,"add_address_of_to_nod":22,"add_array_constructor_cal":16,"add_base_class_cast":9,"add_based_type_list_memb":22,"add_box_to_express":9,"add_cast_to_nod":9,"add_cli_system_base_class":3,"add_conditional_flag_test":16,"add_constructor_cal":16,"add_constructor_param":16,"add_constructor_wrapper_cod":16,"add_curr_token_pseudo_pragma":15,"add_default_include_search_path":0,"add_derived_class_cast":9,"add_destructor_cal":16,"add_destructor_param":16,"add_diag_info":0,"add_dyn_init_cleanup":16,"add_eh_function_prologu":16,"add_empty_source_sequence_entri":22,"add_end_of_construct_source_sequence_entri":22,"add_end_of_parse_act":6,"add_first_time_test":16,"add_implicit_cli_bas":3,"add_indirect_base_class":3,"add_indirection_to_nod":22,"add_instanti":25,"add_integer_valu":9,"add_lambda_captur":3,"add_match_not":10,"add_member_to_proxy_or_nonreal_class":21,"add_orig_line_modif":15,"add_orphaned_file_scope_il_entri":[11,22],"add_pm_base_class_cast":9,"add_pm_derived_class_cast":9,"add_pragma_entry_to_cach":18,"add_pragma_kind_descript":18,"add_pragma_to_il":18,"add_ref_indirection_to_nod":22,"add_reference_to_to_nod":22,"add_scope_orphaned_il_list":[11,22],"add_source_line_modif":15,"add_source_sequence_entry_for_partial_instanti":22,"add_source_sequence_entry_to_list":22,"add_statement_at_stmt_po":20,"add_statement_list":20,"add_stmt_at_stmt_po":20,"add_stop_token":[0,14,15],"add_substitution_if_avail":16,"add_switch_claus":20,"add_symbol_to_lookup_set":21,"add_symbol_to_scope_list":21,"add_to_asm_entries_list":22,"add_to_constants_list":22,"add_to_control_flow_descr_list":20,"add_to_curr_token_pragma_list":18,"add_to_derived_type_list":6,"add_to_destructions_list":22,"add_to_dynamic_inits_list":22,"add_to_exported_templates_list":23,"add_to_front_of_include_search_path":0,"add_to_include_search_path":0,"add_to_inline_function_list":23,"add_to_instantiations_required_list":23,"add_to_labels_list":22,"add_to_macros_list":22,"add_to_namespaces_list":22,"add_to_parameters_list":22,"add_to_partial_order_candidates_list":23,"add_to_pragma_list":22,"add_to_pragmas_list":18,"add_to_request_fil":23,"add_to_routines_list":22,"add_to_scopes_list":22,"add_to_source_sequence_list":22,"add_to_templates_list":22,"add_to_types_list":22,"add_to_using_decls_list":22,"add_to_variables_list":22,"add_token_to_macro_text_map":15,"add_type_qualifi":6,"add_unbox_to_express":9,"add_vtbl_entry_init":16,"addendum":10,"addit":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"additional_arg":16,"addr_of_bit_field_allow":10,"addr_of_constructor_or_destructor":7,"addr_of_ref_class":7,"address":[0,1,2,3,5,6,7,8,10,15,16,18,22,23],"address_of_bit_field":7,"address_of_consteval_funct":7,"address_of_consteval_function_leak":7,"address_of_function_with_pass_object_size_attr":7,"address_of_initonly_field":7,"address_of_managed_member_funct":7,"address_of_nontrue_enable_if_funct":7,"address_of_overload_set_implicit_obj_member_select":7,"address_of_register_vari":7,"address_of_unqualified_explicit_this_funct":7,"address_taken":[11,22],"addscalar":10,"adequ":16,"adher":11,"adjac":[7,10,14,15,18],"adject":10,"adjust":[0,2,7,8,9,10,11,15,16,22],"adjust_bool_operation_typ":16,"adjust_copied_expression_for_inlin":16,"adjust_curr_source_line_structure_after_realloc":15,"adjust_field_selection_for_anonymous_union_refer":16,"adjust_output_posit":5,"adl":16,"adopt":[10,15,17,23],"adv_to_signif_source_sequence_entri":5,"advanc":[15,18,23,25],"advance_to_next_pack_el":23,"advance_to_next_template_arg":23,"advantag":[0,1,10,11,16,23,24],"advers":17,"af":16,"af_gnu":18,"af_ms_declspec":18,"af_std":18,"affect":[0,1,3,5,6,7,10,11,14,16,17,18,21,23,24],"affin":7,"afford":3,"afield":11,"aforement":[3,6,17],"after_end_of_all_sourc":15,"afterward":[15,25],"aggr_init_array":6,"aggr_init_array_design":6,"aggr_init_array_remainder_if_need":6,"aggr_init_class":6,"aggr_init_class_remainder_if_need":6,"aggr_init_cli_array":6,"aggr_init_cli_array_level":6,"aggr_init_cli_array_with_alloc":6,"aggr_init_el":6,"aggr_init_field_design":6,"aggr_init_generic_el":6,"aggr_init_simple_el":6,"aggreg":[2,5,7,9,10,11,16,23],"aggress":16,"agre":23,"ahead":[3,6,10,15],"ai":[10,16,23],"aib":16,"aid":[2,10,14,17,24],"aim":24,"ak_":18,"ak_align":18,"ak_empti":18,"ak_empty_attr":11,"ak_nothrow":18,"ak_sect":18,"ak_unrecogn":[11,18],"akin":[6,17,24],"al":[5,9,10,16],"al_declarator_id":18,"al_post_func":18,"al_postfix":18,"al_prefix":18,"al_specifi":18,"al_tag_nam":18,"alert":[2,10],"algorithm":[3,6,8,9,10,14,15,16,21,23],"alia":[4,6,7,11,14,17,22,26],"alias":[6,7,10,11,14,16,23,26],"alias_cannot_have_definit":7,"alias_ctad_is_cpp20":7,"alias_declar":6,"alias_declaration_is_cpp11":7,"alias_loop":7,"alias_prototype_instanti":23,"alias_template_declar":23,"alias_template_deduction_guid":7,"alias_template_is_cpp11":7,"alias_used_in_typ":7,"aliase":17,"aliased_name_bad_kind":7,"aliased_name_undeclar":7,"aliased_variable_cannot_have_register_storage_class":7,"align":[0,1,2,7,9,10,11,14,17,18],"align_not_equival":7,"align_val_t":7,"aligna":7,"aligned_new":10,"alignment_of_typ":11,"alignment_reduction_ignor":7,"alignment_reduction_unconditionally_ignor":7,"alignment_without_virtual_base_class":3,"alignof":7,"alignof_function_typ":7,"alignof_incomplete_array":7,"alignof_incomplete_typ":7,"all_arguments_must_have_same_typ":7,"all_instanti":25,"all_proto_params_must_be_nam":7,"all_template_info_in_il":[1,11],"all_thread_locals_have_wrapp":16,"alloc":[0,3,6,7,8,9,10,11,15,16,17,18,20,21,23,25],"alloc_":11,"alloc_accessible_base_class":22,"alloc_asm_entri":22,"alloc_asm_function_bodi":22,"alloc_base_class":22,"alloc_base_class_deriv":22,"alloc_cil":[11,22],"alloc_class_type_suppl":22,"alloc_const":22,"alloc_control_flow_descr":20,"alloc_conversion_head":21,"alloc_conversion_list_entri":21,"alloc_ctor_init":22,"alloc_derivation_step":22,"alloc_dtor_dynamic_init":9,"alloc_dynamic_init":22,"alloc_exception_specif":22,"alloc_expr_nod":22,"alloc_f":[0,11,14],"alloc_field":22,"alloc_gener":[0,14],"alloc_hidden_nam":22,"alloc_hidden_name_fixup":5,"alloc_il":[11,14,22],"alloc_in_region":0,"alloc_label":22,"alloc_list_entry_for_class":22,"alloc_list_entry_for_routin":22,"alloc_local_static_variable_init":22,"alloc_lowered_eh_construct_nod":22,"alloc_macro":22,"alloc_macro_arg":15,"alloc_namespac":22,"alloc_node_for_const":22,"alloc_object_lifetim":22,"alloc_overriding_virtual_funct":22,"alloc_param_typ":22,"alloc_pending_pragma":18,"alloc_pragma":[18,22],"alloc_primary_file_scope_il":25,"alloc_resizable_buff":[0,14],"alloc_routin":22,"alloc_scop":22,"alloc_shareable_const":22,"alloc_source_sequence_entri":22,"alloc_src_seq_end_of_construct":22,"alloc_src_seq_secondary_decl":22,"alloc_src_seq_sublist":22,"alloc_stat":22,"alloc_substitut":16,"alloc_switch_case_entri":22,"alloc_symbol":21,"alloc_symbol_head":21,"alloc_templ":22,"alloc_template_arg":22,"alloc_template_param_type_descr":22,"alloc_temporary_vari":22,"alloc_thingi":4,"alloc_typ":22,"alloc_unshared_const":22,"alloc_using_decl":22,"alloc_vari":22,"allocation_operator_in_namespac":7,"allow":[0,1,2,3,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25,26],"allow_nonstandard_anonymous_union":10,"almost":[8,9,10,11,16,21,23,25],"alon":[7,9,10,13,16],"along":[0,1,2,3,4,8,9,10,11,14,15,16,17,21,23,26],"alongsid":[5,9,10,24],"alphabet":[15,17,24],"alphanumer":16,"alreadi":[0,1,3,5,7,9,10,15,16,17,18,21,22,23,24,25],"already_defin":7,"already_defined_with_po":7,"already_in_consteval_context":7,"already_in_lookup_set":21,"already_initi":7,"also":[0,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],"alter":[0,2,7,16,21],"altern":[0,1,2,5,7,8,9,11,13,15,16,18,22,24,26],"alternate_entry_point":16,"alternate_il_file_format":0,"alternative_il_file_format":1,"alternative_token":10,"although":[0,1,2,3,5,6,9,10,11,15,16,18,21,22,23,25],"altogeth":[9,10,11,14,16,18],"alway":[0,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"always_inlin":7,"always_inline_requires_inlin":7,"always_inline_suppress":7,"ambig_literal_oper":7,"ambig_suppresses_copy_asgn_decl":7,"ambig_suppresses_copy_ctor_decl":7,"ambigu":[0,3,5,6,7,8,9,10,11,14,16,21,23],"ambiguous_assignment_oper":7,"ambiguous_base_class":7,"ambiguous_block_size_spec":7,"ambiguous_c11_gener":7,"ambiguous_c11_generic_previous_match":7,"ambiguous_cast_selects_direct_bas":7,"ambiguous_class_cal":7,"ambiguous_constructor":7,"ambiguous_constructor_for_convers":7,"ambiguous_conversion_funct":7,"ambiguous_conversion_to_builtin":7,"ambiguous_copy_constructor":7,"ambiguous_default_constructor":7,"ambiguous_derived_class":7,"ambiguous_destructor":7,"ambiguous_destructor_constraint":7,"ambiguous_fin":7,"ambiguous_function_for_deleg":7,"ambiguous_guiding_decl":7,"ambiguous_injected_template_nam":7,"ambiguous_ms_attribut":7,"ambiguous_nam":7,"ambiguous_operator_funct":7,"ambiguous_overloaded_funct":7,"ambiguous_partial_spec":7,"ambiguous_ptr_to_overloaded_funct":7,"ambiguous_question_oper":7,"ambiguous_user_defined_convers":7,"ambiguous_virtual_function_overrid":7,"aml_boxing_convers":9,"aml_ellipsi":9,"aml_error":9,"aml_exact":9,"aml_non":9,"aml_promot":9,"aml_std_convers":9,"aml_user_convers":9,"among":[0,2,3,6,10,11,14,15,21,22,23],"amount":[0,3,6,7,10,17,23],"an_":[4,14],"an_arg_list_elem":9,"an_arg_match_summari":9,"an_arg_operand":[9,15],"an_asm_entri":[6,11],"an_assert_pred":15,"an_assert_valu":15,"an_attr_appl_descr":18,"an_attr_application_fn":18,"an_attr_descr":18,"an_attribut":[11,18],"an_attribute_arg":11,"an_attribute_group":[11,18],"an_attribute_kind":18,"an_attribute_loc":18,"an_elem":4,"an_error_cod":[0,14],"an_exception_specif":[8,11],"an_exception_specification_typ":11,"an_expr_nod":[11,14,23],"an_expr_node_kind":14,"an_expr_rescan_info_entri":9,"an_ifc_access_sort":17,"an_ifc_basic_specifiers_bitfield":17,"an_ifc_basic_specifiers_bitfield_0_33":17,"an_ifc_basic_specifiers_bitfield_queri":17,"an_ifc_basic_specifiers_bitfield_storag":17,"an_ifc_byte_buff":17,"an_ifc_decl_alia":17,"an_ifc_decl_enumer":17,"an_ifc_decl_foreign_index":17,"an_ifc_decl_foreign_index_storag":17,"an_ifc_decl_funct":17,"an_ifc_decl_function_storag":17,"an_ifc_decl_index":17,"an_ifc_decl_index_0_33":17,"an_ifc_decl_index_0_41":17,"an_ifc_decl_refer":17,"an_ifc_decl_sort":17,"an_ifc_decl_sort_0_33":17,"an_ifc_decl_sort_0_41":17,"an_ifc_decl_speci":17,"an_ifc_file_head":17,"an_ifc_foo_decl":17,"an_ifc_function_traits_bitfield":17,"an_ifc_function_traits_bitfield_queri":17,"an_ifc_function_traits_bitfield_storag":17,"an_ifc_index":17,"an_ifc_index_storag":17,"an_ifc_keyword_sort":17,"an_ifc_keyword_sort_0_33":17,"an_ifc_modul":17,"an_ifc_module_refer":17,"an_ifc_name_index":17,"an_ifc_parameterized_ent":17,"an_ifc_partit":17,"an_ifc_partition_kind":17,"an_ifc_sha256":17,"an_ifc_sha256_storag":17,"an_ifc_source_location_byt":17,"an_ifc_source_location_part":17,"an_ifc_source_location_storag":17,"an_ifc_text_offset":17,"an_ifc_type_design":17,"an_ifc_type_index":17,"an_ifc_type_index_0_33":17,"an_il_entity_list_entri":11,"an_il_entry_kind":11,"an_il_entry_prefix":0,"an_il_to_str_output_control_block":0,"an_immediate_pragma_funct":18,"an_init_compon":[6,9],"an_init_pos_descr":16,"an_init_st":[6,9],"an_initi":6,"an_insert_loc":16,"an_instantiation_direct":11,"an_int_value_part":9,"an_integer_type_suppl":11,"an_integer_valu":[9,11],"an_internal_float_valu":11,"an_ms_attribut":[6,11],"an_ms_if_exist":11,"an_object_lifetim":[11,20],"an_operand":[6,9],"an_opname_kind":21,"an_other_pragma_funct":18,"an_other_variable_typ":4,"an_overriding_virtual_funct":3,"an_property_or_event_descr":9,"anachron":[0,7,11,16],"anachronism_error_sever":0,"anachronist":0,"analys":11,"analysi":[1,9,10,11,13,16,20,23],"analyz":[16,23],"ancestor":11,"and_integer_valu":9,"anew":11,"angl":6,"ani":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,20,21,22,23,24,25,26],"annex":[10,15],"annot":[2,7,10],"annotate_diagnost":10,"annotation_after_us":7,"annotation_must_have_literal_typ":7,"announc":7,"anon_union_alias_member_templ":7,"anon_union_at_decl_posit":7,"anon_union_class_member_templ":7,"anon_union_member_access":7,"anon_union_member_funct":7,"anon_union_ref_in_lambda":7,"anon_union_storage_class":7,"anon_union_using_declar":7,"anonym":[3,7,10],"anonymous_union_field":11,"anonymous_union_qualifier_ignor":7,"anoth":[0,1,2,3,5,6,7,8,9,10,11,13,14,15,16,17,18,19,21,22,23,25,26],"another_long_vari":4,"another_pragma":18,"ansi":[0,1,2,3,5,7,9,11,14,15],"answer":[3,16,17,21,22],"ant":10,"anticip":[3,6,10],"any_cfront_mod":14,"any_mor":23,"any_ref_memb":[3,21],"anyon":16,"anyth":[0,7,9,10,11,14,15,17,20,23,24],"anyway":[9,14,21],"anywher":[1,8,10,11,16,18,23],"ao":16,"apart":[0,9,10,15],"api":[7,15],"apostroph":[7,10],"appar":[0,7,10,11],"apparent_module_pp_direct":7,"appear":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,20,21,22,23,24,25,26],"append":[0,1,3,10,16,18,21,22,23,24],"appendix":[10,13,26],"appertain":[6,18],"appli":[0,3,4,6,7,9,10,11,14,15,16,17,21,22,23,24,26],"applic":[0,1,3,5,6,7,9,10,11,13,15,16,18,21,23],"apply_microsoft_attribut":6,"approach":[0,3,8,10,15,16,17,20,23,26],"appropri":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,20,21,22,23,24,25,26],"approxim":[9,10,16,24],"arbitrari":[0,9,10,11,22,23],"arbitrarili":[3,9,11,15,16],"arcan":21,"arch":[7,16],"architectur":[1,3,7,10,11,16,17],"area":[0,3,4,5,9,10,14,15,19],"aren":[1,2,6,9,11,17,24],"arg":[6,7,10,16,23,24],"arg_default_promote_operand":9,"arg_dep_lookup":[7,10],"arg_for_empty_param_pack":7,"arg_get_token":15,"argsus":[10,15,18],"arguabl":[6,9],"argument":[0,2,6,7,9,11,14,15,16,18,19,22,23,24],"argument_dependent_lookup":21,"argument_templ":23,"arguments_provided_for_attribut":7,"aris":[9,25],"arith_operand":7,"arithmet":[7,9,10,11,16],"ariti":23,"arm":[1,9,10,11,16,20,21],"around":[0,2,3,4,5,7,9,10,11,14,15,16,17,18,21,23,24],"arr":9,"arrang":[3,11,16,18,23],"array":[0,1,2,3,5,6,7,8,9,10,11,14,15,17,18,19,21,22,23,25],"array_condition_always_tru":7,"array_declar":6,"array_designator_for_deduced_context":7,"array_element_typ":22,"array_member_initi":7,"array_new_and_delet":10,"array_of_abstract_class":7,"array_of_funct":7,"array_of_generic_param":7,"array_of_handl":7,"array_of_incomplete_typ":7,"array_of_managed_class":7,"array_of_refer":7,"array_of_void":7,"array_size_must_be_posit":7,"array_size_one_assum":7,"array_size_too_larg":7,"array_subobject_not_initi":7,"array_type_not_allow":7,"arrow_star_operator_in_managed_class":7,"art":14,"as_publ":[11,21],"ascend":[2,14,15],"ascii":15,"asid":[0,3,6,11,15,16,21],"ask":[2,15,21],"asm":[7,10,14,20,22],"asm_decl_not_allow":7,"asm_declar":[6,20],"asm_func_must_be_prototyp":7,"asm_function_allow":[10,11,22],"asm_input_must_not_have_output_mod":7,"asm_name_after_definit":7,"asm_name_conflict":7,"asm_name_in_rout_defn":7,"asm_name_in_typedef":7,"asm_name_is_gnu_extens":7,"asm_name_on_auto_vari":7,"asm_name_or_reg":11,"asm_not_allow":7,"asm_operand_spec_is_gnu_extens":7,"asm_output_must_have_output_mod":7,"asm_stat":20,"aspect":[0,1,6,10,11,14,16,19,21,23],"assembl":[0,1,7,9,10,11,14,16],"assemble_function_cal":9,"assembly_info":7,"assert":[7,10,11,13,14,15,17],"assert_pred":15,"assign":[0,2,3,4,6,7,9,10,14,16,17,18,20,21,23,25,26],"assign_string_literal_sequence_numb":16,"assign_to_eh_curr_region":16,"assign_where_compare_m":7,"assigned_goto_requires_void_ptr":7,"assignment_in_value_class_typ":7,"assignment_oper":21,"assignment_to_thi":7,"assist":[6,14,20],"assoc_block":6,"assoc_info":[3,6,11],"assoc_macro":15,"assoc_pointers_block":21,"assoc_pointers_block_of":21,"assoc_scop":[3,11],"assoc_source_line_modif":15,"assoc_templ":11,"assoc_typ":[3,21],"associ":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"associated_th":4,"assort":0,"asssoci":10,"assum":[1,2,6,7,10,11,14,15,16,18,21,23,24],"assume_expression_discard":7,"assume_statement_applies_to_null_stat":7,"assumpt":[6,7,15],"assumption_fail":7,"assur":[8,21,22,23],"ast":17,"asterisk":15,"atlmfc":1,"atom":7,"atomic_constraint_evaluation_fail":7,"atomic_constraint_fals":7,"atomic_constraint_substitution_fail":7,"att_preprocessing_extensions_allow":[10,15],"attach":[0,2,3,6,9,10,11,15,16,18,20,21,22,23,25],"attach_attribut":18,"attach_specifier_attribut":18,"attach_type_attribut":18,"attempt":[0,3,5,6,7,8,9,10,11,14,15,16,17,20,23,24,25],"attempt_to_read_past_end_of_object":7,"attend":[2,16],"attent":[5,11],"attention_mark":15,"attr_arg_out_of_small_integer_rang":7,"attr_corresp_t":18,"attr_disallows_automatic_storag":7,"attr_disallows_bit_field":7,"attr_disallows_definit":7,"attr_disallows_external_linkag":7,"attr_disallows_function_typ":7,"attr_disallows_handler_param":7,"attr_disallows_inlin":7,"attr_disallows_member_funct":7,"attr_disallows_pure_virtual_funct":7,"attr_disallows_register_storag":7,"attr_disallows_virtual_funct":7,"attr_must_also_appear_in_first_declar":7,"attr_must_appear_in_class_definit":7,"attr_not_applied_to_function_typ":7,"attr_requires_automatic_storag":7,"attr_requires_bit_field":7,"attr_requires_definit":7,"attr_requires_func_typ":7,"attr_requires_function_typ":7,"attr_requires_handler_param":7,"attr_requires_inlin":7,"attr_requires_local_vari":7,"attr_requires_member_funct":7,"attr_requires_pure_virtual_funct":7,"attr_requires_register_storag":7,"attr_requires_virtual_funct":7,"attr_twice_in_group":7,"attribut":[2,3,7,9,10,14,16,21,23,25],"attribute_after_parenthesized_initi":7,"attribute_cleanup_for_paramet":7,"attribute_cleanup_requires_automatic_storag":7,"attribute_conflict":7,"attribute_declared_her":7,"attribute_does_not_apply_to_local_vari":7,"attribute_does_not_apply_to_typ":7,"attribute_ignored_for_thread_loc":7,"attribute_ignored_on_incomplete_class_decl":7,"attribute_ignored_on_nondefinit":7,"attribute_ignored_on_nonstatic_member_funct":7,"attribute_ignored_on_unnamed_typ":7,"attribute_is_gnu_extens":7,"attribute_is_nonstandard":7,"attribute_nam":6,"attribute_namespace_unrecogn":7,"attribute_not_allow":7,"attribute_not_supported_in_x86_64":7,"attribute_on_explicit_instanti":7,"attribute_requires_external_linkag":7,"attributes_ignor":7,"attributes_in_rout_defn":7,"attributes_with_no_decl":7,"augment":[3,16,23],"author":24,"auto":[3,4,7,9,10,11,16,17,23],"auto_brace_initialization_not_allow":7,"auto_cast_is_cpp23":7,"auto_direct_list_init_requires_singleton":7,"auto_ignor":7,"auto_instanti":10,"auto_new_with_braced_init":7,"auto_not_allowed_her":7,"auto_storag":10,"auto_typ":10,"auto_type_brace_initialization_not_allow":7,"auto_type_in_array_typ":7,"auto_type_in_function_typ":7,"auto_type_nonstandard":7,"auto_type_requires_initi":7,"auto_used_two_way":7,"auto_variable_in_own_initi":7,"autom":[14,18],"automat":[0,1,2,6,7,8,9,11,14,15,17,18,19,20,21,26],"automatic_template_instanti":10,"automatically_include_in_il":18,"automatically_instanti":23,"autonom":5,"aux_buffer_for_pcc_macro":15,"auxiliari":[0,2,15],"avail":[0,1,3,5,6,7,8,9,11,14,15,16,17,18,20,21,22,23,25,26],"avail_macro_arg":15,"availability_attribute_ignor":7,"avenu":15,"averag":[0,15],"avoid":[0,1,2,3,5,8,9,10,11,13,14,15,16,17,18,22,23,24,25,26],"avx":16,"await":[10,18],"await_in_unevaluated_operand":7,"await_not_allowed_in_catch_claus":7,"await_not_allowed_in_static_initi":7,"await_not_allowed_outside_function_scop":7,"await_operand_not_a_class":7,"awar":[3,6,10,11],"away":[3,7,9,11,14,15,17,21],"awkward":[11,15],"b":[0,2,3,4,6,8,9,10,11,15,16,21,23,24,25,26],"b1":[6,8,10],"b2":6,"ba":3,"back":[0,1,3,6,7,8,9,10,11,13,14,15,16,17,19,20,21,22,23,24,25,26],"back_end":[0,1,2],"back_end_is_c_gen_b":1,"back_end_is_cp_gen_b":1,"back_end_should_be_cal":1,"backslash":[7,15],"backtrack":3,"backward":[11,15,20],"bad":[0,7,14,17],"bad_address_of_ellipsi":7,"bad_affin":7,"bad_alias_templ_redecl":7,"bad_arg_type_for_operator_new":7,"bad_argument_for_bas":7,"bad_argument_for_underlying_typ":7,"bad_argument_to_make_sign":7,"bad_argument_to_make_unsign":7,"bad_array_element_typ":7,"bad_array_member_initi":7,"bad_asm_constraint_lett":7,"bad_asm_constraint_modifi":7,"bad_asm_func_ellipsi":7,"bad_asm_function_def":7,"bad_assembly_index":7,"bad_assembly_info_attribut":7,"bad_attribute_align":7,"bad_attribute_template_substitut":7,"bad_base_class":7,"bad_binary_digit":7,"bad_bit_field_s":7,"bad_bit_field_typ":7,"bad_c11_noreturn":7,"bad_call_of_class_object":7,"bad_call_of_handl":7,"bad_cast":7,"bad_character_valu":7,"bad_class_template_decl":7,"bad_cli_dynamic_cast_typ":7,"bad_cmd_line_macro":7,"bad_combination_of_dll_attribut":7,"bad_combination_of_type_specifi":7,"bad_complex_operation_result":7,"bad_compound_literal_typ":7,"bad_const_cast":7,"bad_const_cast_typ":7,"bad_const_volatile_ref_init":7,"bad_constant_function_cal":7,"bad_constant_lambda":7,"bad_constant_oper":7,"bad_constructor_decl":7,"bad_constructor_param":7,"bad_constructor_typ":7,"bad_conv_constant_expr_typ":7,"bad_conversion_function_decl":7,"bad_cpp11_constant_function_cal":7,"bad_cppcx_dynamic_cast_typ":7,"bad_cppcx_event_add_return":7,"bad_cppcx_event_remove_paramet":7,"bad_cppcx_event_remove_return":7,"bad_data_member_initi":7,"bad_decl_for_export":7,"bad_declspec_properti":7,"bad_declspec_restrict_return":7,"bad_decltype_qualifi":7,"bad_deduction_guide_access":7,"bad_deduction_guide_return_typ":7,"bad_deduction_guide_scop":7,"bad_default_arg_typ":7,"bad_default_assign":7,"bad_defined_pp_op":7,"bad_delegate_init_list":7,"bad_destructor_decl":7,"bad_digit_separator_po":7,"bad_dynamic_cast_typ":7,"bad_embed_initi":7,"bad_enum_template_decl":7,"bad_event_add_or_remove_return":7,"bad_event_compound_assign":7,"bad_exception_specification_for_speci":7,"bad_export_info_fil":7,"bad_extra_arg_for_postfix_oper":7,"bad_file_scope_storage_class":7,"bad_final_builtin_fpclassify_arg":7,"bad_finalizer_decl":7,"bad_first_arg_type_for_operator_delet":7,"bad_fixed_operation_result":7,"bad_fixed_point_valu":7,"bad_float_const":7,"bad_float_operation_result":7,"bad_float_or_fixed_suffix":7,"bad_float_valu":7,"bad_flt_config":7,"bad_friend_decl":7,"bad_function_for_deleg":7,"bad_function_for_gnu_va_arg_pack":7,"bad_function_return_typ":7,"bad_function_storage_class":7,"bad_gcc_unroll_pragma_valu":7,"bad_generic_declaration_scop":7,"bad_gnu_auto_typ":7,"bad_gnu_stmt_return":7,"bad_gro_on_alloc_fail":7,"bad_handle_dynamic_cast_operand":7,"bad_hex_digit":7,"bad_ident_str":7,"bad_il_fil":7,"bad_indirection_operand":7,"bad_init_capture_captur":7,"bad_init_for_thread_loc":7,"bad_initializer_for_array_with_unspecified_bound":7,"bad_initializer_typ":7,"bad_injection_scop":7,"bad_integral_compound_liter":7,"bad_integral_oper":7,"bad_line_numb":7,"bad_linkage_for_decl":7,"bad_linkage_for_redefine_extnam":7,"bad_linkage_of_ref_within_inline_funct":7,"bad_linkage_specifi":7,"bad_local_var_in_lambda":7,"bad_macro_mode_nam":7,"bad_macro_redef":7,"bad_malloc_attribut":7,"bad_member_storage_class":7,"bad_member_template_decl":7,"bad_member_template_sym":7,"bad_member_type_in_ptr_to_memb":7,"bad_multibyte_char":7,"bad_multibyte_char_local":7,"bad_nested_function_variable_ref":9,"bad_nonconst_ref_init":7,"bad_nonstd_anonymous_union_field":7,"bad_nontype_template_arg":7,"bad_octal_digit":7,"bad_ordering_typ":7,"bad_pack_align":7,"bad_param_kind_for_gener":7,"bad_param_specifi":7,"bad_param_storage_class":7,"bad_param_type_for_defaulted_comparison":7,"bad_parameter_type_for_static_member_oper":7,"bad_partial_speci":7,"bad_pch_fil":7,"bad_pp_directive_keyword":7,"bad_pp_oper":7,"bad_pragma_comment_str":7,"bad_predef_macro_lin":7,"bad_predef_macro_redef":7,"bad_printf_format_str":7,"bad_property_get_return":7,"bad_property_set_return":7,"bad_prototype_argument_for_bas":7,"bad_ptr_dynamic_cast_operand":7,"bad_pure_specifi":7,"bad_qualified_function_typ":7,"bad_qualified_function_type_paramet":7,"bad_qualifier_for_delayed_class_definit":7,"bad_qualifier_for_member_enum_decl":7,"bad_qualifier_for_nested_class_decl":7,"bad_raw_string_delim_char":7,"bad_ref_dynamic_cast_operand":7,"bad_reflection_kind_for_expression_splic":7,"bad_reg_nam":7,"bad_return":7,"bad_return_type_for_op_delet":7,"bad_return_type_for_op_new":7,"bad_return_type_on_main":7,"bad_return_type_on_virtual_function_overrid":7,"bad_return_value_typ":7,"bad_rvalue_array":7,"bad_rvalue_ref_const_cast_operand":7,"bad_rvalue_ref_dynamic_cast_operand":7,"bad_scope_for_concept":7,"bad_scope_for_defaulted_comparison":7,"bad_scope_for_definit":7,"bad_scope_for_explicit_instanti":7,"bad_scope_for_partial_spec":7,"bad_scope_for_redeclar":7,"bad_scope_for_speci":7,"bad_shared_storage_class":7,"bad_size_for_static_address_init":7,"bad_specifier_outside_class_decl":7,"bad_splicer_operand":7,"bad_statement_in_statement_expr":7,"bad_std_string_view":7,"bad_stdc_fx_overflow_pragma_arg":7,"bad_stdc_pragma_arg":7,"bad_stdc_pragma_arg_for_mod":7,"bad_storage_class_for_named_address_space_vari":7,"bad_storage_class_on_template_decl":7,"bad_storage_class_with_inlin":7,"bad_strong_using_scop":7,"bad_suffix":7,"bad_templ_arg_expr_oper":7,"bad_template_declar":7,"bad_template_declaration_scop":7,"bad_template_member_definit":7,"bad_template_nam":7,"bad_thi":7,"bad_tls_model_attr_arg":7,"bad_token":7,"bad_tracking_ref_dynamic_cast_operand":7,"bad_tracking_ref_init":7,"bad_type_for_atomic_fetch":7,"bad_type_for_cleanup_routin":7,"bad_type_for_gnu_sync_funct":7,"bad_type_from_instanti":7,"bad_type_name_redeclar":7,"bad_type_qualifi":7,"bad_typeid":16,"bad_unevaluated_lambda":7,"bad_unicode_char_in_pp_output":7,"bad_unicode_char_in_str":7,"bad_union_field":7,"bad_upc_shared_array_layout_qualifi":7,"bad_upc_shared_pointer_layout_qualifi":7,"bad_upc_shared_void_pointer_layout_qualifi":7,"bad_use_of_cli_array_typ":7,"bad_use_of_delegate_typ":7,"bad_use_of_function_modifi":7,"bad_use_of_main":7,"bad_use_of_member_function_typedef":7,"bad_use_of_sharp":7,"bad_user_defined_suffix":7,"bad_uuid_str":7,"bad_va_arg":7,"bad_va_copi":7,"bad_va_end":7,"bad_va_start":7,"bad_variable_for_init_prior":7,"bad_vector_conditional_s":7,"bad_vector_float_operand_s":7,"badc":24,"balanc":15,"bar":[4,10,24],"bare":[0,16],"base":[0,2,5,6,7,8,10,14,15,16,17,18,20,21,23,24,25,26],"base_assign_op_is_default":10,"base_check":7,"base_class":3,"base_class_already_initi":7,"base_class_has_different_dll_interfac":7,"base_class_init_anachron":7,"base_class_not_allowed_for_union":7,"base_class_of_class_type_with_typedef_nam":7,"base_class_offset_too_larg":7,"base_class_spec":16,"base_class_with_nonvirtual_dtor":7,"base_pp_if_stack_depth":15,"base_subobject_conflict":3,"base_subobject_not_initi":7,"base_typ":17,"base_uses_tail_pad":7,"base_with_flexible_array":7,"based_not_allowed_her":7,"based_not_followed_by_star":7,"based_requires_variable_nam":7,"based_var_cannot_be_loc":7,"based_var_must_be_ptr":7,"bases_not_in_templ":7,"bash":10,"basi":[0,1,3,10,11,14,15,16,21,23,24,25],"basic":[0,2,6,7,9,10,11,12,13,14,15,19,22,23],"basic_hdr":14,"basic_string_view":7,"basicspecifiersbitfield":17,"baz":24,"bc":16,"bcopi":1,"bear":[10,11],"becam":[1,9,11],"becaus":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,18,19,20,21,22,23,25,26],"becom":[3,9,10,11,14,16,17,18,20,21,23,25],"befor":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25],"befriend":[3,11,21],"befriending_class":3,"begin":[0,1,2,3,5,6,7,9,10,11,14,15,16,18,19,20,21,22,23,26],"begin_caching_of_fetched_token":15,"begin_catch_claus":16,"begin_deferral_of_access_check":21,"begin_end_type_mismatch_in_range_based_for":7,"begin_macro_buffer_region":15,"begin_object_lifetim":16,"begin_potential_pack_expansion_context":23,"begin_rescan_of_pragma_token":18,"begin_template_arg_list_travers":23,"begun":[11,15,16,20,23],"behav":10,"behavior":[3,5,7,8,9,15,16,17,22,23],"behind":[15,16,17],"believ":[0,7,16,19],"belong":[1,3,6,10,11,18,20,21,22,23],"benefici":11,"benefit":[0,5,10,11,16,17,23],"benign":[10,15],"berkeley":[1,9],"besid":[1,10,15,16,22],"best":[0,9,10,14,16,17,21,23],"better":[0,8,9,10,11,14,15,16,19,23,25],"bewar":[9,11],"beyond":[0,6,7,9,11,15,22,23],"bf":16,"bf__q2_10a__tm__2_i4b__sfi":16,"bi":16,"big":[9,10,15,16,17,25],"bigger":9,"bin":[1,10],"binari":[1,7,9,14,15,16,17],"binary_oper":9,"bind":[6,7,9,10,11,15,16,17,18,22,23],"bind_object_lifetim":22,"bit":[0,1,2,3,6,7,8,9,10,11,14,15,16,17,20,22],"bit_field_is_sign":11,"bit_precise_integ":10,"bit_siz":11,"bitand":10,"bite":17,"bitfield":7,"bitfields_not_allow":7,"bitint_enum_base_not_allow":7,"bitint_width_too_larg":7,"bitmask":17,"bits_required_to_represent_integer_const":9,"bitwis":[7,10,11],"bitwise_copi":7,"bitwise_copy_of":7,"blank":[10,15,26],"block":[0,1,2,4,6,7,9,10,15,16,17,18,20,21,22,23],"block_extern_initializer_not_allow":7,"block_scope_function_must_be_extern":7,"bodi":[0,2,6,7,8,9,10,11,13,14,15,16,18,20,21,22,23,25],"bom":[1,15],"book":[8,14],"bool":[7,9,10,11,23],"bool_equivalent_operand":7,"bool_operand":7,"bool_typ":[11,16],"bool_type_not_allow":7,"boolean":[0,6,7,9,11,14,15,16,17,23],"boolean_controlling_expr_is_const":7,"borland":[1,10],"born":16,"borrow":16,"both_arguments_must_have_same_typ":7,"both_ref_and_value_constraint":7,"bottom":[3,14,15,17],"bound":[2,5,6,7,9,10,11,16,20,23],"bound_funct":9,"bound_function_cast_anachron":7,"bound_function_must_be_cal":7,"boundari":[3,7,9,14,15],"bourn":1,"box":[3,6,7,9,22],"box_value_type_operand":9,"boxed_type_for":6,"boxing_conversion_poss":22,"brace":[3,4,6,7,9,10,11,14,15,16,20,23],"brace_init_vari":6,"brace_initialization_not_allow":7,"braced_init_in_paren":7,"braced_init_in_paren_init":7,"braced_init_list_not_allow":7,"braced_initi":6,"braced_list_for_implicit_lambda_typ":7,"braced_list_for_implicit_return_typ":7,"braced_list_passed_to_ellipsi":7,"bracket":[6,7,9,10,11,16,18,21],"branch":[7,8,11,16,17,20],"branch_into_constexpr_if":7,"branch_into_fin":7,"branch_into_handl":7,"branch_into_if_constev":7,"branch_into_statement_expr":7,"branch_into_try_block":7,"branch_out_of_const":7,"branch_past_initi":7,"brand":[3,6,11],"breadth":17,"break":[0,5,7,9,10,11,15,17,18,20],"break_cannot_be_in_finally_block":7,"break_label":16,"break_must_be_in_loop_or_switch":7,"break_stat":20,"breakag":10,"breaker":[9,10],"breakpoint":[0,25],"brief":[0,11],"brief_diagnost":10,"briefli":21,"bring":[0,1,11,25,26],"broad":[4,6,11],"broader":[3,9,17],"broken":[2,4,11,21,25],"brought":[3,25],"brush":3,"bsd":2,"bsearch":15,"bucket":[21,22],"buffer":[0,7,8,16,21],"bug":[2,5,7,10,11,14,16,24,26],"build":[0,6,7,9,10,11,14,15,16,17,21,22,23],"build_bin":24,"build_binary_result_operand":9,"build_identifi":1,"build_prefix_inform":0,"build_unary_result_operand":9,"builder":17,"building_pch_prefix":0,"building_runtim":[1,10],"built":[0,1,7,9,10,11,14,15,16,19,21,22,23,25],"builtin":[7,9,10,14,16],"builtin_def":14,"builtin_function_hidden":7,"builtin_function_overload":7,"builtin_kind":14,"builtin_needs_128_bit_float":7,"builtin_needs_128_bit_integ":7,"builtin_needs_char8_t":7,"builtin_needs_vector_typ":7,"builtin_operator_nonviable_because_arg_mismatch":7,"bulk":16,"bullet":6,"bundl":[9,11],"burden":[1,9],"bypass":[3,7,17,20,23],"byte":[0,1,3,7,9,10,11,14,15,16],"c":[7,8,14,17,18,19,20,22,24,25,26],"c1":[6,8,16],"c11":10,"c11_atomic_array_or_function_typ":7,"c11_atomic_bit_field":7,"c11_atomic_specifier_with_qualified_typ":7,"c17":10,"c18":10,"c2":[6,16],"c23":[7,10,15],"c23_alignas_deprec":7,"c23_alignof_deprec":7,"c23_bool_deprec":7,"c23_noreturn_deprec":7,"c23_old_style_param_id":7,"c23_static_assert_deprec":7,"c23_thread_local_deprec":7,"c23_typeof":[7,10],"c8":16,"c89":[1,7,9,10,11,14,16],"c90":10,"c99":[6,14,16,19],"c99_complex":16,"c99_constant_in_unsigned_long_long_rang":7,"c99_il_extensions_support":[11,16],"c_anachronisms_allow":10,"c_dialect":14,"c_dialect_ansi":14,"c_dialect_cplusplus":14,"c_dialect_pcc":14,"c_gen_b":[2,10,14],"c_gen_be_generates_ansi_c":2,"c_mode":14,"c_num_el":9,"c_plusplus":10,"ca":3,"ca4_cwl":16,"cach":[3,6,9,14,18,21,23],"cache_curr_token":15,"cache_template_declar":23,"cache_token_stream":15,"cache_token_stream_coalesce_identifi":15,"cache_token_stream_until_matching_token":15,"cache_token_stream_with_coalesce_flag":15,"cacheabl":18,"cached_token_rescan_stack":15,"caching_pragma_token":15,"calcul":3,"call":[0,1,2,3,5,6,7,8,10,14,15,17,18,19,20,21,22,23,25,26],"call_of_pure_virtu":7,"call_of_zero":7,"call_requires_floating_point_argu":7,"call_requires_one_argu":7,"call_requires_string_liter":7,"call_result_should_be_us":7,"call_with_unusable_argument_convers":7,"callabl":[0,3,7,9,14,26],"callahan":16,"callback":[0,6,18],"callbackcontext":7,"calle":7,"called_function_redeclared_inlin":7,"caller":[0,3,6,7,8,9,11,14,15,16,21,22],"calling_convention_ignor":7,"calling_convention_ignored_for_typ":7,"calling_convention_may_not_precede_nested_declar":7,"calling_convention_not_allow":7,"came":[5,11,15,21,23],"can":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"can_be_instanti":[16,23],"can_boolean_controlling_express":20,"can_instanti":[10,23],"cancel":[0,10],"cancel_il_fil":0,"candid":[7,9,10,21,23],"candidate_constraints_fail":7,"candidate_expl_templ_arg_subst_fail":7,"candidate_failed_constraint":7,"candidate_wrong_param_count":7,"cannot_assign_to_ms_attr":7,"cannot_be_common_internal_linkag":7,"cannot_be_const_qualifi":7,"cannot_be_declared_in_scop":7,"cannot_be_speci":7,"cannot_bind_to_curr_construct":18,"cannot_build_temp_file_nam":7,"cannot_call_member_on_lvalu":7,"cannot_call_member_on_rvalu":7,"cannot_call_named_member_on_lvalu":7,"cannot_call_named_member_on_rvalu":7,"cannot_capture_thi":7,"cannot_capture_this_by_refer":7,"cannot_capture_var":7,"cannot_cast_away_const":7,"cannot_change_access":7,"cannot_chdir":7,"cannot_create_instantiation_request_fil":7,"cannot_create_pch_fil":0,"cannot_deduce_auto_templ_param":7,"cannot_deduce_auto_typ":7,"cannot_deduce_class_template_argu":7,"cannot_deduce_decltype_auto_typ":7,"cannot_deduce_type_in_range_based_for":7,"cannot_define_dllimport_funct":7,"cannot_elide_brac":7,"cannot_evaluate_builtin_offsetof":7,"cannot_export_fgmt":7,"cannot_find_header_for_import":7,"cannot_get_file_s":7,"cannot_import_metadata":7,"cannot_import_modul":7,"cannot_import_module_bad_checksum":7,"cannot_import_module_with_no_nam":7,"cannot_init_auto_flexible_array_memb":7,"cannot_initi":7,"cannot_initialize_destructible_flexible_array":7,"cannot_initialize_field":7,"cannot_initialize_flexible_array_memb":7,"cannot_initialize_indirect_flexible_array":7,"cannot_inlin":7,"cannot_inline_cal":7,"cannot_interpret_target_bit":7,"cannot_open_fil":7,"cannot_open_file_reason":7,"cannot_open_pch_input_file_reason":7,"cannot_open_temp_file_reason":7,"cannot_read_fil":7,"cannot_redef_predef_macro":7,"cannot_redefin":0,"cannot_splice_general_express":7,"cannot_splice_member_access":7,"cannot_undef_predef_macro":7,"cannot_use_thread_local_storag":7,"cannot_write_module_none_declar":7,"canon":[11,15,16,23],"canonic":16,"canonical_":25,"canonical_il_entry_of":25,"canonical_templ":11,"capabl":[1,9,10,11,14,15,16,23],"capit":4,"captur":[0,7,10,11,14,17,23,24],"capture_mode_matches_default":7,"capture_of_static_duration_vari":7,"captured_local_var_not_in_innermost_funct":7,"captured_var_type_not_copy":7,"capturing_struct_bindings_is_cpp20":7,"care":[0,1,2,5,9,10,11,13,14,15,16,17,21,23,25],"caret":0,"carri":[3,9,10,11,18],"carriag":7,"carries_depend":[7,18],"carries_dependency_ignor":7,"carries_dependency_not_on_first_decl":7,"carv":0,"cascad":13,"case":[0,1,2,3,6,7,8,9,10,11,14,15,16,17,18,19,20,22,23,24,25,26],"case_label":20,"case_label_conflict":7,"case_label_must_be_in_switch":7,"cast":[0,2,3,4,5,6,7,9,10,17,21,22],"cast_in_requires_claus":7,"cast_interior_ptr_to_ptr":7,"cast_nod":9,"cast_not_arithmetic_or_enum_or_point":7,"cast_not_integr":7,"cast_not_integral_or_enum":7,"cast_not_scalar":7,"cast_operand":9,"cast_operand_for_reference_cast":9,"cast_operand_ful":9,"cast_pointer_for_field_select":9,"cast_to_abstract_class":7,"cast_to_bad_typ":7,"cast_to_cli_interface_class":7,"cast_to_incomplete_array_typ":7,"cast_to_qualified_typ":7,"cast_type_pre_check":9,"casual":0,"cat":24,"catastroph":[0,10,15,24],"catch":[0,1,7,8,9,11,23],"categori":[3,9,10,16,22,25],"caught":[7,8,10,16],"caus":[0,1,2,3,4,5,7,9,10,11,12,14,15,16,17,18,19,20,21,23,25,26],"caveat":[1,16],"cc":[1,7,10,16,24],"cc_clobber_ignor":7,"ccomcoclass":7,"cd":[1,24],"cdisp":24,"cell":11,"cend":9,"central":[6,14,23],"centric":16,"certain":[0,1,3,5,6,8,9,10,11,13,14,15,16,17,18,19,21,22,23,25,26],"certainti":17,"cfc_":3,"cfe":[0,14],"cfe_daemon":14,"cfe_daemon_common":14,"cfront":[1,3,6,7,8,11,14,19,20,23,26],"cfront_2":10,"cfront_2_1_mod":14,"cfront_2_1_object_code_compat":[10,16],"cfront_3":10,"cfront_3_0_mod":14,"cfront_3_0_object_code_compat":16,"cfront_global_defined_after_nested_typ":7,"cfront_global_vs_member_name_lookup_bug":10,"cfront_multiple_nested_typ":7,"cfront_name_lookup_bug":7,"cfront_object_code_compat":3,"chain":[7,10,11,15,16,22],"challeng":6,"chanc":[5,18],"chang":[0,1,2,3,4,6,7,8,9,10,11,12,13,14,15,16,17,21,22,23,24,25,26],"change_binary_operand_typ":9,"change_class_locator_into_constructor_loc":21,"change_primary_include_search_dir":0,"change_ref_kind":9,"changeabl":16,"chapter":[1,3,6,8,10,11,14,15,16,20,21],"char":[0,2,3,4,6,7,9,10,11,14,15,16,21,23],"char16_t":[7,10,16],"char32_t":[10,16],"char8_t":[7,10],"char_bit":1,"char_ends_id":15,"char_max":[1,10],"char_min":[1,10],"char_too_wide_for_rep":7,"charact":[0,1,2,4,6,7,9,10,11,13,14,16,18,21,24,26],"character_not_latin_1":7,"characterist":[1,13,14,16,21,24],"charg":9,"chart":17,"chartindex":17,"cheapli":16,"check":[0,1,3,6,7,8,10,11,13,15,16,18,20,21,22,23,24,26],"check_":9,"check_abstract_class":3,"check_ambiguity_and_verify_access":21,"check_anonymous_union_symbol":3,"check_arithmetic_operand":9,"check_assert":[0,14,17],"check_assertion_or_expect_error":14,"check_assertion_str":0,"check_boolean_controlling_express":9,"check_class_linkag":3,"check_compatibility_of_pointer_operand":9,"check_concaten":10,"check_exception_specif":8,"check_exception_type_specif":8,"check_for_branch_into_handl":20,"check_for_cli_delegate_definit":3,"check_for_cli_modifi":3,"check_for_done_with_memory_region":[0,21],"check_for_each_stat":[9,20],"check_for_following_parenthesi":15,"check_for_generalized_identifier_error":15,"check_for_jump_over_initi":20,"check_for_operator_overload":9,"check_for_prior_use_of_partial_spec":23,"check_for_template_declarator_error":15,"check_for_virtual_overrid":3,"check_function_pointer_operand":9,"check_goto_and_label":20,"check_if_entity_should_be_automatically_instanti":23,"check_if_present_in_request_fil":23,"check_implicit_lambda_return_typ":3,"check_integral_operand":9,"check_integral_or_enum_operand":9,"check_integral_or_enum_or_fixed_point_operand":9,"check_invalid_use_of_special_cli_class_typ":6,"check_lint_notreached_st":15,"check_modifiable_lvalue_operand":9,"check_narrowing_convers":9,"check_object_pointer_operand":9,"check_operator_function_param":3,"check_partial_spec_nontype_param_usag":23,"check_partial_speci":23,"check_pointer_operand":9,"check_printf_scanf_arg":9,"check_protected_member_access":21,"check_ptr_to_member_operands_for_compat":9,"check_range_based_for_array_cas":9,"check_range_based_for_default_cas":9,"check_range_based_for_member_cas":9,"check_range_based_for_stat":[9,20],"check_scalar_operand":9,"check_shift_count":9,"check_special_declaration_form":6,"check_special_member_funct":3,"check_switch_default_unexpect":14,"check_template_constraint":23,"check_unicode_secur":10,"check_user_defined_conversions_for_cast":9,"check_validity_on":6,"check_void_return_okay":20,"checked_trans_unit_copy_address_of":25,"checksum":[0,14],"chicken":16,"child":11,"children":[11,16],"choic":[0,5,9,11,14,16,17,23,25],"choos":[0,2,8,9,10,11,14,16,18,21,23],"chose":23,"chosen":[0,9,10,15,16,17,25],"chunk":0,"cil":1,"cil_2_59":16,"circuit":16,"circular":[3,7],"circular_constraint":7,"circumspect":9,"circumst":[8,10,18,21,24,25],"circumv":16,"cjk":15,"ck_address":[9,11,16],"ck_aggreg":[6,11,16],"ck_complex":11,"ck_design":[11,16],"ck_dynamic_init":[5,6,11,16],"ck_imaginari":11,"ck_init_repeat":11,"ck_ptr_to_memb":[11,16],"ck_stack_offset":16,"ck_string":[11,15],"ck_template_param":[11,23],"cl":1,"cl_ambiguous_opt":7,"cl_anachronism_option_only_in_cplusplus":7,"cl_arg_dependent_lookup_option_only_in_cplusplus":7,"cl_array_new_and_delete_option_only_in_cplusplus":7,"cl_auto_cannot_be_dis":7,"cl_auto_instantiation_option_only_in_cplusplus":7,"cl_auto_storage_option_only_in_cplusplus":7,"cl_auto_type_option_only_in_cplusplus":7,"cl_back_end_requires_il_fil":7,"cl_bool_option_only_in_cplusplus":7,"cl_c23_typeof_option_only_in_c":7,"cl_cfront_incompatible_with_microsoft":7,"cl_class_name_injection_option_only_in_cplusplus":7,"cl_compound_literals_option_only_in_c":7,"cl_could_not_open_il_fil":7,"cl_cpp26_requires_parse_nonclass_templ":7,"cl_cppcli_only_in_microsoft_cplusplus":7,"cl_cppcx_and_cppc":7,"cl_cppcx_only_in_microsoft_cplusplus":7,"cl_dep_name_option_only_in_cplusplus":7,"cl_dep_name_requires_parse_nonclass_templ":7,"cl_duplicate_file_nam":7,"cl_embedded_c_option_only_in_c":7,"cl_embedded_cplusplus_option_only_in_cplusplus":7,"cl_enum_overloading_option_only_in_cplusplus":7,"cl_error_in_debug_option_argu":7,"cl_exceptions_option_only_in_cplusplus":7,"cl_explicit_option_only_in_cplusplus":7,"cl_export_template_option_incompatible_with_modul":7,"cl_export_template_option_only_in_cplusplus":7,"cl_export_template_requires_dep_nam":7,"cl_export_template_requires_distinct_templ_sig":7,"cl_export_template_requires_no_implicit_includ":7,"cl_extended_designators_option_only_in_c":7,"cl_extern_inline_option_only_in_cplusplus":7,"cl_fixed_point_option_only_in_c":7,"cl_for_init_diff_warning_option_only_in_cplusplus":7,"cl_friend_injection_option_only_in_cplusplus":7,"cl_func_prototype_tags_option_only_in_c":7,"cl_gen_move_operations_and_rvalue_ctor_is_copy_ctor":7,"cl_gen_move_operations_option_only_in_cplusplus":7,"cl_gnu_c89_inlining_option_only_in_c":7,"cl_guiding_decls_option_only_in_cplusplus":7,"cl_ignore_std_option_only_in_cplusplus":7,"cl_ii_file_name_incompatible_with_multiple_input":7,"cl_il_display_requires_il_file_nam":7,"cl_il_file_must_be_specifi":7,"cl_impl_extern_c_conv_option_only_in_cplusplus":7,"cl_implicit_include_incompatible_with_multiple_trans_unit":7,"cl_implicit_inclusion_option_only_in_cplusplus":7,"cl_implicit_noexcept_requires_noexcept_support":7,"cl_implicit_typename_option_only_in_cplusplus":7,"cl_import_only_in_microsoft":7,"cl_incompatible_language_mod":7,"cl_incorrect_host_id":7,"cl_instantiation_option_only_in_cplusplus":7,"cl_invalid_clang_vers":7,"cl_invalid_constexpr_diag_tag":7,"cl_invalid_cwd":7,"cl_invalid_edg_base_directori":7,"cl_invalid_error_limit":7,"cl_invalid_error_numb":7,"cl_invalid_error_tag":7,"cl_invalid_flag_nam":7,"cl_invalid_gnu_vers":7,"cl_invalid_import_directori":7,"cl_invalid_instantiation_directori":7,"cl_invalid_instantiation_mod":7,"cl_invalid_macro_definit":7,"cl_invalid_macro_undefinit":7,"cl_invalid_microsoft_vers":7,"cl_invalid_numb":7,"cl_invalid_opt":7,"cl_invalid_output_mod":7,"cl_invalid_pch_directori":7,"cl_invalid_pch_s":7,"cl_invalid_target":7,"cl_invalid_template_directori":7,"cl_lambdas_option_only_in_cplusplus":7,"cl_late_tiebreaker_option_only_in_cplusplus":7,"cl_list_macros_incompatible_with_multiple_trans_unit":7,"cl_list_make_dependencies_incompatible_with_multiple_trans_unit":7,"cl_long_lifetime_temps_incompat_with_newer_featur":7,"cl_max_constexpr_option_only_in_cplusplus":7,"cl_microsoft_version_insufficient_for_cppc":7,"cl_microsoft_version_insufficient_for_cppcx":7,"cl_missing_argu":7,"cl_missing_source_file_nam":7,"cl_move_operations_require_rvalue_refer":7,"cl_must_specify_cpp11_mod":7,"cl_must_specify_cpp14_mod":7,"cl_named_address_spaces_option_only_in_c":7,"cl_named_registers_option_only_in_c":7,"cl_namespaces_option_only_in_cplusplus":7,"cl_no_output_file_need":7,"cl_nonstandard_qualifier_deduction_option_only_in_cplusplus":7,"cl_nonstd_gnu_keywords_requires_gnu_mod":7,"cl_nonstd_using_decl_option_only_in_cplusplus":7,"cl_old_for_init_option_only_in_cplusplus":7,"cl_old_specializations_option_only_in_cplusplus":7,"cl_one_instantiation_per_object_incompatible_with_multiple_input":7,"cl_one_instantiation_per_object_option_only_in_cplusplus":7,"cl_output_file_incompatible_with_multiple_input":7,"cl_parse_nonclass_templates_option_only_in_cplusplus":7,"cl_pch_incompatible_with_multiple_input":7,"cl_pch_must_be_first":7,"cl_pending_instantiations_option_only_in_cplusplus":7,"cl_pp_output_incompatible_with_multiple_trans_unit":7,"cl_relaxed_abstract_checking_only_in_cplusplus":7,"cl_relaxed_constexpr_requires_bool":7,"cl_report_gnu_extensions_requires_gnu_mod":7,"cl_require_func_prototypes_option_only_in_c":7,"cl_rtti_option_only_in_cplusplus":7,"cl_rvalue_ctor_is_copy_ctor_option_only_in_cplusplus":7,"cl_rvalue_references_option_only_in_cplusplus":7,"cl_short_enums_requires_gcc_mod":7,"cl_special_subscript_cost_option_only_in_cplusplus":7,"cl_strict_mode_incompatible_with_anachron":7,"cl_strict_mode_incompatible_with_cfront":7,"cl_strict_mode_incompatible_with_ignore_std":7,"cl_strict_mode_incompatible_with_long_preserv":7,"cl_strict_mode_incompatible_with_microsoft":7,"cl_strict_mode_incompatible_with_pcc":7,"cl_strict_mode_incompatible_with_sun":7,"cl_strict_mode_incompatible_with_svr4":7,"cl_sun_incompatible_with_cfront":7,"cl_sun_mode_only_in_cplusplus":7,"cl_svr4_c_option_only_in_ansi_c":7,"cl_tim_local_conflicts_with_auto_instanti":7,"cl_too_many_argu":7,"cl_type_traits_helpers_option_only_in_cplusplus":7,"cl_typename_option_only_in_cplusplus":7,"cl_unnamed_module_map":7,"cl_unrecognized_calling_convent":7,"cl_unrecognized_unicode_source_kind":7,"cl_unrestricted_unions_in_microsoft_mod":7,"cl_unrestricted_unions_option_only_in_cplusplus":7,"cl_upc_requires_ansi_c_dialect":7,"cl_variadic_templates_only_in_cplusplus":7,"cl_vla_option_only_in_c":7,"cl_vtbl_option_only_in_cplusplus":7,"cl_wchar_t_option_only_in_cplusplus":7,"clang":[0,1,7,10,13,14],"clang_is_generated_code_target":1,"clang_mod":14,"clang_target_version_numb":1,"clang_vers":10,"clang_version_i":14,"clangc_version_i":14,"clangcpp_version_i":14,"clarifi":10,"clariti":[4,16],"clash":16,"class":[0,2,5,6,7,8,9,10,14,17,18,24,25],"class_and_inherited_member_instance_have_dll_interfac":7,"class_and_member_function_name_conflict":7,"class_and_member_have_dll_interfac":7,"class_and_member_name_conflict":7,"class_decl":[3,6,9,11,14,23],"class_def_in_statement_expr":7,"class_definition_needed_flag_is_set":0,"class_member_declar":3,"class_member_template_declar":[3,23],"class_metadata_not_represent":7,"class_name_inject":[7,10],"class_operand":7,"class_qualified_id_lookup":21,"class_qualified_name_not_allow":7,"class_qualified_name_requir":7,"class_result_via_ctor":7,"class_specifi":[3,6,23],"class_templ":23,"class_template_declar":23,"class_template_instantiations_in_source_sequence_list":11,"class_template_same_name_as_templ_param":7,"class_too_larg":7,"class_typ":[15,21],"class_type_requir":7,"class_type_supp":11,"class_with_op_delete_but_no_op_new":7,"class_with_op_new_but_no_op_delet":7,"classic":3,"classif":[7,18],"classifi":[15,18],"claus":[0,4,6,7,8,10,11,14,15,16,20],"clean":[10,13,17],"cleanup":[0,6,7,8,11,16],"cleanup_attribute_in_constexpr_funct":7,"cleanup_on_exit_from_catch":16,"clear":[0,8,9,11,13,14,15,16,18,20,21,22,23,25],"clear_body_for_routin":25,"clear_const":22,"clear_expr_nod":22,"clear_il_to_str_output_control_block":0,"clear_loc":21,"clear_operand":9,"clear_symbol":21,"clear_variable_definit":25,"clearer":[3,14],"clever":14,"cli":[7,8,13,14,16,20,22],"cli_abstract_member_function_definit":7,"cli_array_element_typ":22,"cli_array_invalid_element_typ":7,"cli_array_invalid_number_of_dimens":7,"cli_array_invalid_number_of_subscript":7,"cli_array_must_have_new_or_array_init":7,"cli_array_rank":22,"cli_array_rank_const":22,"cli_attribute_inaccessible_field":7,"cli_attribute_invalid_argu":7,"cli_attribute_invalid_field":7,"cli_class_type_kind":11,"cli_entity_not_load":7,"cli_enum_base_has_no_system_counterpart":7,"cli_get_accessor_miss":7,"cli_handle_user_defined_conversion_poss":9,"cli_interface_cannot_have_assign":7,"cli_interface_member_function_definit":7,"cli_param_array_attribute_deprec":7,"cli_param_array_must_be_last_paramet":7,"cli_set_accessor_miss":7,"cli_typeid_of_generic_param_in_attribut":7,"cli_typeid_of_managed_point":7,"client":10,"clix":26,"clobber":7,"clone":[9,15,22,24],"clone_macro_text_map_entri":15,"clone_operand":9,"close":[0,1,3,4,6,7,8,9,10,11,14,15,16,17,18,20,21,23],"close_file_if_open":0,"close_or_remove_template_info":23,"close_temp_fil":0,"closer":24,"closur":[3,7,9,11,16],"clr":[9,10,11],"clrcall_requires_cppc":7,"clumsi":19,"cluster":21,"cmake":1,"cmd":[23,24],"cmd_line":[0,14],"cmd_line_early_init":0,"cmd_line_h":14,"cmp_fixed_point_const":9,"cmp_integer_const":9,"cmp_integer_valu":9,"cmp_operator_does_not_return_bool":7,"cmplit_integer_valu":9,"cmpulit_integer_valu":9,"cn":24,"cnl_1_0":16,"co":[9,16,21],"co_await":7,"co_await_on_non_range_based_for":7,"co_return":7,"co_yield":7,"coalesc":21,"coalesce_and_lookup_generalized_identifi":15,"coalesce_and_lookup_qualified_nam":15,"coalesce_function_template_refer":15,"coalesce_template_class_refer":[15,23],"coalesce_template_function_refer":15,"coalesce_template_id":15,"coalesce_variable_template_refer":15,"coclass_base_requirements_not_met":7,"code":[0,3,6,7,9,11,12,13,18,19,20,21,22,23,24,25,26],"code_is_unreach":7,"code_reach":20,"coexist":[3,10,21],"coincident":11,"collaps":4,"collect":[3,9,11,15,16,20,23],"collect_type_qualifi":6,"collector":9,"collid":16,"colon":[3,4,10,24],"color":10,"colorize_diagnost":10,"column":[0,2,4,5,7,10,11,14,15,17,21,25],"com":6,"combin":[0,3,6,7,9,10,11,13,14,15,16,21,22,23,24],"combine_dir_and_file_nam":0,"combine_type_specifi":6,"combine_unneeded_selector_with_operand":9,"comdat":16,"come":[0,1,3,6,7,8,9,10,11,14,15,16,17,20,21,23],"comform":16,"comma":[3,6,7,9,10,11,15,16,23,24],"comma_operator_in_array_subscript_deprec":7,"comma_operator_in_cli_subscript":7,"command":[1,2,6,7,8,9,11,13,14,15,16,19,23,24,25,26],"command_line_error":0,"comment":[0,1,2,4,5,7,9,10,11,13,14,15,16,18,20,23,26],"comment_unclosed_at_eof":7,"commentari":24,"committe":10,"common":[0,3,6,7,9,10,11,14,15,16,17,18,21,22,23,24,26],"common_lifetim":11,"common_object_lifetim":20,"communic":[3,16],"compact":[4,8,11,14,15],"companion":9,"compar":[0,3,7,9,10,11,12,15,18,22,23,25],"compare_arg_match_level":9,"compare_argument_tiebreak":9,"compare_candidate_funct":9,"compare_constraint":23,"compare_function_templ":23,"compare_macro_text_map_entry_with_offset":15,"compare_standard_convers":9,"comparison":[7,9,10,11,16,22,23,26],"comparison_defaulted_in_class_must_be_first_decl":7,"comparison_detail":7,"comparison_of_pointers_to_void_and_funct":7,"compat":[1,3,6,7,8,9,11,14,15,16,19,20,21,22,23,24,25],"compel":11,"compens":15,"compet":21,"compil":[0,1,2,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,21,22,24,25,26],"compile_multiple_source_fil":[0,1,10,14,25],"compile_multiple_translation_unit":[0,14,25],"compiler_gener":11,"compiler_generated_function_cannot_be_instanti":7,"complement":1,"complement_integer_valu":9,"complet":[0,1,2,3,5,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,24,25,26],"complete_class_definit":3,"complete_class_type_is_need":[21,23],"complete_function_template_decl":23,"complex":[0,1,3,7,8,9,10,11,14,15,16,17,20,23],"complex_bar":4,"complex_integral_typ":7,"complex_template_paramet":7,"complex_type_not_allow":7,"compli":17,"compliant":16,"complic":[0,2,3,4,5,6,7,9,10,11,14,15,16,17,20,23],"compon":[3,7,9,11,12,14,16,21,22,23,24,25],"compos":[4,6,17],"composit":[6,22],"composite_routine_typ":11,"composite_typ":22,"compound":[4,6,7,8,9,10,16,20],"compound_assignment_operation_typ":11,"compound_liter":[7,10,11],"compound_literal_enabling_poss":11,"compound_literal_is_nonstandard":7,"compound_lvalue_as_asm_operand":7,"compound_stat":[6,8,20,23],"compress":[15,16],"compris":[3,10,15,18,21,23,25],"compromis":14,"comput":[0,3,7,8,9,11,13,15,16,17,20,21],"compute_area_of_point":4,"compute_vbase_and_vcall_offset_indic":16,"concat_adjacent_string_liter":15,"concat_string_liter":15,"concat_yields_invalid_token":7,"concaten":[0,2,7,10,15,16,18,23],"concept":[2,3,7,9,10,11,16],"concept_arg_list_substitution_fail":7,"concept_fail":7,"concept_not_satisfi":7,"conceptu":[0,5,9,11,17,25],"concern":[1,3,6,9,10,15,16,17,24],"conclud":23,"concret":14,"concurr":24,"cond":23,"condens":[10,15],"condit":[0,1,6,7,8,9,10,13,14,15,18,23,24],"condition":14,"condition_decl_must_have_initi":7,"condition_does_not_declare_a_vari":7,"condition_with_multiple_declar":7,"confer":[3,21],"config":[1,10,24],"configu":10,"configur":[0,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25,26],"confirm":[6,9],"conflict":[2,3,7,10,16,25],"conflicting_attribute_in_other_translation_unit":7,"conflicting_calling_convent":7,"conflicting_cli_class_template_kind":7,"conflicting_cli_class_type_kind":7,"conflicting_nul":7,"conflicting_properti":7,"conflicts_with_predeclared_type_info":7,"conflicts_with_previous_function_decl":6,"conflicts_with_using_decl":7,"conform":[7,10,14,16,19],"confus":[3,5,7,10,15,23],"confusable_identifi":7,"confusable_map":15,"congruent_path":3,"conjg":10,"conjgf":10,"conjgl":10,"conjunct":[1,10,21,24],"connect":[10,11],"consecut":[7,11],"consequ":[0,3,5,6,8,10,11,15,16,18,20,21,23,25,26],"conserv":[9,10],"consid":[0,1,2,3,4,5,7,8,9,10,11,14,15,16,17,18,19,21,23,24],"consider":[3,9,10,16,17,18,24],"consist":[0,1,3,6,10,11,14,16,18,21,23,25],"const":[0,2,3,4,6,7,9,10,11,14,16,17,21,22],"const_cast":[7,9,16],"const_for_curr_token":[9,15],"const_function_anachron":7,"const_ignor":7,"const_int":[1,9,14],"const_mbr_suppresses_copy_asgn_decl":7,"const_string_liter":10,"const_var_in_c_const_expr":7,"const_volatile_ref_init_anachron":7,"const_volatile_ref_init_from_rvalu":7,"constant":[1,2,6,7,8,10,14,16,17,18,20,21,23,25],"constant_addresses_local_vari":7,"constant_expr_ruled_out":9,"constant_glvalue_address":[9,11],"constant_is_an_arg_operand":15,"constant_must_be_posit":7,"constant_narrowing_convers":7,"constant_narrowing_conversion_to_float":7,"constant_prvalue_point":[9,11],"constant_value_not_known":7,"constev":7,"consteval_call_nonconst":7,"consteval_ctor_with_virtual_bas":7,"consteval_destructor":7,"consteval_explicit_instanti":7,"consteval_main":7,"consteval_new_or_delete_oper":7,"consteval_overrides_nonconstev":7,"consteval_vari":7,"consteval_virtual_combin":7,"constexpr":[3,7,10,14,17,21],"constexpr_access_one_past_array_end":7,"constexpr_access_past_object":7,"constexpr_access_to_expired_storag":7,"constexpr_access_to_runtime_storag":7,"constexpr_address_unknown":7,"constexpr_alloc_too_larg":7,"constexpr_alloc_too_smal":7,"constexpr_allocation_mismatch":7,"constexpr_allocation_po":7,"constexpr_allocation_too_larg":7,"constexpr_and_consteval_specifi":7,"constexpr_bad_dealloc":7,"constexpr_bad_deallocation_s":7,"constexpr_bad_deallocation_typ":7,"constexpr_bad_derived_class_cast":7,"constexpr_bad_mantissa_str":7,"constexpr_begin_report":7,"constexpr_begin_report_token":7,"constexpr_call_not_interpret":7,"constexpr_call_to_nonconstexpr_funct":7,"constexpr_called_from":7,"constexpr_called_from_rout":7,"constexpr_class_specific_new":7,"constexpr_comparison_calls_nonconstexpr_funct":7,"constexpr_constructor_initializes_no_variant_field":7,"constexpr_constructor_with_function_try_block":7,"constexpr_ctor_does_not_initialize_bas":7,"constexpr_ctor_with_dtor":7,"constexpr_ctor_with_virtual_bas":7,"constexpr_dependent_array_s":7,"constexpr_destructor":7,"constexpr_diag_arg_count":7,"constexpr_diag_bad_level":7,"constexpr_diag_bad_str":7,"constexpr_diag_bad_tag":7,"constexpr_diag_error":10,"constexpr_diag_remark":10,"constexpr_diag_suppress":10,"constexpr_diag_warn":10,"constexpr_en":9,"constexpr_end_report":7,"constexpr_end_report_token":7,"constexpr_equality_past_the_end_address":7,"constexpr_expiring_temporari":7,"constexpr_explicit_dtor_cal":7,"constexpr_explicit_instanti":7,"constexpr_expression_cannot_be_interpret":7,"constexpr_flexible_array_initi":7,"constexpr_float_error":7,"constexpr_fp_conversion_fail":7,"constexpr_fp_error":7,"constexpr_fp_values_not_compar":7,"constexpr_function_undefin":7,"constexpr_function_with_function_try_block":7,"constexpr_goto":7,"constexpr_ignored_on_microsoft_nonstatic_memb":7,"constexpr_implied_source_nonconst":7,"constexpr_incomplete_typ":7,"constexpr_integer_overflow":7,"constexpr_interpreter_address":7,"constexpr_invalid_constant_kind":7,"constexpr_invalid_dynamic_cast":7,"constexpr_invalid_intrinsic_signatur":7,"constexpr_invalid_null_ptr_oper":7,"constexpr_invalid_pdiff":7,"constexpr_invalid_pm_access":7,"constexpr_invalid_type_convers":7,"constexpr_lambdas_not_en":7,"constexpr_leftover_alloc":7,"constexpr_local_stat":7,"constexpr_main":7,"constexpr_memcpy_distinct_typ":7,"constexpr_memcpy_nontrivial_typ":7,"constexpr_memcpy_operand_not_object":7,"constexpr_memcpy_overflow":7,"constexpr_memcpy_overlap":7,"constexpr_memcpy_partial_object":7,"constexpr_missing_initializer_for_field":7,"constexpr_missing_return_valu":7,"constexpr_modifying_const_storag":7,"constexpr_multiple_union_initi":7,"constexpr_mutable_field_load":7,"constexpr_negative_shift":7,"constexpr_no_active_union_field":7,"constexpr_no_current_paramet":7,"constexpr_non_array_pointer_arithmet":7,"constexpr_non_array_subscript":7,"constexpr_nonvirtual_subobject_delet":7,"constexpr_not_const":7,"constexpr_null_calle":7,"constexpr_null_derefer":7,"constexpr_null_ptr_to_member_data":7,"constexpr_object_too_larg":7,"constexpr_object_with_virtual_bas":7,"constexpr_out_of_bounds_array_access":7,"constexpr_placement_new":7,"constexpr_pointer_ahead_of_array":7,"constexpr_pointers_not_compar":7,"constexpr_reflection_not_of_const":7,"constexpr_reinterpret_cast":7,"constexpr_return_not_const":7,"constexpr_shift_excess":7,"constexpr_shift_negative_valu":7,"constexpr_statement_cannot_be_interpret":7,"constexpr_static_data_member_without_initi":7,"constexpr_string_not_null_termin":7,"constexpr_too_many_nested_anonymous_typ":7,"constexpr_type_invalid":7,"constexpr_type_too_larg":7,"constexpr_union_field_inact":7,"constexpr_vacuous_dtor_cal":7,"constexpr_variable_decl_must_be_definit":7,"constexpr_variable_must_have_literal_typ":7,"constexpr_virtual_bas":7,"constexpr_virtual_combin":7,"constexpr_vla":7,"constexpr_volatile_fetch":7,"constexpr_weak_address":7,"constinit":7,"constinit_variable_has_dynamic_init":7,"constinit_variable_storag":7,"constitu":[9,11],"constitut":[1,6,21,23],"constrain":[9,10],"constraint":[3,6,7,9,10,11,15,16,18,21],"constraint_concept_templ":7,"constraint_mismatch":7,"constraint_number_mismatch":7,"constru":[10,18],"construct":[0,1,2,3,5,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23],"construct_messag":0,"construct_nod":17,"construct_node_from_modul":17,"construct_node_precheck":17,"construct_node_uncheck":17,"construct_not_allowed_in_cpp11_constant_expr":9,"constructor":[0,2,3,4,7,8,10,14,22,23],"constructor_cal":7,"constructor_type_mismatch":7,"consult":[10,14,16,20,23,26],"consum":[0,1,3,10,14,18,23],"consumpt":15,"contain":[0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"contains_try_block":16,"contend":10,"content":[0,1,4,5,8,9,10,11,14,15,16,17,18,23,24],"context":[0,3,5,6,7,8,9,11,14,15,17,18,23,25,26],"context_limit":10,"contextu":[11,24],"contigu":15,"continu":[0,3,4,6,7,8,9,10,11,12,14,15,16,17,20,23],"continue_cannot_be_in_finally_block":7,"continue_must_be_in_loop":7,"continue_stat":20,"contrari":[3,10],"contrast":[3,10,11,17,18],"contriv":8,"control":[0,1,2,3,5,6,7,8,9,14,15,16,18,20,23],"control_flow_descr_list":20,"conv_array_operand_to_pointer_operand":9,"conv_char_liter":15,"conv_class_prvalue_operand_to_object_point":9,"conv_fixed_point_liter":15,"conv_fixed_point_to_fixed_point":9,"conv_fixed_point_to_float":9,"conv_fixed_point_to_integ":9,"conv_float_liter":15,"conv_float_to_fixed_point":9,"conv_float_to_float":9,"conv_float_to_integ":9,"conv_from_inaccessible_base_class":7,"conv_function_designator_to_ptr_to_funct":9,"conv_glvalue_expr_to_prvalu":[9,11],"conv_glvalue_to_prvalu":[9,11],"conv_integer_liter":15,"conv_integer_to_fixed_point":9,"conv_integer_to_float":9,"conv_integer_to_integ":9,"conv_integer_to_point":9,"conv_integer_to_ptr_to_memb":9,"conv_line_loc_to_source_po":15,"conv_lvalue_to_rvalu":[9,11],"conv_object_pointer_to_lvalu":9,"conv_of_pm_to_func_ptr":7,"conv_of_unbound_pm_to_func_ptr":7,"conv_operand_to_object_point":9,"conv_pointer_to_whatev":9,"conv_prvalue_expr_to_glvalu":11,"conv_ptr_to_member_to_ptr_to_memb":9,"conv_selector_to_object_point":9,"conv_seq_to_file_and_lin":[11,22],"conv_single_char":15,"conv_single_wide_char":15,"conv_string_liter":15,"conv_to_error_operand":9,"conveni":[0,1,3,6,9,11,14,16,17,21,22,23],"convent":[7,9,10,11,16,17,18,19,24],"convers":[0,2,5,6,7,8,10,11,14,16,22,23],"conversion_from_class_poss":9,"conversion_function_not_us":7,"conversion_header_list":21,"conversion_list":[3,21],"conversion_poss":9,"conversion_result_typ":21,"conversion_to_class_poss":9,"conversion_to_pointer_loses_bit":7,"convert":[0,3,7,9,10,11,14,15,16,17,21,22,23],"convert_initi":[6,9],"convert_operand":9,"convert_operand_into_temp":9,"convert_operand_to_handle_to_cli_str":9,"converting_to_incomplete_class":7,"convey":9,"convolut":16,"cooki":19,"cooper":8,"coordin":[8,11,23],"copi":[0,1,2,3,6,7,8,10,11,14,15,18,21,22,23],"copy_and_extend_path":3,"copy_and_simplify_short_circuited_oper":16,"copy_constructor_in_value_class_typ":7,"copy_ctor_with_default_arg_cannot_be_default":7,"copy_expr_tre":[16,22],"copy_from_secondary_to_primary_il":25,"copy_function_bodies_to_primary_il":25,"copy_header_nam":15,"copy_ifc_field":17,"copy_macro_invocation_tree_to_il":15,"copy_nod":11,"copy_secondary_trans_unit_il_to_primari":25,"copy_template_param_expr":9,"copy_typ":11,"copy_type_with_substitut":23,"copy_virtual_function_override_list":3,"copyabl":7,"copyright":[10,15],"core":[0,6,10,15],"corei7":16,"coroutin":[7,10,12],"coroutine_with_deduced_return_typ":7,"coroutine_with_ellipsis_paramet":7,"corpor":16,"correct":[0,1,6,7,9,10,11,14,15,16,17,18,19,23,24,26],"corresp_decl_at":7,"corresp_decl_incompat":7,"corresp_intercept":25,"corresp_member_template_is_different_kind":7,"corresp_prototype_sym":23,"correspond":[0,1,2,3,5,6,7,8,9,10,12,13,14,15,16,17,18,21,22,23,24],"correspondence_checking_don":25,"correspondence_checking_underway":25,"corresponding_base_class":22,"corresponding_source_po":15,"corrigenda":10,"corrupt":7,"corrupted_export_template_fil":7,"cost":[9,10,11,16],"count":[0,7,10,11,14,15,16,24,25],"count_charact":4,"counter":23,"counterpart":[3,25],"coupl":[8,24],"cours":[0,1,3,10,11,14,15,16,21],"covari":[2,7],"covariant_override_in_managed_class":7,"cover":[4,9,11,13,14,15,16,17,26],"cp":[1,16,24],"cp_gen_b":[5,11,14],"cp_gen_be_target_matches_source_dialect":1,"cpfe":24,"cpfe_cp":24,"cpfe_custom":24,"cpp":[1,6,10,14,15,24],"cpp03_mode":14,"cpp0x_sfinae_en":9,"cpp11":15,"cpp11_il_extensions_support":19,"cpp17_mode":14,"cpp20_reversed_comparison_ambigu":7,"cpp_driver":[0,15],"cpp_tool":15,"cppbe":24,"cppcli":[1,7,10],"cppcli_attribute_on":7,"cppcli_en":[11,14],"cppcli_enabling_poss":[1,11,14],"cppcli_enumerator_requires_explicit_valu":7,"cppcli_explicit_conversion_is_virtu":7,"cppcli_explicit_conversion_only_in_ref_and_value_class":7,"cppcli_not_en":7,"cppcli_requires_newer_abi_vers":7,"cppcx":[1,10],"cppcx_array_only_one_dimension_allow":7,"cppcx_bad_delegate_init_list":7,"cppcx_box_invalid_typ":7,"cppcx_enabl":14,"cppcx_enabling_poss":1,"cppcx_enum_base_has_no_platform_counterpart":7,"cppcx_generic_constraints_not_allow":7,"cppcx_generic_method_not_allow":7,"cppcx_generic_type_not_allow":7,"cppcx_handle_or_ref_to_generic_param":7,"cppcx_invalid_array_property_set_value_paramet":7,"cppcx_invalid_delegate_object":7,"cppcx_non_const_array_paramet":7,"cppcx_not_en":7,"cppcx_public_global_typ":7,"cppcx_public_indexed_properti":7,"cppcx_public_native_typ":7,"cppcx_public_nested_deleg":7,"cppcx_public_value_class_constructor":7,"cppcx_tracking_reference_on_standard_class_typ":7,"cppcx_value_type_contains_virtual_funct":7,"cppcx_value_type_deriving_from_interfac":7,"cpu":[7,10,11,16],"craft":14,"crash":[17,24],"creat":[3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"create_block_scop":22,"create_cli_delegate_definit":3,"create_expr_temporari":9,"create_external_symbol_for_linked_ent":6,"create_header_unit":[10,24],"create_il_entry_for_pragma":18,"create_initial_template_arg_list":23,"create_module_interfac":10,"create_module_internal_partit":10,"create_mv_resolv":16,"create_or_remove_instantiation_information_fil":23,"create_pch":[0,10],"create_pch_file_not_cr":7,"create_prototype_typ":23,"create_proxy_or_nonreal_class_memb":21,"creating_pch":7,"creation":[3,7,9,10,11,15,16,17,18,21,23],"cref":9,"criteria":21,"critic":18,"cross":[0,6,9,10,14,21],"cs":16,"csin":10,"csinf":10,"csinl":10,"ct":16,"ctor":[6,7,16,23],"ctor_dtor_priority_reserv":7,"ctor_initi":[3,6,23],"ctor_inti":6,"ctor_routin":16,"ctrl":24,"cu":15,"cumbersom":[9,11],"cur":4,"curr_char_loc":15,"curr_construct_":9,"curr_construct_pragma":18,"curr_context":16,"curr_expr_kind_is_traditional_const":9,"curr_object_lifetim":22,"curr_scope_id_lookup":21,"curr_source_lin":[14,15],"curr_stop_token_stack_entri":15,"curr_token":[9,14,15],"curr_token_is_inert_macro":15,"curr_token_pragma":18,"curr_translation_unit":25,"curr_type_symbol":6,"current":[0,1,2,3,5,6,7,8,9,10,11,14,16,17,18,20,22,23,24,25,26],"current_token_pragma":18,"custom":[1,7,8,10,11,16,18,26],"cv":[3,9,10,11,14,16],"cv_qualified_function_typ":7,"cx":[7,10,14],"cxx":[1,3,10,16,17],"cxxabi":12,"cycl":[0,7,16,23],"cygwin":1,"cyril":15,"d":[0,2,3,4,6,10,14,15,16,21,24,25,26],"d0":[2,16],"d1":[6,16],"d2":[6,10,16],"d7":16,"d__unix__":1,"daemon":14,"danger":14,"data":[0,1,2,5,6,7,8,10,11,12,14,18,19,20,21,22,25,26],"data_member_with_interface_typ":7,"databas":23,"date":[0,1,2,9,10,15,20],"david":16,"db":10,"db_abbreviated_typ":22,"db_access_control":22,"db_activ":[0,14],"db_constant":22,"db_corresp":25,"db_dynamic_initi":22,"db_enter":14,"db_exit":14,"db_express":22,"db_field":22,"db_flag_is_set":14,"db_has_traced_nam":14,"db_initi":22,"db_member_funct":22,"db_name":[10,14,22],"db_name_linkag":22,"db_node":17,"db_object_lifetim":22,"db_object_lifetime_stack":22,"db_operator_nam":11,"db_opt":14,"db_scope":22,"db_source_sequence_entri":22,"db_statement":22,"db_statement_list":22,"db_static_data_memb":22,"db_trace":14,"db_type":22,"db_type_nam":22,"db_variabl":22,"db_virtual_function_info":22,"dc":16,"dd":10,"de":[0,10,16],"deactiv":10,"deal":[0,1,2,3,5,6,8,9,11,14,15,16,18,21,22,23,25],"dealloc":[7,8,9,10,16],"deallocation_operator_in_namespac":7,"dealt":[10,11,18,21],"debug":[1,2,3,5,7,11,13,15,16,26],"debug_ent":[0,14],"debug_exit":[0,14],"debug_level":[0,14],"debug_show_loc":7,"debugg":[1,3,5,17,24,25],"decay":10,"decid":[0,1,3,6,9,10,11,14,15,16,18,20,21,23,24],"decim":[9,10,14,15,16,24],"decis":[0,10,11,14,15,16,17,23],"decl":[0,3,6,8,9,10,14,17,23],"decl_call_operator_for_lambda":3,"decl_default_funct":9,"decl_friend_class":3,"decl_friend_funct":3,"decl_function_templ":23,"decl_hdr":[10,14],"decl_hides_catch_paramet":7,"decl_hides_function_paramet":7,"decl_hides_template_paramet":7,"decl_idx":17,"decl_in_prototype_scop":7,"decl_incompatible_with_previous_us":7,"decl_info":23,"decl_init":[3,6,9,14],"decl_lambda_capture_field":3,"decl_literal_field":3,"decl_member_funct":[3,21,23],"decl_member_function_templ":3,"decl_modifiers_ignor":7,"decl_modifiers_incompatible_with_previous_decl":7,"decl_modifiers_invalid_for_this_decl":7,"decl_nonstatic_data_memb":3,"decl_nonstd_member_const":3,"decl_of_void_ignor":7,"decl_paramet":[6,23],"decl_posit":11,"decl_property_or_event_memb":3,"decl_ref":17,"decl_routin":[3,6,23],"decl_scop":21,"decl_scope_level":[3,21],"decl_seq":23,"decl_should_be_of_param":7,"decl_spec":[3,6,14],"decl_specifi":[3,6,8,23],"decl_stat":3,"decl_statement_ful":20,"decl_static_data_memb":[3,6,23],"decl_token_cach":23,"decl_typedef":[3,6],"decl_vari":6,"decl_with_local_type_but_not_defin":7,"decl_with_no_linkage_type_but_not_defin":7,"declalia":17,"declar":[0,2,7,8,9,10,12,13,15,17,18,20,25,26],"declaration_after_stat":7,"declaration_hides_for_init":7,"declaration_scop":23,"declarator_rang":11,"declared_but_not_referenc":7,"declares_someth":3,"declenumer":17,"declforeignindex":17,"declfunct":17,"declindex":17,"declrefer":17,"declsort":17,"declspec_align_reduction_ignor":7,"declspec_property_not_allow":7,"declspeci":17,"declspecializt":17,"decltyp":[7,9,10,11,14,16,22],"decltype_auto_cannot_be_qualifi":7,"decltype_auto_not_allowed_her":7,"decltype_auto_return_must_be_standalon":7,"decltype_auto_type_requires_initi":7,"decltype_is_not_base_class":7,"decltype_qualified_declared_nam":7,"decod":[1,26],"decode_identifi":26,"decor":10,"decreas":10,"decrement":[7,9,14,15,16,23],"decrib":6,"dedg_build_identifi":1,"dedic":[6,11,17],"deduc":[0,3,6,7,9,10,23],"deduced_return_type_conflict":7,"deduced_return_types_is_cpp14":7,"deduct":[7,9,10,23],"deduction_fail":7,"deduction_guide_def":7,"deduction_guide_redeclar":7,"deem":10,"deep":11,"def":[0,10,16,23],"def__tm__7_xcil15":16,"def_arg":14,"def_arg_expr_list":23,"def_external_linkag":6,"def_initi":[6,23],"default":[0,1,2,4,7,8,9,11,12,14,15,16,18,20,21,22,23,24,26],"default_":1,"default_address_of_ellipsis_allow":10,"default_allow_anachron":10,"default_allow_ellipsis_only_param_in_c_mod":10,"default_alternative_tokens_allow":10,"default_arg_already_defin":7,"default_arg_differs_in_other_trans_unit":7,"default_arg_expr_not_allow":7,"default_arg_for_literal_oper":7,"default_arg_not_at_end":7,"default_arg_on_function_template_not_allow":7,"default_arg_on_member_decl":7,"default_arg_on_member_friend":7,"default_arg_on_member_template_def":7,"default_arg_prototype_instanti":23,"default_arg_requires_friend_to_be_definit":7,"default_arg_used_in_param_array_funct":7,"default_args_incompat":7,"default_argument_promot":22,"default_array_new_and_delete_en":10,"default_association_appears_more_than_onc":7,"default_auto_storage_class_specifier_en":10,"default_auto_type_specifier_en":10,"default_automatic_instantiation_mod":10,"default_bool_is_keyword":10,"default_c_and_cpp_function_types_are_distinct":10,"default_calling_convent":10,"default_clang_compat":1,"default_common_tentative_definit":10,"default_constructor_in_value_class_typ":7,"default_constructor_is_explicit":7,"default_context_limit":10,"default_cppcli_en":1,"default_cppcx_en":1,"default_ctor_call_not_const":7,"default_ctor_not_constexpr":7,"default_dependent_name_process":10,"default_display_error_numb":10,"default_edg_bas":0,"default_edg_color":10,"default_emulate_gnu_abi_bug":[1,3,26],"default_enable_colorized_diagnost":10,"default_exceptions_en":[8,10],"default_explicit_keyword_en":10,"default_export_template_allow":10,"default_gnu_abi_vers":1,"default_gnu_compat":1,"default_gnu_stdc_zero_in_system_head":10,"default_guiding_decls_allow":10,"default_impl_conv_between_c_and_cpp_function_ptrs_allow":10,"default_implicit_template_inclusion_mod":10,"default_implicit_typename_en":10,"default_implicit_using_std":10,"default_include_file_suffix_list":10,"default_incognito":10,"default_init_of_refer":7,"default_instantiation_file_suffix_list":10,"default_is_unexpect":[4,14],"default_label":20,"default_label_appears_more_than_onc":7,"default_label_must_be_in_switch":7,"default_macro_positions_in_diagnost":10,"default_max_pending_instanti":10,"default_member_init_for_value_class":7,"default_microsoft_bug":10,"default_microsoft_compat":1,"default_microsoft_mod":10,"default_microsoft_vers":10,"default_module_import_diag_en":10,"default_ms_permiss":10,"default_multibyte_chars_in_source_allow":10,"default_namespaces_en":10,"default_near_and_far_en":10,"default_nocommon_tentative_definit":10,"default_not_allowed_on_partial_spec":7,"default_old_specializations_allow":10,"default_pass_stdarg_references_to_generated_cod":10,"default_record_form_of_name_refer":11,"default_remove_unneeded_ent":[0,11],"default_rtti_en":10,"default_stdc_zero_in_system_head":10,"default_sun_compat":1,"default_sun_linker_scope_allow":10,"default_svr4_c_mod":10,"default_target_configuration_nam":1,"default_template_arg_not_allow":7,"default_template_typedefs_in_diagnost":10,"default_trigraphs_allow":10,"default_typename_en":10,"default_unicode_source_kind":[1,15],"default_use_nonstandard_for_init_scop":10,"default_use_predefined_macro_fil":0,"default_variadic_templates_en":10,"default_version_of_routin":16,"default_warning_on_for_init_differ":10,"default_wchar_t_is_keyword":10,"defaulted_assignment_cannot_have_const_paramet":7,"defaulted_comparison_for_properti":7,"defaulted_copy_ctor_cannot_have_const_paramet":7,"defaulted_default_ctor_cannot_be_constexpr":7,"defaulted_functions_is_cpp11":7,"defect":[15,17],"defer":[0,6,17,18,21],"defer_parse_function_templ":10,"deferr":10,"defin":[0,2,5,6,7,8,10,11,12,13,14,15,16,17,18,19,20,22,23,24,25,26],"define_label":20,"define_macro":10,"define_member_funct":6,"define_one_virtual_function_t":16,"define_scope_virtual_function_t":16,"define_special_member_funct":3,"define_static_data_memb":[3,6],"define_virtual_function_t":16,"defined_always_fals":7,"defines_someth":3,"definit":[1,2,4,5,6,7,8,9,11,12,14,16,17,18,20,21,22,25,26],"definition_list_fil":10,"definition_need":[0,11],"definition_of_implicitly_declared_funct":7,"definition_templ":11,"defintit":23,"degener":10,"degrad":17,"degre":[10,24],"delay":[0,3,6,9,10,15,21,23],"delayed_scan_fixup_for_class":[3,23],"delayed_scan_for_function_template_default_arg":[3,23],"delayed_scan_of_default_arg_expr":3,"deleg":[6,7,9,10,11,17],"delegate_requires_managed_class":7,"delegating_constructor":[7,10],"delegating_constructor_is_cpp11":7,"delegating_constructor_requires_newer_abi_vers":7,"delegation_init_and_mem_init":7,"delegation_loop":7,"delet":[0,7,8,9,10,14,19,21,23,24],"delete_can_be_folded_into_dtor":11,"delete_count_anachron":7,"delete_fil":0,"delete_of_array_typ":7,"delete_of_array_type_nonstandard":7,"delete_of_function_point":7,"delete_of_incomplete_class":7,"delete_routin":16,"delete_source_from_loc":15,"deleted_default_constructor":7,"deleted_elided_cctor":7,"deleted_funct":7,"deleted_function_definition_must_be_first_declar":7,"deleted_function_overrides_nondeleted_funct":7,"deleted_functions_is_cpp11":7,"deleted_inh_def_constructor":7,"deleted_main":7,"deliber":[9,17,25],"delimit":[2,6,7,10,11,14,15,18],"deliv":[10,14,16],"delta":16,"demand":[3,10,23],"demangl":[1,13,16,26],"demonstr":1,"denomin":26,"denot":[4,6,11,15,23,25],"dep":23,"dep_nam":[7,10],"depend":[1,2,3,6,7,9,11,14,16,17,18,20,22,23,24,26],"dependent_stat":20,"dependent_stmt_is_declar":7,"dependent_vector_s":7,"deprec":[7,10,11,18],"deprecated_access_specifi":7,"deprecated_attr":7,"deprecated_ent":7,"deprecated_entity_with_custom_messag":7,"deprecated_string_conv":[7,10],"deprecated_string_conv_gen":7,"depth":[3,7,10,11,15,16,21,23],"depth_innermost_function_scop":21,"depth_innermost_instantiation_scop":[21,23],"depth_innermost_namespace_scop":21,"depth_of_initial_lookup_scop":21,"depth_of_innermost_scope_that_affects_access_control":21,"depth_scope_stack":21,"derefer":[7,9,17],"dereferenc":[7,17],"deriv":[0,1,2,6,7,8,9,10,11,15,16,17,18,21,22,23],"derived_class_from_virtual_bas":7,"derived_class_too_far":7,"derived_nam":0,"derivedcoreproperti":15,"descend":[0,14],"descent":[0,9,13,15],"descib":23,"describ":[0,1,3,4,6,8,9,10,11,13,14,15,16,17,18,19,21,22,23,24,25,26],"descript":[0,1,3,4,6,7,8,9,10,11,14,15,16,17,18,20,22,23,24,26],"descriptor":20,"design":[0,1,3,5,6,7,8,9,10,11,13,14,15,16,17,18,21,23,24],"designated_initializer_enabling_poss":[10,11],"designator_for_non_pod":7,"designator_for_template_dependent_typ":7,"designator_is_nonstandard":7,"designator_requires_aggregate_typ":7,"designators_allow":10,"desir":[0,1,4,5,9,10,11,13,14,15,16,17,22],"desired_typ":16,"despit":[3,10,17],"destin":[6,7,8,9,10,11,16,17],"destroy":[7,8,10,11,16,19],"destroying_delete_with_extra_param":7,"destroying_delete_wrong_typ":7,"destruct":[6,8,9,10,11,16,19,22],"destructor":[3,4,7,8,9,10,14,15,19,20,22,23],"destructor_in_value_class_typ":7,"destructor_name_must_be_qualifi":7,"destructor_or_finalizer_with_named_overrid":7,"destructor_posit":7,"destructor_qualifier_type_mismatch":7,"destructor_type_mismatch":7,"detach":9,"detail":[0,1,3,6,7,8,10,11,13,14,15,16,17,18,20,21,22,23,24,25],"detect":[0,3,7,8,9,10,14,16,18,20,21,23],"determin":[0,1,3,5,6,7,8,9,10,11,12,14,15,16,17,18,20,21,22,23,24,25],"determine_arg_match_level":9,"determine_arithmetic_convers":9,"determine_assoc_namespaces_and_class":21,"determine_correspond":25,"determine_dynamic_init_for_class_init":9,"dev_tool":15,"develop":[4,5,9,10,14,15,16,17,22],"deviat":10,"devic":6,"devot":14,"dfe_wrapup":14,"diag_":10,"diag_annotation_ind":10,"diag_default":[0,10],"diag_error":[0,10],"diag_messag":0,"diag_onc":10,"diag_remark":10,"diag_suppress":10,"diag_warn":10,"diagnos":[3,10,13,14,15,23],"diagnosi":10,"diagnost":[0,1,3,4,6,7,11,14,15,17,18,21,23,24,25,26],"dialect":[3,11,13,15,24],"dictat":[5,10,11,15,16,22],"did_not_fold":9,"didn":[16,17],"difer":23,"diff":[15,24],"differ":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25],"different_enum_comparison":7,"different_return_type_on_virtual_function_overrid":7,"differenti":[2,16],"difficult":[0,6,16],"difficulti":[0,11,23],"digit":[7,10,15,16,24],"digit_separ":10,"digit_separators_not_en":7,"digraph":10,"diirect":21,"dik_call_returning_class_via_cctor":11,"dik_express":11,"dik_non":11,"dik_nonconstant_aggreg":11,"dilemma":0,"dim":16,"dim_not_const_unsigned_int":7,"dimens":[6,7,9,10,11,16,22],"dimension":[6,7],"dinkumwar":16,"dir":[10,23,24],"direct":[0,1,2,3,5,7,8,9,11,14,16,17,18,22,24,25],"direct_alloc":14,"direct_error_output_to_stdout":10,"directori":[0,7,10,14,15,19,23,24,26],"directory_of":0,"disabl":[0,1,7,9,10,11,14,15,16,18,23,24,26],"disable_ldscop":10,"disadvantag":[10,11,23],"disallow":[0,7,9,10],"disambig":[6,14],"disambigu":[5,6,7,10,14,15,18,23],"disappear":21,"discard":[0,7,10,11,14,15,16,18,20,21,23,25],"discard_curr_construct_pragma":18,"discern":[9,15,22],"disciplin":[8,14],"discontinu":11,"discov":[10,14,24],"discret":0,"discretionari":[0,10,14],"discrimin":[14,15,16,17,21],"discuss":[3,6,8,11,15,16,20,21,23],"disguis":10,"disk":10,"disk1":10,"disk2":10,"disk3":10,"disp":24,"disp_":11,"disp_boolean":11,"disp_entri":[0,11],"disp_expr_operator_nam":11,"disp_ptr":11,"dispatch":[3,6,16,23],"display":[4,7,11,13,14,22,23,24,26],"display_error_numb":10,"dispos":[0,3,7,18],"dispose_of_unapplied_attribut":6,"disprov":6,"disqualifi":[7,16,23],"disregard":21,"distinct":[0,2,3,6,7,8,9,10,11,14,15,16,18,21,23],"distinct_template_signatur":[10,16],"distinguish":[0,1,3,5,6,7,8,9,11,14,15,16,21,22,23],"distribut":[4,10,14,26],"disturb":[15,16],"dive":[11,24],"diverg":[11,17],"divid":3,"divide_by_zero":7,"divide_integer_valu":9,"divis":[7,14,23],"dl":16,"dla":16,"dll":[0,1,6,7,10,14,15],"dll_interface_conflict_dllexport_assum":7,"dll_interface_conflict_none_assum":7,"dll_interface_ignored_on_class_templ":7,"dll_interface_ignored_on_qualified_declar":7,"dll_interface_in_unnamed_namespac":7,"dll_interface_requires_external_linkag":7,"dll_thread_conflict":7,"dllexport":7,"dllimport":7,"dllimport_defin":7,"dmi":3,"dmis":11,"dn":16,"do_and":9,"do_any_needed_instanti":23,"do_binary_oper":9,"do_cast":9,"do_class_layout":3,"do_compl":9,"do_fadd":9,"do_fcompar":9,"do_fdivid":9,"do_field_selection_oper":9,"do_fmultipli":9,"do_fneg":9,"do_fsubtract":9,"do_full_portable_eh_low":[8,16,22],"do_fxadd":9,"do_fxcompar":9,"do_fxdivid":9,"do_fxmultipli":9,"do_fxneg":9,"do_fxsubtract":9,"do_iadd":9,"do_icompar":9,"do_idivid":9,"do_il_low":[1,11],"do_imultipli":9,"do_ineg":9,"do_inlining_of_cal":16,"do_isubtract":9,"do_jdivid":9,"do_jmultipli":9,"do_land":9,"do_lor":9,"do_member_function_select":9,"do_namespace_member_promot":16,"do_not":9,"do_not_clear_specific_symbol":21,"do_not_instanti":[10,16,23],"do_not_put_curr_line_in_pp_output":15,"do_not_reus":21,"do_operand_transform":9,"do_or":9,"do_padd":9,"do_pcompar":9,"do_pdiff":9,"do_pmcompar":9,"do_preprocessing_on":15,"do_remaind":9,"do_scope_class_member_promot":16,"do_shift":9,"do_shiftl":9,"do_shiftr":9,"do_stat":20,"do_string_literal_concaten":15,"do_unordered_eh_process":16,"do_using_directive_lookup":21,"do_xadd":9,"do_xcompar":9,"do_xdivid":9,"do_xmultipli":9,"do_xneg":9,"do_xor":9,"do_xsubtract":9,"doc":1,"document":[1,6,9,10,11,14,16,17,26],"doe":[0,1,2,3,4,6,7,8,9,10,11,13,14,15,17,18,19,20,21,22,23,24,25,26],"does_not_return":18,"doesn":[0,1,2,6,9,10,11,15,16,17,18,20,21,23,26],"dollar":10,"don":[0,3,6,7,9,10,11,16,17,18,21,22,23,24,26],"done":[0,1,2,3,5,6,7,8,9,10,11,13,14,15,17,18,19,21,22,23,25,26],"dos":[0,1],"dot":15,"doubl":[0,2,3,6,7,9,10,11,16,17,21,23,26],"double_for_long_doubl":7,"doubli":[15,20],"doubt":14,"downgrad":9,"download":[1,15],"dozen":[0,1,10,14,22],"dp":16,"dps":6,"draft":[3,10],"dramat":[10,14,16],"draw":[9,19],"drive":17,"driven":[1,14,18,20,25],"driver":[10,14,19,23,24,25,26],"driver_debug":24,"drop":[7,10,11,16,18],"ds":16,"dstandalone_il_display":1,"dt":16,"dtest_numb":24,"dtor":16,"dtor_initi":[6,23],"dtor_list":19,"dtor_routin":16,"du":16,"dual_lookup_ambiguous_nam":7,"dualiti":23,"dub":1,"due":[0,3,7,9,10,14,15,16,24],"dumb":17,"dummi":[2,6,23],"dump":[0,1,2,14,24],"dump_ampersand":2,"dump_command_opt":10,"dump_configur":[1,10,24],"dump_const":2,"dump_enum_definit":2,"dump_expr":2,"dump_func_definition_typ":2,"dump_general_declaration_using_typ":2,"dump_header_cod":2,"dump_initi":2,"dump_layout":10,"dump_legacy_as_target":[1,10],"dump_routine_decl":2,"dump_routine_definit":2,"dump_scope_const":2,"dump_scope_routin":2,"dump_scope_typ":2,"dump_scope_vari":2,"dump_source_file_correspondence_info":2,"dump_stat":2,"dump_struct_union_definit":2,"dump_typ":2,"dump_type_decl":2,"dump_typedef_decl":2,"dump_variable_decl":2,"dump_variable_nam":2,"dupl_base_class_nam":7,"dupl_calling_convent":7,"dupl_decl_specifi":7,"dupl_embed_param":7,"dupl_get_or_put":7,"dupl_mem_attrib":7,"dupl_param_nam":7,"dupl_type_qualifi":7,"duplic":[0,7,10,14,16,18,25],"duplicate_asm_qualifi":7,"duplicate_class_modifi":7,"duplicate_constraint":7,"duplicate_design":7,"duplicate_friend_decl":7,"duplicate_function_modifi":7,"duplicate_header_unit_map":7,"duplicate_inheriting_constructor":7,"duplicate_macro_param_nam":7,"duplicate_module_map":7,"duplicate_ms_attr_arg":7,"duplicate_threads_dim":7,"duplicate_type_in_c11_gener":7,"duplicate_typedef":7,"duplicate_typedef_in_class":7,"duplicate_using_decl":7,"durat":[6,7,10,15,16,18],"dure":[0,1,3,6,7,8,9,10,11,15,16,17,18,21,22,23,24,25,26],"duti":17,"dyn_array":4,"dyn_local_static_in_statement_expr":7,"dynam":[0,2,3,5,6,7,8,9,14,15,20,21,22,26],"dynamic_cast":[1,7,9,10,11],"dynamic_cast_operand_must_be_polymorph":7,"dynamic_cast_to_value_gener":7,"dynamic_cast_without_rtti":7,"dynamic_exc_spec_not_permit":7,"dynamic_exception_specifications_deprec":7,"dynamic_init":[7,11],"e":[0,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],"e1":[3,5,10,11],"e2":[3,11],"e3":3,"eabi":[1,10],"earli":[0,3,7,10,11,18,24],"earlier":[0,7,8,9,10,13,14,15,16,17,18,20,21,23,24],"earliest":10,"early_tiebreak":10,"eas":[0,9,10,11,14,22,23],"easi":[0,5,11,14,16,18,23],"easier":[1,3,9,11,15,16,17,24],"easiest":[15,18],"easili":[1,9,10,11,13,14,15,16,18,21,24,25],"ec_":[0,26],"ec_exp_":14,"ec_exp_line_numb":14,"ec_no_error":[0,14],"ec_unclosed_str":0,"eccp":[10,23,24],"eccp_command":24,"eclips":[3,21],"ecma":[1,9,10,11,13],"ed":14,"edg":[0,1,3,4,8,10,11,14,15,16,17,18,19,23,26],"edg_auxiliary_info_dir_nam":0,"edg_bas":[0,1,7],"edg_base_dir":[0,10],"edg_c_to_obj_compil":1,"edg_color":10,"edg_decod":1,"edg_default_defin":1,"edg_eccp_config":1,"edg_header_pack":24,"edg_main":[0,1],"edg_modules_path":10,"edg_munch":1,"edg_prelink":[1,23],"edg_test_hom":24,"edg_test_no_copy_":24,"edg_test_runs_kept":24,"edg_win32":[1,15],"edg_x86_64":24,"edg_x86_64_cp":24,"edgcpdisp":[1,10],"edgcpf":[1,10],"edgtest":24,"edgy_my_test":24,"edison":[10,13],"edit":[1,10,15],"editor":[4,17],"educ":1,"effect":[0,2,3,5,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,26],"effective_decl_level":3,"effici":[0,1,8,9,10,11,14,15,16,17,19,21,25,26],"effort":[15,16],"efil":10,"egg":16,"eh":16,"ehsc":1,"eifc":24,"either":[0,1,2,3,4,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25],"ek_init_const":9,"ek_integral_const":9,"ek_norm":9,"ek_pp":9,"ek_sizeof":9,"elabor":[3,5,7,10,21,23,24],"elaps":[10,24],"elem_s":16,"element":[0,6,7,8,9,10,11,14,15,16,17,18,19,21,22,23,25,26],"element_type_incomplet":7,"elf":16,"elf_visibility_pop_mismatch":7,"elf_visibility_stack_empti":7,"elicit":[18,23],"elid":[3,9,16],"elif":10,"elifdef":7,"elifdef_not_en":7,"elifndef":7,"elig":[7,8,16],"elimin":[0,2,3,5,7,8,11,16,20,22,25,26],"eliminate_bodies_of_unneeded_funct":0,"eliminate_unneeded_il_entri":0,"ellipsi":[7,8,9,10,16],"ellipsis_after_param_array":7,"ellipsis_cli_accessor":7,"ellipsis_not_allow":7,"ellipsis_on_operator_funct":7,"ellipsis_parameter_for_literal_oper":7,"elog":24,"els":[0,3,7,8,9,10,11,14,15,16,17,18,21,23,26],"elseif":7,"elsewher":[2,7,10,14,15,21,23,25],"emb":[6,7,10],"embed":[4,6,7,9,10,11,14,15,16],"embed_directori":10,"embed_narrow":7,"embedded_c":[7,10],"embedded_c_option_incompatible_with_individual_feature_opt":7,"embodi":16,"emiss":6,"emit":[1,2,9,10,16,17,18,23],"emphas":[4,17],"employ":[15,21],"empti":[0,2,7,9,10,11,15,18,21,23,24],"empty_anonymous_union":7,"empty_clobbers_list":7,"empty_delimited_escap":7,"empty_else_stat":7,"empty_include_search_path":7,"empty_lambda_template_param_list":7,"empty_macro_argu":7,"empty_pack_alignment_stack":7,"empty_pack_expans":7,"empty_property_indic":7,"empty_requires_express":7,"empty_template_param_list":7,"empty_then_stat":7,"empty_throw_specification_not_cpp20":7,"empty_translation_unit":7,"empty_unicode_nam":7,"empty_wide_charact":7,"emul":[1,7,9,10,11,14,20,24,26],"enabl":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,20,21,22,23,24,25,26],"enable_if":7,"enable_ldscop":10,"encapsul":[0,3,6],"enclos":[3,6,7,9,10,11,14,15,16,20,21,22,23,25],"enclosing_scop":23,"enclosing_template_decl":23,"encod":[0,1,10,11,15,16,17,18,23],"encount":[0,2,3,5,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25],"end":[0,3,4,6,7,9,12,15,16,17,19,20,21,22,23,24,25,26],"end_caching_of_fetched_token":15,"end_deferral_of_access_check":21,"end_error":0,"end_of_curr_token":15,"end_of_directive_process":15,"end_of_file_scope_needed_flags_phas":0,"end_of_flush":7,"end_of_scope_symbol_check":21,"end_of_source_sequence_list":21,"end_pos_curr_token":9,"end_posit":9,"end_potential_pack_expansion_context":23,"endian":[1,10,15],"endif":[0,2,7,10,14,15,17,24],"endpoint":21,"english":0,"enhanc":[9,10,16],"enk_":[11,14],"enk_braced_init_list":9,"enk_compound_req":23,"enk_concept_id":23,"enk_condit":[11,16],"enk_const":11,"enk_field":11,"enk_fold":11,"enk_gcnew":[9,11],"enk_lambda":[9,11],"enk_lowered_eh_construct":16,"enk_nested_req":23,"enk_new_delet":[9,11,16],"enk_object_lifetim":11,"enk_oper":11,"enk_param_ref":11,"enk_requir":23,"enk_result_of_overriding_funct":[2,16],"enk_reuse_valu":11,"enk_routin":11,"enk_sizeof":11,"enk_temp_init":[9,11,16],"enk_throw":[8,11,16],"enk_type_operand":23,"enk_typeid":[9,11,16],"enk_vari":11,"enk_vla_dealloc":[11,16],"enlarg":0,"enough":[0,1,3,9,10,14,15,16,20],"ensur":[2,10,11,14,15,16,17,18,20,23,25],"ensure_il_scope_exist":20,"ensure_inclass_static_member_constant_initializer_is_scan":3,"entail":[6,8,16,23],"enter":[0,3,6,8,9,10,11,14,15,16,18,20,21,22,23,26],"enter_assert_pred":15,"enter_keyword":21,"enter_namespace_projection_symbol":21,"enter_overloaded_symbol":21,"enter_predef_macro":[0,21],"enter_symbol":21,"enter_synthesized_namespace_projection_symbol":21,"entir":[1,3,6,7,9,10,11,14,15,16,17,20,21,22,23,25],"entireti":[11,15],"entiti":[0,1,2,3,5,6,7,9,10,11,12,14,15,18,20,22,23,25,26],"entity_cannot_be_speci":7,"entity_defined_in_other_trans_unit":7,"entity_defined_twic":7,"entity_differs_in_other_trans_unit":7,"entity_nod":16,"entri":[0,1,2,3,5,6,7,8,9,10,15,18,19,20,23,24],"enum":[0,2,3,5,6,7,9,10,11,14,16,17,22,23],"enum_attribute_ignor":7,"enum_base_type_must_be_integr":7,"enum_base_type_too_limit":7,"enum_bit_field_too_smal":7,"enum_const_cast":7,"enum_in_managed_class_missing_definit":7,"enum_not_allow":7,"enum_operand":7,"enum_overload":[7,10],"enum_previously_declared_without_explicit_bas":7,"enum_qualifier_is_cpp11":7,"enum_specifi":6,"enum_type_not_allow":7,"enum_type_replac":7,"enum_types_can_be_smaller_than_int":[6,10],"enum_value_out_of_int_rang":7,"enum_value_out_of_underlying_rang":7,"enumer":[0,2,4,6,7,8,9,10,11,14,15,16,17,18,21,24,25,26],"enumerator_already_declar":7,"environ":[0,3,6,7,11,13,14,16,19,24,25,26],"environment":[0,10],"eok_":11,"eok_add":11,"eok_address_of":11,"eok_array_to_point":11,"eok_assign":11,"eok_base_class_cast":11,"eok_bassign":[2,11],"eok_bool_cast":[11,16],"eok_box":[9,11],"eok_cal":[11,16],"eok_cast":11,"eok_class_rvalue_adjust":11,"eok_cli_subscript":9,"eok_derived_class_cast":11,"eok_divid":11,"eok_dot_field":[9,11],"eok_dot_member_cal":11,"eok_dot_pm_cal":11,"eok_dot_stat":[9,11],"eok_dot_vacuous_destructor_cal":11,"eok_dynamic_cast":[9,11,16],"eok_eq":11,"eok_handle_to":9,"eok_handle_to_box":11,"eok_indirect":11,"eok_jfadd":11,"eok_jmultipli":11,"eok_land":11,"eok_lor":11,"eok_lvalu":11,"eok_lvalue_adjust":11,"eok_lvalue_cast":11,"eok_n":11,"eok_neg":11,"eok_not":11,"eok_padd":11,"eok_paren":11,"eok_pdiff":11,"eok_pm_base_class_cast":11,"eok_pm_cal":[11,16],"eok_pm_derived_class_cast":11,"eok_pm_field":[9,11,16],"eok_pm_points_to_field":[9,11,16],"eok_points_to_field":[9,11],"eok_points_to_member_cal":11,"eok_points_to_pm_cal":11,"eok_points_to_stat":[9,11],"eok_points_to_vacuous_destructor_cal":[11,16],"eok_post_incr":11,"eok_psubtract":11,"eok_quest":11,"eok_ref_cast":11,"eok_ref_dynamic_cast":[9,11],"eok_ref_indirect":[5,11],"eok_reference_to":[5,11],"eok_subscript":[9,11],"eok_subtract":11,"eok_unbox":11,"eok_unbox_lvalu":11,"eok_vacuous_destructor_cal":16,"eok_virtual_cal":11,"eok_virtual_function_ptr":[11,16],"ephemer":15,"epilogu":[8,16],"eq_const":22,"equal":[3,7,9,10,14,16],"equals_assumed_in_cmd_line_macro_def":7,"equiv_template_arg_list":23,"equival":[0,3,4,6,7,9,10,14,15,16,17,18,22,23,24,26],"eras":[0,2,10],"err_cod":[0,1,14,26],"err_data":[0,1,14,26],"error":[1,3,6,8,9,10,11,13,16,17,18,20,21,22,23,24,25,26],"error_and_make_error_operand":9,"error_cod":[0,26],"error_const":7,"error_detect":9,"error_direct":7,"error_in_operand":9,"error_limit":10,"error_msg":[0,1,14,26],"error_nod":22,"error_number_or_tag":10,"error_output":10,"error_posit":[0,9,14],"error_sever":18,"error_symbol_head":21,"error_tag":[0,1,14,26],"error_typ":[7,22],"ersatz":11,"es_alloc":11,"es_discretionary_error":0,"es_error":0,"es_non":18,"es_warn":0,"escap":[7,10,11,24,26],"especi":[1,9,10,11,15,16,21],"essenc":[9,17],"essenti":[0,1,3,9,10,11,16,18,19,23],"establish":[0,1,2,3,9,10,11,14,15,16,17,21,23,25],"establish_":25,"establish_block_extern_function_correspond":25,"establish_block_extern_variable_correspond":25,"establish_class_instantiation_corresp":25,"establish_friend_type_correspond":25,"establish_function_instantiation_corresp":25,"establish_trans_unit_correspondences_for_class":25,"establish_variable_instantiation_corresp":25,"estim":24,"et":[5,9,10,16,23],"etc":[0,1,2,3,4,5,6,7,9,10,11,14,15,16,18,20,21,22,23,25,26],"evalu":[0,2,3,7,8,9,10,11,14,17,21,23,24],"even":[0,1,2,3,5,6,9,10,11,14,15,16,17,18,20,21,22,23,25],"event":[0,1,5,7,8,9,11,15,16,18,20,21],"event_accessor_missing_value_paramet":7,"event_accessor_value_parameter_mismatch":7,"event_add_already_declar":7,"event_in_cppcx_value_typ":7,"event_interface_cannot_have_definit":7,"event_interface_must_be_previously_defin":7,"event_name_not_allow":7,"event_raise_already_declar":7,"event_raise_type_mismatch":7,"event_remove_already_declar":7,"event_requires_managed_class":7,"event_without_raise_invok":7,"eventregistrationtoken":7,"eventu":[0,6,10,16,25],"ever":[11,14,16,17],"everi":[0,1,3,6,10,11,14,15,16,17,18,21,23,24,25],"everyth":[0,2,8,9,10,11,14,16,17,26],"everywher":[14,16],"evid":5,"evm":10,"evm2":10,"exact":[0,2,3,4,5,7,9,10,11,15,16,17,18,20,22,23,24,25],"examin":[1,3,5,9,10,11,15,16,17,20,21,22,23,25,26],"examine_expr_for_dependent_typ":11,"exampl":[0,1,2,3,5,6,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"exc_spec_in_func_typ":10,"exceed":[4,7,10],"except":[1,3,4,6,7,9,10,11,12,14,15,17,18,19,20,21,22,23,24,25],"exception_handler_us":7,"exception_spec_override_incompat":7,"exception_specif":[8,11],"exception_specification_ignor":7,"exception_specification_not_allow":7,"exception_type_specif":16,"exceptions_en":8,"exceptions_in_embedded_cplusplus":7,"excess":[7,17,23],"excess_characters_in_literal_ignor":7,"excess_initializers_ignor":7,"excess_pack_expans":7,"excessive_comparison_rewrit":7,"excessive_constexpr_complex":7,"excessive_rescan_depth":7,"exchang":23,"exclud":[2,10,11,13,23],"exclude_from_context_output":21,"exclus":[0,9],"exe":1,"exec":7,"execut":[0,1,2,6,7,8,9,10,11,14,15,16,19,22,23,24,26],"execution_arg":24,"executor":24,"exert":10,"exhaust":[0,1,8,15,21,24],"exist":[0,1,2,3,4,6,7,8,9,10,14,15,16,17,21,22,23,25],"existing_log":17,"exit":[0,3,6,8,11,14,15,16,23,24],"exit_compil":0,"exit_foral":7,"exp_asm_clobb":7,"exp_asm_label":7,"exp_asm_operand":7,"exp_asm_str":7,"exp_assign":7,"exp_attribute_nam":7,"exp_auto":7,"exp_class":7,"exp_class_or_typenam":7,"exp_class_typ":7,"exp_colon":7,"exp_comma":7,"exp_comma_or_gt":7,"exp_comma_or_rbracket":7,"exp_concept_nam":7,"exp_cpp_keyword":7,"exp_declar":7,"exp_definition_of_tag":7,"exp_digit_sequ":15,"exp_ellipsi":7,"exp_error_argu":7,"exp_except_or_fin":7,"exp_field_nam":7,"exp_file_nam":7,"exp_gt":7,"exp_gt_not_shift_right":7,"exp_header_nam":15,"exp_id_in_for_each_decl":7,"exp_identifi":7,"exp_in":7,"exp_int_const":7,"exp_interpol":7,"exp_lbrac":7,"exp_lbracket":7,"exp_line_numb":7,"exp_lparen":7,"exp_lparen_or_brac":7,"exp_lsplic":7,"exp_lt":7,"exp_macro_param":7,"exp_member_nam":7,"exp_ms_attr_arg_list":7,"exp_ms_attr_bool_valu":7,"exp_ms_attr_enum_valu":7,"exp_on_or_off":7,"exp_oper":7,"exp_pointer_to_memb":7,"exp_primary_expr":7,"exp_push_pop":7,"exp_rbrac":7,"exp_rbracket":7,"exp_rparen":7,"exp_rparen_and_pragma_ignor":7,"exp_rsplic":7,"exp_semicolon":7,"exp_stat":7,"exp_string_liter":7,"exp_system_header_nam":15,"exp_templ":7,"exp_type_nam":7,"exp_type_specifi":7,"exp_whil":7,"expand":[0,2,5,7,9,10,11,14,15,16,18,23],"expand_curr_source_lin":15,"expand_macro":[15,18],"expand_macro_buff":15,"expand_statement_inlin":16,"expand_top_level_pcc_macro":15,"expanded_text":15,"expans":[1,5,7,9,10,11,14,15,16,18,23],"expansion_contains_no_pack":7,"expect":[0,1,2,5,6,7,9,10,11,13,14,15,16,17,18,23],"expect_error":14,"expected_an_attribut":7,"expected_string_view_valu":7,"expected_template_arg":7,"expedi":1,"expens":[1,14,16,17,21,23,24,25],"expensive_check":[1,14],"experi":17,"experiment":[10,17],"expir":[7,9,11],"expired_reflection_valu":7,"expl_conversion_poss":22,"expl_narrowing_64_bit_int":7,"expl_spec_alias_templ":7,"explain":[1,3,10,18],"explan":3,"explicit":[0,1,2,4,5,6,7,8,9,10,11,14,15,16,18,19,20,21,22,24,26],"explicit_ctor_in_copy_list_init":7,"explicit_deduction_guide_in_copy_list_init":7,"explicit_enum_base_nonstandard_in_current_mod":7,"explicit_instanti":23,"explicit_instantiation_not_in_namespace_scop":7,"explicit_lambda_template_parameters_is_cpp20":7,"explicit_not_allow":7,"explicit_specialization_friend":7,"explicit_specialization_not_in_namespace_scop":7,"explicit_template_args_ignor":7,"explicit_template_args_not_allow":7,"explicit_this_is_cpp23":7,"explicit_this_needs_thi":7,"explicit_this_param_must_be_first":7,"explod":2,"exploit":[0,1,3,10,15],"exploratori":9,"expon":[7,10,16],"export":[0,1,7,16,21,24,25],"export_after_definit":7,"export_cannot_contain_export":7,"export_cannot_contain_import":7,"export_class_memb":7,"export_info":[10,23],"export_internal_linkag":7,"export_must_introduce_nam":7,"export_not_allow":7,"export_not_at_namespace_scop":7,"export_on_instanti":7,"export_only_in_modul":7,"export_remov":7,"exported_in_unnamed_namespac":7,"exported_instantiation_and_speci":7,"exported_template_fil":10,"expos":[14,17,21],"exposit":24,"expr":[6,7,8,9,11,14,15,16,23],"expr1":11,"expr2":11,"expr_":9,"expr_access_checking_should_be_don":9,"expr_diagnostic_should_be_issu":9,"expr_direct_init_object":6,"expr_error_should_be_issu":9,"expr_fold_constexpr_cal":9,"expr_fold_constexpr_ctor":9,"expr_ful":9,"expr_has_no_effect":7,"expr_hdr":14,"expr_init_aggr_vari":6,"expr_init_scalar_vari":6,"expr_is_rescann":9,"expr_not_a_glvalu":7,"expr_not_a_modifiable_lvalu":7,"expr_not_an_lvalu":7,"expr_not_an_lvalue_or_function_design":7,"expr_not_arithmet":7,"expr_not_arithmetic_or_enum":7,"expr_not_arithmetic_or_enum_or_point":7,"expr_not_arithmetic_or_unscoped_enum":7,"expr_not_arithmetic_or_unscoped_enum_or_point":7,"expr_not_bool":7,"expr_not_class":7,"expr_not_const":7,"expr_not_fixed_point":7,"expr_not_integr":7,"expr_not_integral_const":7,"expr_not_integral_or_enum":7,"expr_not_integral_or_enum_or_fixed_point":7,"expr_not_integral_or_fixed_point":7,"expr_not_integral_or_unscoped_enum":7,"expr_not_integral_or_unscoped_enum_or_fixed_point":7,"expr_not_object_point":7,"expr_not_point":7,"expr_not_pointer_nor_handl":7,"expr_not_pointer_or_array_handl":7,"expr_not_pointer_to_object":7,"expr_not_ptr_to_class":7,"expr_not_ptr_to_funct":7,"expr_not_ptr_to_memb":7,"expr_not_ptr_to_struct_or_union":7,"expr_not_scalar":7,"expr_not_struct_or_union":7,"expr_pos_diagnost":9,"expr_pos_error":9,"expr_pos_warn":9,"expr_range_modifiers_in_il":1,"expr_syntax_error":9,"expresison":23,"express":[0,1,2,3,4,5,7,10,13,15,17,18,20,21,23,24,25],"expression_kind":9,"exprutil":[9,11,14,22,23],"ext_vector_typ":7,"ext_vector_type_invalid_s":7,"ext_vector_type_not_in_typedef":7,"ext_vector_type_requires_bool_integral_floating_typ":7,"ext_vector_type_requires_integral_floating_typ":7,"extasm":14,"extend":[1,2,6,7,9,10,14,15,16,17,18,21,23,26],"extended_design":[7,10],"extended_designator_is_gnu_extens":7,"extended_designators_allow":10,"extended_friends_is_cpp11":7,"extended_modifier_ignored_on_enum":7,"extended_variadic_macro":10,"extens":[1,2,6,7,9,11,13,14,16,17,18,19,20,21,22],"extent":[14,17],"extern":[0,2,3,5,6,7,8,11,13,15,22,23,26],"extern_c_literal_oper":7,"extern_inlin":[7,10],"extern_inline_never_defin":7,"extern_template_follows_instanti":7,"external_name_clash":7,"externalize_statics_for_exported_templ":25,"extra":[0,1,3,6,7,9,10,11,14,15,16,17,18,21,23,24,25],"extra_arguments_ignor":7,"extra_bits_ignor":7,"extra_braces_on_simple_init":7,"extra_chars_on_numb":7,"extra_event_accessor_paramet":7,"extra_property_accessor_paramet":7,"extra_semicolon":[0,7],"extra_source_positions_in_il":[1,11,15],"extra_text_in_pp_direct":7,"extract":[7,9,11,14,15,16,21,22,26],"extract_operand_from_expression_compon":9,"extract_specific_pragma":[15,18],"extran":[7,10],"extraneous_injected_declaration_token":7,"extraneous_injected_member_token":7,"extraneous_injected_statement_token":7,"extrem":[0,6,11,14,15,16,18],"f":[0,2,3,4,5,6,8,9,10,11,14,15,16,18,21,23,24,25,26],"f1":[10,18],"f2":[10,18],"f2__tm__4_z1z__fz1z_v":23,"f3":18,"f4":18,"f__13a__tm__2_s__sfv":16,"f__1aff":16,"f__1afv":16,"f__1do1bfv":16,"f__23a__ps__6_pz1zi__tm__2_ifv_v":16,"f__ff":16,"f__s__tm__2_i__10a__tm__2_cfz1_2z_v":16,"f__tm__12_s__pk__3_id__fv_i":16,"f__tm__15_12a__l1__x__fv__fz1z_v":16,"f__tm__2_i__10a__tm__2_ifz1_2z_v":16,"f__tm__2_i__fz1z_yocl_2_4g__gi1io":16,"f__tm__2_i__s__10a__tm__2_ffz1_2z_v":16,"f__tm__4_z1z__fz1z_v":23,"f_check_cli_type_pointed_to":6,"f_check_protected_member_access":21,"f_debug":14,"f_error":14,"f_get_opnam":21,"f_get_type_qualifi":22,"f_identical_typ":22,"f_impl":3,"f_instantiate_template_class":[3,21],"f_is_generalized_identifier_start":15,"f_logical_column_offset":15,"f_mbc_length":15,"f_possibly_add_orphaned_file_scope_il_entri":11,"f_raw_list":[0,15],"f_size":17,"f_types_are_compat":[22,25],"f_update_source_sequence_list":22,"f_xref_info":21,"fabric":15,"facil":[0,1,10,14,15,16,18,23],"facilit":[3,6,10,11,14,15,17,21,24],"fact":[0,2,3,5,6,8,9,10,11,14,15,16,17,18,19,20,21,22,23,25],"facto":16,"factori":15,"fail":[0,7,9,10,11,15,16,21,23],"failed_destructor_constraint":7,"failed_tuple_container_member_get":7,"failur":[0,9,10,14,17,18],"fair":[0,2,3,4,6,9,11,15,16,17,24,25],"faith":11,"fake":2,"fall":[6,9,14,15,17,20,23],"fallthrough":[4,7],"fallthrough_applies_to_null_stat":7,"fallthrough_must_precede_switch_cas":7,"fallthrough_not_in_switch":7,"fals":[0,1,4,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24],"famili":[10,16,18,21],"familiar":13,"fan":15,"fancier":16,"far":[0,3,9,10,11,14,15,17,18,20,21,23],"far_code_point":10,"far_data_point":10,"farther":[3,11],"fashion":[7,10,14,24],"fast":[0,11,15,21],"faster":[10,14,24],"fastest":11,"fault":14,"favor":17,"fc":24,"fe_cleanup":0,"fe_common":[10,14],"fe_init":[0,1,10,14,15,21,25],"fe_wrapup":[0,10,14,23,25],"fe_wrapup_part_2":0,"feasibl":16,"featur":[0,2,3,6,7,8,9,13,14,16,18,21,23,24],"feature_not_allowed_in_current_mod":7,"feature_requires_c":7,"feature_test_macro_ignor":7,"feature_test_macro_req_id":7,"fed":[2,16,24],"feedback":23,"feedgcpdisp":1,"feedgcpf":1,"feel":[11,14],"fetch":[0,3,7,9,11,15,16,18,21,23,25],"fetch_pp_token":15,"fewer":[10,11,16,18],"fghi":0,"fictiti":0,"field":[0,1,2,5,6,7,8,9,10,14,15,16,18,19,21,22,23,25],"field_cannot_be_tracking_refer":7,"field_cannot_involve_vla_typ":7,"field_init_in_class_type_with_typedef_nam":7,"field_initi":3,"field_initializer_is_not_const":7,"field_initializer_list":7,"field_initializers_is_cpp11":7,"field_lvalue_selection_expr":22,"field_name_conflicts_with_class":7,"field_rvalue_selection_expr":22,"field_subobject_not_initi":7,"field_target_on_nontrivial_property_or_ev":7,"field_type_cannot_be_qualified_with_named_address_spac":7,"field_uses_tail_pad":7,"field_with_asm_name_not_allow":7,"field_without_dll_interfac":7,"fifti":10,"figur":[10,11],"file":[2,3,4,5,6,7,9,13,15,17,18,19,25,26],"file_1":10,"file_2":10,"file_delete_error_reason":7,"file_ends_with_unterminated_type_definit":7,"file_for_module_not_found":7,"file_h":10,"file_nam":10,"file_scope_id_lookup":21,"file_scope_pointers_block":25,"file_scope_region_numb":25,"file_write_error":7,"file_write_error_errno":7,"filehead":17,"filenam":[1,10],"fill":[0,8,14,21,22,26],"filter":[1,21,26],"final":[0,1,3,6,7,8,9,10,11,15,16,17,18,20,21,22,25],"final_base_class":7,"final_managed_class":7,"final_modifier_requires_virtual_funct":7,"final_suspend_cannot_throw":7,"finalize_does_not_override_object_fin":7,"finalizer_does_not_exist":7,"finalizer_name_must_be_qualifi":7,"finalizer_qualifier_type_mismatch":7,"finalizer_requires_reference_typ":7,"finalizer_type_mismatch":7,"find":[0,1,3,6,7,8,9,11,14,15,16,17,18,20,21,22,23,24,26],"find_":25,"find_addr_of_overloaded_function_match":9,"find_assoc_pragma":18,"find_attribut":18,"find_base_class_of":22,"find_class_template_instanti":25,"find_class_template_memb":23,"find_copy_assignment_oper":9,"find_copy_constructor":9,"find_corresp_prototype_tag_sym":23,"find_corresponding_inst":23,"find_default_constructor":9,"find_direct_base_class_of":22,"find_direct_or_virtual_base_class_of":22,"find_enclosing_struct_stmt":20,"find_external_symbol":21,"find_function_template_instanti":25,"find_function_template_memb":23,"find_include_histori":15,"find_instantiation_insert_scop":22,"find_linked_symbol":[6,23],"find_matching_template_inst":23,"find_member_function_templ":23,"find_nested_class_symbol":21,"find_out_of_scope_declar":21,"find_progenitor_symbol":21,"find_projected_symbol":21,"find_symbol":[15,21],"find_synthesized_projection_symbol":21,"find_template_class":[15,23],"find_template_funct":[9,23],"find_template_vari":15,"find_trait":17,"find_type_correspond":25,"find_variable_member_templ":23,"find_vla_dimens":11,"fine":[10,14,23,24],"finer":14,"finicki":13,"finish":[0,3,6,11,14,18,21,23,25],"finish_for_init_block":20,"finish_function_body_process":[21,25],"finish_function_processing_for_memory_region":3,"finish_il_fil":0,"finish_moved_entity_process":25,"finish_processing_for_function_bodi":25,"finish_trans_unit_copi":25,"finish_variable_remapping_for_inlin":16,"finit":[14,15],"firm":16,"first":[0,2,3,4,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25],"first_arg_must_be_integer_const":7,"first_decl_not_gnu_inlin":7,"first_inline_after_definit":7,"fit":[4,7,10,11,14,18,23],"five":[7,24,25],"fix":[0,1,3,4,6,7,10,14,15,16,17,24,25],"fix_type_list_ordering_problem":25,"fix_up_dynamic_init_dtor":9,"fixed_point":[7,10],"fixed_point_typ":22,"fixed_pt":[1,9,14,15],"fixed_register_clobb":7,"fixed_register_us":7,"fixed_sign_chang":7,"fixed_template_paramet":7,"fixed_to_fixed_convers":7,"fixed_to_float_convers":7,"fixed_to_integer_convers":7,"fixup":[6,9,11],"fixup_curr_block_labels_and_goto":20,"fixup_function_scope_source_sequence_list":22,"fixup_instantiation_scop":21,"fixup_virtual_base_class":3,"flag":[1,2,3,4,5,6,7,8,9,10,12,14,15,17,18,19,20,21,22,23,24,25,26],"flat":[5,16,18],"flatten":11,"flavor":23,"flexibl":[7,10,11,16,18],"flexible_array_is_nonstandard":7,"flexible_array_member_not_allow":7,"flg":23,"fli":[9,14,23],"flip":[9,16,23],"floa":10,"float":[0,1,2,3,7,10,11,13,14,15,16,18,19,23,25,26],"float128_t":7,"float16":24,"float64_t":7,"float_pt":[1,9,14,15],"float_template_paramet":7,"float_to_fixed_convers":7,"float_to_float_convers":7,"float_to_integer_convers":7,"float_typ":[14,22],"flow":[0,1,4,9,10,11,14,15,16,17,20],"flush":[14,15],"flush_ref_entries_list":9,"flush_token":[0,14,15],"flush_until_matching_token":15,"fmax":10,"fmaxf":10,"fmaxl":10,"fmodul":24,"fms":10,"fmt":[10,26],"fmt_arg_does_not_exist":7,"fmt_arg_is_not_str":7,"fn":24,"fnc_hk":10,"fnc_hr":10,"fnc_k":10,"fnc_lk":10,"fnc_lr":10,"fnc_r":10,"fnc_uhk":10,"fnc_uhr":10,"fnc_uk":10,"fnc_ulk":10,"fnc_ulr":10,"fnc_ur":10,"fnm":23,"focus":24,"fold":[7,10,14,16],"fold_base_class_cast":9,"fold_derived_class_cast":9,"fold_expression_operator_mismatch":7,"fold_expressions_nonstandard":7,"fold_field_select":9,"fold_pm_base_class_cast":9,"fold_pm_derived_class_cast":9,"follow":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,26],"foo":[4,10,11,16,17,24],"foo_avx":16,"foo_corei7":16,"foo_default":16,"foodef":17,"fooproxydecl":17,"fopen":15,"fopen_interfac":15,"for_each_getenumerator_return_type_invalid":7,"for_each_incompatible_typ":7,"for_each_invalid_return_type_for_move_next":7,"for_each_iterator_declar":20,"for_each_missing_field":7,"for_each_missing_funct":7,"for_each_no_matching_overload":7,"for_each_stat":20,"for_each_static_funct":7,"for_each_undefined_identifi":7,"for_init_diff_warn":10,"for_init_hidden_declar":7,"for_init_hides_declar":7,"for_init_stat":20,"for_stat":20,"forbid":26,"forc":[0,9,10,15,16,17,23,24],"force_vtbl":[10,16],"forese":[10,17],"forev":15,"fork":[14,17],"form":[0,1,2,3,5,6,7,9,10,11,13,14,15,16,17,18,21,22,23,24,25,26],"form_address_const":0,"form_array_declar":0,"form_char":0,"form_class_or_namespace_qualifi":0,"form_const":[0,5],"form_float_kind_nam":0,"form_function_declar":0,"form_int_kind_nam":0,"form_integer_const":0,"form_nam":0,"form_pm_const":0,"form_template_arg":0,"form_typ":0,"form_type_first_part":0,"form_type_second_part":0,"form_type_specifi":0,"formal":[1,7,9,10,13,23],"format":[0,1,4,7,9,10,11,14,15,17,22,23,26],"format_output_lin":[0,10],"format_rout_not_vararg":7,"former":[0,3,6,9,10,11,17,18,22,23,25],"forscop":7,"forscope_stack_empti":7,"forth":[0,1,6,9,10,11,18,22,23],"fortran":16,"fortun":[15,23],"forward":[2,3,7,10,11,14,15,17,20],"found":[0,3,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25,26],"found_from_header_unit_map":7,"found_from_module_map":7,"foundat":7,"four":[0,1,6,9,11,18,21,23,25],"fourth":[6,18,21],"fp":[10,16,24],"fp_add":9,"fp_change_kind":9,"fp_compar":9,"fp_divid":9,"fp_hash":9,"fp_hex_string_to_float":9,"fp_hex_string_to_float_point":15,"fp_is_zero_const":9,"fp_long_to_float":9,"fp_multipli":9,"fp_string_to_float":[9,15],"fp_subtract":9,"fp_to_host_large_integ":9,"fp_to_host_large_unsign":9,"fp_to_str":[9,16],"fp_unsigned_long_to_float":9,"fragment":[0,5,7,11,24],"frame":[9,16],"framemak":26,"framework":[3,14,18],"fread":0,"free":[0,1,8,9,10,11,14,15,16,18,21],"free_init_component_list":6,"free_list_of_symbol_list_entri":21,"free_macro_arg":15,"free_memory_region":0,"free_object_lifetim":22,"free_orig_line_modif":15,"free_pending_pragma_list":18,"free_source_line_modif":15,"freed":[0,8,14,15,16,20,21],"freeli":15,"frequent":[6,10,14,21],"fresh":[1,9],"friend":[0,5,6,7,10,11,21,22,23,24],"friend_attribute_requires_definit":7,"friend_cannot_add_default_argu":7,"friend_class":3,"friend_class_template_default_arg_not_allow":7,"friend_inject":[7,10],"friend_is_nonreal_templ":7,"friend_partial_speci":7,"friend_qualification_ignor":7,"friend_routin":3,"friend_specifier_ignor":7,"friend_template_in_local_class":7,"friend_with_def_arg_must_be_definit":7,"friend_with_def_arg_must_be_only_decl":7,"friendship":[3,11],"front":[0,2,3,5,6,8,9,12,15,16,17,18,19,21,22,23,24,25,26],"frozen":16,"fs_constant":22,"fsm":15,"fulfil":[17,21],"full":[0,2,5,7,8,9,10,11,13,14,15,16,26],"full_enter_symbol":21,"full_source_pos_in_il_stat":11,"full_speci":23,"fullfil":18,"fulli":[1,3,7,9,10,11,15,16,17,18,23,24],"fully_qualified_constructor_cal":7,"fully_resolved_macro_posit":[1,10,11,14,15],"func":[10,16],"func_cd":10,"func_cf":10,"func_cl":10,"func_d":10,"func_decl":17,"func_def":[3,6,14],"func_f":10,"func_info":[6,23],"func_l":10,"func_name1":3,"func_name2":3,"func_prototype_tag":10,"func_temp":16,"function":[1,5,6,7,13,17,18,19,20,22,24,25],"function_addr_expr":22,"function_declar":[3,6,8],"function_def_t":11,"function_defaulted_in_friend_decl":7,"function_definit":[3,6],"function_does_not_match_argu":7,"function_inelig":7,"function_lvalue_expr":22,"function_modifier_requires_virtual_funct":7,"function_modifiers_abstract_and_s":7,"function_nam":16,"function_prototype_instanti":[3,23],"function_qualifier_on_ctor_or_dtor":7,"function_qualifier_on_fin":7,"function_qualifier_on_new_or_delet":7,"function_qualifier_on_nonmemb":7,"function_qualifier_on_static_memb":7,"function_returning_abstract_class":7,"function_returning_array":7,"function_returning_funct":7,"function_returning_named_address_spac":7,"function_returning_shar":7,"function_rvalue_nod":22,"function_template_call_argument_deduct":9,"function_template_cannot_be_default":7,"function_template_declar":23,"function_template_named_main":7,"function_typ":16,"function_type_must_come_from_declar":7,"function_type_not_allow":7,"function_type_requir":7,"functionmultivers":16,"functiontraitsbitfield":17,"functor":7,"fundament":[1,3,6,9,10,11,14,15,17,21,22,23,24],"fundamental_type_from_system_typ":[6,22],"funni":11,"furthermor":[3,6,11,15,18,21,23],"futur":[7,10,17],"fuzzi":9,"fwrite":0,"fxp_add":9,"fxp_compar":9,"fxp_divid":9,"fxp_hash":9,"fxp_hex_string_to_fixed_point":[9,15],"fxp_init_valu":9,"fxp_multipli":9,"fxp_string_to_fixed_point":[9,15],"fxp_subtract":9,"fxp_to_str":9,"fxp_value_is_zero":9,"g":[0,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],"g1":[10,16,21],"g2":[16,21],"g3":16,"g__1asff":16,"gain":0,"gap":[3,11,14],"garbag":[9,11],"gate":17,"gather":3,"gc":[9,16],"gc_":16,"gcc":[0,1,2,7,10,14,15,16,18,24],"gcc89_inlin":10,"gcc_is_generated_code_target":1,"gcc_lvalue_cast_ignor":7,"gcc_minor_vers":10,"gcc_mode":14,"gcc_pragma_nothing_to_pop":7,"gcc_use_of_cast_as_lvalu":7,"gcc_version":10,"gcc_version_i":14,"gcc_version_str":10,"gcnew":[7,9,10,11,16],"gcnew_and_abstract":7,"gcnew_and_no_ctor":7,"gcnew_and_no_gcnew":7,"gcnew_bad_type_used_with_array_init":7,"gcnew_of_native_array":7,"gcnew_used_with_auto_syntax":7,"gcnew_used_with_placement_syntax":7,"gdb":24,"gear":1,"gen_attribut":18,"gen_block_stat":5,"gen_bound_funct":5,"gen_c_clang_vers":10,"gen_c_file_nam":10,"gen_c_gnu_vers":10,"gen_c_msvc_vers":10,"gen_class_definit":5,"gen_class_qualifi":5,"gen_cleanup_act":16,"gen_const":5,"gen_decl_nam":5,"gen_declar":5,"gen_declaration_using_typ":5,"gen_dynamic_init":5,"gen_enum_definit":5,"gen_expanded_raw_listing_output_for_curr_lin":15,"gen_expr":5,"gen_field_decl":5,"gen_for_stat":5,"gen_initi":5,"gen_initializer_const":5,"gen_instantiation_direct":5,"gen_macro":5,"gen_member_constant_decl":5,"gen_move_oper":10,"gen_nam":5,"gen_namespac":5,"gen_namespace_qualifi":5,"gen_new_delet":5,"gen_pp_line_info":15,"gen_pp_output_for_curr_lin":15,"gen_prop_event_or_op_synth_cal":5,"gen_raw_listing_output_for_curr_lin":15,"gen_rlisting_line_info":15,"gen_routine_decl":5,"gen_secondary_decl":5,"gen_simple_field_select":5,"gen_stat":5,"gen_switch_stat":5,"gen_temp_init":5,"gen_templ":5,"gen_try_block_stat":5,"gen_typ":5,"gen_type_decl":5,"gen_typedef_decl":5,"gen_unqualified_nam":5,"gen_using_declar":5,"gen_using_directive_or_declar":5,"gen_variable_decl":5,"general":[0,1,2,5,6,9,10,12,13,14,16,17,18,19,20,21,22,23,24,25,26],"generat":[1,6,7,9,11,13,14,15,16,17,18,19,20,21,22,24,25,26],"generate_eh_t":[8,16,19],"generate_portable_assembl":1,"generate_pp_output":15,"generate_precompiled_head":0,"generate_source_sequence_list":[5,11,21],"generate_source_source_sequence_list":22,"generate_special_funct":3,"generate_top_level_metadata_cod":6,"generate_trivial_accessor":3,"generated_default_constructor_used_in_field_initi":7,"generated_default_ctor_exception_spec_circular":7,"generated_exception_spec_override_incompat":7,"generated_preced":11,"generic":[0,1,3,6,7,10,11,14,18,21,22,24],"generic_cast_operand":9,"generic_class_cannot_be_custom_attribut":7,"generic_class_must_be_manag":7,"generic_in_templ":7,"generic_lambda_cannot_captur":7,"generic_param_cannot_have_default":7,"generic_param_if_generic_definition_argu":23,"generic_parameter_does_not_permit_vararg":7,"generic_parameter_requires_clrcal":7,"generic_selection_with_points_to":7,"generic_type_in_template_arg":7,"get":[0,1,3,5,7,9,10,11,14,16,17,19,21,23,24,25,26],"get_based_typ":22,"get_byt":17,"get_current_lambda":3,"get_definition_of_class":[6,15,21],"get_ifc_":17,"get_ifc_decl":17,"get_ifc_declar":17,"get_ifc_home_scop":17,"get_ifc_index":17,"get_ifc_local_index":17,"get_ifc_nam":17,"get_ifc_unit":17,"get_integer_size_and_align":9,"get_mangled_function_nam":23,"get_mangled_variable_nam":23,"get_modul":17,"get_module_head":17,"get_next_source_fil":0,"get_nondependent_call_info":9,"get_opnam":21,"get_pointer_offset":9,"get_property_function_miss":7,"get_property_or_event_accessor_symbol_head":[3,21],"get_return_object_on_allocation_failur":7,"get_storag":17,"get_token":[0,10,14,15,21],"get_token_from_cached_token_rescan_stack":15,"get_token_from_reusable_cache_stack":15,"get_top_level_type_qualifi":22,"get_type_qualifi":22,"get_var_remapping_for_inlin":16,"get_variable_initi":11,"getenumer":7,"gid":15,"gid_template_args_opt":15,"github":[1,3,16],"give":[0,1,3,4,5,9,10,11,13,14,15,16,17,21,24,25],"given":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"glanc":9,"glb_mod_fgmt_decl_must_come_first":7,"global":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,21,22,23,25,26],"global_module_source_conflict":7,"global_ns_has_no_actual_memb":7,"global_operator_new_or_delete_symbol":21,"global_qualifier_not_allow":7,"glvalu":[9,11],"glyph":15,"gnu":[0,1,3,7,11,13,14,18,20,21,24,26],"gnu_":3,"gnu_attr_on_template_redecl":7,"gnu_attr_on_template_redecl_but_original_kept":7,"gnu_attributes_en":18,"gnu_auto_type_with_secondary_declar":7,"gnu_auto_type_without_initi":7,"gnu_extensions_allow":[1,10,14],"gnu_extra_info":11,"gnu_function_multivers":11,"gnu_inlin":7,"gnu_inline_requires_inlin":7,"gnu_may_use_bit_pad":7,"gnu_mv_default_miss":7,"gnu_mv_only_one_arch":7,"gnu_restrict_is_nonstandard":7,"gnu_sentinel_attribute_requires_ellipsi":7,"gnu_sentinel_must_be_ellipsis_argu":7,"gnu_target_version_numb":1,"gnu_vers":[10,11,16,18,24],"gnu_version_i":14,"gnu_virtual_base_gap":7,"gnu_visibility_conflict":7,"go":[0,1,3,7,10,11,14,15,16,17,18,20,23,25],"go_into_insert":15,"goal":[0,9,10,13,14,15],"goe":[0,2,3,6,8,9,10,11,14,15,16,17,21,23],"gone":[6,15],"good":[1,3,7,8,9,10,14,24],"got":7,"goto":[7,8,11,14,16,20],"goto_stat":20,"gotten":10,"govern":[18,22],"gpp":0,"gpp_mode":14,"gpp_version_i":14,"grain":[10,14,24],"grammar":18,"grammat":3,"grant":11,"graph":[0,3,16],"graphic":10,"great":[11,14,21,23,24],"greater":[3,7,8,9,11,14,15,16,21],"greatest":[3,10,21],"greek":15,"grief":16,"gross":21,"group":[2,3,6,9,10,11,13,14,15,18,23,24],"grow":20,"gs_directory_of":0,"guarante":[2,10,11,15,16,17],"guard":[10,22],"guard_var":16,"guess":[0,14],"gui":10,"guid":[7,9,10,11,16,17,23],"guidanc":[10,18],"guidelin":9,"guiding_decl":[7,10],"guilti":4,"gx":18,"h":[0,2,3,4,5,6,8,9,10,11,12,14,15,16,17,18,20,21,22,23,24,25,26],"half":[10,11,22],"hall":10,"halt":[14,23],"hand":[0,3,7,9,11,14,15,16,18,21,23,25],"handl":[0,1,2,3,4,5,6,7,9,10,11,14,15,16,17,18,19,20,21,22,23,25],"handle_elided_copy_constructor":9,"handle_lvalue_constant_nod":5,"handle_member_in_standard_class":7,"handle_of_non_manag":7,"handle_operand":7,"handle_to_address_typ":7,"handle_to_array":7,"handle_to_cli_array_operand":7,"handle_to_enum":7,"handle_to_funct":7,"handle_to_standard_class_typ":7,"handle_to_unscoped_enum_typ":7,"handle_to_value_class":7,"handle_to_void":7,"handle_virtual_bases_in_complete_ctor_dtor":16,"handler":[1,7,10,11,16,20,21,22],"handler_declar":8,"handler_redeclares_paramet":7,"hang":[3,9],"happen":[0,3,6,9,10,16,21,23,24,25],"hard":[9,10,11,14,16],"harder":[11,16,21],"hardwar":9,"harmless":15,"has_assoc_vla_dimens":11,"has_associated_attribut":11,"has_associated_pragma":[11,18],"has_been_coalesc":15,"has_cpp_attrib_not_in_if":7,"has_embed_not_in_if":7,"has_ifc_":17,"has_ifc_decl":17,"has_ifc_home_scop":17,"has_include_next_in_primary_source_fil":7,"has_include_not_in_if":7,"has_matching_template_funct":23,"has_named_register_storage_class":11,"has_valu":17,"hash":[9,21,22,23],"hash_const":22,"hasn":[3,14,16],"have_access_across_path":21,"have_access_to_symbol":[3,21],"have_member_access_privileg":21,"have_proj_access_to_symbol":3,"have_protected_member_access_privileg":21,"haven":16,"hazi":2,"hdrstop":[0,10],"head":[0,11,21,22],"headach":5,"header":[1,2,3,4,6,7,9,13,14,15,16,20,22,23,24,25,26],"header_not_import":7,"header_path":10,"header_text":15,"header_unit":[10,24],"header_unit_fil":24,"header_util":14,"heap":[7,9,11],"heavili":[14,23],"held":[0,9,11,17],"hello":10,"help":[0,2,6,9,11,14,15,16,19,22,23,24,25,26],"helper":[0,1,3,7,10,16],"henc":[3,10,16,23,25],"hereaft":[10,23],"heurist":[3,10,16],"hewlett":19,"hex":7,"hex_fp_const":7,"hexadecim":[1,7,10,15],"hh":[10,16],"hi":16,"hidden":[0,5,7,9,11,16,21,22,24],"hidden_anonymous_union_field":7,"hidden_by_old_for_init":7,"hide":[7,9,10,16],"hide_by_sig_lookup_result":21,"hiding_attr_on_nonhiding_memb":7,"hiding_attr_on_unhidden_memb":7,"hiding_attr_requir":7,"hierarchi":[15,17,21],"high":[1,8,9,10,11,13,14,16,17,18],"higher":[9,10,11,14,16,17,23],"highest":[10,15],"highlight":[0,10,16,24],"hijack":15,"hint":[9,14,16,23],"histor":[14,16],"histori":[0,1],"hit":[16,23],"hoc":[10,14],"hold":[0,1,4,9,11,15,16,23,24],"holder":22,"home":17,"home_scop":17,"home_scope_idx":17,"honor":11,"hop":[9,16],"horizont":[10,15],"host":[1,7,9,10,11,13,14,15,17],"host_allocation_incr":10,"host_envir":[0,11,14,23],"host_util":14,"hour":1,"howev":[0,1,2,3,4,5,6,8,9,10,11,13,14,15,16,17,18,21,22,23,24,25,26],"hp":16,"hpp":10,"hpux":26,"ht":16,"html":16,"http":16,"https":[1,3,16],"human":[0,1,2,10,13,14],"hundr":2,"hybrid":15,"hyphen":[10,15],"hypothet":17,"i1":10,"i2":10,"i__1a":16,"ia":[1,3,10,12,19,26],"ia64":2,"ia64_abi":[1,16,19],"ia64_abi_use_guard_acquire_releas":16,"ia64_abi_use_variant_ptr_to_member_function_repr":16,"ic1_2i":16,"ick_continu":9,"id":[1,6,7,8,10,11,15,16,18,21,23],"id_already_declar":7,"id_can_only_appear_in_funct":7,"id_linkag":[6,23],"id_must_be_class_or_namespace_nam":7,"id_must_be_class_or_type_nam":7,"idea":[9,11,14,16],"ideal":[3,8],"ident":[0,1,3,5,7,8,9,10,11,15,16,17,22,23],"ident_directive_and_pragma":10,"identical_typ":22,"identif":[8,15],"identifi":[0,1,2,3,5,6,7,8,10,11,14,16,18,20,23,24,25,26],"identifier_not_keyword":7,"identifier_rang":11,"identifier_strings_allow_multibyte_char":[11,15],"identify_dir_keyword":15,"identify_source_fil":0,"ideograph":15,"idiom":[10,15,20],"idispos":[3,7],"idl":15,"idl_instantiation_context":21,"idl_is_static_decl":3,"idl_linkage_lookup":21,"idl_projection_symbol_allow":21,"idl_skip_class_scop":21,"idl_skip_curr_function_scop":21,"idl_tentative_type_lookup":21,"idn":23,"idx":17,"iec":[1,9,10,11,13],"iek_":11,"if_consteval_in_nonconstexpr_funct":7,"if_consteval_nonstandard":7,"if_consteval_requires_braced_dependent_stat":7,"if_constexpr_is_cpp17":7,"if_exists_not_allow":7,"if_exists_not_clos":7,"if_stat":20,"ifc":[7,10,14,17,24],"ifc_0_33_bsb_c":17,"ifc_0_33_bsb_cxx":17,"ifc_0_33_bsb_deprec":17,"ifc_0_33_bsb_extern":17,"ifc_0_33_bsb_initialized_in_class":17,"ifc_0_33_bsb_intern":17,"ifc_0_33_bsb_is_member_of_global_modul":17,"ifc_0_33_bsb_non_export":17,"ifc_0_33_bsb_vagu":17,"ifc_0_33_ds_decl_bitfield":17,"ifc_0_33_ds_decl_enumer":17,"ifc_0_33_ds_decl_field":17,"ifc_0_33_ds_decl_paramet":17,"ifc_0_33_ds_decl_scop":17,"ifc_0_33_ds_decl_vari":17,"ifc_0_33_ds_decl_vendor_extens":17,"ifc_0_41_ds_decl_bitfield":17,"ifc_0_41_ds_decl_enumer":17,"ifc_0_41_ds_decl_field":17,"ifc_0_41_ds_decl_paramet":17,"ifc_0_41_ds_decl_scop":17,"ifc_0_41_ds_decl_vari":17,"ifc_0_41_ds_decl_vendor_extens":17,"ifc_as_non":17,"ifc_as_priv":17,"ifc_as_protect":17,"ifc_as_publ":17,"ifc_bad_function_param_nam":7,"ifc_bad_identifi":7,"ifc_bsb_0_33_c":17,"ifc_bsb_0_33_cxx":17,"ifc_bsb_c":17,"ifc_bsb_cxx":17,"ifc_bsb_deprec":17,"ifc_bsb_extern":17,"ifc_bsb_initialized_in_class":17,"ifc_bsb_intern":17,"ifc_bsb_is_member_of_global_modul":17,"ifc_bsb_non_export":17,"ifc_bsb_vagu":17,"ifc_creation_failur":7,"ifc_definition_load_failur":7,"ifc_ds_":17,"ifc_ds_decl_alia":17,"ifc_ds_decl_barren":17,"ifc_ds_decl_bitfield":17,"ifc_ds_decl_concept":17,"ifc_ds_decl_constructor":17,"ifc_ds_decl_deduction_guid":17,"ifc_ds_decl_destructor":17,"ifc_ds_decl_enumer":17,"ifc_ds_decl_expans":17,"ifc_ds_decl_explicit_instanti":17,"ifc_ds_decl_explicit_speci":17,"ifc_ds_decl_field":17,"ifc_ds_decl_funct":17,"ifc_ds_decl_refer":17,"ifc_ds_decl_speci":17,"ifc_ds_decl_vari":17,"ifc_ds_decl_vendor_extens":17,"ifc_entity_ref_failur":7,"ifc_entity_ref_failure_info":7,"ifc_file_incompat":7,"ifc_ftb_constexpr":17,"ifc_ftb_constrain":17,"ifc_ftb_default":17,"ifc_ftb_delet":17,"ifc_ftb_explicit":17,"ifc_ftb_hidden_friend":17,"ifc_ftb_immedi":17,"ifc_ftb_inlin":17,"ifc_ftb_no_return":17,"ifc_ftb_non":17,"ifc_ftb_pure_virtu":17,"ifc_ftb_virtu":17,"ifc_function_template_parse_failur":7,"ifc_initializer_load_failur":7,"ifc_line_number_overflow":7,"ifc_map":[14,17],"ifc_map_funct":[14,17],"ifc_map_functions_acc":[14,17],"ifc_map_functions_dbg":[14,17],"ifc_map_functions_mut":14,"ifc_map_functions_v":[14,17],"ifc_missing_function_definit":7,"ifc_modul":[14,17],"ifc_modules_inst":[14,17],"ifc_modules_intern":[14,17],"ifc_modules_read":[14,17],"ifc_modules_spec":[14,17],"ifc_modules_templ":[14,17],"ifc_modules_writ":[14,17],"ifc_no_corresponding_calling_conv":7,"ifc_no_corresponding_oper":7,"ifc_partition_bad_entry_s":7,"ifc_partition_count":17,"ifc_partition_map":17,"ifc_partition_mismatch":7,"ifc_partition_missing_el":7,"ifc_pk_non":17,"ifc_requirement_failur":7,"ifc_requirement_failure_fill_in":7,"ifc_too_few_template_arg":7,"ifc_too_few_template_args_info":7,"ifc_too_many_template_arg":7,"ifc_too_many_template_args_info":7,"ifc_unexpected_null_scope_memb":7,"ifc_unsupported_token":7,"ifcconditionaldeleg":17,"ifcdirectdeleg":17,"ifcremotedeleg":17,"ifcreusableresult":17,"ifctestsortmatch":17,"ifctextoffsettonameindex":17,"ifdef":[4,15],"iff":16,"ifil":10,"ifn":23,"ifndef":[10,14,15],"ifunc":7,"ifunc_cant_be_alia":7,"ifunc_cant_be_weak":7,"ignor":[3,5,7,8,9,10,11,15,16,17,18,21,22,23,26],"ignore_harmless_trailing_com":15,"ignore_std":[7,10],"ignoring_attribute_on_anonymous_namespac":7,"ignoring_attribute_on_non_inline_namespac":7,"ii":[10,23],"ii_fil":10,"ik_long_long":[11,16],"ik_unsigned_long_long":[11,16],"il":[2,3,5,7,8,9,13,14,15,18,19,20,22,24,25],"il_alloc":[11,14,18,22],"il_alloc_init":11,"il_alloc_one_time_init":11,"il_def":[0,3,8,11,14,15,18,22,23],"il_display":[0,1,10,11,14],"il_entry_kind_nam":11,"il_entry_prefix_of":11,"il_fil":[0,14],"il_head":[0,2,11,15,16,22],"il_identical_typ":22,"il_low":25,"il_output":7,"il_read":[0,1,14],"il_scop":21,"il_should_be_written_to_fil":1,"il_to_str":[0,1,2,5,14],"il_walk":[0,1,11,14],"il_walk_flag":[0,16],"il_writ":[0,14],"ill":[3,26],"illeg":[3,10],"illustr":[0,3,10,24],"ilm_tentative_typ":15,"ilp64_will_narrow":7,"im":16,"imag":0,"imagin":0,"imaginari":[7,9,11,16],"imaginary_times_assign":7,"immedi":[0,1,3,4,5,6,7,9,10,11,15,16,18,21,23,24],"immut":15,"impact":[8,24],"imper":1,"impl_conv_between_c_and_cpp_function_ptrs_poss":10,"impl_conversion_poss":[9,22],"impl_converted_constant_expr_conversion_poss":9,"impl_deleted_move_candidate_ignor":7,"impl_handle_convers":22,"impl_narrowing_64_bit_int":7,"impl_pointer_convers":22,"impl_ptr_to_member_convers":22,"implement":[0,1,2,3,5,6,7,9,11,12,13,14,15,16,18,19,21,24,25,26],"implement_dispose_pattern_if_need":3,"implementation_key":7,"implementation_key_outside_mapping_region":7,"implementation_supports_multiple_thread":10,"implementor":26,"implements_must_precede_virtual_funct":7,"implements_requires_interfac":7,"impli":[3,7,9,10,11,14,16,18,22,23,24],"implic":11,"implicit":[0,2,5,6,7,9,11,14,15,16,20,21,22],"implicit_address_of_explicit_this_funct":7,"implicit_call_of_ambiguous_nam":7,"implicit_cast":[9,11],"implicit_co_return_with_no_return_void":7,"implicit_copy_this_capture_deprec":7,"implicit_el":7,"implicit_extern_c_type_convers":[7,10],"implicit_fixed_point_to_floating_point_convers":7,"implicit_func_decl":7,"implicit_includ":[7,10],"implicit_int_on_main":7,"implicit_noexcept":[7,10],"implicit_return_from_non_void_funct":7,"implicit_this_param_typ":3,"implicit_typenam":10,"implicit_using_std":10,"import":[0,1,3,5,6,7,8,9,10,11,14,17,20,24,25],"import_dir":10,"import_metadata":6,"import_metadata_fil":6,"import_name_not_allow":7,"import_skip":7,"impos":[3,9,15,16,17],"imposs":[10,16,18,21,23],"impract":16,"improp":[7,15,17],"improperly_terminated_macro_cal":7,"improv":[0,2,3,10,11,14,16,17,24,26],"in_potential_constant_constexpr_context":9,"in_pp_if_express":15,"in_preprocessing_direct":15,"in_range_for_integer_kind":9,"inaccess":[0,3,7,9,10,21],"inaccessible_base_class":7,"inaccessible_dtor_not_invok":7,"inaccessible_elided_cctor":7,"inaccessible_elided_dtor":7,"inaccessible_rvalue_dtor":7,"inaccessible_special_funct":7,"inacess":21,"inact":[6,7,25],"inactive_scope_lookup":21,"inadvis":1,"inappropri":18,"incident":23,"incl_dir_both_sys_and_nonsi":7,"incl_suffix":10,"inclass_initializer_fixup":3,"inclass_initializer_fixup_for_class":3,"inclin":16,"includ":[0,1,2,3,4,5,6,7,8,9,11,13,15,16,17,18,19,20,21,22,23,24,25,26],"include_alia":[7,10],"include_c":24,"include_c99":24,"include_comments_in_asm_func_bodi":[10,11],"include_directori":10,"include_in_context_output":0,"include_kind_mismatch":7,"include_next":[7,10],"include_next_in_primary_source_fil":7,"include_recurs":7,"include_unrecognized_pragmas_in_il":18,"include_whitespac":4,"inclus":[0,1,4,7,11,14,15,17],"incognito":10,"incom":16,"incompat":[0,2,7,10,19,25],"incompatible_assignment_operand":7,"incompatible_builtin_complex_typ":7,"incompatible_delegate_object":7,"incompatible_enum_base_typ":7,"incompatible_enum_kind":7,"incompatible_exception_spec":7,"incompatible_exception_specif":7,"incompatible_ifunc_resolver_typ":7,"incompatible_inline_specifier_on_specific_decl":7,"incompatible_linkage_specifi":7,"incompatible_operand":7,"incompatible_param":7,"incompatible_ptr_to_member_selection_operand":7,"incompatible_shuffle_mask":7,"incompatible_shuffle_source_operand":7,"incompatible_std_meta_value_of_typ":7,"incompatible_thread_loc":7,"incompatible_vectors_convers":7,"incomplet":[2,3,7,8,9,10,11,15,21,23],"incomplete_class_return_typ":7,"incomplete_class_typ":7,"incomplete_enum_bit_field_or_bad_opaque_enum":7,"incomplete_function_return_typ":7,"incomplete_return_typ":7,"incomplete_type_not_allow":7,"incomplete_var_typ":7,"incongru":23,"inconsist":[3,7,11,23],"inconsistent_align":7,"inconsistent_deduction_of_auto":7,"inconsistent_std_string_view":7,"inconsistent_tls_model_attr_arg":7,"incorpor":[1,6,14,15,16,21,23,24],"incorrect":[7,10,11,14,15,16],"incorrect_masked_typ":7,"incr":10,"incr_of_bool_deprec":7,"incr_of_bool_not_allow":7,"increas":[1,3,10,15],"increment":[6,7,9,10,11,14,15,16,20,23],"increment_field_offset":3,"incur":[10,15,16],"inde":[0,14],"indefinit":9,"indent":[2,4,5],"independ":[3,6,9,10,11,17,18,19,21,23],"indetermin":[7,10],"indeterminate_not_on_first_decl":7,"indeterminate_overloaded_funct":7,"index":[0,3,6,7,8,9,11,13,14,15,16,18,19,21],"indic":[0,1,2,3,6,7,8,9,10,11,14,15,16,18,19,20,21,22,23,24,25,26],"indicate_cleanup_state_in_unreachable_cod":16,"indirect":[3,5,6,7,8,10,11,14,15,16,17,21,22,23],"indirect_anon_union_design":7,"indirect_nonvirtual_base_class_not_allow":7,"indistinguish":16,"individu":[0,7,11,14,15,16,17,20,21,23,24],"industri":16,"ineffici":[14,15],"inelig":7,"ineligible_default_constructor":7,"ineligible_member_funct":7,"inequ":10,"inert":15,"inexact_fixed_convers":7,"inexact_fp_convers":7,"inexact_fxp_convers":7,"inexpens":1,"infer":[11,15],"infin":10,"infinit":[23,24,25],"influenc":23,"info":[6,7,9,10,23],"infom":23,"inform":[0,1,2,3,5,6,7,8,10,13,14,15,17,18,20,21,24,25,26],"infrastructur":9,"infrequ":[0,15],"ing":24,"inher":[9,14,17],"inherit":[3,7,10,11,16,21],"inheritance_kind_already_set":7,"inheritance_kind_ignored_on_enum":7,"inherited_member_not_allow":7,"inheriting_constructor_is_cpp11":7,"inheriting_ctor_ignored_for_copi":7,"inheriting_ctor_not_from_direct_bas":7,"inhibit":[6,10],"init":[3,7,9,10,16,20,22],"init_auto_instantiation_inform":23,"init_byte_buff":17,"init_cli_symbol":0,"init_conditional_flag_var":16,"init_decl_parse_st":6,"init_kind":11,"init_list_element_type_not_complete_object":7,"init_memory_region":0,"init_needing_temp_not_allow":7,"init_prior":7,"init_priority_reserv":7,"init_stmt_in_range_for_nonstandard":7,"init_text_map_position_track":15,"init_v":3,"initi":[1,2,5,7,10,14,15,17,18,19,20,21,22,24,26],"initialization_not_reach":7,"initializer_addresses_dllimport_vari":7,"initializer_differs_in_other_trans_unit":7,"initializer_in_param":7,"initializer_list":[7,9,12],"initializer_list_not_includ":7,"initializer_not_allowed_on_array_new":7,"initializer_not_const":7,"initializers_incompat":7,"initk_bind":[6,11],"initk_dynam":11,"initk_function_loc":11,"initk_stat":11,"initk_zero":[2,11],"initon":[3,7],"initonly_const_has_no_effect":7,"initonly_requires_managed_class":7,"initonly_static_data_member_not_initi":7,"initonly_volatile_not_allow":7,"inject":[3,7,10,21],"inlin":[0,1,2,4,6,7,11,14,17,21,25],"inline_and_nonfunct":7,"inline_function_cannot_be_instanti":7,"inline_function_wrapup":23,"inline_gnu_noinline_conflict":7,"inline_main":7,"inline_never_defin":7,"inline_new_or_delete_oper":7,"inline_nonstatic_data_mem":7,"inline_not_allow":7,"inline_on_alia":7,"inline_on_nested_namespac":7,"inline_qualifier_ignor":7,"inline_statement_limit":10,"inline_variables_nonstandard":7,"inner":[3,11,14,15,17,20,21,23],"innermost":[0,3,6,7,10,11,16,17,20,21,22],"innocu":10,"input":[1,3,5,6,7,9,11,14,16,17,23,25,26],"input_stack":[0,15],"ins":[0,14,26],"insert":[0,2,6,10,11,21,22,23,26],"insert_expr":16,"insert_if_stat":16,"insert_in_virtual_function_override_list":3,"insert_instantiation_src_seq_list":[21,22],"insert_src_seq_list":22,"insert_stat":16,"insert_string_into_token_stream":15,"insid":[0,2,3,6,7,9,10,11,14,15,16,20,21,22,23],"inspect":10,"instal":[1,10],"instanc":[1,3,4,6,7,9,10,11,15,16,17,20,21,22,23,24,25],"instance_requir":[16,23],"instance_sym":23,"instanti":[0,1,2,3,5,6,7,9,11,14,15,17,18,22,26],"instantiat":[23,25],"instantiate_class_templ":[3,23],"instantiate_ent":23,"instantiate_extern_inlin":[16,23],"instantiate_field_initializer_if_need":3,"instantiate_pragma":18,"instantiate_template_alia":23,"instantiate_template_class":23,"instantiate_template_funct":23,"instantiate_template_vari":23,"instantiation_by_implicit_inclus":10,"instantiation_context_lookup":21,"instantiation_dir":10,"instantiation_flags_in_template_info_fil":[16,23],"instantiation_mod":23,"instantiation_needed_bit_numb":[0,2],"instantiation_requested_and_speci":7,"instantiation_requested_no_definition_suppli":7,"instantiation_requir":23,"instantiation_wrapup":23,"instantiations_requir":23,"instantiations_to_process":25,"instead":[0,1,2,3,4,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"instruct":[15,16,17],"insuffici":[3,4,7,11],"insufficient_address_spac":7,"insufficient_enum_rang":7,"int":[0,2,3,4,5,6,7,8,9,10,11,14,15,16,18,21,22,23,24,26],"int16":7,"int32":[6,7,11,22],"int64":7,"int8":7,"int_constant_is_sign":9,"int_kind_is_sign":22,"int_max":1,"integ":[0,1,3,6,7,10,11,13,14,15,16,17,19,22,24],"integer_may_not_fit_in_fixed_point_result":7,"integer_overflow":7,"integer_overflow_class_intern":7,"integer_overflow_intern":7,"integer_pack_element_for_templ":7,"integer_pack_element_for_typ":7,"integer_sign_chang":7,"integer_to_fixed_convers":7,"integer_to_float_convers":7,"integer_too_larg":7,"integer_trunc":7,"integer_typ":22,"integer_type_supp":11,"integer_valu":9,"integer_value_repr_is_a_host_integ":[9,11],"integr":[1,2,3,7,9,10,11,13,16,22],"integral_operand":7,"intel":[3,16],"intend":[0,1,2,4,5,7,8,9,10,11,13,14,15,16,18,23,24,26],"intens":[15,24],"intent":[4,17],"inter":[15,18],"interact":[11,14,16,17,18],"intercept":[9,25],"interchang":[6,10,22],"interchangeable_typ":22,"interconnect":25,"interest":[3,4,9,10,11,14,15,16,17,20,21,22,24],"interfac":[0,1,3,6,7,8,9,11,13,14,15,16,18,19,21,22,24,26],"interface_cannot_be_loc":7,"interface_cannot_be_nested_class":7,"interface_cannot_have_ctor_or_dtor":7,"interface_cannot_have_data_memb":7,"interface_cannot_have_friend":7,"interface_cannot_have_member_gener":7,"interface_cannot_have_member_templ":7,"interface_cannot_have_oper":7,"interface_cannot_have_private_or_protect":7,"interface_cannot_have_static_memb":7,"interface_cannot_have_typedef":7,"interface_cannot_have_virtual_bas":7,"interface_must_derive_from_interfac":7,"interface_nonstatic_data_memb":7,"interface_not_impl":7,"interior":[6,7],"interior_ptr":[0,6,7,9,11,16],"intermedi":[1,2,3,5,6,7,9,10,13,14,15,16,17,20,21,22],"intermediari":[17,21],"intermingl":3,"intermix":[11,15,16,26],"internal":[0,1,3,6,7,8,9,10,11,13,15,16,17,23,24,25,26],"internal_error":[0,14],"internal_linkag":7,"internal_linkage_not_on_prior_declar":7,"internat":15,"interpol":7,"interpolated_id_is_not_identifi":7,"interpolated_operand_is_not_token_sequ":7,"interpret":[3,7,8,9,10,11,14,15,17],"interpret_constexpr_cal":9,"interpret_constexpr_ctor":9,"interpret_dynamic_init":9,"interpret_expr":9,"interpreter_message_error":7,"interpreter_message_remark":7,"interpreter_message_warn":7,"interrupt":10,"intersect":9,"interven":[11,15,21],"intervent":[10,18],"intimid":17,"intra":15,"intricaci":17,"intrins":[7,16],"intrinsic_name_releas":7,"intrinsic_requires_template_inst":7,"introduc":[3,4,6,7,9,10,11,15,16,17,18,23,25,26],"introduct":[1,3,8],"introductori":11,"invalid":[6,7,9,10,11,14,15,17,23,26],"invalid_access_specifi":7,"invalid_alignment_reducing_attr":7,"invalid_argument_to_attribut":7,"invalid_asm_qualifi":7,"invalid_assignment_operator_to_be_default":7,"invalid_attribute_loc":7,"invalid_attribute_target_for_ms_attr":7,"invalid_attribute_target_for_standalone_ms_attr":7,"invalid_base_for_ms_attribut":7,"invalid_bit_cast_typ":7,"invalid_builtin_fpclassify_arg":7,"invalid_case_rang":7,"invalid_char":7,"invalid_char_in_unicode_nam":7,"invalid_cleanup_routin":7,"invalid_co_return":7,"invalid_concept_id":7,"invalid_concept_redecl":7,"invalid_constev":7,"invalid_constexpr":7,"invalid_constexpr_bodi":7,"invalid_constexpr_memcmp":7,"invalid_constinit":7,"invalid_constraint":7,"invalid_constructor_to_be_default":7,"invalid_declar":7,"invalid_default_arg":7,"invalid_delegate_typ":7,"invalid_designator_kind":7,"invalid_destructor_nam":7,"invalid_empty_attribute_arg_list":7,"invalid_empty_fold_express":7,"invalid_empty_initializer_list":7,"invalid_entity_for_pending_constraint":7,"invalid_enumerator_valu":7,"invalid_error_numb":7,"invalid_error_tag":7,"invalid_event_accessor_decl":7,"invalid_event_handler_typ":7,"invalid_event_typ":7,"invalid_event_us":7,"invalid_explicit_exception_specif":7,"invalid_finalizer_nam":7,"invalid_float_parameter_for_literal_oper":7,"invalid_fold_expression_oper":7,"invalid_function_to_be_default":7,"invalid_gcnew_typ":7,"invalid_generic_arg":7,"invalid_generic_speci":7,"invalid_gnu_sentinel_argu":7,"invalid_gnu_sync_s":7,"invalid_identifier_start_ucn":7,"invalid_identifier_ucn":7,"invalid_idisposable_dispos":7,"invalid_ifc_partit":7,"invalid_ifc_position_backtrace_field":7,"invalid_ifc_position_backtrace_po":7,"invalid_ifc_sort_valu":7,"invalid_inheritance_kind_for_class":7,"invalid_init_stat":7,"invalid_instantiation_argu":7,"invalid_intaddr_address":7,"invalid_integer_parameter_for_literal_oper":7,"invalid_interface_class_bas":7,"invalid_link_scop":7,"invalid_literal_operator_id":7,"invalid_literal_typ":7,"invalid_local":7,"invalid_member_constant_typ":7,"invalid_microsoft_pragma_oper":7,"invalid_misaligned_ifc_posit":7,"invalid_mmap_address":7,"invalid_ms_attr_enum_valu":7,"invalid_ms_attr_nam":7,"invalid_ms_attr_uuid_valu":7,"invalid_ms_attribute_target":7,"invalid_name_after_templ":7,"invalid_neon_polyvector_element_typ":7,"invalid_neon_vector_element_typ":7,"invalid_neon_vector_s":7,"invalid_nested_class_redecl":7,"invalid_noexcept_specifier_operand":7,"invalid_nontype_template_argu":7,"invalid_object_fin":7,"invalid_operator_in_requires_claus":7,"invalid_overflowing_ifc_posit":7,"invalid_param_array_typ":7,"invalid_parameter_for_literal_operator_templ":7,"invalid_parameter_type_for_literal_oper":7,"invalid_pch_fil":7,"invalid_placeholder_for_defaulted_spaceship_return":7,"invalid_pointer_parameter_for_literal_oper":7,"invalid_pragma_conform_kind":7,"invalid_pragma_oper":7,"invalid_prev_decl_iter":7,"invalid_property_accessor_decl":7,"invalid_ref_class_bas":7,"invalid_ref_tracking_ref_combin":7,"invalid_reflection_equ":7,"invalid_reflection_for_intrins":7,"invalid_scalable_vector_element_typ":7,"invalid_scalable_vector_tuple_el":7,"invalid_scoped_enum_elabor":7,"invalid_second_parameter_type_for_literal_oper":7,"invalid_selective_overrider_declar":7,"invalid_spaceship_typ":7,"invalid_specific_ref_class_bas":7,"invalid_specifier_for_deduction_guid":7,"invalid_start_of_member_declar":7,"invalid_start_of_requires_clause_expr":7,"invalid_statement_in_constexpr_constructor":7,"invalid_statement_in_constexpr_funct":7,"invalid_std_comparison_typ":7,"invalid_std_comparison_valu":7,"invalid_std_initializer_list_parameter_list":7,"invalid_std_string_view_for_reflect":7,"invalid_storage_class_in_for_init":7,"invalid_string_literal_operator_templ":7,"invalid_struct_binding_specifi":7,"invalid_struct_binding_syntax":7,"invalid_struct_binding_typ":7,"invalid_symbolic_asm_operand_nam":7,"invalid_target_attribut":7,"invalid_template_parameter_for_literal_operator_templ":7,"invalid_token_after_templ":7,"invalid_tuple_s":7,"invalid_type_constraint":7,"invalid_type_for_builtin":7,"invalid_type_for_nul":7,"invalid_type_for_w64":7,"invalid_type_pointed_to_for_interior_ptr_or_pin_ptr":7,"invalid_typename_specifi":7,"invalid_ucn":7,"invalid_udl_valu":7,"invalid_unrepresentable_ifc_posit":7,"invalid_use_of_concept":7,"invalid_use_of_custom_ms_attr":7,"invalid_use_of_ms_attr":7,"invalid_use_of_standalone_custom_ms_attr":7,"invalid_use_of_standalone_ms_attr":7,"invalid_value_class_bas":7,"invalid_variable_main":7,"invalid_vector_element_typ":7,"invalid_vector_of_bool_oper":7,"invari":17,"invent":[9,10,16,19,23],"investig":[9,10],"invis":[5,17],"invoc":[0,1,2,3,6,7,8,10,11,14,16,21,23,24,25,26],"invocation_record":15,"invok":[0,1,3,6,7,8,10,11,12,14,15,16,17,21,23,24,26],"involv":[0,2,3,6,7,8,9,10,11,14,15,16,18,20,21,22,23,25],"io":[1,3,16],"iostream":[16,19],"ip":3,"iron":17,"irregular":21,"irrelev":[11,20],"irrespect":10,"is_":14,"is_accessible_base_class":21,"is_accessible_imm_base_class":21,"is_aggregate_or_union_typ":22,"is_alias_templ":23,"is_an_lvalu":9,"is_an_xvalu":9,"is_any_ptr_or_ref_typ":22,"is_any_reference_typ":22,"is_arithmetic_or_enum_typ":22,"is_array_typ":22,"is_at_least":17,"is_auto_param":23,"is_bit_field":11,"is_boxable_typ":[9,22],"is_char_array_typ":22,"is_character_typ":22,"is_class_memb":[15,21],"is_class_struct_union_typ":22,"is_class_symbol":21,"is_class_template_decl":23,"is_cli_array":[6,11],"is_cli_array_typ":[6,22],"is_cli_generic_constraint_typ":22,"is_cli_generic_param_typ":22,"is_cli_interface_typ":22,"is_cli_param_array":6,"is_cli_system_object_typ":22,"is_cli_system_string_typ":22,"is_cli_typeid":11,"is_complete_class_struct_union_typ":22,"is_const_qualified_typ":22,"is_constant_evaluated_in_constant_express":7,"is_constant_evaluated_in_consteval_context":7,"is_constant_evaluated_in_nonconstexpr_context":7,"is_constructor_decl":6,"is_constructor_symbol":21,"is_conversion_nam":21,"is_copy_constructor_symbol":21,"is_decl_not_expr":[6,9,20],"is_decl_start":14,"is_declar":23,"is_delegate_class":11,"is_delegate_typ":22,"is_destructor_nam":[15,21],"is_destructor_symbol":21,"is_enum_typeis_integral_or_enum_typ":22,"is_error":21,"is_error_typ":22,"is_far_typ":11,"is_file_scope_qualified_nam":[15,21],"is_fixed_point_typ":22,"is_floating_typ":22,"is_foo_bar":4,"is_for_init_block":20,"is_function_symbol":21,"is_function_typ":22,"is_gc_lvalue_expr":9,"is_gc_lvalue_operand":9,"is_generalized_identifer_start":15,"is_generalized_identifier_start":15,"is_generic_definit":[11,23],"is_global_qualified_nam":[15,21],"is_gnu_two_operand_question_mark":11,"is_guiding_decl":23,"is_handle_or_tracking_ref_typ":22,"is_handle_to_cli_array_typ":22,"is_handle_typ":22,"is_id_char":15,"is_id_char_no_mbc":15,"is_identifier_char":15,"is_illegal_abstract_class_typ":22,"is_immediate_class_typ":22,"is_immediate_error_typ":22,"is_implicitly_cast_integral_const":5,"is_incomplete_typ":22,"is_inlin":[11,23],"is_integr":22,"is_integral_typ":22,"is_interior_ptr_typ":22,"is_isolated_text":15,"is_last_elem":9,"is_literal_convertible_to_cli_str":9,"is_literal_typ":3,"is_lvalu":11,"is_lvalue_reference_typ":22,"is_managed_class_typ":22,"is_managed_nullptr_typ":22,"is_match_for_function_templ":23,"is_max_value_for_integer_kind":9,"is_member_const":3,"is_member_function_symbol":21,"is_more_speci":23,"is_namespace_alia":6,"is_nonclass_destructor":[15,21],"is_nonr":23,"is_nonreal_class":23,"is_nullptr_typ":22,"is_object_typ":22,"is_on_any_derivation_of":22,"is_operator_nam":[15,21],"is_or_contains_local_typ":22,"is_or_contains_specific_template_param":22,"is_or_contains_template_param":22,"is_or_contains_unnamed_or_local_typ":22,"is_pack_el":23,"is_parenthes":11,"is_pin_ptr_typ":22,"is_pointer_or_handle_typ":22,"is_pointer_typ":22,"is_polymorphic_class_typ":22,"is_prototype_instanti":23,"is_ptr_or_ref_typ":22,"is_ptr_to_member_typ":22,"is_qualified_nam":[15,21],"is_qualified_typ":22,"is_ref_class_typ":22,"is_reference_cast":11,"is_reference_typ":22,"is_repres":11,"is_restrict_qualified_typ":22,"is_rvalue_reference_cast":11,"is_rvalue_reference_typ":22,"is_rvalueable_nod":11,"is_scalar_typ":22,"is_secondary_trans_unit":25,"is_semivisible_nested_class":21,"is_signed_integral_typ":22,"is_signed_no_longer_a_keyword":7,"is_speci":23,"is_standard_class_typ":22,"is_super_qualifi":21,"is_tag_symbol":21,"is_target_specif":11,"is_template_alia":23,"is_template_class":[11,23],"is_template_class_typ":22,"is_template_funct":11,"is_template_id":21,"is_template_param_typ":22,"is_top_level_":22,"is_top_level_const_qualified_typ":22,"is_top_level_qualified_typ":22,"is_top_level_restrict_qualified_typ":22,"is_top_level_volatile_qualified_typ":22,"is_tracking_reference_typ":22,"is_two_arg":16,"is_type_constraint":23,"is_type_symbol":21,"is_udl_operator_nam":15,"is_union_typ":22,"is_useless_object_lifetim":[20,22],"is_using_decl":[3,21],"is_vacuous_destructor_refer":[15,21],"is_valid_generic_argumen":23,"is_value_class_typ":22,"is_variable_templ":11,"is_virtu":3,"is_virtual_cal":11,"is_vla":11,"is_void_typ":22,"is_volatile_qualified_typ":22,"is_xvalu":11,"ismemberofglobalmodul":17,"isn":[0,6,10,15,16,17,23],"iso":[1,5,9,10,11,13,15],"isol":[15,17,22],"issu":[1,2,3,6,8,9,11,13,14,15,16,17,18,20,21,22,23,24,25,26],"itanium":[1,3,16],"item":[0,3,10,23],"iter":[7,8,9,10,14,20,24,26],"ix":15,"ixx":24,"j":[2,5,6,9,10,11,14,16,23,24],"j1":10,"j16":10,"japanes":[1,10,15],"java":11,"jis":15,"jj":16,"jkl":10,"jmp_buf":19,"job":[16,18,20,24],"job_count":24,"johnson":10,"join":[6,16,17],"json":24,"judg":[10,11,16,21],"juli":10,"jump":[2,16],"just":[0,1,2,3,5,6,9,10,11,14,15,16,17,18,20,21,22,23,24],"justif":20,"justifi":[4,10],"k":[2,5,7,9,11,15,16],"kanji":15,"keep":[0,4,6,8,10,11,14,15,16,17,18,20,22,23,24],"keep_definition_in_il":0,"keep_in_il":0,"keep_restrict_in_signatur":10,"kept":[0,3,11,14,15,16,21,23,24,25],"kernighan":10,"key":[5,9,10,18,21,25],"keyword":[0,3,6,7,9,10,11,14,16,18,20,21,23,24],"keyword_drop":7,"keywordsort":17,"keywordsyntax":17,"kick":[3,9,11,23,25],"kill":[10,24],"kilobyt":15,"kind":[0,2,3,5,6,7,8,9,10,11,14,15,16,18,20,21,22,23,25,26],"kind_of_white_space_skip":15,"know":[0,6,8,9,10,11,15,16,17,21,23,24,25],"knowledg":[13,16],"known":[0,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"known_attr_appl_t":18,"known_attr_t":18,"known_comparison_with_nul":7,"known_not_to_be_a_literal_typ":3,"known_to_be_a_literal_typ":3,"l":[1,2,7,10,11,15,16,18,26],"l10_1234567890":16,"l212":16,"l3n12":16,"l4n1p5":16,"l_1_2":16,"l_3_0d0_3_1d1":16,"label":[0,2,4,7,8,10,14,15,16,18,20,21,22,23],"label_fill_in":0,"label_in_constexpr_funct":7,"label_operand_number_out_of_rang":7,"labeled_declar":7,"lack":[7,16,18],"laid":3,"lambda":[0,7,9,10,16,21],"lambda_cannot_refer_to_local_entity_her":7,"lambda_capture_for_vari":3,"lambda_capture_involves_variable_length_array":7,"lambda_capture_structured_bind":7,"lambda_captures_handle_or_tracking_ref":7,"lambda_captures_managed_class_typ":7,"lambda_in_class_type_with_typedef_nam":7,"lambda_in_noexcept_specifi":7,"lambda_mutable_and_stat":7,"lambda_not_allowed_her":7,"lambda_not_constant_expr":7,"lambda_without_parameters_nonstandard":7,"lambda_without_parameters_requires_claus":7,"lambdas_is_cpp11":7,"lang_feat":[8,14,23],"languag":[2,3,5,6,7,8,9,13,15,16,17,18,19,20,21,23,24,26],"larg":[0,1,3,5,6,7,9,10,11,14,15,16,17,20,24,25],"larger":[0,7,9,10,11,14,15,16,17],"largest":[10,17],"last":[0,3,7,9,10,11,14,15,16,21,22,23,24],"last_line_backslash":7,"last_line_incomplet":7,"last_matching_source_sequence_entri":22,"last_src_seq_sublist":11,"late":[7,10],"late_tiebreak":10,"later":[0,1,3,5,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25],"latest":[7,10,11,15,16],"latest_initi":16,"latex":26,"latin":[1,7,15],"latitud":11,"latter":[0,1,3,5,6,7,8,9,10,11,13,15,16,17,18,20,21,22,23,25],"lay":[3,14],"layer":9,"layout":[1,7,10,14,16,22],"lazi":21,"lazili":17,"lazy_initialization_uses_weak_refer":16,"lc_all":24,"lc_numer":7,"ld":26,"le_end_of_insert":15,"le_end_of_lin":15,"le_end_of_token":15,"le_escap":15,"le_inert_macro":15,"le_max_value_for_integer_kind":9,"le_newlin":15,"le_nul":15,"lead":[7,10,14,15,16,17,18,21,25,26],"leading_character_ignored_in_char_liter":7,"leaf":[6,9,11],"lean":23,"learn":11,"least":[0,3,5,6,7,8,9,10,11,14,15,16,17,18,21,23],"leav":[2,8,9,10,11,14,15,16,21],"leave_insert":15,"leave_must_be_in_tri":7,"leck_catch_epilogu":16,"leck_caught_object_address":16,"leck_cleanup_st":16,"leck_exception_caught":16,"leck_exception_start":16,"leck_function_epilogu":16,"leck_function_prologu":16,"leck_internal_tri":16,"leck_thrown_object_address":16,"leck_try_epilogu":16,"leck_unreachable_cleanup_st":16,"led":[10,11,15],"left":[0,1,3,4,6,7,9,10,11,14,15,16,18,23],"legaci":[1,10],"legacy_target_configuation_nam":1,"legal":[3,9,10,11,14,21],"legitim":9,"len_of_curr_token":15,"length":[0,1,2,4,6,7,8,10,11,14,15,16,19,21,23],"lengthi":15,"lenient":17,"less":[0,3,6,7,9,10,11,14,15,16,18,20,21,23,24,25],"lessen":14,"let":[11,14,15],"letter":[0,4,7,10,16],"level":[0,2,3,5,6,7,8,10,11,13,14,15,16,17,18,20,21,23,25,26],"levels_up":7,"leverag":17,"lexic":[0,3,11,14,18,21,22,23],"lexical_init":0,"lexical_one_time_init":[0,15],"lexical_trans_unit_init":0,"lfile":10,"li":16,"li6_mil":16,"lib":[0,1,10],"lib_":1,"lib_src":[1,19],"libari":10,"libc":1,"librari":[0,2,6,7,9,11,12,14,15,16,23,24,26],"licens":9,"lie":[9,14],"life":18,"lifetim":[7,8,9,10,17,20],"lifo":15,"light":15,"like":[0,1,2,3,4,5,6,7,9,10,11,12,14,15,17,18,19,20,21,22,23,24,25,26],"likelihood":14,"likely_unlikely_conflict":7,"likewis":[0,3,6,9,10,11,14,16,20,23,25],"limit":[0,1,2,3,6,7,9,10,11,14,15,16,18,20,21,23,26],"line":[1,2,5,6,7,8,9,11,13,14,16,17,21,22,23,24,25,26],"line_start_source_line_modif":15,"linear":15,"link":[0,1,2,3,6,7,8,9,10,11,14,15,16,19,20,21,22,23,24,25,26],"link_scope_relax":7,"link_scope_requires_external_linkag":7,"link_symbol_into_symbol_t":21,"linkag":[2,7,10,16,21,22,23,25,26],"linkage_conflict":7,"linkage_main":7,"linkage_specif":6,"linkage_specifier_not_allow":7,"linker":[1,10,15,16,21,23,26],"linker_opt":24,"lint":[10,14,15,18],"lint_notreached_flag":20,"linux":1,"list":[0,1,2,4,6,7,8,10,13,14,16,17,18,19,20,23,24,25,26],"list_included_fil":15,"list_init_of_incomplet":7,"list_initializer_nonstandard_in_current_mod":7,"list_macro":10,"list_makefile_depend":15,"lit":9,"lit_suffix_no_underscor":7,"liter":[0,1,2,3,6,7,9,10,11,14,16,18,22],"literal_const_has_no_effect":7,"literal_fields_disallowed_in_cppcx_mod":7,"literal_operator_not_found":7,"literal_requires_managed_class":7,"literal_type_convertible_to_cli_str":9,"literal_without_initi":7,"littl":[0,3,5,9,10,11,14,15,17,21,23],"ll":[10,16],"lld":10,"lm":16,"lm0_l11_0":16,"lm0_l2n1_1j":16,"ln":24,"lo":15,"load":[0,6,7,9,10,16,17,21,23],"loader":16,"local":[0,1,2,3,5,6,7,8,9,10,11,14,15,17,19,20,21,22,23,26],"local_class_friend_requires_prior_decl":7,"local_class_function_def_miss":7,"local_class_in_managed_member_funct":7,"local_cli_managed_class_typ":7,"local_entities_should_be_promot":16,"local_function_attribute_ignor":7,"local_index":17,"local_lambda_in_managed_member_funct":7,"local_named_register_initializer_not_allow":7,"local_opt":9,"local_pragma_pack":7,"local_static_variable_init":11,"local_type_in_funct":7,"local_type_in_nonlocal_var":7,"local_type_in_template_arg":7,"local_type_used_in_except":7,"local_variable_hidden":7,"locale_to_set_when_multibyte_chars_en":[1,15],"locat":[1,3,6,7,8,9,10,11,14,15,17,18,20,22,23,24,26],"locator_for_curr_id":[9,15,21],"lock":15,"locus":[10,17],"log":24,"logic":[1,4,9,11,14,17,21,23,24],"logical_column_offset":15,"lone_flexible_array_memb":7,"long":[0,2,4,5,7,9,10,11,14,15,16,17,20,22,23],"long_lifetime_temp":[10,11],"long_long":10,"long_long_allow":[10,11],"long_max":[0,1,10],"long_min":1,"long_preserving_rul":10,"long_vari":4,"longer":[0,7,9,10,11,15,16,17,18,20,21,22,23,26],"longest":4,"longjmp":8,"look":[0,1,3,6,8,9,10,11,14,16,17,18,20,23,24,25,26],"look_up_conversion_template_inst":21,"lookahead":[3,9,14,18],"lookup":[3,6,9,11,14,15,23,25],"lookup_in_namespac":21,"loop":[0,3,6,7,8,9,10,11,14,15,16,20,21,23,24],"loop_not_reach":7,"loop_token":[14,15],"loos":[6,9,11],"lose":0,"lossy_convers":7,"lossy_conversion_warn":10,"lost":[10,11,16],"lot":[0,4,6,9,10,11,15,16,17,21,23,24],"low":[0,5,7,10,11,14,15,16,17,21],"lower":[0,1,2,3,4,5,8,9,10,11,13,14,17,19,21,22,23,24,25],"lower_array_delet":16,"lower_array_new":16,"lower_bool_cast":16,"lower_bool_incr":16,"lower_c99":[14,16],"lower_c99_complex_cast":16,"lower_c99_fixed_point_cast":16,"lower_c99_fixed_point_const":16,"lower_c99_fixed_point_incr_decr":16,"lower_c99_fixed_point_oper":16,"lower_c99_fixed_point_typ":16,"lower_c99_nonreal_float_typ":16,"lower_c99_oper":16,"lower_c99_stmk_init":16,"lower_c99_temp_init":16,"lower_cal":16,"lower_ck_dynamic_init":16,"lower_class_rvalue_adjust":11,"lower_complex":[11,16],"lower_condit":16,"lower_constructor_cod":16,"lower_ctor_init":16,"lower_delet":16,"lower_designated_initi":[11,16],"lower_destructor_cod":16,"lower_destructor_dynamic_init":16,"lower_dtor_init":16,"lower_dynamic_init":16,"lower_dynamic_init_aggregate_const":16,"lower_eh":[8,14,16],"lower_expr_ful":16,"lower_extern_inlin":16,"lower_file_scope_dynamic_init":16,"lower_fixed_point":16,"lower_hdr":14,"lower_ifunc":16,"lower_ifunc_expr":16,"lower_ifunc_routin":16,"lower_il":[14,16,23],"lower_init":[14,16],"lower_lvalue_returning_oper":16,"lower_mv_routin":16,"lower_nam":[14,16],"lower_new":16,"lower_orphaned_entri":16,"lower_pm_cal":16,"lower_pm_field":16,"lower_pm_related_class_cast":16,"lower_ptr_to_member_const":16,"lower_related_class_cast":16,"lower_scop":16,"lower_thread_local_vari":16,"lower_throw":16,"lower_try_block":16,"lower_typ":16,"lower_variable_length_array":[11,16,19],"lower_virtual_function_cal":16,"lower_virtual_function_ptr":16,"lower_vla_dimens":16,"lower_vla_typ":16,"lowered_mv_routin":16,"lowering_normalizes_boolean_controlling_express":16,"lowest":[15,26],"lp":24,"lparen":4,"lparen_after_funct":7,"lstd":26,"ltd":16,"lvalu":[2,5,7,9,10,22],"lvalue_rvalue_test":11,"m":[2,3,10,11,16,18,24,26],"m1":16,"m16":16,"m2":16,"m4":16,"m8":16,"m_":[2,5],"m_write_ch":[2,5],"m_write_spac":5,"m_write_str":2,"m_write_tok_ch":[2,5],"m_write_tok_str":[2,5],"ma":15,"machin":[0,9,10,11,14,15,16,26],"machineri":6,"maco":1,"macosx":[1,26],"macosx64":26,"macro":[2,3,4,6,7,9,12,14,16,17,18,19,20,21,22,23,25],"macro_buff":15,"macro_context":[11,15],"macro_in_pp_direct":7,"macro_invoc":[7,15],"macro_invocation_record_block":15,"macro_invocation_tree_in_il":[1,10,11,14,15],"macro_invocations_per_block":11,"macro_is_en":4,"macro_line_loc_to_source_po":15,"macro_nam":0,"macro_not_udl_suffix":7,"macro_positions_in_diagnost":10,"macro_recurs":7,"macro_text_map":15,"macro_valu":0,"made":[0,1,2,3,5,6,7,8,9,10,11,12,14,15,16,17,18,20,21,23,24],"magnitud":[9,25],"main":[0,1,2,3,5,6,7,8,9,10,11,13,14,15,18,21,22,23,25,26],"main_coroutin":7,"main_first_param_not_int":7,"main_second_param_wrong_typ":7,"main_wrong_num_param":7,"maintain":[0,1,2,5,6,8,9,10,11,14,15,17,20,21,22,23,25],"maintain_class_member_list":11,"maintain_needed_flag":[0,10,11],"mainten":[10,14,16,24],"major":[9,10,11,14,15,22,23],"make":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"make_array_table_entri":16,"make_attr_unrecogn":18,"make_boxed_enum_typ":6,"make_canonical_identifi":15,"make_cli_metadata_fil":6,"make_closure_class":3,"make_code_to_invoke_file_scope_init_routin":16,"make_constant_operand":9,"make_construction_vtbl":16,"make_ctor_implied_arg_list":16,"make_default_assignment_bodi":3,"make_default_constructor_bodi":3,"make_default_destructor_bodi":3,"make_dtor_implied_arg_list":16,"make_error_operand":9,"make_expression_operand":9,"make_field_operand":9,"make_front_end_cal":[0,1,14],"make_function_cal":9,"make_function_designator_operand":9,"make_g":1,"make_glvalue_expression_operand":9,"make_il_template_entri":23,"make_indefinite_function_operand":9,"make_initializer_list_object":9,"make_instantiation_info_var":16,"make_integer_constant_operand":9,"make_integer_value_mask":9,"make_internal_try_expr":16,"make_locator_for_symbol":21,"make_lvalue_reusable_copi":16,"make_lvalue_variable_operand":9,"make_namespace_projection_symbol":21,"make_node_from_operand":9,"make_null_thread_local_init_routine_for_vari":16,"make_operator_nod":[11,22],"make_opname_loc":21,"make_placement_array_new_cal":16,"make_pointer_typ":[6,22],"make_predef_macro_t":1,"make_predefined_macro_fil":0,"make_projection_symbol":21,"make_ptr_to_member_constant_operand":9,"make_qualified_typ":22,"make_reference_typ":[6,22],"make_region_table_entri":16,"make_rescan_operand":9,"make_reusable_copi":16,"make_rvalue_reference_typ":[6,22],"make_selection_for_captured_vari":9,"make_source_sequence_secondary_decl":22,"make_string_constant_operand":9,"make_subobject_class_typ":16,"make_sym_for_ptr_to_member_operand":9,"make_symbol_for_cli_array":6,"make_symbol_for_cli_interior_ptr":6,"make_symbol_for_cli_pin_ptr":6,"make_symbol_for_namespace_c":0,"make_template_class_sym":23,"make_template_class_symbol":21,"make_template_funct":23,"make_template_str":23,"make_text_not_token":18,"make_this_pointer_operand":9,"make_type_conversion_loc":21,"make_unnamed_tag_symbol":[3,21],"make_unqualified_typ":22,"make_using_decl":[3,6],"make_using_direct":6,"make_var_for_virtual_function_t":16,"make_vars_for_virtual_function_t":16,"make_vec_delete_cal":16,"make_win_predef_macro_t":1,"make_zero_of_proper_typ":22,"makefil":[7,15],"maker":26,"malform":[7,15],"malformed_universal_charact":7,"malici":10,"malloc":[0,7,8,9,14,22],"manag":[6,7,9,10,14,15,17,20,25,26],"managed_base_for_standard_class":7,"managed_class_cannot_have_friend":7,"managed_class_type_cannot_have_private_or_protected_bas":7,"managed_member_exception_spec":7,"managed_member_function_cannot_have_ellipsis_paramet":7,"managed_nullptr_not_allow":7,"managed_object_not_caught_by_handl":7,"managed_object_not_thrown_by_handl":7,"mandat":[3,10,21,23],"mangl":[2,7,10,11,14,23,25,26],"mangle_function_nam":16,"mangle_variable_nam":16,"mangle_wrapper_nam":16,"mangled_encoding_for_express":16,"mangled_encoding_for_typ":16,"mangled_id_object_nam":16,"mangled_name_too_long":7,"mangled_operator_nam":16,"mangled_type_name_ful":16,"mangled_typeinfo_nam":16,"mangling_for_requir":7,"mani":[0,1,3,4,6,7,9,10,11,14,15,16,18,19,21,22,23,24,25],"manifest":14,"manipul":[9,11,14,15,22,25],"manner":[1,3,10,15,16,26],"mantissa":7,"manual":[1,14,15,23,24,26],"map":[0,3,6,7,10,14,15,16,21,22,23,24,25],"mappabl":0,"march":8,"margin":[0,2,4],"mark":[0,1,2,3,5,7,9,10,11,15,16,18,21,22,23,24,25,26],"mark_as_need":0,"mark_declar":21,"mark_defin":21,"mark_secondary_trans_unit_il_entities_used_from_primary_as_need":25,"mark_to_keep_in_il":0,"mark_variable_value_set":21,"marker":[0,9,10,11,15,25,26],"markup":26,"mask":[7,8,9,11,15,16,17],"masked_by_default_handl":7,"masked_by_handl":7,"massag":15,"master":23,"match":[0,1,2,3,5,6,7,8,9,10,11,15,16,17,18,21,22,23,24,25],"match_limit_for_symbolic_asm_operand":7,"match_regex":24,"matches_partial_speci":23,"matches_template_typ":[9,23],"matching_lbrac":7,"matching_template_funct":[6,9,23],"math":10,"matter":[0,1,3,9,10,23,24],"max":[3,16,24],"max_cost_constexpr_cal":[9,10],"max_depth_constexpr_cal":[9,10],"max_fail_count":24,"max_include_files_open_at_onc":15,"max_output_line_s":2,"max_pending_instanti":23,"max_prototype_length":15,"maxim":4,"maximum":[0,2,3,4,7,10,11,17,18,24],"may":[0,1,2,3,4,5,6,7,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"may_bind_to_decl":18,"may_bind_to_stat":18,"mayb":[16,23],"mbc_length":15,"mbc_to_wide_char":15,"mblen":[1,15],"mbtowc":15,"mdefn_get_token":15,"mean":[0,2,3,5,6,7,8,9,10,11,14,15,16,17,18,19,20,21,23,24,25],"meaning":[0,10,11,18],"meaningless":[7,23],"meant":[1,6,18,26],"measur":[9,10],"mechan":[0,1,3,5,6,10,11,15,16,17,18,19,21,22,25,26],"medium":14,"meet":[9,10,11,15,18,21],"megabyt":[10,15],"mem":[7,9,10,11,23],"mem_attrib_ignor":7,"mem_attrib_incompat":7,"mem_attrib_may_not_precede_nested_declar":7,"mem_manag":[0,1,14],"mem_tabl":14,"member":[0,2,5,6,7,9,10,14,15,17,18,22,25],"member_access_requires_point":7,"member_already_initi":7,"member_cannot_have_internal_linkag":7,"member_check_ambiguity_and_verify_access":21,"member_constant_not_const":7,"member_declar":11,"member_function_call_on_initonly_field":7,"member_function_modifier_on_static_memb":7,"member_function_modifier_on_templ":7,"member_function_of_class_type_with_typedef_nam":7,"member_function_redecl_outside_class":7,"member_function_redecl_sym":[3,23],"member_function_redeclar":7,"member_name_reserved_by_cli_oper":7,"member_name_reserved_by_properti":7,"member_partial_spec_not_in_namespac":7,"member_ref_requires_object":7,"member_special_after_class_definit":7,"member_type_of_class_type_with_typedef_nam":7,"member_using_declar":[3,6],"member_using_must_be_visible_in_direct_bas":7,"memberwis":3,"memcpi":[1,2,7,14,17],"memmov":7,"memoiz":17,"memori":[1,3,5,6,7,8,9,10,13,14,15,16,18,21,22],"memory_mismatch":7,"memset":2,"mention":[0,1,3,9,11,14,15,16,18,21,23],"mere":[0,5,11,17],"merg":[0,3,5,11,15,21,25],"merge_function_into_lookup_set":21,"merit":0,"messag":[0,1,2,11,13,14,15,18,23,24,26],"messi":[11,16],"met":[9,10],"meta":7,"metadata":[0,1,7,10,14,15,23],"metafunct":7,"metaphor":17,"metaprogram":10,"method":[7,9,10,11,15,16,21,23,26],"meticul":24,"mf":10,"mft":24,"microsoft":[0,1,2,5,7,9,13,14,15,16,17,18,20],"microsoft_16":10,"microsoft_bug":10,"microsoft_build_numb":10,"microsoft_extensions_allow":[1,10,11,14,22],"microsoft_inline_not_allowed_her":7,"microsoft_mod":[14,16],"microsoft_parenthesized_memb":7,"microsoft_ptr_sign_extens":7,"microsoft_ptr_signedness_conflict":7,"microsoft_ptr_signedness_must_follow_star":7,"microsoft_ptr_signedness_on_ptr_to_memb":7,"microsoft_ptr_width_conflict":7,"microsoft_ptr_width_must_follow_star":7,"microsoft_vers":[7,10,20],"microsoft_version_doesnt_support_cpp14_mod":7,"microsoft_version_doesnt_support_cpp17_mod":7,"microsoft_version_doesnt_support_cpp20_mod":7,"microsoft_version_doesnt_support_cpp23_mod":7,"microsoft_version_doesnt_support_cpplatest_mod":7,"mid":[2,23],"middl":[6,11,14,15,16,18,26],"midst":[6,23],"might":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,17,19,21,22,23,24,25,26],"milder":10,"million":9,"mimic":10,"min":[10,16],"mind":[1,10,11,16,18],"mine":[9,24],"mingw":1,"minim":[1,10,11,13,14,16,17],"minimal_inlin":[1,10,11,16],"minimum":[7,10,16],"minor":[0,1,2,9,10,11,16,18,25],"minus":[15,16,23],"minut":1,"mirp":11,"mis":10,"misalign":[7,17],"misc":1,"miscellan":14,"misconfigur":7,"misdiagnos":24,"misinterpret":10,"mismatch":[0,7,17,23],"mismatched_function_for_deleg":7,"mismatched_shared_block_s":7,"misnom":3,"mispars":15,"miss":[0,1,2,7,10,11,14,15,24],"missing_access_specifi":7,"missing_add_or_remove_accessor":7,"missing_attr_namespac":7,"missing_attribute_argu":7,"missing_attribute_in_other_translation_unit":7,"missing_base_class_or_member_nam":7,"missing_bind":7,"missing_class_definit":7,"missing_const_assignment_oper":7,"missing_const_copy_constructor":7,"missing_constinit":7,"missing_constraint_lett":7,"missing_decl_specifi":7,"missing_default_constructor_on_const":7,"missing_default_constructor_on_unnamed_const":7,"missing_delegate_object":7,"missing_endif":7,"missing_exception_declar":7,"missing_fin":7,"missing_floating_point_typ":7,"missing_get_and_set_accessor":7,"missing_gnu_inline_attr_on_redeclar":7,"missing_gnu_srcloc_typ":7,"missing_handl":7,"missing_header_unit_map":7,"missing_implements_list":7,"missing_incr_on_for_each_typ":7,"missing_incr_on_range_based_for_typ":7,"missing_indirect_on_for_each_typ":7,"missing_indirect_on_range_based_for_typ":7,"missing_initi":7,"missing_initializer_list":7,"missing_initializer_list_ctor":7,"missing_initializer_on_const":7,"missing_initializer_on_field":7,"missing_initializer_on_fields_with_constexpr_ctor":7,"missing_initializer_on_refer":7,"missing_initializer_on_unnamed_const":7,"missing_label_operand_numb":7,"missing_lambda_bodi":7,"missing_named_register_storage_class":7,"missing_namespace_nam":7,"missing_notequal_on_for_each_typ":7,"missing_notequal_on_range_based_for_typ":7,"missing_override_attr_in_base_check_class":7,"missing_pp_if":7,"missing_raw_string_delim_lparen":7,"missing_raw_string_delimit":7,"missing_std_tuple_el":7,"missing_std_tuple_element_inst":7,"missing_target_attribut":7,"missing_template_arg_list":7,"missing_template_param":7,"missing_template_param_list":7,"missing_trailing_return_typ":7,"missing_type_specifi":7,"missing_typedef_nam":7,"missing_typenam":7,"missing_va_opt_paren":7,"mission":16,"mistaken":1,"mitig":17,"mix":[4,6,7,9,10,11,16,17,21,24,25],"mixed_enum_typ":7,"mixed_enum_type_anachron":7,"mixed_string_concaten":7,"mixed_vector_scalar_oper":7,"mk_errinfo":[0,1,14],"mm":[10,16],"mmap":[7,10],"mmap_address":10,"mme":16,"mml":26,"mmm":10,"mn":16,"mnemon":10,"mod":17,"mod_by_zero":7,"mode":[0,2,6,7,8,9,11,14,15,16,17,18,19,20,26],"mode_incompatible_with_typ":7,"model":[9,10,11,19,23],"modern":[1,3,10,11,16],"modest":2,"modif":[0,1,5,9,10,13,14,16,18,24,25],"modifi":[0,1,2,3,5,6,7,9,10,11,14,15,16,18,21,23,25,26],"modification_of_initonly_field":7,"modification_of_static_initonly_field":7,"modified_auto_typ":7,"modified_class_template_placehold":7,"modified_decltype_auto_typ":7,"modified_within_try_block":16,"modifier_not_allowed_on_destructor":7,"modifier_not_allowed_on_fin":7,"modifying_lvalu":9,"modul":[2,7,14,16,21,23,24],"module_already_import":7,"module_cannot_depend_on_itself":7,"module_decl_only_after_glb_mod":7,"module_directive_in_if":7,"module_directive_in_macro":7,"module_fil":[10,24],"module_file_contains_unsupported_construct":7,"module_file_mismatch":7,"module_file_not_found":7,"module_id":16,"module_id_ptr":25,"module_import_conflict":7,"module_import_diagnost":10,"module_init":10,"module_interfac":[10,24],"module_internal_partit":[10,24],"module_nam":10,"module_name_not_allow":7,"module_read_error":7,"module_refer":17,"module_req_primary_nam":7,"module_unit_export_expect":7,"module_unit_export_unexpect":7,"module_use_in_multi_tu_mod":7,"module_use_with_export_templ":7,"modulerefer":17,"modules_directori":10,"modules_not_en":7,"modulo":24,"moment":[10,14,15,16,18,23],"monoton":2,"moot":3,"more_than_one_captur":7,"more_than_one_fgmt_decl":7,"more_than_one_module_decl":7,"moreov":[3,8,10,11,15,18,21],"mostly":[0,1,3,6,9,11,14,20,23,25],"move":[1,3,4,6,7,10,11,14,15,16,17,21,22,23,24,25],"move_ctor_or_assign_copy_of_lvalu":7,"move_to_end_of_types_list":3,"movenext":7,"ms":[0,1],"ms_attr_not_allow":7,"ms_attrib":14,"ms_attribut":11,"ms_await":10,"ms_await_strict":10,"ms_c":[7,10],"ms_c11":10,"ms_c17":10,"ms_c23":10,"ms_compat":10,"ms_cplusplus_std_valu":10,"ms_declspec_attributes_en":18,"ms_extens":10,"ms_header_unit":10,"ms_header_unit_angl":10,"ms_header_unit_quot":10,"ms_ifc_unavail":7,"ms_metadata":[1,6,14],"ms_metadata_init_fail":7,"ms_mod_file_map":10,"ms_permiss":10,"ms_rvalue_cast":10,"ms_std_preprocessor":10,"ms_stdc":10,"ms_strict_ternari":10,"ms_translate_includ":10,"ms_version_i":14,"msc_version_i":14,"mscore":1,"mscorlib":[0,1,6,10,14,15,21],"mscorlib_file_nam":10,"mscpp_version_i":14,"msg":10,"msinfo":1,"msvc":[9,11,24],"msvc_is_generated_code_target":1,"msvc_target_vers":10,"msvc_target_version_numb":1,"much":[1,3,6,9,10,11,14,15,16,17,18,20,21,23,24,25],"mult_storage_class":7,"multi":[8,10,15,16,23],"multi_char_liter":7,"multibyt":[1,7,10,11,14],"multibyte_char":10,"multibyte_chars_in_source_support":[1,11,15],"multicastdeleg":3,"multichar_ud_lit":7,"multicharact":7,"multidimension":[3,7,22],"multipl":[0,1,4,6,7,8,9,10,11,14,15,16,17,18,21,23,24],"multiple_attr_namespac":7,"multiple_block_s":7,"multiple_class_constraint":7,"multiple_constraint_claus":7,"multiple_declspec_align":7,"multiple_explicit_instanti":7,"multiple_header_map_match":7,"multiple_inheritance_in_embedded_cplusplus":7,"multiple_link_scope_specifi":7,"multiple_module_match":7,"multiple_named_address_spac":7,"multiple_overrid":7,"multiple_structured_binding_pack":7,"multiple_template_decls_not_allow":7,"multiple_thread_compil":10,"multiple_thread_local_storage_specifi":7,"multiple_union_design":7,"multiple_union_field_initi":7,"multiple_union_field_initializers_empti":7,"multiple_visibility_specifi":7,"multipli":[10,21],"multiply_integer_valu":9,"multivers":[7,11],"munch":[1,16,26],"munch_nm":1,"must":[0,1,2,3,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,25,26],"must_be_atomic_qualified_typ":7,"must_be_class_or_namespace_lookup":21,"must_be_prototype_instanti":7,"must_be_tag_lookup":21,"must_introduce_attribut":7,"mutabl":[3,7,10],"mutable_in_embedded_cplusplus":7,"mutable_not_allow":7,"mutable_qualifier_on_explicit_this_lambda":7,"mutat":14,"mv_info":11,"mx":16,"my_filt":24,"my_templ":4,"my_var_a":4,"my_var_c":4,"my_vari":4,"my_very_long_funct":4,"mylib":10,"mythread":[7,11],"mythread_constant_not_allow":7,"n":[0,1,3,4,7,8,10,11,15,16,21,24,25,26],"n2634":9,"na":0,"naiv":[14,15],"nake":7,"name":[0,1,2,7,8,9,12,13,17,18,19,22,23,24,25,26],"name1":[7,10],"name2":[7,10],"name_before_typeid_not_typ":7,"name_linkag":[3,11],"name_linkage_mismatch_for_vari":7,"name_must_be_prototype_instanti":7,"name_not_class_in_file_scop":7,"name_not_found_in_file_scop":7,"name_not_member_of_class_or_base_class":7,"name_not_tag_in_file_scop":7,"name_space_for_symbol_kind":21,"namealias":15,"named_address_spac":[7,10,11],"named_address_space_for_paramet":7,"named_address_space_not_allow":7,"named_address_space_on_function_typ":7,"named_module_source_conflict":7,"named_override_requires_managed_typ":7,"named_override_requires_virtu":7,"named_override_type_mismatch":7,"named_regist":[7,10],"named_register_not_allow":7,"named_register_storage_class":11,"nameindex":17,"namespac":[0,3,4,5,7,9,14,15,18,22,23,25],"namespace_alia":7,"namespace_alias_def_not_allow":7,"namespace_cli_cannot_be_extend":7,"namespace_declar":6,"namespace_def_not_allow":7,"namespace_default_cannot_be_extend":7,"namespace_name_not_allow":7,"namespace_not_allow":7,"namespace_ptr":15,"namespace_qualified_id_lookup":21,"namespace_qualified_name_requir":7,"namespaces_in_embedded_cplusplus":7,"nan":10,"narrow":[7,9,15,18,24],"narrowing_convers":7,"nativ":[1,7,9,11,14,15,17],"native_multibyte_chars_supported_with_unicod":[10,15],"natur":[0,1,3,9,11,15,16,23],"near":[3,9,10,11,14,15,16,21,23],"near_and_far_allow":[10,11],"near_and_far_en":11,"near_code_point":10,"near_data_point":10,"nearest":[10,20,21],"neat":4,"necess":11,"necessari":[0,1,2,3,5,6,8,9,10,11,13,14,15,16,17,18,20,21,22,23,24,25,26],"necessarili":[6,8,9,10,11,13,14,15,22,23],"necessit":[2,16],"need":[1,2,3,4,5,6,7,9,10,14,15,16,17,18,19,20,21,22,23,24,25,26],"need_il_display":[1,10],"needed_flag_bit_numb":[0,2],"needed_flag_is_set":0,"needless":14,"needn":[3,10],"needs_more_squirrel":4,"negat":[0,4,7,9,11,16,17],"negative_shift_count":7,"negative_valu":7,"neither":[0,9,16,23],"neon":7,"ness":5,"nest":[3,6,7,8,9,10,11,14,15,16,17,18,22,23],"nested_class_anachron":7,"nested_com":7,"nested_inline_namespace_nonstandard":7,"nested_namespace_nonstandard":7,"nested_source_line_modif":15,"nested_upc_foral":7,"nested_va_opt":7,"net":[0,1,10,11,13],"never":[0,2,3,6,7,9,10,11,14,15,16,17,18,21,23,25,26],"never_defin":7,"never_throw":18,"nevertheless":[0,5,10,11],"new":[0,1,3,4,6,7,8,9,10,12,14,15,17,19,20,21,22,23,24,25,26],"new3":16,"new_array_size_must_be_nonneg":7,"new_can_be_folded_into_ctor":[11,16],"new_cast_in_embedded_cplusplus":7,"new_for_init":10,"new_il_region":22,"new_memory_region":0,"new_of_cli_interface_class":7,"new_of_initializer_list":7,"new_or_override_requir":7,"new_or_virtual_requir":7,"new_requires_matching_base_memb":7,"new_routin":16,"new_struct_stmt_stack":[6,23],"new_type_nam":6,"new_used_on_handle_or_tracking_reference_typ":7,"new_used_on_managed_class_typ":7,"new_used_on_unsuitable_value_typ":7,"newer":[4,7,15,16,17],"newli":[11,15,18,21,23],"newlin":[4,7,15],"next":[0,1,3,4,6,8,9,10,11,14,15,16,18,20,21,23,24,25],"next_construct_processing_funct":18,"next_elem":[6,9],"next_in_destruct":11,"next_in_destruction_list":[11,16],"next_in_scop":21,"next_scope_that_affects_access_control":21,"next_symbol_in_overload_set":9,"next_symbol_in_overload_symbol_list":9,"next_token":[14,15],"next_token_is_top_level_decl_start":0,"next_two_token":15,"next_val":10,"nf":0,"ng":16,"nih":10,"nit":16,"nm":[23,26],"nn":[2,14],"nnn":[10,16,24],"nnnn":16,"nnnnnn":2,"no_":10,"no_abi_tag_on_declar":7,"no_access_or_using_decl_in_union":7,"no_access_to_nam":7,"no_access_to_type_cfront_mod":7,"no_add_match_not":10,"no_aligned_new":10,"no_alignment_on_definit":7,"no_alternative_token":10,"no_anachron":10,"no_appropriate_delet":7,"no_arg_dep_lookup":10,"no_array_designators_in_cpp_mod":7,"no_array_new_and_delet":10,"no_array_new_and_delete_support":7,"no_auto_instanti":10,"no_auto_storag":10,"no_auto_typ":10,"no_base_assign_op_is_default":10,"no_bit_precise_integ":10,"no_bool":10,"no_brief_diagnost":10,"no_c":10,"no_c23_typeof":10,"no_c99":10,"no_chained_designators_in_cpp_mod":7,"no_chained_designators_with_destructor":7,"no_char16_t_represent":7,"no_char8_t":10,"no_check_concaten":10,"no_check_unicode_secur":10,"no_clang":10,"no_class_name_inject":10,"no_class_template_guid":7,"no_classification_for_fixed_point_typ":7,"no_code_gen":10,"no_color":10,"no_common_typ":7,"no_compound_liter":10,"no_concept":10,"no_const_string_liter":10,"no_constexpr_coroutin":7,"no_constructor_for_convers":7,"no_conversion_funct":7,"no_corresponding_delet":7,"no_corresponding_member_delet":7,"no_corresponding_push":7,"no_cppc":10,"no_cppcx":10,"no_ctor_but_const_or_ref_memb":7,"no_ctor_or_dtor_using_declar":7,"no_default_constructor":7,"no_default_delete_in_virtual_dtor":7,"no_defer_parse_function_templ":10,"no_delegating_constructor":10,"no_dep_nam":[7,10],"no_deprecated_string_conv":10,"no_design":10,"no_designator_valu":7,"no_diagnost":6,"no_digit_separ":10,"no_display_error_numb":10,"no_distinct_template_signatur":10,"no_embedded_c":10,"no_enum_overload":10,"no_exc_spec_in_func_typ":10,"no_except":10,"no_exception_support":7,"no_explicit":10,"no_export":10,"no_export_support":7,"no_extended_design":10,"no_extended_variadic_macro":10,"no_extern_inlin":10,"no_finalizer_using_declar":7,"no_fixed_point":10,"no_float128":7,"no_float80":7,"no_for_init_diff_warn":10,"no_friend_inject":10,"no_func_prototype_tag":10,"no_g":10,"no_gcc":10,"no_gen_move_oper":10,"no_get_properti":7,"no_gnu_sentinel_argu":7,"no_gnu_virtual_base_gap":7,"no_guiding_decl":10,"no_il_low":[1,10],"no_implicit_capture_on_enclosing_lambda":7,"no_implicit_extern_c_type_convers":10,"no_implicit_includ":10,"no_implicit_noexcept":10,"no_implicit_typenam":10,"no_incognito":10,"no_init":7,"no_inlin":10,"no_internal_linkage_for_new_or_delet":7,"no_keep_restrict_in_signatur":10,"no_lambda":10,"no_line_command":10,"no_long_preserving_rul":10,"no_lossy_conversion_warn":10,"no_macro_positions_in_diagnost":10,"no_match_for_addr_of_overloaded_funct":7,"no_match_for_type_of_overloaded_funct":7,"no_match_in_c11_gener":7,"no_matching_ar":7,"no_matching_constructor":7,"no_matching_forscope_stack_entri":7,"no_matching_funct":7,"no_matching_function_due_to_selector":7,"no_matching_new_funct":7,"no_matching_operator_funct":7,"no_matching_target_attribut":7,"no_microsoft":10,"no_microsoft_bug":10,"no_mixed_init_in_cpp_mod":7,"no_modul":10,"no_module_import_diagnost":10,"no_ms_compat":10,"no_ms_cplusplus_std_valu":10,"no_ms_extens":10,"no_ms_permiss":10,"no_ms_rvalue_cast":10,"no_ms_std_preprocessor":10,"no_ms_stdc":10,"no_ms_strict_ternari":10,"no_ms_translate_includ":10,"no_multibyte_char":10,"no_mutable_allowed_on_anonymous_union":7,"no_named_address_spac":10,"no_named_field":7,"no_named_regist":10,"no_named_register_for_array":7,"no_namespac":10,"no_negative_designator_rang":7,"no_nonconst_ref_anachron":10,"no_nonstd_anonymous_union":10,"no_nonstd_default_arg_deduct":10,"no_nonstd_gnu_keyword":10,"no_nonstd_instantiation_lookup":10,"no_nonstd_qualifier_deduct":10,"no_nonstd_using_decl":10,"no_nothrow_global_new_for_coroutin":7,"no_nullptr":10,"no_old_id_char":10,"no_old_speci":10,"no_ordinary_and_extended_design":7,"no_out_of_order_init_in_cpp_mod":7,"no_overloaded_subscript_with_offsetof":7,"no_overrider_for_pure_virtual_funct":7,"no_pack_expansion_in_design":7,"no_pack_in_fold_express":7,"no_packing_of_non_pod_field":7,"no_parameter_for_literal_oper":7,"no_params_with_class_or_enum_typ":7,"no_params_with_class_typ":7,"no_parent_macro_invoc":[11,14,15],"no_parse_templ":[7,10],"no_pch":[0,10],"no_pch_messag":10,"no_pointer_paramet":7,"no_preproc_on":10,"no_preserve_lvalues_with_same_type_cast":10,"no_prior_declar":7,"no_prior_push_macro":7,"no_put_properti":7,"no_qualified_friend_definit":7,"no_range_designator_with_dynamic_init":7,"no_relaxed_abstract_check":10,"no_remove_unneeded_ent":10,"no_require_func_prototyp":[7,10],"no_restrict":10,"no_return_value_and_return_void":7,"no_rtti":10,"no_rvalue_ref":10,"no_scope_depth":21,"no_short_enum":10,"no_speci":7,"no_special_subscript_cost":10,"no_stdarg_builtin":10,"no_stdc_zero_in_system_head":10,"no_strict_gnu":10,"no_suitable_assignment_oper":7,"no_suitable_copy_constructor":7,"no_suitable_synthesis_assignment_oper":7,"no_sun":10,"no_sun_linker_scop":10,"no_svr4":10,"no_template_typedefs_in_diagnost":10,"no_thread_local_storag":10,"no_token_separators_in_pp_output":10,"no_trigraph":10,"no_type_of_specified_width":7,"no_type_traits_help":10,"no_typenam":10,"no_typename_in_friend_class_decl":7,"no_uliter":10,"no_unrestricted_union":10,"no_upc":10,"no_use_before_set_warn":10,"no_user_defined_convers":7,"no_user_defined_liter":10,"no_using_framework_directori":10,"no_using_std":10,"no_utf8_char_liter":10,"no_value_returned_in_non_void_funct":7,"no_variadic_macro":10,"no_variadic_templ":10,"no_viable_delete_for_coroutin":7,"no_vla":10,"no_warn":10,"no_wchar_t_keyword":10,"no_wrap_diagnost":10,"nocolor":10,"nocommon":10,"node":[0,1,2,5,7,8,9,11,14,16,22,23,25],"node_does_fetch":11,"node_for_integer_const":22,"node_has_side_effect":9,"node_includes_glvalue_to_prvalue_conv":11,"node_is_pointer_with_restrict_semant":11,"nodiscard":7,"nodiscard_constructor":7,"nodiscard_constructor_with_reason":7,"nodiscard_doesnt_appli":7,"nodiscard_object_typ":7,"nodiscard_object_type_with_reason":7,"nodiscard_return_typ":7,"nodiscard_return_type_with_reason":7,"nodiscard_routin":7,"nodiscard_routine_with_reason":7,"noexcept":[7,8,9,11,16],"noinlin":7,"noisi":24,"nomin":21,"non":[0,1,2,3,5,6,7,9,10,11,14,15,16,17,18,19,21,22,24,25],"non_arith_operation_in_templ_arg":7,"non_autonomous_opaque_enum_decl":7,"non_c_like_because_of_base_class":7,"non_c_like_because_of_default_member_init":7,"non_c_like_because_of_friend":7,"non_c_like_because_of_lambda":7,"non_c_like_because_of_memb":7,"non_c_like_typedef_for_linkag":7,"non_initial_dialect":15,"non_integral_operation_in_templ_arg":7,"non_pod_passed_to_ellipsi":7,"non_pod_va_arg":7,"non_scalar_vacuous_dtor_cal":7,"non_template_structured_binding_pack":7,"non_thread_local_follows_thread_loc":7,"non_unicode_char_in_head":7,"non_unicode_char_in_id":7,"non_zero_int_conv_to_point":7,"nonautomatic_var_in_constexpr_funct":7,"nonbool_arith_operand":7,"nonbool_atomic_constraint":7,"nonclass":[3,6,10,11,15,16,21,23],"nonclass_prototype_instanti":11,"nonclass_template_instantiations_in_source_sequence_list":[11,21,22],"noncompli":10,"nonconst":[6,7,9,10,16],"nonconst_defaulted_member_comparison":7,"nonconst_ref_anachron":10,"nonconst_ref_init_anachron":7,"nonconst_ref_init_from_rvalu":7,"nonconstant_enable_if_attr":7,"nonconstant_field_initializer_in_mem_initi":7,"nonconstant_mem_init_for_constexpr_ctor":7,"nonconstant_offsetof":7,"nonconstant_splicer_operand":7,"nonconsteval_overrides_constev":7,"nonconstexpr_call_in_mem_initi":7,"nonconstexpr_mem_init_ctor_for_constexpr_ctor":7,"nondeclar":21,"nondeduc":10,"nondefin":23,"nondefining_friend_requires_claus":7,"nondelet":7,"nondeleted_function_overrides_deleted_funct":7,"nondep_cal":14,"nondepend":23,"nondependent_cal":23,"nondiscretionari":0,"none":[1,3,7,9,10,11,14,15,16,17,21,22,23],"nonempti":[3,23],"nonetheless":6,"nonexist":9,"nonexplicit":23,"nonexternal_entity_in_template_arg":7,"nongener":6,"noninlin":[8,10,23],"nonintegral_shuffle_mask":7,"nonliter":7,"nonliteral_param_type_in_constexpr_funct":7,"nonliteral_return_type_in_constexpr_funct":7,"nonliteral_var_in_constexpr_funct":7,"nonloc":[3,7,26],"nonlocal_label_refer":7,"nonlocal_vla_not_allow":7,"nonmanaged_function_for_deleg":7,"nonmemb":[3,7,9,10,21,22,23],"nonmember_enum_templ":7,"nonmember_operator_function_lookup":[9,21],"nonmember_operator_not_allow":7,"nonmember_reflection_for_intrins":7,"nonmember_using_declar":6,"nonnest":[10,21],"nonnul":[7,11,16],"nonnull_on_nonpoint":7,"nonnull_parameter_number_too_larg":7,"nonobject_pointer_arithmet":7,"nonoverrid":3,"nonpoint":7,"nonpreprocess":18,"nonpubl":[7,10],"nonpublic_data_member_in_public_cppcx_value_typ":7,"nonpublic_implicit_interface_match":7,"nonreal":[15,23],"nonreal_member_symbol_kind":21,"nonreus":15,"nonsens":14,"nonshared_blocksizeof":7,"nonshared_strict_relax":7,"nonstandard":[0,6,7,10],"nonstandard_alias_declaration_context":7,"nonstandard_anonymous_union_qualifi":7,"nonstandard_array_with_flexible_array_el":7,"nonstandard_bit_field_initi":7,"nonstandard_conversion_for_cleanup":7,"nonstandard_conversion_from_scoped_enum":7,"nonstandard_explicit_bool":7,"nonstandard_lambda_attribut":7,"nonstandard_long_float":7,"nonstandard_parenthesized_string_initi":7,"nonstandard_ptr_minus_ptr":7,"nonstandard_secondary_decl_specifi":7,"nonstandard_use_of_explicit_default_constructor":7,"nonstat":[5,6,7,9,10,11,16,21],"nonstatic_addressof_operator_in_managed_class":7,"nonstatic_member_def_not_allow":7,"nonstd":10,"nonstd_address_of_ellipsi":7,"nonstd_address_of_label":7,"nonstd_anonymous_union":10,"nonstd_array_cast":7,"nonstd_asm_funct":7,"nonstd_assigned_goto":7,"nonstd_bit_field_typ":7,"nonstd_brac":7,"nonstd_character_at_start_of_macro_def":7,"nonstd_const_memb":7,"nonstd_const_member_decl_not_allow":7,"nonstd_default_arg":7,"nonstd_default_arg_deduct":10,"nonstd_default_arg_on_function_template_redecl":7,"nonstd_ellipsis_only_param":7,"nonstd_extra_comma":7,"nonstd_fixed_point_suffix":7,"nonstd_forward_decl_enum":7,"nonstd_friend_decl":7,"nonstd_gnu_keyword":[7,10],"nonstd_ignored_array_cast":7,"nonstd_implicit_int":7,"nonstd_instantiation_lookup":10,"nonstd_long_long":7,"nonstd_member_function_address":7,"nonstd_old_speci":7,"nonstd_opaque_enum_decl_in_type_id":7,"nonstd_pp_direct":7,"nonstd_qualified_void_param_list":7,"nonstd_qualifier_deduct":[7,10],"nonstd_qualifier_in_global_scope_decl":7,"nonstd_qualifier_in_namespace_member_decl":7,"nonstd_reinterpret_cast":7,"nonstd_template_void_param_list":7,"nonstd_unnamed_field":7,"nonstd_unnamed_memb":7,"nonstd_using_decl":[7,10],"nonstd_void_param_list":7,"nonstrict":10,"nontempl":[3,23],"nontrivi":[3,6,7,10,16],"nontyp":[7,9,10,11,15,16,21,23],"nonuniform":10,"nonunion":7,"nonvalue_class_type_cannot_be_value_class_memb":7,"nonviable_because_arg_mismatch":7,"nonvirtu":[3,7,11,16],"nonzero":[3,7,10,11,14,16,24,26],"noreturn":[6,7,18],"noreturn_function_does_return":7,"noreturn_with_return_typ":7,"normal":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24],"normal_ref_bound_to_cppcx_lvalu":7,"normal_ref_bound_to_gc_lvalu":7,"normal_termin":0,"normat":10,"not_a_base_class_memb":7,"not_a_class_or_struct_nam":7,"not_a_class_templ":7,"not_a_field":7,"not_a_field_nam":7,"not_a_field_or_base_class":7,"not_a_generic_param":7,"not_a_line_splic":7,"not_a_memb":7,"not_a_member_class":7,"not_a_tag_memb":7,"not_a_templ":7,"not_a_template_nam":7,"not_a_type_memb":7,"not_a_type_nam":7,"not_a_type_reflect":7,"not_a_vari":7,"not_an_actual_memb":7,"not_an_enum_typ":7,"not_an_enum_type_nam":7,"not_captured_local_var_in_lambda":7,"not_captured_this_in_lambda":7,"not_class_memb":7,"not_compatible_with_previous_decl":7,"not_compatible_with_templ_templ_param":7,"not_enough_preallocated_memori":7,"not_found_on_pack_alignment_stack":7,"not_generic_param_of_curr_decl":7,"not_global_namespac":7,"not_instantiatable_ent":7,"not_used_in_partial_spec_arg_list":7,"not_used_in_template_function_param":7,"notabl":[6,8,10,16,17,21],"notat":[3,9,16],"note":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25,26],"noteworthi":[9,10],"noth":[0,8,9,10,11,14,16,17,20,22],"nothrow":[6,7,18],"notic":[10,16,23],"notifi":25,"notion":[3,6,23,24],"notreach":[10,15],"novel":10,"now":[2,3,8,9,14,15,16,20,21,23],"nowher":[9,11],"np":0,"ns":15,"nsdmi":3,"nsdmis":11,"nsk_label":21,"nsk_macro":21,"nsk_other":21,"nt":0,"nt_util":1,"nuisanc":9,"null":[0,2,3,4,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,25],"null_argument_for_nonnull_paramet":7,"null_char_ignor":7,"null_char_in_header_nam":7,"null_char_in_str":7,"null_express":7,"null_refer":7,"null_reflect":7,"null_routin":7,"null_typ":7,"nullabl":7,"nullptr":[7,10,11,16],"nullptr_conv_to_bool":7,"nullptr_operand":7,"nullptr_t":[7,11,16],"num_":11,"num_active_position_track":15,"num_classes_on_scope_stack":21,"num_elem":16,"num_l_paren":4,"num_r_paren":4,"num_slow_tests_report":24,"number":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,19,21,22,23,24,25,26],"number_of_el":19,"numer":[0,1,9,10,15],"nw":16,"nwa":16,"nx":16,"o":[0,1,10,16,19,24,26],"obey":10,"obj":24,"object":[0,1,2,5,6,7,8,9,10,13,14,15,17,19,20,21,23,26],"object_addr_table_index":16,"object_not_initi":7,"object_temp":16,"object_typ":16,"obscur":15,"observ":[3,17,18,21],"obsolet":[7,10,14],"obtain":[1,7,11,15,17,21,23],"obvious":[0,2,3,9,11,14,15,16,17,23],"occasion":[1,9,10,24],"occupi":[3,7,15],"occur":[0,3,5,6,7,8,9,10,11,14,15,16,17,18,21,23,24,25],"occurr":[3,5,10,14,15,16,22],"octal":[7,10,15],"odd":[9,10],"odlg_1_i1io":16,"odr":[10,16],"offend":10,"offer":[3,10,11],"offici":[0,3,17],"offset":[0,7,8,9,10,11,14,15,16,17,19],"offset_bit_remaind":[3,11],"offset_in_non_pod_nonstandard":7,"offsetof":[7,9,10],"offsetof_bit_field":7,"offsetof_nonfield":7,"offsetof_ref_field":7,"offsetof_virtual_base_memb":7,"ofil":10,"often":[0,1,3,6,9,10,11,14,15,16,17,21,22,23,24,25],"ok":[10,24],"ok_braced_init_list":9,"ok_property_ref":9,"okay":[0,2,9,10,15,16,20,22],"okay_as_output_fil":0,"old":[2,3,6,7,9,10,11,14,15,16,22,23],"old_c":10,"old_fashioned_assignment_oper":7,"old_fashioned_field_select":7,"old_fashioned_initi":7,"old_fashioned_ptr_field_select":7,"old_for_init":10,"old_id_char":10,"old_line_command":10,"old_speci":[7,10],"old_specialization_not_allow":7,"old_style_incompatible_param":7,"old_style_parameter_list":7,"old_style_preprocess":10,"older":[4,6,9,10,11,12,16],"oleaut32":1,"omiss":7,"omit":[3,4,7,10,11,14,15,16,20,24],"omitted_exception_specif":7,"omitted_exception_specification_on_speci":7,"on_primary_declar":18,"onc":[0,1,2,3,5,6,7,8,9,11,14,15,16,17,18,20,21,22,23,24,25],"one":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,19,20,21,22,23,24,26],"one_instantiation_per_object":[0,2,7,10,11,16],"one_level_up":7,"one_th":4,"ongo":10,"onli":[0,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"only_applies_to_float_typ":7,"only_gnu_attributes_her":7,"onto":[0,3,6,8,11,15,16,17,18,20,21,22,23,25],"onwg_1_cil_2_10z1z_1_cil_1_0o":16,"op":[4,10,17],"op1":16,"op2":16,"op_arrow_loop":7,"op_is_zero_const":9,"opaqu":7,"open":[0,4,6,7,10,11,14,15,21,23],"open_file_and_push_input_stack":15,"open_file_for_input":15,"open_output_fil":0,"open_source_fil":0,"open_temp_fil":0,"oper":[0,1,3,4,5,6,7,8,10,14,15,17,19,22,23,24,25,26],"operand":[2,6,7,8,10,11,14,16,21],"operand_must_be_real_floating_valu":7,"operand_must_be_vector":7,"operand_type_pattern_for_oper":9,"operation_has_side_effect":11,"operation_may_not_fit_in_fixed_point_result":7,"operation_type_kind":11,"operator_lookup_namespac":21,"operator_name_not_allow":7,"operator_not_allowed_after_new":7,"operator_not_allowed_in_cpp11_constant_expr":9,"operator_takes_lvalue_operand":11,"operator_token_for_expr_rescan":9,"operatorsort":17,"opinion":0,"opl_2_z1zz2zo":16,"opnam":21,"opname_function_symbol":21,"opname_kind":11,"opname_kind_for_token":21,"opname_member_function_symbol":9,"opname_symbol_head":21,"opname_symbol_t":21,"opportun":10,"oppos":[0,8,9,11,16,17],"opposit":[10,26],"opt":17,"opt_declaration_list":20,"opt_idf":17,"opt_univers":17,"optim":[0,9,10,11,13,14,15,17,21],"optimized_expr_for_select":5,"optimum":14,"option":[0,2,3,5,6,7,8,9,11,12,13,14,15,16,17,18,20,22,23,24,25,26],"options_al":24,"options_sep":24,"or_integer_valu":9,"order":[0,1,2,3,5,6,7,9,10,14,15,16,17,18,19,20,21,23,24,26],"ordin":11,"ordinari":[0,3,5,6,7,9,10,11,16,18,21,23],"ordinarili":[0,2,3,6,10,14,15],"org":[15,16],"organiz":[6,10,11,15,24],"orient":14,"orig_column":[11,15],"orig_line_modif_list":15,"orig_seq":[11,15],"orig_src":16,"origin":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,18,21,22,23,24,25],"orphan":0,"orphaned_file_scope_il_entri":[0,11,22],"oszz1z0o":16,"other_argu":4,"other_func":4,"other_macro":4,"other_macro_is_en":4,"other_other_macro_is_en":4,"other_th":4,"others":[0,1,2,3,5,6,9,10,11,14,15,16,21,22],"otherwis":[1,2,3,4,5,6,7,8,9,10,11,15,16,17,18,20,21,23,24,26],"out_of_class_initializer_ignor":7,"out_of_memori":7,"out_of_memory_during_pch_alloc":7,"out_of_order_ctor_init":7,"out_of_order_field_allocation_nonstandard":7,"outer":[3,7,10,11,20,21],"outermost":[0,3,10,11,16,21],"outlin":6,"output":[0,1,2,4,6,7,11,13,14,16,17,21,23,24,25,26],"output_dir":24,"output_mod":10,"outright":10,"outsid":[2,3,5,6,7,8,9,10,11,14,15,16,20,21,23,24],"outward":21,"overal":[0,1,3,6,9,10,11,14,15,16],"overflow":[3,7,9,10],"overhead":[10,11,14,15,16,17,23],"overlap":[3,7,21],"overlay":17,"overload":[0,6,7,10,11,14,15,16,17,22,23],"overload_anachron":7,"overload_check_ambiguity_and_verify_access":21,"overload_distinguish":22,"overloadable_attribute_requires_prototyp":7,"overloaded_function_catch_up":9,"overloaded_function_linkag":7,"overly":[2,5,13,14],"overrid":[0,2,3,7,10,11,16,17,24,26],"overridden":[0,1,2,3,7,10,11,14,16],"overridden_function_for_wrapp":16,"override_and_final_is_cpp11":7,"override_for_interface_memb":7,"override_member_does_not_overrid":7,"override_name_is_destructor_or_fin":7,"override_name_must_be_a_base_class_member_funct":7,"override_name_nonvirtu":7,"override_of_final_funct":7,"override_of_sealed_funct":7,"override_requires_virtu":7,"override_with_constraint_mismatch":7,"override_with_trivial_property_or_ev":7,"overriding_function_for_wrapp":16,"overriding_reduces_accessibility_in_managed_typ":7,"overriding_virtual_funct":3,"overview":[8,11,13,16],"overwrit":[9,10,15,24,25],"overwritten":[0,15],"ovm":10,"owned":7,"owning":17,"owns":17,"p":[0,2,3,5,6,9,10,11,16,23,25],"p1":[9,16],"p2":9,"pa":[10,11],"pack":[7,9,11,14,16,23,24],"pack_align":10,"pack_expansion_for_field_mem_init":7,"pack_expansion_for_non_pack_alias_param":7,"pack_index_out_of_bound":7,"pack_indexing_is_cpp26":7,"pack_init_capture_in_non_variadic_context":7,"pack_init_capture_is_cpp20":7,"pack_init_capture_not_en":7,"pack_length_mismatch":7,"pack_not_expand":7,"pack_not_last_arg":7,"packag":[11,26],"packard":19,"pad":[7,16,17],"page":[7,10,13],"pain":11,"painless":10,"paint":3,"pair":[9,10,11,14,15,17,21,22,23,26],"pal":23,"panic":17,"paper":[9,10,15],"paragraph":[15,16],"parallel":[3,10,15],"param":[11,16,22,23],"param_cannot_be_complet":7,"param_id":23,"param_id_list_needs_function_def":7,"param_is_abstract":7,"param_is_incomplet":7,"param_not_allow":7,"param_pack_cannot_have_default":7,"param_type_list":16,"param_value_has_been_chang":21,"paramet":[0,2,3,6,7,8,9,10,14,15,16,18,21,22,25],"parameter":10,"parameter_array_on_operator_funct":7,"parameter_capture_conflict":7,"parameter_numb":7,"parameter_pack_decl_not_allow":7,"parameter_with_interface_typ":7,"parameter_with_link_scope_specifi":7,"parameteriz":10,"parameterizedent":17,"parametersm":23,"parcel":0,"paren":[4,24],"parens_in_il":11,"parent":[0,3,7,11,15,16,17,21,22],"parent_destruction_sublist":11,"parent_lifetim":11,"parent_macro_index":[11,15],"parent_scop":11,"parenthes":[0,2,5,6,7,9,10,15,20],"parenthesi":[6,7,9,10,11,15,18],"parenthesized_init_not_allow":7,"parm":10,"parmet":23,"pars":[1,3,7,10,13,15,23,25],"parse_braced_init_list_ful":9,"parse_templ":[7,10,11],"parser":[14,23],"part":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25,26],"partial":[0,1,2,7,8,10,11,16,21,22],"partial_class_incorrect_type_or_loc":7,"partial_overrid":7,"partial_spec_after_instanti":7,"partial_spec_after_instantiation_ambigu":7,"partial_spec_arg_depends_on_templ_param":7,"partial_spec_is_primary_templ":7,"partial_spec_template_arg_list":23,"partial_speci":23,"partial_specialization_not_allow":7,"particip":[10,23],"particular":[0,1,2,3,4,5,6,9,10,11,14,15,16,17,18,19,21,22,23,24,25],"partit":7,"partition_kind":17,"pass":[0,1,2,3,4,6,7,8,9,10,11,13,14,15,16,17,18,19,21,22,23,24,25,26],"pass_directive_to_output":15,"pass_object_s":7,"pass_object_size_not_in_function_decl":7,"pass_pp_directive_to_output":15,"past":[6,7,9,15,17,18],"paste":[7,10,15],"paste_cannot_be_first":7,"paste_cannot_be_first_in_va_opt":7,"paste_cannot_be_last":7,"paste_cannot_be_last_in_va_opt":7,"patch":[1,14,16,24,26],"path":[10,11,15,23,24],"pathnam":10,"pathway":18,"pattern":[3,9,10,11,15,16,20,23,24],"pay":[0,11],"pbk_immedi":18,"pbk_next_construct":[10,18],"pbk_next_token":18,"pbk_other":18,"pbk_preproc_immedi":18,"pc":3,"pcc":[2,3,6,9,11,14,15],"pcc_address_of_array":7,"pcc_field_ambigu":7,"pcf":10,"pch":[7,10,14],"pch_cmd_line_option_mismatch":7,"pch_curr_directory_chang":7,"pch_decl_seq_threshold":10,"pch_dir":[0,10],"pch_file_incomplet":7,"pch_file_prefix_mismatch":7,"pch_file_suffix":10,"pch_header_files_have_chang":7,"pch_mem":[0,10],"pch_messag":10,"pch_verbos":10,"pdf":1,"pdm":16,"pdmn":16,"pe":3,"pe_info":3,"peculiar":25,"pedant":14,"pedep":23,"pend":[3,7,15,18,23],"pending_class_definit":3,"pending_instanti":[10,23],"pending_pragma":18,"peopl":16,"per":[0,1,2,9,10,11,14,15,16,17,23,24,26],"per_instantiation_needed_flag":[0,11],"percent":15,"percentag":[0,24],"perfect":[0,24],"perform":[1,3,4,6,7,8,9,11,14,15,16,17,18,21,23,24,25],"perform_deferred_access_check":21,"perform_deferred_access_checks_for_funct":21,"perform_if":15,"perhap":[0,1,14],"period":[8,10,11,16],"period_used_as_qualifi":7,"perman":[21,23],"permiss":[5,10],"permit":[3,6,7,9,10,15,16,21,23],"perobject":26,"persist":[22,23],"perspect":[10,11,15,16,17,22],"pertain":8,"pesep":23,"pf":[10,11],"pfc":11,"phase":[2,3,6,10,11,16,21,23,25],"philosophi":[11,13,16],"physic":15,"pick":[9,16,23,24],"pick_count":24,"piec":[0,3,8,10,11,14,16,17,18,21,22],"piggi":21,"pin":6,"pin_ptr":[0,6,7,9,11,16],"pin_ptr_param_not_allow":7,"pin_ptr_return_type_not_allow":7,"pipe":24,"pipelin":17,"pivot":18,"pk_instanti":18,"pk_lint_argsus":18,"pk_printf_arg":18,"pk_scanf_arg":18,"pk_unrecogn":18,"pkdp":4,"pl":16,"pl_default_use_definition_list_fil":26,"pl_nm":1,"place":[0,1,2,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"placehold":[6,7,9,11,22],"placeholder_type_failed_constraint":7,"placement":[6,7,10],"placement_new_refers_to_non_placement_delet":7,"plain":[1,7,10,23],"plan":16,"platform":[7,8,14,16,24],"play":[9,17,18,23],"plm":1,"plus":[0,2,9,11,16],"pm_call_obj_not_lvalu":7,"pm_call_obj_not_rvalu":7,"pm_class_typ":22,"pm_derived_class_from_virtual_bas":7,"pm_member_typ":22,"pm_virtual_base_from_derived_class":7,"pma":15,"pmf":[10,11,16],"pmf2":10,"pmf_temp":16,"pmg":16,"pmi1":10,"pmi2":10,"pod":[3,6,10],"poimt":11,"point":[1,2,3,5,6,7,8,10,13,14,15,16,18,19,20,21,22,23,25],"pointer":[0,2,3,5,6,7,8,9,10,14,15,17,18,20,21,22,23,26],"pointer_conversion_loses_bit":7,"pointer_conversion_to_same_size_int":7,"pointer_declar":6,"pointer_offset":3,"pointer_operand":7,"pointer_operand_is_second":11,"pointer_outside_base_object":7,"pointer_to_function_operand":7,"pointer_to_member_call_optimization_allow":16,"pointer_to_member_typ":6,"pointer_to_nonconst_for_literal_oper":7,"pointer_to_object_operand":7,"pointer_to_ref_or_interface_class":7,"pointer_to_refer":7,"pointer_to_scalar_requir":7,"pointless":[7,10],"polici":18,"pollut":17,"polymorph":[3,7,11,16],"polyvector":7,"pool":0,"pop":[0,3,6,7,8,10,11,15,16,18,20,21,22,23],"pop_class_reactivation_scop":21,"pop_eh_stack_fram":16,"pop_expr_stack":9,"pop_input_stack":[15,22],"pop_lexical_state_stack":15,"pop_macro":10,"pop_name_context":5,"pop_namespace_extension_scop":21,"pop_namespace_reactivation_scop":21,"pop_object_lifetim":[20,22],"pop_primary_include_search_dir":0,"pop_scop":[0,11,22,23,25],"pop_stmt_stack":20,"pop_stop_token_stack":[14,15],"pop_template_instantiation_scop":23,"popular":[1,14],"portabl":[1,2,7,10,13,16,17,19],"portion":[1,8,10,14,15,16,17,21,24],"pos":0,"pos_curr_token":[9,15],"pos_diagnost":9,"pos_error":9,"pos_ty2_warn":0,"pos_warn":9,"pose":21,"posit":[0,1,2,3,4,5,6,7,9,10,13,17,18,20,21,22,23,24,25],"positional_after_nam":7,"positional_format_specifier_zero":7,"possibl":[0,1,2,3,5,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"post":[0,9,11,20],"postfix":[7,9,10,16],"postincr":16,"potenti":[0,3,7,8,9,10,11,14,15,16,17,21,22,23],"power":[7,10,11,17],"power_idx":17,"pp":[10,15,16],"pp_direct":15,"pp_else_already_appear":7,"pp_if_stack":15,"pp_if_stack_depth":15,"ppe":16,"practic":[9,10,11,14,16,17,21],"pragma":[0,2,6,7,9,14,15,16,22],"pragma_description_for_pragma_kind":[4,18],"pragma_gcc_system_header_in_primary_fil":7,"pragma_id":18,"pragma_init":18,"pragma_inside_funct":7,"pragma_may_not_be_used_her":7,"pragma_must_precede_decl_or_stmt":7,"pragma_must_precede_declar":7,"pragma_must_precede_stat":7,"pragma_pack_show_args_ignor":7,"pragma_weak_allow":10,"pre":[2,7,9,10,11,25],"prealloc":[0,7,10],"prec_level":9,"preced":[0,1,4,5,6,7,8,9,10,11,13,14,15,16,18,20,21,22,23],"precheck":17,"precis":[0,3,10,11,13,15,16,20,21,23],"preclud":[0,16],"precompil":[1,7,11,14,15],"predeclar":[1,7,10],"predeclared_function_cannot_be_delet":7,"predef_macro_redefin":7,"predefin":[1,6,7,11,14,15,16,21],"predefined_macro":[0,1],"predefined_macro_file_nam":0,"predic":[10,15,22,23],"predict":[0,16],"prefer":[3,7,16,20,21,23,24],"prefix":[2,3,4,5,6,7,9,10,14,15,16,17,18,23,24,25,26],"preinclud":10,"preinclude_macro":10,"preliminari":[10,21],"prelink":[1,10,13,14,16,26],"preload":0,"prelow":16,"prelower_class_typ":16,"prematur":[10,18],"premium":10,"prentic":10,"prep_":9,"prep_aggr_initi":[6,9],"prep_argument_operand":9,"prep_assignment_operand":9,"prep_conversion_operand":9,"prep_elision_initializer_operand":9,"prep_initializer_operand":9,"prep_list_initi":9,"prep_return_by_cctor_operand":9,"prepar":[6,9,20],"prepare_for_trans_unit_copi":25,"prepend":21,"preproc":[0,6,14,15,18,22],"preproc_init":0,"preprocess":[0,5,7,9,10,11,12,13,14,16,18,19,23],"preprocessor":[1,7,9,13,14,15,24,25],"prerequisit":0,"prescan":[3,6,23],"prescan_decl_specifi":6,"prescan_declar":6,"prescan_default_arg_expr":[3,23],"prescan_function_declar":6,"prescan_function_definit":3,"prescan_initializer_for_auto_type_deduct":6,"prescrib":16,"presenc":[1,2,3,6,10,11,15,16,18,21,23],"present":[0,1,3,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25],"preserv":[0,2,3,6,7,8,9,10,11,14,15,16,18,21,23,25,26],"preserve_lvalues_with_same_type_cast":10,"pressur":24,"presum":[9,17,24],"pretti":[2,16,17],"preus":[0,6,10,15],"prev_ns_inlin":7,"prev_ns_not_inlin":7,"prevent":[0,7,10,11,17,18,21,23,24,26],"previous":[0,1,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,26],"previous_consteval_decl_conflict":7,"previous_constexpr_decl_conflict":7,"previous_nonconsteval_decl_conflict":7,"previous_nonconstexpr_decl_conflict":7,"previous_scop":21,"price":0,"primari":[0,3,5,7,9,10,11,14,15,16,18,21,22,23,24,25],"primarili":[1,6,11,16,17,18,20,21,23,24],"primary_base_class":3,"primary_cpf":24,"princip":[3,6,8,15,16,18,21,23,25],"principl":[3,9,10,17,25],"print":[0,8,14,15,16,17,24],"print_markered_text":15,"printer":11,"printf":[0,4,8,10,16],"printf_arg_mismatch":7,"prior":[1,3,7,8,9,10,16,17,23,24],"priorit":4,"prioriti":[7,10],"privat":[3,4,6,7,10],"private_virtual_member_function_not_s":7,"privileg":21,"probabl":[0,1,2,7,9,10,14,16,19,26],"probable_guiding_friend":7,"probable_inadvertent_lbracket_digraph":7,"probable_inadvertent_sharp_digraph":7,"probe":15,"problem":[0,1,2,3,6,7,8,10,11,14,15,16,17,20,21,22,23,25,26],"problemat":[11,24],"proc_":15,"proc_assert":15,"proc_command_lin":0,"proc_defin":15,"proc_elif":15,"proc_els":15,"proc_endif":15,"proc_error":15,"proc_id":15,"proc_if":15,"proc_ifdef":15,"proc_includ":15,"proc_lin":[15,22],"proc_pragma":[15,18],"proc_unassert":15,"proc_undef":15,"proc_us":15,"procedur":10,"proceed":[0,3,21,23],"proces":18,"process":[0,1,2,3,5,6,7,8,16,17,20,22,23,24,25,26],"process_converted_constant_express":9,"process_curr_construct_pragma":18,"process_curr_token_pragma":18,"process_deferred_class_fixup":3,"process_deferred_class_fixups_and_instanti":3,"process_deferred_instantiation_request":3,"process_generic_lambda_param_typ":3,"process_ifc_decl":17,"process_pending_instanti":25,"process_preus":[0,15],"process_runtime_checked_safe_cast":9,"process_translation_unit":[23,25],"process_unicode_nam":15,"process_verification_list":25,"processing_c_cod":18,"processor":[5,15],"produc":[0,1,2,3,6,7,8,9,10,11,13,14,15,16,17,19,21,22,23,25],"product":[1,9,10,14,26],"profil":5,"program":[0,2,3,5,7,8,9,10,11,13,14,15,18,19,21,23,24],"program_entity_too_large_for_pch":7,"program_too_larg":7,"programm":[0,8,10,11,13,14,16],"progress":[21,24,25],"prohibit":23,"project":[3,4,6,10,16],"project_base_class_conversion_funct":[3,21],"promis":[7,17],"promise_type_returns_return_void":7,"promot":[2,3,7,9,10,11,20,22],"promote_class_memb":16,"promote_label_and_goto_lifetim":20,"promote_local_entities_to_file_scop":16,"promote_operand":9,"promote_warn":10,"promoted_arith_operand":7,"promoted_integral_operand":7,"prone":14,"propag":3,"proper":[0,1,2,3,6,8,9,10,11,13,15,16,17,18,19,22,23,26],"properti":[7,10,15,17,18,21,23],"property_attribute_in_managed_class":7,"property_get_already_declar":7,"property_get_cannot_have_paramet":7,"property_get_index_type_mismatch":7,"property_get_index_type_miss":7,"property_name_not_allow":7,"property_requires_managed_class":7,"property_set_already_declar":7,"property_set_index_type_mismatch":7,"property_set_index_type_miss":7,"property_set_missing_value_paramet":7,"property_set_value_parameter_mismatch":7,"proport":16,"propos":[3,10],"protect":[3,5,7,10,15,16,21],"protected_access_problem":7,"proto":1,"protocol":14,"prototyp":[1,2,3,6,7,9,10,11,13,14,15,18,21,22,23],"prototype_instanti":23,"prototype_instantiations_in_il":[11,23],"prototype_lost":7,"prototype_templ":23,"prove":20,"provid":[0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"provis":[21,23],"provision":3,"proxi":[3,15,17],"proxy_class_for_template_param":21,"prune":[10,20],"prvalu":[7,9,11],"ps":[11,16],"pseudo":[3,6,7,9,10,11,15,16,18,21],"pt":16,"ptr":10,"ptr_conv_to_bool":7,"ptr_flag":16,"ptr_func_ptr_data_conv":7,"ptr_handle_or_ref_to_generic_param":7,"ptr_handle_or_ref_to_interior_ptr":7,"ptr_handle_or_ref_to_pin_ptr":7,"ptr_incomplete_throw":7,"ptr_or_ref_to_cli_array":7,"ptr_or_ref_to_incomplete_typ":7,"ptr_or_ref_to_qualified_function_typ":7,"ptr_to_incomp_array_arithmetic_allow":10,"ptr_to_mem_of_incomplete_class":7,"ptr_to_mem_to_non_memb":7,"ptr_to_member_cast_to_ptr_to_funct":7,"ptr_to_member_conv_to_bool":7,"ptr_to_member_of_handle_typ":7,"ptr_to_member_of_managed_class":7,"ptr_to_member_of_reference_typ":7,"ptr_to_member_of_type_void":7,"ptr_to_member_of_vla_typ":7,"ptr_to_member_operand":7,"ptr_to_member_typ":22,"ptr_to_member_typedef":7,"ptrdiff_t":[7,9,10,16],"ptrdiff_t_operand":7,"ptrepositori":10,"public":[3,6,7,8,10,15,16,21],"public_data_member_in_public_non_value_typ":7,"public_nested_type_in_cppcx_typ":7,"public_nondata_member_in_public_cppcx_value_typ":7,"publish":[15,19],"pull":[6,10,17],"punctuat":4,"pure":[3,6,7,9,10,16,18],"pure_final_virtu":7,"pure_specifier_on_nonvirtual_funct":7,"pure_specifier_on_sealed_memb":7,"pure_virtual_definit":7,"pure_virtual_funct":7,"pure_virtual_member_templ":7,"purpos":[0,1,3,4,6,7,9,11,14,15,16,17,18,20,21,22,23,24],"push":[3,6,7,8,10,11,15,16,18,20,21,22,23],"push_class_reactivation_scop":21,"push_eh_stack_fram":16,"push_expr_stack":9,"push_input_stack":[15,22],"push_instantiation_context":21,"push_lexical_state_stack":15,"push_macro":[7,10],"push_name_context":5,"push_namespace_extension_scop":21,"push_namespace_reactivation_scop":21,"push_object_lifetim":[20,22],"push_opt":7,"push_primary_include_search_dir":0,"push_scop":[20,23],"push_scope_ful":21,"push_stmt_stack":20,"push_stop_token_stack":[14,15],"push_template_instantiation_scop":[21,23],"put":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,17,21,23,24,25,26],"put_property_function_miss":7,"pvt_mod_fgmt_only_after_modul":7,"pwd":1,"python":24,"q":[3,10,11,16,22,24,25,26],"q2_1a1b":16,"qual":25,"qualif":[3,9,10],"qualifi":[0,2,3,4,5,6,7,9,10,11,14,15,16,21,22,23],"qualified_cli_accessor":7,"qualified_lookup":21,"qualified_name_not_allow":7,"qualified_name_redecl_sym":6,"qualified_name_requir":7,"qualified_reference_typ":7,"qualified_unnamed_bit_field_typ":7,"qualified_using_directive_lookup":21,"qualified_void_return_typ":7,"qualifier_dropped_in_ref_init":7,"qualifier_ignored_on_local_declar":7,"qualifier_in_member_declar":7,"qualifier_in_namespace_member_decl":7,"qualifier_must_be_base_class":7,"qualifier_not_allowed_on_managed_member_funct":7,"qualiti":16,"quantiti":[9,10],"quasi":23,"queri":[17,23],"question":[3,10,11,14,21],"queu":11,"quick":[17,21,24,25],"quirk":16,"quit":[0,1,3,9,10,11,15,16,17,18,21],"quo":10,"quot":[0,7,10,15,26],"quoted_default":7,"quoted_error":7,"quoted_express":7,"quoted_unnam":7,"r":[2,5,7,9,11,15,16,18,24,25,26],"r_declar":[6,18],"ra":24,"race":1,"rais":[3,7,16],"ran":24,"random":[0,15,24],"rang":[1,7,10,11,14,15,16,17,20,21],"range1":10,"range_based_for_incomplete_array_typ":7,"range_based_for_missing_funct":7,"range_based_for_no_matching_overload":7,"range_based_for_nonstandard":7,"range_based_for_undefined_identifi":7,"rank":[6,22,24],"rapid":[10,24],"rare":[9,11,15,17,25],"rather":[0,1,2,3,5,7,8,9,10,11,14,15,16,17,18,21,22,23,25],"raw":[0,7,10,14],"raw_result":17,"raw_text":15,"rc":[3,16],"rcblock":9,"rcc2":16,"re":[0,1,2,3,11,14,15,16,17,20,22,23],"reach":[0,6,8,9,10,11,14,15,16,20,21,23,25],"reachabl":[7,20],"reachablepropertiesbitfield":17,"reactiv":[3,6,9,21,23,25],"reactivate_class_and_instantiation_scop":21,"read":[1,2,3,5,7,10,11,13,14,16,23,25,26],"read_auto_instantiation_inform":23,"read_logical_source_lin":15,"read_memory_region":0,"readabl":[0,1,2,10,13,14,18],"reader":[6,13,15,16],"readi":17,"readili":[23,26],"readm":1,"real":[0,2,6,7,9,10,11,14,15,16,17,21,23],"real_and_imag_applied_to_real_valu":7,"real_and_imag_require_complex_argu":7,"real_imaginary_convers":7,"realist":[17,24],"realiz":16,"realli":[0,3,5,6,9,10,11,16,22,23,25],"realloc":[14,15,21],"realloc_buff":[0,14],"reascend":0,"reason":[0,3,4,6,8,9,10,11,14,15,16,17,18,21,23,24,25],"reassign":25,"recach":23,"recal":[10,16,23],"receiv":[3,6,7,9,10,11,15,16,24],"recent":[1,10,11,16],"recheck":21,"reclaim":[0,11,21],"reclassifi":18,"recod":15,"recogn":[3,6,7,9,10,11,14,20,22,23],"recognit":[10,15,18],"recognize_keywords_in_pragma":15,"recognize_microsoft_attribut":6,"recombin":0,"recommend":[1,10,24],"recompil":[0,10,26],"recomput":[0,21],"reconstitut":5,"reconstruct":[0,7,11,15,17],"record":[0,1,3,6,8,9,10,11,14,15,16,20,21,22,23,25],"record_arg_pragma":18,"record_builtin_typ":25,"record_end_of_lifetime_destruct":22,"record_end_of_source_fil":22,"record_hidden_names_in_il":22,"record_inclass_initializer_fixup":3,"record_instanti":25,"record_lint_argsused_and_varargs_st":[15,18],"record_macro_arg":1,"record_macro_invoc":1,"record_macros_in_il":[1,11,22],"record_needed_destruct":16,"record_nondependent_cal":9,"record_operator_position_in_rescan_info":9,"record_partial_aggregate_cleanup_destruct":6,"record_pragma_text":18,"record_predeclared_template_funct":23,"record_start_of_source_fil":22,"record_struct_binding_expr_for_array_el":6,"record_struct_binding_expr_for_field":6,"record_switch_case_entri":20,"record_symbol_declar":21,"record_symbol_refer":[9,21],"record_template_str":[11,23],"record_unrecognized_attribut":[11,18],"record_virtual_function_overrid":3,"record_vla_component_types_for_low":16,"recours":11,"recov":[5,9,11,14,16],"recoveri":18,"recreat":10,"recurs":[0,3,6,7,9,10,13,15,16,17,21,23,25,26],"recursive_def_arg_instanti":7,"recursive_initializer_instanti":7,"recursive_inst_of_templ_default_arg":7,"recycl":6,"redecl_changes_access":7,"redeclar":[0,7,10,11,21,23],"redeclaration_adds_dll_interfac":7,"redeclaration_of_condition_decl_nam":7,"redeclaration_of_for_init_decl_nam":7,"redeclaration_of_friend_with_default_arg":7,"redeclaration_of_range_iter":7,"redeclaration_of_template_param_nam":7,"redefin":[0,10,11,15,17],"redefine_extname_pragma_en":10,"redefinit":[3,7,15],"redirect":[10,14],"redo":9,"redon":25,"reduc":[0,1,7,10,11,13,14,15,16,17,21,23,24,25],"reduct":[0,7],"redund":[7,10,11,21,24],"redundant_exception_specification_typ":7,"reemit":18,"reenter":21,"reenter_symbol":21,"reevalu":[17,18],"ref":[0,3,4,6,7,10,11,15,16,17,23],"ref_bound_to_initonly_field":7,"ref_class_has_multiple_ref_bas":7,"ref_class_initonly_field":7,"ref_class_not_satisfi":7,"ref_entri":9,"ref_mbr_suppresses_copy_asgn_decl":7,"ref_not_allowed_in_union":7,"ref_or_interface_class_member_in_standard_class":7,"ref_qualifier_ignor":7,"ref_qualifier_nonstandard":7,"ref_qualifier_not_allow":7,"ref_to_nested_function_var":7,"refer":[0,2,3,6,7,8,10,14,16,17,20,21,22,23,25,26],"referenc":[0,3,7,8,9,14,15,16,17,21,22,23,25,26],"reference_declared_mut":7,"reference_to_implicitly_invoked_funct":3,"reference_to_ref_or_interface_class":7,"reference_to_refer":7,"reference_to_trivial_default_constructor":[3,6],"reference_to_void":7,"reference_type_not_allow":7,"referenced_non_loc":11,"referencing_namespac":23,"reflect":[3,7,9,10,11,15,16,18,21,23],"reflection_of_overloaded_set":7,"regard":[5,9,10,11,14,15,16,21],"regardless":[0,9,10,11,15,16,24],"regener":[10,23],"regex":24,"region":[0,3,5,6,8,9,14,15,16,17,18,19,21,22],"region_scope_entri":0,"regist":[0,6,7,9,10,11,14,15,16,25],"register_clobbered_twic":7,"register_in_address_spac":7,"register_in_us":7,"register_keyword_deprec":7,"register_keyword_disallow":7,"register_macro_invoc":15,"register_mapped_variable_cannot_have_initi":7,"register_mapped_variable_must_be_pod":7,"register_name_on_nonregist":7,"register_pch_saved_vari":[0,14],"register_pointer_vari":15,"register_storage_class_conflict":7,"register_too_smal":7,"register_trans_unit_vari":[14,25],"register_trans_unit_variable_with_field":25,"register_used_and_clobb":7,"register_used_twic":7,"registr":14,"registri":14,"regular":[0,3,10,11,15,17,18,23,24],"rehost":13,"reiniti":[0,1],"reinsert":15,"reinstat":21,"reinterpret_cast":[7,9,16,17],"reinterpret_cast_conversion_poss":22,"reinterpret_cast_of_handl":7,"reiser":10,"reject":9,"relat":[0,1,2,3,4,7,8,9,10,11,14,15,17,18,21,23,25,26],"related_class_point":22,"relationship":[3,16,17,23],"relax":[7,9],"relaxed_abstract_check":10,"relaxed_constexpr_en":9,"releas":[0,8,10,11,14,15,16,19,26],"release_macro_buffer_region":15,"releg":14,"relev":[11,14,15,17,23,25],"reli":[1,3,6,15,16,17,19,21,22,23,24,25],"relink_unnamed_tag_symbol":[3,21],"reload":23,"rem_source_line_modif":15,"remain":[0,3,6,8,9,10,11,15,16,18,20,21,23,24,25],"remaind":[1,6,23],"remainder_integer_valu":9,"remap":[0,1,11,14,16,25],"remap_first_ptr_of_orphaned_file_scope_entry_array":11,"remap_il_header_point":0,"remap_last_ptr_of_orphaned_file_scope_entry_array":11,"remap_pointers_in_il_entri":0,"remap_ptr":11,"remark":[0,3,7,10,14,16,24],"remark_as_need":0,"rememb":[0,9,11,14,15,21],"remind":[9,11],"remot":11,"remote_idx":17,"remov":[0,3,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"remove_control_flow_descr":20,"remove_from_destructions_list":22,"remove_from_routines_list":22,"remove_from_source_sequence_list":22,"remove_list_of_flow_control_descr":20,"remove_stop_token":[0,14,15],"remove_symbol":21,"remove_symbol_from_scope_list":21,"remove_unneeded_ent":10,"renam":[2,9,11],"render":[1,2,8,9,11,15,16,18],"rendit":10,"reopen":[0,6],"reopen_error_output_fil":0,"reopen_source_fil":0,"reorder":[0,10],"reorgan":15,"repeat":[1,3,6,9,10,11,13,15,16,18,21,23],"repetit":[0,7,11],"repetitions_of":7,"replac":[0,2,3,6,7,8,9,10,11,14,15,16,17,21,23,24,25],"replace_file_name_suffix":0,"replace_special_characters_in_mangled_nam":16,"report":[3,6,9,10,14,15,20,21,23,26],"report_gnu_extens":[7,10],"report_goto_past_init":20,"report_switch_past_init":20,"report_virtual_function_ambigu":3,"reposit":0,"repositori":[3,15,18,21],"repreent":9,"repres":[0,3,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"represent":[0,1,3,5,7,8,9,10,11,13,14,15,16,17,18,19],"reproduc":[0,1,10,21,23,24,25],"req":16,"request":[0,2,7,9,10,11,14,15,16,17,21,25],"requested_size_too_larg":7,"requir":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25,26],"require_func_prototyp":10,"required_token":[14,15],"requires_clause_arg_list_substitution_fail":7,"requires_clause_satisfi":23,"requires_expr_ellipsis_param":7,"requires_incompatible_with_previous_decl":7,"requisit":15,"requit":1,"rerecord":24,"rerun":[17,24,25],"rescan":[3,6,10,14,15,18,23],"rescan_cached_token":15,"rescan_expr_with_substitution_intern":9,"rescan_reusable_cach":15,"rescann":9,"reserv":[0,2,3,4,7,8,9,15,18,21,22,26],"reserved_dispos":7,"reserved_enumerator_nam":7,"reserved_fin":7,"reset":[0,10,11,14,15,21,23],"reset_curr_block_object_lifetim":20,"resid":[3,15,21],"resiz":[0,14],"resolut":[6,7,9,10,11,14,16,17,21,23],"resolv":[3,7,10,14,15,16,17,21,23,24,25],"resolved_foo":16,"resolver_result":16,"resolver_routine_requir":7,"resort":17,"resourc":24,"respect":[0,1,3,4,6,9,10,11,14,15,16,17,21,22,23,24,26],"respons":[6,8,11,16,17,18,21,23],"rest":[0,3,9,10,11,14,15,16,22,23],"restart":[7,15],"restor":[0,6,8,10,11,14,15,18,21,23,25],"restore_struct_stmt_stack":23,"restrict":[3,5,7,9,10,11,15,16,21,22,23],"restrict_not_allow":7,"restrict_pointer_to_funct":7,"restrict_qualifier_drop":7,"restrict_qualifier_ignor":7,"restructuredtext":26,"result":[0,1,3,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24],"resum":[6,9,15],"retain":[0,9,10,11,15,20,21,23,25,26],"retarget":13,"rethrow":[11,16],"retri":[3,21],"retriev":[3,6,9,11,14,16,17,18],"retroact":[3,10,23],"return":[0,2,3,5,6,7,8,9,10,14,15,17,18,20,21,22,23,24,25],"return_from_ctor_function_try_block_handl":7,"return_from_fin":7,"return_in_coroutin":7,"return_ref_init_requires_temp":7,"return_stat":20,"return_type_cannot_distinguish_funct":7,"return_type_is_interfac":7,"return_type_of_default_comparison_must_be_bool":7,"return_type_on_constructor":7,"return_type_on_conversion_funct":7,"return_type_on_destructor":7,"return_type_on_fin":7,"return_valu":7,"return_value_at":7,"return_void":7,"return_void_at":7,"returning_ptr_to_local_temp":7,"returning_ptr_to_local_vari":7,"returning_ref_to_local_vari":7,"returns_lvalue_instead_of_usual_rvalu":11,"reus":[0,3,6,10,11,14,15,16,17,20,21,22,23],"reusabl":[10,15,17,18,21],"reusable_cache_stack":15,"reveal":[3,10,17,20,24],"revers":[6,7,10,11,16,17,19,23],"review":[15,24],"revis":[9,10,11,13,14,17],"revisit":[3,9,17],"rewrit":[1,2,3,7,9,11,15,16,25],"rewrite_compound_assign":16,"rewrite_property_refer":9,"rewrite_secondary_trans_unit_il_entity_pointers_used_in_primari":25,"rewrite_ucn_escape_char_in_low":[11,16],"rewritten":[2,9,10,11,16,23,25],"rewritten_property_reference_kind":5,"rid":0,"ridicul":16,"right":[0,2,3,4,6,7,8,9,10,11,14,15,16,17,18,20,21,23],"ritchi":10,"rl":16,"rn":24,"role":[18,23],"root":[0,6,11,21],"root_macro_invocation_record_block":11,"rough":[6,9,14,16,17],"round":0,"roundabout":23,"routin":[1,2,3,5,6,7,8,10,12,14,18,19,20,21,23,25,26],"routine_definition_needed_flag_is_set":0,"routine_fixup_list":21,"routine_name_linkag":11,"routine_type_is_nonstatic_member_funct":3,"row":17,"rp":24,"rparen":4,"rs":3,"rst":26,"rt":24,"rt_argument":15,"rt_null":15,"rt_raw_argu":15,"rt_right_raw_argu":15,"rt_stringized_raw_argu":15,"rt_text":15,"rtti":[1,7,10,16],"rtti_in_embedded_cplusplus":7,"rule":[3,6,7,8,9,10,11,14,15,16,17,18,20,21,23],"rule_out_expr_kind":9,"ruled_out_expr_kind":9,"run":[0,5,6,7,9,10,11,14,15,16,17,19,20,25,26],"run_config":24,"run_end_of_parse_act":6,"run_test":24,"run_test_default_config":24,"run_test_flag":24,"runaway":[10,23],"runaway_recursive_instanti":7,"runner":24,"runtim":[0,1,7,8,9,11,12,13,14,15,17,23,24,26],"runtime_uses_namespac":[10,12],"rvalu":[2,7,9,10,16,22],"rvalue_ctor_is_copy_ctor":10,"rvalue_ctor_is_not_copy_ctor":10,"rvalue_defaulted_member_comparison":7,"rvalue_expr_for_lvalu":22,"rvalue_ref":10,"rvalue_ref_template_paramet":7,"rvalue_reference_bound_to_lvalu":7,"rvalue_reference_catch_typ":7,"rvalue_reference_in_exception_specif":7,"rvalue_references_is_cpp11":7,"rvalueabl":11,"s":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"sacrific":17,"safe":[6,10,16,17,21,24],"safe_cast":[9,16],"said":[11,16,17,24],"sake":[11,17],"same_param_types_with_and_without_ref_qualifi":7,"same_param_types_with_different_exception_specif":7,"same_repr_ints_interchangeable_in_il":10,"sampl":[1,10,16,19,23,24],"sample_edg_eccp_config":1,"sane":17,"saniti":[15,17,24],"sarif":[7,10],"sat":7,"satisfi":[0,7,9,10,21,23],"save":[0,3,6,8,9,10,11,14,15,16,21,23,25],"save_rescan_info_for_braced_init_list":9,"saw":24,"say":[0,3,9,10,14,15,16,17,18,19,23,24],"sb":16,"sbyte":7,"sc":16,"sc_asm":11,"sc_auto":11,"sc_extern":[3,11,16],"sc_regist":11,"sc_static":11,"sc_unspecifi":[3,11],"scalabl":7,"scalar":[3,6,7,9,10,11],"scale":[11,16,20,24],"scan":[0,2,8,10,11,13,14,16,18,21,23,25],"scan_":9,"scan_add_oper":9,"scan_alignof_oper":9,"scan_ampersand_oper":9,"scan_and_record_cli_delegate_definit":[3,6],"scan_arith_prefix_oper":9,"scan_assert_predicate_refer":15,"scan_attribut":18,"scan_base_specifier_list":3,"scan_bit_oper":9,"scan_boolean_controlling_express":9,"scan_braced_init_list":[6,9],"scan_braced_init_list_as_operand":9,"scan_call_argu":9,"scan_case_label_const":9,"scan_cast_or_expr":9,"scan_char_const":15,"scan_char_liter":15,"scan_class_definit":[3,6,23],"scan_class_initializer_express":9,"scan_class_parenthesized_initi":[6,9],"scan_cli_array_init":9,"scan_cli_delegate_definition_from_assembly_import":6,"scan_cli_generic_class_definition_from_assembly_import":6,"scan_cli_property_or_event_head":3,"scan_comma_oper":9,"scan_compound_assignment_oper":9,"scan_concept_express":23,"scan_conditional_oper":9,"scan_const_cast_oper":9,"scan_constant_dimension_express":9,"scan_constant_initializer_express":9,"scan_conversion_oper":21,"scan_ctor_argu":9,"scan_declarator_attribut":18,"scan_default_arg_expr":9,"scan_defined_oper":15,"scan_delegate_initi":9,"scan_delete_oper":9,"scan_dependent_type_parenthesized_initi":6,"scan_dynamic_cast_oper":9,"scan_eq_oper":9,"scan_exception_specif":8,"scan_expr":[9,14],"scan_expr_as_init_compon":9,"scan_field_selection_oper":9,"scan_fold_express":9,"scan_for_each_express":20,"scan_fs_constant_express":3,"scan_full_initializer_expr_as_compon":[6,9],"scan_function_bodi":[3,6],"scan_function_cal":9,"scan_functional_notation_type_convers":9,"scan_generic_argument_list":23,"scan_gnu_attribute_group":18,"scan_handle_address_oper":9,"scan_identifi":[3,9],"scan_if_expr":15,"scan_indirection_oper":9,"scan_init_captur":3,"scan_intaddr_oper":9,"scan_integer_express":9,"scan_integral_constant_express":[6,9],"scan_label":20,"scan_lambda":[3,9],"scan_lambda_capture_list":3,"scan_lambda_declar":3,"scan_lambda_express":9,"scan_logical_oper":9,"scan_mem_initi":6,"scan_member_constant_initializer_express":[3,9],"scan_member_declar":23,"scan_microsoft_attribut":6,"scan_microsoft_function_modifi":3,"scan_mult_oper":9,"scan_new_oper":[6,9],"scan_noexcept_oper":9,"scan_nonmember_declar":6,"scan_nonstatic_data_memb":3,"scan_nontype_template_argu":15,"scan_numb":15,"scan_parenthesized_mem_init_arg":6,"scan_postfix_incr_decr":9,"scan_pp_express":[9,15],"scan_prefix_incr_decr":9,"scan_previously_decl_iterator_nam":20,"scan_ptr_to_member_oper":9,"scan_pure_specifi":3,"scan_range_based_for_express":20,"scan_real_declarator_id":6,"scan_reinterpret_cast_oper":9,"scan_rel_oper":9,"scan_requires_claus":23,"scan_requires_expr":23,"scan_return_express":[3,9],"scan_safe_cast_oper":9,"scan_shift_oper":9,"scan_simple_assignment_oper":9,"scan_sizeof_oper":9,"scan_static_cast_oper":9,"scan_string_liter":15,"scan_subscript_oper":9,"scan_tag_nam":[3,6,15,23],"scan_template_argument_constant_express":[9,15],"scan_template_argument_list":15,"scan_template_declar":23,"scan_template_param_list":23,"scan_throw_oper":8,"scan_top_level_metadata_declar":[0,6,15],"scan_typeid":9,"scan_unknown_template_arg_list":15,"scan_void_express":[9,20],"scan_whitespace_keyword":15,"scanf":10,"scanning_generated_code_from_metadata":6,"scenario":[15,24],"scene":[16,17],"scheme":[0,8,10,11,14,15,16,26],"scienc":14,"sck_block":20,"sck_class_reactiv":21,"sck_class_struct_union":21,"sck_function":22,"sck_namespac":6,"sck_namespace_extens":6,"sck_pragma":18,"sck_routin":21,"sck_template_declar":23,"sck_template_instanti":[21,23],"sco":10,"scope":[0,1,2,4,6,7,8,9,10,12,14,15,18,20,22,23,25],"scope_orphaned_list_head":0,"scope_region_entri":11,"scope_stack":[14,21],"scope_stk":[0,6,14,21],"scoped_enum_nonstandard_in_current_mod":7,"scoped_enum_operand":7,"scoped_enum_operation_type_mismatch":7,"script":[0,10,15,23,24,26],"script_fil":24,"se":[11,16],"seach":21,"seal":[3,7],"sealed_base_class":7,"sealed_cli_interfac":7,"sealed_constraint":7,"sealed_requires_virtu":7,"search":[0,3,7,8,9,10,11,12,13,14,15,17,21,22,23,24,25,26],"sec":24,"second":[0,2,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"second_argument_wrong_shap":7,"secondari":[0,5,6,11,14,18,22,23],"secondary_specifier_ignor":7,"secondary_st":4,"section":[0,1,3,6,8,9,10,11,14,15,16,17,18,21,22,23,24],"secur":15,"see":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"seek":0,"seem":[9,11,13,14,15,16,17,22,23,25],"seen":[0,3,6,10,11,15,16,20,21,22,25],"segment":0,"seldom":18,"select":[0,1,2,3,5,7,8,9,10,14,15,16,17,19,21,22,23,24,26],"select_best_candidate_funct":9,"select_best_partial_order_candid":23,"select_copy_constructor":21,"select_curr_construct_pragma":18,"select_default_constructor":21,"select_destructor":21,"select_overloaded_funct":9,"selection_initializer_nonstandard":7,"selector":[7,11,14,20],"selector_match_with_this_param":9,"self":[0,7,9,11,15],"self_friendship":7,"self_referencing_temporary_object":7,"semant":[6,7,9,10,11,14,16,17,18,20,23],"semicolon":[0,3,4,7,10,14],"sens":[5,6,10,11,14,16,21,23],"sensibl":14,"sensit":[3,7,21],"sentinel":7,"separ":[0,1,2,3,4,6,7,8,9,10,11,13,14,15,16,17,18,20,21,23,24],"separate_routines_for_file_scope_dynamic_init":16,"seq":11,"sequenc":[0,1,2,3,6,7,8,9,10,14,15,17,18,21,23,24,25,26],"sequence_id":15,"sequenti":[0,3,11,15,21],"seri":[6,9,10,11,14,15,17,18,23,24],"serial":17,"serious":16,"serv":[0,3,10,11,16,18,21,23,24],"servic":22,"set":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,23,24,25,26],"set_active_using_list_scope_depth":21,"set_array_type_s":22,"set_but_not_us":7,"set_class_definition_need":0,"set_class_definition_needed_flag":0,"set_class_keep_definition_in_il":0,"set_conditional_flag_var":16,"set_constant_kind":22,"set_decl_sequence_numb":21,"set_default_source_corresp":11,"set_err_pos_to_curr_token":14,"set_error_const":22,"set_expr_node_kind":22,"set_field_size_and_offset":3,"set_flag":1,"set_force_external_linkage_flag":22,"set_instantiation_required_for_template_class_memb":23,"set_integer_valu":9,"set_literal_type_flag":3,"set_macro_inv_record_ptr_to_index":11,"set_needed_flag":0,"set_needed_flags_at_end_of_file_scop":0,"set_nested_template_class_symbol_info":23,"set_node_oper":[11,22],"set_offset_for_virtual_function_info":3,"set_offsets_for_empty_nonvirtual_base_class":3,"set_offsets_for_field":3,"set_offsets_for_indirect_base_class":3,"set_offsets_for_nonvirtual_base_class":3,"set_offsets_for_virtual_base_class":3,"set_operand_kind":9,"set_output_posit":[2,5],"set_pointer_offset":9,"set_preferred_base_class_deriv":3,"set_routine_definition_need":0,"set_routine_definition_needed_flag":0,"set_routine_keep_definition_in_il":0,"set_severity_for_error_numb":0,"set_severity_for_error_tag":0,"set_signal_handl":0,"set_source_corresp":21,"set_src_seq_secondary_decl_field":22,"set_symbol_kind":21,"set_to_error_loc":21,"set_to_named_error_loc":21,"set_trans_unit_correspond":25,"set_type_kind":11,"set_type_s":[6,22],"set_unsigned_integer_valu":9,"set_up_for_cast_to_refer":9,"set_up_generic_lambda_declarator_scan":3,"set_up_overload_set_travers":9,"set_up_overload_symbol_list_travers":9,"set_up_routine_for_inlin":16,"set_up_variable_remapping_for_inlin":16,"set_used_in_exception_or_rtti_flag":[8,22],"set_virtual_function_numb":3,"setenv":1,"setjmp":[8,16,19],"setlocal":[1,10,15],"setlocale_lc_numeric_fail":7,"setup":[9,17],"sever":[0,2,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"sf":[10,16],"sfb_no_class_reactiv":3,"sfina":[9,10,16],"sfinae_requires_newer_abi_vers":7,"sfk_none":3,"sft":24,"sgi":26,"sgr":10,"sha256":17,"shape":[7,11],"share":[1,3,6,7,9,10,11,14,15,16,17,20,21,22,23,25],"shareabl":11,"shareable_constants_t":22,"shared_affinity_typ":7,"shared_block_size_must_be_posit":7,"shared_block_size_too_larg":7,"shared_inside_struct":7,"shared_nonthreads_dim":7,"shared_obj":15,"shared_paramet":7,"shell":[1,10,24],"shift":[7,9,10,11,15,16],"shift_count_too_larg":7,"shift_left_integer_valu":9,"shift_right_integer_valu":9,"shine":24,"short":[0,5,9,10,11,14,15,16,23],"short_enum":[7,10],"short_lifetime_temp":10,"shortcom":[2,26],"shortcut":3,"shorten":16,"shorter":[9,10],"should_be_instanti":23,"should_delay_finishing_of_function_bodi":21,"should_delay_lowering_on_funct":21,"shouldn":[4,11,14,25],"show":[0,5,7,9,10,11,16,22,23,24],"show_il_alloc_space_us":11,"show_pragma_conform_forscope_is_nonstandard":7,"show_pragma_conform_forscope_is_standard":7,"shown":[1,9,10,16,21,24],"shrt_max":1,"shuffl":[7,17],"shufflevector_index_out_of_rang":7,"sibl":11,"side":[0,6,7,9,10,11,16,21],"sig":[9,10],"sigint":[10,24],"sign":[0,2,3,7,9,10,11,14,15,16,22],"sign_extend_integer_valu":9,"signal":[0,1,23],"signatur":[3,7,10,11,14,16,18,21,23],"signed":[7,9,10,11,22],"signed_bit_field":10,"signed_bitint_width_too_smal":7,"signed_char":10,"signed_one_bit_field":7,"signed_unsigned_comparison":7,"signific":[0,2,3,8,9,10,11,14,15,16,17,18,21,23],"sigterm":[10,24],"silenc":[14,24],"silent":[10,24],"similar":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25,26],"similar_typedef":7,"simpl":[0,1,3,6,7,9,10,11,13,14,15,16,18,20,21,23,24,25],"simple_incompatible_param":7,"simpler":[9,11,15,16,18,24],"simplest":[9,11,15,17,21],"simpli":[0,1,2,3,4,5,6,8,9,11,14,15,16,17,18,21,23,24,25,26],"simplic":[9,24],"simplif":[9,16],"simplifi":[0,1,3,6,9,10,13,15,16,17,18,21],"simplify_curr_class_qualified_nam":6,"simplify_void_operand":9,"simplist":11,"simul":[2,6,9,10,23],"simultan":[10,18,23,24],"sin":10,"sinc":[0,1,2,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23],"sinf":10,"singl":[0,1,2,3,4,5,6,7,9,10,11,13,14,15,16,18,20,21,22,23,25,26],"single_arg_postfix_incr_decr_anachron":7,"singular":11,"sinl":10,"sit":10,"site":[1,9,10,15,16,21,23],"situ":15,"situat":[0,1,3,11,14,15,17,18,21,25],"six":10,"sixteen":15,"size":[0,1,2,3,6,7,8,9,10,11,13,14,15,16,17,21],"size_affected_by_tail_pad":7,"size_elem":16,"size_t":[1,7,9,10,16,21],"size_t_arg":14,"size_without_virtual_base_class":3,"sizeless":7,"sizeless_type_not_allow":7,"sizeof":[6,7,9,10,14,16,17,23],"sizeof_bit_field":7,"sizeof_funct":7,"sizeof_il_entri":11,"sizeof_operand_not_parameter_pack":7,"sizeof_pack_in_non_variadic_context":7,"sizeof_ref_or_interface_class":7,"sizeof_t":1,"sjis":[1,10,15],"sk":16,"sk_class_or_struct":3,"sk_class_or_struct_tag":23,"sk_class_templ":[3,21,23],"sk_concept_templ":23,"sk_constant":[3,23],"sk_extern_funct":21,"sk_extern_vari":21,"sk_field":3,"sk_function_templ":[3,21,23],"sk_keyword":21,"sk_macro":21,"sk_member_funciont":23,"sk_member_funct":[3,21,23],"sk_namespac":[6,21],"sk_namespace_project":[6,21],"sk_overloaded_funct":[3,21,23],"sk_paramet":21,"sk_project":[3,21],"sk_property_set":3,"sk_property_symbol":3,"sk_routin":[6,21,23],"sk_static_data_memb":[3,21,23],"sk_type":[6,23],"sk_union":3,"sk_union_tag":23,"sk_variabl":[21,23],"sk_variable_templ":23,"skip":[0,3,5,7,9,10,14,24],"skip_lexical_typeref":[11,14,22],"skip_paren":11,"skip_to_endif":15,"skip_typeref":[11,14,22],"skip_typerefs_not_typedef":[11,14,22],"skip_white_spac":[14,15],"skipped_inaccessible_funct":7,"slant":3,"sleight":16,"slice":[0,2,11,16,25],"slight":[0,2,3,9,10,11,15,16,20,21,22],"slot":16,"slow":0,"slower":[9,21],"slowest":[11,24],"slowli":24,"small":[0,1,3,7,9,10,11,14,15,16,17,18],"smaller":[7,10,11],"smallest":10,"smallhash":23,"smart":10,"sn":18,"snake":[4,5,9],"snapshot":[0,10],"snip":17,"snippet":14,"softfloat":9,"softwar":[9,14,16],"solari":[1,26],"solut":16,"solv":[0,11,16],"some_contain":4,"some_error_in_curr_direct":15,"some_func":4,"some_pragma":18,"somehow":15,"someth":[0,2,4,5,6,7,8,9,10,11,14,15,16,17,23,24],"something_els":4,"sometim":[1,3,5,6,8,9,10,11,14,15,17,18,20,21,23,25],"somewhat":[2,3,5,6,9,10,11,16,20,21,23,25],"somewher":[10,11,15,16,18,21,23],"soon":[9,10,11,16,18,23,25],"sooner":23,"sophist":[0,10],"sort":[0,3,5,6,7,11,15,16,18,23],"sought":[3,10,14,21,25],"sourc":[0,2,3,6,7,8,9,10,13,16,18,19,20,21,23,24,25,26],"source_corresp":[1,3,11,21,25],"source_corresp_for_il_entri":11,"source_line_modif_list":15,"source_loc":[7,12],"source_posit":21,"source_sequence_entri":11,"source_sequence_list":[11,21,22],"source_valu":17,"sourceloc":17,"sp":16,"sp_col_predefined_macro":15,"space":[0,2,3,4,7,8,9,10,11,14,16,17,21,22,23,25],"span":15,"spars":16,"spawn":24,"speak":[10,16,21,23],"spec":[16,17],"special":[0,3,5,6,7,8,9,10,11,14,15,16,17,18,22,25,26],"special_class_template_not_found":7,"special_function_kind":3,"special_kind":[3,11],"special_member_coroutin":7,"special_subscript_cost":[7,10],"specialization_follows_param_list":7,"specialization_of_called_inline_template_funct":7,"specialization_of_referenced_ent":7,"specialization_of_referenced_entity_po":7,"specialization_of_referenced_templ":7,"specialization_of_unscoped_enum":7,"specialization_out_of_namespac":7,"specialized_with_old_syntax":23,"specif":[0,2,3,5,7,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"specifi":[0,1,3,4,5,7,8,9,10,11,12,14,15,16,17,18,19,21,22,23,24,25,26],"specific_decl":23,"specific_def":23,"specific_symbol":[15,21],"specifiers_rang":11,"speed":[0,2,5,11,13,14,24],"speedup":10,"spell":[4,7,10,15,24],"spent":15,"sphinx":26,"spill":15,"spirit":11,"spite":[0,9,11,14],"splice":[7,10,11,15],"splice_is_not_a_member_of_class":7,"splicer":7,"split":[14,15,23],"split_token_cach":23,"sporad":14,"spot":[0,15,16,23],"spread":15,"sq":0,"squar":[6,7,10],"src":[1,16],"src_char":15,"src_seq":14,"src_seq_sublist_list":11,"srcloc_column_bound":7,"srcloc_line_bound":7,"ss":10,"st":[0,10],"stabil":17,"stabl":[0,24],"stack":[0,3,5,6,7,10,11,14,16,18,20,21,22,23,25],"stack_offset_of":7,"stack_referenced_include_directori":10,"stage":[16,21,25],"stage_0":17,"stage_1":17,"stage_2":17,"stage_3":17,"stage_4":17,"stage_5":17,"stage_6":17,"stage_6_0":17,"stage_6_1":17,"stage_6_2":17,"stage_6_3":17,"stand":[5,6,9,10,16,21,22],"standalon":[0,7],"standalone_il_display":1,"standalone_utility_program":22,"standard":[0,1,2,3,7,8,9,10,11,13,14,15,16,18,19,20,21,22,23,26],"standard_array_member_in_managed_class":7,"standard_class_member_in_managed_class":7,"standard_class_nested_in_managed_class":7,"star_this_capture_nonstandard":7,"star_this_not_constant_valu":7,"start":[0,1,2,3,4,6,7,8,9,10,11,14,15,16,17,18,19,20,21,23,24,25],"start_block_stat":20,"start_error":0,"start_for_init_block":20,"start_il_fil":0,"start_map_region":7,"start_map_region_ignor":7,"start_of_curr_token":15,"start_of_region":15,"start_secondary_declar":6,"start_stmt_claus":20,"startup":[11,16,26],"state":[0,1,7,8,9,10,11,14,15,16,17,21,23,25],"state_catcher_us":4,"statement":[0,2,3,5,6,7,8,10,13,14,15,16,18,21,23,25],"statement_expr_in_default_arg":7,"statement_expr_with_vla_typ":7,"statement_expression_in_function_on":7,"statement_expression_is_gnu_extens":7,"static":[0,2,4,6,7,8,9,10,11,14,15,17,19,20,21,22,26],"static_accessor_in_nonstatic_property_or_ev":7,"static_assert":[7,11,17],"static_cast":[9,16],"static_cast_conversion_poss":22,"static_constructor_member_templ":7,"static_constructor_with_named_overrid":7,"static_constructor_with_param":7,"static_conversion_function_must_have_one_paramet":7,"static_data_member_not_allow":7,"static_data_member_not_allowed_in_unnamed_class":7,"static_default_indexed_properti":7,"static_dimension_nonstandard":7,"static_extern_templ":7,"static_lambda_nonstandard":7,"static_lambda_with_captur":7,"static_literal_field":7,"static_member_next":3,"static_member_operator_not_allow":7,"static_nonstatic_with_same_param_typ":7,"static_not_allow":7,"static_storage_variable_with_handle_or_tracking_ref_typ":7,"static_storage_variable_with_ref_class_typ":7,"static_typ":16,"static_used_by_instanti":0,"static_variable_in_inline_funct":7,"static_with_explicit_thi":7,"statist":0,"statment":6,"status":[0,8,17,21],"stay":[9,15,25],"std":[1,7,9,10,11,12,16,17],"std_alignof_with_expr_arg":7,"std_attributes_en":18,"std_attributes_is_cpp11":7,"std_float128_not_support":7,"std_initializer_list_has_dtor":7,"std_meta_substitute_bad_arg_reflect":7,"std_meta_substitute_fail":7,"std_thread_local_storage_specifier_en":10,"stdarg":10,"stdc":7,"stdc_host":10,"stdc_iec_559":10,"stdc_iec_559_complex":10,"stdc_iso_10646":10,"stdc_iso_10646_valu":10,"stdc_mb_might_neq_wc":10,"stdc_pragma_not_allowed_her":7,"stdc_zero_in_system_head":10,"stddef":10,"stderr":[10,14],"stdexcept":12,"stdfloat":12,"stdh":12,"stdin":[0,10,26],"stdio":[0,8,10],"stdlib":24,"stdout":[0,1,10,14,24,26],"step":[0,1,5,8,9,10,15,16,17,18,21,23,25],"still":[0,1,2,3,4,5,7,8,9,10,11,14,15,16,18,21,23,26],"still_an_lvalu":9,"stl":[9,11],"stmk_asm":11,"stmk_block":[8,11],"stmk_decl":11,"stmk_end_test_whil":11,"stmk_expr":11,"stmk_for":[11,20],"stmk_for_each":11,"stmk_goto":11,"stmk_if":11,"stmk_init":[11,16],"stmk_range_based_for":20,"stmk_return":[11,16],"stmk_set_vla_s":[6,11,16],"stmk_switch":11,"stmk_switch_cas":[11,16],"stmk_try_block":[8,11,16],"stmk_vla_decl":[11,16],"stmk_while":11,"stmt_update_source_sequence_list":22,"stop":[4,6,9,10,11,14,15,21,24,25,26],"stop_map_region":7,"stop_map_region_ignor":7,"stop_token_array":14,"storag":[0,3,6,7,9,10,11,15,16,17,18,23],"storage_class_in_friend_decl":7,"storage_class_not_allow":7,"storage_class_not_allowed_in_speci":7,"storage_class_not_first":7,"storage_class_requires_function_or_vari":7,"storage_ptr":17,"storage_specifier_ignor":7,"storage_typ":17,"store":[0,2,3,5,7,8,9,10,11,15,16,17,18,21,22,23,24,25],"str":[0,4,6,7,10],"str_command_line_error":0,"str_error":14,"str_for":17,"str_for_integer_const":9,"straightforward":[0,1,2,3,5,10,11,15,16,21],"strang":[5,9,11,16],"strategi":20,"stray_carriage_return":7,"strchr":15,"stream":[3,23],"strength":10,"stress":[2,16],"strict":[0,6,7,10,11,15,16,18,21],"strict_ansi_discretionary_sever":0,"strict_ansi_error_sever":[0,14],"strict_ansi_mod":14,"strict_gnu":10,"strict_warn":10,"stricter":[10,23],"stricter_template_check":10,"stride":2,"string":[1,2,5,6,7,8,9,10,11,14,15,16,17,18,21,23,24,26],"string_literal_cannot_initialize_flexible_array_memb":7,"string_typ":22,"string_view":7,"stringent":10,"stringiz":15,"stringized_arg":15,"strip":11,"strip_local_typedef":22,"strive":0,"strlen":10,"strong":[7,21],"struct":[0,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,21,22,23,25],"struct_binding_constev":7,"struct_binding_constexpr":7,"struct_binding_in_condit":7,"struct_binding_incomplete_typ":7,"struct_binding_inlin":7,"struct_binding_lambda":7,"struct_binding_packs_is_cpp26":7,"struct_binding_private_memb":7,"struct_binding_restricted_storage_class":7,"struct_binding_storage_class":7,"struct_binding_templ":7,"struct_binding_undefined_identifi":7,"struct_binding_with_multiple_declar":7,"struct_bindings_is_cpp17":7,"struct_declspec_ignored_in_c_mod":7,"struct_not_allow":7,"struct_stmt_stack":[14,20],"struct_too_larg":7,"structur":[0,1,3,5,6,7,8,10,11,12,13,16,17,18,19,20,21,22,24,25,26],"stt_gnu_ifunc":16,"stu":23,"stuck":24,"stuctur":6,"studi":13,"studio":[1,7,10,17],"style":[0,2,3,6,7,9,10,11,14,15,16,18,22,23],"sub":[7,11,17,24],"subaggreg":6,"subblock":20,"subcas":[9,14,22],"subdirectori":[1,15,24],"subexpress":[9,16],"subfield":7,"subject":[0,1,3,6,9,10,11,15,16,18,21,23],"subkind":16,"sublist":[11,22],"subobj_copy_asgn_decl_suppress":7,"subobj_copy_ctor_decl_suppress":7,"subobject":[3,7,10,11,16,17],"subordin":15,"subordinate_templ":23,"subrang":15,"subroutin":[0,2,3,9,11,14,15,16,20,21,22],"subscop":[11,25],"subscript":[3,7,9,10,16],"subscript_mechanism_conflict":7,"subscript_or_padd_pointer_operand":11,"subscript_out_of_rang":7,"subsect":[1,10,11,15,17],"subsequ":[0,3,6,7,8,9,10,11,15,18,20,21,23],"subset":[1,3,10,13,14,21],"subsidiari":15,"subst_arg_is_not_vari":7,"substag":17,"substanti":[0,1,16],"substitut":[0,1,7,9,10,15,16,23,26],"substitute_template_argu":23,"substr":15,"substructur":11,"subsum":9,"subt":21,"subtl":[3,5,16,23],"subtleti":9,"subtract":[7,9,10,11,16],"subtract_integer_valu":9,"subtre":[0,16,22],"succeed":[9,15,16,23],"success":[0,6,9,11,14,16,17,21,23],"successor":11,"suffic":15,"suffici":[1,6,9,10,11,15,18,21,22],"suffix":[0,1,2,7,10,12,14,15,16,23,25],"suggest":[0,9,15,16],"suit":24,"suitabl":[1,2,7,9,10,16,18,21,22,26],"sum":7,"summar":[1,3,8,9,11,18,21],"summari":[0,9,14,17],"sun":[1,2,7],"sun_extensions_allow":[1,10],"sun_is_generated_code_target":1,"sun_linker_scop":10,"sun_target_version_numb":1,"sunwcch":10,"super":17,"super_after_scop":7,"super_not_in_class":7,"superflu":20,"superfluous_delegate_object":7,"supersed":7,"superset":[10,11,16],"supplement":[3,6,8,9,11,18,22,23,25],"supplementari":[21,26],"suppli":[0,1,6,7,10,11,12,15,16,18,19,21,23,26],"supplment":11,"support":[0,3,6,7,9,11,13,14,15,17,18,19,20,22,23,25,26],"suppos":[3,7,9,10,11,25],"suppress":[0,1,2,5,6,7,9,10,14,15,16,18,21,23,26],"suppress_inline_bodi":[11,23],"suppress_instantiation_flag":[10,26],"suppress_microsoft_attribute_process":6,"suppress_subsequent_include_of_fil":15,"suppress_vtbl":[10,16],"suppressed_dtor_need":7,"suppressed_module_error_diag":7,"suppressed_module_errors_diag":7,"suppressed_module_warning_diag":7,"suppressed_module_warnings_diag":7,"sure":[0,2,10,11,14,16,17,18,19,21,23,24,25],"surfac":17,"surpris":11,"surrog":7,"surround":[0,1,2,7,9,10,11,14,15,16,23],"surviv":[0,11,14],"suspect":7,"suspend":[6,9,23],"suspici":[7,10],"suspicious_comment_format":7,"suspicious_string_format":7,"svr4":[7,26],"svr4_token_pasting_com":7,"swallow":23,"swap":16,"sweep":[0,2,11,16,25],"swept":0,"switch":[0,1,7,9,10,11,14,15,16,17,18,20,22,23,25],"switch_break_label":11,"switch_il_region":22,"switch_selector_expr_is_const":7,"switch_stat":20,"switch_translation_unit":25,"sy":0,"sym":[0,6],"sym_add_diag_info":0,"sym_not_a_class_templ":7,"sym_not_a_templ":7,"sym_not_a_type_nam":7,"sym_tbl_init":0,"sym_update_source_sequence_list":[21,22],"symbol":[0,1,5,6,7,9,10,13,14,15,16,18,22,23,25,26],"symbol_for_member_funct":3,"symbol_projected_from_base_class":21,"symbol_ref":[3,6,14,21,22],"symbol_supplement_for_class":21,"symbol_t":21,"symbol_tbl":[3,14,15,21,23],"sync":[6,10],"synchron":7,"synonym":[10,14],"syntact":[3,6,7,8,11,14,15,17,18,23],"syntax":[0,3,6,7,9,10,11,13,15,16,18,23],"syntax_error":[0,9,14,15],"syntaxindex":17,"synth_namespace_projection_symbol":21,"synthes":[3,10,11],"synthesi":[7,9],"synthesized_namespace_project":21,"synthet":3,"sys_includ":[10,24],"sys_predef":[1,14],"system":[0,1,2,3,6,7,8,9,10,11,14,15,17,19,22,23,24,26],"system_head":7,"system_type_from_fundamental_typ":[6,22],"sz":16,"t":[0,1,2,3,4,5,6,7,8,9,10,11,14,16,17,18,20,21,22,23,24,25,26],"t1":[0,16,23],"t2":[0,10,16,23,24],"t3":[10,23],"t_c_ee131b0b":23,"tab":[4,10,11,14,15],"tabl":[0,3,5,6,7,8,9,10,14,15,17,18,19,23,24,25,26],"tack":10,"tag":[0,2,3,6,7,9,10,11,14,16,17,21,23,26],"tag_defined_in_constexpr_bodi":7,"tag_kind_incompatible_with_declar":7,"tag_kind_incompatible_with_template_paramet":7,"tag_redefined_differ":7,"tagless":[6,21],"tail":[7,11,15,21],"tak_start_of_pack_expans":23,"take":[0,1,2,3,4,6,7,8,9,10,11,14,15,16,17,18,21,23,24,26],"take_address_of_lvalu":9,"take_reference_to_operand":9,"taken":[0,1,3,7,9,10,11,14,15,16,17,18,23,24,25],"taking_address_of_temporari":7,"talk":16,"tall":10,"tandem":5,"tangut":15,"tantamount":3,"targ_":1,"targ_char_constant_first_char_most_signific":15,"targ_def":[2,11,14,16,23],"targ_external_names_get_underscore_ad":26,"targ_field_alloc_sequence_equals_decl_sequ":3,"targ_ia64_vtable_entry_int_kind":1,"targ_j":16,"targ_jmp_buf_element_float_kind":16,"targ_jmp_buf_elements_are_float":16,"targ_jmp_buf_num_el":16,"targ_little_endian":1,"targ_little_endian_win32":1,"targ_maximum_pack_align":10,"targ_minimum_pack_align":10,"targ_no_error_on_integer_overflow":10,"targ_optimize_empty_base_class_layout":3,"targ_ptrdiff_t_int_kind":1,"targ_supports_x86_64":10,"target":[2,3,6,7,8,9,10,11,13,14,15,16,18,19,22],"target_cfg":14,"target_configuration_":1,"target_map":14,"target_on_special_funct":7,"target_string_must_be_narrow":7,"target_unmatched_paren":7,"targeted_vers":11,"task":[3,6,11,14,15,16,22],"tcf_seek_corresp":25,"tear":0,"technic":[4,6,10],"techniqu":[0,2,3,4,6,11,13,14,15,16,18,21,23],"tell":[0,6,9,11,16,26],"temp":16,"temp_init_from_operand":9,"temp_stat":4,"temp_used_for_ref_init":7,"templ":7,"templ_param_list_not_allow":7,"templ_param_list_too_long":7,"templat":[0,1,6,7,9,13,14,17,18,22,24,25,26],"template_and_inline_function_wrapup":[23,25],"template_and_instance_linkage_conflict":7,"template_arg_cannot_point_to_subobject":7,"template_arg_list":[11,21,23],"template_argument_index_out_of_bound":7,"template_constraint_not_satisfi":7,"template_declar":23,"template_declaration_or_direct":3,"template_deleg":7,"template_dependent_design":7,"template_depth_mismatch":7,"template_directive_or_declar":[6,23],"template_directori":[10,23],"template_friend_definition_not_allow":7,"template_id_not_allow":7,"template_in_gener":7,"template_in_managed_class":7,"template_info":23,"template_info_fil":10,"template_instance_already_us":7,"template_missing_closing_brac":7,"template_not_allow":7,"template_not_in_templ":7,"template_operator_delet":7,"template_operator_new":7,"template_or_specialization_declar":23,"template_param_in_elab_typ":7,"template_param_pack_not_at_end":7,"template_parameter_capture_conflict":7,"template_parameter_has_class_typ":7,"template_parameter_has_nonstructural_class_typ":7,"template_speci":23,"template_static_data_member_init_guard_cod":16,"template_sym":23,"template_template_param":23,"template_template_param_same_name_as_templ_param":7,"template_typedefs_in_diagnost":10,"templates_cleanup":0,"templates_in_embedded_cplusplus":7,"templk_concept":23,"temporari":[0,2,3,6,7,8,10,20,22],"temporarili":[3,10,11,15],"tempt":0,"ten":[7,15],"tend":[0,2,10,15],"tentat":[0,2,6,8,10,11,16,23],"tentative_type_lookup":21,"tera":16,"term":[0,3,4,8,9,10,11,14,15,16,17,18,23],"term_compil":0,"term_stmt_claus":20,"termin":[0,1,4,7,8,9,11,14,15,16,18,20,21,26],"terminate_curr_block_object_lifetim":20,"terminate_macro_text_map":15,"terminolog":23,"ternari":10,"terribl":[15,22],"terse_static_assert":7,"terse_static_assert_not_en":7,"test":[0,1,2,3,7,9,10,11,12,14,15,16,17,20,22,23],"test_":24,"test_bitmask":17,"test_fil":24,"test_nam":[10,24],"test_numb":24,"test_root":24,"test_run_timestamp":24,"test_runs_directori":24,"test_valu":17,"testabl":16,"tex":26,"text":[0,1,5,6,7,8,9,10,11,14,18,23,26],"textoffset":17,"textual":[5,10,11,13,14,16,23],"tf":17,"tgmath":10,"thank":14,"themselv":[0,9,10,11,14,15,16,17,23,24],"theori":[13,14,16,17],"thereaft":[0,9,11,25],"therebi":[3,10,16,21],"therefor":[0,1,2,3,6,8,9,10,11,14,15,16,18,22,23,25],"therein":[10,11,16],"thereof":[10,15,16,23],"thing":[0,1,2,3,4,5,6,8,9,10,11,14,15,16,17,18,19,21,22,23,25,26],"thingi":4,"thingy_help":4,"think":[5,14,23],"third":[2,6,7,8,10,17,20,23,25],"thirti":15,"this_in_lambda":7,"this_not_const":7,"this_temp":16,"this_used_incorrect":7,"thiscall_requires_nonstatic_memb":7,"thorough":14,"though":[0,2,3,5,6,8,9,10,11,14,15,16,17,18,20,21,23,25],"thought":[3,17,21,23],"thousand":[0,9,10,15],"thread":[7,10,11,16],"thread_loc":[7,10],"thread_local_dynamic_init_routin":16,"thread_local_follows_non_thread_loc":7,"thread_local_ignor":7,"thread_local_must_include_static_or_extern":7,"thread_local_not_allow":7,"thread_local_storag":10,"thread_local_wrapper_for_vari":16,"threads_constant_not_allow":7,"threads_dimension_requires_definite_block_s":7,"three":[0,1,3,5,6,7,8,9,10,11,14,15,16,21,22,23,25],"threshold":[0,10],"throughout":[0,9,11,14,15,18],"throw":[1,7,9,14,15,22],"thrown":[7,9,11,15,16,21],"thunk":16,"thus":[0,3,5,6,7,10,11,14,15,16,17,18,21,23,24],"thusli":16,"thwart":15,"ti":[10,23],"tie":[0,1,9,10,11,15,21],"tiebreak":[7,10],"tight":9,"tild":15,"tildize_loc":21,"till":[6,10,20,21],"tim_al":23,"tim_loc":23,"tim_non":23,"tim_us":23,"time":[0,2,3,6,7,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"timeout":24,"timeout_second":24,"timestamp":[0,24],"tinfo":16,"tk_class":[3,21],"tk_complex":11,"tk_float":11,"tk_imaginari":11,"tk_pointer":[6,11],"tk_ptr_to_memb":[11,16],"tk_routin":22,"tk_struct":[3,21],"tk_template_param":[11,23],"tk_typeref":[6,11,14,18],"tk_union":[3,21],"tk_unknown":[3,11],"tl":16,"tlocal":10,"tls_model":7,"tm":16,"tmp":[10,24],"tmpdir":10,"tnm":23,"tnnnn":2,"tnone":10,"to_bitmask_0_33":17,"to_partition_kind":17,"to_to_":22,"to_universal_index":17,"to_universal_sort":17,"to_x":17,"togeth":[0,3,4,6,9,10,11,14,15,16,17,18,23,24,26],"toggl":8,"tok_":2,"tok_digit_sequ":15,"tok_end_of_sourc":[15,18,23],"tok_header_nam":15,"tok_identifi":[15,21],"tok_lparen":15,"tok_newlin":15,"tok_ptr_to_memb":15,"toke":15,"token":[0,2,3,5,6,7,9,10,11,14,18,20,21,23],"token1":18,"token2":18,"token3":18,"token_ends_expr":9,"token_sequence_needs_double_caret":7,"told":[0,10,15,21],"too_few_args_for_oper":7,"too_few_argu":7,"too_few_array_bound":7,"too_few_generic_arg":7,"too_few_macro_arg":7,"too_few_printf_arg":7,"too_few_template_arg":7,"too_few_template_param":7,"too_large_to_inlin":7,"too_many_args_for_convers":7,"too_many_args_for_oper":7,"too_many_argu":7,"too_many_arguments_provided_for_attribut":7,"too_many_array_bound":7,"too_many_cast_operand":7,"too_many_charact":7,"too_many_constraint":7,"too_many_generic_arg":7,"too_many_initializer_valu":7,"too_many_macro_arg":7,"too_many_ms_attr_arg":7,"too_many_parameters_for_literal_oper":7,"too_many_params_for_destructor":7,"too_many_params_for_fin":7,"too_many_printf_arg":7,"too_many_struct_bind":7,"too_many_template_arg":7,"too_many_template_argu":7,"too_many_template_param":7,"too_many_unused_instanti":7,"too_many_virtual_funct":7,"took":24,"tool":[1,10,11,14,16,17,26],"toolset":1,"top":[0,3,5,6,7,8,9,10,11,15,16,18,20,22,23,24,25],"top_dir":24,"top_templ":10,"topic":6,"topmost":[9,11],"toption":6,"tostr":9,"total":[0,7,10,15,16,17,24],"total_error":14,"toward":[1,10],"tp":1,"tr":[9,10,11],"tr39":15,"trace":[0,1,10,11,14,15],"trace_corresp_ptr":25,"trace_includ":10,"track":[1,3,5,6,7,8,9,10,11,16,21,22,23,25],"tracker":15,"tracking_ref_to_const":7,"tracking_reference_member_in_standard_class":7,"tracking_reference_to_deleg":7,"tracking_reference_to_enum":7,"tracking_reference_to_funct":7,"tracking_reference_to_system_str":7,"tracking_reference_to_value_class":7,"trade":10,"tradeoff":8,"tradit":[0,1,3,6,9,10,11,13,18],"trail":[2,4,6,7,10,15,16,18,23],"trailing_requires_clause_not_on_templ":7,"trailing_requires_on_virtual_func":7,"trailing_return_type_function_without_simple_auto":7,"trailing_return_type_in_nested_declar":7,"trailing_return_type_requires_auto":7,"trait":[7,10,11,16,17],"tran":[0,25],"trans_copi":[14,25],"trans_corresp":[10,14,18,25],"trans_unit":[14,25],"trans_unit_copy_address_of":25,"trans_unit_corresp":25,"trans_unit_for_scop":25,"transfer":[6,7,8,9,11,16,18,20,21],"transform":[1,5,6,11,14,15,16,17,22],"transient":9,"transit":[0,9,10,11,14,15,17,20,21],"translat":[0,1,2,3,6,7,9,11,13,14,15,16,17,18,20,21,23,26],"translation_unit":[0,6],"translation_unit_wrapup":25,"transpar":[6,7,9,17],"transparent_attribute_ignor":7,"transparent_type_is_not_union":7,"transparent_union":7,"transparent_union_cannot_have_bit_field_first":7,"transparent_union_cannot_have_floating_first_field":7,"trap":10,"travers":[2,3,5,6,8,9,11,16,17,18,21,22,23,25],"traverse_addressing_subtre":11,"traverse_and_modify_type_tre":22,"traverse_const":11,"traverse_dynamic_init":11,"traverse_expr":[0,11],"traverse_stat":[0,11],"traverse_type_tre":[11,22],"treat":[0,3,6,7,9,10,11,15,16,17,21,23,25,26],"treatment":[3,10,15,16,18,21,23],"tree":[0,1,2,3,5,6,9,10,11,13,14,16,20,23,24,25],"tri":[0,3,7,9,10,11,13,14,15,16,17,20,23,25,26],"trick":[0,23],"tricki":[9,16,20],"trigger":[3,4,10,11,18,23,25],"trigraph":[7,10,11,15],"trigraph_ignor":7,"trim":[0,9],"triplet":16,"trivial":[3,4,6,7,9,10,14,17],"trivial_const_or_volatile_properti":7,"trivial_default_constructor":3,"trivial_indexed_properti":7,"trivial_reference_properti":7,"trk_is_template_alia":23,"troubl":15,"troublesom":11,"true":[0,1,3,4,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,25,26],"truli":[0,3,9,11,16,17],"truncat":[2,7,9,10,15],"try_block_stat":[8,20],"try_builtin_operands_match":9,"try_conversion_function_match_ful":9,"try_conversions_for_builtin_oper":9,"try_op":4,"try_overloaded_function_match":9,"try_pointer_builtin_operands_match":9,"try_static_conversion_function_match":9,"try_string_literal_init":6,"try_to_convert_class_operand_to_builtin_typ":9,"ts":24,"tsr":0,"ttparam":16,"tune":10,"tupl":[7,11],"tuple_el":7,"tuple_get_no_matching_overload":7,"tuple_index_overflow":7,"tuple_s":7,"turn":[0,2,3,5,6,8,9,10,11,15,16,17,18,20,21,22,23,24,25,26],"turn_class_definition_into_declar":[0,11],"tuse":10,"tw":16,"twice":[2,3,9,11,18],"twist":6,"two":[0,1,2,3,4,6,7,8,9,10,11,14,15,16,17,19,20,21,22,23,24,25],"two_packs_in_fold_express":7,"tx":15,"txt":[0,1,14,15,24,26],"ty":[0,16],"ty2":0,"typ":16,"type":[1,2,5,7,8,10,14,15,17,19,20,21,23,24,25,26],"type_after_bit_field_integral_promot":[9,22],"type_after_integral_promot":[9,22],"type_as_subobject":16,"type_cannot_be_class_memb":7,"type_cannot_be_param_nam":7,"type_change_const":9,"type_change_constant_ful":9,"type_code_arithmet":7,"type_code_bool":7,"type_code_bool_equival":7,"type_code_class":7,"type_code_enum":7,"type_code_handl":7,"type_code_handle_to_cli_array":7,"type_code_integ":7,"type_code_non_bool_arithmet":7,"type_code_nullptr_typ":7,"type_code_point":7,"type_code_pointer_to_funct":7,"type_code_pointer_to_memb":7,"type_code_pointer_to_object":7,"type_code_scoped_enum":7,"type_constraint_fail":7,"type_constraint_requires_type_concept":7,"type_decl_in_anon_union":7,"type_def_not_allowed_in_func_type_decl":7,"type_definition_not_allow":7,"type_generic_function_mismatch":7,"type_identifier_not_allow":7,"type_info":[1,8,12,16],"type_is_declared_abstract":7,"type_is_interfac":7,"type_kind":11,"type_masks_handler_param_typ":8,"type_must_be_integr":7,"type_must_be_object_typ":7,"type_must_be_trivially_copy":7,"type_nam":[6,9,15],"type_name_ful":6,"type_not_allowed_her":7,"type_not_arithmetic_or_enum_or_point":7,"type_not_arithmetic_or_unscoped_enum_or_point":7,"type_not_point":7,"type_not_satisfi":7,"type_not_scalar":7,"type_pack_element_cannot_match":7,"type_pointed_to":22,"type_ptr":3,"type_qualifier_ignor":7,"type_qualifier_ignored_on_constructor":7,"type_qualifier_not_allow":7,"type_qualifier_on_lambda":7,"type_qualifier_on_void_return_typ":7,"type_qualifiers_ignored_on_refer":7,"type_specifier_not_allow":7,"type_start_error":0,"type_symbol_typ":21,"type_traits_help":10,"type_with_named_address_space_not_allow":7,"type_with_no_linkage_in_funct":7,"type_with_no_linkage_in_template_arg":7,"type_with_no_linkage_in_var_with_linkag":7,"typedef":[0,2,3,5,6,7,9,10,11,14,15,16,18,21,22,23],"typedef_cannot_be_param_nam":7,"typedef_in_elab_typ":7,"typedef_modification_is_nonstandard":7,"typedef_not_allow":7,"typedesign":17,"typefundament":17,"typeid":[7,8,9,10,22],"typeid_expr":16,"typeid_needs_typeinfo":7,"typeid_of_incomplete_typ":7,"typeid_of_managed_typ":7,"typeindex":17,"typeinfo":[1,7,8,12,16],"typenam":[3,4,7,10,11,15,16,21,23],"typename_need":7,"typename_not_in_templ":7,"typeof":[7,10,11,16],"typeof_is_gnu_extens":7,"typeof_unqu":10,"typepoint":17,"typeref":23,"types_are_both_pointers_or_both_handl":22,"types_are_compat":22,"types_must_have_same_s":7,"typesort":17,"typic":[0,1,3,6,8,9,10,11,15,16,17,18,20,21,23,24,26],"typo":22,"u":[0,2,7,10,11,15,16,23,26],"u00d6":11,"u1":23,"u2":23,"u8":10,"uax44":15,"ucd":15,"uchar_max":1,"ucn":[11,15],"ucn_names_basic_char":7,"ucn_names_invalid_code_point":7,"ucn_names_surrogate_code_point":7,"ucn_tabl":15,"ud":[15,16],"ud_lit_op_sym_for_cur_token":15,"ud_lit_op_sym_for_curr_token":15,"ud_string_suffix_mismatch":7,"udl_cannot_be_class_memb":7,"ugli":[9,11],"ui":16,"uint16":7,"uint32":7,"uint32_t":17,"uint64":7,"uint8":7,"uint8_t":17,"ulimit":24,"uliter":10,"ull":10,"ulong_max":1,"ultim":[3,6,9,11,15,23],"um16":16,"umlaut":15,"un":[3,15,23],"unabl":[7,8,9],"unable_to_get_mapped_memori":7,"unable_to_get_mapped_memory_reason":7,"unalias":11,"unalign":17,"unaligned_qualifier_drop":7,"unalt":[0,16,26],"unambigu":[11,14,16,18,21],"unari":[7,9,11,16],"unary_oper":9,"unassert":[10,15],"unattach":[11,16],"unattached_attribut":7,"unavail":7,"unavailable_attr":7,"unavailable_ent":7,"unavailable_entity_with_custom_messag":7,"unbalanced_attribute_argu":7,"unbind_object_lifetim":22,"unbound":[7,22],"unbounded_constexpr_ctor_init_recurs":7,"unbox":[9,22],"unbox_after_indirection_if_requir":9,"unboxing_conversion_poss":22,"unbundl":9,"unbundle_init_component_express":9,"uncallable_elided_cctor":7,"uncaught":8,"unchang":[0,15,16,26],"unclos":[7,10,14,15],"unclosed_str":7,"unclosed_va_opt":7,"uncommon":15,"uncompress":16,"uncondit":[7,10,18],"unconstrain":23,"unconvent":16,"unconvert":11,"unconvertible_con_expr":7,"und":23,"undeclar":10,"undeclared_paramet":7,"undef":[5,7,11,21],"undefin":[7,9,10,14,15,17,22,23,26],"undefine_macro":10,"undefined_decl_using_local_typ":7,"undefined_decl_using_no_linkage_typ":7,"undefined_identifi":7,"undefined_ifc_partit":7,"undefined_preproc_id":7,"undefined_static_function_treated_as_extern":7,"undefinit":[7,23],"undergo":[9,10,16,23],"underlying":[0,2,6,7,9,10,11,14,16,17,20,22,23,24],"underlying_array_element_typ":22,"underlying_type_of_derived_typ":22,"underneath":11,"underscor":[1,4,7,10,16,18,26],"understand":[1,9,11,17],"understood":[15,17],"undesir":[15,18],"undetermin":7,"undetermined_const":7,"undetermined_templ":7,"undetermined_typ":7,"undifferenti":16,"undo":[11,15],"undon":15,"unduli":2,"unevalu":[7,9,11],"unexpand":[11,15],"unexpect":[7,8],"unexpected_condit":[0,14],"unexpected_condition_str":0,"unexpected_design":7,"unexpected_end_of_default_arg":7,"unexpected_template_arg_list":7,"unexpected_type_for_size_t":7,"unfinished_base_class":7,"unfold":9,"unfortun":[0,3,10,11,26],"unget_token":15,"unhandled_ifc_construct":7,"unicod":[1,7,9,10,11,14,24],"unicode_name_fsm":[14,15],"unicode_name_not_found":7,"unicode_source_kind":[1,10,15],"unicode_source_support":[1,11,15],"unicode_vulnerability_checking_support":10,"unicodedata":15,"unifi":[10,15],"uniform":14,"unimplemented_keyword":7,"uniniti":[6,7,9,10,11,14,16],"uninitialized_base_class_with_const_memb":7,"uninitialized_field_with_const_memb":7,"uninitialized_var_in_constexpr_funct":7,"uninstanti":23,"unintend":[7,24],"uninterpret":[0,10,11,18],"union":[0,2,3,5,6,7,10,14,17,21,22],"union_already_initi":7,"union_as_struct":14,"union_bas":7,"union_cannot_be_transpar":7,"union_cannot_be_transparent_sym":7,"union_constexpr_constructor_initializes_no_field":7,"union_nonunion_mismatch":7,"uniqu":[1,3,8,10,11,14,16,17,21,22,23,25],"unit":[0,1,2,3,5,6,7,11,14,15,16,17,18,21,23,24],"uniterable_reflection_rang":7,"universal":[7,11,15,16,17],"unix":[0,1,2,9,10,23,26],"unknow":9,"unknown":[3,6,7,9,10,11,14,16,17,20,21,22,23],"unknown_ifc_partit":7,"unknown_ifc_partition_convers":7,"unknown_typ":[7,22],"unless":[0,3,4,6,7,9,10,11,12,14,16,20,21,22,23,24],"unlik":[0,1,3,4,6,7,9,10,11,14,15,16,17,18,21,23],"unlink_src_seq_entri":22,"unlink_symbol_from_symbol_t":21,"unlow":[1,8,10,11,16,21],"unmangl":16,"unmatch":7,"unmodifi":16,"unnam":[0,1,2,3,5,6,7,8,10,11,16,18,21,22,23,25],"unnamed_class_virtual_function_def_miss":7,"unnamed_cli_managed_class_typ":7,"unnamed_field_symbol":3,"unnamed_object_with_uninitialized_field":7,"unnamed_require_expr_param":7,"unnamed_scoped_enum":7,"unnamed_tag_symbol_head":21,"unnamed_type_in_template_arg":7,"unnecessari":[9,15,16,17,21],"unneed":[0,10,11,25],"unord":[7,23],"unpack":[1,9],"unparenthes":[7,16],"unpars":23,"unprint":0,"unprocess":[2,18],"unprototyp":[2,7,11],"unqual_function_with_qual_object":7,"unqual_named_function_with_qual_object":7,"unqualifi":[3,10,11,15,21],"unqualified_sup":7,"unreach":[7,16,20],"unread":16,"unrec_embed_param":7,"unrecog":11,"unrecogn":[6,7,9,11,15,18],"unrecognized_attribut":7,"unrecognized_char_escap":7,"unrecognized_format_function_typ":7,"unrecognized_gcc_pragma":7,"unrecognized_gcc_visibility_pragma":7,"unrecognized_microsoft_comment_pragma_typ":7,"unrecognized_ms_attr":7,"unrecognized_pragma":7,"unrecognized_stdc_pragma":7,"unrecognized_target_attribut":7,"unrecognized_upc_pragma":7,"unrecognized_vis":7,"unreferenc":[2,7,11,16,23],"unreferenced_function_param":7,"unrel":[10,17,23],"unreli":17,"unrepres":3,"unrepresent":11,"unresolv":[3,10,23],"unrestrict":[7,10],"unrestricted_union":10,"unrestricted_unions_is_cpp11":7,"unrol":7,"unsaf":[7,17],"unsatisfactori":16,"unsatisfi":24,"unscan_attribut":18,"unscop":[7,11],"unsequenc":7,"unsequenced_use_of_vari":7,"unset":[10,16],"unshar":11,"unsign":[0,7,9,10,11,14,15,16,17],"unsigned_bit_field":10,"unsigned_bitint_width_too_smal":7,"unsigned_char":10,"unsigned_compare_with_neg":7,"unsigned_compare_with_zero":7,"unsigned_enum_bit_field_with_signed_enumer":7,"unsigned_fixed_point_neg":7,"unsigned_value_of_integer_const":9,"unspeci":25,"unspecifi":[6,7,10,11],"unspecified_reflect":7,"unsubscript":7,"unsupport":7,"unsupported_ifc_file_arch_info":7,"unsupported_ifc_file_version_info":7,"unsupported_il_to_ifc":7,"unsupported_type_for_bit_cast":7,"untermin":7,"unterminated_delimited_escap":7,"unterminated_unicode_nam":7,"unus":[0,10,17,21,22],"unusable_pack":7,"unused_dereference_of_ref_class":7,"unusu":[0,3,8,9,11,14,15,16,18,20,21,24],"unwind":20,"unwind_stack_before_calling_termin":8,"unwit":10,"unwound":[8,16],"unwrap":17,"upc":[7,10,11,20],"upc_blocksizeof":7,"upc_foral":[7,20],"upc_relax":10,"upc_shared_void_comparison":7,"upc_strict":10,"upc_thread":10,"updat":[0,1,3,8,9,10,11,14,15,16,17,18,21,22,23,24,25,26],"update_inline_function_flag":23,"update_instantiation_required_flag":23,"update_source_sequence_list":22,"update_template_param_symbol":23,"upon":[10,15,17,18,20,23],"upper":[14,16],"uppercas":4,"upsid":18,"upward":11,"url":15,"usabl":[3,9,16,24],"usag":[7,17,24],"use":[2,4,5,7,8,9,12,13,14,15,16,17,18,19,20,22,23,24,25,26],"use_edg_namespac":14,"use_field_initi":[6,11],"use_fixed_address_for_mmap":[0,10],"use_hide_by_sig_lookup":[9,21],"use_host_fp_convers":9,"use_host_fp_conversion_routin":[9,14],"use_init_section_in_generated_c":16,"use_lazy_initialization_for_thread_local_vari":16,"use_mmap_for_memory_region":10,"use_mmap_for_modul":17,"use_of_generic_class_with_pending_constraint":7,"use_of_non_prototype_func_declar":7,"use_of_undefined_function_with_deduced_return_typ":7,"use_own_sjis_multibyte_char_process":1,"use_pch":[0,10],"use_softfloat":9,"use_system_includ":24,"use_x86_function_multivers":16,"used_before_set":7,"used_in_except":8,"used_in_exception_or_rtti":22,"useless":[9,20],"useless_decl":7,"useless_placement_delet":7,"useless_type_qualifi":7,"useless_type_qualifier_on_return_typ":7,"useless_type_qualifiers_in_type_nam":7,"useless_using_declar":7,"user":[0,1,2,6,7,11,14,15,16,23,24,26],"user_control_of_struct_pack":10,"user_convert_operand":9,"user_defined_conversion_poss":9,"user_defined_liter":10,"user_defined_literals_en":15,"usher":16,"using_attribute_nonstandard":7,"using_decl":6,"using_decl_conflicts_with_prev_decl":7,"using_decl_in_embedded_cplusplus":7,"using_direct":6,"using_directives_appli":21,"using_directori":10,"using_driv":[1,10],"using_enum_conflict":7,"using_enum_redecl":7,"using_framework_directori":10,"using_lvalu":9,"using_not_at_file_scop":7,"using_or_access_declaration_in_managed_class":7,"using_out_of_scope_declar":7,"using_pch":7,"using_std":[10,12],"usk_non":15,"usl":[10,16,19,26],"usr":10,"usr_includ":10,"usual":[0,1,3,4,5,6,7,9,10,11,14,15,16,18,20,21,22,23,25,26],"utf":[1,7,10,11,14,15],"utf16_char_lit_too_long":7,"utf8_char_lit_too_long":7,"utf8_char_liter":10,"utf8_lit_no_ulit":7,"util":[0,2,6,9,10,13,14,16,17,22,23],"uu":16,"uuid":7,"uuidof_requires_uuid_class_typ":7,"v":[1,2,3,10,11,15,16,18,26],"v1":23,"va_arg":7,"va_arg_would_have_been_promot":7,"va_args_not_allow":7,"va_copi":7,"va_end":7,"va_opt_not_allow":7,"va_start":[7,10],"va_start_requires_ellipsis_funct":7,"vacuous":[3,10,15,16,21],"vacuous_destructor_not_cal":7,"vagu":[9,11],"val":[7,10],"valid":[0,3,5,6,7,8,9,10,11,14,15,16,18,21,22,23,24,26],"valid_address_const":9,"valid_node_if_subscript":9,"valu":[0,1,3,5,6,7,8,9,10,14,15,18,19,20,21,22,23,24,25,26],"value__":7,"value_class_not_satisfi":7,"value_has_been_set":21,"value_init_of_funct":7,"value_init_of_incomplet":7,"value_init_of_refer":7,"value_init_of_sizeless_typ":7,"value_initi":9,"value_of_integer_const":9,"value_of_pragma_pack_show":7,"value_returned_in_constructor":7,"value_returned_in_void_funct":7,"valuetyp":3,"var":3,"var_addr_expr":22,"var_initi":[0,14],"var_lvalue_expr":22,"var_retained_incomp_typ":7,"var_rvalue_expr":22,"var_used_as_destructor":7,"var_used_as_fin":7,"var_with_uninitialized_field":7,"var_with_uninitialized_memb":7,"var_with_virtual_bases_in_constexpr_funct":7,"vararg":[6,10,15],"vararg_clrcal":7,"vararg_thiscal":7,"vari":[8,10,11,16,22,24],"variabl":[1,2,3,5,7,8,9,14,17,18,19,20,21,22,24,25],"variable_align_attr_not_on_definit":7,"variable_hides_ent":7,"variable_not_constant_address":7,"variable_not_constant_valu":7,"variable_remappings_for_inlin":16,"variable_templ_function_typ":7,"variable_template_prototype_instanti":23,"variable_templates_is_cpp14":7,"variable_with_interface_typ":7,"variably_modified_type_not_allow":7,"variably_modified_type_not_allowed_her":7,"variad":[6,7,9,10],"variadic_macro":10,"variadic_templ":10,"variant":[0,1,3,7,9,10,11,14,15,16,17,18,19,23],"variat":[0,1,3,6,9,14,23],"varieti":[1,6,8,10,17],"various":[0,1,3,5,6,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"vax":1,"vcmeta":10,"vcmeta_directori":10,"ve":[0,24],"vec":18,"vec_delet":8,"vec_new":8,"vector":[0,2,6,7,11,18],"vector_element_type_mismatch":7,"vector_length_too_larg":7,"vector_of_boolean_requir":7,"vector_operation_requires_integer_vector":7,"vector_s":[7,18],"vector_size_attribute_on_complex_typ":7,"vector_size_attribute_on_enum_typ":7,"vector_size_attribute_requires_integral_floating_or_enum_typ":7,"vector_size_must_be_multiple_of_element_s":7,"vector_size_must_be_power_of_two":7,"vector_size_too_larg":7,"vector_template_paramet":7,"vector_type_requir":7,"vector_type_with_size_is_requir":7,"vector_types_differ_in_length":7,"vectors_must_have_same_s":7,"vendor":[3,16],"verbatim":[5,17,24],"verbos":[10,26],"veri":[0,1,2,3,4,5,6,7,9,10,11,14,15,16,17,23,24],"verif":25,"verifi":[0,1,6,9,10,14,15,23,25],"verify_":25,"verify_generic_arg_list_satisfies_constraint":23,"verify_standalone_attribut":6,"verify_template_nontype_arg":23,"verify_that_all_pp_ifs_were_clos":15,"versa":[3,7,9,14,17,24],"version":[0,1,2,4,7,8,9,10,11,12,14,16,18,19,21,22,23,24,25,26],"versus":14,"very_fals":4,"very_long_long_long_long_foo":4,"very_long_long_long_long_long_foo":4,"via":[0,1,3,4,6,7,8,9,10,11,14,15,16,17,21,22,23,24,25],"viabl":[7,9],"vice":[3,7,9,14,17,24],"view":[1,9,10,11,16,20,23,25],"violat":[0,8,9,10],"virtual":[2,5,6,7,8,9,10,14,19,21,23],"virtual_base_for_managed_class":7,"virtual_function_cannot_have_deduced_return_typ":7,"virtual_function_decl_hidden":7,"virtual_function_info_offset":3,"virtual_function_never_defin":7,"virtual_function_table_should_be_defined_her":16,"virtual_function_templ":7,"virtual_has_no_effect":7,"virtual_ignor":7,"virtual_inline_never_defin":7,"virtual_not_allow":7,"virtual_required_for_base_overrid":7,"virtual_required_for_interface_implement":7,"virtual_static_ev":7,"virtual_static_event_accessor":7,"virtual_static_not_allow":7,"virtual_static_properti":7,"virtual_static_property_accessor":7,"virtual_with_explicit_thi":7,"visibility_specifier_on_nested_typ":7,"visibility_specifier_requires_definit":7,"visibl":[3,7,8,9,10,11,14,16,21,23],"visit":[0,16,21,22],"visual":[1,4,7,10,15,17,24],"vla":[6,7,8,10,16],"vla_allow":[10,11,19],"vla_deallocations_in_il":11,"vla_in_return_typ":7,"vla_in_statement_expr":7,"vla_is_nonstandard":7,"vla_is_not_auto":7,"vla_not_allow":7,"vla_size_ignor":7,"vla_type_in_template_arg":7,"vla_with_unspecified_bound_not_allow":7,"vlas":[10,11,16],"vms":1,"void":[0,2,3,4,5,6,7,8,10,11,14,16,18,20,21,22,23],"void_named_regist":7,"void_param_not_allow":7,"void_property_index_typ":7,"void_template_paramet":7,"void_template_vari":7,"void_throw":7,"void_typ":22,"volatil":[2,3,7,10,11,16,21,22,24],"volatile_asm_is_gnu_extens":7,"volatile_ass_deprec":7,"volatile_dec_deprec":7,"volatile_func_param_deprec":7,"volatile_inc_deprec":7,"volatile_op_ass_deprec":7,"volatile_return_type_deprec":7,"volatile_str_bind_deprec":7,"volatile_type_not_allow":7,"volumin":10,"vptr":16,"vs":[15,18,24],"vt":23,"vtabl":16,"vtbl":14,"vtbl_temp":16,"vtt":16,"vv":16,"vvvvvvvvvv":16,"w":[10,16,24],"wait":[3,18,24],"walk":[0,2,11,14,15,16,22,25],"walk_declarative_entities_in_scop":0,"walk_entri":[0,11,14],"walk_entry_and_subtre":0,"walk_entry_routine_nam":11,"walk_file_scope_il":0,"walk_list":11,"walk_list_on_link_field":11,"walk_orphaned_entry_routine_nam":11,"walk_ptr":11,"walk_routine_scope_il":0,"walk_string_entri":0,"want":[0,2,9,10,11,14,15,16,18,23,24],"warn":[0,6,7,9,10,11,14,18,20,21],"warn_unused_result":[7,18],"warn_unused_result_with_void_return":7,"warning_direct":7,"warrant":[3,11],"wasn":[10,24,26],"wast":[14,21],"watch":16,"way":[0,1,2,3,4,5,6,7,9,11,14,15,16,17,18,19,21,22,23,24,25,26],"wc":10,"wchar_t":[7,9,10,15,16],"wchar_t_keyword":10,"wdir":10,"weak":[7,10,16,23],"weaken":[7,10],"web":[9,10,15],"websit":10,"weight":10,"weirder":11,"well":[0,1,2,3,5,6,8,9,10,11,13,14,15,16,17,18,20,21,23,24,25],"went":6,"wg21":9,"whatev":[3,9,10,11,18,23],"whenev":[0,8,9,10,11,15,16,21,23],"wherea":[1,3,6,9,10,11,14,18,21,23],"wherebi":[3,21,23],"wherev":[11,15,23],"whether":[0,1,3,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,25,26],"whi":[11,15,16],"which_binary_oper":9,"whichev":[11,23],"while_stat":20,"white":[7,10],"white_space_inside_splic":7,"white_space_required_after_macro_nam":7,"whitespac":0,"whole":[1,3,5,11,16,21],"whose":[0,1,3,4,6,7,8,9,10,11,14,15,16,21,23,24,25],"wide":[2,7,9,10,11,15,16],"wide_deprecation_str":7,"wide_string_invalid_in_asm":7,"wide_string_not_allow":7,"widen":7,"width":[3,4,7],"wiki":16,"will":[0,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],"win32":[1,7],"win32_api_error":7,"window":[0,7,9,11,14,15],"winrt":1,"wise":14,"wish":11,"within":[0,3,4,5,6,7,8,9,10,13,14,15,16,17,18,20,21,22,23,24,25,26],"without":[0,1,2,3,5,6,7,8,9,10,11,12,14,15,16,18,20,21,23,24,25,26],"won":[5,10,16,17],"word":[2,6,8,9,10,11,15,16,17,20,21,23,24],"work":[0,1,2,3,6,7,9,10,11,12,13,14,15,16,17,19,21,22,23,24,25,26],"world":[10,15,16],"worri":[10,16,23],"wors":[0,9,16,24],"worth":[0,23],"worthwhil":9,"wouldn":[2,11,18],"wrap":[0,2,10,11,14,16,24],"wrap_diagnost":10,"wrap_up_file_scop":25,"wrapper":[2,9,11,17],"wrapup":23,"wrapup_auto_instantiation_inform":23,"wrapup_base_class":3,"wrapup_control_flow_process":20,"wrapup_function_template_argument_deduct":23,"wrapup_namespace_scop":21,"wrapup_rescan_of_pragma_token":18,"wrapup_scop":21,"wrinkl":9,"writabl":11,"write":[1,2,3,5,7,8,9,10,11,14,15,16,17,18,21,26],"write_ch":[2,5],"write_cppcli_portable_assembl":1,"write_error_source_lin":0,"write_line_direct":2,"write_memory_region":0,"write_num":[2,5],"write_orig_source_lin":0,"write_signoff":0,"write_source_lin":0,"write_spac":5,"write_str":2,"write_tok_ch":[2,5],"write_tok_str":[2,5],"write_unsigned_num":[2,5],"write_xref_entri":21,"writeonlyarray":7,"writer":10,"written":[0,1,2,3,4,6,7,10,11,13,14,15,16,17,22,23,24,25,26],"wrong":[7,16,18,23],"wrong_entity_for_aligna":7,"wrong_entity_for_attribut":7,"wrong_number_of_argu":7,"www":[10,15],"x":[0,1,2,3,4,5,6,7,8,9,10,11,15,16,17,18,21,23,24],"x1":[4,23],"x2":[4,10],"x86":[7,16],"x_val":4,"xf":16,"xfile":10,"xid_continu":15,"xid_start":15,"xor_integer_valu":9,"xref":10,"xvalu":[7,9,11],"xx":[9,11,16,24],"xxx":[0,10,11,14,15,22,23,24,26],"xxxx":[7,11,14,15,16],"xxxxx":10,"xxxxxxxx":[11,15],"xyz":[0,10,16,18,24],"y":[4,6,10,11,15,16,21,23],"y1":4,"y2":4,"y_val":4,"year":[9,14],"yes":0,"yet":[0,3,6,7,9,10,11,14,15,16,18,21,22,23,25],"yield":[3,7,11,15,16],"yield_in_catch":7,"yield_outside_of_funct":7,"yy":11,"yyy":[10,23],"yyy_h":10,"yyyi":10,"z":[4,10,11,15,16,21,23],"z1":[4,16],"z1__tm__4_z2zz":16,"z2":[4,16],"z_val":4,"zc":10,"zero":[0,2,3,6,7,9,10,11,14,15,16,19,22,23,24,25,26],"zero_init":7,"zero_length_array_is_gnu_extens":7,"zero_length_bit_field_must_be_unnam":7,"zero_length_str":7,"zip":1,"zzz":10},"titles":["Administrative Functions","Configuring and Building the C++ Front End","C-Generating Back End","Class Declarations","Coding Style Guide","C++-Generating Back End","Declarations","Error Messages","Exception Handling","Expression Scanning","External Interface","Intermediate Language","ANSI C and C++ Include Files","C/C++ Front End Documentation","Overview of Internal Structure","Lexical Analysis and Preprocessing","IL Lowering","Modules","Pragmas and Attributes","Runtime Library","Statement Scanning","Symbol Table","Table Management","Templates","EDG Testing Framework","Multiple Translation Units","Utility Programs"],"titleterms":{"A":[8,18],"AT":15,"About":22,"At":8,"Do":16,"For":9,"How":[11,16,18],"In":8,"No":24,"Other":[10,21,22],"The":[1,3,8,9,11,15,16,19,21,23,25],"To":11,"Up":[15,21],"What":16,"With":[17,21],"__declspec":6,"__exception_start":8,"__if_exist":11,"__throw":8,"__throw_setup":8,"abi":16,"accept":10,"access":[3,11,21],"accessor":3,"activ":21,"add":[11,18],"address":[9,11,25],"adjust":17,"administr":0,"advanc":[17,24],"aggreg":6,"agnost":17,"aid":1,"alia":23,"align":[3,4,22],"alloc":[14,22],"altern":[10,23],"anachron":[10,21],"analysi":15,"annot":4,"anonym":[11,16],"ansi":[10,12],"apart":22,"appli":18,"argument":[3,4,10,21],"array":[4,16],"ask":22,"asm":[6,11],"assembl":[6,15],"assign":11,"attribut":[6,11,18],"auto":6,"automat":[10,16,23],"avail":10,"back":[2,5,18],"base":[3,4,9,11,22],"basic":[1,17,21],"behavior":[1,10],"binari":[11,24],"bitfield":17,"bitwidth":17,"block":[8,11],"bodi":[3,4],"bool":16,"bound":[17,18],"box":11,"break":4,"breakdown":17,"buffer":[15,17],"build":1,"building_runtim":19,"byte":17,"c":[0,1,2,3,4,5,6,9,10,11,12,13,15,16,21,23],"c99":[10,11],"cach":[15,17],"call":[4,9,11,16],"canon":25,"captur":3,"case":[4,5,21],"cast":[11,16],"catch":16,"categori":[11,17],"cfront":[10,16],"charact":15,"check":[9,14,17,25],"class":[3,4,11,15,16,21,22,23],"classif":15,"classifi":23,"claus":23,"clean":8,"cleanup":24,"cli":[0,1,3,6,9,10,11,15,21,23],"coalesc":15,"code":[1,2,4,5,8,10,14,15,16,17],"command":[0,10],"common":1,"compat":10,"compil":[3,23],"complet":[6,23],"compon":[1,6],"compound":11,"concept":[22,23,24],"condit":[4,11,16],"configur":[1,2,24],"connect":21,"constant":[0,3,5,9,11,15,22],"constexpr":9,"constrain":23,"constraint":23,"construct":6,"constructor":[6,9,11,16,21],"context":[10,16,21],"control":[10,11,21],"convent":[4,14],"convers":[3,9,15,17,21],"copi":[9,16,17,24,25],"correspond":[11,25],"covari":16,"creat":0,"current":[15,21],"cx":1,"data":[3,4,9,15,16,17,23],"dealloc":11,"debug":[0,10,14,17,22,24,25],"declar":[3,4,5,6,11,14,16,21,22,23],"deduct":6,"default":[3,6,10],"defer":3,"defin":[1,3,9,21],"definit":[0,3,10,15,23],"deleg":3,"delet":[11,15,16],"depend":[0,10,15,21,25],"deriv":3,"descent":14,"deseri":17,"destructor":[6,11,16,21],"detect":15,"dettarg":1,"develop":1,"diagnosi":14,"diagnost":[9,10],"dialect":[1,10,14,16],"direct":[4,6,10,15,21,23],"directori":1,"dispatch":18,"display":[0,1,10],"document":[4,13],"doe":16,"done":16,"drive":1,"driver":1,"dynam":[11,16],"dynamic_cast":16,"eccp":1,"edg":24,"edg_decod":26,"edg_munch":26,"edg_prelink":26,"edgcc":1,"edgi":24,"eh":8,"elif":4,"elis":9,"els":4,"empti":[3,4],"end":[1,2,5,8,10,11,13,14,18],"endian":17,"endif":4,"entiti":[16,21],"entri":[11,14,16,21,22,25],"environ":[1,10],"error":[0,7,14,15],"escap":15,"evalu":16,"event":3,"exampl":8,"except":[8,16],"execut":5,"exist":11,"exit":10,"expect":24,"explicit":[3,17,23],"export":[10,23],"express":[6,8,9,11,14,16,22],"extend":11,"extens":[3,10,15],"extern":[10,14,16,21,25],"facil":25,"fail":24,"failur":24,"featur":[1,10,11,15],"feedback":24,"field":[3,11,17],"file":[0,1,10,11,12,14,16,21,22,23,24],"filter":24,"find":[10,25],"fix":[9,11],"fixup":3,"flag":[0,11,16],"flakey":24,"float":9,"fold":[9,11],"foreign":17,"framework":24,"friend":3,"from_partition_kind":17,"front":[1,10,11,13,14],"full":23,"function":[0,2,3,4,8,9,10,11,14,15,16,21,23],"general":[3,4,11,15],"generat":[0,2,3,5,8,10,23],"generic":[9,23],"get":[15,22],"get_ifc_partition_element_s":17,"get_ifc_partition_kind":17,"gnu":[6,10,16],"group":4,"guard":16,"guid":[4,14],"h":1,"handl":8,"handler":8,"hang":15,"has_partition_kind":17,"header":[0,10,11,12,17,21],"hide":21,"host":0,"host_envir":1,"ia":16,"identifi":[9,15,21],"ifunc":16,"il":[0,1,6,10,11,16,21,23],"impact":17,"implement":[8,10,17,22,23],"implicit":[3,10,17,23],"import":[15,21,23],"inact":21,"includ":[10,12,14],"inclus":[10,23],"index":17,"indic":13,"individu":10,"inform":[9,11,16,22,23],"inherit":24,"init":6,"initi":[0,3,4,6,8,9,11,16,23,25],"inlin":[3,10,16,23],"input":[10,15],"insert":[15,16],"instanti":[10,16,21,23,25],"integ":9,"intellig":14,"interfac":10,"intermedi":[0,11,25],"internal":14,"interpret":18,"introduct":[13,18],"invoc":15,"issu":[0,10],"iter":23,"k":10,"keep":25,"keyword":15,"kind":17,"label":11,"lambda":[3,4,11],"lang_feat":1,"languag":[0,1,10,11,14,22,25],"layout":[3,11],"level":[1,9],"lexic":15,"librari":[1,10,19],"lifetim":[11,16,22],"like":16,"limit":[17,24],"line":[0,4,10,15],"linkag":[3,6,11],"list":[3,5,9,11,15,21,22],"liter":15,"live":24,"load":24,"local":16,"locat":[16,21],"logic":15,"look":[15,21],"lookahead":15,"lookup":[10,21],"loop":4,"low":9,"lower":16,"lvalu":[11,16],"macro":[0,1,5,10,11,15],"main":16,"maintain":16,"makefil":1,"manag":[0,3,8,11,21,22,23],"mangl":16,"manual":10,"map":17,"mark":8,"may":8,"mechan":23,"member":[3,4,11,16,21,23],"memori":[0,11,17,25],"messag":[7,10],"metadata":[6,21],"microsoft":[3,6,10,11],"miscellan":10,"mismatch":24,"mk_errinfo":26,"mode":[1,3,10,21,23,24,25],"model":3,"modif":15,"modifi":22,"modul":[10,17],"multi":24,"multibyt":15,"multipl":25,"multivers":16,"name":[3,4,5,6,10,11,14,15,16,21],"namespac":[6,10,11,12,16,21],"need":[0,8,11],"negat":24,"nest":21,"new":[11,16,18],"node":17,"non":[8,23],"nonreal":21,"nonstat":3,"normal_id_lookup":21,"numer":17,"object":[3,11,16,22,25],"offset":3,"onc":10,"one":[18,25],"onli":1,"oper":[2,9,11,16,21],"operand":9,"optim":[3,16],"option":[1,10,19,21],"order":[11,25],"organiz":[17,21],"orphan":[11,16,22],"output":[5,9,10,15],"overload":[3,9,21],"overview":[3,6,14,23],"pack":10,"pair":25,"paramet":[4,11,23],"parenthes":11,"pars":[0,6,9,14,18],"partial":23,"partit":17,"passthrough":17,"path":3,"pcc":10,"pch":0,"per":25,"perform":10,"phase":18,"philosophi":14,"placement":16,"platform":1,"point":[0,9,11,17],"pointer":[4,11,16,25],"pop_scop":21,"portabl":8,"posit":[11,14,15,16],"post":4,"pragma":[10,11,18,23],"pre":[4,17],"precompil":[0,10],"predefin":[0,10],"prefix":[0,11],"prelink":23,"preprocess":15,"preprocessor":[4,10],"presenc":17,"primit":9,"print":22,"problem":24,"process":[9,10,11,14,15,18,21],"program":[1,16,26],"project":21,"prologu":8,"promot":16,"properti":[3,5,9,11],"prototyp":5,"proxi":21,"push_scop":21,"question":22,"r":10,"rang":[4,9],"raw":[15,17],"re":24,"read":[0,15,17],"recogn":[15,18],"recompil":23,"record":[18,24],"recoveri":14,"recurs":14,"reduct":24,"refer":[4,5,9,11,15],"referenc":[10,11],"region":[11,25],"regress":24,"relat":16,"relationship":11,"releas":1,"replac":1,"replay":24,"report":[0,24],"represent":[6,23],"request":23,"requir":24,"rescan":9,"respons":10,"rethrow":8,"return":[4,11,16],"reusabl":16,"rewritten":5,"role":17,"routin":[0,9,11,15,16,22],"rule":4,"run":[1,8,24],"runtim":[10,16,19],"rvalu":11,"scan":[3,6,9,15,20],"scan_expr_ful":9,"scope":[3,5,11,16,17,21],"scope_stack_lookup":21,"script":1,"secondari":[10,25],"select":11,"selector":9,"separ":25,"sequenc":[5,11,16,22],"set":22,"setup":24,"sig":21,"signal":10,"simpl":17,"singl":24,"size":22,"sizeof":11,"skip":[15,17],"slow":[21,24],"sort":17,"sourc":[1,5,11,14,15,22],"space":15,"special":[4,21,23,24],"specif":[1,6,8],"specifi":6,"stack":[8,9,15],"stage":17,"standard":[6,12],"state":6,"statement":[4,9,11,20,22],"static":[3,16,23,25],"status":[10,24],"step":3,"stop":0,"storag":[8,14,22],"stream":15,"string":0,"structur":[9,14,15,23],"style":4,"subscript":[4,11],"subset":24,"sun":10,"supplement":21,"support":[1,8,10,16,24],"svr4":10,"switch":4,"symbol":[3,11,21],"syntax":14,"synthes":21,"t":15,"tabl":[11,13,16,21,22],"tacit":17,"tagless":3,"take":22,"targ_def":1,"target":1,"techniqu":9,"templat":[3,4,5,10,11,15,16,21,23],"temporari":[9,11,16],"termin":[10,23,24,25],"test":24,"text":15,"textual":15,"thread_loc":16,"three":18,"throw":[8,11,16],"thrown":8,"time":[1,8],"token":15,"tool":24,"top":1,"track":15,"transform":[2,9,18],"translat":[10,25],"travers":0,"tree":[15,22],"tri":8,"troublesom":5,"two":18,"type":[0,3,4,6,9,11,16,18,22],"typeid":[11,16],"typeref":[11,14,22],"unbound":18,"unbox":11,"uncheck":17,"unexpect":24,"unicod":15,"union":[11,16],"unit":[10,25],"unord":16,"unscan":18,"use":[0,1,3,6,10,11,21],"user":[3,9,10,21],"util":[1,15,26],"valid":17,"valu":[4,11,16,17],"variabl":[0,4,6,10,11,15,16,23],"variad":23,"verbos":24,"version":[15,17],"versus":11,"virtual":[3,11,16],"visitor":17,"vla":11,"void":9,"vs":[3,6],"vulner":15,"walk":8,"way":10,"white":15,"whitespac":[4,15],"window":1,"within":11,"without":17,"wrap":[4,17],"wrapper":16,"wrapup":0,"write":[0,4,24]}}) \ No newline at end of file diff --git a/dev/doc/statements/index.html b/dev/doc/statements/index.html new file mode 100644 index 0000000..5829745 --- /dev/null +++ b/dev/doc/statements/index.html @@ -0,0 +1,454 @@ + + + + + 12. Statement Scanning - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    12. Statement Scanning#

    +

    statements.c contains the code to scan statements, and statements.h +contains the associated declarations.

    +

    The top-level routine here is compound_statement, which scans a +brace-enclosed list of statements. This is used for the bodies of functions +and for blocks (with and without local declarations) that appear within +functions. In C mode, it first calls opt_declaration_list to scan the +optional list of declarations; then, in C or C++ mode, it calls statement +(in a loop) to scan the statements.

    +

    statement scans one statement, with an optional preceding label or labels. +Its job is mostly to call the appropriate statement-scanning routine based on +the first token of the statement. For most statements, the first token is a +keyword that identifies the statement. Otherwise, the statement is an +expression statement (in C or C++) or a declaration (in C++ only; +is_decl_not_expr is called to decide whether the construct is an expression +or a declaration).

    +

    A stack of active statements is maintained in struct_stmt_stack. For each +active statement, it contains the kind of statement and some information about +what has been scanned so far in the statement. push_stmt_stack and +pop_stmt_stack manage the stack. find_enclosing_struct_stmt can be +used to find the nearest enclosing structured statement of a given type; this +is used in finding the construct associated with a break or continue.

    +

    One important function of the statement stack is that it points to the +intermediate language for the associated statement. The top-most entry +contains enough information to enable one to find the “current” location in the +intermediate language being generated, the point at which one would like to add +a statement. This is, in fact, exactly what add_statement_list does: it +links the given list of statements (possibly just a single statement) into the +growing tree of statements for the function. Usually, this is called throughadd_statement_at_stmt_pos , which allocates a statement of a given kind and +also maintains the code_reachable flag, indicating whether or not the +current location in the code is reachable. This flag is used to check for +unreachable code and issue appropriate warnings. Code is attached to the +statement tree even if it is unreachable. As statements are pushed onto and +popped off the stack, the code_reachable flag is maintained accordingly, +based on whether or not the beginning of the statement can be reached, whether +the end can be reached from the beginning, and whether the end can be reached +from the inside. The lint_notreached_flag is also consulted. For +statements that have several clauses (if and switch) +start_stmt_clause and term_stmt_clause are called at the appropriate +locations in processing to keep the code_reachable flag up to date.

    +

    The statement stack contains pointers to break and continue labels for +the statement. These are initialized to NULL, and later made to point to a +label if a goto is actually generated for a break or continue. At +pop_stmt_stack time, the definition for the break label is generated if +one is needed. The statement scanning routine must handle the continue +label is there is one.

    +

    If a statement is labeled with a simple label, statement calls +scan_label to look up or enter the label, then define_label to add a +label definition statement to the intermediate language.

    +

    Nothing tricky is involved in statement processing routines if_statement, +while_statement, do_statement, goto_statement, break_statement, +and continue_statement. asm_statement is called for asm statements; it +in turn calls asm_declaration.

    +

    dependent_statement is called to scan statements that are dependent +statements of if, switch, while, do while, and for +statements. In C mode, it just scans a statement. In C++ mode, it creates a +block statement and places the dependent statement under it, unless the +dependent statement is a block statement. That ensures that if anything is +declared in the dependent statement, its scope will be limited to the dependent +statement (this is a post-ARM C++ language rule).

    +

    for_statement scans a for or range-based for statement (or, in UPC +mode, a upc_forall statement). Since it is unknown at the beginning of +scanning whether a for or range-based for statement is being scanned, +two block scopes (used to contain the range-based for temporary variables) +are pushed in preparation for the range-based for case (they’re discarded +if scanning reveals a for statement). The first entity inside the +parentheses (initialization) is scanned by calling for_init_statement, +which allows an expression (in C or C++), a declaration (in C++ only), or a +for-range-declaration (in C++11). for_init_statement also determines +(through a call to decl_statement_full) which type of statement is being +scanned. If the for-init is a declaration (and a for statement is +being scanned), start_for_init_block is called to push an sck_block +scope (with is_for_init_block set to TRUE) onto the scope stack, where +it remains till after the dependent statement of the loop is scanned (see +finish_for_init_block). If the second expression (test) is present, it is +scanned by calling can_boolean_controlling_expression. The third +expression (increment) is scanned by calling scan_void_expression. For any +of those expressions/statements that is omitted, a NULL pointer is used in +the stmk_for statement. In the range-based for case, the statement +kind is set to stmk_range_based_for (this is somewhat unusual since the +statement kind is typically known earlier) and +scan_range_based_for_expression is called to scan the range expression. +Semantic checks, determination of the type of range-based for (see header +comments), and IL generation are handled by +check_range_based_for_statement.

    +

    The Microsoft for-each statement (available in C++/CLI emulation mode, as well +as when microsoft_version >= 1400) is scanned by for_each_statement. +If the for-each statement contains a previously declared iterator variable, it +is scanned by scan_previously_decl_iterator_name, otherwise the iterator +declaration is scanned by for_each_iterator_declaration. Two block scopes +are pushed (an outer block scope for the loop temporary variables, and an inner +scope for the iterator variable). The collection expression is scanned by +scan_for_each_expression and semantic checks (and IL generated) by +check_for_each_statement. check_for_each_statement handles the various +types of for-each statements (see the header comment for details). Much of the +underlying code is shared with the range-based for statement.

    +

    return_statement scans the return statement. It examines the type of +the current function. A void function should have returns that +return no value; other functions should return a value. +check_void_return_okay checks whether or not a value-less return is +okay in the current function. It is also used at the final closing brace of +the function if that position is reachable (since there is an implicit +return there).

    +

    switch statements cause the most problems. switch_statement itself is +not too complicated: it just pushes an entry on the statement stack, scans the +selector expression, and scans the dependent statement. The complex processing +comes with case_label (which also handles the GNU extension of case ranges; +e.g., “case 1 ...  3:”) and default_label, or more precisely, with the +subroutine those two cases call, add_switch_clause. That routine +determines whether or not the label can be added to the list of labels for the +currently-active clause, or whether instead a new clause must be begun. It +also determines where the case value (or the default) belongs in the list of +constants for the clause. The configuration macro +RECORD_SWITCH_CASE_ENTRIES determines how individual case labels are +represented. When TRUE (the default), all the labels (including the default +case and any GNU case ranges) are represented using type +a_switch_case_entry. When FALSE (an option maintained primarily for +backward compatibility purposes), the labels within a clause are usually +represented as a list of a_constant entries, but in a clause labeled with +default, any specific values from case labels are superfluous and are +removed. In the latter approach, GNU case ranges are represented as a list +containing all the constants in the range (which doesn’t scale well for large +ranges). Because the intermediate language idiom for switch statements is +slightly different from the C language idiom, a bit of translation from one +idiom to the other is necessary:

    +
      +
    • +
      A break in a switch usually just ends the current clause and makes +the code following it unreachable. Since the intermediate language +switch clauses end with a break by default, no goto to a +break label is usually needed.
      +
      +
    • +
    • +
      Fall-through from one clause into the next is translated as a goto to a +generated label at the start of the next clause.
      +
      +
    • +
    • +
      When case or default labels are not at the top level in the +switch body (i.e., they are defined within structured statements inside +the switch), the switch clause is just a goto to a generated +label at the right location, and the unusual statement(s) inside the +switch body go into the body statement attached to the intermediate +language switch.
      +
      +
    • +
    • +
      Likewise, when there are local declarations in the compound statement that +is the body of the switch, those declarations go into the body +statement.
      +
      +
    • +
    +

    There is also processing to detect and report cases in which a declaration that +involves implicit or explicit initialization is bypassed by a transfer of +control (by means of a goto or switch). A separate data structure is +maintained to assist in this checking: variable control_flow_descr_list +identifies a doubly linked list of entries of type a_control_flow_descr +that represents a view of the static control flow pattern of a given function. +Blocks, gotos, labels, case labels, and initializing declarations are +all represented by entries on the list. Some of these entries point to IL +entries, but the IL does not point back.

    +

    The list is dynamically pruned – it has only enough information on it for the +checking that is required. For instance, once a forward goto has been checked, +it is no longer interesting and is removed, and entire blocks may be removed +once they become irrelevant to subsequent analysis. (See +remove_control_flow_descr and remove_list_of_flow_control_descrs, which +place entries onto an available list, and alloc_control_flow_descr, which +reuses freed entries in preference to allocating new ones.)

    +

    add_to_control_flow_descr_list is called (from add_stmt_at_stmt_pos for +initializations, from push_stmt_stack for blocks, etc.) to add a new entry +to the end of the list, though in some cases the entry will not be +added – because it is not required after all – and sometimes it will even +cause other entries to be removed – for instance, if a completed block turns +out to have no labels or gotos, the entire block can be eliminated.

    +

    At the end of a block within a switch statement, +add_to_control_flow_descr_list may call report_switch_past_init, which +examines the entries on the list for initializing declarations that may be +bypassed by a transfer of control to a case label. An error is issued in +C++ mode, a warning otherwise.

    +

    check_for_jump_over_initialization is called from goto_statement and +from statement when a label definition is seen. For a forwards goto it +calls add_to_control_flow_descr_list to record information that will be +used for checking when the label is processed. For a label it calls +check_goto_and_label to report any previously recorded gotos that may +now be recognized to involve bypassing an initializing declaration (see +report_goto_past_init, which issues an error in C++ and a warning +otherwise); and an entry representing the label is added to the list. For a +backwards goto it again calls check_goto_and_label, which in turn calls +report_goto_past_init, if appropriate.

    +

    The control flow descriptor list is also used by +check_for_branch_into_handler, which reports attempts to branch into an +exception handler from code outside the handler.

    +

    An important part of statement processing is the management of object +lifetimes. For example, each time a compound statement starts, a new object +lifetime begins; and it ends when the compound statement terminates. In other +words, objects (e.g., automatic variables and long-lifetime expression +temporaries) created inside the compound statement have lifetimes that +terminate when it does. The destructor (if any) for such an object must be +called in the event of the normal termination of the scope, a branch out of it, +or unwinding through it as the result of an exception. The information +enabling back ends to support these implicit destructor calls, in the right +place and in the right order, is provided by entries of type +an_object_lifetime, discussed in detail in the chapter on the intermediate +language.

    +

    Each time a new function or block scope is created, a new object lifetime is +pushed on the object lifetime stack – push_object_lifetime is called in +push_scope, and the object lifetime is bound to the scope entry for block +scopes in ensure_il_scope_exists (in il.c). In addition, an object +lifetime is pushed for try blocks in try_block_statement and for cfront +dependent statements in start_block_statement; in the latter case, since +there is no scope, the lifetime entry is bound to the block entry associated +with the block statement.

    +

    When a label is defined, a block-after-label object lifetime is pushed. Such +lifetimes are effectively subblocks of the current lifetime that run from the +label to the end of the block in which the label appears. When a label is +defined inside an inner block, a block-after-label lifetime is also pushed in +the containing block when the inner block terminates. (See +terminate_curr_block_object_lifetime and +reset_curr_block_object_lifetime.) Block-after-label lifetimes are also +pushed for case labels.

    +

    The object lifetime that is current at the point of the label’s definition is +recorded in the label statement. A goto statement that references that +label will point to the innermost object lifetime shared by the label and the +goto; this is computed by common_object_lifetime.

    +

    The general strategy is always to create an object lifetime at standard +transitions in the source code (e.g., upon entering a block or when a label is +seen) and then, when the construct it belongs to terminates, to decide whether +there is justification for retaining that lifetime entry in the IL. If not (as +determined by is_useless_object_lifetime), it is removed from the IL tree.

    +

    Consequently, a label or goto statement may be assigned an object lifetime +that subsequently proves “useless”. In that case the object lifetime pointers +of the statement entries are promoted (see +fixup_curr_block_labels_and_gotos, which calls +promote_label_and_goto_lifetimes; this is also where +pop_object_lifetime is called for block-after-label lifetimes). This +processing is driven by management of the control flow description list (see +add_to_control_flow_descr_list).

    +

    If all the labels and gotos in a function end up pointing to the function +scope lifetime but the function scope lifetime itself turns out to be useless, +then the lifetime pointers in the label and goto statements are cleared +(see wrapup_control_flow_processing).

    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/symbol_tbl/index.html b/dev/doc/symbol_tbl/index.html new file mode 100644 index 0000000..d1be5e1 --- /dev/null +++ b/dev/doc/symbol_tbl/index.html @@ -0,0 +1,2519 @@ + + + + + 6. Symbol Table - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    6. Symbol Table#

    +

    The primary function of the symbol table is to provide a mechanism for +associating names and entities: a name can be entered into the symbol table in +association with a particular definition and then later looked up to get back +to the same definition. Name visibility is controlled by an implementation of +nested name scopes and class member inheritance. Provision is also made for +overloaded operators and user-defined conversion functions, which are not +looked up by name. In addition, the symbol table serves as a repository of +information that is needed for front-end processing but is of no use to back +ends. symbol_tbl.c contains the code to manage the symbol table, +lookup.c contains the code that looks up identifiers, scope_stk.c +contains the code that manages the scope stack, and symbol_ref.c contains +the code that manages the recording of references to symbols. +symbol_tbl.h, lookup.h, scope_stk.h, and symbol_ref.h contain +the associated declarations.

    +
    +

    6.1. Basic Organization#

    +
    +

    6.1.1. Symbols and Symbol Headers#

    +

    The key components of the symbol table are entries of type a_symbol and +a_symbol_header. Typically, symbols represent specific uses of a name +(e.g., the same name may be declared in different name scopes or belong to +different name spaces), but all symbols for a particular name share the same +symbol header. Each symbol entry points to a header which identifies the name +associated with it; the symbol header points in turn to symbols that share its +name. Symbols with the same name from different translation units (see +Multiple Translation Units) share the same symbol header.

    +

    For certain special cases (overloaded operators and user-defined conversions) +the symbol header has no actual name but can be thought of as representing a +family of virtual names to be constructed for the associated symbols: a single +symbol header is shared by all symbols that overload a given operator or, for +user-defined conversions, a given return type. (The names generated by the +compiler to assure type-safe linkage are not produced by the front end and so +do not appear in the symbol table.)

    +

    At the gross level the symbol table has three distinct pieces, each of which +has its own “root”, a global variable that is accessed in the lookup process:

    +
      +
    • +
      For named symbols symbol_table is a hash table where each bucket points +to a linked list of symbol headers. The name is reduced to a hash value +that is used to index the array.
      +
      +
    • +
    • +
      For overloaded operator symbols opname_symbol_table is an array of +symbol header pointers that is indexed by members of the enumeration +an_opname_kind. There will be one symbol header for each overloaded +operator.
      +
      +
    • +
    • +
      For user-defined conversion symbols conversion_header_list points to a +linked list of entities of type a_conversion_header, one for each +result type for which the user has declared a conversion routine. Each +conversion header points to a single symbol header.
      +
      +
    • +
    +
    +
    +

    6.1.2. Active, Inactive, and “Other” Symbols#

    +

    Each symbol header contains pointers to three lists of symbols of the same name +(or that otherwise share the symbol header): the active symbol list, the +inactive symbol list, and the other symbol list.

    +
    +

    6.1.2.1. The Active Symbol List#

    +

    The list of active symbols includes all symbols that are still in scope. The +order of the symbols on the list is significant since certain of the lookup +mechanisms take the first symbol found. When symbols are entered into the +symbol table, their entries are always placed at the beginning of the list, so +that declarations in inner scopes will eclipse outer-scope declarations of the +same names. An exception is made when a tag and a nontype with the same name +exist in the same scope in C++. In such cases the tag is always placed on the +list following the nontype so that it will be hidden except when accessed using +an elaborated type specifier. When the inner scope ends, its symbol entries +are removed, which exposes the outer declarations.

    +

    Note, however, that symbols from the same scope can coexist on the active list, +since different kinds of symbols can belong to different name spaces. For +instance, a variable, a macro, and (in ordinary C) a tag can all share the same +name. The array name_space_for_symbol_kind maps a symbol kind into +a_name_space_kind (e.g., nsk_label, nsk_macro, nsk_other). The +lookup mechanism must check for name-space compatibility: in most cases, it +takes the first in the active list whose kind maps into the appropriate name +space. The name space kind nsk_other is the normal name space for types, +variables, enumeration constants, and functions.

    +
    +
    +

    6.1.2.2. The Inactive Symbol Lists#

    +

    When a scope terminates, the symbol for each name declared in that scope is +removed from the active list of the associated symbol header. In most cases, +this means the symbol is removed from the symbol table (i.e., that it can no +longer be found by any lookup mechanism). But for some symbols (e.g., class +and namespace members) it must remain possible to look up a name even after it +passes out of scope, and so its symbol is moved from the symbol header’s active +list to its inactive list. The order of symbols on the inactive list is not +significant.

    +

    Thus, the inactive symbol list will comprise symbols for class members that are +no longer in scope but are still indirectly accessible, whenever the class is +accessed.

    +

    Similarly, when the template declaration scope terminates, its symbols +representing the template parameters are also added to the inactive list. This +enables them to be accessible during instantiation of the template.

    +

    Namespace scopes are not terminated when the namespace is closed because the +namespace may be extended later in the compilation. Namespaces may be extended +either explicitly by opening a namespace extension scope, or implicitly as a +side-effect of a namespace member definition in the file scope or as a +side-effect of the instantiation of a template entity defined in a namespace +scope. When the original namespace definition scope is closed, the namespace +members are moved from the active list to the inactive list. If the namespace +scope is later extended, new symbols for the namespace are entered directly on +to the inactive list.

    +

    The file scope is popped when the scanning of a translation unit is completed +so that its symbols are not on the active list if any other translation units +must be processed. As with namespaces, the symbols are moved to the inactive +list to permit the file scope to be reactivated later, if additional processing +of the original translation unit is required (e.g., to generate template +instantiations).

    +
    +
    +

    6.1.2.3. The “Other” Symbol List#

    +

    The “other” symbols list is used for symbols that are never found using the +normal lookup routines. Specifically, the “other” symbols list includes +“extern” symbols and synthesized namespace projection symbols, both of which +are described below.

    +
    +
    +
    +

    6.1.3. Scope List#

    +

    When symbols are entered into the symbol table, they are also entered onto a +list of the symbols declared in the current name scope (discussed in detail +below). [1] This list preserves the names in declaration order and is +referenced in removing symbols from the active list (and usually from the +symbol table) when the name scope is terminated.

    +

    Typically, this list lasts no longer than the scope stack entry that points to +it – when the entry is popped off the scope stack, the associated list is +discarded. In some cases, however, the list must be kept around for later use.

    +
      +
    • +
      For class scopes it is stored in the class symbol supplement for the class +for use in cases in which the declaration order must be observed (e.g., in +doing member initialization).
      +
      +
    • +
    • +
      For function prototype scopes it is used to reenter parameter symbols in +the function scope.
      +
      +
    • +
    • +
      For namespace scopes it is preserved in the pointers block for the +namespace.
      +
      +
    • +
    • +
      For file scopes it is preserved in the translation unit entry (there can be +more than one file scope when processing multiple translation units).
      +
      +
    • +
    +
    +
    +

    6.1.4. Special Cases#

    +

    There are several classes of symbol for which special treatment is required.

    +

    Symbol entries for constructors, though they have names, are not entered +directly into the symbol table. That is, they do not appear on the active or +inactive list of the symbol header for the name. Rather, they are accessed +from the constructor field of the class’s supplement entry. Thus the +symbol lookup for constructor X::X is always by way of the symbol +supplement for class X.

    +

    A tagless class, struct, or union presents an interesting case because it has +no name but must have a symbol to serve as a repository of information for the +front end’s processing. Such symbols all share a single symbol header (see +static variable unnamed_tag_symbol_header in symbol_tbl.c) but are not +entered on any list.

    +

    C++/CLI property accessor functions are members of a property which is itself a +member of a class, but the property is not a nested class; it’s a data member. +For the accessors, special symbol headers are generated that are a combination +of the symbol header for the property and the symbol header for the access +name. See get_property_or_event_accessor_symbol_header. Event accessors +are handled similarly.

    +

    Error symbols are created in various cases when errors are detected. They have +no name associated with them, and, like unnamed class symbols, they all share +the same symbol header (see static variable error_symbol_header in +symbol_tbl.c).

    +
    +
    +

    6.1.5. Symbols and IL Entries#

    +

    For the most part symbol entries are little more than an indication of the kind +of symbol and a pointer to an IL entry that provides more information. Thus, +sk_variable and sk_static_data_member symbols point to an entry of type +a_variable; constants, types, tags, fields, functions, and labels are +similar. The principal function of most symbol entries is simply to indicate a +mapping between names and the intermediate language constructs to which those +names correspond.

    +

    But symbol entries also serve as repositories of information that the front end +requires for its processing but that back ends do not care about. For +instance, sk_keyword symbols contain the keyword token value and for +sk_macro symbols there is a pointer to a_macro_def. Most notably, +symbols representing classes, structs, and unions point not only to the +corresponding IL entry but also to an entry of type +a_class_symbol_supplement, which contains a number of flags and pointers +(including a pointer to the constructor symbol, as described above).

    +

    Some symbols just point to other symbols: sk_projection symbols, which +represent names in a derived class that are inherited from a base class, +contain a pointer to the original symbol, and sk_overloaded_function +symbols point to a linked list of routine symbols that represent instances of +the overloaded name.

    +

    sk_parameter symbols are created during parameter processing. They are +needed because parameter names hide names from containing scopes (e.g., in +default argument expressions). However, they do not refer to any IL entity; +rather, when a function definition is present, they are reentered into the +function scope and turned into sk_variable symbols which do point to +variable entries.

    +
    +
    +

    6.1.6. Function Overloading#

    +

    Each instance of an overloaded function is represented by a symbol – of kind +sk_member_function for member functions and sk_routine otherwise. +However, these symbols are not directly present in the symbol table. Rather, +the whole family of functions that share the common name or operator in a given +scope is represented by an sk_overloaded_function symbol, and that is what +actually appears in the symbol table (i.e., is on the active or inactive list +of a symbol header). Consequently, name lookup finds only the overloaded +function symbol, not the symbol for the particular function required. [2]

    +

    The actual function symbols appear on a linked list pointed to from the +overloaded function symbol. The order of symbols on the list is not +significant, since the argument matching algorithm requires visiting every +instance anyway. The list may contain function symbols, function template +symbols, projection or namespace projection symbols that point to functions or +function templates, or a combination of any or all of these.

    +
    +
    +
    +

    6.2. Name Scopes#

    +
    +

    6.2.1. push_scope and pop_scope#

    +

    Aside from the structure described above, the symbol table also has a name +scope structure. Each time a new name scope is entered (for the file scope, a +class, struct, or union, a function, a block, function prototype, namespace, +template declaration, or template instantiation), push_scope is called to +push a new entry onto the scope stack. (See scope_stack, a global variable +that points to an array of elements of type a_scope_stack_entry. Since the +scope stack is implemented as a dynamically allocated array that can be +extended by reallocation when necessary, elements should always be accessed by +indexing into the array rather than by reusing a pointer.)

    +

    There are actually a number of different routines used to push different kinds +of scopes (e.g., push_template_instantiation_scope). The various routines +all call push_scope_full, which does most of the processing. +push_scope is used for pushing “normal” scopes that don’t require that +extra arguments be supplied when called. This section uses the name +push_scope to refer to the set of functions that add scopes to the scope +stack. Most of the actions described here are performed by +push_scope_full.

    +

    push_scope assigns a unique number to each scope, and when an identifier is +entered into the symbol table, the scope number is recorded in its symbol +(field decl_scope); this number may be referenced during symbol lookup, and +it is used to detect multiple declaration errors during symbol entry. When the +name scope ends, pop_scope is called to remove its symbols from the symbol +table (class member symbols are an exception, as described above) and to pop +the scope stack entry off the stack. pop_scope calls wrapup_scope, +which removes the symbol entries for the scope from the active list and +reenters them on the inactive list when appropriate (for class, namespace, and +template declaration scopes). wrapup_scope also calls +end_of_scope_symbol_check, which issues diagnostics on incomplete types and +on entities that were declared and never referenced or set and never used. +When the file scope is popped at the end of the translation unit, pop_scope +calls wrapup_namespace_scopes, which in turn calls wrapup_scope for all +of the namespace scopes in the translation unit.

    +

    The previous_scope field of the scope stack entry is used to determine the +order in which scopes on the scope stack are to be considered for name lookup +purposes. For most scopes, this field is set by push_scope_full.

    +

    push_scope and pop_scope maintain a number of state variables, some +global and some local to symbol_tbl.c:

    +
      +
    • +
      depth_scope_stack gives the depth of the current name scope in the +scope stack. [3]
      +
      +
    • +
    • +
      decl_scope_level gives the scope depth of the scope entry with which +declarations should be associated. [4]
      +
      +
    • +
    • +
      depth_innermost_function_scope is the depth of a sck_routine scope +stack entry that is or contains the current scope; if there is none or if a +class scope intervenes its value is NO_SCOPE_DEPTH.
      +
      +
    • +
    • +
      num_classes_on_scope_stack is the number of class entries currently on +the scope stack (including sck_class_reactivation as well as +sck_class_struct_union scopes).
      +
      +
    • +
    • +
      depth_of_innermost_scope_that_affects_access_control is used in +determining whether a piece of code has member access privileges to a given +class (e.g., in a friend function).
      +
      +
    • +
    • +
      depth_innermost_namespace_scope is the depth of the innermost namespace +scope that is visible on the scope stack, or the depth of the file scope if +no namespace scopes are visible.
      +
      +
    • +
    • +
      depth_innermost_instantiation_scope is the depth of the current +template instantiation scope or NO_SCOPE_DEPTH if no instantiations are +active.
      +
      +
    • +
    +

    push_scope also causes new memory regions to be created for the file scope +and for function scopes. When the scope is popped, the following processing is +done:

    +
      +
    • +
      If IL lowering is being performed, should_delay_lowering_on_function is +called to determine whether the function should be lowered at this point. +A number of circumstances can cause lowering to be delayed, such as the +need to preserve unlowered IL for constexpr evaluations, the need for a +module-id that has not yet been determined, etc.
      +
      +
    • +
    • +
      should_delay_finishing_of_function_body is called to determine whether +a function body should be “finished” at this point. If so, +finish_function_body_processing is called. This will lower the +function, if it has not already been lowered, do needed flag processing (if +necessary), and any other operations that may be needed before the memory +is potentially freed.
      +
      +
    • +
    • +
      check_for_done_with_memory_region is called either to write out the +entries in the memory region to a file and reclaim the entire region for +reuse or, if the interface to the back end is in memory, to reclaim only +the unused portion of it. In some cases the memory must be kept and IL +file generation deferred. This is done, for example, when a function body +is kept for potential inlining, or if the function contains a generic +lambda that may be instantiated later.
      +
      +
    • +
    +

    The name scope for a class whose definition is completed must be reinstated to +process the definition of a member function of that class or the initializer of +static data member of that class. This is accomplished by calling +push_class_reactivation_scope, which has the effect of making the symbols +on a symbol header’s inactive list visible (that is, those inactive list +symbols whose decl_scope value matches the scope number of the reactivated +scope become visible). When the class to be reactivated is a nested class, +push_class_reactivation_scope reactivates its enclosing class first to +create the required name visibility and hiding. If the class being reactivated +is from a namespace, the namespace will also be reactivated (see below). A +matching call to pop_class_reactivation_scope is required once processing +for the member function definition or static member initializer is finished.

    +

    The assoc_type field in sck_class_struct_union and +sck_class_reactivation scope stack entries points to the type entry for the +corresponding class, struct, or union.

    +

    Namespace scopes, like class scopes, are reactivated when processing the +declarations of namespace members outside of their namespace. As mentioned +earlier, namespace scopes are unique in that they are not actually closed +when the end of a namespace definition is reached. The namespace can be +extended later either by a namespace extension declaration or by a name +that is injected while processing the definition of a member of a namespace +outside of the namespace (including the instantiation of templates defined +in the namespace). Namespaces are reactivated by calling +push_namespace_reactivation_scope. +pop_namespace_reactivation_scope is called when the reactivated +namespace is no longer required. Reactivating a namespace causes any +namespaces that enclose the reactivated namespace also to be reactivated. +Namespaces are extended by calling push_namespace_extension_scope. +When the namespace extension scope is no longer required, +pop_namespace_extension_scope must be called. Extending a namespace +causes any namespaces that enclose the extended namespace also to be +extended. A namespace is reactivated in contexts in which the names from +the namespace must be visible but new names cannot be added to the +namespace. A namespace is extended in contexts in which names from the +namespace must be visible and new names can be added.

    +

    The scope stack contains a set of pointers that are used to track the symbols +for the scope and the “last” pointers that point to the end of the each of the +lists of IL entries associated with the scope. For most scope kinds, this +information is no longer needed when the scope stack entry is popped off of the +stack. Because namespace scopes can be extended, this information must be +preserved for those scopes. Furthermore, a given namespace can appear on the +scope stack more than once when templates are being instantiated. When more +than one scope stack entry exists for a given namespace, they must share the +same set of symbol and IL entry pointers. The pointers that must be preserved +between extensions of the namespace and shared between scope stack entries for +the namespace are in a structure called a_scope_pointers_block. Each scope +stack entry contains a pointers block structure and field named +assoc_pointers_block that points to a pointers block structure. For all +scopes except namespace and namespace extension scopes, the +assoc_pointers_block pointer is NULL, indicating that the pointers block +within the scope stack entry should be used. For namespace and namespace +extension scopes, the assoc_pointers_block pointer points to a pointers +block in the namespace symbol supplement for the namespace. The macro +assoc_pointers_block_of should be used to obtain a pointer to the +appropriate pointers block for a given scope stack entry.

    +

    push_template_instantiation_scope is called when the appropriate context in +which a given template can be instantiated needs to be established. When a +template instantiation scope is pushed, the sequence of scopes used for name +lookup purposes is changed. In fact, there are four distinct sets of scopes +used for name lookup when a template instantiation in progress:

    +
      +
    • +
      the scopes associated with the local context of the template: These include +the template instantiation scope (with which the template parameters are +associated), the scope associated with the class or function being +instantiated, and any scopes nested within the class or function being +instantiated.
      +
      +
    • +
    • +
      the template definition context scopes: The scopes that are only part of +the context in which the template was defined.
      +
      +
    • +
    • +
      the referencing context scopes: The scopes that are only part of the +context in which the template reference that caused the instantiation +occurred, beginning with the innermost namespace scope.
      +
      +
    • +
    • +
      the common scopes: The scopes that enclose both the definition context and +the referencing context. This always contains at least the file scope.
      +
      +
    • +
    +

    push_instantiation_context determines which of the required namespace +scopes are already present on the scope stack and pushes those entries that are +not already present. It then calls +reactivate_class_and_instantiation_scopes to reactivate any classes that +may enclose the template that is being instantiated. If an enclosing class is +itself a template class, an instantiation scope for that class is also pushed +so that its template parameters will be visible to the entity being +instantiated.

    +

    fixup_instantiation_scopes is called after all of the scopes have been +pushed. It performs the following functions:

    +
      +
    • +
      All of the instantiation scopes that were pushed, except for the outermost +one, are flagged as nested instantiations. Only nonnested instantiation +scopes are considered for special instantiation context lookups, as +described later.
      +
      +
    • +
    • +
      The context and common scope depths are recorded in the nonnested +instantiation scope.
      +
      +
    • +
    • +
      The previous scope pointers of the outermost definition context scope and +the referencing context scope are set to point to the common scope.
      +
      +
    • +
    • +
      The next_scope_that_affects_access_control field is updated to make +sure that it does not point at a scope that is not part of the current +context.
      +
      +
    • +
    • +
      In the set of instantiation scopes pushed by a call to +push_template_instantiation_scope, all except the innermost one have +their exclude_from_context_output flag set. This prevents unnecessary +context information from being generated during diagnostic output.
      +
      +
    • +
    +

    The previous_scope field is also updated when a namespace reactivation +scope is pushed within a template declaration scope. In such cases, the names +from the namespace extension scope must not be considered until after the +template parameters. For example, in the following case the T in the +function parameter list must refer to the template parameter and not N::T.

    +
    namespace N { typedef int T;}
    +template <class T> void N::f(T);
    +
    +
    +

    If GENERATE_SOURCE_SEQUENCE_LISTS is configured to TRUE, source sequence +lists for active scopes are recorded in the scope stack entry (see +source_sequence_list and end_of_source_sequence_list in +a_scope_stack_entry). When pop_scope is called for the file scope or a +function scope, the list is moved to the corresponding IL scope. Otherwise, +the list is merged into the list of a containing scope, which usually means +that the list is simply appended to the list of the immediately containing +scope; for sck_template_instantiation scopes, however (when a +compiler-generated specialization represents an automatic instantiation – that +is, when either CLASS- or +NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured to +TRUE), insert_instantiation_src_seq_list is called to move the list to an +appropriate location in the list of an enclosing scope.

    +
    +
    +

    6.2.2. Connection With IL Scope Entries#

    +

    While not all scope stack entries correspond to an intermediate language scope +entry, all intermediate language scope entries have a corresponding scope stack +entry. Every scope stack entry has a (possibly NULL) pointer to an +intermediate language scope entry; every intermediate language scope entry +refers back to the corresponding scope stack entry by means of a scope number.

    +

    For example, a new scope stack entry is pushed for a statement block whether or +not it contains any declarations, but the intermediate language scope is not +created until it is needed, and not till then is the IL_scope pointer in +the scope stack entry updated.

    +

    The scope stack entries for the file scope, namespaces, classes, routines, and +blocks are closely tied to a corresponding intermediate language scope entry: +the latter has pointers to the lists of types, variables, etc. for that scope, +and the pointers block has the pointers to the ends of those lists. The +pointers block in the scope stack entry is used for all scopes except for +namespace and namespace extension scopes, for which the pointers block is +located in the namespace symbol supplement. These tail pointers are only +needed while the scope is active, to add entries at the end of the list, and +having them in the pointers block reduces the size of the intermediate language +scope entry.

    +
    +
    +
    +

    6.3. Classes#

    +

    Classes (in the generic sense, including structs and unions) require the +management of quite a lot of information. Some of this must reside in the +intermediate language. For instance, the entities that represent members of a +class are kept on lists pointed to from the intermediate language scope entry +associated with the class; and the base classes from which the class is derived +are associated with the class’s type entry. In these and other cases +information associated with a class is stored in intermediate language +declarative constructs, and appropriately so, since the information is of use +to back ends.

    +

    However, there is a great deal of information that the front end needs but back +ends do not care about, and it would be wasteful to store it in the +intermediate language. Instead, it is kept in the symbol table so that it can +be thrown away when front-end processing is complete.

    +
    +

    6.3.1. Class Symbol Supplement#

    +

    Entities of type a_class_symbol_supplement, pointed to from all class, +struct, and union tag symbols, constitute the main repository for +front-end-only information about classes.

    +

    Among the fields in class symbol supplements are:

    +
      +
    • +
      symbols, the symbol list pointed to from the scope stack entry for the +class, retained even after the scope stack entry disappears. The symbols +are in declaration order, which is the order in which initialization is to +be performed.
      +
      +
    • +
    • +
      constructor, a pointer to the sk_member_function or +sk_overloaded_function symbol that represents the constructor(s) for +the class. As noted above, the constructor symbol cannot be accessed +directly by normal name lookup, but only via this pointer.
      +
      +
    • +
    • +
      destructor and assignment_operator, pointers to the symbols +representing the destructor and operator=() functions for the class. +Both could also be accessed by normal name lookup, but having the pointers +directly available makes some processing, especially implicit invocations +of these functions, more efficient and facilitates deciding whether the +compiler needs to generate one.
      +
      +
    • +
    • +
      conversion_list, a linked list of entries that provide quick access to +the symbols for the user-defined conversion functions for the class (i.e., +that define a conversion from the class to some other type). The list +includes symbols for inherited conversion functions.
      +
      +
    • +
    • +
      routine_fixup_list, a pointer to entities that store cached tokens to +allow for delayed scanning of default arguments and the bodies of member +functions that are defined inline.
      +

      +
      operator_lookup_namespaces, a pointer to a list of namespaces that are +the parent namespaces of the class or one of its base classes. The global +scope is explicitly represented on this list by an entry with a NULL +namespace pointer. This list is used to specify the namespaces to be +searched for operator functions when an overloaded operator function is +called with an operand of the class.
      +
      +
    • +
    • +
      A number of flags to summarize attributes of the class. Most of these +flags are redundant – the attributes could also be computed by examining +other data. For instance, any_ref_member is checked when putting out +warnings on variables that should be initialized; its value could also be +determined by looking at all the nonstatic data members to see if any have +reference types.
      +
      +
    • +
    +
    +
    +

    6.3.2. Class Member Projection Symbols#

    +

    Symbols of kind sk_projection provide a mechanism to represent names that +are visible in a derived class having been declared in a base class. Each +projection symbol has a supplementary entity of type a_projection_descr +which identifies the fundamental base class member by pointing to the base +class entry and to a symbol from that base class. [5]

    +

    Projection symbols are created as needed (in the course of looking up a name) +and are added to the scope of the derived class. Once entered in a class +scope, they permanently associate the name in the derived class with a +declaration in a base class. The next time the name is looked up in the +lexical context of the class, the projection symbol will be found directly, +without the more expensive search of the base classes.

    +

    A projection symbol records a name’s accessibility in the current scope (e.g., +it may have been declared public originally but be less accessible in the +context of the derived class). It also notes whether a name is ambiguous. +These attributes of name inheritance are computed on the initial lookup, when +the projection symbol is created, and thus need not be recomputed on subsequent +references to the name.

    +

    Projection symbols are also used to represent base class member names that are +explicitly incorporated into the derived class by means of a +using-declaration; for these cases the flag is_using_decl is set to +TRUE.

    +

    When a using-declaration in a derived class specifies an overloaded member +function from a base class, each member of the original overload set will be +projected into the base class independently and recorded in an overload set +created in the derived class. The latter may contain a mix of +sk_member_function symbols from the derived class and sk_projection +symbols referring to member functions in one or more base classes. For +example:

    +
    struct A {
    +  void f(int);
    +  void f();
    +};
    +struct B {
    +  void f(double);
    +};
    +struct C : public A, public B {
    +  using A::f;
    +  using B::f;
    +  void f(char);
    +};
    +
    +
    +

    Here, the overload set for C::f will include C::f(char) along with +projections into C of A::f(int), A::f(), and B::f(double).

    +

    On the other hand, when is_using_decl is FALSE in an sk_projection +symbol, the projection may refer to an entire overload set and not to any +particular instance of the name. In such cases the access value will +represent the greatest access available; a particular function may turn out to +have less accessibility.

    +
    +
    +

    6.3.3. Namespace Projection Symbols#

    +

    Symbols of kind sk_namespace_projection are used to represent names made +visible by using-declarations that refer to namespace members +(using-declarations that refer to class members are described above). As +with class member using-declarations, when a using-declaration +specifies a overloaded function from another namespace, each member of the +overload set is projected into the current scope separately. The resulting +overload set may contain a mix of function, function template and namespace +projection symbols.

    +
    +
    +
    +

    6.4. Template Symbols#

    +

    Symbols of kind sk_class_template and sk_function_template have an +associated entry of kind a_template_symbol_supplement. Template processing +is discussed in detail in another chapter.

    +
    +
    +

    6.5. Namespace Symbols#

    +

    Symbols of kind sk_namespace have an associated entry of kind +a_namespace_symbol_supplement. As described above, the namespace symbol +supplement contains the pointers block used by scope stack entries that refer +to the namespace. It is possible for more than one scope stack entry for a +namespace or namespace extension scope to refer to a single namespace. In such +cases the scope stack entries all refer to the one pointers block structure in +the namespace symbol supplement. The namespace symbol supplement also contains +information used by the name lookup routines when doing lookups in the presence +of using-directives.

    +
    +
    +

    6.6. Symbol Lookup#

    +
    +

    6.6.1. Symbol Locator#

    +

    Symbol lookup is the process whereby a name, a qualified name, an operator +token, or a conversion result type is used to search for a symbol in the symbol +table and, if it exists, return it to the caller. A key intermediary construct +in this process is the entity of type a_symbol_locator. It consists of

    +
      +
    • +
      A pointer to a symbol header. (Sometimes error locators have a NULL symbol +header pointer; in all other cases a locator will point to a valid symbol +header.)
      +
      +
    • +
    • +
      A source position, the line and column in the source program at which the +reference starts.
      +
      +
    • +
    • +
      specific_symbol, a pointer to a symbol. This is usually NULL, but if +preliminary processing happens to turn up a symbol (e.g., in validating a +qualified name), it is saved here so that the lookup need not be done +again.
      +
      +
    • +
    • +
      The is_qualified_name, is_global_qualified_name, +is_file_scope_qualified_name, and is_super_qualified flags, which +specify the kind of qualifier, if any, that preceded the name.
      +
      +
    • +
    • +
      is_class_member, a flag that is TRUE for qualified names for which the +qualifier names a class. Note that the qualifier may also contain a +namespace specifier, but the last qualifier specifies a class name.
      +
      +
    • +
    • +
      parent, a union that, for qualified names, contains a pointer to either +the class or namespace specified by the qualifier. The is_class_member +field is used to specify whether the qualifier is a class or a namespace. +This field is also used to specify the class type associated with a vacuous +destructor reference.
      +
      +
    • +
    • +
      The is_template_id flag is TRUE if the name was followed by a template +argument list that has been coalesced. If the name is a class template +name, the specific_symbol will point to the template class designated +by the template argument list. The do_not_clear_specific_symbol flag +is set to TRUE when a class template argument list is coalesced because the +template argument list is not retained in the locator, and it would be +impossible to recompute the specific_symbol value if it were cleared.
      +
      +
    • +
    • +
      template_arg_list is used when an explicit function template argument +list is specified, and points to the template argument list that was +scanned. The is_template_id flag is also set. An empty template +argument list may be specified (e.g., “<>”), so the is_template_id +flag should be used to check for the presence of an explicit function +template argument list, not the template_arg_list field.
      +
      +
    • +
    • +
      The is_operator_name flag and the operator name kind. This flag is +TRUE and the associated field is defined only when it is an operator name +that is being looked up.
      +
      +
    • +
    • +
      The is_conversion_name flag and the conversion result type. This flag +is TRUE and the associated field is defined only when it is a user-defined +conversion that is being looked up.
      +
      +
    • +
    • +
      The is_destructor_name flag is TRUE when the name is a destructor name.
      +
      +
    • +
    • +
      The is_vacuous_destructor_reference and is_nonclass_destructor +flags, which are used to identify explicit destructor references for +classes without destructors or for nonclass types.
      +
      +
    • +
    • +
      The is_semivisible_nested_class flag is TRUE when the name is not +visible by standard scoping rules but only by a special search that +implements the “nested class anachronism” (ARM 18.3.5).
      +
      +
    • +
    • +
      The access_control_error_reported flag is TRUE if an accessibility +error has already been issued on the symbol.
      +
      +
    • +
    • +
      The is_error flag is TRUE when the locator represents an error.
      +
      +
    • +
    • +
      The do_not_clear_specific_symbol flag is TRUE if the +specific_symbol points to a value that should be retained because it +cannot or should not be reproduced by a repeated lookup. This is primarily +used for coalesced class template references, as described above, but is +also used for specific symbol error locators (error locators that refer to +a specially created error symbol).
      +
      +
    • +
    +

    Symbol locators are necessary because symbol lookup sometimes occurs in several +stages at separate points of processing. They provide a way to save and use +the intermediate results. For instance, when an identifier is scanned by +get_token, the locator is stored in locator_for_curr_id. Often a local +copy is made so that the information can be preserved as additional tokens are +scanned. Then when it comes time to actually enter the symbol in the symbol +table, all the information needed is right there in the locator.

    +
    +
    +

    6.6.2. Identifiers and Symbol Headers#

    +

    Each name in the source program is looked up as it is scanned. This is +necessary in part so that get_token processing can distinguish identifiers +from keywords.

    +

    find_symbol is called to look up the names in the hash table pointed to by +global variable symbol_table. The interface to find_symbol uses a name +string with a length rather than a null-terminated string because the string in +question is usually part of the source line buffer.

    +

    After the bucket number is computed, it searches the list of symbol headers +pointed to by the bucket till it finds a matching name. If it finds a match, +it moves the symbol header to the front of its bucket list so that +frequently-used entries will cluster near the beginning. If no match is found, +a new symbol header is created and entered. A pointer to the symbol header +(whether newly created or not) is returned in the symbol locator, and a pointer +to the list of active symbols associated with the symbol header is also +returned.

    +
    +
    +

    6.6.3. normal_id_lookup#

    +

    find_symbol locates a symbol header but does not actually find the symbol +itself. For simple names (e.g., not qualified names) that is done by +normal_id_lookup, which searches the symbol header’s active list – and, if +appropriate, its inactive list – to find a symbol in the appropriate name +space and lexical scope.

    +

    normal_id_lookup uses one of two search algorithms. The fast search (which +is the only one used in ordinary C mode) simply searches the active list: the +first symbol found which meets the search requirements is returned; in C++ mode +this search may only be used when there are no scopes on the scope stack that +alter the sequence in which scopes are considered for name lookup, and when the +lookup is not one of a number of special lookups that disregard certain kinds +of symbols.

    +

    The second and slower algorithm is required when

    +
      +
    • +
      A class or class reactivation scope is present, in which case one must look +for inactive symbols for the class members and for member names that are +inherited from base classes.
      +
      +
    • +
    • +
      A namespace, namespace extension, or namespace reactivation scope is +present, in which case one must look for inactive symbols for the namespace +members.
      +
      +
    • +
    • +
      A template instantiation scope is present, in which case inactive symbols +for the template parameters must be considered, and the scopes must be +searched in an irregular order (as described earlier).
      +
      +
    • +
    • +
      A using-directive is in effect, in which case one must look for symbols +for the namespaces referenced directly or indirectly by the +using-directive.
      +
      +
    • +
    • +
      A special lookup option has been specified for a given lookup. For +example, the lookup may optionally ignore class scopes, etc.
      +
      +
    • +
    +

    In such cases each scope must be considered individually, since there is no +single list that summarizes the visibility of names.

    +

    This comes up, for instance, in the non-inline definition of a member function: +the class definition has been completed and its names have been removed from +the active list, so those names must be searched for on the inactive list. For +example,

    +
    int i;
    +struct S { int i; int f(); };
    +int S::f() { return i; }
    +
    +
    +

    Here, when the body of S::f() is being scanned, the symbol for ::i will +be on the active list of the symbol header for i, whereas the symbol for +S::i will no longer be in scope, having been moved over to the inactive +list when the definition of S was completed. However, since the scope for +S is reactivated before the member function body is scanned, and since the +reactivated scope is examined before the file scope, it is S::i rather than +::i that will be found.

    +

    Similarly, when a namespace member is defined outside of its namespace a +namespace extension scope is pushed onto the scope stack at the point at which +names from the namespace should be visible.

    +
    int i;
    +namespace N { int i; int f(); }
    +void N::f() { return i; }
    +
    +
    +

    Here, as with the class member example shown above, the namespace member +N::i is found, hiding ::i.

    +
    +

    6.6.3.1. Slow Lookup Processing (scope_stack_lookup)#

    +

    scope_stack_lookup and the routines it calls are used to implement the slow +lookup. It is passed a range of scope depths to be included in the lookup. +Each scope is examined separately. The lookup begins with the scope stack +entry indicated by the global variable depth_of_initial_lookup_scope and +proceeds by following the previous_scope link in the scope stack entry +until a scope entry with no previous scope is found. active_scope_lookup +is called for scopes whose symbols are still on the active list and +inactive_scope_lookup is called for scopes whose symbols have been +transferred to the inactive list. When a class or class reactivation scope is +processed, a flag is returned that specifies whether scope_stack_lookup +should look for a projection symbol for the class as described below.

    +

    When a template instantiation scope has been processed, and a symbol has not +yet been found, names from both the context in which the template was defined +and from the context in which the template was used must be considered. This +is done by calling instantiation_context_lookup, which is described below.

    +

    A using-directive can cause names from other namespaces to be visible in a +namespace scope (including the global scope) that is currently on the scope +stack. The using_directives_apply flag in the scope stack entry is used to +indicate that such processing is required. When this flag is set for a +namespace scope or the global scope, do_using_directive_lookup is called to +search for applicable symbols from namespaces named in using-directives.

    +

    The presence of using-directives can result in more than one symbol +being found that satisfies the lookup. In such cases +do_using_directive_lookup creates a synthesized namespace projection +symbol that represents the set of symbols found (See using-Directive Processing and +Synthesized Namespace Projection Symbols). The lookup could determine that the name is +ambiguous in the current context, in which case a synthesized namespace +projection symbol that is flagged as ambiguous is returned.

    +
    +
    +

    6.6.3.2. Looking for Class Member Projection Symbols#

    +

    When a name is not found in a class, the classes from which it is derived must +be searched before the containing scope is examined. This is done by +find_projected_symbol, which looks for the name among the base classes (see +find_progenitor_symbol and symbol_projected_from_base_class) and if +successful creates an sk_projection symbol in the derived class and adds it +to either the active or the inactive list of the symbol header for the name. A +pointer to the projection symbol, which (as described previously) represents +the inheritance, is returned to normal_id_lookup, where it is placed in the +locator (field specific_symbol); a pointer to the symbol of which it is the +projection is returned from normal_id_lookup as the function return value. +Consider this example:

    +
    int i;
    +struct S { int i; };
    +struct T : public S { int f(); };
    +int T::f() { return i; }
    +
    +
    +

    In this case the scope for T is reactivated when the body of T::f() is +scanned. No T::i is found in the scope of T, but before the containing +scope (namely the file scope) is searched, the base class must be examined, and +so normal_id_lookup calls find_projected_symbol. This search turns up +S::i, so again ::i is eclipsed. In addition, a projection symbol for +i is created in class T (it points to S::i since it represents the +“projection” of i from S into T). Thus, on subsequent searches for +i in the scope of T a T::i will be found, namely the projection +symbol referring to S::i, and so the base class search will not have to be +repeated.

    +

    find_projected_symbol and its subroutines also compute the accessibility of +the inherited name and determine whether it is ambiguous. No errors are put +out at this point, since the name lookup routines are interested in name +visibility only; instead, the status is recorded in the projection symbol and +diagnostics can be issued later if appropriate.

    +
    +
    +

    6.6.3.3. Instantiation Context Lookup#

    +

    When a name is looked up as part of a template instantiation, and the name is +not found in the local context of the instantiation (the template parameters +and the scope(s) associated with the class or function being instantiated) it +must be looked up in the instantiation context. The front end implements two +different instantiation context lookup algorithms: the one mandated by the +standard (referred to as “dependent name lookup”), and the one that existed +before dependent name lookup was implemented that more closely reflects +existing practice and is more compatible with other compilers.

    +

    As described earlier, push_template_instantiation_scope configures the +scope stack so that three distinct contexts exist outside of the local context +of the instantiation: the template definition scopes, the referencing context +scopes, and the scopes common to both.

    +

    When doing dependent name lookup, the following steps are used to produce the +final result of the lookup:

    +
      +
    • +
      The name is looked up in the context of the template definition and only +names visible at the point of the template definition are considered.
      +
      +
    • +
    • +
      Only those base classes that do not depend on template parameters are +considered.
      +
      +
    • +
    +

    When not doing dependent name lookup, the following steps are used to produce +the final result of the lookup:

    +
      +
    • +
      The name is looked up in both the template definition context and the +referencing context by calling scope_stack_lookup with the appropriate +starting and ending scope depths. The lookup in the referencing context is +suppressed if the lookup in the definition context finds a class member.
      +
      +
    • +
    • +
      If none or only one of the lookups produces a symbol, and if the lookup in +the definition context did not find a class member, scope_stack_lookup +is called again to look in the common scopes.
      +
      +
    • +
    • +
      If no symbols were found by the two context lookups, the result of the +common scope lookup is used.
      +
      +
    • +
    • +
      If only one of the two context lookups produced a symbol, the result of the +common scope lookup is used as the value of the context lookup that did not +produce a symbol, and the next rule is followed.
      +
      +
    • +
    • +
      If the symbol from the referencing context is not a function or function +template, it is discarded.
      +
      +
    • +
    • +
      If there is still only one symbol from the two context lookups, that symbol +is used.
      +
      +
    • +
    • +
      If there are two symbols, a synthesized namespace projection symbol is +created that represents the result of the lookup.
      +
      +
    • +
    +

    Note that in both cases, these algorithms describe the result of the “normal” +lookup of the name. In addition to the entities made visible by the normal +lookup, additional functions and/or function templates may be made visible by +argument-dependent lookup.

    +
    +
    +

    6.6.3.4. Nested Class Anachronism Lookup#

    +

    If the processing described thus far in normal_id_lookup fails to find a +qualifying symbol, an additional search implementing the “nested class +anachronism” (ARM 18.3.5) is performed by calling find_nested_class_symbol, +which finds names of nested classes which, strictly speaking, should not be +visible. For example,

    +
    struct S {
    +  struct T {
    +    int a;
    +  };
    +  int b;
    +};
    +struct T x;
    +
    +
    +

    After the normal search for T is exhausted without turning up a symbol, an +additional search is made through the inactive list of the corresponding symbol +header for a symbol of a nested class whose innermost non-class containing +scope (in this case, the file scope) is still an active scope (in this case, it +is). When such a symbol is found, and it is the only symbol that qualifies, it +is returned to normal_id_lookup and a warning is issued. [6]

    +
    +
    +

    6.6.3.5. Nonreal and Proxy Class Lookup#

    +

    If the processing described thus far in normal_id_lookup fails to find a +qualifying symbol, and one or more of the classes included in the lookup has a +“nonreal” base class, a nonreal class member is created by calling +add_member_to_proxy_or_nonreal_class, and the symbol for the newly created +class member is returned.

    +
    typedef int Y;
    +template <class T> struct A : T {
    +  X x;   // assumed to be T::X
    +  Y y;   // ::Y
    +};
    +
    +
    +

    The nonreal lookup is only done when the normal lookup fails to find a symbol. +In the example above, ::Y is found, so no nonreal member is created. The +lookup of X fails to find a symbol, so a nonreal member is created.

    +
    +
    +

    6.6.3.6. Hide-by-sig lookup#

    +

    C++/CLI has a special kind of lookup used for members of managed classes, +called “hide-by-sig” lookup. In normal C++ name lookup, a name in a derived +class hides all instances of the same name in a base class; this is called +“hide-by-name” lookup. In hide-by-sig lookup, on the other hand, a member +function in a derived class hides a member in a base class only if their +signatures match. A function “voidf(int)” in a derived class, for +example, would not hide a function “voidf(char)” in a base class; +both would appear in an overload set and might compete with each other. In +addition, hide-by-sig lookup considers access – inaccessible members of base +classes are not seen by the lookup. And there are special rules regarding +interfaces, which are too arcane to describe here. Hide-by-sig lookup only +applies to functions.

    +

    Hide-by-sig lookup is implemented by building a list of +a_hide_by_sig_list_entrys that enumerates all the symbols that co-exist +with a given symbol in an overload set. The list is built by +use_hide_by_sig_lookup and saved in the symbol’s +hide_by_sig_lookup_result field so it only needs to be constructed the +first time a hide-by-sig lookup is done on the symbol. Overload resolution +traverses that list to build up the set of functions in an overload resolution +set. Access is checked while the overload set is built up, and inacessible +functions are discarded at that point (different places in the program may have +differing access to the base class members; this allows a single general +hide-by-sig list to be built and then used with different access contexts).

    +
    +
    +

    6.6.3.7. Lookup of Entities Imported from C++/CLI Metadata#

    +

    When C++/CLI metadata files are imported by way of a #using directive or +implicitly for the entities in mscorlib, only the namespace-scope-level +names in the file are added to the symbol table. For a class, for example, the +class name is entered as an incomplete type, and its definition and members are +not immediately entered. Later, if a lookup is done in the class scope, the +members of the class are fetched from metadata and added to the symbol table. +This “lazy” lookup makes the use of metadata files much more efficient, since +things are not loaded until they are actually needed. This is implemented by +piggy-backing on the mechanism that instantiates templates when a member of the +template is required: f_instantiate_template_class (often invoked from the +macro complete_class_type_is_needed)will call get_definition_of_class +to fill in the definition of an entity imported from metadata. This is done +automatically whenever a class-scope lookup is done in a class that came from +metadata. The definition is loaded, the lookup is then done, and the result is +returned to the caller, who has no need to know that the class definition had +to be loaded to be able to perform the name lookup.

    +
    +
    +

    6.6.3.8. C mode out-of-scope declarations#

    +

    When compiling C code, if the processing described thus far in +normal_id_lookup fails to find a qualifying symbol, +find_out_of_scope_declaration is called to look for an external variable or +function that was declared in a scope that is no longer visible. If such a +symbol is found, it is reentered in the current scope and returned as the +result of the lookup.

    +
    void g1(void) {
    +  extern void f(int);
    +  f(1);
    +}
    +void g2(void) {
    +  f(2);
    +}
    +
    +
    +

    A symbol for void f(int) is reentered in g2, even though f is no +longer visible. This lookup is not performed in strict mode.

    +
    +
    +

    6.6.3.9. Lookup Options#

    +

    Options flags may be supplied to normal_id_lookup that affect the kinds of +symbols that are visible and other aspects of the name lookup process. In +certain contexts a name lookup is required to determine whether a given name is +a type. In this context a projection symbol should not be created unless the +name is a type. The flag IDL_TENTATIVE_TYPE_LOOKUP is used to suppress the +creation of a projection symbol in this instance.

    +

    A special lookup is also required when scanning a constructor initializer list +that may include member names and base class names but may not reference the +names of parameters of the constructor. The IDL_SKIP_CURR_FUNCTION_SCOPE +flag is used to request this kind of lookup.

    +

    IDL_LINKAGE_LOOKUP indicates that the lookup is being used to find a +previous declaration of a name and that certain special lookup features should +be suppressed and that the lookup should terminate at the nearest enclosing +namespace scope. This option suppresses nested class anachronism, nonreal +member lookup, and out-of-scope declaration processing.

    +

    IDL_SKIP_CLASS_SCOPES causes class and class reactivation scopes to be +ignored. This is used when looking up nonmember operator functions.

    +

    IDL_INSTANTIATION_CONTEXT is used to indicate that a lookup operation is +part of a special instantiation lookup that looks in both the template +definition and reference contexts.

    +
    +
    +
    +

    6.6.4. Looking Up Names in the Current Scope#

    +

    curr_scope_id_lookup looks up a name in the current scope and returns the +symbol found or NULL if no symbol is found. The symbol must be a name declared +in the scope. using-directives are not considered and projection symbols +to base class members are not considered unless the +IDL_PROJECTION_SYMBOL_ALLOWED option is specified.

    +
    +
    +

    6.6.5. Looking Up Class Members#

    +

    class_qualified_id_lookup is used to look up a name in the scope of a class +and its base classes. As with normal_id_lookup, the caller provides a +symbol locator that contains a pointer to the symbol header for the identifier +being looked up. The search begins by looking through the inactive list for a +symbol from the scope associated with the class type passed by the caller. If +the symbol is not found on the inactive list, the active list is also checked. +The active list check is needed when a class-qualified lookup is done while the +class is being defined. For example,

    +
    struct A {
    +  struct B {};
    +  A::B f();  // the A:: is not necessary, but is allowed
    +};
    +
    +
    +

    If the symbol has still not been found, and the lookup is being done in a +nonreal class, a symbol for a nonreal class member is created by calling +add_member_to_proxy_or_nonreal_class, and the newly created symbol is +returned (see Nonreal and Proxy Class Members for more information).

    +

    If the symbol has still not been found, the name is checked to see if it is a +constructor or destructor for the class. If so, the symbol for the constructor +or destructor from the class symbol supplement is returned.

    +

    Finally, if the symbol has still not been found, find_projected_symbol is +called to search the base classes for a member that may be projected into the +class.

    +
    +

    6.6.5.1. Nonreal and Proxy Class Members#

    +

    A nonreal class is a template class that has one or more template arguments +that depend on template parameters. A proxy class is a class that stands in +for a template parameter when that template parameter is used in a context that +requires a class type. For example:

    +
    template <class T> struct A {
    +  typename T::A      a;
    +  typename A<T*>::X  b;
    +  typename T::Z<int> c;
    +  int n[T::B];
    +};
    +
    +
    +

    In this example a proxy class is created for T so that A and B may +be looked up in T. A nonreal class for A<T*> is created, a nonreal +template named T::Z is created, and the nonreal instance T::Z<int> is +created.

    +

    proxy_class_for_template_param creates a proxy class associated with a +given template parameter. The proxy class is created the first time that it is +needed

    +

    create_proxy_or_nonreal_class_member creates a member of a nonreal or proxy +class. It is called by add_member_to_proxy_or_nonreal_class which also +adds the newly created symbol to the inactive list so that it may be found by +subsequent lookups. The kind of entity that is created (type, constant, or +template) depends on the kind of lookup that is done, and on whether the +“implicit typename” option is enabled. nonreal_member_symbol_kind is used +to determine the kind of symbol to be created for a given set of lookup +options.

    +
    +
    +
    +

    6.6.6. Looking Up Namespace Members#

    +

    namespace_qualified_id_lookup is used to look up a name in the scope of a +namespace. If the name is not found in the namespace, the name is also sought +in any namespaces referenced by using-directives in the specified +namespace. lookup_in_namespace is called to look for the name in the +specified namespace. If a symbol is found, it is returned; otherwise +lookup_in_namespace calls qualified_using_directive_lookup, which loops +though the using-directives found in the original namespace and calls +lookup_in_namespace recursively to look for the name in those namespaces. +qualified_using_directive_lookup always considers all namespaces named in +using-directives within a given namespace (i.e., it does not stop searching +when a symbol is found in a given namespace). For example, the hierarchy below +would be created by the following example:

    +
    //   D       E
    +//    \     /
    +//     B   C
    +//      \ /
    +//       A
    +namespace E { }
    +namespace D { }
    +namespace C { using namespace E; }
    +namespace B { using namespace D; }
    +namespace A { using namespace B; using namespace C;}
    +
    +
    +

    In such a hierarchy, when looking up a name in namespace A

    +
      +
    • +
      If the name is found in A, the lookup will not look in any other +namespace.
      +
      +
    • +
    • +
      If the name is not found in A, the lookup will always look in both +B and C.
      +
      +
    • +
    • +
      If the name is not found in B, the lookup will look in D.
      +
      +
    • +
    • +
      If the name is not found in C, the lookup will look in E.
      +
      +
    • +
    +

    The presence of using-directives can result in more than one symbol +being found that satisfies the lookup. In such cases +qualified_using_directive_lookup creates a synthesized namespace +projection symbol that represents the set of symbols found (see +using-Directive Processing and Synthesized Namespace Projection Symbols). The lookup could determine +that the name is ambiguous in the current context, in which case a +synthesized namespace projection symbol that is flagged as ambiguous is +returned.

    +

    When a namespace contains an inline namespace (a C++11 feature), or a namespace +named in a GNU strong using-diirective, namespace lookup is done slightly +differently. Normally, if a name is found in a namespace, other namespaces +made visible in that namespace by using-directives are not searched, but a +namespace was made visible as an inline namespace (or strong using-directive) +is searched even when a symbol was found in the original namespace.

    +
    +
    +

    6.6.7. Looking Up Names in the File Scope#

    +

    The file scope is also known as the global scope, and, with the addition of +namespaces, as the “global namespace”. The same qualified name lookup rules +apply to both namespace qualified lookups and file scope qualified lookups. +file_scope_id_lookup looks on the active list for a name declared at the +file scope. If the name is not found on the active list, the inactive list is +seached. If the name is not found in the file scope, +qualified_using_directive_lookup is called to look in scopes named by +using-directives in the file scope.

    +

    In the presence of multiple translation units there can be more than one file +scope. The scope pointer for the file scope to be used is passed to +file_scope_id_lookup.

    +
    +
    +

    6.6.8. Argument-Dependent Lookup#

    +

    When an unqualified name is used as the function name in a function call, the +name is looked up using both the normal lookup mechanism and also using what is +known as “argument-dependent lookup”. Argument-dependent lookup uses the types +of the function arguments to produce a set of “associated classes” and +“associated namespaces” to be searched for candidate functions.

    +

    argument_dependent_lookup is called to perform an argument-dependent +lookup. It calls determine_assoc_namespaces_and_classes to determine the +associated namespaces and classes to be used for the lookup. Normally, only +names from the current translation unit are considered by the +argument-dependent lookup process, but when instantiating exported templates +(and non-exported templates whose instantiation results from the instantiation +of an exported template) argument-dependent lookup is done in each of the +translation units on the translation unit stack and the results of the lookups +are combined.

    +

    Argument-dependent lookup returns a list of symbols representing the candidate +functions being found. The symbol list may contain functions, function +templates, and overload sets. Argument-dependent lookup is normally done in +conjunction with a normal lookup. The symbol representing the normal lookup +result is passed to argument_dependent_lookup and is returned as an element +of the resulting symbol list. The resulting symbol list may directly or +indirectly (as part of an overload set) include multiple instances of a given +function or function template. This occurs for several reasons:

    +
      +
    • +
      The symbol list includes the result of both the normal and +argument-dependent lookups, which may produce overlapping results.
      +
      +
    • +
    • +
      The symbol list includes overload sets which may, as a result of +using-directives, include the same functions or function templates.
      +
      +
    • +
    • +
      The argument-dependent lookup may be done in multiple translation units +when exported templates are used. The same functions or templates may be +found in more than one of the translation units.
      +
      +
    • +
    +
    +
    +

    6.6.9. using-Directive Processing#

    +

    using-directives are used to make names from a namespace visible at a +certain point in the unqualified lookup process (i.e., the lookup performed by +normal_id_lookup). using-directives that appear in namespace scopes +can also affect qualified lookups in the namespace in which they appear. +Qualified using-directive lookups simply make use of the +using-directives list found in the scope entry. Unqualified +using-directive lookups, on the other hand, rely on additional data +structures that are maintained to optimize the process of finding names made +visible by using-directives during the normal_id_lookup process.

    +

    A using-directive can appear in a namespace scope (including the files +scope), or in a block scope. The scope that contains the using-directive +is often not the scope at which the using-directive “applies”, however. A +using-directive “applies” at the nearest enclosing scope that is or +contains the namespace named in the using-directive, and contains the +using-directive. For example,

    +
    namespace A {}
    +namespace B {
    +  namespace C {
    +    using namespace A;  // applies to the file scope
    +  }
    +  using namespace C;    // applies to B
    +}
    +using namespace B::C;   // applies to the file scope
    +
    +
    +

    The primary piece of information that is maintained to optimize unqualified +using-directive lookups is a field in the namespace symbol supplement that +indicates the scope depth of the scope at which a using-directive for that +namespace applies, or contains NO_SCOPE_DEPTH if there is no +using-directive in effect that makes symbols from the associated namespace +visible.

    +

    do_using_directive_lookup simply looks through the inactive symbols for a +symbol whose parent namespace has a using-directive that applies at the +scope depth currently being processed by scope_stack_lookup.

    +

    The problem with this kind of state information is that it needs to be reset +each time a template instantiation begins and restored each time an +instantiation ends. To make the process of clearing and restoring the state +information as efficient as possible, the scope stack entry contains a list of +“active” using-directives for the scope. An active using-directive is +one that appeared in the scope or appeared in one of the namespaces named by a +using-directive in the scope.

    +

    When a using-directive appears, add_active_using_directive is called to +add it to the active using-directive list for the current scope. It then +calls add_active_using_directive_to_scope, which actually adds it to the +list.

    +

    using-directives are transitive, meaning that any using-directives that +appear in the namespace nominated by a using-directive are treated as if +they also appeared in using-directives in the scope containing the original +using-directive. add_active_using_directives_for_namespace is called +to add the namespaces that appear in using-directives in the nominated +namespace to the active using-directive list, which it does by recursively +calling add_active_using_directive_to_scope. When +add_active_using_directive adds a using-directive to a namespace scope +it searches through the scope stack to find active using-directive lists +that refer to the namespace containing the new using-directive. If such +scopes are found, add_active_using_directive_to_scope is called to add the +newly nominated namespace to those scopes.

    +

    add_active_using_directive_to_scope determines the scope depth at which a +using-directive applies. This scope depth is recorded in the namespace +symbol supplement of the namespace being added. The scope stack entry +associated with that scope depth is updated to indicate that there are +using-directives that apply when that scope is reached in an unqualified +lookup.

    +

    set_active_using_list_scope_depths is called to reset and restore the state +of the scope depth information in the namespace symbol supplement and the +using_directives_apply field in the scope stack entry. This is done at the +beginning and end of a template instantiation scope, and is also done whenever +a scope containing active using-directives is popped off of the stack.

    +
    +
    +

    6.6.10. Synthesized Namespace Projection Symbols#

    +

    The addition of namespaces creates situations in which the result of a lookup +can be a set of symbols from different scopes. A synthesized namespace +projection symbol is created to represent the result of such a lookup. +Synthesized namespace projection symbols are created

    +
      +
    • +
      by an unqualified lookup in which the symbols found were made visible by a +using-directive,
      +
      +
    • +
    • +
      by an qualified lookups in which the symbols found were made visible by a +using-directive, and
      +
      +
    • +
    • +
      by an instantiation context lookup in which symbols were found in both the +definition and referencing contexts.
      +
      +
    • +
    +

    The synthesized_namespace_projection flag in the symbol entry identifies a +symbol as a synthesized namespace projection. Such symbols can be of kind +sk_namespace_projection or sk_overloaded_function. In the latter case, +each of the entries on the list of overloaded functions points to a +sk_namespace_projection symbol.

    +

    Where synthesized namespace projection symbols are used, the lookup must result +in at most one symbol being found, or, all of the symbols found must be +functions that can be combined into an overload set. If more than one symbol +is found and they are not all functions, the lookup is ambiguous. The +ambiguous flag in the symbol entry is set in that case.

    +

    The following steps are used to construct a synthesized namespace projection +symbol for a given lookup:

    +
      +
    1. find_synthesized_projection_symbol is called to find a previously +created namespace projection symbol. This is done so that the space used +by a previously created synthesized projection symbol can be reused. +The actual information pointed to by the symbol is not reused because it +may have changed since the last lookup was done. More specifically, a +set of overloaded functions is assumed always to contain at least the +functions that were previously in the set. When looking for a previously +created symbol, the lookup options used for the new lookup must match +the options used when the symbol was created. A number of symbols with +the same name but with different lookup options may be created in a +given scope. Some combinations of lookup options are considered to be +sufficiently unusual that they are not entered in the symbol header for +reuse. Such symbols are identified by setting the do_not_reuse flag in +the symbol entry. find_synthesized_projection_symbol suppresses the +search and returns NULL when asked to find a symbol with a set of lookup +options for which symbols cannot be reused. The lookup options used when +a synthesized namespace projection symbol is created are stored in a set +of flags in the symbol entry. The flags used for this purpose are

      +
        +
      • +
        qualified_lookup
        +
        +
      • +
      • +
        must_be_class_or_namespace_lookup
        +
        +
      • +
      • +
        must_be_tag_lookup
        +
        +
      • +
      • +
        tentative_type_lookup
        +
        +
      • +
      • +
        do_not_reuse
        +
        +
      • +
      • +
        instantiation_context_lookup
        +
        +
      • +
      +
    2. +
    3. +
      As symbols are found that match the lookup criteria, +add_symbol_to_lookup_set is called with a pointer to the previously +created synthesized projection symbol (if any) and the symbol to be added. +The symbol returned is used as the new synthesized projection symbol.
      +
      +
    4. +
    5. +
      add_symbol_to_lookup_set calls merge_function_into_lookup_set +when the symbol being added is a function or function template. Before a +function is actually added, the current lookup set is examined, by calling +already_in_lookup_set, to make sure it is not already present.
      +
      +
    6. +
    7. +
      add_symbol_to_lookup_set determines whether the symbol being added +can coexist with any symbols already in the lookup set, whether the new +symbol should hide a previous symbol, or whether the lookup is ambiguous.
      +
      +
    8. +
    +

    Reusable synthesized projection symbols are entered on the “other” symbols list +in the symbol header and on the synth_namespace_projection_symbols list in +the pointers block for the scope with which they are associated. Symbols that +are not reusable are only entered on the list in the pointers block. +Synthesized projection symbols that are created by a qualified lookup are +entered in the scope of the namespace of the qualifier. All other synthesized +projection symbols are entered into the current scope.

    +
    +
    +

    6.6.11. Overloaded Operators#

    +

    Overloaded operators are not looked up by name, so find_symbol cannot be +used to locate the symbol header. Instead, the header is found by indexing +into the array of symbol header pointers opname_symbol_table. The index +value will be a member of the enumeration an_opname_kind, which maps to the +subset of the enumeration a_token_kind that comprises those operators +subject to overloading. [7]

    +

    When an overloaded operator is explicitly named (for instance, operator+ or +A::operator new), it is represented by a tok_identifier “pseudo-token” +somewhat like qualified names. The symbol locator’s is_operator_name flag +will be set and the field opname will identify the operator being +overloaded. make_opname_locator is called to set these fields and as well +to create and enter the symbol header if one does not yet exist. Scanning the +token sequence representing an overloaded operator is handled by +f_get_opname , [8] which does error checking and also deals with +conversion operators (discussed below).

    +

    nonmember_operator_function_lookup is used to find the set of nonmember +overloaded operator functions for a given operator kind and a pair of operand +types. When looking for a nonmember operator function, one must do a normal +(i.e, unqualified) lookup of the operator name, and one must also look up the +operator name in the namespaces of the operand types and the base classes of +the operand types. For each class type, there is a list of namespaces in which +to look for nonmember operator functions. The list is pointed to by the +operator_lookup_namespaces field of the class symbol supplement. The +search is done by looking at both the active and inactive lists from the +appropriate symbol header and checking whether the parent namespace of the +symbol is on the operator lookup namespaces list of one of the operand class +types. Note that only immediate members of the namespaces on the operator +lookup namespaces list are considered. using-directives in those +namespaces have no effect on the lookup. The result of the lookup is a pointer +to a list of entry of kind a_symbol_list_entry or NULL if no such operator +functions have been declared. Each entry points to a symbol that meets the +lookup criteria. The caller is responsible for freeing the symbol list when it +is no longer needed by calling free_list_of_symbol_list_entries. +opname_function_symbol is a simplified version of +nonmember_operator_function_lookup that is used for looking up new and +delete operators, which cannot be declared in namespaces.

    +

    global_operator_new_or_delete_symbol looks up symbols for the default +versions of operator new and delete at file scope (i.e., ::operator +new(size_t) and ::operator delete(void*)), but unlike +opname_function_symbol it will, if no such symbol exists yet, implicitly +declare the function, creating and entering its symbol and adding the routine +entry to the IL.

    +
    +

    6.6.11.1. Template Conversion Operators#

    +

    When a class contains a template conversion operator, the lookup of a +particular conversion operator may require the partial instantiation of the +conversion operator template. For example:

    +
    struct A {
    +  template <class T> operator T();
    +};
    +int main(){
    +  A a;
    +  a.operator int();
    +}
    +
    +
    +

    Class A does not contain an operator int conversion function that can +be found by the normal lookup mechanism. Instead, the lookup operation must +match the required type (int) with the available conversion templates to +see if a match can be found. look_up_conversion_template_instance is +called to look for the matching conversion template. If more than one matching +template is found a symbol that is marked as ambiguous is returned.

    +

    If the result type of the conversion depends on a template parameter, or if the +class type on which the conversion operator is being called is a nonreal class, +it is not possible to find a matching conversion operator. In such cases an +“unknown conversion function” entry is created. This is represented by a +special kind of template parameter constant that contains a pointer to the +conversion result type.

    +
    +
    +
    +

    6.6.12. Constructors and Destructors#

    +

    Several routines search for a constructor or destructor of a particular kind in +a given class.

    +

    select_default_constructor finds the default constructor for a given class. +A default constructor is one that can be called with no arguments. If the +class has no default constructor, an error is issued.

    +

    select_destructor finds the destructor for a given class. If the class has +no destructor, it returns NULL.

    +

    select_copy_constructor finds a copy constructor for a given class. It can +be told to look for a copy constructor that will accept const- or +volatile-qualified objects. If no appropriate copy constructor exists, an +error is issued.

    +
    +
    +

    6.6.13. User-Defined Conversions#

    +

    Like overloaded operators user-defined conversion functions (or “conversion +operators”) cannot be looked up by name. Rather, the symbol header is looked +up by result type, using the linked list of entries of type +a_conversion_header and pointed to by conversion_header_list, as +described earlier. Since all user-defined conversion functions are member +functions, once the symbol header is found, searching for a symbol simply +involves discriminating on the basis of the parent.class_type field.

    +

    An explicitly named conversion function (e.g., operator int()), is +represented (like overloaded operators) by an identifier token; in its +associated symbol locator is_conversion_name is TRUE and +conversion_result_type points to a type entry for the result of the +conversion. The routine called to find the conversion header (and thereby the +symbol header) and to set these fields is make_type_conversion_locator. It +also creates the conversion header (as well as the symbol header) if none +exists yet. The token sequence representing a conversion function is scanned +by scan_conversion_operator, which is called from f_get_opname.

    +

    Sometimes the question to be answered in processing an expression is, “What +user-defined conversion function exists to convert an object of class A to +type T?” In such cases it would be straightforward to find the appropriate +symbol by using the result type to identify the conversion header and then the +class type to choose among the associated conversion function symbols. But at +other times – for instance, when looking for the best implicit conversion or +when there are inherited conversion functions – the question is subtly +different: “Which, if any, of the user-defined conversion functions that exist +for class A is most suitable for converting to type T?” To optimize +answering this question, another construct appears in the symbol table, +a_conversion_list_entry, each instance of which points to a symbol entry +representing a conversion function. A class’s symbol supplement contains a +pointer to such a list, which is updated in decl_member_function each time +a conversion function is declared; the list also contains projection symbols to +represent inherited conversion functions (see +project_base_class_conversion_functions).

    +
    +
    +
    +

    6.7. “Extern” Symbols#

    +

    When it is required that distinct declarations in different name scopes refer +to the same entity, an extra symbol is created to represent the shared entity. +For instance,

    +
    void f() {
    +  extern int i;
    +}
    +void g() {
    +  extern int i;
    +}
    +extern int i;
    +
    +
    +

    In this example, although all three declarations of i refer to the same +variable, three independent sk_variable symbols are created to represent +it, one in the scope of function f, one in the scope of function g, and +one in the file scope. So a fourth symbol is created at file scope to +represent i – its kind is sk_extern_variable, and it is created at the +first declaration of i. Then, even after the sk_variable symbol for +the declaration of i in function f goes out of scope, the +sk_extern_variable symbol is still around to be found again on the +subsequent declarations of i; this assures that all three i symbols +point to the same IL entity. A similar technique, using sk_extern_function +symbols, is employed for functions. These “extern” symbols are put on the +“other” symbols list instead of being put on either the active or inactive list +and so are not found during normal name lookup.

    +

    The routine that manages all this is find_external_symbol. It also has +special logic, subject to configurable control, to deal with instances in which +different source names resolve to the same “external” name because of object +language constraints – e.g., where linkers can handle only so many characters +or are not case sensitive.

    +
    +
    +

    6.8. Symbol Management#

    +

    It remains to describe briefly some of the other low-level routines and macros +used to manage the symbol table and return information about symbols.

    +
      +
    • +
      alloc_symbol is called to allocate a symbol entry of a specified kind. +When a NULL symbol header is passed, it allocates an error symbol, one +whose header is error_symbol_header. It calls clear_symbol and +set_symbol_kind to initialize the new entities; the latter also +allocates the supplementary constructs for class and projection symbols. +Other routines called to allocate and initialize the entities from which +the symbol table is constructed are
      +
      +
        +
      • +
        alloc_symbol_header,
        +
        +
      • +
      • +
        alloc_conversion_header, and
        +
        +
      • +
      • +
        alloc_conversion_list_entry
        +
        +
      • +
      +
    • +
    • +
      enter_namespace_projection_symbol is called to create new namespace +projection symbols and enter them in the symbol table. Passed a pointer to +the fundamental symbol, it allocates and initializes the symbol and links +it into the symbol table and scope list. This routine is needed because a +namespace projection symbol cannot be entered into the symbol table via +enter_symbol because that doesn’t allow specification/setting of the +fundamental symbol and the fundamental symbol is used by enter_symbol +for checking compatibility with previous declarations of the name in the +current scope.
      +
      +
    • +
    • +
      enter_synthesized_namespace_projection_symbol creates new synthesized +namespace projection symbols and enters them on the “other” symbols list if +they can be reused. This routine also determines the scope list on which +the symbol should be placed based on the lookup options and the qualifier +namespace, and sets the lookup option fields in the symbol entry.
      +
      +
    • +
    • +
      enter_symbol is called to create new symbols and enter them in the +symbol table. Passed a symbol kind, it allocates and initializes the +symbol, marks it as having been referenced, and links it onto the symbol +header’s active list and onto the current scope’s symbol list.
      +
      +
    • +
    • +
      reenter_symbol takes an existing symbol (one that may have been entered +already and then removed) and links it into the symbol table.
      +
      +
    • +
    • +
      full_enter_symbol calls find_symbol to locate the symbol header for +a name and then calls enter_symbol. This is convenient when creating +symbols for the reserved names of keywords and predefined macros (see +enter_keyword and enter_predef_macro in fe_init.c).
      +
      +
    • +
    • +
      link_symbol_into_symbol_table, called from enter_symbol and +elsewhere, links a symbol onto the symbol header’s active list. Though it +normally ends up adding the symbol to the front of the list, it is careful +to account for special cases by determining the precise location based on +the scope number and name space overloading. It will issue a redeclaration +error when it detects that the name has already been declared in the +current scope.
      +
      +
    • +
    • +
      add_symbol_to_scope_list is also called from enter_symbol; it adds +a symbol to the end of the symbol list [9] of the scope stack entry at +the specified scope depth.
      +
      +
    • +
    • +
      enter_overloaded_symbol is called to enter a function symbol in the +symbol table when its name is overloaded. First, it allocates and +initializes the sk_routine or sk_member_function symbol. Then, if +an sk_overloaded_function symbol already exists for the name, the new +symbol is added to its list. If not, a new sk_overloaded_function +symbol must also be created; it will replace the existing function symbol +in the symbol table.
      +
      +
    • +
    • +
      make_namespace_projection_symbol allocates and initializes namespace +projection symbols. A pointer to the fundamental symbol is provided.
      +
      +
    • +
    • +
      make_projection_symbol allocates and initializes sk_projection +symbols, leaving it to the caller, find_projected_symbol, to add the +new symbol to the symbol table, since it may be inserted in either the +active list or the inactive list of the symbol header.
      +
      +
    • +
    • +
      make_template_class_symbol creates and initializes a symbol for an +instance of a class template. It is linked in the template’s instantiation +list rather than added directly to the symbol table.
      +
      +
    • +
    • +
      make_unnamed_tag_symbol is invoked to allocate and initialize a tagless +class, struct, and union symbol. It is not actually entered into the +symbol table since, like error symbols, it uses a special symbol header +(see static variable unnamed_tag_symbol_header). If the class +subsequently acquires a name, relink_unnamed_tag_symbol is called to +modify the symbol entry and add it to the symbol table.
      +
      +
    • +
    • +
      unlink_symbol_from_symbol_table is called from pop_scope for each +name that passes out of scope: it removes the symbol from the symbol +header’s active symbol list, but the symbol remains on the scope list.
      +
      +
    • +
    • +
      remove_symbol removes a symbol from the symbol table, e.g., for a macro +definition when a #undef is encountered. +unlink_symbol_from_symbol_table is called to remove a symbol from the +active list and remove_symbol_from_scope_list is called to remove it +from the symbol list of the scope stack entry.
      +
      +
    • +
    • +
      When cross-reference information is being generated, write_xref_entry +is called to create a record describing a reference and to write it to the +file indicated by f_xref_info.
      +
      +
    • +
    • +
      record_symbol_declaration is called for every declaration and +definition of a name. It sets the source sequence number if this is the +initial declaration, may set the source position (for initial declarations +and for definitions), optionally calls write_xref_entry, and (when +GENERATE_SOURCE_SEQUENCE_LISTS is TRUE) calls +sym_update_source_sequence_list.
      +
      +
    • +
    • +
      mark_defined and mark_declared are macro interfaces to +record_symbol_declaration, for definitions and non-defining +declarations, respectively.
      +
      +
    • +
    • +
      record_symbol_reference is called for nondeclarative references to +symbols. It optionally calls write_xref_entry, specifying the +kind of reference (see a_symbol_reference_kind), sets the +symbol’s referenced flag, and may set the referenced flag in +the IL entry. For variables, it checks for the need to issue a +“used-before-set” warning and calls mark_variable_value_set if +appropriate.
      +
      +
    • +
    • +
      mark_variable_value_set is called to set the value_has_been_set +flag in the symbol of a variable or static data member. For a variable +entry that represents function parameter or a handler parameter it also +sets param_value_has_been_changed.
      +
      +
    • +
    • +
      sym_update_source_sequence_list is called (when +GENERATE_SOURCE_SEQUENCE_LISTS is TRUE) to generate a source sequence +entry for a declaration. (Source sequence lists are discussed in greater +detail in the context of the intermediate language.)
      +
      +
    • +
    • +
      clear_locator is a macro used to clear the fields of a locator and +initialize source_position to a specified value; +set_to_error_locator is similar but is used when errors are +encountered.
      +
      +
    • +
    • +
      set_to_named_error_locator turns a locator into an error locator – but +one that preserves information about the identifier with which the locator +is associated.
      +
      +
    • +
    • +
      tildize_locator takes the locator for an identifier token, turns the +name into a destructor name by prepending a ~, calls find_symbol to +find (or create) the associated symbol header, and returns a locator for +new name.
      +
      +
    • +
    • +
      change_class_locator_into_constructor_locator takes a locator for a +class name (its specific_symbol field will point to the class, struct, +or union symbol) and modifies it to point to a separate header of the same +name that serves as the header for a constructor. [10]
      +
      +
    • +
    • +
      make_opname_locator creates a locator to represent a token sequence +consisting of operator and the token (or token pair) for an +overloadable operator. It looks for the corresponding header in the +opname_symbol_header array; if none is found, it creates one and adds +it to the array.
      +
      +
    • +
    • +
      make_type_conversion_locator creates a locator to represent a token +sequence consisting of operator and tokens making up a type name. It +looks for the corresponding header by scanning conversion_header_list; +if none is found, it creates one, along with a new conversion header entry, +and adds the latter to the head of the linked list.
      +
      +
    • +
    • +
      make_locator_for_symbol is called to initialize a locator based on an +already existing symbol.
      +
      +
    • +
    • +
      set_source_corresp is called to establish a correspondence between an +IL entry and a symbol. It links the IL entry back to the symbol.
      +
      +
    • +
    • +
      set_decl_sequence_number is called to set a declaration sequence number +for a symbol. Such numbers identify the sequential position of one +declaration relative to others in the same translation unit. When a name +is multiply declared, the position of its definition is recorded in the +declaration sequence number.
      +
      +
    • +
    • +
      A number of macros in symbol_tbl.h provide the preferred method of +identifying a given symbol’s special characteristics:
      +
      +
        +
      • +
        is_class_symbol
        +
        +
      • +
      • +
        is_tag_symbol
        +
        +
      • +
      • +
        is_type_symbol
        +
        +
      • +
      • +
        is_function_symbol
        +
        +
      • +
      • +
        is_member_function_symbol
        +
        +
      • +
      • +
        is_constructor_symbol
        +
        +
      • +
      • +
        is_destructor_symbol
        +
        +
      • +
      • +
        is_copy_constructor_symbol
        +
        +
      • +
      +
    • +
    • +
      type_symbol_type is a macro that may be invoked for symbols for which +is_type_symbol is TRUE; it returns a pointer to the associated type +entry.
      +
      +
    • +
    • +
      symbol_supplement_for_class takes a type entry of kind tk_class, +tk_struct, or tk_union and returns a pointer to the associated +symbol’s class symbol supplement entry.
      +
      +
    • +
    +
    +
    +

    6.9. Access Control#

    +

    The function of access control is to determine whether or not a given name can +be accessed from the current location in the source program. Every reference +to a name, whether qualified or not, whether part of an expression or a type, +is checked to make sure the identifier is unambiguous and accessible. There +are several things to remember about access control:

    +
      +
    • +
      Only class members are subject to access control. Non-class members are +always accessible.
      +
      +
    • +
    • +
      Access control is site-specific. A given member can be accessible from one +place in a program and not accessible from somewhere else. In particular, +members and friends of a class have special access to the members of the +class and its base classes.
      +
      +
    • +
    • +
      Access control limits access, not visibility. Members that are not +accessible are still visible. They are found, the access error is issued, +and then (the way the front end does it) they are used anyway.
      +
      +
    • +
    • +
      When members are inherited into derived classes, the access to the members +in the derived class is affected by the type of derivation of the derived +class (see ARM 11.2).
      +
      +
    • +
    • +
      The same member may have different access in different classes, and may be +accessible at a given point in the program through one qualified name and +not through another. In other words, access control applies to names +rather than objects.
      +
      +
    • +
    • +
      A name is ambiguous if the name refers to two or more entities, with no +reason to prefer one over the others. Only inherited class members can be +ambiguous. Ambiguity checking is done before access control checking.
      +
      +
    • +
    +

    The problem of access control, then, reduces to “given a symbol for a class +member, which might be a projection symbol, is the member unambiguous and do we +have access to it from the current location in the program?”

    +

    The ambiguity aspect is easily dealt with: the ambiguous flag in the symbol +indicates whether or not it is ambiguous. The flag can be set only in +projection symbols and in symbols for sets of overloaded functions synthesized +for lookups done in the presence of using-directives.

    +

    Access checking is harder.

    +

    The access to a class member, in its simplest form, is given by the +source_corresp.access field in the member’s IL entry.

    +

    When the member is a direct member of a class, there will be a symbol entry +pointing directly to the IL entry, and the access to that symbol is simply the +access indicated in the IL entry. When the member is inherited, however, each +derived class will have a projection symbol that points to the fundamental +symbol. The access to the member through a projection symbol is filtered +through the class derivations that lead to the derived class containing the +projection symbol; that access is indicated in the projection symbol.

    +

    If the simple access in the symbol or in the projection symbol is +as_public, then the member is accessible. Otherwise, some kind of member +access privilege is required to access it.

    +

    Member access privileges are available when the current position is inside a +class or a function. Being inside a class confers special access to members of +the class and to classes that have befriended the class. Being inside a +function confers special access to classes that have befriended the function, +and, if the function is a member function, to the class of which it is a member +(and classes that have befriended it).

    +

    The scope_stack provides the necessary information about the functions +and/or classes that the current position is inside of.

    +

    For there to be special access to a member x across the derivation +represented by a projection symbol, there must exist a class A somewhere on +the derivation (including either of the endpoints) such that:

    +
      +
    1. A is accessible (meaning that its public members are accessible) from +the current position in the program, starting from the most-derived +class on the derivation. In other words, we can implicitly cast a pointer +to the derived class we start with to a pointer to A.

    2. +
    3. We have member access to A.

    4. +
    5. x is accessible in A, meaning that if one starts with the access +to x in the fundamental class and works outward through the +derivation steps until one gets to A, there is some remaining access +at that point.

    6. +
    +

    The implementation of the above is broken up as follows:

    +
      +
    • +
      access_for_symbol extracts the simple access for a symbol.
      +
      +
    • +
    • +
      access_to_end_of_path determines the effect of a set of derivation +steps on such an access.
      +
      +
    • +
    • +
      have_access_to_symbol determines whether or not there is access to a +symbol. Most of the work is done in have_access_across_path.
      +
      +
    • +
    • +
      The macro is_accessible_imm_base_class determines whether or not a base +class is accessible (ARM 4.6). The macro is also used directly in +determining whether or not base class casts and the like are valid. The +function is_accessible_base_class is similar, but is not limited to +immediate base classes.
      +
      +
    • +
    • +
      have_member_access_privilege determines whether or not there is member +access privilege to a given class.
      +

      +
      When there are protected members or protected derivation steps +involved, derived classes can have a limited form of member access (see +have_protected_member_access_privilege).
      +

      +
      The additional restrictions on access to protected members of ARM 11.5 +require special processing in the expression routines over and above the +access checking done here. The checking there ends up calling the macro +check_protected_member_access, which in turn calls the function +f_check_protected_member_access.
      +
      +
    • +
    • +
      check_ambiguity_and_verify_access (a macro) is the main interface to +access checking. It in turn calls +member_check_ambiguity_and_verify_access for class members.
      +
      +
    • +
    +

    Overloaded functions pose some special problems, because they are represented +as several symbols (which may have distinct accesses) clustered under one +overloaded function symbol. When the cluster is inherited into a derived +class, a single projection symbol points to the overloaded function symbol. +This means that:

    +
      +
    • +
      One cannot determine the access to a name in a set of overloaded functions +until one has determined which specific function is being referenced. For +that reason, when an overloaded function symbol is passed through the +normal access checking routines, it is always judged to be accessible. +Note that ambiguity checking can still be done in the usual way.
      +
      +
    • +
    • +
      Once one has determined which function is being referenced, one cannot use +the normal interface to the access checking routines, because the +projection symbol does not point to the specific function.
      +

      +
      overload_check_ambiguity_and_verify_access does the access check in +this case on the basis of a projection symbol and a (not directly attached) +specific function symbol. In the presence of member +using-declarations, the specific function symbol can be a projection +symbol.
      +
      +
    • +
    +

    It is not possible to determine the access to certain names used in namespace +scope declarations at the point at which the name is seen. In the following +example, the accessibility of A::B in the declaration of A::f cannot be +determined until we know we are scanning a declaration of a member of class +A. In the friend case, we cannot determine the access to A::B until we +know the signature of the function being declared, because we have to determine +that it has been befriended by class A.

    +
    class A {
    +  class B {};
    +  B f();
    +  friend B g(B);
    +};
    +A::B A::f(){ B b; return b; }
    +A::B g(A::B b){ return b; }
    +
    +
    +

    When a namespace scope declaration is processed, a flag is set in the scope +stack indicating that any access errors that occur should, instead of being +issued, be recorded in a list pointed to by the scope stack entry. Later, when +more information about the declaration is available, the accessibility is +rechecked. If the name is now accessible, the entry is removed from the list +of deferred access checks. If it is still not accessible, it will either +remain on the list if the defer access checks flag is still set, otherwise the +error will be issued.

    +

    begin_deferral_of_access_checks and end_deferral_of_access_checks are +macros used to bracket the processing of a declaration that requires deferred +access checking.

    +

    perform_deferred_access_checks is used to retry the access checks that had +failed earlier, and is called during declarator processing to check the +accessibility of member declarations. This is done after the class +reactivation scope for the member declaration has been pushed.

    +

    For the accessibility of friend declarations to be checked, the scope stack +must contain information about the function that is being declared. The +function access scope fulfills this need. After a complete function +declaration has been scanned, perform_deferred_access_checks_for_function +is called with a pointer to the routine that has been declared. It pushes a +function access scope and then calls perform_deferred_access_checks to +determine whether the names are now accessible.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/tables/index.html b/dev/doc/tables/index.html new file mode 100644 index 0000000..f3e1164 --- /dev/null +++ b/dev/doc/tables/index.html @@ -0,0 +1,1282 @@ + + + + + 8. Table Management - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    8. Table Management#

    +

    For a description of the intermediate language itself, see +Intermediate Language.

    +

    The source file il_alloc.c contains routines to allocate and clear the +intermediate language tables, and il.c contains routines to debug-print +them. These routines should always be used, so that new tables are always set +to the proper default values and problems with undefined fields are avoided. +il_def.h, il_alloc.h, and il.h contain associated declarations.

    +

    Note that some of these routines should not be called from a back end, because +the front end data structures they need are no longer set up properly at that +point. In general, routines that allocate new storage or new entries should +not be called, and routines that answer questions about existing entries are +okay to call. The

    +
    #if !STANDALONE_UTILITY_PROGRAM
    +
    +
    +

    guards indicate routines that should not be called by back ends.

    +
    +

    8.1. Storage Allocation#

    +

    alloc_cil has an interface like malloc; it allocates space in the +current intermediate language memory region. new_il_region begins a new +intermediate language memory region. switch_il_region switches to a +previously-created region. alloc_il allocates space in the file-scope +intermediate language memory region.

    +

    When the alternate IL file format is used, space is reserved preceding each IL +entry so that the IL entry number can be stored there.

    +
    +
    +

    8.2. Constant Entries#

    +

    Constant entries (type a_constant) are usually allocated by +alloc_constant; fs_constant is similar to it but allocates the constant +entry at the file scope. make_zero_of_proper_type makes a zero constant of +a given type. clear_constant and set_constant_kind are called to +re-initialize existing constant entries, and set_error_constant changes an +existing constant entry to an error constant.

    +

    In most cases, a constant entry need not be unique – the same entry can be +used for all occurrences of a given literal constant. For these cases, one +should call alloc_shareable_constant instead of alloc_constant. (The +interface is slightly different; one passes a filled-in constant entry rather +than just a kind.) alloc_shareable_constant maintains +shareable_constants_table, a hash table that is searched by hashing a +constant entry to a bucket number (routine hash_constant), then searching a +linked list of constants in that bucket to see if there is a match (comparison +is done by eq_constants). If an entry is found, it is reused. If none is +found, one is entered into the table.

    +

    In cases where the constant entry cannot be shared (as when it must be linked +into an initializer list), alloc_unshared_constant should be called +instead. It basically just calls alloc_constant, but adjusts a few things +in the constant entry.

    +
    +
    +

    8.3. Type Entries#

    +

    Type entries (type a_type) are allocated by alloc_type.

    +

    integer_type, fixed_point_type, float_type, string_type, +void_type, and error_type can be called to create type entries for the +most common types; these routines will reuse the entries once they have created +them. make_pointer_type creates a pointer type pointing to a given base +type. It uses the routine get_based_type to determine if a pointer to the +type has already been created, and it calls add_based_type_list_member to +record the fact that a pointer type has been allocated. +make_reference_type is the similar routine for (lvalue) reference types, +and make_rvalue_reference_type is the similar routine for rvalue reference +types. ptr_to_member_type is the similar routine for pointer-to-member +types.

    +

    make_qualified_type is used to add type qualifiers to an existing type; +make_unqualified_type is used to remove them.

    +

    unknown_type creates an unknown type entry; such an entry is used as a +place-holder within the front end and the references to it must be eliminated +before the back end is called. Another type that is normally not seen by the +back end (unless prototype instantiations are recorded in the IL) is the +template parameter type, which is used in processing template declarations.

    +

    There are several routines that allocate various pieces of the description of a +class type:

    +
      +
    • +
      alloc_derivation_step
      +
      +
    • +
    • +
      alloc_base_class_derivation
      +
      +
    • +
    • +
      alloc_overriding_virtual_function
      +
      +
    • +
    • +
      alloc_base_class
      +
      +
    • +
    • +
      alloc_list_entry_for_class
      +
      +
    • +
    • +
      alloc_class_type_supplement
      +
      +
    • +
    +
    +
    +

    8.4. Other Declarative Entries#

    +

    alloc_variable, alloc_field, alloc_label, and alloc_routine +allocate variable, field, label, and routine entries. They do nothing terribly +interesting. remove_from_routines_list can be used to remove a routine +from the routines list so that it can be added again at the position where its +actual definition appears.

    +

    Routines that allocate other IL entities resulting from declarations include:

    +
      +
    • +
      alloc_param_type allocates a param-entry pointed to from the routine +type supplement of a tk_routine type entry.
      +
      +
    • +
    • +
      alloc_template, alloc_template_arg and +alloc_template_param_type_descr are used in template processing.
      +
      +
    • +
    • +
      alloc_namespace allocates an entry to represent either a namespace or a +namespace alias.
      +
      +
    • +
    • +
      alloc_using_decl allocates an entry to represent a using-directive, +a member using-declaration, or a nonmember using-declaration.
      +
      +
    • +
    • +
      alloc_macro allocates an entry representing a macro definition (when +RECORD_MACROS_IN_IL is set).
      +
      +
    • +
    • +
      alloc_pragma allocates an entry representing a #pragma declaration.
      +
      +
    • +
    • +
      alloc_asm_entry allocates an entry representing an asm declaration. +To support certain extensions (i.e., when ASM_FUNCTION_ALLOWED is set) +alloc_asm_function_body is also available.
      +
      +
    • +
    • +
      alloc_scope allocates a scope entry.
      +
      +
    • +
    • +
      alloc_ctor_init allocates a constructor-initializer entry, a list of +which is recorded in the scope entry associated with a constructor.
      +
      +
    • +
    • +
      alloc_temporary_variable allocates a variable entry for a temporary.
      +
      +
    • +
    • +
      alloc_dynamic_init allocates a dynamic initialization entry, used +(among other things) to represent dynamic initialization on variable +declarations.
      +
      +
    • +
    • +
      alloc_local_static_variable_init allocates an entry used to represent +the initialization of a function-local variable with static storage class.
      +
      +
    • +
    • +
      alloc_list_entry_for_routine allocates an entry used to record a list +of routine entries (used to support friend declarations).
      +
      +
    • +
    • +
      alloc_exception_specification allocates an entry that represents an +exception specification in a function declaration.
      +
      +
    • +
    • +
      alloc_accessible_base_class allocates an accessible base class entry +(unused in implementations in which ABI_CHANGES_FOR_RTTI is set).
      +
      +
    • +
    • +
      alloc_hidden_name allocates a hidden-name entry (for use by the +C++-generating back end, when RECORD_HIDDEN_NAMES_IN_IL is set).
      +
      +
    • +
    +
    +
    +

    8.5. Expressions#

    +

    alloc_expr_node allocates an expression node.

    +

    set_expr_node_kind and clear_expr_node re-initialize existing entries. +make_operator_node creates an expression node for an operation.

    +

    set_node_operator changes the operator or type in an existing operation +expression node.

    +

    error_node makes an error expression node (a new one on each call, since +executable constructs cannot be shared).

    +

    There are several utility routines that help in constructing expressions:

    +
      +
    • +
      alloc_node_for_constant builds an expression node that points to a +constant entry.
      +
      +
    • +
    • +
      node_for_integer_constant builds an expression node for an integer +constant.
      +
      +
    • +
    • +
      var_lvalue_expr builds an expression node for a variable as an lvalue.
      +
      +
    • +
    • +
      var_rvalue_expr builds an expression node for a variable as an rvalue.
      +
      +
    • +
    • +
      var_addr_expr builds an expression node for the address of a variable. +The address_taken flag is set.
      +
      +
    • +
    • +
      function_lvalue_expr builds an expression node for a function as an +lvalue.
      +
      +
    • +
    • +
      function_rvalue_node builds an expression node for a function as an +rvalue, i.e., for the address of the function. This is suitable for +calling the function, but not for the “&” operator applied to the +function, because the address_taken flag is not set.
      +
      +
    • +
    • +
      function_addr_expr builds an expression node for the address of a +function. The address_taken flag is set.
      +
      +
    • +
    • +
      rvalue_expr_for_lvalue converts an lvalue expression to an rvalue. It +also works for function lvalues, but not for arrays.
      +
      +
    • +
    • +
      add_indirection_to_node adds an indirection (”*” operator) to an +expression.
      +
      +
    • +
    • +
      add_ref_indirection_to_node adds the reference equivalent of +“*” to an expression.
      +
      +
    • +
    • +
      add_address_of_to_node adds a “&” operator to an expression.
      +
      +
    • +
    • +
      add_reference_to_to_node adds the reference equivalent of “&” to an +expression. (Note that that is not a typo; the name really does have +“to_to_” in it.)
      +
      +
    • +
    • +
      field_lvalue_selection_expr builds an expression for a field selection +that produces an lvalue.
      +
      +
    • +
    • +
      field_rvalue_selection_expr builds an expression for a field selection +that produces an rvalue.
      +
      +
    • +
    +

    copy_expr_tree makes a copy of an expression tree. When it does so, it can +optionally “clone” any temporary variables found within the tree so that the +copy uses different but equivalent temporaries.

    +

    In addition, alloc_lowered_eh_construct_node allocates an expression node +to represent one of several (partially) lowered exception handling constructs +(used only when IL lowering is enabled and DO_FULL_PORTABLE_EH_LOWERING is +configured to FALSE.

    +
    +
    +

    8.6. Statements#

    +

    alloc_statement allocates a statement (which may allocate a supplement of +type a_for_loop, a_switch_stmt_descr, etc.). +alloc_switch_case_entry allocates the entry used to represent one case +(possibly, the “default:” case) of a switch statement.

    +
    +
    +

    8.7. Object Lifetimes#

    +

    alloc_object_lifetime allocates an object lifetime entry, and +bind_object_lifetime binds it to a specified IL entry (a scope, an +expression, a dynamic init, etc.).

    +

    A dynamic init entry with a destructor is added to the destructions list of an +object lifetime by record_end_of_lifetime_destruction, which calls +add_to_destructions_list. Conversely, it is removed from the list by +remove_from_destructions_list.

    +

    During front-end processing object lifetime entries are pushed onto the object +lifetime stack (see push_object_lifetime and global variable +curr_object_lifetime, which is the top of the stack) and popped off the +stack when appropriate (see pop_object_lifetime).

    +

    If, when it is popped off the object lifetime stack, the entry is not actually +required in the IL (see is_useless_object_lifetime), it is unbound from the +IL entry with which it is associated (see unbind_object_lifetime) and +placed on an available list for reuse (see free_object_lifetime).

    +
    +
    +

    8.8. Source Sequence Entries#

    +

    Source-sequence entries are created only when +GENERATE_SOURCE_SOURCE_SEQUENCE_LISTS is configured to TRUE. See +Intermediate Language for additional information.

    +

    f_update_source_sequence_list creates new source sequence entries and adds +them to the appropriate list.

    +
      +
    • +
      For declarations it is called by sym_update_source_sequence_list (in +symbol_ref.c), which also calls alloc_src_seq_secondary_decl when +the declaration is not a primary declaration.
      +
      +
    • +
    • +
      For statements it is called by stmt_update_source_sequence_list (in +statements.c).
      +
      +
    • +
    • +
      In certain other cases – e.g., for the declaration of unnamed enum +types, for which there is no symbol – it is called via macros +update_source_sequence_list and add_to_source_sequence_list.
      +
      +
    • +
    +

    Other functions called to create and manage source sequence lists include:

    +
      +
    • +
      alloc_source_sequence_entry allocates and initializes a source-sequence +entry.
      +
      +
    • +
    • +
      add_source_sequence_entry_to_list is called to add entries to the end +of the list of the current scope stack entry (see source_sequence_list +in a_scope_stack_entry). When pop_scope is called, the list for a +given scope stack entry is either appended to the list of the enclosing +scope stack entry or, for function scopes and the file scope, moved to the +associated IL scope (see source_sequence_list in a_scope).
      +
      +
    • +
    • +
      add_empty_source_sequence_entry creates and adds a source sequence +entry that does not yet point to an IL entry. Such entries are +placeholders to reserve a position in the list for a declarator when the +particular IL entry it represents is not yet known; they do not persist +beyond the front end.
      +
      +
    • +
    • +
      add_end_of_construct_source_sequence_entry creates a source sequence +entry to mark the end of a construct for a given entity (see +alloc_src_seq_end_of_construct) and adds it to the current source +sequence list. (See also Source Sequence Lists.)
      +
      +
    • +
    • +
      make_source_sequence_secondary_decl creates a source sequence entry to +represent a non-defining declaration (see a_src_seq_secondary_decl), +and set_src_seq_secondary_decl_fields can be called to locate the entry +on the current source sequence list (see +last_matching_source_sequence_entry) and to update various of its +pointers and flags.
      +
      +
    • +
    • +
      When either CLASS- or +NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, +add_source_sequence_entry_for_partial_instantiation is called to enter +a secondary declaration entry to represent the declaration of a +compiler-generated template specialization that stands for a template +instantiation, and when the body of such a specialization is generated, its +source sequence list is added by insert_instantiation_src_seq_list; in +both cases, find_instantiation_insert_scope is called to locate the +point at which the instantiation should be inserted in the source sequence +list (since it is not necessarily at the end of the list for the current +scope stack entry).
      +
      +
    • +
    • +
      insert_src_seq_list inserts a list into another list at a specified +point; it is also called to append a list to another list.
      +
      +
    • +
    • +
      remove_from_source_sequence_list removes a given source sequence entry +from its list; see also macros unlink_src_seq_entries and +unlink_src_seq_entry (which operate on source sequence lists and single +entries, respectively).
      +
      +
    • +
    • +
      fixup_function_scope_source_sequence_list creates both a sublist header +(see alloc_src_seq_sublist) and the source sequence entry that points +to it.
      +
      +
    • +
    +
    +
    +

    8.9. Lists of Entries#

    +

    The routines

    +
      +
    • +
      add_to_constants_list,
      +
      +
    • +
    • +
      add_to_types_list,
      +
      +
    • +
    • +
      add_to_variables_list,
      +
      +
    • +
    • +
      add_to_parameters_list,
      +
      +
    • +
    • +
      add_to_dynamic_inits_list,
      +
      +
    • +
    • +
      add_to_routines_list, and
      +
      +
    • +
    • +
      add_to_labels_list
      +
      +
    • +
    • +
      add_to_namespaces_list
      +
      +
    • +
    • +
      add_to_using_decls_list
      +
      +
    • +
    • +
      add_to_asm_entries_list
      +
      +
    • +
    • +
      add_to_templates_list
      +
      +
    • +
    • +
      add_to_macros_list
      +
      +
    • +
    • +
      add_to_pragma_list
      +
      +
    • +
    +

    add entries of the indicated type to end of the list of similar entries under a +scope entry. The scope will vary depending on the type of entry and what the +caller specifies. In many cases it is either the current scope or the +innermost namespace scope that is used (e.g., variables, constants, types). +Routines that are not class members are added to the list for the file scope or +a namespace scope. Labels are always added to an sck_function scope. And +so forth.

    +

    There is also an add_to_scopes_list; it is called by create_block_scope +when a scope for a statement block is created. Special handling is required +because the IL scope for a block is not created until there is some declaration +in that block.

    +
    +
    +

    8.10. Orphaned Entries#

    +

    Orphans are entries in the file scope memory region that are referenced only +from function scope memory regions. When the parents of such entries are +written out and then removed from memory, the entries are orphaned because they +are not attached to the rest of the file-scope IL tree.

    +

    The orphan mechanism makes lists of such entries so that they can be found +during traversal of the file-scope IL. In the file scope, each entry is +preceded by space for an orphan-list pointer. When a potential orphan entry is +encountered, for example when an entry in a function scope memory region points +to an entry in the file scope memory region, +add_orphaned_file_scope_il_entry is called. It adds the potential orphan +to a list of entries of its type headed by the proper element of the array +orphaned_file_scope_il_entries and linked by the hidden pointer. An entry +is ignored if it is already on the list (which can be discerned from the fact +that the orphan-list pointer is already non-NULL or the fact that the entry +address matches the last-on-list pointer for that entry type).

    +

    There is also a special mechanism for keeping track of the lists of local +static variables and types in function and block scopes. These are lists that +are entirely in the file scope memory region but originate with a pointer that +is in a function scope memory region. To keep track of these, entries of type +a_scope_orphaned_list_header are allocated in the file scope memory region +and attached to the il_header. Each entry contains a copy of the static +variables and types pointers from a function or block scope, so that the lists +can be visited in the file scope memory region even if the associated function +scope memory region is no longer in memory. See +add_scope_orphaned_il_lists.

    +
    +
    +

    8.11. Source File Information#

    +

    record_start_of_source_file and record_end_of_source_file build +information about the correspondence between source files and sequence numbers. +Basically, this is a tree that shows the nesting of include files, with added +entries to show the information provided by #line directives. These +routines are called from push_input_stack and pop_input_stack in +lexical.c, and proc_line in preproc.c. +conv_seq_to_file_and_line uses that data structure to map sequence numbers +into file names and line numbers.

    +
    +
    +

    8.12. Debug Print Routines#

    +

    The following debug-print routines can be used to display intermediate language +constructs for debugging purposes:

    +
      +
    • +
      db_name
      +
      +
    • +
    • +
      db_type_name
      +
      +
    • +
    • +
      db_name_linkage
      +
      +
    • +
    • +
      db_type
      +
      +
    • +
    • +
      db_abbreviated_type
      +
      +
    • +
    • +
      db_access_control
      +
      +
    • +
    • +
      db_field
      +
      +
    • +
    • +
      db_static_data_member
      +
      +
    • +
    • +
      db_member_function
      +
      +
    • +
    • +
      db_virtual_function_info
      +
      +
    • +
    • +
      db_constant
      +
      +
    • +
    • +
      db_variable
      +
      +
    • +
    • +
      db_expression
      +
      +
    • +
    • +
      db_dynamic_initializer
      +
      +
    • +
    • +
      db_initializer
      +
      +
    • +
    • +
      db_statement
      +
      +
    • +
    • +
      db_statement_list
      +
      +
    • +
    • +
      db_object_lifetime
      +
      +
    • +
    • +
      db_object_lifetime_stack
      +
      +
    • +
    • +
      db_scope
      +
      +
    • +
    • +
      db_source_sequence_entry
      +
      +
    • +
    +
    +

    8.12.1. Types#

    +

    The routines and data structures described in this section are defined in +types.c and types.h. These are routines that manipulate intermediate +language types in various ways. They answer questions about them, and do +various language transformations on them.

    +
    +
    +
    +

    8.13. Typerefs#

    +

    In type trees, typedefs, type qualifiers (e.g., const and volatile), type +operators such as decltype, and various other types are represented by an entry +called a typeref. It indicates a reference to an existing type. For qualified +pointer types, the typeref indicating the qualifier is on top of the +pointer type: for int *const q the type is a consttyperef +pointing to a pointer type entry, which points to an entry for int. Macros +get_type_qualifiers and get_top_level_type_qualifiers (the former may +check for qualifiers on the underlying array element type, the latter does not) +call f_get_type_qualifiers when appropriate, returning a bit set (see +a_type_qualifier_set).

    +

    It is often necessary for code that deals with types to access the target of a +typeref or chain of typerefs. Various convenience functions are provided for +this purpose, including skip_typerefs, skip_typerefs_not_typedefs, +skip_lexical_typerefs, etc.

    +
    +
    +

    8.14. Asking Questions About Types#

    +

    There are many predicates that determine whether or not a given type is of a +given kind. Having predicate functions (instead of doing the testing by direct +coding) is necessary because of the possibility of there being typeref +entries on a type. These predicates are implemented as functions, although +they could be implemented as macros for any cases where it seems desirable. +Within types.c, macros are used so as to avoid having one predicate routine +call a half-dozen others to get an answer. The predicate macros have the same +names as the corresponding predicate functions, with the final _type of the +name removed (i.e., is_integral corresponds to is_integral_type). They +do not call skip_typerefs.

    +

    The predicate functions are

    +
      +
    • +
      is_error_type
      +
      +
    • +
    • +
      is_function_type
      +
      +
    • +
    • +
      is_incomplete_type
      +
      +
    • +
    • +
      is_object_type
      +
      +
    • +
    • +
      is_void_type
      +
      +
    • +
    • +
      is_integral_type
      +
      +
    • +
    • +
      is_signed_integral_type
      +
      +
    • +
    • +
      is_enum_typeis_integral_or_enum_type
      +
      +
    • +
    • +
      is_character_type
      +
      +
    • +
    • +
      is_fixed_point_type
      +
      +
    • +
    • +
      is_floating_type
      +
      +
    • +
    • +
      is_arithmetic_or_enum_type
      +
      +
    • +
    • +
      is_pointer_type
      +
      +
    • +
    • +
      is_reference_type
      +
      +
    • +
    • +
      is_lvalue_reference_type
      +
      +
    • +
    • +
      is_rvalue_reference_type
      +
      +
    • +
    • +
      is_ptr_or_ref_type
      +
      +
    • +
    • +
      is_scalar_type
      +
      +
    • +
    • +
      is_array_type
      +
      +
    • +
    • +
      is_char_array_type
      +
      +
    • +
    • +
      is_class_struct_union_type
      +
      +
    • +
    • +
      is_complete_class_struct_union_type
      +
      +
    • +
    • +
      is_union_type
      +
      +
    • +
    • +
      is_aggregate_or_union_type
      +
      +
    • +
    • +
      is_polymorphic_class_type
      +
      +
    • +
    • +
      is_ptr_to_member_type
      +
      +
    • +
    • +
      is_template_class_type
      +
      +
    • +
    • +
      is_template_param_type
      +
      +
    • +
    • +
      is_nullptr_type
      +
      +
    • +
    +

    Macros that may be called to get information about the type (when +skip_typerefs is not to be called) include

    +
      +
    • +
      is_immediate_error_type
      +
      +
    • +
    • +
      is_immediate_class_type
      +
      +
    • +
    • +
      is_qualified_type
      +
      +
    • +
    • +
      is_const_qualified_type
      +
      +
    • +
    • +
      is_volatile_qualified_type
      +
      +
    • +
    • +
      is_top_level_qualified_type
      +
      +
    • +
    • +
      is_top_level_const_qualified_type
      +
      +
    • +
    • +
      is_top_level_volatile_qualified_type
      +
      +
    • +
    +

    (Among those that check type qualifiers, the is_top_level_xxx versions +differ from the others in not checking for qualifiers on underlying array +element types.) Other type qualifiers besides const and volatile may be +recognized; for instance, when support for restrict is enabled, +is_restrict_qualified_type and is_top_level_restrict_qualified_type are +also defined.

    +

    is_illegal_abstract_class_type returns TRUE if the type is that of an +abstract class, struct, or union, or if it is an array of abstract class +objects, or if it is pointer or reference to an array of abstract class +objects.

    +

    int_kind_is_signed determines whether a given integer kind is a signed +type.

    +

    There are in addition some predicate functions that examine an entire type +tree, if necessary, to return information about a type:

    +
      +
    • +
      is_or_contains_local_type
      +
      +
    • +
    • +
      is_or_contains_unnamed_or_local_type
      +
      +
    • +
    • +
      is_or_contains_template_param
      +
      +
    • +
    • +
      is_or_contains_specific_template_param
      +
      +
    • +
    +

    These routines call traverse_type_tree, a generic type-walking routine; it +is passed the address of a service routine that examines a node in the type +tree, and its detailed behavior is governed by setting some combination of +flags (see a_type_tree_traversal_flag_set).

    +

    Another set of predicates tests C++/CLI types and can be used only inside +#if guards for MICROSOFT_EXTENSIONS_ALLOWED:

    +
      +
    • +
      is_handle_type
      +
      +
    • +
    • +
      is_managed_nullptr_type
      +
      +
    • +
    • +
      is_ref_class_type
      +
      +
    • +
    • +
      is_value_class_type
      +
      +
    • +
    • +
      is_managed_class_type
      +
      +
    • +
    • +
      is_standard_class_type
      +
      +
    • +
    • +
      is_cli_interface_type
      +
      +
    • +
    • +
      is_tracking_reference_type
      +
      +
    • +
    • +
      is_handle_or_tracking_ref_type
      +
      +
    • +
    • +
      is_interior_ptr_type
      +
      +
    • +
    • +
      is_pin_ptr_type
      +
      +
    • +
    • +
      is_cli_array_type
      +
      +
    • +
    • +
      is_handle_to_cli_array_type
      +
      +
    • +
    • +
      is_cli_generic_param_type
      +
      +
    • +
    • +
      is_cli_generic_constraint_type
      +
      +
    • +
    • +
      is_boxable_type
      +
      +
    • +
    • +
      is_delegate_type
      +
      +
    • +
    • +
      is_cli_system_object_type
      +
      +
    • +
    • +
      is_cli_system_string_type
      +
      +
    • +
    +

    To ease pointer/reference/handle tests in code that might have to deal with +C++/CLI types, the following test certain general categories of pointers and +references:

    +
      +
    • +
      is_any_reference_type
      +
      +
    • +
    • +
      is_any_ptr_or_ref_type
      +
      +
    • +
    • +
      is_pointer_or_handle_type
      +
      +
    • +
    • +
      types_are_both_pointers_or_both_handles
      +
      +
    • +
    +
    +
    +

    8.15. Taking Apart Types#

    +

    Given an array type, array_element_type and +underlying_array_element_type return the type of an element; the second +deals with multidimensional arrays. type_pointed_to is used to get the +base type from a pointer or reference type. pm_member_type and +pm_class_type extract the base types from pointer-to-member types. +underlying_type_of_derived_type extracts the underlying type for all +derived types (pointer, pointer-to-member, array, etc.).

    +

    Given a C++/CLI array type, cli_array_element_type returns the type of the +element. cli_array_rank_constant and cli_array_rank return the rank +(number of dimensions) of the array in different forms.

    +
    +
    +

    8.16. Setting Sizes and Alignments of Types#

    +

    The size and alignment for a type are recorded in the type entry (except for +typerefs, which have their sizes and alignments dictated by the type they +refer to). These values, however, are not set all over the front end, but only +by isolated routines. The main routine is set_type_size, which will set +the size of an arbitrary type. The type must be completely built by the time +this routine is called. set_type_size calls set_array_type_size for +arrays. Size and alignment for class types are set by code in layout.c.

    +
    +
    +

    8.17. Modifying Type Trees#

    +

    set_used_in_exception_or_rtti_flag is called for types that appear as the +type of a throw object, in an exception specification list, as the type of a +handler, or in a typeid operator. It sets the type entry’s +used_in_exception_or_rtti flag. To assure that such types have external +linkage, it also calls set_force_external_linkage_flag, which in turn calls +traverse_type_tree to mark all the components of the type tree that have +linkage.

    +

    strip_local_typedefs is called to remove all local typedef components +of a type tree. It calls traverse_and_modify_type_tree to help accomplish +this task. If a subtree of the type tree is modified, a new type tree is built +to accommodate the change.

    +
    +
    +

    8.18. Getting Information About Base Classes#

    +

    find_base_class_of returns a pointer to a base class entry if a given class +type is represented on the base classes list of another class type. Similar +functionality, but with the implied restrictions, is provided by +find_direct_base_class_of and find_direct_or_virtual_base_class_of. +related_class_pointers will do the same for pointers to classes.

    +

    corresponding_base_class, given a base class belonging to one class, +searches the base classes of another class, finds the corresponding entry, and +returns a pointer to it.

    +

    is_on_any_derivation_of returns TRUE if a given base class is on the +derivation of another base class.

    +
    +
    +

    8.19. Routines that Implement Language Concepts#

    +

    The routines described in this section implement concepts of the C or C++ +languages.

    +

    Two routines handle type promotions: type_after_integral_promotion +determines the type that results from integral promotion done in an expression, +and default_argument_promotion determines the type of an argument to a +function with old-style parameter declarations after default promotion. See +also type_after_bit_field_integral_promotion in exprutil.c for a +special case involving bit-fields.

    +

    Several routines compare two types to see if they are compatible in some way. +identical_types determines whether the two types are structurally identical +(they don’t have to be the same pointer). il_identical_types sees if the +two types are identical from an IL perspective (e.g., int and long +might be identical if the front end is configured that way). +types_are_compatible sees if two types are compatible (C standard, +3.1.2.6). (Those three names are actually macros which call +f_identical_types and f_types_are_compatible only if the type pointers +are not exactly the same.) interchangeable_types sees if two types are +interchangeable as arguments to functions (basically, this is true if they are +compatible except for signedness issues).

    +

    impl_pointer_conversion determines whether or not an implicit conversion +from a given type to a given pointer type is valid, with some special cases for +pointers to void and for null pointer constants.

    +

    impl_conversion_possible determines whether or not an implicit conversion +from a given type to another is valid. impl_ptr_to_member_conversion +handles the subcase of implicit conversion of one pointer-to-member type to +another.

    +

    expl_conversion_possible determines whether or not an explicit conversion +(cast) from a given type to another is valid. It relies on two subroutines for +the major subcases:

    +
      +
    • +
      static_cast_conversion_possible and
      +
      +
    • +
    • +
      reinterpret_cast_conversion_possible.
      +
      +
    • +
    +

    composite_type develops a composite type from two types (C standard, +3.1.2.6).

    +

    overload_distinguishable determines whether or not two function types are +sufficiently different that they can be distinguished by overload processing +(and therefore routines with those types can be overloaded).

    +

    impl_handle_conversion determines whether or not an implicit conversion +from a given type to a given C++/CLI handle type is valid.

    +

    boxing_conversion_possible determines whether a conversion from one given +type to another is a C++/CLI boxing conversion. The cases accepted convert a +value type to a handle to that value type.

    +

    unboxing_conversion_possible determines whether a conversion from one given +type to another is a C++/CLI unboxing conversion. The cases accepted convert a +handle type to a value type.

    +

    system_type_from_fundamental_type and fundamental_type_from_system_type +are a pair of functions that convert back and forth between fundamental types +and the corresponding C++/CLI value class types (e.g., between int and +System::Int32).

    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/templates/index.html b/dev/doc/templates/index.html new file mode 100644 index 0000000..552dbd5 --- /dev/null +++ b/dev/doc/templates/index.html @@ -0,0 +1,3547 @@ + + + + + 13. Templates - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    13. Templates#

    +

    Support for template declarations and the instantiation of classes and objects +based on templates is found principally in templates.c; templates.h +contains the associated declarations.

    +
    +

    13.1. Overview#

    +

    Template support is almost entirely a front-end issue. By default, templates +themselves are not represented in the IL, and classes and functions that are +generated on the basis of templates look just like any other class or function. +The exceptions to this rule are:

    +
      +
    • +
      Classes, functions, variables, and aliases generated from templates +identify the associated template arguments, because those arguments may +be needed in generating the name of the entity.
      +
      +
    • +
    • +
      In automatic instantiation mode additional flags are provided in the +variable and routine entries so that the information provided by the flags +may be represented in the resulting object file in some form.
      +
      +
    • +
    • +
      A template IL entry is created for each template declaration. When +PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the entry points to a +“prototype instantiation”, which is an IL entry that represents the entity +declared by the template. When RECORD_TEMPLATE_STRINGS is TRUE, the +entry contains a null-terminated string that represents the template +declaration. The IL template entry is also used to represent the value of +a template template argument.
      +
      +
    • +
    • +
      The template instantiation mechanism may require support in the back end. +For example, if each instantiation is placed in its own object file, the +back end must recognize the data structures provided to accomplish this.
      +
      +
    • +
    +

    Generally speaking, when a template definition is scanned, the definition of +the template is saved and then used later to generate instances of the +template. There are two common techniques used by compilers to save the +definition of a template: in the first technique, the template is parsed +(without semantic analysis) and the parse tree is saved; in the second, some +unparsed (more or less textual) representation of the template is saved. A +parse tree may be a reasonable choice for a multi-pass front-end featuring a +separate parser. However, in the EDG C++ front end (which uses a single pass +approach in which parsing and semantic analysis are done together), a textual +representation, which we call a “token cache”, is more appropriate. Correctly +implemented, the two techniques are semantically equivalent.

    +

    When using exported templates (see Exported Templates) the front end +reloads the translation unit(s) that define the exported templates that require +instantiation so that the information from all of the translation units is +available to the front end. Even though there is a great deal of special +processing required to make exported templates work properly, the underlying +mechanism of rescanning tokens from a token cache is still used to produce the +actual instantiation.

    +

    Since the method one chooses to record the definition of the template affects +the data structures used in the implementation and also influences the +terminology used to describe them, it will be helpful to introduce some terms +that are used in the EDG C++ front end:

    +
      +
    • +
      A template denotes a sequence of tokens that, along with one or more +template parameters and a declarative context, is used as the basis for +generating an instance of the template.
      +

      +
      A template entity may be
      +
      +
        +
      • +
        a class template (e.g., class A),
        +
        +
      • +
      • +
        a function template (e.g., function f),
        +
        +
      • +
      • +
        a member function of a class template (e.g., A<T>::f),
        +
        +
      • +
      • +
        a static data member of a class template (e.g., A<T>::t),
        +
        +
      • +
      • +
        a nested class of a class template (e.g., A<T>::B),
        +
        +
      • +
      • +
        a member class template (e.g., A<T>::C),
        +
        +
      • +
      • +
        a member function template (e.g., A<T>::g),
        +
        +
      • +
      • +
        a variable template (e.g., x<T>),
        +
        +
      • +
      • +
        an alias template, or
        +
        +
      • +
      • +
        a partial specialization of a class template, member class template, +or variable template.
        +
        +
      • +
      +
      +
      For example,
      +
      +
      template <class T> void f(T);       // function template
      +template <class T> class A {        // class template
      +  T f() { return t; }               // member function of class template
      +  static T t;                       // static data member of class template
      +  struct B {};                      // nested class of class template
      +  template <class U> void g(U);     // member function template
      +  template <class U> struct C {};   // member class template
      +  template <class U> struct C<U*> {}; // partial specialization
      +  template <class U> static U vt;   // member variable template
      +};
      +template <class T> T x = 1;         // variable template
      +template <class T> using B = A<T*>; // alias template
      +
      +
      +
    • +
    • +
      A template parameter refers to a template formal argument, and a +template argument is a template actual argument.
      +
      +
    • +
    • +
      A template instance is a class (sometimes called a template class) +generated on the basis of a class template, an alias (i.e., typedef, +sometimes called a template alias) generated on the basis of an alias +template, a function (sometimes called a template function) generated on +the basis of a function template, or a variable (sometimes called a +template variable) generated on the basis of a variable template. In +addition, a member function or static data member of a template class is +itself an instance of the corresponding member function or static data +member of the class template. For example,
      +
      +
      template <class T> class A {
      +  static T t;
      +  T f() { return t; }
      +};
      +A<int> ai;
      +template <class T> T g(T t) { return t; }
      +int i = g(0);
      +
      +
      +
      +
      With the declaration of ai an instance of class template A, namely, +A<int>, is generated, and in the process instances A<int>::f and +A<int>::t are also generated. Similarly, the reference to g(int) +causes an instance of function template g to be generated.
      +
      +
    • +
    • +
      In many cases instances of variable templates and static data members of +template classes are treated similarly. The term “template variable” is +used to refer to both cases, unless otherwise specified.
      +
      +
    • +
    • +
      The generation of an instance of a template is called instantiation. +(Sometimes the result of instantiation, namely an instance, is also called +an instantiation.)
      +
      +
    • +
    • +
      An instantiation may be either a partial instantiation or a full +instantiation. A partial instantiation of a class template is like a +declaration of an ordinary class when no body is supplied; similarly, a +partial instantiation of a function template is like a declaration of a +function without a function body. On the other hand, a full instantiation +is the generation of a class or function definition – i.e., it includes +the body. For instance,
      +
      +
      template <class T> class A {};
      +A<long> *pal;
      +A<int> ai;
      +
      +
      +
      +
      In this case the declaration of pal causes the partial instantiation of +A<long> – that is, no body needs to be generated – whereas the +declaration of ai causes the full instantiation of A<int>. The +instantiation of an alias template is always a full instantiation.
      +
      +
    • +
    • +
      The first time a class template is scanned – partly to record its member +functions, static data members, nested classes, and friend declarations, +and partly to check for errors – the result is referred to as a prototype +instantiation of the class template, and the class produced is called a +“nonreal” class; in general, a template class based on template arguments +that include at least one template parameter is called “nonreal”. In +addition, a template class based on a template that is a member of a +nonreal class is also called “nonreal”. Consider this example:
      +
      +
      template <class T, int I> struct A {
      +  template <class T2> struct X {};
      +};
      +template <class T> struct B {
      +  A<T, 0> a;
      +  typename T::X<int> x;
      +};
      +B<A<int,1> > b;
      +
      +
      +
      +
      In this example, when class template A is scanned, the prototype +instantiation produces nonreal class A<T,I>, and during the scanning of +class template B nonreal classes A<T,0> and T::X<int> are +generated. Subsequently, when b is declared and B<A<int,1> > is +instantiated, A<int,0>, a real class, is instantiated to serve as the +type for member B<int>::a, and A<int,1>::X<int> is instantiated to +serve as the type for member B<int>::x.
      +
      +
    • +
    • +
      A prototype instantiation is also performed for alias templates resulting +in a nonreal alias. Nonreal aliases are also created for instantiations of +alias templates if the template argument list depends on a template +parameter. Unlike nonreal classes, nonreal aliases are actually +instantiated by rescanning the tokens of the alias.
      +
      +
    • +
    • +
      Nested classes of class templates are not themselves referred to as +templates, but their member functions and static data members are, +respectively, member functions of class templates and static data members +of class templates, and a member function or static data member of a class +nested within a template class is handled as an instance of the +corresponding member function or static data member from the class +template. A class nested within a nonreal class is considered a nonreal +class.
      +
      +
    • +
    • +
      The definition of a template instance may be supplied explicitly by the +user instead of being generated based on the template. Such instances are +referred to as explicit specializations of the template.
      +
      +
    • +
    • +
      A class template or variable template may be partially specialized. A +partial specialization is an alternate version of the template that is used +to generate instances whose template argument lists match a specified +pattern. For example, a partial specialization could be provided that will +be used to generate all instances for which a specified template argument +is a pointer type.
      +
      +
      template <class T> struct A {};      // primary template
      +template <class T> struct A<T*> {};  // partial specialization
      +
      +
      +
      +
      The template that is specialized by a partial specialization is called +the primary template.
      +
      +
    • +
    • +
      Function templates may be overloaded with normal functions and with other +function templates. Overload resolution is used to select the function or +template to be used for a given call. If, as a result of overload +resolution, there are two or more templates that could generate equivalent +functions, partial ordering rules are used to select the template to be +used. Partial ordering is different from partial specialization in that +there is no relationship between the function templates being ordered (i.e, +one is not considered to be a specialization of the other).
      +
      +
    • +
    • +
      In some modes, prototype instantiations are performed for entities other +than classes and aliases. When semantic analysis of nonclass templates has +been requested, prototype instantiations are done for the bodies and +default arguments of function templates and member functions of class +templates, the initializers of template static data members, and the +default values of template arguments.
      +
      +
    • +
    • +
      Template template parameters are class templates for which the template +definition to be used for a given reference is supplied by a template +template argument.
      +
      +
    • +
    +

    By default, prototype instantiations and entries associated with nonreal +classes and aliases do not appear in the IL. When +PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, IL entries for prototype +instantiations are generated. See Templates for more +information.

    +

    Template definitions are typically placed in header files that are included by +the programs that make use of the templates. Alternatively, the definitions of +template static data members and non-inline template functions may be provided +using the “export” facility of the C++ language (see +Exported Templates).

    +

    The major part of template support falls into several phases. The first is +processing the declaration of the template, which for a class template also +involves doing a prototype instantiation. The second phase is recognizing a +reference to an instance of a template and producing a partial template +instantiation, which can be thought of as an on-the-fly declaration of the +instance. The third phase is the full instantiation of the template instance; +typically, a template class is fully instantiated at the first point of +reference in a given translation unit, but a template function presents special +complications, since the full instantiation of a noninline template function +may occur only once in a program, no matter how many translation units it may +appear in.

    +

    Each of these phases of template processing will be examined in detail, but +first it is necessary to describe the data structures that are built to +represent templates and their instances.

    +
    +
    +

    13.2. Data Structures#

    +

    Each collection of tokens that is stored so that the tokens may be rescanned +later is represented by an entry of type a_template_cache. The fields of +the template cache entry are:

    +
      +
    • +
      tokens, where the tokens are kept on which an instantiation of the +template is to be based.
      +
      +
        +
      • +
        For classes the tokens comprise the base specifiers list as well as the +body of the class.
        +
        +
      • +
      • +
        For functions, including member functions, they extend from the opening +left brace to the closing right brace of the function body, except that +for templates of constructors the ctor-initializer list, if present, is +also included.
        +
        +
      • +
      • +
        For static data members the tokens identify the initializer, if any.
        +
        +
      • +
      +
      +
      The last token in the token cache is always a tok_end_of_source token.
      +
      +
    • +
    • +
      decl_info, a pointer to an entry of type a_template_decl_info, +which describes the context in which the tokens stored in the token cache +appeared.
      +
      +
    • +
    +

    The template declaration information entry (a_template_decl_info) in turn +includes the following fields:

    +
      +
    • +
      parameters, a pointer to list of entries of type a_template_param; +they record the template parameters declared in the template declaration.
      +
      +
        +
      • +
        For type parameters a template param entry points to an sk_type +symbol (which in turn refers to a tk_template_param type entry).
        +
        +
      • +
      • +
        For nontype parameters a template param entry points to an +sk_constant symbol (which refers to a ck_template_param constant +entry).
        +
        +
      • +
      • +
        For template template parameters a template param entry pointed to an +sk_class_template symbol. The template symbol supplement for which +the template_template_param field is TRUE.
        +
        +
      • +
      +
    • +
    • +
      declaration_scope, identifying the sck_template_declaration scope +in which the template parameter symbols were declared.
      +
      +
    • +
    • +
      enclosing_scope, a pointer to the scope containing the template +declaration. This is important, for example, when a function template is +defined in a friend declaration within a class, in which case the class +must be reactivated when instantiations of that function template are +generated.
      +
      +
    • +
    • +
      enclosing_template_decl, a pointer to the template declaration +information for an enclosing template declaration. This is used for member +class templates and member function templates when one needs to know, for +example, not only the template parameters of the member template, but also +the template parameter lists of any enclosing class templates.
      +
      +
    • +
    • +
      decl_seq, the declaration sequence number at the point of the template +declaration. This is used when doing dependent name lookup to exclude +names not visible at the point of the template definition.
      +
      +
    • +
    • +
      nondependent_calls, used when doing dependent name processing to record +the result of overload resolution for nondependent calls that were +evaluated during a prototype instantiation.
      +
      +
    • +
    +

    A template (of whatever flavor) is represented by the combination of a symbol +and an associated entry of type a_template_symbol_supplement (defined in +symbol_tbl.h). An instance of the template is then represented by an entry +that appears on a list pointed to from the template symbol supplement. That is +the basic pattern for representing a template and its instances – a template +symbol, a supplement, and a list of instances – but each sort of template +presents a different version of the pattern.

    +

    The template symbol supplement contains a template cache entry for the template +body and also has fields that are specific to the kind of template it is +associated with; these are discussed below.

    +

    In most cases the instantiation of a template creates one or more classes, +functions, and/or static data members. However, when a class template contains +members that are themselves templates (i.e, member function templates or member +class templates) the instantiation of the enclosing class template results in +the creation of entities that are templates. When this happens, it is +necessary to record the template from which the new template was generated. +The template symbol supplement field named prototype_template contains a +pointer to the symbol associated with the template from which a given member +template was generated. Similarly the prototype template contains a field +named subordinate_templates that points to a list of templates that were +generated from the prototype template.

    +
    +

    13.2.1. Class Templates#

    +

    An sk_class_template symbol represents a class template; it contains a +pointer to a template symbol supplement. The supplement for a class template +includes the variant field instantiations, a pointer to a list of the +symbols (of kind sk_class_or_struct_tag or sk_union_tag) that represent +instances of the template. The symbol for the prototype instantiation is +pointed to by the field prototype_instantiation.

    +

    For each template class represented by a symbol on the instantiations list the +class symbol supplement has several important fields:

    +
      +
    • +
      class_template is a pointer back to the sk_class_template symbol +that represents the template upon which its instantiation is based. +However, for a nested class of a template class the class_template +pointer will always be NULL.
      +
      +
    • +
    • +
      corresp_prototype_sym is a pointer to the template class symbol for the +prototype instantiation and is present for template class instances and +classes nested within template classes.
      +
      +
    • +
    • +
      is_nonreal_class is TRUE for template classes produced by prototype +instantiations (and in general for template classes for which the template +argument list contains at least one template parameter reference). It is +also TRUE for a class that is a nested class of a nonreal template class.
      +
      +
    • +
    +

    A class symbol for a template class (i.e., for an instance of a class template) +does not otherwise appear in the symbol table. It cannot be looked up directly +but rather must be looked up via the class template symbol.

    +

    The type entry associated with a template class is like that of any other class +except that it contains the following additional information about template +classes:

    +
      +
    • +
      template_arg_list points to the template argument used to generate the +type (the template arguments are incorporated in the type so that back ends +can use them to generate names for template classes).
      +
      +
    • +
    • +
      is_template_class TRUE for template class instances and classes nested +within template class instances.
      +
      +
    • +
    • +
      is_nonreal_class is TRUE for nonreal instantiations and for local +classes of prototype instantiations.
      +
      +
    • +
    • +
      is_prototype_instantiation is TRUE for prototype instantiations of +class templates and nested classes of class templates.
      +
      +
    • +
    • +
      is_specialized is TRUE for template classes declared or defined in an +explicit specialization declaration.
      +
      +
    • +
    • +
      specialized_with_old_syntax was specialized, but not with the +“template <>” syntax that is now required by the standard.
      +
      +
    • +
    • +
      partial_spec_template_arg_list is used when a partial specialization is +used to generate the definition of the template class. It points to the +template argument list that is specified with respect to the partial +specialization’s template parameter list.
      +
      +
    • +
    +

    A class template may have associated with it a set of partial specializations +that may be used instead of the primary template when generating full +instantiations of instances of the class template. The template symbol +supplement contains a field named partial_specializations that points to a +list of sk_class_template symbols for any partial specializations that may +exist. Instances created from partial specializations go on the instantiations +list of the primary template. Each partial specialization has its own +prototype instantiation, which also goes on the instantiations list of the +primary template. The class type supplement field +partial_spec_template_arg_list is used in class types generated from class +template partial specializations (including the prototype instantiation). It +contains the template argument list with respect to the partial specialization, +while the template_arg_list field contains the template argument list with +respect to the primary template. In the following example, the template +argument list with respect to the primary template is “<int*, int>”, while +the template argument list with respect to the partial specialization is +“<int>”.

    +
    template <class T1, class T2> struct A {};
    +template <class T> struct A<T*, int> {};
    +A<int*, int> a;
    +
    +
    +

    As mentioned previously, it is here that the type entries of real and nonreal +template classes differ – the template arguments of a nonreal template class +involve at least one tk_template_param type or ck_template_param +constant. In addition, the type entry for a nonreal class does not appear in +the IL that is passed on to the back end for further processing.

    +

    When an instance of a class template is fully instantiated, partial +instantiations for all of its member functions, static data members, and nested +classes are generated. Because these entities are not themselves templates, +they do not have their own template argument lists. The template argument list +for their enclosing class is used when a full instantiation is performed.

    +
    +
    +

    13.2.2. Alias Templates#

    +

    Alias templates are represented in much the same way as class templates. An +sk_class_template symbol is used to represent the alias template, however +the instantiation list and prototype instantiation fields of the template +symbol supplement point to sk_type symbols. The is_alias_template +field of the template symbol supplement is used to identify alias templates.

    +

    The typeref type created for instantiations of alias templates (with typeref +kind trk_is_template_alias) is like that of normal aliases except that it +contains additional information, including the template argument list and flags +such as is_template_alias, is_nonreal, and +is_prototype_instantiation.

    +
    +
    +

    13.2.3. Function Templates#

    +

    An sk_function_template symbol is used to represent a function template, +including member function templates, but not member functions of class +templates. It contains a pointer to a template symbol supplement whose variant +field instantiations points to a list of entries of type +a_template_instance: each time a partial instantiation is performed on the +function template, the resulting instance is recorded in this list.

    +

    Entries of type a_template_instance are also utilized to record instances +of member function of class templates and static data members of class +templates, but they are used somewhat differently in those cases (as described +later). When a template instance is used to record an instance of a function +template, the following use is made of its fields:

    +
      +
    • +
      instance_sym points to the sk_routine symbol that represents the +instance. That symbol will in turn point to the routine entry created to +represent the instantiated function. A full instantiation need not have +been done. The routine entry contains a pointer to the template arguments +on which the instance is based.
      +
      +
    • +
    • +
      template_sym points to the sk_function_template symbol that +represents the template.
      +
      +
    • +
    • +
      instantiation_required is TRUE if the routine instance was actually +called or had its address taken. It means that a full instantiation +needs to be performed – i.e., that the function body needs to be +generated. When this flag is set, the instance is placed on the +instantiations_required list, to assure that it is checked for +additional processing once the entire translation unit has been +scanned.
      +
      +
    • +
    • +
      is_guiding_decl is TRUE if this routine was explicitly declared by the +user (whether or not a body was supplied). When this flag is set, the +symbol pointed to by instance_sym will have been added to the overload +list for this name. Note that a “specific declaration” is different than +an “explicit specialization”. A specifically declared function +participates in overload resolution, but need not be explicitly +specialized.
      +

      +
      Here’s an example:
      +
      +
      template <class T> void f(T) {}
      +void f(int);
      +
      +
      +
      +
      The second declaration assures that f(int) is represented both in the +instantiations list for function template f and on the overload list +associated with an sk_overloaded_function symbol with an identifier +f. Such a declaration affects how the function is found during +overload resolution, but it does not prevent a body from being generated +for it based on the function template.
      +
      +
    • +
    • +
      explicit_instantiation is TRUE if the user has explicitly requested +full instantiation by means of an explicit instantiation directive or +#pragma instantiate directive.
      +
      +
    • +
    • +
      referencing_namespace points to the namespace in which the use that +first required the instantiation of the template was encountered, or NULL +if the first reference was in the global namespace. This field is set when +the instantiation_required flag is set to TRUE.
      +
      +
    • +
    +

    In addition to the pointer to the instantiations list, the template symbol +supplement for a function template makes use of some other variant fields:

    +
      +
    • +
      routine is a pointer to a routine entry. This entry is generated when +the function template declaration is scanned, but it doesn’t actually map +to a real routine (and does not appear in the IL proper). Rather, it +serves as a convenient place to store the routine type and other +information about the function (e.g., the storage class, the special +function kind, and whether inlining was specified in the original +declaration).
      +
      +
    • +
    • +
      func_info is a field of type a_func_info_block and stores +information picked up during declaration processing that needs to be reused +during instantiation (e.g., the names of the function parameters).
      +
      +
    • +
    • +
      def_arg_expr_list is a list of entries containing information about +default arguments to be applied to the function parameters when the +instantiation is done.
      +
      +
    • +
    +

    Whereas, as noted previously, an instance of a class template cannot be looked +up independently of its template, the same is not necessarily the case for an +instance of a function template. When there has been a guiding declaration, +the template function’s symbol may be found during ordinary overload +resolution. However, when there is no guiding declaration, the symbol can only +be found via the function template symbol and its list of instantiations. +Consider this example:

    +
    template <class T> T f(T t) { return t; }
    +char f(char);           // Guiding declaration
    +int i = f(0);           // Instantiation of f(int)
    +void f(int, int);       // Unrelated to the template
    +
    +
    +

    Symbols are arrayed under the symbol header for “f” as follows:

    +
      +
    • +
      overloaded function symbol with overload list:
      +
      +
    • +
    • +
      template function symbol f(T) with instantiation list:
      +
      +
    • +
    • +
      instance entry pointing to routine symbol f(char)
      +
      +
    • +
    • +
      instance entry pointing to routine symbol f(int)
      +
      +
    • +
    • +
      routine symbol f(char)
      +
      +
    • +
    • +
      routine symbol f(int,int)
      +
      +
    • +
    +

    Notice that the symbol for f(char) appears both on the overload list and on +the instantiation list (there are not two different symbols), whereas +f(int) appears only on the instantiation list. The former, consequently, +is subject to the ordinary lookup rules, whereas the latter must be looked up +using the stricter rules for template functions. Guiding declarations have +been removed from the standard language, but are still supported by the front +end depending on the command line options and configuration flags being used. +When guiding declarations are disabled, declarations such as f(char) are +simply declarations of normal functions that are unrelated to the template.

    +
    +
    +

    13.2.4. Member Function of Class Templates#

    +

    A member function of a class template is represented by an +sk_member_function symbol created during the prototype instantiation of the +class template. These symbols look like ordinary member function symbols, +which among other things means they do not have their own pointer to a template +symbol supplement; rather they point to a template instance entry, and it has a +pointer to a template symbol supplement.

    +

    The problem being addressed with this somewhat roundabout arrangement is that a +member function of a class template is really a “quasi-template” whose partial +instantiation is in fact always part of any full instantiation of the class +template to which it belongs. A consequence of this approach is that the +instantiations list from the associated template symbol supplement includes +both

    +
      +
    1. ordinary instance entries that point to ordinary member function symbols +(members of real instantiations of the class template) and

    2. +
    3. one special instance entry that represents the quasi-template by +pointing to a member function symbol of the nonreal prototype +instantiation of the class template.

    4. +
    +

    The template instance entries for member functions are similar to those for +ordinary template functions:

    +
      +
    • +
      instance_sym points to the sk_member_function symbol that +represents the instance.
      +
      +
    • +
    • +
      template_sym points to the sk_member_function symbol that +represents the template.
      +
      +
    • +
    • +
      When instance_sym and template_sym are identical, the +template_info field is non-NULL and points to the template symbol +supplement belonging to this member function of a class template.
      +
      +
    • +
    • +
      The flags are used as for nonmember function instances, except that +specific_decl is always TRUE.
      +
      +
    • +
    +
    +
    +

    13.2.5. Variable Templates#

    +

    A variable template is represented by an sk_variable_template symbol. +Instantiations of the template result in variable entries and associated +sk_variable symbols. Variable templates declared in class scopes are, from +a language point of view, static data members, but they and their +instantiations are represented in the same way as non-member variable +templates. When a variable template is instantiated using a dependent template +argument list, the is_nonreal flag is set in the variable entry. The +variable variant of the template symbol supplement contains information +used for both variable templates and static data members of class templates +(although some fields are only used for one or the other). The +instantiations field points to a list of symbols for the real +instantiations of the variable template. Template instance entries are created +for the real instantiations of a variable template.

    +
    +
    +

    13.2.6. Static Data Members of Class Templates#

    +

    Static data members of class templates are represented much like member +functions of class templates. The template symbol, an +sk_static_data_member symbol from the prototype instantiation of the class +template, points to an instance entry whose template_sym field points back +to it and whose template_info field points on to a template symbol +supplement. The latter has a definitions field that points to the instance +list. The fields in the instance entries are used just like those for member +functions.

    +
    +
    +

    13.2.7. Template Declaration Information#

    +

    As described earlier, each token cache that is used in the template +instantiation process is associated with a pointer to an entry of type +a_template_decl_info, which contains information about the template +parameters, the scope in which the template was declared, and a pointer to an +enclosing template declaration information entry, if applicable. An enclosing +template declaration information pointer is used when a member function +template or member class template is declared within another class template. A +function template, or member function of a class template, contains a token +cache that contains the function declaration and a separate token cache +containing the function body. Each token cache has associated with it a +separate template declaration information pointer, because the two caches may +have come from different declarations with different template parameter lists, +etc.

    +

    There is one template declaration information entry for each template <...> +clause that is scanned (except for those with empty parameter lists, which are +used in explicit specializations). When there is more than one template clause +in a given declaration, the inner template clauses contain a pointer to the +enclosing template declaration clause (the one to the left of a given template +clause).

    +

    When a template is defined within another template the enclosing template +declaration information pointer is NULL indicating that the template +declaration information for the enclosing template should be obtained by +consulting its template symbol supplement.

    +
    +
    +
    +

    13.3. Template Declarations#

    +
    +

    13.3.1. Overview#

    +

    template_directive_or_declaration is the top-level routine for handling +template directives and template declarations. It is called when the +template or export keyword is encountered during declaration +processing. This occurs for template declarations, explicit specialization +declarations, and explicit instantiation directives. For example:

    +
    template <class T> struct A {};       // template declaration
    +export template <class T> void f(T){} // exported template declaration
    +template <> class A<int> {};          // explicit specialization
    +template class A<int>;                // explicit instantiation
    +
    +
    +

    When no template parameter list is present explicit_instantiation is +called. See Explicit Instantiation Directives for further information. When a +template parameter list is present, including an empty one (e.g., <>), +template_or_specialization_declaration is called.

    +

    It first calls cache_template_declaration to create a token cache +containing the entire template declaration, including both the template +parameter list(s) and the declaration that follows. The definition of the +template (e.g., the class or function body) is not included in this cache. An +initial scan of the tokens in the cache is done to determine whether the +declaration is a full specialization, and whether it is a friend declaration.

    +
    +

    13.3.1.1. Template Parameter Clauses#

    +

    A template declaration or template specialization declaration contains one or +more “template parameter clauses”. A template parameter clause consists of the +template keyword followed by a possibly empty template parameter list. The +initial declaration of a template always has a single template parameter clause +(although a template declaration may be nested within another template +declaration). Multiple template parameter clauses are used only when a member +template of a class template is defined or specialized outside of its class.

    +

    Each template parameter list has associated with it a template “nesting depth”. +The nesting depth of the parameter list and the position within the template +parameter list are the attributes used when comparing two template parameters +to see if they represent the same parameter. The names of the template +parameters are not significant. The nesting depth and position are +collectively called the template parameter’s “coordinates”.

    +

    For example:

    +
    template <class T1> struct A {
    +  template <class T2, class T3> void f(T1, T2, T3);
    +};
    +template <class X> template <class Y, class Z> void A<X>::f(X,Y,Z){}
    +
    +
    +

    where

    +
      +
    • +
      T1 and X both have a nesting depth of 1 and a position of 1
      +
      +
    • +
    • +
      T2 and Y both have a nesting depth of 2 and a position of 1
      +
      +
    • +
    • +
      T3 and Z both have a nesting depth of 2 and a position of 2
      +
      +
    • +
    +

    The nesting depth of a template parameter clause in a namespace scope is 1, a +template parameter clause declared within one enclosing class template is 2, +etc. When scanning a template friend declaration any enclosing class templates +are ignored and the template parameter clauses are numbered beginning with 1. +This is necessary so that any types declared in the friend declaration match up +correctly with the template that is being made a friend. For example, to make +the template in the example above a friend of another template, you would do +the following:

    +
    template <class T> struct B {
    +  template <class X>
    +  template <class Y, class Z> friend void A<X>::f(X,Y,Z);
    +};
    +
    +
    +

    The declaration of a template template parmeter also includes a template +parameter clause. The template parameters in the template parameter clause for +a template template parameter have a nesting depth of zero.

    +

    For each nonempty template parameter list, the template parameters from the +parameter list are scanned. This process includes the following steps:

    +
      +
    • +
      An sck_template_declaration scope is pushed. This will be the +declaration scope to which the template parameter names belong.
      +
      +
    • +
    • +
      scan_template_param_list is called to scan the template parameters and +build a linked list of entries of type a_template_param to represent +them. Each template parameter has an associated symbol. These symbols +initially point to special “prototype argument” values that, for class +templates, are used during the prototype instantiation. During real +instantiation these symbols are modified to point to the actual argument +values to be used.
      +
      +
        +
      • +
        A type parameter points to an sk_type symbol that initially points to +a tk_template_param type. The type symbol points to the actual +argument type during an instantiation.
        +
        +
      • +
      • +
        A nontype parameter points to an sk_constant symbol that initially +points to a ck_template_param constant. The constant symbol points +to the actual argument constant during an instantiation.
        +
        +
      • +
      • +
        A template template parameter points to an sk_class_template symbol. +Unlike the type and nontype cases, the template template parameter symbol +always points to the template symbol supplement for that template +template parameter. The argument_template field of the template +symbol supplement points to the actual argument to be used during an +instantiation. Template template parameters differ from other template +parameters in that they have certain properties that must persist through +real instantiations. For example, the default template argument values +used for a template template parameter are always the ones specified in +the template template parameter declaration, never those associated with +the actual template template argument.
        +
        +
      • +
      +
    • +
    • +
      If the template parameter has a default argument, the type or expression is +scanned on the spot if possible. However, if the default argument depends +on another template parameter, the default argument must be rescanned when +its value is needed using the actual argument values for the template +parameters on which it depends. Therefore, its tokens are cached so that +they may be scanned later (see prescan_default_arg_expr). There are a +number of ways in which a default argument can depend on another template +parameter:
      +
      +
        +
      • +
        The type of a nontype parameter may make use of another template type +parameter.
        +
        +
      • +
      • +
        The value of a default nontype argument may depend on a template type +parameter or nontype parameter.
        +
        +
      • +
      • +
        The type used as the default argument for a type parameter may make use +of another template parameter.
        +
        +
      • +
      +
      +
      For example:
      +
      +
      template <class T = int, class T2 = T, int I = 0, T J = I+1> class A {}
      +
      +
      +
      +
      The default type of T and the default constant value for I can +be known when the template parameters are scanned, but the default type +of T2 and the value for J are dependent upon whatever type +T takes on, and the value of J depends on the value used for +I.
      +
      +
    • +
    +
    +
    +

    13.3.1.2. Classifying the Template Declaration#

    +

    When processing specializations a distinction is made between a “full +specialization” and a “template specialization”. A full specialization is one +in which the entity being declared is a class, function, variable, or static +data member, while a template specialization is one in which the entity being +declared is still a template. For example:

    +
    template <class T> struct A {
    +  void f();
    +  template <class T2> void g(T2);
    +  template <class T2> struct B {};
    +  struct C {};
    +};
    +// Full specializations
    +template <> void A<int>::f();
    +template <> struct A<int>::C {};
    +// Template specializations
    +template <> template <class T2> void A<int>::g(T2);
    +template <> template <class T2> struct A<int>::B {};
    +
    +
    +

    A partial specialization of a template is treated as a normal template +declaration, not as a template specialization. A template specialization is a +template with one or more empty template parameter clauses.

    +

    Full specializations are handled by calling full_specialization. See +Explicit Specializations for more information. The rest of this +section describes template_declaration, which is responsible for +processing template declarations and template specializations.

    +

    Earlier, a token cache was built that contains the template parameter clauses +and the declaration that follows them. We are now at the point in the token +stream that marks the division between the two components. Because the +declaration component must be prescanned to determine the kind of template +being declared, and because the declaration may be needed later for the purpose +of generating partial instantiations of functions, the existing cache is split +into a template parameter cache and a template declaration cache. In certain +error cases, such as the presence of a syntax error in the template parameter +list, the template declaration may not have been cached correctly when the +initial cache was built. When this occurs, the template declaration is +recached now that the true position of the beginning of the declaration is +known.

    +

    Next, is_class_template_decl is called. If the declaration is in fact of a +class template, TRUE is returned. If it is not a class template declaration, +FALSE is returned to signal that processing for other kinds of template +declarations should be done.

    +

    The template parameters are checked to ensure that they are compatible with any +previous declaration of the template, and for class members, that the template +parameter lists that correspond to enclosing class templates are compatible +with the template parameter lists of those class templates.

    +
    +
    +
    +

    13.3.2. Class Templates#

    +

    class_template_declaration is called to process class template +declarations. This includes normal class templates, partial specializations, +and template specializations. It is also called to process declarations of +nested classes of class templates that are defined outside of the class. +class_template_declaration performs the following functions:

    +
      +
    • +
      Looks up and verifies the template name.
      +
      +
    • +
    • +
      Creates the sk_class_template symbol and enters it into the symbol +table, if necessary. The symbols for partial specializations are not +entered into the symbol table.
      +
      +
    • +
    • +
      Calls create_prototype_type to create the symbol and type for the +prototype instantiation, and to create the template argument list(s) for +the prototype instantiation.
      +
      +
    • +
    • +
      If a definition is provided, collects the tokens for the base class +specifiers and the class body and caches them for use later.
      +
      +
    • +
    • +
      For partial specializations, the template parameters of the partial +specialization must appear in the template argument list associated with +the partial specialization in such a way that their values can be deduced. +In addition, nontype arguments cannot have types that depend on other +template parameters, nor may they be used in expressions. These error +tests are accomplished by calling +check_partial_spec_nontype_param_usage.
      +
      +
    • +
    • +
      If the template is a partial specialization, +check_for_prior_use_of_partial_spec is called to determine whether the +newly declared partial specialization would have been used to generate any +existing full instantiations of the primary template, had it been declared +when the full instantiation had been done. If any such full instantiations +are found, an error is issued.
      +
      +
    • +
    +

    Then the template declaration scopes that were pushed when the template +parameter clauses were scanned are popped, and instantiate_class_template +is called to do a prototype instantiation – i.e., to scan the template +definition even though the template parameters have not yet been given “real” +values. Because declaration/expression disambiguation often cannot be done +based on dummy types, only declarative information is scanned; inline function +bodies and default argument expressions are cached and, in some modes, have +their prototype instantiations done later. Most syntax errors and some +semantic errors are detected, but some errors cannot be reported until a real +instantiation is done.

    +

    The main benefit of prototype instantiation is to record the names and types of +member functions and static data members – in effect, to create symbols to +represent member functions of class templates and static data members of class +templates. instantiate_class_template accomplishes its work in the +following steps:

    +
      +
    • +
      An sck_template_instantiation scope is pushed onto the scope stack.
      +
      +
    • +
    • +
      The token cache for the class template body is activated.
      +
      +
    • +
    • +
      scan_class_definition is called to process the tokens. Special +provisions are made for prototype instantiations:
      +
      +
        +
      • +
        Diagnostics are suppressed where appropriate.
        +
        +
      • +
      • +
        decl_member_function and decl_static_data_member create template +instance entries, template symbol supplements, and whatever else is +needed to make the member symbols serve as templates.
        +
        +
      • +
      • +
        delayed_scan_fixup_for_class moves the tokens cached for member +function bodies into the appropriate template symbol supplement; it also +moves the entries describing default argument expressions onto a list in +the appropriate template symbol supplement. The cached tokens for +inline-defined friend functions are discarded – they will be picked up +during real instantiation.
        +
        +
      • +
      +
    • +
    • +
      The starting and ending token positions of any nested classes, member +functions whose definitions were provided in the class, and member +templates (functions or classes) whose definitions were provided in the +class are recorded. These token positions will be used to remove the +definitions from the token cache for the class template body.
      +
      +
    • +
    • +
      The template instantiation scope is popped.
      +
      +
    • +
    • +
      The bodies of nested classes, etc. are removed from the class template +body token cache. Nested classes, member functions, and member templates +may all be specialized. In other words, the definitions provided in the +class template definition may not be the ones actually used for a given +instance of the class template, so there is no sense in scanning them while +instantiating the class. As with class templates and function templates, +nested classes of class templates, member functions of class templates, and +member class and function templates are only instantiated when needed, and +may be specialized any time before the point at which they are first used +in a way that requires their instantiation.
      +
      +
    • +
    +
    +
    +

    13.3.3. Alias templates#

    +

    alias_template_declaration is called to process alias template declarations +and performs the following functions:

    +
      +
    • +
      Verifies the template name.
      +
      +
    • +
    • +
      Creates the sk_class_template symbol and enters it into the symbol +table.
      +
      +
    • +
    • +
      Calls create_prototype_type to create the symbol and type for the +prototype instantiation, and to create the template argument list(s) for +the prototype instantiation.
      +
      +
    • +
    • +
      Collects the tokens for the type defined by the alias and caches them for +use later.
      +
      +
    • +
    +

    After calling alias_template_declaration, template_declaration calls +alias_prototype_instantiation to create the prototype instantiation of the +alias.

    +
    +
    +

    13.3.4. Function Templates#

    +

    The above is what happens when is_class_template_decl does in fact +determine that the declaration is a class declaration. However, if it returns +FALSE, template_declaration proceeds to examine what must be a template +declaration for something other than a class template.

    +

    If the template declaration appears within the definition of a class it must be +a member function template declaration or a template friend declaration. If it +is a member function template declaration class_member_template_declaration +(in class_decl.c) is called to scan its declaration, then +complete_function_template_decl is called to create the necessary template +data structures and to scan the template body, if present.

    +

    For all other cases, scan_template_declaration is called to scan the +declaration, which it does by calling decl_specifiers and declarator. +If that produces a function type, the declaration is processed as a function +template or member function of a class template declaration; otherwise, it is +processed as a variable template or static data member of a class template +declaration or reported as an error.

    +

    function_template_declaration is called for function templates. It, in +turn, calls either decl_function_template (in decls.c) or +template_specialization.

    +

    decl_function_template does for member and nonmember template declarations +more or less what decl_routine does for ordinary function declarations. +The processing for nonmember function templates includes the following:

    +
      +
    • +
      id_linkage is called to determine whether this is a redeclaration of a +function template that is already in the symbol table and whether the name +of the function template is overloaded.
      +
      +
    • +
    • +
      If this is not a redeclaration, then:
      +
      +
        +
      • +
        An sk_function_template symbol is entered into the symbol table +(either directly or into an overload set).
        +
        +
      • +
      • +
        A routine entry is allocated and its fields are set to record the type, +storage class, and so forth specified in the declaration. It is not +added to the IL, however, because it does not designate a “real” routine.
        +
        +
      • +
      +
    • +
    +

    Member functions, for which a qualified name must be present, will already have +been declared in the class template definition. Their processing includes a +call to member_function_redecl_sym, which returns the member function +symbol with a matching type signature.

    +

    decl_function_template returns to function_template_declaration an +already existing or newly created symbol that represents the function template. +Then, as with member function template declarations, +complete_function_template_decl is called.

    +
    +

    13.3.4.1. Completing the Function Template#

    +

    The next step is to collect the tokens of the function body (including, for +a constructor, the ctor-initializers) and store them in a cache in the +template symbol supplement. For both member and nonmember function +templates the new template declaration information (parameter list, etc.) +is recorded in the associated template symbol supplement.

    +

    When doing nonclass prototype instantiations, +function_prototype_instantiation is called to perform a prototype +instantiation on the body of a function template or member function of a class +template, and default_arg_prototype_instantiation is called to perform a +prototype instantiation on the default arguments of such functions.

    +
    +
    +
    +

    13.3.5. Variable Templates and Static Data Member Templates#

    +

    Variable template declarations can be either extern declarations, or are +definitions. Static data member declarations are always definitions. For +definitions, the template parameter list is recorded in the template symbol +supplement, and the tokens comprising the initializer, if any, are cached. In +some cases, some or all of the initializer may have already been cached as part +of the template declaration. In such cases, split_token_cache is used to +move the initializer tokens from the declaration cache to the initializer +cache; the remaining initializer tokens are then appended to the initializer +cache.

    +

    When doing nonclass prototype instantiations, +variable_template_prototype_instantiation is called to perform a prototype +instantiation on the initializer of the variable template or template static +data member.

    +
    +
    +

    13.3.6. Variadic Templates#

    +

    The C++11 standard adds “variadic templates,” which are templates that take a +variable number of arguments. For example:

    +
    template<class ...T> void f(T ...args) {
    +  int a[] = {0, args..., 5};
    +}
    +int main() {
    +  f(1, 2, 3, 4);
    +}
    +
    +
    +

    The template f can be called with zero or more arguments. For a given +call, the parameter pack T is deduced to be a list of types, matching the +types of the arguments supplied, and args is a function parameter pack that +is a series of parameters of the types given by T.

    +

    The front end implements variadic templates by storing, along with the tokens +of the template, information on the location and details of any pack references +and expansions. When the template is instantiated, the cached tokens of its +declaration or definition are scanned, and in places where there are pack +expansions, the processing loops over a sequence of tokens, substituting a +different value for the pack name on each iteration, thus producing an expanded +version of the source text.

    +

    The language definition of variadic templates uses a syntax-based trick: in +contexts that allow a list of items (usually, a comma-separated list), an item +in the list can be suffixed by “...” to indicate that it is a pack +expansion. In an instantiation of the template, that pack expansion is +replaced by, in effect, a list of entities generated by the expansion of the +pack. So, in the above example, the aggregate initialization expands to the +equivalent of

    +
    int a[] = {0, 1, 2, 3, 4, 5};
    +
    +
    +

    with the elements of the pack expansion inserted into the surrounding list.

    +

    Such expansions are allowed in parameter lists, call argument lists, +brace-enclosed aggregate initializers, base class specifiers, +mem-initializers, template argument lists, exception specifications, +attributes, and capture lists.

    +

    The front end uses its own trick to expand these patterns. In each of those +contexts, the code that handles the normal, non-variadic, case is enclosed in a +loop with the following general structure:

    +
    a_pack_expansion_stack_entry_ptr pesep;
    +a_boolean                        any_more;
    +
    +any_more = begin_potential_pack_expansion_context(&pesep);
    +while (any_more) {
    +  a_pack_expansion_descr_ptr pedep;
    +
    +  /* Normal processing for one item is done here. */
    +  ...
    +  pedep = end_potential_pack_expansion_context(pesep,
    +                                               /*is_declarator=*/FALSE);
    +  if (pedep != NULL) {
    +    /* Mark the IL created as being for a pack expansion. */
    +  }  /* if */
    +  any_more = advance_to_next_pack_element(pesep);
    +}  /* while */
    +
    +
    +

    When no pack expansions are present, the “begin...” call returns TRUE, the +“end...” call returns NULL, and the “advance...” call returns FALSE, so +the loop goes around exactly once and handles one item on the list.

    +

    When a pack expansion is present, in the prototype instantiation the +“begin...” call returns TRUE, the “end...” call swallows the “...” +indicating the pack expansion and returns a pointer to a structure that +describes the pack expansion, and the “advance...” call returns FALSE. +Again, the loop goes around exactly once, but information about the pack +expansion is recorded in the IL and in data structures attached to the +template.

    +

    In a real instantiation, the loop goes around as many times as the pack being +expanded has values. Each time through, the source token position is reset to +the start of the expansion, the pack identifier is given an appropriate value +for that iteration, and the tokens are scanned again. After the right number +of iterations, the “advance...” call returns FALSE and the loop exits. If +the pack has zero elements, the “begin...” call advances the source token +position to after the “...” at the end of the expansion, and returns FALSE, +and the loop goes around zero times, thus producing no items on the list for +the pack expansion.

    +

    The pattern above appears in every place where a pack expansion could occur. +In a call argument list, for example, it must be done around the scanning of +every argument, which means in a lot of places. (Or, at least, in a lot of +places when inside a template that has variadic parameters.) Almost all the +time, the variadic processing notes a starting position and starts a potential +expansion context, but then finds out later that there is no trailing “...” +and therefore no pack expansion, and discards the information saved. This has +to be done, however, so that we can recall the starting position of a pack +expansion in the cases where one does occur.

    +

    The information saved for a pack expansion in the prototype scope (and, +incidentally, prototype instantiations are forced for variadic templates, so +that such information can be recorded) includes the starting position of the +pack expansion, so that, in a real instantiation, the “begin...” call can +look up the current token position and see whether a pack expansion starts at +the current token, and what the details of the expansion are. The saved +information includes the list of pack names that were referenced and are to be +iterated over in the loop. With that information, the “begin...” routine +can set up the proper looping over the proper sequence of tokens.

    +

    There are variant versions of these variadic-loop-management routines that are +used for expression rescan contexts (no source tokens are consumed; pack +identifiers are updated and the right number of iterations of the loop are +done) and prescan and disambiguation contexts (where we don’t know yet the +context of the code, and therefore can’t be certain about what pack expansions +mean, so we don’t want to record anything permanent).

    +

    Template argument lists need to contain some extra information when variadic +templates are used. For example, for a case like

    +
    template<class U, class ...T> void f(U p, T ...args) {
    +}
    +int main() {
    +  f(1, 2.0, 3.0f);
    +}
    +
    +
    +

    the complete deduced template argument list for f has int for U, +and then a list of double and float for T. In diagnostics, this is +displayed as <int, <double, float>>. Internally, it requires a way to +indicate that part of the list is a pack expansion. That’s the function of the +tak_start_of_pack_expansion kind of template argument: it marks the start +of a sequence of template arguments associated with a pack expansion (and each +member of that sequence is marked with the is_pack_element flag).

    +

    That causes problems for lots of code in the front end that traverses template +argument lists. In most cases, that code does not want to worry about +start-of-pack-expansion entries. It just wants the “real” entries on the list. +That’s what the traversal routines begin_template_arg_list_traversal, +advance_to_next_template_arg, and the “..._simple” versions of those +routines do. They allow easy set up of a traversal of a template argument list +that ignores the start-of-pack-expansion entries. They should be used in +general to process template argument lists, to avoid problems.

    +

    Deduction does special processing to handle parameter packs, matching up +template parameters with multiple types, or nontype values, or template +template parameters. Zero-length packs are a particular problem, in that they +are deduced from an absense of information (e.g., no arguments corresponding to +that parameter pack).

    +

    Overload resolution does special processing for parameter packs, and in +particular has to be careful because the normal one-to-one correspondence +between arguments and parameters does not always hold.

    +

    Initializer processing deals with pack expansions by using expresison caches. +The initializer routines call to fetch one expression. If the expression +scanned is a pack expansion, the first expresison of the expansion is returned, +and the rest are pushed into an expression cache. They are then returned on +subsequent calls at the same or a higher or lower level. If the pack expansion +produces zero expressions, another expression is scanned, unless we hit the end +of the initializer (e.g., a closing brace). In some cases an expression is +prescanned so we can decide whether the expression-list is over before going +down a path in the code that will expects to be able to fetch an expression.

    +

    Partial ordering and partial specialization processing also deal specially with +variadic templates.

    +
    +
    +
    +

    13.4. Templates in the IL#

    +

    An entry of type a_template is created for each template declaration (see +make_il_template_entry). By default, no information about the template +itself is preserved in the IL. There are two different optional mechanisms +that can be used to record information about templates:

    +
      +
    • +
      If PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, any prototype instantiation +is recorded in the IL. If nonclass prototype instantiations have been +requested, prototype instantiations will be generated for each template +entity declared; otherwise, prototype instantiations will be recorded only +for class templates. A prototype instantiation is an IL entry whose kind +corresponds to the kind of entry being declared, but that represents the +template itself and not any particular instantiation thereof. In other +words, it still contains references to the template parameters. A type +entry is used to represent a class template, a routine entry is used to +represent a function template, and a variable entry is used to represent a +variable template or template static data member.
      +
      +
    • +
    • +
      If RECORD_TEMPLATE_STRINGS to TRUE, the IL template entry will point to +a null-terminated string that reproduces the text (minus comments, after +preprocessing) of the template declaration in the source program (see +make_template_string). If a template has more than one declaration +(e.g., a nondefining declaration followed by a definition), an IL template +entry is produced for each declaration.
      +
      +
    • +
    +

    Both of these mechanisms can be used at the same time. Note that while all +templates can be represented as template strings, only those templates that +make use of the standard-mandated typename and template keywords +can have prototype instantiation IL entries generated (because without such +keywords it is not possible to parse the template definitions in the +absence of a set of actual template argument values). See +Templates for more information.

    +
    +
    +

    13.5. Partial Instantiation#

    +

    Partial instantiation occurs automatically for nested classes, member +functions, and static data members when the class of which they are members is +instantiated. That is to say, the full instantiation of a class necessarily +entails the implicit declaration of all its members: symbols are introduced +into the symbol table, type entries are created as required, IL entries are +created and added to the IL, and so forth. The partial instantiation of class +templates and function templates, on the other hand, is triggered by a +reference.

    +
    +

    13.5.1. Class Templates#

    +

    When a class template reference – class-template-name<template-arg-list> – is encountered, a call is made to +coalesce_template_class_reference to scan the template argument list and +look up the reference. Having verified that types in the template argument +list correspond to type template parameters and constants correspond to nontype +template parameters, it builds a linked-list representation of the template +arguments. If there are more template parameters than template arguments and +if the template parameters have default values, entries are supplied for the +default values as well, whether from a saved constant value or after rescanning +the cached tokens comprising the default argument expression.

    +

    The template argument list is then passed to find_template_class, which +searches among the instantiations that already exist for the class template, +calling equiv_template_arg_lists to compare the template arguments scanned +for the current reference against the template arguments associated with +existing instantiations. If an instance with matching template arguments is +located, the symbol for it is returned. If no match is found, a new symbol is +created (see make_template_class_sym in symbol_tbl.c) and added to the +instantiations list for the class template. A new class type is also created, +but, since this is a partial instantiation, no body is generated for it yet.

    +

    A reference to an instance of a class template always causes a partial +instantiation, but not all references cause full instantiation. Partial +instantiation occurs during the lexical scan of a template class reference, +whereas the decision whether to do full instantiation occurs during semantic +processing. Partial and full instantiation are always separate steps in +template processing.

    +

    Note that a partial instantiation can be generated on the basis of an +incomplete class template. For example:

    +
    template <class T> class A;
    +A<int> *x;
    +
    +
    +

    Even though no body has been supplied for class template A, a partial +instantiation of A<int> can be produced. On the other hand, A<int> is +an incomplete (and incompletable) type, and so an error would be issued if it +were used in a context that required a complete type. Similarly, partial +specializations are not relevant when a partial instantiation is generated. +They are only considered when a full instantiation is done.

    +
    +
    +

    13.5.2. Function Templates#

    +

    A function template may be referenced in several different ways:

    +
      +
    • +
      as a function call,
      +
      +
    • +
    • +
      by taking the address of a function,
      +
      +
    • +
    • +
      and by declaring a function in an explicit specialization, explicit +instantiation, or friend instance declaration.
      +
      +
    • +
    +

    In each case, determining which function template is to be used, and which +instance of the template is being referenced, requires the evaluation of an +explicitly specified template argument list, deducing template arguments from +the function template’s parameters, or some combination of the two. This +process involves the following steps for each of the candidate function +templates:

    +
      +
    • +
      If an explicit template argument list was specified, +substitute_template_arguments is called. Note that an explicit +template argument list is completely scanned before +substitute_template_arguments is called. When it is scanned, the +number of parameters, and their types are not known. Consequently, the +template argument list needs to be converted into one that matches the +template parameter list of the candidate template. This is done by calling +create_initial_template_arg_list. If the specified template arguments +cannot be converted to the types of the corresponding parameters, or if +there are more template arguments than template parameters, no template +argument list is created and the candidate template is disqualified. Note +that an error is not issued because there may be another candidate template +that is actually the one intended to be used.
      +
      +
    • +
    • +
      Once an appropriate template argument list has been produced, +substitute_template_arguments calls copy_type_with_substitution to +create a function type that represents the function type of the candidate +template with the template parameters that correspond to the explicitly +specified template arguments replaced with the specified template argument +values. If the substitution process would result in an invalid type (e.g., +a pointer to a reference type, or an array of void) the candidate template +is disqualified.
      +
      +
    • +
    • +
      Template argument deduction is done using the substituted function type +created above in an attempt to deduce the template arguments that were not +explicitly specified. Template argument deduction is done by calling +matches_template_type, which is described below.
      +
      +
    • +
    • +
      If template argument deduction succeeds, +wrapup_function_template_argument_deduction is called to verify that +values have been deduced for all of the template parameters, and that the +types of any deduced nontype parameters match the types of the +corresponding template parameters. copy_type_with_substitution is +called once again to create a new function type in which all of the +template parameters have been replaced with the corresponding template +argument values.
      +
      +
    • +
    +

    When the reference is from a function call, the routines described above are +called from the overload resolution routines. When the reference is from the +address of a function or from a declaration, these routines are called by +is_match_for_function_template, which in turn is called from either +matching_template_function or has_matching_template_function.

    +

    There are several routines in templates.c that directly and indirectly +support the process described above:

    +
      +
    • +
      matches_template_type is designed to be called successively to build a +template argument list while checking for a match between a type from the +function template routine type and a type from a new routine type; it also +calls itself recursively to apply the processing to type trees. When a +template parameter type is found, the “real” type with which it is paired +is recorded in the corresponding template argument entry – unless it +already has some other type, in which case an inconsistency has been found. +As long as there are no inconsistencies or type incongruities, this process +of augmenting the template argument list continues; otherwise, +matches_template_type returns FALSE to halt further processing and +invalidate the template argument list built thus far.
      +

      +
      After matches_template_type has indicated that each of the arguments +match the template, verify_template_nontype_args must be called to +verify that nontype parameters whose types depend on a template parameter +are consistent with the deduced types. It also supplies types for nontype +parameters that are deduced entirely from array bounds.
      +
      +
    • +
    • +
      compare_function_templates is used to determine whether one function +template is more specialized than another based on the partial ordering +rules for function templates. It is called by the overload resolution +routines to compare two function templates that are otherwise identical +from the point of view of overload resolution.
      +
      +
    • +
    • +
      add_to_partial_order_candidates_list is used in contexts other than +overload resolution in which a function template must be selected from a +set of function templates using the partial ordering rules. This is done +when taking the address of a function that is determined to be an instance +of a function template, and when the lookup of a conversion operator name +results in the partial instantiation of a template (e.g., when operator +int* is a reference to an instance of a function template such as +operator T*). After this routine has been called for each candidate +template, select_best_partial_order_candidate is called to return the +best matching template.
      +
      +
    • +
    • +
      find_template_function is passed a function template symbol and a +template argument list. After checking for the use of a local type among +the template arguments (an error), it goes through the instances that +already exist for the template, calling equiv_template_arg_lists until +a match is found. If none of the existing instances match the new template +argument list, it creates a new instance by calling +make_template_function, to which the new template argument list is +passed.
      +
      +
    • +
    • +
      is_match_for_function_template is passed a function template symbol and +a new routine type. It returns TRUE if the type fits the type signature of +the template and FALSE if not. First, obvious mismatches are detected, +such as mismatches in the number of function parameters. Next, if an +explicit template argument list was specified, the template arguments are +compared with the corresponding template parameters. Type arguments must +be associated with type parameters, nontype arguments must be associated +with nontype parametersm, and the specific nontype value specified must +match the type of the nontype parameter or must be capable of being +converted to the type of the nontype parameter. It then tries to find +among the instances of the template one whose type signature exactly +matches the new routine type. If it finds such an instance, it returns +TRUE, along with the symbol it found. Otherwise, it makes successive calls +to matches_template_type in an attempt to construct a template argument +list based on any explicitly specified template arguments, the template +parameter types, the template routine type, and the new routine type; if +this is successful, it returns TRUE, along with the new template argument +list, but otherwise it returns FALSE.
      +
      +
    • +
    • +
      matching_template_function is passed a function template symbol and a +routine type. It calls is_match_for_function_template which checks for +a match between the routine type and the template. If there is a match but +no instance already exists, it creates a new instance by calling +make_template_function, to which the routine type is passed.
      +
      +
    • +
    • +
      has_matching_template_function is similar to +matching_template_function in that it determines whether a given +routine type matches a potential instance of the specified template, but it +does not create an instance of the template. It is primarily used when +issuing diagnostics, to choose the most appropriate of several possible +messages. In the following example, the error “specializing overloaded +function "A::f" requires template <> syntax” is used because the +function type matches the template declared in the class.
      +
      +
      struct A {
      +  template <class T> void f(T);
      +};
      +void A::f(int) {}
      +
      +
      +
    • +
    • +
      make_template_function is the routine that actually does the partial +instantiation. When it is passed a non-NULL routine type, it simply uses +that type; otherwise, it activates the declaration token cache (see the +decl_token_cache field in the template symbol supplement) and calls +either scan_member_declaration or scan_template_declaration, for +member and nonmember function templates, respectively, to assure that +template arguments are correctly substituted for template parameters in the +new routine type; and then, if there are default arguments, it calls +delayed_scan_for_function_template_default_args. In addition, it +creates the sk_member_funciont or sk_routine symbol entry, the +routine entry, and the template instance, setting all their pointers and +other fields appropriately. The symbol is not entered directly into the +symbol table – it is accessible to lookup via the instantiation list only.
      +
      +
    • +
    +
    +
    +

    13.5.3. Variable Templates#

    +

    A reference to a variable template results in a full instantiation of the +instance if a definition is available. The only exception is when the variable +template is used in a declarative context (i.e., to declare an explicit +specialization of the variable template). In a partial instantiation the +initializer is not scanned.

    +
    +
    +
    +

    13.6. Full Instantiation#

    +

    Full instantiation of a template means providing an instance of the template +with a defining body (or, in the case of a static data member, a definition +with an implicit or explicit initializer). Typically, this occurs +automatically, on the basis of the template provided. However, it can also +occur when the user provides an explicit specialization definition. Both cases +are discussed in this section.

    +
    +

    13.6.1. Explicit Specializations#

    +

    Two forms of explicit specialization are supported by the front end: the new +explicit specialization syntax (e.g., template <> ...), and the old form +that used the normal declaration syntax. The new form is accepted in all +modes, while acceptance of the old form is controlled by a command line option. +Member function templates and member class templates may only be explicitly +specialized using the new syntax.

    +

    For example:

    +
    template <class T> void f(T);
    +template <class T> class A {};
    +template <> class A<int>;       // new specialization declaration
    +template <> class A<int> {};    // new specialization definition
    +class A<char>;                  // old specialization declaration
    +class A<short> {};              // old specialization definition
    +template <> void f(int);        // new specialization declaration
    +template <> void f(int){}       // new specialization definition
    +void f(char);                   // guiding declaration
    +void f(double){}                // old specialization
    +
    +
    +

    Explicit specializations that use the new syntax begin with one or more +template parameter clauses in which the parameter list is empty. An explicit +specialization can be a declaration or a definition. The language requires +that an explicit specialization be declared before its first use in a +translation unit.

    +

    When using the old syntax, only classes can be declared as specializations. +For all other kinds of entities, specializations can only be supplied as +definitions. A function declaration that looks like an old-style +specialization declaration is actually what is known as a “guiding +declaration”, whose only purpose is to cause a template instance to be treated +like a normal function for overload resolution purposes. There are no member +guiding declarations.

    +

    Old-style explicit specializations look like normal class, function, and static +data member declarations and are handled by the same routines that handle +normal declarations.

    +

    full_specialization processes new-style explicit specializations and is +called after the template parameter clauses have been scanned. +decl_specifiers and declarator are called to scan the declaration that +follows the template parameter clauses. If the entity being specialized is a +class, the call to declarator is bypassed. full_specialization then +identifies the template instance that is being specialized.

    +
    +

    13.6.1.1. Class Templates#

    +

    An explicit specialization of a class template occurs when the explicit +specialization syntax is used, or when old specializations are enabled, when an +ordinary class definition is provided in which the class name is a template +class reference, for example:

    +
    template <class T> class A {};
    +template <> class A<short> {};
    +class A<int> {};
    +A<char> x;
    +
    +
    +

    In this example the bodies for A<int> and A<short> are the ones +provided by the user’s explicit definitions. The bodies for all other +instances of template class A, such as A<char>, are based on the +template definition.

    +

    The processing of class template explicit specializations is done within +class_specifier, even when the new specialization syntax is used. This is +necessary because only when class_specifier is called is it possible to +determine whether the class is being specialized or whether the class specifier +is part of an elaborated type specifier in some other kind of declaration.

    +

    When the template class reference is encountered as a tag name (see +scan_tag_name), a partial instantiation is done automatically and the +symbol is entered on the instantiations list of the class template. Then +class_specifier marks the class as being explicitly specialized by setting +the is_specialized flag in the type entry, and adds the definition, if one +has been supplied. Because the is_specialized flag is set, no subsequent +automatic instantiation will be attempted.

    +

    The same processing applies to both class templates and member class templates. +The processing for nested classes of class templates is basically the same +except that, as with other members of class templates, the partial +instantiation of the nested class is done when the enclosing class is +instantiated.

    +
    +
    +

    13.6.1.2. Function Templates and Member Functions of Class Templates#

    +

    An instance of a function template may be explicitly specialized using the +explicit specialization syntax, or when old specializations are enabled, by +providing a function definition that happens to match the type signature of a +function template. For example:

    +
    template <class T> void f(T) {}
    +template <> void f(char);         // explicit specialization
    +void f(int) {}                    // old explicit specialization
    +void f(int,int} {}                // Unrelated to the template
    +
    +
    +

    In both the old and new style specializations, the is_specialized flag in +the routine entry is set, which suppresses the full instantiation of the +template. The old-style specialization of a function also acts as a guiding +declaration for overload resolution purposes.

    +

    When the new specialization syntax is used, find_matching_template_instance +is called to find the template instance that matches the routine type returned +by declarator. This is done not only for instances of function templates +and member function templates, but also for member functions of class +templates.

    +

    Processing for old-style explicit specializations follows the track for +ordinary function definitions. The primary difference appears in +find_linked_symbol (called from decl_routine via id_linkage), which +searches for previous declarations of the entity being declared. If the +ordinary search fails to turn up a matching function but does find a function +template with the given name, a call is made to matching_template_function, +which extends the search to instances of the template function and, as +described above, creates a new one when appropriate. In other words, this +search in id_linkage may have the effect of doing a partial instantiation +of a new template function. Once the instance symbol has been found (or +created by means of a partial instantiation), attaching the function definition +to the routine involves no special processing.

    +

    It can happen that an old-style explicit specialization of a function template +precedes the declaration of the template itself. For example:

    +
    void f(int) {}                 // Specific definition
    +template <class T> void f(T) {}
    +
    +
    +

    When the function template declaration is encountered, +decl_function_template goes back through existing functions of the same +name and calls record_predeclared_template_function for each – if the +function turns out to match the new template, it is retroactively entered as an +instance.

    +

    Old-style explicit specializations of member functions or static data members +of instances of a class templates involve little special handling beyond what +is normally done for definitions of member functions and static data members of +nontemplate classes. Here’s an example:

    +
    template <class T> class A {
    +  void f(T);
    +  static T s;
    +};
    +void A<int>::f(int) {}
    +int A<int>::s = 0;
    +
    +
    +

    The reason no special processing is required is that the full instantiation of +A<int> entails the partial instantiation of its members f(int) and +s. After that it’s just a matter of marking the symbols as defined and +adding the function body or initializer.

    +
    +
    +

    13.6.1.3. Variable Templates#

    +

    The use of a variable template in an expression context results in a full +instantiation if a definition is available. If a definition is not available, +the normal instantiation processing is done as for template functions and +static data members of template classes (e.g., an instantiation could be done +later in the translation unit if a definition was provided, depending on the +instantiation mode). Even though a full instantiation may be done, an external +definition of the instance may or may not be emitted depending on the +instantiation mode.

    +
    +
    +
    +

    13.6.2. Automatically Generated Definitions#

    +
    +

    13.6.2.1. Class Templates#

    +

    The full instantiation of a template class occurs at the first point in the +translation unit where a reference to the instance requires it to be a complete +type. In other words, it is done as soon as necessary, but no sooner. For +example:

    +
    template <class T> class A {};
    +A<int> *p;                   // Partial instantiation of A<int>
    +A<int> a;                    // Full instantiation of A<int>
    +
    +
    +

    The first declaration involving A<int> does not require that it be a +complete type, but the second one does, and so that is the point at which the +full instantiation occurs. At points in the front end where a complete type is +required, the macro complete_class_type_is_needed is invoked, resulting, if +appropriate, in a call to instantiate_template_class to generate the full +instantiation.

    +
    +
    13.6.2.1.1. Partial Specializations#
    +

    A class or variable template may be partially specialized. A partial +specialization is a version of the template that should be used for certain +instantiations. The template to be used is selected based on the template +argument list on which the instantiation is to be based.

    +

    When a full instantiation is required, check_partial_specializations is +called to match the template argument list of the class being instantiated with +each of the partial specializations that have been declared for the template. +matches_partial_specialization is called to perform the actual matching.

    +

    The matching is done using the same process and routines that are used to do +function template argument deduction (see matches_template_type above). If +the template parameters for a given partial specialization can be deduced from +the actual template arguments, then the template class matches the partial +specialization. For example:

    +
    template <class T1, class T2> struct A {};              // #1
    +template <class U1, class U2> struct A<U1*, U2> {};     // #2
    +template <class V1>           struct A<V1, V1> {};      // #3
    +template <class X1>           struct A<X1*, short> {};  // #4
    +A<int, char> a1;  // uses primary template (#1)
    +A<int*, int> a2;  // uses #2
    +A<int, int> a3;   // uses #3
    +
    +
    +

    The declaration of a1 does not match any of the partial specializations, so +the primary template is used. The declaration of a2 matches the partial +specialization labeled #2 because U1 and U2 can be deduced from +<int*, int> (as int and int, respectively). Partial specialization +#3 is used when the two template arguments are the same, as in the declaration +of a3.

    +

    Each partial specialization that matches the argument list is added to a list +of candidate partial specializations using the routine +add_to_partial_order_candidates_list, which compares the new entry with any +entries already on the candidates list. The comparison is done by +is_more_specialized, which determines whether a given partial +specialization is “more specialized” than another. If the entry being added is +not as specialized as an entry already on the list, the new entry is not added. +If the new entry is more specialized than an entry already on the list, that +entry is removed from the list. After all of the partial specializations have +been evaluated, the candidates list contains a set of partial specializations +that match the template argument list of the class being instantiated and which +are unordered relative to one another. If there are no entries on the list, +the primary template is used to generate the class. If there is exactly one +entry on the list, that partial specialization is used to generate the class or +variable. If there is more than one entry on the list, the instantiation is +ambiguous and an error is issued.

    +
    A<int*, int*> a4;  // ambiguous - could be #2 or #3
    +A<int*, short> a5; // uses #4
    +
    +
    +

    The declaration of a5 uses partial specialization #4, even though both #2 +and #4 match. #4 is preferred because it is “more specialized” than #2. +Whether a given partial specialization is more specialized than another is +determined in much the same way in which a partial specialization is determined +to match a given actual template argument list, i.e., though use of the +argument deduction routines. In the example above, if the argument list of #4 +was considered to be the actual argument list and the argument list of #2 was +considered to be the parameter list, the parameters of #2 could be deduced as +U1=X1 and U2=short. If the roles of the two partial specializations +are reversed, making #2 the actual argument list and #4 the formal parameter +list, the type deduction fails. Therefore, #4 is considered more specialized +than #2.

    +
    +
    +
    13.6.2.1.2. Generating the Template Class#
    +

    Once the appropriate template has been selected (i.e., either the primary +template or a partial specialization), the body of the template class is +generated. These are the steps:

    +
      +
    • +
      The pending_instantiations value in the template symbol supplement for +the class template is incremented. This allows the compiler to catch and +report “runaway recursive instantiation,” as the following example would +produce:
      +
      +
      template <int I> class A { A<I+1> a; };
      +A<0> x;
      +
      +
      +
      +
      Once the pending instantiations counter reaches +max_pending_instantiation (a global variable that can be set by a +command-line option, and whose default is defined in lang_feat.h), an +error is issued and the recursion is halted.
      +
      +
    • +
    • +
      push_template_instantiation_scope is called to push a template +instantiation scope onto the scope stack and to do some special processing +for template instantiations:
      +
      +
        +
      • +
        Pointers to the template symbol, the instance symbol, and the template +argument list are recorded in the scope stack entry.
        +
        +
      • +
      • +
        depth_innermost_instantiation_scope is updated with the current scope +stack depth.
        +
        +
      • +
      • +
        update_template_param_symbols is called to bind the symbols for +template parameters to the values in the corresponding template +arguments. For example:
        +
        +
        template <class T, int I> class A {};
        +A<int,0> x;
        +
        +
        +
      • +
      +
      +
      By default the sk_type symbol for template parameter T refers to a +tk_template_param type entry and the sk_constant symbol for I +refers to a ck_template_param constant. But during the instantiation +of A<int,0> – that is, while the template instantiation scope is +active – any reference to T or I should be translated into a +reference to the value of the corresponding template argument, namely, to +int or 0, respectively. This is done by modifying the pointers in +the symbols; the default pointers are restored when the template +instantiation scope is popped.
      +
      +
    • +
    • +
      The cache containing the tokens for class template definition is activated.
      +
      +
    • +
    • +
      scan_class_definition is called. In most respects processing is +identical to the processing for any class definition. The differences have +mainly to do with recording member functions and static data members as +instances:
      +
      +
        +
      • +
        find_corresp_prototype_tag_sym is called to find the symbol for the +prototype instantiation of the class. (When a nested class within a +template class is scanned, the symbol returned is the corresponding +nested class of the prototype instantiation.) That symbol is required for +calling the two routines described next.
        +
        +
      • +
      • +
        find_member_function_template is called for member functions of the +new template class. It locates the template symbol (i.e., the symbol for +the corresponding member function in prototype instantiation), creates a +template instance entry for the new member function, and adds it to the +instantiation list of the template. The template argument list for the +new template class serves for the instance, too.
        +
        +
      • +
      • +
        find_variable_member_template is called for variable templates and +static data members of the new template class. The processing is similar +to what is done for member functions.
        +
        +
      • +
      • +
        find_function_template_member is called for member function templates +of the new template class. The processing is similar to what is done for +member functions.
        +
        +
      • +
      • +
        find_class_template_member is called for member class templates of +the new template class. The processing is similar to what is done for +member functions.
        +
        +
      • +
      • +
        set_nested_template_class_symbol_info is called for nested classes of +the new template class. This call is made by class_specifier when +the nested class is first encountered. The processing is otherwise +similar to what is done for member function.
        +
        +
      • +
      • +
        delayed_scan_fixup_for_class, called at the end of scanning the class +definition, provides somewhat special handling for template classes. For +inline-defined member functions the function bodies are not scanned at +this time; such functions are only instantiated if they are called, so +that errors are not issued on functions that are not actually used. +Also, delayed_scan_for_function_template_default_args is called to +process the default arguments on the function parameters: the token cache +to be used is accessed through the template symbol supplement.
        +
        +
      • +
      +
    • +
    • +
      set_instantiation_required_for_template_class_members is invoked; for +each member function and static data member, both of the template class and +of any classes nested within the template class, it calls +update_instantiation_required_flag.
      +
      +
    • +
    • +
      pop_template_instantiation_scope is called to pop the template +instantiation scope. The template parameter symbols and +depth_innermost_instantiation_scope are restored to the values they had +before the scope was pushed. (Note that the possibility of recursive +instantiation prohibits restoring these values to default values.)
      +
      +
    • +
    • +
      The pending_instantiations value in the template symbol supplement for +the class template is decremented.
      +
      +
    • +
    +
    +
    +
    +

    13.6.2.2. Alias Templates#

    +

    When an instance of an alias template is referenced, find_template_class is +called to look for a previously created template alias or instantiate a new +alias if no previously created instance exists. Template aliases are +instantiated by instantiate_template_alias. Note that unlike class +templates, there are no partial instantiations of alias templates

    +
    +
    +

    13.6.2.3. Function Templates#

    +

    The timing for the instantiation of member and nonmember template functions is +partly controlled by the user (as discussed in the next section). A function +may end up being instantiated

    +
      +
    • +
      at the point of first reference in a given translation unit (e.g., +functions declared inline);
      +
      +
    • +
    • +
      at the end of the translation unit; or
      +
      +
    • +
    • +
      externally to the current translation unit.
      +
      +
    • +
    +

    Wherever it occurs, it is instantiate_template_function that is called to +generate a function body based on a template. These are the steps in the +process:

    +
      +
    • +
      The function’s storage class and name linkage are set, along with its +is_inline flag if required.
      +
      +
    • +
    • +
      The pending_instantiations value in the template symbol supplement is +incremented. As for class templates, this field is used to catch runaway +recursive instantiation.
      +
      +
    • +
    • +
      push_template_instantiation_scope is called to push a template +instantiation scope onto the scope stack.
      +
      +
    • +
    • +
      The token cache is activated.
      +
      +
    • +
    • +
      push_scope is called again to push a function scope onto the scope +stack.
      +
      +
    • +
    • +
      On the basis of the param_id list saved in the template symbol +supplement the function parameters are entered into the symbol table (in +the function scope) by decl_parameter.
      +
      +
    • +
    • +
      For constructors a call is made to ctor_initializer to process the +ctor-initializer list, if any, as well as to do default processing, +and for destructors a call is made to dtor_initializer.
      +
      +
    • +
    • +
      In case a function is being instantiated “on the fly” in the midst of +executable code, the structured statement stack is suspended and a new one +begun by a call to new_struct_stmt_stack.
      +
      +
    • +
    • +
      compound_statement is called to process the tokens comprising the +function body. The IL produced is recorded in the function scope.
      +
      +
    • +
    • +
      If appropriate, restore_struct_stmt_stack is called.
      +
      +
    • +
    • +
      pop_scope is called for the function scope.
      +
      +
    • +
    • +
      pop_template_instantiation_scope is called for the template +instantiation scope.
      +
      +
    • +
    • +
      The pending_instantiations value in the template symbol supplement for +the class template is decremented.
      +
      +
    • +
    +
    +
    +

    13.6.2.4. Variable Templates and Static Data Members of Class Templates#

    +

    instantiate_template_variable is invoked to handle full instantiation of +static data members and for partial and full instantiations of variable +templates. It performs the following:

    +
      +
    • +
      Static data members are marked as defined. Variable templates are marked +as defined if the declaration is a definition.
      +
      +
    • +
    • +
      If an explicit initializer was specified in the static data member template +declaration, then:
      +
      +
        +
      • +
        push_template_instantiation_scope is called to push a template +instantiation scope onto the scope stack.
        +
        +
      • +
      • +
        The token cache is activated.
        +
        +
      • +
      • +
        The type is scanned to determine the type of a template variable, or to +make sure the type agrees with the declaration in the class for static +data members.
        +
        +
      • +
      • +
        For a full instantiation, if a definition is available, initializer +is called to process the tokens comprising the initializer.
        +
        +
      • +
      • +
        pop_template_instantiation_scope is called for the template +instantiation scope.
        +
        +
      • +
      +
    • +
    • +
      If no initializer was specified for a defined variable template or static +data member, def_initializer is called.
      +
      +
    • +
    +
    +
    +
    +
    +

    13.7. Constrained Templates#

    +

    C++20 introduces the notion of “constrained templates”, which is often referred +to as “concepts” (although concepts are just one feature in support of +constrained templates). For example:

    +
    template<typename T> requires(sizeof(T)<4*sizeof(int*))
    +  int hash(T *p);
    +
    +
    +

    Constraints are boolean predicates. In the example above, it’s just a normal +expression. Whenever template instance is considered (e.g., for overload +resolution or for a partial instantiation), its constraint predicates are +substituted and evaluated: If the predicates evaluates to false, the +template is discarded. For functions and partial specializations, that may not +be an error (assuming other candidates satisfy their constraint or are +unconstrained), but other cases will then elicit an error that will indicate +which constraint failed to be satisfied.

    +
    +

    13.7.1. Concepts#

    +

    A constraint expression can be abstracted through a concept template. For +example:

    +
    template<typename T> concept SmallHashable = sizeof(T)<4*sizeof(int*);
    +
    +
    +

    After that definition, the declaration of hash above can instead be rewritten +as:

    +
    template<typename T> requires SmallHashable(T)
    +  int hash(T *p);
    +
    +
    +

    or

    +
    template<typename T>
    +  int hash(T *p) requires SmallHashable(T);
    +
    +
    +

    or

    +
    template<SmallHashable T> int hash(T *p);
    +
    +
    +

    or even

    +
    int hash(SmallHashable auto *p);
    +
    +
    +

    Although concept template are a kind of template, they are not (partially or +fully) instantiated. Instead, they are “substituted” somewhat like function +templates are substituted during the deduction process.

    +

    Concept templates are represented in the IL using a_template entries of +templk_concept kind, and in the symbol table using sk_concept_template +symbols (that point to a_template_symbol_supplement entries with no variant +fields). A templk_concept template points to the predicate, which is +represented as an ordinary expression tree (an_expr_node structure).

    +

    Concept templates can also be “invoked” directly to produce a boolean value. +For example:

    +
    auto cond = SmallHashable<X>;
    +
    +
    +

    Such expressions are represented using enk_concept_id nodes: They point to +a templk_concepta_template entry and, optionally, to a list of +template arguments.

    +
    +
    +

    13.7.2. Representation of constraints#

    +

    As hinted above, there are four possible syntactic locations for constraints:

    +
      +
    • +
      A concept name used to introduce a template type parameter. Such +constraints – called type constraints – are represented as +enk_concept_id nodes pointed to by the +a_template_param_type_supplement associated with the constrained +template parameter. The first template argument for such +enk_concept_id nodes are implied (it’s the template parameter being +constrained) and that is indicated by the is_type_constraint flag in +the enk_concept_id node.
      +
      +
    • +
    • +
      A requires clause following a template<...> header, as in our +original example. Such constrains are represented using +a_requires_clause entries pointed to from a_template_decl, +itself pointed to from a_template. a_requires_clause is itself +mostly a structure pointing to an expression tree.
      +
      +
    • +
    • +
      An implicit template type parameter introduces by a so-called “abbreviated +function template declaration”, as in the example int hash(SmallHashable +auto *p); above. This case is represented very much as the first case +(concept name used to introduce a template type parameter): By having the +associated a_template_param_type_supplement entry point to an +enk_concept_id node representing the constraint. However, in this +case, the a_param_type entry corresponding to the parameter that +introduced the constrained also has the flag is_auto_param set to TRUE.
      +
      +
    • +
    • +
      A trailing requires clause following the function declaration itself, as we +showed in the second variation of our example:
      +
      +
      template<typename T>
      +  int hash(T *p) requires SmallHashable(T);
      +
      +
      +
      +
      This is represented by having the a_routine entry for the prototype +instantiation of the function template point to an entry of type +a_requires_clause. It’s worth noting that this variation of a +constraint can also be applied to ordinary member functions of class +templates (hence the need to point to it from an a_routine entry rather +than a template-specific entry).
      +
      +
      +
      To ease the description of constraints, C++20 also introduces +requires-expressions (not to be confused with requires-clauses, +which were described above). For example:
      +
      +
    • +
    +
    template<typename T> void f() {
    +  bool b = requires { typename T::node; };
    +}
    +
    +
    +

    Such expressions are represented by an enk_requires node, which points to a +list of expression nodes: Entries on that list that are of kind +enk_type_operand, enk_compound_req, and enk_nested_req are of +special significance. See il_def.h and expr.c for details.

    +
    +
    +

    13.7.3. Important Constrained-Template Functions#

    +

    The following are some functions that are central to the handling of +constrained templates:

    +
      +
    • +
      scan_requires_clause and scan_concept_expression (both in +expr.c). These are the functions that parse constraint expressions, +which requires special treatment of the logical operators (&& and +||).
      +
      +
    • +
    • +
      scan_requires_expr (expr.c), which parses requires-expressions.
      +
      +
    • +
    • +
      check_template_constraints (templates.c), which determines if a +given template’s constraints are satisfied by a given set of template +arguments.
      +
      +
    • +
    • +
      requires_clause_satisfied (exprutil.c). This function performs +substitution of constraint expression, which is subject to various subtle +rules. It leans heavily on the expression rescanning facilities (see +Rescanning Expressions).
      +
      +
    • +
    • +
      compare_constraints (exprutil.c). When determining the partial +order of function templates or partial specializations, constraint can play +a special role. This function, is the main function for comparing the +constraints on templates (to determine whether a template is more or less +constrained than another, or maybe neither is more constrained than the +other). The algorithm for this comparison is relatively complex and +described in great detail in exprutil.c.
      +
      +
    • +
    +
    +
    +
    +

    13.8. Managing Instantiation of Functions, Variables, and Static Data Members#

    +

    As noted previously, the full instantiation of template classes occurs as soon +as necessary, but no sooner. The timing for the automatic instantiation of +template functions, variables and members of template classes is more +complicated.

    +

    For example, if a member function of a template class is not referenced, +there is no reason to instantiate it. But even if it is referenced, its +instantiation may occur elsewhere. The EDG C++ front end supports several +methods whereby the user can manage the instantiation of templates: +automatic instantiation, instantiation modes that are specified on the +command line, and explicit instantiation directives included in the source +code of the program. Explicit instantiation directives are supported in +both the form specified by the C++ standard and as #pragma directives. +For a detailed description of how the instantiation modes and pragmas are +used, see Template Instantiation.

    +

    The instantiation_required flag in template instance entries is set to +indicate that a function, variable, or static data member has been referenced +in such a way as to require its definition (i.e., full instantiation) somewhere +in the program, even if not in the current translation unit. For example, +calling a template function causes the flag to be set.

    +

    update_instantiation_required_flag is called to set the flag and to place +the instance on a linked list (see add_to_instantiations_required_list) so +that it can be readily found later, when the actual instantiation is done. +Sometimes the routine to do full instantiation is called immediately, however +(e.g., for calls to template functions that are declared as inline or when +in the midst of instantiation wrapup processing); in such cases the instance is +not placed on the list.

    +

    It is do_any_needed_instantiations, called by +template_and_inline_function_wrapup, as part of the fe_wrapup process, +that goes through the instantiations_required list. It determines for each +instance whether full instantiation is actually required in the current +translation unit as a result of the instantiation mode being used, explicit +instantiation and #pragma directives found in the program (see +should_be_instantiated, which checks instantiation modes and directives), +and whether the instantiation has been assigned to the current translation unit +by the automatic instantiation mechanism. It then will call +instantiate_entity, if appropriate.

    +

    Instantiations are normally generated as part of the object file of the +translation unit in which the instantiations are performed. But when “one +instantiation per object” mode is specified, each instantiation is placed in +its own object file, and the names of those object files are written to the +template information file (which is described below). One instantiation per +object mode is useful when generating libraries that need to include copies of +the instances referenced from the library. If each instance is not placed in +its own object file it may be impossible to link the library with another +library containing some of the same instances. Without this feature it is +necessary to create each individual instantiation object file using the manual +instantiation mechanism.

    +
    +

    13.8.1. Automatic Instantiation#

    +

    The EDG C++ front end provides a complete prototype implementation of an +automatic instantiation mechanism. The EDG automatic instantiation mechanism +is a “linker feedback” mechanism. It works by providing additional information +in the object file that is used by a “prelinker” to determine which template +entities require instantiation so that the program can be linked successfully. +Unlike most aspects of the front end the automatic instantiation mechanism is, +by its nature, dependent on certain operating system and object file format +properties. In particular the prelinker is a separate program that makes use +of the UNIX nm command to access information about the symbols defined in +object files. Furthermore it relies on features implemented in the eccp +driver script. Consequently, this code should be viewed as a sample +implementation that may need adaptation to work on other systems.

    +

    This section describes the steps involved in automatic instantiation. The +steps are described in the sequence in which they would occur while compiling +and linking an application and not necessarily the sequence in which they occur +in a given execution of the front end. While one might expect the two +sequences to be the same the automatic instantiation mechanism may, in fact, +compile a given file a number of times while determining the set of +instantiations that are needed to link the application.

    +
    +

    13.8.1.1. Initial Compilation#

    +

    When a program is compiled, the front end generates a set of flags that are +provided to the back end and are ultimately either output as a separate file by +the front end or are encoded in some form in the generated object file. The +flags are stored in the IL variable and routine entries.

    +
      +
    • +
      The can_be_instantiated flag indicates that this translation unit is +capable of generating an instantiation for a given function, variable, or +static data member (hereafter referred to as a “template entity”). This is +used by the prelinker to determine which source files are possible +instantiation sites for the template entity. This flag is set even if the +translation unit provides an instantiation of the template entity.
      +
      +
    • +
    • +
      The instance_required flag indicates that a definition of the template +entity must be supplied by some translation unit (but not necessarily this +one). Both the instance_required and the can_instantiate flags +indicate that the entity is one that can potentially be defined by a +generated template instantiation. This information allows the prelinker to +distinguish between an unresolved template reference and a plain undefined +symbol. These flags are also used by the prelinker to distinguish class +specializations, whose members cannot be defined by generated +instantiations, from regular template classes whose members may be defined +by generated instantiations.
      +
      +
    • +
    • +
      The do_not_instantiate flag indicates that instantiation of the +template entity has been explicitly prohibited by use of the +do_not_instantiate#pragma directive. When automatic +instantiation is used, the do_not_instantiate pragma prohibits +instantiation not only in the file in which the pragma was included but +anywhere within the application with which the resulting object file is +being linked.
      +
      +
    • +
    +

    In the default configuration, these flags are written to the template +information file, which is descibed below. In earlier versions of the front +end these flags were translated by IL lowering into tentative definitions of +specially named symbols. The old behavior can be selected using the +INSTANTIATION_FLAGS_IN_TEMPLATE_INFO_FILE configuration flag. The flags +were removed from the object file because the amount of space consumed by the +names of the flags could be excessive, because the mangled names of template +entities can be very long. When the flags are generated as part of the object +file, the symbol names include a code that indicates the flag kind and also +includes the name of the symbol being described. The special symbol includes a +prefix of __CBI__ (can be instantiated), __TIR__ (template instance +required), or __DNI__ (do not instantiate) followed by the mangled name of +the entity. For example, a template function of type void f(int) could +have the following flags generated.

    +
    __CBI__f__fi__TIR__f__fi__DNI__f__fi``
    +
    +
    +

    Because they are generated as tentative definitions, they may each appear in +any or all of the object files being linked into an application while only +appearing once in the generated executable file

    +

    When a template class contains noninline virtual functions, the instantiation +mechanism must ensure that the virtual function table is defined. IL lowering +does this by generating a “template instance required” flag for the first +noninline virtual function of any template class, because it’s the presence or +absence of a definition for that function that controls whether or not IL +lowering puts out a definition for the virtual function table. By requiring +the first noninline virtual function to be defined we ensure that the virtual +function table will also be defined

    +
    +
    +

    13.8.1.2. The Template Information and Instantiation Request Files#

    +

    Information is exchanged between the front end and prelinker using the +“template information” and “instantiation request” files. These files are also +known respectively as the .ti and .ii files [1]. The template +information file is used for infomation produced by the front end for use by +the prelinker. The instantiation request file is produced by the prelinker for +use by the front end. The template information file was added in version 2.37 +of the front end to support features such as one-instantiation-per-object mode, +and generation of instantiation flags in a separate file instead of the object +file. The front end can be configured to not use a template information file +in order to be compatible with earlier versions of the front end, but this +requires that the features that use the template information file be disabled.

    +

    The template information file provides several diferent kinds of information to +the prelinker. Each line of the file contains a type code followed by a +string. The type code indicates the type of information being provided. The +following types of lines are generated by either the front end or driver:

    +
      +
    • +
      cmd: command line (supplied by the driver)
      +
      +
    • +
    • +
      dir: compilation directory (supplied by the driver)
      +
      +
    • +
    • +
      fnm: compilation file name (supplied by the driver)
      +
      +
    • +
    • +
      idn: instantiation directory (in one-instantiation-per-object mode, +supplied by the driver)
      +
      +
    • +
    • +
      flg: instantiation flags (when not encoded in the object file)
      +
      +
    • +
    • +
      ifn: instantiation file names (in one-instantiation-per-object mode)
      +
      +
    • +
    • +
      stu: secondary translation units (supplied by the driver)
      +
      +
    • +
    • +
      tnm: export templates defined in this file
      +
      +
    • +
    • +
      dep: dependency information when exported instantiations have been +generated
      +
      +
    • +
    +

    The order in which these are specified is not, in general, significant except +that the prelinker currently requires that the instantiation directory entry +precede any instantiation file name entries.

    +

    The template information and instantiation request files have the same base +name as the source file, but use special suffixes specified by configuration +parameters in host_envir.h, with the default values indicated above.

    +

    At the end of each compilation the front end determines whether any template +entities were referenced in the translation unit. If so a template information +file is created (or an instantiation request file, if template information +files are not being used). If no template entities were referenced in the +translation unit the file will not be created and any existing file will be +removed. When template information files are being used, the instantiation +request file is also removed if the template information file is removed.

    +

    After invoking the front end the driver checks for the existence of either the +template information or instantiation request file, depending on the +configuration. If one exists, the driver updates it with the command line used +to compile the source file, the name of the current directory when the +compilation was done, and the name of the file that was compiled. This +information is used later if the prelinker needs to recompile the file.

    +
    +
    +

    13.8.1.3. Prelinker#

    +

    Once a complete set of object files has been generated, including the +appropriate flags, the prelinker is invoked to determine whether any new +instantiations are required or if any existing instantiations are no longer +required. The command line arguments to the prelinker include a list of input +files to be analyzed. The input files are the object files and libraries that +constitute the application. The prelinker begins by looking for template +information files for each of the object files (or instantiation request files, +if template information files are not being used). If no template information +(or instantiation request) files are present, the prelinker concludes that no +further action is required.

    +

    If there are template information (or instantiation request) files, the +prelinker reads the template information file and the current instantiation +list from the instantiation request file. The instantiation list is the list +of instantiations assigned to a given source file by a previous invocation of +the prelinker. The prelinker uses the UNIX nm command to produce a list of +the global symbols that are referenced or defined by each of the input files. +The prelinker then simulates a link operation to determine which symbols must +be defined for the application to link successfully.

    +

    When the link simulation has been completed, the prelinker processes each input +file to determine whether any new instantiations should be assigned to the +input file or if any existing instantiations should be removed. The prelinker +goes through the current instantiation list from the instantiation request file +to determine whether any of the existing instantiations are no longer needed. +An instantiation may be no longer needed because the template entity is no +longer referenced by the program or because a user supplied specialization has +been provided. If the instantiation is no longer needed, it is removed from +the list (internally; the file will be updated later) and the file is flagged +as requiring recompilation.

    +

    The prelinker then examines any symbols referenced by the input file. The +responsibility for generating an instantiation of a given entity that has not +already been defined is assigned to the first file that is capable of +generating that instantiation.

    +

    If a given file contains instantiations of exported templates, the template +information file contains dependency information. If a source file that is +part of an exported template translation unit changes, the dependency +information is used to detect such a change so that the prelinker can recompile +the file and regenerate the instantiations of the exported templates.

    +
    +
    +

    13.8.1.4. Recompilation#

    +

    Once all of the assignments have been updated, the prelinker once again goes +through the list of object files. For each, if the corresponding instantiation +request file must be updated, the new file is written. Only source files whose +corresponding instantiation request file has been modified will be recompiled.

    +

    At this point the combination of the template information and instantiation +request files contains the information needed to recompile the source file, and +a list of instantiations assigned to the source file (in the form of mangled +function, variable and static data member names).

    +

    Then, during recompilation the front end reads the entries from the +instantiation request file produced by the prelinker and checks them against +entries on its own “instantiations required” list. Whenever a match is found, +based on comparing the mangled name from the instantiation request file and the +name returned by either get_mangled_function_name or +get_mangled_variable_name (in lower_il.c), the +automatically_instantiated flag is set in the template instance entry.

    +

    When the prelinker invokes the front end, it provides a “definition list file”, +which contains a list of all the external definitions found in the object files +and libraries specified on the prelinker command line. The front end reads the +definition list file and determines whether each of the entries on its +instantiations required list has already been defined elsewhere. If an entity +is found that is not defined elsewhere, its automatically_instantiated flag +is set.

    +

    Later, in instantiation_wrapup, instantiations will be generated for all +instances for which the automatically_instantiated flag is set, whether as +a result of being included in the instantiation request file or “adopted” by +the front end when it was determined that the instance was not defined +elsewhere. A list of the entities adopted by the front end is written to the +definition list file. This list is used by the prelinker to add the adopted +entities to the adopting translation unit’s instantiation request file.

    +

    The definition list file permits the front end to perform instantiations that +have become necessary as a result of other instantiations that were assigned by +the prelinker, without requiring that the prelinker invoke the front end an +additional time to perform those instantiations. This reduces the number of +iterations of the prelinker and front end that are required to generate a +complete set of instantiations for a program.

    +

    If an error occurs during a recompilation, the prelinker exits without updating +the remaining information files and without attempting any additional +compilations.

    +
    +
    +

    13.8.1.5. Iteration and Termination#

    +

    If all recompilations complete without error, the prelink process is repeated, +since an instantiation can produce the demand for another instantiation. This +prelink cycle (finding uninstantiated templates, updating the appropriate +instantiation request files, and dispatching recompilations) continues until no +further recompilations are required. [2]

    +

    When the prelinker is finished, the linker is invoked. Note that simply +because the prelinker completes successfully does not assure that the linker +will not detect errors. Unresolvable template references and other linker +errors will not be diagnosed by the prelinker.

    +

    In many cases, once the application has been successfully linked, the +recompilation overhead will have become a one-time-only expense, because the +next time the source file is compiled, the instantiation request file will +provide precisely the right list of instantiations to be done. Recompilation +will be required again only if the instantiation request file is invalidated, +that is:

    +
      +
    • +
      if additional instantiations come to be needed (in this or another file);
      +
      +
    • +
    • +
      if existing instantiations are not longer referenced;
      +
      +
    • +
    • +
      if a different set of command-line options is used to compile the file; or
      +
      +
    • +
    • +
      if the instantiation request file is deleted.
      +
      +
    • +
    +

    Except in such cases, once the complete set of instantiation request files has +been generated, the prelinker should not need to force recompilation for any +source files in the application.

    +
    +
    +

    13.8.1.6. Implementing Alternative Automatic Instantiation Mechanisms#

    +

    The default automatic instantiation implementation uses the instantiation +request file as described above. The routines in templates.c are designed +to permit an alternative mechanism to be used (e.g., querying a database) to +determine whether a given entity should be instantiated. This may be done by +modifying the following routines:

    +
      +
    • +
      init_auto_instantiation_information is called at the beginning of the +automatic instantiation processing. The default version calls +read_auto_instantiation_information, which opens the instantiation +request file and reads its contents.
      +
      +
    • +
    • +
      check_if_entity_should_be_automatically_instantiated is called for each +instantiatable entity (external function, variable, or static data member). +It sets the automatically_instantiated flag if the entity is to be +instantiated in this translation unit, and the add_to_request_file flag +if the instantiation was “adopted” by this translation unit and must be +added to the instantiation request file by the prelinker. The default +version calls check_if_present_in_request_file to determine whether the +specified entity was named in the instantiation request file and/or the +definition list file.
      +
      +
    • +
    • +
      wrapup_auto_instantiation_information is called by fe_wrapup. The +default version calls create_or_remove_instantiation_information_file +and close_or_remove_template_info file.
      +
      +
    • +
    +
    +
    +
    +

    13.8.2. Instantiation Modes#

    +

    The instantiation mode is specified by a command line option and determines +whether the compiler should automatically generate instances of template +entities (function templates, variable templates, member function of template +classes, and static data members of template classes.) The command line option +is used to set the global variable instantiation_mode to one of the +following values:

    +
    + + + + + + + + + + + + + + + +
    +
    tim_none
    +
    +
    +
    Do not automatically create instantiations of any template entities. +This is the default.
    +
    +
    +
    tim_used
    +
    +
    +
    Instantiate those template entities that were used in the compilation. +This will include all static data members for which there are template +definitions.
    +
    +
    +
    tim_all
    +
    +
    +
    Instantiate all template entities declared or referenced in the +compilation unit. For each fully instantiated template class, all of +its member functions and static data members will be instantiated +whether or not they were used. Nonmember template functions will be +instantiated even if the only reference was a declaration.
    +
    +
    +
    tim_local
    +
    +
    +
    Similar to tim_used except that the functions are given internal +linkage. This is intended to provide a very simple mechanism for +those getting started with templates. The compiler will instantiate +the functions, variables and static data members used in the +compilation as local (static) functions and local (static) variables.
    +
    +
    +
    +

    Inline functions are usually instantiated when they are first referenced, and +so unreferenced inline functions are usually not instantiated. However, in +tim_all mode they are always instantiated – either during +instantiation_wrapup or, for member functions for which the body is +supplied in the class template definition, when the class is instantiated.

    +
    +
    +

    13.8.3. #pragma Directives#

    +

    There are three instantiation pragmas, instantiate, which causes the +specified entity to be instantiated, do_not_instantiate, which causes +instantiation of the specified entity to be suppressed, and +can_instantiate, which indicates that the specified entity can be +instantiated by an automatic instantiation mechanism, but need not be. [3] +The do_not_instantiate pragma is typically used with the manual +instantiation mechanisms when a specific definition will be supplied elsewhere.

    +

    The argument to the instantiation pragmas may be a template class name, a +member function name, a variable name, a static data member name, a member +function declaration, a function declaration, an elaborated type specifier for +a class, or a static data member declaration. When a class name or elaborated +type specifier is specified, the directive is applied to all member functions +and static data members of the class.

    +

    Processing the pragmas results in setting some flags in the template instance. +They are later checked by should_be_instantiated (called from +instantiation_wrapup) to determine whether the entity requires full +instantiation. The instantiate pragma sets the instantiation_required +and explicit_instantiation flags and records the current source position +(for reporting errors later). The do_not_instantiate pragma clears +instantiation_required and sets specific_def to block instantiation +based on the instantiation mode.

    +

    Explicit instantiations are processed by instantiation_wrapup in much the +same way as instantiations that may be generated depending on the instantiation +mode. The only difference is that certain conditions that are ignored for +nonexplicit instantiations cause errors to be issued for explicit +instantiation. If no template definition has been supplied from which to +generate an instantiation, an error is issued for explicit instantiation +requests. Likewise, if a specific definition has been supplied and an explicit +instantiation was requested, an error is also issued.

    +
    +
    +

    13.8.4. Explicit Instantiation Directives#

    +

    Explicit instantiation directives are processed in nearly the same way as +instantiation pragmas. The differences between the handling of the +instantiation pragma and an explicit instantiation directive are as follows:

    +
      +
    • +
      Inline functions may be specified in explicit instantiation directives, +even though doing so is meaningless.
      +
      +
    • +
    • +
      An entity may not appear in more than one explicit instantiation directive.
      +
      +
    • +
    • +
      Explicit instantiation directives require that a declaration follow the +template keyword, while the instantiation pragmas permit a simple name +to be specified.
      +
      +
    • +
    +
    +
    +

    13.8.5. Implicit Inclusion#

    +

    In the cfront model of programming with templates the template +declarations are placed in a header (e.g., “.h”) file while the +definitions of noninline functions and static data members are placed in a +source (e.g., “.c”) file. To support this style of programming the +front end provides an optional “implicit inclusion” feature. When this +feature is enabled, the front end will implicitly include a source file +when needed to provide definitions of template entities declared in a given +header file.

    +

    When a header file is included, information about the kind of include statement +used is stored in the IL source file structure. This specifies whether the +include statement was a “normal” include (e.g., #include "file.h") or a +system include (e.g., #include <file.h>).

    +

    At the end of compilation, during instantiation wrapup processing, the source +file associated with a given header file will be included if needed. A file is +“needed” if an instantiation of an entity is required as a result of a command +line option, pragma directive, or instantiation list file. In automatic +instantiation mode implicit inclusions of template definition files will +essentially always be done so that accurate “can be instantiated” flags may be +generated.

    +

    The implicit inclusion is done by searching through each of the directories in +the appropriate search path list (based on the kind of include statement used +to include the header file). A configuration parameter specifies a list of +file suffixes to be used during the search for a file to be implicitly +included. In each directory on the search path each of the possible suffixes +will be tried in sequence. If no matching file is found, the next directory in +the list is used. If no matching file is found in any directory, no error is +reported (unless the instantiation was explicitly requested using an +instantiate pragma in which case an error will be issued indicating that no +template definition was supplied).

    +
    +
    +

    13.8.6. Instantiating Non-Template Inline Functions#

    +

    The front end provides two implementations of C++``extern inline`` functions, +referred to as “lower extern inline” and “instantiate extern inline”. The +“lower” version is the default, and causes extern inline functions to be +translated into static functions with special care taken to ensure that +entities such as local static variables have the proper semantics. (See the +comments on the definition of INSTANTIATE_EXTERN_INLINE in targ_def.h +for the advantages and disadvantages of each implementation.)

    +

    The “instantiate” version, which is enabled by setting the +INSTANTIATE_EXTERN_INLINE configuration flag, ensures that only a single +external out-of-line copy of the inline function is generated, and then only if +one is required by the program. The automatic template instantiation mechanism +is used to implement this mechanism.

    +

    When an inline function is defined, add_to_inline_function_list is called +to add the function to a list of all of the inline functions in the translation +unit. During the wrapup processing at the end of the compilation, +inline_function_wrapup uses the inline function list to determine which +inline functions should have their bodies emitted as part of this compilation. +The suppress_inline_body flag in the routine entry is cleared if a back end +should emit an out-of-line body of an inline function. +update_inline_function_flags emits instantiation flags as is done for +template entities. The prelinker will then assign the “instantiation” of +inline functions for which out-of-line bodies are required.

    +
    +
    +
    +

    13.9. Exported Templates#

    +

    The C++ standard specifies that the definition of certain templates (static +data members and non-inline functions) can be separately compiled. This +feature is generally referred to as “export” as such templates are declared +using the export keyword. The definition of an exported template is +provided in a single translation unit. Other translation units that use the +template require only a declaration of the template.

    +

    Exported templates require special processing not needed for normal +(non-exported) templates:

    +
      +
    • +
      When the definition of an exported template is encountered, a record of the +translation unit containing the exported template must be made so that the +definition can be found later when an instantiation is needed.
      +
      +
    • +
    • +
      When an instantiation of an exported template is generated, the front end +must be able to search for a definition of the template.
      +
      +
    • +
    • +
      Generating an instantiation of an exported template requires that the front +end have access to information about the translation unit containing the +template definition and the translation unit containing the reference. One +exported template may call another, which may call another, and so on. As +a result, the front end must be able to simultaneously process an arbitrary +number of translation units at the same time (see Multiple Translation Units).
      +
      +
    • +
    • +
      Whenever a partial or full instantiation of an entity must be done, the +front end must update its context information so that the translation unit +containing the template is the current translation unit +(see Initialization, Termination, and Keeping Translation Units Separate).
      +
      +
    • +
    +

    When an exported template is defined, information about the definition must be +recorded. add_to_exported_templates_list is called when an exported +definition is encountered. This information is used at the end of the +compilation to create a file that provides a list of the exported templates +defined in the translation unit. This file is known as the “exported template” +file and, by default, has a suffix of .et. The following is an example of +an exported template file:

    +
    fnm:t.c
    +tnm:f__tm__4_Z1Z__FZ1Z_v
    +tnm:f2__tm__4_Z1Z__FZ1Z_v
    +mid:t_c_ee131b0b
    +def:XXX=3
    +und:YYY
    +end:
    +
    +
    +

    The following types of lines appear in such a file:

    +
      +
    • +
      fnm: The name of the primary source file to be used when reloading the +translation unit.
      +
      +
    • +
    • +
      tnm: The mangled name of a template defined in the translation unit.
      +
      +
    • +
    • +
      mid: The module ID to be used when instantiating templates from the +file.
      +
      +
    • +
    • +
      def: A command-line macro definition to be used when reloading the +translation unit.
      +
      +
    • +
    • +
      und: A command-line macro un-definition to be used when reloading the +translation unit.
      +
      +
    • +
    • +
      end: The end of the entries associated with the previous fnm: +entry.
      +
      +
    • +
    +

    The information for a given file always begins with “fnm:” and ends with +“end:”. This makes it possible to concatenate a group of exported template +files together, which is useful when creating a library that defines exported +templates.

    +

    When the front end compiles a file that makes use of exported templates, a +search path of exported template directories is used to locate the file that +defines a given exported template. The entries on the search path are +specified with the --template_directory command-line option. The front end +searches each of the directories in the search path to find any exported +template files that exist there. Each of the exported template files is read +to determine which exported templates are defined, and the name of the file +that defines each template. An exported template directory can also contain a +file named export_info, which provides information used when reloading +exported template translation units. The export info file contains the include +search path to be used when reloading a translation unit. If no export info +file is present, the include search path associated with the primary +translation unit is used.

    +

    A translation unit may contain entities that must be given unique names (e.g., +unnamed namespace members). A “module ID” is used as part of the name in such +cases to ensure that the name is unique. The instantiation of an exported +template must be able to refer to, and generate additional, entities with +appropriate unique names. To accomplish this, the module ID is saved in the +exported template file and that module ID is re-used when the translation unit +containing the exported template definitions is reloaded.

    +

    When an exported template translation unit is reloaded, it undergoes what is +basically the normal compilation process, except that none of the external +entities defined in the translation unit are emitted. Only the instantiations +of exported templates, and other templates or inline functions referenced as a +result of such instantiations (directly or indirectly) are emitted. The +entities that are emitted are copied into the IL of the primary file being +compiled (see Copying from Secondary Translation Units). The command-line options used when the +exported template translation unit is loaded are the same options used to +compile the primary translation unit. The only exceptions are command-line +macro definitions/undefinitions, and the include search path to be used. The +command-line macro definitions/undefinitions are saved in the exported template +file, and those values are used when the exported template translation unit is +loaded (include search path handling is described above).

    +

    A mangled name is generated for each exported template. It is this mangled +name that is used to match a reference to an exported template with the +definition found elsewhere. A hash table of exported template definitions is +built as the exported template files are read. When an instantiation is +needed, the mangled name is looked up in the hash table to see if a definition +is available. If a definition is available, process_translation_unit is +called to load the translation unit that defines the exported template.

    +

    A template instance entry is created for each function, variable, or static +data member instance that is partially or fully instantiated. If a given +instance is declared in more than one translation unit, there will be multiple +template instance entries created. In addition, a “master instance” entry is +created to represent the information that is shared among translation units. +For template instances in the primary translation unit, the master instance is +created when the template instance is added to the instantiation required list. +For template instances in secondary translation units, the correspondence +information is used to find a master instance entry that may have been already +created for an earlier translation unit. Because the correspondence +information is not set until a translation unit has been completely scanned, +the master instance information cannot be established until after scanning has +completed. The master instance entry points to the template instance entry +associated with the canonical copy of the instance (see +Canonical Entries). Each template instance contains a pointer to the +associated master instance.

    +

    Instantiations of exported templates are generated during the “instantiation +wrapup” process, which is performed by template_and_inline_function_wrapup. +The instantiations required list for each translation unit is examined, and +instantiations are generated if appropriate. An instantiation in one +translation unit may result in the need for an instantiation in another +translation unit. Because the other translation unit may already have been +processed, the wrapup process must iterate over the set of translation units +until no additional instantiations are added for during an iteration.

    +

    The instantiation of a function, variable, or static data member is initiated +by calling instantiate_entity with the template instance entry of the +instance to be generated. For exported templates defined in other translation +units, the translation unit is loaded and find_corresponding_instance is +called to find or create the template instance entry in the exported template +translation unit that corresponds to the one for which the instantiation is +being generated. The corresponding instance is then used for the remainder of +the instantiation process.

    +

    A “translation unit stack” is maintained when instantiating an entities defined +in other translation units. This stack serves two purposes: it provides a +sequence of lookup contexts for resolving dependent function names during the +instantiation process, and it provides a record of the translation unit +switches that have taken place so that the prior translation unit state can be +restored when an instantiation has completed.

    +
    +
    +

    13.10. C++/CLI Generics#

    +

    C++/CLI generics are sort of like templates, and sort of not. They have +arguments, but the arguments are more constrained than for templates, being +effectively only managed class types or handles to them, value classes, +fundamental types, or scoped enum types. (And types only: No nontype +arguments, no template template arguments.) In addition, generics can have +user-written constraint clauses that further restrict the valid argument values +to certain kinds of class types. Generic classes do get instantiated for each +set of template arguments, much like template classes, but generic functions +effectively have just one instantiation, which corresponds to a single routine +body that can operate on all types. That’s possible because the function can +only perform those operations that are valid based on the declared constraints. +That allows the instantiation of generic functions to be delayed until runtime +and for most references to share a single instantiation (for example, all +instantiations based on handles to ref classes share a single instantiation at +runtime). That in turn forces some restrictions on the code that can be +written in generic functions.

    +

    Generics are represented as templates marked with the is_generic_definition +flag in the class type or routine entry. If they have constraints, those are +represented by entries of type a_generic_constraint and +a_generic_constraint_clause.

    +

    Generic classes and generic functions don’t get the standard prototype +instantiations. Instead, they undergo a process similar to prototype +instantiation (and kicked off by the same routine that does prototype +instantiations) using invented types based on the constraints. The result is +marked as a “generic definition” instead of a prototype instantiation. The +same process applies to static data members as well.

    +

    During the generic definition instantiation, a “constraint type” is created for +each generic parameter. It is a class type that reflects the constraints, +e.g., if the generic parameter is required to be derived from a class X, the +constraint type has X as a base class. The constraint type is a real type (not +a nonreal type), and lookups can be done in it. Such lookups in fact +significantly define what can be done with an object of that generic parameter +type, in the sense, for example, that a “+” operation can be done only if a +lookup finds an appropriate “operator+” function in the constraint type.

    +

    The actual type that is used for a given generic parameter type during the +generic defintition instantiation is known as the “generic definition argument +type.” It is a handle to the constraint type except in cases when the generic +parameter is constrained to be a value class type, in which case it is the same +as the constraint type.

    +

    During the generic definition instantiation, the template parameter symbols for +the generic are set to the generic definition argument type. That makes a lot +of processing, in declarations and expressions, work out fine without special +handling: uses of the template parameter name produce the generic definition +argument type, and for the most part that that can be processed without +difficulty. In particular, the generic definition argument type is not a +dependent type, and therefore real types can be built (instead of unknown +template parameter types), real results of overload resolution can be +determined, etc. However, there are also cases where one wants to think of the +type as being the generic parameter type. There’s a duality here: the template +parameter type and the generic definition argument type are really equivalent +types, and sometimes we want one and sometimes the other. We chose to make the +default value be the generic definition argument type, because that seemed to +work out better in terms of requiring less special-case code, but whichever way +we had decided that there would be cases that wanted to look at the type the +other way. Fortunately, because the types point to each other, it’s easy to +flip to the other representation if one has the wrong one. See, for example, +generic_param_if_generic_definition_argument.

    +

    Because the rules for valid generic template arguments are different than those +for normal template arguments, a special routine is used to scan generic +template argument lists: scan_generic_argument_list. It calls +is_valid_generic_argument to check that each argument is valid for any +kind of generic. Later, when one has a full set of generic type arguments +(whether from an explicit list or through type deduction), +verify_generic_arg_list_satisfies_constraints is called to check that the +arguments satisfy their constraints.

    +

    Generic classes can overload on arity, meaning that there can be multiple +generic classes with the same name, but differing numbers of type arguments, +declared in the same scope. That is not valid in source code, but it does come +up in libraries written in other languages and imported via metadata. When +such overloading occurs, the first generic that is declared is what is entered +into the symbol table and what is returned by lookup. The template symbol +supplement for that symbol has a pointer to a list of any other generic classes +with the same name and different arities in the same scope. If there is also a +non-generic class in the same scope, it is pointed to by another pointer there. +With this information, references to the name can be resolved to the proper +instance of the generic or to the non-generic.

    +

    Template deduction for generics is done in the usual way; there are no special +tricks to speak of.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/testing/index.html b/dev/doc/testing/index.html new file mode 100644 index 0000000..50f42d2 --- /dev/null +++ b/dev/doc/testing/index.html @@ -0,0 +1,1155 @@ + + + + + 26. EDG Testing Framework - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    26. EDG Testing Framework#

    +

    The EDG front end testing framework is fundamentally based on process exit +codes and recorded “expected output.”

    +
    +

    26.1. Writing a Test File#

    +

    Test files are written using a series of directives at the start of the test +file.

    +

    The following is a sample single-file test (the common case) to help illustrate +some of the features described below:

    +
    //remark:Simple friend functions in class template
    +//options::;cn
    +template <class T> class A {
    +  friend int f(A);
    +  int     i;
    +};
    +
    +A<int>  a;
    +
    +int f(A<int> a) {
    +  return a.i;     // Should be OK
    +}
    +
    +#if TEST_NUMBER==2
    +int f(A<int> a, int i) {
    +  return a.i;     // No access -- should fail
    +}
    +#endif
    +
    +
    +
    +

    26.1.1. Single-file Testing#

    +

    Individual test files end in either .sft.c or .sft.cpp depending on +the programming language being tested. The testing directives that can be +used in a single-file test are enumerated below. Additional directives +have meaning in multi-file tests and are described in Multi-file Testing.

    +
    +
    +
    //remark:A string that gets printed on the output
    +
    //type:xx
    +
    //name:xxx
    +
    //options:-a:-b=xx:-c=
    +
    //options_all:-A
    +
    //options_sep:x
    +
    //match_regex:regular expression
    +
    //cases:n
    +
    //eccp_command:compile-command
    +
    //ulimit:options
    +
    //linker_options:options
    +
    //execution_args:command line arguments
    +
    //use_system_includes:true/false
    +
    //edg_header_pack:string
    +
    //require:string
    +
    //filter:pipe-command
    +
    +
    +

    xx is a type identifier. The accepted values are:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Identifier

    Meaning

    fn

    front end only negative

    fp

    front end only positive

    fc

    front end - expect catastrophic error

    cn

    compile negative

    cp

    compile positive (including compiling generated C) - DEFAULT

    cc

    compile - expect catastrophic error

    ln

    compile and link negative

    lp

    compile and link positive

    rn

    runtime negative

    rp

    runtime positive

    ra

    runtime - expect abort

    cppbe

    a special C++-generating back end only mode that dumps the +generated code for review and validation

    s

    skip the test

    +
    +

    Positive tests expect a return code of zero. Negative tests expect a +non-zero return code.

    +

    The //name: directive specifies the name to be used when the file is +compiled. This is useful for tests that need to test platform support for +Unicode file names and similar file name-dependent scenarios.

    +

    The //options: directive specifies a set of command line options to be +used, separated (by default) by colons. The compiler will be invoked once +for each set of options. An option set can override the type specified by +appending the optional string ;xx on the end of an option +specification.

    +

    If the options need to include a colon, the //options_sep: directive +can be used to specify a different separator. For example, +//options_sep:! will change the separator to !. The separator can +be multiple characters.

    +

    The //options_all: directive specifies a set of command line options +that will be provided on every compilation. This is useful for tests with +a single case and for options that don’t vary from case to case. This may +be used in conjunction with the //options: directive. The options from +each option set are put in the command line after the //options_all: +string so that they can override values in the //options_all: string.

    +

    The //match_regex: directive allows specification of a regular +expression (expressed in the Python regex dialect) that must be found in +the output for the test to pass. Matches will additionally add sections to +the captured output highlighting the matching lines (thus serving as a +further sanity check against unintended changes). This directive is +particularly useful if wanting to require fine grained details like +specific diagnostics, IL output fragments, or generated C++ code (when +using a cppbe test).

    +

    The //linker_options: directive specifies an additional set of options +that are placed at the end of the command used to compile and link the +program and is intended to be used for library names.

    +

    The string specified in the //remark: directive is printed in the test +results output to help identify what a test is doing.

    +

    As shown in the initial testing example, it is often useful to be able to have +code conditionally compiled for each of the different compilations specified by +the options string. The test driver defines a preprocessor variable named +TEST_NUMBER. This variable has the value “1” for the first set of options, +“2” for the second, and so on.

    +

    If you have a number of test cases that don’t require different command +line options and that have the same result type you can use the +//cases:n directive to specify that the compiler should by invoked +n times, with TEST_NUMBER set to the current invocation number.

    +

    //options: and //cases: can be used together. For example, you may +have five test cases but only need to specify options for the first two.

    +
    //options:-A;cn:-O;cn
    +//cases:5
    +
    +
    +

    The //ulimit: directive specifies command-line options passed to a +ulimit command prior to compiling, linking, and running the test. This +can be used to prevent a test from exhausting system resources or running +in a non-terminating loop.

    +

    Special characters can be incorporated into the test case by using special +escape sequences. The escapes are of the form ???nnn where n is +a decimal digit.

    +

    If //require: is specified, the string that follows is searched for in the +output of --dump_configuration; if not found, the test is skipped. If +multiple //require: cases are specified, all strings must be found or the +test will be skipped.

    +

    If //use_system_includes: is set to true, the system headers +associated with the current EDG base will be added to the default include +paths. Additionally, EDG compiler emulation modes will be enabled as +appropriate. For instance, if the test is run using a GCC 15.1 base this will +add the include paths for system headers associated with GCC 15.1 and +--gnu_version 150100 to the command line. Otherwise, if this directive is +set to false, EDG headers in include_c99 (for C programs) and +include_c++ (for C++ programs) will be added to the default include paths.

    +

    The //edg_header_pack: directive specifies an “EDG header pack” to include +as system headers for testing. Header packs are include directories that are +themselves subdirectories of $TEST_ROOT/.includes/. For instance, +//edg_header_pack: foo will result in a hidden +--sys_include $TEST_ROOT/.includes/foo command line argument.

    +

    If //filter: is specified, the specified command will be used to filter +the run_test output before diff-ing it. By default, a test driver +uses in-process test normalization logic as a filter.

    +
    +
    +

    26.1.2. Multi-file Testing#

    +

    Multi-file tests work similarly to single-file tests; however, they end +with either .mft.c or .mft.cpp. Additionally, for correct +operation, these tests live in their own test directory, typically +following the convention of test-name/test.mft.cpp. This allows the +test to live alongside its supporting files.

    +

    For instance, testing a simple C++ #include might using the following +structure:

    +
    simple-include/
    +  test.h
    +  test.mft.cpp
    +
    +
    +

    Similarly, for testing an import of a module, the test might use the +following structure:

    +
    modules-function/
    +  exporting-module.ixx
    +  test.mft.cpp
    +
    +
    +

    where test.mft.cpp contains the testing directives (described below) that +compile exporting-module.ixx.

    +

    As previously noted, there are additional directives which are useful for +multi-file testing:

    +
    +
    +
    //header_unit_files:t.h t2.h
    +
    //module_files:i-part.ixx internal:i-internal.cpp i.ixx obj:msvc-module.ixx
    +
    //script:script_file
    +
    +
    +

    The //header_unit_files: directive specifies any header files that should +be compiled via --create_header_unit and passed to the test invocation via +a --header_unit mapping.

    +

    The //module_files: directive specifies any module files to be compiled for +the test.

    +

    In most cases these files should be listed without a prefix; such files are +presumed to be module interface source files and will be compiled with the +--module_interface flag to generate both an IFC and a .obj file for +the module source file.

    +

    If given the obj: prefix it’s assumed the IFC file is already present and +only the .obj file should be compiled.

    +

    If given the internal: prefix this is a module implementation unit that an +IFC file should be force-generated for (this is unusual). These module +source files are compiled under the --module_internal_partition flag to +generate both an IFC and a .obj file.

    +

    Note that when testing modules in a compiler emulation mode (e.g., with +--gnu_version=150100 added to //options_all:), the --modules +option must also be specified: emulation modes disable the module keywords +by default to match the emulated compiler (no version of g++ enables them +without -fmodules-ts). For example:

    +
    //options_all:--c++20 --gnu_version=150100 --modules
    +
    +
    +

    See the modules/eifc/modules/import-function-gnu and +modules/eifc/modules/export-float16-gnu tests for examples.

    +

    If //script: is specified, that script is executed instead of any other +commands. In general, the test type does not matter for script files except +for checking the return code. For example, a cp test will expect a zero +return code, while a cn will expect a non-zero. The script will be passed +command-line arguments in the same way that the compile command would.

    +
    +
    +

    26.1.3. Advanced Concepts#

    +

    The directives are processed in the following sequence:

    +
      +
    • those specified in $TEST_ROOT/.run_test_flags

    • +
    • (for multi-file tests) the flags.txt file in the directory of the test

    • +
    • those specified at the start of the test file

    • +
    +

    In some cases later directives overwrite earlier ones (e.g., //type:). +In other cases, a list of the specified values is accumulated (in the order in +which the various lists are specified above). The directives for which the +values are accumulated are:

    +
      +
    • options

    • +
    • options_all

    • +
    • match_regex

    • +
    • linker_options

    • +
    • execution_args

    • +
    • require

    • +
    • header_unit_files

    • +
    • module_files

    • +
    +

    Compile tests are processed through eccp -c. Runtime tests are +compiled and linked using eccp. Compile and link tests are also +compiled and linked using eccp, however a ln test is expected to +return a non-zero status from eccp where a rn test is expected to +return a zero status from eccp and a nonzero status when the program is +executed. If the //eccp_command: directive is used, the command +specified is used instead of the eccp command.

    +
    +
    +
    +

    26.2. Testing Tools#

    +

    There are two primary tools for testing, edgy and edg-run-test. +Both of these tools rely on the same internal edgtest Python library, +they just provide a different interface to it.

    +

    In most cases edgy is the preferred testing tool as it’s designed for +large-scale testing. However, when authoring a new test edg-run-test +can be a great way to get immediate feedback.

    +
    +

    26.2.1. edgy#

    +

    Usage information:

    +
    usage: edgy [-h] [-c RUN_CONFIGS] [--runs-dir TEST_RUNS_DIRECTORY]
    +            [--run-timestamp TEST_RUN_TIMESTAMP] [-j JOB_COUNT] [-T TIMEOUT_SECONDS]
    +            [-A] [-D] [-E] [-M] [-R] [-n MAX_FAIL_COUNT] [--pick PICK_COUNT]
    +            [--disp-run-dir] [-W] [--crash-avoidance] [--no-flakey-tests]
    +            [--replay {all-failing,output-mismatch,regress,unexpected}]
    +            [--slow-tests NUM_SLOW_TESTS_REPORTED] [--fully-random-order]
    +            [--cmd] [--verbose] [filters]
    +
    +EDG test runner.
    +
    +positional arguments:
    +  filters               the test filter to apply; "all" for all suites
    +
    +options:
    +  -h, --help            show this help message and exit
    +  -c, --config RUN_CONFIGS
    +                        the run configurations to apply
    +  --runs-dir TEST_RUNS_DIRECTORY
    +                        override the directory where tests runs are stored
    +  --run-timestamp TEST_RUN_TIMESTAMP
    +                        override the timestamp when creating a new test run (does
    +                        not apply to replay runs)
    +  -j, --jobs JOB_COUNT  the number of concurrent jobs
    +  -T, --timeout TIMEOUT_SECONDS
    +                        the number of seconds to wait for tests before killing them
    +                        (0 to disable)
    +  -A                    include slow tests (marked by an "_" prefix)
    +  -D, --debug-failures  print debug commands for failures
    +  -E, --no-expectations
    +                        disable expectations
    +  -M, --meticulous      disable faster mode (on by default) and run all expensive
    +                        checking
    +  -R, --regress         silence non-regressive changes
    +  -n, --max-failure-count MAX_FAIL_COUNT
    +                        the maximum number of failures
    +  --pick PICK_COUNT     the maximum number of tests to run (this option implies
    +                        --fully-random-order)
    +  --disp-run-dir        print the directory where the run output is being stored
    +  -W, --record          record tests
    +  --crash-avoidance     avoid tests that are likely to crash the compiler (this option
    +                        also implies --no-flakey-tests)
    +  --no-flakey-tests     do not run tests that are known to be flakey
    +  --replay {all-failing,output-mismatch,regress,unexpected}
    +                        rerun tests from the last run
    +  --slow-tests NUM_SLOW_TESTS_REPORTED
    +                        the number of the slowest tests to report
    +  --fully-random-order  completely randomize test execution order (this can help lower
    +                        system pressure by mixing more "intensive" test suites with
    +                        less intensive test suites)
    +  --cmd                 print all run test commands
    +  --verbose             enable verbose mode
    +
    +
    +
    +

    26.2.1.1. Setup Requirements#

    +

    edgy was designed to be usable from any directory. To facilitate this, +the EDG_TEST_HOME environment variable must be set to the directory +where the tests subdirectory and .edgy/config.json are.

    +

    In the typical configuration, CPFE should be set to the C-generating +back end binary being tested and CPFE_CP should be set to the +C++-generating back end binary being tested.

    +
    +
    +

    26.2.1.2. Filtering#

    +

    `edgy works off of one or more (comma-separated) filters. These +filters are typically test suite names, e.g.,

    +
    edgy regressions,stdlib
    +
    +
    +
    +
    26.2.1.2.1. Filter Reduction#
    +

    These can be reduced by adding addition path components. For instance, if +you want to run the tests in the modules directory of the +regressions test suite, you can do so via

    +
    edgy regressions/modules
    +
    +
    +

    You can also elaborate on this to dive down to a single test, e.g., +regressions/foo.sft.cpp:

    +
    edgy regressions/modules/foo.sft.cpp
    +
    +
    +
    +
    +
    26.2.1.2.2. Special Filters#
    +

    There are also a couple of special filters, the primary one is all +(which simply means all the test suites edgy knows about), e.g.,

    +
    edgy all
    +
    +
    +

    An additional very useful one is the mine filter. This filter is +configured by setting the EDGY_MY_TESTS environment variable to a +comma-separated list of test suites. For instance, if concerned primarily +with regressions and the stdlib impact in your work, this might be +a reasonable use:

    +
    export EDGY_MY_TESTS=regressions,stdlib
    +edgy mine
    +
    +
    +

    Note that special filters cannot be reduced (e.g., edgy mine/xyz +does not work).

    +
    +
    +
    26.2.1.2.3. Negative Filters#
    +

    Negative filters can be applied as well. These start with a ! and are +applied as a reduction of positive filters, e.g.,

    +
    edgy regressions,!regressions/modules
    +
    +
    +

    Here we’re running all tests in the regressions suite except for the +tests in the modules subdirectory.

    +
    +
    +
    26.2.1.2.4. File-Loaded Filters#
    +

    Filters can also be loaded from a file:

    +
    $> cat my_filters.txt
    +regressions
    +!regressions/modules
    +$> edgy @my_filters.txt
    +
    +
    +

    The above is logically equivalent to the above negative filter example (the +filters are just spelled out in a file on a line-separated basis).

    +

    This feature is particularly useful for working with fine-grained lists of +tests (such as edgy’s .elog files).

    +
    +
    +
    +

    26.2.1.3. Live Feedback#

    +
    +
    26.2.1.3.1. Test Run Status#
    +

    Progress reporting is provided by a (fairly rapidly) updating status line:

    +
    588/83,651 (0%) in 00:00:04 ~127/sec (00:10:54 remaining)
    +
    +
    +

    This status line shows:

    +
    <number of completed tests>/<number of tests to run total>
    +(<percentage of tests completed>%) in <elapsed time>
    +~<tests per second>/sec
    +(<estimated time remaining at current test per second> remaining)
    +
    +
    +
    +
    +
    26.2.1.3.2. Problem Reporting#
    +

    Any encountered problems are reported above the status line as they’re +discovered.

    +

    A completed run might look something like:

    +
    - regressions/foo.sft.cpp cp::ABORT:
    ++ regressions/foo.sft.cpp cp::PASS--OUTPUT MISMATCH:
    +
    +
    +

    “+” is used to indicate an unexpected problem, while “-” is used to indicate an +unsatisfied expectation (the above is an example of what might happen if there +was a regression resulting in a crash that has been resolved).

    +

    When multiple configurations are in use, the configuration is specified in +parens prior to the test “name”, e.g.:

    +
    + (edg_x86_64) regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH:
    ++ (edg_x86_64_cp) regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH:
    +
    +
    +

    edgy also will print “commentary” in this output without using a marking +character. These are used to report extra information that might be +good to know (e.g., that a particular test ran very slowly), e.g.,

    +
    + regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH:
    +  Consider marking regressions/foo.sft.cpp slow (Took: 00:01:04)
    +
    +
    +
    +
    +
    26.2.1.3.3. Test Termination#
    +

    edgy supports early termination when it receives SIGINT (Ctrl + C +in most shells) or SIGTERM. Early termination will make edgy quickly +terminate all spawned process groups (and thus their processes). Any tests +terminated in this fashion will be reported to the user with an “X” prefix, +e.g.,

    +
    X regressions/foo.sft.cpp
    +X stdlib/bar/test.mft.cpp
    +X regressions/baz/test.mft.cpp
    +
    +
    +

    Note: This is particularly helpful both for killing (and finding) tests that +are stuck in an infinite loop if your tests aren’t terminating.

    +
    +
    +
    +

    26.2.1.4. Failure Debug Mode#

    +

    edgy has a failure debug mode (enabled via -D or +--debug-failures) that enables additional “commentary” for failed +tests, aimed at debugging issues with said tests.

    +

    For exposition purposes the below section uses <TEST_ROOT> for the path +represented by EDG_TEST_HOME and <BUILD_BIN> for the location of +the directory containing the front end cpfe binary. Additionally \ +lines have been added to wrap lines.

    +

    As an example, commentary from this option typically looks something like:

    +
    RUN_TEST_DEFAULT_CONFIG="edg_x86_64" LC_ALL="C" CDISP="<BUILD_BIN>" \
    +  edg-run-test -o \
    +  <TEST_ROOT>/runs/2026.06.25-17.14.55/edg_x86_64/regressions
    +  --driver-debug --faster -t \
    +  <TEST_ROOT>/tests/regressions \
    +  <TEST_ROOT>/tests/regressions/foo.sft.cpp
    +
    +
    +

    This can be copied verbatim and when executed will print something like +the following:

    +
    Source file clone:
    +cd $(clone-test-to-tmp <TEST_ROOT>/tests/regressions/foo.sft.cpp)
    +<BUILD_BIN>/cpfe -DTEST_NUMBER=1 --c++20 Test_name.c
    +
    +
    +

    This combined information can then be used to set up a test directory, and a +debug command, following the general setup:

    +
    <make test directory>
    +<set environment variables> <debugger command> <front end invocation>
    +
    +
    +

    Using the above sample output, that would look something like:

    +
    cd $(clone-test-to-tmp <TEST_ROOT>/tests/regressions/foo.sft.cpp)
    +RUN_TEST_DEFAULT_CONFIG="edg_x86_64" LC_ALL="C" CDISP="<BUILD_BIN>" \
    +  gdb --args <BUILD_BIN>/cpfe -DTEST_NUMBER=1 --c++20 Test_name.c
    +
    +
    +

    This will quickly give you a debugger invocation (modulo any bugs/missing +features for test directory setup driver debug) that should exactly reproduce +the circumstances that resulted in edgy seeing what it saw.

    +

    Note that many tests may not have a Source file clone line reported by +the test executor. In these cases it’s perfectly safe to omit this (i.e., +<make test directory> may not always be a part of the pattern).

    +
    +
    +

    26.2.1.5. Regress Mode#

    +

    edgy has a test regression reporting mode (enabled via -R or +--regress). This is aimed at reporting only those tests whose status +changed to something worse and is particularly useful for noisy tests where +there may be lots of valid --OUTPUT-MISMATCHs. The severity ranking +used to determine what’s “worse” is represented in the following table:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Test Status

    Severity Ranking

    PASS

    0

    FAIL

    1

    BADC

    1

    CATASTROPHE

    2

    ABORT

    3

    RUNTIME ABORT

    3

    +
    +

    As an example, a FAIL to an ABORT will be reported, but an +ABORT to a FAIL will not be reported. Similarly, FAIL to +BADC (or vice versa) will not be reported.

    +
    +
    +

    26.2.1.6. Failure Limiting#

    +

    edgy has a failure limit mode (enabled via -n MAX_FAIL_COUNT or +--max-failure-count MAX_FAIL_COUNT, where MAX_FAIL_COUNT is an +integer) that stops test execution after MAX_FAIL_COUNT tests have +been reported as problematic. This is compatible with regression mode, and +will only count reported regressions.

    +
    +
    +

    26.2.1.7. Re-record Mode#

    +

    edgy has a mode for updating test recordings and patching expectations +in the process (enabled via -W or --record).

    +

    As this mode is intended for usage only to update output, edgy does not +check expectations or otherwise report test status during re-recording. +The process for using re-record mode is something akin to the following:

    +
      +
    1. Run the tests

    2. +
    3. Review the changes

    4. +
    5. Determine if any tests’ expectations or output need to be updated

    6. +
    7. Rerecord the tests that need to be updated (e.g, +edgy -W regressions/foo.sft.cpp)

    8. +
    +

    When re-recording multiple configurations, the default configuration’s +expectations are updated first. The expectations of the other configurations +are then recorded as their differences from the default configuration’s (see +Expectation Inheritance).

    +
    +
    +

    26.2.1.8. No Expectations Mode#

    +

    edgy has a no expectations mode (enabled via -E or +--no-expectations) which as the name implies disables expectations. +This is useful for seeing true test statuses (i.e., seeing all failures, +including failures that were previously marked as expected).

    +
    +
    +

    26.2.1.9. No Flakey Tests Mode#

    +

    edgy has a “no flakey tests” mode (enabled via --no-flakey-tests) +which, as the name implies, skips known flakey tests. This is useful for +avoiding problematic tests that are known to regularly misdiagnose problems +in your configuration.

    +

    For this to work, the configuration in use must have the flakey tests +listed in the $EDG_TEST_HOME/flakey-tests directory. For example, to +mark regressions/baz/foo.sft.cpp flakey in the foo-bar +configuration, one would add a file +$EDG_TEST_HOME/flakey-tests/foo-bar/regressions.txt with the contents:

    +
    baz/foo.sft.cpp
    +
    +
    +

    Note: It’s recommended (but not required) to organize this file alphabetically +for easier maintenance.

    +
    +
    +

    26.2.1.10. Replay mode#

    +

    edgy has a mode for replaying a portion of the previous test run +(enabled via --replay). It’s important to note that the “runs” that +are replayed are the original “run” not a “replay”, i.e., replay 2 is not +run against replay 1 but is run against the last run that wasn’t a replay +run.

    +

    Replay mode is compatible with the normal edgy options (e.g., filters). +Replay mode itself supports the following sub-options:

    +
    + + + + + + + + + + + + + + + + + + + + +

    Option

    Description

    all-failing

    All tests without PASS status/all tests that +appear in the previous run’s log files.

    output-mismatch

    All tests with OUTPUT MISMATCH status (including +tests that are otherwise passing).

    regress

    All tests that had a status regression vs the current +configuration’s expectations (see the +Regress Mode section for more information +about status regressions).

    unexpected

    All tests that are reporting a status differing from +the current configuration’s expectations.

    +
    +

    Replay results are stored in the last test execution’s run output directory +(typically tests/runs/some-timestamp) in their own replays +subdirectory. Every time a replay is performed a new subdirectory will be +created within the respective replays subdirectory for the replay output. +This gives replay runs a few special characteristics:

    +
      +
    • Test selections are stable across all replay runs (in other words, if you +have run “T” you’re replaying, replay “{N, N + 1, …}” will not affect each +other’s output/test selections).

    • +
    • Replays can be run many times without resulting in edgy’s test run +cleanup deleting anything.

    • +
    +

    As a visual aid, this is the expected directory structure for a run with two +replays in the runs directory:

    +
    .
    +├── 2026.06.07-16.19.15
    +│   ├── replays
    +│   │   ├── 1
    +│   │   │   └── edg_x86_64
    +│   │   │       ├── regressions
    +│   │   │       │   ├── test-a.rt
    +│   │   │       │   ├── test-b.rt
    +│   │   │       │   └── test-c.rt
    +│   │   │       └── regressions.log
    +│   │   └── 2
    +│   │       └── edg_x86_64
    +│   │           ├── regressions
    +│   │           │   ├── test-a.rt
    +│   │           │   ├── test-b.rt
    +│   │           │   └── test-c.rt
    +│   │           └── regressions.log
    +│   └── edg_x86_64
    +│       ├── regressions
    +│       │   ├── test-a.rt
    +│       │   ├── test-b.rt
    +│       │   └── test-c.rt
    +│       └── regressions.log
    +...
    +
    +
    +
    +
    26.2.1.10.1. Replaying Failed Test#
    +

    As an example, consider you’ve run a test suite:

    +
    edgy regressions
    +
    +
    +

    This then revealed 5 of the 500 tests are failing. You then make a change, and +then want to run those 5 tests again to see if you’ve fixed the problem:

    +
    edgy --replay all-failing
    +
    +
    +

    This runs only the 5 failing tests.

    +
    +
    +
    26.2.1.10.2. Replaying Subset of Failed Test#
    +

    As an example, consider you’ve run a test suite:

    +
    edgy regressions
    +
    +
    +

    This then revealed 50 of the 500 tests are failing, but you’re only +interested in the 10 tests in regressions/foo. You then make a change, +and then want to run those 10 tests again to see if you’ve fixed the +problem:

    +
    edgy --replay all-failing regressions/foo
    +
    +
    +

    This runs only the 10 failing tests.

    +
    +
    +
    26.2.1.10.3. Replaying Mismatched#
    +

    As an example, consider you’ve run a test suite:

    +
    edgy regressions
    +
    +
    +

    This then revealed 5 of the 500 tests have an output mismatch due to changes +you made. You review the changes, and decide you want to rerecord these +tests:

    +
    edgy --replay output-mismatch -W
    +
    +
    +

    This runs only the 5 tests with the output mismatch, rerecording them and +updating expectations in the process.

    +
    +
    +
    26.2.1.10.4. Replaying Regressions#
    +

    As an example, consider you’re working with volatile code that’s failing many +tests, and you’re using regression mode to focus down the reported tests:

    +
    edgy -R regressions
    +
    +
    +

    This then revealed 5 of the 500 tests are regressing while 50 are unexpected +status changes, and 200 are failing. The other replay modes will not help you +realistically narrow down the set of test output being reviewed. This is where +regress replays shine:

    +
    edgy --replay regress
    +
    +
    +

    This runs only the 5 tests that actually have regressive status changes, +allowing you to evaluate much more effectively whether your iterative +changes are improvements.

    +
    +
    +
    26.2.1.10.5. Replaying Unexpected#
    +

    As an example, consider you’ve run a test suite:

    +
    edgy regressions
    +
    +
    +

    This then revealed 5 of the 500 tests differ from their expected status or +otherwise have an output mismatch. You review the changes, and decide you want +to rerecord these tests:

    +
    edgy --replay unexpected -W
    +
    +
    +

    This runs only the 5 tests, rerecording them and updating expectations in the +process.

    +
    +
    +
    +

    26.2.1.11. Slow Test Reporting#

    +

    edgy has a slow test reporting mode (enabled via --slow-tests +NUM_SLOW_TESTS_REPORTED, where NUM_SLOW_TESTS_REPORTED is an integer) +that reports the NUM_SLOW_TESTS_REPORTED slowest test executions. This +is compatible with all modes (with the exception of re-record mode which does +not record the necessary timings).

    +
    +
    +

    26.2.1.12. Verbose Mode#

    +

    edgy has a verbose mode (enabled via --verbose) that enables +printing of additional details. Verbose mode provides additional +information about environment variables, what cleanup actions are being +taken, and remarks for failure debugging are turned on for every tests +(regardless of its pass/fail status). This can be useful for initial +setup, or when attempting to get a debug invocation for one or more test(s) +that aren’t currently failing.

    +
    +
    +

    26.2.1.13. Copying Tested Binaries#

    +

    By default edgy copies the executables being tested for each test run. +This allows for (some degree of) working on the front end while testing +occurs as updated binaries will not impact testing.

    +

    If the environment variable EDG_TEST_NO_COPY_X is set or +TEST_X (where X is the environment variable corresponding +to the tested binary – typically CPFE or CPFE_CP) is set, this +functionality is disabled.

    +
    +
    +

    26.2.1.14. Test Run Cleanup#

    +

    If the environment variable EDG_TEST_RUNS_KEPT is set to a valid +integer N (e.g., 10), edgy will only keep the last N entries in the +run directory.

    +

    Note: This does not take into account directory names, it simply deletes +directories in the runs directory based on their modification time. +Make sure you don’t have any subdirectories in the runs directory that +should be kept around before setting this environment variable.

    +
    +
    +

    26.2.1.15. Multi-Configuration Support#

    +

    edgy, as previously noted, has support for simultaneous testing of +different configurations. The configurations that can be tested, as well as +the default set of configurations to test, is configured in the +.edgy/config.json file.

    +

    To manually specify which configurations to run, the -c flag can be +used with a comma-separated list of configurations, e.g.:

    +
    edgy -c edg_x86_64,edg_x86_64_cp regressions
    +
    +
    +

    This will run the regression test suite, in both the edg_x86_64 and +edg_x86_64_cp configurations (which is also the default as edgy is +typically configured).

    +
    +
    26.2.1.15.1. Expectation Inheritance#
    +

    Test output recordings and test expectations are both inherited from the +default configuration (edg_x86_64 unless RUN_TEST_DEFAULT_CONFIG says +otherwise). For expectations, each configuration other than the default +configuration starts from the default configuration’s expectations +(tests/expectations/<default>/<suite>.log), and its own expectations file +(tests/expectations/<config>/<suite>.log) only needs to hold the +differences. For each test (and test case):

    +
      +
    • a line in the configuration’s own file is the expectation, otherwise

    • +
    • a line in the default configuration’s file is the expectation, otherwise

    • +
    • the test is expected to pass.

    • +
    +

    As the absence of a line means the default configuration’s expectation applies, +a configuration that passes a test that the default configuration fails +records an explicit PASS line (e.g., +regressions/foo.sft.cpp:fp:-DTEST_NUMBER=1:PASS:) to say so. Lines in a +configuration’s own file that are the same as the default configuration’s +are redundant, and are removed the next time the configuration is re-recorded. +A configuration with an empty (or missing) expectations file expects exactly +what the default configuration does.

    +
    +
    +
    +
    +

    26.2.2. edg-run-test#

    +

    Usage information:

    +
    usage: edg-run-test [-h] [-d] [-r] [--driver-debug] [--faster] [-q] [-t TOP_DIR]
    +                    [-o OUTPUT_DIR] test_files [test_files ...]
    +
    +EDG Python based test executor.
    +
    +positional arguments:
    +  test_files            the paths to the test files to run
    +
    +options:
    +  -h, --help            show this help message and exit
    +  -d, --debug           keep the output files
    +  -r, --record, --silent-record
    +                        update the expected test output to be the output from this run.
    +  --driver-debug        add --driver_debug to the test's command line arguments. The
    +                        resulting additional output will be printed to stdout with the
    +                        original test file replacing the generic name. This makes the
    +                        underlying command more easily accessible so that it may be
    +                        more easily fed to a debugger (e.g., gdb) or checked for
    +                        correctness.
    +  --faster              enable command line flags that might speed up the compilation
    +                        of the test files
    +  -q                    only display log output for errors
    +  -t, --top-dir TOP_DIR
    +                        the path to the contextually "top" directory
    +  -o OUTPUT_DIR         the path where output will be stored
    +
    +
    +

    edg-run-test is a considerably simpler tool than edgy. Consider +the following edgy command:

    +
    edgy regressions
    +
    +
    +

    Assuming EDG_TEST_HOME is /edg/tests, the corresponding +edg-run-test invocation would be approximately the following:

    +
    edg-run-test -t /edg/tests/tests/regressions \
    +  /edg/tests/tests/regressions/**/*.sft.c   \
    +  /edg/tests/tests/regressions/**/*.sft.cpp \
    +  /edg/tests/tests/regressions/**/*.mft.c   \
    +  /edg/tests/tests/regressions/**/*.mft.cpp
    +
    +
    +

    Here TEST_ROOT is specified by -t so that any .run_test_flags file +can be correctly processed.

    +

    Of note, edg-run-test does not support expectations or have a notion of +configuration, so this will report the status of all tests regardless of +expected output.

    +

    Additionally, by default all statuses are reported; -q can be used to +reduce the output to something closer to what’s given by edgy.

    +

    The tested binary is the binary found at the CPFE environment variable by +default. However, alternative environment variables can be tested by +specifying the PRIMARY_CPFE environment variable to a different environment +variable (e.g., CPFE_CUSTOM).

    +

    The occasional advantage of edg-run-test over edgy is simplicity. +It’s possible to author a new test outside of the test tree and quickly +execute and iterate on the test before moving the file(s) to include the +test in a test suite.

    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/trans_unit/index.html b/dev/doc/trans_unit/index.html new file mode 100644 index 0000000..c3a1410 --- /dev/null +++ b/dev/doc/trans_unit/index.html @@ -0,0 +1,812 @@ + + + + + 17. Multiple Translation Units - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    17. Multiple Translation Units#

    +

    A translation unit is a set of source files translated as a unit, comprising +a primary source file and all of the source files included by that file. +Sometimes, the front end has to deal with more than one translation unit at a +time:

    +
      +
    • +
      When exported templates are used, the source file in which a template is +defined may be different than the one in which is it used. The front end +has to read in a translation unit for the defining source file while +retaining the translation unit for the referencing source file, and then +perform the instantiation in a merged context that includes both +translation units. Additional translation units may be read in for +instantiations of other templates.
      +
      +
    • +
    • +
      When COMPILE_MULTIPLE_TRANSLATION_UNITS is TRUE, multiple files can be +specified on the command line for the front end. Each file is read in turn +as the primary file of a translation unit.
      +
      +
    • +
    +

    In both these cases, the first translation unit read is called the primary +translation unit, and any translation units read after the first are called +secondary translation units. The translation units are kept separate within +the front end. They have separate intermediate language (IL) trees and +conceptually separate symbol tables. After all translation units have been +processed, the IL for each secondary translation unit is merged into the IL for +the primary translation unit. Duplicate copies of entities that appear in more +than one translation unit are eliminated during the merge, and errors are +issued for conflicts between entities that have incompatible definitions in +different translation units. The final merged primary IL tree is then passed +to a back end, looking much like an IL tree from a simple one-translation-unit +compilation.

    +

    The process of translating a primary translation unit and zero or more +secondary translation units into an IL tree is called a compilation.

    +

    Note that when COMPILE_MULTIPLE_SOURCE_FILES [1] is TRUE and the front +end is given several source file names on the command line, each translation +unit is treated as a separate compilation. It is read separately and its IL +tree is written to a separate IL file. No merging is done on the translation +unit IL trees, and no checking for matching between translation units. There +are no secondary translation units in this mode (except those that might be +brought in for exported templates).

    +

    The principal source files of the front end involved in +multiple-translation-unit processing are trans_unit.c, trans_unit.h, +trans_corresp.c, trans_corresp.h, trans_copy.c, and +trans_copy.h.

    +
    +

    17.1. Initialization, Termination, and Keeping Translation Units Separate#

    +

    By and large, the code in the front end is written as if there is only one +translation unit. Global variables and tables indicate the state at the +current point in the input, which is a particular point within a single +translation unit. For the handling of multiple translation units, this global +state must be carefully managed, and updated when one switches between +translation units.

    +

    The process of initialization in the front end is broken down into three parts:

    +
      +
    • +
      Initialization that is done only once in the entire front end invocation. +Initialization routines in this class have names that have the suffix +“_one_time_init”.
      +
      +
    • +
    • +
      Initialization that is redone for each compilation. Initialization +routines in this class have names that have the suffix “_init”.
      +
      +
    • +
    • +
      Initialization that is redone for each translation unit. Initialization +routines in this class have names that have the suffix +“_trans_unit_init”.
      +
      +
    • +
    +

    It can be seen that in COMPILE_MULTIPLE_TRANSLATION_UNITS mode, the front +end does one-time initialization, compilation initialization, and then, for +each source file specified on the command line, translation unit +initialization. In COMPILE_MULTIPLE_SOURCE_FILES mode, on the other hand, +the front end does one-time initialization and then, for each source file +specified on the command line, compilation initialization and then +translation-unit initialization. See the top-level routines in fe_init.c.

    +

    Similarly, termination is done in several parts:

    +
      +
    • +
      pop_scope for the file scope does necessary processing at the end of +the file scope for a translation unit.
      +
      +
    • +
    • +
      translation_unit_wrapup does necessary processing at the end of a +translation unit.
      +
      +
    • +
    • +
      fe_wrapup does necessary processing at the end of a compilation. This +includes calling template_and_inline_function_wrapup, which does most +template instantiation.
      +
      +
    • +
    • +
      wrap_up_file_scopes finishes up each translation unit and merges the +IL.
      +
      +
    • +
    +

    The instantiation process (during the third step above) can bring in additional +secondary translation units for exported templates, which go through their own +initialization, reading/parsing, and termination phases. Eventually, all +necessary templates have been instantiated, which means all necessary +translation units have been created and processed, and wrap_up_file_scopes +is called.

    +

    The source code for a secondary translation unit is read, and the corresponding +IL is generated, all at one time. There is no switching between translation +units while the source code is being read. Once a secondary translation unit +has been read, additional processing may be done in that translation unit that +will add more IL to it, but that is done through template instantiations, and +never by going back and reading more source code. Likewise, instantiations can +add additional IL to the primary translation unit, but no additional source +code will be read into it.

    +

    A structure of type a_translation_unit contains information about a single +translation unit within a compilation, and the global variable +curr_translation_unit points to the entry for the translation unit that is +currently active. By calling switch_translation_unit, one can switch to a +different translation unit, i.e., make another translation unit the “active” +one. This is a relatively expensive process that changes the values of many +global variables to match the new translation unit.

    +

    How does switch_translation_unit know what to update? It updates the +variables recorded by calling register_trans_unit_variable during one-time +initialization. Variables registered in that way are known as trans unit +variables, and their per-translation-unit values are recorded in a data +structure associated with the a_translation_unit structure: They are saved +when the translation unit becomes inactive, and restored when the translation +unit is reactivated. Certain values that need to be accessed efficiently even +when the corresponding translation unit is not the active one are stored +directly in the a_translation_unit structure (e.g., +file_scope_pointers_block), or are pointed to by fields in that structure +(e.g., module_id_ptr; variables of this kind are registered via +register_trans_unit_variable_with_field).

    +

    process_translation_unit is the driver for the reading/parsing of a single +translation unit.

    +

    Some data structures and numbering sequences are deliberately shared across +multiple translation units. The source file data structure and source line +sequence numbers, for example, are shared, so that a source position consisting +of a sequence number and column number is unique across the entire compilation. +Likewise, the symbol table and scope number sequence is shared, which ensures +that scopes always have unique numbers, and therefore that one can do a lookup +in the symbol table by scope number and find only entities from a single scope +from a single translation unit.

    +
    +
    +

    17.2. Memory Regions and Intermediate Language#

    +

    Each secondary translation unit has its own set of IL memory regions, one for +its file scope and one for each top-level function definition. The global +variable file_scope_region_number indicates the region number of the file +scope of the current translation unit, whether it is a primary or secondary +translation unit.

    +

    The function alloc_primary_file_scope_il allocates space in the primary +translation unit IL even if the current translation unit is a secondary +translation unit.

    +

    The macro is_secondary_trans_unit returns true for an IL entry allocated in +a memory region that is part of a secondary translation unit. The global array +trans_unit_for_scope maps a scope number back to a pointer to the +translation unit that contains that scope. Note that when IL is moved from +secondary translation units to the primary IL at the end of the compilation, +the value of is_secondary_trans_unit will change, but that of +trans_unit_for_scope stays as it was.

    +

    The front end memory region is shared across all translation units.

    +
    +
    +

    17.3. Translation Unit Correspondences#

    +

    Each IL entry with external linkage is assigned to a correspondence set +containing all of the related IL entries from different translation units, +i.e., all the entries that represent the same entity. So, for example, all +external global variables called “i” will be in one correspondence set.

    +

    A correspondence set is represented by an entry of type +a_trans_unit_corresp, which is allocated in front end memory (so it is not +really part of the IL). Each entry that is a member of the correspondence set +points to the appropriate a_trans_unit_corresp entry via the +trans_unit_corresp pointer in its source_corresp field. These pointers +are set when secondary translation units are processed, and therefore in a +compilation consisting only of a single translation unit the pointers will be +NULL and the correspondence-set entries will not be allocated. [2] For +entries without linkage, or with internal linkage, the trans_unit_corresp +pointer is always NULL.

    +

    IL entries of type a_base_class are also matched up in correspondence sets +and therefore contain a trans_unit_corresp pointer (though it is not part +of a source_corresp field in that case).

    +
    +
    +

    17.4. Canonical Entries#

    +

    In each correspondence set, one entry is chosen as the canonical entry, and +the canonical field in the a_trans_unit_corresp points to it. The +entry chosen as the canonical entry is an instance that contains the most +detailed information available about the entity: one with a definition if a +definition is available, and a specialization if both specialized and +unspecialized versions of a template instance are available. All other things +being e qual, an entry in the primary IL is chosen over one in a secondary +translation unit, because that means less copying later.

    +

    The canonical entry chosen can change as the compilation progresses. The first +instance seen will generally be chosen as the canonical entry, but it may be +replaced afterwards by a better choice from some other secondary translation +unit scanned later.

    +

    Note that it is possible for a class or namespace not to be the canonical entry +in its correspondence set while at the same time some of its members are the +canonical entries in their sets.

    +

    The macro canonical_il_entry_of can be used to fetch the address of the +canonical entry corresponding to a given entry. For an entry without linkage, +the entry itself is returned.

    +
    +
    +

    17.5. The Copy Address Pointer#

    +

    All IL entries have a prefix that contains various flags and numbers. IL +entries in the file scope of a secondary translation unit have, in addition, a +copy address pointer, which is set during the copy process to indicate the +address in the primary IL to which the entry should be copied or remapped.

    +

    For entries in correspondence sets, generally the canonical entry will be +copied to the primary IL and its copy address pointer will be set to the +address of the copy. The other members of the correspondence set will not be +copied, but their copy address pointers will be set to the same copy address so +that references to them can be remapped to the unique copy in the primary IL.

    +

    For entries not in correspondence sets, including non-declarative entries like +statement and expression nodes, no copy address is pre-assigned. When the +entry is encountered during the copy process, it is copied to the primary IL +and the copy address pointer is set to the address of the copy. All references +to the entry encountered thereafter are remapped to the established copy +address.

    +

    In some cases, entries in the secondary IL are “merged” into the primary IL. +This is necessary, for example, if the canonical entry for a correspondence set +is in a secondary translation unit but there is also a member of that +correspondence set in the primary IL. The address in the primary IL must be +preserved (because there are references to it from elsewhere in the primary IL, +which will not be rewritten), so the canonical entity must be copied on top of +the existing primary IL entry. In such cases, the copy address pointer is used +to form a two-element list: The copy address pointer of the entry in the +secondary translation unit points to allocated space for a copy (also in the +secondary translation unit IL), and the copy address pointer of that copy entry +points in turn to the address of the existing entry in the primary IL. The +copy process copies the original entry to the intermediate copy, with pointer +remapping, and then later overwrites the primary IL entry, carefully preserving +certain information (e.g., next-on-list pointers).

    +

    The macro trans_unit_copy_address_of gives access to the correspondence +pointer of an IL entry (for both fetching and setting). The macro +checked_trans_unit_copy_address_of does the same thing, but also checks +that the entry pointer provided is actually in the file scope of a secondary +translation unit.

    +
    +
    +

    17.6. Correspondence Checking#

    +

    The code in trans_corresp.c establishes correspondences between entities in +a secondary translation unit and similar entities in the primary translation +unit and in other secondary translation units. It sets the correspondence +pointer of IL entries to indicate the correspondences found. While +establishing these correspondences, it checks that linked entities are in fact +compatible, and issues errors when they are not. The entities that have +correspondences set in this way are types, routines, variables, fields, +namespaces, base classes (i.e., a_base_class entries), using-declarations +appearing in class scopes, and templates (including template instances).

    +

    Correspondence checking can occur in three stages of the compilation:

    +
      +
    • +
      Built-in types have their correspondences set by record_builtin_type as +soon as they are created.
      +
      +
    • +
    • +
      When a translation unit has been processed, +set_trans_unit_correspondences is called from +translation_unit_wrapup to establish correspondences for the entities +that were created in that translation unit. The global variable +correspondence_checking_underway is TRUE during this stage (and only +during this stage); after that correspondence_checking_done is TRUE.
      +
      +
    • +
    • +
      The correspondence checking process is notified of every template +instantiation by calls to record_instantiation. When this occurs in a +translation unit after its translation_unit_wrapup call, the +correspondence pointer is established for the new instantiation. The +instantiation process also notifies the correspondence checking process of +template instantiations being completed, through calls to +establish_class_instantiation_corresp, +establish_function_instantiation_corresp, +establish_variable_instantiation_corresp, +establish_block_extern_function_correspondence, +establish_block_extern_variable_correspondence and +establish_friend_type_correspondence.
      +
      +
    • +
    +
    +

    17.6.1. Finding Corresponding Pairs#

    +

    Several different mechanisms are used to find an entity in another translation +unit that corresponds to a given entity:

    +
      +
    • +
      For named entities in namespace scope, the symbol table is used. The +search process simply traverses the list of symbols attached to the symbol +header of the entity for which a correspondence is being searched. This is +done in functions with the prefix find_ (e.g., +find_type_correspondence).
      +
      +
    • +
    • +
      For class members, we can rely on the fact that the lists of IL entities +representing the members should have their elements correspond on a +one-to-one basis. Hence no search is needed, although care must be taken +with compiler-generated members that may not appear in every translation +unit. This principle is implemented by +establish_trans_unit_correspondences_for_class. A similar process can +be used for enumeration constants.
      +
      +
    • +
    • +
      Correspondences for instantiations of templates are usually established +after the templates from which they are generated have been matched up. To +support the search for a matching instantiation, a field +all_instantiations was added to a_template_symbol_supplement. This +field is set only in the supplement for the canonical template entry and +points to a list of all the instantiation symbols for the template, +including those for corresponding templates in other translation units. +Some of the key functions manipulating this list are add_instantiation, +find_class_template_instantiation and +find_function_template_instantiation.
      +
      +
    • +
    • +
      Correspondences are also sometimes established between unnamed types. This +happens when matching up declarations of entities with linkage involving +unnamed types. For example:
      +
      +
      struct { float a, b; } *p, q; // Could appear in two translation units
      +
      +
      +
      +
      In such cases, the correspondence is first established for the entities +with linkage (variables or routines), and the correspondence between the +types is sought by comparing the two types using f_types_are_compatible +with the option TCF_SEEK_CORRESP.
      +
      +
    • +
    +
    +
    +

    17.6.2. Ordering Dependencies#

    +

    Determining whether two entities from different translation units correspond +may require that other correspondences are known. For example, suppose we have +two namespace scope functions f that are declared as

    +
    extern R N::f();
    +
    +
    +

    then the two must correspond if the entities denoted by N correspond, and +if that is the case the entities denoted by R must correspond too. The +ordering of corresponding checks must therefore be managed carefully.

    +

    To reduce the magnitude of this issue, correspondences are determined in two +steps. In the first step, correspondences are established: Only those +components of the entity that uniquely identify it are compared (e.g., the +entity’s name, its enclosing classes and namespaces, parameter types of +functions, etc.) and if they match the correspondence pointer is set. Some +diagnostics may be issued at this time. This process is mostly done in +functions with the prefix establish_. In the second step, which starts +after all the correspondences for the translation unit have been established, +the correspondences are verified. This involves comparing the remaining +relevant attributes of entities that were found to correspond after the first +step; diagnostics are issued if the entities do not match. Most of the +verification work is done in functions with the prefix verify_. This +separation into two steps makes sure that in our example above the +correspondence for R has been established by the time it is needed.

    +

    To deal with other ordering issues, such as the requirement that the +correspondence of N be established in our example, the correspondence +checking process may be stacked. For example, while searching for a +correspondence for N::f above, another search for a correspondence for +N may be initiated. This is driven by calls to functions named +canonical_entity_entry_of where entity is one of +namespace, type, field, routine, variable or template. +If a correspondence was already established, these functions return the +requested canonical entry; if not, they first determine the correspondence by +calling determine_correspondence [3].

    +

    Other ordering issues sometimes arise because establishing a correspondence for +a template instantiation seemingly leads to infinite recursion. Such +situations are resolved in part by placing appropriate markers in the +all_instantiations list and in part by as much as possible establishing the +correspondences of all templates before attempting to match their +instantiations. To that end, the front end maintains a list of instantiations +whose correspondences are yet to be determined (the list is pointed to by +instantiations_to_process). That list is processed at appropriate times +(i.e., when the correspondences of the various templates have been found) by +calls to process_pending_instantiations.

    +

    Finally, we should note that the verification process always compares an entity +with its canonical counterpart. If a canonical entry (from an already +processed translation unit) is replaced by a new entry (from the current +translation unit) the former will need to be compared with the latter when all +the correspondences have been established in the current translation unit. +This is done in process_verification_list.

    +
    +
    +

    17.6.3. Debugging Facilities#

    +

    When the preprocessor symbol DEBUG is TRUE,a few facilities are provided by +trans_corresp.c to help identify problems during correspondence checking. +First, the command-line option “-d-trans_corresp” will cause a line of +output to be produced for each correspondence pointer being set (or cleared), +as well as for certain operations on the all_instantiations lists. Second, +the function db_corresp can be called from a debugger to examine the +correspondence of a given entity. Finally, the modification of a +correspondence pointer for a specific entity can easily be intercepted in a +debug environment where addresses are reproducible from run to run. To enable +this, set breakpoints on main and on corresp_intercept. Rerun the +front end and at the stop in main, set the static variable +trace_corresp_ptr to the address of the entity whose correspondence value +should be tracked: corresp_intercept will be called (triggering the +breakpoint) when that value is modified.

    +
    +
    +
    +

    17.7. Copying from Secondary Translation Units#

    +

    The code in trans_copy.c copies IL from a secondary translation unit to the +primary translation unit IL. It is run after elimination of unneeded entries +in the secondary translation unit, so it copies only entries that are actually +“needed.” It also runs after correspondence checking has established the +correspondences between externally-linked entities, so it does not copy entries +for which there is already an instance in the primary translation unit IL; for +such cases, all references to the entity are simply rewritten to point to the +primary IL instance.

    +

    The secondary translation unit IL consists of a file scope memory region and +zero or more function scope memory regions. The file scope memory region is +actually copied into the primary IL, via a tree walk, with duplicates +eliminated as indicated above. The function scope memory regions, on the other +hand, are not copied. Instead, they are walked to update pointers +appropriately, and then the memory region numbers are simply reassigned to the +primary IL.

    +

    The copy process is handled by copy_secondary_trans_unit_IL_to_primary, +which has five main phases:

    +
      +
    • +
      prepare_for_trans_unit_copy walks through the declaration lists of the +file scope of a secondary translation unit and its subscopes, and puts each +entry into one of four categories: (a) entries that should be copied to the +primary IL; (b) entries that should overwrite a corresponding entry in the +primary IL (e.g., a function in the secondary translation unit that has a +definition, where the corresponding function in the primary IL has only a +declaration); (c) entries that are in a correspondence set but are not the +canonical entry, which should be removed from the lists and discarded; and +(d) entries in a correspondence set that provide additional (minor) +information over what is present in the canonical entry, which should be +merged into the corresponding entry.
      +
      +
    • +
    • +
      copy_from_secondary_to_primary_IL uses the IL-walking routines to walk +the IL tree, copy over entries that need to be copied, and update pointers +so that the copied IL refers only to copies or to pre-existing entries in +the primary IL.
      +
      +
    • +
    • +
      copy_function_bodies_to_primary_IL processes the bodies of any +functions that are to be moved over, by using the IL-walking routines to +walk the IL tree and update pointers appropriately.
      +
      +
    • +
    • +
      finish_trans_unit_copy walks through the declaration lists again, and +links copied entries into the declaration lists of the primary IL. A +struct type copied over, for example, would be linked into the types list +of the primary scope of the primary IL. Variables, types, and routines +that must be merged into the corresponding entries are also copied onto the +corresponding entries at this point. This part of the processing runs +while switched into the primary translation unit. See also +finish_moved_entity_processing, which is similar but reaches all copied +or merged entities, even those from non-merged scopes.
      +
      +
    • +
    • +
      finish_processing_for_function_bodies calls +finish_function_body_processing for each copied function scope memory +region, and kicks off IL lowering for the function if it’s needed. This +part of the processing runs while switched into the primary translation +unit.
      +
      +
    • +
    +

    For entries that are being merged into the primary IL, the copy process sets +the il_lowering flag in the IL entry prefix to indicate merging rather than +copying. (The flag is available for this use because IL lowering is never done +on secondary translation units.) For merged entries, the copy process uses an +extra copy of the entity allocated in the secondary translation unit: The +entity’s copy address pointer points to the copy, whose copy address pointer +points to the corresponding entity in the primary IL. During the copy, the +original entry is copied to the copy space, and its pointers are remapped +there. This allows finish_trans_unit_copy later to have access to both the +original entity in the primary IL and the entity from the secondary translation +unit as updated for the copy. This is often important because some flags from +the two entries need to be merged.

    +

    The bodies of functions not copied over are eliminated, and likewise for the +initializers of variables. See clear_body_for_routine and +clear_variable_definition. Non-template functions and variables in +secondary translation units included only to get exported templates are turned +into external declarations, because the definition of those entities is put out +when the file is compiled as a primary translation unit.

    +

    The IL for secondary translation units can contain references to other +translation units. In some ways, the IL trees for all secondary translation +units have to be viewed as one big somewhat interconnected tree. For this +reason, each of the processing phases described above is done for all secondary +translation units before advancing to the next phase.

    +

    Part of the function of the copy process is to produce a primary IL tree that +contains no references to IL entries in secondary translation units, and this +is done by making sure that every entity copied over has only pointers that +refer to the primary IL. Sometimes, however, the instantiation of a template +that is defined in the primary translation unit introduces exactly the kind of +mixed-translation-unit IL that we are trying to avoid. To eliminate such +references, a pair of routines in trans_copy.c is called:

    +
      +
    • +
      mark_secondary_trans_unit_IL_entities_used_from_primary_as_needed +sweeps the primary translation unit IL and looks for references to +secondary translation unit entries. When it finds them, it marks the +secondary translation unit entries as needed so that they will be copied to +the primary IL when the secondary translation unit is copied.
      +
      +
    • +
    • +
      rewrite_secondary_trans_unit_IL_entity_pointers_used_in_primary sweeps +the primary translation unit IL after the secondary translation units have +been copied in, and looks for references to secondary translation unit +entries. When it finds them, it rewrites them either as references to the +corresponding entity in the primary translation unit (if there is one) or +it copies them and rewrites the pointer to the copy.
      +
      +
    • +
    +

    In some (relatively rare) cases, the merged IL produced by the copy process has +some type entries out of order on the type lists, where “out of order” is +defined according to the peculiar ordering required by the C-generating back +end so that it can generate compilable C code. +fix_type_list_ordering_problems is called after IL lowering to examine the +file-scope types list to look for ordering problems and to move types to fix +those problems. If there are no ordering problems (which is almost always the +case), the checking is done fairly quickly and efficiently.

    +
    +
    +

    17.8. Externalization of statics#

    +

    When a source file includes exported templates, it is possible that the +exported templates will refer to static entities in the file. Because the +template instances may be generated as part of the translation of other source +files, and be included in the object code for those files, it may be necessary +to refer to the static entities from another compilation. Therefore, the front +end externalizes all statics when a compilation includes exported templates. +This gives the static functions and variables external linkage and special +mangled names. This has a number of consequences, such as that static inline +functions become extern inline functions, which in some configurations makes +them instantiatable. See externalize_statics_for_exported_templates.

    +
    +
    +

    17.9. One-instantiation-per-object mode#

    +

    In one-instantiation-per-object mode, each instantiated template is put into a +separate “slice” of the IL, so that a back end can put out each instantiation +in a separate object file. The slices are defined by having a separate +“needed” flag for each slice (there’s an array of them attached to each IL +entity), and setting the slice-specific needed flags so that each slice +contains only the types, variables, etc. referenced by the template +instantiation in that slice.

    +

    When there are multiple translation units, the per-instantiation needed flags +are not maintained in the secondary translation unit IL. Once the IL is copied +to the primary IL, the flags are built up and maintained appropriately there.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/dev/doc/utilities/index.html b/dev/doc/utilities/index.html new file mode 100644 index 0000000..8a9649c --- /dev/null +++ b/dev/doc/utilities/index.html @@ -0,0 +1,656 @@ + + + + + 22. Utility Programs - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    22. Utility Programs#

    +

    Several utility programs are provided with the front end. Most of the utility +programs help with various link-time issues and are meant to be called from a +driver program or script. One (mk_errinfo) is a tool program used when +modifying the front end. The source for these programs is in the util +directory of the release structure.

    + +
    +

    22.2. edg_munch#

    +

    edg_munch is the EDG version of the USL munch utility. Its source +code is in edg_munch.c, with associated declarations in +edg_munch.h. edg_munch implements a lowest-common-denominator +method for getting global initialization and termination code executed on +systems that have no special support for that. [1]

    +

    edg_munch operates by reading as input a file that is the output of nm +run on a linked executable program. It looks for names beginning with +__sti__ or __std__, those being, respectively, initialization and +termination routines to be called at runtime. It generates a C program that +defines a data structure containing a list of pointers to the initialization +and termination routines. This generated program is then compiled and linked +in with the executable. The data structure is consulted at runtime by startup +code invoked from _main, and the routines on the list are invoked at the +appropriate times.

    +

    edg_munch takes only a single option: -u, if used, specifies whether +external names have an added leading underscore. The command-line option +selects the opposite of the configuration flag +TARG_EXTERNAL_NAMES_GET_UNDERSCORE_ADDED.

    +
    +
    +

    22.3. edg_decode#

    +

    edg_decode is a name demangler. The demangling code is in decode.c, +with associated declarations in decode.h. A main program that uses the +demangling code is provided in edg_decode.c.

    +

    edg_decode reads input from stdin and writes output to stdout. +Things that look like mangled names in the input are demangled. Everything +else is passed through unchanged. This makes the program suitable, for +example, as a filter for the output of a linker: error messages in general are +passed through unaltered, but mangled names are demangled. For example, using +the cfront-like ABI,

    +
    ld: Undefined symbol
    +   _f__Fif
    +
    +
    +

    is turned into

    +
    ld: Undefined symbol
    +   f(int, float)
    +
    +
    +

    Mangled names that are ill-formed in some way are also passed through +unchanged.

    +

    edg_decode usually has only a single option: -u, if used, specifies +whether external names have an added leading underscore. The command-line +option selects the opposite of the configuration flag +TARG_EXTERNAL_NAMES_GET_UNDERSCORE_ADDED. When the IA-64 ABI is used, +however, there is also a -g option, which selects the opposite of the +configuration flag DEFAULT_EMULATE_GNU_ABI_BUGS, which when TRUE extends the +demangling to cover some invalid mangled names put out by g++ 3.2 (and the EDG +front end, when configured to emulate those bugs).

    +

    The demangling is intended to work only on names of external entities. There +is some name mangling done for internal entities, or by the C-generating back +end, that this program does not try to decode.

    +

    In the cfront-like ABI, names that contain double underscores in the source +code will probably not be demangled correctly. This is an unfortunate +consequence of using a mangling scheme that is based on the one used by cfront. +The standard forbids use of double underscores in names in user code, reserving +such names for the implementation, so the effect of this shortcoming is +limited. Implementors should try to avoid using such names for entities with +external linkage. Double underscores at the beginnings of external names do, +however, work correctly. In the IA-64 ABI, a similar problem applies to names +that begin with “_Z”.

    +

    The name demangling is also available through a callable interface, which is +used in edg_prelink. See routine decode_identifier.

    +
    +
    +

    22.4. mk_errinfo#

    +

    mk_errinfo translates a text file containing error message codes and +associated descriptions into a pair of header files that represent this +information in a manner more readily used by the front end.

    +

    The invocation of the mk_errinfo is typically

    +
    mk_errinfo error_msg.txt error_tag.txt err_codes.h err_data.h
    +
    +
    +

    The error_msg.txt file defines the diagnostic messages generated by the +front end. This file, along with error_tag.txt, is processed by +mk_errinfo to generate the err_codes.h and err_data.h include +files. mk_errinfo may also be used to automatically generate the file used +to generate the Error Messages appendix of this manual.

    +

    When used to generate a documentation file, the invocation is typically one of +the following:

    +
    +
    +
    mk_errinfo -d error_msg.txt error_tag.txt generated.tex
    +
    mk_errinfo -mml error_msg.txt error_tag.txt generated.mml
    +
    mk_errinfo -rst error_msg.txt error_tag.txt generated.rst
    +
    +
    +

    generated.tex is the name of the generated output file containing the +documentation in LaTeX format. generated.mml is the name of the generated +output file containing the documentation in MML (Maker Markup Language), which +can be used to create a FrameMaker document. generated.rst is the name of +the generated output file containing the documentation in reStructuredText +format, which can be used with Sphinx and various other tools.

    +

    error_msg.txt contains lines that have the following form:

    +
    error_code;tag;"text"
    +
    +
    +

    The error code is the enumeration element name that is used by the front end. +The file must be specified in enumeration order. To preserve the numbering of +error codes, errors may not be inserted in the middle of the file, nor may +lines be removed. If an error message is no longer in use, the line on which +it is defined should be prefixed with the string REMOVED. This will retain +its sequence number but eliminate it from the generated tables.

    +

    The tag is an alias for a given error code to be used by the end-user to name +that error in the command-line options that change the severities of +diagnostics. If no tag is specified, the error code (with the ec_ removed) +is used as the tag.

    +

    Some messages are used as part of the formatting of other messages (for +example, the messages used to provide error context information). These +messages should have a tag of INTERNAL. This prevents the message from +being entered in the tag table and also prevents the message from appearing in +the automatically generated documentation file.

    +

    The text string contains a quoted string similar to one that would be used in a +C program to define the equivalent string. Any quote characters within the +text string must be escaped.

    +

    The text string includes markers indicating the location of fill-ins in the +message (e.g., %t for a type). Full information on those fill-in codes can +be found in Error Reporting.

    +

    The message text may include supplementary information that is only used to +improve the automatically generated documentation file (which is formatted +into the Error Messages appendix of this manual). For example, an +error text string might look like this

    +
    "a message with %s\='fill-in' included"
    +
    +
    +

    The string \='fill-in' is used when creating the documentation file as the +value to be substituted for the %s. This string is removed from the error +text information when the err_data.h file is created.

    +

    error_tag.txt is used to supply additional tags that may be used as aliases +for diagnostic messages. This mechanism is intended to be used by customers +who are packaging the front end as part of their product and allows them to +assign their own set of error tags without the need to modify the distributed +error_msg.txt file. Note that these tags are used in addition to (not in +place of) the default tags specified in the error_msg.txt file.

    +

    Each line should be formatted as:

    +
    error_code;tag
    +
    +
    +

    The error code is the enumeration element name used by the front end. The tag +is the alias being assigned. There may be more than one alias that references +a given enumerator.

    +

    In both error_msg.txt and error_tag.txt, blank lines are ignored and +lines that begin with a “#” are treated as comments.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/_sources/admin.rst.txt b/doc/_sources/admin.rst.txt new file mode 100644 index 0000000..cf56bcf --- /dev/null +++ b/doc/_sources/admin.rst.txt @@ -0,0 +1,1654 @@ +======================== +Administrative Functions +======================== + + + + +The source file ``cfe.c`` contains the main program. It calls +``proc_command_line`` (in ``cmd_line.c``) to parse the command line; +``fe_init`` (in ``fe_init.c``) to do global initialization; +``translation_unit`` (in ``decls.c``) to compile or ``cpp_driver`` (in +``preproc.c``) to do preprocessing; and ``fe_wrapup`` (in ``fe_wrapup.c``) +to do global termination. If a back end should be called, and there were no +errors, it also calls ``back_end``. Then, it calls ``fe_wrapup_part_2`` +(also in ``fe_wrapup.c``) to do post-back-end wrapup. Finally, it calls +``exit_compilation`` to exit with the exit status appropriate to the +severity of the errors detected. + +If multiple source files can be compiled, the main program includes a loop +around the steps from ``fe_init`` to ``back_end``. It calls +``get_next_source_file`` to see if there are any more source file names in +the command line. + +Usually, the front end has its own main program, but it can instead be used +as part of some other main program. This is done by setting the +``MAKE_FRONT_END_CALLABLE`` configuration macro. The name of the main entry +point into the front end is specified by the ``EDG_MAIN`` macro, and is +``edg_main`` by default. When the front end is callable, +``exit_compilation`` does not actually exit the program, but instead +returns control to the routine that called the front end. + +Initialization and Wrapup +========================= + +``fe_init.c`` contains one-time initialization. Declarations of external +variables in ``.h`` files, which must begin with ``EXTERN``, are compiled +here with ``EXTERN`` defined as an empty string, so storage is actually +allocated. Likewise, ``VAR_INITIALIZERS`` is defined as 1, so that +initializers on those variables are put out. The main routine is +``fe_init``; it calls other routines to initialize predefined macros, +keywords, and assorted state variables. In particular, it calls some +initialization routines in other files (e.g., ``lexical_init``, +``sym_tbl_init``). There are several different kinds of initialization +routines: + +* | "early" initialization routines (e.g., ``cmd_line_early_init``), which + are called before command-line processing is done. + +* | "one time" initialization routines (e.g., ``lexical_one_time_init``), + which are called only once per invocation of the front end, even if + multiple source files have been specified on the command-line (when + ``COMPILE_MULTIPLE_SOURCE_FILES`` is enabled). + +* | "per-compilation" initialization routines (e.g., ``lexical_init``), + which are called for each source file specified on the command-line + (when ``COMPILE_MULTIPLE_SOURCE_FILES`` is enabled). + +* | "trans-unit" initialization routines (e.g., + ``lexical_trans_unit_init``), which are called once for each + translation unit processed when processing exported template definition + files or when ``COMPILE_MULTIPLE_TRANSLATION_UNITS`` is enabled. + +Because the front end can be reinitialized (when +``MAKE_FRONT_END_CALLABLE`` is used), most variables must be initialized +dynamically, not statically. Variables that are modified by command-line +processing must be initialized in early initialization routines. + +Command-line ``-D`` and ``-U`` options are also handled here (see +``preproc_init``). + +If multiple source files are accepted, ``fe_init`` is called at the start +of compilation of each file. + +``fe_wrapup.c`` contains one-time wrapup code. This involves popping the +file name scope, checking for errors on files written, and dumping debug +statistics, such as information on symbol table efficiency and on total +memory used. ``fe_wrapup`` is called after the front end is done but before +the back end (if any) is executed, and ``fe_wrapup_part_2`` is called after +the back end (if any) is executed. + +.. _cppcli-init: + +C++/CLI Initialization +---------------------- + +The C++/CLI language depends in some essential ways on its core library, +which is loaded from assembly metadata (usually a file called +``mscorlib.dll``). The initialization process therefore preloads that +library and any others specified via the ``--preusing`` command-line option +with a call to ``process_preusings``. + +Immediately after loading the top-level declarations of the core library, +``process_preusings`` also initializes a number of global variables (and +global array elements) to point to the symbols for special entities from +the core library (for example, the ref class ``System::Object``). This is +done in ``init_cli_symbols``. + +``init_cli_symbols`` also creates templates for ``cli::array``, +``cli::interior_ptr``, and ``cli::pin_ptr``. This is achieved by running +ordinary front end processing on string literals (via calls to +``scan_top_level_metadata_declarations``) containing the declarations for +those templates. The symbols representing these templates are recorded at +this time (for ease of reference in later contexts). + +The symbol for namespace ``::cli`` itself is created even earlier by a call +to ``make_symbol_for_namespace_cli``. + +Debug Routines +============== + +The source file ``debug.c`` contains the routine that processes the +command-line debug request option (``-d``), and also the routines +``debug_enter`` and ``debug_exit`` which are called for flow tracing. When +the command-line debug request includes routine names, ``debug_enter`` +checks the name of the routine entered against the names on the request +list. If the name is found, the associated modification of ``debug_level`` +is done. An internal stack is used to preserve information from +``debug_enter`` time to ``debug_exit`` time for a function. One trick: A +checksum of the stop tokens set is computed and stored on entry, and +recomputed and checked on exit. This helps catch mismatched +``add_stop_token`` and ``remove_stop_token`` calls in recursive descent +scanning routines. + +``debug_enter`` and ``debug_exit`` are not called if there is no +command-line debug request (i.e., if ``db_active`` is FALSE). + +Generating Strings from IL Types and Constants +============================================== + +``il_to_str.c`` contains code that converts IL types and constants into +C/C++-form strings. Associated declarations are in ``il_to_str.h``. + +To use these routines, one needs to declare a control block of type +``an_il_to_str_output_control_block``, call +``clear_il_to_str_output_control_block`` to initialize it, and then set +applicable fields to describe how the string output should be done. The +control block includes, among other things, a pointer to a routine to +output a string, so one can establish a control block that provides an +output routine that writes to a file, or a control block that provides a +routine that puts the output string into a buffer, etc. Other fields in the +control block control the style of output and provide other (optional) +callback routines to do specialized output (instead of the default version) +for certain constructs. + +``form_type`` produces a string for a type. It does this by calling + +* | ``form_type_first_part``, which outputs the type specifiers and the + part of the declarator that precedes the name, and then + +* | ``form_type_second_part``, which outputs the part of the declarator + following the name. + +So, for example, for the type + + | *array* ``[10]`` *of pointer to* ``const int`` + +the "first part" would be + +.. code:: c++ + + const int * + +and the second part would be + +.. code:: c++ + + [10] + +If one wants to put out a declaration of an identifier, one can do so by + +#. calling ``form_type_first_part``, then + +#. outputting the identifier, then + +#. calling ``form_type_second_part``. + + +producing an overall output string like "``const int *a[10]``". + +``form_type_first_part`` descends through any derived types that are at the +top of the type by calling itself recursively. When it reaches a +non-derived type, it calls ``form_type_specifier`` to output the specifiers +part of the type (e.g., "``const int``" for the above example). Then, while +reascending, it puts out the parts of the declarator that appear on the +left-hand side of the declarator (pointers, references, +pointers-to-members, and any required parentheses). + +``form_type_second_part`` also descends through any derived types by +calling itself recursively. While descending, it puts out the parts of the +declarator that appear on the right-hand side of the declarator (arrays, +functions, and any required parentheses). ``form_array_declarator`` puts +out array declarators. ``form_function_declarator`` puts out function +declarators; it can be replaced by a user-provided routine if desired. One +reason to replace it: It does not handle putting out function declarators +for function definitions. + +``form_type_specifier`` puts out non-derived types. Most cases are simple +(see, for example, ``form_int_kind_name`` and +``form_float_kind_name``). Typedef names are put out as such. ``class``, +``struct``, ``union``, and ``enum`` types are always put out as references +to those types, i.e., a definition is never put out. + +``form_name`` puts out names; it can be replaced by a user-provided routine +if desired. It handles qualified names (see +``form_class_or_namespace_qualifier``), unnamed entities, and template +argument lists on classes (see ``form_template_args``). + +``form_constant`` produces a string for a constant. It does some processing +itself, and has several important helper routines: + +* | ``form_integer_constant`` puts out integer constants, including sign, + suffix, and implicit casts. It also handles integer constants cast to + pointer types (e.g., null pointers). + +* | ``form_address_constant`` puts out address constants, including the + "``&``" and optimizations for arrays and for adding a byte offset to + the base address. + +* | ``form_pm_constant`` puts out pointer-to-member constants, including + null constants and any required implicit casts. + +* | ``form_char`` puts out a single character of a string or character + constant, dealing with unprintable characters and the like. + +.. _error-reporting: + +Error Reporting +=============== + +``error.c`` contains code that handles reporting of errors. ``error.h`` +contains the declarations needed to use the error +routines. ``error_msg.txt`` defines the error codes and associated error +message text for all of the error messages, and, along with +``error_tag.h``, is used by ``mk_errinfo`` to generate the ``err_codes.h`` +and ``err_data.h`` files. It is the generated files that are actually used +by the front end to define the ``an_error_code`` enumeration and the array +of error message text. See :ref:`mk-errinfo` for a description. + +``an_error_code`` defines enumeration constants that represent each error +message (for example, ``ec_unclosed_string`` represents the error message +"missing closing quote"). ``ec_no_error`` is the first member of the +enumeration, and therefore has the value ``0``, which has the effect of +allowing flags with the value ``0`` for no error, and a non-zero value to +indicate a specific error. + +Within the error message texts, fill-in codes beginning with "``%``" +indicate points at which information is to be inserted: + +.. list-table:: + + * - | ``%%`` + - | A "``%``" is inserted into the message. + * - | ``%d`` + - | A number is inserted into the message. + * - | ``%s`` + - | A character string is inserted into the message. ``%sq`` indicates + that the inserted string should be placed in quotes, e.g., + + ``could not open source file "abc.h"`` + + * - | ``%t`` + - | A description of a type is inserted into the message. It is always + placed in quotes, e.g., + + ``cast to array type is nonstandard (treated as cast to + "int *")`` + + * - | ``%n`` + - | A description of an entity in the program (identified by a symbol) + is inserted into the message. The default ``%n`` ("name") can be + modified by appending an "``o``" (``%no``, "name only") to get just + the name of the entity, a "``p``" (``%np``, "name with function + parameters") to force parameter information on a function, an + "``f``" (``%nf``, "name full") to get full type information on the + name, an "``a``" (``%na``, "name with template arguments") to get + arguments on a template, "``t``" to force the "``A with T=int``" + form of template name to be used, or a "T" to get the translation + unit in which the symbol was declared. + + .. list-table:: + + * - | ``%n`` + - | ``function "A::f"`` + * - | ``%no`` + - | ``"A::f"`` + * - | ``%np`` + - | ``"A::f(int, float)"`` + * - | ``%na`` + - | ``"A"`` + * - | ``%nt`` + - | ``"A with T=int"`` + * - | ``%nT`` + - | ``function "f(int)" (from translation unit "x.c")`` + +.. list-table:: + + * - | ``%p`` + - | A source position is inserted into the message. + * - | ``%[``\ *label*\ ``]`` + - | The specified label is looked up in the ``label_fill_ins`` array + and one of two error messages is substituted depending on the + value of a boolean variable associated with the label. The + substituted error messages cannot themselves have fill-ins. See + the definition of ``label_fill_ins`` to determine the list of + valid label fill-ins (or to add a new one). + * - | ``%T`` + - | A template argument list is inserted into the message. + +In the default mode, the entity description is preceded by a keyword that +identifies the type of the entity (e.g., ``function`` above). That is also +done in the "full" mode for entities that are not variable-like or +function-like. The normal "``%n``" displays function parameter types only +for overloaded functions. Any of the ``%n`` codes can be modified by +appending a "``d``" to request information on the point of declaration of +the symbol: + +.. code:: text + + declaration is incompatible with "int f(char)" (declared at line 17) + +Following the optional "``d``" modifier, the "``T``" modifier may be used +to display the translation unit associated with the symbol ("``from +translation unit "x.c"``"). When compiling a primary translation unit, this +will cause the translation unit to be displayed for symbols from secondary +translation units. When compiling a secondary translation unit, this will +cause the translation unit to be displayed for all symbols. + +There can be more than one fill-in code in a message. When there is, each +fill-in code can be numbered (e.g., ``%t1``, ``%t2``) to tie it to a +corresponding fill-in argument. Note that this technique allows one to +reorder the fill-ins in a message (say, when changing the error messages to +a language other than English) without changing the order of the fill-in +arguments on error calls throughout the front end. + +Each normal diagnostic includes four kinds of information: + +* | the error code, which is a value from the enumeration just mentioned, + and indicates the error message text; + +* | a severity (remark, warning, discretionary error, error, or + catastrophic error); + +* | the error position (a sequence number and column); and + +* | optionally, some information that goes into fill-in spots in the error + message text. + +The severity is usually indicated by the routine called (e.g., ``warning`` +instead of ``error``). There are also routines that accept the severity as +an argument. A given message can be (and is, in many cases) output with +different severities in different modes or different places. + +The severity of a given error code may be overridden through the use of a +command line option or pragma. For example, the option +``--diag_error=extra_semicolon`` may be used to cause the extra semicolon +diagnostic to be issued as an error, even if the ``warning`` function was +actually called to report the error. Only diagnostics that would by default +be issued as remarks, warnings, or discretionary errors may have their +severities overridden (i.e., nondiscretionary errors and catastrophic +errors may not have their severities overridden). When a severity is +overridden by a pragma, the default severity can be restored by use of the +``diag_default`` pragma. The default severity is the severity as would +normally be used for the message as adjusted by any command-line options. + +The error severity may be overridden by specifying either an error "tag" or +an error number. The error tag is a name assigned to each error code. The +error number is the numeric value of the error code enumerator that +represents the message. By default, the error tag is the same as the error +code enumerator name with the ``ec_`` prefix removed. The error tag may be +changed by specifying an alternate tag in the ``error_msg.txt`` +file. Additional tags may be provided by creating entries in the +``error_tag.txt`` file. ``set_severity_for_error_tag`` and +``set_severity_for_error_number`` are used to override the severity for a +given diagnostic. These routines are called to process the error severity +options during command line processing. + +The error position is usually given by the global variable +``error_position``, but it can also be explicitly +supplied. ``error_position`` is set to the start of each token as it is +scanned, and is set on exit from recursive descent routines to the start of +the entity just scanned, unless that entity is extremely large (like +several lines). This usually results in the correct position in +``error_position``, at least for syntax errors. + +When the sequence number of ``a_source_position`` is ``0``, the column has +special meaning (for example, it can indicate that the error occurred in +the command line). See ``basics.h``. + +The error routines themselves have names that encode the severity (one of +``remark``, ``warning``, ``error``, ``catastrophe`` or the generic +``diagnostic``), and the particular combination of fill-ins and a source +position that they accept. That is, an error routine name may be as simple +as ``error`` or as complicated as ``pos_ty2_warning``. ``pos`` indicates +that a source position is provided; ``str`` or ``st`` indicates that a +string fill-in is provided; ``sym`` or ``sy`` indicates that a symbol +fill-in is provided; ``type`` or ``ty`` indicates that a type fill-in is +provided. These can be followed by a number if more than one fill-in is +needed, e.g., ``ty2`` for two types. So, for example, ``pos_ty2_warning`` +issues a warning, and the caller is expected to provide the error code, the +source position, and two fill-in types. See ``error.c`` for the full list +of routines. Not all combinations exist, but it is easy to add any routine +that does not exist. + +For a syntax error, one can instead call + +.. code:: c++ + + syntax_error(error_code); + +which will call ``error`` and then ``flush_tokens`` (see ``lexical.c``). + +For complicated errors that may have to list an arbitrary number of items, +for example diagnostics for overloading ambiguity, one can make an initial +call to issue the initial line of the error (calling ``start_error`` or one +of its variants such as ``type_start_error``), then any number of calls to +add individual lines of additional information (calling ``add_diag_info`` +or one of its variants such as ``sym_add_diag_info``), and then a call to +``end_error`` to finish the error processing (including writing the source +line in error). The end result is illustrated by + +.. code:: text + + "test.C", line 7: more than one constructor applies to convert from + "double" to "A": + function "A::A(int)" + function "A::A(float)" + f(2.0); + ^ + +The usual fill-in processing is available on both the initial line and any +lines of additional information. The additional lines are described by an +error code, so they can also contain arbitrary text. + +The error formatting and processing is done by ``construct_message``. It +fetches the error message text, builds a linked list of message segments +describing the message and its fill-in codes, expands each fill-in +appropriately, and writes the full message. + +If an error is detected while processing a template instantiation or during +implicit generation of a routine (e.g., a constructor), it is helpful to +provide additional information on the context in which the error was +detected: + +.. code:: text + + "test.c", line 7: error: "A::A()" is inaccessible + B x; + ^ + detected during implicit generation of "B::B()" at line 7 + +The context is deduced from the entries in the scope +stack. ``include_in_context_output`` identifies the scope stack entries +that merit extra context information. If there are any such entries, +``diag_message`` outputs an extra context line for each, in order from +innermost context to outermost. + +``format_output_line`` is the routine that actually prints the diagnostic +messages; it is the routine to change to modify the error output. To output +the source line associated with the diagnostic, ``write_source_line`` is +called. If the error is in the current line, ``write_orig_source_line`` +reconstructs and writes out the original source line, with a caret under +the column position of the error. If the error is not in the current line, +``write_error_source_line`` reads the line from the source file, if +possible, and writes out the source line. Long diagnostic messages are +wrapped across multiple lines. If raw listing information is requested, +similar information is written to ``f_raw_listing`` (in encoded form). The +diagnostic routines count the number of diagnostics of each severity so +that the compilation can be ended with an appropriate exit status. They +suppress diagnostics that are below the error display threshold. If an +error is catastrophic or if the error limit is reached, the compilation is +terminated. + +The severity of diagnostics for strict ANSI violations and C++ anachronisms +can be specified by command line options. To simplify handling of these +diagnostics the global variables ``strict_ansi_error_severity`` and +``strict_ansi_discretionary_severity`` contain the error severity to be +used for strict ANSI violations. The former is either ``es_warning`` or +``es_error``, while the latter is either ``es_warning`` or +``es_discretionary_error``, depending on which strict mode was selected on +the command line. ``anachronism_error_severity`` contains the error +severity to be used when anachronistic features are used. These global +variables can be used as arguments to the ``diagnostic`` reporting +routines. + +``command_line_error`` and ``str_command_line_error`` are the routines +called for command-line errors (without or with fill-in text, +respectively). They do not return. + +The routine ``internal_error`` should be called for internal errors, such +as failures of consistency checks. It should not be called for anything +that is due to a source program error or some environmental error (like a +missing file). The call should look like + + ``internal_error("``\ *routine-name*: *problem found*\ ``");`` + +Several routines are provided as convenient ways to do consistency +checking. Calls of these routines need not be surrounded by ``#if +CHECKING``/``#endif``; they are defined as macros that expand to nothing +when ``CHECKING`` is disabled. ``check_assertion`` can be used to check an +expression to make sure it is true; ``check_assertion_str`` is similar, but +includes a string to be printed on error +termination. ``unexpected_condition`` is used when a piece of code is not +expected to be reached (for example, the default clause of a switch); +``unexpected_condition_str`` is similar, but includes a string to be +printed on error termination. + +Memory Management +================= + +``mem_manage.c`` contains memory management routines. ``mem_manage.h`` +contains the associated declarations. + +Memory is allocated in *memory regions*. File-scope intermediate language +information is put in memory region 1, and the functions in the source +program will each have one of the memory regions 2, 3, and so forth. Memory +region 0 is used for storage that need not survive the front end, like the +symbol table. + +Before using a memory region, one calls either ``init_memory_region`` (for +regions 0 and 1) or ``new_memory_region`` (for regions for functions) to +initialize the new region. + +``alloc_in_region`` is then called when needed to allocate space in a given +region. (``alloc_fe`` can be called for the special case of allocation in +region 0, the front-end-only region.) ``alloc_in_region`` allocates a large +block of memory for each memory region by calling ``malloc``, then parcels +out that storage as it is needed. When the block is exhausted, a new block +is allocated and put on a linked list of blocks for that memory region. + +When one is done with an IL memory region, +``check_for_done_with_memory_region`` is called; it will either write the +information to a file and free the block, or trim the end of the memory +region to reclaim any unused space (depending on whether an IL file is +being generated), or defer this processing until later if the memory is +potentially needed for operations such as inlining or generic lambda +instantiation. "Trimming" means making a separate available block from the +remaining space at the end of the last block in the region. Since the +blocks are large (typically, 64K) and a typical function will use less than +10K of the block, this is an important feature. The combination of using a +large block size and reusing the remaining space improves efficiency (in +reducing the number of calls to ``malloc``) and avoids the need to guess at +the amount of storage a particular memory region is likely to +need. Eventually, when the partial blocks created in this way are released, +they are recombined into the original large blocks allocated via +``malloc``, and freed using the system ``free``. Thus storage used is +freed, but only on a large-block basis, so fragmentation is not a problem. + +``alloc_general`` is a more-or-less direct interface to ``malloc`` to be +used in the infrequent cases where storage must be allocated that will +survive into the back end if the back end is called in the same program. An +example of such storage is the debug option control list, which holds +information about the command-line debug option. + +``alloc_resizable_buffer`` and ``realloc_buffer`` are used to allocate +tables that can be enlarged (e.g., ``input_stack``). + +When ``MAKE_FRONT_END_CALLABLE`` is used, the front end keeps a record of +all memory allocations so that all of the memory allocated can be freed +before returning control to the caller. + +When precompiled headers are used, the memory management routines work to +allocate the IL memory region blocks at reproducible addresses, so that the +information in a precompiled header file can be read back in without the +need to walk the IL and remap pointer references. See +:ref:`memory-management-issues`. + +File Variables +============== + +Normally, any open files are closed when the front end exits, but when +``MAKE_FRONT_END_CALLABLE`` is used, any open files must be closed if the +front-end were to terminate abnormally. This is accomplished by having a +special cleanup routine (e.g., ``templates_cleanup``) in any file that +opens and closes files. The cleanup routine is present only when +``MAKE_FRONT_END_CALLABLE`` is used. File variables must be set to ``NULL`` +when they do not refer to an open file. The cleanup routine generally calls +``close_file_if_open``, to close any files that may be open. The cleanup +routines are called by ``fe_cleanup`` (in ``fe_wrapup.c``). + +Command-line Parsing +==================== + +``cmd_line.c`` contains code to parse the command line; ``cmd_line.h`` +contains the associated declarations. The main routine is +``proc_command_line``. Aside from setting switches, ``proc_command_line`` +establishes the primary source file, the preprocessing output file if there +is one, the raw listing output file if there is one, the cross-reference +output file if there is one, and the include file search list. + +If multiple source files can be compiled, ``get_next_source_file`` is +called after each source file is compiled to see if there is another file +name on the command line. It also does some minor initialization. + +``proc_command_line`` is called only once, even if multiple source files +are specified on the command line. Since the IL memory for each source file +is separate and self-contained, ``proc_command_line`` cannot allocate +anything in the IL memory: For one thing, it does not exist yet, and for +another, there will be a distinct copy for each source file +compiled. Therefore, file names and other information saved by +``proc_command_line`` must be saved in general memory, and copied into IL +memory later (e.g., in ``fe_init``) for each source file. + +Host-dependent Routines +======================= + +``host_envir.c`` contains host-dependent routines; ``host_envir.h`` +contains the associated declarations. + +The following routines are used to maintain the list of directory names to +be searched for include files: + +* | ``add_default_include_search_path`` +* | ``add_to_include_search_path`` +* | ``add_to_front_of_include_search_path`` +* | ``push_primary_include_search_dir`` +* | ``pop_primary_include_search_dir`` +* | ``change_primary_include_search_dir`` + +The following routines are used to tear apart and build up file names: + +* | ``directory_of`` +* | ``gs_directory_of`` +* | ``derived_name`` +* | ``replace_file_name_suffix`` +* | ``combine_dir_and_file_name`` + +The following routines are used to open files in various ways: + +* | ``open_source_file`` +* | ``reopen_source_file`` +* | ``okay_as_output_file`` +* | ``open_output_file`` +* | ``reopen_error_output_file`` + +``delete_file`` is used to delete files (specifically, files that were +partially generated and are to be canceled because of detection of an +error). + +``open_temp_file`` and ``close_temp_file`` provide support for creating +temporary files. (Note: At the present time, the front end only uses +temporary files when generating an intermediate language file for immediate +use by a back end called in the same program, and in the C-generating back +end.) + +``normal_termination`` and ``term_compilation`` are used for termination of +the compilation. The low-level functions of ``term_compilation`` are +available individually through ``write_signoff`` and ``exit_compilation``. + +``identify_source_file`` is called from ``fe_init`` at the start of +compilation of each source file when there are multiple source files on the +command line. It outputs a message identifying the start of the compilation +of the file. + +``set_signal_handlers`` is called during initialization to set up handling +for signals that should abort the compilation. + +This file is likely to be modified for different hosts. See the section on +host configuration for more information. + +Intermediate Language Traversal +=============================== + +``il_walk.c`` contains the routines that walk the intermediate language +tree, and ``il_walk.h`` contains the associated +declarations. ``walk_entry.h`` contains the detailed code to process the +fields of each IL entry kind. + +"Walking" the tree means traversing the in-memory form of the IL and +calling a supplied routine for each node in the tree. This is used in +displaying the IL in human-readable form, in writing the IL to a file, and +in reading the IL from a file. + +The walking is done on a memory region basis, i.e., for the file-scope +memory region or the memory region for a function. The routines for those +cases are ``walk_file_scope_il`` and ``walk_routine_scope_il``. They call +``walk_entry_and_subtree`` or ``walk_string_entry`` for each entry, and +those in turn call the user-supplied entry processing functions. There are +two separate entry processing functions supplied for each traversal: one +for strings, and one for non-strings. The main reason for the difference is +that string entries do not have fixed sizes, so the string routine has an +extra parameter for the size. + +Since the tree is actually a graph and has cycles, there needs to be a way +to tell when the traversal returns to an entry that has already been +visited. This is provided by the ``il_walk_flag`` in the prefix that +precedes each IL entry. This flag starts out as 0 in all entries. On the +first traversal, it is changed to 1 in all entries, and it keeps +alternating between 0 and 1 on each subsequent traversal. Therefore, on a +given traversal, the entries already seen have one value, and those not yet +seen have the other value. + +While the tree is traversed, one can also request that all the pointers in +the tree be remapped in some way. For example, when writing to an IL file +in the alternate form, each pointer is replaced by an entry number. Such +remapping can be requested by providing a pointer remap function for the IL +walk, or explicitly by calling ``remap_pointers_in_il_entry`` or +``remap_il_header_pointers``. + +Special handling is required for "orphan" entries. These are entries +allocated in the file scope memory region that are referenced only from +function scope memory regions. When the parents of such entries are written +out and then removed from memory, the entries are orphaned because they are +not attached to the rest of the file-scope IL tree. + +The orphan mechanism makes lists of such entries so that they can be found +during traversal of the file-scope IL. + +The array ``orphaned_file_scope_il_entries`` heads lists of orphaned +entries linked together by a hidden orphan-list pointer that precedes the +storage for each file-scope IL entry. (It also precedes the +``an_il_entry_prefix`` structure.) + +The orphan lists are built up while the function scope memory regions are +walked. Each time an entry in a function scope memory region contains a +pointer into the file scope memory region, the entry pointed to is recorded +as a potential orphan. Later, at the end of the walk of the file scope IL, +the entries on the orphan lists are visited. If the entries are not in fact +orphans, they will have been previously visited, and the IL walk flag will +indicate that fact. + +A separate mechanism exists for orphaned lists, specifically the lists of +local types and local static variables in function and block scopes. Those +are unusual in that the list is completely in the file scope memory region +but the pointer to the list is in a function scope memory region +entry. Each of the entries on those lists is placed on the orphaned entries +list, but there needs in addition to be a way to remember the head-of-list +pointers so that the ``next`` pointers in the entries can be +remapped. That's done with a list of entries of type +``a_scope_orphaned_list_header`` pointed to by the +``scope_orphaned_list_headers`` field of ``il_header``. Each entry on the +list points to a list of types and a list of static variables preserved +from a function or block scope. + +Obviously, the code in ``walk_entry.h`` must be kept up-to-date whenever +the IL definition in ``il_def.h`` is changed. + +``il_walk.c`` also contains some special-purpose walking routines: +``walk_declarative_entities_in_scope`` can be used to walk entities like +variables in a given scope; ``traverse_expr`` can be used to walk an +expression tree; and ``traverse_statement`` can be used to walk a statement +tree. In each case, user-provided callback routines can be called for each +node of the tree. + +.. _needed-flags: + +Needed Flags +============ + +When the configuration switch ``MAINTAIN_NEEDED_FLAGS`` is TRUE, the front +end will maintain the ``needed`` flag in the source-correspondence entry, +and the ``definition_needed`` flag in class types and routines. The code to +do this is in ``il_walk.c``, ``walk_entry.h``, ``il.c``, and +``scope_stk.c``. The needed flags are a more sophisticated version of the +``referenced`` flag. They are set by beginning with all externally-defined +variables, static data members, and functions in the compilation unit, and +marking those as needed. Then the entities referenced by those are marked +as needed, and so on. The resulting ``needed`` flag setting indicates +whether something is "really" needed, as opposed to referenced from +something that is itself unneeded. For example: + +.. code:: c++ + + static int i; // i is referenced, not needed + static void f() { // f is not referenced, not needed + i = 1; + } + int main () {} // main is needed, not referenced + +The ``definition_needed`` flag indicates whether the definition of a class +is needed, as opposed to merely a declaration. For example: + +.. code:: c++ + + struct A { }; + struct B { }; + A *p; // forces needed on A, but not definition_needed + B b; // forces needed and definition_needed on B + +There is a similar flag for functions as well. + +If ``DEFAULT_REMOVE_UNNEEDED_ENTITIES`` is TRUE, and that setting is not +overridden via a command-line option, unneeded entities are removed from +the IL. Classes that have ``needed`` TRUE and ``definition_needed`` FALSE +are modified to eliminate their definitions. Function-local entities are +never affected by this process (they are not removed, and local classes are +never turned into declarations). The IL tree after alteration is +self-consistent, in that a back end that does not use the "needed" flags +will find all the IL entries it expects. A back end that does use the +"needed" flags should be sure to use both of them, i.e., +``definition_needed`` as well as ``needed``. + +The "needed" flags processing and removal of unneeded entries works with +and without IL lowering, and for both C and C++. When IL lowering is used, +the "needed" flag information is determined on the basis of the lowered +code. When the C++-generating back end is used, and the source program has +templates, elimination of unneeded entities is disabled, because the +template bodies may contain references to apparently unneeded +entities. This can be changed, carefully, if one has a situation where all +template instantiation will be done by the EDG front end rather than by +some compiler operating on the source code generated by the C++-generating +back end. + +The setting of the "needed" flags is done as follows: + +* | At the end of scanning a function definition, if the function is + externally defined, ``pop_scope`` calls ``mark_as_needed`` on the + routine, which in turn calls ``set_routine_definition_needed``. These + use a specialized version of the ``walk_entry.h`` IL-walking code to + sweep through the IL tree and set the ``needed`` flag on all + transitively-referenced entities. If the type of reference requires a + complete type, and the type is a class, ``set_class_definition_needed`` + is called to set the ``definition_needed`` flag on the class. If a + reference to a routine requires that the routine have a definition, + ``set_routine_definition_needed`` is called for the routine. + | + | When a routine's definition is needed, the definition is also walked, + and then the memory region for the function can be disposed + of. (``mark_to_keep_in_il`` is also called for the function memory + region; more on this below.) That means the memory region can be + written to a file and then freed, if an IL file is being + used. Conversely, as long as a function is not known to be needed, its + body must be retained. If the function is still marked as unneeded at + the end of the compilation, it is then clear that the function truly is + unneeded. It is deleted and its memory region is freed (without writing + it to the IL file, if there is one). +* | When the file scope is being + popped from the scope stack, several things are done. First, + ``set_needed_flags_at_end_of_file_scope`` is called. It visits all + variables (including static data members), and calls ``mark_as_needed`` + for those that are externally-defined. This causes the variables and + everything they reference to be marked as "needed." +* | Then, + ``mark_to_keep_in_il`` is called for the file scope. This uses another + variant of the ``walk_entry.h`` IL-walking code to sweep through the IL + tree and set the ``keep_in_il`` flags in the IL entry prefix and the + ``keep_definition_in_il`` flag in classes and routines. These flags + have meanings similar to the ``needed`` and ``definition_needed`` + flags, but they are set in more cases, to deal with the fact that some + entities in the IL tree must be retained (for consistency) even if they + are "unneeded." In this sweep, entities that can and will be removed + (based on the ``needed`` and ``definition_needed`` flags and the + context where the entities appear) will not be visited. The + ``keep_in_il`` sweep also notes whether complete class types are + needed, and calls ``set_class_keep_definition_in_il`` when appropriate, + and whether routine definitions are needed, and calls + ``set_routine_keep_definition_in_il``. + | + | All decisions about + removing IL entries from the IL tree are based on the ``keep_in_il`` + and ``keep_definition_in_il`` flags, rather than on ``needed`` and + ``definition_needed``. +* | Then, + ``eliminate_bodies_of_unneeded_functions`` is called. It eliminate the + bodies (but not the declarations) of functions that are not needed. +* | Then, ``eliminate_unneeded_il_entries`` is called. It removes types, + variables, and routines in the file scope that are unneeded, and + reduces classes to declarations where appropriate (by calling + ``turn_class_definition_into_declaration``). Auxiliary parts of the IL + data structure, such as source sequence entries and the hidden-name + table, are updated as necessary. + +The IL-walk process used to set these "needed" flags stops when it +encounters an entry with the flag already set. This is desirable for +compilation speed reasons, and necessary to avoid loops for parts of the IL +structure that are graphs instead of trees, but it also makes certain kinds +of problems possible. Variables, routines, and types that are not +function-local have the potential to be redeclared after the "needed" flag +is initially set. For example, a class ``A`` might be declared, then marked +as needed, then defined. Or, a function might be defined, then declared to +add an additional default argument. In all such cases, The ``needed`` or +``keep_in_il`` flag would be set already on the entry, and therefore an +attempt to set it again would result in an immediate return, rather than a +sweep through the updated subtree. To avoid this problem, the subtrees of +these redeclarable entities are not swept ordinarily; the appropriate flag +is set on the entry itself, but its subtree is not visited. At the end of +the file scope, when no more redeclarations are possible, the global flag +``end_of_file_scope_needed_flags_phase`` is set to TRUE, and that enables +the subtree walks. ``set_needed_flags_at_end_of_file_scope`` and +``mark_to_keep_in_il``, as they are doing the ``needed`` and ``keep_in_il`` +walks respectively, look for these delayed-subtree-processing entries, and +handle them by clearing the ``needed`` or ``keep_in_il`` flag and then +calling the subroutine to set them again, which this time will visit the +subtree. For the ``needed`` flag walk, ``remark_as_needed`` provides a +convenient way of doing this. + +When ``ONE_INSTANTIATION_PER_OBJECT`` is TRUE, a more complicated set of +"needed" flags is maintained. In that mode, each instantiation is put out +as a separate object file. There is still only one IL tree, but it is +marked so that a back end can sweep through it several times and put out a +different "slice" each time, each slice containing one instantiated entity +(function, variable, or static data member) plus exactly the set of other +entities needed by that entity. This is done via a set of per-instantiation +"needed" flags, represented as a bit vector implemented as a linked list of +entries of type ``a_per_instantiation_needed_flags_entry`` attached to the +``per_instantiation_needed_flags`` field of the source correspondence. Each +slice is assigned one bit in that bit vector, and if the bit is 1 the +associated entity is needed in the slice. + +The per-instantiation "needed" flags are tested and set by the macros +``needed_flag_is_set`` and ``set_needed_flag``. The global variable +``needed_flag_bit_number`` indicates the bit number to be tested or set. +If it is zero, the ``needed`` flag is tested or set instead of the bit +vector. + +Each instantiation is actually assigned two bits in the bit vector, the +second one used for the per-instantiation versions of the class and +function ``definition_needed`` flags. These are tested and set by +``class_definition_needed_flag_is_set``, +``set_class_definition_needed_flag``, +``routine_definition_needed_flag_is_set``, and +``set_routine_definition_needed_flag``. As with the needed-flag macros, +these macros depend on the value of ``needed_flag_bit_number`` and use the +``definition_needed`` flags if that variable is zero. + +The bit number assigned to a given instantiation entity is recorded in the +``instantiation_needed_bit_number`` field in the variable or routine. When +``mark_as_needed`` is called for the entity, after the standard "needed" +flag processing has been done, another sweep is done to set the proper bit +in the per-instantiation "needed" flag bit vectors of all entities +referenced from the instantiation. The class and function per-instantiation +definition-needed bits are also set in this sweep. + +All externally-defined entities that are not instantiations are assigned to +the slice numbered 1 (though their ``instantiation_needed_bit_number`` +fields are left as zero), and a similar sweep is done for them. By the end +of the compilation, therefore, every externally-defined entity has been +assigned to a slice, and the per-instantiation bits show what must be +included in each slice. The "1" slice includes everything that isn't in an +instantiation slice. + +Some entities are present in multiple slices. Constants, types, and class +definitions appear in each slice as needed. Inline functions are also +present in a slice if they are referenced in that slice. In general, +however, functions and variables can only appear in one slice, or more +precisely, their definitions can only appear in one slice. If other slices +reference them, they appear only as declarations in those slices. This +causes a problem for static functions and variables, which by definition +cannot be referenced from other object files. This is handled by making +those entities external with generated names. The sweeping routines will +set the ``static_used_by_instantiation`` flag in static entities that are +used by an instantiation, and IL lowering will turn such routines and +variables into external entities. + +The simple ``needed`` and ``definition_needed`` flags end up being in +effect the unions of the corresponding per-instantiation sets. That is, if +any per-instantiation "needed" flag is set on an entity, then the +``needed`` flag will be set, and likewise for the definition-needed +flags. Therefore, when the normal processing to remove unneeded entities is +done, it will remove only entities that are unneeded in all slices. + +Intermediate Language Display +============================= + +``il_display.c`` contains routines to display the IL in human-readable +form. ``il_display.h`` contains the associated declarations. The code is +currently set up to be compiled as a standalone utility program: It reads +the IL from a file (by calling the IL read routines), then traverses the +in-memory form using the IL walk routines, producing output on +``stdout``. ``il_display`` could be set up as a subroutine to be called +from within the front end. + +The processing is very simple: Using the IL walk routines, it walks the +file scope and displays it, then walks each routine scope and displays +that. The IL walk routines are told to call ``disp_entry`` for each +non-string entry, and to call nothing for string entries (string entries +are displayed when pointers pointing to them are displayed). Most of the +display routines are very straightforward. When pointers are displayed, an +attempt is made to show what is pointed to. That is, if the entity pointed +to is named, or if it is a string, a constant, or a type, a brief summary +of the entity is given so one does not have to look at, say, a type entry +to find out that it is the entry for ``int``. + +If there are errors in the IL, they are highlighted (e.g., +"**BAD-TYPE-SPECIFIER-KIND**") and the display continues as well as it +can. An internal error is not generated. + +Obviously, the code in ``il_display.c`` must be kept up-to-date whenever +the IL definition in ``il_def.h`` is changed. + +Writing the Intermediate Language to a File +=========================================== + +``il_write.c`` contains routines that write the intermediate language to a +file, and ``il_write.h`` contains associated declarations. + +IL writing takes the in-memory IL and writes it to a file for later +reading. + +``start_il_file`` is called to open the IL file, and ``finish_il_file`` to +close it. Alternatively, ``cancel_il_file`` can be called to delete the IL +file and suppress further IL file generation if an error is detected during +the compilation. + +``write_memory_region`` is called to write out each memory region, i.e., +the file-scope memory region or a memory region for a function. It writes +the memory region at the end of the intermediate language file. + +There are two IL file formats. The switch ``ALTERNATE_IL_FILE_FORMAT`` in +``host_envir.h`` indicates which is to be used. The file header is the same +in both formats: + +* | A special string identifying the file as an IL file, and including the + version number of the IL (see ``il_file.h``). + +* | The number of memory regions. +* | The number of function definitions. +* | The file position of the file index (at the end of the file). +* | The file position of the file-scope memory region. +* | The ``il_header`` struct, which is the root of the IL tree. +* | The array of orphan-list pointers. + +In terms of processing, the space for the header information is reserved at +``start_il_file`` time, but the full information is not known until all +regions have been written. At ``finish_il_file`` time, the file pointer is +repositioned and the final information is overwritten on the reserved +space. + +The file index is also the same in both formats: It is an array of file +positions, such that file-index[*i*] gives the file position of the start of +the information for memory region *i*. The index is the last thing written in +the file. No entry 0 is written; the first entry is entry 1 (i.e., for the +file scope), which is at the position indicated by the file index position +in the header. The other entries follow. There are as many entries as the +"number of memory regions" given in the header. + +Between the header and the file index is a sequence of one or more memory +regions. Since the file-scope region is not complete until the end of the +compilation, the file contains all the function regions first, in order of +definition, and then the file-scope region at the end. + +In both formats, the information for a memory region begins with the memory +region number, and the overall sequence of regions is followed by a zero +which serves as an end marker if the regions are read sequentially. + +Beyond that, the information for a memory region is quite different in the +two file formats. + +The default file format involves writing out the memory blocks for each +region exactly as they appear in memory -- i.e., large blocks, in memory image +form. On the reading side, these blocks are read back in, and since they +are probably not read in at the same address they had when written out, the +IL tree is walked to find and remap all the pointers. A tree walk is also +required on the writing side, at least for function scope memory regions, +to get the data structure for orphaned entries built. The process is fairly +fast on both the writing side and the reading side; although the tree walk +takes time, at least the I/O for reading the blocks can be done +efficiently, in large blocks. + +The information for a region in the default format is as follows: + +* | The memory region number. +* | The original memory address for the first block header. +* | The original memory address for the primary scope entry for the region. + +* | The total size in bytes of the information following (i.e., the total + size of all blocks and their associated headers). + +* | For each memory block, the block header and block data. The header + contains pointers that point to the next block and to the data (all as + original memory addresses). + +In the alternate file format, each entry is assigned an entry number (which +is recorded in the prefix preceding the entry), all pointers are changed to +the corresponding entry numbers, and each entry is written individually to +the file, preceded by an indication of the entry kind and by the entry +number. On the reading side, the entries are read individually and the +pointers in them are changed to the proper new pointer values. This format +is less efficient than the default format, because the actual I/O is done +one entry at a time for both writing and reading (there is of course +buffering under this, but it is still less efficient to make thousands of +calls to ``fwrite`` and ``fread`` than to make dozens of calls). The +advantage of the alternate file format is that it allows resizing or other +alteration of the entries on the reading side. If one wants to add +back-end-specific information, for example, one can do so. + +The information for a region in the alternate file format is as follows: + +* | The memory region number. + +* | An array giving, for all the IL entry kinds (see ``il_walk.h``), the + number of entries of each kind in this memory region. + +* | A sequence of entries, giving for each entry the entry kind, the entry + number, the entry length (only for string entries), the orphan-list + pointer (only for non-string file-scope memory region entries), and the + entry itself. After the last entry, a zero entry kind marks the end of + the sequence. + +Entry numbers are assigned from 1 for each kind of table; there can be, for +example, a type entry 27 and a constant entry 27. 0 is used to represent a +NULL pointer. The entry numbers in each function scope start again from 1, +but in addition they have the top bit on, i.e., they effectively start with +``LONG_MAX+2``. Thus there can be identical entry numbers in two function +scopes (and that is not a problem), but a file-scope entry number can +always be distinguished from a function-scope number. + +For string entries, the "entry number" used is an offset into a conceptual +block formed by concatenating all the strings of that kind, including the +terminating null if any, and with space reserved between the strings for +the entry prefix and for any required alignment. The offsets start from 1 +to preserve 0 as a NULL pointer. In the array of entry counts, the values +for string entries indicate the total size of the conceptual block, in +bytes, rather than an entry count. Thus, if there were three strings "``abc``", +"``de``", and "``fghi``" in a region, the prefix takes 4 bytes, and the host +machine requires 4-byte alignment, the strings' entry numbers would be 5, +13, and 21, respectively, and the entry in the count array would be 25. + +Reading the Intermediate Language from a File +============================================= + +``il_read.c`` contains routines that read the intermediate language from a +file, and ``il_read.h`` contains associated declarations. + +File reading takes the IL in file form and reads it in to re-create the +in-memory form. + +The routine ``il_read`` reads the file header and the file index, then +calls ``read_memory_region`` to read the file-scope memory region. Other +(function-scope) regions must be read explicitly by calling +``read_memory_region`` directly. This allows the back end to read each +function, process it, and then free its IL by calling +``free_memory_region``, to reduce overall memory requirements. + +With the default file format, the information for each memory region is +read with one large read, and the pointers in the region are then remapped +to the proper values by calling ``walk_file_scope_il`` or +``walk_routine_scope_il`` with a pointer remap function. If all the memory +blocks are read back in at their original addresses (an attempt is made to +do this), the IL walk is not needed. + +With the alternate file format, the array of entry counts is read at the +beginning of processing the region. For each entry kind, an area is +allocated that is large enough to contain all the entries of that kind (its +size is the number of entries times the size of each entry). This area is +then considered an array of entries of that kind, and the entry number is +an index into the area. (For string entries, the "entry count" is the +actual total size, and the "entry number" is still an index -- with the area +treated as an array of characters.) Each entry is then read, placed at the +right place in the allocated space, and its pointers changed from entry +numbers back to real pointers. Note that no overall tree walk is done, and +no special orphan processing is required: Since each entry is read +individually, one can do all the processing for each entry when it is read, +and be sure no entries were missed. + +As each region is read, the associated entry of ``region_scope_entry`` in +``il_header`` is set to point to the primary scope entry for the region. + +Precompiled Headers +=================== + +The precompiled headers ("PCH") facility is intended to speed up +compilations that include relatively stable header files. It does this by +writing a precompiled header file that is a snapshot of the front end's +internal state at a point in the compilation process immediately following +the initial sequence of ``#include``\ s. On a recompilation of that file +(or another that begins with the same sequence of ``#includes``), the front +end checks to see if all the header files are unchanged since the +precompiled header file was generated, and if so reads in the precompiled +header file to re-establish the front end state as it would be after +reading and compiling the header files. Reading in the PCH file takes less +time than compiling the header files from source, so there is a net savings +in compilation time. + +Since the point of this feature is saving time, it is important that the +process of writing and reading the PCH files be as fast as possible. One +would like to see savings of 80% or the like (comparing the time to restore +a PCH file to the time to compile the original source code); an improvement +of only 30% or so would barely be worth the extra complexity. In addition, +one should not have to pay a large price to write out the precompiled +header file; it's okay to slow compilations a little to get the benefits of +precompiled headers on later compilations, but if it takes too long to +write the file, the net gain is marginal or negative. + +These speed issues suggest some basic design decisions: + +* | The information written to the precompiled header file must not require + a tree walk, because visiting every entry takes a lot of time. (It also + requires code or data structures that describe how to do the tree walk, + which exist for IL entries but not for the front-end-only data + structures.) Therefore, the information must be written out and read + back in as large chunks (rather than one entry at a time), and it must + not be necessary to remap all pointers in the information to new values + (i.e., it must be possible to bring the information back in at the same + address). These requirements also make it possible to exploit memory + mapping on systems that support it. + +* | Precompiled header files should contain snapshots of compilation + states, and not information about individual header files. While it's + tempting to imagine writing precompiled header files for individual + header files, the work required in carving out the right information + and the description of dependencies so that the information can be + written to a file, and the work to bring it back in and merge it with + the front end state, will make substantial time savings unlikely. + +An unfortunate consequence of this latter design decision is that users are +probably forced to change their source code to get any meaningful benefit +from the PCH facility. In average source code, the order of inclusion of +header files is essentially random. The net effect of the various orders of +inclusion is often the same, because of the way header files tend to be +written, but it is difficult to deduce that fact, and time-consuming. So we +have a dilemma: If we strive for maximum save/restore speed, we will find +few "natural" common sequences, and therefore generate many PCH files for +little benefit. On the other hand, if we try for maximum ability to reuse +precompiled headers from unaltered source files, we lose something +significant on save/restore speed. + +We've chosen to go in the direction of maximum save/restore speed. We +believe that users are willing to make small changes in their source code +to get large reductions in compilation time, and that given a choice +between + +#. | You don't have to change your source, and precompiled headers will + give you a 15% savings, or + +#. | You may have to reorder your initial ``#include``\ s or add the + equivalent of + + ``#include `` + + | to the beginning of your source files, and precompiled headers will + give you a 50% savings, + +users will choose option 2. This, of course, is a matter of opinion, and +the percentages are fictitious. But for better or worse, this is what we +decided. + +Because PCH processing is not likely to be helpful on arbitrary files, it +is disabled by default. + +The code for precompiled header processing is mostly in ``pch.c``, with +associated declarations in ``pch.h``. + +Prefix and Header Stop Point +---------------------------- + +The initial sequence of the source code of the primary source file that is +subject to the PCH optimization is referred to as the *prefix*. It consists +of the preprocessing directives preceding the *header stop point*. The header +stop point is determined as follows: + +* | Start at the first token of the primary source file that is not part of + a preprocessing directive (or the end of the file if there is no such + token). + +* | If there is a ``#pragma hdrstop`` preceding that token, back up to the + pragma position. + +* | If the position determined by the first two steps is inside a + preprocessing directive like an ``#if``, back up to (just after) the + previous top-level preprocessing directive. + +For example: + +.. code:: c++ + + /* Comments. */ + #define flag 1 + #if flag + #include "abc.h" + #else + #include "def.h" + #endif + #include + /* header-stop point. */ + int i = 1; + #include "abc.h" + /* header-stop point. */ + #if xyz + #include "def.h" + #pragma hdrstop + #endif + +Note that, while determining the prefix, ``#if``\ s and the like are not +evaluated, so code that will be skipped in the actual compilation can +nevertheless serve as a header stop point. This is particularly important +with ``#pragma hdrstop``. + +At the beginning of compilation, if precompiled headers are enabled, the +prefix for the primary source file is accumulated. This is done by opening +the primary source file, reading the beginning of it in a special mode +while building an in-memory representation of the preprocessing directives +read, and closing the source file. This is a separate process from the +normal compilation of the file, and is a necessary first step whether the +front end ends up using an existing PCH file or creating a new one. See +``build_prefix_information``. + +The prefix scan is done by setting ``building_pch_prefix`` and calling +``get_token`` once. That causes the scanning of all of the preprocessing +directives preceding the first "real" token of the primary source file. The +preprocessing directives are not evaluated in the usual way; they are just +placed on the prefix event list. (In particular, ``#include`` directives +are just accumulated like the others; the included files are not read.) +Each such event contains an enumeration code for the preprocessing +directive and a null-terminated string giving the text of the directive +following the directive keyword. + +After the initial prefix list is built up, the list is trimmed down by +discarding anything after a ``#pragma hdrstop`` and then, if the end is +inside an ``#if`` or the like, discarding preprocessing directives back to +the last top-level directive. + +If the primary source for the compilation is coming from ``stdin`` instead +of a file, the prefix construction cannot be done (and therefore PCH files +cannot be created or used). + +A list of the command-line options for the current compilation is also +built. It is also a linked list, and each entry on the list indicates one +command-line option. Options that have no effect on the state preserved by +PCH processing are not put on the list, but the rest (most of them) +are. The option code is represented by an enumeration, so the difference +between the single-letter form of the option and the keyword form is +erased, but in all other respects the list built up will have to match the +corresponding list for a PCH file exactly -- same options, same order. + +Using a PCH file +---------------- + +Once the prefix has been created, the front end will look to see if any of +the existing PCH files can be used to avoid some part of the compilation +for the current file. A host-dependent routine is used to fetch the names +of all PCH files in the appropriate directory (the directory can be +specified via the ``--pch_dir`` command-line option). Each file is checked +to make sure it is a regular file (not, say, a directory), that it has the +right header string identifying it as a PCH file, that the compiler version +number and generation date/time are the same, and that the flag indicating +that the file is completely written has been set. If any of those checks +fails, the file is closed and not considered further; in effect, it's +considered not to be a PCH file. + +The next round of checks seeks to determine whether the PCH file is +applicable to the current compilation. The front end checks that the +current directory and the one recorded in the PCH file are the same; that +the command-line event lists are the same; and that the preprocessing +directive event lists are the same (or the current file's prefix list is +longer than the prefix list in the PCH file). If those are okay, the front +end checks that the header files included in the PCH file have not changed +since the PCH file was built (this is done by checking the timestamps of +the files against the timestamps recorded in the PCH file). If the +timestamps indicate that the PCH file is out of date, it is deleted. + +A PCH file that makes it this far can be used, but it might not be the best +choice: There might be another PCH file that also matches but includes more +of the prefix preprocessing directives. Therefore, if the match is not +perfect, other PCH files are considered and the best-matching PCH file is +chosen. Each PCH file is closed after it is considered and must be reopened +later if selected as the best file. + +If the user has used the ``--use_pch`` command-line option, the indicated +PCH file is chosen directly. No other PCH files are considered, and the +applicability test is not done (at this point; see below). + +Once the best-matching PCH file is selected for a file called (say) +``x.C``, if the PCH file selected is not ``x.pch``, and there exists an +``x.pch``, ``x.pch`` is deleted. This is a simple way of getting rid of PCH +files that are no longer needed. + +Once a PCH file is selected, the front end state is restored from the +file. The PCH file is opened again and the prefix check is done again to +make sure the file has not changed since the first check. For a PCH file +specified via a ``--use_pch`` command-line option, this is the only +applicability test done (and if the file fails, a warning is issued and the +compilation continues without using the PCH file); for other cases, this is +a repetition of the applicability test already done. Next, the global +variables registered via ``register_pch_saved_variables`` are read and +restored. Finally, the contents of the various memory regions (IL and front +end) are restored. These are restored at the original addresses, so it is +not necessary to walk through the restored data to adjust pointers. (See +the section on memory management issues below for more information on this +aspect.) + +The restoration process occurs after most initialization of the front end, +so some variables are initialized then overwritten by the restoration from +the PCH file. + +Once the front end state has been restored from the PCH file, the lexical +routines are reset and the primary source file is opened again. The prefix +is skipped by doing a ``get_token`` in a special lexical mode. This is very +similar to the scan done to accumulate the prefix, in that initial +preprocessing directives are passed over uninterpreted. However, once the +preprocessing directive that marks the end of the matched part of the +prefix is processed, normal processing of preprocessing directives is +re-enabled. Shortly thereafter, the initial ``get_token`` finishes, and +normal compilation continues from that point (we know we are between +top-level declarations, so we can continue simply by entering the main +compilation-unit loop). + +The PCH restoration process restores the front end state after compilation +of the precompiled headers, but it doesn't duplicate the output that would +have been done on auxiliary files during the skipped part of the +compilation. Diagnostics that would have been written, and output lines on +the raw listing and cross-reference output files that would have been +generated, are not put out when a PCH file is used. If the front end is +configured to use an IL file, that file also is not generated as this +point. However, the IL file does get generated by a catch-up process done +after the point where a PCH file is generated or a decision is made not to +generate one; see below. + +Because the source sequence numbers of the original compilation may not +exactly match the sequence numbers in the current compilation (e.g., +because of whitespace differences), the source file mapping information in +the IL in the PCH file is restored as, in effect, the first include file on +the list under the primary source file of the current compilation. + +Creating a PCH File +------------------- + +After the front end has read in a PCH file or chosen not to use one, the +"normal" compilation process begins. When the compilation reaches the +header stop point, we have the option of creating a PCH file that +encapsulates the front end's state at that point for later restoration. + +Note that it is possible to both use and create a PCH file in the same +compilation, because the best-matching PCH file might contain only the head +of the full prefix. In that case, the internal state is restored from the +PCH file, then the rest of the prefix is compiled in the normal way, and at +the header stop point the compiled form of the full prefix is saved to a +new PCH file. + +The position of the header stop point was determined by the prefix scan at +the very beginning of the compilation. Its position is defined in terms of +a preprocessing directive, more specifically as the end of the processing +for that directive. Compilation starts up or continues in a mostly normal +way, with the header stop position set as a sort of breakpoint. When the +end of the indicated preprocessing directive is reached, the front end will +check to see whether a PCH file can be generated. + +On the way to the header stop point, some things may happen to preclude +generation of a PCH file: + +* | A reference to one of the macros ``__DATE__`` or ``__TIME__``. Since + these would change from compilation to compilation, there is no point + to saving the state of a compilation that uses them. + +* | A ``#pragma no_pch``. This is an explicit request not to generate a PCH + file. + +* | A ``#line`` directive. (Such directives could probably be allowed but + are not accommodated at present.) + +When the header stop point is reached, ``generate_precompiled_header`` is +called. It starts by making several checks that the current position is +acceptable: + +* | The current position is not inside a declaration, i.e., it is between + two file-scope declarations, or before the first such declaration, or + after the last. ``next_token_is_top_level_decl_start``, maintained by + the declaration-scanning routines, gives this information. + +* | The preprocessing ``#if`` stack is empty, i.e., the current position is + not inside a conditionally-compiled section. + +* | There have been no errors. + +* | The global variable ``cannot_create_pch_file`` is not set. It is set + for things that preclude generation of a PCH file (e.g., referencing + ``__DATE__``). + +If the current position is acceptable, a precompiled header file can be +written, and the front end will write out a file *xxx*\ ``.pch``, where "*xxx*" +is the base file name of the file being compiled. The user can specify a +different file name via the ``--create_pch`` command-line option. If a file +with the chosen name already exists, it is deleted. Precompiled header +files are written in the current directory by default, but another +directory can be specified via the ``--pch_dir`` command-line option. + +The following information is written to the PCH file, in the order given: + +* | An string that identifies the file as a PCH file, and gives the front + end version number and generation date/time. + +* | The current directory name (this may affect the include file search + order, etc.). + +* | The list of command-line events, i.e., all the command-line options + that could have an effect on PCH files. + +* | The list of preprocessing directive events, i.e., the sequence of + preprocessing directives whose compiled form is encapsulated in the PCH + file. + +* | Timestamps for all the header files referenced by the compilation (this + includes all files, not just those included directly from the primary + source file). + +* | The values of all front end variables registered with + ``register_pch_saved_variables``. + +* | The contents of all memory regions, i.e., the front end memory region + and all IL memory regions. + +* | Once the rest of the information has been written, the front end goes + back to the header and writes a flag indicating that the PCH file is + complete. This flag prevents other compilations from using a PCH file + that is not yet completely written. + +After writing out the PCH file, the front end continues with +compilation. Because the header-stop point has been passed, no further +precompiled-header checking or processing is done in the rest of the +compilation. + +If an IL file is being generated, function scope memory regions that are +completed before the header stop point are held in memory and neither +written to the IL file nor freed. Once the header stop point has been +reached, and a PCH file has been written or a decision made not to write +one, those memory regions are written to the IL file and freed. + +.. _memory-management-issues: + +Memory Management Issues +------------------------ + +As was mentioned earlier, one of the prerequisites for fast PCH processing +is the ability to bring memory regions back into memory at the same +addresses they had when written out. Clearly, that requires that (a) +nothing else happens to have been allocated at the desired addresses, and +(b) there is some way to request allocation or assignment of those +addresses so that no later allocation uses them. + +The front end provides two schemes that accomplish this goal. The first and +better scheme requires memory mapping support from the underlying operating +system (UNIX and Windows NT versions are provided). A fixed set of +addresses is chosen for all memory regions (the exact addresses are either +left to the discretion of the operating system or chosen in the +configuration of the front end; see +``USE_FIXED_ADDRESS_FOR_MMAP``). Initially, these memory addresses are +mapped onto a temporary file. When a PCH file is created, the memory is +written to the PCH file (using normal file I/O). On restoration of a PCH +file, the default mapping to the temporary file is released, and the +reserved memory addresses are mapped onto the PCH file being restored. This +brings the saved information into the front end's address space without any +immediate I/O. (In the actual implementation, the memory addresses are +tentatively mapped once to verify that the mapping can be done, and then, +once it is known that all the mappings will be successful, they are done +again with the official mappings.) All dynamically allocated memory that is +not part of a memory region is just allocated in the normal way through +``malloc``, since it need not be at any particular addresses. This means, +in effect, that there are two completely separate pools of memory -- memory +region allocations are done at the fixed mappable addresses, and everything +else is done more casually in the traditional way. + +The other implementation does not require memory mapping, but it is +slightly less friendly to users. Very early in the execution of the front +end a large amount of memory is preallocated in large blocks and saved off +to the side for use exclusively for memory regions. This is done early so +that the allocated addresses are reproducible (i.e., one can get the same +addresses on all compilations). If the allocations were done later, their +addresses would be affected by minor variations in the amount of memory +used during the command-line processing, and perhaps by memory allocated by +runtime routines of the host C compiler (e.g., ``printf`` formatting). As +the compilation proceeds, requests for memory for memory region blocks are +satisfied by taking blocks from this preallocated list. All other +allocations (for things not in memory regions) are done directly through +``malloc``. When a PCH file is created, the memory addresses of blocks are +written to the PCH file along with the block contents. Also written is an +array of the preallocated memory block addresses used, serving as a sort of +allocation history (this array is written to the file also in the +memory-mapped mode). Once the header stop point is passed, and either a PCH +file was written or a decision was made not to write one, the remaining +preallocated memory is freed, and subsequent allocation for all purposes is +done directly through ``malloc``. + +If the preallocated space is too small to hold the memory regions created +up to the header stop point, the precompiled header cannot be created +(since the remaining required space cannot be allocated at predictable +addresses). A warning is issued, telling the programmer that the +``--pch_mem`` option can be used (on a subsequent invocation of the front +end) to request a larger preallocation to avoid the problem. The +compilation continues normally -- the PCH file cannot be created, but the +compilation can be completed regardless. + +Since the preallocated blocks have a fixed (though large) size, any +requirement to allocate a single entity larger than that fixed size cannot +be satisfied from the preallocated pool, and therefore precludes generation +of a PCH file. This could happen, for example, if a user program contains a +single literal string containing 200,000 characters. Again, the compilation +continues without difficulty, but a warning is issued that a PCH file could +not be generated. + +When a PCH file is read back in the non-memory-mapped mode, the allocation +history information history is read in from the PCH file and used to check that +the preallocated blocks are indeed at the same addresses (on some systems, in +spite of the care taken to allocate the blocks early, the addresses still +change; for example, under MS-DOS, the addresses can be affected by placing a +new TSR program in memory). If the addresses are not right, it is still +possible to give up on using the PCH file and continue with normal compilation. +If the history information matches, the memory regions are read in: The address +for each block is read from the file, the preallocated block at the right +address is assigned, and the memory region contents are read from the PCH file +into the proper addresses. + +It should be noted that if a given environment provides a (nonstandard) way +of allocating memory from a pool distinct from the normal ``malloc`` +allocation pool, the non-memory-mapped approach can be made to work without +preallocation and without the ``--pch_mem`` command-line option. + +When multiple source files are specified in one invocation of the front +end, the preallocation scheme breaks down: The first file can be processed +okay, but on subsequent files the preallocated memory has been used and +reclaimed and is no longer in quite the right predictable state. This can +probably be solved in some way, but the current implementation takes the +easy way out and disallows PCH file use on compilations where more than one +source file is specified on the command line. + +.. _predefined-macro-defs: + +Predefined Macro Definition File +================================ + +Macros may be predefined either by explicit calls of +``enter_predef_macro``, and/or through use of a predefined macro definition +file. Whether or not the front end reads a predefined macro definition file +is controlled by the ``DEFAULT_USE_PREDEFINED_MACRO_FILE`` macro. The file +``EDG_BASE/EDG_AUXILIARY_INFO_DIR_NAME/PREDEFINED_MACRO_FILE_NAME`` is read +to provide the macro definitions. The ``EDG_BASE`` directory can be +specified by an environment variable (``EDG_BASE``), build-time macro +(``DEFAULT_EDG_BASE``), or command-line option +(``--edg_base_dir``). ``EDG_AUXILIARY_INFO_DIR_NAME`` and +``PREDEFINED_MACRO_FILE_NAME`` are configuration macros with default values +of "``lib``" and "``predefined_macros.txt``". If +``EDG_AUXILIARY_INFO_DIR_NAME`` is null, the ``EDG_BASE`` directory is used +directly. The format of the entries in the file is: + +.. code:: text + + mode,!mode,mode cannot_redefine macro_name macro_value + +* | ``mode`` is a label from the predefined macro modes table. The macro is + defined if the mode is set, or if the mode is not set when ``!mode`` is + used. The macro is defined if any of the mode tests is TRUE. The set of + mode values is specified in ``host_envir.h``. + +* | ``cannot_redefine`` indicates whether the predefined macro may later be + redefined. The value must be "yes" or "no". + +* | ``macro_name`` is the name of the macro to be defined. + +* | ``macro_value`` is the value to which the macro should be defined. All + of the characters until the end of the line are used as the macro + value. + +For example: + +.. code:: text + + gcc no __HAVE_BUILTIN_SETJMP__ 1 + gpp no __CHAR_BIT__ 8 + gnu no __GNUC_PATCHLEVEL__ 0 + gnu no __WINT_TYPE__ unsigned int + gnu,microsoft __IS_GNU_OR_MICROSOFT_MODE 1 + +A script (``make_predefined_macro_file``) is provided that automatically +generates the ``predefined_macros.txt`` file for a given version of gcc/g++ +or clang. It does this by invoking gcc and g++ or clang and capturing the +predefined macro information. diff --git a/doc/_sources/build.rst.txt b/doc/_sources/build.rst.txt new file mode 100644 index 0000000..2bda6bf --- /dev/null +++ b/doc/_sources/build.rst.txt @@ -0,0 +1,887 @@ +========================================== +Configuring and Building the C++ Front End +========================================== + + + +This chapter is an introduction to configuring and building the front end and +the various tools that come with it. Bringing up the front end on a new +platform typically can be done in a few hours, and if the platform is close +enough to a system for which sample configurations are available (e.g., Linux, +Windows, etc.) that initial process can be reduced to a matter of minutes. + +The front end can be configured for a variety of uses. For example, it could +be part of a compiler with a custom code generator, or a compiler with a +portable C-generating back end (the latter is provided). Alternatively, it +could be part of a source analysis tool (without a code generator) or of a +source transformation/translation tool (using the supplied C/C++-generating +back end). Some of the tools supplied with the front end will not be needed +for some of these applications. For example, a source analysis tool is +unlikely to need the supplied prelinker tool to perform automatic +instantiations. The details of the build process are therefore likely going to +depend on the application. However, the overall structure of the source code +is simple enough that customizing the build process should be straightforward. + +The source code implementing the front end and associated tools is written in +C++11 (i.e., ISO/IEC 14882:2011) and can be compiled using relatively current +C++ compilers. The front end has been compiled with g++ 4.8.1, clang 3.3, and +Microsoft Visual Studio 2015 (build 19.00.24215.1). The front end does not +explicitly throw or catch exceptions and does not use C++ features that would +requite runtime type information (RTTI), so those features can be disabled when +compiling the front end (for compilers that support that). (The sample +run-time support library is written in C++ and (if needed) is normally compiled +using the front end itself. When building on Microsoft Windows, a component is +also available to read metadata in C++/CLI mode: This is written in C++ for the +Microsoft C++ compiler.) + +Directories and Files in a Release +================================== + +After unpacking a release, its top-level directory should contain the following +directories and files: + +.. list-table:: + + * - | ``Makefile`` + - | In a Unix-like environment (including Windows-hosted environments like + Cygwin or MinGW), the ``make`` utility can be used to build the front + end and its supporting tools and components. This top-level + ``Makefile`` runs the ``make`` tool in the various subdirectories as + needed. It is geared primarily toward building a compiler using the + C-generating back end along with the sample run-time support library. + A ``make`` process using this top-level ``Makefile`` may therefore + terminate with errors for other situations; in that case, the + ``Makefile``\ s in the appropriate subdirectories (especially + ``misc/`` and ``src/``) are still likely to be useful. + * - | ``src/`` + - | The directory containing the source files of the C++ front end and its + optional components (such as the C- and C++-generating back ends). + This directory contains a subdirectory ``disp/`` used to build the + stand-alone IL display utility. In addition to source code, the + ``src/`` directory also holds the ``Changes`` file, which describes + the various changes made to the front end in the current and previous + releases. Note that most of the source files have the ``.c`` suffix + that would normally indicate a C source file. Starting with the 6.0 + release, these files contain C++ source code and must be compiled + using a C++ compiler (with the C++11 dialect). The original filenames + have been maintained to make patching files easier. If desired, + symbolic links can be added to accommodate build environments as + necessary. + * - | ``bin/`` + - | Initially, this directory contains a script ``eccp`` that can be used + to run the front end much like typical C++ compilers in Unix-like + environments (such as ``CC`` and ``g++``). See + ":ref:`the-eccp-script`" for details. Once the front end is built (in + the ``src/`` directory), it can be moved here for invocation by + ``eccp`` (this is done automatically if the top-level ``Makefile`` is + used). + * - | ``sample_edg_eccp_config/`` + - | The ``eccp`` script can be configured in various ways. This directory + contains sample configuration files for some popular Unix-like + operating systems (Linux, MacOS X, and Solaris). It also includes a + script ``make_g++_incl_paths`` (to be run from the ``lib/`` directory) + to establish the location of ``g++``\ 's header files (in cases where + ``eccp`` should rely on a native ``g++`` installation for system and + standard header files). + * - | ``include/`` + - | This directory contains prototype implementations for a few standard + C++ header files that are closely tied to the compiler's internals. + (For example, the contents of the ```` header must match the + compiler's understanding of the ``std::type_info`` type.) + * - | ``lib_src/`` + - | This directory contains C++ source code implementing a minimal C++ + run-time support library (in support of C++ features like exception + handling, the ``dynamic_cast`` operator, and ``operator new``). The + library also includes support for certain extensions to the C89 + language (like operations on complex floating-point types and support + for variable-length arrays). All of this code is primarily meant for + demonstration purposes, and is probably not suitable for end-user + products: It is very portable, but not very efficient. It is usually + not needed for non-compiler applications such as source analysis or + source-to-source translation. This directory also contains a + ``Changes`` file describing the history of the run-time support + library. + * - | ``lib/`` + - | Initially, this directory only contains a file + ``predefined_macros.txt``. This file is read by the front end to + predefine certain macros. It is typically used to define macros that + are defined by compilers being emulated (see + ``make_predef_macro_table`` and ``make_win_predef_macro_table.c`` for + utilities that automatically generate a set of predefined macros for + GNU and Microsoft compilers, respectively). Once the run-time support + library is built (in the ``lib_src/`` directory), it can be moved here + so the ``eccp`` script can find it (this is done automatically if the + top-level ``Makefile`` is used). Note that this directory is only + used when an unnamed "legacy" target configuration is specified -- see + ``lib_``\ *target*\ ``/`` below for cases where a named target + configuration is used. + * - | ``lib_``\ *target*\ ``/`` + - | Target-specific version of the ``lib/`` directory described above + used when the "``--target`` *target*" command-line option is + specified. This directory can have the same + ``predefined_macros.txt`` and ``libC.a`` files as ``lib/``, or can + be different as required by the specific target. If a + target-specific version of ``libC.a`` is required, it must be + built manually (see ``lib_src/Makefile``). + * - | ``misc/`` + - This directory contains sources for four utility programs (and a + ``Makefile`` to build them) to build and configure the front end: + + * ``make_predef_macro_table``: A script to generate a predefined macros + file (like ``lib/predefined_macros.txt``) to match a given version of + ``gcc/g++``. + * ``make_win_predef_macro_table.c``: A program to generate a + predefined macros file (like ``lib/predefined_macros.txt``) to match + a given version of Microsoft Visual Studio. Note that this program + is not built by the ``Makefile`` (and must be built manually if + required). + * ``mk_errinfo.c``: A program to translate the files describing the + diagnostics emitted by the front end to plain C++ code. + * ``dettarg.c``: A utility to determine basic configuration settings for + a target platform (e.g., the size and alignment of various integer + types). See ":ref:`the-detarg-utility`" below. + * - | ``util/`` + - This directory contains sources for three utility programs (and a + ``Makefile`` to build them) that can be used in conjunction with the + front end (e.g., by the ``eccp`` script): + + * ``edg_prelink.c``: A program that implements automatic template + instantiation by re-running the front end to generate missing + instantiations. + * ``edg_decode.c``: A name demangler (which can, for example, be used on + the output of a linker to make that output more readable). It is + an interface for the actual demangling logic, which is contained + in ``decode.c`` to allow its use in other programs as well. + * ``edg_munch.c``: A utility that generates a C program that will call + all required start-up initialization routines. This is needed only + if your linker does not provide a way to invoke code automatically at + program start-up time. + * - | ``doc/`` + - | This directory contains a PDF version of this document (``plm.pdf``). + * - | ``README`` + - | A plain text file summarizing some of the information in this chapter. + +Configuring the Front End +========================= + +A large number of behaviors of the front end can be configured by appropriately +defining various configuration macros. These macros can affect which +components of the front end are enabled, which dialects are supported, what +host and target platform characteristics are assumed, and so forth. See +:ref:`macro-defaults` below for information about where all the macros are +documented. + +Beginning with version 4.10.1 of the front end, a facility to provide for +run-time selection of a target configuration (through the use of the +``--target`` command-line option) is provided. To support this run-time +target-configuration feature, a number of the configuration macros have +been designated as "target-specific". See +:ref:`target-specific-configuration` for more information. + +The ``defines.h`` File +---------------------- + +It is highly recommended that the front end be configured by defining the +appropriate macros in the ``src/defines.h`` file. Occasionally, it may be +expedient to set the macros directly through ``src/Makefile`` or a similar +build-system mechanism (e.g., to enable debugging facilities), but modifying +other front end sources to set the configuration macros is not a recommended +option. + +Sample configuration files are provided in the ``src/`` directory for Linux, +MacOS X, Solaris, and Windows (``defines.h.linux``, ``defines.h.macosx``, +``defines.h.solaris``, and ``defines.h.win32``, respectively). These are +recommended starting points when building the front end on these platforms: For +example, to build the front end on MacOS X, one can start by copying +``src/defines.h.macosx`` to ``src/defines.h``. + +A partial configuration file ``src/defines.h.proto`` is also provided: It +contains the macros needed to enable the modern IA-64 ABI (also called the +Itanium ABI), but it must be complemented by additional target characteristics +(which can be obtained by running the ``dettarg`` utility described next). + +.. _the-detarg-utility: + +The ``dettarg`` Utility +----------------------- + +File ``misc/dettarg.c`` is a simple C++ program that can be compiled, linked, +and run on a system for which the compiler is targeted to determine some basic +characteristics (like endianness, size and alignment of fundamental types, and +so forth) of that target platform. The output produced by ``dettarg`` is in a +form suitable for addition to the ``src/defines.h`` file. + +.. _macro-defaults: + +``lang_feat.h``, ``host_envir.h``, ``targ_def.h``, and ``target.h`` +------------------------------------------------------------------- + +A typical ``src/defines.h`` file will not explicitly set all the configuration +macros available in the front end. Instead, most macros are just left to their +default values. These defaults are specified in four header files. Perhaps +more importantly, these header files are also the place where all the +configuration macros are documented (in comments preceding the directives +determining the default values). The header files are as follows: + +.. list-table:: + + * - | ``src/lang_feat.h`` + - | Configuration macros controlling language features. Some macros + control a single language feature detail, whereas others control whole + dialects. + * - | ``src/host_envir.h`` + - | Configuration macros that determine characteristics of the host + platform (the platform on which the front end runs). + * - | ``src/targ_def.h`` + | ``src/target.h`` + - | Configuration macros describing characteristics of the target platform + (the platform for which code must be generated). Many of these macros + have names that begin with ``TARG_``. Characteristics that are + entirely fixed at the time the front end is built are normally + documented in ``targ_def.h``, whereas ``target.h`` describes target + characteristics that can be overridden for every invocation of the + front end. + +These descriptions are generally correct, but occasionally a configuration +macro may need to be placed in a header that doesn't quite match that macro's +function. For example, ``targ_def.h`` contains some macros that would more +naturally belong to ``lang_feat.h``, but the default value of the macro depends +on a target platform characteristic. + +Note that these files should not be modified to set configuration options. +Instead, the appropriate macros should be defined in ``src/defines.h`` or +perhaps in a ``Makefile`` or similar build system tool. + +``basics.h`` and Build Environment Configuration +------------------------------------------------ + +The front end is written in portable C++11 (except for one file in the +Microsoft dialect if the capability of reading Microsoft metadata for +C++/CLI is needed). The ``basics.h`` header adds abstractions to allow +most of the remainder of the front end source code to be written without +concern for variations in system headers. The build environment type can +often be determined by the preprocessor tests in ``basics.h``, but when +that is not the case, one should define one of the following build +environment macros (on the command-line or in ``src/defines.h``): +``__ANSIC__`` (for ANSI C; also used for Borland and Microsoft C under +MS-DOS and Windows), ``__SYSV__`` (for System V), ``__BSD__`` (for Berkeley +4.n), ``__VMS__`` (for VAX/VMS C; this will cause ``__SYSV__`` to be +defined, but the ``__VMS__`` flag will control some minor variations from +System V). + +Some ANSI library functions do not exist in all system libraries. This problem +is handled by remapping such function calls (via macros) to functions that do +exist. For example, traditional Berkeley UNIX does not have ``memcpy``, but +does have ``bcopy``; the front end source is written using calls to ``memcpy``, +but when it is compiled with the ``__BSD__`` flag set, a macro ``memcpy`` +transforms those calls into calls to ``bcopy``. Another function of the build +environment macros is controlling inclusion of appropriate header files. Even +when identical functions exist on different host systems, they are sometimes +defined by different header files (e.g., Berkeley systems use ```` +instead of the ANSI/System V ````). ``basics.h`` includes the +appropriate definitions for the most common functions (standard I/O, string and +block operations, and character typing); any other required headers are +included only in those source files that need them, with appropriate +conditional compilation surrounding the ``#include``\ s. + +Very occasionally, the macro definitions in ``basics.h`` must be modified +directly (i.e., by editing ``basics.h``). Specifically, when ``__ANSIC__`` is +not set, some ``#define``\ s in ``basics.h`` must establish values for about a +dozen of the most useful values (specifically, ``CHAR_BIT``, ``CHAR_MIN``, +``CHAR_MAX``, ``UCHAR_MAX``, ``SHRT_MAX``, ``INT_MAX``, ``LONG_MAX``, +``LONG_MIN``, and ``ULONG_MAX``). These should be set to proper values for the +host. ``sizeof_t`` should also be defined as the integral type to be used for +sizes of things. Usually this is the same as ``size_t``, but it might be +different if ``size_t`` is too small (e.g., 16 bits). These values cannot be +set in ``defines.h`` or on the compilation command line. + +Finally, ``basics.h`` also determines the default values of some macros that +control the presence of code aiding in the development of the front end (e.g., +``DEBUG`` for debugging aids and ``CHECKING`` for internal consistency checks). + +The front end requires a minimal C++ standard library. Prior to release 6.0, +the front end was written in C and used various host C standard library +functions (e.g., for file I/O). When switching to C++, it was decided not to +use the additional portions of the C++ standard library that became available +(e.g., ``std::string``) as this would add a burden to our customers and would +require testing against many versions of the C++ standard library. Instead, a +small subset of library-like utility functions was developed for the front end +(in ``util.h``). As a result, the portion of a C++ standard library that the +front end requires is about the same as that provided by a C standard library. + +Commonly-used Configuration Macros +---------------------------------- + +The following subsections describe a selection of macros that commonly appear +in ``src/defines.h``. This list is not meant to be exhaustive. Many (but not +all) configuration macros are used to initialize global variables with a +similar name, and it is the value of the variable that controls a particular +behavior. For example, ``GCC_IS_GENERATED_CODE_TARGET`` (described below) +initializes the global variable ``gcc_is_generated_code_target``. This allows +particular behaviors to be controlled at run time (via the command line or via +custom code additions). + +Note that none of the configuration macros described below are +"target-specific" (so, for example, there can't be one target configuration +where ``DO_IL_LOWERING`` is TRUE and another where it is FALSE). + +Optional Components +^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + + * - | ``BACK_END_SHOULD_BE_CALLED`` + - | TRUE if a back end should be called (the call is to a function + ``back_end``). + * - | ``DO_IL_LOWERING`` + - | TRUE if IL lowering (rewriting C++-specific constructs in the + intermediate language in C form) should be done. + * - | ``BACK_END_IS_C_GEN_BE`` + - | TRUE if the C-generating back end should be used. If FALSE, some + other back end must be supplied or ``BACK_END_SHOULD_BE_CALLED`` must + be FALSE. The C-generating back end takes the lowered IL for a + translation unit and generates a C source file suitable for + compilation to binary code by a native C compiler. + * - | ``BACK_END_IS_CP_GEN_BE`` + - | TRUE if the C++/C-generating back end should be used. If FALSE, some + other back end must be supplied or ``BACK_END_SHOULD_BE_CALLED`` must + be FALSE. The C++/C-generating back end is intended for + source-to-source transformation applications. It takes the unlowered + IL for a translation unit and generates a source file that is similar + to the original C or C++ input. + * - | ``MINIMAL_INLINING`` + - | TRUE if minimal inlining of function calls should be done during IL + lowering. This option is intended mostly for use with the + C-generating back end, and is limited to inlining calls to very simple + functions that are defined inline in the source. + +Support for Source Language Dialects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + + * - | ``GNU_EXTENSIONS_ALLOWED`` + | ``DEFAULT_GNU_COMPATIBILITY`` + | + - | Control whether compatibility with GNU's ``gcc`` and ``g++`` compilers + should be enabled, either by default or only when the ``--gcc`` or + ``--g++`` command-line options are specified. + * - | ``MICROSOFT_EXTENSIONS_ALLOWED`` + | ``DEFAULT_MICROSOFT_COMPATIBILITY`` + | + - | Control whether compatibility with Microsoft's C and C++ compilers + should be enabled, either by default or only when the ``--microsoft`` + command-line option is specified. + * - | ``SUN_EXTENSIONS_ALLOWED`` + | ``DEFAULT_SUN_COMPATIBILITY`` + | + - | Control whether compatibility with Sun CC should be enabled, either by + default or only when the ``--sun`` command-line option is specified. + +Setting an ...\ ``_ALLOWED`` macro to TRUE makes the corresponding +``DEFAULT_``\ ... macro TRUE by default. If the front end is configured to +support multiple dialects, the ``DEFAULT_``\ ... macros must be set explicitly +to avoid selecting more than one dialect as the default. + +.. list-table:: + + * - | ``CPPCLI_ENABLING_POSSIBLE`` + | + - | Control whether a mode compatible with Microsoft's C++/CLI extensions + should be available through the command-line option ``--cppcli``. + Setting this option to TRUE requires that + ``MICROSOFT_EXTENSIONS_ALLOWED`` also be TRUE. + * - | ``DEFAULT_CPPCLI_ENABLED`` + | + - | TRUE if C++/CLI extensions should be enabled by default when Microsoft + extensions are enabled. + +IL Features +^^^^^^^^^^^ + +.. list-table:: + + * - | ``EXTRA_SOURCE_POSITIONS_IN_IL`` + | + - | TRUE if certain additional IL entries, besides those that already have + ``a_source_correspondence`` fields, should contain source position + information. For example, expression nodes will record the starting + and ending position of the corresponding expression, as well as the + position of that expression's top-level operator. Note that this can + increase the size of the IL substantially. + * - | ``EXPR_RANGE_MODIFIERS_IN_IL`` + | + - | TRUE to extend the tracking of source ranges for expressions by + including position information for operators that generally do not + appear in the IL, such as ``*``, ``&``, and ``()``. + * - | ``RECORD_MACROS_IN_IL`` + | ``FULLY_RESOLVED_MACRO_POSITIONS`` + | ``MACRO_INVOCATION_TREE_IN_IL`` + | + - | Indicate whether extra information should be recorded in the IL to + track macros and their expansions. Setting either of the latter two + configuration macros to TRUE can increase the size of the IL + substantially. + * - | ``PROTOTYPE_INSTANTIATIONS_IN_IL`` + | + - | TRUE if prototype template instantiations (i.e., the parsed generic + form of templates) should be recorded in the main IL tree. + +Target Platform Options +^^^^^^^^^^^^^^^^^^^^^^^ + +Note that although these configuration macros deal with issues related to the +target, they are not considered "target-specific" (because these values cannot +differ between target configurations). + +.. list-table:: + + * - | ``IA64_ABI`` + - | Controls whether the IA-64 ABI standard is used for code generation + and object layout. This is a "modern" C++ object layout (unlike the + cfront layout), and is a good starting point even on architectures + other than IA-64 (Itanium). This ABI is used by many versions of g++ + (3.2 and later). For a complete specification, see + ``www.codesourcery.com/cxx-abi``. See also other macro names + beginning with ``IA64_ABI``, some of which enable compatibility with + the ARM EABI variant of the ``IA64_ABI``. If ``IA64_ABI`` is set to + FALSE (or 0), a cfront-like ABI is used instead. + * - | ``DEFAULT_GNU_ABI_VERSION`` + | ``DEFAULT_EMULATE_GNU_ABI_BUGS`` + | + - | Control the emulation of the GNU variant of the IA-64 ABI. + * - | ``GCC_IS_GENERATED_CODE_TARGET`` + | ``GNU_TARGET_VERSION_NUMBER`` + | ``MSVC_IS_GENERATED_CODE_TARGET`` + | ``MSVC_TARGET_VERSION_NUMBER`` + | ``SUN_IS_GENERATED_CODE_TARGET`` + | ``SUN_TARGET_VERSION_NUMBER`` + | + - | Control whether the code generated by the C- or C++-generating back + end should target a specific GNU, Microsoft, or Sun compiler. This is + information is used to avoid limitations of those compilers and to + exploit extensions provided by those compilers. + * - | ``CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT`` + | + - | TRUE if the C++-generating back end should generate code that matches + the dialect selected for the front end. (E.g., if the front end is + set to parse GNU code, the back end can generate GNU ``__attribute`` + constructs, whereas if the front end is set to accept Microsoft + extensions, the back end might generate ``__declspec`` specifiers.) + +Front End Behaviors +^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + + * - | ``MAKE_FRONT_END_CALLABLE`` + | + - | TRUE if, instead of having its own main program, the front end is to + be linked as part of some other main program. When this flag is set, + the ``EDG_MAIN`` macro provides the name of the main entry point into + the front end.The front end can then be called repeatedly by the same + process (each call reinitializes the front end's internal state). + * - | ``COMPILE_MULTIPLE_SOURCE_FILES`` + | + - | Indicates that the front end should be capable of compiling a list of + source files in a single invocation. + * - | ``IL_SHOULD_BE_WRITTEN_TO_FILE`` + | + - | TRUE if the intermediate language should be written to a file; FALSE + if the intermediate language is passed in memory to the back end + (assuming ``BACK_END_SHOULD_BE_CALLED`` is TRUE). + * - | ``USING_DRIVER`` + - | Indicates that the front end is being run from a driver program. + Setting this flag suppresses termination messages (like + "``Compilation terminated.``") written to the error output file + because it is expected that the driver will write those. + * - | ``MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED`` + | + - | TRUE if multibyte character sequences (e.g., like Unicode UTF-8 or + those in the Japanese SJIS encoding) are supported in comments, + string literals, identifiers, and character constants. + * - | ``USE_OWN_SJIS_MULTIBYTE_CHAR_PROCESSING`` + | + - | TRUE if, instead of the routines in the standard C library (e.g., + ``mblen``), custom routines in ``host_envir.c`` should be used to deal + with Japanese SJIS multibyte characters in source code. + * - | ``LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED`` + | + - | Indicates the locale to be established by a call to ``setlocale`` to + get the desired processing of multibyte characters from the C library + while reading the source code. + * - | ``UNICODE_SOURCE_SUPPORTED`` + | + - | TRUE if the multibyte character set to be supported is Unicode encoded + as UTF-8. UTF-16 is also accepted, and is translated to UTF-8 + immediately on input. + +Development Aids +^^^^^^^^^^^^^^^^ + +.. list-table:: + + * - | ``DEBUG`` + - | Enables additional code in the front end to simplify debugging. This + includes flow/event tracing options, routines that can be called from + a debugger to examine the IL, and an option to output the settings of + the configuration macros. + * - | ``CHECKING`` + - | Enables inexpensive internal consistency checking. Recommended even + in production builds. + * - | ``EXPENSIVE_CHECKING`` + - | Enables more expensive internal consistency checking. (Not generally + recommended for production builds.) + * - | ``WRITE_CPPCLI_PORTABLE_ASSEMBLIES`` + | + - | When TRUE, this enables an internal command-line option "``--set_flag + generate_portable_assemblies``" that causes a front end built with + support for C++/CLI (for Microsoft Windows) to write out all + assemblies used in the compilation (likely including ``mscorlib.dll``) + to be written in the current directory in a format that is readable on + non-Windows platforms (i.e., with a front end not built with + ``EDG_WIN32`` set to TRUE). Since the assemblies are written in the + current directory with their original file name (e.g., + "``mscorlib.dll``"), care should be taken that no required assemblies + are in the current directory when the front end is invoked in this + way. + +.. _target-specific-configuration: + +Target-Specific Configuration +----------------------------- + +A target configuration is defined by giving appropriate values to a set of +configuration macros (dubbed the target-specific configuration macros). +Multiple target configurations can be specified when the front end is built; +the ``--target`` command-line option is used to select a non-default target +configuration when the front end is invoked. The ``--dump_legacy_as_target`` +command-line option can be used to display the set of target-configuration +macros. + +Each target-specific configuration macro has a "legacy" version, i.e., one +without any target-specific suffix, as well as a version for each target +configuration that is specified when the front end is built. Non-legacy +configuration macro names are formed by appending an underscore and the target +configuration name to the legacy configuration macro name. For example, the +legacy macro ``TARG_LITTLE_ENDIAN`` would have a corresponding +``TARG_LITTLE_ENDIAN_win32`` configuration macro for the ``win32`` target +configuration. + +By default, the legacy configuration has no name, but one may be specified by +setting ``LEGACY_TARGET_CONFIGUATION_NAME`` to the desired name. The default +target configuration can be specified by giving its name as the definition of +the ``DEFAULT_TARGET_CONFIGURATION_NAME`` configuration macro; otherwise, the +legacy target configuration will be used as the default. + +Note that specifying a named target configuration (either explicitly or through +defaults) requires that an ``$EDG_BASE/lib_``\ *target*\ ``/`` directory be +present at run time. Having target-specific ``$EDG_BASE/lib_``\ *target*\ +``/`` directories allows each target configuration to have different predefined +macros (e.g., to define ``_M_IX86`` in one and ``_M_X64`` in another). + +A legacy configuration can be configured manually (by specifying values for +each target-specific macro), or automatically (by using the ``dettarg`` tool +and defaults that many configuration macros have). The +``--dump_configuration`` command-line option provides a convenient display of +all configuration macros and their settings. + +A non-legacy target configuration is most easily generated as a derivative from +an existing legacy target configuration using the ``--dump_legacy_as_target`` +command-line option. This option takes a target configuration name and +generates a list of the target-specific macro names for the given target +configuration name along with the values of the legacy configuration. This +file (after verifying that ``TARGET_CONFIGURATION_``\ *number* is unique) can +then be included in ``defines.h`` as the basis for a new target configuration. +Additional target configurations can be generated from different legacy +configurations in the same manner, or by using an existing target configuration +as a template (and changing the target configuration name in each macro, along +with the ``TARGET_CONFIGURATION_``\ *number*). Note that all target-specific +configurations must share the same non-target-specific configuration, so for +instance, it's not possible to have an IA-64 ABI target configuration and a +Cfront target configuration in the same front end configuration (because +``IA64_ABI`` is not a target-specific configuration macro and must have the +same value across all target configurations). + +Note that it is inadvisable to use a target-specific global variable as the +value for a target-specific configuration macro. For example: + + ``#define TARG_IA64_VTABLE_ENTRY_INT_KIND targ_ptrdiff_t_int_kind`` + +is subject to race conditions (because ``targ_ptrdiff_t_int_kind`` may or may +not have been initialized before its value is used to set +``targ_ia64_vtable_entry_int_kind``). The following will work as expected: + + ``#define TARG_IA64_VTABLE_ENTRY_INT_KIND TARG_PTRDIFF_T_INT_KIND`` + +An important aspect of this architecture is that each legacy configuration +macro has an associated global variable whose value is set at initialization +time to the value of the (legacy or per-target) configuration macro for the +selected target. Because of this, it is imperative that user modifications to +the front end use the run-time value of global variables rather than the +compile-time values of legacy configuration macros. + +Replaceable Code +---------------- + +Occasionally, some customizations are needed that cannot simply be expressed +through configuration macros. Those may require instead that various routines +be replaced with custom code. The following files in ``src/`` are written with +such modifications in mind: + +.. list-table:: + + * - | ``fixed_pt.c`` + - | Routines implementing operations on fixed-point values (only supported + in some configurations). + * - | ``float_pt.c`` + - | Routines implementing operations on floating-point values. + * - | ``host_envir.c`` + - | Includes routines dealing with operations on files and directories. + Signal handlers can also be set up there. + * - | ``sys_predef.c`` + - | Routines to predefine platform-specific entities (macros, types, + routines, etc.) + +Building the Front End +====================== + +Using the Top-Level Makefile +---------------------------- + +Assuming a Unix-like environment, a complete demonstration compiler can be +configured and built using a sequence of shell commands like the one shown +below (for a typical Linux platform, but other Unix-like environments are +similar). The sequence assumes that the current directory is the top-level +directory of a freshly unpacked release. + +.. code:: bash + + cp sample_edg_eccp_config/edg_eccp_config.linux edg_eccp_config + cp src/defines.h.linux src/defines.h + cd lib + ../sample_edg_eccp_config/make_g++_incl_paths + ../misc/make_predef_macro_table + cd .. + export EDG_BASE=`pwd` # or setenv EDG_BASE `pwd` + make + +This builds a front end with a C-generating back end, along with a run-time +support library and helper tools such as the prelinker and demangler. The +entire toolset can be driven with the ``eccp`` script (see +":ref:`the-eccp-script`"). + +Building the Front End Only +--------------------------- + +In an environment with a Unix-like ``make`` utility, the front end can be +compiled and linked by running + +.. code:: bash + + make edgcpfe + +in the ``src/`` directory (after constructing an appropriate ``defines.h`` file +and editing ``src/Makefile`` to select the desired compiler and compiler +options for building the front end). This can be useful to update the front +end for modifications after building the complete tool set, or when only the +front end program itself is desired. If ``make`` is not available, the front +end can be built using the following manual steps. + +* | Configure the ``defines.h`` file. For example, under Windows the following + is a useful starting point: + + .. code:: powershell + + copy src\defines.h.win32 src\defines.h + +* | In the ``misc/`` directory, compile and link the ``mk_errinfo`` program + into a ``mk_errinfo`` executable file. For example, using a Windows + command line and the Microsoft C++ compiler: + + .. code:: powershell + + cd misc + cl /TP /I..\src mk_errinfo.c + cd .. + + | See :ref:`mk-errinfo` for additional information about ``mk_errinfo`` and + the format of its input files. +* | In the ``src/`` directory, translate the diagnostic messages using the + ``mk_errinfo`` program that was built in the previous step. For example, + using a Windows command line + + .. code:: powershell + + cd src + ..\misc\mk_errinfo error_msg.txt error_tag.txt err_codes.h err_data.h + +* | Still in the ``src/`` directory, compile and link all the ``.c`` and + ``.cpp`` files. For example: + + .. code:: powershell + + cl /TP /EHsc /Feedgcpfe.exe *.c *.cpp /link mscoree.lib oleaut32.lib + +Building Support for C++/CLI and C++/CX Modes +--------------------------------------------- + +C++/CLI is a Microsoft extension to C++ that simplifies writing C++-like +programs for Microsoft's ".NET" environment. It is formally specified by the +ECMA standard ECMA-372. The front end can support this extension, provided it +is built on a sufficiently recent Microsoft Windows platform with a compiler +that is sufficiently compatible with Microsoft's "Visual C++" compiler. This +support is currently limited to producing high-level IL. The C++-generating +back end can consume this IL (and render the C++/CLI constructs it describes), +but lowering and the C-generating back end are not available in C++/CLI mode. + +C++/CX is a Microsoft extension to C++ similar to C++/CLI, but it targets the +"Windows Runtime" (WinRT) platform instead of the ".NET" environment. Unlike +C++/CLI, there is no formal document specifying this extension. The front end +can also support C++/CX, with the same caveats as those mentioned for C++/CLI +support (in particular, IL lowering is not available for C++/CX mode). + +To include support for C++/CLI and/or C++/CX the configuration macros +``CPPCLI_ENABLING_POSSIBLE`` and/or ``CPPCX_ENABLING_POSSIBLE`` (respectively) +must be set to TRUE. (The macros ``MICROSOFT_EXTENSIONS_ALLOWED`` and +``EDG_WIN32`` must also be TRUE when building such configurations.) In addition +to compiling the C files constituting the front end proper (as explained +above), support for C++/CLI and/or C++/CX requires that the C++ source file +``ms_metadata.cpp`` be compiled as C++ and the resulting object file must be +added to the set of files linked into the final front end executable (or +library). The system libraries ``mscoree.lib`` and ``oleaut32.lib`` are then +also required in the final executable. + +Compiling ``ms_metadata.cpp`` requires Visual C++ 2012 or later (or a C++ +compiler and libraries that are sufficiently compatible with that). The free +"Express" version of Visual C++ is not sufficient because it doesn't include +the ATLMFC library, which ``ms_metadata.cpp`` depends on. + +Building and Using the IL Display Program +----------------------------------------- + +For educational and debugging purposes, the front end comes with a utility +named ``edgcpdisp`` that reads a file containing the IL produced when the front +end compiles one or more source files and displays it in a human-readable form. +(In order to use this facility, of course, the front end must be configured to +write an IL file, i.e., ``IL_SHOULD_BE_WRITTEN_TO_FILE`` must be set to TRUE in +``defines.h`` or in ``src/Makefile``.) + +Because the IL file written by the front end is essentially a binary dump of +the IL data structures, it is necessary for the front end and ``edgcpdisp`` to +be built on the same platform and using the same configuration options. (Many +of the IL data structures contain fields that are present only in certain +configurations.) + +In an environment with a Unix-like ``make`` utility, ``edgcpdisp`` is +automatically built (with a configuration that correctly matches that of the +front end) when ``make`` is run for the default target in either the top-level +or ``src/``\ directory. It can also be built separately by using ``make`` in +the ``src/disp/``\ directory. + +If ``make`` is not available, ``edgcpdisp`` can be built after the front end is +built (as described in the preceding section) in the ``src/``\ directory by +compiling a subset of the source files with ``STANDALONE_IL_DISPLAY`` set to +TRUE. For example, on a Windows platform using the Microsoft C++ compiler, the +command would be (all on one line): + +.. code:: powershell + + cl /TP /Feedgcpdisp.exe -DSTANDALONE_IL_DISPLAY const_ints.c debug.c \ + error.c fixed_pt.c float_pt.c host_envir.c il.c il_display.c il_read.c \ + il_to_str.c il_walk.c mem_manage.c target.c types.c fe_init.c + +Displaying the IL for a source file ``x.cpp`` can be accomplished with the +following commands: + +.. code:: bash + + edgcpfe --output x.cil x.cpp + edgcpdisp x.cil + +(In configurations that do IL lowering, ``x.cil`` will contain the lowered IL. +To view the unlowered IL, see the ``--no_il_lowering`` front-end command-line +option described in the next chapter.) + +Driving the Front End +===================== + +For many applications, it is useful to invoke the front end through another +"driver" program. One such driver is the ``bin/eccp`` script that is part of +every release. Another is the ``edgcc`` program that can be downloaded +separately from the EDG download site. + +.. _the-eccp-script: + +The ``eccp`` script +------------------- + +The ``bin/`` directory contains a (Bourne) shell script ``eccp`` that +allows the front end to be used much like most Unix-hosted compilers. It +invokes the front end -- which must be configured with the C-generating back +end -- with various default options, and then compiles any generated C files +through a "native" C compiler (e.g., the GNU ``gcc`` compiler) and a native +linker. The script accepts Unix-like compiler options (such as ``-c``, +``-o``, ``-O``, ``-g``, ``-I``, ``-L``, and ``-l``) and also passes through +most of the options handled by the front end proper (see :ref:`cli`). + +The script can be moved anywhere, but it normally looks for various components +(the front end, the prelinker, etc.) under a directory designated by the +environment variable ``EDG_BASE``. The ``eccp`` script can be edited to set a +default substitute value for the ``EDG_BASE`` variable. Normally, the value of +``EDG_BASE`` is the top level directory of a fully-built release tree (although +the ``src/`` and ``lib_src/`` directories are not used by ``eccp``). ``eccp`` +will start by setting various environment variables by executing a script +``$EDG_BASE/edg_eccp_config``. Sample scripts for various platforms are +provided in the ``sample_edg_eccp_config/`` directory. Two environment +variables commonly customized in the ``edg_eccp_config`` script are +``EDG_DEFAULT_DEFINES`` (to add options like ``-D__unix__``) and +``EDG_C_TO_OBJ_COMPILER`` (to establish which "native" compiler to use; e.g., +``gcc``). + +``eccp`` may also invoke the prelinker (``util/edg_prelink``) to automatically +instantiate templates (and, with some front end configurations, inline +functions that need an out-of-line copy). See +:ref:`template-auto-instantiation` for notes on this process. The script will +also run ``util/edg_munch`` if needed, and filter linker errors through +``util/edg_decode``. + +See ":ref:`utility-programs`" for more information on the utility programs +``edg_prelink``, ``edg_munch``, and ``edg_decode`` used by the ``eccp`` script. + +The ``edgcc`` Driver for Windows +-------------------------------- + +A Windows program implementing a subset of ``eccp``\ 's functionality can be +downloaded from the EDG download site. The file to download is +``nt_util.zip``. In addition to source code for the driver program ``edgcc``, +it also contains source code for a Windows-hosted prelinker (``pl_nm``) and +munch-like program (``munch_nm``). + +The plain text file ``src/msinfo`` contains additional notes for running the +front end in the Windows environment. + +Configuring and Building the Run-Time Support Library +===================================================== + +Source code for a sample run-time support library is provided in the +``lib_src/`` directory. This library is meant to be built using the front end +(i.e., a compiler incorporating the EDG front end). The library is useful for +demonstration and debugging purposes. However, it is normally not suitable for +production compilers because it is written in portable C++ that cannot take +advantage of more efficient platform-specific mechanisms (e.g., to implement +exception handling). + +Similarly to the front end, the library can be configured through macro +definitions placed in ``lib_src/defines.h``. Typically, however, few or no +macros need to be defined because the ``--build_runtime`` option to the front +end (used to build this library) causes most or all required macros to be +predeclared. + +The macros that might need manual configuration are documented in +``lib_src/config.h``. + +When using multiple target configurations, a version of the run-time support +library must be built for each target configuration and installed in the +appropriate ``lib_``\ *target*\ ``/`` directory. See ``lib_src/Makefile`` for +directions to build target-specific versions of the library. diff --git a/doc/_sources/c_gen_be.rst.txt b/doc/_sources/c_gen_be.rst.txt new file mode 100644 index 0000000..ded1396 --- /dev/null +++ b/doc/_sources/c_gen_be.rst.txt @@ -0,0 +1,395 @@ +===================== +C-Generating Back End +===================== + +``c_gen_be.c`` contains code to translate the intermediate language to C; +``c_gen_be.h`` contains the associated declarations. This is a fake "back end" +that is useful as a way of testing the front end in the absence of a real back +end, as a portability aid, and as an example of how to traverse the +intermediate code (which may be helpful to those writing back ends). + +Function +======== + +Generated C Code +---------------- + +The C code generated can be either ANSI C or old-style K&R C, depending on the +setting of the configuration flag ``C_GEN_BE_GENERATES_ANSI_C``. + +The output contains ``#line`` directives that relate the generated code back to +the original source lines that generated it. The ``#line`` directives do not +ascend monotonically through the line numbers of the source file; they jump +around as the code generation jumps around. However, since the C-generating +back end tends to process all declarations of entities of one kind in a sweep +through those entities in source order, the output tends to have all the types +in source order, then all the variables in source order, etc. + +Long output lines are broken (between tokens) to avoid unduly stressing C +compilers that must process the generated code. + +Since the generated code is intended to be fed into a C compiler, rather than +read by a human, it is not very readable. The readability can be improved +(slightly) by turning on debugging (e.g., ``-d0`` on the command line); that +will cause the C-generating back end to generate annotation comments and +indentation. Unreferenced entities, which ordinarily are not put out at all, +are generated inside ``#if 0``/``#endif`` delimiters in this mode. + +Transformations +--------------- + +For the most part, what the C-generating back end does is just writing out the +C code that corresponds directly to the IL. Since the IL has the same concepts +and constructs as the C language, the processing is pretty straightforward. +However, there are a few complicating transformations. + +The following transformations on names are done: + +* | Names that match C reserved words, or words that are likely to mean + something to the underlying C compiler (e.g., ``unix``), are given a prefix + of "``__x``". +* | Names with no linkage (e.g., local variables) are given a prefix that is + the source sequence (line) number and column number of the name's + declaration, to make sure they do not conflict with similar names from + elsewhere in the program (e.g., "``i``" is output as "``__28_7_i``"). +* | Unnamed entities are given generated names of the form "``__T``\ *nnnnnn*", + with *nnnnnn* generated from the IL entry address. +* | The "``this``" parameter, passed through from C++, is given the name + "``this``". +* | Function-local and prototype-scope types are given names formed by + concatenating the original name, "``__``", the (mangled) function name, + "``__``", and "``L``\ *nn*", where *nn* is a number identifying the + function, prototype, or block scope scope of which the type is a + member. (Renaming is needed because such types are promoted out of + functions; more on this below.) +* | When generating K&R C, file-scope static variables are given a suffix + formed from the name of the module and the date and time of compilation. + This suffix is needed because initialized file-scope static variables must + be made external to avoid some pcc limitations on declaring static + variables more than once. The suffix helps to ensure that the now-external + name does not conflict with like-named static and external variables from + other compilation units. + +Another set of transformations is necessitated by the fact that IL lowering +generates "C" IL that actually contains some minor extensions. These +"extensions" are things that a real back end would probably take in its stride +(i.e., it wouldn't see these cases as being different than normal cases), but +which must be rewritten if standard C code must be generated: + +* | Dynamic initializations for declarations can appear in mid-block, after + executable statements have appeared. (These are generated as executable + code. Because of this, "``const``" type qualifiers are suppressed on + variables initialized dynamically and on all struct members.) +* | Structs and unions can have no members at all, and aggregate constants used + in initializers can contain empty lists of constants ("``{}``"). (The + struct/union definition will include a dummy field, and the initialization + puts a zero into that field.) +* | Enumerations having no enumerator constants are put out as the + corresponding integral type. +* | The ``eok_bassign`` operator is used to do assignment of arrays (e.g., in + generated copy constructors). (A ``memcpy`` is generated.) +* | Prototyped parameter variables may be unnamed. (A name is generated.) +* | Variables can be indicated to be initialized to zero (the ``initk_zero`` + initialization kind). This is used to differentiate real definitions of + external variables from tentative definitions (a distinction that is hazy + in C), and for local aggregate variables that are partially initialized. + (For static variables, the initialization to zero is preserved in the + generated C; for automatic variables, a ``memset`` is generated.) +* | String literals in C++ are ``const``. IL lowering leaves them ``const``, + even though string literals in C are not ``const``. (This does not require + a transformation in the generated C code: the string literals are put out + as such, and the C compiler sees them as non-``const``, which works out + okay.) + +When generating K&R C, some transformations are needed to erase ANSI C features +that do not exist in K&R C: + +* | Prototyped functions are put out as old-style unprototyped functions. +* | Type qualifiers ("``const``" and "``volatile``") are not put out. +* | Enumerations are put out as integral types, and enumeration constants are + put out as integral constants. +* | "``signed``" is never put out. "``signed char``" is put out as "``char``", + and "``signed int``" is not used for the base type of a bit field. +* | "``long double``" is put out as "``double``". +* | The suffixes "``U``" on integral constants and "``F``" and "``L``" on + floating constants are not put out; a cast is used instead. +* | Union initializations are rendered as executable code. +* | Initializations of automatic aggregates are rendered as executable code. +* | Bit fields in unions are put out as normal fields. +* | Signed bit fields are simulated by adding code to sign-extend and truncate + the bit fields on each access. +* | Second and third operands of "``?``" of type ``void`` are rewritten. +* | ``extern void`` variables are put out with type ``char``. +* | Labels are given a prefix of "``__L_``" to accommodate the fact that pcc + does not maintain a separate name space for labels. + +The following transformations also deal with features missing in K&R C, but +these transformations are done even when generating ANSI C to avoid some +features that might not be implemented (well) in C compilers: + +* | Rvalue field selections (e.g., "``f(x).i``") are rewritten as lvalue field + selections by using a temporary. + + .. code:: c++ + + struct A { int i; }; + extern struct A f(); + void m() { + j = f().i; /* Rewritten as "j = (Tnnnn = f(), Tnnnn.i)" */ + } + +* | Wide string constants are stored in generated static variables and the + variables are used in place of the constants at each reference. +* | Character arrays initialized with string constants not containing a + trailing null character are rendered in "exploded" form, e.g., something + like + + .. code:: c++ + + int a[4] = "abcd"; + + | is rendered as + + .. code:: c++ + + int a[4] = {'a', 'b', 'c', 'd'}; + +The following transformations are necessary to deal with ordering problems +(i.e., they're necessary because of the order in which the C-generating back +end outputs entities): + +* | Local types of functions are generated at file scope. This avoids problems + with extern declarations written inside functions (the extern entity is on + the file-scope list, but it may refer to local types of the function). + + .. code:: c++ + + void f() { + struct A { int i; }; + extern void g(struct A); + } + + | is rewritten as + + .. code:: c++ + + struct A { int i; }; + extern void g(struct A); + void f() {} + +* | Types in the prototype scope of a function are promoted out of the + prototype scope. This is because each function and variable is put out + twice, once as a declaration and once as a definition. Without this + promotion, the declaration and definition would be incompatible because the + two copies of the prototype scope types would be considered to be distinct + types. + + .. code:: c++ + + void f(struct A { int i; } p) {} + + | is rewritten as + + .. code:: c++ + + struct A { int i; }; + void f(struct A); + void f(struct A p) {} + + | Prototype scopes that are not part of a function or variable definition are + not processed in this way. When generating K&R C, such unprocessed + function types are put out unprototyped, which eliminates the types defined + in the prototype scope. When generating ANSI C, such unprocessed function + types are put out prototyped, and if any structs, unions, or enums are + defined in the prototype scope they are put out inline. + | + | When a pointer type containing a prototype scope needs to be put out (i.e., + as the type of a constant or in a cast), the type (and cast) is suppressed, + because the conversion must have been implicit in the source program -- + it's not possible to name the types defined in a prototype scope outside of + that scope. + +When virtual functions with covariant return types appear in the source +program, IL lowering rewrites them in a way that uses wrapper functions. That +is, when an overriding virtual function returns a pointer to a derived class, +and the overridden virtual function returns a pointer to a base, a wrapper +function is generated that calls the overriding function but returns a pointer +appropriate for the overridden function. Such functions have a body that is +simply a return of an ``enk_result_of_overriding_function`` node cast to the +proper pointer-to-base-class type. The C-generating back end expands these +wrapper functions by generating the body of the overriding function again, with +the added cast inserted over the expression at each return statement. Note +that the "obvious" implementation technique of replacing the +``enk_result_of_overriding_function`` node by a call of the overriding function +(i.e., implementing these as actual wrapper functions) will not work if the +functions have variable-length argument lists. The same technique is used for +alternate entry points for constructors in the IA64-ABI, but only if the +routine has a variable-length argument list. + +Configuration +------------- + +Although the generated C code is generally portable, there are some +configuration issues that must be attended to. + +The most obvious is to make sure that the sizes and alignments of basic types +defined in ``targ_def.h`` match those assumed by the target C compiler. + +Block operations (e.g., ``memcpy``) are generated in either the BSD form or the +System V/ANSI form under control of the ``__BSD__`` configuration option, so +make sure its setting matches the library of the target C compiler. + +If the target C compiler has some way of indicating that a function is inline, +the code in ``dump_routine_decl`` should probably be changed to output that +construct. + +Long output lines are wrapped to avoid overly long lines. You can alter the +maximum size by adjusting ``MAX_OUTPUT_LINE_SIZE``. The default is fairly +modest (a few hundred characters). + +If the target C compiler has particular bugs or shortcomings, you may want to +add code to work around them. There is existing code for the Sun, Microsoft, +and gcc C compilers. + +The C-generating back end can emit ``#pragma`` directives for IL pragma +entries, but only in a somewhat limited way. For pragmas bound to an entity, +the pragma is emitted right before the declaration of the entity. However, +pragmas not bound to an entity are emitted at the beginning of the scope +containing them, and therefore they may not be where expected. That makes that +kind of pragma suitable only in cases where the exact position of the pragma is +not very significant, e.g., for global-effect pragmas and those that associate +attributes with entities by naming the entities. + +Operation +========= + +The code can be compiled either as a subroutine ``back_end`` that is called in +the same program as the front end, or as a main program. In either case, +``c_gen_be`` is called to do the C generation. It begins at ``il_header`` and +walks through the intermediate language tree, generating C and writing it to a +file with a ``.int.c`` suffix. First, it dumps the source correspondence +information (``dump_source_file_correspondence_info``) and some other header +code (``dump_header_code``). Then, for the file scope level, it + +* | calls ``dump_scope_constants`` to dump code for constants on the file-scope + list. This has marginal utility, but dumps class member constants (an + extension) promoted to the file scope by IL lowering. They are put out as + ``enum`` declarations. +* | calls ``dump_scope_types`` to dump declarations for all named types -- + i.e., ``typedef``\ s and tags. The tags are output twice: as incomplete + declarations on a first pass, and as complete declarations on the second, + to avoid forward-reference problems. Local and prototype-scope types are + also output here (at the file scope) to avoid some ordering problems. +* | calls ``dump_scope_routines`` to dump routine headers (no bodies). +* | calls ``dump_scope_variables`` twice. The first time dumps variables + without initializers, and tentative declarations for those with + initializers. The second time dumps only the initialized variables, this + time with initializers. This is to avoid forward-reference problems. +* | calls ``dump_scope_routines`` to dump routines with bodies. + +When ``ONE_INSTANTIATION_PER_OBJECT`` is enabled, each instantiation is put +out as a separate object file. There is still only one IL tree, but it is +marked so that the C-generating back end can sweep through it several times +and put out a different C file (a "slice") each time, each C file +containing one instantiated entity (function or static data member) plus +exactly the set of other entities needed by that entity. The information +on which entities to include on each sweep is provided by the +per-instantiation "needed" flags, which are a bit vector attached to the +source correspondence entry (see :ref:`needed-flags`). Each slice is +assigned one bit in that bit vector, and if the bit is 1 the associated +entity is needed in the slice. On beginning the generation of the C file +for a slice, the C-generating back end sets the global variable +``needed_flag_bit_number`` to the bit number for the slice, and then goes +through the normal processing to generate C for everything in the IL tree. +The normal test of the "needed" flag, used to exclude things that aren't +needed, in this mode tests the proper bit in the bit vector, and therefore +excludes all entities that are not in the slice. In addition, when a +variable or function with a definition is encountered, if the variable or +function is not assigned to the current slice (as indicated by the +``instantiation_needed_bit_number`` field in the variable or routine +entry), the variable or function is put out as a declaration instead of a +definition. + +The lower-level routines are as follows: + +``dump_type_decl`` generates a type declaration. It calls + +* | ``dump_enum_definition``, +* | ``dump_struct_union_definition``, or +* | ``dump_typedef_decl``. + +Types are written out by ``dump_type`` and +``dump_general_declaration_using_type``. They use routines from +``il_to_str.c`` to produce the output for the type. ``dump_enum_definition`` +puts out enum definitions, and ``dump_struct_union_definition`` puts out +struct/union definitions. + +``dump_variable_decl`` generates a variable declaration. For a variable with +an initializer, it calls ``dump_initializer``. There's some fairly complicated +processing under that routine to turn constant aggregate initialization into +executable code. Among other things, it involves writing initialization +assignments to an auxiliary file while processing declarations, then copying +the initialization code to the right place after all the declarations have been +processed. Because initialized static variables are put out twice (on two +calls of ``dump_variable_decl``), they are made external when generating K&R C, +so their names are modified (by ``dump_variable_name``) to avoid name conflicts +with like-named static and external variables in other compilation units. + +Code generated for file-scope initializations (of unions when generating K&R C) +is placed in a separate routine (with a name beginning with "``__cgi__``") that +needs to be called at program start-up time. If the compilation contains a +main program, or an initialization routine generated by IL lowering (with a +prefix of "``__sti__``"), a call to the C-generating back end initialization +routine is inserted there. Otherwise, if the compilation is of C++ source, the +C-generating back end generates an initialization routine of the same form as +that generated by IL lowering ("``__sti__``" prefix), along with the variables +needed to alert the link phase to the presence of the initialization routine. +If the compilation is of C source, a message is issued to ask the user to +include an appropriate "``-i``" option elsewhere to request invocation of the +initialization code. + +``dump_routine_decl`` generates a routine declaration. For a routine with a +definition, it calls ``dump_routine_definition``. That in turn calls +``dump_func_definition_type`` to dump the parameters (prototyped or old-style). + +``dump_statement`` is called to generate code for statements. + +The statements and expressions of functions are pre-scanned before code for the +routine is generated, to generate declarations for any temporaries that will be +needed in the generated code. Specifically, temporaries are generated for +rvalue field selections and wide string constants. + +Expressions are dumped by calling ``dump_expr``. It outputs the expression by +walking the tree. It puts in explicit parentheses where necessary to guarantee +the grouping of operators. Taking the address of a function or array must also +be handled carefully, and is done by ``dump_ampersand``. + +Since ``pcc`` doesn't allow signed bit fields, operations on such fields are +surrounded by references to macros to sign-extend them or truncate them for +storing. + +``dump_constant`` dumps out a literal constant or address constant using the +IL-to-string routines in ``il_to_str.c``. + +Actual output of generated code is handled by the following routines: + +* | ``m_write_ch``, +* | ``write_ch``, +* | ``m_write_str``, +* | ``write_str``, +* | ``m_write_tok_ch``, +* | ``write_tok_ch``, +* | ``m_write_tok_str``, +* | ``write_tok_str``, +* | ``write_unsigned_num``, and +* | ``write_num``. + +The "``m_``" versions are macros; the others are not. One can choose between +them based on the need for speed and/or a single evaluation of the argument. +The "``tok_``" routines always write a full token (or several); that allows the +output line to be broken before or after the output if the line is too long. + +``set_output_position`` is called to establish the source position of an entity +about to be generated. If necessary, it generates a ``#line`` directive or the +right number of empty lines to adjust the output position (see +``write_line_directive``). diff --git a/doc/_sources/class_decl.rst.txt b/doc/_sources/class_decl.rst.txt new file mode 100644 index 0000000..bb11902 --- /dev/null +++ b/doc/_sources/class_decl.rst.txt @@ -0,0 +1,1865 @@ +================== +Class Declarations +================== + +All class, struct, and union declarations are scanned in ``decl_spec.c``, and +their definitions, including the declarations of class members, are handled +through a set of routines, most of which are found in ``class_decl.c``. The +layout of classes is handled in ``layout.c``. Associated declarations are in +``class_decl.h`` and ``layout.h``. + +Declarations of structs and unions in C mode are, for the most part, precisely +compatible with C++ declarations; they just make use of a small subset of the +syntactic options. + +C++/CLI managed class add both a number of variant class kinds (collectively +called "managed classes") and a number of variant member kinds (e.g., events). +These are also mostly implemented in ``class_decl.c``. + +C++11 lambda expressions implicitly define a closure class type. While the +top-level class declaration parsing routines (``class_specifier`` and +``scan_class_definition``) are not applicable for parsing lambdas, some other +important routines in this area are reused (see :ref:`lambdas`). + +Similarly, C++/CLI delegate definitions implicitly define a ref class type, +which reuses some important routines supporting the ordinary definitions of +class types, but not the routines that parse such definitions. + +Overview +======== + +Class Declarations +------------------ + +``class_specifier`` (in ``decl_spec.c``) is called from ``decl_specifiers`` +when a ``class``, ``struct``, or ``union`` keyword is encountered. [#f1]_ In +Microsoft mode, this is also done with the ``__interface`` keyword, and in +C++/CLI mode with the "keywords" ``ref class``, ``ref struct``, ``value +class``, ``value struct``, ``interface class``, and ``interface struct``. A +tag name may be present, and if it is ``declares_something`` is returned +TRUE. A definition may be present, and if it is ``defines_something`` is +returned TRUE. In every case, even when there is an error, a pointer to a +``tk_class``, ``tk_struct``, or ``tk_union`` type entry is returned in +``type_ptr``. + +The processing of class declarations consists of several steps. The tag name +(if present) is scanned and looked up in the symbol table (see +``scan_tag_name``). A declaration may be the declaration of a new class, a +reference to an existing class, or the completion of a declaration whereby an +incomplete class is fully defined; it may also be a specialization of a class +template. If this is a brand new class, the type entry is allocated for it; +otherwise, the old one is fetched from the symbol entry. + +If the declaration does not actually *define* a class, that's about all that +needs to be done. The type is returned to the caller and declaration +processing continues. + +Class Definitions +----------------- + +If a class declaration is a class definition -- that is, if the class body is +present -- then ``scan_class_definition`` is called from ``class_specifier`` +(it is also called from other places like ``f_instantiate_template_class`` to +create an instance of a template class and ``instantiate_class_template`` to do +prototype instantiation of the class template). The creation of a class +definition is tracked using type ``a_class_def_state``; this is true for +ordinary definitions appearing in the source, but also for definitions +generated for, e.g., lambda expressions (i.e., closure types). This structure +records all kinds properties of the definition (e.g., the current accessibility +or whether a member has been seen that requires a nontrivial constructor) and +is passed around to many routines that implement class member declarations. + +Most of the tasks performed by ``scan_class_definition`` are done in C++ mode +only: + +* | The base class specifiers (if any) are scanned and recorded. +* | The scope stack is pushed for the class (and the scope stack entry is made + to point to the ``a_class_def_state`` structure for the definition). +* | A loop is entered to scan class members. In ordinary C this means scanning + the declarations of fields. In C++ it means scanning all kinds of member + declarations. +* | At the top of the loop (in C++ only) an optional access control specifier + is scanned. +* | When ``using`` appears (or there is only a qualified name and no + declaration specifiers), a using declaration (or access declaration) is + scanned. +* | When ``template`` appears ``template_declaration_or_directive`` is called + to process a member template. +* | Otherwise, ``class_member_declaration`` is called: + + * | A structure of type ``a_member_decl_info`` tracks properties of the + declaration. This structure includes a field ``decl_state`` of type + ``a_decl_parse_state`` (which is the kind of structure used for general + declaration processing). + * | ``decl_specifiers`` (in ``decl_spec.c``) is called to scan the + declaration specifiers. + * | When there is no declarator following, + + * | if it is a friend class declaration, ``decl_friend_class`` is called + and declarator processing is skipped. + * | if it is a nested ``class``, ``struct``, ``union``, or ``enum`` + declaration, declarator processing is skipped. + * | if it is a nested anonymous union declaration, declarator processing is + entered (even though the call to ``declarator`` itself is skipped) + since the rest of the processing is done in + ``decl_nonstatic_data_member``. + * | A loop is entered to scan a declarator list. In cases where only a + single declarator is permitted, the loop will be exited at the + appropriate point. + * | ``declarator`` (in ``declarator.c``) is called to scan a single + declarator. If default arguments are encountered when a parameter list + for a member function is scanned, they will be cached away to be + rescanned later. + * | Based on the combined information returned from ``decl_specifiers`` and + ``declarator``, one of the following is done: + + * | ``decl_member_function`` is called to process a member function + declaration (static or nonstatic, virtual or nonvirtual). If the + function body is present, the tokens are cached so that they can + scanned later (see ``prescan_function_definition``). If there is no + function body, a pure specifier ("``= 0``") is checked for (see + ``scan_pure_specifier``). + * | ``decl_friend_function`` is called to process a friend function (member + or nonmember). If the function body is present, the tokens are cached + so that they can scanned later (see ``prescan_function_definition``). + * | ``decl_member_function_template`` is called to process a member + function template. + * | ``decl_typedef`` is called to process a ``typedef`` declaration. + * | ``decl_nonstd_member_constant`` is called to process a member constant + declaration (an extension). + * | ``decl_static_data_member`` is called if the keyword ``static`` was + used in a non-function declaration. + * | ``decl_nonstatic_data_member`` is called to do processing for ordinary + fields. + * | At the bottom of the declarator loop, continue looking for declarators if + the next token is a comma. +* | At the bottom of the loop, continue looking for member declarations unless + a right brace (or end of file) is encountered. +* | Once the member declarations have been processed, further error checking is + done, and in addition: + + * | In case the class was declared before the current definition, + ``move_to_end_of_types_list`` is called to move the type entry for the + class to the end of the scope types list. (It will have been initially + put onto the list in ``class_specifier``.) + * | ``set_virtual_function_numbers`` is called to do the remaining processing + for virtual functions -- in typical implementations, the virtual function + number in a routine entry corresponds to its position in the virtual + function table. + * | ``check_special_member_functions`` is called to determine whether a + compiler-generated default constructor, copy constructor, and assignment + operator is needed and, if so, to generate the declarations. (The bodies + are generated if and when the function is referenced.) + * | ``do_class_layout`` is called to allocate space for base classes and + nonstatic data members, as well as for whatever information is needed + (e.g., pointers) to support accessing virtual base classes and calling + virtual functions. + * | ``project_base_class_conversion_functions`` is called to add projection + symbols for inherited conversion functions to the class symbol + supplement's ``conversion_list``. + * | ``report_virtual_function_ambiguities`` is called to issue diagnostics on + unresolved ambiguities in virtual function declarations. + * | ``check_abstract_class`` is called to mark a class with pure virtual + functions as "abstract." +* | The scope stack is popped, and the closing right brace of the class + definition is bypassed. +* | For non-nested classes ``delayed_scan_fixup_for_class`` is called to rescan + member function default argument declarations and inline member function + definitions. + +Many of these "class definition completion" tasks are initiated from the +``complete_class_definition`` function. This function is also called for class +types that don't appear using ordinary class definition syntax in the source +code (for example, closure types for lambda expressions; see :ref:`lambdas`). + +Ideally, all properties of a class should be known once the definition has been +seen. Unfortunately, that is not always the case. In particular, the C++11 +notion of whether a class type is a "literal type" cannot always be determined +until it is known whether it has a constexpr constructor, which in turn +sometimes requires waiting until all the field initializers have been scanned +(and for template classes that can be arbitrarily delayed). Whether a class +type is a literal type is therefore tracked by two flags in the class symbol +supplement [#f2]_ (``known_to_be_a_literal_type`` and +``known_not_to_be_a_literal_type``), which can be determined "on demand" by a +call to ``set_literal_type_flag`` or, more generally, ``is_literal_type``. + +.. _cppcli-managed-types: + +C++/CLI Managed Class Definitions +--------------------------------- + +Managed class definitions are parsed using the same framework as standard class +definitions. However, C++/CLI adds many new kinds of members, several of which +are implemented with new top-level mechanisms. + +Several "field-like" managed member kinds rely on "context-sensitive +keywords", i.e., specific identifiers (``event``, ``initonly``, +``literal``, and ``property``) that are keywords only if the rest of the +declaration would not otherwise be valid. The function +``check_for_cli_modifier`` looks ahead through the token stream for such +keywords, and records their presence in the ``a_decl_parse_state`` +structure for the current declaration. If the keywords ``event`` or +``property`` were found, the member declaration is handled using the +special-purpose function ``scan_cli_property_or_event_head``, after which +the front end proceeds with the next declaration. The other two keywords +(``initonly`` and ``literal``) are consumed by the regular call of +``decl_specifiers`` (which is passed the ``a_decl_parse_state`` structure +indicating that these identifiers should be treated as keywords). + +Delegate definitions appearing as member declarations also rely on a +context-sensitive keyword ``delegate``. That case is identified by the +function ``check_for_cli_delegate_definition``, and is then handled by +``scan_and_record_cli_delegate_definition``. + +Properties and events are represented as fields (``a_field``) if they are +nonstatic or as static data members (``a_variable``) if they are static. These +representations are created by calls to ``decl_nonstatic_data_member`` or +``decl_static_data_member`` respectively, which is done by the function +``decl_property_or_event_member``. + +Property and event definitions may include a brace-enclosed list of accessor +declarations (such properties/events are called *nontrivial*). Accessors are a +special kind of member function (i.e., their ``a_routine`` entry has a +special_kind field that is not ``sfk_none``) of the parent class of the +property or event: The braces are for grouping purposes only and do not +introduce a new scope. Accessors declarations are handled as separate member +declarations in the main loop of ``scan_class_definition``; not as part of the +call to ``scan_cli_property_or_event_head``. However, a copy of the +``a_member_decl_info`` structure recorded for the property/event declaration +itself is kept around while scanning the accessors (accessible via the +``pe_info`` field of the current ``a_class_def_state`` structure). This is +needed because the exact nature of the property/event may depend on the storage +class specified on the first accessor: If no storage class was specified on the +property/event declaration itself, but the first accessor is declared static, +then the property/event should be treated as static. Hence for a nontrivial +property or events, the call to ``decl_property_or_event_member`` is delayed +until parsing of the subsequent accessor has started: At that point a lookahead +for a ``static`` specifier (using function ``static_member_next``) is performed +if needed to determine the static/nonstatic nature of the property or event. + +Literal fields (i.e., fields declared with the context-sensitive keyword +``literal``) are recorded in ``decl_literal_field``: The result is an IL entry +of type ``a_constant``, not a_field (i.e., "literal field" is somewhat of a +misnomer). ``initonly`` members, on the other hand, are just treated as +slightly special cases in ``decl_nonstatic_data_member`` and +``decl_static_data_member``. + +Conversion functions and other operators can be static members of managed +classes; such members must have one more explicit parameter than their +nonstatic counterparts. The constraints on those parameters are checked in the +function ``check_operator_function_params``. + +Names +===== + +Name Scope +---------- + +When a class is declared with a tag name, an ``sk_class_or_struct`` or +``sk_union`` symbol is created to represent the use of the name. Since an +elaborated class specifier appearing in the source may refer to an existing +class, its name must be looked up in the symbol table. Finding a tag name in +the current or a containing scope is handled by ``scan_tag_name``. + +This is not a simple lookup, however. An interesting case occurs when a tag +name has already been declared in an outer scope: a reference to the same name +in an inner scope may or may not be a reference to the same entity. For +instance, + +.. code:: c++ + + struct S { int i; }; + void f() { struct S s; } + void g() { struct S { /* ... */ } s; } + +In this example, the ``S`` in function ``f`` refers to the ``S`` defined in the +file scope, whereas the one in function ``g`` refers to another ``S``, one +local to the function scope. The difference is that the declaration in ``g`` +is a definition and so eclipses the name from the file scope, whereas in ``f`` +there no redefinition of ``S``. For this reason ``scan_tag_name`` must take +into account whether the class is being defined in the current declaration in +deciding whether to reuse a class defined in a containing scope. A further +complexity is revealed by another example: + +.. code:: c++ + + struct S { int i; }; + void f() { struct S; struct S *p; struct S { } s; } + +Here the first declaration of ``S`` in function ``f``, referred to as a +"vacuous declaration" of ``S`` because it does not define a class and is not +used in the definition of any other object, has the effect of introducing an +incomplete class ``S`` into the routine scope and thereby eclipsing the file +scope ``S``. [#f3]_ ``scan_tag_name`` also deals with this kind of case. + +When no tag symbol is found, there is still the question of what scope a new +symbol is to be declared in. This too is determined in ``scan_tag_name``; the +answer is returned to the caller by ``effective_decl_level``. In most cases it +is simply the current scope (given in ``decl_scope_level`` [#f4]_). However, +in C++ a non-defining initial use of a class name in a function prototype scope +or a class scope is treated as declaring that name in the innermost containing +scope that is not the scope of a function prototype or a class. For example, + +.. code:: c++ + + int f(struct S *p) { return (p == 0); } + struct S { /* ... */ } s; + +Here (and contrary to the interpretation in ordinary C mode) there is only one +``S``; the second reference defines the ``struct`` to which the first is a kind +of forward reference. Thus ``scan_tag_name`` would return the file scope as +the ``effective_decl_level`` for ``S`` in its initial declaration. Similar +treatment is accorded declarations in classes: + +.. code:: c++ + + class A { + class B; + class C *pc; + class D { + class E *pe; + }; + }; + +Here ``class B`` is a vacuous declaration (it anticipates a definition of a +nested ``class B`` later in the definition of ``A``), whereas ``class C`` is a +forward reference to a file scope declaration of ``C``. Similarly, ``class E`` +anticipates a file scope declaration as well, even though the file scope is not +the immediately containing scope of ``class D``. + +The tag name can be a qualified name, not only in a reference (e.g., a +``friend`` declaration or the declaration of another entity using an elaborated +type specifier) but also in a definition. + +* | It can be a class-qualified name for a "delayed definition" of a nested + class. For example, + + .. code:: c++ + + class A { + struct S; + /* ... */ + }; + struct A::S { /* ... */ } + + | Here ``scan_tag_name`` returns a symbol locator specifying the qualified + name; the parent class scope is then reactivated in + ``scan_class_definition`` before the body of the class definition is + scanned. +* | It can also be a namespace-qualified name -- most interestingly when a + class declared in a namespace is then defined outside the namespace. (It + is a requirement that the scope in which the definition occurs enclose the + scope in which original declaration occurs.) For example, + + .. code:: c++ + + namespace N { + struct S; + /* ... */ + }; + struct N::S { /* ... */ } + + | ``scan_tag_name`` returns a symbol locator specifying the qualified name, + and ``class_specifier`` pushes a namespace-extension scope before calling + ``scan_class_definition``. + +Tagless Classes +--------------- + +When classes are declared with no tag name, though obviously no symbol is +needed for lookup on a subsequent reference, one *is* needed to store +information about the class (see below). Creating such a symbol, which is +not actually added to the symbol table, is done by +``make_unnamed_tag_symbol``. + +There is a way by which a tagless class can acquire a name retroactively -- +when its definition appears within a ``typedef`` declaration. Here is an +example, + +.. code:: c++ + + typedef struct { /* ... */ } S; + +in which case the tagless ``struct`` comes to acquire the name ``S``. This +cannot be anticipated during the processing done by ``scan_class_definition``. +Rather, the situation is detected only after the class definition has been +scanned, in ``decl_typedef``. In general, this means the name is assigned "for +linkage purposes", which means the ``name`` field in the type's +source-correspondence is updated. Additionally in cfront mode, +``relink_unnamed_tag_symbol`` is called to add the symbol for the unnamed class +to the symbol table after turning it into a symbol of the specified name. + +C++/CLI Accessor Names +---------------------- + +The names of accessor functions of properties and events (``get``, ``set``, +``add``, ``remove``, and ``raise``) are not directly visible in the class of +which they are members (although accessors are members of that class in all +other ways; e.g., they have a ``this`` handle). Instead, referring to them +directly requires qualification with the name of the property or event. For +example + +.. code:: c++ + + ref struct RS { + int get(); // (1) + property int p[int] { + int get(int); // (2) Use p::get + } + property int p[double] { + int get(double); // (3) Use p::get + } + property int q { + int get(int); // (4) Use q::get + } + }; + +The accessors marked (2) and (3) form an overload set. The accessors marked +(1) and (4) are not part of overload sets. (See also :ref:`cppcli-delegates`.) + +The symbol for an CLI accessor is not linked under the symbol header used for +normal lookups of the accessor's name. For example, a ``get`` accessor for a +property is not linked on the list of the symbol header normally associated +with the identifier ``get``, and hence looking up the identifier ``get`` in the +usual way will never find an accessor. Instead, a special symbol header is +synthesized by combining the accessor name and its parent event or property; +see ``get_property_or_event_accessor_symbol_header`` for details. (See also +:ref:`cppcli-member-funcs` for additional notes on accessor functions and their +representation, as well as :ref:`cppcli-props` for related remarks about +properties and events.) + +.. _type-scope-and-symbol: + +Type, Scope, and Symbol +======================= + +Processing a class declaration involves forming a potentially extensive and +complex description of the class. There are three principal data structures +that serve as repositories for this information: a symbol entry, a type entry, +and an IL scope entry. The information that must be passed on to the back end +(including the IL lowering phase, if applicable) is stored in the type and +scope entries; information that is only of use in front end processing (e.g., +for error detection) is recorded in the symbol. + +Detailed descriptions of these data structures are provided in the files +``il_def.h`` and ``symbol_tbl.h``; introductions painted with a broader brush +may be found in the Intermediate Language and Symbol Table chapters. + +One thing that might be a bit confusing is that both the symbols and type +entries for classes have supplements, entities of type +``a_class_symbol_supplement`` and ``a_class_type_supplement``, respectively. + +Moving among the symbol, type, and scope entries that represent a class is +fairly straightforward: + +* | The ``assoc_type`` field of the IL scope entries points to the associated + class type. +* | The ``assoc_scope`` field of the class type supplement points to the + corresponding IL scope entry. +* | In the type entry the ``source_corresp.assoc_info`` field is a pointer to + the class's symbol entry. [#f5]_ +* | The symbol points to the type entry by means of the ``type`` field. + +To make it a bit easier to get from source language categories to the data +structures that represent them, here (from a slightly different slant) is yet +another description of how the symbol, type, and scope divide up the task of +summarizing a class declaration: + +* | Nonstatic data members ("fields") are recorded on a linked list of + ``a_field`` that is accessed from the type entry. +* | Static data members are represented by ``a_variable`` entries; a list of + them appears on the scope entry. +* | Member functions appear on a linked list of ``a_routine`` entries which is + also accessed from the scope entry. Static and nonstatic member functions + are intermingled on this list; they can be distinguished by the presence or + absence of an implicit ``this`` parameter type in the associated routine + type. +* | Member function templates are represented by ``sk_function_template`` + symbols. (They also appear in the IL, but only very limited information is + available there: see the linked list of ``a_template`` pointed to from the + scope entry for the class.) Instances of member function templates, like + ordinary member functions, appear on the ``routines`` list of the class + scope entry. +* | As far as the IL is concerned, constructors, destructors, overloaded + operator routines, and user-defined conversion routines are just like any + other member function. They can be identified by the + ``special_function_kind`` value in the routine entry (e.g., for generating + their names). To facilitate front-end processing, however, the symbol's + class supplement contains pointers to the symbols for the constructor(s), + the destructor, and the assignment operator routine(s). +* | Member types (including type entries for nested classes) and member + constants also appear on lists hanging off the scope entry. +* | Member class templates are represented by ``sk_class_template`` symbols. + (They also appear in the IL, but only very limited information is available + there: see the linked list of ``a_template`` pointed to from the scope + entry for the class.) Instances of member class templates, like ordinary + nested classes, appear on the ``types`` list of the class scope entry. +* | Friendship is represented by a reference to the befriending class in the + routine entry for the friend function (or in the type entry when friendship + is conferred on an entire class). +* | Derivation is represented by a list of ``a_base_class`` entries that is + pointed to from the class type supplement of the derived class. All base + classes (direct, indirect, virtual) appear on this list. The specific ways + the class is derived are given by the ``a_base_class_derivation`` entry + associated with each base class; and there may be more than one such entry + for a given base class if it is virtual. +* | Inherited names are represented by ``sk_projection`` symbols. The + projection symbol identifies both the fundamental symbol and the base class + entry with which that instance of the symbol is associated. +* | Names brought into a derived class from a base class by a + *using-declaration* (or an access declaration) appear in the symbol table + as projection symbols for which ``is_using_decl`` is TRUE. Such + declarations are also recorded in the IL by entries of type + ``a_using_decl``, pointed to from the scope entry. +* | Accessibility is recorded in IL entries (for front-end use and symbolic + debug purposes only), in projection symbols (which can end up marked + "inaccessible"), and in base class derivation entries. But since + accessibility is generally dynamic, it must usually be computed (e.g., see + ``access_to_end_of_path`` and ``have_access_to_symbol`` in + ``symbol_tbl.c``). + +Base Classes +============ + +Once the tag symbol and type entry have been created for a class definition, +``scan_class_definition`` calls ``scan_base_specifier_list`` to scan any base +classes that may have been specified. It goes through the comma-separated list +of base classes one by one, creating for each (and for each of the indirect +base classes derived through it) an entry of type ``a_base_class`` that is +added to the ``base_classes`` list of the class type supplement. When all base +classes have been added, ``wrapup_base_classes`` is called to establish certain +properties (like the preferred derivation path of virtual bases) that cannot in +general be determined by looking at a single derivation. + +Base Class List +--------------- + +The list of base classes associated with any derived class contains a base +class entry for each of its base classes -- not just for those from which it is +directly derived. The order of the list is significant: depth-first +left-to-right, following the source code order of declarations. Base classes +contain a ``direct`` flag to distinguish direct from indirect base classes; +there is also an ``is_virtual`` flag. Consider this example: + +.. code:: c++ + + class V { /* ... */ }; + class A : virtual V { /* ... */ }; + class B : virtual V { /* ... */ }; + class C : public B { /* ... */ }; + class D : public C, public A { /* ... */ }; + +Here the base classes list for class ``D`` will contain the following entries; +note that the virtual base class appears only once in the list: + +* | Indirect virtual base class ``V`` +* | Indirect base class ``B`` +* | Direct base class ``C`` +* | Direct base class ``A`` + +Base class entries are not shared between classes because they contain +information uniquely identifying the relation of a base class to its derived +class. Thus, in the previous example, class ``C`` also has its own base +classes list, namely: + +* | Indirect virtual base class ``V`` +* | Direct base class ``B`` + +Despite some overlap of information, new copies of the base class entries of +``C`` are made for the base classes list of ``D``. + +In ``scan_base_specifier_list``, for each base specifier in the source the +optional access-specifier and optional ``virtual`` keyword are scanned, the +base class name is scanned, and error checking is performed. If the same base +class name appears twice in the base specifier list, an error is issued. +However, if the name of a direct base class is identical to that of an indirect +base class already on the list, no error is reported at this time; rather, both +base classes are marked as ambiguous. This is an example of such a case: + +.. code:: c++ + + class A { /* ... */ }; + class B : public A { /* ... */ }; + class C : public B, public A { /* ... */ }; + +The base classes list for ``C`` will contain: + +* | Indirect base class ``A`` (marked ambiguous) +* | Direct base class ``B`` +* | Direct base class ``A`` (marked ambiguous) + +Only later, if, say, a qualified name using ``A`` appeared within a member +function of ``C``, would the base class ambiguity be reported. + +Creating the base classes list is done by ``scan_base_specifier_list``, which +adds direct base classes, and ``add_indirect_base_classes``, which in recording +indirect base classes calls itself recursively as required. Both routines call +``fixup_virtual_base_class`` when a virtual base class is encountered more than +once among the direct and indirect base classes. + +Derivation Path +--------------- + +Each base class entry contains a ``derivation`` field, which points to one +or more entries of type ``a_base_class_derivation``. (Nonvirtual base +classes will have only one such entry, but virtual bases may have more.) +Each base class derivation entry points to a linked list of one or more +entities of type ``a_derivation_step``. Such a list is referred to as a +"derivation path" because it records the derivation of the derived class +from the base class: it is the path *from* a derived class back up its base +class tree *to* the required base class. Here is a simple example: + +.. code:: c++ + + class A { /* ... */ }; + class B : public A { /* ... */ }; + class C : public B { /* ... */ }; + +The derivation path from derived class ``C`` to direct base class ``B`` is +=>B, whereas the path to indirect base class ``A`` is =>B=>A. (The notation => +can be thought of as a cast from a derived to a direct base class.) + +The first step on a derivation path is either a direct base class, as in the +examples above, or a virtual base class. In the latter case, the paths to the +virtual base class (there may be more than one) are elided and may be found by +examining its base class derivation entries. For example: + +.. code:: c++ + + class X { /* ... */ }; + class A : public X { /* ... */ }; + class B : virtual public A { /* ... */ }; + class C : virtual public A { /* ... */ }; + class D : private B, public C { /* ... */ }; + +Here the derivation path for ``X`` in ``D`` is represented as =>A=>X, whereas +``A`` itself has two derivation paths, =>B=>A and =>C=>A, which are in effect +implicit in the derivation for ``X``. + +Base class ambiguity can be seen as a case in which there are two distinct +paths to nonvirtual base class entries that refer to the same class. Returning +to a previous example, + +.. code:: c++ + + class A { /* ... */ }; + class B : public A { /* ... */ }; + class C : public B, public A { /* ... */ }; + +there are two base class entries for ``A`` in class ``C``, with derivation +paths of =>B=>A and =>A. + +``add_indirect_base_class`` takes an existing base class entry and creates a +new one based on it, but to do this it needs a new derivation path as well. +``copy_and_extend_path`` creates a new path based on the derivation path of the +original base class entry. + +For cases in which it is necessary to compare two derivation paths, +``congruent_paths`` returns TRUE if two paths refer, step for step, to the same +classes. + +Virtual Base Class +------------------ + +When two or more base classes of the same type are specified ``virtual``, they +share the same base class entry. Its position in the base classes list will be +that of first appearance in the depth-first left-to-right traversal of the base +classes. However, each appearance in the derivation graph is recorded with a +separate derivation entry, and each derivation entry gives a unique derivation +path. + +``set_preferred_base_class_derivation`` is called to identify the "preferred" +path of a virtual base class -- tantamount to the sequence of casts that +affords the greatest "normal" accessibility (i.e., without special treatment +for casts in the context of member or friend functions). For example, + +.. code:: c++ + + class A { /* ... */ }; + class B : virtual public A { /* ... */ }; + class C : virtual public A { /* ... */ }; + class D : private B, public C { /* ... */ }; + +Class ``D`` is derived from virtual base class ``A`` via two paths, BA and CA. +Therefore ``A``\ 's base class entry points to a list of two base class +derivation entries, one for each path. Since the path through ``C`` gives +greater accessibility, the base class derivation entry that points to CA is the +one marked "preferred". (When several entries afford equally good access, a +direct base class is preferred over an indirect, and an indirect base class +with no virtual base classes in its derivation is preferred over one that has +virtual base classes in its derivation.) + +Virtual Functions +----------------- + +A final task performed by ``scan_base_specifier_list`` and its subroutines is +to accumulate virtual function information for its base classes. + +When a function in a derived class "overrides" a virtual function from one of +its base classes, that information is recorded for later use: [#f6]_ A list of +entries of type ``an_overriding_virtual_function`` is pointed to from the base +class entry to identify the virtual functions that are members of that class +and that are overridden in some other class derived from it. This information +must be propagated as base classes are copied. Here is an example to make this +a bit clearer: + +.. code:: c++ + + class A { virtual void f(); }; + class B : public A { void f(); }; + class C : public B { }; + +``A::f()`` is a virtual function of the base class ``A`` that is overridden +by ``B::f()`` in the derived class ``B``. The +``overriding_virtual_functions`` field of the base class entry for ``A`` in +``B`` points to an entry that identifies ``A::f()`` as the *primary +function* and ``B::f()`` as the *overriding function*. When ``C`` is +derived from ``B``, this information is passed along. At the time the base +class entry for ``A`` is created in ``C``, the virtual function override +information is copied from the base class entry for ``A`` in ``B``, with an +additional piece of information -- a pointer to the base class entry for +``B`` in ``C``. [#f7]_ + +The virtual function override list is sorted on the basis of the virtual +function number in the routine entry of the primary function. It can be that +more than one overriding virtual function entry for a given primary function +ends up on the overriding virtual function list -- and it needn't be illegal. +Consider the following example: + +.. code:: c++ + + class A { virtual void f(); }; + class B : virtual public A { void f(); }; + class C : virtual public B { void f(); }; + class D : public B, public C { }; + +Within both ``B`` and ``C`` there are an overriding virtual function entries +for base class ``A`` specifying that primary function ``A::f()`` is overridden, +in the one instance by ``B::f()`` and in the other by ``C::f()``. Within ``D`` +there is also a base class entry for ``A``, and both the overriding by +``B::f()`` and the overriding by ``C::f()`` are recorded in its list; both +overriding function entries will refer to the same primary function, +``A::f()``. As written above, this example is illegal. But the diagnostic +cannot be issued until the definition of ``D`` is complete (see +``report_virtual_function_ambiguities``), since a declaration ``D::f()`` would +override both ``B::f()`` and ``C::f()``, making the ambiguity moot and the +program legal. + +``copy_virtual_function_override_list`` copies the overriding virtual function +for a base class from one class to another derived from it, calling +``insert_in_virtual_function_override_list`` to place the copy in the proper +sorted location in the new list. + +C++/CLI Derivations +------------------- + +C++/CLI managed classes can derive from base classes in two different ways: +They can "inherit" from one ref class and they can "implement" any number of +interface classes. If the definition of a managed class (other than +``System::Object``) does not specify a base class explicitly, it inherits +``System::ValueType`` if it is a value class, or it derives virtually from +``System::Object`` otherwise (hence, all managed classes ultimately derive from +a virtual base class ``System::Object``). See ``add_implicit_cli_bases``. + +"Implementing an interface" is modeled as virtual derivation. Inheriting from +a ref class other than ``System::Object`` corresponds to regular (i.e., +nonvirtual) derivation. + +Some ref classes must implicitly directly derive from (i.e., "implement") the +``System::IDisposable`` interface according to a set of rules known as the "CLI +dispose pattern" (see ``implement_dispose_pattern_if_needed``). However, this +cannot be determined until after the complete class definition has been seen: +This is therefore a unique situation where a (virtual) base class is added +after members have been seen. When this is done, ``wrapup_base_classes`` must +be called a second time. + +Some generated managed classes implicitly inherit specific ref classes (by +calling ``add_cli_system_base_class``): delegate classes inherit +``System::MulticastDelegate`` and boxed enum types inherit ``System::Enum``. + +Generic parameters are modeled using proxy (managed) class types called +"constraint types". A type constraint specifying a type C on a parameter +modeled by a constraint type P is modeled by adding C as a base class of P. +Note that Microsoft compilers permit "sealed" classes [#f8]_ to be specified as +type constraints, which means that in this context a sealed class can be +derived from (and in that case, the deriving constraint type is marked as +sealed also). + +Fields +====== + +Declarations +------------ + +``scan_nonstatic_data_member`` is called from ``class_member_declaration`` to +process the declarations of what in ordinary C are called "fields" and in C++ +are "nonstatic data members". It handles parsing of bit field widths and +C++11-style initializers (see below), and calls ``decl_nonstatic_data_member`` +to create the actual IL entry (type ``a_field``) and associated symbol (if any) +as well as to do some error checking and set various flags. [#f9]_ + +Field symbols point to their corresponding IL entry and also to a field symbol +supplement that carries some additional (mostly C++-specific) information. + +Processing is straightforward for ordinary fields. There are several special +cases that warrant a little more explanation, however. + +* | For bit-fields ``scan_fs_constant_expression`` is called to scan the size + specified after the colon. It scans the constant value. This constant is + then used by decl_nonstatic_data_member to perform error checking, and, in + a few unusual cases, to modify the field's type to accommodate the + bit-field (e.g., when a signed integer kind was specified but the bit-field + is too small for a sign bit). +* | For unnamed fields a field entry is created and added to the IL tree (the + field entry is needed when ``set_field_size_and_offset`` is called), and a + symbol is created for it (see ``unnamed_field_symbol`` in + ``symbol_tbl.c``). The space allocated by the unnamed field is represented + as a gap left in the layout of the class. +* | Anonymous union "parent fields" have no names, but they do have an + associated symbol and a field entry in the IL. In addition, + ``check_anonymous_union_symbols`` is called both to do error checking and + to promote the symbols for the fields of the anonymous union into the name + scope of the class of which the anonymous union is a member field. This + produces an inconsistency between the IL representation, which is that of + any nested union, and the symbol table representation, where the names of + the fields of the anonymous union are treated as though they were declared + in the containing class -- for example, the parent class of the promoted + ``sk_field`` symbol is the containing class, but the IL field entries to + which it points continues to be represented as a member of the nested + anonymous union. + +In addition to actually doing error checking, ``decl_nonstatic_data_member`` +also sets some flags in the symbol to facilitate error checking and other +processing at a later time. For instance, if the field's type is a reference +type, ``any_ref_member`` is set in the class symbol supplement; the setting can +then be checked to determine whether the compiler can generate a default +constructor. + +Offset and Alignment +-------------------- + +The front end is configurable to use either of two models for assigning offsets +to fields. Either a class is laid out so that the fields are allocated exactly +in the order in which they are declared, or else they are grouped by access, +with first the ``public`` fields allocated in order of declaration, then the +``protected`` and finally the ``private`` fields. + +Processing for both models is done by ``set_offsets_for_fields``, called from +``do_class_layout`` in ``layout.c``. For each field it calls +``set_field_size_and_offset``, which takes as input offset values left over +from the previous allocation and uses them to allocate the current field. The +maximum alignment required for the structure as a whole is also tracked. The +computations are done in ``increment_field_offsets``, which does overflow +checking on all calculations. + +By default, fields are assigned offsets in declaration order; the other +model is activated by setting +``TARG_FIELD_ALLOC_SEQUENCE_EQUALS_DECL_SEQUENCE`` to ``0``. *However, at +this time only the default allocation model is supported by the IL lowering +pass.* + +.. _field-inits: + +Field Initializers +------------------ + +C++11 allows a field initializer (also known as a DMI -- default member +initializer -- or, previously, an NSDMI -- non-static data member +initializer) to be specified on a field declaration. For example: + +.. code:: c++ + + struct S { + int i = init_val; + static int init_val; + }; + +The initializer must be parsed in the context of the completed class (which, +e.g., means a field initializer can make use of a member that is declared at a +point that is lexically after the initializer). To achieve this, +``scan_nonstatic_data_member`` caches the initializer for later parsing. In +the case of nontemplate classes, this later parsing is handled by recording a +fixup entry (by calling ``record_inclass_initializer_fixup``) which is later +processed by a call to ``inclass_initializer_fixup`` (when the class is +completed), and that in turn calls ``field_initializer`` (in ``decl_inits.c``) +to actually parse and record the initializer. For template classes, the +initializers are not parsed until they're needed. If a field initializer of a +template class must be accessed by the front end, it must call +``instantiate_field_initializer_if_needed`` prior to examining the IL for that +initializer (recorded in ``a_field::initializer``). In the template case also +``field_initializer`` is the routine that performs the actual parsing of the +initializer. + +Field initializers are subject to various error checks. One of the more subtle +checks in this context is for circular dependencies: The initializer for a +field may depend on that field's value in various indirect ways. The front end +will diagnose this if the circularity affects compile-time evaluation +(particularly, when dealing with constexpr constructors). + +Static Data Members +=================== + +``decl_static_data_member`` is called to process declarations of static data +members. It creates a variable entry (typically with ``sc_extern`` storage +class -- it will later be changed to ``sc_unspecified`` if it is defined in the +current translation unit) and appends it to the ``variables`` list of the IL +scope entry for the current class. It also creates a symbol entry of kind +``sk_static_data_member`` and enters it into the symbol table. + +When a static data member of integral type is declared as ``const``-qualified +and an initializer appears in the in-class declaration, it is usable as a +member constant. The initializer expression is scanned by +``scan_member_constant_initializer_expression``, and the variable is flagged +with ``is_member_constant`` set to TRUE. + +Definitions of static data members, with optional initializer, are handled as +part of normal declaration processing, where ``define_static_data_member`` is +called from ``function_definition``. Aside from setting a few flags, little +needs to be done except some error checking. + +C++/CLI Static Data Members +--------------------------- + +Static data members of C++/CLI managed classes can have an initializer when +they're first declared in the class, and that declaration is then considered to +be a definition. Unlike standard static data members, there are no type +restrictions for this in-class initialization to be permitted and any +initializer that would be allowed in namespace scope can be specified. + +Furthermore, such initializers are by default not processed until the complete +class definition has been seen [#f10]_. This parallels the standard treatment +of in-class function definitions and in-class default arguments. However, if +the value of the static data member is needed to evaluate a +constant-expression, the initializer is processed at that point (i.e., early; +see ``ensure_inclass_static_member_constant_initializer_is_scanned``). + +Member Functions +================ + +``decl_member_function`` is called to complete processing a member function +declaration, but the work has already been started by ``function_declarator``, +which needs to recognize member function declarations for two reasons: + +* | Default arguments in parameter declarations are not passed to + expression-scanning routines immediately; rather, the tokens are cached and + scanned only once the entire class declaration has been completed. +* | After the parameters have been scanned, an optional ``const`` or + ``volatile`` qualifier may be present on nonstatic member functions. And + whether the qualifier is there or not, the type of the implicit ``this`` + parameter is determined in ``function_declarator`` and the routine type + supplement for the member function's routine type entry is updated + accordingly. + +Consequently, even before ``decl_member_function`` is called, quite a bit of +processing has been done on member functions. What remains is to create a +symbol entry and a routine entry for the member function, add the symbol to the +symbol table, and append the routine entry to the ``routines`` list of the IL +scope entry for the current class. Some special processing is required for +overloaded functions, for virtual functions, for constructors and destructors, +for user-defined conversions, and for operator functions. The field +``special_kind`` of ``a_routine`` entries identifies special member functions +(like constructors, destructors, operators, C++/CLI accessors, etc.); it is set +to ``sfk_none`` for ordinary member functions (and non-member functions). + +Static *vs.* Nonstatic +---------------------- + +As noted above, a nonstatic member function receives special treatment in +``function_declarator``: the ``implicit_this_param_type`` field of the routine +type supplement is updated with a pointer to the (optionally qualified) class +of which the function is a member. In a static member function this pointer +remains NULL. This is the only way static and nonstatic member functions are +distinguished in the IL. ``routine_type_is_nonstatic_member_function`` is a +macro that is available to test the field. + +Overloading +----------- + +Function overloading is a matter for name lookup only -- that a function is +overloaded is not explicitly represented in the IL. The general technique for +supporting function name overloading with ``sk_overloaded_function`` symbols is +discussed in detail in the chapter on the Symbol Table. + +Entering a new member function symbol in a way that takes overloading into +account is handled by ``symbol_for_member_function``. One of the subroutines +it calls is ``member_function_redecl_sym``, which checks for type +compatibility, recognizing when the type of the implicit ``this`` parameter +should be ignored and when it must be taken into account. + +In addition to ``sk_member_function`` symbols, the overload set may include +``sk_projection`` symbols representing ``using``-declarations and +``sk_function_template`` symbols representing member function templates. + +Virtual Functions +----------------- + +A member function may be explicitly declared ``virtual``, or it may be a +virtual function implicitly, because of having the same name and type as a +virtual function from a base class. In either case, for every member function +it is necessary to go through all the base classes and look for functions with +the same name and type. Then, if the original function is virtual for either +reason, not only must it be so marked, but it is also necessary to record the +fact that a virtual function from a base class is overridden by a function from +a derived class. This, as already described in another context, is done with +entries of type ``an_overriding_virtual_function``. + +``decl_member_function`` calls ``check_for_virtual_override`` to accomplish all +this. The latter does the search through the base classes for overridden +virtual functions, and when it finds one it calls +``record_virtual_function_override`` to add an entry to the +``overriding_virtual_functions`` list in the base class. When an entry that +refers to the same primary function is already there (as a result of an +override by an inherited function), that entry is updated to record the +override by the current class's member. When more than one such entry is on +the list, the extras are removed, since the ambiguity is resolved by the +current declaration. + +After all declarations of the current class have been processed, +``scan_class_definition`` calls ``set_virtual_function_numbers`` to assign +sequential numbers to nonoverriding virtual functions declared in the current +class. (Overriding virtual functions will have already been assigned the +number of the associated base class function.) + +Then it calls ``report_virtual_function_ambiguities``, which makes another pass +over the base classes to look for ambiguous virtual function overriding -- it +issues errors when such ambiguities, caused by merging overriding virtual +function lists from several base classes, are not resolved by a member function +declaration in the current class. + +Default Arguments +----------------- + +Default arguments specified for parameter declarations in member function +declarations require special handling, because the expressions must not be +scanned until all the member declarations in the class have been scanned. +Parameter declarations are scanned in ``function_declaration``. When a default +argument is encountered in a member function declaration that is part of a +class definition, ``prescan_default_arg_expr`` is called to cache the tokens +that make up the expression; the cache resides in an entry of type +``a_def_arg_expr_fixup``, which is kept on a list pointed to by an entry of +type ``a_routine_fixup`` that is accessed from the class symbol supplement. +When the class's member declarations are complete, that list is revisited and +the default argument expression is rescanned (see +``delayed_scan_of_default_arg_expr``, which is called from +``delayed_scan_fixup_for_class``). + +Inline Definitions +------------------ + +When a member function body appears within a class definition, it is handled +somewhat like default argument expressions: ``prescan_function_definition`` is +called to cache the tokens that comprise the function body (the cache resides +in an entry of type ``a_routine_fixup``), and when the class definition is +complete, ``delayed_scan_fixup_for_class`` calls ``scan_function_body`` (in +``func_def.c``) to process the function body retroactively. (For constructors +that are defined inline, the constructor initializer list is included among the +cached tokens, and ``ctor_initializer`` (in ``decl_inits.c``) is later called +to scan it.) + +A somewhat special case occurs when inline definitions and default argument +expressions appear within a nested class: the language definition requires that +a reference to a name in the enclosing class be found even if that name is +declared after the nested class definition is complete. For instance, + +.. code:: c++ + + struct Outer { + struct Inner { + static int f() { return i; } + }; + static int i; + }; + +Since a call to ``Inner::f()`` should return the current value of ``Outer::i``, +the body of ``Inner::f()`` cannot be processed until all the members of +``Outer`` have been seen. Therefore the delayed scan fixup list for a nested +class is not rescanned until its outermost containing class has been completely +scanned. Only then does ``scan_class_definition`` call +``delayed_scan_fixup_for_class``, which in turn calls itself recursively for +nested classes before processing the tokens cached for the members of the class +passed to it. + +User-Defined Conversions +------------------------ + +When ``decl_member_function`` is called for a user-defined conversion, it +creates an entry of type ``a_conversion_list_entry`` to record the existence of +the conversion routine in the class symbol supplement for the current class. +The entry simply points to the symbol for the user-defined conversion; all such +routines for a given class are accumulated on a linked list. + +Since conversion functions are functions that convert an object of the current +class to a specified result type, the list that is created can serve as a list, +for a given source type, of all the target types for which a user-defined +conversion exists. This kind of list can be useful in selecting the +appropriate implicit cast during expression processing. + +User-defined conversion functions are inherited, so after all member +declarations have been seen, the list is augmented by projection symbols for +inherited conversion functions that result in types that are not already +present in the list (see ``project_base_class_conversion_functions`` which goes +through the conversion lists for each of the direct base classes of the current +class looking for unrepresented result types). + +Compiler-Generated Functions +---------------------------- + +A default constructor or a copy constructor is created by the compiler when it +is required in a class but was not explicitly declared by the user. Likewise a +compiler-generated destructor may be needed, or an assignment operator which +effectively copies an object of a given class onto another object of the same +class. Even if one of these functions is needed, only a declaration is +generated at first, not a function body. The body is generated only when there +is an actual invocation of the function. The functions will be declared as +extern inline member functions, just as if they had been explicitly defined in +the class definition. + +After all member declarations have been scanned, +``check_special_member_functions`` is called. For each compiler-generated +function determined to be needed, it calls ``generate_special_function``, which +creates a routine type entry and calls ``decl_member_function`` to create the +symbol and the routine entry. + +``reference_to_implicitly_invoked_function`` is called when a +compiler-generated function is implicitly invoked. If the function has no +body, ``define_special_member_function`` (in ``func_def.c``) is called, which +in turn calls ``make_default_constructor_body``, +``make_default_destructor_body``, or ``make_default_assignment_body``. The +compiler-generated assignment function is created only when a simple ``struct`` +copy is insufficient, i.e., when memberwise copying must be done explicitly. + +Trivial default constructors present a special problem. They are "trivial" +because calling them has no actual effect, so an obvious optimization is to +eliminate them. When the symbol supplement for a class has a NULL +``constructor`` pointer, that means the implicitly declared default constructor +for the class (always present in principle) is trivial and can generally be +ignored. There is an exception, however, when the definition of a trivial +default constructor would be ill-formed: then, even though no call is put out +in the IL, a diagnostic must still be issued. Here's an example: + +.. code:: c++ + + class A { + const int i; + }; + A var; + +Since class ``A`` is not a "POD-struct", ``var`` is default-initialized, which +means the default constructor ``A::A()`` is supposed to be called, and calling +an implicitly-declared constructor normally triggers its definition. The call +can be optimized away since it has no effect, but the definition would be +ill-formed (because ``A::i`` is ``const``-qualified). So to preserve the +behavior *as if* ``A::A()`` were called, its declaration is saved in the symbol +(see ``trivial_default_constructor`` in the class symbol supplement) and its +definition is generated at the point of implicit reference by a call to +``reference_to_trivial_default_constructor`` in ``symbol_ref.c``. + +.. _cppcli-member-funcs: + +C++/CLI Member Functions +------------------------ + +C++/CLI adds several variations for member function declarations in managed +classes. + +Syntactically, a static constructor is like a default constructor (i.e., with +no parameters) declared with the storage class ``static``. The two can +coexist, but they don't create an overload set. In expression contexts, +default construction always refers to the nonstatic constructor kind. In +declaration contexts, the static constructor is only found if the declaration +includes ``static`` (which is communicated to the lookup functions with the +flag ``IDL_IS_STATIC_DECL``). Static constructors are the only members that +can be defined outside their parent class with an explicit storage class +specifier (and such definitions must include that ``static`` specifier). + +Managed classes can contain finalizers: Their handling is completely parallel +to that of destructors. The syntax uses "``!X``" instead of "``~X``". + +User-declared accessor functions for properties and events are explained in +:ref:`cppcli-managed-types`. For trivial properties and events (which don't +include user-declared accessors), accessors are generated by calls to +``generate_trivial_accessor``. Whether generated or user-declared, the +``a_routine`` for an accessor function points to the +``a_property_or_event_descr`` entry associated with the corresponding event or +property. + +The member function modifiers ``sealed``, ``abstract``, and ``override`` are +accepted in both ordinary Microsoft mode and in C++/CLI mode. They can appear +after the optional const and/or volatile at the end of a nonstatic member +function declarator (see ``scan_microsoft_function_modifiers``), but in C++/CLI +``override`` is not optional for derived class members that override a member +in a base ref class. The modifier ``new`` is also accepted at this grammatical +location to indicated that a function does not implicitly override a virtual +base member with the same name and type. + +A virtual member function can also specify specific base members it overrides +using a specifier like "``= B::m, C::n``" where ``B`` and ``C`` are the base +classes or interfaces whose respective members ``m`` and ``n`` are +overridden/implemented. This is called "named overriding" (in contrast to +"implicit overriding"). + +Named overriding and the requirements of the ``override`` and ``new`` modifiers +are mostly handled in ``check_for_virtual_override`` and its helper functions. +These features add considerable complexity to that function. + +Member Function Templates +========================= + +``scan_class_definition`` calls ``template_declaration_or_directive`` (in +``templates.c``) when a member declaration begins with the keyword +``template``. When the declaration designates a function template, this +results in a call to ``class_member_template_declaration``, which in turn calls +``class_member_declaration``. Once processing by ``decl_specifiers`` and +``declarator`` has been done, ``decl_member_function_template`` is called to +create the ``sk_function_template`` symbol. A routine entry is also created, +but (as with nonmember template functions) it is not added to the IL. Rather, +it is attached to the template symbol supplement and is for front-end use only. + +Member Constant Extension +========================= + +As an extension to C++ the EDG front end allows "member constant" declarations. +[#f11]_ Member constants may be of any scalar type. For integers such a +declaration is similar to declaring a constant name in an ``enum`` declaration. +For example, instead of this: + +.. code:: c++ + + class A { + enum { MAX = 100 }; + int array[MAX]; + }; + +the program may declare and use a member constant: + +.. code:: c++ + + class A { + const int MAX = 100; + int array[MAX]; + }; + +Qualified-name references to member constants (e.g., to ``A::MAX``) are also +permitted, subject to the same access and ambiguity constraints imposed on any +class member. + +``class_member_declaration`` calls ``decl_nonstd_member_constant`` to process +such a declaration. It adds to the IL an entry of type ``a_constant`` (it is +appended to the ``constants`` list of the IL scope associated with the current +class), and it enters an ``sk_constant`` symbol that points to it. Note that a +member constant is not equivalent to an initialized ``const`` static data +member, which is represented as a variable in the IL. + +Friend Declarations +=================== + +A ``friend`` declaration involves (1) a class which gives ``friend`` access to +nonmembers and (2) the routine or class to which that access is given; and so +one may refer to the former as the *befriending* class and the latter as the +*befriended* routine or class. + +The class type supplement of the befriending class contains pointers +(``friend_routines`` and ``friend_classes``) to linked lists of entries +identifying the routines and classes to which friendship is given. This +corresponds to the way in which a friend declaration actually appears in the +source. + +In addition, the befriending-befriended relationship is represented the other +way around as well, with the befriending class also recorded in the befriended +routine or class. Specifically, routine entries have a pointer to a list of +entries that point to classes; the linked list identifies the befriending +classes, those that afford ``friend`` access to the specified routine. A +similar ``befriending_classes`` field can be found in the type supplement for a +befriended class. + +``decl_friend_function`` is called by ``class_member_declaration`` to process a +``friend`` function declaration. For a member function +``member_function_redecl_sym`` is called to get the symbol; otherwise, +``decl_routine`` in ``decls.c`` is called (where, if this is the first +declaration of the function, the symbol will be created in the appropriate +non-class scope). Once the symbol is retrieved, the current class is recorded +as a befriending class in the routine entry. + +``decl_friend_class`` is called to process a ``friend`` class declaration. +This is just a matter of recording the current class as a befriending class in +the type supplement of the befriended class. + +A class- or namespace-qualified ``friend`` declaration must refer to a +previously declared entity, but it may be that the first declaration of an +entity is an *un*\ qualified ``friend`` declaration. The lookup for an +unqualified ``friend`` declaration begins in the innermost enclosing +nonclass scope and continues to (but no farther than) the innermost +enclosing namespace scope, and if it is not found a declaration is +"injected" into the innermost enclosing nonclass scope. [#f12]_ For +instance: + +.. code:: c++ + + namespace N { + class S { + friend void f(); + /* ... */ + }; + void f() { /* ... */ } // Same "f" as declared a friend by N::S + } + +This approach is taken even when the specified name is visible in a scope +enclosing the innermost namespace scope -- in the above example, ``f`` would be +injected into namespace ``N`` even if a ``::f`` were visible. + +Using Declarations and Access Declarations +========================================== + +A ``using``-declaration inside a class definition is processed by +``member_using_declaration``, which is also called when +``scan_class_definition`` encounters a declaration that is a class-qualified +name followed by a semicolon, interpreted to be an old-style access declaration +of an inherited member. ``member_using_declaration`` performs error checking +and causes a projection symbol to be created to reserve the name in the current +class. The flag ``is_using_decl`` is set in the projection symbol, since this +is not an ordinary kind of projection and is subject to somewhat different +rules for computing accessibility; [#f13]_ it can also be added to an overload +set if it refers to an inherited member function. In addition, the declaration +is recorded in the IL by adding an entry of type ``a_using_decl`` to the scope +associated with this class, in case a symbolic debugger would need the +information (see ``make_using_decl`` in\ ``decls.c``). + +.. _cppcli-delegates: + +Delegates (C++/CLI mode) +======================== + +A C++/CLI delegate is a managed function object (i.e., a "callable" object) +that encapsulates an invocation list. A delegate type is introduced by a +delegate definition, which looks like a typedef for a function type where the +keyword ``typedef`` is replaced by a context-sensitive keyword ``delegate``. +The front end represents a delegate type as a mostly ordinary ref class type +synthesized from the signature provided in the definition. For example, a +definition like + +.. code:: c++ + + delegate void D(System::Object^); + +causes the front end to synthesize (in ``create_cli_delegate_definition``) +a ref class called ``D``, implementing the interface +``System::MulticastDelegate`` with (among others) a member function called +``Invoke`` with the signature of the delegate definition (to which "calls" +of delegate objects are dispatched), a constructor, and static member +operators ``+`` and ``-`` (to add or remove targets from the encapsulated +invocation list). + +.. _cppcli-props: + +Properties and Events (Microsoft and C++/CLI modes) +=================================================== + +Microsoft C++ includes a notion of "property" members for (otherwise +standard) class types. Syntactically, this is a field declared with an +attribute of the form ``__declspec(property(get=``\ *func_name1*\ ``, +put=``\ *func_name2*\ ``))``. The result is not really a field: No storage +is allocated for it, but every "read" operation on the pseudo-field is +mapped to a call of *func_name1* and every "write" operation is mapped to a +call of *func_name2* (either operation name may be omitted from the +attribute to create a read-only or write-only property). The IL +representation of this kind of property members uses ``a_field`` entries, +which point to entries of type ``a_property_or_event_descr``, and those +entries in turn record the name of the specified get and/or put functions. +*func_name1* and *func_name2* are looked up at every point that requires +their use, which may not always yield consistent results. Therefore, the +rewriting of property-field accesses is done right away in the front end +proper (and not, for example, in a later lowering pass since the symbol +table might have changed by then). + +C++/CLI provides a similar notion of properties for managed class types, but +instead of indicating the "accessor functions" (named ``get`` and ``set`` in +this case) by name in an attribute, they are part of the property definition +syntax. For example: + +.. code:: c++ + + ref struct RS { + property int p { int get(); void set(int); } + }; + +The IL representation is similar to that of the first kind of property (i.e., +the non-C++/CLI variant described above), but since the accessor functions are +independent from the point of use in this case, the corresponding ``a_routine`` +entries are pointed to directly from the ``a_property_or_event_descr`` entry +and vice versa. Also, since C++/CLI properties can be static or nonstatic, +their representation can be entries of type ``a_field`` and ``a_variable`` (the +latter corresponding to a pseudo-static-data-member). + +C++/CLI properties can be "indexed" to model a sort of "array field" (but +unlike regular fields, indexed properties can be truly multidimensional). +Furthermore, such indexed properties can be overloaded: + +.. code:: c++ + + ref class RC { + property double ip[double, int] { + double get(double, int); + set(double, int, double); + } + property float ip[float, int] { + float get(float, int); + } + }; + +Because of this possibility, the symbol representing a property in a class has +a kind ``sk_property_set``, which reflects that it potentially represents a set +of properties (unlike function symbols, there is no separate symbol kind for +single properties and overloaded sets). ``sk_property_set`` symbols point to a +structure of type ``a_property_set_symbol_supplement``, which in turn points +both to the associated pseudo-data-members (``sk_field`` or +``sk_static_data_member``) and to the overload sets formed by their ``get`` and +``set`` accessors respectively. + +Indexed properties can have the name ``default``: Applying a subscript to such +a property's parent object amounts to a use of such a property (this has some +similarity to the more traditional ``operator[]``). If any such +default-indexed properties are present in a class, the corresponding +``sk_property_symbol`` is pointed to from the class' symbol supplement. + +C++/CLI has a notion of "event" members. These are similar to C++/CLI +properties, but they cannot be indexed, must have handle-to-delegate type, and +they allow only three operations: ``+=``, ``-=``, and "call". An event +definition can declare up to three accessors (matching the aforementioned three +operations) called ``add``, ``remove``, and ``raise``, or it can be "trivial" +(in which case those accessors are generated by the front end). Since events +cannot be indexed, they cannot be overloaded, and no separate symbol kind is +needed for them: They're simply associated with the ``sk_field`` or +``sk_static_data_member`` symbol for their pseudo-data-member. + +Class Object Layout +=================== + +Laying out the storage for a class means computing the overall size of an +object of that type and assigning to each of its components an offset +representing its position in the object. Nonstatic data members are +represented by entries of type ``a_field``, each of which has an ``offset`` +value that represents the byte offset from the beginning of the object and a +``offset_bit_remainder`` value (nonzero for bit fields only) that represents +the additional bits that must be taken into consideration if the field is not +aligned on a byte boundary. Base classes have an ``offset`` field that +contains the byte offset from the beginning of storage for the class as a whole +to the beginning of storage for the base class's data section; for virtual base +classes there is also a ``pointer_offset`` field, which is the offset of the +pointer to the data section. The class type supplement also has a +``virtual_function_info_offset`` field. All these offset values together make +up the abstraction we refer to as the class's layout. + +Object Layout Models +-------------------- + +The front end provides by default two distinct object models: a "classic" model +based on the original cfront implementation and a more modern "IA-64" model +based on specifications drafted by a group of vendors for the 64-bit Itanium +Architecture of Intel. At the time of this writing, the latter specifications +can be found at: + + `www.codesourcery.com/cxx-abi `__ + +The implementation of both models can be found in ``layout.c``. Where +convenient, the same routines are used to implement the two models (e.g., there +is only one ``do_class_layout`` function). + +The front end can also be configured to implement small variations of both the +cfront-like and IA-64 models. For the cfront-like model, increased +compatibility with the original cfront implementation can be achieved by +setting ``CFRONT_OBJECT_CODE_COMPATIBILITY`` to TRUE (this involves routines +whose names start with ``cfc_``). Similarly, by setting +``DEFAULT_EMULATE_GNU_ABI_BUGS`` to TRUE, improved compatibility is achieved +with the default IA-64-based ABI implemented by GNU C++ 3.2 (and this involves +routines in ``layout.c`` whose names start with the ``gnu_`` prefix). + +General Layout Steps +--------------------- + +All classes are laid out in the same general way, following this pattern (in +the sequence indicated): + +* | First, in the IA-64 model, storage is reserved for the so-called *primary + base class* (if it exists) or for a pointer to a virtual table (if the + class is polymorphic without having a primary base): + + * | There is no primary base class concept in the cfront-like object model. + * | The primary base class shares a "virtual pointer" at offset zero with the + complete class. Usually, the primary base class is a nonvirtual direct + base class, but it can also be indirect and/or virtual in less common + situations. If none of the base classes are polymorphic, the derived + class has no primary base class. The primary base class is also pointed + to from the class type supplement (by the field ``primary_base_class``). + * | No storage is allocated for non-primary virtual bases of the primary base + class at this point. +* | Next, storage is allocated for all the remaining *direct* base classes + (which implicitly includes storage for nonvirtual *indirect* base + classes as well): + + * | In the cfront-like model, when the direct base class is also virtual, + only enough space is set aside for a pointer to the actual storage, + which appears later. In the IA-64 model, no such pointer is used and + -- unless it is also the primary base -- the direct virtual base is + allocated later on. + * | In the case of a nonvirtual direct base class, enough storage is set + aside for its own primary base class (if any), its nonvirtual base + classes, its virtual base class pointers (in the cfront-like model), its + own fields, and its virtual function information, but no space is + allocated for its virtual base classes. + * | In the cfront-like model, nonvirtual direct base classes that are *empty* + (no own or inherited nonstatic data members and no virtual functions or + direct or indirect virtual base classes) are allocated in a separate pass + when ``targ_optimize_empty_base_class_layout`` is TRUE. In the IA-64 + model, direct empty bases are allocated in the same pass as nonempty + bases. (See :ref:`empty-base-class-optimization`). +* | Next, storage is reserved for the class's own fields. +* | Next, in the cfront-like model, storage for virtual function information + (typically, a pointer to a virtual function table). +* | Finally, storage for its virtual base classes, with space enough in each + case for its own primary and nonvirtual base classes, virtual base class + pointers (cfront-like model only), fields, and virtual function + information. + +The storage and alignment for all the items but the last are recorded in the +class's type supplement as ``size_without_virtual_base_classes`` and +``alignment_without_virtual_base_classes``; the ``size`` and ``alignment`` +fields of the type entry itself record the values for the entire object. +Except in an incomplete type, both size values will be at least 1. + +This general sequence is implemented by ``do_class_layout``, which is called by +``scan_class_definition`` once all the members have been scanned. +``do_class_layout`` calls several subroutines: + +* | ``set_offsets_for_nonvirtual_base_classes`` to assign the offsets for + nonvirtual base classes; +* | ``set_offsets_for_fields`` to set the ``offset`` and + ``offset_bit_remainder`` values of each field; +* | ``set_offset_for_virtual_function_info`` to record the position at which + (typically) the virtual function table pointer will be found; +* | ``set_offsets_for_virtual_base_classes`` to lay out the part of the class + object where the data sections of virtual bases classes are kept; and +* | ``set_offsets_for_indirect_base_classes`` to record the offsets of indirect + nonvirtual base classes (this phase is really just a fixup pass -- no new + storage is reserved). + +.. _empty-base-class-optimization: + +The Empty Base Class Layout Optimization +---------------------------------------- + +The C++ language specifications allow an implementation to allocate an empty +base subobject at the same location as another subobject provided this does not +cause two objects or subobjects of the same type to be allocated at the same +address. For example: + +.. code:: c++ + + struct E {}; + struct A: E { char c; }; + struct B: E { E e; }; + +In ``A``, the base class ``E`` can be allocated at the same offset as the field +``c``, but in ``B`` the optimization cannot be applied because two subobjects +of the same type (the field and the base) would occupy the same address. + +In the cfront-like model, the front end implements this optimization when +``targ_optimize_empty_base_class_layout`` is TRUE and most of the required work +is performed in ``set_offsets_for_empty_nonvirtual_base_classes``. The +cfront-like optimization heuristic uses a two-pass algorithm: + +* | First the direct nonvirtual nonempty direct base classes are allocated as + usual; i.e. empty base classes are skipped. +* | Next, an additional pass is made in + ``set_offsets_for_empty_nonvirtual_base_classes`` to place the direct + nonvirtual empty base classes. The first offset to be attempted is the + origin of the object (i.e., zero). If a situation is detected that + would cause two subobjects with the same type to be allocated at the + same offset, a new offset is sought after the next allocated base (if + one is available). This is repeated for every empty base -- without + backtracking the offset -- until there are no more empty bases. + | Another example illustrates how the second pass is a single pass (i.e., + the offset if not backtracked): + + .. code:: c++ + + struct E1 {}; // Empty + struct E2: E1 {}; // Empty + struct E3 {}; + struct B { E1 e; } // Not empty + struct D: E1, E2, E3, B { char c; }; + // Layout: + // B : this+0. (a nonempty base is allocated in the first pass) + // E1: after B because at this+0 it conflicts with B::e. + // E2: at least one byte farther than direct base E1 because else + // E2::E1 conflicts with base E1. + // E3: same offset as E2 since there is no type conflict; there is, + // however, no backing up to the offset of direct base E1. + // c : same offset as E2 and E3. + + | The optimization can only be applied to empty base classes and not to empty + (nonstatic) data members. Hence, ``B`` cannot be considered empty in this + last example. + +In the IA-64 model, empty base classes are allocated in the same pass as other +direct nonvirtual base classes. In this case the heuristic is different: If +the base can be allocated at offset zero without causing a conflict with a +subobject that has already been allocated there, then that is where the empty +base class is allocated. Otherwise, it is allocated at the next available +offset. Every time a base class is allocated (whether empty or not), +``base_subobject_conflict`` is called: If a conflict is detected, the +allocation is retried at the next alignment boundary. This process is repeated +until there is no conflict. A similar process is needed for the first field +(to avoid having an empty base of a field end up at the same offset as an empty +base of the complete class). + +The IA-64 model also handles the concept of a *nearly-empty base class*: This +is a virtual base class whose storage requirement is limited to a virtual table +pointer and (optionally) its own virtual base classes. Such a class can be +selected as a primary base class, in which case it is allocated at offset zero. + +Deferred Class Fixup +==================== + +As mentioned above, default arguments, inline member function bodies, and field +initializers are not processed until the entire class definition has been seen; +and when the class is a nested class, the processing is deferred until the +definition of the outermost containing class has been completed. + +However, it gets even more complicated when templates are involved. Consider +this example: + +.. code:: c++ + + template class A { + void f(T* = new T) { ... } + }; + class B { + A x; + } b; + +Here, the instantiation of ``A`` is kicked off before the definition of +``B`` has finished, but the default argument expression for ``A::f(B*)`` +requires that ``B`` be complete. + +To accommodate cases like this, the default argument and inline function body +processing is deferred until all pending class definitions have completed. +(The definition of ``B`` is pending when the definition of ``A`` is +finished, so the fixup for the latter is deferred.) + +``scan_class_definition`` calls +``process_deferred_class_fixups_and_instantiations``, and if global variable +``pending_class_definitions`` is zero, +``process_deferred_instantiation_requests`` (in ``templates.c``) and +``process_deferred_class_fixups`` are called. + +The latter calls ``delayed_scan_fixup_for_class``, which scans the token caches +saved for default arguments and function bodies. First it pushes a class +reactivation scope. Then, for default arguments it pushes a function prototype +scope and calls ``delayed_scan_of_default_arg_expr`` (or, for class template +instances, ``delayed_scan_for_function_template_default_args``). For function +bodies it calls ``scan_function_body`` -- except that the scanning of inline +member function bodies inside a class template instance is further deferred +until the member function has actually been referenced. + +A similar mechanism is also used to delay processing of in-class initializers +for nonstatic data members in C++11 mode and of static data members of C++/CLI +managed classes; see ``record_inclass_initializer_fixup`` and +``inclass_initializer_fixup_for_class``. + +Class Linkage +============= + +Like functions and variables, a class has linkage recorded in the +``source_corresp.name_linkage`` field of its type entry. Ordinarily (i.e., +except in cfront-compatibility mode), when a class is first created, it is +given external linkage by default, except for local classes (which have no +linkage) and classes declared inside an unnamed namespace (which have internal +linkage). This setting in turn determines the linkage and storage class +applied to class members. + +In cfront mode, however, when a class is first created, it is given internal +linkage by default, and, since the class and its members are supposed to have +the same linkage, its members also have internal linkage (and correspondingly a +storage class of ``static``). These are provisional settings, however, since +the presence of a non-inline member function or a static data member requires a +class to become externally linked. Moreover, if a class is referenced in a +declaration of an externally linked entity, it needs to have external linkage. +Thus, at the end of translation unit processing ``check_class_linkage`` is +called (in cfront-compatibility mode only) to make a pass over all the classes +defined in the translation unit and, where appropriate, to fix up the linkage +and storage class of classes and their members. + +.. _lambdas: + +Lambdas +======= + +A C++11 lambda expression is essentially a shortcut to define a "function +object" class and initialize a temporary object of that class. For example: + +.. code:: c++ + + int f(int x) { + auto f_impl = [x]()->int { return x*2; }; + return f_impl(); + } + +is largely equivalent to: + +.. code:: c++ + + int f(int x) { + class _Closure { + int x; + public: + int operator()() const { return x*2; }; + }; + _Closure f_impl = (_Closure){ x }; + return f_impl(); + } + +The implementation of lambdas in the front end exploits this equivalence: When +expression processing encounters the beginning of a lambda expression, it hands +over the task of parsing the construct to ``scan_lambda`` (see +:ref:`scanning-operations`). This routine calls ``make_closure_class``, pushes +an associated class scope on the stack (after captures have been scanned -- see +below), and records a synthetic ``a_class_def_state`` structure to go along +with the class definition scope. This allows the lambda to be parsed much as +if it were an in-class definition of a member function. + +``scan_lambda`` also creates the ``a_lambda`` entry and records it in the scope +stack entry for the closure class. That allows, e.g., expression and statement +processing to be aware of the lambda context. The convenience function +``get_current_lambda`` is also useful for this purpose. The type entry for the +closure class does not itself directly point to the associated lambda (due to +memory region constraints), but its class type supplement has a flag indicating +that it is a lambda closure class type (rather than a user-defined class type). + +Explicit and Implicit Captures +------------------------------ + +The C++11 lambda syntax allows for the optional specification of an implicit +capture mode and explicitly captured local variables and expressions (the +latter are often referred to as "init-captures"). ``scan_lambda_capture_list`` +parses this construct and records it in the ``a_lambda`` entry. Explicitly +captured variables are recorded with a call to ``add_lambda_capture`` and +explicitly captured expressions are handled by a call to ``scan_init_capture``. +The fields associated with these explicit captures are added by a call to +``decl_lambda_capture_fields`` (after the closure class definition scope has +been pushed and after the optional lambda declarator has been processed). + +If an implicit capture mode has been specified (using the "``[=`` ... ``]``" +or "``[&`` ... ``]``" forms of the lambda capture list), +``add_lambda_capture`` is also the routine that records the capture (it also +creates the associated field in the implicit capture case). However, in such +cases we get there via ``lambda_capture_for_variable``, which is called from +the expression scanning routines while parsing the lambda body (ultimately, via +``scan_identifier``\ --see :ref:`scanning-idents`). + +The "Lambda Declarator" +----------------------- + +The syntax to describe lambda parameters, return type, and mutability is +optional and, when present, it differs from the ordinary member function +declaration syntax. Still, the function ``scan_lambda_declarator`` is much +simplified by reusing ``function_declarator``. (``function_declarator`` is +also used when parsing ordinary functions/operators, and is aware of the +enclosing class definition environment.) Similarly, +``decl_call_operator_for_lambda`` -- which creates the ``operator()`` member of +the closure class -- mostly relies on ``decl_member_function`` and +``decl_member_function_template``. + +For generic lambdas (a C++14 feature), the lambda declarator corresponds to the +declarator of a function template, where the template parameters are created +implicitly from the use of ``auto`` as a parameter type. For example: + +.. code:: c++ + + [](auto p) { return p*2; } + +creates a closure class with an ``operator()`` that is a member template +corresponding to: + +.. code:: c++ + + template auto operator()(_T p) { return p*2; } + +The front end implements this by prescanning the lambda declarator to record +information about ``auto`` parameters. If there are any such parameters, +``set_up_generic_lambda_declarator_scan`` then proceeds to set up a member +function template declaration environment. ``decl_specifiers`` also uses the +information gathered during the ``prescan`` to map occurrences of ``auto`` in +the parameter list to the appropriate template parameter type (see +``process_generic_lambda_param_type``). + +``a_func_info_block`` has been augmented with a pointer to the associated +``a_lambda`` when applicable, and some lambda-specific behaviors of +``function_declarator`` (e.g., ``mutable`` as a function qualifier instead of +cv-qualifiers) make use of it. + +If no return type is specified explicitly for the lambda, the return type is +temporarily set to the unknown type (``tk_unknown``). +``scan_return_expression`` is aware of this arrangement, and it will update the +return type if appropriate. After the lambda body has been scanned +``scan_lambda`` sets the return type to ``void`` if no return statement was +seen (through ``check_implicit_lambda_return_type``, which also performs other +language-mandated checks if the return type was implicitly determined by a +return statement). + +Scanning the Lambda Body +------------------------ + +The lambda body is parsed by ``scan_function_body`` as would the body of a +member function of a user-defined class type (or via +``function_prototype_instantiation``, in the case of a generic lambda). There +are however a few subtle differences involved for the lambda case. + +First, ``scan_function_body`` is called while the class scope is still active. +This is needed so that closure fields associated with implicit captures can be +generated. So the option ``SFB_NO_CLASS_REACTIVATION`` is passed to +``scan_function_body`` to avoid reactivating the scope of the not-yet-completed +closure class. + +Second, if IL lowering is enabled, the function body is not lowered when the +associated function scope is popped. Instead, that lowering is triggered by a +call from ``scan_lambda`` to ``finish_function_processing_for_memory_region``. +This is a consequence of the previous observation: Lowering of the member +function cannot happen when the associated member function is popped because +the parent (closure) class hasn't been completed yet. + +.. [#f1] For the most part the term "class" will be used generically in this + chapter to include structs and unions as well as types declared with + the ``class`` keyword. +.. [#f2] See :ref:`type-scope-and-symbol`. +.. [#f3] This rule does not apply in ``pcc`` mode, only in ANSI C and C++. +.. [#f4] In C mode a ``struct`` does not cause a new name scope to be + established, and so ``decl_scope_level`` for a nested ``struct`` + will be the scope in which the parent ``struct`` is contained. On + the other hand, in C++ where a new name scope *is* established for + classes, ``decl_scope_level`` is the scope of the class itself. +.. [#f5] This field is used in this manner during front end processing only. +.. [#f6] For instance, to create a virtual function table. (This would be the + typical use of this information, but the front end tries to avoid + introducing any constraints that would imply a particular + implementation of virtual functions.) +.. [#f7] To take this example a step further, if there were a declaration of + ``C::f()``, the overriding virtual function entry for ``A::f()`` (the + one that is associated with the base class for ``A`` in ``C``) would + have to be modified, since it now would be overridden by ``C::f()``. + This is discussed later. +.. [#f8] "Sealed" is called "final" in other dialects; the IL uses flags named + ``final`` to indicate this property. +.. [#f9] Computing the field's storage properties (alignment and offset within + an object of the class to which it belongs) is done as the class is + being laid out; see ``set_field_size_and_offset`` in ``layout.c``. +.. [#f10] As a consequence, the C++11 ``auto`` type specifier cannot be used + for these members since the type of the member could not be deduced + from the initializer. +.. [#f11] This functionality is based on an extension offered by the GNU C++ + compiler and was added before a similar feature was proposed for the + official language -- namely, ``const`` static data members with + in-class initializers. +.. [#f12] For nonlocal classes, of course, the "innermost enclosing nonclass + scope" and the "innermost enclosing namespace scope" will be one and + the same. +.. [#f13] See ``have_proj_access_to_symbol`` in ``symbol_tbl.c``. diff --git a/doc/_sources/code_style.rst.txt b/doc/_sources/code_style.rst.txt new file mode 100644 index 0000000..1c48c10 --- /dev/null +++ b/doc/_sources/code_style.rst.txt @@ -0,0 +1,702 @@ +================== +Coding Style Guide +================== + + +General Whitespace Rules +======================== + +* Maximum line length is 79 characters. +* Indentation is by 2 spaces. +* Editors should be set to use an 8 space tab width. + +General Line Wrapping +===================== + +General Condition Rules +----------------------- + +Conditions that cause the line length to exceed 79 characters are wrapped via a +line break following an operator. The continuation is left aligned with the +opening paren: + +.. code:: cpp + + if (/* something very long */ && + /* something else */) { + /* etc... */ + } /* if */ + + if ((a || b) && + (/* something very long */ || + /* something else */)) { + /* etc... */ + } /* if */ + + if ((a || b) && (/* something very long */ || + /* something else */)) { + /* etc... */ + } /* if */ + +General Statement Rules +----------------------- + +Expressions that cause the line length to exceed 79 characters are wrapped via +a line break following an operator. The continuation is right-aligned: + +.. code:: cpp + + int x = /* something very long */ && + /* something else (right-aligned to column 79) */; + +General Line Breaks +=================== + +Line breaks are prioritized as follows: + +* 1 line for a conditional preprocessor directives (e.g., #if, #ifdef, etc.) + unless adding whitespace would break a visual "grouping" (e.g., conditional + inclusion of a header in a list of headers, conditionally enabling a single + statement in a function, etc.). +* 1 line for a namespace declaration and its associated closing comments. +* 2 lines for a function definition. +* 1 line for a function, variable, or type declaration. + +Naming Convention +================= + +The EDG naming convention can be broadly described as "snake case" (with an +exception for templates). In snake case, names are composed of lower case +letters and underscores. + +For types, the naming convention additionally adds a "``a_``/``an_``" +prefixed to the typename. For instance, what (in many projects) would be +spelled ``struct thing`` is called ``struct a_thing``. + +Writing a Variable +================== + +Variables appearing in "global" (these technically shouldn't exist as +there's a conditional "``edg``" namespace around all file contents) or +namespace scope are indented using tabs in older files which make use of +tabs and the equivalent +(8) spaces in newer files. The type is not indented, the name is indented by +2 tabs, and a comment should be added at 3 tabs: + +.. code:: cpp + + a_variable_type_name + my_variable; + /* A descriptive comment. */ + +If a variable type or name ends before the next tab stop, the lines should be +collapsed: + +.. code:: cpp + + a_variable_type_name + x; /* A descriptive comment. */ + int my_variable; + /* A descriptive comment. */ + int x; /* A descriptive comment. */ + +.. _writing-a-function: + +Writing a Function +================== + +Parameter Alignment +------------------- + +Functions declarations that fit within a single line should do so: + +.. code:: cpp + + void foo(int a, int b, int c); + +If a function declaration does not fit on a single line, it should be broken up +with the parameters broken up into two left-aligned columns, one column of +parameter types, and one column of parameter names: + +.. code:: cpp + + void foo(a_variable_type thing, + an_other_variable_type other_thing, + a_thingy thingy); + +Wrapping Function Declarations +------------------------------ + +Particularly for function definitions with lots of qualifiers and long names +(member functions are particularly guilty), simply wrapping the parameters can +be insufficient. In these cases, there are two accepted techniques for keeping +the function within the required line length. + +If the function has qualifiers like ``static`` and ``inline`` these can be +moved to the preceding line along with the return type: + +.. code:: cpp + + static inline void + very_long_long_long_long_foo(a_variable_type thing, + a_nother_variable_type other_thing, + a_thingy thingy); + +If this is still insufficient, the parameters can be moved to a new line and +right-aligned: + +.. code:: cpp + + void very_long_long_long_long_long_foo( + a_variable_type thing, + a_nother_variable_type other_thing, + a_thingy thingy); + +Documentation +------------- + +In a function definition, a comment should be added after the closing paren but +before the opening curly brace. This comment should describe all of the +parameters, the return value, and any actions it takes, and the closing +``}`` of the function should be followed by a comment giving the name +of the function, separated from the ``}`` by two spaces: + +.. code:: cpp + + a_boolean foo(int num_l_parens, int num_r_parens) + /* + Given the number of left parens (num_l_parens) and the number of right + parens (num_r_parens), display the values and return TRUE if the + numbers are equivalent; otherwise, return FALSE. + */ + { + printf("lparens=%d, rparens= %d\n", num_l_parens, num_r_parens); + return num_l_parens == num_r_parens; + } /* foo */ + +This also applies to void functions that use output parameters: + +.. code:: cpp + + void foo(a_boolean *result, int num_l_parens, int num_r_parens) + /* + Given the number of left parens (num_l_parens) and the number of right + parens (num_r_parens), assign *result to TRUE if the numbers are equivalent; + otherwise, assign *result to FALSE. + */ + { + *result = (num_l_parens == num_r_parens); + } /* foo */ + +Return Value +------------ + +If a function requires a variable to hold the result, it should be the first +variable in the function, and it should be named "``result``": + +.. code:: cpp + + int foo() + /* + A descriptive comment. + */ + { + int result; + + /* etc... */ + return result; + } /* foo */ + +Variable Grouping +----------------- + +Variables should be grouped into blocks with their types and names aligned. +The first block of variables should have a trailing newline, and any following +blocks should use a preceding newline: + +.. code:: cpp + + int foo() + /* + A descriptive comment. + */ + { + int result; + a_boolean temp_state; + + /* etc... */ + + a_state_catcher secondary_state; + a_boolean state_catcher_used = FALSE; + /* etc... */ + return result; + } /* foo */ + +Writing a Lambda +================ + +Lambdas are a case that's a mix of variable and function rules. Lambda +parameters -- similar to function parameters -- should be broken up into two +left-aligned columns, one column of parameter types, and one column of +parameter names: + +.. code:: cpp + + auto x = [](int num_l_parens, + int num_r_parens) -> a_boolean { + return num_l_parens == num_r_parens; + }; + +Unlike functions, lambdas do not require a documentation comment, or a closing +comment. For this reason, lambdas should be reserved for fairly trivial +operations. + +If a lambda appears in a block of other variables, the lambda should follow the +name alignment of the variables in the same block, e.g., + +.. code:: cpp + + a_long_type_name y = /* etc... */; + auto x = [](int num_l_parens, + int num_r_parens) -> a_boolean { + return num_l_parens == num_r_parens; + }; + +Writing a Class +=============== + +Classes should be preceded by a descriptive comment, and terminated by a +closing comment giving the class name and separated from the ``;`` by two +spaces: + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + /* etc... */ + }; /* foo */ + +Data Members +------------ + +Data members should be written at the end of the class. In terms of +indentation, data members are indented similarly to variables in global & +namespace scope, with the exception that the type is always indented by two +spaces: + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + /* etc... */ + private: + a_variable_type_name + my_var_a; + /* A descriptive comment. */ + a_variable_type_name + b; /* A descriptive comment. */ + int my_var_c; + /* A descriptive comment. */ + int d; /* A descriptive comment. */ + }; /* foo */ + +Member Functions +---------------- + +Member functions (including special member functions like constructors and +destructors) that do not exceed 1 line can be written inline: + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + void bar() + { this->x += 1; } + private: + int x; /* A descriptive comment. */ + }; /* foo */ + +If the member function is empty it should be spelled "``{}``" (no space): + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + void foo() + {} + }; /* foo */ + +Member functions that exceed 1 line should be written out-of-line: + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + void complex_bar(); + private: + int x; /* A descriptive comment. */ + }; /* foo */ + + + void foo::complex_bar() + /* + A descriptive comment about complex_bar. + */ + { + /* etc... */ + }; /* foo::complex_bar */ + +Additionally see :ref:`writing-a-function` as those rules also apply to member +functions. + +Member Initializer +------------------ + +If initializing using a passed value, the data members and parameters +should have names that differ (e.g., for a data member ``x``, ``x_val`` can +be an appropriate parameter name). + +Additionally, the introducing colon and all member initializers should be +indented two spaces, e.g., + +.. code:: cpp + + /* + A descriptive comment about class foo. + */ + struct foo { + void foo() + : x(1), y(2), z(3) + {} + inline void foo(int x_val, int y_val, int z_val); + int x; /* A descriptive comment. */ + int y; /* A descriptive comment. */ + int z; /* A descriptive comment. */ + }; /* foo */ + + + void foo::foo(int x_val, int y_val, int z_val) + /* + A descriptive comment about foo::foo. + */ + : x(x_val + 100), y(y_val + 1000), + z(z_val + 10000) + { + /* etc... */ + }; /* foo::foo */ + +Statements +========== + +``for`` Statements +------------------ + +C-style +^^^^^^^ + +"C-style" ``for`` loops should be formatted with their contents indented by 2 +spaces, and a closing comment (with two preceding spaces): + +.. code:: cpp + + for (int x = 0; x < 10; ++x) { + /* etc... */ + } /* for */ + +If the condition of the ``for`` loop causes the line length to exceed 79 +characters, it should be broken up at the semicolons: + +.. code:: cpp + + for (int long_variable = 0; + long_variable < another_long_variable; + ++long_variable) { + /* etc... */ + } /* for */ + +Range-based +^^^^^^^^^^^ + +Range-based ``for`` loops should be formatted as "C-style" ``for`` loops +are, with the exception that, if the condition cause the line length to +exceed 79 characters, it should be broken at the colon and right aligned: + +.. code:: cpp + + for (a_long_type &&x : + some_container) { + /* etc... */ + } /* for */ + +``if`` Statements +----------------- + +``if`` statements should be formatted with their contents indented by 2 +spaces. ``else`` and ``else if`` clauses should be preceded and followed by +braces, aligned with the ``if``, and the closing brace aligned with the +``if`` and followed by an ``if`` comment (with two preceding spaces): + +.. code:: cpp + + if (argument) { + /* something */ + } else if (other_argument) { + /* something else */ + } else { + /* default action */ + } /* if */ + +``switch`` Statements +--------------------- + +``switch`` statements should be formatted with their case labels indented +by 2 spaces, the contents further indented by two spaces, and a closing +comment (with two preceding spaces). The opening brace of a scoping block +can be immediately followed on the same line by the first statement of the +block, and its closing brace should have no comment: + +.. code:: cpp + + switch (argument) { + case a: + { int y = 10; + + x += y; + } + break; + case b: + x += 1; + break; + case c: + /* no-op */ + break; + default_is_unexpected(); + } /* switch */ + +``while`` Statements +-------------------- + +Pre-condition +^^^^^^^^^^^^^ + +"Pre-condition" ``while`` statements should be formatted with their contents +indented by 2 spaces, and a closing comment (with two preceding spaces): + +.. code:: cpp + + while (argument) { + /* etc... */ + } /* while */ + +Post-condition +^^^^^^^^^^^^^^ + +"Post-condition" (i.e., ``do``) while statements should similarly be +formatted with their contents indented by 2 spaces. However, unlike +"pre-condition" ``while`` statements, no closing comment is required: + +.. code:: cpp + + do { + /* etc... */ + } while (argument); + +Preprocessor Directives +======================= + +``#if`` and ``#endif`` +---------------------- + +``#if`` should have its closing #endif commented with the condition used +(preceded by a single space): + +.. code:: cpp + + #if MACRO_IS_ENABLED + /* etc... */ + #endif /* MACRO_IS_ENABLED */ + +If the condition is complicated, the closing comment can be abbreviated: + +.. code:: cpp + + #if MACRO_IS_ENABLED && (OTHER_MACRO_IS_ENABLED || \ + OTHER_OTHER_MACRO_IS_ENABLED) + /* etc... */ + #endif /* MACRO_IS_ENABLED && (OTHER_MACRO...) */ + +``#else`` +--------- + +If an ``#if`` makes use of an ``#else`` a comment should express the negated +condition (preceded by a single space): + +.. code:: cpp + + #if MACRO_IS_ENABLED + /* etc... */ + #else /* !MACRO_IS_ENABLED */ + /* etc... */ + #endif /* MACRO_IS_ENABLED */ + +``#elif`` +--------- + +If an ``#if`` makes use of an ``#elif``, no change to comments is performed: + +.. code:: cpp + + #if MACRO_IS_ENABLED + /* etc... */ + #elif OTHER_MACRO_IS_ENABLED + /* etc... */ + #endif /* MACRO_IS_ENABLED */ + +Templates +========= + +Templates follow the rules of the respective thing being templated, with +the exception that the name for templates declaring a type should not +follow the normal naming convention. For class and alias templates, no +``a_`` or ``an_`` qualifier is used, instead an uppercase letter starts the +name (e.g., ``Dyn_array``). + +Template Parameters +------------------- + +Template parameters, like template declarations, have their own naming +convention. They should be named ``a_``/``an_`` followed by a capital +letter, and then a descriptive name, e.g., + +.. code:: cpp + + template + struct My_template; + +If multiple template parameters need to be denoted as the "1st, 2nd, 3rd, +etc." version of a parameter, capital letters can be used to denote this, +e.g., + +.. code:: cpp + + template + struct Thingy_helper; + +Special Cases +============= + +Pointer & Reference Types +------------------------- + +The rule for pointer and reference types is that the pointer or ref qualifier +accompanies the name being typed (for purposes of a function, consider the +return type the "type" of the function) e.g., + +.. code:: cpp + + void foo(int *result, const thingy &a) + /* + A descriptive comment. + */ + { + int &c = a.value; + + *result = c; + } /* foo */ + + + a_thingy *alloc_thingy(); + +Empty Loop Bodies +----------------- + +Empty compound statements (e.g., function bodies and loop bodies) should be +spelled "``{}``" (no space) and follow the looping statement on the same line, +e.g., + +.. code:: cpp + + for (x = 0; x < y; x *= 2) {} + + while (try_op(x)) {} + +Annotating Function Arguments +----------------------------- + +When a function is called with an argument of a fixed value (e.g., a +``TRUE`` or ``FALSE`` value for a "flag" argument) the argument should be +annotated with a comment naming the associated parameter, e.g., + +.. code:: cpp + + int chars = count_characters(str, /*include_whitespace=*/FALSE); + +When ``NULL`` is passed, it should either follow the same convention or +be cast to the parameter's type, e.g., + +.. code:: cpp + + some_func(one_thing, /*associated_thing=*/NULL); + other_func(something_else, (a_foo*)NULL); + +Wrapping Function Calls +----------------------- + +Function calls that cause the line length to exceed 79 characters can be +handled one of two ways. + +If the function call is initializing a variable, and would otherwise fit on the +line, it can be moved down a line and right aligned: + +.. code:: cpp + + int x = + my_very_long_function(a, b, c, d, e, f, g, h); + +Otherwise, the function call should be wrapped on the arguments, aligning +continuation lines with the "``(``" of the function call; if there is a +single argument that cannot fit between the "``(``" column and the right +margin, the call should be broken after the "``(``" and all continuation lines +aligned with the position resulting from right-justifying the longest +argument. The exact style for wrapping the arguments is not specified, but +in general developers should, in the interest of compact code, flow as many +arguments together as will fit on each line: + +.. code:: cpp + + int x = my_very_long_function(a, b, c, d, e, f, + g, h); + +If arguments have some logical relation, e.g., for an area function, these +arguments can be grouped to emphasize the relation instead of flowing for +maximal compactness: + +.. code:: cpp + + compute_area_of_points(x1, y1, z1, + x2, y2, z2); + +In cases where the arguments are annotated with embedded comments, it may be +desirable to distribute them across multiple lines for clarity and neatness, +e.g., + +.. code:: cpp + + f(a, b, c, d, /*is_foo_bar=*/FALSE, + /*needs_more_squirrels=*/VERY_FALSE); + +instead of: + +.. code:: cpp + + f(a, b, c, d, /*is_foo_bar=*/FALSE, /*needs_more_squirrels=*/VERY_FALSE); diff --git a/doc/_sources/cp_gen_be.rst.txt b/doc/_sources/cp_gen_be.rst.txt new file mode 100644 index 0000000..b809f87 --- /dev/null +++ b/doc/_sources/cp_gen_be.rst.txt @@ -0,0 +1,300 @@ +======================= +C++-Generating Back End +======================= + +The C++-generating back end is a "back end" that turns C or C++ intermediate +language back into source text in C or C++. It is designed for +source-to-source-transformation applications, i.e., processors that read in +source code, make some modifications to its meaning (e.g., adding profiling +code), and then write it out as modified. + +The C++-generating back end handles C++, ANSI/ISO C, and K&R C [#f1]_. The +output is in the same language as the input, and means the same thing, but +is not expected to be identical. At the very least, comments are +eliminated and preprocessing is done, which means ``#include`` files are +merged in, macros are expanded, and ``#if``\ s and the like are processed. +The output *will* match the input exactly with regard to entity names and +source line numbers (the latter by use of ``#line`` directives, if +necessary), and in the order of declarations and statements in the source. +In short, it should be possible to compile the output file with a C or C++ +compiler, execute it to get the same results as the original program, and +debug it using the original source text. + +The source code for the C++-generating back end is in ``cp_gen_be.c``; +``cp_gen_be.h`` contains the associated declarations. + +Source Sequence Lists +===================== + +The C++-generating back end requires the source sequence list, which is a +construct that lists all declarations and statements of the source program in +the order of their appearance. It is optional, and must be enabled by the +configuration flag ``GENERATE_SOURCE_SEQUENCE_LISTS``. The source sequence +list stands alongside the "normal" tree-structured intermediate language, as a +sort of table of contents for the IL tree. That is, for a program fragment +that declares variable ``i``, function ``f``, and variable ``j``, the source +sequence list would be a list of three entries, pointing to the IL entries for +``i``, ``f``, and ``j``, and the tree-structured information under those +entries would provide full information on the entities. + +The list is conceptually a single list that runs through the whole compilation +unit, though in actuality it is implemented by a somewhat more complicated data +structure that snakes between the file scope memory region and the function +scope memory regions. That is, however, merely the low-level representation +dictated by the restrictions on pointers between memory regions, and is hidden +by access functions, e.g., ``adv_to_signif_source_sequence_entry``. + +Some entities in the source program may be declared or defined more than once. +For example, a function can be declared and then later defined. For such +cases, one of the occurrences (the definition if there is one) is selected as +the primary declaration, and the source sequence entry for that declaration +points directly at the IL entry for the entity. For all the other +declarations, the source sequence entry on the list points to a source sequence +secondary declaration entry, which points to the IL entry for the entity and +also gives information about that particular declaration, e.g., the source +position and the specific type used (which may differ from that of the +definition by use of typedefs, array bounds, etc.). + +The C++-generating back end operates by traversing the list and generating code +for each construct it encounters. A program is considered to be made up of an +alternation of declarative regions and executable regions. + +In declarative regions, the C++-generating back end steps through the +entries on the source sequence list, each of which points to a declared +entity, and generates declarations. Source sequence entries for class, +struct, union, and enum types that are declared as part of some other +declaration (e.g., "``struct A {int i;} x;``"), called *non-*\ autonomous +declarations, are skipped over without generating a declaration for the +type, but the type is marked to be put out when encountered while putting +out the type of the containing entity (e.g., "``x``" above). All other +declarative source sequence entries are processed immediately. + +In executable regions, the C++-generating back end steps through the source +sequence entries (a flat list) and the IL statement entries (a tree) in tandem, +and generates code for the statements. + +Declarations +============ + +The top-level routine for declaration processing is ``gen_declaration``. It +calls routines like + +* | ``gen_variable_decl``, +* | ``gen_routine_decl``, +* | ``gen_namespace``, +* | ``gen_type_decl``, +* | ``gen_template``, +* | ``gen_using_directive_or_declaration``, and +* | ``gen_instantiation_directive``. + +``gen_type_decl`` breaks the various type-declaration cases down as calls to + +* | ``gen_class_definition``, +* | ``gen_enum_definition``, or +* | ``gen_typedef_decl``. + +``gen_declaration_using_type`` and ``gen_type`` output types in general, by +calling routines in ``il_to_str.c``. + +``gen_secondary_decl`` handles secondary declaration source sequence entries. + +``gen_initializer`` handles initializers on variables. It calls +``gen_dynamic_init`` to handle dynamic initialization. + +``gen_class_definition`` uses normal declaration routines like +``gen_routine_decl`` to put out code for the class members, and also the +following, which handle special kinds of members: + +* | ``gen_field_decl``, +* | ``gen_member_constant_decl``, and +* | ``gen_using_declaration.`` + +``gen_type_decl``, ``gen_variable_decl`` and ``gen_routine_decl`` include +special code to deal with declarations within class definitions. In +particular, they deal with friend declarations. + +Executable Code +=============== + +The top-level routine for executable code processing is ``gen_statement``. +Most statements are straightforward, but the following routines handle the more +complicated cases: + +* | ``gen_block_statement``, +* | ``gen_try_block_statement``, +* | ``gen_switch_statement``, and +* | ``gen_for_statement``. + +Expressions are handled by ``gen_expr``, with some more complicated cases +handled by: + +* | ``gen_new_delete`` and +* | ``gen_temp_init`` + +The expression routines always add parentheses around expressions if there is +any chance of precedence confusion. + +Constants +========= + +Constants are put out by ``gen_constant``, which calls routines in +``il_to_str.c`` to do the actual output. + +``gen_initializer_constant`` handles initializer constants, which include +aggregate constants, ``ck_dynamic_init`` constants, and cases where a reference +is initialized from a constant, as well as the usual kinds of constants. + +Templates and Macros +==================== + +Templates and macros are strange cases in the IL. Both are macro-like, in +that the source provides a prototype that is expanded by the front end on +each use of the construct. That means that template and macro references +are largely invisible in the IL -- one sees only the expanded form and +little evidence that it came from a template or macro reference. + +It is nevertheless desirable to be able to put out the template and macro +definitions in some way so that template instantiation and symbolic debugging +can be done on the generated code. To accommodate this need, the IL optionally +contains entries for templates and macros. These contain normalized textual +representations of the template or macro (e.g., a string like "``#define x(a) +a+1``"). The C++-generating back just puts those out verbatim. (The macro +entries are all put out at the end of the output file, so they won't affect the +already-macro-expanded code that is put out, but they will still be available +for symbolic debuggers.) Note that macro entries are also used for ``#undef`` +directives. See ``gen_template`` and ``gen_macro``. + +Source Output +============= + +The effective position for source output is set by calling +``set_output_position``. That will result in generation of ``#line`` +directives as necessary, but not until some text is actually output, at which +point ``adjust_output_position`` is called. Note that while line number +correspondence is maintained in the output, there is no attempt to maintain +column number correspondence, or even to do appropriate indentation. + +Actual text output is done through + +* | ``write_ch``, +* | ``m_write_ch``, +* | ``write_space``, +* | ``m_write_space``, +* | ``write_tok_ch``, +* | ``m_write_tok_ch``, +* | ``write_tok_str``, +* | ``m_write_tok_str``, +* | ``write_unsigned_num``, and +* | ``write_num``, + +The names that begin with "``m_``" are macros and are intended for those cases +where speed is important. The others are functions. The names that include +"``_tok_``" are used to write complete tokens or sequences of tokens; the +low-level routines are given permission to break long output lines before or +after such text to avoid overly-long lines. + +Troublesome Cases +================= + +Names +----- + +Names are, in general, put out exactly as they appear in the IL. In some +cases, unnamed entities are given generated names. Members of classes are in +general put out as qualified names (e.g., ``A::x``), but sometimes special care +is required: + +* | The declaration of a member within its class must not use a qualified name. + To handle this, a name context stack is maintained (see + ``push_name_context`` and ``pop_name_context``), tracking the current + scope. When immediately within a class definition, the class qualifier for + that class is suppressed. The same thing is done for namespaces. +* | A call of a virtual function with a qualified name suppresses the + virtual-ness of the function, so a qualified name must be used only if that + behavior is desired. +* | In references to nonstatic members of classes (data or function), the + choice of name can have an effect on access control (e.g., for protected + members) and can disambiguate an otherwise ambiguous member name. + ``gen_simple_field_selection`` and ``gen_bound_function`` handle such + references for data and function cases, and call + ``optimized_expr_for_selection`` to determine the class to be used in + naming the member (that's done by examining any implicit casts used in the + member selection). +* | Sometimes, a prefix "``::``" or an elaborated type specifier (e.g., ``class + X``) must be used to distinguish one name from another. One would think + that always generating those would be the appropriate (and easy) thing to + do. It turns out, however, that various compilers have bugs in that area, + and won't accept some valid code generated in that mechanical way. As a + consequence, the C++-generating back end uses the hidden-name information + developed by the front end to generate prefix "``::``", qualified names in + general, and elaborated type specifiers only when they are required. See + ``alloc_hidden_name_fixup`` et al. This processing has an additional + benefit: it handles external variables and functions that are declared + ``extern`` within a function. References to such entities must not use a + "``::``" prefix, because although the entity named is external, and thus in + some sense in the global scope, the name used for it is declared local to + the function. + +See + +* | ``gen_name``, +* | ``gen_unqualified_name``, +* | ``gen_decl_name``, +* | ``gen_class_qualifier``, and +* | ``gen_namespace_qualifier``. + +References +---------- + +Reference types, or rather uses of entities with such types, require some +special attention. In expressions, ``eok_reference_to`` and +``eok_ref_indirect`` occur in order to make explicit the indirection implicit +in the uses of the reference types; these operators are simply ignored when +generating the expressions. + +More subtle is the fact that certain kinds of constants implicitly contain an +"address-of" operation. The ordinary processing of these by ``form_constant`` +adds an ``&`` to the output before writing the constant's value; this ``&`` +must be suppressed when the constant has a reference type (or, more generally, +is used in an lvalue context). This special processing is provided by +``handle_lvalue_constant_node``. + +Prototype Scopes +---------------- + +Prototype scopes (scopes associated with a prototyped function declarator, in +C) cause a particular set of headaches, because while such types cannot be +named outside of the prototype scope, they do nevertheless show up in the types +of objects outside those scopes. For example: + +.. code:: c++ + + void f(struct A {int i;} *p); + void g(enum E {e1}); + main() { + f(0); /* Really f((struct A *)0) */ + g(1); /* Really g((enum E)1) */ + return 0; + } + +The C++-generating back end deals with these by noting such cases and +suppressing the explicit casts in those cases. The conversion is then once +again implicit in the output program. + +See ``is_implicitly_cast_integral_constant``. + +Rewritten Property References +----------------------------- + +References to Microsoft properties are rewritten by the front end. Something +like "``p+1``", referring to a property ``p``, might have been rewritten as +"call the get accessor function for ``p``, add ``1``\ to it, and store the +resulting value by calling the set accessor for ``p``." The C++-generating back +end recovers the original source form. This is based on a field in expression +nodes called ``rewritten_property_reference_kind``, which is set by the front +end to special values to identify certain key nodes in the expansion. See +``gen_prop_event_or_op_synth_call``. Event references are similarly +reconstituted. + +.. [#f1] It cannot be used, however, to generate C from the output of IL + lowering. diff --git a/doc/_sources/decls.rst.txt b/doc/_sources/decls.rst.txt new file mode 100644 index 0000000..f87d801 --- /dev/null +++ b/doc/_sources/decls.rst.txt @@ -0,0 +1,1081 @@ +============ +Declarations +============ + +Declaration scanning is shared among a number of files. What is specific to +class member declarations is found in ``class_decl.c`` and is discussed in the +next chapter. The remainder of declaration processing is found in ``decls.c``, +which contains the top level routines and a number of utility functions; +``decl_spec.c``, which handles declaration specifiers; ``declarator.c``, which +scans declarators; ``func_def.c``, which contains the code to process function +definitions; and ``decl_inits.c``, which contains the code to scan +initializers. ``decls.h``, ``decl_spec.h``, ``declarator.h``, ``func_def.h``, +and ``decl_inits.h`` contain associated declarations. In addition, code for +disambiguating C++ declarations and expressions is found in ``disambig.c``, +with associated declarations in ``disambig.h``. + +Overview +======== + +The top level routine in declaration scanning, and in fact in the overall +compilation process, is ``translation_unit``, which scans a series of +declarations and stops at end of file. The routine it calls is +``scan_nonmember_declaration`` (via the older ``declaration`` interface), which +is also called for local declarations that appear within functions or blocks +(including old-style parameter declarations). (The only declarations that do +not pass through ``declaration`` are class member declarations and new-style +parameter declarations.) + +Since a typical declaration looks like this: + + | *decl-specifiers* *declarator-list* ``;`` + +two principal elements in the structure of ``scan_nonmember_declaration`` are + +* | a call to ``decl_specifiers``, which scans the type specifier, storage + class keyword, and so forth; and +* | a loop to handle a comma-separated list of declarators with successive + calls to ``declarator``. + +There are many details, including a lot of error checking and some special +cases. But in general, after the return from ``declarator``, one of several +routines is called (though not called directly from ``declaration``) to do +additional processing: + +* | When a function body is present ``function_definition`` is called and the + loop is exited. +* | ``decl_variable`` is called for declarations of variables. +* | ``decl_routine`` is called for declarations of non-member functions without + bodies (it is also called via ``function_definition`` when a body is + present). +* | ``decl_typedef`` is called for ``typedef`` declarations. +* | ``decl_parameter`` is called for old-style parameter list declarations. +* | ``define_static_data_member`` is called for C++ static data member + definitions. + +Finally, if an initializer is present in a variable or static data member +declaration, it is scanned by a call to ``initializer``; in cases where default +initialization may be required, ``def_initializer`` is called. + +Other sorts of declarations are handled by the following (via +``check_special_declaration_form``): + +* | ``template_directive_or_declaration`` is called for template declarations, + template instantiation directives, and template specializations (in other + words, declarations that begin with the keyword ``template``). +* | ``namespace_declaration`` is called for namespace and namespace alias + declarations. +* | ``nonmember_using_declaration`` is called for all ``using``-declarations + except those appearing in a class definition. +* | ``using_directive`` is called for ``using``-directives. +* | ``asm_declaration`` is called for declarations that begin with the keyword + ``asm``. +* | ``alias_declaration`` is called for C++11-style alias declarations. +* | ``scan_and_record_cli_delegate_definition`` is called for C++/CLI delegate + definitions. + +Declaration Parse State +----------------------- + +The outline above just lists a few of the many functions involved in parsing +declarations, and many of those functions need to share various bits of state. +The principal structure tracking this state through this process have type +``a_decl_parse_state``. This keeps track of types (declared type, effective +type, etc.), positions (start of declaration, declarator, certain specifier +keywords, etc.), additional declarative attributes (GNU, Microsoft, etc.), and +so forth. + +For declarations involving a declarator, the declared entity's symbol, once +available, is pointed to by ``dps->sym`` where ``dps`` is a pointer to the +declaration parse state for that declaration. + +In most cases the declaration parse state is initialized using the +``init_decl_parse_state`` macro, but when multiple comma-separated declarators +are handled, the state is recycled for each secondary declarator by calling +``start_secondary_declarator`` (which preserves and even restores state +associated with the common declaration specifiers). + +``a_decl_parse_state`` includes a field of type ``an_init_state`` to describe +the processing of any initializer associated with the declaration (although +``an_init_state`` variables can also exist independent of a specific +declaration; see also :ref:`init-components-and-state`). + +The ``a_decl_parse_state`` stucture also maintains a list of "actions" +(pointers to functions accepting a pointer to that state) that should be run at +the end of a declaration; this can be useful when a local declaration element +is encountered that cannot be checked until the declaration has been more or +less completely processed. New actions can be registered by calls to +``add_end_of_parse_action`` (they are eventually run by a call to +``run_end_of_parse_actions``). + +The ``a_decl_parse_state`` structure is not only used by declarations handled +by ``scan_nonmember_declaration``, but also for class member declarations, +parameter declarations, and even when parsing type names in contexts such as +casts and template arguments (through function ``type_name_full``), which isn't +really declaration parsing at all. + +.. _cppcli-assembly-decls: + +Declarations from C++/CLI Assembly Metadata +------------------------------------------- + +In C++/CLI mode, the front end is able to import assembly metadata files. This +is achieved by first transforming the metadata into equivalent C++/CLI source +code, and then parsing that code. Whether metadata is imported implicitly +(because it is the core library file), explicitly through a "preusing" +command-line toption, or explicitly through a ``#using`` directive, the root +function doing the importing is ``import_metadata`` (in ``preproc.c``). This +function sequences the following operations: + +* | It prepares a file for importing by calling ``make_cli_metadata_file`` and + ``import_metadata_file``. +* | If all went well, it calls ``generate_top_level_metadata_code``, which + creates a string containing C++/CLI source representing the + declarations -- but not the definitions -- of the top-level entities + (which are managed class types) in the metadata file. The actual work + for this is done by the "metadata reader" implemented in + ``ms_metadata.cpp`` (a C++ file meant to be compiled only in a + Microsoft environment). +* | Finally, the generated string is passed to + ``scan_top_level_metadata_declarations``, which (much like + ``translation_unit``) repeatedly calls ``declaration`` to internalize the + generated code. + +The definitions of the generated entities [#f1]_ aren't imported until (and +unless) they are needed. When that happens, a process somewhat similar to that +of ``import_metadata`` is performed by ``get_definition_of_class``, but this +time routines to process definitions are called instead of ``declaration``: +``scan_cli_generic_class_definition_from_assembly_import`` for generic entities +(including generic delegates), +``scan_cli_delegate_definition_from_assembly_import`` for non-generic delegate +definitions, and ``scan_class_definition`` for other non-generic class type +definition. +An imported assembly is assigned a number (the "assembly index") and that +number is recorded in the IL representation of class and enum types loaded from +the assembly. +While processing code generated from metadata (top-level or needed +definitions), the global variable ``scanning_generated_code_from_metadata`` is +TRUE. This is used, for example, to suppress certain diagnostics that do not +apply to code generated from metadata. + +Linkage Specifications +====================== + +In C++ the first thing ``declaration`` must check for is the token ``extern`` +followed by a string literal (e.g., ``extern "C"``). This introduces a linkage +specification, which may control a single declaration or a brace-enclosed block +of declarations. In either case ``linkage_specification`` is called. It sets +global variable ``def_external_linkage`` to describe the kind of linkage that +is to be the default for subsequent declarations, and then it calls +``declaration`` again. + +Declarations *vs.* Expressions +============================== + +Inside a function body it is sometimes difficult to determine whether something +is a declaration or an executable statement. In C the presence of a +declaration specifier keyword or a type name is sufficient to disambiguate the +cases, but in C++ it can be more complicated. Similar disambiguation problems +appear in other contexts as well. Here are some examples. + +* | a statement *vs.* a declaration: + + .. code:: c++ + + typedef int I; + I(i); // declaration (= I i); + I(i)++; // cast i to I, then increment +* | with ``operator new``, a parenthesized type *vs.* a placement expression: + + .. code:: c++ + + new (int(1.5)) A // placement + new (int(* )) // type +* | a parenthesized initializer *vs.* a parameter declaration + + .. code:: c++ + + struct A { /* ... */ }; + A a(int(1)); // declare variable a (initialized by + // calling A::A() with arg 1) + A f(int(i)); // declare function f to take an integer + // argument and return an A + +The function ``is_decl_not_expr`` is called in cases where disambiguation is +required. This may in turn use the routines ``prescan_declaration``, +``prescan_decl_specifiers``, ``prescan_declarator``, and +``prescan_function_declarator``. In general, if a sequence of tokens looks +like a declaration, then it is a declaration, even if it could also be an +expression. The technique requires looking ahead as many tokens as necessary +to confirm or disprove the assumption that the token sequence is a declaration; +tokens are cached so that they can be rescanned by the caller. + +Thus, in statement processing, when ``is_decl_not_expr`` returns TRUE the +tokens are scanned as a declaration (``declaration`` is called); otherwise, the +tokens are scanned assuming that they constitute a statement. + +Declaration Scanning +==================== + +Declaration Specifiers +---------------------- + +The principal part of the code for processing declaration specifiers appears in +``decl_spec.c``. + +``decl_specifiers`` scans a list of type specifiers, type qualifiers, and/or +storage class specifiers, and returns (through a ``a_decl_parse_state`` object) +a pointer to a type tree. It is passed a vector of input flags (telling it +that a storage class specifier is allowed, that the declaration is of a class +member, etc.) and it returns additional information about the results of the +scan (reporting that ``inline`` was scanned, that an explicit type specifier +was present, etc.) via the ``a_decl_parse_state`` object that was passed in. + +The specifiers are scanned in a loop. The simple ones are handled directly. +When ``enum`` is seen, ``enum_specifier`` is called. When ``class``, +``struct``, or ``union`` is scanned, ``class_specifier`` is called; the +processing entailed in scanning a class definition (see +``scan_class_definition`` in ``class_decl.c``) is described in the chapter on +Class Declarations. + +A ``typedef`` name may appear as a type specifier, as may a class name in C++. +Therefore, to tell whether an identifier (including a qualified name) is a type +name or a declarator, a call is made to ``curr_type_symbol``; it returns a +symbol pointer when the identifier is a type name and NULL otherwise. Since +class name can also be a constructor name under some conditions, that case is +also checked for by ``is_constructor_decl``. + +The loop continues until it reaches something it does not recognize as a +declaration specifier. Then the accumulated information is combined to create +a type entry (see ``combine_type_specifiers`` and ``add_type_qualifiers``, and +the output flags are set. When no type is explicitly specified, a default type +is returned; ordinarily it is ``int``, but when the declarator is recognized to +be a constructor, the default is a reference to the class type, and for +destructors it is ``void``. + +``decl_specifiers`` is also called to scan a set of type qualifiers only, e.g., +as part of scanning a pointer-declarator. For such cases +``a_type_qualifier_set`` is always returned independently of the type (even +though in the usual case it is also part of the returned type). (See also +``collect_type_qualifiers`` in ``declarator.c``.) + +The details of an ``enum`` declaration are handled by ``enum_specifier``. +First it calls ``scan_tag_name`` (which is also called from +``class_specifier``) to look up the (optional) tag name and return a symbol. +When a brace-enclosed declaration follows the tag name, ``enum_specifier`` +scans the list of enumeration constant declarations, calling +``scan_integral_constant_expression`` when a value is specified. Each +declaration is turned into a constant entry with the proper value, and all of +the constant entries are linked together under the type entry for the +enumerated type. The size of the enumerated type is also determined from the +value. [#f2]_ Note that in C++, unlike C, the types of the enumeration and its +constants are always the same. + +Declarators +----------- + +Most of the code for scanning declarators is found in ``declarator.c``. + +``declarator`` scans a declarator. It can scan either a real declarator or an +abstract declarator. It receives as input (via the ``a_decl_parse_state`` +object tracking that declaration) the type from an associated specifiers list, +and combines that type with the type information in the declarator. It also +returns a symbol locator for the name declared in the middle of the declarator. +For an abstract declarator, it returns an error locator. It takes as input a +vector of flags to direct its processing, and it returns a vector of output +flags to report results to the caller (again via the ``a_decl_parse_state`` +object). + +``declarator`` is the top-level interface and calls ``r_declarator``, which is +recursive. Declarator processing has three parts: + +* | ``pointer_declarator`` is called to handle pointer modifiers (``*``) and in + C++ references (``&``) and pointer-to-member syntax. There can be more + than one such modifier, and each can be accompanied by one or more type + qualifiers. These are combined with the type returned by + ``decl_specifiers``; the routines invoked to construct the new types are + ``make_pointer_type``, ``make_reference_type``, + ``make_rvalue_reference_type``, and ``pointer_to_member_type``. +* | The middle section is either an identifier (or the place where one would + be, for an abstract declarator) or a nested declarator enclosed in + parentheses. The left parenthesis is ambiguous in an abstract declarator, + so the routine looks one token past it to disambiguate the function + declarator case from the nested declarator case. The declarator + identifier, scanned by ``scan_real_declarator_id``, may be a simple + identifier, a qualified name, [#f3]_ a destructor name, or a token sequence + representing an overloaded operator or a user-defined conversion (such as + ``operator+`` or ``operator int``). +* | The third section consists of zero or more function or array declarators, + for which calls are made to ``function_declarator`` or + ``array_declarator``. + + * | ``function_declarator`` scans the parameter list (an old-style id list, a + prototype parameter list, or ``void``) and builds a function type. For a + top-level function type some additional information is returned in a + block called ``func_info``, which is returned to the caller to assist + with later function processing; most notably, this includes a list of the + identifier names in an old-style id list. If the function declarator is + a prototype, and if any tags are declared in the prototype, a prototype + scope is created. + * | ``array_declarator`` scans constant and nonconstant array dimensions (the + latter for variable length arrays in C mode and type names in ``new`` + expressions in C++). + + | The processing for VLA declarations has several twists. In the ordinary + case in which a VLA declaration appears at function or block scope, a VLA + dimension entry is created and an ``stmk_set_vla_size`` statment is put + out. If the VLA declaration appears in a function prototype, then the + dimension expression may be unspecified (i.e., the\ ``[*]`` syntax is + accepted); this is not permitted, however, when the function prototype + belongs to a function definition, but this check is delayed till + ``scan_function_body``. If the dimension expression *is* specified in a + function prototype scope, a fixup entry is created and processing is + completed in ``scan_function_body``: once the routine's IL scope has been + created, the VLA dimension entry can be allocated and any references to + parameter variables can be properly incorporated into the VLA dimension + expression. + +The type information from the three sections is combined into a single type +tree. The routine that combines derived types is ``add_to_derived_type_list``; +aside from the purely mechanical task of joining types, it also does error +checking, and calls ``set_type_size`` once all the parts of a derived type have +come together. + +Information about the *declarator-id* is returned from ``declarator`` in a +symbol locator. + +C++/CLI Type Constructs +----------------------- + +C++/CLI adds several type composition mechanisms: handles, tracking references, +interior pointers, pin pointers, CLI arrays, and delegates. It also adds new +class type and enum type variations. + +The C++/CLI core library (which is always imported, and is usually +``mscorlib.dll``) defines a number of special "value class types" (e.g., +``System::Int32``) that map onto fundamental types (like ``int``). When the +type scanned by ``decl_specifiers`` is such a special class type, it is +immediately replaced by the corresponding fundamental type (by a call to +``fundamental_type_from_system_type``). However, if a handle to a fundamental +type with a corresponding value class type is formed, the fundamental type is +replaced by the class type (through a call to ``boxed_type_for``, which in turn +calls ``system_type_from_fundamental_type``). Handles to enumeration type are +handled similarly: A C++/CLI value class type is created that "boxes" the +enumeration (see ``make_boxed_enum_type``), and the handle is to that class +type. + +Syntactically, handles and tracking references are like pointers and references +that use different declarator operators ("``^``" and "``%``" respectively). +They have different semantics and constraints, however. Many of the basic +constraints on their underlying types are checked in +``f_check_cli_type_pointed_to``. + +Like handles and tracking references, C++/CLI interior pointers and pin +pointers are represented using ``tk_pointer`` entries. However, the syntax to +express interior pointers and pin pointers uses template-like angle brackets +(e.g., ``cli::pin_ptr``) instead of declarator operators. The front end +implements support for that syntax by predefining special alias templates +``cli::pin_ptr`` and ``cli::interior_ptr`` (see +``make_symbol_for_cli_interior_ptr`` and ``make_symbol_for_cli_pin_ptr``) that +rely on internal ``__declspec`` attributes to form the aliased ``tk_pointer`` +type. + +CLI arrays are instances of a ref class template ``cli::array`` +(see ``make_symbol_for_cli_array``). Instances of this template have the flag +``is_cli_array`` set (in their class type supplement); this simplifies, among +other things, the implementation of the function ``is_cli_array_type``). CLI +arrays can mostly only be used via handles-to-CLI-arrays (see +``check_invalid_use_of_special_cli_class_type``). + +A delegate is a special kind of generated reference class type that +encapsulates an "invocation list" (see :ref:`cppcli-delegates` for details). +Like CLI arrays, they can mostly only be used via handles-to-delegates. + +C++/CLI function declarators can include a trailing "parameter array" (with +syntax like "``void f(double, ...cli::array ^p)``", where the type must +be a handle to a one-dimensional CLI array). They are akin to traditional C +variadic function arguments ("varargs"), but they are type-safe and limited to +accepting a variadic list of arguments that are all of the same type. A +parameter array is represented with a single ``a_param_type`` entry whose +``is_cli_param_array`` flag is TRUE. + +Completing the Declaration +-------------------------- + +Once the declaration specifiers and the declarator have been scanned, it +remains to put the type and other declarative information together and generate +IL and symbol representations for the objects declared. + +If ``typedef`` was seen among the declaration specifiers, ``decl_typedef`` is +called. It enters a ``tk_typeref`` type entry into the IL and an ``sk_type`` +symbol in the symbol table. In C++ it has some extra processing when the type +passed in to it is that of a tagless class or enum: the ``typedef`` name is +transferred to the class or enum type entry, and in cfront-compatibility mode +the symbol for the class is modified accordingly. + +``define_static_data_member`` is called to process the definition of a static +data member. The IL entry and symbol were created at the original point of +declaration. + +Variables and routines are entered by calling ``decl_variable`` or +``decl_routine``, which are similarly organized functions made fairly +complicated by the need to check the declaration's compatibility with previous +declarations of the same entity. + +* | ``id_linkage`` is used to determine whether the declared name has linkage, + and if so, to what (see ``find_linked_symbol``, which returns a symbol if + there is a previous use in scope). +* | ``qualified_name_redecl_sym`` is called instead of ``id_linkage`` if the + declarator is a namespace-qualified name (e.g., a friend declaration or a + namespace member definition that appears outside the scope of the namespace + to which it belongs); it also calls ``find_linked_symbol``. +* | ``find_linked_symbol`` not only calls the appropriate lookup routine; it + also deals with function overloading and function template specializations + (see ``matching_template_function`` in ``templates.c``). +* | ``create_external_symbol_for_linked_entity`` is called to find any previous + external variable or routine of the same name, even if the previous name + has since gone out of scope; it also checks that the old and new types are + compatible. ``decl_variable`` and ``decl_routine`` use this information to + decide whether to create a new variable or routine entry or instead to + reuse or complete a previous declaration. + +"Block-extern" variables and routines have linkage and are always entered at +the file scope or namespace scope in the intermediate language, but their +symbols belong to the current scope in the symbol table (except in ``pcc`` +mode, where they are entered at the file scope in the symbol table too). When +a ``friend`` declaration introduces a new routine, its symbol is entered in the +innermost enclosing nonclass scope, and the associated routine entry is entered +in the innermost enclosing namespace scope. + +In addition to deciding whether an existing symbol and IL entry can be reused +or new ones need to be created, ``decl_variable`` and ``decl_routine`` are also +responsible for checking type compatibility, storage class, and name-linkage, +and they call the routines that record cross-reference and source-sequence +information. + +Functions with bodies need additional processing. ``function_definition`` +finishes the scanning of a function definition started by ``declaration``. If +there is an old-style parameter list, the declarations are scanned through a +series of calls to ``declaration``. Next, it calls ``decl_routine`` (for +normal functions) or ``define_member_function`` (for member functions) to +retrieve or create the function's symbol and routine entry. + +Then, ``scan_function_body`` is called. First, the scope stack is fixed up -- +if the routine is a member function defined outside the class body, the scope +of the class of which it is a member is reactivated, or, if it is a namespace +member appearing outside the scope of the namespace, a namespace extension +scope is pushed -- after which the routine's own function scope is pushed. + +Function parameter processing is completed within the function scope, so that +parameter variables will be entered into the symbol table correctly. A pass is +made over the linked list of ``a_param_type`` entries recorded in the function +type and the linked list of ``a_param_id`` entries created from scanning the +parameter declarations (the two lists should be in sync; the latter knows the +name of the parameter, the former only the type), and ``decl_parameter`` is +called to create the parameter variable entries. + +When support for variable length arrays is enabled, a fixup is performed on any +VLA declarations that appeared in the function prototype. If the VLA dimension +expression referred to a parameter, a dummy variable is replaced with the +"real" parameter variable that has just been created. Then, the dimension +expression is copied from the file-scope memory region to the function-scope +memory region, and an entry of type ``a_vla_dimension`` is created to record it +in the IL. + +If it is a constructor that is being defined, ``ctor_intializer`` is called to +scan the constructor initializer list and to enter implicit ctor-initializers; +similar processing is done for a destructor with a call to +``dtor_initializer``. If this definition appears in the midst of statement +processing (either because it is an inline member function of a local class or +a template instantiation), it is necessary to save the structured statement +stack and start a brand new one (see ``new_struct_stmt_stack``). Then +``compound_statement`` can finally be called to scan the body of the function; +the resulting statement tree is recorded in the ``assoc_block`` field of the +function's scope entry. Before returning, ``scan_function_body`` restores the +structured statement stack and pops the various scopes off the scope stack. + +Initialization +============== + +Initialization is a broad topic in C and C++. It includes: + +* | Setting the initial value of a variable as part of its declaration (the + traditional C notion of initialization) +* | Initializing members and bases of a class as part of the execution of a + constructor +* | Initializing a temporary variable as part of a cast or C99-style compound + literal +* | Passing arguments in a function call (parameter variables are initialized + with argument values) + +Furthermore, "default" initialization actions may be required even in the +absence of an explicit source construct, and the binding of references, while +treated as a form of initialization, involves a number of rules of its own. +Also, C++17 structured bindings are sometimes "aliases" for expressions and +those are represented as variables with a special kind of "initializer" +(although arguably those do not correspond to actual initialization). + +Source file ``decl_inits.c`` is primarily concerned with declaration contexts: +Initializing variables and initializing members of classes as part of +constructor definitions (i.e., the first two bullets). It also includes the +structural handling of aggregate initialization (the traditional brace-enclosed +initializers), and that handling is also used in non-declaration contexts; +particularly, in C99-style compound literals and in various C++11-style list +initialization contexts. + +IL Representation +----------------- + +The special case of a variable with static storage duration initialized with a +true constant is represented by associating the ``a_constant`` entry directly +with the ``a_variable`` entry (via the ``an_initializer`` entry embedded in the +variable entry). C++17 structured bindings for array elements and structure +fields are represented as variables with a special kind of "binding" +initializer pointing to the aliased expression (also via the ``an_initializer`` +entry). In all other cases, initialization involves a dynamic element and an +entry of type ``a_dynamic_init`` is used to represent it (see +:ref:`il-dynamic-init`). + +In addition, even for entities that are not initialized (or whose +initialization is "trivial"), a dynamic init entry may nonetheless be generated +to represent the eventual destruction of that entity (assuming that entity has +a nontrivial destructor). + +.. _init-components-and-state: + +Init Components and Init States +------------------------------- + +It is frequently convenient in the front end to separate the parsing of an +initializer from its actual binding to a target entity. When this is done, the +parsing phase produces an "init component" (type ``an_init_component``, defined +in ``expr.h``). Such a component can represent either + +* | an expression, or +* | a C99-style aggregate member designator, or +* | a brace-enclosed list of init components. + +(A fourth kind of "placeholder" init component exists. It represents a +point at which the parsing of a large aggregate initializer has been +suspended for later continuation. This is transparent to the routines +processing initializers because they don't access the ``next`` pointer of +init components directly and instead use macros -- like ``next_elem`` -- that +automatically resume parsing when reaching one of these placeholder +entries.) + +An init component that represents an expression ultimately points to an object +of type ``an_operand`` (see :ref:`expr-operands`), as well as other information +needed for the second ("binding") phase of initializer processing. + +``decl_inits.c`` relies on two functions from ``expr.c`` to scan init +components: ``scan_braced_init_list`` for list initializers (which in +general will return the top component of a tree representing the braced +structure), and ``scan_full_initializer_expr_as_component`` (which will +return a simple expression component). Sometimes, initializers must be +"prescanned" (to deduce the type of a C++11-style ``auto`` declaration): +The two aforementioned functions will retrieve the prescanned init +components from a cache if needed. Eventually, +``free_init_component_list`` must be called on the top-level component +produced for every initializer. + +The binding of an initializer as represented by an init component to its target +entity is generally handled by a call to ``convert_initializer``, except for +aggregate initialization where the structure of the initializer is mapped to +that of the target type using a variety of functions (see +:ref:`decl-aggregate-init`) which eventually call the ``expr.c`` function +``convert_initializer`` for the non-aggregate "leaf" elements of the aggregate +initializer. + +Initializer processing shares a fair amount of information across calls to a +large number of functions. To facilitate this, the information is recorded in +a structure of type ``an_init_state``. This is both an "input" and an "output" +device: Some fields are used to pass information down the initializer +processing functions, while others are used to return results. In particular, +some input fields inhibit the generation of IL entries +(``check_validity_only``) and/or the emission of diagnostics +(``no_diagnostics``): This is needed to handle overload resolution and template +deduction (which requires "tentative" initialization in C++11). + +A declaration parse state block (``a_decl_parse_state``) embeds an init state +for initialization directly associated with a declaration (variable +initializers, particularly), and in that case, the embedded init state also +contains a pointer back to the associated declaration parse state block. + +Variable Initializers +--------------------- + +Variable initializers (including initializers for static data members) are +scanned and processed by calling ``initializer`` in ``decl_inits.c``. After +checking for errors independently of the initializer itself, and if necessary +deducing the type of the variable from the type of the initializer +(``prescan_initializer_for_auto_type_deduction``), the function distinguishes +four syntactic cases: + +#. | parenthesized initializers (a C++ feature; e.g., "``T x(3);``"), +#. | direct list initializers (a C++11 feature; e.g., "``T x{3};``"), +#. | traditional list initializers (e.g., "``T x = {3};``"), and +#. | simple initializers (e.g., "``T x = 3;``"). + +Parenthesized initializers for class types and for template-dependent types are +the only variations that do not use init components as an intermediate +representation of the initializer: Instead, these cases are handled by calls to +``scan_class_parenthesized_initializer`` and +``scan_dependent_type_parenthesized_initializer``, respectively. The remaining +parenthesized cases (i.e., those that cannot involve a constructor and +therefore must allow for only a single parenthesized expression) are handled by +``expr_direct_init_object``. + +Both the C++11-style direct list initialization syntax and the more traditional +list initialization syntax are handled by calls to ``brace_init_variable``, +except that the initialization of a C++/CLI array using traditional list +initialization syntax uses a dedicated routine +``aggr_init_cli_array_with_alloc``. brace_init_variable calls +braced_initializer + +Finally, initializations of the form "``T x =`` *expr*" are handled by +``expr_init_aggr_variable`` (for variables of class or array types) and +``expr_init_scalar_variable`` (for scalar variables). + +Structured bindings to array elements and to fields are technically not +variables (they are aliased to components of the unnamed "container" variable +for the binding), but they are represented though ``a_variable`` entries in the +front end. These entries have an ``initk_binding`` initializer kind and point +to the aliased expression. The routines +``record_struct_binding_expr_for_array_element`` and +``record_struct_binding_expr_for_field`` (both in ``expr.c``) handle this +pseudo-initializers. + +Auto type deduction +^^^^^^^^^^^^^^^^^^^ + +Some modes allow the keyword ``auto`` to be used as a type specifier. In such +cases, the actual type must be deduced from the initializer using rules similar +to those for function template argument deduction. This presents an ordering +challenge: The expression handling routines called by ``initializer`` must know +the type of the entity being initialized (e.g., to determine appropriate +conversions), but that type is not known until the initializer has been +determined. To address this, the initializer for entities declared with the +``auto`` type specifier is prescanned (routine +``prescan_initializer_for_auto_type_deduction`` in ``expr.c``): That process +deduces the actual type of ``auto`` (using the same machinery as that used for +calls of function templates) and records the prescanned init component in the +``a_decl_parse_state`` entity for the current declaration. The routines called +by ``initializer`` to scan init components are aware of this record and will +use it instead of actually scanning tokens when appropriate. + +The same mechanism is also used to support the ``auto`` type specifier in +*new-expression*\ s (``scan_new_operator`` in ``expr.c``) and in +declarations of ``static const`` data members with in-class initializers +(``decl_static_data_member`` in ``class_decl.c``). + +Default Initialization +^^^^^^^^^^^^^^^^^^^^^^ + +C++ entities of class type that are declared without an explicit initializer +are "default-initialized" -- which means calling the class's default +constructor (or, for an array, calling the default constructor for each +element): + +.. code:: c++ + + struct A { A(); /* ... */ } a; // a is default-initialized by A::A() + +The routine ``def_initializer`` is called for declarations without +initializers, and it generates the default initialization if appropriate. +Default initialization is done only for variables and static data members that +are defined in the current translation unit, and not all classes are subject to +default initialization in the same way: + +#. | "POD" structs and unions (roughly, C-style structs: no non-public + members, no user-defined constructor, destructor, or assignment operator, + no base classes, no virtual functions, etc.) are *never* + default-initialized: + + .. code:: c++ + + struct A { int i; }; // POD + A a1; // a1 goes uninitialized + const A a2; // error -- no explicit initializer + +#. | Non-POD classes with an implicitly-declared trivial default constructor + (i.e., classes for which each base class or nonstatic data member of + class type, if any, will in turn be initialized with its own trivial + default constructor) are default-initialized only when the object is + non-``const``: + + .. code:: c++ + + struct B { private: int i; }; // implicit trivial B::B() + B b1; // b1 is default-initialized + const B b2; // error -- no explicit initializer + +#. | Classes with an implicitly-declared nontrivial default constructor are + likewise default-initialized only when the object is non-``const``: + + .. code:: c++ + + struct C { int i; virtual void f(); }; // implicit nontrivial C::C() + C c1; // c1 is default-initialized + const C c2; // error -- no explicit initializer + +#. | Classes with at least one user-declared constructor are default + initialized whether or not the object is ``const``: + + .. code:: c++ + + struct D { int i; D(); }; // user-declared D::D() + D d1; // d1 is default-initialized + const D d2; // d2 is default-initialized + +A further distinction is made between the second and third groups (classes with +trivial vs. nontrivial implicitly declared default constructor): ``b1`` and +``c1`` differ in how their default initialization is implemented. A call to +the nontrivial default constructor ``C::C()`` is actually added to the IL (it +needs to deal with the virtual function info for class ``C``), but the trivial +default constructor ``B::B()`` need not actually be called, since calling it +would have no effect. Its definition is generated in case there might be +compile-time side-effects (see ``reference_to_trivial_default_constructor`` in +``symbol_ref.c``), but the IL for a trivial default constructor does not appear +in the IL. + +.. _decl-aggregate-init: + +Aggregate Initializers +---------------------- + +An aggregate type is an array type or a class type that has no user-provided +constructors. When an entity of such a type is initialized with a +braced-enclosed construct, the front end traverses the initializer structure +and the destination type's structure mapping one onto the other. The result is +an aggregate constant (``ck_aggregate``), which may contain elements that are +not actually constants (i.e., ``ck_dynamic_init`` "constants"). Four cases are +distinguished: + +* | aggregate class types: handled by ``aggr_init_class``, with help from + ``aggr_init_field_designator`` to handle C99- and GNU-style designators, + and from ``aggr_init_class_remainder_if_needed`` to represent nontrivial + initializations (in C++) of fields that have no explicit initializer. +* | array types: handled by ``aggr_init_array``, with help from + ``aggr_init_array_designator`` to handle designators, and from + ``aggr_init_array_remainder_if_needed`` to represent nontrivial + initializations (in C++) of array elements that have no explicit + initializer. +* | template-dependent types: handled by ``aggr_init_generic_element``; since + the structure of the destination type is not known in that case, the + structure of the resulting constant is entirely determined by the + brace-structure of the initializer. +* | C++/CLI array types: handled by ``aggr_init_cli_array`` with help from + ``aggr_init_cli_array_level`` (which deals with the special rules for + deducing CLI array dimensions from the initializer when applicable). + +The cases can be composed (e.g., an aggregate struct can contain an array of +aggregate structs), which is handled through recursion: ``aggr_init_element`` +handles the dispatching of the recursion based on the subaggregate object's +type. Leaf entities (i.e., entities whose initialization doesn't fall into one +of the cases above) are handled by ``aggr_init_simple_element``. Cleanup +actions needed in case of an exception occurring during the initialization of a +leaf entity -- including default initialization -- is handled by calls to +``record_partial_aggregate_cleanup_destruction``. + +The complete handling of a top-level aggregate initialization is initiated +either by a call to ``braced_initializer`` (for the initialization of variables +and static data members, compound literals, and constructor-initializers), or +by a call to ``prep_aggr_initializer`` (for all other expression contexts). + +While "aggregate initializer" mainly deals with the initialization of an entity +of aggregate type with a brace-enclosed construct, it also includes the +initialization of a character array with a string literal. This can happen at +the top-level (e.g., "``char str[] = "text``";") or at a subaggregate level +(e.g., "``X x = { 1, 2, "three" };``"). A central routine for this aspect of +initialization is ``try_string_literal_init``. + +Constructor Initializers +------------------------ + +Constructor initializers can be written explicitly in the source: + +.. code:: c++ + + struct A { + int i, j; + A() : i(1), j{2} // Constructor initializers with parenthesized + {} // and braced syntax, respectively. + }; + +They can also be generated implicitly by the front end for class members and +base classes that must be initialized and are not explicitly initialized in the +source. (This includes, as an extreme case, constructor routines that are +front-end-generated; any needed constructor-initializers would have to be +implicit). + +``ctor_initializer`` builds the proper list of constructor-initializer entries +and attaches it to a constructor routine entry. It is called with a flag that +indicates whether or not it should attempt to scan the source construct (if +not, it just generates a default list without looking at the source). + +The list generated is in the "right" order, that is, the order in which +initialization should be done, which is not necessarily the order in which the +explicit constructor-initializer clauses were written. The list contains three +parts, tracked by the ``a_ctor_init_block`` data structure: direct base +entries, virtual base entries, and field entries. Each initialization is +represented in the IL with an entry of type ``a_constructor_init`` (which in +turn points to a dynamic init entry). + +The explicit clauses are scanned by calling ``scan_mem_initializer``, which +ultimately calls + +* | ``scan_parenthesized_mem_init_args`` for parenthesized initializers (often + in turn calling ``scan_dependent_type_parenthesized_initializer`` for + template-dependent entities, ``scan_class_parenthesized_initializer`` for + class type entities initialized through a constructor call, or + ``expr_direct_init_object`` for other initializations not involving a + constructor). +* | ``braced_initializer`` for C++11-style braced initializers. + +Once any explicit clauses have been scanned, default initializers are generated +for any base classes and members that require them. In addition, in C++11 +mode, implicit constructor initializer entries may be generated for fields with +"field initializers" (see also :ref:`field-inits`): Such entries do not decribe +the initialization directly, but defer to the initializer recorded in the +``a_field`` entry by setting the ``use_field_initializer`` flag to TRUE. + +Destructor-initializers +----------------------- + +The destructor-initializers list attached to a destructor indicates any +destructions required for base classes and members of the destructor's class. +The list is in the order in which the destructions should be done, i.e., the +reverse of the order of the list on the corresponding constructor. + +Unlike in the constructor case, there is no source form for the +destructor-initializers, and therefore all the entries on the list are +front-end generated. + +Type Names in Expressions +========================= + +When a type name appears in an expression, routines that are used in +declaration processing are invoked to scan the type name. + +``type_name`` is called to scan a type that appears in a cast expression or as +an argument to ``sizeof``. It calls [#f4]_ ``decl_specifiers`` and, for +abstractor declarators only, ``declarator``. It returns a pointer to a type. + +``new_type_name`` is called to scan a C++ *new-type-name* or a parenthesized +*type-name* that may appear in a ``new`` expression. Only abstract declarators +are allowed, but a nonconstant bound expression is permitted for the first +array dimension. + +``asm`` Declarations +==================== + +``asm_declaration`` is called when an ``asm`` keyword is encountered. A +parenthesized string literal is scanned and recorded in an entity of kind +``an_asm_entry``. The ``asm``-string is not parsed or validated by the front +end -- it is simply passed as-is to the back end. + +In Microsoft and GNU modes, some syntax variations are accepted, and in GNU +modes, this can involve some limited validation checks. + +Namespaces +========== + +Namespace Declarations +---------------------- + +``namespace_declaration`` is called to process original namespace definitions, +namespace extensions, and declarations of namespace aliases. + +When a namespace is originally declared, an entry of type ``a_namespace`` is +created and an ``sk_namespace`` symbol is entered in the symbol table. Then, +an ``sck_namespace`` scope is pushed, and declarations inside the namespace are +represented by symbols that are entered on the active symbol list of a given +symbol header; when the scope is popped the symbols are moved from the active +list to the inactive list. However, that namespace can be reopened again, in +which case it is an ``sck_namespace_extension`` scope that is pushed onto the +scope stack. It points to the same IL scope as the original ``sck_namespace`` +scope, but symbols that are entered within this scope are added directly to the +inactive list. This affects how name lookup is done inside a namespace +extension definition -- see the :ref:`symbol-table` chapter. + +For both original and extending namespace definitions, once the appropriate +scope has been pushed, a loop is executed to make a series of calls to +``declaration`` until the closing ``}`` of the namespace definition is +encountered. Then the ``sck_namespace`` or ``sck_namespace_extension`` scope +is popped off the scope stack. + +Unnamed namespace definitions are a special case. For an original unnamed +namespace definition, an ``sck_namespace`` scope is immediately pushed and then +popped, a ``using``-directive is simulated, and then an +``sck_namespace_extension`` scope is opened. [#f5]_ In other words, an +original unnamed namespace definition that is written like this + +.. code:: c++ + + namespace { + int i; + } + +is represented internally as if it were + + | ``namespace`` ** ``{ }`` + | ``using namespace`` **\ ``;`` + | ``namespace`` ** ``{`` + | ``int i;`` + | ``}`` + +``namespace_declaration`` also handles declarations of namespace aliases, for +which a namespace IL entry and a namespace symbol are also created. However, +in this case the namespace IL entry has its ``is_namespace_alias`` flag set to +TRUE and points not to an associated IL scope but to the namespace entry it +stands for. + +Using-Directives +---------------- + +A *using-directive* is processed by ``using_directive``, which looks up the +namespace name and calls ``make_using_directive`` to create and enter an entry +of type ``a_using_decl`` and to "activate" the using directive in the current +scope (see ``add_active_using_directive`` in ``scope_stk.c``). The effect of a +*using-directive* on the lookup algorithm is discussed in the Symbol Table +chapter. + +Using-Declarations +------------------ + +A *using-declaration* that appears in a scope other than that of a class +definition is processed by ``nonmember_using_declaration``. [#f6]_ First it +looks up and validates the namespace-qualified or globally qualified name. +Then it enters an ``sk_namespace_projection`` symbol to represent the name +pulled into the current scope by the using-declaration. + +When a *using-declaration* specifies the name of an overloaded function, each +member of the overload set will have its own projection symbol. An overload +set in the current scope may end up with a mix of ``sk_routine`` symbols +(declarations from the current scope) and ``sk_namespace_projection`` symbols +(referring to declarations from another scope). +``conflicts_with_previous_function_decl`` is called to determine if a function +specified by a *using-declaration* is not distinguishable, for purposes of +overloading, from functions actually declared in the current scope. + +An IL entry is created to represent the *using-declaration* (see +``make_using_decl``); it is available to back ends from the ``using_decls`` +list pointed to from the current scope. + +Standard Attributes, GNU Attributes, and ``__declspec`` Attributes +================================================================== + +In declarative contexts, the processing for standard attributes (delimited by +double square brackets) is very similar to that for GNU attributes +("``__attribute((...))``") and Microsoft ``__declspec(...)`` attributes. The +main difference (other than the delimiting tokens) is that standard attributes +have strict "appertaining rules" whereas nonstandard (GNU and Microsoft +``__declspec``) attributes can be placed more loosely. The standard rules are +basically that an attribute applies to the construct immediately preceding it, +except for "prefix attributes" which apply to all the entities denoted by the +declarators of the prefixed declaration. With nonstandard attributes, the +entity modified by an attribute depends on the attribute. For example: + +.. code:: c++ + + [[noreturn]] int [[X]] f [[ nothrow ]] () [[Y]], g(); // (1) + #define A __attribute + A((noreturn)) int A((nothrow)) f() A((pure)), g(); // (2) + +In (1), the ``noreturn`` attribute applies to the functions ``f`` and ``g``, +and any attribute in that location would apply to those entities. The unknown +attribute ``X`` (in (1)) applies to ``int``, ``nothrow`` applies to ``f``, and +``Y`` applies to the function type associated with the function declarator that +precedes it. (There are currently no standard attributes that could appear in +the locations indicated by X and Y, but the language specification does +anticipate their appertainance.) + +While in (2) the ``noreturn`` attribute applies as in (1), the ``nothrow`` +attribute applies to the type of ``f`` (a function type) and the ``pure`` +attribute applies to ``f`` itself. Furthermore, the locations of the +``nothrow`` and ``pure`` attributes can be interchanged with no change of +meaning. + +The principal routines for parsing and applying attributes are described in +detail :ref:`pragmas-and-attributes`. For attributes that apply to +declarations, the attribute application "callback" functions can rely on the +``assoc_info`` field of the attribute entry pointing to the +``a_decl_parse_state`` structure for that declaration. + +.. _ms-attributes: + +Microsoft Attributes +==================== + +In Microsoft mode, Microsoft attributes delimited by single brackets are +accepted. Attributes may, in general, be specified where a declaration is +accepted. In particular, they are accepted in namespace scopes, class scopes, +and in function parameter lists. Attributes have the form: + +.. code:: c++ + + [attribute_name] + [attribute_name(args)] + +When the bracket that begins an attribute is encountered, +``scan_microsoft_attributes`` is used to scan the attributes and create the IL +entries used to represent them. A list of attributes is returned. This list +is later passed to one of the following routines that either add the attributes +to the IL or issue the appropriate diagnostics if the attributes appear in +invalid locations: + +.. code:: c++ + + apply_microsoft_attributes + verify_standalone_attributes + dispose_of_unapplied_attributes + +The attribute scanning routines use an attribute description data structure to +describe the attributes that should be recognized and to describe the argument +lists expected by those attributes. When the +``RECOGNIZE_MICROSOFT_ATTRIBUTES`` macro is TRUE, the front end supplies +attribute descriptions for the documented Microsoft attributes. When +``SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING`` is TRUE, the Microsoft attributes +are recognized in the sense that no "unrecognized attribute" warning is issued, +but they are otherwise treated as unrecognized attributes (see below). + +Each attribute is represented by an entry of type ``an_ms_attribute``. The +entry contains a string representation of the attribute. In addition, a +structured representation is also created for recognized attributes. In the +structured representation, each attribute has a list of associated argument +values. The argument values are checked to verify that they match the kind of +value expected for a given argument (e.g., for a boolean parameter the value +must be true or false). When processing an unrecognized attribute, no semantic +checking of argument values is performed and no checking is done to verify that +a given attribute is used in an acceptable location. + +Attribute processing results in a list of attribute IL entries, and a flag +in the source correspondence that indicates that attributes apply to a +given entity (see the :ref:`intermediate-language` chapter for more +information). The source correspondence flag is only available when the +structured attribute representation is being used. Beyond the error +checking described above, no additional semantic processing of attributes +is performed. For example, no code insertion is performed for the COM +attributes. + +C++/CLI makes use of the same attribute syntax. Currently, however, no +C++/CLI-specific attributes are recognized (and as a consequence no associated +semantics are implemented). + +.. [#f1] The top-level entities imported from assemblies are generic and + nongeneric managed classes, including some expressed using delegate + definition syntax. A delegate whose definition has not yet been + loaded is treated like a ref class without a definition. +.. [#f2] See ``enum_types_can_be_smaller_than_int`` in the configuration + section of this document. +.. [#f3] As an extension it is permitted to use a qualified name as the + declarator in a class member declaration (see + ``simplify_curr_class_qualified_name``). For instance, +.. [#f4] The indirect call is via the more general function ``type_name_full``. +.. [#f5] The reason for this is to correctly handle globally qualified + references to unnamed namespace members within the original namespace + definition the same way as within a subsequent namespace extension. + For example: +.. [#f6] Using-declarations that appear inside a class definition are handled + by ``member_using_declaration`` in ``class_decl.c``, which is + described in the Class Declarations chapter. diff --git a/doc/_sources/err_msgs.rst.txt b/doc/_sources/err_msgs.rst.txt new file mode 100644 index 0000000..0393d21 --- /dev/null +++ b/doc/_sources/err_msgs.rst.txt @@ -0,0 +1,10449 @@ +.. _error-messages: + +============== +Error Messages +============== + +.. list-table:: + + * - ``0001``\ + - | ``last_line_incomplete``\ : + | last line of file ends without a newline + * - ``0002``\ + - | ``last_line_backslash``\ : + | last line of file ends with a backslash + * - ``0003``\ + - | ``include_recursion``\ : + | #include file *"xxxx"*\ includes itself + * - ``0004``\ + - | ``out_of_memory``\ : + | out of memory + * - ``0006``\ + - | ``comment_unclosed_at_eof``\ : + | comment unclosed at end of file + * - ``0007``\ + - | ``bad_token``\ : + | unrecognized token + * - ``0008``\ + - | ``unclosed_string``\ : + | missing closing quote + * - ``0009``\ + - | ``nested_comment``\ : + | nested comment is not allowed + * - ``0010``\ + - | ``bad_use_of_sharp``\ : + | "#" not expected here + * - ``0011``\ + - | ``bad_pp_directive_keyword``\ : + | unrecognized preprocessing directive + * - ``0012``\ + - | ``end_of_flush``\ : + | parsing restarts here after previous syntax error + * - ``0013``\ + - | ``exp_file_name``\ : + | expected a file name + * - ``0014``\ + - | ``extra_text_in_pp_directive``\ : + | extra text after expected end of preprocessing directive + * - ``0017``\ + - | ``exp_rbracket``\ : + | expected a "]" + * - ``0018``\ + - | ``exp_rparen``\ : + | expected a ")" + * - ``0019``\ + - | ``extra_chars_on_number``\ : + | extra text after expected end of number + * - ``0020``\ + - | ``undefined_identifier``\ : + | identifier *"xxxx"*\ is undefined + * - ``0021``\ + - | ``useless_type_qualifiers``\ : + | type qualifiers are meaningless in this declaration + * - ``0022``\ + - | ``bad_hex_digit``\ : + | invalid hexadecimal number + * - ``0023``\ + - | ``integer_too_large``\ : + | integer constant is too large + * - ``0024``\ + - | ``bad_octal_digit``\ : + | invalid octal digit + * - ``0025``\ + - | ``zero_length_string``\ : + | quoted string should contain at least one character + * - ``0026``\ + - | ``too_many_characters``\ : + | too many characters in character constant + * - ``0027``\ + - | ``bad_character_value``\ : + | character value is out of range + * - ``0028``\ + - | ``expr_not_constant``\ : + | expression must have a constant value + * - ``0029``\ + - | ``exp_primary_expr``\ : + | expected an expression + * - ``0030``\ + - | ``bad_float_value``\ : + | floating constant is out of range + * - ``0031``\ + - | ``expr_not_integral``\ : + | expression must have integral type + * - ``0032``\ + - | ``expr_not_arithmetic``\ : + | expression must have arithmetic type + * - ``0033``\ + - | ``exp_line_number``\ : + | expected a line number + * - ``0034``\ + - | ``bad_line_number``\ : + | invalid line number + * - ``0035``\ + - | ``error_directive``\ : + | #error directive: *xxxx*\ + * - ``0036``\ + - | ``missing_pp_if``\ : + | the #if for this directive is missing + * - ``0037``\ + - | ``missing_endif``\ : + | the #endif for this directive is missing + * - ``0038``\ + - | ``pp_else_already_appeared``\ : + | directive is not allowed -- an #else has already appeared + * - ``0039``\ + - | ``divide_by_zero``\ : + | division by zero + * - ``0040``\ + - | ``exp_identifier``\ : + | expected an identifier + * - ``0041``\ + - | ``expr_not_scalar``\ : + | expression must have arithmetic or pointer type + * - ``0042``\ + - | ``incompatible_operands``\ : + | operand types are incompatible (*"type"*\ and *"type"*\ ) + * - ``0044``\ + - | ``expr_not_pointer``\ : + | expression must have pointer type + * - ``0045``\ + - | ``cannot_undef_predef_macro``\ : + | #undef may not be used on this predefined name + * - ``0046``\ + - | ``cannot_redef_predef_macro``\ : + | *"entity"*\ is predefined; attempted redefinition ignored + * - ``0047``\ + - | ``bad_macro_redef``\ : + | incompatible redefinition of macro *"entity"*\ (declared at line + *xxxx*\ ) + * - ``0049``\ + - | ``duplicate_macro_param_name``\ : + | duplicate macro parameter name + * - ``0050``\ + - | ``paste_cannot_be_first``\ : + | "##" may not be first in a macro definition + * - ``0051``\ + - | ``paste_cannot_be_last``\ : + | "##" may not be last in a macro definition + * - ``0052``\ + - | ``exp_macro_param``\ : + | expected a macro parameter name + * - ``0053``\ + - | ``exp_colon``\ : + | expected a ":" + * - ``0054``\ + - | ``too_few_macro_args``\ : + | too few arguments in invocation of *entity-kind "entity"*\ + * - ``0055``\ + - | ``too_many_macro_args``\ : + | too many arguments in invocation of *entity-kind "entity"*\ + * - ``0056``\ + - | ``sizeof_function``\ : + | operand of sizeof may not be a function + * - ``0057``\ + - | ``bad_constant_operator``\ : + | this operator is not allowed in a constant expression + * - ``0058``\ + - | ``bad_pp_operator``\ : + | this operator is not allowed in a preprocessing expression + * - ``0059``\ + - | ``bad_constant_function_call``\ : + | function call is not allowed in a constant expression + * - ``0060``\ + - | ``bad_integral_operator``\ : + | this operator is not allowed in an integral constant expression + * - ``0061``\ + - | ``integer_overflow``\ : + | integer operation result is out of range + * - ``0062``\ + - | ``negative_shift_count``\ : + | shift count is negative + * - ``0063``\ + - | ``shift_count_too_large``\ : + | shift count is too large + * - ``0064``\ + - | ``useless_decl``\ : + | declaration does not declare anything + * - ``0065``\ + - | ``exp_semicolon``\ : + | expected a ";" + * - ``0066``\ + - | ``enum_value_out_of_int_range``\ : + | enumeration value is out of "int" range + * - ``0067``\ + - | ``exp_rbrace``\ : + | expected a "}" + * - ``0068``\ + - | ``integer_sign_change``\ : + | integer conversion resulted in a change of sign + * - ``0069``\ + - | ``integer_truncated``\ : + | integer conversion resulted in truncation + * - ``0070``\ + - | ``incomplete_type_not_allowed``\ : + | incomplete type *"type"*\ is not allowed + * - ``0071``\ + - | ``sizeof_bit_field``\ : + | operand of sizeof may not be a bit field + * - ``0075``\ + - | ``bad_indirection_operand``\ : + | operand of "\*" must be a pointer but has type *"type"*\ + * - ``0076``\ + - | ``empty_macro_argument``\ : + | argument to macro is empty + * - ``0077``\ + - | ``missing_decl_specifiers``\ : + | this declaration has no storage class or type specifier + * - ``0078``\ + - | ``initializer_in_param``\ : + | a parameter declaration may not have an initializer + * - ``0079``\ + - | ``exp_type_specifier``\ : + | expected a type specifier + * - ``0080``\ + - | ``storage_class_not_allowed``\ : + | a storage class may not be specified here + * - ``0081``\ + - | ``mult_storage_classes``\ : + | more than one storage class may not be specified + * - ``0082``\ + - | ``storage_class_not_first``\ : + | storage class is not first + * - ``0083``\ + - | ``dupl_type_qualifier``\ : + | type qualifier specified more than once + * - ``0084``\ + - | ``bad_combination_of_type_specifiers``\ : + | invalid combination of type specifiers + * - ``0085``\ + - | ``bad_param_storage_class``\ : + | invalid storage class for a parameter + * - ``0086``\ + - | ``bad_function_storage_class``\ : + | invalid storage class for a function + * - ``0087``\ + - | ``type_specifier_not_allowed``\ : + | a type specifier may not be used here + * - ``0088``\ + - | ``array_of_function``\ : + | array of functions is not allowed + * - ``0089``\ + - | ``array_of_void``\ : + | array of void is not allowed + * - ``0090``\ + - | ``function_returning_function``\ : + | function returning function is not allowed + * - ``0091``\ + - | ``function_returning_array``\ : + | function returning array is not allowed + * - ``0092``\ + - | ``param_id_list_needs_function_def``\ : + | identifier-list parameters may only be used in a function definition + * - ``0093``\ + - | ``function_type_must_come_from_declarator``\ : + | function type may not come from a typedef + * - ``0094``\ + - | ``array_size_must_be_positive``\ : + | the size of an array must be greater than zero + * - ``0095``\ + - | ``array_size_too_large``\ : + | array is too large + * - ``0096``\ + - | ``empty_translation_unit``\ : + | a translation unit must contain at least one declaration + * - ``0097``\ + - | ``bad_function_return_type``\ : + | a function may not return a value of this type + * - ``0098``\ + - | ``bad_array_element_type``\ : + | an array may not have elements of this type + * - ``0099``\ + - | ``decl_should_be_of_param``\ : + | a declaration here must declare a parameter + * - ``0100``\ + - | ``dupl_param_name``\ : + | duplicate parameter name + * - ``0101``\ + - | ``id_already_declared``\ : + | *"xxxx"*\ has already been declared in the current scope + * - ``0102``\ + - | ``nonstd_forward_decl_enum``\ : + | forward declaration of enum type is nonstandard + * - ``0103``\ + - | ``class_too_large``\ : + | class is too large + * - ``0104``\ + - | ``struct_too_large``\ : + | struct or union is too large + * - ``0105``\ + - | ``bad_bit_field_size``\ : + | invalid size for bit field + * - ``0106``\ + - | ``bad_bit_field_type``\ : + | invalid type for a bit field + * - ``0107``\ + - | ``zero_length_bit_field_must_be_unnamed``\ : + | zero-length bit field must be unnamed + * - ``0108``\ + - | ``signed_one_bit_field``\ : + | signed bit field of length 1 + * - ``0109``\ + - | ``expr_not_ptr_to_function``\ : + | expression preceding parentheses of apparent call must have + (pointer-to-) function type + * - ``0110``\ + - | ``exp_definition_of_tag``\ : + | expected either a definition or a tag name + * - ``0111``\ + - | ``code_is_unreachable``\ : + | statement is unreachable + * - ``0112``\ + - | ``exp_while``\ : + | expected "while" + * - ``0114``\ + - | ``never_defined``\ : + | *entity-kind "entity"*\ was referenced but not defined + * - ``0115``\ + - | ``continue_must_be_in_loop``\ : + | a continue statement may only be used within a loop + * - ``0116``\ + - | ``break_must_be_in_loop_or_switch``\ : + | a break statement may only be used within a loop or switch + * - ``0117``\ + - | ``no_value_returned_in_non_void_function``\ : + | non-void *entity-kind "entity"*\ should return a value + * - ``0118``\ + - | ``value_returned_in_void_function``\ : + | a void function may not return a value + * - ``0119``\ + - | ``cast_to_bad_type``\ : + | cast to type *"type"*\ is not allowed + * - ``0120``\ + - | ``bad_return_value_type``\ : + | return value type does not match the function type + * - ``0121``\ + - | ``case_label_must_be_in_switch``\ : + | a case label may only be used within a switch + * - ``0122``\ + - | ``default_label_must_be_in_switch``\ : + | a default label may only be used within a switch + * - ``0124``\ + - | ``default_label_appears_more_than_once``\ : + | default label has already appeared in this switch + * - ``0125``\ + - | ``exp_lparen``\ : + | expected a "(" + * - ``0126``\ + - | ``expr_not_an_lvalue``\ : + | expression must be an lvalue + * - ``0127``\ + - | ``exp_statement``\ : + | expected a statement + * - ``0128``\ + - | ``loop_not_reachable``\ : + | loop is not reachable + * - ``0129``\ + - | ``block_scope_function_must_be_extern``\ : + | a block-scope function may only have extern storage class + * - ``0130``\ + - | ``exp_lbrace``\ : + | expected a "{" + * - ``0131``\ + - | ``expr_not_ptr_to_class``\ : + | expression must have pointer-to-class type but it has type *"type"*\ + * - ``0132``\ + - | ``expr_not_ptr_to_struct_or_union``\ : + | expression must have pointer-to-struct-or-union type but it has type + *"type"*\ + * - ``0133``\ + - | ``exp_member_name``\ : + | expected a member name + * - ``0134``\ + - | ``exp_field_name``\ : + | expected a field name + * - ``0135``\ + - | ``not_a_member``\ : + | *entity-kind "entity"*\ has no member *"xxxx"*\ + * - ``0136``\ + - | ``not_a_field``\ : + | *entity-kind "entity"*\ has no field *"xxxx"*\ + * - ``0137``\ + - | ``expr_not_a_modifiable_lvalue``\ : + | expression must be a modifiable lvalue + * - ``0138``\ + - | ``address_of_register_variable``\ : + | taking the address of a register variable is not allowed + * - ``0139``\ + - | ``address_of_bit_field``\ : + | taking the address of a bit field is not allowed + * - ``0140``\ + - | ``too_many_arguments``\ : + | too many arguments in function call + * - ``0141``\ + - | ``all_proto_params_must_be_named``\ : + | unnamed prototyped parameters not allowed when body is present + * - ``0142``\ + - | ``expr_not_pointer_to_object``\ : + | expression must have pointer-to-object type but it has type *"type"*\ + * - ``0143``\ + - | ``program_too_large``\ : + | program too large or complicated to compile + * - ``0144``\ + - | ``bad_initializer_type``\ : + | a value of type *"type"*\ cannot be used to initialize an entity of + type *"type"*\ + * - ``0145``\ + - | ``cannot_initialize``\ : + | *entity-kind "entity"*\ may not be initialized + * - ``0146``\ + - | ``too_many_initializer_values``\ : + | too many initializer values + * - ``0147``\ + - | ``not_compatible_with_previous_decl``\ : + | declaration is incompatible with *entity-kind "entity"*\ (declared + at line *xxxx*\ ) + * - ``0148``\ + - | ``already_initialized``\ : + | *entity-kind "entity"*\ has already been initialized + * - ``0149``\ + - | ``bad_file_scope_storage_class``\ : + | a global-scope declaration may not have this storage class + * - ``0150``\ + - | ``type_cannot_be_param_name``\ : + | a type name may not be redeclared as a parameter + * - ``0151``\ + - | ``typedef_cannot_be_param_name``\ : + | a typedef name may not be redeclared as a parameter + * - ``0152``\ + - | ``non_zero_int_conv_to_pointer``\ : + | conversion of nonzero integer to pointer + * - ``0153``\ + - | ``expr_not_class``\ : + | expression must have class type but it has type *"type"*\ + * - ``0154``\ + - | ``expr_not_struct_or_union``\ : + | expression must have struct or union type but it has type *"type"*\ + * - ``0155``\ + - | ``old_fashioned_assignment_operator``\ : + | old-fashioned assignment operator + * - ``0156``\ + - | ``old_fashioned_initializer``\ : + | old-fashioned initializer + * - ``0157``\ + - | ``expr_not_integral_constant``\ : + | expression must be an integral constant expression + * - ``0158``\ + - | ``expr_not_an_lvalue_or_function_designator``\ : + | expression must be an lvalue or a function designator + * - ``0159``\ + - | ``decl_incompatible_with_previous_use``\ : + | declaration is incompatible with previous *"entity"*\ (declared at + line *xxxx*\ ) + * - ``0160``\ + - | ``external_name_clash``\ : + | external name conflicts with external name of *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``0161``\ + - | ``unrecognized_pragma``\ : + | unrecognized #pragma + * - ``0163``\ + - | ``cannot_open_temp_file_reason``\ : + | could not open temporary file *"xxxx"*\ : *xxxx*\ + * - ``0165``\ + - | ``too_few_arguments``\ : + | too few arguments in function call + * - ``0166``\ + - | ``bad_float_constant``\ : + | invalid floating constant + * - ``0167``\ + - | ``incompatible_param``\ : + | argument of type *"type"*\ is incompatible with parameter of type + *"type"*\ + * - ``0168``\ + - | ``function_type_not_allowed``\ : + | a function type is not allowed here + * - ``0169``\ + - | ``exp_declaration``\ : + | expected a declaration + * - ``0170``\ + - | ``pointer_outside_base_object``\ : + | pointer points outside of underlying object + * - ``0171``\ + - | ``bad_cast``\ : + | invalid type conversion + * - ``0172``\ + - | ``linkage_conflict``\ : + | external/internal linkage conflict with previous declaration at line + *xxxx*\ + * - ``0173``\ + - | ``float_to_integer_conversion``\ : + | floating-point value does not fit in required integral type + * - ``0174``\ + - | ``expr_has_no_effect``\ : + | expression has no effect + * - ``0175``\ + - | ``subscript_out_of_range``\ : + | subscript out of range + * - ``0177``\ + - | ``declared_but_not_referenced``\ : + | *entity-kind "entity"*\ was declared but never referenced + * - ``0178``\ + - | ``pcc_address_of_array``\ : + | "&" applied to an array has no effect + * - ``0179``\ + - | ``mod_by_zero``\ : + | right operand of "%" is zero + * - ``0180``\ + - | ``old_style_incompatible_param``\ : + | argument is incompatible with formal parameter + * - ``0181``\ + - | ``printf_arg_mismatch``\ : + | argument is incompatible with corresponding format string conversion + (expected type *"type"*\ but argument has type *"type"*\ ) + * - ``0182``\ + - | ``empty_include_search_path``\ : + | could not open source file *"xxxx"*\ (no directories in search list) + * - ``0183``\ + - | ``cast_not_integral``\ : + | type of cast must be integral + * - ``0184``\ + - | ``cast_not_scalar``\ : + | type of cast must be arithmetic or pointer + * - ``0185``\ + - | ``initialization_not_reachable``\ : + | dynamic initialization in unreachable code + * - ``0186``\ + - | ``unsigned_compare_with_zero``\ : + | pointless comparison of unsigned integer with zero + * - ``0187``\ + - | ``assign_where_compare_meant``\ : + | use of "=" where "==" may have been intended + * - ``0188``\ + - | ``mixed_enum_type``\ : + | enumerated type mixed with another type + * - ``0189``\ + - | ``file_write_error``\ : + | error while writing *xxxx*\ file + * - ``0190``\ + - | ``bad_il_file``\ : + | invalid intermediate language file + * - ``0191``\ + - | ``cast_to_qualified_type``\ : + | type qualifier is meaningless on cast type + * - ``0192``\ + - | ``unrecognized_char_escape``\ : + | unrecognized character escape sequence + * - ``0193``\ + - | ``undefined_preproc_id``\ : + | zero used for undefined preprocessing identifier *"xxxx"*\ + * - ``0194``\ + - | ``exp_asm_string``\ : + | expected an asm string + * - ``0195``\ + - | ``asm_func_must_be_prototyped``\ : + | an asm function must be prototyped + * - ``0196``\ + - | ``bad_asm_func_ellipsis``\ : + | an asm function may not have an ellipsis + * - ``0219``\ + - | ``file_delete_error_reason``\ : + | error while deleting file *"xxxx"*\ : *xxxx*\ + * - ``0220``\ + - | ``integer_to_float_conversion``\ : + | integral value does not fit in required floating-point type + * - ``0221``\ + - | ``float_to_float_conversion``\ : + | floating-point value does not fit in required floating-point type + * - ``0222``\ + - | ``bad_float_operation_result``\ : + | floating-point operation result is out of range + * - ``0223``\ + - | ``implicit_func_decl``\ : + | function *"xxxx"*\ declared implicitly + * - ``0224``\ + - | ``too_few_printf_args``\ : + | the format string requires additional arguments + * - ``0225``\ + - | ``too_many_printf_args``\ : + | the format string ends before this argument + * - ``0226``\ + - | ``bad_printf_format_string``\ : + | invalid format string conversion + * - ``0227``\ + - | ``macro_recursion``\ : + | macro recursion + * - ``0228``\ + - | ``nonstd_extra_comma``\ : + | trailing comma is nonstandard + * - ``0229``\ + - | ``enum_bit_field_too_small``\ : + | bit field cannot contain all values of the enumerated type + * - ``0230``\ + - | ``nonstd_bit_field_type``\ : + | nonstandard type for a bit field + * - ``0231``\ + - | ``decl_in_prototype_scope``\ : + | declaration is not visible outside of function + * - ``0232``\ + - | ``decl_of_void_ignored``\ : + | old-fashioned typedef of "void" ignored + * - ``0233``\ + - | ``old_fashioned_field_selection``\ : + | left operand is not a struct or union containing this field + * - ``0234``\ + - | ``old_fashioned_ptr_field_selection``\ : + | pointer does not point to struct or union containing this field + * - ``0235``\ + - | ``var_retained_incomp_type``\ : + | variable *"xxxx"*\ was declared with a never-completed type + * - ``0236``\ + - | ``boolean_controlling_expr_is_constant``\ : + | controlling expression is constant + * - ``0237``\ + - | ``switch_selector_expr_is_constant``\ : + | selector expression is constant + * - ``0238``\ + - | ``bad_param_specifier``\ : + | invalid specifier on a parameter + * - ``0239``\ + - | ``bad_specifier_outside_class_decl``\ : + | invalid specifier outside a class declaration + * - ``0240``\ + - | ``dupl_decl_specifier``\ : + | duplicate specifier in declaration + * - ``0241``\ + - | ``base_class_not_allowed_for_union``\ : + | a union is not allowed to have a base class + * - ``0242``\ + - | ``access_already_specified``\ : + | multiple access control specifiers are not allowed + * - ``0243``\ + - | ``missing_class_definition``\ : + | class or struct definition is missing + * - ``0244``\ + - | ``name_not_member_of_class_or_base_classes``\ : + | qualified name is not a member of class *"type"*\ or its base classes + * - ``0245``\ + - | ``member_ref_requires_object``\ : + | a nonstatic member reference must be relative to a specific object + * - ``0246``\ + - | ``nonstatic_member_def_not_allowed``\ : + | a nonstatic data member may not be defined outside its class + * - ``0247``\ + - | ``already_defined``\ : + | *entity-kind "entity"*\ has already been defined + * - ``0248``\ + - | ``pointer_to_reference``\ : + | pointer to reference is not allowed + * - ``0249``\ + - | ``reference_to_reference``\ : + | reference to reference is not allowed + * - ``0250``\ + - | ``reference_to_void``\ : + | reference to void is not allowed + * - ``0251``\ + - | ``array_of_reference``\ : + | array of reference is not allowed + * - ``0252``\ + - | ``missing_initializer_on_reference``\ : + | reference *entity-kind "entity"*\ requires an initializer + * - ``0253``\ + - | ``exp_comma``\ : + | expected a "," + * - ``0254``\ + - | ``type_identifier_not_allowed``\ : + | type name is not allowed + * - ``0255``\ + - | ``type_definition_not_allowed``\ : + | type definition is not allowed + * - ``0256``\ + - | ``bad_type_name_redeclaration``\ : + | invalid redeclaration of type name *"entity"*\ (declared at line + *xxxx*\ ) + * - ``0257``\ + - | ``missing_initializer_on_const``\ : + | const *entity-kind "entity"*\ requires an initializer + * - ``0258``\ + - | ``this_used_incorrectly``\ : + | "this" may only be used inside a nonstatic member function + * - ``0259``\ + - | ``constant_value_not_known``\ : + | constant value is not known + * - ``0260``\ + - | ``missing_type_specifier``\ : + | explicit type is missing ("int" assumed) + * - ``0261``\ + - | ``missing_access_specifier``\ : + | access control not specified (*"xxxx"*\ by default) + * - ``0262``\ + - | ``not_a_class_or_struct_name``\ : + | not a class or struct name + * - ``0263``\ + - | ``dupl_base_class_name``\ : + | duplicate base class name + * - ``0264``\ + - | ``bad_base_class``\ : + | invalid base class + * - ``0265``\ + - | ``no_access_to_name``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) is inaccessible + * - ``0266``\ + - | ``ambiguous_name``\ : + | *"entity"*\ is ambiguous + * - ``0267``\ + - | ``old_style_parameter_list``\ : + | old-style parameter list (anachronism) + * - ``0268``\ + - | ``declaration_after_statements``\ : + | declaration may not appear after executable statement in block + * - ``0269``\ + - | ``inaccessible_base_class``\ : + | conversion to inaccessible base class *"type"*\ is not allowed + * - ``0274``\ + - | ``improperly_terminated_macro_call``\ : + | improperly terminated macro invocation + * - ``0276``\ + - | ``id_must_be_class_or_namespace_name``\ : + | name followed by "::" must be a class or namespace name + * - ``0277``\ + - | ``bad_friend_decl``\ : + | invalid friend declaration + * - ``0278``\ + - | ``value_returned_in_constructor``\ : + | a constructor or destructor may not return a value + * - ``0279``\ + - | ``bad_destructor_decl``\ : + | invalid destructor declaration + * - ``0280``\ + - | ``class_and_member_name_conflict``\ : + | declaration of a member with the same name as its class + * - ``0281``\ + - | ``global_qualifier_not_allowed``\ : + | global-scope qualifier (leading "::") is not allowed + * - ``0282``\ + - | ``name_not_found_in_file_scope``\ : + | the global scope has no *"xxxx"*\ + * - ``0283``\ + - | ``qualified_name_not_allowed``\ : + | qualified name is not allowed + * - ``0284``\ + - | ``null_reference``\ : + | NULL reference is not allowed + * - ``0285``\ + - | ``brace_initialization_not_allowed``\ : + | initialization with "{...}" is not allowed for object of type + *"type"*\ + * - ``0286``\ + - | ``ambiguous_base_class``\ : + | base class *"type"*\ is ambiguous + * - ``0287``\ + - | ``ambiguous_derived_class``\ : + | derived class *"type"*\ contains more than one instance of class + *"type"*\ + * - ``0288``\ + - | ``derived_class_from_virtual_base``\ : + | cannot convert pointer to base class *"type"*\ to pointer to derived + class *"type"*\ -- base class is virtual + * - ``0289``\ + - | ``no_matching_constructor``\ : + | no instance of constructor *"entity"*\ matches the argument list + * - ``0290``\ + - | ``ambiguous_copy_constructor``\ : + | copy constructor for class *"type"*\ is ambiguous + * - ``0291``\ + - | ``no_default_constructor``\ : + | no default constructor exists for class *"type"*\ + * - ``0292``\ + - | ``not_a_field_or_base_class``\ : + | *"xxxx"*\ is not a nonstatic data member or base class of class + *"type"*\ + * - ``0293``\ + - | ``indirect_nonvirtual_base_class_not_allowed``\ : + | indirect nonvirtual base class is not allowed + * - ``0294``\ + - | ``bad_union_field``\ : + | invalid union member -- class *"type"*\ has a disallowed member + function + * - ``0296``\ + - | ``bad_rvalue_array``\ : + | invalid use of non-lvalue array + * - ``0297``\ + - | ``exp_operator``\ : + | expected an operator + * - ``0298``\ + - | ``inherited_member_not_allowed``\ : + | inherited member is not allowed + * - ``0299``\ + - | ``indeterminate_overloaded_function``\ : + | cannot determine which instance of *entity-kind "entity"*\ is + intended + * - ``0300``\ + - | ``bound_function_must_be_called``\ : + | a pointer to a bound function may only be used to call the function + * - ``0301``\ + - | ``duplicate_typedef``\ : + | typedef name has already been declared (with same type) + * - ``0304``\ + - | ``no_matching_function``\ : + | no instance of *entity-kind "entity"*\ matches the argument list + * - ``0305``\ + - | ``type_def_not_allowed_in_func_type_decl``\ : + | type definition is not allowed in function return type declaration + * - ``0306``\ + - | ``default_arg_not_at_end``\ : + | default argument not at end of parameter list + * - ``0307``\ + - | ``default_arg_already_defined``\ : + | redefinition of default argument + * - ``0308``\ + - | ``ambiguous_overloaded_function``\ : + | more than one instance of *entity-kind "entity"*\ matches the + argument list: + * - ``0309``\ + - | ``ambiguous_constructor``\ : + | more than one instance of constructor *"entity"*\ matches the + argument list: + * - ``0310``\ + - | ``bad_default_arg_type``\ : + | default argument of type *"type"*\ is incompatible with parameter of + type *"type"*\ + * - ``0311``\ + - | ``return_type_cannot_distinguish_functions``\ : + | cannot overload functions distinguished by return type alone + * - ``0312``\ + - | ``no_user_defined_conversion``\ : + | no suitable user-defined conversion from *"type"*\ to *"type"*\ + exists + * - ``0314``\ + - | ``virtual_static_not_allowed``\ : + | only nonstatic member functions may be virtual + * - ``0315``\ + - | ``unqual_function_with_qual_object``\ : + | the object has type qualifiers that are not compatible with the + member function + * - ``0316``\ + - | ``too_many_virtual_functions``\ : + | program too large to compile (too many virtual functions) + * - ``0317``\ + - | ``bad_return_type_on_virtual_function_override``\ : + | return type is not identical to nor covariant with return type + *"type"*\ of overridden virtual function *"entity"*\ + * - ``0318``\ + - | ``ambiguous_virtual_function_override``\ : + | override of virtual *entity-kind "entity"*\ is ambiguous + * - ``0319``\ + - | ``pure_specifier_on_nonvirtual_function``\ : + | pure specifier ("= 0") allowed only on virtual functions + * - ``0320``\ + - | ``bad_pure_specifier``\ : + | badly-formed pure specifier (only "= 0" is allowed) + * - ``0321``\ + - | ``bad_data_member_initialization``\ : + | data member initializer is not allowed + * - ``0322``\ + - | ``abstract_class_object_not_allowed``\ : + | object of abstract class type *"type"*\ is not allowed: + * - ``0323``\ + - | ``function_returning_abstract_class``\ : + | function returning abstract class *"type"*\ is not allowed: + * - ``0324``\ + - | ``duplicate_friend_decl``\ : + | duplicate friend declaration + * - ``0325``\ + - | ``inline_and_nonfunction``\ : + | inline specifier allowed on function declarations only + * - ``0326``\ + - | ``inline_not_allowed``\ : + | "inline" is not allowed + * - ``0327``\ + - | ``bad_storage_class_with_inline``\ : + | invalid storage class for an inline function + * - ``0328``\ + - | ``bad_member_storage_class``\ : + | invalid storage class for a class member + * - ``0329``\ + - | ``local_class_function_def_missing``\ : + | local class member *entity-kind "entity"*\ requires a definition + * - ``0330``\ + - | ``inaccessible_special_function``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) is inaccessible + * - ``0332``\ + - | ``missing_const_copy_constructor``\ : + | class *"type"*\ has no copy constructor to copy a const object + * - ``0333``\ + - | ``definition_of_implicitly_declared_function``\ : + | defining an implicitly declared member function is not allowed + * - ``0334``\ + - | ``no_suitable_copy_constructor``\ : + | class *"type"*\ has no suitable copy constructor + * - ``0335``\ + - | ``linkage_specifier_not_allowed``\ : + | linkage specification is not allowed + * - ``0336``\ + - | ``bad_linkage_specifier``\ : + | unknown external linkage specification + * - ``0337``\ + - | ``incompatible_linkage_specifier``\ : + | linkage specification is incompatible with previous *"entity"*\ + (declared at line *xxxx*\ ) + * - ``0338``\ + - | ``overloaded_function_linkage``\ : + | more than one instance of overloaded function *"entity"*\ has "C" + linkage + * - ``0339``\ + - | ``ambiguous_default_constructor``\ : + | class *"type"*\ has more than one default constructor + * - ``0340``\ + - | ``temp_used_for_ref_init``\ : + | value copied to temporary, reference to temporary used + * - ``0341``\ + - | ``nonmember_operator_not_allowed``\ : + | "operator*xxxx*\ " must be a member function + * - ``0342``\ + - | ``static_member_operator_not_allowed``\ : + | operator may not be a static member function + * - ``0343``\ + - | ``too_many_args_for_conversion``\ : + | no arguments allowed on user-defined conversion + * - ``0344``\ + - | ``too_many_args_for_operator``\ : + | too many parameters for this operator function + * - ``0345``\ + - | ``too_few_args_for_operator``\ : + | too few parameters for this operator function + * - ``0346``\ + - | ``no_params_with_class_type``\ : + | nonmember operator requires a parameter with class type + * - ``0347``\ + - | ``default_arg_expr_not_allowed``\ : + | default argument is not allowed + * - ``0348``\ + - | ``ambiguous_user_defined_conversion``\ : + | more than one user-defined conversion from *"type"*\ to *"type"*\ + applies: + * - ``0349``\ + - | ``no_matching_operator_function``\ : + | no operator *"xxxx"*\ matches these operands + * - ``0350``\ + - | ``ambiguous_operator_function``\ : + | more than one operator *"xxxx"*\ matches these operands: + * - ``0351``\ + - | ``bad_arg_type_for_operator_new``\ : + | first parameter of allocation function must be of type "size_t" + * - ``0352``\ + - | ``bad_return_type_for_op_new``\ : + | allocation function requires "void \*" return type + * - ``0353``\ + - | ``bad_return_type_for_op_delete``\ : + | deallocation function requires "void" return type + * - ``0354``\ + - | ``bad_first_arg_type_for_operator_delete``\ : + | first parameter of deallocation function must be of type "void \*" + * - ``0356``\ + - | ``type_must_be_object_type``\ : + | type must be an object type + * - ``0357``\ + - | ``base_class_already_initialized``\ : + | base class *"type"*\ has already been initialized + * - ``0358``\ + - | ``base_class_init_anachronism``\ : + | base class name required -- *"type"*\ assumed (anachronism) + * - ``0359``\ + - | ``member_already_initialized``\ : + | *entity-kind "entity"*\ has already been initialized + * - ``0360``\ + - | ``missing_base_class_or_member_name``\ : + | name of member or base class is missing + * - ``0361``\ + - | ``assignment_to_this``\ : + | assignment to "this" (anachronism) + * - ``0362``\ + - | ``overload_anachronism``\ : + | "overload" keyword used (anachronism) + * - ``0363``\ + - | ``anon_union_member_access``\ : + | invalid anonymous union -- nonpublic member is not allowed + * - ``0364``\ + - | ``anon_union_member_function``\ : + | invalid anonymous union -- member function is not allowed + * - ``0365``\ + - | ``anon_union_storage_class``\ : + | anonymous union at global or namespace scope must be declared static + * - ``0366``\ + - | ``missing_initializer_on_fields``\ : + | *entity-kind "entity"*\ provides no initializer for: + * - ``0367``\ + - | ``cannot_initialize_fields``\ : + | implicitly generated constructor for class *"type"*\ cannot + initialize: + * - ``0368``\ + - | ``no_ctor_but_const_or_ref_member``\ : + | *entity-kind "entity"*\ defines no constructor to initialize the + following: + * - ``0369``\ + - | ``var_with_uninitialized_member``\ : + | *entity-kind "entity"*\ has an uninitialized const or reference + member + * - ``0370``\ + - | ``var_with_uninitialized_field``\ : + | *entity-kind "entity"*\ has an uninitialized const field + * - ``0371``\ + - | ``missing_const_assignment_operator``\ : + | class *"type"*\ has no assignment operator to copy a const object + * - ``0372``\ + - | ``no_suitable_assignment_operator``\ : + | class *"type"*\ has no suitable assignment operator + * - ``0373``\ + - | ``ambiguous_assignment_operator``\ : + | ambiguous assignment operator for class *"type"*\ + * - ``0375``\ + - | ``missing_typedef_name``\ : + | declaration requires a typedef name + * - ``0377``\ + - | ``virtual_not_allowed``\ : + | "virtual" is not allowed + * - ``0378``\ + - | ``static_not_allowed``\ : + | "static" is not allowed + * - ``0379``\ + - | ``bound_function_cast_anachronism``\ : + | cast of bound function to normal function pointer (anachronism) + * - ``0380``\ + - | ``expr_not_ptr_to_member``\ : + | expression must have pointer-to-member type + * - ``0381``\ + - | ``extra_semicolon``\ : + | extra ";" ignored + * - ``0382``\ + - | ``nonstd_const_member``\ : + | in-class initializer for nonstatic member is nonstandard + * - ``0384``\ + - | ``no_matching_new_function``\ : + | no instance of overloaded *"entity"*\ matches the argument list + * - ``0386``\ + - | ``no_match_for_addr_of_overloaded_function``\ : + | no instance of *entity-kind "entity"*\ matches the required type + * - ``0387``\ + - | ``delete_count_anachronism``\ : + | delete array size expression used (anachronism) + * - ``0389``\ + - | ``cast_to_abstract_class``\ : + | a cast to abstract class *"type"*\ is not allowed: + * - ``0390``\ + - | ``bad_use_of_main``\ : + | function "main" may not be called or have its address taken + * - ``0391``\ + - | ``initializer_not_allowed_on_array_new``\ : + | a new-initializer may not be specified for an array + * - ``0392``\ + - | ``member_function_redecl_outside_class``\ : + | member function *"entity"*\ may not be redeclared outside its class + * - ``0394``\ + - | ``ref_to_nested_function_var``\ : + | reference to local variable of enclosing function is not allowed + * - ``0395``\ + - | ``single_arg_postfix_incr_decr_anachronism``\ : + | single-argument function used for postfix *"xxxx"*\ (anachronism) + * - ``0397``\ + - | ``bad_default_assignment``\ : + | implicitly generated assignment operator cannot copy: + * - ``0398``\ + - | ``nonstd_array_cast``\ : + | cast to array type is nonstandard (treated as cast to *"type"*\ ) + * - ``0399``\ + - | ``class_with_op_new_but_no_op_delete``\ : + | *entity-kind "entity"*\ has an operator new*xxxx*\ () but no default + operator delete*xxxx*\ () + * - ``0400``\ + - | ``class_with_op_delete_but_no_op_new``\ : + | *entity-kind "entity"*\ has a default operator delete*xxxx*\ () but + no operator new*xxxx*\ () + * - ``0401``\ + - | ``base_class_with_nonvirtual_dtor``\ : + | destructor for base class *"entity"*\ (declared at line *xxxx*\ ) is + not virtual + * - ``0403``\ + - | ``member_function_redeclaration``\ : + | invalid redeclaration of member *entity-kind "entity"*\ (declared at + line *xxxx*\ ) + * - ``0404``\ + - | ``inline_main``\ : + | function "main" may not be declared inline + * - ``0405``\ + - | ``class_and_member_function_name_conflict``\ : + | member function with the same name as its class must be a constructor + * - ``0406``\ + - | ``nested_class_anachronism``\ : + | using nested *entity-kind "entity"*\ (anachronism) + * - ``0407``\ + - | ``too_many_params_for_destructor``\ : + | a destructor may not have parameters + * - ``0408``\ + - | ``bad_constructor_param``\ : + | copy constructor for class *"type"*\ may not have a parameter of + type *"type"*\ + * - ``0409``\ + - | ``incomplete_function_return_type``\ : + | *entity-kind "entity"*\ returns incomplete type *"type"*\ + * - ``0410``\ + - | ``protected_access_problem``\ : + | protected *entity-kind "entity"*\ (declared at line *xxxx*\ ) is not + accessible through a *"type"*\ pointer or object + * - ``0411``\ + - | ``param_not_allowed``\ : + | a parameter is not allowed + * - ``0412``\ + - | ``asm_decl_not_allowed``\ : + | an "asm" declaration is not allowed here + * - ``0413``\ + - | ``no_conversion_function``\ : + | no suitable conversion function from *"type"*\ to *"type"*\ exists + * - ``0414``\ + - | ``delete_of_incomplete_class``\ : + | delete of pointer to incomplete class + * - ``0415``\ + - | ``no_constructor_for_conversion``\ : + | no suitable constructor exists to convert from *"type"*\ to + *"type"*\ + * - ``0416``\ + - | ``ambiguous_constructor_for_conversion``\ : + | more than one constructor applies to convert from *"type"*\ to + *"type"*\ : + * - ``0417``\ + - | ``ambiguous_conversion_function``\ : + | more than one conversion function from *"type"*\ to *"type"*\ + applies: + * - ``0418``\ + - | ``ambiguous_conversion_to_builtin``\ : + | more than one conversion function from *"type"*\ to a built-in type + applies: + * - ``0424``\ + - | ``addr_of_constructor_or_destructor``\ : + | a constructor or destructor may not have its address taken + * - ``0426``\ + - | ``nonconst_ref_init_anachronism``\ : + | temporary used for initial value of reference to non-const + (anachronism) + * - ``0427``\ + - | ``qualifier_in_member_declaration``\ : + | qualified name is not allowed in member declaration + * - ``0428``\ + - | ``mixed_enum_type_anachronism``\ : + | enumerated type mixed with another type (anachronism) + * - ``0429``\ + - | ``new_array_size_must_be_nonnegative``\ : + | the size of an array in "new" must be non-negative + * - ``0430``\ + - | ``return_ref_init_requires_temp``\ : + | returning reference to local temporary + * - ``0432``\ + - | ``enum_not_allowed``\ : + | "enum" declaration is not allowed + * - ``0433``\ + - | ``qualifier_dropped_in_ref_init``\ : + | qualifiers dropped in binding reference of type *"type"*\ to + initializer of type *"type"*\ + * - ``0434``\ + - | ``bad_nonconst_ref_init``\ : + | a reference of type *"type"*\ (not const-qualified) cannot be + initialized with a value of type *"type"*\ + * - ``0435``\ + - | ``delete_of_function_pointer``\ : + | a pointer to function may not be deleted + * - ``0436``\ + - | ``bad_conversion_function_decl``\ : + | conversion function must be a nonstatic member function + * - ``0437``\ + - | ``bad_template_declaration_scope``\ : + | a template declaration is not allowed here + * - ``0438``\ + - | ``exp_lt``\ : + | expected a "<" + * - ``0439``\ + - | ``exp_gt``\ : + | expected a ">" + * - ``0440``\ + - | ``missing_template_param``\ : + | template parameter declaration is missing + * - ``0441``\ + - | ``missing_template_arg_list``\ : + | argument list for *entity-kind "entity"*\ is missing + * - ``0442``\ + - | ``too_few_template_args``\ : + | too few arguments for *entity-kind "entity"*\ + * - ``0443``\ + - | ``too_many_template_args``\ : + | too many arguments for *entity-kind "entity"*\ + * - ``0445``\ + - | ``not_used_in_template_function_params``\ : + | *entity-kind "entity"*\ is not used in declaring the parameter types + of *entity-kind "entity"*\ + * - ``0446``\ + - | ``cfront_multiple_nested_types``\ : + | two nested types have the same name: *"entity"*\ and *"entity"*\ + (declared at line *xxxx*\ ) (cfront compatibility) + * - ``0447``\ + - | ``cfront_global_defined_after_nested_type``\ : + | global *"entity"*\ was declared after nested *"entity"*\ (declared + at line *xxxx*\ ) (cfront compatibility) + * - ``0449``\ + - | ``ambiguous_ptr_to_overloaded_function``\ : + | more than one instance of *entity-kind "entity"*\ matches the + required type + * - ``0450``\ + - | ``nonstd_long_long``\ : + | the type "long long" is nonstandard + * - ``0451``\ + - | ``nonstd_friend_decl``\ : + | omission of *"xxxx"*\ is nonstandard + * - ``0452``\ + - | ``return_type_on_conversion_function``\ : + | return type may not be specified on a conversion function + * - ``0456``\ + - | ``runaway_recursive_instantiation``\ : + | excessive recursion at instantiation of *entity-kind "entity"*\ + * - ``0457``\ + - | ``bad_template_declaration``\ : + | *"xxxx"*\ is not a function or static data member + * - ``0458``\ + - | ``bad_nontype_template_arg``\ : + | argument of type *"type"*\ is incompatible with template parameter + of type *"type"*\ + * - ``0459``\ + - | ``init_needing_temp_not_allowed``\ : + | initialization requiring a temporary or conversion is not allowed + * - ``0460``\ + - | ``decl_hides_function_parameter``\ : + | declaration of *"xxxx"*\ hides function parameter + * - ``0461``\ + - | ``nonconst_ref_init_from_rvalue``\ : + | initial value of reference to non-const must be an lvalue + * - ``0463``\ + - | ``template_not_allowed``\ : + | "template" is not allowed + * - ``0464``\ + - | ``not_a_class_template``\ : + | *"type"*\ is not a class template + * - ``0466``\ + - | ``function_template_named_main``\ : + | "main" is not a valid name for a function template + * - ``0467``\ + - | ``union_nonunion_mismatch``\ : + | invalid reference to *entity-kind "entity"*\ (union/nonunion + mismatch) + * - ``0468``\ + - | ``local_type_in_template_arg``\ : + | a template argument may not reference a local type + * - ``0469``\ + - | ``tag_kind_incompatible_with_declaration``\ : + | tag kind of *xxxx*\ is incompatible with declaration of *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``0470``\ + - | ``name_not_tag_in_file_scope``\ : + | the global scope has no tag named *"xxxx"*\ + * - ``0471``\ + - | ``not_a_tag_member``\ : + | *entity-kind "entity"*\ has no tag member named *"xxxx"*\ + * - ``0472``\ + - | ``ptr_to_member_typedef``\ : + | member function typedef (allowed for cfront compatibility) + * - ``0473``\ + - | ``bad_use_of_member_function_typedef``\ : + | *entity-kind "entity"*\ may be used only in pointer-to-member + declaration + * - ``0475``\ + - | ``nonexternal_entity_in_template_arg``\ : + | a template argument may not reference a non-external entity + * - ``0476``\ + - | ``id_must_be_class_or_type_name``\ : + | name followed by "::~" must be a class name or a type name + * - ``0478``\ + - | ``destructor_type_mismatch``\ : + | type used as destructor name does not match type *"type"*\ + * - ``0479``\ + - | ``called_function_redeclared_inline``\ : + | *entity-kind "entity"*\ redeclared "inline" after being called + * - ``0481``\ + - | ``bad_storage_class_on_template_decl``\ : + | invalid storage class for a template declaration + * - ``0482``\ + - | ``no_access_to_type_cfront_mode``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) is an + inaccessible type (allowed for cfront compatibility) + * - ``0484``\ + - | ``invalid_instantiation_argument``\ : + | invalid explicit instantiation declaration + * - ``0485``\ + - | ``not_instantiatable_entity``\ : + | *entity-kind "entity"*\ is not an entity that can be instantiated + * - ``0486``\ + - | ``compiler_generated_function_cannot_be_instantiated``\ : + | compiler generated *entity-kind "entity"*\ cannot be explicitly + instantiated + * - ``0487``\ + - | ``inline_function_cannot_be_instantiated``\ : + | inline *entity-kind "entity"*\ cannot be explicitly instantiated + * - ``0489``\ + - | ``instantiation_requested_no_definition_supplied``\ : + | *entity-kind "entity"*\ cannot be instantiated -- no template + definition was supplied + * - ``0490``\ + - | ``instantiation_requested_and_specialized``\ : + | *entity-kind "entity"*\ cannot be instantiated -- it has been + explicitly specialized + * - ``0493``\ + - | ``no_match_for_type_of_overloaded_function``\ : + | no instance of *entity-kind "entity"*\ matches the specified type + * - ``0494``\ + - | ``nonstd_void_param_list``\ : + | declaring a void parameter list with a typedef is nonstandard + * - ``0495``\ + - | ``cfront_name_lookup_bug``\ : + | global *entity-kind "entity"*\ used instead of *entity-kind + "entity"*\ (cfront compatibility) + * - ``0496``\ + - | ``redeclaration_of_template_param_name``\ : + | template parameter *"xxxx"*\ may not be redeclared in this scope + * - ``0497``\ + - | ``decl_hides_template_parameter``\ : + | declaration of *"xxxx"*\ hides template parameter + * - ``0498``\ + - | ``must_be_prototype_instantiation``\ : + | template argument list must match the parameter list + * - ``0500``\ + - | ``bad_extra_arg_for_postfix_operator``\ : + | extra parameter of postfix "operator*xxxx*\ " must be of type "int" + * - ``0501``\ + - | ``function_type_required``\ : + | an operator name must be declared as a function + * - ``0502``\ + - | ``operator_name_not_allowed``\ : + | operator name is not allowed + * - ``0503``\ + - | ``bad_scope_for_specialization``\ : + | *entity-kind "entity"*\ cannot be specialized in the current scope + * - ``0504``\ + - | ``nonstd_member_function_address``\ : + | nonstandard form for taking the address of a member function + * - ``0505``\ + - | ``too_few_template_params``\ : + | too few template parameters -- does not match previous declaration + (declared at line *xxxx*\ ) + * - ``0506``\ + - | ``too_many_template_params``\ : + | too many template parameters -- does not match previous declaration + (declared at line *xxxx*\ ) + * - ``0507``\ + - | ``template_operator_delete``\ : + | function template for operator delete(void \*) is not allowed + * - ``0508``\ + - | ``class_template_same_name_as_templ_param``\ : + | class template and template parameter may not have the same name + * - ``0510``\ + - | ``unnamed_type_in_template_arg``\ : + | a template argument may not reference an unnamed type + * - ``0511``\ + - | ``enum_type_not_allowed``\ : + | this operation on an enumerated type requires an applicable + user-defined operator function + * - ``0512``\ + - | ``qualified_reference_type``\ : + | type qualifier on a reference type is not allowed + * - ``0513``\ + - | ``incompatible_assignment_operands``\ : + | a value of type *"type"*\ cannot be assigned to an entity of type + *"type"*\ + * - ``0514``\ + - | ``unsigned_compare_with_negative``\ : + | pointless comparison of unsigned integer with a negative constant + * - ``0515``\ + - | ``converting_to_incomplete_class``\ : + | cannot convert to incomplete class *"type"*\ + * - ``0516``\ + - | ``missing_initializer_on_unnamed_const``\ : + | const object requires an initializer + * - ``0517``\ + - | ``unnamed_object_with_uninitialized_field``\ : + | object has an uninitialized const or reference member + * - ``0518``\ + - | ``nonstd_pp_directive``\ : + | nonstandard preprocessing directive + * - ``0519``\ + - | ``unexpected_template_arg_list``\ : + | *entity-kind "entity"*\ may not have a template argument list + * - ``0520``\ + - | ``missing_initializer_list``\ : + | initialization with "{...}" expected for aggregate object + * - ``0521``\ + - | ``incompatible_ptr_to_member_selection_operands``\ : + | pointer-to-member selection class types are incompatible (*"type"*\ + and *"type"*\ ) + * - ``0522``\ + - | ``self_friendship``\ : + | pointless friend declaration + * - ``0523``\ + - | ``period_used_as_qualifier``\ : + | "." used in place of "::" to form a qualified name + * - ``0524``\ + - | ``const_function_anachronism``\ : + | non-const function called for const object (anachronism) + * - ``0525``\ + - | ``dependent_stmt_is_declaration``\ : + | a dependent statement may not be a declaration + * - ``0526``\ + - | ``void_param_not_allowed``\ : + | a parameter may not have void type + * - ``0529``\ + - | ``bad_templ_arg_expr_operator``\ : + | this operator is not allowed in a template argument expression + * - ``0530``\ + - | ``missing_handler``\ : + | try block requires at least one handler + * - ``0531``\ + - | ``missing_exception_declaration``\ : + | handler requires an exception declaration + * - ``0532``\ + - | ``masked_by_default_handler``\ : + | handler is masked by default handler + * - ``0533``\ + - | ``masked_by_handler``\ : + | handler is potentially masked by previous handler for type *"type"*\ + * - ``0534``\ + - | ``local_type_used_in_exception``\ : + | use of a local type to specify an exception + * - ``0535``\ + - | ``redundant_exception_specification_type``\ : + | redundant type in exception specification + * - ``0536``\ + - | ``incompatible_exception_specification``\ : + | exception specification is incompatible with that of previous + *entity-kind "entity"*\ (declared at line *xxxx*\ ): + * - ``0540``\ + - | ``no_exception_support``\ : + | support for exception handling is disabled + * - ``0541``\ + - | ``omitted_exception_specification``\ : + | allowing all exceptions is incompatible with previous *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``0542``\ + - | ``cannot_create_instantiation_request_file``\ : + | could not create instantiation request file *"xxxx"*\ + * - ``0543``\ + - | ``non_arith_operation_in_templ_arg``\ : + | non-arithmetic operation not allowed in nontype template argument + * - ``0544``\ + - | ``local_type_in_nonlocal_var``\ : + | use of a local type to declare a nonlocal variable + * - ``0545``\ + - | ``local_type_in_function``\ : + | use of a local type to declare a function + * - ``0546``\ + - | ``branch_past_initialization``\ : + | transfer of control bypasses initialization of: + * - ``0548``\ + - | ``branch_into_handler``\ : + | transfer of control into an exception handler + * - ``0549``\ + - | ``used_before_set``\ : + | *entity-kind "entity"*\ is used before its value is set + * - ``0550``\ + - | ``set_but_not_used``\ : + | *entity-kind "entity"*\ was set but never used + * - ``0551``\ + - | ``bad_scope_for_definition``\ : + | *entity-kind "entity"*\ cannot be defined in the current scope + * - ``0552``\ + - | ``exception_specification_not_allowed``\ : + | exception specification is not allowed + * - ``0553``\ + - | ``template_and_instance_linkage_conflict``\ : + | external/internal linkage conflict for *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``0554``\ + - | ``conversion_function_not_usable``\ : + | *entity-kind "entity"*\ will not be called for implicit or explicit + conversions + * - ``0555``\ + - | ``tag_kind_incompatible_with_template_parameter``\ : + | tag kind of *xxxx*\ is incompatible with template parameter of type + *"type"*\ + * - ``0556``\ + - | ``template_operator_new``\ : + | function template for operator new(size_t) is not allowed + * - ``0558``\ + - | ``bad_member_type_in_ptr_to_member``\ : + | pointer to member of type *"type"*\ is not allowed + * - ``0559``\ + - | ``ellipsis_on_operator_function``\ : + | ellipsis is not allowed in operator function parameter list + * - ``0560``\ + - | ``unimplemented_keyword``\ : + | *"entity"*\ is reserved for future use as a keyword + * - ``0561``\ + - | ``cl_invalid_macro_definition``\ : + | invalid macro definition: *xxxx*\ + * - ``0562``\ + - | ``cl_invalid_macro_undefinition``\ : + | invalid macro undefinition: *xxxx*\ + * - ``0565``\ + - | ``cl_il_file_must_be_specified``\ : + | IL file name must be specified if input is + * - ``0570``\ + - | ``cl_error_in_debug_option_argument``\ : + | error in debug option argument + * - ``0571``\ + - | ``cl_invalid_option``\ : + | invalid option: *xxxx*\ + * - ``0572``\ + - | ``cl_back_end_requires_il_file``\ : + | back end requires name of IL file + * - ``0573``\ + - | ``cl_could_not_open_il_file``\ : + | could not open IL file *xxxx*\ + * - ``0574``\ + - | ``cl_invalid_number``\ : + | invalid number: *xxxx*\ + * - ``0575``\ + - | ``cl_incorrect_host_id``\ : + | incorrect host CPU id + * - ``0576``\ + - | ``cl_invalid_instantiation_mode``\ : + | invalid instantiation mode: *xxxx*\ + * - ``0578``\ + - | ``cl_invalid_error_limit``\ : + | invalid error limit: *xxxx*\ + * - ``0585``\ + - | ``cl_vtbl_option_only_in_cplusplus``\ : + | virtual function tables can only be suppressed when compiling C++ + * - ``0586``\ + - | ``cl_anachronism_option_only_in_cplusplus``\ : + | anachronism option can be used only when compiling C++ + * - ``0587``\ + - | ``cl_instantiation_option_only_in_cplusplus``\ : + | instantiation mode option can be used only when compiling C++ + * - ``0588``\ + - | ``cl_auto_instantiation_option_only_in_cplusplus``\ : + | automatic instantiation mode can be used only when compiling C++ + * - ``0589``\ + - | ``cl_implicit_inclusion_option_only_in_cplusplus``\ : + | implicit template inclusion mode can be used only when compiling C++ + * - ``0590``\ + - | ``cl_exceptions_option_only_in_cplusplus``\ : + | exception handling option can be used only when compiling C++ + * - ``0591``\ + - | ``cl_strict_mode_incompatible_with_pcc``\ : + | strict mode is incompatible with K&R mode + * - ``0592``\ + - | ``cl_strict_mode_incompatible_with_cfront``\ : + | strict mode is incompatible with cfront mode + * - ``0593``\ + - | ``cl_missing_source_file_name``\ : + | missing source file name + * - ``0594``\ + - | ``cl_output_file_incompatible_with_multiple_inputs``\ : + | output files may not be specified when compiling several input files + * - ``0595``\ + - | ``cl_too_many_arguments``\ : + | too many arguments on command line + * - ``0596``\ + - | ``cl_no_output_file_needed``\ : + | an output file was specified, but none is needed + * - ``0597``\ + - | ``cl_il_display_requires_il_file_name``\ : + | IL display requires name of IL file + * - ``0598``\ + - | ``void_template_parameter``\ : + | a template parameter may not have void type + * - ``0599``\ + - | ``too_many_unused_instantiations``\ : + | excessive recursive instantiation of *entity-kind "entity"*\ due to + instantiate-all mode + * - ``0600``\ + - | ``cl_strict_mode_incompatible_with_anachronisms``\ : + | strict mode is incompatible with allowing anachronisms + * - ``0601``\ + - | ``void_throw``\ : + | a throw expression may not have void type + * - ``0602``\ + - | ``cl_tim_local_conflicts_with_auto_instantiation``\ : + | local instantiation mode is incompatible with automatic instantiation + * - ``0603``\ + - | ``abstract_class_param_type``\ : + | parameter of abstract class type *"type"*\ is not allowed: + * - ``0604``\ + - | ``array_of_abstract_class``\ : + | array of abstract class *"type"*\ is not allowed: + * - ``0605``\ + - | ``float_template_parameter``\ : + | floating-point template parameter is nonstandard + * - ``0606``\ + - | ``pragma_must_precede_declaration``\ : + | this pragma must immediately precede a declaration + * - ``0607``\ + - | ``pragma_must_precede_statement``\ : + | this pragma must immediately precede a statement + * - ``0608``\ + - | ``pragma_must_precede_decl_or_stmt``\ : + | this pragma must immediately precede a declaration or statement + * - ``0609``\ + - | ``pragma_may_not_be_used_here``\ : + | this kind of pragma may not be used here + * - ``0611``\ + - | ``partial_override``\ : + | overloaded virtual function *"entity"*\ is only partially overridden + in *entity-kind "entity"*\ + * - ``0612``\ + - | ``specialization_of_called_inline_template_function``\ : + | specific definition of inline template function must precede its + first use + * - ``0613``\ + - | ``cl_invalid_error_tag``\ : + | invalid error tag in diagnostic control option: *xxxx*\ + * - ``0614``\ + - | ``cl_invalid_error_number``\ : + | invalid error number in diagnostic control option: *xxxx*\ + * - ``0617``\ + - | ``ptr_to_member_cast_to_ptr_to_function``\ : + | pointer-to-member-function cast to pointer to function + * - ``0618``\ + - | ``no_named_fields``\ : + | struct or union declares no named members + * - ``0619``\ + - | ``nonstd_unnamed_field``\ : + | nonstandard unnamed field + * - ``0620``\ + - | ``nonstd_unnamed_member``\ : + | nonstandard unnamed member + * - ``0624``\ + - | ``not_a_type_name``\ : + | *"xxxx"*\ is not a type name + * - ``0625``\ + - | ``cannot_open_pch_input_file_reason``\ : + | cannot open precompiled header input file *"xxxx"*\ : *xxxx*\ + * - ``0626``\ + - | ``invalid_pch_file``\ : + | precompiled header file *"xxxx"*\ is either invalid or not generated + by this version of the compiler + * - ``0627``\ + - | ``pch_curr_directory_changed``\ : + | precompiled header file *"xxxx"*\ was not generated in this directory + * - ``0628``\ + - | ``pch_header_files_have_changed``\ : + | header files used to generate precompiled header file *"xxxx"*\ have + changed + * - ``0629``\ + - | ``pch_cmd_line_option_mismatch``\ : + | the command line options do not match those used when precompiled + header file *"xxxx"*\ was created + * - ``0630``\ + - | ``pch_file_prefix_mismatch``\ : + | the initial sequence of preprocessing directives is not compatible + with those of precompiled header file *"xxxx"*\ + * - ``0631``\ + - | ``unable_to_get_mapped_memory``\ : + | unable to obtain mapped memory + * - ``0632``\ + - | ``using_pch``\ : + | "*xxxx*\ ": using precompiled header file "*xxxx*\ " + * - ``0633``\ + - | ``creating_pch``\ : + | "*xxxx*\ ": creating precompiled header file "*xxxx*\ " + * - ``0634``\ + - | ``memory_mismatch``\ : + | memory usage conflict with precompiled header file *"xxxx"*\ + * - ``0635``\ + - | ``cl_invalid_pch_size``\ : + | invalid PCH memory size: *xxxx*\ + * - ``0636``\ + - | ``cl_pch_must_be_first``\ : + | PCH options must appear first in the command line + * - ``0637``\ + - | ``out_of_memory_during_pch_allocation``\ : + | insufficient memory for PCH memory allocation + * - ``0638``\ + - | ``cl_pch_incompatible_with_multiple_inputs``\ : + | precompiled header files may not be used when compiling several input + files + * - ``0639``\ + - | ``not_enough_preallocated_memory``\ : + | insufficient preallocated memory for generation of precompiled header + file (*xxxx*\ bytes required) + * - ``0640``\ + - | ``program_entity_too_large_for_pch``\ : + | very large entity in program prevents generation of precompiled + header file + * - ``0641``\ + - | ``cannot_chdir``\ : + | *"xxxx"*\ is not a valid directory + * - ``0642``\ + - | ``cannot_build_temp_file_name``\ : + | cannot build temporary file name + * - ``0643``\ + - | ``restrict_not_allowed``\ : + | "restrict" is not allowed + * - ``0644``\ + - | ``restrict_pointer_to_function``\ : + | a pointer or reference to function type may not be qualified by + "restrict" + * - ``0646``\ + - | ``calling_convention_not_allowed``\ : + | a calling convention modifier may not be specified here + * - ``0647``\ + - | ``conflicting_calling_conventions``\ : + | conflicting calling convention modifiers + * - ``0648``\ + - | ``cl_strict_mode_incompatible_with_microsoft``\ : + | strict mode is incompatible with Microsoft mode + * - ``0649``\ + - | ``cl_cfront_incompatible_with_microsoft``\ : + | cfront mode is incompatible with Microsoft mode + * - ``0650``\ + - | ``calling_convention_ignored``\ : + | calling convention specified here is ignored + * - ``0651``\ + - | ``calling_convention_may_not_precede_nested_declarator``\ : + | a calling convention may not be followed by a nested declarator + * - ``0652``\ + - | ``calling_convention_ignored_for_type``\ : + | calling convention is ignored for this type + * - ``0654``\ + - | ``decl_modifiers_incompatible_with_previous_decl``\ : + | declaration modifiers are incompatible with previous declaration + * - ``0655``\ + - | ``decl_modifiers_invalid_for_this_decl``\ : + | the modifier *"xxxx"*\ is not allowed on this declaration + * - ``0656``\ + - | ``branch_into_try_block``\ : + | transfer of control into a try block + * - ``0657``\ + - | ``incompatible_inline_specifier_on_specific_decl``\ : + | inline specification is incompatible with previous *"entity"*\ + (declared at line *xxxx*\ ) + * - ``0658``\ + - | ``template_missing_closing_brace``\ : + | closing brace of template definition not found + * - ``0659``\ + - | ``cl_wchar_t_option_only_in_cplusplus``\ : + | wchar_t keyword option can be used only when compiling C++ + * - ``0660``\ + - | ``bad_pack_alignment``\ : + | invalid packing alignment value + * - ``0661``\ + - | ``exp_int_constant``\ : + | expected an integer constant + * - ``0662``\ + - | ``call_of_pure_virtual``\ : + | call of pure virtual function + * - ``0663``\ + - | ``bad_ident_string``\ : + | invalid source file identifier string + * - ``0664``\ + - | ``template_friend_definition_not_allowed``\ : + | a class template cannot be defined in a friend declaration + * - ``0665``\ + - | ``asm_not_allowed``\ : + | "asm" is not allowed + * - ``0666``\ + - | ``bad_asm_function_def``\ : + | "asm" must be used with a function definition + * - ``0667``\ + - | ``nonstd_asm_function``\ : + | "asm" function is nonstandard + * - ``0668``\ + - | ``nonstd_ellipsis_only_param``\ : + | ellipsis with no explicit parameters is nonstandard + * - ``0669``\ + - | ``nonstd_address_of_ellipsis``\ : + | "&..." is nonstandard + * - ``0670``\ + - | ``bad_address_of_ellipsis``\ : + | invalid use of "&..." + * - ``0672``\ + - | ``const_volatile_ref_init_anachronism``\ : + | temporary used for initial value of reference to const volatile + (anachronism) + * - ``0673``\ + - | ``bad_const_volatile_ref_init``\ : + | a reference of type *"type"*\ cannot be initialized with a value of + type *"type"*\ + * - ``0674``\ + - | ``const_volatile_ref_init_from_rvalue``\ : + | initial value of reference to const volatile must be an lvalue + * - ``0675``\ + - | ``cl_SVR4_C_option_only_in_ansi_C``\ : + | SVR4 C compatibility option can be used only when compiling ANSI C + * - ``0676``\ + - | ``using_out_of_scope_declaration``\ : + | using out-of-scope declaration of *entity-kind "entity"*\ (declared + at line *xxxx*\ ) + * - ``0677``\ + - | ``cl_strict_mode_incompatible_with_SVR4``\ : + | strict mode is incompatible with SVR4 C mode + * - ``0678``\ + - | ``cannot_inline_call``\ : + | call of *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot + be inlined + * - ``0679``\ + - | ``cannot_inline``\ : + | *entity-kind "entity"*\ cannot be inlined + * - ``0680``\ + - | ``cl_invalid_pch_directory``\ : + | invalid PCH directory: *xxxx*\ + * - ``0681``\ + - | ``exp_except_or_finally``\ : + | expected \__except or \__finally + * - ``0682``\ + - | ``leave_must_be_in_try``\ : + | a \__leave statement may only be used within a \__try + * - ``0688``\ + - | ``not_found_on_pack_alignment_stack``\ : + | *"xxxx"*\ not found on pack alignment stack + * - ``0689``\ + - | ``empty_pack_alignment_stack``\ : + | empty pack alignment stack + * - ``0690``\ + - | ``cl_rtti_option_only_in_cplusplus``\ : + | RTTI option can be used only when compiling C++ + * - ``0691``\ + - | ``inaccessible_elided_cctor``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ), required for + copy that was eliminated, is inaccessible + * - ``0692``\ + - | ``uncallable_elided_cctor``\ : + | *entity-kind "entity"*\ , required for copy that was eliminated, is + not callable because reference parameter cannot be bound to rvalue + * - ``0693``\ + - | ``typeid_needs_typeinfo``\ : + | must be included before typeid is used + * - ``0694``\ + - | ``cannot_cast_away_const``\ : + | *xxxx*\ cannot cast away const or other type qualifiers + * - ``0695``\ + - | ``bad_dynamic_cast_type``\ : + | the type in a dynamic_cast must be a pointer or reference to a + complete class type, or void \* + * - ``0696``\ + - | ``bad_ptr_dynamic_cast_operand``\ : + | the operand of a pointer dynamic_cast must be a pointer to a complete + class type + * - ``0697``\ + - | ``bad_ref_dynamic_cast_operand``\ : + | the operand of a reference dynamic_cast must be an lvalue of a + complete class type + * - ``0698``\ + - | ``dynamic_cast_operand_must_be_polymorphic``\ : + | the operand of a runtime dynamic_cast must have a polymorphic class + type + * - ``0699``\ + - | ``cl_bool_option_only_in_cplusplus``\ : + | bool option can be used only when compiling C++ + * - ``0701``\ + - | ``array_type_not_allowed``\ : + | an array type is not allowed here + * - ``0702``\ + - | ``exp_assign``\ : + | expected an "=" + * - ``0704``\ + - | ``redeclaration_of_condition_decl_name``\ : + | *"xxxx"*\ , declared in condition, may not be redeclared in this scope + * - ``0705``\ + - | ``default_template_arg_not_allowed``\ : + | default template arguments are not allowed for function templates + * - ``0706``\ + - | ``exp_comma_or_gt``\ : + | expected a "," or ">" + * - ``0707``\ + - | ``missing_template_param_list``\ : + | expected a template parameter list + * - ``0708``\ + - | ``incr_of_bool_deprecated``\ : + | incrementing a bool value is deprecated + * - ``0709``\ + - | ``bool_type_not_allowed``\ : + | bool type is not allowed + * - ``0710``\ + - | ``base_class_offset_too_large``\ : + | offset of base class *"entity"*\ within class *"entity"*\ is too + large + * - ``0711``\ + - | ``expr_not_bool``\ : + | expression must have bool type (or be convertible to bool) + * - ``0712``\ + - | ``cl_array_new_and_delete_option_only_in_cplusplus``\ : + | array new and delete option can be used only when compiling C++ + * - ``0713``\ + - | ``based_requires_variable_name``\ : + | *entity-kind "entity"*\ is not a variable name + * - ``0714``\ + - | ``based_not_allowed_here``\ : + | __based modifier is not allowed here + * - ``0715``\ + - | ``based_not_followed_by_star``\ : + | __based does not precede a pointer operator, \__based ignored + * - ``0716``\ + - | ``based_var_must_be_ptr``\ : + | variable in \__based modifier must have pointer type + * - ``0717``\ + - | ``bad_const_cast_type``\ : + | the type in a const_cast must be a pointer, reference, or pointer to + member to an object type + * - ``0718``\ + - | ``bad_const_cast``\ : + | a const_cast can only adjust type qualifiers; it cannot change the + underlying type + * - ``0719``\ + - | ``mutable_not_allowed``\ : + | mutable is not allowed + * - ``0720``\ + - | ``cannot_change_access``\ : + | redeclaration of *entity-kind "entity"*\ is not allowed to alter its + access + * - ``0722``\ + - | ``probable_inadvertent_lbracket_digraph``\ : + | use of alternative token "<:" appears to be unintended + * - ``0723``\ + - | ``probable_inadvertent_sharp_digraph``\ : + | use of alternative token "%:" appears to be unintended + * - ``0724``\ + - | ``namespace_def_not_allowed``\ : + | namespace definition is not allowed + * - ``0725``\ + - | ``missing_namespace_name``\ : + | name must be a namespace name + * - ``0726``\ + - | ``namespace_alias_def_not_allowed``\ : + | namespace alias definition is not allowed + * - ``0727``\ + - | ``namespace_qualified_name_required``\ : + | namespace-qualified name is required + * - ``0728``\ + - | ``namespace_name_not_allowed``\ : + | a namespace name is not allowed + * - ``0729``\ + - | ``bad_combination_of_dll_attributes``\ : + | invalid combination of DLL attributes + * - ``0730``\ + - | ``sym_not_a_class_template``\ : + | *entity-kind "entity"*\ is not a class template + * - ``0731``\ + - | ``array_of_incomplete_type``\ : + | array with incomplete element type is nonstandard + * - ``0732``\ + - | ``allocation_operator_in_namespace``\ : + | allocation operator may not be declared in a namespace + * - ``0733``\ + - | ``deallocation_operator_in_namespace``\ : + | deallocation operator may not be declared in a namespace + * - ``0734``\ + - | ``conflicts_with_using_decl``\ : + | *entity-kind "entity"*\ conflicts with using-declaration of + *entity-kind "entity"*\ + * - ``0735``\ + - | ``using_decl_conflicts_with_prev_decl``\ : + | using-declaration of *entity-kind "entity"*\ conflicts with + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``0736``\ + - | ``cl_namespaces_option_only_in_cplusplus``\ : + | namespaces option can be used only when compiling C++ + * - ``0737``\ + - | ``useless_using_declaration``\ : + | using-declaration ignored -- it refers to the current namespace + * - ``0738``\ + - | ``class_qualified_name_required``\ : + | a class-qualified name is required + * - ``0742``\ + - | ``not_an_actual_member``\ : + | *entity-kind "entity"*\ has no actual member *"xxxx"*\ + * - ``0744``\ + - | ``mem_attrib_incompatible``\ : + | incompatible memory attributes specified + * - ``0745``\ + - | ``mem_attrib_ignored``\ : + | memory attribute ignored + * - ``0746``\ + - | ``mem_attrib_may_not_precede_nested_declarator``\ : + | memory attribute may not be followed by a nested declarator + * - ``0747``\ + - | ``dupl_mem_attrib``\ : + | memory attribute specified more than once + * - ``0748``\ + - | ``dupl_calling_convention``\ : + | calling convention specified more than once + * - ``0749``\ + - | ``type_qualifier_not_allowed``\ : + | a type qualifier is not allowed + * - ``0750``\ + - | ``template_instance_already_used``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was used before + its template was declared + * - ``0751``\ + - | ``static_nonstatic_with_same_param_types``\ : + | static and nonstatic member functions with same parameter types + cannot be overloaded + * - ``0752``\ + - | ``no_prior_declaration``\ : + | no prior declaration of *entity-kind "entity"*\ + * - ``0753``\ + - | ``template_id_not_allowed``\ : + | a template-id is not allowed + * - ``0754``\ + - | ``class_qualified_name_not_allowed``\ : + | a class-qualified name is not allowed + * - ``0755``\ + - | ``bad_scope_for_redeclaration``\ : + | *entity-kind "entity"*\ may not be redeclared in the current scope + * - ``0756``\ + - | ``qualifier_in_namespace_member_decl``\ : + | qualified name is not allowed in namespace member declaration + * - ``0757``\ + - | ``sym_not_a_type_name``\ : + | *entity-kind "entity"*\ is not a type name + * - ``0758``\ + - | ``explicit_instantiation_not_in_namespace_scope``\ : + | explicit instantiation is not allowed in the current scope + * - ``0759``\ + - | ``bad_scope_for_explicit_instantiation``\ : + | *entity-kind "entity"*\ cannot be explicitly instantiated in the + current scope + * - ``0760``\ + - | ``multiple_explicit_instantiations``\ : + | *entity-kind "entity"*\ explicitly instantiated more than once + * - ``0761``\ + - | ``typename_not_in_template``\ : + | typename may only be used within a template + * - ``0762``\ + - | ``cl_special_subscript_cost_option_only_in_cplusplus``\ : + | special_subscript_cost option can be used only when compiling C++ + * - ``0763``\ + - | ``cl_typename_option_only_in_cplusplus``\ : + | typename option can be used only when compiling C++ + * - ``0764``\ + - | ``cl_implicit_typename_option_only_in_cplusplus``\ : + | implicit typename option can be used only when compiling C++ + * - ``0765``\ + - | ``nonstd_character_at_start_of_macro_def``\ : + | nonstandard character at start of object-like macro definition + * - ``0766``\ + - | ``exception_spec_override_incompat``\ : + | exception specification for virtual *entity-kind "entity"*\ is + incompatible with that of overridden *entity-kind "entity"*\ + * - ``0767``\ + - | ``pointer_conversion_loses_bits``\ : + | conversion from pointer to smaller integer + * - ``0768``\ + - | ``generated_exception_spec_override_incompat``\ : + | exception specification for implicitly declared virtual *entity-kind + "entity"*\ is incompatible with that of overridden *entity-kind + "entity"*\ + * - ``0769``\ + - | ``implicit_call_of_ambiguous_name``\ : + | *"entity"*\ , implicitly called from *entity-kind "entity"*\ , is + ambiguous + * - ``0770``\ + - | ``cl_explicit_option_only_in_cplusplus``\ : + | option "explicit" can be used only when compiling C++ + * - ``0771``\ + - | ``explicit_not_allowed``\ : + | "explicit" is not allowed + * - ``0772``\ + - | ``conflicts_with_predeclared_type_info``\ : + | declaration conflicts with *"xxxx"*\ (reserved class name) + * - ``0773``\ + - | ``array_member_initialization``\ : + | only "()" is allowed as initializer for array *entity-kind "entity"*\ + * - ``0774``\ + - | ``virtual_function_template``\ : + | "virtual" is not allowed in a function template declaration + * - ``0775``\ + - | ``anon_union_class_member_template``\ : + | invalid anonymous union -- class member template is not allowed + * - ``0776``\ + - | ``template_depth_mismatch``\ : + | template nesting depth does not match the previous declaration of + *entity-kind "entity"*\ + * - ``0777``\ + - | ``multiple_template_decls_not_allowed``\ : + | this declaration cannot have multiple "template <...>" clauses + * - ``0778``\ + - | ``cl_old_for_init_option_only_in_cplusplus``\ : + | option to control the for-init scope can be used only when compiling + C++ + * - ``0779``\ + - | ``redeclaration_of_for_init_decl_name``\ : + | *"xxxx"*\ , declared in for-loop initialization, may not be + redeclared in this scope + * - ``0780``\ + - | ``hidden_by_old_for_init``\ : + | reference is to *entity-kind "entity"*\ (declared at line *xxxx*\ ) + -- under old for-init scoping rules it would have been *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``0781``\ + - | ``cl_for_init_diff_warning_option_only_in_cplusplus``\ : + | option to control warnings on for-init differences can be used only + when compiling C++ + * - ``0782``\ + - | ``unnamed_class_virtual_function_def_missing``\ : + | definition of virtual *entity-kind "entity"*\ is required here + * - ``0783``\ + - | ``svr4_token_pasting_comment``\ : + | empty comment interpreted as token-pasting operator "##" + * - ``0784``\ + - | ``storage_class_in_friend_decl``\ : + | a storage class is not allowed in a friend declaration + * - ``0785``\ + - | ``templ_param_list_not_allowed``\ : + | template parameter list for *"entity"*\ is not allowed in this + declaration + * - ``0786``\ + - | ``bad_member_template_sym``\ : + | *entity-kind "entity"*\ is not a valid class member template + * - ``0787``\ + - | ``bad_member_template_decl``\ : + | not a valid member class or function template declaration + * - ``0788``\ + - | ``specialization_follows_param_list``\ : + | a template declaration containing a template parameter list may not + be followed by an explicit specialization declaration + * - ``0789``\ + - | ``specialization_of_referenced_template``\ : + | explicit specialization of *entity-kind "entity"*\ must precede the + first use of *entity-kind "entity"*\ + * - ``0790``\ + - | ``explicit_specialization_not_in_namespace_scope``\ : + | explicit specialization is not allowed in the current scope + * - ``0791``\ + - | ``partial_specialization_not_allowed``\ : + | partial specialization of *entity-kind "entity"*\ is not allowed + * - ``0792``\ + - | ``entity_cannot_be_specialized``\ : + | *entity-kind "entity"*\ is not an entity that can be explicitly + specialized + * - ``0793``\ + - | ``specialization_of_referenced_entity``\ : + | explicit specialization of *entity-kind "entity"*\ must precede its + first use + * - ``0794``\ + - | ``template_param_in_elab_type``\ : + | template parameter *"xxxx"*\ may not be used in an elaborated type + specifier + * - ``0795``\ + - | ``old_specialization_not_allowed``\ : + | specializing *entity-kind "entity"*\ requires "template<>" syntax + * - ``0798``\ + - | ``cl_old_specializations_option_only_in_cplusplus``\ : + | option "old_specializations" can be used only when compiling C++ + * - ``0799``\ + - | ``nonstd_old_specialization``\ : + | specializing *entity-kind "entity"*\ without "template<>" syntax is + nonstandard + * - ``0800``\ + - | ``bad_linkage_for_decl``\ : + | this declaration may not have extern "C" linkage + * - ``0801``\ + - | ``not_a_template_name``\ : + | *"xxxx"*\ is not a class or function template name in the current + scope + * - ``0802``\ + - | ``nonstd_default_arg_on_function_template_redecl``\ : + | specifying a default argument when redeclaring an unreferenced + function template is nonstandard + * - ``0803``\ + - | ``default_arg_on_function_template_not_allowed``\ : + | specifying a default argument when redeclaring an already referenced + function template is not allowed + * - ``0804``\ + - | ``pm_derived_class_from_virtual_base``\ : + | cannot convert pointer to member of base class *"type"*\ to pointer + to member of derived class *"type"*\ -- base class is virtual + * - ``0805``\ + - | ``bad_exception_specification_for_specialization``\ : + | exception specification is incompatible with that of *entity-kind + "entity"*\ (declared at line *xxxx*\ ): + * - ``0806``\ + - | ``omitted_exception_specification_on_specialization``\ : + | allowing all exceptions is incompatible with *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``0807``\ + - | ``unexpected_end_of_default_arg``\ : + | unexpected end of default argument expression + * - ``0808``\ + - | ``default_init_of_reference``\ : + | default-initialization of reference is not allowed + * - ``0809``\ + - | ``uninitialized_field_with_const_member``\ : + | uninitialized *entity-kind "entity"*\ has a const member + * - ``0810``\ + - | ``uninitialized_base_class_with_const_member``\ : + | uninitialized base class *"type"*\ has a const member + * - ``0811``\ + - | ``missing_default_constructor_on_const``\ : + | const *entity-kind "entity"*\ requires an initializer -- class + *"type"*\ has no user-provided default constructor + * - ``0812``\ + - | ``missing_default_constructor_on_unnamed_const``\ : + | const object requires an initializer -- class *"type"*\ has no + user-provided default constructor + * - ``0813``\ + - | ``cl_impl_extern_c_conv_option_only_in_cplusplus``\ : + | option "implicit_extern_c_type_conversion" can be used only when + compiling C++ + * - ``0814``\ + - | ``cl_strict_mode_incompatible_with_long_preserving``\ : + | strict mode is incompatible with long preserving rules + * - ``0815``\ + - | ``useless_type_qualifier_on_return_type``\ : + | type qualifier on return type is meaningless + * - ``0816``\ + - | ``type_qualifier_on_void_return_type``\ : + | in a function definition a type qualifier on a "void" return type is + not allowed + * - ``0817``\ + - | ``static_data_member_not_allowed``\ : + | static data member declaration is not allowed in this class + * - ``0818``\ + - | ``invalid_declaration``\ : + | template instantiation resulted in an invalid function declaration + * - ``0819``\ + - | ``ellipsis_not_allowed``\ : + | "..." is not allowed + * - ``0820``\ + - | ``cl_extern_inline_option_only_in_cplusplus``\ : + | option "extern_inline" can be used only when compiling C++ + * - ``0821``\ + - | ``extern_inline_never_defined``\ : + | extern inline *entity-kind "entity"*\ was referenced but not defined + * - ``0822``\ + - | ``invalid_destructor_name``\ : + | invalid destructor name for type *"type"*\ + * - ``0824``\ + - | ``ambiguous_destructor``\ : + | destructor reference is ambiguous -- both *entity-kind "entity"*\ + and *entity-kind "entity"*\ could be used + * - ``0825``\ + - | ``virtual_inline_never_defined``\ : + | virtual inline *entity-kind "entity"*\ was never defined + * - ``0826``\ + - | ``unreferenced_function_param``\ : + | *entity-kind "entity"*\ was never referenced + * - ``0827``\ + - | ``union_already_initialized``\ : + | only one member of a union may be specified in a constructor + initializer list + * - ``0828``\ + - | ``no_array_new_and_delete_support``\ : + | support for "new[]" and "delete[]" is disabled + * - ``0829``\ + - | ``double_for_long_double``\ : + | "double" used for "long double" in generated C code + * - ``0830``\ + - | ``no_corresponding_delete``\ : + | *entity-kind "entity"*\ has no corresponding operator delete*xxxx*\ + (to be called if an exception is thrown during initialization of an + allocated object) + * - ``0831``\ + - | ``useless_placement_delete``\ : + | support for placement delete is disabled + * - ``0832``\ + - | ``no_appropriate_delete``\ : + | no appropriate operator delete is visible + * - ``0833``\ + - | ``ptr_or_ref_to_incomplete_type``\ : + | pointer or reference to incomplete type *"type"*\ is not allowed + * - ``0834``\ + - | ``bad_partial_specialization``\ : + | invalid partial specialization -- *entity-kind "entity"*\ is already + fully specialized + * - ``0835``\ + - | ``incompatible_exception_specs``\ : + | incompatible exception specifications + * - ``0836``\ + - | ``returning_ref_to_local_variable``\ : + | returning reference to local variable + * - ``0837``\ + - | ``nonstd_implicit_int``\ : + | omission of explicit type is nonstandard ("int" assumed) + * - ``0838``\ + - | ``ambiguous_partial_spec``\ : + | more than one partial specialization matches the template argument + list of *entity-kind "entity"*\ + * - ``0840``\ + - | ``partial_spec_is_primary_template``\ : + | a template argument list is not allowed in a declaration of a primary + template + * - ``0841``\ + - | ``default_not_allowed_on_partial_spec``\ : + | partial specializations may not have default template arguments + * - ``0842``\ + - | ``not_used_in_partial_spec_arg_list``\ : + | *entity-kind "entity"*\ is not used in or cannot be deduced from the + template argument list of *entity-kind "entity"*\ + * - ``0844``\ + - | ``partial_spec_arg_depends_on_templ_param``\ : + | the template argument list of the partial specialization includes a + nontype argument whose type depends on a template parameter + * - ``0845``\ + - | ``partial_spec_after_instantiation``\ : + | this partial specialization would have been used to instantiate + *entity-kind "entity"*\ + * - ``0846``\ + - | ``partial_spec_after_instantiation_ambiguous``\ : + | this partial specialization would have made the instantiation of + *entity-kind "entity"*\ ambiguous + * - ``0847``\ + - | ``expr_not_integral_or_enum``\ : + | expression must have integral or enum type + * - ``0848``\ + - | ``expr_not_arithmetic_or_enum``\ : + | expression must have arithmetic or enum type + * - ``0849``\ + - | ``expr_not_arithmetic_or_enum_or_pointer``\ : + | expression must have arithmetic, enum, or pointer type + * - ``0850``\ + - | ``cast_not_integral_or_enum``\ : + | type of cast must be integral or enum + * - ``0851``\ + - | ``cast_not_arithmetic_or_enum_or_pointer``\ : + | type of cast must be arithmetic, enum, or pointer + * - ``0852``\ + - | ``expr_not_object_pointer``\ : + | expression must be a pointer to a complete object type + * - ``0855``\ + - | ``different_return_type_on_virtual_function_override``\ : + | return type is not identical to return type *"type"*\ of overridden + virtual function *"entity"*\ + * - ``0856``\ + - | ``cl_guiding_decls_option_only_in_cplusplus``\ : + | option "guiding_decls" can be used only when compiling C++ + * - ``0857``\ + - | ``member_partial_spec_not_in_namespace``\ : + | a partial specialization of a class template must be declared in the + namespace of which it is a member + * - ``0858``\ + - | ``pure_virtual_function``\ : + | *entity-kind "entity"*\ is a pure virtual function + * - ``0859``\ + - | ``no_overrider_for_pure_virtual_function``\ : + | pure virtual *entity-kind "entity"*\ has no overrider + * - ``0860``\ + - | ``decl_modifiers_ignored``\ : + | __declspec attributes ignored + * - ``0861``\ + - | ``invalid_char``\ : + | invalid character in input line + * - ``0862``\ + - | ``incomplete_return_type``\ : + | function returns incomplete type *"type"*\ + * - ``0863``\ + - | ``local_pragma_pack``\ : + | effect of this "#pragma pack" directive is local to *entity-kind + "entity"*\ + * - ``0864``\ + - | ``not_a_template``\ : + | *xxxx*\ is not a template + * - ``0865``\ + - | ``friend_partial_specialization``\ : + | a friend declaration may not declare a partial specialization + * - ``0866``\ + - | ``exception_specification_ignored``\ : + | exception specification ignored + * - ``0867``\ + - | ``unexpected_type_for_size_t``\ : + | declaration of "size_t" does not match the expected type *"type"*\ + * - ``0868``\ + - | ``exp_gt_not_shift_right``\ : + | space required between adjacent ">" delimiters of nested template + argument lists (">>" is the right shift operator) + * - ``0869``\ + - | ``bad_multibyte_char_locale``\ : + | could not set locale *"xxxx"*\ to allow processing of multibyte + characters + * - ``0870``\ + - | ``bad_multibyte_char``\ : + | invalid multibyte character sequence + * - ``0871``\ + - | ``bad_type_from_instantiation``\ : + | template instantiation resulted in unexpected function type of + *"type"*\ (the meaning of a name may have changed since the template + declaration -- the type of the template is *"type"*\ ) + * - ``0872``\ + - | ``ambiguous_guiding_decl``\ : + | ambiguous guiding declaration -- more than one function template + *"entity"*\ matches type *"type"*\ + * - ``0873``\ + - | ``non_integral_operation_in_templ_arg``\ : + | non-integral operation not allowed in nontype template argument + * - ``0874``\ + - | ``cl_embedded_cplusplus_option_only_in_cplusplus``\ : + | option "embedded_c++" can be used only when compiling C++ + * - ``0875``\ + - | ``templates_in_embedded_cplusplus``\ : + | Embedded C++ does not support templates + * - ``0876``\ + - | ``exceptions_in_embedded_cplusplus``\ : + | Embedded C++ does not support exception handling + * - ``0877``\ + - | ``namespaces_in_embedded_cplusplus``\ : + | Embedded C++ does not support namespaces + * - ``0878``\ + - | ``rtti_in_embedded_cplusplus``\ : + | Embedded C++ does not support run-time type information + * - ``0879``\ + - | ``new_cast_in_embedded_cplusplus``\ : + | Embedded C++ does not support the new cast syntax + * - ``0880``\ + - | ``using_decl_in_embedded_cplusplus``\ : + | Embedded C++ does not support using-declarations + * - ``0881``\ + - | ``mutable_in_embedded_cplusplus``\ : + | Embedded C++ does not support "mutable" + * - ``0882``\ + - | ``multiple_inheritance_in_embedded_cplusplus``\ : + | Embedded C++ does not support multiple or virtual inheritance + * - ``0883``\ + - | ``cl_invalid_microsoft_version``\ : + | invalid Microsoft version number: *xxxx*\ + * - ``0884``\ + - | ``inheritance_kind_already_set``\ : + | pointer-to-member representation *"xxxx"*\ has already been set for + *entity-kind "entity"*\ + * - ``0885``\ + - | ``bad_constructor_type``\ : + | *"type"*\ cannot be used to designate constructor for *"type"*\ + * - ``0886``\ + - | ``bad_suffix``\ : + | invalid suffix on integral constant + * - ``0887``\ + - | ``uuidof_requires_uuid_class_type``\ : + | operand of \__uuidof must have a class or enum type for which + \__declspec(uuid("...")) has been specified + * - ``0888``\ + - | ``bad_uuid_string``\ : + | invalid GUID string in \__declspec(uuid("...")) + * - ``0889``\ + - | ``cl_vla_option_only_in_C``\ : + | option "vla" can be used only when compiling C + * - ``0890``\ + - | ``vla_with_unspecified_bound_not_allowed``\ : + | variable length array with unspecified bound is not allowed + * - ``0891``\ + - | ``explicit_template_args_not_allowed``\ : + | an explicit template argument list is not allowed on this declaration + * - ``0892``\ + - | ``variably_modified_type_not_allowed``\ : + | an entity with linkage cannot have a type involving a variable length + array + * - ``0893``\ + - | ``vla_is_not_auto``\ : + | a variable length array cannot have static storage duration + * - ``0894``\ + - | ``sym_not_a_template``\ : + | *entity-kind "entity"*\ is not a template + * - ``0896``\ + - | ``expected_template_arg``\ : + | expected a template argument + * - ``0898``\ + - | ``no_params_with_class_or_enum_type``\ : + | nonmember operator requires a parameter with class or enum type + * - ``0899``\ + - | ``cl_enum_overloading_option_only_in_cplusplus``\ : + | option "enum_overloading" can be used only when compiling C++ + * - ``0901``\ + - | ``destructor_qualifier_type_mismatch``\ : + | qualifier of destructor name *"type"*\ does not match type *"type"*\ + * - ``0902``\ + - | ``type_qualifier_ignored``\ : + | type qualifier ignored + * - ``0903``\ + - | ``cl_nonstandard_qualifier_deduction_option_only_in_cplusplus``\ : + | option "nonstd_qualifier_deduction" can be used only when compiling + C++ + * - ``0904``\ + - | ``cannot_define_dllimport_function``\ : + | a function declared "dllimport" may not be defined + * - ``0905``\ + - | ``bad_declspec_property``\ : + | incorrect property specification; correct form is + \__declspec(property(get=name1,put=name2)) + * - ``0906``\ + - | ``dupl_get_or_put``\ : + | property has already been specified + * - ``0907``\ + - | ``declspec_property_not_allowed``\ : + | __declspec(property) is not allowed on this declaration + * - ``0908``\ + - | ``no_get_property``\ : + | member is declared with \__declspec(property), but no "get" function + was specified + * - ``0909``\ + - | ``get_property_function_missing``\ : + | the \__declspec(property) "get" function *"xxxx"*\ is missing + * - ``0910``\ + - | ``no_put_property``\ : + | member is declared with \__declspec(property), but no "put" function + was specified + * - ``0911``\ + - | ``put_property_function_missing``\ : + | the \__declspec(property) "put" function *"xxxx"*\ is missing + * - ``0912``\ + - | ``dual_lookup_ambiguous_name``\ : + | ambiguous class member reference -- *entity-kind "entity"*\ + (declared at line *xxxx*\ ) used in preference to *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``0916``\ + - | ``pm_virtual_base_from_derived_class``\ : + | cannot convert pointer to member of derived class *"type"*\ to + pointer to member of base class *"type"*\ -- base class is virtual + * - ``0917``\ + - | ``cl_invalid_instantiation_directory``\ : + | invalid directory for instantiation files: *xxxx*\ + * - ``0918``\ + - | ``cl_one_instantiation_per_object_option_only_in_cplusplus``\ : + | option "one_instantiation_per_object" can be used only when compiling + C++ + * - ``0921``\ + - | ``cl_ii_file_name_incompatible_with_multiple_inputs``\ : + | an instantiation information file name may not be specified when + compiling several input files + * - ``0922``\ + - | ``cl_one_instantiation_per_object_incompatible_with_multiple_inputs``\ + : + | option "one_instantiation_per_object" may not be used when compiling + several input files + * - ``0923``\ + - | ``cl_ambiguous_option``\ : + | more than one command line option matches the abbreviation + "--*xxxx*\ ": + * - ``0925``\ + - | ``cv_qualified_function_type``\ : + | type qualifiers on function types are ignored + * - ``0927``\ + - | ``cl_late_tiebreaker_option_only_in_cplusplus``\ : + | late/early tiebreaker option can be used only when compiling C++ + * - ``0928``\ + - | ``bad_va_start``\ : + | incorrect use of va_start + * - ``0929``\ + - | ``bad_va_arg``\ : + | incorrect use of va_arg + * - ``0930``\ + - | ``bad_va_end``\ : + | incorrect use of va_end + * - ``0931``\ + - | ``cl_pending_instantiations_option_only_in_cplusplus``\ : + | pending instantiations option can be used only when compiling C++ + * - ``0932``\ + - | ``cl_invalid_import_directory``\ : + | invalid directory for #import files: *xxxx*\ + * - ``0933``\ + - | ``cl_import_only_in_microsoft``\ : + | an import directory can be specified only in Microsoft mode + * - ``0934``\ + - | ``ref_not_allowed_in_union``\ : + | a member with reference type is not allowed in a union + * - ``0935``\ + - | ``typedef_not_allowed``\ : + | "typedef" may not be specified here + * - ``0936``\ + - | ``redecl_changes_access``\ : + | redeclaration of *entity-kind "entity"*\ alters its access + * - ``0937``\ + - | ``qualified_name_required``\ : + | a class or namespace qualified name is required + * - ``0938``\ + - | ``implicit_int_on_main``\ : + | return type "int" omitted in declaration of function "main" + * - ``0939``\ + - | ``invalid_inheritance_kind_for_class``\ : + | pointer-to-member representation *"xxxx"*\ is too restrictive for + *entity-kind "entity"*\ + * - ``0940``\ + - | ``implicit_return_from_non_void_function``\ : + | missing return statement at end of non-void *entity-kind "entity"*\ + * - ``0941``\ + - | ``duplicate_using_decl``\ : + | duplicate using-declaration of *"entity"*\ ignored + * - ``0942``\ + - | ``unsigned_enum_bit_field_with_signed_enumerator``\ : + | enum bit fields are always unsigned, but enum *"type"*\ includes + negative enumerator + * - ``0943``\ + - | ``cl_class_name_injection_option_only_in_cplusplus``\ : + | option "class_name_injection" can be used only when compiling C++ + * - ``0944``\ + - | ``cl_arg_dependent_lookup_option_only_in_cplusplus``\ : + | option "arg_dep_lookup" can be used only when compiling C++ + * - ``0945``\ + - | ``cl_friend_injection_option_only_in_cplusplus``\ : + | option "friend_injection" can be used only when compiling C++ + * - ``0946``\ + - | ``invalid_name_after_template``\ : + | name following "template" must be a template + * - ``0948``\ + - | ``local_class_friend_requires_prior_decl``\ : + | nonstandard local-class friend declaration -- no prior declaration in + the enclosing scope + * - ``0949``\ + - | ``nonstd_default_arg``\ : + | specifying a default argument on this declaration is nonstandard + * - ``0950``\ + - | ``cl_nonstd_using_decl_option_only_in_cplusplus``\ : + | option "nonstd_using_decl" can be used only when compiling C++ + * - ``0951``\ + - | ``bad_return_type_on_main``\ : + | return type of function "main" must be "int" + * - ``0952``\ + - | ``template_parameter_has_class_type``\ : + | a nontype template parameter may not have class type + * - ``0953``\ + - | ``default_arg_on_member_decl``\ : + | a default template argument cannot be specified on the definition of + a member of a class template outside the template + * - ``0954``\ + - | ``return_from_ctor_function_try_block_handler``\ : + | a return statement is not allowed in a handler of a function try + block of a constructor + * - ``0955``\ + - | ``no_ordinary_and_extended_designators``\ : + | ordinary and extended designators cannot be combined in an + initializer designation + * - ``0956``\ + - | ``no_negative_designator_range``\ : + | the second subscript must not be smaller than the first + * - ``0958``\ + - | ``cl_extended_designators_option_only_in_C``\ : + | option "extended_designators" can be used only when compiling C + * - ``0959``\ + - | ``extra_bits_ignored``\ : + | declared size for bit field is larger than the size of the bit field + type; truncated to *xxxx*\ bits + * - ``0960``\ + - | ``constructor_type_mismatch``\ : + | type used as constructor name does not match type *"type"*\ + * - ``0961``\ + - | ``type_with_no_linkage_in_var_with_linkage``\ : + | use of a type with no linkage to declare a variable with linkage + * - ``0962``\ + - | ``type_with_no_linkage_in_function``\ : + | use of a type with no linkage to declare a function + * - ``0963``\ + - | ``return_type_on_constructor``\ : + | return type may not be specified on a constructor + * - ``0964``\ + - | ``return_type_on_destructor``\ : + | return type may not be specified on a destructor + * - ``0965``\ + - | ``malformed_universal_character``\ : + | incorrectly formed universal character name + * - ``0966``\ + - | ``invalid_UCN``\ : + | universal character name specifies an invalid character + * - ``0967``\ + - | ``UCN_names_basic_char``\ : + | a universal character name cannot designate a character in the basic + character set + * - ``0968``\ + - | ``invalid_identifier_UCN``\ : + | this universal character is not allowed in an identifier + * - ``0969``\ + - | ``VA_ARGS_not_allowed``\ : + | the identifier \__VA_ARGS\__ can only appear in the replacement lists + of variadic macros + * - ``0970``\ + - | ``friend_qualification_ignored``\ : + | the qualifier on this friend declaration is ignored + * - ``0971``\ + - | ``no_range_designator_with_dynamic_init``\ : + | array range designators cannot be applied to dynamic initializers + * - ``0972``\ + - | ``property_name_not_allowed``\ : + | property name cannot appear here + * - ``0973``\ + - | ``inline_qualifier_ignored``\ : + | "inline" used as a function qualifier is ignored + * - ``0974``\ + - | ``cl_compound_literals_option_only_in_C``\ : + | option "compound_literals" can be used only when compiling C + * - ``0975``\ + - | ``vla_not_allowed``\ : + | a variable-length array type is not allowed + * - ``0976``\ + - | ``bad_integral_compound_literal``\ : + | a compound literal is not allowed in an integral constant expression + * - ``0977``\ + - | ``bad_compound_literal_type``\ : + | a compound literal of type *"type"*\ is not allowed + * - ``0978``\ + - | ``friend_template_in_local_class``\ : + | a template friend declaration cannot be declared in a local class + * - ``0979``\ + - | ``ambiguous_question_operator``\ : + | ambiguous "?" operation: second operand of type *"type"*\ can be + converted to third operand type *"type"*\ , and vice versa + * - ``0980``\ + - | ``bad_call_of_class_object``\ : + | call of an object of a class type without appropriate operator() or + conversion functions to pointer-to-function type + * - ``0982``\ + - | ``ambiguous_class_call``\ : + | there is more than one way an object of type *"type"*\ can be called + for the argument list: + * - ``0983``\ + - | ``similar_typedef``\ : + | typedef name has already been declared (with similar type) + * - ``0984``\ + - | ``no_internal_linkage_for_new_or_delete``\ : + | operator new and operator delete cannot be given internal linkage + * - ``0985``\ + - | ``no_mutable_allowed_on_anonymous_union``\ : + | storage class "mutable" is not allowed for anonymous unions + * - ``0986``\ + - | ``bad_pch_file``\ : + | invalid precompiled header file + * - ``0987``\ + - | ``abstract_class_catch_type``\ : + | abstract class type *"type"*\ is not allowed as catch type: + * - ``0988``\ + - | ``bad_qualified_function_type``\ : + | a qualified function type cannot be used to declare a nonmember + function or a static member function + * - ``0989``\ + - | ``bad_qualified_function_type_parameter``\ : + | a qualified function type cannot be used to declare a parameter + * - ``0990``\ + - | ``ptr_or_ref_to_qualified_function_type``\ : + | cannot create a pointer or reference to qualified function type + * - ``0991``\ + - | ``nonstd_braces``\ : + | extra braces are nonstandard + * - ``0992``\ + - | ``bad_cmd_line_macro``\ : + | invalid macro definition: *xxxx*\ + * - ``0993``\ + - | ``nonstandard_ptr_minus_ptr``\ : + | subtraction of pointer types *"type"*\ and *"type"*\ is nonstandard + * - ``0994``\ + - | ``empty_template_param_list``\ : + | an empty template parameter list is not allowed in a template + template parameter declaration + * - ``0995``\ + - | ``exp_class``\ : + | expected "class" + * - ``0996``\ + - | ``struct_not_allowed``\ : + | the "struct" keyword may not be used when declaring a template + template parameter + * - ``0997``\ + - | ``virtual_function_decl_hidden``\ : + | *entity-kind "entity"*\ is hidden by *"entity"*\ -- virtual + function override intended? + * - ``0998``\ + - | ``no_qualified_friend_definition``\ : + | a qualified name is not allowed for a friend declaration that is a + function definition + * - ``0999``\ + - | ``not_compatible_with_templ_templ_param``\ : + | *entity-kind "entity"*\ is not compatible with *entity-kind + "entity"*\ + * - ``1000``\ + - | ``storage_class_requires_function_or_variable``\ : + | a storage class may not be specified here + * - ``1001``\ + - | ``member_using_must_be_visible_in_direct_base``\ : + | class member designated by a using-declaration must be visible in a + direct base class + * - ``1003``\ + - | ``cl_sun_incompatible_with_cfront``\ : + | Sun mode is incompatible with cfront mode + * - ``1004``\ + - | ``cl_strict_mode_incompatible_with_sun``\ : + | strict mode is incompatible with Sun mode + * - ``1005``\ + - | ``cl_sun_mode_only_in_cplusplus``\ : + | Sun mode is only allowed when compiling C++ + * - ``1006``\ + - | ``template_template_param_same_name_as_templ_param``\ : + | a template template parameter cannot have the same name as one of its + template parameters + * - ``1007``\ + - | ``recursive_def_arg_instantiation``\ : + | recursive instantiation of default argument + * - ``1009``\ + - | ``bad_template_name``\ : + | *entity-kind "entity"*\ is not an entity that can be defined + * - ``1010``\ + - | ``destructor_name_must_be_qualified``\ : + | destructor name must be qualified + * - ``1011``\ + - | ``no_typename_in_friend_class_decl``\ : + | friend class name may not be introduced with "typename" + * - ``1012``\ + - | ``no_ctor_or_dtor_using_declaration``\ : + | a using-declaration may not name a constructor or destructor + * - ``1013``\ + - | ``friend_is_nonreal_template``\ : + | a qualified friend template declaration must refer to a specific + previously declared template + * - ``1014``\ + - | ``bad_class_template_decl``\ : + | invalid specifier in class template declaration + * - ``1015``\ + - | ``simple_incompatible_param``\ : + | argument is incompatible with formal parameter + * - ``1016``\ + - | ``cl_dep_name_option_only_in_cplusplus``\ : + | option "dep_name" can be used only when compiling C++ + * - ``1017``\ + - | ``op_arrow_loop``\ : + | loop in sequence of "operator->" functions starting at class + *"type"*\ + * - ``1018``\ + - | ``not_a_member_class``\ : + | *entity-kind "entity"*\ has no member class *"xxxx"*\ + * - ``1019``\ + - | ``name_not_class_in_file_scope``\ : + | the global scope has no class named *"xxxx"*\ + * - ``1020``\ + - | ``recursive_inst_of_templ_default_arg``\ : + | recursive instantiation of template default argument + * - ``1021``\ + - | ``no_access_or_using_decl_in_union``\ : + | access declarations and using-declarations cannot appear in unions + * - ``1022``\ + - | ``not_class_member``\ : + | *"entity"*\ is not a class member + * - ``1023``\ + - | ``nonstd_const_member_decl_not_allowed``\ : + | nonstandard member constant declaration is not allowed + * - ``1024``\ + - | ``cl_ignore_std_option_only_in_cplusplus``\ : + | option "ignore_std" can be used only when compiling C++ + * - ``1025``\ + - | ``cl_parse_nonclass_templates_option_only_in_cplusplus``\ : + | option "parse_templates" can be used only when compiling C++ + * - ``1026``\ + - | ``cl_dep_name_requires_parse_nonclass_templates``\ : + | option "dep_name" cannot be used with "no_parse_templates" + * - ``1027``\ + - | ``cl_incompatible_language_modes``\ : + | language modes specified are incompatible + * - ``1028``\ + - | ``invalid_nested_class_redecl``\ : + | invalid redeclaration of nested class + * - ``1029``\ + - | ``flexible_array_member_not_allowed``\ : + | type containing an unknown-size array is not allowed + * - ``1030``\ + - | ``static_variable_in_inline_function``\ : + | a variable with static storage duration cannot be defined within an + inline function + * - ``1031``\ + - | ``bad_linkage_of_ref_within_inline_function``\ : + | an entity with internal linkage cannot be referenced within an inline + function with external linkage + * - ``1032``\ + - | ``type_generic_function_mismatch``\ : + | argument type *"type"*\ does not match this type-generic function + macro + * - ``1034``\ + - | ``friend_cannot_add_default_arguments``\ : + | friend declaration cannot add default arguments to previous + declaration + * - ``1035``\ + - | ``cannot_be_declared_in_scope``\ : + | *entity-kind "entity"*\ cannot be declared in this scope + * - ``1036``\ + - | ``id_can_only_appear_in_function``\ : + | the reserved identifier *"xxxx"*\ may only be used inside a function + * - ``1037``\ + - | ``invalid_identifier_start_UCN``\ : + | this universal character cannot begin an identifier + * - ``1038``\ + - | ``exp_string_literal``\ : + | expected a string literal + * - ``1039``\ + - | ``unrecognized_stdc_pragma``\ : + | unrecognized STDC pragma + * - ``1040``\ + - | ``bad_stdc_pragma_arg``\ : + | expected "ON", "OFF", or "DEFAULT" + * - ``1041``\ + - | ``stdc_pragma_not_allowed_here``\ : + | a STDC pragma may only appear between declarations in the global + scope or before any statements or declarations in a block scope + * - ``1042``\ + - | ``bad_va_copy``\ : + | incorrect use of va_copy + * - ``1043``\ + - | ``only_applies_to_float_types``\ : + | *xxxx*\ can only be used with floating-point types + * - ``1044``\ + - | ``complex_type_not_allowed``\ : + | complex type is not allowed + * - ``1045``\ + - | ``invalid_designator_kind``\ : + | invalid designator kind + * - ``1046``\ + - | ``inexact_fp_conversion``\ : + | floating-point value cannot be represented exactly + * - ``1047``\ + - | ``bad_complex_operation_result``\ : + | complex floating-point operation result is out of range + * - ``1048``\ + - | ``real_imaginary_conversion``\ : + | conversion between real and imaginary yields zero + * - ``1049``\ + - | ``cannot_initialize_flexible_array_member``\ : + | an initializer cannot be specified for a flexible array member + * - ``1050``\ + - | ``imaginary_times_assign``\ : + | imaginary \*= imaginary sets the left-hand operand to zero + * - ``1051``\ + - | ``undeclared_parameter``\ : + | standard requires that *entity-kind "entity"*\ be given a type by a + subsequent declaration ("int" assumed) + * - ``1052``\ + - | ``inline_never_defined``\ : + | a definition is required for inline *entity-kind "entity"*\ + * - ``1053``\ + - | ``conversion_to_pointer_loses_bits``\ : + | conversion from integer to smaller pointer + * - ``1054``\ + - | ``missing_floating_point_type``\ : + | a floating-point type must be included in the type specifier for a + _Complex or _Imaginary type + * - ``1055``\ + - | ``type_decl_in_anon_union``\ : + | types cannot be declared in anonymous unions + * - ``1056``\ + - | ``returning_ptr_to_local_variable``\ : + | returning pointer to local variable + * - ``1057``\ + - | ``returning_ptr_to_local_temp``\ : + | returning pointer to local temporary + * - ``1058``\ + - | ``cl_export_template_option_only_in_cplusplus``\ : + | option "export" can be used only when compiling C++ + * - ``1059``\ + - | ``cl_export_template_requires_dep_name``\ : + | option "export" cannot be used with "no_dep_name" + * - ``1060``\ + - | ``cl_export_template_requires_no_implicit_include``\ : + | option "export" cannot be used with "implicit_include" + * - ``1061``\ + - | ``corresp_decl_incompatible``\ : + | declaration of *entity-kind "entity"*\ is incompatible with a + declaration in another translation unit + * - ``1062``\ + - | ``corresp_decl_at``\ : + | the other declaration is at line *xxxx*\ + * - ``1065``\ + - | ``field_cannot_involve_vla_type``\ : + | a field declaration cannot have a type involving a variable length + array + * - ``1066``\ + - | ``entity_differs_in_other_trans_unit``\ : + | declaration of *entity-kind "entity"*\ had a different meaning + during compilation of *"xxxx"*\ + * - ``1067``\ + - | ``exp_template``\ : + | expected "template" + * - ``1068``\ + - | ``export_on_instantiation``\ : + | "export" cannot be used on an explicit instantiation + * - ``1069``\ + - | ``bad_decl_for_export``\ : + | "export" cannot be used on this declaration + * - ``1070``\ + - | ``exported_in_unnamed_namespace``\ : + | a member of an unnamed namespace cannot be declared "export" + * - ``1071``\ + - | ``export_after_definition``\ : + | a template cannot be declared "export" after it has been defined + * - ``1072``\ + - | ``labeled_declaration``\ : + | a declaration cannot have a label + * - ``1073``\ + - | ``no_export_support``\ : + | support for exported templates is disabled + * - ``1075``\ + - | ``entity_defined_in_other_trans_unit``\ : + | *entity-kind "entity"*\ already defined during compilation of + *"xxxx"*\ + * - ``1076``\ + - | ``entity_defined_twice``\ : + | *entity-kind "entity"*\ already defined in another translation unit + * - ``1077``\ + - | ``based_var_cannot_be_local``\ : + | a nonstatic local variable may not be used in a \__based specification + * - ``1078``\ + - | ``cl_list_make_dependencies_incompatible_with_multiple_trans_units``\ + : + | the option to list makefile dependencies may not be specified when + compiling more than one translation unit + * - ``1080``\ + - | ``cl_pp_output_incompatible_with_multiple_trans_units``\ : + | the option to generate preprocessed output may not be specified when + compiling more than one translation unit + * - ``1081``\ + - | ``field_name_conflicts_with_class``\ : + | a field with the same name as its class cannot be declared in a class + with a user-declared constructor + * - ``1082``\ + - | ``cl_implicit_include_incompatible_with_multiple_trans_units``\ : + | "implicit_include" cannot be used when compiling more than one + translation unit + * - ``1083``\ + - | ``corrupted_export_template_file``\ : + | exported template file *"xxxx"*\ is corrupted + * - ``1084``\ + - | ``exported_instantiation_and_specialized``\ : + | *entity-kind "entity"*\ cannot be instantiated -- it has been + explicitly specialized in the translation unit containing the + exported definition + * - ``1086``\ + - | ``unqual_named_function_with_qual_object``\ : + | the object has type qualifiers that are not compatible with the + member *entity-kind "entity"*\ + * - ``1087``\ + - | ``no_matching_function_due_to_selector``\ : + | no instance of *entity-kind "entity"*\ matches the argument list and + object (the object has type qualifiers that prevent a match) + * - ``1088``\ + - | ``mode_incompatible_with_type``\ : + | an attribute specifies a mode incompatible with *"type"*\ + * - ``1089``\ + - | ``no_type_of_specified_width``\ : + | there is no type with the width specified + * - ``1090``\ + - | ``bad_attribute_alignment``\ : + | invalid alignment value specified by attribute + * - ``1091``\ + - | ``attribute_does_not_apply_to_type``\ : + | invalid attribute for *"type"*\ + * - ``1094``\ + - | ``arguments_provided_for_attribute``\ : + | attribute *"xxxx"*\ does not take arguments + * - ``1096``\ + - | ``exp_attribute_name``\ : + | expected an attribute name + * - ``1097``\ + - | ``unrecognized_attribute``\ : + | unknown attribute *"xxxx"*\ + * - ``1098``\ + - | ``attribute_not_allowed``\ : + | attributes may not appear here + * - ``1099``\ + - | ``invalid_argument_to_attribute``\ : + | invalid argument to attribute *"xxxx"*\ + * - ``1101``\ + - | ``assigned_goto_requires_void_ptr``\ : + | in "goto \*expr", expr must have type "void \*" + * - ``1102``\ + - | ``nonstd_assigned_goto``\ : + | "goto \*expr" is nonstandard + * - ``1103``\ + - | ``nonstd_address_of_label``\ : + | taking the address of a label is nonstandard + * - ``1104``\ + - | ``cl_duplicate_file_name``\ : + | file name specified more than once: *xxxx*\ + * - ``1105``\ + - | ``warning_directive``\ : + | #warning directive: *xxxx*\ + * - ``1107``\ + - | ``transparent_type_is_not_union``\ : + | the "transparent_union" attribute only applies to unions, and + *"type"*\ is not a union + * - ``1108``\ + - | ``transparent_attribute_ignored``\ : + | the "transparent_union" attribute is ignored on incomplete types + * - ``1109``\ + - | ``union_cannot_be_transparent_sym``\ : + | *"type"*\ cannot be transparent because *entity-kind "entity"*\ + does not have the same size as the first field + * - ``1110``\ + - | ``union_cannot_be_transparent``\ : + | *"type"*\ cannot be transparent because it has a field of type + *"type"*\ which is not the same size as the first field + * - ``1112``\ + - | ``attribute_does_not_apply_to_local_variable``\ : + | attribute *"xxxx"*\ does not apply to local variables + * - ``1113``\ + - | ``attributes_in_rout_defn``\ : + | attributes are not permitted in a function definition + * - ``1115``\ + - | ``invalid_case_range``\ : + | the second constant in a case range must be larger than the first + * - ``1116``\ + - | ``asm_name_in_rout_defn``\ : + | an asm name is not permitted in a function definition + * - ``1117``\ + - | ``asm_name_in_typedef``\ : + | an asm name is ignored in a typedef + * - ``1118``\ + - | ``bad_reg_name``\ : + | unknown register name "*xxxx*\ " + * - ``1120``\ + - | ``bad_asm_constraint_modifier``\ : + | unknown asm constraint modifier '*xxxx*\ ' + * - ``1121``\ + - | ``bad_asm_constraint_letter``\ : + | unknown asm constraint letter '*xxxx*\ ' + * - ``1122``\ + - | ``missing_constraint_letter``\ : + | asm operand has no constraint letter + * - ``1123``\ + - | ``asm_output_must_have_output_mod``\ : + | an asm output operand must have one of the '=' or '+' modifiers + * - ``1124``\ + - | ``asm_input_must_not_have_output_mod``\ : + | an asm input operand may not have the '=' or '+' modifiers + * - ``1127``\ + - | ``register_used_twice``\ : + | register "*xxxx*\ " used more than once + * - ``1128``\ + - | ``register_used_and_clobbered``\ : + | register "*xxxx*\ " is both used and clobbered + * - ``1129``\ + - | ``register_clobbered_twice``\ : + | register "*xxxx*\ " clobbered more than once + * - ``1130``\ + - | ``fixed_register_used``\ : + | register "*xxxx*\ " has a fixed purpose and may not be used in an asm + statement + * - ``1131``\ + - | ``fixed_register_clobbered``\ : + | register "*xxxx*\ " has a fixed purpose and may not be clobbered in + an asm statement + * - ``1132``\ + - | ``empty_clobbers_list``\ : + | an empty clobbers list must be omitted entirely + * - ``1133``\ + - | ``exp_asm_operand``\ : + | expected an asm operand + * - ``1134``\ + - | ``exp_asm_clobber``\ : + | expected a register to clobber + * - ``1135``\ + - | ``format_rout_not_varargs``\ : + | "format" attribute requires an ellipsis parameter or parameter pack + * - ``1136``\ + - | ``subst_arg_is_not_variable``\ : + | first substitution argument is not the first variable argument + * - ``1137``\ + - | ``fmt_arg_does_not_exist``\ : + | format argument index is greater than number of parameters + * - ``1138``\ + - | ``fmt_arg_is_not_string``\ : + | format argument does not have string type + * - ``1139``\ + - | ``template_not_in_template``\ : + | the "template" keyword used for syntactic disambiguation may only be + used within a template + * - ``1142``\ + - | ``attr_requires_func_type``\ : + | attribute *"xxxx"*\ does not apply to non-function type *"type"*\ + * - ``1143``\ + - | ``nonobject_pointer_arithmetic``\ : + | arithmetic on pointer to void or function type + * - ``1144``\ + - | ``invalid_storage_class_in_for_init``\ : + | storage class must be auto or register + * - ``1145``\ + - | ``va_arg_would_have_been_promoted``\ : + | *"type"*\ would have been promoted to *"type"*\ when passed through + the ellipsis parameter; use the latter type instead + * - ``1146``\ + - | ``not_a_base_class_member``\ : + | *"xxxx"*\ is not a base class member + * - ``1147``\ + - | ``super_after_scope``\ : + | __super cannot appear after "::" + * - ``1148``\ + - | ``super_not_in_class``\ : + | __super may only be used in a class scope + * - ``1149``\ + - | ``unqualified_super``\ : + | __super must be followed by "::" + * - ``1151``\ + - | ``mangled_name_too_long``\ : + | mangled name is too long + * - ``1152``\ + - | ``aliased_name_undeclared``\ : + | declaration aliased to undefined entity *"xxxx"*\ + * - ``1153``\ + - | ``aliased_name_bad_kind``\ : + | declaration does not match its alias *entity-kind "entity"*\ + * - ``1154``\ + - | ``alias_cannot_have_definition``\ : + | entity declared as alias cannot have definition + * - ``1155``\ + - | ``vla_size_ignored``\ : + | variable-length array field type will be treated as zero-length array + field type + * - ``1156``\ + - | ``gcc_lvalue_cast_ignored``\ : + | nonstandard cast on lvalue ignored + * - ``1157``\ + - | ``cl_invalid_flag_name``\ : + | unrecognized flag name: *xxxx*\ + * - ``1158``\ + - | ``qualified_void_return_type``\ : + | void return type cannot be qualified + * - ``1159``\ + - | ``auto_ignored``\ : + | the auto specifier is ignored here (invalid in standard C/C++) + * - ``1160``\ + - | ``alignment_reduction_ignored``\ : + | a reduction in alignment without the "packed" attribute is ignored + * - ``1161``\ + - | ``corresp_member_template_is_different_kind``\ : + | a member template corresponding to *"entity"*\ is declared as a + template of a different kind in another translation unit + * - ``1162``\ + - | ``excess_initializers_ignored``\ : + | excess initializers are ignored + * - ``1163``\ + - | ``va_start_requires_ellipsis_function``\ : + | va_start can appear only in a function with an ellipsis parameter + * - ``1164``\ + - | ``cl_short_enums_requires_gcc_mode``\ : + | the "short_enums" option is only valid in GNU C and GNU C++ modes + * - ``1165``\ + - | ``bad_export_info_file``\ : + | invalid export information file *"xxxx"*\ at line number *xxxx*\ + * - ``1166``\ + - | ``statement_expression_in_function_only``\ : + | statement expressions are only allowed in block scope + * - ``1168``\ + - | ``asm_name_on_auto_variable``\ : + | an asm name is ignored on a non-register automatic variable + * - ``1170``\ + - | ``unrecognized_upc_pragma``\ : + | unrecognized UPC pragma + * - ``1171``\ + - | ``mismatched_shared_block_size``\ : + | shared block size does not match one previously specified + * - ``1172``\ + - | ``ambiguous_block_size_spec``\ : + | bracketed expression is assumed to be a block size specification + rather than an array dimension + * - ``1173``\ + - | ``shared_block_size_must_be_positive``\ : + | the block size of a shared array must be greater than zero + * - ``1174``\ + - | ``multiple_block_sizes``\ : + | multiple block sizes not allowed + * - ``1175``\ + - | ``nonshared_strict_relaxed``\ : + | strict or relaxed requires shared + * - ``1176``\ + - | ``threads_constant_not_allowed``\ : + | THREADS not allowed in this context + * - ``1177``\ + - | ``shared_block_size_too_large``\ : + | block size specified exceeds the maximum value of *xxxx*\ + * - ``1178``\ + - | ``function_returning_shared``\ : + | function returning shared is not allowed + * - ``1180``\ + - | ``shared_nonthreads_dim``\ : + | one dimension of an array of a shared type must be a multiple of + THREADS when the number of threads is nonconstant + * - ``1181``\ + - | ``shared_inside_struct``\ : + | shared type inside a struct or union is not allowed + * - ``1182``\ + - | ``shared_parameter``\ : + | parameters may not have shared types + * - ``1183``\ + - | ``threads_dimension_requires_definite_block_size``\ : + | a dynamic THREADS dimension requires a definite block size + * - ``1184``\ + - | ``bad_shared_storage_class``\ : + | shared variables must be static or extern + * - ``1185``\ + - | ``nonshared_blocksizeof``\ : + | argument of upc_blocksizeof is a pointer to a shared type (not shared + type itself) + * - ``1186``\ + - | ``nested_upc_forall``\ : + | affinity expression ignored in nested upc_forall + * - ``1187``\ + - | ``exit_forall``\ : + | branching into or out of a upc_forall loop is not allowed + * - ``1188``\ + - | ``bad_affinity``\ : + | affinity expression must have a shared type or point to a shared type + * - ``1189``\ + - | ``shared_affinity_type``\ : + | affinity has shared type (not pointer to shared) + * - ``1190``\ + - | ``upc_shared_void_comparison``\ : + | shared void\* types can only be compared for equality + * - ``1191``\ + - | ``cl_upc_requires_ansi_c_dialect``\ : + | UPC mode is incompatible with C++ and K&R modes + * - ``1192``\ + - | ``null_char_ignored``\ : + | null (zero) character in input line ignored + * - ``1193``\ + - | ``null_char_in_string``\ : + | null (zero) character in string or character constant + * - ``1194``\ + - | ``null_char_in_header_name``\ : + | null (zero) character in header name + * - ``1195``\ + - | ``for_init_hides_declaration``\ : + | declaration in for-initializer hides a declaration in the surrounding + scope + * - ``1196``\ + - | ``for_init_hidden_declaration``\ : + | the hidden declaration is at line *xxxx*\ + * - ``1197``\ + - | ``prototype_lost``\ : + | the prototype declaration of *entity-kind "entity"*\ (declared at + line *xxxx*\ ) is ignored after this unprototyped redeclaration + * - ``1199``\ + - | ``bad_linkage_for_redefine_extname``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) must have + external C linkage + * - ``1200``\ + - | ``declaration_hides_for_init``\ : + | variable declaration hides declaration in for-initializer + * - ``1201``\ + - | ``typedef_in_elab_type``\ : + | typedef *"xxxx"*\ may not be used in an elaborated type specifier + * - ``1202``\ + - | ``call_of_zero``\ : + | call of zero constant ignored + * - ``1203``\ + - | ``handler_redeclares_parameter``\ : + | parameter *"xxxx"*\ may not be redeclared in a catch clause of + function try block + * - ``1204``\ + - | ``specialization_out_of_namespace``\ : + | the initial explicit specialization of *entity-kind "entity"*\ must + be declared in the namespace containing the template + * - ``1205``\ + - | ``cc_clobber_ignored``\ : + | "cc" clobber ignored + * - ``1206``\ + - | ``invalid_token_after_template``\ : + | "template" must be followed by an identifier + * - ``1207``\ + - | ``mythread_constant_not_allowed``\ : + | MYTHREAD not allowed in this context + * - ``1208``\ + - | ``bad_upc_shared_pointer_layout_qualifier``\ : + | layout qualifier cannot qualify pointer to shared + * - ``1209``\ + - | ``bad_upc_shared_array_layout_qualifier``\ : + | layout qualifier cannot qualify an incomplete array + * - ``1210``\ + - | ``decl_hides_catch_parameter``\ : + | declaration of *"xxxx"*\ hides handler parameter + * - ``1211``\ + - | ``nonstd_ignored_array_cast``\ : + | nonstandard cast to array type ignored + * - ``1212``\ + - | ``invalid_pragma_operator``\ : + | this pragma cannot be used in a _Pragma operator (a #pragma directive + must be used) + * - ``1213``\ + - | ``field_uses_tail_padding``\ : + | field uses tail padding of a base class + * - ``1214``\ + - | ``gnu_may_use_bit_padding``\ : + | GNU C++ compilers may use bit field padding + * - ``1215``\ + - | ``deprecated_entity``\ : + | *entity-kind "entity"*\ was declared deprecated + * - ``1216``\ + - | ``field_with_asm_name_not_allowed``\ : + | an asm name is not allowed on a nonstatic member declaration + * - ``1217``\ + - | ``unrecognized_format_function_type``\ : + | unrecognized format function type *"xxxx"*\ ignored + * - ``1218``\ + - | ``base_uses_tail_padding``\ : + | base class *"entity"*\ uses tail padding of base class *"entity"*\ + * - ``1219``\ + - | ``bad_variable_for_init_priority``\ : + | the "init_priority" attribute can only be used for definitions of + static data members and namespace scope variables of class types + * - ``1220``\ + - | ``init_priority_reserved``\ : + | requested initialization priority is reserved for internal use + * - ``1221``\ + - | ``hidden_anonymous_union_field``\ : + | this anonymous union/struct field is hidden by *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``1222``\ + - | ``invalid_error_number``\ : + | invalid error number + * - ``1223``\ + - | ``invalid_error_tag``\ : + | invalid error tag + * - ``1224``\ + - | ``exp_error_argument``\ : + | expected an error number or error tag + * - ``1225``\ + - | ``size_affected_by_tail_padding``\ : + | size of class is affected by tail padding + * - ``1226``\ + - | ``nonlocal_label_reference``\ : + | labels can be referenced only in function definitions + * - ``1227``\ + - | ``branch_into_statement_expr``\ : + | transfer of control into a statement expression is not allowed + * - ``1229``\ + - | ``bad_statement_in_statement_expr``\ : + | this statement is not allowed inside of a statement expression + * - ``1230``\ + - | ``class_def_in_statement_expr``\ : + | a class that is not trivially copyable cannot be defined inside a + statement expression + * - ``1232``\ + - | ``dyn_local_static_in_statement_expr``\ : + | a dynamically-initialized local static variable is not allowed inside + of a statement expression + * - ``1233``\ + - | ``vla_in_statement_expr``\ : + | a variable-length array is not allowed inside of a statement + expression + * - ``1234``\ + - | ``statement_expr_in_default_arg``\ : + | a statement expression is not allowed inside of a default argument + * - ``1235``\ + - | ``ptr_func_ptr_data_conv``\ : + | nonstandard conversion between pointer to function and pointer to data + * - ``1236``\ + - | ``interface_cannot_have_virtual_base``\ : + | interface types cannot have virtual base classes + * - ``1237``\ + - | ``interface_cannot_have_private_or_protected``\ : + | interface types cannot specify "private" or "protected" + * - ``1238``\ + - | ``interface_must_derive_from_interface``\ : + | interface types can only derive from other interface types + * - ``1239``\ + - | ``type_is_interface``\ : + | *"type"*\ is an interface type + * - ``1240``\ + - | ``interface_cannot_have_typedef``\ : + | interface types cannot have typedef members + * - ``1241``\ + - | ``interface_cannot_have_ctor_or_dtor``\ : + | interface types cannot have user-declared constructors or destructors + * - ``1242``\ + - | ``interface_cannot_have_operator``\ : + | interface types cannot have user-declared member operators + * - ``1243``\ + - | ``interface_cannot_be_local``\ : + | interface types cannot be declared in functions + * - ``1245``\ + - | ``interface_cannot_have_data_member``\ : + | interface types cannot have data members + * - ``1246``\ + - | ``interface_cannot_have_friend``\ : + | interface types cannot contain friend declarations + * - ``1248``\ + - | ``interface_cannot_be_nested_class``\ : + | interface types cannot be nested class types + * - ``1249``\ + - | ``interface_cannot_have_member_templates``\ : + | interface types cannot have member templates + * - ``1250``\ + - | ``interface_cannot_have_static_members``\ : + | interface types cannot have static member functions + * - ``1251``\ + - | ``invalid_microsoft_pragma_operator``\ : + | this pragma cannot be used in a \__pragma operator (a #pragma + directive must be used) + * - ``1252``\ + - | ``qualifier_must_be_base_class``\ : + | qualifier must be base class of *"type"*\ + * - ``1253``\ + - | ``invalid_selective_overrider_declaration``\ : + | declaration must correspond to a pure virtual member function in the + indicated base class + * - ``1254``\ + - | ``integer_overflow_class_internal``\ : + | integer overflow in internal computation due to size or complexity of + *"type"*\ + * - ``1255``\ + - | ``integer_overflow_internal``\ : + | integer overflow in internal computation + * - ``1256``\ + - | ``invalid_type_for_w64``\ : + | __w64 can only be specified on int, long, and pointer types + * - ``1257``\ + - | ``ilp64_will_narrow``\ : + | potentially narrowing conversion when compiled in an environment + where int, long, or pointer types are 64 bits wide + * - ``1258``\ + - | ``value_of_pragma_pack_show``\ : + | current value of pragma pack is *xxxx*\ + * - ``1259``\ + - | ``pragma_pack_show_args_ignored``\ : + | arguments for pragma pack(show) are ignored + * - ``1262``\ + - | ``multiple_declspec_align``\ : + | earlier \__declspec(align(...)) ignored + * - ``1263``\ + - | ``exp_ms_attr_enum_value``\ : + | expected an argument value for the *"xxxx"*\ attribute parameter + * - ``1264``\ + - | ``invalid_ms_attr_enum_value``\ : + | invalid argument value for the *"xxxx"*\ attribute parameter + * - ``1265``\ + - | ``exp_ms_attr_bool_value``\ : + | expected a boolean value for the *"xxxx"*\ attribute parameter + * - ``1266``\ + - | ``positional_after_named``\ : + | a positional argument cannot follow a named argument in an attribute + * - ``1267``\ + - | ``invalid_ms_attr_name``\ : + | attribute *"xxxx"*\ has no parameter named *"xxxx"*\ + * - ``1268``\ + - | ``exp_ms_attr_arg_list``\ : + | expected an argument list for the *"xxxx"*\ attribute + * - ``1269``\ + - | ``exp_comma_or_rbracket``\ : + | expected a "," or "]" + * - ``1270``\ + - | ``duplicate_ms_attr_arg``\ : + | attribute argument *"xxxx"*\ has already been given a value + * - ``1271``\ + - | ``cannot_assign_to_ms_attr``\ : + | a value cannot be assigned to the *"xxxx"*\ attribute + * - ``1272``\ + - | ``ptr_incomplete_throw``\ : + | a throw expression may not have pointer-to-incomplete type + * - ``1273``\ + - | ``alignof_incomplete_type``\ : + | alignment-of operator applied to incomplete type + * - ``1274``\ + - | ``invalid_use_of_standalone_ms_attr``\ : + | *"xxxx"*\ may only be used as a standalone attribute + * - ``1275``\ + - | ``invalid_use_of_ms_attr``\ : + | *"xxxx"*\ attribute cannot be used here + * - ``1277``\ + - | ``ms_attr_not_allowed``\ : + | attributes are not allowed here + * - ``1278``\ + - | ``invalid_ms_attr_uuid_value``\ : + | invalid argument value for the *"xxxx"*\ attribute parameter + * - ``1279``\ + - | ``too_many_ms_attr_args``\ : + | too many attribute arguments + * - ``1280``\ + - | ``conv_from_inaccessible_base_class``\ : + | conversion from inaccessible base class *"type"*\ is not allowed + * - ``1281``\ + - | ``cl_export_template_requires_distinct_templ_sigs``\ : + | option "export" requires distinct template signatures + * - ``1282``\ + - | ``mixed_string_concatenation``\ : + | string literals with different character kinds cannot be concatenated + * - ``1283``\ + - | ``no_gnu_virtual_base_gap``\ : + | GNU layout bug not emulated because it places virtual base + *"entity"*\ outside *"entity"*\ object boundaries + * - ``1284``\ + - | ``gnu_virtual_base_gap``\ : + | virtual base *"entity"*\ placed outside *"entity"*\ object + boundaries + * - ``1285``\ + - | ``nonstd_qualifier_in_namespace_member_decl``\ : + | nonstandard qualified name in namespace member declaration + * - ``1286``\ + - | ``declspec_align_reduction_ignored``\ : + | reduction in alignment ignored + * - ``1287``\ + - | ``const_ignored``\ : + | const qualifier ignored + * - ``1289``\ + - | ``invalid_asm_qualifiers``\ : + | invalid GNU asm qualifiers + * - ``1290``\ + - | ``non_pod_passed_to_ellipsis``\ : + | a class type that is not trivially copyable passed through ellipsis + * - ``1291``\ + - | ``non_pod_va_arg``\ : + | a class type that cannot be trivially copied cannot be fetched by + va_arg + * - ``1292``\ + - | ``nonstd_fixed_point_suffix``\ : + | the 'u' or 'U' suffix must appear before the 'l' or 'L' suffix in a + fixed-point literal + * - ``1293``\ + - | ``cl_fixed_point_option_only_in_C``\ : + | option "fixed_point" can be used only when compiling C + * - ``1294``\ + - | ``integer_may_not_fit_in_fixed_point_result``\ : + | integer operand may cause fixed-point overflow + * - ``1295``\ + - | ``bad_fixed_point_value``\ : + | fixed-point constant is out of range + * - ``1296``\ + - | ``inexact_fxp_conversion``\ : + | fixed-point value cannot be represented exactly + * - ``1297``\ + - | ``c99_constant_in_unsigned_long_long_range``\ : + | constant is too large for long long; given unsigned long long type + (nonstandard) + * - ``1298``\ + - | ``bad_upc_shared_void_pointer_layout_qualifier``\ : + | layout qualifier cannot qualify pointer to shared void + * - ``1299``\ + - | ``duplicate_threads_dim``\ : + | duplicate THREADS in multidimensional array type + * - ``1300``\ + - | ``bad_strong_using_scope``\ : + | a strong using-directive may only appear in a namespace scope + * - ``1301``\ + - | ``probable_guiding_friend``\ : + | *entity-kind "entity"*\ declares a non-template function -- add <> + to refer to a template instance + * - ``1302``\ + - | ``operation_may_not_fit_in_fixed_point_result``\ : + | operation may cause fixed-point overflow + * - ``1303``\ + - | ``expr_not_integral_or_enum_or_fixed_point``\ : + | expression must have integral, enum, or fixed-point type + * - ``1304``\ + - | ``expr_not_integral_or_fixed_point``\ : + | expression must have integral or fixed-point type + * - ``1305``\ + - | ``noreturn_function_does_return``\ : + | function declared with "noreturn" does return + * - ``1306``\ + - | ``asm_name_conflict``\ : + | asm name ignored because it conflicts with a previous declaration + * - ``1307``\ + - | ``duplicate_typedef_in_class``\ : + | class member typedef may not be redeclared + * - ``1308``\ + - | ``taking_address_of_temporary``\ : + | taking the address of a temporary + * - ``1309``\ + - | ``attribute_ignored_on_incomplete_class_decl``\ : + | attributes are ignored on a class declaration that is not also a + definition + * - ``1310``\ + - | ``implicit_fixed_point_to_floating_point_conversion``\ : + | fixed-point value implicitly converted to floating-point type + * - ``1311``\ + - | ``no_classification_for_fixed_point_type``\ : + | fixed-point types have no classification + * - ``1312``\ + - | ``fixed_template_parameter``\ : + | a template parameter may not have fixed-point type + * - ``1313``\ + - | ``hex_fp_constant``\ : + | hexadecimal floating-point constants are not allowed + * - ``1314``\ + - | ``cl_named_address_spaces_option_only_in_C``\ : + | option "named_address_spaces" can be used only when compiling C + * - ``1315``\ + - | ``float_to_fixed_conversion``\ : + | floating-point value does not fit in required fixed-point type + * - ``1316``\ + - | ``inexact_fixed_conversion``\ : + | value cannot be converted to fixed-point value exactly + * - ``1317``\ + - | ``fixed_sign_change``\ : + | fixed-point conversion resulted in a change of sign + * - ``1318``\ + - | ``integer_to_fixed_conversion``\ : + | integer value does not fit in required fixed-point type + * - ``1319``\ + - | ``bad_fixed_operation_result``\ : + | fixed-point operation result is out of range + * - ``1320``\ + - | ``multiple_named_address_spaces``\ : + | multiple named address spaces + * - ``1321``\ + - | ``bad_storage_class_for_named_address_space_variable``\ : + | variable with automatic storage duration cannot be stored in a named + address space + * - ``1322``\ + - | ``type_with_named_address_space_not_allowed``\ : + | type cannot be qualified with named address space + * - ``1323``\ + - | ``named_address_space_on_function_type``\ : + | function type cannot be qualified with named address space + * - ``1324``\ + - | ``field_type_cannot_be_qualified_with_named_address_space``\ : + | field type cannot be qualified with named address space + * - ``1325``\ + - | ``fixed_to_float_conversion``\ : + | fixed-point value does not fit in required floating-point type + * - ``1326``\ + - | ``fixed_to_integer_conversion``\ : + | fixed-point value does not fit in required integer type + * - ``1327``\ + - | ``fixed_to_fixed_conversion``\ : + | value does not fit in required fixed-point type + * - ``1328``\ + - | ``cl_named_registers_option_only_in_C``\ : + | option "named_registers" can be used only when compiling C + * - ``1329``\ + - | ``named_register_not_allowed``\ : + | a named-register storage class is not allowed here + * - ``1330``\ + - | ``register_storage_class_conflict``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) redeclared with + incompatible named-register storage class + * - ``1331``\ + - | ``aliased_variable_cannot_have_register_storage_class``\ : + | named-register storage class cannot be specified for aliased variable + * - ``1332``\ + - | ``register_in_use``\ : + | named-register storage specifier is already in use + * - ``1333``\ + - | ``embedded_c_option_incompatible_with_individual_feature_options``\ : + | option "embedded_c" cannot be combined with options to control + individual Embedded C features + * - ``1334``\ + - | ``cl_invalid_edg_base_directory``\ : + | invalid EDG_BASE directory: *xxxx*\ + * - ``1336``\ + - | ``bad_predef_macro_line``\ : + | invalid predefined macro entry at line *xxxx*\ : *xxxx*\ + * - ``1337``\ + - | ``bad_macro_mode_name``\ : + | invalid macro mode name *"xxxx"*\ + * - ``1338``\ + - | ``bad_predef_macro_redef``\ : + | incompatible redefinition of predefined macro *"xxxx"*\ + * - ``1339``\ + - | ``missing_named_register_storage_class``\ : + | redeclaration of *entity-kind "entity"*\ (declared at line *xxxx*\ ) + is missing a named-register storage class + * - ``1340``\ + - | ``register_too_small``\ : + | named register is too small for the type of the variable + * - ``1341``\ + - | ``no_named_register_for_array``\ : + | arrays cannot be declared with named-register storage class + * - ``1342``\ + - | ``enum_const_cast``\ : + | const_cast to enum type is nonstandard + * - ``1343``\ + - | ``cl_embedded_c_option_only_in_C``\ : + | option "embedded_c" can be used only when compiling C + * - ``1344``\ + - | ``named_address_space_not_allowed``\ : + | a named address space qualifier is not allowed here + * - ``1345``\ + - | ``bad_initializer_for_array_with_unspecified_bound``\ : + | an empty initializer is invalid for an array with unspecified bound + * - ``1346``\ + - | ``incomplete_class_return_type``\ : + | function returns incomplete class type *"type"*\ + * - ``1347``\ + - | ``out_of_class_initializer_ignored``\ : + | *entity-kind "entity"*\ has already been initialized; the + out-of-class initializer will be ignored + * - ``1348``\ + - | ``local_variable_hidden``\ : + | declaration hides *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``1349``\ + - | ``named_address_space_for_parameter``\ : + | a parameter cannot be allocated in a named address space + * - ``1350``\ + - | ``bad_float_or_fixed_suffix``\ : + | invalid suffix on fixed-point or floating-point constant + * - ``1351``\ + - | ``register_in_address_space``\ : + | a register variable cannot be allocated in a named address space + * - ``1352``\ + - | ``bad_stdc_fx_overflow_pragma_arg``\ : + | expected "SAT" or "DEFAULT" + * - ``1353``\ + - | ``no_corresponding_member_delete``\ : + | *entity-kind "entity"*\ has no corresponding member operator + delete*xxxx*\ (to be called if an exception is thrown during + initialization of an allocated object) + * - ``1354``\ + - | ``dll_thread_conflict``\ : + | a thread-local variable cannot be declared with "dllimport" or + "dllexport" + * - ``1355``\ + - | ``function_returning_named_address_space``\ : + | a function return type cannot be qualified with a named address space + * - ``1356``\ + - | ``cannot_initialize_destructible_flexible_array``\ : + | an initializer cannot be specified for a flexible array member whose + elements have a nontrivial destructor + * - ``1357``\ + - | ``cannot_initialize_indirect_flexible_array``\ : + | an initializer cannot be specified for an indirect flexible array + member + * - ``1358``\ + - | ``cl_invalid_gnu_version``\ : + | invalid GNU version number: *xxxx*\ + * - ``1359``\ + - | ``attribute_after_parenthesized_initializer``\ : + | variable attributes appearing after a parenthesized initializer are + ignored + * - ``1360``\ + - | ``gcc_use_of_cast_as_lvalue``\ : + | the result of this cast cannot be used as an lvalue + * - ``1361``\ + - | ``unsigned_fixed_point_negation``\ : + | negation of an unsigned fixed-point value + * - ``1364``\ + - | ``register_name_on_nonregister``\ : + | register names can only be used for register variables + * - ``1365``\ + - | ``void_named_register``\ : + | named-register variables cannot have void type + * - ``1367``\ + - | ``parameter_with_link_scope_specifier``\ : + | parameters cannot have link scope specifiers + * - ``1368``\ + - | ``multiple_link_scope_specifiers``\ : + | multiple link scope specifiers + * - ``1369``\ + - | ``link_scope_requires_external_linkage``\ : + | link scope specifiers can only appear on functions and variables with + external linkage + * - ``1370``\ + - | ``link_scope_relaxation``\ : + | a redeclaration cannot weaken a link scope + * - ``1371``\ + - | ``invalid_link_scope``\ : + | link scope specifier not allowed on this declaration + * - ``1372``\ + - | ``nonstd_qualifier_in_global_scope_decl``\ : + | nonstandard qualified name in global scope declaration + * - ``1373``\ + - | ``impl_narrowing_64_bit_int``\ : + | implicit conversion of a 64-bit integral type to a smaller integral + type (potential portability problem) + * - ``1374``\ + - | ``expl_narrowing_64_bit_int``\ : + | explicit conversion of a 64-bit integral type to a smaller integral + type (potential portability problem) + * - ``1375``\ + - | ``pointer_conversion_to_same_size_int``\ : + | conversion from pointer to same-sized integral type (potential + portability problem) + * - ``1377``\ + - | ``friend_specifier_ignored``\ : + | friend specifier is not allowed in a class definition; friend + specifier is ignored + * - ``1378``\ + - | ``cannot_use_thread_local_storage``\ : + | only static and extern variables can use thread-local storage + * - ``1379``\ + - | ``multiple_thread_local_storage_specifiers``\ : + | multiple thread-local storage specifiers + * - ``1380``\ + - | ``virtual_function_never_defined``\ : + | virtual *entity-kind "entity"*\ was not defined (and cannot be + defined elsewhere because it is a member of an unnamed namespace) + * - ``1381``\ + - | ``stray_carriage_return``\ : + | carriage return character in source line outside of comment or + character/string literal + * - ``1382``\ + - | ``expr_not_fixed_point``\ : + | expression must have fixed-point type + * - ``1383``\ + - | ``invalid_access_specifier``\ : + | invalid use of access specifier is ignored + * - ``1384``\ + - | ``ptr_conv_to_bool``\ : + | pointer converted to bool + * - ``1385``\ + - | ``ptr_to_member_conv_to_bool``\ : + | pointer-to-member converted to bool + * - ``1386``\ + - | ``storage_specifier_ignored``\ : + | storage specifier ignored + * - ``1387``\ + - | ``dll_interface_ignored_on_class_template``\ : + | dllexport and dllimport are ignored on class templates + * - ``1388``\ + - | ``base_class_has_different_dll_interface``\ : + | base class dllexport/dllimport specification differs from that of the + derived class + * - ``1389``\ + - | ``redeclaration_adds_dll_interface``\ : + | redeclaration cannot add dllexport/dllimport to *"entity"*\ + (declared at line *xxxx*\ ) + * - ``1390``\ + - | ``dll_interface_conflict_dllexport_assumed``\ : + | dllexport/dllimport conflict with *"entity"*\ (declared at line + *xxxx*\ ); dllexport assumed + * - ``1391``\ + - | ``dllimport_defined``\ : + | cannot define dllimport entity + * - ``1392``\ + - | ``dll_interface_requires_external_linkage``\ : + | dllexport/dllimport requires external linkage + * - ``1393``\ + - | ``class_and_member_have_dll_interface``\ : + | a member of a class declared with dllexport/dllimport cannot itself + be declared with such a specifier + * - ``1394``\ + - | ``field_without_dll_interface``\ : + | field of class type without a DLL interface used in a class with a + DLL interface + * - ``1395``\ + - | ``microsoft_parenthesized_member``\ : + | parenthesized member declaration is nonstandard + * - ``1396``\ + - | ``white_space_inside_splice``\ : + | white space between backslash and newline in line splice ignored + * - ``1397``\ + - | ``dll_interface_conflict_none_assumed``\ : + | dllexport/dllimport conflict with *"entity"*\ (declared at line + *xxxx*\ ); dllimport/dllexport dropped + * - ``1398``\ + - | ``bad_nonstd_anonymous_union_field``\ : + | invalid member for anonymous member class -- class *"type"*\ has a + disallowed member function + * - ``1399``\ + - | ``nonstd_reinterpret_cast``\ : + | nonstandard reinterpret_cast + * - ``1400``\ + - | ``positional_format_specifier_zero``\ : + | positional format specifier cannot be zero + * - ``1401``\ + - | ``nonlocal_vla_not_allowed``\ : + | a local class cannot reference a variable-length array type from an + enclosing function + * - ``1402``\ + - | ``class_and_inherited_member_instance_have_dll_interface``\ : + | member *entity-kind "entity"*\ (declared at line *xxxx*\ ) already + has an explicit dllexport/dllimport specifier + * - ``1403``\ + - | ``vla_in_return_type``\ : + | a variable-length array is not allowed in a function return type + * - ``1404``\ + - | ``ptr_to_member_of_vla_type``\ : + | variable-length array type is not allowed in pointer to member of + type *"type"*\ + * - ``1405``\ + - | ``statement_expr_with_vla_type``\ : + | the result of a statement expression cannot have a type involving a + variable-length array + * - ``1406``\ + - | ``trigraph_ignored``\ : + | support for trigraphs is disabled + * - ``1407``\ + - | ``attribute_requires_external_linkage``\ : + | the *"xxxx"*\ attribute can only appear on functions and variables + with external linkage + * - ``1408``\ + - | ``cl_strict_mode_incompatible_with_ignore_std``\ : + | strict mode is incompatible with treating namespace std as an alias + for the global namespace + * - ``1414``\ + - | ``invalid_symbolic_asm_operand_name``\ : + | invalid symbolic operand name *"xxxx"*\ + * - ``1415``\ + - | ``match_limit_for_symbolic_asm_operand``\ : + | a symbolic match constraint must refer to one of the first ten + operands + * - ``1416``\ + - | ``if_exists_not_allowed``\ : + | use of \__if_exists is not supported in this context + * - ``1417``\ + - | ``if_exists_not_closed``\ : + | __if_exists block not closed in the same scope in which it was opened + * - ``1418``\ + - | ``bad_init_for_thread_local``\ : + | thread-local variable cannot be dynamically initialized + * - ``1419``\ + - | ``unaligned_qualifier_dropped``\ : + | conversion drops "\__unaligned" qualifier + * - ``1420``\ + - | ``insufficient_enum_range``\ : + | some enumerator values cannot be represented by the integral type + underlying the enum type + * - ``1421``\ + - | ``friend_class_template_default_arg_not_allowed``\ : + | default argument is not allowed on a friend class template declaration + * - ``1422``\ + - | ``multi_char_literal``\ : + | multicharacter character literal (potential portability problem) + * - ``1423``\ + - | ``exp_class_type``\ : + | expected a class, struct, or union type + * - ``1424``\ + - | ``offsetof_nonfield``\ : + | second operand of offsetof must be a field + * - ``1425``\ + - | ``offsetof_bit_field``\ : + | second operand of offsetof may not be a bit field + * - ``1426``\ + - | ``offsetof_virtual_base_member``\ : + | cannot apply offsetof to a member of a virtual base + * - ``1427``\ + - | ``offset_in_non_POD_nonstandard``\ : + | offsetof applied to a type other than a standard-layout class + * - ``1428``\ + - | ``default_arg_on_member_friend``\ : + | default arguments are not allowed on a friend declaration of a member + function + * - ``1429``\ + - | ``default_arg_requires_friend_to_be_definition``\ : + | default arguments are not allowed on friend declarations that are not + definitions + * - ``1430``\ + - | ``redeclaration_of_friend_with_default_args``\ : + | redeclaration of *entity-kind "entity"*\ (declared at line *xxxx*\ ) + previously declared as a friend with default arguments is not allowed + * - ``1431``\ + - | ``bad_qualifier_for_nested_class_decl``\ : + | invalid qualifier for *"type"*\ (a derived class is not allowed here) + * - ``1432``\ + - | ``bad_qualifier_for_delayed_class_definition``\ : + | invalid qualifier for definition of class *"type"*\ + * - ``1433``\ + - | ``no_prior_push_macro``\ : + | no prior push_macro for *"xxxx"*\ + * - ``1434``\ + - | ``wide_string_not_allowed``\ : + | wide string literal not allowed + * - ``1436``\ + - | ``feature_requires_c``\ : + | *"xxxx"*\ is only allowed in C + * - ``1437``\ + - | ``microsoft_ptr_width_must_follow_star``\ : + | __ptr32 and \__ptr64 must follow a "\*" + * - ``1438``\ + - | ``microsoft_ptr_width_conflict``\ : + | __ptr32 and \__ptr64 cannot both apply + * - ``1439``\ + - | ``name_must_be_prototype_instantiation``\ : + | template argument list of *"xxxx"*\ must match the parameter list + * - ``1440``\ + - | ``incomplete_class_type``\ : + | an incomplete class type is not allowed + * - ``1441``\ + - | ``complex_integral_type``\ : + | complex integral types are not supported + * - ``1442``\ + - | ``real_and_imag_require_complex_argument``\ : + | __real and \__imag can only be applied to complex values + * - ``1443``\ + - | ``real_and_imag_applied_to_real_value``\ : + | __real/\__imag applied to real value + * - ``1444``\ + - | ``deprecated_entity_with_custom_message``\ : + | *entity-kind "entity"*\ was declared deprecated (*"xxxx"*\ ) + * - ``1446``\ + - | ``dll_interface_in_unnamed_namespace``\ : + | dllimport/dllexport applied to a member of an unnamed namespace + * - ``1447``\ + - | ``thiscall_requires_nonstatic_member``\ : + | __thiscall can only appear on nonstatic member function declarations + * - ``1448``\ + - | ``vararg_thiscall``\ : + | __thiscall not allowed on function with ellipsis parameter + * - ``1449``\ + - | ``specialization_of_referenced_entity_pos``\ : + | explicit specialization of *entity-kind "entity"*\ must precede its + first use (at line *xxxx*\ ) + * - ``1450``\ + - | ``sealed_base_class``\ : + | a sealed class type cannot be used as a base class + * - ``1451``\ + - | ``duplicate_class_modifier``\ : + | duplicate class modifier + * - ``1452``\ + - | ``function_modifiers_abstract_and_sealed``\ : + | a member function cannot have both the "abstract" and "sealed" + modifiers + * - ``1453``\ + - | ``pure_specifier_on_sealed_member``\ : + | a sealed member cannot be pure virtual + * - ``1454``\ + - | ``function_modifier_requires_virtual_function``\ : + | nonvirtual function cannot be declared with "abstract" or "sealed" + modifier + * - ``1455``\ + - | ``override_member_does_not_override``\ : + | member function declared with "override" does not override a base + class member + * - ``1456``\ + - | ``override_of_sealed_function``\ : + | cannot override sealed *entity-kind "entity"*\ (declared at line + *xxxx*\ ) + * - ``1457``\ + - | ``type_is_declared_abstract``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was declared + with the class modifier "abstract" + * - ``1534``\ + - | ``duplicate_function_modifier``\ : + | duplicate function modifier + * - ``1535``\ + - | ``no_char16_t_representation``\ : + | invalid character for char16_t literal + * - ``1537``\ + - | ``cl_unrecognized_calling_convention``\ : + | unrecognized calling convention *xxxx*\ , must be one of: + * - ``1541``\ + - | ``enum_base_type_must_be_integral``\ : + | underlying type of enum type must be an integral type + * - ``1542``\ + - | ``enum_base_type_too_limited``\ : + | some enumerator constants cannot be represented by *"type"*\ + * - ``1543``\ + - | ``feature_not_allowed_in_current_mode``\ : + | *"xxxx"*\ not allowed in current mode + * - ``1544``\ + - | ``cl_type_traits_helpers_option_only_in_cplusplus``\ : + | type traits helpers option can be used only when compiling C++ + * - ``1545``\ + - | ``gnu_sentinel_attribute_requires_ellipsis``\ : + | attribute "sentinel" requires an ellipsis parameter + * - ``1546``\ + - | ``invalid_gnu_sentinel_argument``\ : + | argument must be a constant null pointer value + * - ``1547``\ + - | ``no_gnu_sentinel_argument``\ : + | insufficient number of arguments for sentinel value + * - ``1548``\ + - | ``gnu_sentinel_must_be_ellipsis_argument``\ : + | sentinel argument must correspond to an ellipsis parameter + * - ``1549``\ + - | ``implementation_key_outside_mapping_region``\ : + | __declspec(implementation_key(...) can appear only between #pragma + start_map_region and #pragma stop_map_region + * - ``1550``\ + - | ``start_map_region_ignored``\ : + | #pragma start_map_region already active: pragma ignored + * - ``1551``\ + - | ``stop_map_region_ignored``\ : + | no #pragma start_map_region is currently active: pragma ignored + * - ``1552``\ + - | ``var_used_as_destructor``\ : + | *entity-kind "entity"*\ cannot be used to name a destructor (a type + name is required) + * - ``1553``\ + - | ``empty_wide_character``\ : + | nonstandard empty wide character literal treated as L'\0' + * - ``1554``\ + - | ``invalid_typename_specifier``\ : + | "typename" may not be specified here + * - ``1555``\ + - | ``no_default_delete_in_virtual_dtor``\ : + | a non-placement operator delete must be visible in a class with a + virtual destructor + * - ``1556``\ + - | ``name_linkage_mismatch_for_variable``\ : + | name linkage conflicts with previous declaration of *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``1557``\ + - | ``alias_loop``\ : + | alias creates cycle of aliased entities + * - ``1559``\ + - | ``register_mapped_variable_cannot_have_initializer``\ : + | a variable with static storage duration allocated in a specific + register cannot be declared with an initializer + * - ``1560``\ + - | ``register_mapped_variable_must_be_POD``\ : + | a variable allocated in a specific register must be trivially copyable + * - ``1561``\ + - | ``predef_macro_redefined``\ : + | predefined meaning of *"entity"*\ discarded + * - ``1563``\ + - | ``designator_for_non_POD``\ : + | class type not suitable for use with designators + * - ``1565``\ + - | ``nonstandard_anonymous_union_qualifier``\ : + | anonymous union qualifier is nonstandard + * - ``1566``\ + - | ``anonymous_union_qualifier_ignored``\ : + | anonymous union qualifier is ignored + * - ``1568``\ + - | ``struct_declspec_ignored_in_C_mode``\ : + | __declspec(*xxxx*\ ) ignored (it has no meaning for a C struct) + * - ``1569``\ + - | ``nonstandard_secondary_decl_specifiers``\ : + | specifiers after comma between declarations are nonstandard + * - ``1570``\ + - | ``secondary_specifier_ignored``\ : + | nonstandard specifier ignored + * - ``1571``\ + - | ``enum_attribute_ignored``\ : + | attributes are ignored on an enum declaration that is not also a + definition + * - ``1572``\ + - | ``reference_declared_mutable``\ : + | declaring a reference with "mutable" is nonstandard + * - ``1573``\ + - | ``array_condition_always_true``\ : + | a condition declaration for an array is always true + * - ``1574``\ + - | ``static_assert``\ : + | static assertion failed with *"xxxx"*\ + * - ``1575``\ + - | ``gnu_visibility_conflict``\ : + | visibility attribute ignored because it conflicts with a previous + declaration + * - ``1576``\ + - | ``pcc_field_ambiguity``\ : + | field name resolves to more than one offset -- see *"entity"*\ + (declared at line *xxxx*\ ) and *"entity"*\ (declared at line + *xxxx*\ ) + * - ``1577``\ + - | ``not_a_field_name``\ : + | *"xxxx"*\ is not a field name + * - ``1578``\ + - | ``case_label_conflict``\ : + | case label value has already appeared in this switch at line *xxxx*\ + * - ``1579``\ + - | ``member_cannot_have_internal_linkage``\ : + | a member function cannot have internal linkage + * - ``1580``\ + - | ``builtin_function_hidden``\ : + | declaration hides built-in *entity-kind "entity"*\ + * - ``1581``\ + - | ``builtin_function_overloaded``\ : + | declaration overloads built-in *entity-kind "entity"*\ + * - ``1582``\ + - | ``cl_list_macros_incompatible_with_multiple_trans_units``\ : + | the option to list macro definitions may not be specified when + compiling more than one translation unit + * - ``1583``\ + - | ``lparen_after_function``\ : + | unexpected parenthesis after declaration of *entity-kind "entity"*\ + (malformed parameter list or invalid initializer?) + * - ``1584``\ + - | ``nonstandard_parenthesized_string_initializer``\ : + | parentheses around a string initializer are nonstandard + * - ``1586``\ + - | ``auto_variable_in_own_initializer``\ : + | a variable declared with an auto type specifier cannot appear in its + own initializer + * - ``1587``\ + - | ``cannot_deduce_auto_type``\ : + | cannot deduce "auto" type + * - ``1588``\ + - | ``auto_brace_initialization_not_allowed``\ : + | initialization with "{...}" is not allowed for "auto" type + * - ``1589``\ + - | ``auto_type_in_array_type``\ : + | "auto" type cannot appear in top-level array type + * - ``1590``\ + - | ``auto_type_in_function_type``\ : + | "auto" type cannot appear in top-level function type + * - ``1591``\ + - | ``invalid_member_constant_type``\ : + | a member of type *"type"*\ cannot have an in-class initializer + * - ``1592``\ + - | ``member_constant_not_const``\ : + | a member with an in-class initializer must be const + * - ``1593``\ + - | ``auto_type_requires_initializer``\ : + | cannot deduce "auto" type (initializer required) + * - ``1594``\ + - | ``inconsistent_deduction_of_auto``\ : + | "auto" type is *"type"*\ for this entity, but was previously implied + to be *"type"*\ + * - ``1595``\ + - | ``bad_constructor_decl``\ : + | invalid constructor declaration + * - ``1596``\ + - | ``bad_type_qualifier``\ : + | invalid use of a type qualifier + * - ``1597``\ + - | ``abstract_or_sealed_on_union``\ : + | a union cannot be abstract or sealed + * - ``1598``\ + - | ``auto_not_allowed_here``\ : + | "auto" is not allowed here + * - ``1599``\ + - | ``unfinished_base_class``\ : + | definition of base class type not completed yet + * - ``1600``\ + - | ``static_extern_template``\ : + | "extern template" cannot refer to a specialization of static + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``1601``\ + - | ``extern_template_follows_instantiation``\ : + | "extern template" cannot follow explicit instantiation of + *entity-kind "entity"*\ + * - ``1602``\ + - | ``bad_declspec_restrict_return``\ : + | __declspec(restrict) requires a function returning a pointer type + * - ``1603``\ + - | ``cl_report_gnu_extensions_requires_gnu_mode``\ : + | the "report_gnu_extensions" option is only valid in GNU C and GNU C++ + modes + * - ``1604``\ + - | ``vla_is_nonstandard``\ : + | variable-length array types are nonstandard + * - ``1605``\ + - | ``designator_is_nonstandard``\ : + | designators are nonstandard + * - ``1606``\ + - | ``extended_designator_is_gnu_extension``\ : + | this designator syntax is a GNU extension + * - ``1607``\ + - | ``compound_literal_is_nonstandard``\ : + | compound literals are nonstandard + * - ``1608``\ + - | ``statement_expression_is_gnu_extension``\ : + | statement expressions are a GNU extension + * - ``1609``\ + - | ``asm_name_after_definition``\ : + | asm name ignored for previously defined entity + * - ``1610``\ + - | ``attribute_is_gnu_extension``\ : + | attributes are a GNU extension + * - ``1611``\ + - | ``asm_operand_spec_is_gnu_extension``\ : + | extended asm syntax is a GNU feature + * - ``1612``\ + - | ``volatile_asm_is_gnu_extension``\ : + | volatile asm declarations are a GNU extension + * - ``1613``\ + - | ``asm_name_is_gnu_extension``\ : + | asm name specifiers are a GNU extension + * - ``1614``\ + - | ``gnu_restrict_is_nonstandard``\ : + | the "\__restrict" qualifier is nonstandard + * - ``1615``\ + - | ``typeof_is_gnu_extension``\ : + | "typeof" is a GNU extension + * - ``1616``\ + - | ``typedef_modification_is_nonstandard``\ : + | modifying the size or signedness of a typedef is nonstandard + * - ``1617``\ + - | ``zero_length_array_is_gnu_extension``\ : + | zero-length arrays are a GNU extension + * - ``1618``\ + - | ``flexible_array_is_nonstandard``\ : + | flexible array members are nonstandard + * - ``1619``\ + - | ``nonnull_on_nonpointer``\ : + | attribute "nonnull" references nonpointer parameter + * - ``1620``\ + - | ``nonnull_parameter_number_too_large``\ : + | argument for attribute "nonnull" is larger than number of parameters + * - ``1621``\ + - | ``no_pointer_parameters``\ : + | no parameter has pointer type + * - ``1622``\ + - | ``null_argument_for_nonnull_parameter``\ : + | null argument provided for parameter marked with attribute "nonnull" + * - ``1623``\ + - | ``access_prevents_dtor_generation``\ : + | the destructor for *"type"*\ has been suppressed because the + destructor for *"type"*\ is inaccessible + * - ``1624``\ + - | ``suppressed_dtor_needed``\ : + | the suppressed destructor for *"type"*\ is needed + * - ``1625``\ + - | ``inline_gnu_noinline_conflict``\ : + | routine is both "inline" and "noinline" + * - ``1626``\ + - | ``invalid_cleanup_routine``\ : + | invalid cleanup routine + * - ``1627``\ + - | ``attribute_cleanup_requires_automatic_storage``\ : + | attribute "cleanup" requires automatic storage duration + * - ``1628``\ + - | ``attribute_cleanup_for_parameter``\ : + | attribute "cleanup" does not apply to parameters + * - ``1629``\ + - | ``bad_type_for_cleanup_routine``\ : + | cleanup routine has invalid type + * - ``1630``\ + - | ``nonstandard_conversion_for_cleanup``\ : + | call of cleanup routine requires suspect conversion + * - ``1631``\ + - | ``microsoft_ptr_signedness_must_follow_star``\ : + | __sptr and \__uptr must follow a "\*" + * - ``1632``\ + - | ``microsoft_ptr_signedness_conflict``\ : + | __sptr and \__uptr cannot both be specified + * - ``1633``\ + - | ``microsoft_ptr_sign_extension``\ : + | widening pointer conversion from *"type"*\ to *"type"*\ extends + sign bit + * - ``1634``\ + - | ``microsoft_ptr_signedness_on_ptr_to_member``\ : + | __sptr and \__uptr don't apply to pointer-to-member types + * - ``1635``\ + - | ``const_mbr_suppresses_copy_asgn_decl``\ : + | the declaration of the copy assignment operator for *"type"*\ has + been suppressed because *entity-kind "entity"*\ is const + * - ``1636``\ + - | ``ref_mbr_suppresses_copy_asgn_decl``\ : + | the declaration of the copy assignment operator for *"type"*\ has + been suppressed because *entity-kind "entity"*\ has reference type + * - ``1637``\ + - | ``subobj_copy_asgn_decl_suppressed``\ : + | the declaration of the copy assignment operator for *"type"*\ has + been suppressed because that of *"type"*\ was suppressed + * - ``1638``\ + - | ``ambig_suppresses_copy_asgn_decl``\ : + | the declaration of the copy assignment operator for *"type"*\ has + been suppressed because that of *"type"*\ is ambiguous + * - ``1639``\ + - | ``access_suppresses_copy_asgn_decl``\ : + | the declaration of the copy assignment operator for *"type"*\ has + been suppressed because that of *"type"*\ is inaccessible + * - ``1640``\ + - | ``subobj_copy_ctor_decl_suppressed``\ : + | the declaration of the copy constructor for *"type"*\ has been + suppressed because that of *"type"*\ was suppressed + * - ``1641``\ + - | ``ambig_suppresses_copy_ctor_decl``\ : + | the declaration of the copy constructor for *"type"*\ has been + suppressed because that of *"type"*\ is ambiguous + * - ``1642``\ + - | ``access_suppresses_copy_ctor_decl``\ : + | the declaration of the copy constructor for *"type"*\ has been + suppressed because that of *"type"*\ is inaccessible + * - ``1643``\ + - | ``inaccessible_dtor_not_invoked``\ : + | the destructor for *"type"*\ will not be called because it is + inaccessible and the destructor for *"type"*\ was suppressed + * - ``1644``\ + - | ``file_ends_with_unterminated_type_definition``\ : + | definition at end of file not followed by a semicolon or a declarator + * - ``1645``\ + - | ``bad_type_for_gnu_sync_function``\ : + | first argument must be a pointer to integer or enum type + * - ``1646``\ + - | ``invalid_gnu_sync_size``\ : + | synchronized operations are valid only on objects of size 1, 2, 4, or + 8 + * - ``1647``\ + - | ``extra_arguments_ignored``\ : + | extra arguments ignored + * - ``1648``\ + - | ``equals_assumed_in_cmd_line_macro_def``\ : + | '=' assumed following macro name *"xxxx"*\ in command-line definition + * - ``1649``\ + - | ``white_space_required_after_macro_name``\ : + | white space is required between the macro name *"xxxx"*\ and its + replacement text + * - ``1650``\ + - | ``call_result_should_be_used``\ : + | result of call is not used + * - ``1651``\ + - | ``warn_unused_result_with_void_return``\ : + | attribute "warn_unused_result" is ignored for void return type + * - ``1653``\ + - | ``dll_interface_ignored_on_qualified_declaration``\ : + | dllimport/dllexport is ignored on redeclaration using a qualified name + * - ``1654``\ + - | ``leading_character_ignored_in_char_literal``\ : + | too many characters in character literal -- extra leading characters + ignored + * - ``1655``\ + - | ``first_inline_after_definition``\ : + | *entity-kind "entity"*\ cannot be declared inline after its + definition at line *xxxx*\ + * - ``1658``\ + - | ``type_with_no_linkage_in_template_arg``\ : + | a template argument may not reference a type with no name linkage + * - ``1659``\ + - | ``virtual_ignored``\ : + | "virtual" is ignored here + * - ``1660``\ + - | ``vla_type_in_template_arg``\ : + | a template argument may not reference a variable-length array type + * - ``1661``\ + - | ``UCN_names_surrogate_code_point``\ : + | a universal character name cannot designate a surrogate code point + * - ``1662``\ + - | ``include_next_in_primary_source_file``\ : + | #include_next cannot be used in the primary source file + * - ``1663``\ + - | ``bad_template_member_definition``\ : + | *"entity"*\ cannot be specified in a template member definition -- + *"entity"*\ assumed instead + * - ``1664``\ + - | ``local_function_attribute_ignored``\ : + | attribute *"xxxx"*\ is ignored on local function declaration + * - ``1665``\ + - | ``concat_yields_invalid_token``\ : + | concatenation with *"xxxx"*\ in *entity-kind "entity"*\ does not + create a valid token + * - ``1666``\ + - | ``ambiguous_injected_template_name``\ : + | *"entity"*\ is ambiguous (*entity-kind "entity"*\ assumed) + * - ``1667``\ + - | ``function_qualifier_on_static_member``\ : + | a type qualifier is not allowed on a static member function + * - ``1668``\ + - | ``function_qualifier_on_ctor_or_dtor``\ : + | a type qualifier is not allowed on a constructor or destructor + * - ``1669``\ + - | ``function_qualifier_on_new_or_delete``\ : + | a type qualifier is not allowed on operator new or operator delete + * - ``1670``\ + - | ``function_qualifier_on_nonmember``\ : + | a type qualifier is not allowed on a nonmember function + * - ``1671``\ + - | ``assume_expression_discarded``\ : + | argument to *xxxx*\ has side-effects but is unevaluated + * - ``1672``\ + - | ``cl_unrecognized_unicode_source_kind``\ : + | unrecognized Unicode source kind (must be one of UTF-8, UTF-16, + UTF-16LE, UTF-16BE): *xxxx*\ + * - ``1673``\ + - | ``bad_unicode_char_in_pp_output``\ : + | Unicode character with hex value *xxxx*\ not representable in + preprocessing output + * - ``1674``\ + - | ``ctor_dtor_priority_reserved``\ : + | requested constructor/destructor priority is reserved for internal use + * - ``1675``\ + - | ``unrecognized_gcc_pragma``\ : + | unrecognized GCC pragma + * - ``1676``\ + - | ``unrecognized_gcc_visibility_pragma``\ : + | unrecognized GCC visibility pragma directive + * - ``1677``\ + - | ``unrecognized_visibility``\ : + | unrecognized visibility kind + * - ``1678``\ + - | ``ELF_visibility_pop_mismatch``\ : + | visibility pragma was still active + * - ``1679``\ + - | ``ELF_visibility_stack_empty``\ : + | no matching visibility push + * - ``1680``\ + - | ``typeid_of_incomplete_type``\ : + | typeid of incomplete type + * - ``1682``\ + - | ``array_size_one_assumed``\ : + | array *entity-kind "entity"*\ assumed to have one element + * - ``1683``\ + - | ``vector_size_attribute_requires_integral_floating_or_enum_type``\ : + | vector_size attribute requires an arithmetic or enum type + * - ``1684``\ + - | ``vector_size_too_large``\ : + | vector size is too large + * - ``1685``\ + - | ``vector_size_must_be_power_of_two``\ : + | the number of elements in a vector must be a power of two + * - ``1686``\ + - | ``vector_size_must_be_multiple_of_element_size``\ : + | vector size must be a multiple of the element size + * - ``1687``\ + - | ``mixed_vector_scalar_operation``\ : + | mixed vector-scalar operation not allowed + * - ``1688``\ + - | ``vectors_must_have_same_size``\ : + | operation requires two vectors of the same size + * - ``1689``\ + - | ``dependent_vector_size``\ : + | template-dependent vector size is not allowed + * - ``1692``\ + - | ``vector_size_attribute_on_complex_type``\ : + | vector_size attribute is not allowed with a complex element type + * - ``1694``\ + - | ``vector_element_type_mismatch``\ : + | vector operation requires identical element types + * - ``1695``\ + - | ``vector_operation_requires_integer_vector``\ : + | vector operation does not apply to vector with non-integral type + * - ``1696``\ + - | ``cannot_open_file``\ : + | cannot open *xxxx*\ file *"xxxx"*\ + * - ``1697``\ + - | ``cannot_open_file_reason``\ : + | cannot open *xxxx*\ file *"xxxx"*\ : *xxxx*\ + * - ``1703``\ + - | ``file_write_error_errno``\ : + | error while writing *xxxx*\ file: *xxxx*\ + * - ``1712``\ + - | ``il_output``\ : + | IL output + * - ``1713``\ + - | ``restrict_qualifier_dropped``\ : + | conversion drops "\__restrict" qualifier + * - ``1714``\ + - | ``unable_to_get_mapped_memory_reason``\ : + | unable to obtain mapped memory for *"xxxx"*\ : *xxxx*\ + * - ``1715``\ + - | ``restrict_qualifier_ignored``\ : + | restrict qualifier is ignored + * - ``1717``\ + - | ``nonstandard_array_with_flexible_array_element``\ : + | array of elements containing a flexible array member is nonstandard + * - ``1718``\ + - | ``vector_template_parameter``\ : + | a template parameter may not have a vector type + * - ``1719``\ + - | ``out_of_order_ctor_init``\ : + | the initialization of *entity-kind "entity"*\ will be done before + that of *entity-kind "entity"*\ + * - ``1721``\ + - | ``inheritance_kind_ignored_on_enum``\ : + | inheritance kind is ignored on an enum specifier + * - ``1723``\ + - | ``extended_modifier_ignored_on_enum``\ : + | modifier is ignored on an enum specifier + * - ``1724``\ + - | ``non_unicode_char_in_ident``\ : + | identifier character cannot be represented in Unicode + * - ``1725``\ + - | ``non_unicode_char_in_header``\ : + | header name contains characters that cannot be represented in Unicode + * - ``1726``\ + - | ``invalid_locale``\ : + | *"xxxx"*\ is not a valid locale name + * - ``1727``\ + - | ``nonstd_template_void_param_list``\ : + | declaring a void parameter list with a template parameter is + nonstandard + * - ``1728``\ + - | ``cl_lambdas_option_only_in_cplusplus``\ : + | lambdas option can be used only when compiling C++ + * - ``1729``\ + - | ``capture_mode_matches_default``\ : + | explicit capture matches default + * - ``1730``\ + - | ``not_a_variable``\ : + | *entity-kind "entity"*\ is not a variable + * - ``1731``\ + - | ``capture_of_static_duration_variable``\ : + | a variable with static storage duration cannot be captured in a lambda + * - ``1732``\ + - | ``cannot_capture_this_by_reference``\ : + | "this" cannot be captured by reference + * - ``1733``\ + - | ``this_in_lambda``\ : + | "this" cannot be used inside the body of this lambda + * - ``1734``\ + - | ``anon_union_ref_in_lambda``\ : + | a member of an outer-scope anonymous union cannot be referenced + inside the body of a lambda + * - ``1735``\ + - | ``not_captured_local_var_in_lambda``\ : + | an enclosing-function local variable cannot be referenced in a lambda + body unless it is in the capture list + * - ``1736``\ + - | ``bad_local_var_in_lambda``\ : + | invalid reference to an outer-scope local variable in a lambda body + * - ``1737``\ + - | ``captured_local_var_not_in_innermost_function``\ : + | a local variable outside the current function scope cannot be captured + * - ``1738``\ + - | ``not_captured_this_in_lambda``\ : + | the enclosing-function "this" cannot be referenced in a lambda body + unless it is in the capture list + * - ``1740``\ + - | ``captured_var_type_not_copyable``\ : + | lambda captured variable of type *"type"*\ cannot be copied to + closure class field of type *"type"*\ + * - ``1741``\ + - | ``cl_invalid_template_directory``\ : + | invalid template directory: *xxxx*\ + * - ``1749``\ + - | ``enum_value_out_of_underlying_range``\ : + | enumeration value is outside the range of its underlying type + (*"type"*\ ) + * - ``1750``\ + - | ``not_a_line_splice``\ : + | "\" followed by white space is not a line splice + * - ``1751``\ + - | ``dynamic_cast_without_rtti``\ : + | this dynamic_cast cannot be done without runtime type information, + which is disabled + * - ``1752``\ + - | ``ambiguous_cast_selects_direct_base``\ : + | conversion to *"type"*\ is ambiguous; direct base selected + * - ``1753``\ + - | ``requested_size_too_large``\ : + | an internal buffer would be too large + * - ``1754``\ + - | ``exception_handler_used``\ : + | C++ exception handler used, but exception handling semantics have not + been specified + * - ``1755``\ + - | ``type_qualifier_ignored_on_constructor``\ : + | type qualifier ignored on constructor + * - ``1756``\ + - | ``lambda_capture_involves_variable_length_array``\ : + | a variable captured by a lambda cannot have a type involving a + variable-length array + * - ``1757``\ + - | ``incompatible_vectors_conversion``\ : + | conversion between incompatible vector types + * - ``1758``\ + - | ``missing_lambda_body``\ : + | expected a "{" introducing a lambda body + * - ``1759``\ + - | ``cl_rvalue_references_option_only_in_cplusplus``\ : + | rvalue references option can be used only when compiling C++ + * - ``1760``\ + - | ``type_qualifier_on_lambda``\ : + | a type qualifier is not allowed on a lambda + * - ``1761``\ + - | ``more_than_one_capture``\ : + | a name cannot appear more than once in a capture-list + * - ``1762``\ + - | ``explicit_template_args_ignored``\ : + | explicit template arguments ignored + * - ``1763``\ + - | ``bad_constant_lambda``\ : + | a lambda is not allowed in a constant expression + * - ``1764``\ + - | ``class_type_required``\ : + | *"type"*\ is not a class type + * - ``1765``\ + - | ``delete_of_array_type``\ : + | "delete" applied to a pointer-to-array type treated as delete[] + * - ``1766``\ + - | ``delete_of_array_type_nonstandard``\ : + | "delete" applied to a pointer-to-array type is nonstandard; treated + as delete[] + * - ``1767``\ + - | ``function_does_not_match_arguments``\ : + | *entity-kind "entity"*\ cannot be called with the given argument list + * - ``1768``\ + - | ``rvalue_reference_bound_to_lvalue``\ : + | an rvalue reference cannot be bound to an lvalue + * - ``1769``\ + - | ``rvalue_ref_template_parameter``\ : + | a nontype template parameter cannot have rvalue reference type + * - ``1770``\ + - | ``type_qualifiers_ignored_on_reference``\ : + | type qualifiers are ignored (underlying type is a reference) + * - ``1771``\ + - | ``decl_with_local_type_but_not_defined``\ : + | *entity-kind "entity"*\ , declared using a local type, must be + defined in this translation unit + * - ``1772``\ + - | ``decl_with_no_linkage_type_but_not_defined``\ : + | *entity-kind "entity"*\ , declared using a type with no linkage, must + be defined in this translation unit + * - ``1773``\ + - | ``bad_rvalue_ref_dynamic_cast_operand``\ : + | the operand of an rvalue reference dynamic_cast must have a complete + class type + * - ``1774``\ + - | ``invalid_function_to_be_defaulted``\ : + | "= default" can only appear on default constructors, copy/move + constructors, copy/move assignment operators, and destructors + * - ``1775``\ + - | ``deleted_function_definition_must_be_first_declaration``\ : + | "= delete" can only appear on the first declaration of a function + * - ``1776``\ + - | ``deleted_function``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot be + referenced -- it is a deleted function + * - ``1777``\ + - | ``bad_unevaluated_lambda``\ : + | a lambda is not allowed in an unevaluated expression + * - ``1778``\ + - | ``bad_function_for_gnu_va_arg_pack``\ : + | __builtin_va_arg_pack/\__builtin_va_arg_pack_len can appear only in + an inline function with an ellipsis parameter + * - ``1779``\ + - | ``function_defaulted_in_friend_decl``\ : + | "= default" cannot be specified on a friend declaration + * - ``1780``\ + - | ``exp_cpp_keyword``\ : + | expected a C++ keyword + * - ``1782``\ + - | ``nonconstant_offsetof``\ : + | offset is not constant + * - ``1783``\ + - | ``unrecognized_microsoft_comment_pragma_type``\ : + | unrecognized #pragma comment type *"xxxx"*\ + * - ``1784``\ + - | ``cl_auto_type_option_only_in_cplusplus``\ : + | option to control whether "auto" is a type specifier can be used only + when compiling C++ + * - ``1785``\ + - | ``cl_auto_storage_option_only_in_cplusplus``\ : + | option to control whether "auto" is a storage class can be used only + when compiling C++ + * - ``1786``\ + - | ``cl_auto_cannot_be_disabled``\ : + | the type specifier and storage class specifier meanings of "auto" + cannot both be disabled + * - ``1787``\ + - | ``bad_pragma_comment_string``\ : + | invalid string in #pragma comment + * - ``1788``\ + - | ``deleted_function_overrides_nondeleted_function``\ : + | deleted function overrides nondeleted *entity-kind "entity"*\ + * - ``1789``\ + - | ``nondeleted_function_overrides_deleted_function``\ : + | nondeleted function overrides deleted *entity-kind "entity"*\ + * - ``1790``\ + - | ``deleted_default_constructor``\ : + | the default constructor of *"type"*\ cannot be referenced -- it is a + deleted function + * - ``1791``\ + - | ``rvalue_reference_catch_type``\ : + | an rvalue reference is not allowed as a catch type + * - ``1792``\ + - | ``default_args_incompatible``\ : + | default arguments of *entity-kind "entity"*\ is incompatible with a + declaration in another translation unit + * - ``1793``\ + - | ``default_arg_differs_in_other_trans_unit``\ : + | default arguments of *entity-kind "entity"*\ were different during + compilation of *"xxxx"*\ + * - ``1795``\ + - | ``initializers_incompatible``\ : + | initializer for *entity-kind "entity"*\ is different in another + translation unit + * - ``1796``\ + - | ``initializer_differs_in_other_trans_unit``\ : + | initializer for *entity-kind "entity"*\ was different during + compilation of *"xxxx"*\ + * - ``1797``\ + - | ``designator_for_template_dependent_type``\ : + | a designator into a template-dependent type is not allowed + * - ``1798``\ + - | ``invalid_pragma_conform_kind``\ : + | unrecognized conformance kind + * - ``1799``\ + - | ``exp_on_or_off``\ : + | expected "on" or "off" + * - ``1800``\ + - | ``forScope_stack_empty``\ : + | #pragma conform(forScope) stack is empty + * - ``1801``\ + - | ``no_matching_forScope_stack_entry``\ : + | no previous #pragma conform(forScope) entry matches *"xxxx"*\ + * - ``1802``\ + - | ``show_pragma_conform_forScope_is_nonstandard``\ : + | forScope behavior is nonstandard + * - ``1803``\ + - | ``show_pragma_conform_forScope_is_standard``\ : + | forScope behavior is standard + * - ``1804``\ + - | ``deleted_main``\ : + | function "main" cannot be deleted + * - ``1805``\ + - | ``useless_type_qualifiers_in_type_name``\ : + | type qualifiers are meaningless here + * - ``1806``\ + - | ``invalid_assignment_operator_to_be_defaulted``\ : + | invalid type for defaulted assignment operator + * - ``1807``\ + - | ``function_template_cannot_be_defaulted``\ : + | function templates cannot be defaulted + * - ``1808``\ + - | ``invalid_constructor_to_be_defaulted``\ : + | invalid type for defaulted constructor + * - ``1809``\ + - | ``call_requires_one_argument``\ : + | function call requires one argument + * - ``1810``\ + - | ``call_requires_floating_point_argument``\ : + | function call requires a real floating-point argument + * - ``1811``\ + - | ``copy_ctor_with_default_arg_cannot_be_defaulted``\ : + | a copy constructor with a default argument cannot be defaulted + * - ``1812``\ + - | ``predeclared_function_cannot_be_deleted``\ : + | a predeclared function cannot be deleted + * - ``1813``\ + - | ``empty_then_statement``\ : + | empty dependent statement in if-statement + * - ``1814``\ + - | ``empty_else_statement``\ : + | empty dependent statement in "else" clause of if-statement + * - ``1815``\ + - | ``deleted_elided_cctor``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ), required for + copy that was eliminated, cannot be referenced -- it is a deleted + function + * - ``1816``\ + - | ``main_first_param_not_int``\ : + | nonstandard first parameter *"type"*\ of "main", expected "int" + * - ``1817``\ + - | ``main_wrong_num_params``\ : + | nonstandard number of parameters for "main", expected zero or two + parameters + * - ``1818``\ + - | ``main_second_param_wrong_type``\ : + | nonstandard second parameter *"type"*\ of "main", expected "char + \*[]" or "char \*\*" + * - ``1819``\ + - | ``incl_dir_both_sys_and_nonsys``\ : + | *"xxxx"*\ was specified as both a system and non-system include + directory -- the non-system entry will be ignored + * - ``1820``\ + - | ``cl_rvalue_ctor_is_copy_ctor_option_only_in_cplusplus``\ : + | option to control move constructors and move assignment operators can + be used only when compiling C++ + * - ``1823``\ + - | ``trailing_return_type_requires_auto``\ : + | a trailing return type requires the "auto" type specifier + * - ``1824``\ + - | ``trailing_return_type_in_nested_declarator``\ : + | a trailing return type cannot appear in a nested declarator + * - ``1825``\ + - | ``trailing_return_type_function_without_simple_auto``\ : + | a function declarator with a trailing return type must be preceded by + a simple "auto" type specifier + * - ``1826``\ + - | ``missing_trailing_return_type``\ : + | "auto" function requires a trailing return type + * - ``1827``\ + - | ``pure_virtual_member_template``\ : + | a member template cannot have a pure specifier + * - ``1828``\ + - | ``excess_characters_in_literal_ignored``\ : + | string literal too long -- excess characters ignored + * - ``1830``\ + - | ``nullptr_conv_to_bool``\ : + | std::nullptr_t converted to bool + * - ``1833``\ + - | ``invalid_empty_attribute_arg_list``\ : + | attribute *"xxxx"*\ does not allow an empty argument list + * - ``1834``\ + - | ``attr_twice_in_group``\ : + | attribute appears more than once + * - ``1835``\ + - | ``wrong_entity_for_attribute``\ : + | attribute *"xxxx"*\ does not apply here + * - ``1836``\ + - | ``attr_disallows_bit_field``\ : + | attribute *"xxxx"*\ does not apply to bit fields + * - ``1837``\ + - | ``attr_requires_bit_field``\ : + | attribute *"xxxx"*\ requires a bit field + * - ``1838``\ + - | ``attr_disallows_member_function``\ : + | attribute *"xxxx"*\ does not apply to member functions + * - ``1839``\ + - | ``attr_requires_member_function``\ : + | attribute *"xxxx"*\ requires a member function + * - ``1840``\ + - | ``attr_disallows_virtual_function``\ : + | attribute *"xxxx"*\ does not apply to virtual functions + * - ``1841``\ + - | ``attr_requires_virtual_function``\ : + | attribute *"xxxx"*\ requires a virtual function + * - ``1842``\ + - | ``attr_disallows_pure_virtual_function``\ : + | attribute *"xxxx"*\ does not apply to pure virtual functions + * - ``1843``\ + - | ``attr_requires_pure_virtual_function``\ : + | attribute *"xxxx"*\ requires a pure virtual function + * - ``1844``\ + - | ``attr_disallows_register_storage``\ : + | attribute *"xxxx"*\ does not apply to register variables + * - ``1845``\ + - | ``attr_requires_register_storage``\ : + | attribute *"xxxx"*\ requires a register variable + * - ``1846``\ + - | ``attr_must_also_appear_in_first_declaration``\ : + | attribute *"xxxx"*\ did not appear on original declaration + * - ``1847``\ + - | ``invalid_attribute_location``\ : + | attributes are not allowed here + * - ``1848``\ + - | ``attr_must_appear_in_class_definition``\ : + | attribute *"xxxx"*\ must appear in a class definition + * - ``1849``\ + - | ``pure_final_virtual``\ : + | "final" applied to a pure virtual function + * - ``1850``\ + - | ``override_of_final_function``\ : + | cannot override "final" *entity-kind "entity"*\ (declared at line + *xxxx*\ ) + * - ``1851``\ + - | ``undefined_static_function_treated_as_extern``\ : + | static *entity-kind "entity"*\ treated as extern because it was + referenced but not defined + * - ``1852``\ + - | ``cl_gnu_c89_inlining_option_only_in_C``\ : + | option to enable GNU-C89-style inlining can be used only when + compiling C + * - ``1853``\ + - | ``first_decl_not_gnu_inline``\ : + | function was previously declared without the "gnu_inline" attribute + * - ``1854``\ + - | ``gnu_inline_requires_inline``\ : + | the "gnu_inline" attribute is ignored on non-inline functions + * - ``1855``\ + - | ``carries_dependency_not_on_first_decl``\ : + | *entity-kind "entity"*\ previously declared without the + carries_dependency attribute + * - ``1856``\ + - | ``bad_array_member_initialization``\ : + | invalid initializer for array *entity-kind "entity"*\ + * - ``1857``\ + - | ``cl_must_specify_cpp11_mode``\ : + | must specify C++11 or C++14 mode when building runtime library + * - ``1858``\ + - | ``attr_disallows_function_type``\ : + | attribute *"xxxx"*\ does not apply to function types + * - ``1859``\ + - | ``attr_requires_function_type``\ : + | attribute *"xxxx"*\ requires a function type + * - ``1860``\ + - | ``attribute_ignored_on_nonstatic_member_function``\ : + | attribute *"xxxx"*\ does not apply to nonstatic member functions + * - ``1861``\ + - | ``attr_disallows_automatic_storage``\ : + | attribute *"xxxx"*\ does not apply to automatic variables + * - ``1862``\ + - | ``attr_requires_automatic_storage``\ : + | attribute *"xxxx"*\ requires an automatic variable + * - ``1863``\ + - | ``attr_disallows_external_linkage``\ : + | attribute *"xxxx"*\ does not apply to a variable or function with + external linkage + * - ``1864``\ + - | ``attr_requires_local_variable``\ : + | attribute *"xxxx"*\ requires a local variable + * - ``1865``\ + - | ``attributes_ignored``\ : + | attributes ignored here + * - ``1866``\ + - | ``unattached_attribute``\ : + | attribute does not apply to any entity + * - ``1867``\ + - | ``bad_attribute_template_substitution``\ : + | bad attribute argument substitution + * - ``1868``\ + - | ``bad_tls_model_attr_arg``\ : + | the argument of the "tls_model" attribute must be "global-dynamic", + "local-dynamic", "initial-exec", or "local-exec" + * - ``1869``\ + - | ``inconsistent_tls_model_attr_arg``\ : + | the declaration at line *xxxx*\ specified a different "tls_model" + argument + * - ``1870``\ + - | ``attr_disallows_inline``\ : + | attribute *"xxxx"*\ does not apply to inline functions + * - ``1871``\ + - | ``attr_requires_inline``\ : + | attribute *"xxxx"*\ requires a inline function + * - ``1872``\ + - | ``include_kind_mismatch``\ : + | both file names in an include_alias pragma must use the same + delimiter characters + * - ``1873``\ + - | ``signed_unsigned_comparison``\ : + | comparison between signed and unsigned operands + * - ``1874``\ + - | ``attribute_ignored_on_unnamed_type``\ : + | attribute *"xxxx"*\ ignored on unnamed type + * - ``1875``\ + - | ``attribute_ignored_on_nondefinition``\ : + | attribute *"xxxx"*\ ignored because no definition follows + * - ``1876``\ + - | ``incompatible_thread_locality``\ : + | thread locality is incompatible with a previous declaration of + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``1877``\ + - | ``no_implicit_capture_on_enclosing_lambda``\ : + | this enclosing-function local variable cannot be referenced in this + lambda body because an enclosing lambda does not allow implicit + captures + * - ``1878``\ + - | ``unbalanced_attribute_argument``\ : + | this attribute argument contains unmatched parentheses, brackets, or + braces + * - ``1879``\ + - | ``invalid_builtin_fpclassify_args``\ : + | a call to \__builtin_fpclassify requires five integral arguments + followed by one floating-point argument + * - ``1880``\ + - | ``bad_final_builtin_fpclassify_arg``\ : + | the last argument in a call to \__builtin_fpclassify must have a real + floating-point type + * - ``1881``\ + - | ``invalid_alignment_reducing_attr``\ : + | alignment cannot be set to less than the default alignment + * - ``1882``\ + - | ``attribute_on_explicit_instantiation``\ : + | attributes are not allowed on explicit instantiations + * - ``1883``\ + - | ``attr_disallows_definition``\ : + | attribute *"xxxx"*\ does not apply to a definition + * - ``1884``\ + - | ``attr_requires_definition``\ : + | attribute *"xxxx"*\ requires a definition + * - ``1885``\ + - | ``friend_attribute_requires_definition``\ : + | standard attributes cannot appear on friend declarations that are not + definitions + * - ``1886``\ + - | ``inconsistent_alignment``\ : + | specified alignment (*xxxx*\ ) is different from alignment (*xxxx*\ ) + specified on a previous declaration + * - ``1887``\ + - | ``variable_align_attr_not_on_definition``\ : + | alignment attribute must also appear on definition at line *xxxx*\ + * - ``1888``\ + - | ``alias_used_in_type``\ : + | *entity-kind "entity"*\ may not be used in the type-id of the + alias-declaration + * - ``1890``\ + - | ``transparent_union_cannot_have_floating_first_field``\ : + | *"type"*\ cannot be transparent because its first field has a + floating-point type + * - ``1891``\ + - | ``transparent_union_cannot_have_bit_field_first``\ : + | *"type"*\ cannot be transparent because its first field is a bit + field + * - ``1892``\ + - | ``missing_override_attr_in_base_check_class``\ : + | virtual function of a "base_check" class overrides a base class + member but lacks the "override" attribute + * - ``1893``\ + - | ``hiding_attr_on_nonhiding_member``\ : + | "hiding" attribute specified on a declaration that does not hide a + base class declaration + * - ``1894``\ + - | ``hiding_attr_on_unhidden_member``\ : + | "hiding" attribute specified on a declaration referred to by the + using-declaration at line *xxxx*\ + * - ``1895``\ + - | ``hiding_attr_required``\ : + | attribute "hiding" is required on a declaration (in a "base_check" + class) that hides *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``1896``\ + - | ``undefined_decl_using_local_type``\ : + | *entity-kind "entity"*\ is not defined in this translation unit but + depends on a local type + * - ``1897``\ + - | ``undefined_decl_using_no_linkage_type``\ : + | *entity-kind "entity"*\ is not defined in this translation unit but + depends on a type with no linkage + * - ``1898``\ + - | ``missing_attribute_in_other_translation_unit``\ : + | attribute *"xxxx"*\ is missing in another translation unit + * - ``1899``\ + - | ``conflicting_attribute_in_other_translation_unit``\ : + | attribute *"xxxx"*\ conflicts with another translation unit + * - ``1900``\ + - | ``cl_nonstd_gnu_keywords_requires_gnu_mode``\ : + | the "nonstd_gnu_keywords" option is only valid in GNU C and GNU C++ + modes + * - ``1901``\ + - | ``const_var_in_C_const_expr``\ : + | use of a const variable in a constant expression is nonstandard in C + * - ``1902``\ + - | ``cannot_init_auto_flexible_array_member``\ : + | an initializer cannot be specified for a flexible array member with + automatic storage duration + * - ``1904``\ + - | ``final_base_class``\ : + | a "final" class type cannot be used as a base class + * - ``1905``\ + - | ``export_removed``\ : + | exported templates are no longer in the standard C++ language + * - ``1906``\ + - | ``template_dependent_designator``\ : + | a template-dependent designator is not allowed + * - ``1907``\ + - | ``offsetof_ref_field``\ : + | second operand of offsetof may not be a field with reference type + * - ``1908``\ + - | ``cl_long_lifetime_temps_incompat_with_newer_features``\ : + | long lifetime temporaries are incompatible with other requested newer + language features + * - ``1909``\ + - | ``wide_deprecation_string``\ : + | wide character string literal will not be quoted in diagnostics + * - ``1910``\ + - | ``missing_attribute_arguments``\ : + | missing arguments for attribute *"xxxx"*\ + * - ``1911``\ + - | ``sfinae_requires_newer_abi_version``\ : + | options "c++11" and "c++11_sfinae" require a different compiler + configuration + * - ``1912``\ + - | ``template_param_pack_not_at_end``\ : + | template parameter pack not at end of parameter list + * - ``1913``\ + - | ``parameter_pack_decl_not_allowed``\ : + | a parameter pack declaration is not allowed here + * - ``1914``\ + - | ``param_pack_cannot_have_default``\ : + | a parameter pack cannot have a default + * - ``1915``\ + - | ``cl_cppcli_only_in_microsoft_cplusplus``\ : + | C++/CLI can be enabled only in Microsoft C++ mode + * - ``1916``\ + - | ``reserved_enumerator_name``\ : + | "value\__" cannot be used as the name of an enumerator constant (it + is a reserved name in this context) + * - ``1917``\ + - | ``cppcli_enumerator_requires_explicit_value``\ : + | an explicit enumerator value is required in an enum type with boolean + underlying type + * - ``1919``\ + - | ``pack_not_expanded``\ : + | parameter pack *"xxxx"*\ was referenced but not expanded + * - ``1920``\ + - | ``expansion_contains_no_packs``\ : + | pack expansion does not make use of any argument packs + * - ``1921``\ + - | ``pack_length_mismatch``\ : + | pack *"xxxx"*\ does not have the same number of elements as + *"xxxx"*\ + * - ``1923``\ + - | ``vector_size_attribute_on_enum_type``\ : + | vector_size attribute is not allowed with an enum type + * - ``1924``\ + - | ``virtual_static_property``\ : + | a property cannot be both static and virtual + * - ``1925``\ + - | ``trivial_indexed_property``\ : + | an indexed property cannot be trivial + * - ``1926``\ + - | ``invalid_property_accessor_decl``\ : + | this declaration cannot appear in a property definition + * - ``1927``\ + - | ``qualified_cli_accessor``\ : + | a qualified function type cannot be used to declare an accessor + function + * - ``1928``\ + - | ``ellipsis_cli_accessor``\ : + | an accessor function cannot have an ellipsis parameter + * - ``1929``\ + - | ``property_get_already_declared``\ : + | a "get" accessor was already declared for this property at line + *xxxx*\ + * - ``1930``\ + - | ``property_set_already_declared``\ : + | a "set" accessor was already declared for this property at line + *xxxx*\ + * - ``1931``\ + - | ``property_get_cannot_have_parameter``\ : + | a "get" accessor cannot have a parameter + * - ``1932``\ + - | ``bad_property_get_return``\ : + | return type of "get" accessor does not match property type + * - ``1933``\ + - | ``bad_property_set_return``\ : + | return type of "set" accessor must be void + * - ``1934``\ + - | ``empty_property_indices``\ : + | a property cannot declare an empty list of indices + * - ``1935``\ + - | ``void_property_index_type``\ : + | a property index cannot have type void + * - ``1936``\ + - | ``property_set_index_type_mismatch``\ : + | index type does not match the corresponding parameter in the "set" + accessor + * - ``1937``\ + - | ``property_get_index_type_mismatch``\ : + | index type does not match the corresponding parameter in the "get" + accessor + * - ``1938``\ + - | ``property_set_index_type_missing``\ : + | index type is missing in the "set" accessor + * - ``1939``\ + - | ``property_get_index_type_missing``\ : + | index type is missing in the "get" accessor + * - ``1940``\ + - | ``property_set_missing_value_parameter``\ : + | "set" accessor is missing its value parameter + * - ``1941``\ + - | ``extra_property_accessor_parameters``\ : + | accessor function has too many parameters + * - ``1942``\ + - | ``property_set_value_parameter_mismatch``\ : + | the last parameter of the "set" accessor does not match the property + type + * - ``1943``\ + - | ``cppcli_not_enabled``\ : + | *"xxxx"*\ requires C++/CLI mode + * - ``1944``\ + - | ``win32_api_error``\ : + | error in Win32 API "*xxxx*\ ": *xxxx*\ + * - ``1945``\ + - | ``using_not_at_file_scope``\ : + | #using may only be used at global scope + * - ``1947``\ + - | ``member_name_reserved_by_property``\ : + | member name *"xxxx"*\ is reserved by *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``1948``\ + - | ``exp_lbracket``\ : + | expected a "[" + * - ``1949``\ + - | ``cl_microsoft_version_insufficient_for_cppcli``\ : + | C++/CLI mode requires microsoft_version >= 1600 + * - ``1950``\ + - | ``static_default_indexed_property``\ : + | a default-indexed property cannot be static + * - ``1951``\ + - | ``virtual_static_property_accessor``\ : + | a property accessor cannot be both static and virtual + * - ``1952``\ + - | ``visibility_specifier_on_nested_type``\ : + | a top-level visibility specifier cannot appear on a nested type + declaration + * - ``1953``\ + - | ``visibility_specifier_requires_definition``\ : + | a top-level visibility specifier requires a type definition + * - ``1954``\ + - | ``trivial_reference_property``\ : + | a trivial property cannot have a reference type + * - ``1955``\ + - | ``trivial_const_or_volatile_property``\ : + | a trivial property cannot have a const or volatile type + * - ``1956``\ + - | ``incompatible_enum_kinds``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared as a different kind of enum type + * - ``1957``\ + - | ``lambda_captures_managed_class_type``\ : + | a variable captured by a lambda cannot have a managed class type + * - ``1958``\ + - | ``covariant_override_in_managed_class``\ : + | virtual function overriding with a covariant return type is not + allowed in a managed class + * - ``1959``\ + - | ``array_of_handle``\ : + | array of handles is not allowed + * - ``1960``\ + - | ``handle_to_array``\ : + | handle to array is not allowed + * - ``1961``\ + - | ``handle_to_function``\ : + | handle to function is not allowed + * - ``1962``\ + - | ``handle_to_void``\ : + | handle to void is not allowed + * - ``1963``\ + - | ``handle_to_address_type``\ : + | handle to handle, pointer, or reference is not allowed + * - ``1964``\ + - | ``tracking_reference_to_function``\ : + | tracking reference to function is not allowed + * - ``1966``\ + - | ``field_cannot_be_tracking_reference``\ : + | a field cannot be a tracking reference + * - ``1967``\ + - | ``invalid_ref_tracking_ref_combination``\ : + | a tracking reference cannot be combined with an ordinary reference in + this way + * - ``1968``\ + - | ``static_storage_variable_with_ref_class_type``\ : + | a variable with static storage duration cannot have a ref class type + * - ``1969``\ + - | ``unnamed_cli_managed_class_type``\ : + | a managed class cannot be unnamed + * - ``1970``\ + - | ``local_cli_managed_class_type``\ : + | a managed class cannot be local + * - ``1971``\ + - | ``conflicting_cli_class_type_kinds``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared as a different kind of class + * - ``1972``\ + - | ``conflicting_cli_class_template_kinds``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared as a different kind of class template + * - ``1973``\ + - | ``literal_requires_managed_class``\ : + | literal data members can only be members of managed classes + * - ``1974``\ + - | ``literal_without_initializer``\ : + | a literal data member must be initialized + * - ``1975``\ + - | ``invalid_literal_type``\ : + | a literal data member of type *"type"*\ is not allowed + * - ``1976``\ + - | ``literal_const_has_no_effect``\ : + | const has no effect on a literal data member + * - ``1977``\ + - | ``initonly_requires_managed_class``\ : + | initonly data members can only be members of managed classes + * - ``1978``\ + - | ``initonly_const_has_no_effect``\ : + | const has no effect on an initonly data member + * - ``1979``\ + - | ``cli_get_accessor_missing``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) has no "get" + accessor + * - ``1980``\ + - | ``cli_set_accessor_missing``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) has no "set" + accessor + * - ``1981``\ + - | ``static_constructor_with_params``\ : + | a static constructor cannot have parameters + * - ``1982``\ + - | ``static_constructor_member_template``\ : + | a static constructor cannot be a member template + * - ``1983``\ + - | ``compound_lvalue_as_asm_operand``\ : + | a compound lvalue is not allowed as an asm output operand + * - ``1984``\ + - | ``property_requires_managed_class``\ : + | properties can only be members of managed classes + * - ``1985``\ + - | ``qualifier_not_allowed_on_managed_member_function``\ : + | a type qualifier is not allowed on a member function of a managed + class + * - ``1986``\ + - | ``pointer_to_ref_or_interface_class``\ : + | an ordinary pointer to a C++/CLI ref class or interface class is not + allowed + * - ``1987``\ + - | ``reference_to_ref_or_interface_class``\ : + | an ordinary reference to a C++/CLI ref class or interface class is + not allowed + * - ``1988``\ + - | ``override_name_must_be_a_base_class_member_function``\ : + | override specifier does not name a base class member function + * - ``1989``\ + - | ``override_name_nonvirtual``\ : + | override specifier designates a nonvirtual member *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``1990``\ + - | ``multiple_overrides``\ : + | member function overrides *entity-kind "entity"*\ (declared at line + *xxxx*\ ) which is already overridden by *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``1991``\ + - | ``multiple_visibility_specifiers``\ : + | at most one visibility specifier is allowed + * - ``1992``\ + - | ``invalid_delegate_type``\ : + | type *"type"*\ used for delegate definition is not a function type + * - ``1993``\ + - | ``delegate_requires_managed_class``\ : + | delegate member types can only be members of managed classes + * - ``1994``\ + - | ``tracking_reference_to_delegate``\ : + | a tracking reference to a delegate type is not allowed + * - ``1995``\ + - | ``bad_use_of_delegate_type``\ : + | a delegate type is not allowed here + * - ``1996``\ + - | ``empty_pack_expansion``\ : + | this pack expansion produced an empty list of expressions, and an + expression is needed here + * - ``1997``\ + - | ``virtual_static_event``\ : + | an event cannot be both static and virtual + * - ``1998``\ + - | ``event_requires_managed_class``\ : + | events can only be members of managed classes + * - ``1999``\ + - | ``invalid_event_accessor_decl``\ : + | this declaration cannot appear in an event definition + * - ``2000``\ + - | ``invalid_event_type``\ : + | event type must be a handle-to-delegate type + * - ``2001``\ + - | ``event_add_already_declared``\ : + | an "add" accessor was already declared for this event at line *xxxx*\ + * - ``2002``\ + - | ``event_remove_already_declared``\ : + | a "remove" accessor was already declared for this event at line + *xxxx*\ + * - ``2003``\ + - | ``event_raise_already_declared``\ : + | a "raise" accessor was already declared for this event at line + *xxxx*\ + * - ``2004``\ + - | ``virtual_static_event_accessor``\ : + | an event accessor cannot be both static and virtual + * - ``2005``\ + - | ``bad_event_add_or_remove_return``\ : + | return type of "add" and "remove" accessors must be void + * - ``2006``\ + - | ``event_accessor_missing_value_parameter``\ : + | event accessor is missing its value parameter + * - ``2007``\ + - | ``extra_event_accessor_parameters``\ : + | accessor function has too many parameters + * - ``2008``\ + - | ``event_accessor_value_parameter_mismatch``\ : + | the type *"type"*\ of the parameter of the event accessor does not + match the event type (*"type"*\ ) + * - ``2009``\ + - | ``event_raise_type_mismatch``\ : + | the type of the "raise" accessor does not match the event's delegate + invocation type + * - ``2010``\ + - | ``missing_add_or_remove_accessor``\ : + | an event definition must include both "add" and "remove" accessors + * - ``2011``\ + - | ``static_conversion_function_must_have_one_parameter``\ : + | a static conversion function must accept exactly one argument + * - ``2012``\ + - | ``bad_parameter_type_for_static_member_operator``\ : + | static operator must have a parameter type T, T&, T%, or T^ with T = + *"type"*\ + * - ``2013``\ + - | ``sizeof_operand_not_parameter_pack``\ : + | the operand of sizeof... must be a parameter pack name + * - ``2014``\ + - | ``sizeof_pack_in_non_variadic_context``\ : + | the sizeof... operator can be used only in a variadic template + * - ``2015``\ + - | ``event_name_not_allowed``\ : + | event name cannot appear here + * - ``2016``\ + - | ``handle_to_standard_class_type``\ : + | a handle to a non-managed class is not allowed + * - ``2017``\ + - | ``handle_to_unscoped_enum_type``\ : + | a handle to an unscoped enum type is not allowed + * - ``2018``\ + - | ``property_attribute_in_managed_class``\ : + | "property" attribute not allowed in managed class + * - ``2019``\ + - | ``pure_virtual_definition``\ : + | a pure specifier ("= 0") followed by a definition is nonstandard + * - ``2020``\ + - | ``managed_nullptr_not_allowed``\ : + | the managed nullptr type cannot be used here + * - ``2021``\ + - | ``addr_of_ref_class``\ : + | the "&" operator cannot be used to take the address of an object with + a ref class type + * - ``2022``\ + - | ``array_of_managed_class``\ : + | array of managed class is not allowed + * - ``2023``\ + - | ``static_storage_variable_with_handle_or_tracking_ref_type``\ : + | a variable with static storage duration cannot have a handle or + tracking reference type + * - ``2024``\ + - | ``lambda_captures_handle_or_tracking_ref``\ : + | a variable captured by a lambda cannot be a handle or tracking + reference + * - ``2025``\ + - | ``invalid_param_array_type``\ : + | a C++/CLI parameter array requires a handle to a one-dimensional + cli::array type + * - ``2026``\ + - | ``cannot_import_metadata``\ : + | could not import metadata from file *"xxxx"*\ + * - ``2027``\ + - | ``namespace_cli_cannot_be_extended``\ : + | the cli namespace cannot be extended + * - ``2028``\ + - | ``cli_array_invalid_element_type``\ : + | the element type of a cli::array must be a handle or value type + * - ``2029``\ + - | ``cli_array_invalid_number_of_dimensions``\ : + | invalid number of dimensions for cli::array type + * - ``2030``\ + - | ``invalid_type_pointed_to_for_interior_ptr_or_pin_ptr``\ : + | a cli::interior_ptr/cli::pin_ptr must point to a standard class, a + value class, an integer, a handle, or a standard pointer + * - ``2031``\ + - | ``type_cannot_be_class_member``\ : + | *"type"*\ cannot be a class member + * - ``2032``\ + - | ``pin_ptr_param_not_allowed``\ : + | a parameter of type cli::pin_ptr is not allowed + * - ``2033``\ + - | ``bad_finalizer_decl``\ : + | invalid finalizer declaration + * - ``2034``\ + - | ``too_many_params_for_finalizer``\ : + | a finalizer may not have parameters + * - ``2035``\ + - | ``function_qualifier_on_finalizer``\ : + | a type qualifier is not allowed on a finalizer + * - ``2036``\ + - | ``return_type_on_finalizer``\ : + | a return type may not be specified on a finalizer + * - ``2037``\ + - | ``no_finalizer_using_declaration``\ : + | a using-declaration may not name a finalizer + * - ``2038``\ + - | ``finalizer_name_must_be_qualified``\ : + | a finalizer name must be qualified + * - ``2039``\ + - | ``finalizer_qualifier_type_mismatch``\ : + | qualifier of finalizer name *"type"*\ does not match type *"type"*\ + * - ``2040``\ + - | ``var_used_as_finalizer``\ : + | *entity-kind "entity"*\ cannot be used to name a finalizer (a type + name is required) + * - ``2041``\ + - | ``invalid_finalizer_name``\ : + | invalid finalizer name for type *"type"*\ + * - ``2042``\ + - | ``ambiguous_finalizer``\ : + | finalizer reference is ambiguous -- both *entity-kind "entity"*\ and + *entity-kind "entity"*\ could be used + * - ``2043``\ + - | ``finalizer_requires_reference_type``\ : + | a finalizer can only be a member of a ref class + * - ``2045``\ + - | ``finalizer_type_mismatch``\ : + | type used as finalizer name does not match type *"type"*\ + * - ``2046``\ + - | ``finalizer_does_not_exist``\ : + | a finalizer does not exist for this type + * - ``2047``\ + - | ``handle_of_non_managed``\ : + | the "%" operator can be used only on an object with a managed class + type + * - ``2048``\ + - | ``ptr_handle_or_ref_to_interior_ptr``\ : + | a pointer, handle, or reference to a cli::interior_ptr is not allowed + * - ``2049``\ + - | ``ptr_handle_or_ref_to_pin_ptr``\ : + | a pointer, handle, or reference to a cli::pin_ptr is not allowed + * - ``2050``\ + - | ``ptr_or_ref_to_cli_array``\ : + | a pointer or reference to a C++/CLI array is not allowed + * - ``2051``\ + - | ``bad_use_of_cli_array_type``\ : + | a C++/CLI array type is not allowed here + * - ``2052``\ + - | ``invalid_ref_class_base``\ : + | a C++/CLI ref class can only derive from another ref class or from + interface classes + * - ``2053``\ + - | ``invalid_value_class_base``\ : + | a C++/CLI value class can only derive from interface classes + * - ``2054``\ + - | ``invalid_interface_class_base``\ : + | a C++/CLI interface class can only derive from interface classes + * - ``2055``\ + - | ``ref_class_has_multiple_ref_bases``\ : + | a ref class can have at most one direct ref base class (*"type"*\ is + already such a base) + * - ``2056``\ + - | ``managed_base_for_standard_class``\ : + | a standard class cannot derive from a managed class + * - ``2057``\ + - | ``virtual_base_for_managed_class``\ : + | a managed class cannot have a virtual base + * - ``2058``\ + - | ``managed_class_type_cannot_have_private_or_protected_base``\ : + | a managed class cannot have a "private" or "protected" base + * - ``2059``\ + - | ``override_requires_virtual``\ : + | the "override" modifier requires a virtual function declaration with + an explicit "virtual" keyword + * - ``2060``\ + - | ``abstract_requires_virtual``\ : + | the "abstract" modifier requires a virtual function declaration with + an explicit "virtual" keyword + * - ``2061``\ + - | ``sealed_requires_virtual``\ : + | the "sealed" modifier requires a virtual function declaration with an + explicit "virtual" keyword + * - ``2062``\ + - | ``named_override_requires_virtual``\ : + | a named override specifier requires a virtual function declaration + with an explicit "virtual" keyword + * - ``2063``\ + - | ``pin_ptr_return_type_not_allowed``\ : + | a cli::pin_ptr return type is not allowed + * - ``2064``\ + - | ``cppcli_attribute_only``\ : + | attribute *"xxxx"*\ applies in C++/CLI mode only + * - ``2065``\ + - | ``normal_ref_bound_to_gc_lvalue``\ : + | a simple (non-tracking) reference cannot be bound to an entity on the + managed heap + * - ``2067``\ + - | ``cli_entity_not_loaded``\ : + | "*xxxx*\ " not loaded from default assemblies + * - ``2068``\ + - | ``list_initializer_nonstandard_in_current_mode``\ : + | list initialization syntax is a C++11 feature + * - ``2069``\ + - | ``sizeof_ref_or_interface_class``\ : + | operand of sizeof may not be a ref class type or interface class type + * - ``2070``\ + - | ``cli_array_invalid_number_of_subscripts``\ : + | invalid number of subscripts for this cli::array type + * - ``2071``\ + - | ``ptr_to_member_of_managed_class``\ : + | a pointer-to-member is not valid for a managed class + * - ``2072``\ + - | ``private_virtual_member_function_not_sealed``\ : + | private virtual member function of managed class is not "sealed" + * - ``2073``\ + - | ``modifier_not_allowed_on_destructor``\ : + | modifier is not allowed on a destructor + * - ``2074``\ + - | ``modifier_not_allowed_on_finalizer``\ : + | modifier is not allowed on a finalizer + * - ``2075``\ + - | ``virtual_has_no_effect``\ : + | "virtual" has no effect on a destructor of a managed class + * - ``2076``\ + - | ``new_or_override_required``\ : + | "new" or "override" is required because this declaration matches + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``2077``\ + - | ``new_or_virtual_required``\ : + | "new" or "virtual" is required because this declaration matches + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``2078``\ + - | ``override_for_interface_member``\ : + | "new" or "override" are not valid here because the matching + *entity-kind "entity"*\ (declared at line *xxxx*\ ) is a member of + an interface + * - ``2079``\ + - | ``new_requires_matching_base_member``\ : + | "new" modifier without a matching base ref class member + * - ``2080``\ + - | ``overriding_reduces_accessibility_in_managed_type``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) overridden with + reduced access + * - ``2081``\ + - | ``bad_tracking_ref_init``\ : + | a reference of type *"type"*\ cannot be initialized with a value of + type *"type"*\ + * - ``2082``\ + - | ``copy_constructor_in_value_class_type``\ : + | a copy constructor cannot be declared in a value class + * - ``2083``\ + - | ``default_constructor_in_value_class_type``\ : + | a default constructor cannot be declared in a value class + * - ``2084``\ + - | ``destructor_in_value_class_type``\ : + | a destructor cannot be declared in a value class + * - ``2085``\ + - | ``assignment_in_value_class_type``\ : + | an assignment operator cannot be declared in a value class + * - ``2086``\ + - | ``nonvalue_class_type_cannot_be_value_class_member``\ : + | non-value class *"type"*\ cannot be the type of a member of a value + class + * - ``2087``\ + - | ``cppcli_requires_newer_abi_version``\ : + | option "cppcli" requires a different compiler configuration + * - ``2088``\ + - | ``managed_member_exception_spec``\ : + | exception specifications are not allowed on member functions of + managed classes + * - ``2089``\ + - | ``managed_class_cannot_have_friend``\ : + | a managed class cannot declare a friend + * - ``2092``\ + - | ``local_class_in_managed_member_function``\ : + | a local class definition is not allowed in a member function of a + managed class + * - ``2093``\ + - | ``local_lambda_in_managed_member_function``\ : + | a local lambda is not allowed in a member function of a managed class + * - ``2094``\ + - | ``cli_interface_member_function_definition``\ : + | a member function of a C++/CLI interface class type cannot have a + definition + * - ``2095``\ + - | ``missing_get_and_set_accessors``\ : + | a property definition must include at least one accessor ("get" or + "set") + * - ``2096``\ + - | ``subscript_mechanism_conflict``\ : + | default-indexed property conflicts with *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``2097``\ + - | ``unusable_pack``\ : + | *entity-kind "entity"*\ cannot be used because it follows a + parameter pack and cannot be deduced from the parameters of + *entity-kind "entity"*\ + * - ``2098``\ + - | ``excess_pack_expansion``\ : + | this pack expansion produced more than one expression, and a single + expression is needed here + * - ``2099``\ + - | ``cli_enum_base_has_no_system_counterpart``\ : + | type must correspond to System::Boolean, System::Byte, System::SByte, + System::Int16, System::UInt16, System::Int32, System::UInt32, + System::Int64, or System::UInt64 + * - ``2100``\ + - | ``bad_call_of_handle``\ : + | call of an object of a handle type without appropriate operator() or + conversion functions to pointer-to-function type + * - ``2101``\ + - | ``abstract_declarator_pack_is_nested``\ : + | an unnamed parameter pack declaration cannot be parenthesized + * - ``2102``\ + - | ``cl_variadic_templates_only_in_cplusplus``\ : + | variadic templates can be enabled only when compiling C++ + * - ``2103``\ + - | ``conflicting_properties``\ : + | property definition conflicts with *entity-kind "entity"*\ (declared + at line *xxxx*\ ) + * - ``2106``\ + - | ``generic_param_cannot_have_default``\ : + | a generic parameter cannot have a default + * - ``2107``\ + - | ``bad_param_kind_for_generic``\ : + | a generic can only have type parameters + * - ``2108``\ + - | ``for_each_missing_function``\ : + | to be used with "for each" statements, type *"type"*\ must provide + nonstatic member function *"xxxx"*\ + * - ``2109``\ + - | ``for_each_static_function``\ : + | "for each" cannot use member *entity-kind "entity"*\ because it is + static + * - ``2110``\ + - | ``for_each_no_matching_overload``\ : + | in this "for each" statement, no instance of *"entity"*\ is callable + with an empty argument list + * - ``2111``\ + - | ``for_each_invalid_return_type_for_move_next``\ : + | "for each" cannot use member function "MoveNext" because the return + type is invalid + * - ``2112``\ + - | ``for_each_incompatible_type``\ : + | a "for each" statement cannot operate on an expression of type + *"type"*\ + * - ``2113``\ + - | ``for_each_missing_field``\ : + | to be used with "for each" statements, type *"type"*\ must provide a + non-indexed property *"xxxx"*\ + * - ``2115``\ + - | ``for_each_getenumerator_return_type_invalid``\ : + | in this "for each" statement, *"type"*\ is not a valid enumerator + (returned by "GetEnumerator" of *"type"*\ ) + * - ``2116``\ + - | ``exp_in``\ : + | expected "in" + * - ``2117``\ + - | ``no_suitable_synthesis_assignment_operator``\ : + | class *"type"*\ has no suitable assignment operator (after operator + synthesis) + * - ``2118``\ + - | ``not_a_generic_param``\ : + | *"xxxx"*\ is not a generic parameter + * - ``2119``\ + - | ``not_generic_param_of_curr_decl``\ : + | *"xxxx"*\ is not a generic parameter of the innermost generic + parameter list + * - ``2120``\ + - | ``invalid_constraint``\ : + | invalid generic constraint + * - ``2121``\ + - | ``invalid_event_use``\ : + | invalid use of event member (only subscription, unsubscription, and + invocation are allowed) + * - ``2122``\ + - | ``event_without_raise_invoked``\ : + | invoking an event with no "raise" accessor is invalid + * - ``2123``\ + - | ``bad_event_compound_assignment``\ : + | only "+=" and "-=" are valid for events + * - ``2124``\ + - | ``typeid_of_managed_type``\ : + | typeid of a managed type is not allowed + * - ``2125``\ + - | ``cli_typeid_of_managed_pointer``\ : + | typeid of a managed pointer type is not allowed + * - ``2126``\ + - | ``name_before_typeid_not_type``\ : + | name followed by "::typeid" must be a type name + * - ``2127``\ + - | ``reserved_dispose``\ : + | a member *"xxxx"*\ of this type is reserved within a managed class + -- destructor intended? + * - ``2128``\ + - | ``reserved_finalize``\ : + | a member *"xxxx"*\ of this type is reserved within a managed class + -- finalizer intended? + * - ``2129``\ + - | ``invalid_idisposable_dispose``\ : + | System::IDisposable::Dispose is missing or invalid + * - ``2130``\ + - | ``invalid_object_finalize``\ : + | System::Object::Finalize is missing or invalid + * - ``2131``\ + - | ``finalize_does_not_override_object_finalize``\ : + | *entity-kind "entity"*\ does not override System::Object::Finalize + * - ``2132``\ + - | ``bad_handle_dynamic_cast_operand``\ : + | the operand of a handle dynamic_cast must be a handle to a complete + class type + * - ``2133``\ + - | ``bad_tracking_ref_dynamic_cast_operand``\ : + | the operand of a tracking-reference dynamic_cast must be an lvalue of + a complete class type + * - ``2134``\ + - | ``bad_cli_dynamic_cast_type``\ : + | the type in a dynamic_cast to a handle or tracking reference type + must refer to a complete class + * - ``2135``\ + - | ``cast_interior_ptr_to_ptr``\ : + | an interior pointer cannot be cast to a native pointer + * - ``2136``\ + - | ``cppcli_explicit_conversion_only_in_ref_and_value_classes``\ : + | explicit conversion operators can only be declared in ref and value + class types + * - ``2137``\ + - | ``cppcli_explicit_conversion_is_virtual``\ : + | explicit conversion operator cannot be virtual + * - ``2138``\ + - | ``expr_not_arithmetic_or_unscoped_enum``\ : + | expression must have arithmetic or unscoped enum type + * - ``2139``\ + - | ``expr_not_arithmetic_or_unscoped_enum_or_pointer``\ : + | expression must have arithmetic, unscoped enum, or pointer type + * - ``2140``\ + - | ``expr_not_integral_or_unscoped_enum``\ : + | expression must have integral or unscoped enum type + * - ``2141``\ + - | ``expr_not_integral_or_unscoped_enum_or_fixed_point``\ : + | expression must have integral, unscoped enum, or fixed-point type + * - ``2142``\ + - | ``scoped_enum_operation_type_mismatch``\ : + | a built-in binary operator applied to a scoped enumeration requires + two operands of the same type + * - ``2143``\ + - | ``invalid_gcnew_type``\ : + | gcnew cannot allocate an entity of type *"type"*\ + * - ``2144``\ + - | ``gcnew_used_with_placement_syntax``\ : + | placement syntax cannot be used with gcnew + * - ``2145``\ + - | ``new_used_on_unsuitable_value_type``\ : + | new can only be used with simple value types + * - ``2146``\ + - | ``new_used_on_managed_class_type``\ : + | new cannot be used on a managed class (gcnew should be used instead) + * - ``2147``\ + - | ``new_used_on_handle_or_tracking_reference_type``\ : + | new cannot be used on a handle type + * - ``2148``\ + - | ``cli_array_must_have_new_or_array_init``\ : + | gcnew for a C++/CLI array must have a new initializer or an array + initializer + * - ``2149``\ + - | ``gcnew_bad_type_used_with_array_init``\ : + | an array initializer can only be used to initialize a C++/CLI array + type + * - ``2150``\ + - | ``gcnew_used_with_auto_syntax``\ : + | gcnew does not allow auto + * - ``2151``\ + - | ``too_many_array_bounds``\ : + | too many array bounds + * - ``2152``\ + - | ``too_few_array_bounds``\ : + | too few array bounds + * - ``2153``\ + - | ``too_few_generic_args``\ : + | too few arguments for *entity-kind "entity"*\ + * - ``2154``\ + - | ``too_many_generic_args``\ : + | too many arguments for *entity-kind "entity"*\ + * - ``2156``\ + - | ``no_matching_arity``\ : + | no declaration of *entity-kind "entity"*\ accepts the number of + generic arguments supplied + * - ``2157``\ + - | ``bad_function_for_delegate``\ : + | invalid delegate initializer -- must be a function + * - ``2158``\ + - | ``ambiguous_function_for_delegate``\ : + | invalid delegate initializer -- more than one function matches the + delegate type + * - ``2159``\ + - | ``mismatched_function_for_delegate``\ : + | invalid delegate initializer -- function does not match the delegate + type + * - ``2160``\ + - | ``missing_delegate_object``\ : + | invalid delegate initializer -- an object is needed in addition to a + function + * - ``2161``\ + - | ``nonmanaged_function_for_delegate``\ : + | invalid delegate initializer -- function is not a member of a managed + class + * - ``2162``\ + - | ``superfluous_delegate_object``\ : + | invalid delegate initializer -- object is not needed for the + specified function + * - ``2163``\ + - | ``incompatible_delegate_object``\ : + | invalid delegate initializer -- object has type *"type"*\ but type + *"type"*\ is expected + * - ``2164``\ + - | ``address_of_managed_member_function``\ : + | taking the address of a member function of a managed class is not + allowed + * - ``2165``\ + - | ``bad_delegate_init_list``\ : + | invalid delegate initializer -- expected either + "()" or "(, )" + * - ``2166``\ + - | ``interface_not_implemented``\ : + | class fails to implement interface member *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``2167``\ + - | ``gcnew_of_native_array``\ : + | gcnew cannot be used to allocate a native array + * - ``2168``\ + - | ``cli_interface_cannot_have_assignment``\ : + | a C++/CLI interface class cannot declare an assignment operator + * - ``2169``\ + - | ``sealed_cli_interface``\ : + | a C++/CLI interface class cannot be sealed + * - ``2171``\ + - | ``destructor_or_finalizer_with_named_override``\ : + | a destructor or finalizer declaration cannot include a named override + specifier + * - ``2172``\ + - | ``override_name_is_destructor_or_finalizer``\ : + | an override specifier cannot designate a destructor or finalizer + * - ``2173``\ + - | ``named_override_requires_managed_type``\ : + | a named override specifier is allowed only in a managed class + * - ``2174``\ + - | ``named_override_type_mismatch``\ : + | no member designated by the named override specifier matches the type + of this member + * - ``2175``\ + - | ``static_constructor_with_named_override``\ : + | a static constructor declaration cannot include a named override + specifier + * - ``2176``\ + - | ``unnamed_scoped_enum``\ : + | a scoped enum type must have a name + * - ``2177``\ + - | ``branch_into_finally``\ : + | transfer of control into a finally block is not allowed + * - ``2178``\ + - | ``return_from_finally``\ : + | return statement inside a finally block is not allowed + * - ``2179``\ + - | ``missing_finally``\ : + | try block requires at least one handler or finally clause + * - ``2180``\ + - | ``managed_object_not_thrown_by_handle``\ : + | a managed object must be thrown by handle + * - ``2181``\ + - | ``managed_object_not_caught_by_handle``\ : + | a managed object must be caught by handle + * - ``2182``\ + - | ``break_cannot_be_in_finally_block``\ : + | a break statement cannot be used in a finally block + * - ``2183``\ + - | ``continue_cannot_be_in_finally_block``\ : + | a continue statement cannot be used in a finally block + * - ``2184``\ + - | ``no_overloaded_subscript_with_offsetof``\ : + | builtin offsetof cannot be used when subscripting is overloaded + * - ``2185``\ + - | ``duplicate_constraint``\ : + | duplicate constraint + * - ``2186``\ + - | ``multiple_class_constraints``\ : + | more than one class constraint: *"type"*\ and *"type"*\ + * - ``2187``\ + - | ``multiple_constraint_clauses``\ : + | more than one constraint clause for *entity-kind "entity"*\ + * - ``2188``\ + - | ``initonly_static_data_member_not_initialized``\ : + | initonly static data members must have an initializer or be + initialized in a static constructor + * - ``2189``\ + - | ``gnu_attr_on_template_redecl``\ : + | GNU attributes on a template redeclaration have no effect + * - ``2190``\ + - | ``gnu_attr_on_template_redecl_but_original_kept``\ : + | GNU attributes on a template redeclaration have no effect (the + attributes of the original declaration at line *xxxx*\ apply instead) + * - ``2191``\ + - | ``cli_param_array_must_be_last_parameter``\ : + | a C++/CLI parameter array must be the last parameter + * - ``2192``\ + - | ``default_arg_used_in_param_array_function``\ : + | a function with a C++/CLI parameter array cannot have default + arguments + * - ``2193``\ + - | ``ellipsis_after_param_array``\ : + | a C++/CLI parameter array cannot be followed by an ellipsis parameter + * - ``2194``\ + - | ``parameter_array_on_operator_function``\ : + | a C++/CLI parameter array is not allowed in an operator function + parameter list + * - ``2195``\ + - | ``microsoft_inline_not_allowed_here``\ : + | __inline and \__forceinline are not allowed here + * - ``2196``\ + - | ``data_member_with_interface_type``\ : + | a data member cannot have a C++/CLI interface class type + * - ``2197``\ + - | ``variable_with_interface_type``\ : + | a variable cannot have a C++/CLI interface class type + * - ``2198``\ + - | ``parameter_with_interface_type``\ : + | a parameter cannot have a C++/CLI interface class type + * - ``2199``\ + - | ``return_type_is_interface``\ : + | a function return type cannot be a C++/CLI interface class type + * - ``2200``\ + - | ``array_of_generic_param``\ : + | an array of generic parameter type is not allowed + * - ``2201``\ + - | ``ptr_handle_or_ref_to_generic_param``\ : + | a pointer, handle, or reference to a generic parameter type is not + allowed + * - ``2202``\ + - | ``ref_class_initonly_field``\ : + | an initonly field cannot have a ref class type + * - ``2203``\ + - | ``ref_bound_to_initonly_field``\ : + | a reference cannot be bound to an initonly field + * - ``2204``\ + - | ``address_of_initonly_field``\ : + | taking the address of an initonly field is not allowed + * - ``2205``\ + - | ``modification_of_initonly_field``\ : + | an initonly field can only be modified by the instance constructor of + its containing class + * - ``2206``\ + - | ``modification_of_static_initonly_field``\ : + | a static initonly field can only be modified by the static + constructor of its containing class + * - ``2207``\ + - | ``member_function_call_on_initonly_field``\ : + | member function will be invoked on a copy of the initonly field + * - ``2208``\ + - | ``expr_not_pointer_nor_handle``\ : + | expression must have pointer or handle type but it has type *"type"*\ + * - ``2209``\ + - | ``move_ctor_or_assign_copy_of_lvalue``\ : + | a move constructor or move assignment operator is used to copy an + lvalue here, which may destroy the source object + * - ``2210``\ + - | ``generic_selection_with_points_to``\ : + | member selection on a C++/CLI generic entity must use the "->" + syntax, not "." + * - ``2211``\ + - | ``invalid_specific_ref_class_base``\ : + | a ref class type cannot derive from *"type"*\ + * - ``2212``\ + - | ``generic_class_must_be_managed``\ : + | a generic class must be managed (i.e., a ref class, a value class, or + an interface class) + * - ``2213``\ + - | ``sealed_constraint``\ : + | a sealed class cannot be used as a constraint + * - ``2214``\ + - | ``dynamic_cast_to_value_generic``\ : + | the type in a dynamic_cast cannot be a generic type that might be a + value type + * - ``2215``\ + - | ``UCN_names_invalid_code_point``\ : + | a universal character name must designate a valid code point + * - ``2216``\ + - | ``override_with_constraint_mismatch``\ : + | generic constraints do not match those of *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``2217``\ + - | ``bad_argument_for_underlying_type``\ : + | __underlying_type only applies to enum types + * - ``2218``\ + - | ``too_many_cast_operands``\ : + | expected only one operand expression for this cast + * - ``2219``\ + - | ``bad_unicode_char_in_string``\ : + | Unicode character with hex value *xxxx*\ not representable in the + system default code page + * - ``2220``\ + - | ``conv_of_pm_to_func_ptr``\ : + | nonstandard conversion of bound pointer-to-member to a function + pointer + * - ``2221``\ + - | ``deprecated_access_specifier``\ : + | access specifier *xxxx*\ is deprecated -- use *xxxx*\ instead + * - ``2222``\ + - | ``static_accessor_in_nonstatic_property_or_event``\ : + | a static accessor function is not permitted in a nonstatic property + or event definition + * - ``2223``\ + - | ``both_ref_and_value_constraints``\ : + | *"type"*\ has both a value class and ref class constraint + * - ``2224``\ + - | ``circular_constraints``\ : + | *"type"*\ and *"type"*\ involve circular naked type constraints + * - ``2225``\ + - | ``invalid_type_constraint``\ : + | *"type"*\ is not a valid type constraint + * - ``2226``\ + - | ``pch_file_incomplete``\ : + | precompiled header file *"xxxx"*\ not used (because it is incomplete) + * - ``2227``\ + - | ``invalid_generic_arg``\ : + | *"type"*\ is not a valid generic argument + * - ``2228``\ + - | ``bad_assembly_info_attribute``\ : + | assembly_info attribute applied to an invalid type + * - ``2229``\ + - | ``ref_class_not_satisfied``\ : + | *"type"*\ does not satisfy the ref class constraint of generic + parameter *"type"*\ + * - ``2230``\ + - | ``value_class_not_satisfied``\ : + | *"type"*\ does not satisfy the value class constraint of generic + parameter *"type"*\ + * - ``2231``\ + - | ``gcnew_and_abstract``\ : + | *"type"*\ does not satisfy the gcnew constraint of generic parameter + *"type"*\ because it is abstract + * - ``2232``\ + - | ``gcnew_and_no_ctor``\ : + | *"type"*\ does not satisfy the gcnew constraint of generic parameter + *"type"*\ because it does not have a public default constructor + * - ``2233``\ + - | ``gcnew_and_no_gcnew``\ : + | generic parameter *"type"*\ does not satisfy the gcnew constraint of + generic parameter *"type"*\ because it does not have the gcnew + constraint + * - ``2234``\ + - | ``type_not_satisfied``\ : + | *"type"*\ does not satisfy the *"type"*\ type constraint of generic + parameter *"type"*\ + * - ``2235``\ + - | ``constraint_mismatch``\ : + | constraint on generic parameter *"type"*\ differs from previous + declaration (at line *xxxx*\ ) + * - ``2236``\ + - | ``standard_array_member_in_managed_class``\ : + | a member of a managed class cannot be a standard array + * - ``2237``\ + - | ``handle_member_in_standard_class``\ : + | a member of a non-managed class cannot be a handle + * - ``2238``\ + - | ``tracking_reference_member_in_standard_class``\ : + | a member of a non-managed class cannot be a tracking reference + * - ``2239``\ + - | ``reinterpret_cast_of_handle``\ : + | unsafe reinterpret_cast of handle + * - ``2240``\ + - | ``generic_type_in_template_arg``\ : + | a template argument may not reference a generic type parameter + * - ``2241``\ + - | ``comma_operator_in_cli_subscript``\ : + | an expression list is not allowed in this subscript operation (use + parentheses around a top-level comma operator) + * - ``2242``\ + - | ``expr_not_pointer_or_array_handle``\ : + | expression must have pointer-to-object or handle-to-C++/CLI-array + type but it has type *"type"*\ + * - ``2243``\ + - | ``unrecognized_ms_attr``\ : + | unrecognized attribute + * - ``2244``\ + - | ``standard_class_member_in_managed_class``\ : + | a member of a managed class cannot be of a non-managed class type + * - ``2245``\ + - | ``ref_or_interface_class_member_in_standard_class``\ : + | a member of a non-managed class cannot have a ref class type or + interface class type + * - ``2247``\ + - | ``template_delegate``\ : + | a delegate may not be declared as a template + * - ``2248``\ + - | ``invalid_generic_specialization``\ : + | a generic cannot be explicitly specialized + * - ``2249``\ + - | ``generic_in_template``\ : + | a generic cannot be declared in a class template + * - ``2250``\ + - | ``template_in_generic``\ : + | a template cannot be declared in a generic class + * - ``2251``\ + - | ``static_literal_field``\ : + | a literal field cannot be declared "static" + * - ``2252``\ + - | ``nonstandard_long_float``\ : + | "long float" is a nonstandard extension -- use "double" instead + * - ``2253``\ + - | ``standard_class_nested_in_managed_class``\ : + | a standard class cannot be nested in a managed class + * - ``2254``\ + - | ``clrcall_requires_cppcli``\ : + | __clrcall is valid only in C++/CLI mode + * - ``2255``\ + - | ``vararg_clrcall``\ : + | __clrcall not allowed on function with ellipsis parameter + * - ``2256``\ + - | ``bad_use_of_function_modifier``\ : + | *"xxxx"*\ is not allowed here + * - ``2257``\ + - | ``override_with_trivial_property_or_event``\ : + | a trivial property or event cannot be used to override *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``2258``\ + - | ``exp_id_in_for_each_decl``\ : + | expected an iterator variable name + * - ``2259``\ + - | ``missing_notequal_on_for_each_type``\ : + | the iterator type in this "for each" statement is *"type"*\ , which + is not a pointer type or an iterator-like class type + * - ``2260``\ + - | ``missing_incr_on_for_each_type``\ : + | the iterator type in this "for each" statement is *"type"*\ , which + is not a pointer type or an iterator-like class type + * - ``2261``\ + - | ``missing_indirect_on_for_each_type``\ : + | the iterator type in this "for each" statement is *"type"*\ , which + is not a pointer type or an iterator-like class type + * - ``2262``\ + - | ``no_packing_of_non_POD_field``\ : + | packing attribute on the parent type is ignored for this field of + class type *"type"*\ that is not standard-layout + * - ``2263``\ + - | ``nonpublic_implicit_interface_match``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) not implemented + because this declaration is not public and has no named override + specifier + * - ``2264``\ + - | ``missing_gnu_inline_attr_on_redeclaration``\ : + | this declaration is missing the gnu_inline attribute specified in the + previous declaration at line *xxxx*\ + * - ``2265``\ + - | ``managed_member_function_cannot_have_ellipsis_parameter``\ : + | a member function of a managed class cannot have an ellipsis parameter + * - ``2266``\ + - | ``invalid_prev_decl_iterator``\ : + | previously-declared *entity-kind "entity"*\ invalid as iterator of + "for each" statement + * - ``2267``\ + - | ``generic_parameter_requires_clrcall``\ : + | calling convention ignored because the function type involves a + generic parameter; \__clrcall used instead + * - ``2268``\ + - | ``generic_parameter_does_not_permit_varargs``\ : + | a function type involving a generic parameter cannot have an ellipsis + parameter + * - ``2269``\ + - | ``virtual_required_for_base_override``\ : + | "virtual" is required to override the matching *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``2270``\ + - | ``virtual_required_for_interface_implementation``\ : + | "virtual" is required to implement the matching *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``2271``\ + - | ``initonly_volatile_not_allowed``\ : + | an initonly data member cannot be volatile + * - ``2272``\ + - | ``member_name_reserved_by_cli_operator``\ : + | a member *"xxxx"*\ of this type is reserved within a managed class + -- C++/CLI operators must be declared using the keyword "operator" + * - ``2273``\ + - | ``tracking_ref_to_constant``\ : + | a tracking reference to non-const cannot be bound to a constant + * - ``2274``\ + - | ``attributes_with_no_decl``\ : + | attributes ignored here because they do not apply to a declared entity + * - ``2275``\ + - | ``tracking_reference_to_system_string``\ : + | a tracking reference to System::String is not allowed + * - ``2276``\ + - | ``use_of_generic_class_with_pending_constraint``\ : + | invalid use of a generic class *"type"*\ with pending constraints + (probably caused by an invalid metadata file) + * - ``2277``\ + - | ``invalid_entity_for_pending_constraint``\ : + | a pending constraint clause is only allowed for generic class + declarations (but not generic class definitions) + * - ``2278``\ + - | ``invalid_empty_initializer_list``\ : + | empty initializer list not allowed here + * - ``2279``\ + - | ``template_in_managed_class``\ : + | a template cannot be declared in a managed class + * - ``2280``\ + - | ``bad_generic_declaration_scope``\ : + | a generic declaration is not allowed here + * - ``2281``\ + - | ``interface_cannot_have_member_generics``\ : + | interface types cannot have member generics + * - ``2282``\ + - | ``character_not_latin_1``\ : + | Unicode character not Latin-1, truncated to low-order byte + * - ``2283``\ + - | ``range_based_for_missing_function``\ : + | to be used with range-based "for" statements, type *"type"*\ must + provide function *"xxxx"*\ + * - ``2284``\ + - | ``missing_notequal_on_range_based_for_type``\ : + | the iterator type in this range-based "for" statement is *"type"*\ , + which is not a pointer type or an iterator-like class type + * - ``2285``\ + - | ``missing_incr_on_range_based_for_type``\ : + | the iterator type in this range-based "for" statement is *"type"*\ , + which is not a pointer type or an iterator-like class type + * - ``2286``\ + - | ``missing_indirect_on_range_based_for_type``\ : + | the iterator type in this range-based "for" statement is *"type"*\ , + which is not a pointer type or an iterator-like class type + * - ``2287``\ + - | ``range_based_for_incomplete_array_type``\ : + | a range-based "for" statement cannot operate on an array of unknown + size or incomplete type *"type"*\ + * - ``2288``\ + - | ``begin_end_type_mismatch_in_range_based_for``\ : + | return types for "begin" and "end" functions used in a range-based + "for" statement must be the same ("begin" return type is *"type"*\ , + "end" return type is *"type"*\ ) + * - ``2289``\ + - | ``inaccessible_elided_dtor``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ), required to + destroy temporary that was eliminated, is inaccessible + * - ``2290``\ + - | ``range_based_for_no_matching_overload``\ : + | in this range-based "for" statement, no instance of *"entity"*\ + matches the argument list + * - ``2291``\ + - | ``range_based_for_undefined_identifier``\ : + | this range-based "for" statement requires a suitable *"xxxx"*\ + function and none was found + * - ``2292``\ + - | ``for_each_undefined_identifier``\ : + | this "for each" statement requires a suitable *"xxxx"*\ function and + none was found + * - ``2293``\ + - | ``class_metadata_not_representable``\ : + | *"type"*\ has a metadata representation not representable using + C++/CLI + * - ``2294``\ + - | ``exp_ellipsis``\ : + | expected "..." + * - ``2295``\ + - | ``implements_requires_interface``\ : + | *"type"*\ in \__implements list is not an interface + * - ``2296``\ + - | ``implements_must_precede_virtual_functions``\ : + | an \__implements list must precede virtual function declarations + * - ``2297``\ + - | ``missing_implements_list``\ : + | *"type"*\ specified "\__implements ..." in its list of bases, but is + missing a matching \__implements list + * - ``2298``\ + - | ``unused_dereference_of_ref_class``\ : + | the result of dereferencing a handle to a ref or interface class type + must be used + * - ``2300``\ + - | ``exp_rparen_and_pragma_ignored``\ : + | expected a ")"; pragma ignored + * - ``2301``\ + - | ``using_or_access_declaration_in_managed_class``\ : + | a using-declaration or access declaration cannot appear in a managed + class + * - ``2302``\ + - | ``skipped_inaccessible_function``\ : + | Note: *entity-kind "entity"*\ (declared at line *xxxx*\ ) could have + been called but was not considered because it is inaccessible + * - ``2303``\ + - | ``cli_abstract_member_function_definition``\ : + | an abstract member function of a C++/CLI managed class cannot have a + definition + * - ``2304``\ + - | ``nonstatic_addressof_operator_in_managed_class``\ : + | declaring this unary "operator\*" can change the meaning of + dereferencing a handle (use static member operators to explicitly + indicate applicable types) + * - ``2319``\ + - | ``interface_nonstatic_data_member``\ : + | an interface class cannot contain a nonstatic data member + * - ``2320``\ + - | ``pragma_gcc_system_header_in_primary_file``\ : + | #pragma GCC system_header cannot be used in the primary source file + * - ``2321``\ + - | ``too_large_to_inline``\ : + | *entity-kind "entity"*\ is too large to be inlined + * - ``2323``\ + - | ``cl_gen_move_operations_option_only_in_cplusplus``\ : + | option to control move operations can be used only when compiling C++ + * - ``2324``\ + - | ``cl_gen_move_operations_and_rvalue_ctor_is_copy_ctor``\ : + | move operations cannot be generated when rvalue constructors are copy + constructors + * - ``2325``\ + - | ``cl_move_operations_require_rvalue_references``\ : + | option to control move operations cannot be used when rvalue + references are disabled + * - ``2326``\ + - | ``final_managed_class``\ : + | "final" cannot be used for managed classes (use "sealed" instead) + * - ``2327``\ + - | ``cast_to_cli_interface_class``\ : + | a cast to CLI interface class *"type"*\ is not allowed -- cast to + handle intended? + * - ``2328``\ + - | ``new_of_cli_interface_class``\ : + | cannot create an object of a CLI interface class + * - ``2329``\ + - | ``enum_type_replacement``\ : + | this declaration hides the nonstandard declaration of *entity-kind + "entity"*\ (declared at line *xxxx*\ ) because the underlying types + are incompatible + * - ``2330``\ + - | ``known_comparison_with_null``\ : + | pointer comparison result is constant, because operand can never be + null + * - ``2331``\ + - | ``value_init_of_incomplete``\ : + | an object of the incomplete type *"type"*\ cannot be + value-initialized + * - ``2332``\ + - | ``value_init_of_reference``\ : + | a reference cannot be value-initialized + * - ``2333``\ + - | ``exp_lparen_or_brace``\ : + | expected a "(" or a "{" + * - ``2334``\ + - | ``explicit_ctor_in_copy_list_init``\ : + | copy-list-initialization cannot use a constructor marked "explicit" + * - ``2335``\ + - | ``ptr_to_member_of_type_void``\ : + | pointer to member of type void is not allowed + * - ``2336``\ + - | ``ptr_to_member_of_reference_type``\ : + | pointer to member of reference type is not allowed + * - ``2337``\ + - | ``ptr_to_member_of_handle_type``\ : + | pointer to member of handle type is not allowed + * - ``2338``\ + - | ``braced_init_list_not_allowed``\ : + | a brace-enclosed list is not allowed here + * - ``2339``\ + - | ``arrow_star_operator_in_managed_class``\ : + | an operator->\* member is not allowed in a managed class + * - ``2340``\ + - | ``bad_assembly_index``\ : + | assembly metadata refers to non-existent assembly + * - ``2341``\ + - | ``attribute_conflict``\ : + | attribute *"xxxx"*\ conflicts with earlier attribute *"xxxx"*\ + * - ``2342``\ + - | ``incompatible_enum_base_types``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared with a different base type + * - ``2343``\ + - | ``invalid_scoped_enum_elaboration``\ : + | "enum class" and "enum struct" cannot be used here (use plain "enum" + instead) + * - ``2344``\ + - | ``extra_braces_on_simple_init``\ : + | only one level of braces is allowed on an initializer for an object + of type *"type"*\ + * - ``2345``\ + - | ``not_an_enum_type_name``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot be used + as an enum type name + * - ``2347``\ + - | ``auto_new_with_braced_init``\ : + | a braced-initializer cannot be used with "new auto" + * - ``2348``\ + - | ``missing_initializer_list_ctor``\ : + | the definition of std::initializer_list does not contain the expected + constructor + * - ``2349``\ + - | ``variable_hides_entity``\ : + | declaration hides *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``2350``\ + - | ``invalid_std_initializer_list_parameter_list``\ : + | invalid template parameter list for std::initializer_list (it should + be one ordinary type parameter with no default) + * - ``2351``\ + - | ``braced_list_passed_to_ellipsis``\ : + | a brace-enclosed list cannot be passed for an ellipsis parameter + * - ``2352``\ + - | ``initializer_list_not_included``\ : + | an #include is needed prior to a use of + std::initializer_list, including an implicit use + * - ``2353``\ + - | ``inline_on_alias``\ : + | the "inline" keyword cannot be used on a namespace alias declaration + * - ``2354``\ + - | ``prev_ns_not_inline``\ : + | the previous declaration of *entity-kind "entity"*\ was not declared + inline + * - ``2355``\ + - | ``prev_ns_inline``\ : + | *entity-kind "entity"*\ was previously declared inline + * - ``2356``\ + - | ``first_arg_must_be_integer_constant``\ : + | the first argument must be an integer constant + * - ``2357``\ + - | ``designator_requires_aggregate_type``\ : + | a designator cannot be used with a non-aggregate type *"type"*\ + * - ``2358``\ + - | ``indirect_anon_union_designator``\ : + | a designator for an anonymous union member can only appear within + braces corresponding to that anonymous union + * - ``2359``\ + - | ``cl_func_prototype_tags_option_only_in_C``\ : + | function prototype tags can only be enabled when compiling C + * - ``2360``\ + - | ``cannot_elide_braces``\ : + | braces cannot be omitted for this subobject initializer + * - ``2361``\ + - | ``narrowing_conversion``\ : + | invalid narrowing conversion from *"type"*\ to *"type"*\ + * - ``2362``\ + - | ``constant_narrowing_conversion``\ : + | invalid narrowing conversion from *"type"*\ to *"type"*\ : constant + value does not fit in destination type + * - ``2363``\ + - | ``cast_to_incomplete_array_type``\ : + | cast to incomplete array type *"type"*\ is not allowed + * - ``2364``\ + - | ``constant_narrowing_conversion_to_float``\ : + | invalid narrowing conversion from *"type"*\ to *"type"*\ : constant + value cannot be represented exactly in destination type + * - ``2365``\ + - | ``braced_init_in_paren_init``\ : + | a parenthesized initializer for a non-class entity must be an + expression, not a brace-enclosed list + * - ``2366``\ + - | ``braced_list_for_implicit_lambda_type``\ : + | a brace-enclosed list does not provide a return type for this lambda + * - ``2367``\ + - | ``invalid_explicit_exception_specification``\ : + | the declared exception specification is incompatible with the + generated one + * - ``2368``\ + - | ``scoped_enum_nonstandard_in_current_mode``\ : + | scoped enum types are a C++11 feature + * - ``2369``\ + - | ``value_init_of_function``\ : + | a function type cannot be value-initialized + * - ``2370``\ + - | ``list_init_of_incomplete``\ : + | list-initialization of an object type *"type"*\ is not allowed + because the type is incomplete + * - ``2371``\ + - | ``std_initializer_list_has_dtor``\ : + | std::initializer_list has a destructor, and is not supposed to -- + library is misconfigured + * - ``2372``\ + - | ``explicit_enum_base_nonstandard_in_current_mode``\ : + | explicit enum base types are a C++11 feature + * - ``2373``\ + - | ``unconvertible_con_expr``\ : + | this constant expression has type *"type"*\ instead of the required + *"type"*\ type + * - ``2374``\ + - | ``new_of_initializer_list``\ : + | a "new" of an std::initializer_list object is unlikely to work as + expected because the underlying array will be destroyed at the end of + the full expression + * - ``2377``\ + - | ``defined_always_false``\ : + | "defined" is always false in a macro expansion in Microsoft mode + * - ``2378``\ + - | ``init_list_element_type_not_complete_object``\ : + | *"type"*\ cannot be the element type of an initializer list because + it is not a complete object type + * - ``2379``\ + - | ``invalid_default_arg``\ : + | mismatched delimiters in default argument expression + * - ``2380``\ + - | ``conv_of_unbound_pm_to_func_ptr``\ : + | nonstandard conversion of pointer-to-member to a function pointer + * - ``2381``\ + - | ``dynamic_exception_specifications_deprecated``\ : + | dynamic exception specifications are deprecated + * - ``2382``\ + - | ``bad_scope_for_partial_spec``\ : + | *entity-kind "entity"*\ cannot be partially specialized in the + current scope + * - ``2383``\ + - | ``previous_constexpr_decl_conflict``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared constexpr + * - ``2384``\ + - | ``previous_nonconstexpr_decl_conflict``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + not declared constexpr + * - ``2385``\ + - | ``constexpr_variable_decl_must_be_definition``\ : + | missing initializer for constexpr variable + * - ``2386``\ + - | ``invalid_constexpr``\ : + | "constexpr" is not valid here + * - ``2387``\ + - | ``invalid_constexpr_body``\ : + | a constexpr function must contain exactly one return statement + * - ``2388``\ + - | ``invalid_statement_in_constexpr_function``\ : + | statement may not appear in a constexpr function + * - ``2389``\ + - | ``invalid_statement_in_constexpr_constructor``\ : + | statement may not appear in a constexpr constructor + * - ``2390``\ + - | ``constexpr_virtual_combination``\ : + | a function cannot be both constexpr and virtual in this mode + * - ``2391``\ + - | ``nonliteral_return_type_in_constexpr_function``\ : + | a constexpr function cannot have a nonliteral return type *"type"*\ + * - ``2392``\ + - | ``nonliteral_param_type_in_constexpr_function``\ : + | a constexpr function cannot have a parameter of nonliteral type + *"type"*\ + * - ``2393``\ + - | ``unsequenced_use_of_variable``\ : + | unsequenced uses of *entity-kind "entity"*\ in expression may + produce undefined results + * - ``2394``\ + - | ``3rd_arg_of_assume_aligned_must_be_integral``\ : + | the optional third argument of a call to \__builtin_assumed_aligned + must have integral type + * - ``2395``\ + - | ``constexpr_destructor``\ : + | a destructor cannot be constexpr + * - ``2396``\ + - | ``invalid_mmap_address``\ : + | address supplied for mmap must be aligned on a page boundary: *xxxx*\ + * - ``2397``\ + - | ``constexpr_constructor_with_function_try_block``\ : + | the body of a constexpr constructor cannot be a function try block + * - ``2398``\ + - | ``missing_initializer_on_fields_with_constexpr_ctor``\ : + | constexpr *entity-kind "entity"*\ provides no initializer for: + * - ``2400``\ + - | ``default_ctor_call_not_constant``\ : + | calling the default constructor for *"type"*\ does not produce a + constant value + * - ``2401``\ + - | ``default_ctor_not_constexpr``\ : + | the default constructor for *"type"*\ is not constexpr + * - ``2402``\ + - | ``constexpr_variable_must_have_literal_type``\ : + | a constexpr variable must have a literal type or a reference type + * - ``2403``\ + - | ``constexpr_ctor_with_virtual_base``\ : + | a constructor for a class with virtual bases cannot be constexpr + * - ``2404``\ + - | ``bad_cpp11_constant_function_call``\ : + | function call must have a constant value in a constant expression + * - ``2405``\ + - | ``constexpr_main``\ : + | function "main" may not be declared constexpr + * - ``2407``\ + - | ``tag_defined_in_constexpr_body``\ : + | a class or enum type definition cannot appear in a constexpr function + or constructor body + * - ``2408``\ + - | ``only_gnu_attributes_here``\ : + | only GNU-style attributes are permitted here + * - ``2409``\ + - | ``auto_used_two_ways``\ : + | nonstandard use of "auto" to both deduce the type from an initializer + and to announce a trailing return type + * - ``2410``\ + - | ``nonstd_qualified_void_param_list``\ : + | declaring a void parameter list with a qualified void type is + nonstandard + * - ``2411``\ + - | ``qualifier_ignored_on_local_declaration``\ : + | the qualifier on this local declaration is ignored + * - ``2412``\ + - | ``bad_conv_constant_expr_type``\ : + | this constant expression has type *"type"*\ instead of the required + *xxxx*\ type + * - ``2413``\ + - | ``bad_argument_for_bases``\ : + | an instantiation of \__bases or \__direct_bases requires a class type + * - ``2414``\ + - | ``bad_prototype_argument_for_bases``\ : + | the argument of \__bases and \__direct_bases must be a type template + parameter + * - ``2415``\ + - | ``bases_not_in_template``\ : + | *xxxx*\ can only be used in template contexts + * - ``2416``\ + - | ``constexpr_return_not_constant``\ : + | constexpr function return is non-constant + * - ``2417``\ + - | ``nonconstexpr_call_in_mem_initializer``\ : + | constexpr constructor calls non-constexpr *entity-kind "entity"*\ + * - ``2418``\ + - | ``nonconstant_field_initializer_in_mem_initializer``\ : + | constructor cannot be constexpr because the initializer of + *entity-kind "entity"*\ is not a constant expression + * - ``2419``\ + - | ``nonconstant_mem_init_for_constexpr_ctor``\ : + | non-constant initializer for constexpr constructor + * - ``2420``\ + - | ``generated_default_constructor_used_in_field_initializer``\ : + | the generated default constructor for *"type"*\ cannot be used in an + initializer for its own data member + * - ``2421``\ + - | ``recursive_initializer_instantiation``\ : + | instantiation of initializer of *entity-kind "entity"*\ depends on + its own value + * - ``2422``\ + - | ``defaulted_default_ctor_cannot_be_constexpr``\ : + | defaulted default constructor cannot be constexpr because the + corresponding implicitly declared default constructor would not be + constexpr + * - ``2424``\ + - | ``bad_binary_digit``\ : + | invalid binary number + * - ``2425``\ + - | ``multiple_union_field_initializers``\ : + | a union can have at most one field initializer -- *entity-kind + "entity"*\ (declared at line *xxxx*\ ) also has an initializer + * - ``2427``\ + - | ``union_constexpr_constructor_initializes_no_field``\ : + | constexpr constructor of a union must initialize one of its fields + * - ``2428``\ + - | ``constexpr_constructor_initializes_no_variant_field``\ : + | constexpr constructor fails to initialize an anonymous union (defined + at line *xxxx*\ ) + * - ``2429``\ + - | ``constexpr_static_data_member_without_initializer``\ : + | a constexpr static data member declaration requires an in-class + initializer + * - ``2430``\ + - | ``cl_max_constexpr_option_only_in_cplusplus``\ : + | maximum constexpr depth/count options can be used only when compiling + C++ + * - ``2431``\ + - | ``excessive_constexpr_complexity``\ : + | expression not folded to a constant due to excessive constexpr + function call complexity + * - ``2432``\ + - | ``cl_unrestricted_unions_option_only_in_cplusplus``\ : + | unrestricted union options can be used only when compiling C++ + * - ``2433``\ + - | ``constexpr_ctor_does_not_initialize_base``\ : + | constexpr constructor must initialize direct base class *"type"*\ + * - ``2434``\ + - | ``field_initializer_list``\ : + | creation of an std::initializer_list object in a field initializer is + unlikely to work as expected because the underlying array will be + destroyed at the end of the full expression + * - ``2435``\ + - | ``this_not_constant``\ : + | "this" cannot be used in a constant expression + * - ``2437``\ + - | ``constexpr_explicit_instantiation``\ : + | "constexpr" is not allowed on an explicit instantiation directive + * - ``2438``\ + - | ``generated_default_ctor_exception_spec_circularity``\ : + | cannot determine the exception specification of the default + constructor due to a circular dependency + * - ``2439``\ + - | ``anon_union_at_decl_position``\ : + | anonymous union defined at line *xxxx*\ + * - ``2440``\ + - | ``unbounded_constexpr_ctor_init_recursion``\ : + | this constructor uses the initializer of *entity-kind "entity"*\ + (declared at line *xxxx*\ ), which would result in unbounded recursion + * - ``2442``\ + - | ``block_extern_initializer_not_allowed``\ : + | an initializer is not allowed on a local declaration of an extern + variable + * - ``2443``\ + - | ``local_named_register_initializer_not_allowed``\ : + | an initializer is not allowed on a local declaration of a named + register variable + * - ``2445``\ + - | ``cl_unrestricted_unions_in_microsoft_mode``\ : + | unrestricted unions cannot be enabled in Microsoft mode + * - ``2446``\ + - | ``delegation_loop``\ : + | constructor delegates directly or indirectly to itself + * - ``2447``\ + - | ``delegation_init_and_mem_init``\ : + | a delegating constructor cannot have other mem-initializers + * - ``2448``\ + - | ``ref_qualifier_not_allowed``\ : + | a ref-qualifier is not allowed here + * - ``2449``\ + - | ``same_param_types_with_and_without_ref_qualifiers``\ : + | overloading two member functions with the same parameter types + requires that they both have ref-qualifiers or both lack + ref-qualifiers + * - ``2450``\ + - | ``bad_raw_string_delim_char``\ : + | invalid character in raw string delimiter + * - ``2451``\ + - | ``missing_raw_string_delim_lparen``\ : + | parenthesis terminating raw string delimiter not found within 16 + characters -- raw string indicator ignored + * - ``2452``\ + - | ``missing_raw_string_delimiter``\ : + | ending delimiter for raw string not found + * - ``2453``\ + - | ``pack_not_last_arg``\ : + | a parameter pack must be the final template argument in a partial + specialization + * - ``2454``\ + - | ``pm_call_obj_not_lvalue``\ : + | a pointer-to-member function with type *"type"*\ can only be used + with an lvalue object + * - ``2455``\ + - | ``pm_call_obj_not_rvalue``\ : + | a pointer-to-member function with type *"type"*\ can only be used + with an rvalue object + * - ``2456``\ + - | ``defaulted_copy_ctor_cannot_have_const_parameter``\ : + | the parameter of this defaulted copy-constructor cannot be const + because a base or member copy constructor parameter is non-const + * - ``2457``\ + - | ``defaulted_assignment_cannot_have_const_parameter``\ : + | the parameter of this defaulted assignment operator cannot be const + because a base or member copy assignment parameter is non-const + * - ``2458``\ + - | ``empty_anonymous_union``\ : + | an anonymous union must contain at least one nonstatic data member + * - ``2459``\ + - | ``delegating_constructor_requires_newer_abi_version``\ : + | option "delegating_constructors" requires a different compiler + configuration + * - ``2460``\ + - | ``alignment_reduction_unconditionally_ignored``\ : + | a reduction in alignment is ignored + * - ``2461``\ + - | ``bad_rvalue_ref_const_cast_operand``\ : + | the operand of a const_cast to an rvalue reference type cannot be a + non-class prvalue + * - ``2462``\ + - | ``expr_not_a_glvalue``\ : + | expression must be an lvalue or xvalue + * - ``2463``\ + - | ``lossy_conversion``\ : + | conversion may change the value + * - ``2464``\ + - | ``deprecated_string_conv``\ : + | conversion from a string literal to "char \*" is deprecated + * - ``2465``\ + - | ``deprecated_string_conv_gen``\ : + | conversion from a string literal to pointer-to-character (non-const) + is deprecated + * - ``2466``\ + - | ``override_and_final_is_cpp11``\ : + | "override" and "final" are C++11 features + * - ``2467``\ + - | ``rvalue_reference_in_exception_specification``\ : + | rvalue references are not allowed as exception specification types + * - ``2468``\ + - | ``attr_disallows_handler_param``\ : + | attribute *"xxxx"*\ does not apply to handler parameters + * - ``2469``\ + - | ``attr_requires_handler_param``\ : + | attribute *"xxxx"*\ requires a handler parameter + * - ``2470``\ + - | ``wrong_entity_for_alignas``\ : + | alignas does not apply here + * - ``2471``\ + - | ``std_alignof_with_expr_arg``\ : + | the standard "alignof" operator does not accept an expression + argument (use a type instead) + * - ``2472``\ + - | ``bad_qualifier_for_member_enum_decl``\ : + | invalid qualifier for *"type"*\ (a derived class is not allowed here) + * - ``2473``\ + - | ``always_inline_requires_inline``\ : + | the "always_inline" attribute is ignored on non-inline functions + * - ``2474``\ + - | ``inheriting_ctor_not_from_direct_base``\ : + | inheriting constructors must be inherited from a direct base class + * - ``2476``\ + - | ``exp_asm_label``\ : + | expected a label + * - ``2477``\ + - | ``missing_label_operand_number``\ : + | expected an operand number after "%" + * - ``2478``\ + - | ``label_operand_number_out_of_range``\ : + | operand number for "%" does not refer to a valid label argument + * - ``2479``\ + - | ``wide_string_invalid_in_asm``\ : + | a wide string is invalid in an "asm" statement + * - ``2480``\ + - | ``attribute_is_nonstandard``\ : + | attribute is nonstandard + * - ``2481``\ + - | ``decltype_is_not_base_class``\ : + | not a base class of class *"type"*\ + * - ``2482``\ + - | ``bad_user_defined_suffix``\ : + | non-identifier character in user-defined literal suffix + * - ``2483``\ + - | ``multichar_ud_lit``\ : + | a multicharacter literal cannot be part of a user-defined literal + * - ``2484``\ + - | ``ud_string_suffix_mismatch``\ : + | user-defined literal suffix does not match the earlier *"xxxx"*\ + * - ``2485``\ + - | ``invalid_literal_operator_id``\ : + | invalid literal operator name + * - ``2486``\ + - | ``literal_operator_not_found``\ : + | user-defined literal operator not found + * - ``2487``\ + - | ``ambig_literal_operator``\ : + | ambiguous literal operators and/or literal operator template: + * - ``2488``\ + - | ``udl_cannot_be_class_member``\ : + | a literal operator cannot be a member of a class + * - ``2489``\ + - | ``extern_c_literal_operator``\ : + | a literal operator cannot have extern "C" name linkage + * - ``2490``\ + - | ``no_parameter_for_literal_operator``\ : + | at least one parameter expected for a literal operator + * - ``2491``\ + - | ``too_many_parameters_for_literal_operator``\ : + | too many parameters for this literal operator + * - ``2492``\ + - | ``invalid_parameter_type_for_literal_operator``\ : + | invalid parameter type *"type"*\ for literal operator + * - ``2493``\ + - | ``invalid_integer_parameter_for_literal_operator``\ : + | invalid integer parameter type (*"type"*\ ) for literal operator; + expected a character type or unsigned long long + * - ``2494``\ + - | ``invalid_float_parameter_for_literal_operator``\ : + | invalid floating-point parameter type (*"type"*\ ) for literal + operator; expected long double + * - ``2495``\ + - | ``pointer_to_nonconst_for_literal_operator``\ : + | invalid first parameter type (*"type"*\ ) for literal operator; + pointer to non-const type is not allowed + * - ``2496``\ + - | ``invalid_second_parameter_type_for_literal_operator``\ : + | invalid second parameter type (*"type"*\ ) for literal operator; must + be size_t + * - ``2497``\ + - | ``invalid_pointer_parameter_for_literal_operator``\ : + | invalid pointer parameter type (*"type"*\ ) for literal operator; + expected a pointer to a character type + * - ``2498``\ + - | ``ellipsis_parameter_for_literal_operator``\ : + | a literal operator cannot have an ellipsis parameter + * - ``2499``\ + - | ``invalid_parameter_for_literal_operator_template``\ : + | a literal operator template cannot have any parameters + * - ``2500``\ + - | ``invalid_template_parameter_for_literal_operator_template``\ : + | a literal operator template must have a template parameter list + equivalent to "" + * - ``2501``\ + - | ``thread_local_not_allowed``\ : + | thread-local storage class is not valid here + * - ``2502``\ + - | ``thread_local_follows_non_thread_local``\ : + | thread-local declaration follows non-thread-local declaration + (declared at line *xxxx*\ ) + * - ``2503``\ + - | ``non_thread_local_follows_thread_local``\ : + | non-thread-local declaration follows thread-local declaration + (declared at line *xxxx*\ ) + * - ``2504``\ + - | ``default_arg_for_literal_operator``\ : + | a literal operator cannot have default arguments + * - ``2505``\ + - | ``attribute_ignored_for_thread_local``\ : + | attribute is ignored for thread-local variables + * - ``2506``\ + - | ``lit_suffix_no_underscore``\ : + | a user-provided literal suffix must begin with "_" + * - ``2507``\ + - | ``rvalue_references_is_cpp11``\ : + | rvalue references are a C++11 feature + * - ``2508``\ + - | ``lambdas_is_cpp11``\ : + | lambda expressions are a C++11 feature + * - ``2509``\ + - | ``std_attributes_is_cpp11``\ : + | standard attribute syntax is a C++11 feature + * - ``2510``\ + - | ``delegating_constructor_is_cpp11``\ : + | delegating constructors are a C++11 feature + * - ``2511``\ + - | ``inheriting_constructor_is_cpp11``\ : + | inheriting constructors are a C++11 feature + * - ``2512``\ + - | ``field_initializers_is_cpp11``\ : + | field initializers are a C++11 feature + * - ``2513``\ + - | ``deleted_functions_is_cpp11``\ : + | deleted functions are a C++11 feature + * - ``2514``\ + - | ``defaulted_functions_is_cpp11``\ : + | defaulted functions are a C++11 feature + * - ``2515``\ + - | ``storage_class_not_allowed_in_specialization``\ : + | a storage class is not allowed in an explicit specialization + * - ``2517``\ + - | ``specialization_of_unscoped_enum``\ : + | an unscoped enumeration must be opaque in order to be specialized + * - ``2518``\ + - | ``nonmember_enum_template``\ : + | an enumeration template declaration must refer to a previously + declared member of a class template + * - ``2519``\ + - | ``operand_must_be_vector``\ : + | expected a vector operand + * - ``2520``\ + - | ``incompatible_shuffle_source_operands``\ : + | shuffle source operands have incompatible types *"type"*\ and + *"type"*\ + * - ``2521``\ + - | ``nonintegral_shuffle_mask``\ : + | shuffle mask (type *"type"*\ ) is not a vector of integers + * - ``2522``\ + - | ``incompatible_shuffle_mask``\ : + | shuffle mask (type *"type"*\ ) has a length different from the source + operand (type *"type"*\ ) + * - ``2523``\ + - | ``bad_size_for_static_address_init``\ : + | static initialization with an address value requires a destination of + the same size as the address + * - ``2524``\ + - | ``feature_test_macro_req_id``\ : + | the argument to a feature-test macro must be a simple identifier + * - ``2525``\ + - | ``has_include_next_in_primary_source_file``\ : + | __has_include_next cannot be used in the primary source file + * - ``2526``\ + - | ``absolute_file_name_in_has_include_next``\ : + | absolute file name used in \__has_include_next + * - ``2527``\ + - | ``attr_not_applied_to_function_type``\ : + | attribute *"xxxx"*\ must be applied to a function type + * - ``2529``\ + - | ``bad_c11_noreturn``\ : + | _Noreturn is not allowed here + * - ``2530``\ + - | ``operand_must_be_real_floating_value``\ : + | expected an operand of real floating-point type (not *"type"*\ ) + * - ``2531``\ + - | ``incompatible_builtin_complex_types``\ : + | __builtin_complex requires operands of compatible types (unlike + *"type"*\ and *"type"*\ ) + * - ``2532``\ + - | ``default_association_appears_more_than_once``\ : + | a default association already appeared in this _Generic selection + * - ``2533``\ + - | ``variably_modified_type_not_allowed_here``\ : + | a type involving a variable length array is not allowed here + * - ``2534``\ + - | ``duplicate_type_in_c11_generic``\ : + | duplicate association type (*"type"*\ ) in _Generic selection + * - ``2535``\ + - | ``no_match_in_c11_generic``\ : + | no association matches the selector type *"type"*\ + * - ``2536``\ + - | ``incompatible_ifunc_resolver_type``\ : + | the type of *entity-kind "entity"*\ (*"type"*\ ) is incompatible + with an ifunc resolver type + * - ``2537``\ + - | ``ifunc_cant_be_alias``\ : + | a function cannot have both ifunc and alias attributes + * - ``2538``\ + - | ``ifunc_cant_be_weak``\ : + | a function cannot have both ifunc and weak attributes + * - ``2539``\ + - | ``call_requires_string_literal``\ : + | call requires a string literal operand + * - ``2540``\ + - | ``duplicate_inheriting_constructor``\ : + | duplicate inheriting constructor declaration (previous at line + *xxxx*\ ) + * - ``2541``\ + - | ``modified_decltype_auto_type``\ : + | "decltype(auto)" must be a placeholder for the complete type of the + variable (not for a component of that type) + * - ``2542``\ + - | ``decltype_auto_not_allowed_here``\ : + | decltype(auto) is not allowed here + * - ``2543``\ + - | ``decltype_auto_type_requires_initializer``\ : + | cannot deduce "decltype(auto)" (initializer required) + * - ``2544``\ + - | ``cannot_deduce_decltype_auto_type``\ : + | cannot deduce "decltype(auto)" type + * - ``2545``\ + - | ``thread_local_must_include_static_or_extern``\ : + | a block-scope thread-local declaration must include static or extern + * - ``2546``\ + - | ``deduced_return_type_conflict``\ : + | deduced return type *"type"*\ conflicts with previously deduced type + *"type"*\ + * - ``2547``\ + - | ``use_of_undefined_function_with_deduced_return_type``\ : + | cannot deduce the return type of *entity-kind "entity"*\ (declared + at line *xxxx*\ ); it has not been defined + * - ``2548``\ + - | ``virtual_function_cannot_have_deduced_return_type``\ : + | a virtual function cannot have a deduced return type + * - ``2549``\ + - | ``keyword_dropped``\ : + | *entity-kind "entity"*\ will be treated as a context-sensitive + keyword from this point + * - ``2550``\ + - | ``global_ns_has_no_actual_member``\ : + | the global namespace has no actual member *"xxxx"*\ + * - ``2551``\ + - | ``different_enum_comparison``\ : + | comparison between two different enum types (*"type"*\ and + *"type"*\ ) + * - ``2552``\ + - | ``unrecognized_target_attribute``\ : + | target attribute not recognized + * - ``2553``\ + - | ``gnu_mv_default_missing``\ : + | missing "default" target function + * - ``2554``\ + - | ``gnu_mv_only_one_arch``\ : + | only one arch= target may be specified + * - ``2555``\ + - | ``generic_class_cannot_be_custom_attribute``\ : + | a generic class cannot be a custom attribute + * - ``2556``\ + - | ``invalid_ms_attribute_target``\ : + | invalid attribute target *"xxxx"*\ + * - ``2557``\ + - | ``ambiguous_ms_attribute``\ : + | ambiguous attribute -- both *"type"*\ and *"type"*\ could be used + * - ``2558``\ + - | ``cli_attribute_inaccessible_field``\ : + | a named attribute argument can only reference a public nonstatic + read/write field or scalar property + * - ``2559``\ + - | ``cli_attribute_invalid_field``\ : + | a named attribute argument can only reference a nonstatic field or + scalar property of an attribute parameter type + * - ``2560``\ + - | ``cli_attribute_invalid_argument``\ : + | invalid attribute argument -- expression must be a constant of an + attribute parameter type + * - ``2561``\ + - | ``cli_typeid_of_generic_param_in_attribute``\ : + | an attribute argument cannot use generic type parameters + * - ``2562``\ + - | ``invalid_use_of_standalone_custom_ms_attr``\ : + | *"type"*\ may only be used as a standalone attribute + * - ``2563``\ + - | ``field_target_on_nontrivial_property_or_event``\ : + | the 'field' attribute target cannot be used on a non-trivial + property/event + * - ``2564``\ + - | ``invalid_attribute_target_for_standalone_ms_attr``\ : + | invalid attribute target for a standalone attribute + * - ``2565``\ + - | ``invalid_attribute_target_for_ms_attr``\ : + | invalid attribute target for this context + * - ``2566``\ + - | ``invalid_use_of_custom_ms_attr``\ : + | *"type"*\ attribute cannot be used here + * - ``2567``\ + - | ``cli_param_array_attribute_deprecated``\ : + | *"type"*\ is deprecated; use '...' to specify a parameter array + * - ``2568``\ + - | ``namespace_default_cannot_be_extended``\ : + | the default namespace cannot be extended + * - ``2569``\ + - | ``cppcx_box_invalid_type``\ : + | the boxed type must be a value class or enum + * - ``2570``\ + - | ``tracking_reference_to_value_class``\ : + | tracking reference to value class is not allowed + * - ``2571``\ + - | ``handle_to_value_class``\ : + | handle to value class is not allowed + * - ``2572``\ + - | ``tracking_reference_to_enum``\ : + | tracking reference to enum is not allowed + * - ``2573``\ + - | ``handle_to_enum``\ : + | handle to enum is not allowed + * - ``2574``\ + - | ``cppcx_public_native_type``\ : + | a public native type is not allowed + * - ``2575``\ + - | ``public_nested_type_in_cppcx_type``\ : + | a public nested type is not allowed + * - ``2576``\ + - | ``cppcx_generic_type_not_allowed``\ : + | generic types are not permitted in C++/CX + * - ``2577``\ + - | ``cppcx_generic_method_not_allowed``\ : + | generic methods are not permitted in C++/CX + * - ``2578``\ + - | ``cppcx_generic_constraints_not_allowed``\ : + | generic constraints are not allowed + * - ``2579``\ + - | ``nonpublic_data_member_in_public_cppcx_value_type``\ : + | non-public data members are not allowed in public C++/CX value types + * - ``2580``\ + - | ``public_nondata_member_in_public_cppcx_value_type``\ : + | public non-data members are not allowed in public C++/CX value types + * - ``2581``\ + - | ``cppcx_public_value_class_constructor``\ : + | constructors are not allowed in public C++/CX value types + * - ``2582``\ + - | ``bad_cppcx_event_add_return``\ : + | the return type of the "add" accessor must be + Windows::Foundation::EventRegistrationToken + * - ``2583``\ + - | ``bad_cppcx_event_remove_return``\ : + | the return type of the "remove" accessor must be void + * - ``2584``\ + - | ``bad_cppcx_event_remove_parameter``\ : + | the parameter type of the "remove" accessor must be + Windows::Foundation::EventRegistrationToken + * - ``2585``\ + - | ``cppcx_handle_or_ref_to_generic_param``\ : + | a handle or reference to a generic parameter type is not allowed + * - ``2586``\ + - | ``public_data_member_in_public_non_value_type``\ : + | public data members are not allowed in non-value types + * - ``2587``\ + - | ``cl_cppcx_only_in_microsoft_cplusplus``\ : + | C++/CX can be enabled only in Microsoft C++ mode + * - ``2588``\ + - | ``cl_cppcx_and_cppcli``\ : + | C++/CLI and C++/CX modes cannot be combined + * - ``2589``\ + - | ``cppcx_not_enabled``\ : + | *"xxxx"*\ requires C++/CX mode + * - ``2590``\ + - | ``cl_microsoft_version_insufficient_for_cppcx``\ : + | C++/CX mode requires microsoft_version >= 1600 + * - ``2591``\ + - | ``literal_fields_disallowed_in_cppcx_mode``\ : + | Literal fields are not allowed in C++/CX + * - ``2592``\ + - | ``normal_ref_bound_to_cppcx_lvalue``\ : + | a standard reference cannot be bound to a C++/CX type + * - ``2593``\ + - | ``cppcx_enum_base_has_no_platform_counterpart``\ : + | type must correspond to Platform::Boolean, default::uint8, + default::int8, default::int16, default::uint16, default::int32, + default::uint32, default::int64, or default::uint64 + * - ``2594``\ + - | ``event_in_cppcx_value_type``\ : + | a C++/CX value type cannot have events + * - ``2595``\ + - | ``bad_cppcx_dynamic_cast_type``\ : + | a dynamic_cast to a handle type must refer to a complete class type + * - ``2596``\ + - | ``cppcx_array_only_one_dimension_allowed``\ : + | Platform::Array can only be one-dimensional + * - ``2597``\ + - | ``cppcx_tracking_reference_on_standard_class_type``\ : + | tracking reference to standard class type is not allowed + * - ``2598``\ + - | ``cppcx_value_type_deriving_from_interface``\ : + | a C++/CX value type cannot inherit from an interface + * - ``2599``\ + - | ``cppcx_value_type_contains_virtual_function``\ : + | a C++/CX value type cannot contain virtual functions + * - ``2600``\ + - | ``partial_class_incorrect_type_or_location``\ : + | "partial" can only be applied to "ref class" or "ref struct" at + global scope or namespace scope + * - ``2601``\ + - | ``cppcx_invalid_array_property_set_value_parameter``\ : + | the parameter of the "set" accessor must be of type "const + Platform::Array^" + * - ``2602``\ + - | ``cppcx_public_global_type``\ : + | the definition of a public C++/CX type is not allowed at global scope + * - ``2603``\ + - | ``cppcx_public_indexed_property``\ : + | an indexed property with a public "get" or "set" accessor is not + allowed + * - ``2604``\ + - | ``cppcx_public_nested_delegate``\ : + | a public nested delegate type is not allowed + * - ``2605``\ + - | ``cppcx_bad_delegate_init_list``\ : + | invalid delegate initializer -- expected either "( [, Platform::CallbackContext])" or "(, [, Platform::CallbackContext [, bool]])" + * - ``2606``\ + - | ``cppcx_invalid_delegate_object``\ : + | invalid delegate initializer -- object must be a handle to a managed + class + * - ``2607``\ + - | ``cppcx_non_const_array_parameter``\ : + | C++/CX does not support 'in/out' arrays -- use "const + Platform::Array^" for 'in' and "Platform::WriteOnlyArray^" or + "Platform::Array^\*" for 'out' on public APIs + * - ``2608``\ + - | ``missing_target_attribute``\ : + | missing "target" attribute for *entity-kind "entity"*\ (declared at + line *xxxx*\ ) + * - ``2609``\ + - | ``no_matching_target_attribute``\ : + | no declared member function matches "target" attributes for + *entity-kind "entity"*\ + * - ``2610``\ + - | ``invalid_base_for_ms_attributes``\ : + | Microsoft attributes in this location are only permitted for + interface types + * - ``2611``\ + - | ``resolver_routine_required``\ : + | GNU function multiversion resolver routine required + * - ``2612``\ + - | ``enum_in_managed_class_missing_definition``\ : + | an enum type declared in a managed class must include a definition + * - ``2613``\ + - | ``decltype_qualified_declared_name``\ : + | a decltype-qualified name is nonstandard in this declaration context + * - ``2614``\ + - | ``final_modifier_requires_virtual_function``\ : + | nonvirtual function cannot be declared with "final" modifier + * - ``2615``\ + - | ``target_on_special_function``\ : + | "target" attribute on special function is not supported + * - ``2616``\ + - | ``target_string_must_be_narrow``\ : + | must be a narrow string literal + * - ``2617``\ + - | ``target_unmatched_parens``\ : + | unmatched parentheses + * - ``2618``\ + - | ``gcc_pragma_nothing_to_pop``\ : + | no corresponding "push_options" + * - ``2619``\ + - | ``pragma_inside_function``\ : + | this pragma is not allowed inside a function + * - ``2620``\ + - | ``inline_new_or_delete_operator``\ : + | declaring a new or delete operator "inline" is nonstandard + * - ``2621``\ + - | ``pack_expansion_for_field_mem_init``\ : + | a mem-initializer for a data member cannot be a pack expansion + * - ``2622``\ + - | ``generic_lambda_cannot_capture``\ : + | generic lambda expressions cannot have capture defaults in this mode + * - ``2623``\ + - | ``friend_with_def_arg_must_be_definition``\ : + | a default template argument in a friend declaration may only be + specified in a definition + * - ``2624``\ + - | ``friend_with_def_arg_must_be_only_decl``\ : + | a friend template declaration with a default template argument must + be the only declaration (first declared at line *xxxx*\ ) + * - ``2625``\ + - | ``non_autonomous_opaque_enum_decl``\ : + | an opaque enum declaration cannot be part of another declaration + * - ``2626``\ + - | ``nonstd_opaque_enum_decl_in_type_id``\ : + | an opaque enum declaration is nonstandard in this context + * - ``2627``\ + - | ``extended_friends_is_cpp11``\ : + | extended friend syntax is a C++11 feature + * - ``2628``\ + - | ``digit_separators_not_enabled``\ : + | digit separators not enabled, apostrophe begins a character literal + * - ``2629``\ + - | ``bad_digit_separator_pos``\ : + | digit separator cannot appear here + * - ``2630``\ + - | ``constexpr_ignored_on_microsoft_nonstatic_member``\ : + | "constexpr" is ignored here in Microsoft mode + * - ``2631``\ + - | ``bad_gnu_stmt_return``\ : + | invalid expression for statement expression result + * - ``2632``\ + - | ``macro_not_udl_suffix``\ : + | identifier is a macro and not a literal suffix + * - ``2633``\ + - | ``cannot_call_named_member_on_lvalue``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot be called + on an lvalue + * - ``2634``\ + - | ``cannot_call_named_member_on_rvalue``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot be called + on an rvalue + * - ``2635``\ + - | ``cannot_call_member_on_lvalue``\ : + | member function cannot be called on an lvalue + * - ``2636``\ + - | ``cannot_call_member_on_rvalue``\ : + | member function cannot be called on an rvalue + * - ``2637``\ + - | ``templ_param_list_too_long``\ : + | the template parameter list is too long + * - ``2638``\ + - | ``bad_alias_templ_redecl``\ : + | alias template type *"type"*\ is incompatible with the previous type + of *"type"*\ in the redeclaration of *entity-kind "entity"*\ + (declared at line *xxxx*\ ) + * - ``2639``\ + - | ``field_initializer_is_not_constant``\ : + | the field initializer for *entity-kind "entity"*\ (declared at line + *xxxx*\ ) is not a constant expression + * - ``2640``\ + - | ``constraint_number_mismatch``\ : + | the number of operand constraints must be the same in each constraint + string + * - ``2641``\ + - | ``too_many_constraints``\ : + | the constraint string contains too many alternative constraints; not + all constraints were checked + * - ``2643``\ + - | ``decltype_auto_cannot_be_qualified``\ : + | decltype(auto) cannot have added type qualifiers + * - ``2644``\ + - | ``bad_init_capture_capture``\ : + | init-capture *"entity"*\ (declared at line *xxxx*\ ) cannot be + captured here + * - ``2645``\ + - | ``invalid_nontype_template_argument``\ : + | invalid nontype template argument of type *"type"*\ + * - ``2646``\ + - | ``abi_tag_ignored_in_C_mode``\ : + | the abi_tag attribute is ignored (it has no meaning in C mode) + * - ``2647``\ + - | ``abi_tag_redefinition``\ : + | redeclaration adds abi_tag attribute "*xxxx*\ " + * - ``2648``\ + - | ``abi_tag_ignored``\ : + | abi_tag attribute is ignored (superseded by later abi_tag attribute) + * - ``2649``\ + - | ``no_abi_tag_on_declaration``\ : + | previous declaration of *entity-kind "entity"*\ (declared at line + *xxxx*\ ) had no abi_tag attribute + * - ``2651``\ + - | ``abi_tag_ignored_on_specialization``\ : + | abi_tag attribute is ignored on specialization + * - ``2652``\ + - | ``decltype_auto_return_must_be_standalone``\ : + | decltype(auto) cannot appear under a pointer, reference, or + pointer-to-member construct + * - ``2653``\ + - | ``exp_class_or_typename``\ : + | expected "class" or "typename" + * - ``2654``\ + - | ``placement_new_refers_to_non_placement_delete``\ : + | placement "new" expression refers to non-placement *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``2655``\ + - | ``cl_must_specify_cpp14_mode``\ : + | must specify C++14 mode when building runtime library + * - ``2659``\ + - | ``constexpr_not_const``\ : + | constexpr non-static member function will not be implicitly 'const' + in C++14 + * - ``2660``\ + - | ``nonliteral_var_in_constexpr_function``\ : + | variable type *"type"*\ in constexpr function is not a literal type + * - ``2661``\ + - | ``nonautomatic_var_in_constexpr_function``\ : + | variable in constexpr function does not have automatic storage + duration + * - ``2662``\ + - | ``uninitialized_var_in_constexpr_function``\ : + | variable in constexpr function is uninitialized + * - ``2663``\ + - | ``auto_direct_list_init_requires_singleton``\ : + | braced initialization of a variable declared with a placeholder type + but without "=" requires exactly one element inside the braces + * - ``2664``\ + - | ``cl_invalid_target``\ : + | no "*xxxx*\ " --target configuration exists + * - ``2665``\ + - | ``attribute_not_supported_in_x86_64``\ : + | attribute is supported only in 32-bit x86 configurations + * - ``2666``\ + - | ``cl_missing_argument``\ : + | "*xxxx*\ " requires an argument + * - ``2667``\ + - | ``special_member_coroutine``\ : + | a constructor or destructor cannot be a coroutine + * - ``2668``\ + - | ``main_coroutine``\ : + | *entity-kind "entity"*\ cannot be a coroutine + * - ``2669``\ + - | ``yield_in_catch``\ : + | co_yield expressions are not permitted in a catch clause + * - ``2674``\ + - | ``special_class_template_not_found``\ : + | class template *"xxxx"*\ not found + * - ``2675``\ + - | ``typename_needed``\ : + | use the "typename" keyword to treat *entity-kind "entity"*\ as a + type in a dependent context + * - ``2676``\ + - | ``shufflevector_index_out_of_range``\ : + | argument value must be less than the sum of the vector elements + * - ``2677``\ + - | ``not_a_type_member``\ : + | *"type"*\ has no member *"xxxx"*\ + * - ``2678``\ + - | ``braced_list_for_implicit_return_type``\ : + | a brace-enclosed list does not provide a return type + * - ``2679``\ + - | ``await_not_allowed_outside_function_scope``\ : + | a co_await expression must appear in a function scope + * - ``2680``\ + - | ``await_not_allowed_in_catch_clause``\ : + | a co_await expression is not allowed inside a catch clause + * - ``2681``\ + - | ``coroutine_with_ellipsis_parameter``\ : + | a coroutine cannot have an ellipsis parameter + * - ``2682``\ + - | ``cl_relaxed_constexpr_requires_bool``\ : + | enabling C++14-style constexpr requires support for "bool" + * - ``2683``\ + - | ``constexpr_function_undefined``\ : + | constexpr *entity-kind "entity"*\ (declared at line *xxxx*\ ) is not + defined + * - ``2684``\ + - | ``constexpr_call_not_interpretable``\ : + | this call cannot be evaluated because the target function + *entity-kind "entity"*\ (declared at line *xxxx*\ ) is not constexpr + or not completely defined yet + * - ``2687``\ + - | ``anon_union_alias_member_template``\ : + | invalid anonymous union -- alias member template is not allowed + * - ``2688``\ + - | ``utf8_char_lit_too_long``\ : + | a UTF-8 character literal value cannot occupy more than one code unit + * - ``2689``\ + - | ``variable_not_constant_valued``\ : + | the value of *entity-kind "entity"*\ (declared at line *xxxx*\ ) + cannot be used as a constant + * - ``2690``\ + - | ``variable_not_constant_addressed``\ : + | a pointer or reference to *entity-kind "entity"*\ (declared at line + *xxxx*\ ) cannot be used as a constant + * - ``2691``\ + - | ``constexpr_non_array_subscript``\ : + | nonzero subscript for non-array object + * - ``2692``\ + - | ``constexpr_out_of_bounds_array_access``\ : + | cannot access position *n*\ in array of *n*\ elements + * - ``2693``\ + - | ``constexpr_called_from``\ : + | called from: + * - ``2694``\ + - | ``constexpr_union_field_inactive``\ : + | invalid access to inactive *entity-kind "entity"*\ of union + (*entity-kind "entity"*\ is active) + * - ``2695``\ + - | ``constexpr_goto``\ : + | 'goto' cannot be executed in constexpr contexts + * - ``2696``\ + - | ``constexpr_missing_return_value``\ : + | missing return value + * - ``2697``\ + - | ``constexpr_null_callee``\ : + | callee is null + * - ``2698``\ + - | ``constexpr_null_dereference``\ : + | attempt to dereference a null pointer + * - ``2699``\ + - | ``constexpr_access_one_past_array_end``\ : + | attempt to access storage one position past the end of an array of + *n*\ elements + * - ``2700``\ + - | ``constexpr_access_to_expired_storage``\ : + | attempt to access expired storage + * - ``2701``\ + - | ``constexpr_access_to_runtime_storage``\ : + | attempt to access run-time storage + * - ``2703``\ + - | ``constexpr_call_to_nonconstexpr_function``\ : + | cannot call non-constexpr *entity-kind "entity"*\ (declared at line + *xxxx*\ ) + * - ``2704``\ + - | ``constexpr_vla``\ : + | cannot use variable-length array during constexpr evaluation + * - ``2705``\ + - | ``constexpr_negative_shift``\ : + | cannot perform a negative shift + * - ``2706``\ + - | ``constexpr_shift_excess``\ : + | shift amount (*n*\ ) too large + * - ``2707``\ + - | ``constexpr_integer_overflow``\ : + | value exceeds range of *"type"*\ + * - ``2708``\ + - | ``constexpr_fp_error``\ : + | floating-point error + * - ``2709``\ + - | ``constexpr_null_ptr_to_member_data``\ : + | attempt to dereference a null pointer-to-member (data member) + * - ``2710``\ + - | ``comparison_of_pointers_to_void_and_function``\ : + | comparing a pointer to void and a pointer to a function is nonstandard + * - ``2711``\ + - | ``ms_metadata_init_failed``\ : + | metadata initialization failed + * - ``2712``\ + - | ``constexpr_bad_derived_class_cast``\ : + | invalid base-to-derived cast (actual derived class type is *"type"*\ ) + * - ``2713``\ + - | ``constexpr_invalid_pm_access``\ : + | invalid access to *entity-kind "entity"*\ in object of complete type + *"type"*\ + * - ``2714``\ + - | ``bad_gnu_auto_type``\ : + | *"xxxx"*\ not allowed here + * - ``2715``\ + - | ``gnu_auto_type_with_secondary_declarator``\ : + | *"xxxx"*\ does not permit multiple declarators + * - ``2716``\ + - | ``auto_type_brace_initialization_not_allowed``\ : + | initialization with "{...}" is not allowed for *"xxxx"*\ + * - ``2717``\ + - | ``modified_auto_type``\ : + | *"xxxx"*\ must be a placeholder for the complete type of the + variable (not for a component of that type) + * - ``2718``\ + - | ``gnu_auto_type_without_initializer``\ : + | a variable declared with *"xxxx"*\ requires an initializer + * - ``2719``\ + - | ``constant_must_be_positive``\ : + | integer constant must be greater than or equal to zero + * - ``2720``\ + - | ``type_must_be_integral``\ : + | type must be an integral type + * - ``2721``\ + - | ``constexpr_expression_cannot_be_interpreted``\ : + | expression cannot be interpreted + * - ``2722``\ + - | ``constexpr_statement_cannot_be_interpreted``\ : + | statement cannot be interpreted + * - ``2723``\ + - | ``constexpr_interpreter_address``\ : + | invalid use of address of interpreter storage + * - ``2724``\ + - | ``constexpr_invalid_constant_kind``\ : + | invalid constant kind for constant-expression + * - ``2725``\ + - | ``constexpr_type_too_large``\ : + | type *"type"*\ too large for constant-expression evaluation + * - ``2726``\ + - | ``constexpr_type_invalid``\ : + | invalid type *"type"*\ for constant-expression evaluation + * - ``2727``\ + - | ``constexpr_invalid_type_conversion``\ : + | conversion from *"type"*\ to *"type"*\ is invalid in + constant-expression evaluation + * - ``2728``\ + - | ``constexpr_fp_conversion_failed``\ : + | floating-point conversion failed + * - ``2730``\ + - | ``deduced_return_types_is_cpp14``\ : + | deduced return types are a C++14 feature + * - ``2731``\ + - | ``constexpr_ctor_with_dtor``\ : + | cannot evaluate a constructor with an associated destructor + * - ``2732``\ + - | ``constexpr_missing_initializer_for_field``\ : + | *entity-kind "entity"*\ not initialized during constexpr evaluation + * - ``2733``\ + - | ``constexpr_invalid_pdiff``\ : + | invalid pointer difference in constexpr evaluation + * - ``2734``\ + - | ``constexpr_non_array_pointer_arithmetic``\ : + | invalid arithmetic on non-array pointer + * - ``2735``\ + - | ``constexpr_pointer_ahead_of_array``\ : + | cannot set pointer before the first array element + * - ``2736``\ + - | ``coroutine_with_deduced_return_type``\ : + | a coroutine with a deduced return type is invalid + * - ``2737``\ + - | ``await_in_unevaluated_operand``\ : + | expression not allowed in unevaluated context + * - ``2740``\ + - | ``return_in_coroutine``\ : + | "return" is not permitted in a coroutine (use "co_return" instead) + * - ``2741``\ + - | ``invalid_co_return``\ : + | "co_return" is only allowed in coroutines + * - ``2742``\ + - | ``constexpr_fp_values_not_comparable``\ : + | floating-point values cannot be compared + * - ``2743``\ + - | ``constexpr_pointers_not_comparable``\ : + | pointer values cannot be compared because they do not point into the + same complete object or they point to subobjects with different + accessibility + * - ``2744``\ + - | ``ignoring_attribute_on_non_inline_namespace``\ : + | ignoring abi_tag attribute on non-inline namespace + * - ``2745``\ + - | ``ignoring_attribute_on_anonymous_namespace``\ : + | ignoring abi_tag attribute on anonymous namespace + * - ``2746``\ + - | ``complex_template_parameter``\ : + | complex or imaginary template parameter type is nonstandard + * - ``2747``\ + - | ``yield_outside_of_function``\ : + | co_yield expression is not permitted outside a function scope + * - ``2748``\ + - | ``thread_local_ignored``\ : + | ignoring thread-local indication on anonymous union + * - ``2751``\ + - | ``object_not_initialized``\ : + | access to uninitialized object + * - ``2752``\ + - | ``constexpr_volatile_fetch``\ : + | attempt to read from volatile storage + * - ``2753``\ + - | ``constexpr_no_active_union_field``\ : + | invalid access to inactive *entity-kind "entity"*\ of union (no + field is active) + * - ``2754``\ + - | ``label_in_constexpr_function``\ : + | label definitions cannot appear in constexpr functions + * - ``2755``\ + - | ``constexpr_equality_past_the_end_address``\ : + | cannot compare a pointer past the end of an array with a pointer to + another complete object + * - ``2756``\ + - | ``variable_templ_function_type``\ : + | function type *"type"*\ is an invalid type for a variable template + instantiation + * - ``2757``\ + - | ``incomplete_var_type``\ : + | variable cannot have incomplete type *"type"*\ + * - ``2758``\ + - | ``field_subobject_not_initialized``\ : + | access to uninitialized subobject (*entity-kind "entity"*\ ) + * - ``2759``\ + - | ``base_subobject_not_initialized``\ : + | access to uninitialized subobject (base class *"type"*\ ) + * - ``2760``\ + - | ``constexpr_vacuous_dtor_call``\ : + | a pseudo-destructor call is not permitted in a constant-expression + * - ``2761``\ + - | ``constexpr_modifying_const_storage``\ : + | attempt to modify const storage + * - ``2764``\ + - | ``constexpr_access_past_object``\ : + | attempt to access storage one position past an object treated as an + array of one element + * - ``2765``\ + - | ``constexpr_reinterpret_cast``\ : + | cannot use reinterpret_cast in constant-expression evaluation + * - ``2766``\ + - | ``constexpr_invalid_null_ptr_operation``\ : + | operation not allowed on null pointer + * - ``2767``\ + - | ``star_this_not_constant_valued``\ : + | the value of \*this cannot be used as a constant + * - ``2768``\ + - | ``inline_on_nested_namespace``\ : + | the "inline" keyword cannot be used on a nested namespace declaration + * - ``2769``\ + - | ``carries_dependency_ignored``\ : + | the "carries_dependency" attribute is ignored + * - ``2770``\ + - | ``event_interface_cannot_have_definition``\ : + | an "\__event \__interface" cannot have a definition here + * - ``2771``\ + - | ``invalid_event_handler_type``\ : + | an event handler must have a void or integral return type + * - ``2772``\ + - | ``event_interface_must_be_previously_defined``\ : + | an "\__event \__interface" must have been previously defined + * - ``2773``\ + - | ``too_many_template_arguments``\ : + | too many template arguments for *entity-kind "entity"*\ + * - ``2774``\ + - | ``enumerator_already_declared``\ : + | enumerator already declared (see *entity-kind "entity"*\ (declared + at line *xxxx*\ )) + * - ``2775``\ + - | ``microsoft_version_doesnt_support_cpp14_mode``\ : + | the version of Microsoft being emulated must be at least 1903 to use + "--ms_c++14" + * - ``2776``\ + - | ``microsoft_version_doesnt_support_cpplatest_mode``\ : + | the version of Microsoft being emulated must be at least 1903 to use + "--ms_c++latest" + * - ``2777``\ + - | ``c11_atomic_array_or_function_type``\ : + | type *"type"*\ cannot be _Atomic because it is an array or function + type + * - ``2778``\ + - | ``c11_atomic_specifier_with_qualified_type``\ : + | the _Atomic(...) specifier cannot be applied to qualified type + *"type"*\ + * - ``2779``\ + - | ``access_to_member_of_c11_atomic_object``\ : + | access to member of _Atomic object + * - ``2780``\ + - | ``c11_atomic_bit_field``\ : + | a bit field cannot have an _Atomic type + * - ``2782``\ + - | ``nonconstexpr_mem_init_ctor_for_constexpr_ctor``\ : + | constexpr constructor calls non-constexpr constructor for subobject + initialization + * - ``2783``\ + - | ``terse_static_assert_not_enabled``\ : + | expected a comma (the one-argument version of static_assert is not + enabled in this mode) + * - ``2784``\ + - | ``terse_static_assert``\ : + | static assertion failed + * - ``2785``\ + - | ``conflicting_nullability``\ : + | at most one of the qualifiers _Nullable, _Nonnull, and + _Null_unspecified can modify a type + * - ``2786``\ + - | ``invalid_type_for_nullability``\ : + | nullability qualifiers are only permitted on pointer and + pointer-to-member types + * - ``2787``\ + - | ``vector_length_too_large``\ : + | vector length is too large + * - ``2788``\ + - | ``invalid_vector_element_type``\ : + | vector element type must be integral, enum, or real floating-point + type + * - ``2789``\ + - | ``builtin_needs_128_bit_integers``\ : + | builtin function is not available because 128-bit integers are not + supported + * - ``2790``\ + - | ``builtin_needs_vector_types``\ : + | builtin function is not available because vector types are not + supported + * - ``2791``\ + - | ``must_introduce_attribute``\ : + | two consecutive left square brackets always introduce an attribute + list but an attribute list cannot appear here + * - ``2792``\ + - | ``invalid_target_attribute``\ : + | unrecognized "target" attribute disqualifies this routine from being + used by resolver routine + * - ``2793``\ + - | ``vector_type_required``\ : + | *"type"*\ is not a vector type + * - ``2794``\ + - | ``vector_types_differ_in_length``\ : + | vector types *"type"*\ and *"type"*\ must have the same length + * - ``2795``\ + - | ``member_special_after_class_definition``\ : + | added default arguments cannot result in declaring a default or copy + constructor + * - ``2796``\ + - | ``template_arg_cannot_point_to_subobject``\ : + | a nontype template argument of reference type must bind to a function + or to a complete object + * - ``2797``\ + - | ``type_not_allowed_here``\ : + | *"type"*\ not allowed here + * - ``2798``\ + - | ``register_keyword_disallowed``\ : + | use of the "register" storage class specifier is not allowed + * - ``2799``\ + - | ``register_keyword_deprecated``\ : + | use of the "register" storage class specifier is deprecated + * - ``2800``\ + - | ``incr_of_bool_not_allowed``\ : + | incrementing a bool value is not allowed + * - ``2801``\ + - | ``redeclaration_of_range_iterator``\ : + | *"xxxx"*\ , declared as iterator of range-based "for" statement, may + not be redeclared in this scope + * - ``2802``\ + - | ``namespace_not_allowed``\ : + | an attribute namespace may not be used here (because a "using" prefix + was specified) + * - ``2803``\ + - | ``attribute_namespace_unrecognized``\ : + | attribute namespace *"xxxx"*\ is unrecognized + * - ``2804``\ + - | ``default_member_init_for_value_class``\ : + | a default member initializer is not permitted in a value class + * - ``2805``\ + - | ``cl_implicit_noexcept_requires_noexcept_support``\ : + | "--implicit_noexcept" requires a mode that enables noexcept + * - ``2806``\ + - | ``constexpr_virtual_base``\ : + | cannot fold operation involving virtual base class (*"type"*\ ) + * - ``2807``\ + - | ``initializer_not_constant``\ : + | initialization is not constant + * - ``2808``\ + - | ``constexpr_incomplete_type``\ : + | cannot evaluate value of incomplete *"type"*\ + * - ``2809``\ + - | ``nodiscard_routine``\ : + | ignoring return value from routine declared with "nodiscard" attribute + * - ``2810``\ + - | ``nodiscard_return_type``\ : + | ignoring return value type with "nodiscard" attribute + * - ``2811``\ + - | ``nodiscard_doesnt_apply``\ : + | the "nodiscard" attribute does not apply to destructors or routines + with void return type + * - ``2812``\ + - | ``fallthrough_applies_to_null_statement``\ : + | the "fallthrough" attribute only applies to null statements + * - ``2813``\ + - | ``fallthrough_not_in_switch``\ : + | the "fallthrough" attribute may only appear in an enclosing switch + statement + * - ``2814``\ + - | ``fallthrough_must_precede_switch_case``\ : + | fallthrough statement must precede switch case label or default + * - ``2815``\ + - | ``constexpr_expiring_temporary``\ : + | reference or pointer to temporary with limited lifetime + * - ``2816``\ + - | ``address_of_nontrue_enable_if_function``\ : + | cannot take the address of a function with an "enable_if" attribute + whose condition is not unconditionally true + * - ``2817``\ + - | ``nonconstant_enable_if_attr``\ : + | "enable_if" attributes with conditions that are not constant values + are not currently supported + * - ``2818``\ + - | ``attribute_declared_here``\ : + | attribute was declared here + * - ``2819``\ + - | ``has_include_not_in_if``\ : + | __has_include cannot appear outside #if + * - ``2820``\ + - | ``coclass_base_requirements_not_met``\ : + | could not add CComCoClass base class + * - ``2821``\ + - | ``constexpr_string_not_null_terminated``\ : + | not a null-terminated string + * - ``2822``\ + - | ``non_scalar_vacuous_dtor_call``\ : + | non-scalar type *"type"*\ cannot be used in a pseudo-destructor call + * - ``2823``\ + - | ``constexpr_weak_address``\ : + | address of "weak" *entity-kind "entity"*\ is not constant + * - ``2824``\ + - | ``excessive_rescan_depth``\ : + | too many recursive substitutions of function template signatures + * - ``2825``\ + - | ``invalid_struct_binding_specifier``\ : + | invalid specifier for structured binding declaration + * - ``2826``\ + - | ``invalid_struct_binding_syntax``\ : + | invalid structured binding syntax + * - ``2827``\ + - | ``missing_initializer``\ : + | missing initializer + * - ``2828``\ + - | ``invalid_struct_binding_type``\ : + | type *"type"*\ has no components to bind to + * - ``2829``\ + - | ``too_many_struct_bindings``\ : + | too many identifiers + * - ``2830``\ + - | ``missing_bindings``\ : + | there are more elements than there are binding names + * - ``2831``\ + - | ``missing_std_tuple_element``\ : + | "std::tuple_element" not defined + * - ``2832``\ + - | ``missing_std_tuple_element_instance``\ : + | cannot instantiate "std::tuple_element" for <*xxxx*\ , *"type"*\ > + * - ``2833``\ + - | ``failed_tuple_container_member_get``\ : + | cannot call member function "get<*xxxx*\ >()" for type *"type"*\ + * - ``2834``\ + - | ``tuple_get_no_matching_overload``\ : + | no instance of *"entity"*\ matches the argument list + * - ``2835``\ + - | ``struct_binding_undefined_identifier``\ : + | this structured binding requires a suitable *"xxxx"*\ function and + none was found + * - ``2836``\ + - | ``struct_binding_inline``\ : + | a structured binding cannot be declared "inline" + * - ``2837``\ + - | ``struct_binding_constexpr``\ : + | a structured binding cannot be declared "constexpr" + * - ``2838``\ + - | ``struct_binding_storage_class``\ : + | a structured binding cannot declare an explicit storage class + * - ``2839``\ + - | ``invalid_tuple_size``\ : + | std::tuple_size<*"type"*\ >::value is not a valid integral + constant-expression + * - ``2840``\ + - | ``condition_does_not_declare_a_variable``\ : + | a condition declaration must declare a variable + * - ``2841``\ + - | ``condition_decl_must_have_initializer``\ : + | a condition declaration must include an initializer + * - ``2842``\ + - | ``parenthesized_init_not_allowed``\ : + | a parenthesized initializer is not permitted for a condition + declaration + * - ``2843``\ + - | ``condition_with_multiple_declarators``\ : + | a condition declaration can only declare one variable + * - ``2844``\ + - | ``struct_binding_lambda``\ : + | structured binding cannot bind to closure type + * - ``2845``\ + - | ``struct_binding_private_member``\ : + | cannot bind to non-public *entity-kind "entity"*\ + * - ``2846``\ + - | ``struct_binding_incomplete_type``\ : + | cannot bind to incomplete type *"type"*\ + * - ``2847``\ + - | ``invalid_init_statement``\ : + | this declaration is not valid here + * - ``2848``\ + - | ``constexpr_function_with_function_try_block``\ : + | the body of a constexpr function cannot be a function try block + * - ``2849``\ + - | ``branch_into_constexpr_if``\ : + | transfer of control into a constexpr if block is not allowed + * - ``2850``\ + - | ``lambda_capture_structured_binding``\ : + | structured binding cannot be captured + * - ``2851``\ + - | ``microsoft_version_doesnt_support_cpp17_mode``\ : + | the version of Microsoft being emulated must be at least 1911 to use + "--ms_c++17" + * - ``2852``\ + - | ``attempt_to_read_past_end_of_object``\ : + | attempt to read past the end of the object + * - ``2853``\ + - | ``constexpr_lambdas_not_enabled``\ : + | constexpr lambdas are not enabled in this mode + * - ``2854``\ + - | ``lambda_not_constant_expr``\ : + | a constant expression cannot contain a lambda expression + * - ``2855``\ + - | ``template_argument_index_out_of_bounds``\ : + | value exceeds number of template arguments + * - ``2856``\ + - | ``fold_expression_operator_mismatch``\ : + | second operator in binary fold expression does not match first + * - ``2857``\ + - | ``invalid_fold_expression_operator``\ : + | invalid fold expression operator + * - ``2858``\ + - | ``two_packs_in_fold_expression``\ : + | a binary fold expression cannot apply to two parameter packs + * - ``2859``\ + - | ``invalid_empty_fold_expression``\ : + | empty expansion not valid for this fold expression + * - ``2860``\ + - | ``inline_nonstatic_data_mem``\ : + | a nonstatic data member cannot be declared as inline + * - ``2861``\ + - | ``no_pack_in_fold_expression``\ : + | fold expression does not refer to a parameter pack + * - ``2862``\ + - | ``same_param_types_with_different_exception_specifications``\ : + | two functions with the same parameter types but different exception + specifications cannot be overloaded + * - ``2863``\ + - | ``dynamic_exc_spec_not_permitted``\ : + | dynamic exception specifications are not permitted in this mode + * - ``2865``\ + - | ``invalid_noexcept_specifier_operand``\ : + | invalid operand for noexcept specifier + * - ``2866``\ + - | ``lambda_in_noexcept_specifier``\ : + | lambda expression cannot appear in noexcept specifier of a template + * - ``2867``\ + - | ``inaccessible_rvalue_dtor``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) is inaccessible + * - ``2868``\ + - | ``bad_enum_template_decl``\ : + | invalid specifier in enum template declaration + * - ``2869``\ + - | ``no_float80``\ : + | 80-bit floating-point types are not supported in this configuration + * - ``2870``\ + - | ``no_float128``\ : + | 128-bit floating-point types are not supported in this configuration + * - ``2871``\ + - | ``invalid_enumerator_value``\ : + | invalid enumerator value + * - ``2872``\ + - | ``must_be_atomic_qualified_type``\ : + | must be an _Atomic qualified type + * - ``2873``\ + - | ``element_type_incomplete``\ : + | type of array element must be complete + * - ``2874``\ + - | ``always_inline_suppressed``\ : + | the always_inline attribute has been suppressed for this function + * - ``2875``\ + - | ``negative_value``\ : + | a negative value is not permitted here + * - ``2876``\ + - | ``integer_pack_element_for_type``\ : + | an integer pack element cannot match *entity-kind "entity"*\ + * - ``2877``\ + - | ``integer_pack_element_for_template``\ : + | an integer pack element cannot match *entity-kind "entity"*\ + * - ``2878``\ + - | ``unexpected_designator``\ : + | unexpected designator + * - ``2879``\ + - | ``cannot_evaluate_builtin_offsetof``\ : + | cannot evaluate \__builtin_offsetof + * - ``2880``\ + - | ``deduction_guide_def``\ : + | deduction guide *"type"*\ cannot be defined + * - ``2881``\ + - | ``bad_deduction_guide_scope``\ : + | deduction guide must be declared in the same scope as *entity-kind + "entity"*\ + * - ``2882``\ + - | ``invalid_specifier_for_deduction_guide``\ : + | invalid specifier for deduction guide declaration (only "explicit" is + permitted) + * - ``2883``\ + - | ``constexpr_mutable_field_load``\ : + | mutable *entity-kind "entity"*\ of a constant cannot be accessed in + a constant expression + * - ``2884``\ + - | ``member_function_modifier_on_static_member``\ : + | function modifier does not apply to static member declaration + * - ``2885``\ + - | ``overloadable_attribute_requires_prototype``\ : + | the "overloadable" attribute requires a prototyped function + declaration + * - ``2886``\ + - | ``cannot_deduce_auto_templ_param``\ : + | cannot deduce "auto" template parameter type *"type"*\ from + *"type"*\ + * - ``2887``\ + - | ``modified_class_template_placeholder``\ : + | class template name must be a placeholder for the complete type being + initialized (not for a component of that type) + * - ``2888``\ + - | ``alias_declaration_is_cpp11``\ : + | alias declarations are a C++11 feature + * - ``2889``\ + - | ``alias_template_is_cpp11``\ : + | alias templates are a C++11 feature + * - ``2890``\ + - | ``bad_deduction_guide_return_type``\ : + | the return type must directly designate a specialization of the + associated class template + * - ``2891``\ + - | ``explicit_deduction_guide_in_copy_list_init``\ : + | copy-list-initialization cannot use "explicit" *entity-kind + "entity"*\ + * - ``2893``\ + - | ``invalid_udl_value``\ : + | Invalid value for user-defined literal operator + * - ``2894``\ + - | ``has_cpp_attrib_not_in_if``\ : + | *xxxx*\ cannot appear outside of preprocessor directives + * - ``2895``\ + - | ``bad_deduction_guide_access``\ : + | deduction guide must be declared with the same accessibility as + *entity-kind "entity"*\ + * - ``2896``\ + - | ``lambda_not_allowed_here``\ : + | a lambda is not permitted in this context + * - ``2897``\ + - | ``align_not_equivalent``\ : + | specified alignment is not equivalent to previous declaration + * - ``2898``\ + - | ``no_alignment_on_definition``\ : + | no alignment specified on definition; previous declaration had + specified an alignment + * - ``2899``\ + - | ``builtin_needs_128_bit_floats``\ : + | builtin function is not available because 128-bit floating-point + types are not supported + * - ``2900``\ + - | ``constexpr_shift_negative_value``\ : + | left-shifting a negative value has undefined behavior + * - ``2901``\ + - | ``no_array_designators_in_cpp_mode``\ : + | array designators are nonstandard in C++ + * - ``2902``\ + - | ``no_chained_designators_in_cpp_mode``\ : + | chained designators are nonstandard in C++ + * - ``2903``\ + - | ``no_mixed_init_in_cpp_mode``\ : + | mixing designated and non-designated initializers is nonstandard in + C++ + * - ``2904``\ + - | ``no_out_of_order_init_in_cpp_mode``\ : + | out-of-order initializers are nonstandard in C++ + * - ``2905``\ + - | ``invalid_string_literal_operator_template``\ : + | a string literal operator template must have a template parameter + list equivalent to "" + * - ``2906``\ + - | ``duplicate_designator``\ : + | duplicate designator is not allowed + * - ``2907``\ + - | ``likely_unlikely_conflict``\ : + | attribute conflicts with previous likely/unlikely attribute + * - ``2908``\ + - | ``implicit_copy_this_capture_deprecated``\ : + | the implicit by-copy capture of "this" is deprecated + * - ``2909``\ + - | ``empty_lambda_template_param_list``\ : + | an empty template parameter list is not allowed in a lambda expression + * - ``2910``\ + - | ``microsoft_version_doesnt_support_cpp20_mode``\ : + | the version of Microsoft being emulated must be at least 1920 to use + "--ms_c++20" + * - ``2911``\ + - | ``bad_stdc_pragma_arg_for_mode``\ : + | STDC pragma argument not accepted in this mode + * - ``2912``\ + - | ``if_constexpr_is_cpp17``\ : + | constexpr if statements are a C++17 feature + * - ``2913``\ + - | ``no_pack_expansion_in_designator``\ : + | pack expansion is not allowed in a designated initializer list + * - ``2914``\ + - | ``no_designator_value``\ : + | field designator has no value + * - ``2915``\ + - | ``multiple_union_field_initializers_empty``\ : + | a union can have at most one field initializer + * - ``2916``\ + - | ``bad_ordering_type``\ : + | no valid std::*xxxx*\ type found ( must be included) + * - ``2917``\ + - | ``invalid_spaceship_types``\ : + | invalid types (*"type"*\ and *"type"*\ ) for built-in operator<=> + * - ``2918``\ + - | ``fold_expressions_nonstandard``\ : + | fold expressions are nonstandard in this mode + * - ``2919``\ + - | ``selection_initializer_nonstandard``\ : + | C++17-style initializer is nonstandard in this mode + * - ``2920``\ + - | ``star_this_capture_nonstandard``\ : + | capturing \*this is nonstandard in this mode + * - ``2921``\ + - | ``using_attribute_nonstandard``\ : + | C++17-style "using" attribute prefix is nonstandard in this mode + * - ``2922``\ + - | ``nested_namespace_nonstandard``\ : + | C++17-style nested namespaces are nonstandard in this mode + * - ``2923``\ + - | ``constexpr_and_consteval_specifiers``\ : + | only one of "constexpr", "consteval", and "constinit" can appear on a + declaration + * - ``2924``\ + - | ``consteval_virtual_combination``\ : + | a function cannot be both consteval and virtual in this mode + * - ``2925``\ + - | ``consteval_explicit_instantiation``\ : + | "consteval" is not allowed on an explicit instantiation directive + * - ``2926``\ + - | ``invalid_consteval``\ : + | "consteval" is not valid here + * - ``2927``\ + - | ``consteval_destructor``\ : + | a destructor cannot be consteval + * - ``2928``\ + - | ``consteval_ctor_with_virtual_base``\ : + | a constructor for a class with virtual bases cannot be consteval + * - ``2929``\ + - | ``consteval_variable``\ : + | "consteval" is not permitted on the declaration of a variable or + static data member + * - ``2930``\ + - | ``previous_consteval_decl_conflict``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared consteval + * - ``2931``\ + - | ``previous_nonconsteval_decl_conflict``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + not declared consteval + * - ``2932``\ + - | ``consteval_main``\ : + | function "main" may not be declared consteval + * - ``2933``\ + - | ``consteval_call_nonconstant``\ : + | call to consteval *entity-kind "entity"*\ did not produce a valid + constant expression + * - ``2934``\ + - | ``address_of_consteval_function``\ : + | address of consteval *entity-kind "entity"*\ in constant expression + result + * - ``2935``\ + - | ``consteval_overrides_nonconsteval``\ : + | consteval member cannot override non-consteval *entity-kind + "entity"*\ + * - ``2936``\ + - | ``nonconsteval_overrides_consteval``\ : + | non-consteval member cannot override consteval *entity-kind + "entity"*\ + * - ``2938``\ + - | ``constexpr_invalid_dynamic_cast``\ : + | dynamic_cast to subobject of type *"type"*\ is invalid (most-derived + type is *"type"*\ ) + * - ``2939``\ + - | ``VA_OPT_not_allowed``\ : + | the identifier \__VA_OPT\__ can only appear in the replacement lists + of variadic macros + * - ``2940``\ + - | ``nested_VA_OPT``\ : + | __VA_OPT\__ cannot appear in a \__VA_OPT\__ operand + * - ``2941``\ + - | ``unclosed_VA_OPT``\ : + | missing closing parenthesis for \__VA_OPT\__ + * - ``2942``\ + - | ``missing_VA_OPT_paren``\ : + | __VA_OPT\__ must be followed by "(" + * - ``2943``\ + - | ``paste_cannot_be_first_in_VA_OPT``\ : + | "##" may not be first in a \__VA_OPT\__ operand + * - ``2944``\ + - | ``paste_cannot_be_last_in_VA_OPT``\ : + | "##" may not be last in a \__VA_OPT\__ operand + * - ``2945``\ + - | ``nested_inline_namespace_nonstandard``\ : + | C++20-style nested inline namespaces are nonstandard in this mode + * - ``2946``\ + - | ``derived_class_too_far``\ : + | cannot convert pointer to base class *"type"*\ to pointer to derived + class *"type"*\ -- attempt to point beyond the most-derived object + * - ``2948``\ + - | ``invalid_variable_main``\ : + | "main" cannot be used as a global variable name or given C language + linkage + * - ``2949``\ + - | ``linkage_main``\ : + | function "main" cannot be declared in a linkage-specification + * - ``2950``\ + - | ``struct_binding_in_condition``\ : + | structured binding is not allowed in a condition + * - ``2951``\ + - | ``missing_attr_namespace``\ : + | an attribute namespace identifier is required before "::" + * - ``2952``\ + - | ``multiple_attr_namespaces``\ : + | only one attribute namespace is allowed + * - ``2953``\ + - | ``bad_return``\ : + | "return" not allowed here + * - ``2954``\ + - | ``struct_binding_with_multiple_declarators``\ : + | a structured binding cannot be combined with other declarators + * - ``2955``\ + - | ``branch_out_of_constant``\ : + | cannot branch out of a constant-evaluation context + * - ``2956``\ + - | ``struct_binding_template``\ : + | structured binding templates are not permitted + * - ``2957``\ + - | ``braced_init_in_parens``\ : + | a parenthesized initializer must be an expression, not a + brace-enclosed list + * - ``2958``\ + - | ``cannot_deduce_class_template_arguments``\ : + | cannot deduce class template arguments + * - ``2959``\ + - | ``consteval_new_or_delete_operator``\ : + | a new or delete operator cannot be declared "consteval" + * - ``2960``\ + - | ``address_of_consteval_function_leaked``\ : + | the address of a consteval function cannot be used here + * - ``2961``\ + - | ``alignof_function_type``\ : + | the alignment of a function type (*"type"*\ ) is nonstandard + * - ``2962``\ + - | ``alignof_incomplete_array``\ : + | the alignment of an array of unspecified bound is nonstandard in C + * - ``2963``\ + - | ``cannot_be_common_internal_linkage``\ : + | a variable cannot have both "common" and "internal_linkage" attributes + * - ``2964``\ + - | ``internal_linkage_not_on_prior_declaration``\ : + | the "internal_linkage" attribute did not appear on a prior declaration + * - ``2965``\ + - | ``no_class_template_guide``\ : + | no viable template argument deduction candidate found for + *entity-kind "entity"*\ + * - ``2966``\ + - | ``fully_qualified_constructor_call``\ : + | a fully qualified constructor call is not allowed + * - ``2967``\ + - | ``bad_scope_for_defaulted_comparison``\ : + | a defaulted comparison operator must be a member or a friend of the + class it applies to + * - ``2968``\ + - | ``bad_param_type_for_defaulted_comparison``\ : + | bad type *"type"*\ for parameter of defaulted comparison operator + (must be "reference to const X" where X is the enclosing class type) + * - ``2969``\ + - | ``return_type_of_default_comparison_must_be_bool``\ : + | return type of defaulted comparison operator must be "bool" + * - ``2970``\ + - | ``nonconst_defaulted_member_comparison``\ : + | a defaulted member comparison operator must be "const" + * - ``2972``\ + - | ``no_return_value_and_return_void``\ : + | a coroutine's promise type *"type"*\ cannot have both "return_void" + and "return_value" set + * - ``2973``\ + - | ``return_value_at``\ : + | "return_value" declared at line *xxxx*\ + * - ``2974``\ + - | ``return_void_at``\ : + | "return_void" declared at line *xxxx*\ + * - ``2975``\ + - | ``implicit_co_return_with_no_return_void``\ : + | missing co_return statement while *"type"*\ has no "return_void" at + end of *entity-kind "entity"*\ + * - ``2976``\ + - | ``no_nothrow_global_new_for_coroutine``\ : + | no nothrow variant of the global "operator new" found for coroutine + state allocation + * - ``2977``\ + - | ``no_viable_delete_for_coroutine``\ : + | no viable "operator delete" found for coroutine state deallocation + * - ``2978``\ + - | ``no_constexpr_coroutine``\ : + | a constexpr function cannot be a coroutine + * - ``2979``\ + - | ``await_operand_not_a_class``\ : + | the operand to this *xxxx*\ expression resolves to non-class + *"type"*\ + * - ``2980``\ + - | ``await_not_allowed_in_static_initializer``\ : + | a co_await expression is not allowed in a static initializer + * - ``2981``\ + - | ``final_suspend_cannot_throw``\ : + | the co_await expression calling *entity-kind "entity"*\ must be + non-throwing + * - ``2982``\ + - | ``excessive_comparison_rewrites``\ : + | too many recursive comparison rewrite operations + * - ``2983``\ + - | ``invalid_placeholder_for_defaulted_spaceship_return``\ : + | a deducible return type for a default operator<=> must be "auto" + * - ``2984``\ + - | ``constexpr_implied_source_nonconstant``\ : + | implicit copy of non-constant source + * - ``2985``\ + - | ``struct_binding_restricted_storage_class``\ : + | a structured binding cannot declare an explicit storage class other + than static or thread_local + * - ``2986``\ + - | ``defaulted_comparison_for_property``\ : + | defaulted comparison operators are not supported for nontrivial + Microsoft property fields + * - ``2987``\ + - | ``invalid_std_comparison_type``\ : + | standard comparison type (*"type"*\ ) must be a class type with a + single nonstatic data member of integral type + * - ``2988``\ + - | ``invalid_std_comparison_value``\ : + | no constexpr static data member *"xxxx"*\ found in *"type"*\ + * - ``2989``\ + - | ``constexpr_alloc_too_large``\ : + | number of elements (*n*\ ) too large for dynamic allocation + * - ``2990``\ + - | ``constexpr_allocation_too_large``\ : + | constexpr dynamic allocation request too large + * - ``2991``\ + - | ``constexpr_bad_deallocation``\ : + | deallocation of storage that was not dynamically allocated + * - ``2992``\ + - | ``constexpr_bad_deallocation_size``\ : + | deallocation size (*n*\ ) does not correspond to size allocated + (*n*\ ) + * - ``2993``\ + - | ``constexpr_allocation_pos``\ : + | allocation occurred here + * - ``2994``\ + - | ``constexpr_bad_deallocation_type``\ : + | deallocation type (*"type"*\ ) does not correspond to allocation type + (*"type"*\ ) + * - ``2995``\ + - | ``constexpr_leftover_allocations``\ : + | some dynamic allocations (total number = *n*\ ) were not deallocated + * - ``2996``\ + - | ``constexpr_invalid_intrinsic_signature``\ : + | intrinsic *entity-kind "entity"*\ declared with unexpected signature + (type *"type"*\ ) + * - ``2997``\ + - | ``constexpr_begin_report``\ : + | >> output from std::\__report_constexpr_value + * - ``2998``\ + - | ``constexpr_end_report``\ : + | >> end output from std::\__report_constexpr_value + * - ``2999``\ + - | ``constexpr_dependent_array_size``\ : + | cannot use array with dependent array size in constexpr evaluation + * - ``3000``\ + - | ``nodiscard_routine_with_reason``\ : + | ignoring return value from routine declared with "nodiscard" + attribute (*"xxxx"*\ ) + * - ``3001``\ + - | ``nodiscard_return_type_with_reason``\ : + | ignoring return value type with "nodiscard" attribute (*"xxxx"*\ ) + * - ``3002``\ + - | ``nodiscard_constructor``\ : + | constructor used to create discarded object has "nodiscard" attribute + * - ``3003``\ + - | ``nodiscard_constructor_with_reason``\ : + | constructor used to create discarded object has "nodiscard" attribute + (*"xxxx"*\ ) + * - ``3004``\ + - | ``nodiscard_object_type``\ : + | type of discarded object has "nodiscard" attribute + * - ``3005``\ + - | ``nodiscard_object_type_with_reason``\ : + | type of discarded object has "nodiscard" attribute (*"xxxx"*\ ) + * - ``3006``\ + - | ``vacuous_destructor_not_called``\ : + | a pseudo-destructor reference can only be used for a + pseudo-destructor call + * - ``3007``\ + - | ``constexpr_explicit_dtor_call``\ : + | an explicit destructor call is not permitted in a constant-expression + * - ``3008``\ + - | ``comma_operator_in_array_subscript_deprecated``\ : + | an unparenthesized comma operator in an array subscript expression is + deprecated + * - ``3009``\ + - | ``constexpr_alloc_too_small``\ : + | number of dynamically-allocated elements (*n*\ ) too small for + initializer + * - ``3011``\ + - | ``volatile_ass_deprecated``\ : + | use of the result of an assignment to a volatile scalar object is + deprecated + * - ``3012``\ + - | ``volatile_op_ass_deprecated``\ : + | a volatile destination type for a compound assignment expression is + deprecated + * - ``3013``\ + - | ``volatile_func_param_deprecated``\ : + | a volatile function parameter is deprecated + * - ``3014``\ + - | ``volatile_return_type_deprecated``\ : + | a volatile return type is deprecated + * - ``3015``\ + - | ``volatile_str_bind_deprecated``\ : + | use of a volatile qualifier on a structured binding is deprecated + * - ``3016``\ + - | ``ext_vector_type_invalid_size``\ : + | the "ext_vector_type" argument must be between 1 and 2047 + * - ``3017``\ + - | ``ext_vector_type_not_in_typedef``\ : + | the "ext_vector_type" attribute may appear only in a typedef + * - ``3018``\ + - | ``ext_vector_type_requires_integral_floating_type``\ : + | the "ext_vector_type" attribute applies only to integer or + floating-point types + * - ``3019``\ + - | ``feature_test_macro_ignored``\ : + | this feature-test macro is ignored (and returns 0) in the current + compilation mode + * - ``3020``\ + - | ``constexpr_multiple_union_initializers``\ : + | cannot evaluate an aggregate initializer with multiple elements for a + union + * - ``3021``\ + - | ``cmp_operator_does_not_return_bool``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) selected for + operator rewrite does not return type bool + * - ``3022``\ + - | ``constexpr_class_specific_new``\ : + | a new-expression calling a class-specific allocation function cannot + be constant-evaluated + * - ``3023``\ + - | ``constexpr_placement_new``\ : + | a placement new-expression cannot be constant-evaluated + * - ``3024``\ + - | ``constexpr_nonvirtual_subobject_delete``\ : + | deleting through a subobject pointer requires a virtual destructor + * - ``3026``\ + - | ``invalid_intaddr_address``\ : + | operand of \__INTADDR\__ must be offset from null pointer + * - ``3027``\ + - | ``ambiguous_c11_generic``\ : + | _Generic construct matches multiple types + * - ``3028``\ + - | ``ambiguous_c11_generic_previous_match``\ : + | the other match is *"type"*\ + * - ``3029``\ + - | ``availability_attribute_ignored``\ : + | the "availability" attribute used here is ignored + * - ``3030``\ + - | ``init_stmt_in_range_for_nonstandard``\ : + | C++20-style initializer statement in a range-based "for" statement is + nonstandard in this mode + * - ``3031``\ + - | ``co_await_on_non_range_based_for``\ : + | co_await can only apply to a range-based "for" statement + * - ``3032``\ + - | ``cannot_deduce_type_in_range_based_for``\ : + | cannot deduce type of range in range-based "for" statement + * - ``3033``\ + - | ``inline_variables_nonstandard``\ : + | inline variables are a C++17 feature + * - ``3034``\ + - | ``destroying_delete_wrong_type``\ : + | destroying operator delete requires *"type"*\ as first parameter + * - ``3035``\ + - | ``destroying_delete_with_extra_params``\ : + | a destroying operator delete cannot have parameters other than + std::size_t and std::align_val_t + * - ``3036``\ + - | ``cl_relaxed_abstract_checking_only_in_cplusplus``\ : + | relaxed abstract class options can be used only when compiling C++ + * - ``3037``\ + - | ``invalid_start_of_requires_clause_expr``\ : + | invalid start of expression in requires clause + * - ``3038``\ + - | ``cast_in_requires_clause``\ : + | a cast expression in a requires-clause must be parenthesized + * - ``3039``\ + - | ``invalid_operator_in_requires_clause``\ : + | this operator cannot appear at the top level (without parentheses) in + a requires-clause + * - ``3040``\ + - | ``nonbool_atomic_constraint``\ : + | atomic constraint must have type bool + * - ``3041``\ + - | ``atomic_constraint_substitution_failed``\ : + | atomic constraint failed substitution + * - ``3042``\ + - | ``atomic_constraint_evaluation_failed``\ : + | atomic constraint not constant + * - ``3043``\ + - | ``atomic_constraint_false``\ : + | atomic constraint evaluates to false + * - ``3044``\ + - | ``template_constraint_not_satisfied``\ : + | template constraint not satisfied + * - ``3045``\ + - | ``bad_scope_for_concept``\ : + | concept definition cannot appear in this scope + * - ``3046``\ + - | ``invalid_concept_redecl``\ : + | invalid redeclaration of *entity-kind "entity"*\ (declared at line + *xxxx*\ ) + * - ``3047``\ + - | ``concept_arg_list_substitution_failed``\ : + | substitution of arguments *""*\ for concept-id failed + * - ``3048``\ + - | ``concept_failed``\ : + | concept is false for arguments *""*\ + * - ``3049``\ + - | ``trailing_requires_clause_not_on_template``\ : + | a requires-clause is not allowed here (not a templated function) + * - ``3051``\ + - | ``requires_incompatible_with_previous_decl``\ : + | requires-clause incompatible with *entity-kind "entity"*\ (declared + at line *xxxx*\ ) + * - ``3052``\ + - | ``expected_an_attribute``\ : + | expected an attribute + * - ``3054``\ + - | ``exp_type_name``\ : + | expected a type name + * - ``3055``\ + - | ``requires_expr_ellipsis_param``\ : + | an ellipsis parameter is not permitted in a requires-expression + * - ``3056``\ + - | ``unnamed_require_expr_param``\ : + | unnamed parameter in requires-expression has no effect + * - ``3057``\ + - | ``exp_concept_name``\ : + | expected a concept name + * - ``3058``\ + - | ``is_constant_evaluated_in_constant_expression``\ : + | call to *xxxx*\ appearing in a constant expression always produces + "true" + * - ``3059``\ + - | ``is_constant_evaluated_in_consteval_context``\ : + | call to *xxxx*\ appearing in a consteval context always produces + "true" + * - ``3060``\ + - | ``is_constant_evaluated_in_nonconstexpr_context``\ : + | call to *xxxx*\ appearing in a non-constexpr function always + produces "false" + * - ``3061``\ + - | ``type_constraint_failed``\ : + | type constraint failed for *"type"*\ + * - ``3062``\ + - | ``cl_export_template_option_incompatible_with_modules``\ : + | option "export" cannot be used in modes where C++ modules are enabled + * - ``3063``\ + - | ``glb_mod_fgmt_decl_must_come_first``\ : + | a global module fragment declaration must precede any other + declaration + * - ``3064``\ + - | ``module_decl_only_after_glb_mod``\ : + | a module declaration can only be preceded by a global module fragment + * - ``3065``\ + - | ``pvt_mod_fgmt_only_after_module``\ : + | a private module fragment must be preceded by a module declaration + * - ``3066``\ + - | ``cannot_export_fgmt``\ : + | a *xxxx*\ module fragment cannot be exported + * - ``3067``\ + - | ``more_than_one_module_decl``\ : + | cannot declare more than one module + * - ``3068``\ + - | ``more_than_one_fgmt_decl``\ : + | cannot declare more than one *xxxx*\ module fragment + * - ``3069``\ + - | ``module_req_primary_name``\ : + | a module must be declared with a non-empty name + * - ``3070``\ + - | ``header_not_importable``\ : + | *"xxxx"*\ is not an importable header + * - ``3071``\ + - | ``cannot_import_module_with_no_name``\ : + | cannot import a module with no name + * - ``3072``\ + - | ``module_cannot_depend_on_itself``\ : + | a module cannot have an interface dependency on itself + * - ``3073``\ + - | ``module_already_imported``\ : + | *module "module name"*\ has already been imported + * - ``3075``\ + - | ``module_file_not_found``\ : + | could not find module file for module *"xxxx"*\ + * - ``3076``\ + - | ``cannot_import_module``\ : + | could not import module file *"xxxx"*\ + * - ``3079``\ + - | ``unknown_ifc_partition``\ : + | unknown partition name *"xxxx"*\ + * - ``3085``\ + - | ``types_must_have_same_size``\ : + | the type of the second operand *"type"*\ must have the same size as + *"type"*\ + * - ``3086``\ + - | ``type_must_be_trivially_copyable``\ : + | type must be trivially copyable + * - ``3087``\ + - | ``unsupported_type_for_bit_cast``\ : + | type *"type"*\ is currently not supported for constexpr evaluation + of \__builtin_bit_cast + * - ``3088``\ + - | ``bitfields_not_allowed``\ : + | class types with bitfields *"type"*\ are not currently supported for + constexpr evaluation of \__builtin_bit_cast + * - ``3089``\ + - | ``reference_type_not_allowed``\ : + | non-static data member of reference type *"type"*\ prevents + constexpr evaluation of \__builtin_bit_cast + * - ``3090``\ + - | ``volatile_type_not_allowed``\ : + | a volatile type *"type"*\ prevents constexpr evaluation of + \__builtin_bit_cast + * - ``3091``\ + - | ``invalid_bit_cast_type``\ : + | a union, pointer, or pointer-to-member type *"type"*\ prevents + constexpr evaluation of \__builtin_bit_cast + * - ``3093``\ + - | ``deleted_inh_def_constructor``\ : + | the sub-object construction of *"type"*\ for inheriting constructors + cannot be performed -- the associated constructor is deleted + * - ``3094``\ + - | ``promise_type_returns_return_void``\ : + | *entity-kind "entity"*\ must return void + * - ``3095``\ + - | ``invalid_start_of_member_declaration``\ : + | invalid start of member declaration + * - ``3096``\ + - | ``exp_auto``\ : + | expected "auto" + * - ``3097``\ + - | ``operator_not_allowed_after_new``\ : + | this operator is not allowed at this point; parenthesize the + preceding new-expression + * - ``3098``\ + - | ``invalid_use_of_concept``\ : + | invalid use of concept + * - ``3099``\ + - | ``rvalue_defaulted_member_comparison``\ : + | a defaulted member comparison operator cannot be "&&"-qualified + * - ``3100``\ + - | ``constexpr_comparison_calls_nonconstexpr_function``\ : + | default constexpr comparison function calls non-constexpr function + *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``3101``\ + - | ``invalid_constexpr_memcmp``\ : + | constexpr memory comparison is only supported for integer or + array-of-integer objects + * - ``3102``\ + - | ``constraint_concept_template``\ : + | a concept template cannot have associated constraints + * - ``3103``\ + - | ``export_not_allowed``\ : + | "export" is not allowed + * - ``3104``\ + - | ``export_class_members``\ : + | exporting individual class members is not allowed + * - ``3105``\ + - | ``export_must_introduce_name``\ : + | an exported declaration must introduce a name + * - ``3106``\ + - | ``export_cannot_contain_export``\ : + | an export declaration cannot contain an export declaration (previous + declaration at line *xxxx*\ ) + * - ``3107``\ + - | ``export_cannot_contain_import``\ : + | an export declaration cannot contain a module import declaration + * - ``3108``\ + - | ``export_only_in_modules``\ : + | an export declaration can only appear in a module interface unit + * - ``3109``\ + - | ``export_internal_linkage``\ : + | an export declaration cannot export a name with internal linkage + * - ``3112``\ + - | ``empty_requires_expression``\ : + | a requires-expression must specify at least one requirement + * - ``3113``\ + - | ``invalid_constinit``\ : + | "constinit" is not valid here + * - ``3114``\ + - | ``constinit_variable_storage``\ : + | "constinit" is only valid for declarations of variables with static + or thread storage duration + * - ``3115``\ + - | ``constinit_variable_has_dynamic_init``\ : + | constinit variable requires dynamic initialization + * - ``3116``\ + - | ``missing_constinit``\ : + | variable was previously declared with "constinit" at line *xxxx*\ + * - ``3117``\ + - | ``use_of_non_prototype_func_declarator``\ : + | use of non-prototype function declarator + * - ``3118``\ + - | ``cannot_be_const_qualified``\ : + | argument cannot have a const-qualified type + * - ``3119``\ + - | ``ptr_to_mem_of_incomplete_class``\ : + | a pointer-to-member of an incomplete type *"type"*\ is not allowed + * - ``3120``\ + - | ``pack_init_capture_not_enabled``\ : + | pack expansion in init-capture not enabled in this mode + * - ``3121``\ + - | ``pack_init_capture_is_cpp20``\ : + | pack expansion in init-capture is a C++20 feature + * - ``3122``\ + - | ``comparison_defaulted_in_class_must_be_first_decl``\ : + | a comparison operator defaulted in a class definition must be the + first declaration of that comparison operator (*entity-kind + "entity"*\ (declared at line *xxxx*\ )) + * - ``3123``\ + - | ``pack_init_capture_in_non_variadic_context``\ : + | a pack expansion in an init-capture can be used only in a variadic + template + * - ``3124``\ + - | ``type_constraint_requires_type_concept``\ : + | type constraint uses *entity-kind "entity"*\ (declared at line + *xxxx*\ ) that is not a type concept (i.e., a concept template whose + first parameter is a type parameter) + * - ``3125``\ + - | ``placeholder_type_failed_constraint``\ : + | the deduced placeholder type *"type"*\ failed the type constraint + * - ``3126``\ + - | ``ineligible_default_constructor``\ : + | default constructor for *"type"*\ is not eligible + * - ``3127``\ + - | ``ambiguous_destructor_constraints``\ : + | destructor for *"type"*\ is ambiguous because of unordered + constraints + * - ``3128``\ + - | ``failed_destructor_constraints``\ : + | destructor for *"type"*\ is ineligible because of failed constraints + * - ``3129``\ + - | ``destructor_position``\ : + | ambiguous destructor candidate + * - ``3130``\ + - | ``trailing_requires_on_virtual_func``\ : + | a virtual function cannot have a trailing requires clause + * - ``3131``\ + - | ``function_ineligible``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) does not satisfy + its constraints + * - ``3132``\ + - | ``bad_decltype_qualifier``\ : + | result of decltype qualifier *"type"*\ is not a class or enumeration + * - ``3133``\ + - | ``cpp20_reversed_comparison_ambiguity``\ : + | comparison is ambiguous in standard C++20 because the implied + comparison operator with reversed parameters is an equally good match + -- this is usually caused by a missing "const" qualifier on the + comparison operator; see *"entity"*\ (declared at line *xxxx*\ ) + * - ``3134``\ + - | ``invalid_concept_id``\ : + | invalid concept-id + * - ``3135``\ + - | ``requires_clause_arg_list_substitution_failed``\ : + | substitution of arguments *""*\ for requires-clause + failed + * - ``3136``\ + - | ``ineligible_member_function``\ : + | constraints for *entity-kind "entity"*\ (declared at line *xxxx*\ ) + are not satisfied + * - ``3137``\ + - | ``var_with_virtual_bases_in_constexpr_function``\ : + | variable type *"type"*\ in constexpr function has virtual base + classes + * - ``3138``\ + - | ``constexpr_object_with_virtual_base``\ : + | a constant expression cannot allocate a virtual base subobject (for + type *"type"*\ ) + * - ``3139``\ + - | ``template_parameter_has_nonstructural_class_type``\ : + | a template parameter of class type must be of structural class type + * - ``3140``\ + - | ``utf8_lit_no_ulit``\ : + | support for UTF-8 literals requires u-literal support. + * - ``3141``\ + - | ``duplicate_module_map``\ : + | module file mapping for "*xxxx*\ " specified more than once + * - ``3142``\ + - | ``duplicate_header_unit_map``\ : + | header unit mapping for "*xxxx*\ " specified more than once + * - ``3143``\ + - | ``missing_header_unit_map``\ : + | no mapping specified for "*xxxx*\ " + * - ``3145``\ + - | ``cannot_find_header_for_import``\ : + | cannot find header "*xxxx*\ " to import + * - ``3146``\ + - | ``multiple_module_matches``\ : + | more than one file in the module file list matches "*xxxx*\ " + * - ``3147``\ + - | ``module_file_mismatch``\ : + | module file found for "*xxxx*\ " is for a different module + * - ``3149``\ + - | ``module_read_error``\ : + | unable to read module file + * - ``3150``\ + - | ``builtin_needs_char8_t``\ : + | builtin function is not available because the char8_t type is not + supported with the current options + * - ``3152``\ + - | ``nonstandard_use_of_explicit_default_constructor``\ : + | nonstandard use of explicit constructor *"entity"*\ (declared at + line *xxxx*\ ) for default aggregate element initialization + * - ``3153``\ + - | ``constexpr_memcpy_operand_not_object``\ : + | source or destination of memcpy-like intrinsic does not point to an + object + * - ``3154``\ + - | ``constexpr_memcpy_distinct_types``\ : + | memcpy-like intrinsic attempts to copy representationally-distinct + types *"type"*\ and *"type"*\ + * - ``3155``\ + - | ``constexpr_memcpy_nontrivial_type``\ : + | memcpy-like intrinsic attempts to copy nontrivially-copyable type + *"type"*\ + * - ``3156``\ + - | ``constexpr_memcpy_partial_object``\ : + | memcpy-like intrinsic attempts to copy partial object + * - ``3157``\ + - | ``constexpr_memcpy_overflow``\ : + | memcpy-like intrinsic attempts to copy past array boundary + * - ``3158``\ + - | ``constexpr_memcpy_overlap``\ : + | memcpy-like intrinsic attempts to copy overlapping byte ranges (using + corresponding memmove operation instead) + * - ``3159``\ + - | ``nondefining_friend_requires_clause``\ : + | a friend declaration with a trailing-requires-clause must be a + definition + * - ``3160``\ + - | ``type_not_scalar``\ : + | expression must have arithmetic or pointer type but has type + *"type"*\ + * - ``3161``\ + - | ``type_not_arithmetic_or_enum_or_pointer``\ : + | expression must have arithmetic, enum, or pointer type but has type + *"type"*\ + * - ``3162``\ + - | ``type_not_arithmetic_or_unscoped_enum_or_pointer``\ : + | expression must have arithmetic, unscoped enum, or pointer type but + has type *"type"*\ + * - ``3163``\ + - | ``type_not_pointer``\ : + | expression must have pointer type but it has type *"type"*\ + * - ``3164``\ + - | ``member_access_requires_pointer``\ : + | operator -> or ->\* applied to *"type"*\ instead of to a pointer type + * - ``3166``\ + - | ``cannot_interpret_target_bits``\ : + | cannot interpret bit layout for this compilation target + * - ``3167``\ + - | ``ifc_no_corresponding_operator``\ : + | no corresponding operator for IFC operator *"xxxx"*\ + * - ``3168``\ + - | ``ifc_no_corresponding_calling_conv``\ : + | no corresponding calling convention for IFC calling convention + *"xxxx"*\ + * - ``3169``\ + - | ``module_file_contains_unsupported_constructs``\ : + | *module "module name"*\ contains unsupported constructs + * - ``3170``\ + - | ``unhandled_ifc_construct``\ : + | unsupported IFC construct: *"xxxx"*\ + * - ``3171``\ + - | ``is_signed_no_longer_a_keyword``\ : + | __is_signed is no longer a keyword from this point + * - ``3172``\ + - | ``dim_not_const_unsigned_int``\ : + | an array dimension must have a constant unsigned integer value + * - ``3174``\ + - | ``modules_not_enabled``\ : + | modules are not enabled in this mode + * - ``3175``\ + - | ``import_name_not_allowed``\ : + | "import" is not allowed in a module name + * - ``3176``\ + - | ``module_name_not_allowed``\ : + | "module" is not allowed in a module name + * - ``3179``\ + - | ``not_an_enum_type``\ : + | *entity-kind "entity"*\ is not an enum type + * - ``3180``\ + - | ``using_enum_conflicts``\ : + | enumerator *"entity"*\ conflicts with *entity-kind "entity"*\ + * - ``3181``\ + - | ``using_enum_redecl``\ : + | enumerator *"entity"*\ has already been declared in this scope at + line *xxxx*\ + * - ``3182``\ + - | ``empty_throw_specification_not_cpp20``\ : + | the "throw()" specification is not part of C++20 and later + * - ``3183``\ + - | ``multiple_header_map_matches``\ : + | more than entry in the header unit map matches "*xxxx*\ " + * - ``3184``\ + - | ``exp_push_pop``\ : + | #pragma diagnostic must have either 'push' or 'pop' argument + * - ``3185``\ + - | ``no_corresponding_push``\ : + | no '#pragma diagnostic push' was found to match this 'diagnostic pop' + * - ``3186``\ + - | ``macro_in_pp_directive``\ : + | *"xxxx"*\ cannot be a macro when used in an import or module + directive + * - ``3187``\ + - | ``not_global_namespace``\ : + | this directive can only appear in the global namespace scope + * - ``3188``\ + - | ``export_not_at_namespace_scope``\ : + | an "export" declaration can appear only at global or namespace scope + * - ``3189``\ + - | ``identifier_not_keyword``\ : + | *"xxxx"*\ is parsed as an identifier rather than a keyword because + the tokens that follow it do not match those of a preprocessor + directive + * - ``3190``\ + - | ``apparent_module_pp_directive``\ : + | this appears to be the start of a preprocessor directive, but the + lack of a ';' followed immediately by a newline prevents that + * - ``3191``\ + - | ``module_directive_in_macro``\ : + | this appears to be a modules preprocessing directive, but such + directives cannot appear within a macro expansion + * - ``3192``\ + - | ``module_directive_in_if``\ : + | a "module" directive cannot appear within the scope of conditional + inclusion (e.g., #if, #else, #elseif, etc.) + * - ``3193``\ + - | ``import_skipped``\ : + | the import of *"xxxx"*\ has been skipped + * - ``3194``\ + - | ``bad_gro_on_alloc_fail``\ : + | promise type *"type"*\ must declare + get_return_object_on_allocation_failure as a static member function + requiring no arguments + * - ``3195``\ + - | ``expl_spec_alias_template``\ : + | an alias template cannot be explicitly specialized + * - ``3196``\ + - | ``matching_lbrace``\ : + | to match this "{" + * - ``3197``\ + - | ``macro_invocation``\ : + | in this macro invocation + * - ``3198``\ + - | ``call_with_unusable_argument_conversion``\ : + | call requires an ambiguous argument conversion + * - ``3199``\ + - | ``named_module_source_conflict``\ : + | declaration owned by module *xxxx*\ conflicts with *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``3200``\ + - | ``global_module_source_conflict``\ : + | declaration owned by global module conflicts with *entity-kind + "entity"*\ (declared at line *xxxx*\ ) owned by a named module + * - ``3201``\ + - | ``bad_malloc_attribute``\ : + | the first argument to a "malloc" attribute must be a function + * - ``3202``\ + - | ``cannot_capture_var``\ : + | cannot capture *"entity"*\ (declared at line *xxxx*\ ) + * - ``3203``\ + - | ``cannot_capture_this``\ : + | cannot capture "this" + * - ``3204``\ + - | ``already_in_consteval_context``\ : + | already in consteval context + * - ``3205``\ + - | ``if_consteval_requires_braced_dependent_statement``\ : + | "if consteval" and "if not consteval" require braced dependent + statements + * - ``3206``\ + - | ``if_consteval_in_nonconstexpr_function``\ : + | "if consteval" and "if not consteval" are meaningless in a + non-constexpr function + * - ``3207``\ + - | ``branch_into_if_consteval``\ : + | transfer of control into an "if consteval" or "if not consteval" + statement is not allowed + * - ``3208``\ + - | ``constexpr_local_static``\ : + | constant-evaluation cannot go through the declaration of a variable + with static or thread storage duration + * - ``3209``\ + - | ``mutable_qualifier_on_explicit_this_lambda``\ : + | the mutable qualifier is not allowed on a lambda with an explicit + "this" parameter + * - ``3210``\ + - | ``static_with_explicit_this``\ : + | a member function declared with "static" cannot have an explicit + "this" parameter + * - ``3211``\ + - | ``explicit_this_param_must_be_first``\ : + | an explicit "this" parameter must be the first declared parameter + * - ``3212``\ + - | ``bad_this``\ : + | "this" is not allowed here + * - ``3214``\ + - | ``explicit_this_needs_this``\ : + | an explicit "this" function requires a selector operand + * - ``3215``\ + - | ``if_consteval_nonstandard``\ : + | "if consteval" and "if not consteval" are not standard in this mode + * - ``3216``\ + - | ``lambda_without_parameters_nonstandard``\ : + | omitting "()" in a lambda declarator is nonstandard in this mode + * - ``3217``\ + - | ``lambda_without_parameters_requires_clause``\ : + | a trailing-requires-clause is not permitted when the lambda parameter + list is omitted + * - ``3218``\ + - | ``invalid_ifc_partition``\ : + | *module "module name"*\ invalid partition requested + * - ``3219``\ + - | ``undefined_ifc_partition``\ : + | *module "module name"*\ undefined partition (believed to be + *"xxxx"*\ ) requested + * - ``3222``\ + - | ``invalid_overflowing_ifc_position``\ : + | *module "module name"*\ file position *n*\ (relative position + *n*\ ) requested for partition *"xxxx"*\ - which overflows the end + of its partition + * - ``3223``\ + - | ``invalid_misaligned_ifc_position``\ : + | *module "module name"*\ file position *n*\ (relative position + *n*\ ) requested for partition *"xxxx"*\ - which is misaligned with + its partitions elements + * - ``3224``\ + - | ``invalid_ifc_position_backtrace_field``\ : + | from subfield *"xxxx"*\ (relative position to node *n*\ ) + * - ``3225``\ + - | ``invalid_ifc_position_backtrace_pos``\ : + | from partition *"xxxx"*\ element *n*\ (file position *n*\ , + relative position *n*\ ) + * - ``3226``\ + - | ``nonstandard_lambda_attributes``\ : + | attributes on lambdas are a C++23 feature + * - ``3227``\ + - | ``confusable_identifier``\ : + | identifier *"xxxx"*\ could be confused with a visually-similar one + appearing at line *xxxx*\ + * - ``3228``\ + - | ``suspicious_comment_formatting``\ : + | this comment contains suspicious Unicode formatting control characters + * - ``3229``\ + - | ``suspicious_string_formatting``\ : + | this string contains Unicode formatting control characters that could + result in unexpected runtime behavior + * - ``3230``\ + - | ``suppressed_module_warning_diag``\ : + | *n*\ suppressed warning was encountered while processing *module + "module name"*\ + * - ``3231``\ + - | ``suppressed_module_warnings_diag``\ : + | *n*\ suppressed warnings were encountered while processing *module + "module name"*\ + * - ``3232``\ + - | ``suppressed_module_error_diag``\ : + | *n*\ suppressed error was encountered while processing *module + "module name"*\ + * - ``3233``\ + - | ``suppressed_module_errors_diag``\ : + | *n*\ suppressed errors were encountered while processing *module + "module name"*\ + * - ``3236``\ + - | ``virtual_with_explicit_this``\ : + | a virtual member function cannot have an explicit "this" parameter + * - ``3237``\ + - | ``address_of_unqualified_explicit_this_function``\ : + | taking the address of an explicit "this" function requires a + qualified name + * - ``3238``\ + - | ``implicit_address_of_explicit_this_function``\ : + | forming the address of an explicit "this" function requires the "&" + operator + * - ``3239``\ + - | ``string_literal_cannot_initialize_flexible_array_member``\ : + | a string literal cannot be used to initialize a flexible array member + * - ``3246``\ + - | ``ifc_missing_function_definition``\ : + | the IFC representation of the definition of function *"xxxx"*\ is + missing + * - ``3247``\ + - | ``member_function_modifier_on_template``\ : + | function modifier does not apply to member template declaration + * - ``3248``\ + - | ``constexpr_too_many_nested_anonymous_types``\ : + | member selection involves too many nested anonymous types + * - ``3249``\ + - | ``no_common_type``\ : + | there is no common type between the operands + * - ``3250``\ + - | ``exp_pointer_to_member``\ : + | expected a pointer-to-member + * - ``3251``\ + - | ``lone_flexible_array_member``\ : + | a flexible array member cannot be declared in an otherwise-empty type + * - ``3252``\ + - | ``missing_gnu_srcloc_type``\ : + | expected "std::source_location::\__impl" to be defined to a class + with only the data members "_M_function_name", "_M_file_name", + "_M_column", "_M_line" + * - ``3253``\ + - | ``srcloc_column_bounds``\ : + | given column number is too large for "std::source_location" + implementation + * - ``3254``\ + - | ``srcloc_line_bounds``\ : + | given line number is too large for "std::source_location" + implementation + * - ``3255``\ + - | ``utf16_char_lit_too_long``\ : + | a UTF-16 character constant cannot occupy more than one code unit; + value truncated + * - ``3256``\ + - | ``both_arguments_must_have_same_type``\ : + | both arguments must have the same type + * - ``3257``\ + - | ``invalid_type_for_builtin``\ : + | type *"type"*\ is invalid as an argument for this builtin + * - ``3258``\ + - | ``constexpr_called_from_rout``\ : + | called from *entity-kind "entity"*\ (declared at line *xxxx*\ ): + * - ``3259``\ + - | ``qualified_unnamed_bit_field_type``\ : + | a qualified type is nonstandard for anonymous bit fields + * - ``3260``\ + - | ``bad_vector_conditional_size``\ : + | the element type of the vector condition (*"type"*\ ) must have the + same size as the element type of the result (*"type"*\ ) + * - ``3261``\ + - | ``bad_vector_float_operand_size``\ : + | the floating-point vector operand type (*"type"*\ ) has no matching + integer vector type + * - ``3262``\ + - | ``mangling_for_requires``\ : + | mangling for "requires" expressions is not yet implemented + * - ``3263``\ + - | ``unavailable_attr``\ : + | because of an "unavailable" attribute + * - ``3264``\ + - | ``duplicate_asm_qualifier``\ : + | duplicate 'asm' qualifier + * - ``3265``\ + - | ``incomplete_enum_bit_field_or_bad_opaque_enum``\ : + | either a bit field with an incomplete enum type or an opaque + enumeration with an invalid base type + * - ``3266``\ + - | ``ifc_partition_mismatch``\ : + | attempted to construct an element from IFC partition *"xxxx"*\ using + an index into IFC partition *"xxxx"*\ + * - ``3267``\ + - | ``ifc_partition_bad_entry_size``\ : + | the partition *"xxxx"*\ specified its entry size as *n*\ when *n*\ + was expected + * - ``3268``\ + - | ``ifc_requirement_failure``\ : + | an unexpected IFC requirement was encountered while processing + *module "module name"*\ + * - ``3269``\ + - | ``ifc_requirement_failure_fill_in``\ : + | condition failed at line *n*\ in *xxxx*\ : *"xxxx"*\ + * - ``3270``\ + - | ``circular_constraint``\ : + | atomic constraint depends on itself + * - ``3271``\ + - | ``noreturn_with_return_type``\ : + | "noreturn" function has non-void return type + * - ``3272``\ + - | ``ifc_bad_function_param_name``\ : + | a correction has been made by dropping the parameter *"xxxx"*\ (at + relative index *n*\ ) + * - ``3273``\ + - | ``default_arg_on_member_template_def``\ : + | a default template argument cannot be specified on the definition of + a member template outside its class + * - ``3274``\ + - | ``ifc_bad_identifier``\ : + | invalid IFC identifier name *"xxxx"*\ encountered during entity + reconstruction + * - ``3276``\ + - | ``invalid_ifc_sort_value``\ : + | *module "module name"*\ invalid sort value + * - ``3277``\ + - | ``ifc_function_template_parse_failure``\ : + | a function template loaded from an IFC module was incorrectly parsed + as *entity-kind "entity"*\ (declared at line *xxxx*\ ) + * - ``3278``\ + - | ``ifc_entity_ref_failure``\ : + | failed to load an IFC entity reference in *module "module name"*\ + * - ``3279``\ + - | ``ifc_entity_ref_failure_info``\ : + | from partition *"xxxx"*\ element *n*\ (file position *n*\ , + relative position *n*\ ) + * - ``3280``\ + - | ``no_chained_designators_with_destructor``\ : + | chained designators are not permitted for a class type with a + nontrivial destructor + * - ``3281``\ + - | ``explicit_specialization_friend``\ : + | an explicit specialization declaration may not be a friend declaration + * - ``3282``\ + - | ``std_float128_not_supported``\ : + | the std::float128_t type is not supported; std::float64_t will be + used instead + * - ``3284``\ + - | ``alias_template_deduction_guide``\ : + | a deduction guide may not be declared for alias template *"entity"*\ + * - ``3285``\ + - | ``unavailable_entity``\ : + | *entity-kind "entity"*\ was declared declared unavailable + * - ``3286``\ + - | ``unavailable_entity_with_custom_message``\ : + | *entity-kind "entity"*\ was declared unavailable (*"xxxx"*\ ) + * - ``3287``\ + - | ``deprecated_attr``\ : + | because of a "deprecated" attribute + * - ``3288``\ + - | ``explicit_lambda_template_parameters_is_cpp20``\ : + | explicit lambda template parameters are a C++20 feature + * - ``3289``\ + - | ``c23_noreturn_deprecated``\ : + | the use of "_Noreturn" has been obsoleted in C23; use "[[noreturn]]" + instead + * - ``3290``\ + - | ``c23_alignof_deprecated``\ : + | the use of "_Alignof" has been obsoleted in C23; use "alignof" instead + * - ``3291``\ + - | ``c23_alignas_deprecated``\ : + | the use of "_Alignas" has been obsoleted in C23; use "alignas" instead + * - ``3292``\ + - | ``c23_bool_deprecated``\ : + | the use of "_Bool" has been obsoleted in C23; use "bool" instead + * - ``3293``\ + - | ``c23_static_assert_deprecated``\ : + | the use of "_Static_assert" has been obsoleted in C23; use + "static_assert" instead + * - ``3294``\ + - | ``c23_thread_local_deprecated``\ : + | the use of "_Thread_local" has been obsoleted in C23; use + "thread_local" instead + * - ``3295``\ + - | ``ms_ifc_unavailable``\ : + | Microsoft mode must be enabled to use the module file *"xxxx"*\ (a + Microsoft Visual Studio IFC module) + * - ``3296``\ + - | ``file_for_module_not_found``\ : + | could not open module file *"xxxx"*\ + * - ``3297``\ + - | ``found_from_module_map``\ : + | found in the module map for module *"xxxx"*\ + * - ``3298``\ + - | ``found_from_header_unit_map``\ : + | found in the header unit map for *"xxxx"*\ + * - ``3299``\ + - | ``cl_invalid_output_mode``\ : + | unrecognized output mode (must be one of text, sarif): *xxxx*\ + * - ``3300``\ + - | ``cl_c23_typeof_option_only_in_C``\ : + | option "c23_typeof" can be used only when compiling C + * - ``3301``\ + - | ``cl_invalid_clang_version``\ : + | invalid clang version number: *xxxx*\ + * - ``3305``\ + - | ``constexpr_flexible_array_initializer``\ : + | cannot evaluate an initializer for a flexible array member + * - ``3306``\ + - | ``nonstandard_bit_field_initializer``\ : + | a default bit-field initializer is a C++20 feature + * - ``3307``\ + - | ``ifc_too_many_template_args``\ : + | too many arguments in template argument list in *module "module + name"*\ + * - ``3308``\ + - | ``ifc_too_many_template_args_info``\ : + | detected for the template argument represented by *"xxxx"*\ element + *n*\ (file position *n*\ , relative position *n*\ ) + * - ``3309``\ + - | ``ifc_too_few_template_args``\ : + | too few arguments in template argument list in *module "module + name"*\ + * - ``3310``\ + - | ``ifc_too_few_template_args_info``\ : + | detected while processing the template argument list represented by + *"xxxx"*\ element *n*\ (file position *n*\ , relative position + *n*\ ) + * - ``3311``\ + - | ``nonstandard_conversion_from_scoped_enum``\ : + | conversion from scoped enumeration type *"type"*\ is nonstandard + * - ``3312``\ + - | ``constexpr_allocation_mismatch``\ : + | deallocation does not match allocation kind (one is for an array and + the other not) + * - ``3313``\ + - | ``constexpr_address_unknown``\ : + | comparison involves unknown address (e.g., the address of a weak + variable) + * - ``3314``\ + - | ``bad_argument_to_make_signed``\ : + | __make_signed is only compatible with non-bool integer and enum types + * - ``3315``\ + - | ``bad_argument_to_make_unsigned``\ : + | __make_unsigned is only compatible with non-bool integer and enum + types + * - ``3316``\ + - | ``intrinsic_name_released``\ : + | the intrinsic name *"xxxx"*\ will be treated as an ordinary + identifier from here + * - ``3317``\ + - | ``array_subobject_not_initialized``\ : + | access to uninitialized subobject at index *n*\ + * - ``3318``\ + - | ``ifc_line_number_overflow``\ : + | IFC line number (*n*\ ) overflows maximum allowed value (*n*\ ) + *module "module name"*\ + * - ``3319``\ + - | ``invalid_unrepresentable_ifc_position``\ : + | *module "module name"*\ requested element *n*\ of partition + *"xxxx"*\ , this file position exceeds the maximum representable value + * - ``3320``\ + - | ``wrong_number_of_arguments``\ : + | wrong number of arguments + * - ``3321``\ + - | ``candidate_failed_constraint``\ : + | constraint on candidate *entity-kind "entity"*\ not satisfied + * - ``3322``\ + - | ``candidate_wrong_param_count``\ : + | number of parameters of *entity-kind "entity"*\ does not match the + call + * - ``3323``\ + - | ``candidate_expl_templ_arg_subst_failed``\ : + | substituting explicit template arguments *""*\ for + *entity-kind "entity"*\ failed + * - ``3324``\ + - | ``impl_deleted_move_candidate_ignored``\ : + | *entity-kind "entity"*\ is an implicitly "= delete" move function + and thus ignored during overload resolution + * - ``3325``\ + - | ``arg_for_empty_param_pack``\ : + | *entity-kind "entity"*\ does not match because argument #*n*\ is + provided for an empty parameter pack + * - ``3326``\ + - | ``nonviable_because_arg_mismatch``\ : + | *entity-kind "entity"*\ does not match because argument #*n*\ does + not match parameter + * - ``3327``\ + - | ``deduction_failed``\ : + | candidate *entity-kind "entity"*\ failed deduction + * - ``3328``\ + - | ``builtin_operator_nonviable_because_arg_mismatch``\ : + | built-in operator*xxxx*\ does not match because argument #*n*\ does + not match parameter + * - ``3329``\ + - | ``integral_operand``\ : + | + * - ``3330``\ + - | ``promoted_integral_operand``\ : + | + * - ``3331``\ + - | ``ptrdiff_t_operand``\ : + | + * - ``3332``\ + - | ``enum_operand``\ : + | + * - ``3333``\ + - | ``scoped_enum_operand``\ : + | + * - ``3334``\ + - | ``arith_operand``\ : + | + * - ``3335``\ + - | ``promoted_arith_operand``\ : + | + * - ``3336``\ + - | ``nonbool_arith_operand``\ : + | + * - ``3337``\ + - | ``pointer_operand``\ : + | + * - ``3338``\ + - | ``nullptr_operand``\ : + | + * - ``3339``\ + - | ``handle_operand``\ : + | + * - ``3340``\ + - | ``handle_to_cli_array_operand``\ : + | + * - ``3341``\ + - | ``pointer_to_object_operand``\ : + | + * - ``3342``\ + - | ``pointer_to_function_operand``\ : + | + * - ``3343``\ + - | ``ptr_to_member_operand``\ : + | + * - ``3344``\ + - | ``bool_operand``\ : + | + * - ``3345``\ + - | ``bool_equivalent_operand``\ : + | + * - ``3346``\ + - | ``class_operand``\ : + | + * - ``3347``\ + - | ``auto_cast_is_cpp23``\ : + | auto() and auto{} are a C++23 feature + * - ``3348``\ + - | ``anon_union_using_declaration``\ : + | invalid anonymous union -- using declaration is not allowed + * - ``3349``\ + - | ``ifc_file_incompatibility``\ : + | IFC file *"xxxx"*\ cannot be processed + * - ``3350``\ + - | ``unsupported_ifc_file_version_info``\ : + | IFC version *n*\ .*n*\ is not supported + * - ``3351``\ + - | ``unsupported_ifc_file_arch_info``\ : + | IFC architecture *"xxxx"*\ is incompatible with the current target + architecture + * - ``3352``\ + - | ``unknown_ifc_partition_conversion``\ : + | *module "module name"*\ requests index *n*\ of an unsupported + partition corresponding to *"xxxx"*\ + * - ``3353``\ + - | ``param_cannot_be_completed``\ : + | parameter number *n*\ of *entity-kind "entity"*\ has type + *"type"*\ which cannot be completed + * - ``3354``\ + - | ``param_is_incomplete``\ : + | parameter number *n*\ of *entity-kind "entity"*\ has incomplete + type *"type"*\ + * - ``3355``\ + - | ``param_is_abstract``\ : + | parameter number *n*\ of *entity-kind "entity"*\ has abstract type + *"type"*\ + * - ``3356``\ + - | ``struct_bindings_is_cpp17``\ : + | structured bindings are a C++17 feature + * - ``3357``\ + - | ``capturing_struct_bindings_is_cpp20``\ : + | capturing structured bindings is a C++20 feature + * - ``3358``\ + - | ``bad_splicer_operand``\ : + | operand of splicer has type *"type"*\ instead of std::meta::info + * - ``3359``\ + - | ``not_a_type_reflection``\ : + | operand (reflection for *reflection-description*\ ) is not the + reflection of a type + * - ``3360``\ + - | ``nonconstant_splicer_operand``\ : + | nonconstant operand of splicer + * - ``3361``\ + - | ``bad_std_string_view``\ : + | use of *"type"*\ instead of std::string_view (= + std::basic_string_view) + * - ``3362``\ + - | ``inconsistent_std_string_view``\ : + | std::string_view used here is inconsistent with use in other + intrinsics + * - ``3363``\ + - | ``invalid_std_string_view_for_reflection``\ : + | definition of std::string_view does not match assumptions of + reflection (no base classes and data members for pointer and length) + * - ``3364``\ + - | ``constexpr_reflection_not_of_constant``\ : + | reflection is not that of a constant value + * - ``3368``\ + - | ``bad_reflection_kind_for_expression_splice``\ : + | bad reflection (*reflection-description*\ ) for expression splice + * - ``3369``\ + - | ``already_defined_with_pos``\ : + | *entity-kind "entity"*\ has already been defined (previous + definition at line *xxxx*\ ) + * - ``3371``\ + - | ``incompatible_std_meta_value_of_type``\ : + | extract of type *"type"*\ is not compatible with the given + reflection (entity with type *"type"*\ ) + * - ``3372``\ + - | ``reflection_of_overloaded_set``\ : + | reflecting an overload set is not currently permitted + * - ``3373``\ + - | ``intrinsic_requires_template_instance``\ : + | this intrinsic requires a reflection for a template instance + * - ``3374``\ + - | ``invalid_reflection_equality``\ : + | incompatible types *"type"*\ and *"type"*\ for operator + * - ``3375``\ + - | ``invalid_reflection_for_intrinsic``\ : + | invalid reflection for intrinsic metafunction + * - ``3376``\ + - | ``nonmember_reflection_for_intrinsic``\ : + | intrinsic metafunction requires a reflection for a class member + * - ``3377``\ + - | ``union_base``\ : + | a class cannot not derive from a union + * - ``3378``\ + - | ``base_with_flexible_array``\ : + | cannot derive from a class with a flexible array member + * - ``3379``\ + - | ``null_reflection``\ : + | null reflection + * - ``3380``\ + - | ``namespace_alias``\ : + | namespace alias + * - ``3381``\ + - | ``unspecified_reflection``\ : + | reflection (details unavailable) + * - ``3382``\ + - | ``std_meta_substitute_bad_arg_reflection``\ : + | bad reflection (*reflection-description*\ ) for template argument in + std::meta::substitute + * - ``3383``\ + - | ``std_meta_substitute_failed``\ : + | call to std::meta::substitute (for *reflection-description*\ ) failed + * - ``3384``\ + - | ``expired_reflection_value``\ : + | reflection value refers to inactive entity + * - ``3385``\ + - | ``cannot_splice_general_expression``\ : + | an expression splice must splice a constant value, a variable, or a + function + * - ``3386``\ + - | ``cannot_splice_member_access``\ : + | a member access splice must splice a data member or a member function + * - ``3387``\ + - | ``splice_is_not_a_member_of_class``\ : + | member *entity-kind "entity"*\ (declared at line *xxxx*\ ) is not a + direct or indirect member of *"type"*\ + * - ``3388``\ + - | ``unicode_name_not_found``\ : + | the name *"xxxx"*\ does not designate a known Unicode character + * - ``3389``\ + - | ``unterminated_unicode_name``\ : + | unterminated named Unicode character escape + * - ``3390``\ + - | ``invalid_char_in_unicode_name``\ : + | character cannot appear in a Unicode name + * - ``3391``\ + - | ``empty_unicode_name``\ : + | empty named Unicode character escape + * - ``3392``\ + - | ``exp_lsplice``\ : + | expected a "[:" + * - ``3393``\ + - | ``exp_rsplice``\ : + | expected a ":]" + * - ``3394``\ + - | ``lambda_mutable_and_static``\ : + | a lambda expression cannot be both "mutable" and "static" + * - ``3395``\ + - | ``static_lambda_nonstandard``\ : + | a "static" lambda expression is nonstandard + * - ``3396``\ + - | ``static_lambda_with_capture``\ : + | a "static" lambda expression must have an empty capture specification + * - ``3399``\ + - | ``ifc_creation_failure``\ : + | an IFC file could not be produced for the current translation unit + * - ``3400``\ + - | ``unsupported_il_to_ifc``\ : + | one or more entities cannot currently be written to an IFC file + * - ``3401``\ + - | ``nonstandard_explicit_bool``\ : + | 'explicit(bool)' is a C++20 feature + * - ``3402``\ + - | ``bad_type_for_atomic_fetch``\ : + | first argument must be a pointer to integer, enum, or supported + floating-point type + * - ``3403``\ + - | ``module_use_in_multi_tu_mode``\ : + | C++ modules cannot be used when compiling multiple translation units + * - ``3404``\ + - | ``module_use_with_export_template``\ : + | C++ modules cannot be used with the pre-C++11 "export" feature + * - ``3405``\ + - | ``ifc_unsupported_token``\ : + | the IFC token *"xxxx"*\ is not supported + * - ``3406``\ + - | ``pass_object_size_not_in_function_decl``\ : + | the "pass_object_size" attribute is only valid on parameters of + function declarations + * - ``3407``\ + - | ``attr_arg_out_of_small_integer_range``\ : + | the argument of the *"xxxx"*\ attribute *n*\ must be a value + between 0 and *n*\ + * - ``3408``\ + - | ``ref_qualifier_ignored``\ : + | a ref-qualifier here is ignored + * - ``3409``\ + - | ``invalid_neon_vector_element_type``\ : + | invalid NEON vector element type *"type"*\ + * - ``3410``\ + - | ``invalid_neon_polyvector_element_type``\ : + | invalid NEON polyvector element type *"type"*\ + * - ``3411``\ + - | ``invalid_scalable_vector_element_type``\ : + | invalid scalable vector element type *"type"*\ + * - ``3412``\ + - | ``invalid_scalable_vector_tuple_elements``\ : + | invalid number of tuple elements for scalable vector type + * - ``3413``\ + - | ``invalid_neon_vector_size``\ : + | a NEON vector or polyvector must be either 64 or 128 bits wide + * - ``3414``\ + - | ``sizeless_type_not_allowed``\ : + | sizeless type *"type"*\ is not allowed + * - ``3415``\ + - | ``value_init_of_sizeless_type``\ : + | an object of the sizeless type *"type"*\ cannot be value-initialized + * - ``3416``\ + - | ``ifc_unexpected_null_scope_member``\ : + | unexpected null declaration index found as part of scope *n*\ + * - ``3417``\ + - | ``cl_unnamed_module_map``\ : + | a module name must be specified for the module file map referencing + the file *"xxxx"*\ + * - ``3418``\ + - | ``ifc_partition_missing_element``\ : + | a null index value was received where a node in the IFC partition + *"xxxx"*\ was expected + * - ``3419``\ + - | ``void_template_variable``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) cannot have type + *"type"*\ + * - ``3420``\ + - | ``ref_qualifier_nonstandard``\ : + | a ref-qualifier is nonstandard in this mode + * - ``3421``\ + - | ``range_based_for_nonstandard``\ : + | a range-based "for" statement is nonstandard in this mode + * - ``3422``\ + - | ``auto_type_nonstandard``\ : + | "auto" as a type specifier is nonstandard in this mode + * - ``3423``\ + - | ``cannot_import_module_bad_checksum``\ : + | could not import module file *"xxxx"*\ due to file corruption + * - ``3425``\ + - | ``extraneous_injected_member_tokens``\ : + | extraneous tokens injected after member declaration + * - ``3426``\ + - | ``bad_injection_scope``\ : + | bad injection scope (*reflection-description*\ ) + * - ``3427``\ + - | ``expected_string_view_value``\ : + | expected a value of type std::string_view but got *"type"*\ + * - ``3428``\ + - | ``extraneous_injected_statement_tokens``\ : + | extraneous tokens injected after statement + * - ``3429``\ + - | ``extraneous_injected_declaration_tokens``\ : + | extraneous tokens injected after declaration + * - ``3430``\ + - | ``tuple_index_overflow``\ : + | tuple index value (*n*\ ) overflow + * - ``3431``\ + - | ``constexpr_begin_report_tokens``\ : + | >> output from std::meta::\__report_tokens + * - ``3432``\ + - | ``constexpr_end_report_tokens``\ : + | >> end output from std::meta::\__report_tokens + * - ``3433``\ + - | ``constexpr_no_current_parameters``\ : + | not in a context with parameter variables + * - ``3434``\ + - | ``empty_delimited_escape``\ : + | a delimited escape sequence must have at least one character + * - ``3435``\ + - | ``unterminated_delimited_escape``\ : + | unterminated delimited escape sequence + * - ``3436``\ + - | ``constant_addresses_local_variable``\ : + | constant contains address of a local variable + * - ``3437``\ + - | ``struct_binding_consteval``\ : + | a structured binding cannot be declared "consteval" + * - ``3438``\ + - | ``module_import_conflict``\ : + | *"entity"*\ conflicts with the imported declaration *entity-kind + "entity"*\ (declared at line *xxxx*\ ) + * - ``3439``\ + - | ``char_too_wide_for_rep``\ : + | character cannot be represented in the specified character type + * - ``3440``\ + - | ``annotation_after_using``\ : + | an annotation cannot appear in the context of a "using" attribute + prefix + * - ``3441``\ + - | ``annotation_must_have_literal_type``\ : + | type *"type"*\ of annotation is not a literal type + * - ``3442``\ + - | ``ext_vector_type_requires_bool_integral_floating_type``\ : + | the "ext_vector_type" attribute applies only to bool, integer, or + floating-point types + * - ``3443``\ + - | ``multiple_union_designators``\ : + | multiple designators into the same union are not permitted + * - ``3444``\ + - | ``debug_show_location``\ : + | test message + * - ``3445``\ + - | ``microsoft_version_doesnt_support_cpp23_mode``\ : + | the version of Microsoft being emulated must be at least 1943 to use + "--ms_c++23" + * - ``3446``\ + - | ``cl_invalid_cwd``\ : + | invalid current working directory: *xxxx*\ + * - ``3447``\ + - | ``cleanup_attribute_in_constexpr_function``\ : + | "cleanup" attribute within a constexpr function is not currently + supported + * - ``3448``\ + - | ``assume_statement_applies_to_null_statements``\ : + | the "assume" attribute can only apply to a null statement + * - ``3449``\ + - | ``assumption_failed``\ : + | assumption failed + * - ``3450``\ + - | ``variable_templates_is_cpp14``\ : + | variable templates are a C++14 feature + * - ``3451``\ + - | ``address_of_function_with_pass_object_size_attr``\ : + | cannot take the address of a function with a parameter declared with + the "pass_object_size" attribute + * - ``3452``\ + - | ``all_arguments_must_have_same_type``\ : + | all arguments must have the same type + * - ``3453``\ + - | ``comparison_details``\ : + | the final comparison was *xxxx*\ *xxxx*\ *xxxx*\ + * - ``3454``\ + - | ``too_many_arguments_provided_for_attribute``\ : + | too many arguments for attribute *"xxxx"*\ + * - ``3455``\ + - | ``constexpr_bad_mantissa_string``\ : + | mantissa string does not contain a valid number + * - ``3456``\ + - | ``constexpr_float_error``\ : + | floating-point error during constant evaluation + * - ``3457``\ + - | ``inheriting_ctor_ignored_for_copy``\ : + | inheriting constructor *entity-kind "entity"*\ ignored for + copy/move-like operation + * - ``3458``\ + - | ``cannot_get_file_size``\ : + | cannot determine size of file *xxxx*\ + * - ``3459``\ + - | ``cannot_read_file``\ : + | cannot read *xxxx*\ + * - ``3461``\ + - | ``unrec_embed_param``\ : + | unrecognized parameter name + * - ``3462``\ + - | ``dupl_embed_param``\ : + | parameter specified more than once + * - ``3463``\ + - | ``has_embed_not_in_if``\ : + | __has_embed cannot appear outside #if + * - ``3464``\ + - | ``setlocale_lc_numeric_failed``\ : + | could not set LC_NUMERIC locale to C + * - ``3465``\ + - | ``elifdef_not_enabled``\ : + | elifdef and elifndef are not enabled in this mode and are ignored in + text being skipped + * - ``3466``\ + - | ``nonstandard_alias_declaration_context``\ : + | an alias declaration is nonstandard in this context + * - ``3467``\ + - | ``out_of_order_field_allocation_nonstandard``\ : + | the target ABI may allocate nonstatic members in an order not + matching their declaration order, which is nonstandard in C++23 and + later + * - ``3470``\ + - | ``module_unit_export_unexpected``\ : + | the module declaration cannot be exported from this translation unit + unless creating a module interface file + * - ``3471``\ + - | ``module_unit_export_expected``\ : + | the module declaration must be exported from this translation unit to + create a module interface file + * - ``3472``\ + - | ``cannot_write_module_none_declared``\ : + | module file generation was requested but no module was declared in + the translation unit + * - ``3473``\ + - | ``candidate_constraints_failed``\ : + | substituting *""*\ for *entity-kind "entity"*\ failed + constraints + * - ``3474``\ + - | ``concept_not_satisfied``\ : + | *entity-kind "entity"*\ not satisfied for *""*\ + * - ``3475``\ + - | ``bad_embed_initializer``\ : + | the #embed expansion is too long to initialize an entity of type + *"type"*\ + * - ``3476``\ + - | ``bad_defined_pp_op``\ : + | the "defined" operator is not permitted here + * - ``3477``\ + - | ``ptr_to_mem_to_non_member``\ : + | *entity-kind "entity"*\ is not a member of *"type"*\ + * - ``3478``\ + - | ``embed_narrowing``\ : + | narrowing conversion to signed character in #embed data + * - ``3479``\ + - | ``invalid_vector_of_bool_operator``\ : + | operator is not permitted for "vector of bool" types + * - ``3480``\ + - | ``constexpr_object_too_large``\ : + | object too large for constant-evaluation + * - ``3481``\ + - | ``self_referencing_temporary_object``\ : + | self-referencing temporary object + * - ``3482``\ + - | ``lambda_cannot_refer_to_local_entity_here``\ : + | a lambda cannot refer to a local variable or init-capture in this + context + * - ``3483``\ + - | ``parameter_capture_conflict``\ : + | a lambda parameter cannot hide an explicit capture + * - ``3484``\ + - | ``template_parameter_capture_conflict``\ : + | a lambda template parameter cannot hide an explicit capture + * - ``3485``\ + - | ``insufficient_address_space``\ : + | insufficient address space exists to process this translation unit + * - ``3486``\ + - | ``undetermined_type``\ : + | + * - ``3487``\ + - | ``undetermined_constant``\ : + | + * - ``3488``\ + - | ``undetermined_template``\ : + | + * - ``3489``\ + - | ``bad_flt_config``\ : + | the configured size of *xxxx*\ is too small for the specified number + of mantissa + exponent bits + * - ``3490``\ + - | ``expression``\ : + | expression + * - ``3491``\ + - | ``quoted_expression``\ : + | + * - ``3492``\ + - | ``unnamed``\ : + | unnamed + * - ``3493``\ + - | ``quoted_unnamed``\ : + | + * - ``3494``\ + - | ``error_type``\ : + | + * - ``3495``\ + - | ``unknown_type``\ : + | + * - ``3496``\ + - | ``something``\ : + | + * - ``3497``\ + - | ``null_type``\ : + | + * - ``3498``\ + - | ``no_init``\ : + | + * - ``3499``\ + - | ``zero_init``\ : + | + * - ``3500``\ + - | ``bitwise_copy_of``\ : + | bitwise copy of: + * - ``3501``\ + - | ``bitwise_copy``\ : + | + * - ``3502``\ + - | ``class_result_via_ctor``\ : + | class result via ctor: + * - ``3503``\ + - | ``constructor_call``\ : + | + * - ``3504``\ + - | ``null_expression``\ : + | + * - ``3505``\ + - | ``quoted_error``\ : + | + * - ``3506``\ + - | ``null_routine``\ : + | + * - ``3507``\ + - | ``quoted_default``\ : + | + * - ``3508``\ + - | ``parameter_number``\ : + | parameter # + * - ``3509``\ + - | ``one_level_up``\ : + | (one level up) + * - ``3510``\ + - | ``levels_up``\ : + | levels up + * - ``3511``\ + - | ``dynamic_init``\ : + | dynamic-init: + * - ``3512``\ + - | ``error_constant``\ : + | + * - ``3513``\ + - | ``stack_offset_of``\ : + | stack-offset-of: + * - ``3514``\ + - | ``implicit_element``\ : + | + * - ``3515``\ + - | ``repetitions_of``\ : + | repetitions of + * - ``3516``\ + - | ``type_code_integer``\ : + | integer + * - ``3517``\ + - | ``type_code_enum``\ : + | enum + * - ``3518``\ + - | ``type_code_scoped_enum``\ : + | scoped enum + * - ``3519``\ + - | ``type_code_arithmetic``\ : + | arithmetic + * - ``3520``\ + - | ``type_code_non_bool_arithmetic``\ : + | non-bool arithmetic + * - ``3521``\ + - | ``type_code_pointer``\ : + | pointer + * - ``3522``\ + - | ``type_code_nullptr_type``\ : + | nullptr type + * - ``3523``\ + - | ``type_code_handle``\ : + | handle + * - ``3524``\ + - | ``type_code_handle_to_CLI_array``\ : + | handle-to-CLI-array + * - ``3525``\ + - | ``type_code_pointer_to_object``\ : + | pointer-to-object + * - ``3526``\ + - | ``type_code_pointer_to_function``\ : + | pointer-to-function + * - ``3527``\ + - | ``type_code_pointer_to_member``\ : + | pointer-to-member + * - ``3528``\ + - | ``type_code_bool``\ : + | bool + * - ``3529``\ + - | ``type_code_bool_equivalent``\ : + | bool-equivalent + * - ``3530``\ + - | ``type_code_class``\ : + | class + * - ``3531``\ + - | ``volatile_inc_deprecated``\ : + | a volatile operand to an increment expression is deprecated + * - ``3532``\ + - | ``volatile_dec_deprecated``\ : + | a volatile operand to a decrement expression is deprecated + * - ``3533``\ + - | ``indeterminate_not_on_first_decl``\ : + | *entity-kind "entity"*\ previously declared without the + "indeterminate" attribute + * - ``3534``\ + - | ``default_constructor_is_explicit``\ : + | the default constructor for *"type"*\ is explicit + * - ``3535``\ + - | ``ifc_definition_load_failure``\ : + | failed to load the definition of *entity-kind "entity"*\ in *module + "module name"*\ + * - ``3536``\ + - | ``ifc_initializer_load_failure``\ : + | failed to load the initializer for *entity-kind "entity"*\ in + *module "module name"*\ + * - ``3537``\ + - | ``base_class_of_class_type_with_typedef_name``\ : + | a class with a typedef name for linkage purposes cannot have a base + class + * - ``3538``\ + - | ``member_function_of_class_type_with_typedef_name``\ : + | a class with a typedef name for linkage purposes cannot have a member + function + * - ``3539``\ + - | ``member_type_of_class_type_with_typedef_name``\ : + | a class with a typedef name for linkage purposes cannot have a nested + type, other than an enumeration type or a non-closure class type + * - ``3540``\ + - | ``lambda_in_class_type_with_typedef_name``\ : + | a class with a typedef name for linkage purposes cannot contain a + lambda expression + * - ``3541``\ + - | ``field_init_in_class_type_with_typedef_name``\ : + | a class with a typedef name for linkage purposes cannot have a + nonstatic data member with a default member initializer + * - ``3542``\ + - | ``static_data_member_not_allowed_in_unnamed_class``\ : + | a static data member declaration is not allowed in an unnamed class + * - ``3543``\ + - | ``initializer_addresses_dllimport_variable``\ : + | initializer result addresses a dllimport variable + * - ``3544``\ + - | ``cannot_be_specialized``\ : + | template with "no_specializations" attribute cannot be specialized + * - ``3545``\ + - | ``static_dimension_nonstandard``\ : + | "static" is nonstandard here + * - ``3546``\ + - | ``enum_previously_declared_without_explicit_base``\ : + | *entity-kind "entity"*\ (declared at line *xxxx*\ ) was previously + declared without an explicit enum base + * - ``3547``\ + - | ``missing_typename``\ : + | missing "typename" is nonstandard here + * - ``3548``\ + - | ``abbreviated_deduction_guide``\ : + | abbreviated function template syntax is nonstandard for deduction + guides + * - ``3549``\ + - | ``explicit_this_is_cpp23``\ : + | explicit "this" parameters are a C++23 feature + * - ``3550``\ + - | ``array_designator_for_deduced_context``\ : + | array designators are not supported in template deduction contexts + * - ``3551``\ + - | ``second_argument_wrong_shape``\ : + | the second argument must be an integer type with the same shape (a + scalar or vector type) as the first argument + * - ``3552``\ + - | ``vector_of_boolean_required``\ : + | argument must be a vector of boolean types + * - ``3553``\ + - | ``pointer_to_scalar_required``\ : + | argument must be a pointer to a scalar type + * - ``3554``\ + - | ``incorrect_masked_type``\ : + | incorrect argument type (should be *"type"*\ ) + * - ``3555``\ + - | ``vector_type_with_size_is_required``\ : + | a vector type (with the same number of elements as the first + argument) is required + * - ``3556``\ + - | ``struct_binding_packs_is_cpp26``\ : + | structured binding packs are a C++26 feature + * - ``3557``\ + - | ``non_template_structured_binding_pack``\ : + | a structured binding pack can only be declared inside a template + * - ``3558``\ + - | ``multiple_structured_binding_packs``\ : + | cannot declare multiple packs in a structured binding declaration + * - ``3559``\ + - | ``cl_cpp26_requires_parse_nonclass_templates``\ : + | The "--no_parse_templates" option cannot be used in C++26 mode + * - ``3560``\ + - | ``type_pack_element_cannot_match``\ : + | a type pack element cannot match *entity-kind "entity"*\ + * - ``3561``\ + - | ``c23_old_style_param_id``\ : + | identifier-only parameters can only be used in old-style function + definitions, which are nonstandard since C23 + * - ``3562``\ + - | ``cl_require_func_prototypes_option_only_in_C``\ : + | option "no_require_func_prototypes" can be used only when compiling C + * - ``3563``\ + - | ``address_of_overload_set_implicit_obj_member_selected``\ : + | overload resolution for an address-of-overload-set call may not + select implicit-object member *entity-kind "entity"*\ (declared at + line *xxxx*\ ) + * - ``3564``\ + - | ``pack_indexing_is_cpp26``\ : + | pack indexing is a C++26 feature + * - ``3565``\ + - | ``pack_index_out_of_bounds``\ : + | pack index exceeds number of pack elements + * - ``3566``\ + - | ``alias_ctad_is_cpp20``\ : + | class template argument deduction for alias templates is a C++20 + feature + * - ``3567``\ + - | ``bitint_width_too_large``\ : + | _BitInt(*n*\ ) is invalid; the maximum integer width is *n*\ + * - ``3568``\ + - | ``signed_bitint_width_too_small``\ : + | _BitInt(*n*\ ) is invalid; the minimum signed _BitInt width is *n*\ + * - ``3569``\ + - | ``unsigned_bitint_width_too_small``\ : + | unsigned _BitInt(*n*\ ) is invalid; the minimum unsigned _BitInt + width is *n*\ + * - ``3570``\ + - | ``bitint_enum_base_not_allowed``\ : + | _BitInt types cannot be the underlying type of an enumeration type + * - ``3571``\ + - | ``deduction_guide_redeclaration``\ : + | redeclaration of deduction guide *"type"*\ (previous declaration at + line *xxxx*\ ) + * - ``3572``\ + - | ``create_pch_file_not_created``\ : + | precompiled header file *"xxxx"*\ was not created + * - ``3576``\ + - | ``non_c_like_typedef_for_linkage``\ : + | anonymous non-C-like type given name for linkage purposes by typedef + or alias declaration + * - ``3577``\ + - | ``non_c_like_because_of_base_class``\ : + | type is not C-like because of this base class + * - ``3578``\ + - | ``non_c_like_because_of_default_member_init``\ : + | type is not C-like because of this default member initializer + * - ``3579``\ + - | ``non_c_like_because_of_friend``\ : + | type is not C-like because of this friend declaration + * - ``3580``\ + - | ``non_c_like_because_of_member``\ : + | type is not C-like because of this member declaration + * - ``3581``\ + - | ``non_c_like_because_of_lambda``\ : + | type is not C-like because of this lambda expression + * - ``3582``\ + - | ``enum_qualifier_is_cpp11``\ : + | an enum-type name qualifier is a C++11 feature + * - ``3583``\ + - | ``unrestricted_unions_is_cpp11``\ : + | unrestricted unions are a C++11 feature + * - ``3584``\ + - | ``pack_expansion_for_non_pack_alias_param``\ : + | a pack expansion cannot be used as an argument for non-pack + *entity-kind "entity"*\ of *entity-kind "entity"*\ + * - ``3585``\ + - | ``uniterable_reflection_range``\ : + | the range passed to the metafunction cannot be iterated + * - ``3587``\ + - | ``interpreter_message_remark``\ : + | *xxxx*\ *xxxx*\ + * - ``3588``\ + - | ``interpreter_message_warning``\ : + | *xxxx*\ *xxxx*\ + * - ``3589``\ + - | ``interpreter_message_error``\ : + | *xxxx*\ *xxxx*\ + * - ``3590``\ + - | ``constexpr_diag_arg_count``\ : + | a call to "\__builtin_constexpr_diag" requires three arguments + * - ``3591``\ + - | ``constexpr_diag_bad_level``\ : + | the first argument in a call to "\__builtin_constexpr_diag" must be 0 + (remark), 1 (warning), 2 (error), 16 (remark at caller), 17 (warning + at caller), or 18 (error at caller) + * - ``3592``\ + - | ``constexpr_diag_bad_string``\ : + | a string literal or an object with the representation of + std::string_view is required for the tag and the message in a call to + "\__builtin_constexpr_diag" + * - ``3593``\ + - | ``constexpr_diag_bad_tag``\ : + | the tag in a call to "\__builtin_constexpr_diag" may contain only + letters, digits, and underscores + * - ``3594``\ + - | ``cl_invalid_constexpr_diag_tag``\ : + | invalid tag in constexpr diagnostic control option: *xxxx*\ + * - ``3595``\ + - | ``token_sequence_needs_double_caret``\ : + | a token sequence must be introduced by "^^" + * - ``3596``\ + - | ``exp_interpolator``\ : + | expected an interpolator ("\[", "\[:", "\{", "\val", or "\str") + * - ``3597``\ + - | ``interpolated_id_is_not_identifier``\ : + | *"xxxx"*\ does not spell an identifier + * - ``3598``\ + - | ``interpolated_operand_is_not_token_sequence``\ : + | the operand of a "\{...}" interpolator is not a token sequence + * - ``3599``\ + - | ``tag_redefined_differently``\ : + | this declaration of *entity-kind "entity"*\ does not declare the + same type as the declaration at line *xxxx*\ diff --git a/doc/_sources/exceptions.rst.txt b/doc/_sources/exceptions.rst.txt new file mode 100644 index 0000000..5178d16 --- /dev/null +++ b/doc/_sources/exceptions.rst.txt @@ -0,0 +1,566 @@ +================== +Exception Handling +================== + +The high-level representation of exception handling in the IL closely follows +the C++ language specification. The data structures involved are defined in +``il_def.h``, and the routines to manage declarations and other support are in +``decls.c``, ``statements.c``, and ``expr.c``. + +A global variable, ``exceptions_enabled``, controls whether exception +processing is done. An error is issued if the flag is FALSE and the source +program attempts to use a syntactic feature that pertains to exception +handling. The default value of the ``exceptions_enabled`` flag is configurable +(see ``DEFAULT_EXCEPTIONS_ENABLED`` in ``lang_feat.h``). The value may be +toggled by a command-line option (``-x``), except that its value may be TRUE +only in C++ mode and only when cfront-compatibility mode has not been selected. + +Any actual implementation of exception handling will require a tradeoff between +portability and efficiency. The high-level representation of exception +handling (that is, the representation of the "unlowered" IL) is not explicit +about a number of details that an actual implementation will have to deal with, +notably finding the right handler, copying the ``throw`` object to the right +handler parameter, and calling the right set of destructors at the right time. +Therefore, though a portable implementation of exception handling is provided +(see ``lower_eh.c`` and routines provided for run-time support), back ends may +choose to replace it with an implementation adapted to the specific support +available on the target platform. IL lowering can instead be configured to do +partial lowering or no lowering of exception handling features. + +This chapter describes the high-level support for exceptions and then +summarizes the main features of the portable implementation. + +Exception Specifications +======================== + +An exception specification that appears on a function declaration is +represented by an entry of type ``an_exception_specification``. The +function refers to it by means of the ``exception_specification`` field of +its routine type supplement. When the function is declared with no +exception specification (meaning that *any* exception might be thrown), the +``exception_specification`` pointer will be NULL. A dynamic ``throw`` +specification entry itself has a pointer to a linked list of entries of +type ``a_throw_spec_type_entry``, each of which indicates a type of +exception that will be thrown from the given routine; that pointer is NULL +to indicate that *no* exceptions will be thrown. A ``noexcept`` specifier +points to a constant representing its operand or NULL if there is no such +operand. + +``scan_exception_specification``, which is called from ``function_declarator``, +scans an exception specification and allocates a ``throw`` specification entry +and its associated list of types, if any. Subsequently (i.e., after the +routine entry has been identified) the exception specification is either added +to the routine type supplement or checked against a prior declaration (see +``check_exception_specification``). + +The ``used_in_exception`` flag is set for any type that appears in an exception +specification (as well as for any type that is the type of a ``throw`` +expression or appears in the exception declaration of a handler). Some +implementations of exception handling may use this flag in generating special +code for run-time type identification. In addition, if such a type is (or +"contains") a class or enumeration type, that class or enumeration type must be +externally linked. See ``set_used_in_exception_or_rtti_flag`` (in +``types.c``). + +``try`` Blocks +============== + +A ``try`` block is represented in the IL by a statement of kind +``stmk_try_block``, which points to a compound statement block and a linked +list of handlers. The latter are entries of type ``a_handler``; each points to +a (possibly unnamed) parameter (the local variable to which the ``throw`` +object will be copied when the handler is invoked) and to an ``stmk_block`` +statement, the body of the handler; for a default handler (i.e., the +``catch(...)`` case) the parameter pointer in the handler entry is NULL. + +A ``try`` block is scanned by ``try_block_statement`` (in ``statements.c``). +First ``compound_statement`` is called to scan the part of the ``try`` block +that precedes the first handler declaration. Then ``handler_declaration`` (in +``decls.c``) is called for each ``catch`` clause. + +``handler_declaration`` scans the exception declaration (calling +``decl_specifiers`` and, if a named parameter is present, ``declarator``). +Except for the default handler case, it creates a ``variable`` entry to +represent the parameter, whether it is explicitly declared or not. It also +does various checks to assure that the parameter's type is valid (e.g., that it +is not an incomplete type) and calls ``set_used_in_exception_or_rtti_flag``; +then it calls ``type_masks_handler_param_type`` (in ``types.c``), to assure +that it is not masked by a previous handler declaration in the same ``try`` +block. + +Finally, ``compound_statement`` is called to scan the handler's body. Special +checking is done to assure that no label defined within the handler is +referenced by a ``goto`` from outside the handler. + +in C++/CLI mode, there may be a "``finally``" block at the end, either in +addition to or in place of the catch clauses. It provides code that is +always executed when the try block is exited, whether normally, via a +``goto`` or ``return``, or via a thrown exception. + +``throw`` Expressions +===================== + +A ``throw`` expression is scanned by ``scan_throw_operator`` (in ``expr.c``). +An ``enk_throw`` expression node is produced, which points to a dynamic +initialization entry that describes the object to be thrown (or rather, how to +copy it to the space for the object allocated by the run-time). +``set_used_in_exception_or_rtti_flag`` is called for the type. A "rethrow", +where no ``throw`` object is specified (i.e., ``throw;``), is represented by an +``enk_throw`` expression with a NULL pointer. + +Portable Implementation +======================= + +One exception handling implementation provided in this release is a portable +implementation that provides complete EH support while requiring few changes to +existing back ends. Because this is a portable implementation there is a +significant impact on the performance of the generated code when exception +handling is enabled. + +A walk-through of an EH example +------------------------------- + +What follows is a rather contrived example that provides an overview of how the +compiled code and the run-time system cooperate in throwing and handling +exceptions. It is intended as an introduction, with a more detailed discussion +of some of its features in subsequent sections. + +Here is the example (with the numbers to the right corresponding to the text +that follows): + +.. code:: c++ + + #include + struct A { ~A() { } }; + struct B : public A { }; + struct C { }; + void f(int i) throw(A) { // 2, 3, 4 + A a1; // 5 + if (i==0) throw a1; // 6 + B b1; + if (i==1) throw b1; + C c1; + if (i==2) throw c1; + } + int main() { + for (int i = 0; i < 3; ++i) { + printf("i=%0d\n", i); + try { // 1 + f(i); + } + catch (A a) { printf("Caught an A\n"); } // 7, 8 + catch (...) { printf("Caught something else\n"); } + } /* for */ // 9 + } + +#. Each time the ``for`` loop in ``main`` is executed and control enters + the ``try`` block, prologue code is executed, which includes pushing an + entry onto the "EH stack" to record that a ``try`` block has been + entered. (The EH stack is the principal data structure used to track the + dynamic context in which exception handling events occur.) + +#. Each time ``f`` is called, prologue code for the function pushes another + entry onto the EH stack to record that a function with exception + specifications has been entered. This entry provides the run-time system + with a list of the types that may be thrown from ``f``. + +#. Moreover, since ``f`` contains objects (namely, automatic variables with + destructors) that may need to be cleaned up if an exception is thrown + during its execution, an additional entry is pushed onto the EH stack + for object cleanup. [#f1]_ The array it points to is updated each time + an object that is eligible for clean-up is constructed. + +#. The first clean-up region of ``f`` is entered, and global variable + ``__eh_curr_region`` is updated accordingly. This routine has three such + regions -- the region in which no objects require clean-up, the region in + which ``a1`` requires clean-up, and the region in which both ``a1`` and + ``b1`` require clean-up. [#f2]_ + +#. When ``a1`` is constructed, the second clean-up region is entered. The + address of ``a1`` is entered in the "object address table". + +#. The processing for the original source expression "``throw a1``" + involves three steps: + + * | ``__throw_setup`` is called to record information about ``a1`` (most + importantly, its type) and to return a pointer to a piece of storage + into which it may be copied. [#f3]_ + + * | The compiled code makes a copy of ``a1`` to pass to + ``__throw``. Note that if class ``A`` had a copy constructor, the + generated code would include a call of ``__exception_started`` prior + to making the copy of ``a1``. + + * | ``__throw`` is called. First it walks the EH stack to identify the + action that is required -- in this case, it locates a handler that + can catch an ``A`` object. It then makes a second pass through the + EH stack to do the appropriate clean-up, which in this case involves + calling the destructor for ``a1`` and popping a couple of entries + off the EH stack. The actions performed by ``__throw`` may entail a + good deal more complexity, as described in greater detail later. + +#. After the clean-up is complete, control transfers back to the ``try`` + block in ``main``, and specifically to the first handler (since it is + the one that catches an ``A`` object), and then "``Caught an A``" is + printed out. + +#. The epilogue code of the handler involves a call to + ``__free_thrown_object``, to deallocate the storage into which ``a1`` + was copied. + +#. As the ``try`` block is exited, the EH stack entry for the current + ``try`` block is popped, restoring the state to what it was originally, + before the try block was entered. + +On the second iteration of the ``for`` loop in ``main``, the same sequence of +events takes place, except for two things. First, in function ``f``\ ``b1`` is +also constructed, so that the third clean-up region is entered and the address +of ``b1`` is recorded in the object address table (along with that of ``a1``); +that means that two objects are eligible for clean-up when an exception occurs. +Second, ``__throw`` must take into account that ``A`` is an accessible base +class of ``B`` in locating the handler that can catch ``b1``. + +Finally, on the third iteration of the loop, ``__throw`` detects a violation of +the exception specification for function ``f`` -- ``c1`` is the thrown object +this time, but ``C`` is not on the list of types that the function is allowed +to throw. As a result, ``unexpected`` is called, which results in a call to +``terminate``. + +Run-Time Support +---------------- + +The EH Stack +^^^^^^^^^^^^ + +A principal data structure used in coordinating the compiled code and the +run-time is the "EH stack". It maintains information about the dynamic context +in which exception handling events occur. The EH stack is a linked list of +structures, and a new entry is pushed onto the stack each time a ``try`` block +is entered, each time a function with an exception specification is entered, +and each time a function is entered for which some kind of object clean-up must +be done if an exception is thrown. + +Code generated for a ``try`` block +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a ``try`` block is entered, a ``try`` block entry is pushed onto the EH +stack. The ``try`` block entry contains + +* | a ``setjmp`` buffer that will be used for transfer of control back to the + ``try`` block when an exception is thrown; +* | a list of the ``catch`` clauses associated with the ``try`` block; +* | other status information used to record the current state of the ``try`` + block. + +The state information in the ``try`` block is initialized so that the run-time +knows that the ``try`` section of the block (as opposed to one of the handlers) +is currently being executed. When generating code for exception cleanup it is +sometimes necessary for the front end to generate ``try`` blocks that do not +appear in the original program. These are known as "internal" ``try`` blocks +and are distinguished from normal ``try`` blocks by the fact that the pointer +to the list of ``catch`` clauses is null. + +Prologue code for a function with an exception specification +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a function with an exception specification is entered, a ``throw`` +specification entry is pushed onto the EH stack. This entry provides a list of +the types that may be thrown (directly or indirectly) by the function. It is +removed from the EH stack when the function returns. + +Prologue code for a function that may need clean-up if an exception is thrown +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a function constructs objects that may need to be cleaned up in the event +of an exception, its prologue code pushes a function clean-up entry onto the EH +stack. Note that a given function may push both a ``throw`` specification +entry and a function clean-up entry. + +A function clean-up entry will be pushed on the stack if the function creates +any automatic objects (including temporaries) of classes with destructors; one +is also generated when an object may be dynamically allocated using ``operator +new`` and the front end is configured to generate the ``operator new`` call +outside the constructor. + +The function clean-up entry contains + +* | a pointer to an array of region entries that are used to describe the + clean-up regions within the function +* | a pointer to an array table that provides additional information for + certain region entries +* | a pointer to an object address table used to determine the address of + objects referenced by the region and array tables + +A region is associated with a specific sequence of clean-up actions that would +be required should an exception occur. A new region is typically started +whenever a destructable object comes into or goes out of scope. + +The global variable ``__eh_curr_region`` records the region number currently +being executed. It is saved each time a new function entry or ``try`` block is +pushed on the stack and restored when the entry is popped. + +The region entries contain the information needed to identify the object to be +cleaned up and the kind of clean-up action required. The run-time must be able +to determine the address of each object for which some kind of clean-up must be +done. Ideally this would be done by putting stack offsets in the region +entries. This can't be done in the portable implementation, and so instead the +region entries contain an index into the object address table. The object +address table is allocated on the stack because its contents vary with each +invocation of the function. As each region is entered, the appropriate entry +in the object address table is filled in with the address of the object to be +cleaned up. The address of the object address table is recorded in the +function entry on the EH stack. + +The region entries have been designed to be as compact as possible. Some +unusual circumstances require additional information not normally available in +the region entry. The additional information is needed when the region entry +describes an array or when the region entry describes a new allocation of a +class object whose ``operator delete`` function is of the two-operand variety. +In these cases the region entry contains an index into an array supplement and +the array supplement pointer is stored in the function entry on the EH stack. + +Throwing an exception (generated code) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When an exception is thrown, the run-time routine ``__throw_setup`` is called +to provide information to the run-time system about the object being thrown and +to allocate space into which the thrown object may be copied. A pointer to +this space is returned to the caller (i.e., the compiled code), which is +responsible for actually making the copy of the object. If copying the object +requires calling a copy constructor, ``__exception_started`` is called after +the evaluation of the object to be thrown, but before the copy constructor is +called. Once the object has been copied the run-time routine ``__throw`` is +called to complete the throw processing. If the thrown object requires +destruction, ``__throw_setup_dtor`` is called instead of ``__throw_setup``. If +the thrown object is a multi-level pointer, ``__throw_setup_ptr`` is called +instead of ``__throw_setup``. + +Throwing an exception (``__throw_setup``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When ``__throw_setup`` is called, an entry is pushed onto the throw stack +(which is distinct from the EH stack). The throw stack contains information +about each of the thrown objects and is needed because throws may be nested +(i.e., a throw may occur while in a handler reached as the result of an earlier +throw). ``__throw_setup`` records the information provided by the caller in +the throw stack entry. This includes information about the type of the thrown +object. + +The run-time system requires information about the types of objects that are +thrown and caught and also for types used in exception specifications. The +term "``typeinfo``" is used to refer to this type description information. +[#f4]_ It is not necessarily possible to generate only one ``typeinfo`` record +for a given type. [#f5]_ Consequently it must be possible to determine that +two ``typeinfo`` records refer to the same type. This is done by having each +``typeinfo`` point to a "unique ID object". The unique ID objects are +generated as tentative definitions to avoid potential multiple definition +problems. Two ``typeinfo`` records refer to the same type if they point to the +same unique ID object. The ``typeinfo`` information includes a list of the +base classes of the type. The base class list includes all direct base classes +as well as all virtual base classes, whether direct or indirect. + +When checking exception specifications and looking for a ``catch`` clause that +can catch the thrown object, it is necessary to determine whether a given type +is a base class (and an accessible one) of the thrown type. This is done by +traversing the ``typeinfo`` base class list. The base class list includes +information about accessibility and ambiguity, which allows the runtime to +ignore non-public and ambiguous base classes. + +In front end versions preceding 2.29, the runtime routine ``__throw_alloc`` was +called instead of ``__throw_setup``. It had a similar function and a similar +interface, with one additional parameter, which (when non-NULL) was a string +indicating the accessibility for each base class, computed by the front end at +the point of the throw. This changed because the C++ language changed: As of +March 1995, the rules for ``throw`` were changed to allow catching only public +base classes, which eliminates the need for determining any special +accessibility at the point of throw. + +Marking the initiation of the exception (``__exception_started``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An exception is considered "uncaught" after the expression in the throw +statement has been evaluated. If a copy constructor must be called to copy the +thrown object into the temporary copy used by the EH runtime, the copy +constructor must be called while the exception is considered uncaught. In +other words, if an exception is thrown during the evaluation of the expression +in the throw, that exception is handled normally. If, however, an exception is +thrown from a copy constructor called to copy an object to the temporary used +by the EH runtime (and control is transferred out of the copy constructor +because of the exception) ``terminate()`` must be called instead. + +``__exception_started`` is called to mark the point at which an exception is +considered uncaught. When the copy of the thrown object can be made without +calling a copy constructor ``__exception_started`` is not called, and the +exception is considered uncaught at the point at which ``__throw`` is called. + +Throwing an exception (``__throw``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +After the compiled code copies the thrown object into the space designated by +``__throw_setup``, it issues a call to ``__throw`` to complete the processing. + +``__throw`` makes two passes through the ``try`` stack. The first pass +determines what should occur as a result of the throw -- transferring to a +specific handler, calling ``unexpected`` because an exception specification was +violated, or calling ``terminate`` (for any of several reasons). Once the end +result of the throw has been determined, a second pass is made through the EH +stack entries to perform any clean-up actions that are required. + +During the first pass through the EH stack +``check_exception_type_specifications`` is called for each ``try`` block entry +and each ``throw`` specification entry. Only ``try`` blocks that are executing +the ``try`` portion of the block (as opposed to a handler) are eligible to be +the destination of a ``throw``. ``try`` blocks that are currently in handlers +are simply ignored. The search is terminated when a matching ``catch`` clause +is found or a violated exception specification is detected. When it is a +matching ``catch`` clause that is found, a pointer to the thrown object is +passed to the routine so that it may be adjusted for any derived-to-base-class +conversions that may be needed. If the matching ``catch`` clause is associated +with an internal ``try`` block, the search of the EH stack continues to +determine if a normal ``try`` block can be found. The search for a normal +``try`` block that with a matching handler is used to determine whether +``terminate()`` should be called. + +According to the standard it is implementation-defined whether the stack is +unwound before ``terminate()`` is called. The runtime can be configured to +select either of the possible behaviors by setting the +``UNWIND_STACK_BEFORE_CALLING_TERMINATE`` configuration flag. If this flag is +not set, ``terminate()`` would be called now if no matching handler was found. + +In the second pass only the function clean-up entries are processed. The +function ``cleanup`` is called for each such entry. ``cleanup`` processes the +region entries associated with the function starting with the region number +specified by the caller. Each region entry contains a "flags" field that +controls how the region information is interpreted. + +* | If the "conditional flag" bit is set, the region entry describes an object + that is conditionally constructed and must only be destroyed if a variable, + whose address is determined from the next element in the region array, + indicates the object was actually constructed. +* | If the "new allocation" bit is set, the region entry describes an object + allocated by ``new`` that must be deleted during clean-up. In this case + the function pointer in the region entry that normally points to the + destructor instead points to the delete routine to be called. +* | If the "VLA" bit is set, the region entry describes a variable length + array, whose size is determined from the next element in the region array. + +One of the fields in the region entry is the region number of the next entry to +be processed. The end of the region list is designated by a reserved value in +the next entry field. + +If an exception occurs while constructing or destructing an array, the clean-up +operation must destroy the remaining portion of the partially constructed (or +destructed) array. To accomplish this there is a special kind of EH stack +entry that is only used by ``vec_new`` and ``vec_delete``. When this entry is +encountered during the clean-up pass, ``__cleanup_vec_new_or_delete`` is called +to the required clean-up. + +After all of the function clean-up entries have been processed, ``__throw`` +determines whether there are any clean-up actions required by the ``try`` block +associated with the handler to which control is to be transferred. If so, +``cleanup`` is called to do the required clean-up operations. + +Only after all the clean-up operations have been completed is the action +performed that was determined by the first pass through the EH stack: + +* | If an exception specification was violated, ``unexpected`` is called. +* | If no handler was found, ``terminate()`` is called (when the + ``UNWIND_STACK_BEFORE_CALLING_TERMINATE`` configuration flag is set). +* | Otherwise, control is transferred to the handler. Global variable + ``__catch_clause_number`` is set to the sequence number of the ``catch`` + clause to which control is to be transferred, and another global variable, + ``__caught_object_address``, is set to the address of the object to be used + to initialize the handler parameter. The state information in the ``try`` + block entry is updated to indicate that a handler is now being executed. + Finally, ``longjmp`` is used to branch back to the appropriate ``try`` + block. + +In the handler +^^^^^^^^^^^^^^ + +The ``try`` block code uses ``__catch_clause_number`` to select the appropriate +handler, and then the handler parameter is initialized using +``__caught_object_address``: If the handler parameter is a reference, it is +initialized by setting a pointer to the global variable; otherwise, the object +pointed to by ``__caught_object_address`` is used to initialize the handler +parameter. ``__exception_caught`` is called after the handler parameter has +been initialized. This marks the end of the period during which an exception +is considered uncaught. ``__exception_caught`` is not called by the catch +clause associated with an internal try block. Instead, an internal try block +exits by calling ``__internal_rethrow``, which calls ``__exception_caught`` +before performing the rethrow. + +A rethrow from the handler +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A rethrow (a ``throw`` with no operand) may be executed anywhere within the +dynamic context of a handler. This has the effect of doing a nested throw of +the object on top of the throw stack. Note that it rethrows the thrown object +and not the caught object (the two can be different if a derived-to-base +conversion occurred or if the object was caught using ellipsis). + +The handling of rethrow is almost identical to the handling of a normal throw. +The only difference is that the thrown object is not copied. The throw stack +entry for the rethrow points to the copy of the thrown object made when the +original throw was done. + +At the end of a handler +^^^^^^^^^^^^^^^^^^^^^^^ + +At the end of each handler ``__free_throw_object`` is called to pop entries off +of the throw stack, call the destructor for the thrown object, and to free the +space used for copies of the thrown objects associated with the throw stack +entries being cleared. + +Run-Time storage management +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The exception handling run-time dynamically allocates information used for book +keeping (e.g., throw stack entries) and for making copies of thrown objects. +The memory is allocated and freed using a stack discipline. The run-time +includes a static buffer that is used for this dynamically allocated memory. +If the static buffer is exhausted, additional memory is allocated using +``malloc``. If the run-time is unable to allocate the memory needed to handle +an exception, ``terminate`` is called. + +Non-Portable Implementation +=========================== + +The non-portable implementation would be more properly described as "turning +off parts of the portable implementation so that a back end can do something +better." EDG does not provide a complete non-portable implementation (in IL +lowering and the runtime), but our customers should be able to write one using +the information provided by the front end. + +The portable implementation is also known as the full-lowering implementation, +because it lowers everything related to exception handling to C, leaving +nothing related to exception handling in the IL. It is enabled by setting +``DO_FULL_PORTABLE_EH_LOWERING`` to TRUE. + +The next step down from that is the partial-lowering implementation, which is +enabled by setting ``GENERATE_EH_TABLES`` to TRUE. In that mode, the data +tables of the portable scheme are still generated, but the executable code is +rendered as exception-handling operations, so that a back end can choose a +different approach (e.g., not using ``setjmp``, not maintaining a separate EH +stack). + +The final step down is the no-lowering implementation, which is enabled by +having both ``DO_FULL_PORTABLE_EH_LOWERING`` and ``GENERATE_EH_TABLES`` FALSE. +In that mode, the data tables are not generated either, but the object lifetime +information is preserved so that the back end can use it to generate its own +version of the cleanup tables. + +See the :ref:`il-lowering` chapter for details on the constructs +preserved and lowered under each alternative. + +.. [#f1] Note that the prologue code for ``f`` pushes two entries onto the EH + stack, one for its exception specifications and one for object + clean-up. +.. [#f2] ``c1`` requires no clean-up since ``C`` has no destructor. +.. [#f3] In versions before 2.29, the runtime routine was called + ``__throw_alloc``. +.. [#f4] This is not the structure called "``type_info``" that is visible to + the programmer via ``typeid``. +.. [#f5] Unique ``typeinfo`` records can only be generated for classes with at + least one noninline virtual function (i.e., the same algorithm that is + used to generate virtual function tables). diff --git a/doc/_sources/expr.rst.txt b/doc/_sources/expr.rst.txt new file mode 100644 index 0000000..36ef517 --- /dev/null +++ b/doc/_sources/expr.rst.txt @@ -0,0 +1,2262 @@ +=================== +Expression Scanning +=================== + + + + +``expr.c`` and ``expr.h`` contain the code and associated declarations to scan +expressions. ``exprutil.c`` and ``exprutil.h`` contain utilities related to +expression scanning, for processing other than the actual syntax analysis. +``overload.c`` and ``overload.h`` contain code to do overload resolution and +conversions. + +The expression routines function as an expression-scanning utility for the rest +of the front end. They provide a set of simple interface routines that are +called to scan various kinds of expressions: + +* | ``scan_integer_expression`` scans an integral expression, e.g., the + selector expression for a ``switch`` statement. +* | ``scan_void_expression`` scans a "void" expression, one whose value is + thrown away, e.g., an expression statement or the incrementing expression + in a ``for`` statement. +* | ``scan_default_arg_expr`` scans a default argument expression. +* | ``scan_template_argument_constant_expression`` scans a nontype argument of + a template reference. +* | ``scan_return_expression`` scans the expression in a ``return`` statement. +* | ``scan_case_label_constant`` scans a constant expression for a switch case. +* | ``scan_constant_dimension_expression`` scans a constant array bound. +* | ``scan_pp_expression`` scans a preprocessing expression, e.g., an + expression in an ``#if``. +* | ``scan_integral_constant_expression`` scans an integral constant + expression. +* | ``scan_constant_initializer_expression`` scans an initializer that is + required to be a constant. +* | ``scan_member_constant_initializer_expression`` scans an initializer for a + member constant (integral or enum) in C++. +* | ``scan_full_initializer_expr_as_component``\ scans an initializer that need + not be a constant. +* | ``scan_class_initializer_expression`` scans an initializer for a class. +* | ``scan_class_parenthesized_initializer`` scans a parenthesized initializer + for a class. +* | ``scan_boolean_controlling_expression`` scans a scalar expression that + controls a conditional statement (``if``, ``while``, ``do while``, and + ``for``). + +Each of these routines has roughly the same structure. ``scan_expr_full`` is +called to do the actual expression scanning. This produces a result of type +``an_operand``, which is checked for kind, converted to a required type (if +there is one), and then converted to the form required on return from the +interface routine, usually an expression node or a constant. + +Some other utility expression routines with a different type of interface: + +* | ``scan_ctor_arguments`` is called to scan a parenthesized list of + expressions that acts as the argument list for a constructor call, for + example + + .. code:: c++ + + struct A { + A(int, int); + }; + A aa(1, j+1); // scan_ctor_arguments is called + +* | ``try_to_convert_class_operand_to_builtin_type`` is called to convert an + expression of a class type to a builtin type, as when such an expression + appears as the conditional expression in an ``if`` statement or the like. +* | ``scan_braced_init_list`` scans a complete braced-enclosed initializer as + in the C++11 "initializer lists" feature. ``convert_initializer`` is used + to convert initializers, in particular brace-enclosed initializers, to the + type of the entity being initialized. +* | ``find_default_constructor`` finds a default constructor capable of + initializing an object of a given class type. +* | ``find_copy_constructor`` finds a copy constructor capable of copying an + object of a given class type with a given cv-qualification. +* | ``find_copy_assignment_operator`` is similar for an ``operator=`` function. + +``scan_expr_full`` +------------------ + +``scan_expr_full`` actually handles all expression scanning. It is called with +a set of option flags that configure its processing for various types of +expressions. It scans through the tokens of an expression, builds an +expression tree for the expression scanned, and returns an argument of type +``an_operand`` to describe the expression scanned. + +Its arguments are as follows: + +.. list-table:: + + * - | ``result`` + - | The result (of type ``an_operand``) of this level of expression + scanning. + * - | ``prec_level`` + - | The operator precedence level at which to terminate the scanning. + Expression scanning continues while the next operator precedence is + higher than this (or equal, with right-associative operators). + * - | ``expression_kind`` + - | The kind of expression that is expected: ``ek_pp`` for a preprocessing + expression, ``ek_integral_constant`` for an integral constant + expression, ``ek_init_constant`` for a constant initializer expression + (not used in C++, except for nontype template arguments and some C++11 + expressions), ``ek_normal`` for a normal expression, or ``ek_sizeof`` + for the operand of ``sizeof``. For the three constant expression + cases, some operators are restricted, some operand types are + restricted, and values of variables (etc.) may not be loaded. (See + the section on constant expressions.) + * - | ``local_options`` + - | A bit-set of option switches that apply to just this level of + expression scanning (i.e., they do not apply to subexpressions scanned + within this expression scan). The switches control whether the comma + operator is allowed, whether the expression is being scanned as the + immediate operand of a cast, etc. + +Note that typically ``scan_expr_full`` is called through the macro +``scan_expr``. + +Parsing Technique +----------------- + +``scan_expr_full`` scans an expression using a modified version of recursive +descent. The technique is "modified" in that it includes an operator +precedence level (higher precedences, numerically, bind more tightly). This +modification avoids the many levels of subroutine calls inherent in the +traditional recursive descent method. In the modified method, there is +approximately one subroutine call per leaf operand. Basically, +``scan_expr_full`` will scan an expression up to either something it does not +understand (presumably something that follows the end of the expression), or up +to an operator that has lower precedence than the level being scanned (or equal +precedence when left-associative). + +The precedence check is done by the routine ``token_ends_expr``. One special +case: when inside a template argument list, "``>``" is treated as the closing +bracket for the argument list rather than the "greater than" operator. + +For example, the expression ``1+2*3-4`` is parsed as follows: + +#. ``scan_expr_full`` is called with level 0. It takes the ``1``, then + looks at the operator ``+``. The current level (0) is less than the + level of ``+`` (12), so ``scan_expr_full`` takes the ``+`` and calls + itself with level 12. + +#. ``scan_expr_full`` (called with level 12) takes the ``2``, then looks at + the operator ``*``. The current level (12) is less than the level of + ``*`` (13), so ``scan_expr_full`` takes the ``*`` and calls itself + with level 13. + +#. ``scan_expr_full`` (called with level 13) takes the ``3``, then looks at + the operator ``-``. The current level (13) is greater than the level of + ``-`` (12), so ``scan_expr_full`` returns the constant expression for + ``3``. + +#. Back in ``scan_expr_full`` (level 12, step 2 above), ``2*3`` is + assembled (by computing the constant result). ``scan_expr_full`` then + looks at the operator ``-``. The current level (12) is equal to the + level of ``-``, and ``-`` is left-associative, so ``scan_expr_full`` + returns the constant expression for ``2*3`` (i.e., 6). + +#. Back in ``scan_expr_full`` (level 0, step 1), ``1+(2*3)`` is assembled + (by computing the constant result). ``scan_ \expr_full`` then looks at + the operator ``-``. The current level (0) is less than the level of + ``-`` (12), so ``scan_expr_full`` takes the ``-`` and calls itself with + level 12. + +#. ``scan_expr_full`` (called with level 12) takes the ``4``, then looks at + the next token of input, which is something unrecognized, and returns + the constant expression for ``4``. + +#. Back in ``scan_expr_full`` (level 0, step 5), ``(1+(2*3))-4`` is + assembled (by computing the constant result). ``scan_expr_full`` then + looks at the next token of input, which is something unrecognized, and + returns the constant expression for ``(1+(2*3))-4`` (i.e., 3). + +``scan_expr_full`` Processing +----------------------------- + +The processing within ``scan_expr_full`` is only slightly more complicated than +the description above. There are two major sections: In the first, a leaf +operand (identifier or constant), a prefix operator followed by an expression, +or an expression in parentheses (or a cast) is scanned. In the second section, +there is a loop with the above-described precedence level test at the top. So +long as the next thing in the input (whether it is a postfix operator, +subscript, function argument list, or binary operator) has an appropriate +precedence, it will be taken and added to the current expression. The loop +stops on the first thing that is not recognized or has a lower precedence. A +loop is required for expressions containing equal-precedence left-associative +operators, like ``1+2*3*4+5``: the ``*3`` and ``*4`` would be accumulated on +successive iterations of the loop in one call of ``scan_expr_full``. + +.. _scanning-idents: + +Scanning Identifiers +-------------------- + +When ``scan_expr_full`` scans an identifier, it calls ``scan_identifier``, +which builds an operand for identifiers for enumeration constants, variables, +functions, etc. Odd C++ "names" like ``operator+`` are also handled by +``scan_identifier``. The appropriate routines are called to turn them into +pseudo-identifier tokens, and thereafter the handling is the same as for other +names. + +In constant expressions, variables are only allowed if they can legitimately be +part of a constant expression. + +For undefined identifiers in C mode, ``scan_identifier`` enters the identifier +as an undefined identifier; shortly, the identifier will turn out to be either +truly undefined (in which case an error is generated) or will turn out to be +the name of an implicitly-declared function (in which case +``decl_default_function`` in ``decls.c`` will be called to declare it as such). + +In C++, nonstatic data members and nonstatic member functions are processed as +if preceded by "``this->``" (see ``make_this_pointer_operand``). If the +identifier is a type identifier and it is followed by a left parenthesis, +``scan_functional_notation_type_conversion`` is called to scan a type cast. + +Also in C++, special considerations are made for uses of identifiers in local +classes (which can only use entities from the enclosing function in very +limited ways) and in local lambdas (which have similarities to local classes, +with the added wrinkle that references to enclosing local variables must be +interpreted as uses of fields of the associated closure class, and these fields +may have to be created as a result of these references). See +``bad_nested_function_variable_ref`` and +``make_selection_for_captured_variable``. + +Scanning Constants +------------------ + +When ``scan_expr_full`` scans a constant, it calls ``make_constant_operand`` to +build the appropriate operand. Floating constants are allowed in integral +constant expressions only as the immediate operand of a cast (see +``local_options``, above). For string literals, +``make_string_constant_operand`` is called instead. It produces an lvalue for +the array of characters; except in unusual cases (e.g., when the string is used +to initialize a character array), this is changed to a pointer to the string +(by ``conv_array_operand_to_pointer_operand``). + +.. _scanning-operations: + +Scanning Operations +------------------- + +Processing for operators is done by lower-level routines. The routines are +called when the operator token has been scanned, so for non-unary operators, +this means after the left operand expression has been scanned. Most of these +routines have a structure similar to the following, which describes a generic +binary operation routine: + +* | A check is made to see if the operator is allowed in the present type of + expression (some operators, for example, are disallowed in some kinds of + constant expressions). +* | The right operand is scanned by calling ``scan_expr_full`` with appropriate + switches. +* | In C++ mode if either of the operands has a class type, + ``check_for_operator_overloading`` is called to see if operator overloading + applies. If it does, an appropriate operator function call is generated. + If not, the remaining steps are done. +* | The left operand (passed in) is converted from a glvalue to a prvalue. In + cases where the left operand is supposed to be an lvalue, that is checked, + and ``using_lvalue`` or ``modifying_lvalue`` (depending on how the lvalue + is used) is called. +* | The type of the left operand is checked. +* | The right operand is converted from a glvalue to a prvalue. +* | The type of the right operand is checked. +* | The types of the operands are checked to see if they are compatible with + one another and with the operation. This sometimes selects a subcase of + the operation (e.g., pointer addition instead of integer addition). + + * | For arithmetic operations, ``determine_arithmetic_conversions`` is called + to determine the usual arithmetic conversions and + ``change_binary_operand_types`` is called to promote the operand types as + necessary. + * | For pointer operands, ``check_compatibility_of_pointer_operands`` is + called to check the operand types and do implicit type changes. + * | For pointers to members, + ``check_ptr_to_member_operands_for_compatibility`` is called to do a + similar check. +* | ``which_binary_operator`` is called to select the proper intermediate + language operator for the operation on this type of operands. +* | ``do_binary_operation`` is called to produce the result operand, either by + folding an operation on constants (by calling ``binary_operation`` in + ``folding.c``, but not when not-evaluated), or by building an expression + tree. +* | The start position of the expression is recorded in the result operand. + +The prefix ``++`` and ``--`` operators are scanned by +``scan_prefix_incr_decr``. + +The unary operator ``&`` is scanned by ``scan_ampersand_operator``. It usually +calls ``take_address_of_lvalue`` to produce the prvalue address result. In +``pcc`` mode, it issues a warning for taking the address of an array, and calls +``conv_array_operand_to_pointer_operand`` to produce address-of-array-element +instead of the ANSI address-of-array. If the operand is the qualified name of +a class member, a pointer-to-member constant is created. In C++/CLI, ``&`` +applied to an lvalue that might be on the CLR heap (as determined by +``is_gc_lvalue_expr``) produces an ``interior_ptr`` result. + +The C++/CLI unary operator ``%`` is scanned by +``scan_handle_address_operator``. It produces an ``eok_handle_to`` or +``eok_box`` operator. The result is a handle. + +The unary operator ``*`` is scanned by ``scan_indirection_operator``, producing +an lvalue or function designator as a result. + +``scan_arith_prefix_operator`` is called to scan the prefix operators ``+``, +``-``, ``~``, and ``!``. The unary version of the code in +``do_binary_operation`` (fold if constant by calling ``unary_operation`` in +``folding.c``, else build expression node) is included directly here, since +these are all of the normal unary operators. + +The ``sizeof`` operator is scanned by ``scan_sizeof_operator``, which calls +``is_decl_not_expr`` to decide whether or not the argument is a type name. If +it is, ``type_name`` is called to scan the type. If the argument is not a +type, it is scanned as a not-evaluated expression. The size of the type is +taken from the type entry in either case. + +``scan_alignof_operator`` is used to scan the ``__ALIGNOF__`` construct (an +extension; similar to ``sizeof``, but returns the alignment for a type instead +of its size). + +``scan_intaddr_operator`` is used to scan the ``__INTADDR__`` construct (used +in the ``offsetof`` macro to scan an address expression and cast it to integral +type). + +``scan_noexcept_operator`` scans the C++11 ``noexcept`` operator. + +``scan_typeid`` scans the ``typeid`` operator. It produces an expression node +of kind ``enk_typeid``. + +``scan_dynamic_cast_operator`` scans the ``dynamic_cast`` operator. Cases that +require runtime type determination are rendered as ``eok_dynamic_cast`` +expression nodes (or ``eok_ref_dynamic_cast``, for casts to reference types); +the other cases are turned into ordinary casts. + +``scan_static_cast_operator`` scans ``static_cast``. + +``scan_safe_cast_operator`` scans the C++/CLI ``safe_cast``. It's essentially +the same as ``static_cast`` except that it allows additional runtime-checked +cases, which are found by ``process_runtime_checked_safe_cast``. + +``scan_reinterpret_cast_operator`` scans ``reinterpret_cast``. + +``scan_const_cast_operator`` scans ``const_cast``. + +``scan_new_operator`` is used to scan the ``new`` operator. The ``new`` +operation is rendered as an ``enk_new_delete`` operator tagged as a "new", +whose supplement describes the operator ``new`` function to call plus +(optionally) some kind of initialization of the space allocated (for example, a +constructor call). For the C++/CLI ``gcnew``, an ``enk_gcnew`` is used, and +the supplement for that includes additional information, including an +initializer. For a ``gcnew`` of a C++/CLI array, the supplement contains both +information about the array bounds (either as explicitly provided, or deduced +from the number of elements in the initializer), and an aggregate initializer +for the array elements (the latter is scanned by ``scan_cli_array_init``). For +delegate initializers, ``scan_delegate_initializer`` scans the initializer, +which requires hand-coded checking because the delegate class doesn't have +constructors that accurately cover the allowed initializers. + +``scan_delete_operator`` is used to scan the ``delete`` operator. The +``delete`` operation is rendered as an ``enk_new_delete`` operator tagged as a +"delete", whose supplement describes the operator ``delete`` function to call +plus (optionally) a destructor to call on the space being deallocated. + +A left parenthesis can indicate a cast, a nested expression, or a C++17 fold +expression. ``scan_cast_or_expr`` is called for all cases. It uses +``is_decl_not_expr`` to decide whether or not the thing following the left +parenthesis is a type name. If it is, ``type_name`` is called to scan the +type, ``cast_type_pre_check`` to check the legality of the type, and +``do_cast`` to check and process the cast. For casts to void, an explicit +cast-to-void expression node is placed on top of the expression, as a special +marker for ``simplify_void_operand``, but no simplification is done at this +point. In ``pcc`` mode, certain casts of lvalues leave an lvalue as the result +(see ``still_an_lvalue``). If what is inside the parentheses is not a type, +``scan_expr_full`` is called to scan a nested expression or the first term of a +fold expression. If it turns out to be a fold expression (or the left +parenthesis was followed by an ellipsis, which also implies a fold expression), +``scan_fold_expression`` is called to scan the fold expression in either +generic form (during the prototype instantiation of the enclosing template) or +expanded form (during real instantiations). + +The postfix ``++`` and ``--`` operators are scanned by +``scan_postfix_incr_decr``. + +Subscripting is scanned by ``scan_subscript_operator``. The subscript is +represented by an ``eok_subscript`` operator. Constant subscripts are checked +for legality by ``valid_node_if_subscript`` or by the constant-folding +routines. When the first operand is a C++/CLI array, the contents of the ``[`` +... ``]`` are scanned as an expression list (no top-level comma operator is +allowed), and an ``eok_cli_subscript`` operator is used. Default indexed +properties, indexed properties, and ``operator[]`` functions can all be used to +implement the subscripting operation. Property rewrites are considered both +for the entire subscripted operation and for the first operand if it can be +converted to something subscriptable. + +Function calls are scanned by ``scan_function_call``. The function name is +entered as a default function if it is undefined (in C89 mode). The argument +list is scanned, and each argument is cast or default-promoted (see +``prep_argument_operand`` and ``arg_default_promote_operand``) appropriately. +The arguments are checked against the applicable function prototype or, if the +called function has an old-style declaration with a body, against the declared +old-style parameters. If the called function was declared with the pragma +``__printf_args`` or the pragma ``__scanf_args``, and the format string is a +constant, ``check_printf_scanf_arg`` is called for each argument following the +format string. It checks that the type of the argument matches the type of the +corresponding formatting specifier, and issues a warning if not. +``assemble_function_call`` and ``make_function_call`` are called to put +together the actual function call. If the function is a virtual function, a +different expression operator is used; the virtual call is suppressed if the +function was named with a qualified name or if the proper function to call can +be determined statically. If the function is an overloaded function, +``scan_call_arguments`` just builds a list of entries of type +``an_arg_list_elem`` that describe the arguments scanned. No checking can be +done on them until the specific function to be called is identified in overload +resolution. + +The operators ``->`` and ``.`` are scanned by +``scan_field_selection_operator``. After the right operand (a member name) is +scanned, the processing breaks apart into several cases: + +* | For nonstatic data members (C fields), ``do_field_selection_operation`` is + called; it in turn calls ``fold_field_selection`` to fold field selection + relative to a constant address to produce another constant address. The + expression operator generated is ``eok_dot_field`` or + ``eok_points_to_field``. +* | For nonstatic member functions, ``do_member_function_selection`` is called. + It produces an operand for a bound function, i.e., a function bound to a + selector object. +* | For static data members and static member functions, + ``combine_unneeded_selector_with_operand`` is called, and it generates an + ``eok_dot_static`` or ``eok_points_to_static`` operation. + +For nonstatic members, ``cast_pointer_for_field_selection`` is called to cast +the left operand pointer to a base class if necessary. + +The operators ``->*`` and ``.*`` are scanned by +``scan_ptr_to_member_operator``. For member function cases, the result is a +bound member function. For data member cases, an ``eok_pm_field or +eok_pm_points_to_field`` operation is generated. + +The operators ``*``, ``/``, and ``%`` are scanned by ``scan_mult_operator``. + +The operators ``+`` and ``-`` are scanned by ``scan_add_operator``. + +The operators ``>>`` and ``<<`` are scanned by ``scan_shift_operator``. + +The operators ``>``, ``<``, ``<=``, and ``>=`` are scanned by +``scan_rel_operator``, and the operators ``==`` and ``!=`` are scanned by +``scan_eq_operator``. + +The operators ``&``, ``^``, and ``|`` are scanned by ``scan_bit_operator``. + +The operators ``&&`` and ``||`` are scanned by ``scan_logical_operator``, and +the operator ``?`` (and the associated ``:``) is scanned by +``scan_conditional_operator``. When these operators have constant operands for +the boolean controlling expressions, some operands will be scanned as +not-evaluated expressions, and the result tree is (conditionally) simplified +accordingly. + +The operator "``,``" is scanned by ``scan_comma_operator``. Note that the +comma operator is not allowed at the top level in initializer expressions and +in argument lists, because it means something else in those contexts; see the +``local_options`` parameter of ``scan_expr_full``. + +``scan_simple_assignment_operator`` scans the operator ``=``. It calls +``prep_assignment_operand`` to check and convert the right operand in most +cases. Assignment to "``this``" is recognized as a special case and +allowed with a warning. + +``scan_compound_assignment_operator`` scans compound assignment operators +(``+=``, ``-=``, et al.). + +Lambda expressions are scanned by ``scan_lambda_expression``. The actual +parsing is handed to ``scan_lambda`` in ``class_decl.c``, and +``scan_lambda_expression`` constructs the required temporary initialization +from the resulting ``a_lambda`` entry. (See also :ref:`scanning-idents` for +special measures needed when parsing identifiers in a lambda body.) + +.. _expr-operands: + +Operand Data Structure +---------------------- + +Throughout the expression routines (and nowhere else), all the information +about an operand is maintained in an entry called ``an_operand``. The operand +contains the type of the operand, its "kind" (indicating the way in which the +operand is represented, i.e., as a constant or an expression tree), its "state" +(none, glvalue, prvalue, or function designator), and its source position. +Variables of type ``an_operand`` are typically stack-based variables within the +expression routines. They are never allocated in the intermediate language +memory region. + +An *lvalue* is an object in memory; an *rvalue* is a value, with no associated +memory location. The distinction between lvalues and rvalues is very important +in the C language. [#f1]_ Names of variables start out as lvalues, and if +their values are used, they are implicitly converted to rvalues. C++11 adds +*xvalues*, which are eXpiring values produced by certain rvalue reference +operations. They share an operand state with lvalues, since the two are very +similar (they have addresses, possibly cv-qualified types, dynamic type, object +identity). They can be distinguished with the ``is_an_lvalue()`` and +``is_an_xvalue()`` tests. Lvalues and xvalues are collectively known as +*glvalues*. The things formerly known as rvalues in C and in pre-C++11 C++ are +now known in C++11 as *prvalues*, and prvalues and xvalues collectively are now +known as rvalues. + +The expression scanning routines attempt to model the C++11 concept of "value +categories" exactly, and the ``an_operand`` entry plays a part in that. [#f2]_ +It is always clear from the operand whether an expression is currently an +lvalue, xvalue, or prvalue, and the transformation from glvalue to prvalue is +done deliberately and when appropriate (see ``conv_glvalue_to_prvalue``). + +For functions, the equivalent of an lvalue is a *function designator*, and +there is a representation for those in ``an_operand``. + +In the C++ language definition, the term "lvalue" includes C's function +designator as well as C's lvalue, but in this implementation and this +documentation we use the term with the narrower C meaning. + +When the operand representation is an expression, the operand points to an +expression tree in an intermediate language memory region. When the operand +representation is a constant, however, the constant is contained directly in +the operand (it is not allocated). This allows the expression routines to scan +constant expressions and fold them to constant results without allocating and +throwing away useless intermediate constant entries. + +When an operand represents a bound function, that is, a C++ member function +with an associated object, the operand has the ``bound_function`` flag set. A +second operand is used to describe the associated object. There's no direct +link between the two; the expression routines must carry around two operand +entries. + +When expressions appear in a comma-separated list, such as an argument list, +the operands on the list are often represented as entries of type +``an_arg_list_elem``. Such entries can represent either an expression (in +``an_operand`` form), or a brace-enclosed list, the latter being needed for the +C++11 "initializer lists" feature. + +The C++/CLI ECMA standard mentions the concept of a "gc-lvalue," and defines +conversions between normal lvalues and gc-lvalues. It turns out those concepts +are not needed, at least not in the suggested way, and no added kind of lvalue +is needed in ``an_operand`` entries. The important principle is that the +language must never allow the address of something that might be on the CLR +heap to be placed in a normal pointer where the garbage collector cannot find +it. So, whenever the address of something that might be in the CLR heap is +taken, the address must be placed in an ``interior_ptr`` or a ``pin_ptr``, both +which are visible to the garbage collector. The functions +``is_gc_lvalue_expr`` and ``is_gc_lvalue_operand`` test for lvalues that might +be in the CLR heap; if they return TRUE, the address of such an entity is made +an ``interior_ptr``. + +Primitive Operations on Operands +-------------------------------- + +Many routines exist to do primitive operations on operands. Routines that +perform initialization are + +* | ``set_operand_kind`` and +* | ``clear_operand``. + +Constructors for the various kinds of operands are + +* | ``make_constant_operand``, +* | ``make_string_constant_operand``, +* | ``make_integer_constant_operand``, +* | ``make_expression_operand``, +* | ``make_glvalue_expression_operand``, +* | ``make_indefinite_function_operand``, +* | ``make_sym_for_ptr_to_member_operand``, +* | ``make_lvalue_variable_operand``, +* | ``make_ptr_to_member_constant_operand``, +* | ``make_function_designator_operand``, and +* | ``make_field_operand``. + +Routines that create operands for one- and two-operand expressions are + +* | ``build_unary_result_operand`` and +* | ``build_binary_result_operand``. + +Error operands are created for parts of expressions containing errors by + +* | ``make_error_operand``, +* | ``conv_to_error_operand``, +* | ``error_in_operand``, and +* | ``error_and_make_error_operand``, + +which differ in whether or not they issue errors, and where. +``make_node_from_operand`` converts an operand to an equivalent expression +tree. + +Checking Operands +----------------- + +``op_is_zero_constant`` tests for a zero operand. There is also a set of +``check_...`` routines, which are called to verify that an operand has certain +attributes, and if not, issue an error and change the operand to an error +operand: + +* | ``check_modifiable_lvalue_operand``, +* | ``check_integral_operand``, +* | ``check_integral_or_enum_operand``, +* | ``check_integral_or_enum_or_fixed_point_operand``, +* | ``check_arithmetic_operand``, +* | ``check_pointer_operand``, +* | ``check_object_pointer_operand``, +* | ``check_function_pointer_operand``, +* | ``check_scalar_operand``. + +``check_boolean_controlling_expression`` checks that an expression controlling +a conditional is a scalar expression, and in C++ modes that don't disable the +``bool`` keyword, it converts the expression to ``bool``. + +Transformations on Operands +--------------------------- + +Several routines handle transformations on expressions defined by the standard: + +* | ``conv_glvalue_to_prvalue`` changes a glvalue to a prvalue. Several + special cases are handled. Type qualifiers on the glvalue type are removed + to make the prvalue type. Most of the work for expression cases is handled + by ``conv_glvalue_expr_to_prvalue``. ``conv_glvalue_to_prvalue`` calls + ``using_lvalue`` to do the error check for using the element just past the + end of an array; it also generates an error if it is called to convert a + glvalue in a constant expression. +* | ``conv_array_operand_to_pointer_operand`` changes an array to a pointer to + the first element of the array. +* | ``conv_function_designator_to_ptr_to_function`` changes a function + designator to a pointer to the function. + +``do_operand_transformations`` is a convenient way to request the preceding +three transformations. It can do any or all of them. + +Note that in C++ operand transformations often cannot be done until one knows +the way in which an expression will be used. In an expression like ``arr + +xx``, for example, with ``arr`` an array, one cannot convert the array to a +pointer until one has ruled out the possibility that this operation is an +overloaded use of operator "``+``" with a function for which the first +parameter is a reference to an array. In C, the transformations can often be +done earlier, but for ease of handling they are delayed as in C++. + +* | ``promote_operand`` handles the integral promotions (C standard, 6.3.1.1); + these are done only where explicitly called for. +* | ``determine_arithmetic_conversions`` handles the usual arithmetic + conversions (C standard, 6.3.1.8). In ``pcc`` mode, the promotions are + unsigned preserving (e.g., ``unsigned char`` is promoted to ``unsigned + int``), and all ``float`` operations are forced to ``double``. To + determine integral promotion types ``type_after_integral_promotions`` (in + ``types.c``) is called; a special case involving bit-fields is handled by + ``type_after_bit_field_integral_promotion``. +* | ``arg_default_promote_operand`` does the default argument promotions on an + operand (C standard, 6.5.2.2). +* | ``take_address_of_lvalue`` converts an lvalue to a prvalue pointer to the + object. This is the ``&`` operator for objects. It checks for taking the + address of a bit field or a register variable. + ``take_reference_to_operand`` does the similar operation for a reference + binding. + +When fixed-point types (an Embedded C extension described in ISO/IEC TR 18037) +are enabled, transformations of fixed-point operands are also performed as +needed. For example, in arithmetic operations involving both a fixed-point and +a floating-point operand the fixed-point operand is converted to a +floating-point type. However, unlike most other mixed-type operations, +operations involving a mix of fixed-point and integer operands do not cause the +conversion of the operands to a common type. + +The Expression Stack +-------------------- + +While expressions are being scanned, the expression routines maintain an +expression stack. This stack snakes through local stack frames (i.e., it is +not allocated via ``malloc``). The expression stack contains information on +the kind of expression being scanned, whether or not the expression is being +evaluated (e.g., the operand of a ``sizeof`` is not evaluated), and some other +minor information. + +There is a new stack entry for each major kind of expression scanned, but not +for each level in the expression. That is, if one started on a normal +expression, an entry would be placed on the stack; no new entries would be +added for parentheses or grouped operators in the expression; but if a sizeof +expression, or an integral constant expression in an array size in a type in a +cast, is reached, a new entry would be placed on the top of the stack. + +See ``push_expr_stack`` and ``pop_expr_stack``. + +Expression Lists and Initializer Lists +-------------------------------------- + +The C++ language, as of the C++11 revision, uses lists of expressions in two +contexts: + +* | argument lists of function calls (syntax term *expression-list*), for + example "``f(x, 2)``", and +* | initializer lists (syntax term *initializer-list*), for example + initializers of variables as in "``A a{x, 2};``". + +Those contexts at first glance might seem to have little in common other than +the fact that they involve lists of expressions. However, the standard ties +the use of variadic template pack expansions and the use of brace-enclosed +initializer lists to those expression-list contexts, and in some cases +initializer lists become argument lists for constructor calls. So, in the end, +it becomes appropriate and desirable to represent both kinds of expression +lists with the same data structure and to process them with many of the same +routines. + +The data structure used is ``an_init_component``, which can represent + +* | an expression, e.g., "``x``", in ``an_operand`` form, or +* | a braced-enclosed list, e.g., "``{1, 2, 3}``", as a pointer to a list of + init-component entries, or +* | a designator, e.g., an array element designation like "``[1]=``" in an + aggregate initializer, or +* | a continuation state to resume parsing when parsing of an initializer list + was suspended (see below). + +In initializer processing, e.g., in ``decl_inits.c`` and expression routines +that interface with that, the name ``an_init_component`` is used. In routines +that are more related to argument lists and overload resolution, on the other +hand, the name ``an_arg_list_elem`` is used instead. It's a typedef to the +same type, but it reflects a slightly different view of what the structure +represents. In practice, the line between the two is a bit fuzzy, and +especially with some lower-level routines the naming has to choose one or the +other name and is therefore somewhat arbitrary. Probably the main thing to +remember is that both names are used for the same data structure, with the +expression routines using the ``an_arg_list_elem`` name somewhat more often, +and the initializer routines using ``an_init_component`` exclusively. About +the only real difference that can be pointed out is that an argument list +referred to via ``an_arg_list_elem`` will never have a designator on the list. + +Init-component entries are linked together into lists and trees. Something +like "``{1, {2, 3, 4}}``", for example, creates a braced-init-list component +pointing to a list of two entries, the second of which is a braced-init-list +component pointing to a list of three expression components. + +The essence of the initializer lists feature in the language is that the same +notation can be used for initializations that are ultimately interpreted in +many different ways. Therefore, the handling of initializer lists inherently +involves a two-step process: first, parsing the source into a tree of +init-component entries, and then interpreting those entries by context as +describing calls and initializations of various kinds. At the simplest level, +the initializer processing calls ``scan_braced_init_list`` first to scan an +entire braced-init-list, and then ``convert_initializer`` to convert it to the +type of the entity being initialized. The real work in scanning +braced-init-lists is done by ``parse_braced_init_list_full`` and its +subroutines. + +In some cases the front end will process a very long braced initializer list in +parts to avoid tying up too much memory in init-component entries (which are +transient front end structures). It does this by suspending and resuming the +parsing of the initializer (repeatedly if needed) and using placeholder +init-component entries (of kind ``ick_continued``) that point to some state +information sufficient to resume parsing later on. This is fairly transparent +to the routines processing init-component entries, but requires that those +routines use macros like ``next_elem`` and ``is_last_elem`` rather than +directly access the ``next`` pointers of init-component entries. This is only +possible for traditional aggregate initializers, but it is a worthwhile +optimization because occasionally programs contain initializers with thousands +or even millions of elements. + +So some expression routines deal with an init-component (or list or tree of +them) as the "source" for an initialization. And some routines will scan an +expression or braced-init-list in init-component form to do lookahead, and then +place the init-component entry in an *initializer cache*, later to be fetched +out of there as if it had been freshly scanned from source. That's used, for +example, for declarations with "``auto``" type; an expression is scanned so its +type can be used for the ``auto`` type deduction, and the expression is then +put into the initializer cache so it will be picked up at the appropriate time +later. + +Because expression components are scanned at one point and then revisited later +for processing, some of the context information for them must be saved along +with the init-component entries. In particular, because it's not known at the +time of scan where the full-expression boundaries will fall, each expression is +scanned in its own invented lifetime, and is "bundled" with that lifetime in +the init-component. When the expression is removed from the list later for +additional processing, the lifetime is reactivated or subsumed into an existing +lifetime. Likewise, the cross reference entries associated with an expression +are detached from the current expression and saved in the init-component, and +then reactivated when the expression is processed further. This allows things +like tracking of whether a variable is ultimately used as an lvalue or rvalue. +(See ``scan_expr_as_init_component`` for the bundling code, and +``extract_operand_from_expression_component`` and +``unbundle_init_component_expressions`` for the unbundling.) + +The processing when a braced-init-list meets a destination type is handled by +``convert_initializer`` (callable from outside the expression routines) and +``prep_list_initializer`` (callable only from within the expression routines). +The latter does the real work. It has some significant subroutines: + +* | ``make_initializer_list_object`` makes an object of type + ``std::initializer_list`` from a braced-init-list, which involves a call + to a constructor of ``initializer_list`` passing an array containing the + element values. +* | ``value_initialization`` handles value-initialization, which is usually the + result when the braced-init-list is an empty list, "``{}``". +* | ``check_narrowing_conversion`` checks for the "narrowing" conversions, + issuing appropriate diagnostics. + +``prep_list_initializer`` operates in one of three modes: + +#. Producing ``an_operand result``. This is the usual mode for internal calls + in the expression routines. + +#. Guided by ``an_init_state``, producing either a dynamic init entry or a + constant as a result. This is the usual mode for calls that come from + initializer processing by way of ``convert_initializer``. This mode can + be modified to produce no diagnostics or generate no IL, which is used + for SFINAE analysis. + +#. Doing overload resolution analysis, producing a result in an entry of + type ``an_arg_match_summary``. That is used when evaluating arguments in + overload resolution, and in that mode no errors are issued, no IL is + generated, and the source init-components are not modified (in other + words, it's purely exploratory). + +All processing for aggregates, i.e., arrays and aggregate classes, is done by +code in ``decl_inits.c``. ``prep_list_initializer`` calls +``prep_aggr_initializer`` to handle aggregate initialization from a +braced-init-list, and the initializer processing routines will call back into +the expression routines as necessary. In certain cases, processing will hop +back and forth between the two areas repeatedly. In those cases, the +``an_init_state`` structure is used to convey information across the +transitions, e.g., to record something that expression processing knows so that +as the transfer or control goes to the ``decl_inits.c`` routines and back into +expression processing that information is still known. + +The expression routines have to be quite careful about whether they are dealing +with a single expression or (a member of) an expression list, and that is made +easier by using different structures to represent those, i.e., ``an_operand`` +for a single expression, and ``an_arg_list_elem`` for (a member of) an +expression list. There are some rare cases in the C++11 language where a +brace-enclosed list is allowed in a context where a single expression is +allowed, and in those cases ``an_operand`` of kind ``ok_braced_init_list`` is +constructed, which points to an init-component list. That allows a lot of the +existing routines to accept a braced-init-list in some limited cases. To give +one example, the assignment operators allow a braced-init-list as their second +operand, even though that's not an expression list context. So, if a +braced-init-list is present, it is scanned as an operand (see +``scan_braced_init_list_as_operand``) and passed around in that form to the +usual routines. When it gets to the operator-overloading routine +``check_for_operator_overloading``, that routine is prepared to unpack that +operand and use the braced-init-list in overload resolution. There are also +some cases when rescanning expressions (see below) where a braced-init-list +operand is constructed so that a braced-init-list can be returned through an +interface that is designed for single operand expressions. + +The ``an_arg_operand`` data structure, which in the past was used for operands +in argument lists, is now reserved for a few cases where a single +non-expression-list expression needs to be returned to a caller outside the +expression routines, specifically for nontype template arguments values. + +In most cases, there is no direct IL representation for initializer lists, +because when a braced-init-list meets a destination type it is converted to +some expression form that is no longer a braced-init-list. (For example, it +might become a dynamic init for a constructor call, or a nonconstant aggregate +dynamic init.) However, in prototype instantiations of templates there may be +braced-init-lists that have not met a real destination type and therefore +cannot be interpreted yet, and those must remain in braced-init-list form. For +those, the ``enk_braced_init_list`` expression node kind is used. It points to +a list of expressions, some of which may themselves be ``enk_braced_init_list`` +nodes. + +Constant Expressions +-------------------- + +Constant expression processing has two fairly different modes: + +#. In C mode, and in C++ mode prior to C++11, each constituent of an + expression is checked immediately to see whether it is allowed in a + constant expression. An error is issued if not. So, for example, the + appearance of a ``throw`` operator in a constant expression draws an + immediate error. Class-typed values are never allowed, and neither are + user-defined conversions. This mode is referred to as the "traditional + constant expression" mode (see, for example, + ``curr_expr_kind_is_traditional_const``). + +#. In C++11 (roughly, when ``constexpr_enabled`` is TRUE), what matters is + whether the expression overall folds to a constant, regardless of the + constituents of the expression. So, for example, "``1 ? 2 : i``" is a + valid C++11 constant expression: the reference to "``i``" is not + evaluated and does not rule out a constant expression. Class-typed + constant values (of "literal" type) are allowed, and so are user-defined + conversions using ``constexpr`` functions. This mode is referred to as + the constexpr mode. (A variation of that mode, known as "relaxed + ``constexpr`` mode", is enabled in C++14 mode. See also + :ref:`constexpr-and-expr-folding`.) + +In both modes, references to constant-valued variables and operations on +constant operands are folded as soon as they can be, [#f3]_ and a constant +value is passed up to the next level, so the basic processing is very much the +same. The main differences are: + +* | In traditional constant expressions, many operator-scan routines check + immediately on entry whether the operator they handle is valid, and issue + an error if not. In C++11 constant expressions, the check is done by + calling ``operator_not_allowed_in_cpp11_constant_expr`` (or + ``construct_not_allowed_in_cpp11_constant_expr``), which issues no error in + unevaluated parts of expressions. +* | Various routines that handle looking for user-defined conversions (e.g., + ``check_user_defined_conversions_for_cast``) allow user-defined conversions + when ``constexpr_enabled`` is TRUE. +* | Calls, including constructor calls, can be folded to constants. This is + done by first building the normal IL for the call and then, if the function + or constructor involved is ``constexpr``, seeing whether the call can be + folded to a constant. This is done by ``expr_fold_constexpr_call`` and + ``expr_fold_constexpr_ctor``. Implicit calls, like conversion function + calls, can also be folded to constants. If backing expressions are being + recorded, the original IL for the call is recorded as the backing + expression for the result constant. +* | Both modes require tracking, in non-constant expressions, of whether the + expression makes use of anything not allowed in a constant expression. + [#f4]_ In traditional constant expressions, the kinds of expressions ruled + out are tracked at the ``an_operand`` level (see the + ``ruled_out_expr_kinds`` set and the ``rule_out_expr_kinds`` routine), and + for specific kinds of constant expressions (e.g., integral constant + expressions). In C++11 constant expressions, a single boolean flag called + ``constant_expr_ruled_out`` is maintained in the expression stack, and + there's effectively only one kind of constant expression. (Note, however, + that in C++11 mode some kinds of expressions are scanned as traditional + constant expressions, e.g., preprocessor expressions and nontype template + argument address expressions, because the C++11 language rules still impose + many restrictions on the kinds of operators that can be used in them.) + | In certain contexts, the rules about what is ruled out are relaxed + slightly. Specifically, in contexts that will later be subject to + parameter substitution in ``constexpr`` call evaluation, a use of the value + of a parameter variable does not rule the expression out as a potential + constant expression (because in a real evaluation, the parameter might have + a constant value). Those contexts (the return expression of a + ``constexpr`` function, the mem-initializers of a ``constexpr`` + constructor, and the field initializers of a literal class) are identified + by ``in_potential_constant_constexpr_context``. + | When init-components are used, expression processing is often done in two + steps: first, the expression is scanned into an init-component, and then + the init-component is converted to the final required type. In those + cases, the ``constant_expr_ruled_out`` flag is copied from the expression + stack into the init-component, and then back from the init-component to the + expression stack when the conversion processing is started. +* | In several contexts, the C++11 standard calls for a "converted constant + expression" of a given type (for example, an array bound is a converted + constant expression of type ``size_t``). This is implemented by + ``process_converted_constant_expression``. The required type can be a + specific type, like ``size_t``, or a general category of types, like + integral types. In traditional constant expressions, that routine just + scans a constant expression and converts it as necessary, not allowing + user-defined conversions. In C++11 mode, it allows user-defined + conversions but imposes a restriction on the types of implicit conversions + allowed at the end (e.g., not "narrowing" conversions). The C++11 rules + are therefore broader overall but more restrictive in certain cases. The + set of allowed implicit conversions is defined by + ``impl_converted_constant_expr_conversion_possible``. +* | ``constexpr`` calls and constructions in constant expressions produce a + constant result directly, i.e., not a temporary initialized by a constant, + but other temporaries (e.g., a temporary needed to bind "``const int &``" + to an integer constant ``2``) are created as usual. Processing within + folding fetches the value out of the temporary if appropriate, or creates a + special compile-time temporary using a ``ck_address/abk_temporary`` + constant that holds the necessary constant value. Operations that cannot + be converted to those forms are left as initialization of a temporary, + which is considered non-constant. + +.. _rescanning-exprs: + +Rescanning Expressions +---------------------- + +The C++11 standard introduced some new rules for template deduction (see +`WG21 paper N2634 +`__). +When a function template is considered in overload resolution, part of the +process is "template deduction," which is an attempt to find values for the +template parameters of that template that will specify a template instance +that is a viable function for the call. The deduction rules require that +any expressions that appear in the template type be valid after +substitution of the deduced template arguments for the template parameters. +Whereas in older versions of the standard "valid" was defined by a specific +list of requirements, and only relatively simple expressions were allowed, +the C++11 rules now allow arbitrarily complex expressions inside +unevaluated contexts (e.g., ``sizeof`` and ``decltype``), and "valid" is +defined by the normal semantic rules of the language, except that access +checking is not done. So, for example: + +.. code:: c++ + + template auto f(T p1, T p2) -> decltype(p1 + p2) { + return p1 + p2; + }; + struct A { + const A & operator +(const A&); + }; + A a1, a2; + int main() { + f(a1, a2); + } + +Here, the call is valid only if the expression "``p1+p2``" is valid, which is +true only if there is a valid meaning for the "``+``" operator, possibly found +by doing overload resolution as in this case. Any error detected during this +process should cause only a failure of deduction for that template, and not a +hard error. (This idea is summarized in the acronym that is often used to +refer to this non-error-producing deduction process, SFINAE, which stands for +Substitution Failure Is Not An Error.) + +To implement this, the Front End is capable of "rescanning" expressions to redo +the semantic checking on them. An expression saved during the initial scan of +a template is copied, with substitution of template argument values for +template parameters, and is then passed through the normal +expression-processing routines in order to do everything that would have been +done to that expression after scanning it from source tokens. A key part of +the infrastructure for performing that is that almost all operator-scanning +routines have an ``rcblock`` parameter, which can be used to pass in a rescan +control block. When that parameter is non-NULL, it gives information about the +expression to be rescanned, the template arguments and template parameters, and +some options. The operator scan function tests ``rcblock`` each time it is +about to get something from source tokens, and when ``rcblock`` is non-null it +instead uses the previously-scanned IL expression to produce the same +information in the same form. That information then passes through the parts +of the operator routine that handle semantic checking, implicit conversions and +transformations, etc., undergoing exactly the processing it would have received +if scanned from source. + +Because IL expressions don't contain all the information that was available +when the expression was originally scanned, additional information (in the form +of ``an_expr_rescan_info_entry``) is saved whenever an expression is scanned in +a context that might later be subject to a rescan (essentially, in function +template headers). That rescan information includes a copy of the +``an_operand`` entry that represented the IL expression, and a bit of +additional information like the operator source position. + +When deduction is being done, if ``expr_is_rescannable`` is true for an +expression, it is passed to ``rescan_expr_with_substitution_internal``, which +determines the operator-scanning function that corresponds to the top operator +of the expression (see ``operator_token_for_expr_rescan``) and then calls that +operator-scanning function. The scanning function will then do substitution +and rescanning on its operands (see ``make_rescan_operands``), followed by the +semantic checking and processing it usually does, before returning an operand +back to its caller, which will continue through the rescan process. If an +error occurs, the error flag in the rescan control block is set, and once the +processing returns to the top level the deduction fails. + +The expression rescanning code co-exists with the older code that handled +SFINAE processing for many years before this change, e.g., routines like +``copy_template_param_expr``. Those routines are still used when new-style +SFINAE is turned off (see ``cpp0x_sfinae_enabled``), and also for parts of +expressions that aren't rescannable. + +For braced-init-lists, a copy of the original list in init-component form is +saved in the rescan info operand (see +``save_rescan_info_for_braced_init_list``). On the rescan, that list is +rescanned. As with all rescans, the source of the rescan is mined for +source-like information, and a lot of other information is ignored. That +means, for rescanned braced-init-lists, that the original list is not modified +or really "used" -- it's a guide for the rescan as opposed to a source of +expression operands to be used directly. + +Making rescanning work requires some special coding conventions in +expression-processing routines: + +#. The error-reporting routines cannot be called directly. Instead the + corresponding routines beginning with "``expr_``" must called. So, for + example, instead of "``pos_error``" one must call + "``expr_pos_error``". This allows the interception of error calls so + that they set a flag in the expression stack instead of issuing an + error. + +#. Code that checks access must be conditional on + ``expr_access_checking_should_be_done()``. Note that it's usually + necessary to avoid the access checks altogether rather than doing them + and getting to the point where an error would be issued, in order that + complete and correct IL is generated. + +#. Calls out to utility routines in other parts of the front end must not + generate errors (unless those errors come from handling something + outside of the expression; for example, it's okay to issue an error out + of a template instantiation that is kicked off by the expression + processing). If those utility routines might generate errors, they must + have parameters that can be used to get an error return instead of + having an error issued. For an example, see ``binary_operation`` in + ``folding.c`` and its ``error_detected`` parameter. + +#. Scanning routines for added operators must have an ``rcblock`` + parameter, to indicate the rescan. Within such routines, all processing + that deals with source tokens must have a rescan alternative that pick + up the information from the expression being rescanned. As a general + guideline, beware of using ``curr_token``, ``pos_curr_token``, + ``end_pos_curr_token``, ``locator_for_curr_id``, + ``const_for_curr_token``, ``curr_construct_ end_position``, + ``error_position``, and the error-reporting routines that use an implied + position. + + Near the end of the scanning routine, call + ``record_operator_position_in_rescan_info`` to record the operator + position in the rescan information for the expression. + + The scanning routine should be added to + ``operator_token_for_expr_rescan`` and + ``rescan_expr_with_substitution_internal`` so it will be rescannable. If + an operator scanning routine is not added to those routines, it will not + be rescannable, and if it comes up in a deduction context the deduction + will simply fail. That may be acceptable for certain kinds of + operators. + +#. Note that none of these restrictions are necessary for features used + only in C mode, but may be desirable anyway to allow the option of using + that feature in C++ mode at some later date. + +Void Expressions +---------------- + +When a void expression has been scanned, either by ``scan_void_expression`` or +as the first operand in ``scan_comma_operator``, ``simplify_void_operand`` is +called to trim off any parts of the expression that have no effect. This +trimming is done very conservatively, however. Top-level casts to ``void`` are +removed. Other kinds of trimming could be done, but they are not in the +interest of preserving the source expression. ``simplify_void_operand`` issues +a warning for expressions that have no overall effect. (See +``node_has_side_effects``.) + +Expressions that are explicitly cast to void are not processed as void +expressions at the time of the cast; a cast-to-void node is placed on top of +the expression, and the expression is handed up. If the node makes it up to +the top level, it is simplified and the cast-to-void node is removed. Casts to +void can remain in the final intermediate language, but only in rare cases +(such as + +.. code:: c++ + + i>0 ? (void)f(1) : (void)g(2) + +as a statement). + +Type Conversions +---------------- + +Type conversions happen implicitly (in assignments and initializations) and +explicitly (in casts). Either way, they are done under control of the +expression routines. And they must be: in C++, conversions involve not just +the type of an expression, but whether it is and stays an lvalue or an rvalue, +and whether or not other implicit transformations may be done. The data +structure that can express these concepts is ``an_operand``, and it exists only +within ``expr.c``, ``exprutil.c``, and ``overload.c``. + +To scan and process an expression correctly, one needs to know what will +ultimately be done with it, specifically what type it will be converted to. +Therefore, in all cases involving conversion, all necessary information about +the destination is passed into the expression routines, and they take care of +the conversion. By the time the expression is returned to the caller, it has +the correct type. + +The routines that control these conversions have names beginning with +"``prep_``": + +* | ``prep_conversion_operand`` deals with the general assignment or + initialization case. +* | ``prep_initializer_operand`` deals with initialization. Its interesting + special case is initialization of references. +* | ``prep_elision_initializer_operand`` deals with initialization of entities + with class types that have constructors, where it may be possible to avoid + a copy constructor call. +* | ``prep_argument_operand`` deals with initialization when it applies to + arguments. Its interesting special case is generating copy constructor + calls for class values passed by value. +* | ``prep_return_by_cctor_operand`` deals with expressions in ``return`` + statements (also considered an initialization case), specifically in + routines that return class values by calling a copy constructor. A dynamic + initialization entry describing the initializing operation is built and + returned to the caller. +* | ``prep_assignment_operand`` deals with the right-side expressions in + assignments. + +In general, these routines do their work in two parts: + +* | They determine whether or not the source operand can be converted to the + destination type, and if so, how. This is done by calling + ``conversion_possible``. +* | If the conversion is valid, they do it, by calling ``convert_operand``. + +``conversion_possible`` uses ``impl_conversion_possible`` (from ``types.c``) to +see if a standard conversion if available to do the conversion); if not, it +calls ``user_defined_conversion_possible`` to see if a user-defined conversion +can be done. + +``user_defined_conversion_possible`` calls ``conversion_to_class_possible`` to +check for constructors and ``conversion_from_class_possible`` to check for +conversion functions that might be applicable. + +``convert_operand`` calls ``cast_operand`` for simple conversions, and +``user_convert_operand`` for user-defined conversions. + +``cast_operand`` and ``cast_node`` are called to change the type of an +operand or expression node. (``cast_operand`` is actually just a wrapper +on top of ``cast_operand_full``, which does the real work.) The caller of +those routines must have already determined that the conversion is valid. +If the cast is implicit and if it does not change the type of an operand, +that operand is usually left alone. (An exception are casts on bit fields, +because a bit-field access that has no cast on it has slightly different +properties -- especially with respect to promotion -- from the same access +with a cast on top.) + +If the operand is a constant, ``type_change_constant`` is called to fold the +conversion. + +If the operand is an expression, ``add_cast_to_node`` is called to add a cast +to the expression tree. For casting a pointer-to-class to a +pointer-to-related-class it calls ``add_base_class_casts`` or +``add_derived_class_casts``, and for the similar cases involving pointers to +members, it calls ``add_pm_base_class_casts`` or +``add_pm_derived_class_casts``. + +The routines that scan explicit casts use several lower-level routines: + +* | ``check_user_defined_conversions_for_cast`` looks to see if a cast performs + any user-defined conversions, and if so applies them. +* | ``set_up_for_cast_to_reference`` does some checking and setup in the cases + where the cast is to a reference type. +* | ``cast_operand_for_reference_cast`` is like ``cast_operand``, but for cases + where the operand is being cast to a reference type (including an rvalue + reference type). +* | ``generic_cast_operand`` performs a cast when either the source operand or + the destination type involves something template-dependent in a prototype + instantiation. In such cases, it's not generally possible to know what the + cast does, and we just want to put a generic representation of it in the + IL. + +In C++/CLI, string literals start out as standard C++ string constants, and are +converted to C++/CLI strings if the context requires it. So, for example, if a +standard string literal is passed as an argument to a function that takes a +parameter of type "``System::String``\ ``^``", the string will be converted to +a C++/CLI string. This is done by setting the constant type to "handle to +``System::String``" without setting the ``implicit_cast`` flag. There is no +conversion of the characters in the string to Unicode (or in any other way), in +spite of what the ECMA standard seems to require. Wide string literals can +also be converted to C++/CLI strings in this way, and in that case the string +contents are treated as Unicode (as they always are in Microsoft mode, and +therefore in C++/CLI mode; but still no conversion is done). Having C++/CLI +strings represented as constants is a little strange, since ultimately they +have to result in creation of a class object on the heap, and use of its -- +non-constant -- address. However, MSVC treats such strings as constants, so +representing them that way makes it easier to emulate MSVC's behavior. See +``literal_type_convertible_to_cli_string``, +``is_literal_convertible_to_cli_string``, and +``convert_operand_to_handle_to_cli_string``. + +C++/CLI also allows boxing and unboxing conversions, i.e., between a value of a +value type and (a handle to) a boxed value in the CLR heap. Boxing can be +either an implicit conversion or a cast; unboxing is always done explicitly by +a cast. Operands having fundamental types will be implicitly converted to a +boxed value in cases where a class is required, e.g., in an example like +"``(3).toString()``", or when they are implicitly converted to an appropriate +handle type. Significant routines for boxing and unboxing are +``is_boxable_type``, ``add_box_to_expression``, ``add_unbox_to_expression``, +``box_value_type_operand``, and ``unbox_after_indirection_if_required``. + +Temporaries +----------- + +``create_expr_temporary`` creates an ``enk_temp_init`` node that defines a +expression temporary. It hangs a dynamic initialization entry under that node +and, if the temporary will require a destructor call, puts the destructor +information in the dynamic initialization entry. + +``alloc_dtor_dynamic_init`` is the routine that actually allocates the dynamic +initialization entry for the temporary. If the temporary is within the +expression in a return statement in a routine that returns its value via a copy +constructor, the destructor routine is recorded in the dynamic initialization +entry, but the destructor routine is not marked as referenced. This is because +the topmost initialization in the return expression should not indicate a +destructor (the caller does the destruction), but one cannot know at the time +the dynamic initialization entry is created whether or not it will end up being +the topmost one. Therefore, all entries are given destructors, but the +destructor routines are not marked as referenced. Each such dynamic +initialization is placed on a fixup list. After the entire expression is +processed, the destructor indication is cleared in the topmost initialization, +and ``fix_up_dynamic_init_dtors`` is called to revisit the dynamic +initialization entries and mark the (remaining) destructors as referenced. + +``temp_init_from_operand`` creates a temporary variable and initializes it from +a given operand value. + +``convert_operand_into_temp`` creates a temporary variable and initializes it +from a given operand value where there might be type conversion involved. + +Note that the temporary closure object resulting from a lambda expression is +not represented with an ``enk_temp_init`` node; the ``enk_lambda`` node itself +represents the temporary (it points to an associated dynamic initialization +entry). + +Copy Constructor Elision +------------------------ + +In cases where a class entity is being initialized, it is often possible to +avoid calling a copy constructor: + +.. code:: c++ + + struct A { A(int) {...}}; + A xx = 1; // A::A(int) + +The constructor in that case can be used to directly initialize the variable +``xx``. It's not necessary to initialize a temporary with that constructor and +then copy the temporary to ``xx`` using a copy constructor. The process of +avoiding the unnecessary copy constructor call is called *copy constructor +elision*. + +``determine_dynamic_init_for_class_init`` is the routine that checks for the +possibility of copy constructor elision. It attempts to find a constructor or +other routine that can do the initialization directly. Failing that, it +returns a copy constructor. + +If a copy constructor call is elided, the copy constructor must still exist. +To confirm its existence and accessibility ``handle_elided_copy_constructor`` +is called. + +Selector Operands +----------------- + +A function call like + +.. code:: c++ + + p->f(xx); + +is processed by (1) scanning ``p->f`` and generating a pair of operands (one +for the object, one for the function) bound together, then (2) processing the +call. Between the first step and the second, the selector operand for the +object is carried around alongside of the (primary) operand for the function. + +If the function being called is a nonstatic member function (which would be the +usual case), the selector must sometimes become a pointer to an object rather +than an lvalue or rvalue for the object. ``conv_operand_to_object_pointer`` +does that transformation. + +``conv_selector_to_object_pointer`` also does that transformation but has a +flag indicating whether or not the object has been turned into a pointer, so +that the transformation is not done more than once. + +``conv_object_pointer_to_lvalue`` does the transformation in the other +direction. + +It is noteworthy that the addresses of class prvalues can be taken. The +language does not allow the addresses of other kinds of prvalues to be taken. +However, the addresses of class objects are needed in order to do copy +constructor calls, member function calls, and base/derived class casts. The +language hints that all class prvalues might really be temporary variables of +class type, and that therefore it is possible to take their addresses. +Accordingly, the front end generates temporaries for class prvalues, including +cases when functions return class values. The routine +``conv_class_prvalue_operand_to_object_pointer`` can turn an expression for a +class prvalue back into a pointer to the class object, usually by finding the +``enk_temp_init`` node that defines the temporary and flipping the +address/value flag in that node back to "address." + +Overloaded Function Calls +------------------------- + +Overloaded function calls can be explicit calls or they can be implicit in +contexts that involve user-defined conversions (constructors or conversion +functions). In either case, the process of overload resolution must be done. +It involves considering an argument list and a set of overloaded functions, +selecting the function that best matches the argument list, then adjusting the +types of the arguments so that they are appropriate arguments for the function +selected. + +The argument list is represented as a list of entries of type +``an_arg_list_elem``, with each entry containing either an expression in +``an_operand`` form or a brace-enclosed list. + +Each function in the overload set is considered in turn to see how well it +matches the argument list. If all of the arguments can be made to match the +function parameters, the function is added to a candidate functions list (see +type ``a_candidate_function``). Under that entry is a list of entries that +describes how well each argument matches the function's corresponding formal +parameter. + +After all the functions are considered, ``select_best_candidate_functions`` is +called to select the function(s) with the best argument matches. For each +argument, it forms the set of functions that match best on that argument; then +the intersection of those best-match sets is formed. If the intersection has +just one function, it is the best-matching function. However, it must still be +compared to all the other functions to verify that the chosen function is +better in some argument position than each of the other functions (though not +necessarily on the same argument position for each function). After the +candidate functions list has been trimmed to a list of best-matching functions, + +* | If there are no functions on the list, an error is issued: no function is + appropriate. +* | If there is more than one function on the list, an error is issued: several + functions are appropriate, so the call is ambiguous. +* | If there is exactly one function on the list, that is the function to call. + The arguments are converted to the proper parameter types and the call is + generated. + +``compare_arg_match_levels`` compares two argument match summaries and +determines which of the two is a better match. Often, this is just a matter of +comparing the match levels. However, one of the overload resolution rules says +that if one match is a subsequence of the other (for certain cases), the +shorter sequence is the better match; this is the routine that implements that +rule. When comparing two matches at the same level, it looks to see if either +one is a subsequence of the other, and if so, the shorter sequence is called a +better match. The functions ``compare_argument_tiebreakers`` and +``compare_standard_conversions`` are called to do most of the work. + +There are several tie-breakers that will select one function over another when +the argument matches are equally good for the two functions. See +``compare_candidate_functions``. + +If function templates are involved in the overload resolution, the candidate +functions set is built more or less as described above. After an initial check +that the number of arguments matches the number of parameters, +``function_template_call_argument_deduction`` is called to do template +parameter deduction for the call. If deduction is possible, it returns a list +of template argument values and a routine type with the template argument +values substituted for the corresponding template parameters. This routine +type (which is a normal routine type containing no template parameters) is then +used for the rest of the overload resolution process. If the function name was +accompanied by a set of explicit template arguments (e.g., ``f(1)``), the +explicit template argument list is passed to the deduction routines and those +template parameters are not deduced. +``function_template_call_argument_deduction`` calls ``matches_template_type`` +to do the actual deduction. After the list of candidate functions has been +built, ``select_best_candidate_functions`` considers the template candidates +alongside the non-template functions. If a template function is chosen as the +best function, ``find_template_function`` is called to build the instance of +the function, and the template function routine is then used as the result of +the overload resolution. + +When template-dependent name lookup is enabled, some special processing is +done. If, in a prototype instantiation, the argument list contains an +expression of template-dependent type, overload resolution cannot be done. A +special "unknown dependent function" indication is returned to the caller. If, +in a prototype instantiation, the argument list contains no dependent +expressions, the call is a "non-dependent call" according to the standard. +Overload resolution is done, and the function selected is recorded (in +association with the token sequence number of the position of the call or +overloaded operator) by calling ``record_nondependent_call``. Then, in a real +instantiation of the template, ``get_nondependent_call_info`` is called to +retrieve the information, if any, recorded for a given call. If there is +information associated with the call, the call is non-dependent and the +function previously determined by overload resolution is used again (overload +resolution is not done). + +There are several things that are done during the processing of a +non-overloaded call that cannot be done at that point during the processing of +an overloaded function call, because it's not known which specific function +will be called. Once overload resolution has been done, those things are done +by ``overloaded_function_catch_up``: + +* | Check access to the function if it is a class member. +* | Record reference information for the function called. +* | Check that the return type of the function is not incomplete. + +The casting of the arguments to the proper types is also a "catch-up" function. + +``select_overloaded_function`` is the top-level routine for overload +resolution. To find the best match it calls ``try_overloaded_function_match``, +which first calls ``determine_arg_match_level`` to see how well the arguments +match (for the selector object, it uses ``selector_match_with_this_param`` +instead) and then calls ``select_best_candidate_functions`` to pick the best +function from the list of viable functions. + +``set_up_overload_set_traversal``, ``next_symbol_in_overload_set``, +``set_up_overload_symbol_list_traversal``, and +``next_symbol_in_overload_symbol_list`` are used to set up and traverse +overload sets (the first two for normal sets, and the second two for sets +introduced by symbol lists, e.g., argument-dependent lookup or conversion +functions). + +``determine_arg_match_level`` implements the argument matching rules of the +language. An argument can match at any of the following levels: + +.. list-table:: + + * - | ``aml_exact`` + - | Exact match or trivial conversions. + * - | ``aml_promotion`` + - | Match with promotions. + * - | ``aml_std_conversion`` + - | Match with standard conversions. + * - | ``aml_boxing_conversion`` + - | Match with boxing conversion (C++/CLI only) + * - | ``aml_user_conversion`` + - | Match with user-defined conversions. + * - | ``aml_ellipsis`` + - | Match with ellipsis. + * - | ``aml_error`` + - | Match with error type (not in ARM). + * - | ``aml_none`` + - | No match. + +C++/CLI adds a few additional complexities: + +* | Parameter arrays, where zero of more arguments at the end of the argument + list can be bundled together into a CLI array of values passed to a final + parameter with a parameter array type. Such a match is worse than other + matches except for an ellipsis match. Parameter arrays are also handled + when template type deduction is done. +* | Overload sets are formed using hide-by-sig lookup. + ``use_hide_by_sig_lookup`` is called on a function symbol to see whether + hide-by-sig lookup applies (it only applies to members of managed classes), + and to build a list, attached to the symbol, of the symbols that should be + in the overload set for that symbol. The overload set traversal routines + ``set_up_overload_set_traversal`` and ``next_symbol_in_overload_set`` + determine whether the symbol requires hide-by-sig lookup, and traverse the + hide-by-sig list if so, skipping any inaccessible functions. Since + hide-by-sig applies only to member functions, it never has to co-exist with + argument-dependent lookup. + +User-defined Conversions +------------------------ + +``conversion_to_class_possible`` looks for a constructor or conversion function +that will convert an expression to a particular class type, and +``conversion_from_class_possible`` looks for a conversion function that will +convert an expression from a class type to a specific other type or to a +built-in type from a given set. These use ``try_overloaded_function_match`` +for the constructor cases, and ``try_conversion_function_match_full`` for the +conversion function cases. + +Conversion functions that return reference types are a little tricky in that +their results are lvalues or xvalues, but that falls out more or less naturally +from the fact that operand transformations (like glvalue to prvalue) are put +off as long as possible. When the result of a conversion is to be bound to a +reference, the kind of reference (lvalue reference or rvalue reference) +constrains the choice of suitable conversion functions. + +C++/CLI adds static conversion functions. Those can convert to a class in +addition to from a class, and can also convert to/from a handle to a class or +tracking reference to a class. Therefore, places that look for conversion +functions must also look in the destination class for conversion functions, and +in the base classes of the source type, and must also consider handles to be +class-like as both source and destination types of a conversion, because the +classes underlying those handle types may have static conversion functions. +See ``try_static_conversion_function_match`` and +``cli_handle_user_defined_conversion_possible``. + +Operator Overloading +-------------------- + +``check_for_operator_overloading`` looks for operator overloading +possibilities. It is called only when one or more of the operands of an +operator has a class or enum type [#f5]_. It considers three ways of +processing the operands: + +#. As arguments of an operator member function. + +#. As arguments of an operator function that is not a member function. + +#. As operands of the built-in version of the operator, with the operands + converted from the class types to acceptable built-in types by use of + conversion functions. This is not tried for operators that have a + built-in meaning for classes ("``,``", "``->``", "``=``", and unary + "``&``"). + +As with overload resolution for function calls, the overloaded operator +resolution process considers each of the alternatives (functions and built-in +operator) in turn and builds a list of candidate functions. After all the +alternatives have been examined, the best one is selected (or an error is +issued). The operands are then adjusted to match the function or built-in +operator that was selected. + +``try_overloaded_function_match`` is called (possibly several times) to +determine how well the operator functions match the operands. +``opname_member_function_symbol`` is used to find the applicable member +functions (if any), and ``nonmember_operator_function_lookup`` is used to find +the applicable nonmember functions (if any); special processing is done for +those if the operand types come from namespaces. + +``try_conversions_for_builtin_operator`` is called to try to find conversions +that will allow use of the built-in version of the operator. Its subroutines +-- ``operand_type_pattern_for_operator``, ``try_builtin_operands_match``, and +``try_pointer_builtin_operands_match`` -- do the necessary investigation. + +C++/CLI adds some additional issues: + +* | When the first operand is a handle, it is overloadable much as if it had + the underlying class type. An expression like "``h+x``" can be treated as + "``h->operator+(x)``". +* | When either operand is a handle, it may be possible to use a static + conversion function to convert the operand to a fundamental type for which + there is a builtin version of the operator, much as is done for class + operands. +* | Static operator functions can apply. They don't have a "``this``" + parameter, so the first operand matches the first parameter, and the + second operand (if there is one) the second parameter. "``a+b``" could + become "``X::operator+(a,b)``". These are also searched for in the + class of the second operand, if there is one and it has class type. +* | Operator synthesis can be done. If a class does not have an + "``operator+=``", for example, the combination of an "``operator+``" and an + "``operator=``" can be used. +* | In certain cases, string literals can act as if they are handles to + ``System::String``, which then makes them overloadable. + +Address of Overloaded Function +------------------------------ + +When an overloaded function appears in an expression, it is represented an as +indefinite function operand, which is basically just an operand that points to +the overloaded function symbol. + +When such an operand is subjected to the function-to-pointer transformation, +the operand stays an indefinite function, but changes from a function +designator to a prvalue pointer. + +When such an operand shows up in a conversion where the destination type is a +function pointer, ``find_addr_of_overloaded_function_match`` is called to find +out which (if any) of the specific functions matches the required function +pointer. The operand is then converted to the specific function pointer in +``cast_operand_full``; ``overloaded_function_catch_up`` is called to do +whatever would have been done had it been known all along which specific +function was intended. + +If the overload set includes one or more template functions, the resolution +algorithm is as follows: + +#. If there is an exact match in the set of non-function-templates, it is + selected (if there is more than one, the pointer use is ambiguous); + otherwise, + +#. If there is a template function from which a function can be generated + that will match exactly, it is selected (if there is more than one, the + pointer use is ambiguous); otherwise, + +#. If there is a non-exact match in the set of non-function-templates, it is + selected (this can only happen with pointers to member functions, where + an implicit conversion from base to derived is allowed). + +``matching_template_function`` is called to attempt to find a match under rule +(2). + +Range-based ``for`` statement +----------------------------- + +The C++11 range-based ``for`` statement is checked and assembled by +``check_range_based_for_statement``. It determines which of the three +"patterns" is applicable for the statement and calls +``check_range_based_for_array_case``, ``check_range_based_for_member_case``, or +``check_range_based_for_default_case`` as necessary to perform the necessary +semantic checks and generate the IL. + +The range-based-for statement takes the form: + + | ``for (`` *for-range-declaration* ``:`` *expression* ``)`` *statement* + +and is defined to be equivalent to: + + | ``{`` + | ``auto && __range = (``\ *expression*\ ``);`` + | ``for ( auto __begin =`` *begin-expr*\ ``,`` + | ``__end =`` *end-expr*\ ``;`` + | ``__begin != __end;`` + | ``++__begin ) {`` + | *for-range-declaration* ``= *__begin;`` + | *statement* + | ``}`` + | ``}`` + +Lower level routines for handling variable initializer expressions, member +lookup, overload resolution, etc. are shared (where applicable) with the +for-each statement handling described below (together the range-based ``for`` +and for-each statements are referred internally as "enhanced ``for``" +statements). + +For-each Statement +------------------ + +The C++/CLI for-each statement is checked and assembled by +``check_for_each_statement``. There are four "patterns" for the for-each +statement (the STL pattern, the CLI collection pattern, the CLI array pattern, +and the native array pattern). ``check_for_each_statement`` determines the +pattern matched by a given loop, and calls the right one of four routines, each +charged with checking one of the patterns and building the IL. + +The for-each statement is defined in terms of a rewrite for each of the +patterns. For example, a for-each loop that matches the native array pattern +is rewritten from + + | ``for each (``\ *T t* ``in`` *c*\ ``)`` *statement* + +to + + | ``{ C &cref =`` *c*\ ``;`` + | ``I *cend = &cref[0]+``\ *c_num_elements*\ `;`` + | ``I *i = cref;`` + | ``for (; i != cend; ++i) {`` + | *T t* ``= static_cast<``\ *T*\ ``>(*i);`` + | *statement* + | ``}`` + | ``}`` + +The IL for this case contains variables and associated scopes for the iterator +variable and the added temporary variables, initializer expressions for each of +those, and additional expressions for the loop ``!= and ++`` expressions. +Those are relatively simple in this case, but in other cases and other patterns +the generated expressions can be complex, and developing them may involve +member lookup, overload resolution, operator overloading, or user-defined +conversions. The front end's goal is to provide IL that completely describes +the actions needed to implement the loop, while at the same time retaining the +parts in a high-enough-level form that source-analysis programs can discern the +original loop variables and expressions. + +Properties +---------- + +Microsoft mode has properties, which are data members of classes that are +implemented by accessor functions, e.g., one to get the current value of the +property, and one to set the current value of the property. Properties come in +two kinds: + +* | Old-style properties, indicated by the ``__declspec(property(``... )) + attribute. The accessor functions are only loosely associated with the + property, by being named in the attribute. +* | New-style properties in C++/CLI, which begin with the "``property``" + context-dependent keyword. The accessor functions are declared as part of + the property declaration, in a form that looks vaguely like a nested class. + +In both cases, the IL has a description of the property declaration, in +something close to the source form (that information is held in +``an_property_or_event_descr`` entry). However, also in both cases, references +to the properties are expanded by expression processing, so they are not +retained in source form. A bit of source code like "``p``\ ``+=``\ ``1``" +might be expanded into a series of calls something like "call the get accessor +for ``p``, call ``operator+`` on the fetched value and 1, and call the put +accessor to store the computed value." The generated IL contains some tags on +various nodes in the expansion that help source-analysis code recover the +original meaning, though in a cumbersome way. + +Property references cannot be rewritten immediately. They have to be carried +around for a short while in expression processing until it becomes clear from +the context how the property is being used, i.e., a "get" or a "set". Before +they are rewritten, property references are carried around as ``an_operand`` +entries of kind ``ok_property_ref``. The operand can include a list of +subscripts that is part of the property reference. Once the context is +established, the property reference is rewritten; that's handled by +``rewrite_property_reference``. As hinted at above, some rewrites are more +complicated than a simple "get" or "set", and might involve a "get", some +operation on the fetched value, possibly surrounded by conversions, and finally +a "set". That happens for compound assignment operators and for pre- and +post-increment and -decrement operators. In such cases, the operand is cloned +(see ``clone_operand``), so that it will only be evaluated once, and +``rewrite_property_reference`` is called twice, once for the "get" and once for +the "set". + +C++/CLI events are very similar to the new-style properties, in representation +and in the fact that references are expanded by the front end. + +C++/CLI Generics +---------------- + +Expression processing for C++/CLI generics, meaning handling of expressions +during the scanning of a generic definition, mostly falls out of normal +expression processing. During the generic definition, the parameters of the +generic (represented as template parameters) are given values that are +generated class types that reflect the constraints on the generic parameters. +So, for example, if a generic parameter is constrained to derive from an +interface I, the generated class type will be such that it will be possible to +look up members of I in the class and find them in a base class that is I. +That makes most operations work without special handling. Also, for many +cases, the template parameter's value is a handle to the constraint class type, +so that operations like assignment work because they become handle assignments +instead of class assignments (where it might not be possible to know whether +the class will have an appropriate ``operator=`` at runtime). There are a few +special cases with casting, where a generic parameter might or might not be a +value class type, or might or might not effectively be a handle at runtime. +Casts are rejected if they might be invalid because they treat a value type as +a handle, or vice-versa. Also, casts are rejected if it can be shown at +compile time that the source value type can never satisfy the constraints of +the destination type. + +Reference Information +--------------------- + +To track references to identifiers, ``ref_entry`` is called for each identifier +reference in an expression. The information provided is used to write +cross-reference information (when requested) and to set the referenced, used, +modified, and address-taken flags in variable and routine entries. For some +identifiers, the kind of reference is known immediately, so +``record_symbol_reference`` is called to record the information. For others, +the kind of reference is dependent on the expression context, and therefore it +is not known immediately. For such cases, an entry called ``a_ref_entry`` is +allocated and placed on a list of such entries for the current expression. +When the reference kind becomes known, the kind in the entry is updated (see +``change_ref_kinds``). At the end of the expression, +``flush_ref_entries_list`` is called. It scans the entries on the list, calls +``record_symbol_reference`` to record the (now fully determined) reference, and +then frees the entries. + +Diagnostic output +----------------- + +Diagnostic output in the expression-processing routines must be handled +specially in order that it be possible to suppress diagnostics when rescanning +an expression during template deduction. For that reason, what would normally +be simply a call of a diagnostic-output routine must be slightly more +complicated in the expression-processing source files. For the simpler +diagnostics, there are direct ``expr_`` equivalents: + +* | For ``pos_error``, use ``expr_pos_error``. +* | For ``pos_warning``, use ``expr_pos_warning``. +* | For ``pos_diagnostic``, use ``expr_pos_diagnostic``. +* | For ``syntax_error``, use ``expr_syntax_error``. + +Other diagnostic calls should be enclosed in a test of +``expr_error_should_be_issued`` or ``expr_diagnostic_should_be_issued``, as +appropriate. + +Any access-checking code must be conditioned on +``expr_access_checking_should_be_done``. It's not enough to simply surround +access-error diagnostic calls with a suppression test; when template deduction +is being done, it must be as if no access checking is even attempted, and the +flow of control must continue as if the error were not present. + +Folding of Constant Operations +============================== + +There are four main files involved in folding constant operations: + +* | ``const_ints.c`` contains the code for low-level integer operations, with + ``const_ints.h`` containing associated declarations. +* | ``fixed_pt.c`` contains the code for low-level fixed-point operations, with + ``fixed_pt.h`` containing associated declarations. +* | ``float_pt.c`` contains the code for low-level floating-point operations, + with ``float_pt.h`` containing associated declarations. +* | ``folding.c`` contains the higher-level code that handles folding of + constant operations and of type conversions on constants. ``folding.h`` + contains associated declarations. Code for folding of ``constexpr`` calls + and operations is also here. + +Low-level Integer Routines +-------------------------- + +``const_ints.c`` contains the routines that manipulate low-level integers. Any +integer literal constant in the source program and any operation on constant +integers implied by the source program are ultimately handled by the routines +here. For the most part, the low-level integer form can be viewed as a +representation for target machine integers on the host machine, although it is +also used for some things (like array dimensions) that are only arguably target +machine constants. + +The point of these routines is to collect all the code that operates on target +integers in one place, so that it can be modified if necessary, and so that the +rest of the front end does not need to deal with the subtleties of signed and +unsigned representations, overflow, etc. + +There are two different possible representations for integer values (type +``an_integer_value``): + +* | If there is some host integer type that is big enough to hold any target + integer (the usual case), an integer value is simply represented as a host + integer. Operations on that representation are done using the host C + operators, with extra overflow checking. If the host C compiler supports + ``long long``, that type can be used as the representation type. +* | Otherwise (for example, in a cross-compiler for a 64-bit target running on + a 32-bit host), an integer value is represented as a ``struct`` containing + an array of small integers (of type ``an_int_value_part``). Operations on + that representation are simulated in software. + +(See configuration constant ``INTEGER_VALUE_REPR_IS_A_HOST_INTEGER``.) + +The ``an_integer_value`` representation may be used to represent signed or +unsigned quantities. It is not self-identifying in that regard, i.e., the +representation does not contain an indication of the signedness of the value. +Therefore, in cases where signedness is significant, (e.g., multiplication), +the caller must pass in a separate argument indicating the signedness to be +used for the integer value. For values that can be represented in both the +signed and unsigned forms, the representation in the two forms is the same. +That allows small constants to be used as either signed or unsigned quantities +as the need arises. + +The ``const_ints.c`` routines deal with integer values as single-sized +entities, the size being large enough to hold any of the target integer types. +The routines check for overflow relative to that representation, but they know +nothing of different integer types and their sizes. + +Most routines in ``const_ints.c`` operate on values in the ``an_integer_value`` +form. For convenience, some routines are provided that operate on the IL +``a_constant`` form, but it's a circumspect use of that form: as far as the +routines are concerned, ``a_constant`` is a structure that only contains +``an_integer_value`` (in the variant ``integer_value`` field) and a type (in +the ``type`` field) that can be passed to ``int_constant_is_signed`` to +determine the signedness of the value. No other fields of the constant need be +defined. + +The routines that are used to translate between ``a_host_large_integer`` (some +large built-in host integral type) and the ``an_integer_value`` form are + +* | ``set_integer_value``, +* | ``set_unsigned_integer_value``, +* | ``value_of_integer_constant``, and +* | ``unsigned_value_of_integer_constant``. + +Routines used to get attributes of integer values are + +* | ``get_integer_size_and_alignment`` and +* | ``int_constant_is_signed``. + +Utility routines used to determine the magnitude of an integer value, create a +bit mask, and sign-extend a value are + +* | ``bits_required_to_represent_integer_constant``, +* | ``make_integer_value_mask``, and +* | ``sign_extend_integer_value``. + +Routines used to format integer values in decimal string form are + +* | ``str_for_integer_constant``. + +Routines used to compare integer values (including some comparisons against the +limits of integers of given kinds) are + +* | ``cmp_integer_values``, +* | ``cmp_integer_constants``, +* | ``cmplit_integer_value``, +* | ``cmpulit_integer_value``, +* | ``in_range_for_integer_kind``, +* | ``le_max_value_for_integer_kind``, and +* | ``is_max_value_for_integer_kind``. + +On these, the two values being compared may have independent signedness. The +``lit`` routines do comparison against ``a_host_large_integer`` or +``a_host_large_unsigned`` value, typically a small constant. + +Routines used to perform arithmetic and logical operations are + +* | ``add_integer_values``, +* | ``subtract_integer_values``, +* | ``multiply_integer_values``, +* | ``divide_integer_values``, +* | ``remainder_integer_values``, +* | ``and_integer_values``, +* | ``or_integer_values``, +* | ``xor_integer_values``, +* | ``shift_left_integer_values``, +* | ``shift_right_integer_values``, and +* | ``complement_integer_values``. + +On these, the two operands must have the same signedness (except that there are +versions of the add and subtract routines for the independent-signedness +cases). The result of the operation overwrites the first operand. + +For some kinds of values, it's just too much of a nuisance to use the integer +value routines, so the front end converts such values to +``a_host_large_integer`` or ``a_host_large_unsigned`` (which are typically +signed and unsigned ``long``, or signed and unsigned ``long long``) and +operates on them in that form. The values handled that way are: + +* | Sizes of objects, including arrays (conceptually of type ``size_t`` on the + target). +* | Offsets relative to objects (conceptually of type ``ptrdiff_t`` on the + target). +* | Single characters (but not a character constant containing one or more + characters). +* | Single ``wchar_t`` values. + +Note that the target ``size_t`` and ``ptrdiff_t`` are allowed to be bigger than +the host ``a_host_large_integer``; the use of ``a_host_large_integer`` +representation just restricts the possible constant values of that type that +the front end can deal with. The conversions into the host types are done with +overflow checking, so the front end will issue errors for values larger than +those it can accommodate. + +Low-level Fixed-point Routines +------------------------------ + +The routines in ``fixed_pt.c`` manipulate the internal repreentation of +fixed-point constants on the host machine. As with the integer routines, they +are collected in one place so that they can be changed more easily and so that +the front end at large need know nothing about the fixed-point representation. + +They implement very low-level operations on the internal form of fixed-point +constants. Some of the standard product versions of these routines (e.g., for +conversion of a decimal text form of a fixed-point constant to internal form) +are not always accurate to the last significant bit: They are best viewed as +prototype routines for testing purposes, to be replaced by real routines for +the production version. + +The main routines (or macros) in ``fixed_pt.c`` are the following: + +* | ``cmp_fixed_point_constants`` +* | ``fxp_init_value`` +* | ``fxp_value_is_zero`` +* | ``fxp_string_to_fixed_point`` +* | ``fxp_hex_string_to_fixed_point`` +* | ``conv_fixed_point_to_fixed_point`` +* | ``conv_integer_to_fixed_point`` +* | ``conv_fixed_point_to_integer`` +* | ``conv_float_to_fixed_point`` +* | ``conv_fixed_point_to_float`` +* | ``fxp_to_string`` +* | ``fxp_add`` +* | ``fxp_subtract`` +* | ``fxp_multiply`` +* | ``fxp_divide`` +* | ``fxp_compare`` +* | ``fxp_hash`` + +Low-level Floating-point Routines +--------------------------------- + +The routines in ``float_pt.c`` manipulate target floating-point constants on +the host machine. As with the integer routines, they are collected in one +place so that they can be changed more easily and so that the front end at +large need know nothing about the floating-point representation. + +They implement very low-level operations on the internal form of floating-point +constants. When ``USE_HOST_FP_CONVERSION_ROUTINES`` is TRUE (the default), +binary to decimal conversions are performed using standard UNIX conversion +routines provided by the host. When ``USE_HOST_FP_CONVERSION_ROUTINES`` is +FALSE, internal routines (in ``floating.c``) are used to perform these +conversions. Arithmetic operations are performed without range checking; +therefore, they are best viewed as prototype routines for testing purposes, to +be replaced by real routines for the production version. + +In cases where the target configuration supports floating-point types that are +not supported by the host compiler (e.g., ``__float128`` and ``__float80`` on +Windows), the `Berkeley SoftFloat library +`__ can be used to perform +arithmetic operations on the host. This configuration can be selected by +setting the ``USE_SOFTFLOAT`` configuration macro to TRUE. In such +configurations, the ``USE_HOST_FP_CONVERSION`` routines is automatically set to +FALSE to enable a software-only floating-point configuration. Note that +such configurations are inherently slower than those that use floating-point +hardware. See the SoftFloat web site for licensing information. + +The main routines in ``float_pt.c`` are the following: + +* | ``fp_change_kind`` +* | ``fp_string_to_float`` +* | ``fp_hex_string_to_float`` +* | ``fp_to_string`` +* | ``fp_long_to_float`` +* | ``fp_unsigned_long_to_float`` +* | ``fp_to_host_large_integer`` +* | ``fp_to_host_large_unsigned`` +* | ``fp_is_zero_constant`` +* | ``fp_add`` +* | ``fp_subtract`` +* | ``fp_multiply`` +* | ``fp_divide`` +* | ``fp_compare`` +* | ``fp_hash`` + +Constant Folding +---------------- + +The routines in ``folding.c`` do folding of constant operations and type +conversions on constants. + +This folding is done in target machine arithmetic. For integers, routines in +``const_ints.c`` do the actual operations on the generic integer value, but the +routines here add a layer that understands specific integer types, and does +overflow checking, masking, and sign extension according to the size and +signedness of the integer type. For fixed-point and floating operations, +target-specific code in ``fixed_pt.c`` and ``float_pt.c`` does the actual +operations. For pointer operations, the constants are either address constants +(a base symbol plus a byte offset) or integer constants cast to a pointer type +(the most common of these is ``NULL``/0). The routines ``get_pointer_offset`` +and ``set_pointer_offset`` are used to extract and set the offsets in both +those cases. + +The folding routines detect errors and warnings and call the error routines to +report them. When they are called in nonconstant contexts (like executable +statements), errors are downgraded to warnings, and the operation is left +unfolded, to be tried at runtime. + +If the folding routines are unable to fold an operation to a constant (because +of some attribute of the operands, not because of an error), they return a flag +``did_not_fold`` set to TRUE, which tells the caller to leave the operation +unfolded. For example, the pointer difference of pointers to different static +objects is a constant, but one that is unknowable until link time. +``did_not_fold`` would be returned TRUE for that case (and no error or warning +would be indicated). The folding routines also record the unfolded expression +in constants resulting from the folding. + +``unary_operation`` and ``binary_operation`` are the top-level routines for +operations on constants. They take as input an operator and one or two +constants, and produce a constant (or an error indication) as output. The +operations are done with all necessary checking for overflows, etc. The +routines called by ``unary_operation`` to do the actual folding are + +* | ``do_inegate``, +* | ``do_fxnegate``, +* | ``do_fnegate``, +* | ``do_xnegate``, +* | ``do_complement``, and +* | ``do_not``, + +and those called by ``binary_operation`` are: + +* | ``do_iadd``, +* | ``do_isubtract``, +* | ``do_imultiply``, +* | ``do_idivide``, +* | ``do_remainder``, +* | ``do_shiftr``, +* | ``do_shiftl``, +* | ``do_icompare``, +* | ``do_and``, +* | ``do_or``, and +* | ``do_xor`` + +for integers; + +* | ``do_land`` and +* | ``do_lor`` + +for scalars; + +* | ``do_fxadd``, +* | ``do_fxsubtract``, +* | ``do_fxmultiply``, +* | ``do_fxdivide``, and +* | ``do_fxcompare`` + +for fixed-point; + +* | ``do_fadd``, +* | ``do_fsubtract``, +* | ``do_fmultiply``, +* | ``do_fdivide``, and +* | ``do_fcompare`` + +for floating-point; + +* | ``do_xadd``, +* | ``do_xsubtract``, +* | ``do_xmultiply``, +* | ``do_xdivide``, +* | ``do_jmultiply``, +* | ``do_jdivide``, and +* | ``do_xcompare`` + +for complex and imaginary; + +* | ``do_padd``, +* | ``do_pdiff``, and +* | ``do_pcompare`` + +for pointers; and + +* | ``do_pmcompare`` + +for pointers to members. + +Actual shifting is performed by ``do_shift``, which calls ``check_shift_count`` +for error checking. The shifting is implemented with the integer size and +sign-extension appropriate for the target. + +When pointer addition or subtraction is folded, the resulting constant, if an +address constant, is checked to see if the offset lies within the base object. +Offsets beyond the end of the object and negative offsets are flagged with a +warning (most often, this is due to a constant subscript out of bounds). This +is checked by ``valid_address_constant``. + +In ordinary constant folding, ``valid_address_constant`` will allow the +position just past the end of an object without a warning, since it does not +know whether the address of that position is required (which is allowed by ANSI +C) or the value (which is an error). The routine ``using_lvalue`` calls +``valid_address_constant`` again to check for the error once it is known that +it is the value that is being accessed. + +``type_change_constant_full`` changes the type of a constant to something else. +It's usually called through the simpler interface ``type_change_constant``. It +has subroutines + +* | ``conv_integer_to_integer``, +* | ``conv_integer_to_float``, +* | ``conv_float_to_integer``, +* | ``conv_float_to_float``, +* | ``conv_pointer_to_whatever``, +* | ``conv_integer_to_pointer``, +* | ``conv_ptr_to_member_to_ptr_to_member``, and +* | ``conv_integer_to_ptr_to_member``. + +with the obvious functions. Warnings about truncation and hidden changes of +sign are issued (the latter are suppressed if the type change was the result of +an explicit cast or if the operand was a non-decimal constant). + +Casts of pointers to classes to pointers to base or derived classes are handled +by + +* | ``fold_base_class_cast`` and +* | ``fold_derived_class_cast``. + +The similar cases for pointers to members are handled by + +* | ``fold_pm_base_class_cast`` and +* | ``fold_pm_derived_class_cast``. + +``fold_field_selection`` is called to fold a field selection relative to a +constant address. Because of the unusual second operand (a field rather than a +constant), ``binary_operation`` could not be used for this case. If the field +is a bit field, ``fold_field_selection`` returns a ``did_not_fold`` flag. + +``constant_glvalue_address`` and its companion routine +``constant_prvalue_pointer`` examine expression trees to determine if they +represent constant addresses, computing and returning the appropriate constant +value on the fly. + +.. _constexpr-and-expr-folding: + +Folding and ``constexpr`` +------------------------- + +C++11 and C++14 permit calls to ``constexpr`` functions and constructors in +constant-expressions. To implement this, the front end includes an IL +interpreter implemented in the source file ``interpret.c``. The start of that +file contains extensive comments describing the overall structure of the +interpreter. The global variable ``relaxed_constexpr_enabled`` is TRUE +when the C++14 version of the ``constexpr`` feature is enabled. This enables +the interpretation of expressions, like assignments, with side-effects (valid +in C++14, but not C++11). It also removes C++11 structural constraints for +``constexpr`` functions and constructors (e.g., it allows multiple statements +in definitions). + +To avoid burdening the IL or the rest of the front end, the interpreter does +not record state information in the IL or other front end structures. Instead, +it maintains its own data structures linked to the IL through efficient hash +tables. It does, however, use front end types to represent integral and +floating-point values. Other kinds of values (e.g., addresses) are represented +using interpreter-specific structures. + +The interpreter can fold calls to ``constexpr`` functions and constructors, but +it can also more generally fold expressions and dynamic initializations. + +The entry points into the interpreter are ``interpret_expr,``\ +``interpret_dynamic_init,``\ ``interpret_constexpr_call,`` and +``interpret_constexpr_ctor``. These functions return a boolean value +indicating whether interpretation succeeded (TRUE) or failed (FALSE). +Interpretation can fail because it encountered an operation not permitted +during ``constexpr`` evaluation (e.g., a virtual function call), including +operations with undefined behavior (e.g., attempting to fetch a value from +uninitialized storage). It can also fail when the cost of interpretation +becomes too high. The parameters limiting that cost can be set through the +command-line options ``--max_depth_constexpr_call`` and +``--max_cost_constexpr_call``. If interpretation fails, the interpreter also +returns a diagnostic description indicating the reason for the failure (that +description can be emitted as part of the diagnostic if a constant was +required). + +.. [#f1] Note that the C standard does not actually have an rvalue concept, + though it has lvalues. This is a difference from K&R. However, the + distinction between an rvalue and a non-lvalue is almost nonexistent. + It has to do with some strange cases (like ``sizeof``) that allow + unevaluated non-lvalues. For simplicity, the term "rvalue" is used, + but what is actually implemented by the front end is the ANSI C + non-lvalue. +.. [#f2] Following the implementation of C++11 value categories in version + 4.8, the front end has tried to use the C++11 terms in general + internally. That caused a lot of renaming of routines and fields; for + example, ``conv_lvalue_to_rvalue`` became ``conv_glvalue_to_prvalue``. + Ugly until you get used to it, but very helpful in reminding you to + consider xvalues when you write code that deals with expressions. +.. [#f3] Meaning, more or less, when the glvalue-to-prvalue conversion is done + on the operand. Constant-valued variables are replaced by their + values at that point, and member access and subscripting operations, + and pointer dereferences, produce constant values only when the + glvalue addressing expression is converted to a prvalue. +.. [#f4] This is used, for example, for the initializer expression on a + const-typed variable; the initializer is not required to be a constant + expression, but if it is, the variable is usable as a constant. So + the expression is scanned as a normal (non-constant) expression, and + if it produces a constant value and does not violate the rules for a + well-formed constant expression, the variable is a constant. +.. [#f5] Actually, it is also called -- during prototype instantiations -- when + at least one operand has a template-dependent type. In that case, it + generates a generic expression and returns without doing overload + resolution. diff --git a/doc/_sources/ext_intf.rst.txt b/doc/_sources/ext_intf.rst.txt new file mode 100644 index 0000000..77754c4 --- /dev/null +++ b/doc/_sources/ext_intf.rst.txt @@ -0,0 +1,5681 @@ +================== +External Interface +================== + +Bear in mind that this information applies to the standard product. If any +local modifications are made, the documentation given to users must be adjusted +accordingly. + +.. _cli: + +Command Line +============ + +The front end is invoked by a command of the form + + ``edgcpfe [``\ *options*\ ``]`` *ifile* + +to compile the single input file *ifile*. If ``-`` (hyphen) is specified +for *ifile*, the front end reads from ``stdin``. [#f1]_ No particular +file name suffix is required on input files. + +Command line options may be specified using either single character option +codes (e.g., ``-o``) or keyword options (e.g., ``--output``). A single +character option specification consists of a hyphen followed by one or more +option characters (e.g., ``-Ab``). If an option requires an argument, the +argument may immediately follow the option letter, or may be separated from the +option letter by white space. A keyword option specification consists of two +hyphens followed by the option keyword (e.g., ``--strict``). Keyword options +may be abbreviated by specifying as many of the leading characters of the +option name as are needed to uniquely identify an option name (for example, the +``--wchar_t_keyword`` option may be abbreviated as ``--wc``). If an option +requires an argument, the argument may be separated from the keyword by white +space, or the keyword may be immediately followed by ``=``\ *argument*. When +the second form is used there may not be any white space on either side of the +equals sign. + +If the configuration flag ``COMPILE_MULTIPLE_SOURCE_FILES`` is defined as TRUE, +a list of files may appear for *ifile*. If a list of files is specified, +options that specify a compilation output file (``--output``, ``--list``, and +``--xref``) may not be used, and the name of each source file is written to the +error output file as the compilation of that file begins. + +When one of the preprocessing-only modes is specified (see below), the +``--output`` option can be used to specify the preprocessing output file. If +``--output`` is not specified, preprocessing output is written to ``stdout``. +Preprocessing output has trigraphs and line splices processed (and thus they do +not appear in their original form). + +When compilation (rather than just preprocessing) is done, the output (if any) +from the compilation is written to a file selected by the back end; see the +documentation of the back end for further information. For versions of the +front end that generate an intermediate language file, the ``--output`` option +can be used to specify the IL output file. + +The *options* are described in the following subsections (organized by +category). + +Language Dialect Options +------------------------ + +The following options select among various C and C++ dialects. + +.. list-table:: + + * - | ``--anachronisms`` + | ``--no_anachronisms`` + - | Enable or disable anachronisms in C++ mode. The default for this + option is specified by ``DEFAULT_ALLOW_ANACHRONISMS``. This option is + valid only in C++ mode. + * - | ``--c`` + | ``-m`` + - | Enable compilation of C rather than C++. + * - | ``--c89`` + - | Enable the compilation of the C89 version of C. + * - | ``--c99`` + | ``--no_c99`` + - | Enable or disable compilation of the C99 version of C. In either + case, C rather than C++ is compiled. + * - | ``--c11`` + - | Enable language features added in the C11 standard. This option + cannot be combined with options enabling or requiring a C++ mode. + * - | ``--c18`` + | ``--c17`` + - | Enable support for C18 (which is only a minor "bug fix" change from + C11). This option cannot be combined with options enabling or + requiring a C++ mode. + * - | ``--c23`` + - | Enable language features added in drafts of the anticipated C23 + standard. This option cannot be combined with options enabling or + requiring a C++ mode. + * - | ``--old_c`` + | ``-K`` + - | Enable K&R/pcc mode, which approximates the behavior of the standard + UNIX ``pcc``. ANSI/ISO C features that do not conflict with K&R/pcc + features are still supported in this mode. + * - | ``--c++`` + | ``-p`` + - | Enable compilation of C++. This is the default. + * - | ``--c++03`` + - | Enable compilation of C++ as specified by the ISO/IEC 14882:2003 + standard by explicitly disabling all C++11 features, regardless of + their configured default values (but individual C++11 features can be + enabled on the command line). This option implicitly enables C++ mode + and can be combined with the options enabling strict ANSI/ISO + conformance, as well as other emulation modes (e.g., ``--microsoft``, + ``--g++``). + * - | ``--c++11`` + | ``--no_c++11`` + | ``--c++0x`` + | ``--no_c++0x`` + - | Enable or disable extensions added in the C++11 standard. This option + is only valid in C++ mode and can be combined with the options + enabling strict ANSI/ISO conformance. + * - | ``--c++14`` + - | Enable language features added in the C++14 standard. This option + cannot be combined with options enabling or requiring a C mode. + * - | ``--c++17`` + - | Enable language features added in the C++17 standard. This option + cannot be combined with options enabling or requiring a C mode. + * - | ``--c++20`` + - | Enable language features added in the C++20 standard. This option + cannot be combined with options enabling or requiring a C mode. + * - | ``--c++23`` + - | Enable language features added in the C++23 standard. This option + cannot be combined with options enabling or requiring a C mode. + * - | ``--c++26`` + - | Enable language features added in drafts of the anticipated C++26 + standard. This option cannot be combined with options enabling or + requiring a C mode. + * - | ``--cfront_2.1`` + | ``-b`` + - | Enable compilation of C++ with compatibility with cfront version 2.1. + This causes the compiler to accept language constructs that, while not + part of the C++ language definition, are accepted by the AT&T C++ + Language System (cfront) release 2.1. This option also enables + acceptance of anachronisms. + * - | ``--cfront_3.0`` + - | Enable compilation of C++ with compatibility with cfront version 3.0. + This causes the compiler to accept language constructs that, while not + part of the C++ language definition, are accepted by the AT&T C++ + Language System (cfront) release 3.0. This option also enables + acceptance of anachronisms. + * - | ``--c++cli`` + | ``--no_c++cli`` + | ``--cppcli`` + | ``--no_cppcli`` + | ``--clr`` + - | Enable or disable compilation of C++/CLI source. This option implies + Microsoft C++ mode; it cannot be combined with options that are + contrary to such a mode (e.g., forcing strict mode) or with the option + ``--microsoft_version`` with a value less than 1600. + * - | ``--c++cx`` + | ``--no_c++cx`` + | ``--cppcx`` + | ``--no_cppcx`` + - | Enable or disable compilation of C++/CX source. This option implies + Microsoft C++ mode; it cannot be combined with options that are + contrary to such a mode (e.g., forcing strict mode) or with the option + ``--microsoft_version`` with a value less than 1600. Support for this + mode is preliminary and will be improved in future versions of the + front end. + * - | ``--clang`` + | ``--no_clang`` + - | Enable or disable clang C or C++ language compatibility features. + This option also enables the GNU C or C++ language compatibility + features. It is only recognized when ``GNU_EXTENSIONS_ALLOWED`` is + TRUE. As of this writing, the only effect of clang mode apart from + enabling GNU emulation is to enable the feature-test macros like + ``__has_feature``. + * - | ``--clang_version`` *version-number* + | + - | The version of the clang compiler that should be emulated. Version + x.y.z of the clang compiler is encoded as x*10000+y*100+z (e.g., + version 3.4.1 is emulated with the option "``--clang_version + 30401``"). + * - | ``--embedded_c`` + | ``--no_embedded_c`` + - | Enable or disable support for all Embedded C language extensions + (fixed-point types, named address space qualifiers, and named-register + storage class specifiers). These options are not available with C++ + modes. + * - | ``--embedded_c++`` + - | Enable the diagnosis of noncompliance with the "Embedded C++" subset + (from which templates, exceptions, namespaces, new-style casts, RTTI, + multiple inheritance, virtual base classes, and ``mutable`` are + excluded). + * - | ``--g++`` + | ``--no_g++`` + - | Enable or disable GNU C++ language compatibility features. This + option also specifies that the source language being compiled is C++. + It is only recognized when ``GNU_EXTENSIONS_ALLOWED`` is TRUE. + * - | ``--gcc`` + | ``--no_gcc`` + - | Enable or disable GNU C language compatibility features. This option + also specifies that the source language being compiled is C. It is + only recognized when ``GNU_EXTENSIONS_ALLOWED`` is TRUE. + * - | ``--gnu_version`` *version-number* + | + - | The version of the GNU compiler that should be emulated in any of the + GNU (C or C++) modes. Version x.y.z of the GNU compiler is encoded as + x*10000+y*100+z (e.g., version 3.4.1 is emulated with the option + "``--gnu_version 30401``"). + * - | ``--microsoft`` + | ``--microsoft_16`` + | ``--no_microsoft`` + - | Enable or disable Microsoft emulation mode. These options may only be + used if ``MICROSOFT_EXTENSIONS_ALLOWED`` is TRUE. ``--microsoft`` + enables 32-bit mode. ``--microsoft_16`` enables 16-bit mode (i.e., + support for ``near`` and ``far``; the option is accepted only if + ``NEAR_AND_FAR_ALLOWED`` is TRUE). The default values are supplied by + ``DEFAULT_MICROSOFT_MODE`` and ``DEFAULT_NEAR_AND_FAR_ENABLED``. In + Microsoft emulation mode, language features that are not recognized by + the Microsoft compiler are disabled by default. In most cases these + features can then be enabled through use of other command line options + (for example, ``--bool``). Microsoft bugs mode is also enabled when + ``DEFAULT_MICROSOFT_BUGS`` is TRUE. + * - | ``--microsoft_version`` *version-number* + - | The version of the Microsoft compiler that should be emulated in + Microsoft mode. This enables or disables particular Microsoft mode + features when the acceptance of those features varies between versions + of the Microsoft compiler. The value specified is the value of the + predefined macro ``_MSC_VER`` supplied by the version of the Microsoft + compiler to be emulated. For example, 1100 is the value that + corresponds to Visual C++ version 5.0. This option also enables + Microsoft mode, but it does not imply either 16-bit or 32-bit mode + (i.e., it uses whatever value has already been specified, or the + default value if none has been explicitly specified). + * - | ``--microsoft_build_number`` *build-number* + - | The "build number" of the Microsoft compiler that should be emulated + in Microsoft mode (this option also enables Microsoft mode). This + value is used to set the value of the predeclared macro + ``_MSC_FULL_VER`` (which is a concatenation of the microsoft version + number and the build number; e.g., with "``--microsoft_version 1600 + --microsoft_build_number 30507``" ``_MSC_FULL_VER`` is defined to + expand to ``160030507``). The default build number is 99999. + * - | ``--microsoft_bugs`` + | ``--no_microsoft_bugs`` + - | Enable or disable recognition of certain Microsoft bugs. These + options also enable Microsoft mode. Microsoft bugs mode is + automatically enabled when Microsoft mode is used and + ``DEFAULT_MICROSOFT_BUGS`` is TRUE. + * - | ``--ms_await`` + - | Emulate the Microsoft Visual Studio ``/await`` command-line switch + that enables a pre-C++20 version of coroutines. + * - | ``--ms_await_strict`` + - | Emulate the Microsoft Visual Studio ``/await:strict`` command-line + switch that enables a pre-C++20 version of coroutines. + * - | ``--ms_c11`` + - | Emulate the Microsoft Visual Studio ``/std:c11`` command-line switch + by enabling the same set of C11 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1927 for this + option to have an effect. + * - | ``--ms_c17`` + - | Emulate the Microsoft Visual Studio ``/std:c17`` command-line switch + by enabling the same set of C17 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1928 for this + option to have an effect. + * - | ``--ms_c23`` + - | Emulate the Microsoft Visual Studio ``/std:c23`` command-line switch + by enabling the same set of C23 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1935 for this + option to have an effect. + * - | ``--ms_c++14`` + - | Emulate the Microsoft Visual Studio ``/std:c++14`` command-line switch + by enabling the same set of C++14 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1903 to use this + option. + * - | ``--ms_c++17`` + - | Emulate the Microsoft Visual Studio ``/std:c++17`` command-line switch + by enabling the same set of C++17 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1911 to use this + option. + * - | ``--ms_c++20`` + - | Emulate the Microsoft Visual Studio ``/std:c++20`` command-line switch + by enabling the same set of C++20 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1920 to use this + option. + * - | ``--ms_c++23`` + - | Emulate the Microsoft Visual Studio ``/std:c++23`` command-line switch + by enabling the same set of C++23 options that are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + ``microsoft_version`` must have a value of at least 1943 to use this + option. + * - | ``--ms_c++latest`` + - | Emulate the Microsoft Visual Studio ``/std:c++latest`` command-line + switch by enabling the same set of C++ options as are supported by the + Visual Studio version that corresponds to the value of + ``microsoft_version``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + * - | ``--ms_compatibility`` + | ``--no_ms_compatibility`` + - | Enable or disable certain Microsoft compatibility options (as defined + by the ``clang``\ ``-fms-compatibility`` option). Unlike the + ``--microsoft`` option (i.e., Microsoft emulation mode), this + command-line option can be combined with other emulation modes (e.g., + ``--clang``). Specifying ``--ms_compatibility`` implies + ``--ms_extensions``. If not specified explicitly with the + ``--microsoft_version`` command-line option, ``microsoft_version`` is + set to the value of the ``DEFAULT_MICROSOFT_VERSION`` macro. + * - | ``--ms_std_preprocessor`` + | ``--no_ms_std_preprocessor`` + - | Enable or disable a mode in which the behavior of the preprocessor in + Microsoft emulation mode conforms with the C and C++ Standards; when + disabled, the preprocessor emulates the behavior of the traditional + Microsoft preprocessor. + * - | ``--ms_stdc`` + | ``--no_ms_stdc`` + - | Emulate the ``/Zc:__STDC__`` option of Microsoft's Visual Studio by + setting the value of the ``__STDC__`` macro to the value ``1`` or + leaving the macro undefined respectively. Implicitly enables + Microsoft emulation mode. + * - | ``--ms_cplusplus_std_value`` + | ``--no_ms_cplusplus_std_value`` + | + - | Emulate the ``/Zc:__cplusplus[-]`` option of Microsoft's Visual Studio + by either setting the value of the ``__cplusplus`` macro to the value + implied by the C++ standard currently being implemented or leaving it + as the default value of ``199711L`` used by Visual Studio. Implicitly + enables Microsoft emulation mode. + * - | ``--ms_extensions`` + | ``--no_ms_extensions`` + - | Enable or disable certain Microsoft extensions (as defined by the + ``clang``\ ``-fms-extensions`` option). Unlike the ``--microsoft`` + option (i.e., Microsoft emulation mode), this command-line option can + be combined with other emulation modes (e.g., ``--clang``). If not + specified explicitly with the ``--microsoft_version`` command-line + option, ``microsoft_version`` is set to the value of the + ``DEFAULT_MICROSOFT_VERSION`` macro. + * - | ``--ms_permissive`` + | ``--no_ms_permissive`` + - | Enable or disable "permissive" mode during Microsoft emulation. These + command-line options control emulation of the Visual Studio + ``/permissive[-]`` command-line options and can be used in C, C++, + C++/CLI, or C++/CX modes. The default value is controlled by the + ``DEFAULT_MS_PERMISSIVE`` configuration macro. Specifying one of + these command-line options also implicitly enables Microsoft emulation + mode. + * - | ``--nonstd_gnu_keywords`` + | ``--no_nonstd_gnu_keywords`` + | + - | In GNU modes, ``--no_nonstd_gnu_keywords`` disables GNU-specific + keywords that do not start with underscores (notably: ``typeof``); the + option has no effect in other modes. ``--nonstd_gnu_keywords`` is + only accepted in GNU modes and enables any keywords that were disabled + by a prior occurrence of ``--no_nonstd_gnu_keywords``. + * - | ``--no_strict_gnu`` + | ``--strict_gnu`` + - | For every version of the C and C++ ISO standards, the GNU and Clang + compilers support both the language as defined by ISO (with + ``-std=c*`` command-line options) as well as the language with certain + incompatible compiler-specific extensions (with ``-std=gnu*``). + Specifying ``--strict_gnu`` on the command-line causes the front end + to emulate the ``-std=c*`` behavior of the selected GNU/Clang + compiler, while specifying ``--no_strict_gnu`` emulates the + ``-std=gnu*`` behavior. When these options are not specified, the + front end implicitly emulates the ``-std=c*`` behavior whenever any + ``--c*`` or ``--c++*`` command-line options are specified (e.g., + ``--c++11`` mimics ``-std=c++11``); otherwise the ``-std=gnu*`` + behavior is emulated. + * - | ``--strict_warnings`` or ``-a`` + | ``--strict`` or ``-A`` + - | Enable strict ANSI/ISO mode, which provides diagnostic messages when + nonstandard features are used, and disables features that conflict + with ANSI/ISO C or C++. This is compatible with both C and C++ mode. + It is not compatible with pcc mode. ANSI/ISO violations can be issued + as either warnings or errors depending on which command line option is + used. The ``-A`` and ``--strict`` options cause errors to be issued + whereas the ``-a`` and ``--strict_warnings`` options produce warnings. + (Note that nonstandard types, functions, etc., that might be + predeclared by various compilers will not be declared by the front end + in this mode, so any references to these names will be diagnosed as + errors, regardless of which of these options is specified.) The error + threshold is set so that the requested diagnostics will be listed. + * - | ``--stricter_template_checking`` + - | If a selected dialect weakens the type checking performed in a + template, adding this option makes it stricter again (although not + always as strict as what is done in strict ANSI/ISO mode). + * - | ``--sun`` + | ``--no_sun`` + - | Enable or disable Sun CC (version 5.x) language compatibility + features. This option can only be used in C++ mode, and cannot be + combined with options to enable strict ANSI mode, or compatibility + with cfront, Microsoft, or GNU. It is only recognized when + ``SUN_EXTENSIONS_ALLOWED`` is TRUE. + * - | ``--svr4`` + | ``--no_svr4`` + - | Enable or disable recognition of SVR4 C compatibility features. The + default value is supplied by ``DEFAULT_SVR4_C_MODE``. This option + also specifies that the source language being compiled is ANSI C. + * - | ``--upc`` + | ``--no_upc`` + - | Enable or disable UPC (Unified Parallel C) extensions. + * - | ``--upc_threads`` *n* + - | Specify a fixed number of UPC threads (this is the value of the + THREADS identifier). + * - | ``--upc_strict`` + | ``--upc_relaxed`` + - | Specify the default UPC access method for objects of shared types. + +Input/output Options +-------------------- + +The following options control the kind of input read or output produced or the +location of such input or output. + +.. list-table:: + + * - | ``--unicode_source_kind`` *kind* + | + - | Source input files that do not begin with a byte order mark indicating + the kind of Unicode encoding are assumed to use the Unicode encoding + indicated by *kind*. Possible values of *kind* are ``UTF-8``, + ``UTF-16``, ``UTF-16LE`` (little-endian), ``UTF-16BE`` (big-endian), + and ``none`` (to indicate that the source file is not Unicode). + * - | ``--gen_c_file_name`` *file-name* + | + - | When using the C-generating back end or the C++-generating back end, + this option specifies the file name to be used for the generated + output. + * - | ``--dependencies`` + | ``-M`` + - | Do preprocessing only. Instead of the normal preprocessing output, + generate on the preprocessing output file a list of dependency lines + suitable for input to the UNIX ``make`` program. Note that when + implicit inclusion of templates is enabled, the output may indicate + false (but safe) dependencies unless ``--no_preproc_only`` is also + used. + * - | ``--error_output`` *efile* + - | Redirect the output that would normally go to the error output + file (i.e., diagnostic messages) to the file *efile*. This option + is useful on systems where output redirection of files is not well + supported. If used, this option should probably be specified + first in the command line, since otherwise any command-line errors + for options preceding the ``--error_output`` would be written to + ``stderr`` before redirection. + * - | ``--list`` *lfile* + | ``-L``\ *lfile* + - | Generate raw listing information in the file *lfile*. This + information is likely to be used to generate a formatted listing. + The raw listing file contains raw source lines, information on + transitions into and out of include files, and diagnostics + generated by the front end. Each line of the listing file begins + with a key character that identifies the type of line, as follows: + + ``N``: + a normal line of source; the rest of the line is the text of the + line. + + ``X``: + the expanded form of a normal line of source; the rest of the + line is the text of the line. This line appears following the N + line, and only if the line contains non-trivial modifications + (comments are considered trivial modifications; macro expansions, + line splices, and trigraphs are considered non-trivial + modifications). Comments are replaced by a single space in the + expanded-form line. + + ``S``: + a line of source skipped by an #if or the like; the rest of the + line is text. Note that the #else, #elif, or #endif that ends a + skip is marked with an N. + + ``L``: + an indication of a change in source position. The line has a + format similar to the # line-identifying directive output by cpp, + that is to say + + ``L`` *line-number* ``"``\ *file-name*\ ``"`` *key* + + where *key* is 1 for entry into an include file, 2 for exit from an + include file, and omitted otherwise. The first line in the raw + listing file is always an L line identifying the primary input + file. L lines are also output for #line directives (*key* is + omitted). L lines indicate the source position of the following + source line in the raw listing file. + + ``R``, ``W``, ``E``, or ``C``: + an indication of a diagnostic (``R`` for remark, ``W`` for + warning, ``E`` for error, and ``C`` for catastrophic error). The + line has the form + + *S* ``"``\ *file-name*\ ``"`` *line-number column-number + message-text* + + where *S* is ``R``, ``W``, ``E``, or ``C``, as explained + above. Errors at the end of file indicate the last line of the + primary source file and a column number of zero. Command-line + errors are catastrophes with an empty file name (``""``) and a + line and column number of zero. Internal errors are catastrophes + with position information as usual, and message-text beginning + with (internal error). When a diagnostic displays a list (e.g., + all the contending routines when there is ambiguity on an + overloaded call), the initial diagnostic line is followed by one + or more lines with the same overall format (code letter, file + name, line number, column number, and message text), but in which + the code letter is the lower case version of the code letter in + the initial line. The source position in such lines is the same + as that in the corresponding initial line. + + * - | ``--list_macros`` + - | Do preprocessing only. Instead of the normal preprocessing output, + generate on the preprocessing output file a list of all the macros in + effect after processing the source file, including predefined and + command-line macros along with their definitions. + * - | ``--no_line_commands`` + | ``-P`` + - | Do preprocessing only. Write preprocessed text to the preprocessing + output file, with comments removed and without line control + information. + * - | ``--old_line_commands`` + - | When generating source output (e.g., with the C-generating back end), + put out ``#line`` directives in the form used by the Reiser cpp, i.e., + "``#`` *nnn*" instead of "``#line`` *nnn*". + * - | ``--output`` *ofile* + | ``-o`` *ofile* + - | Specify the output file of the compilation, i.e., the preprocessing or + intermediate language output file. + * - | ``--xref`` *xfile* + | ``-X``\ *xfile* + - | Generate cross-reference information in the file *xfile*. For each + reference to an identifier in the source program, a line of the form + + *symbol-id name ref-code file-name line-number column-number* + + | is written, where *ref-code* is ``D`` for definition, ``d`` for + declaration (that is, a declaration that is not a definition), ``T`` + for a full template instantiation, ``t`` for a partial template + instantiation (i.e., an instantiation of the template declaration, but + not of its definition), ``M`` for modification, ``A`` for address + taken, ``U`` for used, ``C`` for changed (but actually meaning "used + and modified in a single operation," such as an increment), ``R`` for + any other kind of reference, or ``E`` for an error in which the kind + of reference is indeterminate. *symbol-id* is a unique decimal number + for the symbol. The fields of the above line are separated by tab + characters. + * - | ``--create_header_unit`` *file* + - | Write an EDG IFC header unit file + representing the current translation unit to *file*. + * - | ``--create_module_interface`` *file* + | + - | Write an EDG IFC module file for a module interface unit to *file*. + * - | ``--create_module_internal_partition`` *file* + | + - | Write an EDG IFC module file for a module implementation unit to + *file*. + * - | ``--module_interface`` + - | Write an EDG IFC module file for a module interface unit in the + current working directory. The filename is derived from the parsed + module declaration. + * - | ``--module_internal_partition`` + | + - | Write an EDG IFC module file for a module implementation unit in the + current working directory. The filename is derived from the parsed + module declaration. + +Preprocessor Options +-------------------- + +The following options control the behavior of the preprocessor. + +.. list-table:: + + * - | ``--comments`` + | ``-C`` + - | Keep comments in the preprocessed output. This should be specified + after either ``--preprocess`` or ``--no_line_commands``; it does not + of itself request preprocessing output. + * - | ``--define_macro`` *name* [ ``(`` *parm-list* ``)`` ] [ = *def* ] + | ``-D`` *name* [ ``(`` *parm-list* ``)`` ] [ ``=`` *def* ] + | + - | Define macro *name* as *def*. If "``=`` *def* " is omitted, + define *name* as ``1``. Function-style macros can be defined by + appending a macro parameter list to *name*. + * - | ``--embed_directory`` *dir* + - | Add *dir* to the list of directories searched for ``#embed``\ s. The + process by which files named in #embed directives are found is similar + to that used for ``#include``. See :ref:`finding-includes`. + * - | ``--import_dir`` *dir-name* + - | Specify the directory in which the files to be included by ``#import`` + directives are to be found. These files must have been generated + previously by the Microsoft compiler. This option is valid only in + Microsoft mode. + * - | ``--incl_suffixes`` *str* + - | Specifies the list of suffixes to be used when searching for an + include file whose name was specified without a suffix. The + argument is a colon-separated list of suffixes (e.g., + ``"h:hpp::"``). If a null suffix is to be allowed, it must be + included in the suffix list. The default is specified by the + configuation flag ``DEFAULT_INCLUDE_FILE_SUFFIX_LIST``. + * - | ``--include_directory`` *dir* + | ``--sys_include`` *dir* + | ``-I``\ *dir* + - | Add *dir* to the list of directories searched for ``#include``\ s. + See :ref:`finding-includes`. + * - | ``--modules_directory`` *dir* + | + - | Add *dir* to the list of directories searched for module files when + processing an ``import`` directive. The current working directory is + automatically added to the start of this list. If the + ``EDG_MODULES_PATH`` environment variable is set, that path is added + to the end of the list. See :ref:`finding-modules`. + * - | ``--ms_header_unit`` *header_path*\ ``=``\ *module_file* + | ``--header_unit`` *header_path*\ ``=``\ *module_file* + | + - | Add *module_file* to the header unit map, corresponding to + *header_path*. When importing a header unit, if the resolved path + to the header matches *header_path*, then *module_file* is used as + the match. See :ref:`finding-modules`. + * - | ``--ms_header_unit_angle`` *header_path*\ ``=``\ *module_file* + | ``--ms_header_unit_quote`` *header_path*\ ``=``\ *module_file* + | + - | Add *module_file*, corresponding to *header_path*, to a header + unit map selected by the form in which *header_path* is written, + ``<...>`` and ``"..."``, respectively. Unlike --ms_header_unit, + *header_path* is not resolved immediately but will be resolved on + demand. (See :ref:`finding-includes`.) If the resolved path to + the header for the header unit matches the resolved *header_path*, + *module_file* is used as the match. See :ref:`finding-modules`. + * - | ``--ms_mod_file_map`` [ *module_name*\ ``=`` ] *file* + | + - | If *module_name* is omitted, *file* will be examined to determine + if the module it represents matches the module named in the + ``import`` directive. Otherwise, an import of *module_name* will + resolve to *file* without examining its contents. See + :ref:`finding-modules`. + * - | ``--ms_translate_include`` + | ``--no_ms_translate_include`` + | + - | Enable or disable the automatic translation of ``#include`` + directives into ``import`` directives when a header has a mapping + to a module file in a header unit map (see ``--ms_header_unit``, + ``--ms_header_unit_angle``, and ``--ms_header_unit_quote`` + regarding how such mappings are specified.) + * - | ``--old_style_preprocessing`` + | + - | Forces pcc style preprocessing when compiling in ANSI C or C++ mode. + This may be used when compiling an ANSI C or C++ program on a system + in which the system header files require pcc style preprocessing. + * - | ``--preinclude_macros`` *filename* + | ``--preinclude`` *filename* + - | Include the source code of the indicated file at the beginning of the + compilation. This can be used to establish standard macro + definitions, etc. The file name is searched for in the directories on + the include search list. When the ``preinclude_macros`` variant is + used, only the preprocessing directives from the file are evaluated. + All of the actual code is discarded. The effect of this option is + that any macro definitions from the specified file will be in effect + when the primary source file is compiled. All of the macro-only files + are processed before any of the normal preincludes. Within each + group, the files are processed in the order in which they were + specified. + * - | ``--preprocess`` + | ``-E`` + - | Do preprocessing only. Write preprocessed text to the preprocessing + output file, with comments removed and with line control information. + * - | ``--no_preproc_only`` + - | May be used in conjunction with the options that normally cause the + front end to do preprocessing only (e.g., ``--preprocess``, etc.) to + specify that a full compilation should be done (not just + preprocessing). When used with the implicit inclusion option, this + makes it possible to generate a preprocessed output file that includes + any implicitly included files. + * - | ``--stdc_zero_in_system_headers`` + | ``--no_stdc_zero_in_system_headers`` + | + - | Enable or disable special processing of the ``__STDC__`` macro + when referenced from system headers. When this feature is + enabled, ``__STDC__`` has the value zero in system header files + (files found in directories specified using the ``--sys_include`` + option) and one otherwise. This feature is provided to emulate + the behavior of ``gcc`` in certain configurations. The default is + specified by ``DEFAULT_STDC_ZERO_IN_SYSTEM_HEADERS``. If the flag + is not TRUE by default, the GNU mode default is specified by the + ``DEFAULT_GNU_STDC_ZERO_IN_SYSTEM_HEADERS`` macro. + * - | ``--trace_includes`` + | ``-H`` + - | Output a list of the names of files ``#include``\ d to the error + output file. The source file is compiled normally (i.e., it is not + just preprocessed) unless another option that causes preprocessing + only is specified. + * - | ``--undefine_macro`` *name* + | ``-U``\ *name* + - | Remove any initial definition of the macro *name*. + ``--undefine_macro`` options are processed after all + ``--define_macro`` options in the command line have been + processed. + * - | ``--check_concatenations`` + | ``--no_check_concatenations`` + | + - | Specifies whether or not the front end will issue a diagnostic if a + concatenation operator ``##`` in a macro expansion fails to produce a + valid preprocessor token as required by the C and C++ Standards. + * - | ``--no_token_separators_in_pp_output`` + | + - | Used in connection with options that generate preprocessing output, + suppresses the extra spaces the front end inserts in the text of macro + expansions to ensure that tokens that should not be combined remain + separate tokens. This can be used to prevent the insertion of + extraneous spaces when the front end is used as a preprocessor for + text that is not C or C++. + +Diagnostic Options +------------------ + +The following options control when or how diagnostics are emitted. + +.. list-table:: + + * - | ``--add_match_notes`` + | ``--no_add_match_notes`` + - | Enable or disable diagnostic notes that + provide further details for a failure to match candidates in an + overload set. + * - | ``--brief_diagnostics`` + | ``--no_brief_diagnostics`` + | + - | Enable or disable a mode in which a shorter form of the diagnostic + output is used. When enabled, the original source line is not + displayed and the error message text is not wrapped when too long to + fit on a single line. + * - | ``--colors`` + | ``--no_colors`` + - | Enable or disable colorization of diagnostic messages. The default + behavior is controlled by the ``DEFAULT_ENABLE_COLORIZED_DIAGNOSTICS`` + configuration macro (which defaults to TRUE). Colorized + diagnostics are disabled when not writing to a terminal, and are also + disabled when the ``NOCOLOR`` environment variable is set, the + ``TERM`` environment variable is unset, or the ``EDG_COLORS`` + environment variable is set to an empty string. + * - | ``--constexpr_diag_suppress`` *tag, tag,...* + | ``--constexpr_diag_remark`` *tag, tag,...* + | ``--constexpr_diag_warning`` *tag, tag,...* + | ``--constexpr_diag_error`` *tag, tag,...* + - | Override the severity of the diagnostics that calls of + ``__builtin_constexpr_diag`` request with any of the specified tags. + A tag is shown in brackets at the end of the diagnostic it names, and + may contain only letters, digits, and underscores. When more than + one of these options names a given tag, the last one on the command + line takes effect. + * - | ``--context_limit`` *number* + | + - | Set the context limit to *number*. The context limit is the maximum + number of template instantiation context entries to be displayed as + part of a diagnostic message. The default is specified by the + ``DEFAULT_CONTEXT_LIMIT`` macro. If the number of context entries + exceeds the limit, the first and last N context entries are displayed, + where N is half of the context limit. A value of zero is used to + indicate that there is no limit. + * - | ``--diag_suppress`` *tag, tag,...* + | ``--diag_remark`` *tag, tag,...* + | ``--diag_warning`` *tag, tag,...* + | ``--diag_error`` *tag, tag,...* + - | Override the normal error severity of the specified diagnostic + messages. The message(s) may be specified using a mnemonic error tag + or using an error number. The error tag names and error numbers are + listed in the Error Messages appendix. + * - | ``--diag_once`` *tag, tag,...* + - | Causes the specified diagnostic to be issued only once as a warning or + remark. The message(s) may be specified using a mnemonic error tag or + using an error number. The error tag names and error numbers are + listed in the Error Messages appendix. + * - | ``--display_error_number`` + | ``--no_display_error_number`` + | + - | Enable or disable the display of an error message number in any + diagnostic messages that are generated. The option may be used to + determine the error number to be used when overriding the severity of + a diagnostic message. The configuration macro + ``DEFAULT_DISPLAY_ERROR_NUMBER`` specifies the default behavior. + * - | ``--error_limit`` *number* + | ``-e`` *number* + - | Set the error limit to *number*. The front end will abandon + compilation after this number of errors (remarks and warnings are + not counted toward the limit). By default, the limit is 100. + * - | ``--for_init_diff_warning`` + | ``--no_for_init_diff_warning`` + | + - | Enable or disable a warning that is issued when programs compiled + under the new for-init scoping rules would have had different behavior + under the old rules. The diagnostic is only put out when the new + rules are used. ``DEFAULT_WARNING_ON_FOR_INIT_DIFFERENCE`` specifies + the default behavior. This option is valid only in C++ mode. + * - | ``--lossy_conversion_warning`` + | ``--no_lossy_conversion_warning`` + | + - | Enable or disable a warning that is issued when conversion of an + arithmetic value to a different type might result in lost data because + the target type cannot represent all the values of the source type. + * - | ``--macro_positions_in_diagnostics`` + | ``--no_macro_positions_in_diagnostics`` + | + - | Enable or disable display of extra information for diagnostics that + refer to text in macro expansions. These options may only be used if + ``FULLY_RESOLVED_MACRO_POSITIONS`` is TRUE. The additional + information includes the original source line from which the text + identified by the message was copied into the macro expansion (i.e., a + macro definition or an argument in the top-level macro invocation), as + well as the chain of macro invocations that led to the expanded text + designated by the diagnostic (if ``MACRO_INVOCATION_TREE_IN_IL`` is + TRUE). The default value is given by + ``DEFAULT_MACRO_POSITIONS_IN_DIAGNOSTICS``. + * - | ``--module_import_diagnostics`` + | ``--no_module_import_diagnostics`` + | + - | Enable or disable the issuing of diagnostics while importing entities + from module files. + * - | ``--output_mode`` *mode* + - | Set the front end diagnostic output mode to *mode*. Valid modes + are ``text`` for traditional command line diagnostic output and + ``sarif`` for SARIF (Static Analysis Results Interchange Format) + output (see `www.sarif.info `__). + * - | ``--promote_warnings`` + | ``-W`` + - | Issue all warnings as if they were discretionary errors.`` + * - | ``--remarks`` + | ``-r`` + - | Issue remarks, which are diagnostic messages even milder than + warnings. + * - | ``--report_gnu_extensions`` + | + - | Warn about the use of certain GNU extensions outside system header + files. Only valid in GNU C or C++ mode. + * - | ``--template_typedefs_in_diagnostics`` + | ``--no_template_typedefs_in_diagnostics`` + | + - | Disable or enable, respectively, the replacement of typedefs + declared in template classes with their underlying type. + Diagnostic messages are often more useful when such typedefs are + replaced. The default behavior is specified by the + ``DEFAULT_TEMPLATE_TYPEDEFS_IN_DIAGNOSTICS`` macro. + * - | ``--timing`` + | ``-#`` + - | Generate compilation timing information. This option causes the + compiler to display the amount of CPU time and elapsed time used by + each phase of the compilation and a total for the entire compilation. + * - | ``--top_templates`` *number* + - | At the end of the compilation, write to the error output file a report + of the templates that were substituted the most. *number* specifies + how many templates to report; if it is zero, every template that has a + nonzero number of substitutions is reported. + * - | ``--no_use_before_set_warnings`` + | ``-j`` + - | Suppress warnings on local automatic variables that are used before + their values are set. The front end's algorithm for detecting such + uses is conservative and is likely to miss some cases that an + optimizer with sophisticated flow analysis could detect; thus, an + implementation might choose to suppress the warnings from the front + end when optimization has been requested but to permit them when the + optimizer is not being run. + * - | ``--no_warnings`` + | ``-w`` + - | Suppress warnings. Errors are still issued. + * - | ``--wrap_diagnostics`` + | ``--no_wrap_diagnostics`` + - | Enable or disable a mode in which the error message text is not + wrapped when too long to fit on a single line. + +Individual Language Features +---------------------------- + +The following options enable or disable specific language syntax. (Options +that affect the meaning of existing constructs are listed in +:ref:`cli-alt-lang-behaviors`.) + +.. list-table:: + + * - | ``--alternative_tokens`` + | ``--no_alternative_tokens`` + | + - | Enable or disable recognition of alternative tokens. This controls + recognition of the digraph tokens in C and C++, and controls + recognition of the operator keywords (e.g., ``and``, ``bitand``, etc.) + in C++. The default behavior is specified by the + ``DEFAULT_ALTERNATIVE_TOKENS_ALLOWED`` configuration constant. + * - | ``--array_new_and_delete`` + | ``--no_array_new_and_delete`` + | + - | Enable or disable support for array new and delete. The default + behavior is specified by the configuration constant + ``DEFAULT_ARRAY_NEW_AND_DELETE_ENABLED``. This option is valid only + in C++ mode. The front end can be configured to define a + preprocessing variable when array new and delete are enabled. This + preprocessing variable may then be used by the standard header files + to decide whether to include the declarations for the array new/delete + functions. + * - | ``--auto_storage`` + | ``--no_auto_storage`` + - | Enable or disable the traditional meaning of ``auto`` as a storage + class specifier (only valid in C++ mode). (If disabled, then ``auto`` + must be a type specifier.). The default behavior is specified by the + ``DEFAULT_AUTO_STORAGE_CLASS_SPECIFIER_ENABLED`` configuration + constant. + * - | ``--auto_type`` + | ``--no_auto_type`` + - | Enable or disable ``auto`` as a type specifier where the actual type + is deduced from an initializer (only valid in C++ mode). This is a + C++11 feature. If enabled, the traditional meaning of ``auto`` as a + storage class specifier is disabled (which matches C++11), unless the + option ``--auto_storage`` is also supplied. The default behavior is + specified by the ``DEFAULT_AUTO_TYPE_SPECIFIER_ENABLED`` configuration + constant. + * - | ``--bit_precise_integers`` + | ``--no_bit_precise_integers`` + - | Enable or disable support for C23-style ``_BitInt`` types. + * - | ``--bool`` + | ``--no_bool`` + - | Enable or disable recognition of ``bool``. The default value is + supplied by ``DEFAULT_BOOL_IS_KEYWORD``. This option is valid only in + C++ mode. The front end can be configured to define a preprocessing + variable when ``bool`` is recognized. This preprocessing variable may + then be used by header files to determine whether a typedef should be + supplied to define ``bool``. + * - | ``--c23_typeof`` + | ``--no_c23_typeof`` + - | Enable or disable support for the C23 ``typeof`` and + ``typeof_unqual`` operators, regardless of the current C language + level. This option is valid only in C mode. + * - | ``--c++11_sfinae`` + | ``--no_c++11_sfinae`` + - | Enable or disable template deduction in the style dictated by the + C++11 standard, i.e., where general expressions are allowed in + deduction contexts and they undergo the full usual semantic + checking. This type of deduction is necessary to get the full + power of the ``decltype`` feature in return types. ("SFINAE" is + an acronym for "Substitution Failure Is Not An Error", which is + the guiding principle for template deduction, and by extension a + name for the process of deduction.) + * - | ``--c++11_sfinae_ignore_access`` + | ``--no_c++11_sfinae_ignore_access`` + | + - | When new-style SFINAE is enabled, these options control whether or not + access errors cause deduction failures. The positive option indicates + that access checking should not be done during template deduction, and + therefore that access errors cannot cause a deduction failure; this + was the status quo ante when the new-style SFINAE rules were proposed. + The "``no``" version of the option indicates that access checking + should be done during template deduction, and therefore that access + errors cause a deduction failure; this is the revised direction chosen + by the standards committee. + * - | ``--char8_t`` + | ``--no_char8_t`` + | + - | Enable or disable support for the ``char8_t`` keyword and type (a + C++20 feature). Enabled by default in C++20 mode. + * - | ``--compound_literals`` + | ``--no_compound_literals`` + - | Enable or disable support for "compound literals" (a C99 feature). + * - | ``--concepts`` + | ``--no_concepts`` + | + - | Enable or disable support for concepts (a C++20 feature). + * - | ``--delegating_constructors`` + | ``--no_delegating_constructors`` + | + - | Enable or disable delegating constructors (a C++11 feature). + * - | ``--deprecated_string_conv`` + | ``--no_deprecated_string_conv`` + | + - | Enable or disable the deprecated conversion from a string literal to + ``char *``. Meaningful only when string literals are const. + * - | ``--designators`` + | ``--no_designators`` + - | Enable or disable support for designators (a C99 feature). These + options are not available in C++ mode. + * - | ``--digit_separators`` + | ``--no_digit_separators`` + - | Enable or disable support for digit separators (a C++14 feature). + When this feature is enabled, an apostrophe can appear between the + digits of a numeric literal and is ignored, e.g., ``123'456'789``. + * - | ``--extended_designators`` + | ``--no_extended_designators`` + | + - | Enable or disable support for "extended designators," an extension + accepted only in C mode to emulate the behavior of certain other C + compilers when it comes to designators in aggregate initializers. + * - | ``--dollar`` + | ``-$`` + - | Accept dollar signs in identifiers. The default value of this option + is specified in a configuration file. + * - | ``--exceptions--no_exceptions`` + | ``-x`` + - | Enable or disable support for exception handling. ``-x`` is + equivalent to ``--exceptions``. The default behavior is specified by + the configuration constant ``DEFAULT_EXCEPTIONS_ENABLED``. This + option is valid only in C++ mode. + * - | ``--exc_spec_in_func_type`` + | ``--no_exc_spec_in_func_type`` + - | Enable or disable exceptions being part of a function type (enabled by + default in C++17 modes and disabled by default otherwise). + * - | ``--explicit`` + | ``--no_explicit`` + - | Enable or disable support for the ``explicit`` specifier on + constructor declarations. The default behavior is specified by the + configuration constant ``DEFAULT_EXPLICIT_KEYWORD_ENABLED``. This + option is valid only in C++ mode. + * - | ``--export`` + | ``--no_export`` + - | Enable or disable recognition of exported templates. The default + value is supplied by ``DEFAULT_EXPORT_TEMPLATE_ALLOWED``. This option + is valid only in C++ mode. This option requires that dependent name + processing be done, and cannot be used with implicit inclusion of + template definitions. + * - | ``--extern_inline`` + | ``--no_extern_inline`` + - | Enable or disable support for ``inline`` functions with external + linkage in C++. When ``inline`` functions are allowed to have + external linkage (as required by the standard), then ``extern`` and + ``inline`` are compatible specifiers on a nonmember function + declaration; the default linkage when ``inline`` appears alone is + external (that is, ``inline`` means ``extern inline`` on nonmember + functions); and an ``inline`` member function takes on the linkage of + its class (which is usually external). However, when ``inline`` + functions have only internal linkage (as specified in the ARM), then + ``extern`` and ``inline`` are incompatible; the default linkage when + ``inline`` appears alone is internal (that is, ``inline`` means + ``static inline`` on nonmember functions); and ``inline`` member + functions have internal linkage no matter what the linkage of their + class. + * - | ``--fixed_point`` + | ``--no_fixed_point`` + - | Enable or disable support for Embedded C fixed-point types. (Not + available in C++ modes.) + * - | ``--lambdas`` + | ``--no_lambdas`` + - | Enable or disable support for C++11 lambdas. (Only available in C++ + modes.) + * - | ``--long_long`` + - | Permit the use of ``long long`` in strict mode in dialects in which it + is non-standard. + * - | ``--modules`` + | ``--no_modules`` + - | Enable or disable support for modules. Modules are currently + experimental and will be enabled by default in future releases in the + applicable modes. The front end does not currently generate modules + files of its own and can only consume module files produced by + Microsoft Visual Studio version 16.8. This support is incomplete and + compatibility will change in future releases. + | + * - | ``--multibyte_chars`` + | ``--no_multibyte_chars`` + - | Enable or disable processing for multibyte character sequences in + comments, string literals, and character constants. The default + behavior is specified by + ``DEFAULT_MULTIBYTE_CHARS_IN_SOURCE_ALLOWED``. Multibyte encodings + are used for character sets like the Japanese SJIS. + * - | ``--named_address_spaces`` + | ``--no_named_address_spaces`` + | + - | Enable or disable support for Embedded C named address space + qualifiers. (Not available in C++ modes.) + * - | ``--named_registers`` + | ``--no_named_registers`` + - | Enable or disable support for Embedded C named-register storage class + specifiers. (Not available in C++ modes.) + * - | ``--namespaces`` + | ``--no_namespaces`` + - | Enable or disable support for namespaces. The default behavior is + specified by the configuration constant + ``DEFAULT_NAMESPACES_ENABLED``. This option is valid only in C++ + mode. + * - | ``--nonstd_using_decl`` + | ``--no_nonstd_using_decl`` + | + - | In C++, controls whether a nonmember using-declaration that specifies + an unqualified name is allowed. + * - | ``--nullptr`` + | ``--no_nullptr`` + - | Enable or disable support for the C++11/C23 ``nullptr`` keyword. + * - | ``--old_specializations`` + | ``--no_old_specializations`` + | + - | Enable or disable acceptance of old-style template specializations + (i.e., specializations that do not use the ``template<>`` syntax). + Default behavior is specified by + ``DEFAULT_OLD_SPECIALIZATIONS_ALLOWED``. This option is valid only in + C++ mode. + * - | ``--relaxed_abstract_checking`` + | ``--no_relaxed_abstract_checking`` + | + - | Enable or disable a mode in which checking for the use abstract class + types as function parameter or return types is performed only when the + function is defined or called. Traditionally this checking has been + performed on non-defining function declarations as well, and this + behavior can be preserved via the second option. + * - | ``--restrict`` + | ``--no_restrict`` + - | Enable or disable recognition of the ``restrict`` keyword. + * - | ``--rtti`` + | ``--no_rtti`` + - | Enable or disable support for RTTI (runtime type information) + features: ``dynamic_cast``, ``typeid``. The default behavior is + specified by the configuration constant ``DEFAULT_RTTI_ENABLED``. + This option is valid only in C++ mode. + * - | ``--rvalue_ctor_is_copy_ctor`` + | ``--rvalue_ctor_is_not_copy_ctor`` + | + - | Determines whether an rvalue (or "move") constructor is treated as a + copy constructor (the default) or not. If rvalue constructors are + treated as copy constructors, a user-declared rvalue constructor will + inhibit the implicit generation of a traditional copy constructor. + * - | ``--rvalue_refs`` + | ``--no_rvalue_refs`` + - | Enable or disable support for rvalue references. (Only valid in C++ + mode.) + * - | ``--sun_linker_scope`` + | ``--no_sun_linker_scope`` + | + - | Enable or disable support for Sun CC 5.5 link scope specifiers + (``__global``, ``__symbolic``, and ``__hidden``). The default setting + is supplied by ``DEFAULT_SUN_LINKER_SCOPE_ALLOWED``. + * - | ``--thread_local_storage`` + | ``--no_thread_local_storage`` + | + - | Enable or disable the C++11 ``thread_local`` specifier (and, if so + configured, the ``__thread`` specifier) to indicate that variables + should be stored in thread-local storage. By default, the + ``__thread`` specifier is enabled in Sun mode and in GNU mode when + ``gnu_version`` >= 30400. + * - | ``--trigraphs`` + | ``--no_trigraphs`` + | + - | Enable or disable recognition of trigraphs. The default behavior is + specified by the ``DEFAULT_TRIGRAPHS_ALLOWED`` configuration constant. + * - | ``--typename`` + | ``--no_typename`` + - | Enable or disable recognition of ``typename``. The default value is + supplied by ``DEFAULT_TYPENAME_ENABLED``. This option is valid only + in C++ mode. + * - | ``--type_traits_helpers`` + | ``--no_type_traits_helpers`` + | + - | Enable or disable support for type traits helpers (like ``__is_union`` + and ``__has_virtual_destructor``; intended to ease the implementation + of ISO/IEC TR 19768). Only valid in C++. Type traits helpers are + enabled in all C++ modes by default, except in GNU and Sun C++ modes. + * - | ``--uliterals`` + | ``--no_uliterals`` + - | Enable or disable recognition of U-literals (string literals of the + forms ``U"..."`` and ``u"..."``, and character literals of the forms + ``U'...'`` and ``u'...'``). In C++ mode, this also enables or + disables the C++11 ``char16_t`` and ``char32_t`` keywords. + * - | ``--unrestricted_unions`` + | ``--no_unrestricted_unions`` + | + - | Enable or disable C++11-style "unrestricted unions" (i.e., unions with + data members that have nontrivial initialization and/or destruction + semantics). This option can currently not be enabled in Microsoft + mode. + * - | ``--user_defined_literals`` + | ``--no_user_defined_literals`` + | + - | Enable or disable C++11-style "user-defined literals," i.e., + literals with a suffix designating an operator function that is to + be called to produce the value of the literal, e.g., ``12.34_km``, + which calls ``operator ""_km(12.34)``. + * - | ``--utf8_char_literals`` + | ``--no_utf8_char_literals`` + | + - | Enable or disable C++17-style ``UTF-8`` character literals (e.g., + ``u8'a'``). Enabled by default in C++17 mode as well as when + ``microsoft_version`` >= 1900. + * - | ``--variadic_macros`` + | ``--no_variadic_macros`` + - | Enable or disable support for variadic macros (a C99 feature that is + also available in C++ mode). + * - | ``--extended_variadic_macros`` + | ``--no_extended_variadic_macros`` + | + - | Enable or disable support for "extended variadic macros," an extension + that emulates the behavior of certain other C compilers when it comes + to variadic macros. + * - | ``--variadic_templates`` + | ``--no_variadic_templates`` + | + - | Enable or disable support for "variadic templates," a C++11 feature + that allows declaration of templates with a variable number of + arguments. The default value is dependent on the major language mode + and on ``DEFAULT_VARIADIC_TEMPLATES_ENABLED``. This option is valid + only in C++ modes. + * - | ``--vla`` + | ``--no_vla`` + - | Enable or disable support for "variable length arrays," a C99 feature + and an extension in some other modes that allows the declaration and + use of arrays of automatic storage duration with dimensions that are + fixed at run time. These options are available only if + ``VLA_ALLOWED`` is configured to TRUE. + * - | ``--wchar_t_keyword`` + | ``--no_wchar_t_keyword`` + - | Enable or disable recognition of ``wchar_t`` as a keyword. The + default value is supplied by ``DEFAULT_WCHAR_T_IS_KEYWORD``. This + option is valid only in C++ mode. The front end can be configured to + define a preprocessing variable when ``wchar_t`` is recognized as a + keyword. This preprocessing variable may then be used by the standard + header files to determine whether a typedef should be supplied to + define ``wchar_t``. + +.. _cli-alt-lang-behaviors: + +Alternative Language Behaviors +------------------------------ + +The following options affect the meaning of various language constructs. + +.. list-table:: + + * - | ``--aligned_new`` + | ``--no_aligned_new`` + | + - | Enable or disable calling special allocation and deallocation + functions for types with more stringent alignment requirements than + the fundamental types (enabled by default in C++17 modes and disabled + otherwise). + * - | ``--arg_dep_lookup`` + | ``--no_arg_dep_lookup`` + | + - | In C++, controls whether argument dependent lookup of unqualified + function names is performed + * - | ``--base_assign_op_is_default`` + | ``--no_base_assign_op_is_default`` + | + - | Enable or disable the anachronism of accepting a copy assignment + operator that has an input parameter that is a reference to a base + class as a default copy assignment operator for the derived class. + This option is enabled by default in cfront compatibility mode. + * - | ``--class_name_injection`` + | ``--no_class_name_injection`` + | + - | In C++, controls whether the name of a class is injected into the + scope of the class (as required by the standard) or is not injected + (as was true in earlier versions of the C++ language). + * - | ``--const_string_literals`` + | ``--no_const_string_literals`` + | + - | Control whether C++ string literals and wide string literals are const + (as required by the standard) or non-const (as was true in earlier + versions of the C++ language). + * - | ``--default_calling_convention`` *calling-convention* + | + - | The calling convention that should be assumed for functions that are + declared without an explicit calling convention. This option may only + be used if ``MICROSOFT_EXTENSIONS_ALLOWED`` is TRUE. + *calling-convention* must be one of ``__cdecl``, ``__fastcall``, + ``__stdcall``, and ``__thiscall``. + * - | ``--default_nocommon_tentative_definitions`` + | ``--default_common_tentative_definitions`` + | + - | Control whether tentative definitions are placed in "common" storage. + These options are only available in configurations with + ``GNU_EXTENSIONS_ALLOWED`` set to TRUE. The default can be overridden + for specific variables with the GNU attributes ``common`` and + ``nocommon``. + * - | ``--defer_parse_function_templates`` + | ``--no_defer_parse_function_templates`` + | + - | Enable or disable deferral of prototype instantiations until the + first actual instantiation of a function. This is used to permit + the compilation of programs that contain definitions of unusable + function templates. It is enabled by default in g++ mode when + ``gnu_version`` is >= 30400 (but not when using the C++-generating + back end). + * - | ``--dep_name`` + | ``--no_dep_name`` + - | Enable or disable dependent name processing; i.e., the special lookup + of names used in templates as required by the C++ standard. The + default value is supplied by ``DEFAULT_DEPENDENT_NAME_PROCESSING``. + This option is valid only in C++ mode and ``--dep_name`` cannot be + combined with ``--no_parse_templates``. + * - | ``--distinct_template_signatures`` + | ``--no_distinct_template_signatures`` + | + - | Control whether the signatures for template functions can match those + for non-template functions when the functions appear in different + compilation units. (This option is available only on versions that do + name mangling on the names of external entities.) The default is + ``--distinct_template_signatures``, under which a normal function + cannot be used to satisfy the need for a template instance; e.g., a + function "``void f(int)``" could not be used to satisfy the need for + an instantiation of a template "``void f(T)``" with ``T`` set to + ``int``. ``--no_distinct_template_signatures`` provides the older + language behavior, under which a non-template function can match a + template function. Also controls whether function templates may have + template parameters that are not used in the function signature of the + function template. + * - | ``--enum_overloading`` + | ``--no_enum_overloading`` + - | Enable or disable support for using operator functions to overload + builtin operations on enum-typed operands. + * - | ``--far_data_pointers`` + | ``--near_data_pointers`` + | ``--far_code_pointers`` + | ``--near_code_pointers`` + - | Set the default size for pointers when support for ``near`` and + ``far`` is enabled (e.g., in Microsoft 16-bit mode). Ignored in other + modes. + * - | ``--friend_injection`` + | ``--no_friend_injection`` + | + - | In C++, controls whether the name of a class or function that is + declared only in friend declarations is visible when using the normal + lookup mechanisms. When friend names are injected, they are visible + to such lookups. When friend names are not injected (as required by + the standard), function names are visible only when using + argument-dependent lookup, and class names are never visible. + * - | ``--func_prototype_tags`` + | ``--no_func_prototype_tags`` + - | in C, controls whether tag types first + declared in a function prototype belong to the function prototype + scope (standard C behavior) or to a surrounding scope (default + Microsoft C behavior). + * - | ``--gcc89_inlining`` + - | Use the GNU C89 semantics of ``inline`` in C99 mode. (Not valid in + C++ modes.) + * - | ``--gen_move_operations`` + | ``--no_gen_move_operations`` + | + - | Enable or disable the generation of move constructors and move + assignment operators according to standard C++11 rules. + * - | ``--guiding_decls`` + | ``--no_guiding_decls`` + - | Enable or disable recognition of "guiding declarations" of template + functions. A guiding declaration is a function declaration that + matches an instance of a function template but has no explicit + definition (since its definition derives from the function template). + For example: + + .. code:: c++ + + template void f(T) { ... } + void f(int); + + | When regarded as a guiding declaration, ``f(int)`` is an instance of + the template; otherwise, it is an independent function for which a + definition must be supplied. If ``--no_guiding_decls`` is combined + with ``--old_specializations``, a specialization of a non-member + template function is not recognized -- it is treated as a definition + of an independent function. Default behavior is specified by + ``DEFAULT_GUIDING_DECLS_ALLOWED``. This option is valid only in C++ + mode. + * - | ``--ignore_std`` + - | Enable a ``g++`` compatibility feature that makes the ``std`` + namespace a synonym for the global namespace. + * - | ``--implicit_extern_c_type_conversion`` + | ``--no_implicit_extern_c_type_conversion`` + | + - | Enable or disable an extension to permit implicit type conversion in + C++ between a pointer to an ``extern "C"`` function and a pointer to + an ``extern "C++"`` function. This extension is allowed in + environments where C and C++ functions share the same calling + conventions: ``IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE`` + must be set for it to be available. (It is useful for cfront + compatibility when ``DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT`` + is TRUE -- in standard C++ the linkage specification is part of the + function type, with the consequence that otherwise identical function + types, one declared ``extern "C"`` and the other declared ``extern + "C++"``, are viewed as distinct.) + * - | ``--implicit_noexcept`` + | ``--no_implicit_noexcept`` + | + - | Enable or disable the implicit generation of exception specifications + for user-declared destructors and deallocation functions in C++11 + mode. (In strict C++11 mode, it is enabled by default, whereas in + other C++11 modes it is disabled by default.) + * - | ``--implicit_typename`` + | ``--no_implicit_typename`` + | + - | Enable or disable implicit determination, from context, whether a + template parameter dependent name is a type or nontype. The default + value is supplied by ``DEFAULT_IMPLICIT_TYPENAME_ENABLED``. This + option is valid only in C++ mode. + * - | ``--late_tiebreaker`` + | ``--early_tiebreaker`` + - | Select the way that tie-breakers (e.g., cv-qualifier differences) + apply in overload resolution. In "early" tie-breaker processing, the + tie-breakers are considered at the same time as other measures of the + goodness of the match of an argument value and the corresponding + parameter type (this is the standard approach). In "late" tiebreaker + processing, tie-breakers are ignored during the initial comparison, + and considered only if two functions are otherwise equally good on all + arguments; the tie-breakers can then be used to choose one function + over another. + * - | ``--long_lifetime_temps`` + | ``--short_lifetime_temps`` + | + - | Select the lifetime for temporaries: "short" means to end of full + expression; "long" means to the earliest of end of scope, end of + switch clause, or the next label. "short" is standard C++, and "long" + is what cfront uses (the cfront compatibility modes select "long" by + default). + * - | ``--long_preserving_rules`` + | ``--no_long_preserving_rules`` + | + - | Enable or disable the K&R usual arithmetic conversion rules with + respect to ``long``. This means the rules of K&R I, Appendix A, 6.6, + not the rules used by the pcc compiler. The significant difference is + in the handling of "``long`` *op* ``unsigned int``" when ``int`` and + ``long`` are the same size. The ANSI/ISO/pcc rules say the result is + ``unsigned long``, but K&R I says the result is ``long`` (``unsigned + long`` did not exist in K&R I). + * - | ``--max_depth_constexpr_call=`` *n* + | ``--max_cost_constexpr_call=`` *n* + | + - | Specify the maximum depth of recursion or the maximum "cost" for + folding a top-level ``constexpr`` call (function or constructor). In + C++11 modes, the "cost" is the number of calls expanded from a single + top-level call. In C++14 modes, the "cost" is a combination of the + number of calls interpreted and the number of loop iterations + performed during the interpretation of a top-level call. + * - | ``--ms_rvalue_cast`` + | ``--no_ms_rvalue_cast`` + | + - | Explicitly disable or enable treating a cast of an lvalue to its own + type as that same lvalue. (``--ms_rvalue_cast`` corresponds to + standard behavior, but Microsoft compilers traditionally behaved + otherwise.) Implies Microsoft mode. + * - | ``--ms_strict_ternary`` + | ``--no_ms_strict_ternary`` + | + - | Enable or disable strict standard-conforming behavior of the + conditional ternary operator (?:) in Microsoft mode. It is disabled + by default in Microsoft mode, unless Microsoft permissive mode is + disabled (see ``--no_ms_permissive``). Implies Microsoft mode. + * - | ``--nonconst_ref_anachronism`` + | ``--no_nonconst_ref_anachronism`` + | + - | Enable or disable the anachronism of allowing a reference to nonconst + to bind to a class rvalue of the right type. This anachronism is also + enabled by the ``--anachronisms`` option and the cfront-compatibility + options. + * - | ``--nonstd_anonymous_unions`` + | ``--no_nonstd_anonymous_unions`` + | + - | Enable or disable extensions to the C++ anonymous union feature + (including of anonymous "structs" or "classes"). This option can also + be used in C modes. Enabled by default in GNU and Microsoft modes, + and disabled by default in strict modes. + * - | ``--nonstd_default_arg_deduction`` + | ``--no_nonstd_default_arg_deduction`` + | + - | Controls whether default arguments are retained as part of deduced + function types. The C++ standard requires that default arguments not + be part of deduced function types. + * - | ``--nonstd_instantiation_lookup`` + | ``--no_nonstd_instantiation_lookup`` + | + - | Controls whether the lookup of names during template instantiation + should, instead of the normal lookup rules, use rules that were part + of the C++98 working paper for some time during the development of the + standard. In this mode, names are looked up in both the namespace of + the template definition and in the namespace in which a template + entity was first referenced in a way that would require an + instantiation. + * - | ``--nonstd_qualifier_deduction`` + | ``--no_nonstd_qualifier_deduction`` + | + - | Controls whether nonstandard template argument deduction should be + performed in the qualifier portion of a qualified name. With this + feature enabled, a template argument for the template parameter ``T`` + can de deduced in contexts like ``A::B`` or ``T::B``. The standard + deduction mechanism treats these as nondeduced contexts that use the + values of template parameters that were either explicitly specified or + deduced elsewhere. + * - | ``--old_id_chars`` + | ``--no_old_id_chars`` + - | Controls whether the set of extended characters accepted in C++ + identifiers should be those specified by pre-C++23 C++ standards or by + Unicode Standard Annex #44. The latter is the default in all C++ + modes, because the C++ Standard Committee adopted the Unicode + specification of identifier characters both for C++23 and + retroactively for earlier standards. + * - | ``--old_for_init`` + | ``--new_for_init`` + - | Control the scope of a declaration in a ``for-init-statement``. The + old (cfront-compatible) scoping rules mean the declaration is in the + scope to which the ``for`` statement itself belongs; the new + (standard-conforming) rules in effect wrap the entire ``for`` + statement in its own implicitly generated scope. The default behavior + is specified by configuration constant + ``DEFAULT_USE_NONSTANDARD_FOR_INIT_SCOPE``. This option is valid only + in C++ mode. + * - | ``--pack_alignment`` *n* + - | Set the default alignment for packing classes and structs to *n*, a + power-of-2 value within the range defined by + ``TARG_MINIMUM_PACK_ALIGNMENT`` and ``TARG_MAXIMUM_PACK_ALIGNMENT``. + The argument *n* is the default maximum alignment for nonstatic data + members; it can be overridden by a ``#pragma pack`` directive. This + option is allowed only when ``USER_CONTROL_OF_STRUCT_PACKING`` is + TRUE. + * - | ``--parse_templates`` + | ``--no_parse_templates`` + | + - | Enable or disable the parsing of nonclass templates in their generic + form (i.e., even if they are not really instantiated). It is done by + default if dependent name processing is enabled. This option is valid + only in C++ mode. + * - | ``--preserve_lvalues_with_same_type_casts`` + | ``--no_preserve_lvalues_with_same_type_casts`` + | + - | Explicitly enable or disable treating a cast of an lvalue to its own + type as that same lvalue (whereas both C and C++ specify that such + casts result in rvalues). Enabled by default in Microsoft and Sun + modes. + * - | ``--require_func_prototypes`` + | ``--no_require_func_prototypes`` + - | In C, controls whether old-style non-prototype function declarators + are recognized. If not, something like "``int f();``" is equivalent + to "``int f(void);``". The default is that non-prototype function + declarators are not recognized in C23 mode, while they are recognized + in earlier C modes. + * - | ``--short_enums`` + | ``--no_short_enums`` + - | Enable or disable a mode in which all enumeration types are "packed" + (meaning that the underlying type of the enumeration is chosen to be + the smallest integer that will accommodate the enumerator constants). + Only valid in GNU C compatibility mode. + * - | ``--signed_bit_fields`` + | + - | Make bit fields declared with a plain integer type (e.g., ``short`` or + ``int``, but not ``signed short`` or ``unsigned int``) signed. + * - | ``--signed_chars`` + | ``-s`` + - | Make plain ``char`` signed. The default signedness for ``char`` is + selected at the time of installation of the front end (information on + this appears in a later section of this document). When plain + ``char`` is signed, the macro ``__SIGNED_CHARS__`` is defined by the + front end. + * - | ``--special_subscript_cost`` + | ``--no_special_subscript_cost`` + | + - | Enable or disable a special nonstandard weighting of the conversion to + the integral operand of the ``[]`` operator in overload resolution. + This is a compatibility feature that may be useful with some existing + code. The special cost is enabled by default in cfront 3.0 mode. + With this feature enabled, the following code compiles without error: + + .. code:: c++ + + struct A { + A(); + operator int *(); + int operator[](unsigned); + }; + void main() { + A a; + a[0]; // Ambiguous, but allowed with + // this option operator[] + // is chosen + } + + | As of July 1996, the above is again acceptable, if ``ptrdiff_t`` is + configured as ``long``. Using a parameter of type ``ptrdiff_t`` + (instead of ``unsigned``\ ``int``) is recommended for portability. + * - | ``--no_stdarg_builtin`` + - | Disable special treatment of the ```` header. When enabled, + the ```` header is treated as a built-in, and references to + its macros (``va_start`` et al) are passed through as such in + generated C or C++ code. The default value is supplied by + ``DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE``. This option + cannot be used when the feature is disabled by default. + * - | ``--unsigned_bit_fields`` + | + - | Make bit fields declared with a plain integer type (e.g., ``short`` or + ``int``, but not ``signed short`` or ``unsigned int``) unsigned. + * - | ``--unsigned_chars`` + | ``-u`` + - | Make plain ``char`` unsigned. The default signedness for ``char`` is + selected at the time of installation of the front end (information on + this appears in a later section of this document). + * - | ``--using_std`` + | ``--no_using_std`` + - | Enable or disable implicit use of the ``std`` namespace when standard + header files are included. The default behavior is specified by the + configuration constant ``DEFAULT_IMPLICIT_USING_STD``. This option is + valid only in C++ mode. Note that this does *not* do the equivalent + of putting a "``using namespace std;``" in the program to allow old + programs to be compiled with new header files; it has a special and + localized meaning related to the EDG versions of certain header files, + and is unlikely to be of much use to end-users of the Front End. + +Template Instantiation Options +------------------------------ + +.. list-table:: + + * - | ``--auto_instantiation`` + | ``--no_auto_instantiation`` + | ``-T`` + - | Enable or disable automatic instantiation of templates. The + ``-T`` option is equivalent to ``--auto_instantiation``. The + default behavior is specified by the configuration flag + ``DEFAULT_AUTOMATIC_INSTANTIATION_MODE``. See + :ref:`template-instantiation`. This option is valid only in C++ + mode. + * - | ``--definition_list_file`` *file_name* + | + - | This option specifies the name of the template definition list file + passed between the front end and the prelinker. This file is a + temporary file and does not remain after the compilation is complete. + This option is supplied for use by the driver program that invokes the + front end and is not intended to be used by end-users. + * - | ``--exported_template_file`` *file-name* + | + - | This option specifies the name to be used for the exported template + file used for processing of exported templates. This option is + supplied for use by the driver program that invokes the front end and + is not intended to be used by end-users. + * - | ``--ii_file`` *file-name* + - | This option specifies the name to be used for the template + instantiation request file used in automatic instantiation mode. This + option is supplied for use by the driver program that invokes the + front end and is not intended to be used by end-users. + * - | ``--implicit_include`` + | ``--no_implicit_include`` + | ``-B`` + - | Enable or disable implicit inclusion of source files as a method + of finding definitions of template entities to be instantiated. + ``-B`` is equivalent to ``--implicit_include``. The default + behavior is specified by the configuration flag + ``DEFAULT_IMPLICIT_TEMPLATE_INCLUSION_MODE``. See + :ref:`template-instantiation`. This option is valid only in C++ + mode. + * - | ``--instantiate`` *mode* + | ``-t``\ *mode* + - | Control instantiation of external template entities. External + template entities are external (i.e., noninline and nonstatic) + template functions, variables, and template static data members. The + instantiation mode determines the template entities for which code + should be generated based on the template definition): + + ``none`` + Instantiate no template entities. This is the default. + + ``used`` + Instantiate only the template entities that are used in this + compilation. + + ``all`` + Instantiate all template entities whether or not they are used. + + ``local`` + Instantiate only the template entities that are used in this + compilation and force those entities to be local to this + compilation. + + | See :ref:`template-instantiation`. This option is valid only in + C++ mode. + * - | ``--instantiation_dir`` *dir-name* + | + - | When ``--one_instantiation_per_object`` is used, this option can be + used to specify a directory into which the generated object files (or + C files, if the C-generating back end if being used) should be put. + The ``eccp`` script always specifies this option when invoking the + front end, with the default of ``Template.dir`` if the option is not + specified by the user. + * - | ``--one_instantiation_per_object`` + | + - | Put out each template instantiation in this compilation (function, + variable, or static data member) in a separate object file. The + primary object file contains everything else in the compilation, i.e., + everything that isn't an instantiation. Having each instantiation in + a separate object file is very useful when creating libraries, because + it allows the user of the library to pull in only the instantiations + that are needed. That can be essential if two different libraries + include some of the same instantiations. This option is valid only in + C++ mode, and only if the configuration constant + ``ONE_INSTANTIATION_PER_OBJECT`` is TRUE. + * - | ``--pending_instantiations=`` *n* + | + - | Specifies the maximum number of instantiations of a given template + that may be in process of being instantiated at a given time. This is + used to detect runaway recursive instantiations. If *n* is zero, + there is no limit. The default is specified by the configuration + parameter ``DEFAULT_MAX_PENDING_INSTANTIATIONS``. + * - | ``--suppress_instantiation_flags`` + | + - | When automatic instantiation is being used, this option suppresses the + generation of the special symbols used by the prelinker to do + automatic instantiation processing. This option is for use by the + driver and prelinker and should not be used directly by users. This + option is used by to implement the driver option that removes the + instantiation flags from object files once the prelinking step has + completed. + * - | ``--template_directory`` *dir* + | + - | Specifies a directory name to be placed on the exported template + search path. The directories are used to find the definitions of + exported templates and are searched in the order in which they are + specified on the command-line. The current directory is always the + first entry on the search path. + * - | ``--template_info_file`` *file-name* + | + - | This option specifies the name to be used for the template + instantiation information file used in automatic instantiation mode. + This option is supplied for use by the driver program that invokes the + front end and is not intended to be used by end-users. + +Code Generation Options +----------------------- + +The following options control the IL produced, the C-generating back end, or +the C++-generating back end. + +.. list-table:: + + * - | ``--no_code_gen`` + | ``-n`` + - | Do syntax-checking only, i.e., do not run the back end. + * - | ``--force_vtbl`` + - | Force definition of virtual function tables in cases where the + heuristic used by the front end to decide on definition of virtual + function tables provides no guidance. See ``--suppress_vtbl``. This + option is valid only in C++ mode. + * - | ``--no_il_lowering`` + | ``-N`` + - | On versions that include IL lowering and that write an intermediate + language file, suppress both IL lowering and the back end, and write + an unlowered (i.e., C++ rather than C) IL file. Probably not of + interest to end users. + * - | ``--inline_statement_limit`` *size* + | + - | When inlining is enabled, sets the maximum size (in number of lowered + statements) for a routine to be inlinable. A value of zero allows an + inlined routine to be any size. Only available when + ``MINIMAL_INLINING`` is configured to be TRUE. + * - | ``--inlining`` + | ``--no_inlining`` + - | Enable or disable minimal inlining of function calls. These options + are available only when ``MINIMAL_INLINING`` is configured to be TRUE. + The default is to do inlining when the C-generating back end is used. + * - | ``--keep_restrict_in_signatures`` + | ``--no_keep_restrict_in_signatures`` + - | In most modern configurations, top-level parameter type qualifiers + are removed from function types. In such configurations, this + option overrides or preserves that behavior for the ``restrict`` + qualifier; i.e., when the option is enabled, the mangled name of a + function will reflect the presence of top-level restrict parameter + type qualifiers. + * - | ``--module_init`` *name1,name2,...* + | ``-i``\ *name1,name2,...* + - | When generating C output for testing (see ``c_gen_be`` in an + Appendix), when compiling in C mode, and if the current compilation + contains a main program, force calling of the file-scope + initialization routines in the indicated compiled units. This is + needed only when there are file-scope union initializations in + translation units that do not contain a main program. A message will + be issued during compilation of such units, indicating the need for + the ``--module_init`` option. All necessary names must be specified + in one ``--module_init`` option; a second ``--module_init`` will + overwrite the original list, not add to it. This option is not needed + when object code is generated by a back end other than the + C-generating back end, nor is it needed when the C-generating back end + is configured to generate ANSI C. This option is not needed in C++ + mode, because C++ has a language mechanism for getting initialization + code executed at program start-up. + * - | ``--gen_c_clang_version`` *version-number* + | + - | When using the C- or C++-generating back end to produce code that + is to be compiled with the ``clang`` compiler, this specifies the + version of the compiler being used (e.g., 150000 for version + 15.0). This option is supplied for use by the driver program that + invokes the front end and is not intended to be used by end-users. + * - | ``--gen_c_gnu_version`` *version-number* + | + - | When using the C- or C++-generating back end to produce code that + is to be compiled with the ``gcc`` compiler, this specifies the + version of the compiler being used (e.g., 140100 for version + 14.1.0). This option is supplied for use by the driver program + that invokes the front end and is not intended to be used by + end-users. + * - | ``--gen_c_msvc_version`` *version-number* + | + - | When using the C- or C++-generating back end to produce code that + is to be compiled with the Microsoft compiler, this specifies the + version of the compiler being used (e.g., 1932 for Visual Studio + 2022 Update 2). (This option is identical to the earlier + ``--msvc_target_version`` option, which continues to be accepted.) + This option is supplied for use by the driver program that invokes + the front end and is not intended to be used by end-users. + * - | ``--remove_unneeded_entities`` + | ``--no_remove_unneeded_entities`` + | + - | Enable or disable an optimization to prune the IL tree of types, + variables, routines, and related IL entries that are not "really + needed." (Something may be referenced but unneeded if it is referenced + only by something that is itself unneeded; certain entities, such as + global variables and routines defined in the translation unit, are + always considered to be needed.) The positive form of the option is + available only when ``MAINTAIN_NEEDED_FLAGS`` is TRUE. + * - | ``--suppress_vtbl`` + | ``-V`` + - | Suppress definition of virtual function tables in cases where the + heuristic used by the front end to decide on definition of virtual + function tables provides no guidance. The virtual function table for + a class is defined in a compilation if the compilation contains a + definition of the first non-inline non-pure virtual function of the + class. For classes that contain no such function, the default + behavior is to define the virtual function table (but to define it as + a local static entity). The option ``--suppress_vtbl`` suppresses the + definition of the virtual function tables for such classes, and + ``--force_vtbl`` forces the definition of the virtual function table + for such classes. ``--force_vtbl`` differs from the default behavior + in that it does not force the definition to be local. This option is + valid only in C++ mode. + * - | ``--target`` *target-config-name* + | + - | For configurations that support multiple targets, specifies that the + target configuration named *target-config-name* should be used for the + compilation. If no ``--target`` option is specified, the default + target configuration (which may or may not be the legacy + configuration) is used. + +Precompiled Header Options +-------------------------- + +The following options control how precompiled header files are generated and +used. + +.. list-table:: + + * - | ``--pch`` + - | Automatically use and/or create a precompiled header file -- for + details, see :ref:`precompiled-headers`. If + ``--use_pch`` or ``--create_pch`` (manual PCH mode) appears on the + command line following this option, its effect is erased. + * - | ``--create_pch`` *file-name* + - | If other conditions are satisfied (see + :ref:`precompiled-headers`), create a precompiled header file with + the specified name. If ``--pch`` (automatic PCH mode) or + ``--use_pch`` appears on the command line following this option, + its effect is erased. + * - | ``--use_pch`` *file-name* + - | Use a precompiled header file of the specified name as part of the + current compilation. If ``--pch`` (automatic PCH mode) or + ``--create_pch`` appears on the command line following this option, + its effect is erased. + * - | ``--pch_dir`` *directory-name* + - | The directory in which to search for and/or create a precompiled + header file. This option may be used with automatic PCH mode + (``--pch``) or with manual PCH mode (``--create_pch`` or + ``--use_pch``). + * - | ``--pch_messages`` + | ``--no_pch_messages`` + - | Enable or disable the display of a message indicating that a + precompiled header file was created or used in the current + compilation. + * - | ``--pch_verbose`` + - | In automatic PCH mode, for each precompiled header file that cannot be + used for the current compilation, a message is displayed giving the + reason that the file cannot be used. + * - | ``--pch_mem`` *size* + - | The number of 1024-byte units of preallocated memory in which to save + precompiled-header state (only if ``USE_MMAP_FOR_MEMORY_REGIONS`` is + FALSE). + +C++/CLI Options +--------------- + +.. list-table:: + + * - | ``--mscorlib_file_name`` *file-name* + - | Use the given assembly metadata file instead of ``mscorlib.dll`` to + import system types. + * - | ``--preusing`` *file-name* + - | Import the given assembly metadata file prior to processing the input + source (but after importing ``mscorlib.dll`` or the file specified + with the ``--mscorlib_file_name`` option). + * - | ``--using_directory`` *directory-name* + | + - | Add the given directory to the search path used when searching for + assembly metadata files. + * - | ``--using_framework_directory`` + | ``--no_using_framework_directory`` + | + - | Do or do not implicitly include the installation directory of the + Microsoft .NET runtime in the search path used when searching for + assembly metadata files. The default is to include that directory. + * - | ``--vcmeta_directory`` *directory-name* + | + - | Search for the ``vcmeta.dll`` file in the specified directory. If + omitted, ``vcmeta.dll`` is searched for in the same directory as the + module that contains the front end. + +Front End Debugging Options +--------------------------- + +.. list-table:: + + * - | ``--db``\ *n* + | ``--db``\ *name*\ ``=``\ *n* + | ``-d``\ *n* + | ``-d``\ *name*\ ``=``\ *n* + - | Set the debug output level in the front end, which controls the + output of flow-tracing and similar information to the debug output + file (``stderr``). ``--db``\ *n* sets the debug level to *n* (in + the range 1-5) for the entire execution of the compiler (higher + values generate more voluminous debugging output). One can + control the debug output more precisely by specifying a routine + name and the debug level desired upon entry to that routine, as in + ``--db``\ *name*\ ``=``\ *n*. Regardless of the previous setting + of the debug level, it will be changed to the indicated value on + entry to the indicated routine; on exit, it will be restored to + its former value. One can also use ``+=`` or ``-=`` in place of + ``=`` in that option to increase or decrease the debug level + relative to its current value. The former value is also restored + on exit from the routine in those cases. Ordinarily, a message is + written to debug output whenever the debug level is changed (i.e., + both on entry and exit in the above cases). If that is not + desirable, a ``!`` (implying "not") can be appended to the level + number in the command-line option, to indicate that the + level-change messages should not be produced for that request. + Several routine names can be specified, and/or several requests + can be made, by separating them with commas, as in the following: + + ``--db fe_init,fe_wrapup+=2,get_token=3`` + * - | ``-d-``\ *name1*\ ``,-``\ *name2*\ ``,``\ *...* + - | Enable the named "debug flags", which will enable debug output + associated with the flag. For example, ``-d-dump_layout`` produces + output related to the class type layout process. + * - | ``-d#``\ *name1*\ ``,#``\ *name2*\ ``,``\ *...* + - | Disable the named "debug flags". + * - | ``--db_name=``\ *name* + - | Enable debug output for source entities with the given name. Not all + debug output takes this option into account; i.e., even with this + option some debug output not associated with the given name may be + produced. When simultaneously compiling multiple translation units, + entities in all translation units are considered by default. The + given name can be restricted to entities in the primary translation + units by preceding it with ``[]`` or to entities in a secondary + translation unit by preceding it with ``[``\ *file*\ ``]`` where + *file* is the name of the secondary source file. For example, + + ``-d-trans_corresp --db_name=[x.cpp]A::f`` + + | will output debugging information about cross-translation-unit + correspondences for a member ``A::f`` declared in a secondary + translation unit defined by source file x.cpp. + +Miscellaneous Options +--------------------- + +.. list-table:: + + * - | ``--version`` + | ``-v`` + - | Display the version number of the front end, and the Edison Design + Group copyright. + * - | ``--building_runtime`` + - | Used to indicate that the EDG runtime library is being compiled. This + causes additional macros to be predefined that are used to pass target + configuration information from the front end to the runtime. + * - | ``--edg_base_dir`` + - | The name of the directory in which to find files needed by the front + end at execution time. This option is supplied for use by the driver + program that invokes the front end and is not intended to be used by + end-users. + * - | ``--dump_command_options`` + - | Display the complete set of ``--``\ *name* + command-line options recognized by the front end in a format that is + compatible with, e.g., the bash shell's complete command to allow the + shell's completion facility to be used with front end options. + * - | ``--dump_configuration`` + - | Display the complete set of configuration + macros with which the front end was built. The output (to the error + output file) can be captured and used as the contents of the + ``defines.h`` file to recreate that configuration. This option is + available only in executables built with ``DEBUG`` set to TRUE. + * - | ``--dump_legacy_as_target`` *target-config-name* + - | Displays the legacy configuration in such a manner that the + configuration can be used to specify a new target configuration named + *target-config-name*. For customers who have multiple versions of the + front end (each configured for a specific target), this option can be + used to generate a separate target configuration for each of the + legacy configurations, and the output combined to form a single + configuration where the target can be specified at run-time (via the + ``--target`` option). This option is available only in executables + built with ``DEBUG`` set to TRUE. The output is directed to the error + output file. + * - | ``--incognito`` + | ``--no_incognito`` + - | Enable or disable the suppression of implicitly-defined + EDG-specific macros such as ``__EDG__`` and ``__EDG_VERSION__``. + Suppressing these macros facilitates compilation of code that + incorrectly configures itself via conditional compilation when it + detects that the compiler is based on the EDG front end. The + default behavior of the front end is determined by the value of + the configuration macro DEFAULT_INCOGNITO. + * - | ``--il_display`` + - | Displays the IL in a human-readable form. This is + the same output that would be generated by writing the IL to a file + and displaying it with the ``edgcpdisp`` utility. The IL that is + displayed is lowered IL (if the configuration does lowering) unless + the ``--no_il_lowering`` command-line option is also specified. + * - | ``--mmap_address`` *address* + - | Specify the fixed address to be used in calls to ``mmap``. Valid + addresses are specific to the host operating system (and + architecture), and may change from invocation to invocation + (depending, say on which shared libraries are loaded). The address + chosen should be aligned to the page size of the host. The use of a + fixed address for ``mmap`` is useful in cases where pre-compiled + header files are used (to ensure that the same address space is + available from one invocation of the front end to another). This + option is available only in executables built with + ``USE_FIXED_ADDRESS_FOR_MMAP`` set to TRUE. + * - | ``--check_unicode_security`` + | ``--no_check_unicode_security`` + - | Enable or disable checking of comments, string literals, and + identifiers for Unicode patterns that could be used to disguise + malicious source code by making it appear innocuous; suspicious + patterns are reported as warnings. Checking is only applicable to + UTF-encoded Unicode source and header files. These options are + available only in executables built with + ``UNICODE_VULNERABILITY_CHECKING_SUPPORTED`` set to TRUE. + * - | ``--module_import_diagnostics`` + | ``--no_module_import_diagnostics`` + - | Enable or disable the issuing of diagnostic messages during the import + of entities from a module. The option can be used to reduce verbosity + and condense diagnostics that do not relate to the source file being + compiled. The default setting is specified by the + ``DEFAULT_MODULE_IMPORT_DIAG_ENABLED`` configuration macro. + * - | ``--wdir`` *directory-name* + - | Specify the directory to use in expanding relative path names. All + relative paths are expanded after command-line processing is complete, + so that any ``--wdir`` options preceding the final one have no effect. + +Environment Variables +===================== + +The environment variable ``USR_INCLUDE`` can be set to a directory to be used +instead of ``/usr/include`` on the standard include file search list. (Of +course, this has no effect if the front end has been configured to have an +empty "standard list" of include files.) + +When the front end is built with the ``__MICROSOFT_OS__`` flag set, the +environment variable ``TMP`` is used to specify the directory to be used for +temporary files. If ``TMP`` is not set, and when ``__MICROSOFT_OS__`` is not +set, the environment variable ``TMPDIR`` is used to indicate a directory to be +used for temporary files. If ``TMPDIR`` is not set, a default temporary +directory (often, ``/usr/tmp``) is used. (Note: at the present time, the front +end only uses temporary files when generating an intermediate language file for +immediate use by a back end called in the same program, and in the C-generating +back end.) + +Diagnostic Messages +=================== + +Diagnostic messages have an associated *severity*, as follows: + +* | Catastrophic errors indicate problems of such severity that the compilation + cannot continue. For example: command-line errors, internal errors, and + missing include files. If multiple source files are being compiled, any + source files after the current one will not be compiled. +* | Errors indicate violations of the syntax or semantic rules of the C or C++ + language. Compilation continues, but object code is not generated. +* | Warnings indicate something valid but questionable. Compilation continues + and object code is generated (if no errors are detected). +* | Remarks indicate something that is valid and probably intended, but which a + careful programmer may want to check. These diagnostics are not issued by + default. Compilation continues and object code is generated (if no errors + are detected). + +Diagnostics are written to the error output file with a form like the +following: + +.. code:: text + + "test.c", line 5: a break statement may only be used within a loop + or switch + break; + ^ + +Diagnostics are normally written to ``stderr``, but the front end can be +configured to use ``stdout`` by setting the ``DIRECT_ERROR_OUTPUT_TO_STDOUT`` +configuration macro. When this flag is set, messages are directed to +``stdout``, except when doing preprocessing only. Errors during command-line +processing are always directed to ``stderr``. + +Diagnostic messages can optionally be "colorized". Colorization is enabled +when the ``colorize_diagnostics`` global variable is TRUE. To support +colorization of diagnostics, diagnostics are annotated when the +``annotate_diagnostics`` global variable is TRUE. In that case, annotation +sequences are inserted into the diagnostic message itself to identify pieces of +the diagnostic that might later be highlighted in some fashion. These two +character annotations take the form of an "escape" character +(``DIAG_ANNOTATION_INDICATOR``) followed by an ``a_diagnostic_annotation_kind`` +enumerator. When colorization is enabled, ``format_output_line`` replaces the +annotations with Select Graphic Rendition (SGR) codes that, on most terminal +emulators, can be used to highlight text in various ways. The SGR codes used +for colorization default to a string specified by ``DEFAULT_EDG_COLORS`` which +can be overridden by the ``EDG_COLORS`` environment variable (if set). The +string consists of a colon-separated list of elements, where each element +specifies a string that maps to an ``a_diagnostic_annotation_kind`` value +followed by an "``=``" and the SGR string to use when highlighting text of that +kind. For example: + +.. code:: text + + "error=01;31:warning=01;35:note=01;36:locus=01:quote=01:range1=32" + +A customer can use the annotations in a diagnostic to display the annotated +pieces in any fashion they desire (e.g., when a GUI is available). + +Note that the message identifies the file and line involved, and that the +source line itself (with position indicated by the ``^``) follows the message. +If there are several diagnostics in one source line, each diagnostic will have +the form above, with the result that the text of the source line will be +displayed several times, with an appropriate position each time. + +Long messages are wrapped to additional lines when necessary. + +A configuration flag controls whether or not the string "``error:``" appears, +i.e., the front end can be configured so that the severity string is omitted +when the severity is "``error``". + +A command line option may be used to request a shorter form of the diagnostic +output in which the original source line is not displayed and the error message +text is not wrapped when too long to fit on a single line. + +A command line option may be used to request that the error number be included +in the diagnostic message. When displayed, the error number also indicates +whether the error may have its severity overridden on the command line. If the +severity may be overridden, the error number will include the suffix "``-D``" +(for "discretionary"); otherwise no suffix will be present. + +.. code:: text + + "Test_name.c", line 7: error #64-D: declaration does not declare anything + struct {}; + ^ + "Test_name.c", line 9: error #77: this declaration has no storage class or + type specifier + xxxxx; + ^ + +Because an error is determined to be discretionary based on the error severity +associated with a specific context, a given error may be discretionary in some +cases and not in others. + +For some messages, a list of entities is useful; they are listed following the +initial error message: + +.. code:: text + + "test.c", line 4: error: more than one instance of overloaded function "f" + matches the argument list: + function "f(int)" + function "f(float)" + argument types are: (double) + f(1.5); + ^ + +In some cases, some additional context information is provided; specifically, +such context information is useful when the front end issues a diagnostic while +doing a template instantiation or while generating a constructor, destructor, +or assignment operator function. For example: + +.. code:: text + + "test.c", line 7: error: "A::A()" is inaccessible + B x; + ^ + detected during implicit generation of "B::B()" at line 7 + +Without the context information, it is very hard to figure out what the error +refers to. + +If the front end is configured with ``FULLY_RESOLVED_MACRO_POSITIONS`` (and, +optionally, ``MACRO_INVOCATION_TREE_IN_IL``) set to TRUE, messages referring to +text occurring inside a macro expansion may provide additional information. +This additional information gives the source location from which the text was +copied into the macro expansion (i.e., from a macro definition or one of the +arguments in the top-level macro invocation), as well as possibly the chain of +macro invocations leading to the expanded text to which the diagnostic refers. +If the front end is configured to permit the display of this information, it +can also be enabled or disabled by the command-line option +``--[no_]macro_positions_in_diagnostics``. The information is presented in a +form like the following: + +.. code:: text + + "test.c", line 1: error: identifier "val" is undefined + #define incr(x) (x)+=val + ^ + in expansion of macro "incr" at "test.c", line 2, + in expansion of macro "next_val" at "test.c", line 4: + return next_val(i); + ^ + +Termination Messages +==================== + +When the front end is installed without the ``USING_DRIVER`` option (see +information on configuration later in this document), it writes sign-off +messages to the error output file. For example, one of the following forms of +message + +.. code:: text + + n errors detected in the compilation of "ifile". + 1 catastrophic error detected in the compilation of "ifile". + n errors and 1 catastrophic error detected in the compilation of "ifile". + +is written to indicate the detection of errors in the compilation. No message +is written if no errors were detected. The following message + +.. code:: text + + Error limit reached. + +is written when the count of errors reaches the error limit (see the ``-e`` +option, above); compilation is then terminated. The message + +.. code:: text + + Compilation terminated. + +is written at the end of a compilation that was prematurely terminated because +of a catastrophic error. The message + +.. code:: text + + Compilation aborted. + +is written at the end of a compilation that was prematurely terminated because +of an internal error. Such an error indicates an internal problem in the +compiler and should be reported to those responsible for its maintenance. + +Response to Signals +=================== + +Except in multi-threaded builds, the signals ``SIGINT`` (caused by a user +interrupt, like ``^C``) and ``SIGTERM`` (caused by a ``kill`` command) are +trapped by the front end and cause abnormal termination. When +``MULTIPLE_THREAD_COMPILATION`` is TRUE, it's expected that the customer +application will install handlers as appropriate and no signal handling is +performed by the front end. + +Exit Status +=========== + +On completion, the front end returns with a code indicating the +highest-severity diagnostic detected: 4 if there was a catastrophic error, 2 if +there were any errors, or 0 if there were any warnings or remarks or if there +were no diagnostics of any kind. + +If multiple source files are compiled, the exit status indicates the +highest-severity diagnostic detected in the entire compilation. + +.. _finding-includes: + +Finding Include Files +===================== + +A file name specified in a ``#include`` directive is searched for in a set of +directories specified by command-line options and environment variables. If +the file name specified does not include a suffix, a set of suffixes is used +when searching for the file. + +Files whose names are not absolute pathnames and that are enclosed in ``"..."`` +will be searched for in the following directories, in the order listed: + +#. The directory containing the current input file (the primary source file + or the file containing the ``#include``); [#f2]_ +#. any directories specified in ``--include_directory`` options (in the + order in which they were listed on the command line); +#. any directories on the standard list (this list is selected at the time + of installation of the front end; often, it is just the one directory + ``/usr/include`` or a similar system include directory for C++). + +For file names enclosed in ``<...>``, only the directories that are specified +using the ``--include_directory`` option and those on the standard list are +searched. If the directory name is specified as "``-``", e.g., "``-I-``", the +option indicates the point in the list of ``--include_directory`` options at +which the search for file names enclosed in ``<...>`` should begin. That is, +the search for ``<...>`` names should only consider directories named in +``--include_directory`` options following the ``-I-``, and the directories of +item 3 above. ``-I-`` also removes the directory containing the current input +file (item 1 above) from the search path for file names enclosed in ``"..."``. + +An include directory specified with the ``--sys_include`` option is considered +a "system" include directory. Warnings are suppressed when processing files +found in system include directories. If a default include directory has been +specified using the ``USR_INCLUDE`` configuration flag or environment variable, +it is considered a system include directory. + +If the file name has no suffix it will be searched for by appending each of a +set of include file suffixes. When searching in a given directory all of the +suffixes are tried in that directory before moving on to the next search +directory. The default set of suffixes is specified by the +``DEFAULT_INCLUDE_FILE_SUFFIX_LIST`` configuration parameter. The default can +be overridden using the ``--incl_suffixes`` command-line option. A null file +suffix cannot be used unless it is present in the suffix list (i.e., the front +end will always attempt to add a suffix from the suffix list when the file name +has no suffix). + +.. _finding-modules: + +Finding Module Files +==================== + +An ``import`` directive can specify either a module unit or a header unit, and +the process of finding these differ. A header unit import names the header +identically to the equivalent ``#include`` directive (a file name enclosed in +``<...>`` or ``"..."``), while a module unit is imported by its name and not +the name of the file containing the module unit. + +An ``import`` directive that specifies a header unit first finds the named +header using the process for finding ``#include`` files. See +:ref:`finding-includes`. If the header is found, the corresponding module file +is found by the following search, in the listed order: + +#. Using the direct mappings provided by ``--ms_header_unit``. +#. Using the unresolved mappings provided by ``--ms_header_unit_angle`` (if + the header file name is specified via ``<...>``) or by + ``--ms_header_unit_quote`` (if the header file name is specified via + ``"..."``). If a match is found here, that match is added to the map + for ``--ms_header_unit``. + +An ``import`` directive that specifies a module unit will search for the module +file, in the order listed: + +#. Any direct mappings from that module name to a module file as specified + by ``--ms_mod_file_map`` +#. Any files listed without a direct map by ``--ms_mod_file_map``, examining + those files to determine if the module each represents matches the module + being imported +#. Files in the directory containing the current input file (the primary + source file or the file containing the ``import``) +#. Files in any directories specified by\ ``--modules_directory`` (in the + order in which they were listed on the command line) +#. Files in the directory specified by the ``EDG_MODULES_PATH`` environment + variable, if it's set. + +C++ Dialect Accepted +==================== + +In strict C++ mode, the front end accepts the complete C++ language as defined +by the ISO/IEC 14882:2003 standard, including export templates (if the front +end's configuration allows them). In nonstrict C++ mode (which is the default +in common configurations), a small set of features -- particularly, export +templates -- are not supported, but some minor extensions commonly available on +other compilers are accepted. + +The front end accepts the complete C++17 language as defined by the ISO/IEC +14882:2017 standard (enabled through the command-line option ``--c++17``). The +front end also fully supports the earlier C++14, C++11, and (as noted above) +C++98/03 versions of the language. The front end supports most of the features +of the C++20 language as defined by the 14882:2020 standard (enabled through +the command-line option ``--c++20``). The C++20 features that are not accepted +yet are described below. + +Extensive compatibility modes are also available for the Microsoft Visual C++ +compilers, the GNU C++ ("GCC") compilers, and the clang C++ compiler. A more +basic Sun C++ compatibility mode is also implemented. Only one emulation mode +may be active at a time (but ``--ms_extensions`` or ``--ms_compatibility`` may +be enabled in non-Microsoft emulation modes). + +The front end also has a cfront compatibility mode, which duplicates a number +of "features" and bugs of cfront 2.1 and 3.0.x. Complete compatibility is not +guaranteed or intended -- the mode is there to allow programmers who have +unwittingly used cfront features to continue to compile their existing code. +In particular, if a program gets an error when compiled by cfront, the EDG +front end may produce a different error or no error at all. + +Command-line options are available to enable and disable anachronisms, to +control strict standard-conformance checking, and to adjust the severity of +certain diagnostics. + + + +C++20 Implementation Status +--------------------------- + +Most of the new features and changes in the C++20 standard are accepted by +the front end. Details about the specific changes (e.g., the first version +of the front end to support the feature, and the standard committee papers +that introduced the feature) can be found on the `EDG website +`__. + +The following C++20 features are not yet supported (our web site has links with +further details): + +* | Concepts are supported, but some of the most recent changes to the feature + are not yet supported: + + * | Partial ordering of rewritten operator candidates resulting from + constrained templates + * | Clarify declaration matching and partial ordering requiring substitution + into constraints +* | When are ``constexpr`` member functions defined? (core issue 1581). This + is not yet implemented because of concerns about potential code breakage. +* | Modules. (There is partial support for importing Microsoft modules. See + the release notes for more information.) + +C++23 and C++26 Implementation Status +------------------------------------- + +Some of the new features and changes in the C++23 and draft C++26 standard are +accepted by the front end. Details about the specific changes (e.g., the first +version of the front end to support the feature, and the standard committee +papers that introduced the feature) can be found on the `EDG website +`__. + +"Default" C++ Mode +------------------ + +The following extensions are accepted default C++ mode. Most of these are also +accepted in any other C++ mode that does not diagnose strict ANSI violations as +errors (exceptions are explicitly noted). + +* | A ``friend`` declaration for a class may omit the ``class`` keyword: + + .. code:: c++ + + class B; + class A { + friend B; // Should be "friend class B" + }; + +* | Constants of scalar type may be defined within classes (this is an old + form; the modern form uses an initialized static data member): + + .. code:: c++ + + class A { + const int size = 10; + int a[size]; + }; + +* | In the declaration of a class member, a qualified name may be used: + + .. code:: c++ + + struct A { + int A::f(); // Should be int f(); + }; + +* | If ``ALLOW_NONSTANDARD_ANONYMOUS_UNIONS`` is TRUE, an extension is + supported to allow an anonymous union to be introduced into a containing + class by a ``typedef`` name -- it needn't be declared directly, as with a + true anonymous union. For example: + + .. code:: c++ + + typedef union { + int i, j; + } U; // U identifies a reusable anonymous union. + class A { + U; // Okay -- references to A::i and A::j are allowed. + }; + + | In addition, the extension also permits "anonymous classes" and "anonymous + structs," as long as they have no C++ features (e.g., no static data + members or member functions and no nonpublic members) and have no nested + types other than other anonymous classes, structs, or unions. For + instance, + + .. code:: c++ + + struct A { + struct { + int i, j; + }; // Okay -- references to A::i and A::j are allowed. + }; + +* | If recognition of the ``restrict`` keyword is enabled, the C99 ``restrict`` + feature is supported in a form extended for C++, which allows ``restrict`` + as a type qualifier for reference and pointer-to-member types and for + nonstatic member functions. The set of C++ extensions is described in + J16/92-0057. +* | If ``IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE`` is TRUE, implicit + type conversion between a pointer to an ``extern "C"`` function and a + pointer to an ``extern "C++"`` function is permitted. Here's an example: + + .. code:: c++ + + extern "C" void f(); // f's type has extern "C" linkage + void (*pf)() // pf points to an extern "C++" function + = &f; // error unless implicit conversion is allowed + + | This extension is allowed in environments where C and C++ functions share + the same calling conventions (though it is pointless unless + ``DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT`` is TRUE). When + ``DEFAULT_IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_ALLOWED`` is set, it is + enabled by default; it can also be enabled in cfront-compatibility mode or + with command-line option ``--implicit_extern_c_type_conversion``. +* | A "``?``" operator whose second and third operands are string literals or + wide string literals can be implicitly converted to "``char *``" or + "``wchar_t *``". (Recall that in C++ string literals are ``const``. There + is a deprecated implicit conversion that allows conversion of a string + literal to "``char *``", dropping the ``const``. That conversion, however, + applies only to simple string literals. Allowing it for the result of a + "``?``" operation is an extension.) + + .. code:: c++ + + char *p = x ? "abc" : "def"; + +* | Default arguments may be specified for function parameters other than those + of a top-level function declaration (e.g., they are accepted on ``typedef`` + declarations and on pointer-to-function and pointer-to-member-function + declarations). +* | Nonstatic local variables of an enclosing function can be referenced in a + non-evaluated expression (e.g., a ``sizeof`` expression) inside a local + class. A warning is issued. +* | In default C++ mode (but not other non-C++11 modes), the friend class + syntax is extended to allow nonclass types as well as class types expressed + through a typedef or without an elaborated type name. For example: + + .. code:: c++ + + typedef struct S ST; + class C { + friend S; // Okay (requires S to be in scope). + friend ST; // Okay (same as "friend S;"). + friend int; // Okay (no effect). + friend S const; // Error: cv-qualifiers cannot appear directly. + }; + +* | In default C++ mode, mixed string literal concatenations are accepted. + (This is a feature carried over from C99 and also available in GNU modes. + It is not enabled in other non-C++11 modes.) + + .. code:: c++ + + wchar_t *str = "a" L"b"; // Okay, same as L"ab". + +* | In default C++ mode, variadic macros are accepted. (This is a feature + carried over from C99 and also available in GNU modes. It is not by + default enabled in other non-C++11 modes.) +* | In default C++ mode, empty macro arguments are accepted (a feature carried + over from C99). +* | A trailing comma in the definition of an enumeration type is silently + accepted (a feature carried over from C99): + + .. code:: c++ + + enum E { e, }; + +Except where noted, all of the extensions described in the C dialect section +are also allowed in C++ mode. + +.. _gnu-mode: + +GNU C++ Mode +------------ + +The front end can be built to accept GNU extensions. In GNU C++ mode, a large +number of extensions and bugs are closely emulated. This feature enables the +front end to compile many large and complex projects that were developed using +the GNU tool chain; this includes major open-source projects. + +Support for this emulation is ongoing: New GNU C++ features are added as +needed, with priority given to features used in system headers. + +Because the GNU compiler frequently changes behavior between releases, the +front end provides an option (``--gnu_version``) to specify a specific version +of GCC to emulate. Generally speaking, features and bugs are emulated to +exactly match each known version of GCC, but occasionally the emulation is +approximate and in such cases the front end is often a little more permissive +than GCC on the principle that it is more important to accept source that GCC +accepts than to diagnose every case that GCC diagnoses. The front end does +not, however, attempt to emulate every GCC command-line option; in particular, +GCC options to be extra-permissive are not emulated (however, the severity of +specific error diagnostics can sometimes be decreased to accept constructs that +are not by-default allowed in GNU emulation mode). + +Some GNU features are only emulated when specific configuration options are +enabled. For example, support for complex floating-point types is only +available when the front end is configured to support C99 extensions. + +A few GCC extensions there are likely *not* going to be supported in the +foreseeable future: + +* | The forward declaration of function parameters (so they can participate in + variable-length array parameters). +* | GNU-style complex *integral* types (complex *floating-point* types are + supported) +* | Nested functions +* | Local structs with variable-length array fields. Such fields are treated + (with a warning) as zero-length arrays in GNU C mode, which is a useful + approximation in some circumstances, but not generally equivalent to the + GNU feature. + +Microsoft C++ Mode +------------------ + +The front end also extensively emulates the Microsoft Visual C++ compilers. As +is the case with GNU modes, an option (``--microsoft_version``) is available to +select a specific version of Microsoft's compiler to emulate. + +Although Microsoft C++ and C modes generally emulate both extensions/features +and bugs, the emulation of a certain class of bugs (considered more severe) can +be controlled separately (using the ``--no_microsoft_bugs/--microsoft_bugs`` +options). + +Microsoft C++ mode can be combined with certain other language options to +enable a larger superset of the language accepted by the Microsoft compiler. + +In addition to full Microsoft emulation mode, two subsets of Microsoft +emulation are available: ``--ms_extensions``, and ``--ms_compatibility``, +corresponding to clang's ``-fms-extensions`` and ``-fms-compatibility`` +command-line options, respectively. These command-line options allow a certain +degree of Microsoft emulation while the primary emulation mode is something +else (e.g., ``--clang``). + +Support for Microsoft C++ emulation is ongoing: New features are added as +needed, with priority given to features used in system headers. + +Microsoft C++/CLI Mode +---------------------- + +The front end implements the language extensions known as "C++/CLI" that +simplifies writing C++-like programs for Microsoft's ".NET" environment. These +extensions are formally described through the ECMA-372 standard, but where the +Microsoft compiler deviates from the standard, the front end follows the +Microsoft compiler rather than the standard. + +Almost all C++/CLI features are implemented in the front end. This includes +various managed class kinds and the special members (e.g., properties) that +they can contain, delegates, handles and tracking references, ``gcnew``, +generics, importing of assemblies, hide-by-sig lookup rules, string literal +rules, and so forth. A notable exception is Microsoft-style attributes +(delimited by square brackets): The front end can parse them, but does not +currently implement their semantics. + +An earlier attempt at integrating C++ and .NET was known as "Managed C++": The +front end does not support those earlier Microsoft compiler features (which +have since been deprecated by Microsoft). + +Extensions Accepted in Sun Compatibility Mode +--------------------------------------------- + +The front end provides a "Sun Compatibility" mode. This mode automatically +selects a set of command-line options that provides the greatest compatibility +with the Sun CC 5.x compiler. It also enables certain extensions that are +accepted by the Sun compiler. Note that this mode is provided to enable the +front end to compile code such as commonly used Sun header files, and is not +intended to provide complete compatibility with the Sun compiler. + +Sun compatibility mode currently corresponds to the following combination of +options: + +.. code:: text + + --no_guiding_decls + --extern_inline + --nonstd_using_decl + +These settings can explicitly be overridden using more command-line options. + +The following extensions are accepted in Sun compatibility mode: + +* | The Sun-specific link scope specifiers ``__global``, ``__symbolic``, and + ``__hidden`` can be recognized. In modes that recognize these keywords, + the pragmas "``#pragma disable_ldscope``" and "``#pragma enable_ldscope``" + can be used to temporarily allow these keywords as normal identifiers. For + example: + + .. code:: c++ + + __global int i; // Accepted in some Sun modes. + #pragma disable_ldscope + int __global; // Okay: Keyword (temporarily) deactivated. + #pragma enable_ldscope + struct __global; // Error: __global is a keyword. + +* | The ``__thread`` specifier can be used to indicate that a variable should + be placed in thread-local storage. +* | In Sun mode, a non-tag from one scope hides a tag from another scope when + both are visible as a result of a using-directive. + + .. code:: c++ + + template struct B { }; + namespace N { + typedef B A; + } + using namespace N; + class A;typedef A C; // Sun mode uses typedef N::A instead of ambiguity + +* | A reference to an undeclared function template is accepted when the + reference appears in the definition of a class template. + + .. code:: c++ + + template struct A { + friend void f<>(T&); // Accepted in Sun mode + }; + +* | When a friend class is declared with an unqualified name, the lookup of + that name is not restricted to the nearest enclosing namespace scope. + + .. code:: c++ + + struct S; + namespace N { + class C { + friend struct S; // ::S in Sun and Microsoft modes + }; + // (N::S otherwise) + } + +* | The ``typename`` keyword is ignored in most contexts. + + .. code:: c++ + + // The Sun compiler does recognize typename in a template parameter list + template class C { + // Illegal uses of typename that are accepted by the Sun compiler + typename T t; + typename typename T typename typename x; + }; + +* | A default argument may be specified in the definition of a member function + of a class template declared outside of the class. + + .. code:: c++ + + template struct A { + void f(int); + }; + template void A::f(int = 0) { } + +* | A template argument list may appear following a constructor name in + constructor definition that appears outside of the class definition: + + .. code:: c++ + + template struct A { + A(); + }; + template A::A(){} + +* | Template parameters are (incorrectly) visible in class template + specializations and specializations of members of class templates. + + .. code:: c++ + + template struct A { + void f(); + }; + template <> struct A { + T t; // T should not be visible here + }; + template <> void A::f() { + T t; // T should not be visible here + } + +* | The explicit instantiation of a class does not cause the instantiation of + its inline members. + + .. code:: c++ + + template struct A { + void f() { + g(); + } // Not instantiated in Sun mode + }; + template class A; + +* | An ``extern inline`` function that is referenced but not defined is + permitted (with a warning). +* | Default arguments are retained as part of deduced function types. +* | When searching for a header file specified using the ``<...>`` syntax, the + front end searches for the specified header file name and also for a + version with the suffix ``.SUNWCCh`` appended (e.g., ``stddef.h.SUNWCCh``). +* | The ``std`` namespace is predeclared. +* | A reference to a nonstatic data member may be written without an object + (not even an implicit ``this->``) inside a sizeof: + + .. code:: c++ + + typedef struct _X { + char A[512]; + } X; + static unsigned int foo() { + return sizeof(X::A); + } + +* | A storage class may appear in a declaration that also has a "direct" + linkage specification -- e.g., + + .. code:: c++ + + extern "s" static void f(); + + | is treated as equivalent to + + .. code:: c++ + + extern "C" { static void f(); } + +Anachronisms Accepted +--------------------- + +The following anachronisms are accepted when anachronisms are enabled: + +* | ``overload`` is allowed in function declarations. It is accepted and + ignored. +* | Definitions are not required for static data members that can be + initialized using default initialization. The anachronism does not apply + to static data members of template classes; they must always be defined. +* | The number of elements in an array may be specified in an array ``delete`` + operation. The value is ignored. +* | A single ``operator++()`` and ``operator--()`` function can be used to + overload both prefix and postfix operations. +* | The base class name may be omitted in a base class initializer if there is + only one immediate base class. +* | Assignment to ``this`` in constructors and destructors is allowed. This is + allowed only if anachronisms are enabled and the "assignment to ``this``" + configuration parameter is enabled. +* | A bound function pointer (a pointer to a member function for a given + object) can be cast to a pointer to a function. +* | A nested class name may be used as a nonnested class name provided no other + class of that name has been declared. The anachronism is not applied to + template classes. +* | A reference to a non-const type may be initialized from a value of a + different type. A temporary is created, it is initialized from the + (converted) initial value, and the reference is set to the temporary. +* | A reference to a non-const class type may be initialized from an rvalue of + the class type or a derived class thereof. No (additional) temporary is + used. +* | A function with old-style parameter declarations is allowed and may + participate in function overloading as though it were prototyped. Default + argument promotion is not applied to parameter types of such functions when + the check for compatibility is done, so that the following declares the + overloading of two functions named ``f``: + + .. code:: c++ + + int f(int); + int f(x) char x; { return x; } + + | It will be noted that in C this code is legal but has a different + meaning: a tentative declaration of ``f`` is followed by its definition. +* | When ``--nonconst_ref_anachronism`` is enabled, a reference to a nonconst + class can be bound to a class rvalue of the same type or a derived type + thereof. + + .. code:: c++ + + struct A { + A(int); + A operator=(A&); + A operator+(const A&); + }; + main () { + A b(1); + b = A(1) + A(2); // Allowed as anachronism + } + +Extensions Accepted in Cfront 2.1 Compatibility Mode +---------------------------------------------------- + +The following extensions are accepted in cfront 2.1 compatibility mode in +addition to the extensions listed in the 2.1/3.0 section following (i.e., these +are things that were corrected in the 3.0 release of cfront): + +* | The dependent statement of an ``if``, ``while``, ``do``-``while``, or + ``for`` is not considered to define a scope. The dependent statement may + not be a declaration. Any objects constructed within the dependent + statement are destroyed at exit from the dependent statement. +* | Implicit conversion from integral types to enumeration types is allowed. +* | A non-``const`` member function may be called for a ``const`` object. A + warning is issued. +* | A ``const void *`` value may be implicitly converted to a ``void *`` value, + e.g., when passed as an argument. +* | When, in determining the level of argument match for overloading, a + reference parameter is initialized from an argument that requires a + non-class standard conversion, the conversion counts as a user-defined + conversion. (This is an outright bug, which unfortunately happens to be + exploited in the NIH class libraries.) +* | When a builtin operator is considered alongside overloaded operators in + overload resolution, the match of an operand of a builtin type against the + builtin type required by the builtin operator is considered a standard + conversion in all cases (e.g., even when the type is exactly right without + conversion). +* | A reference to a non-``const`` type may be initialized from a value that is + a ``const``-qualified version of the same type, but only if the value is + the result of selecting a member from a ``const`` class object or a pointer + to such an object. +* | The cfront 2.1 "transitional model" for nested type support is simulated. + In the transitional model a nested type is promoted to the file scope + unless a type of the same name already exists at the file scope. It is an + error to have two nested classes of the same name that need to be promoted + to file scope or to define a type at file scope after the declaration of a + nested class of the same name. This "feature" actually restricts the + source language accepted by the compiler. This is necessary because of the + effect this feature has on the name mangling of functions that use nested + types in their signature. This feature does not apply to template classes + and is only enabled when the configuration switch + ``CFRONT_2_1_OBJECT_CODE_COMPATIBILITY`` is TRUE. +* | A cast to an array type is allowed; it is treated like a cast to a pointer + to the array element type. A warning is issued. +* | When an array is selected from a class, the type qualifiers on the class + object (if any) are not preserved in the selected array. (In the normal + mode, any type qualifiers on the object are preserved in the element type + of the resultant array.) +* | An identifier in a function is allowed to have the same name as a parameter + of the function. A warning is issued. +* | An expression of type ``void`` may be supplied on the return statement in a + function with a ``void`` return type. A warning is issued. +* | Cfront has a bug that causes a global identifier to be found when a member + of a class or one of its base classes should actually be found. This bug + is emulated in cfront compatibility mode but can be disabled by setting the + parameter ``CFRONT_GLOBAL_VS_MEMBER_NAME_LOOKUP_BUG`` to FALSE. A + warning is issued when, because of this feature, a nonstandard lookup is + performed. + | + | The following conditions must be satisfied for the nonstandard lookup to be + performed: + + * | A member in a base class must have the same name as an identifier at the + global scope. The member may be a function, static data member, or + nonstatic data member. Member type names don't apply because a nested + type will be promoted to the global scope by cfront which disallows a + later declaration of a type with the same name at the global scope. + * | The declaration of the global scope name must occur between the + declaration of the derived class and the declaration of an out-of-line + constructor or destructor. The global scope name must be a type name. + * | No other member function definition -- even one for an unrelated class + -- may appear between the destructor and the offending reference. + This has the effect that the nonstandard lookup applies to only one + class at any given point in time. For example: + + .. code:: c++ + + struct B { + void func(const char*); + }; + struct D : public B { + public: + D(); + void Init(const char* ); + }; + struct func { + func( const char* msg); + }; + D::D(){} + void D::Init(const char* t){ + // Should call B::func -- calls func::func instead. + new func(t); + } + + | The global scope name must be present in a base class (``B::func`` in this + example) for the nonstandard lookup to occur. Even if the derived class + were to have a member named ``func``, it is still the presence of + ``B::func`` that determines how the lookup will be performed. +* | A parameter of type "``const void *``" is allowed on ``operator delete``; + it is treated as equivalent to "``void *``". +* | A period ("``.``") may be used for qualification where "``::``" should be + used. Only "``::``" may be used as a global qualifier. Except for the + global qualifier, the two kinds of qualifier operators may not be mixed in + a given name (i.e., you may say ``A::B::C`` or ``A.B.C`` but not ``A::B.C`` + or ``A.B::C``). A period may not be used in a vacuous destructor reference + nor in a qualifier that follows a template reference such as ``A::B``. +* | Cfront 2.1 does not correctly look up names in friend functions that are + inside class definitions. In this example function f should refer to the + functions and variables (e.g., ``f1`` and ``a1``) from the class + declaration. Instead, the global definitions are used. + + .. code:: c++ + + int a1; + int e1; + void f1(); + class A { + int a1; + void f1(); + friend void f() { + int i1 = a1; // cfront uses global a1 + f1(); // cfront uses global f1 + } + }; + + | Only the innermost class scope is (incorrectly) skipped by cfront + as illustrated in the following example. + + .. code:: c++ + + int a1; + int b1; + struct A { + static int a1; + class B { + static int b1; + friend void f() { + int i1 = a1; // cfront uses A::a1 + int j1 = b1; // cfront uses global b1 + } + }; + }; + +* | ``operator=`` may be declared as a nonmember function. (This is flagged as + an anachronism by cfront 2.1) +* | A type qualifier is allowed (but ignored) on the declaration of a + constructor or destructor. For example: + + .. code:: c++ + + class A { + A() const; // No error in cfront 2.1 mode + }; + +* | The preprocessing symbol ``c_plusplus`` is defined in addition to the + standard ``__cplusplus``. + +Extensions Accepted in Cfront 2.1 and 3.0 Compatibility Mode +------------------------------------------------------------ + +The following extensions are accepted in both cfront 2.1 and cfront 3.0 +compatibility mode (i.e., these are features or problems that exist in both +cfront 2.1 and 3.0): + +* | Type qualifiers on the ``this`` parameter may be dropped in contexts + such as this example: + + .. code:: c++ + + struct A { + void f() const; + }; + void (A::*fp)() = &A::f; + + | This is actually a safe operation. A pointer to a ``const`` function may + be put into a pointer to non-``const``, because a call using the pointer is + permitted to modify the object and the function pointed to will actually + not modify the object. The opposite assignment would not be safe. +* | Conversion operators specifying conversion to ``void`` are allowed. +* | A nonstandard friend declaration may introduce a new type. A friend + declaration that omits the elaborated type specifier is allowed in default + mode, but in cfront mode the declaration is also allowed to introduce a new + type name. + + .. code:: c++ + + struct A { + friend B; + }; + +* | The third operand of the ``?`` operator is a conditional expression instead + of an assignment expression as it is in the modern language. +* | A reference to a pointer type may be initialized from a pointer value + without use of a temporary even when the reference pointer type has + additional type qualifiers above those present in the pointer value. For + example, + + .. code:: c++ + + int *p; + const int *&r = p; // No temporary used + +* | A reference may be initialized with a null. +* | Because cfront does not check the accessibility of types, access errors for + types are issued as warnings instead of errors. +* | When matching arguments of an overloaded function, a ``const`` variable + with value zero is not considered to be a null pointer constant. In + general, in overload resolution a null pointer constant must be spelled + "``0``" to be considered a null pointer constant (e.g., ``'\0'`` is not + considered a null pointer constant). +* | Inside the definition of a class type, the qualifier in the declarator for + a member declaration is dropped if that qualifier names the class being + defined. + + .. code:: c++ + + struct S { + void S::f(); // No warning in cfront mode + }; + +* | An alternate form of declaring pointer-to-member-function variables is + supported, namely: + + .. code:: c++ + + struct A { + void f(int); + static void sf(int); + typedef void A::T3(int); // nonstd typedef decl + typedef void T2(int); // std typedef + }; + typedef void A::T(int); // nonstd typedef decl + T* pmf = &A::f; // nonstd ptr-to-member decl + A::T2* pf = A::sf; // std ptr to static mem decl + A::T3* pmf2 = &A::f; // nonstd ptr-to-member decl + + | where ``T`` is construed to name a routine type for a nonstatic member + function of class ``A`` that takes an ``int`` argument and returns + ``void``; the use of such types is restricted to nonstandard + pointer-to-member declarations. The declarations of ``T`` and ``pmf`` in + combination are equivalent to a single standard pointer-to-member + declaration: + + .. code:: c++ + + void (A::* pmf)(int) = &A::f; + + | A nonstandard pointer-to-member declaration that appears outside of a class + declaration, such as the declaration of ``T``, is normally invalid and + would cause an error to be issued. However, for declarations that appear + within a class declaration, such as ``A::T3``, this feature changes the + meaning of a valid declaration. cfront version 2.1 accepts declarations, + such as ``T``, even when ``A`` is an incomplete type; so this case is also + excepted. +* | Protected member access checking is not done when the address of a + protected member is taken. For example: + + .. code:: c++ + + class B { protected: int i; }; + class D : public B { void mf(); }; + void D::mf() { + int B::* pmi1 = &B::i; // error, OK in cfront mode + int D::* pmi2 = &D::i; // OK + } + + | Note that protected member access checking for other operations (i.e., + everything except taking a pointer-to-member address) is done in the normal + manner. +* | The destructor of a derived class may implicitly call the private + destructor of a base class. In default mode this is an error but in cfront + mode it is reduced to a warning. For example: + + .. code:: c++ + + class A { + ~A(); + }; + class B : public A { + ~B(); + }; + B::~B(){} // Error except in cfront mode + +* | When disambiguation requires deciding whether something is a parameter + declaration or an argument expression, the pattern *type-name-or-keyword*\ + ``(``\ *identifier*... ``)`` is treated as an argument. For example: + + .. code:: c++ + + class A { + A(); + }; + double d; + A x(int(d)); + A(x2); + + | By default ``int(d)`` is interpreted as a parameter declaration (with + redundant parentheses), and so ``x`` is a function; but in + cfront-compatibility mode ``int(d)`` is an argument and ``x`` is a + variable. + | The declaration ``A(x2);`` is also misinterpreted by cfront. It should be + interpreted as the declaration of an object named ``x2``, but in cfront + mode is interpreted as a function style cast of ``x2`` to the type ``A``. + | Similarly, the declaration + + .. code:: c++ + + int xyz(int()); + + | declares a function named ``xyz``, that takes a parameter of type "function + taking no arguments and returning an ``int``." In cfront mode this is + interpreted as a declaration of an object that is initialized with the + value ``int()`` (which evaluates to zero). +* | A named bit-field may have a size of zero. The declaration is treated as + though no name had been declared. +* | Plain bit fields (i.e., bit fields declared with a type of ``int``) are + always unsigned. +* | The name given in an elaborated type specifier is permitted to be a + ``typedef`` name that is the synonym for a class name, e.g., + + .. code:: c++ + + typedef class A T; + class T *pa; // No error in cfront mode + +* | No warning is issued on duplicate size and sign specifiers. + + .. code:: c++ + + short short int i; // No warning in cfront mode + +* | An extra comma is allowed after the last argument in an argument list, as + for example in + + .. code:: c++ + + f(1, 2, ); + +* | A constant pointer-to-member-function may be cast to a pointer-to-function. + A warning is issued. + + .. code:: c++ + + struct A { + int f(); + }; + main () { + int (*p)(); + p = (int (*)())A::f; // Okay, with warning + } + +* | Arguments of class types that allow bitwise copy construction but also have + destructors are passed by value (i.e., like C structures), and the + destructor is not called on the "copy." In normal mode, the class object is + copied into a temporary, the address of the temporary is passed as the + argument, and the destructor is called on the temporary after the call + returns. Note that because the argument is passed differently (by value + instead of by address), code like this compiled in cfront mode is not + calling-sequence compatible with the same code compiled in normal mode. In + practice, this is not much of a problem, since classes that allow bitwise + copying usually do not have destructors. +* | A union member may be declared to have the type of a class for which the + user has defined an assignment operator (as long as the class has no + constructor or destructor). A warning is issued. +* | When an unnamed class appears in a ``typedef`` declaration, the ``typedef`` + name may appear as the class name in an elaborated type specifier. + + .. code:: c++ + + typedef struct { + int i, j; + } S; + struct S x; // No error in cfront mode + +* | Two member functions may be declared with the same parameter types when one + is static and the other is nonstatic with a function qualifier. + + .. code:: c++ + + class A { + void f(int) const; + static void f(int); // No error in cfront mode + }; + +* | The scope of a variable declared in the ``for-init-statement`` is the scope + to which the ``for`` statement belongs. + + .. code:: c++ + + int f(int i) { + for (int j = 0; j < i; ++j) { /* ... */ } + return j; // No error in cfront mode + } + +* | Function types differing only in that one is declared ``extern "C"`` and + the other ``extern "C++"`` can be treated as identical: + + .. code:: c++ + + typedef void (*PF)(); + extern "C" typedef void (*PCF)(); + void f(PF); + void f(PCF); + + | When ``DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT`` is FALSE, ``PF`` and + ``PCF`` are considered identical and ``void f(PCF)`` is treated as a + compatible redeclaration of ``f``. (By contrast, in standard C++``PF`` and + ``PCF`` are different and incompatible types -- ``PF`` is a pointer to an + ``extern "C++"`` function whereas ``PCF`` is a pointer to an ``extern "C"`` + function -- and the two declarations of ``f`` create an overload set.) + | + | However, even if ``DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT`` is TRUE, + it is possible to set + ``IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE`` to TRUE as well, so + that in cfront-compatibility mode an implicit type conversion will always + be done between a pointer to an ``extern "C"`` function and a pointer to an + ``extern "``\ C++``"`` function. +* | Functions declared ``inline`` have internal linkage. +* | ``enum`` types are regarded as integral types. +* | An uninitialized ``const`` object of non-POD class type is allowed even if + its default constructor is implicitly declared: + + .. code:: c++ + + struct A { virtual void f(); int i; }; + const A a; + +* | A function parameter type is allowed to involve a pointer or reference to + array of unknown bounds. +* | If the user declares an ``operator=`` function in a class, but not one that + can serve as the default ``operator=``, and bitwise assignment could be + done on the class, a default ``operator=`` is not generated; only the + user-written ``operator=`` functions are considered for assignments (and + therefore bitwise assignment is not done). +* | A member function declaration whose return type is omitted (and thus + implicitly ``int``) and whose name is found to be that of a type is + accepted if it takes no parameters: + + .. code:: c++ + + typedef int I; + struct S { + I(); // Accepted in cfront mode (declares "int S::I()") + I(int); // Not accepted + }; + +* | Default arguments are retained as part of deduced function types. + +C Dialect Accepted +================== + +The front end accepts the ANSI/ISO C language as defined by ANSI/ISO +9899:1990. In C99 mode, it accepts the ANSI/ISO C language defined by +ISO/IEC 9899:1999 as modified by Technical Corrigenda 1 through 3. In C11 +mode, it accepts the C language defined by ISO/IEC 9899:2011 and in C18 +mode the language defined by ISO/IEC 9899:2018 (which only differs from C11 +in minor ways). In C23 mode, many of the features of the latest standard +have been implemented. See the `EDG web site +`__ for up-to-date information about +feature implementation. + +When Embedded C extensions are enabled, the front end can accept the constructs +described in ISO/IEC TR 18037 (fixed-point types, named address space +qualifiers, and named-register storage class specifiers). + +The front end extensively emulates the C modes of the Microsoft, GNU, and clang +compilers. See :ref:`gnu-mode`. As with C++ mode, only one emulation mode may +be in effect for a given compilation. The ``--ms_extensions`` and +``--ms_compatibility`` options can be used to emulate certain Microsoft +behaviors irrespective of the emulation mode. + +There is no Sun C mode corresponding to Sun C++ mode, however. + +The special comments recognized by the UNIX ``lint`` program -- +``/*ARGSUSED*/``, ``/*VARARGS*/`` (with or without a count of non-varying +arguments), and ``/*NOTREACHED*/`` -- are also recognized by the front end. + +When Unified Parallel C (UPC) mode is enabled, it also accepts the core +language extensions described in `version 1.0 of the UPC Language +Specifications `__). + +C99 Features Available in Other Modes +------------------------------------- + +Certain C language features were added in the C99 version of the ISO C standard +and are supported in C99 mode. For a full list of those features, see ISO/IEC +9899:1999. A few features are noteworthy, however, because they are +implementation-specific or because they can be enabled in older C modes or +(when indicated) in C++ mode: + +* | The options ``--variadic_macros``, ``--no_variadic_macros``, + ``--extended_variadic_macros`` and ``--no_extended_variadic_macros`` + control whether macros taking a variable number of arguments are + recognized. Configuration flags are available to select the default + setting of these options; these are also available in C++ mode. + | Ordinary variadic macros (as included in C99) are illustrated by the + following example: + + .. code:: c++ + + #define OVM(x, ...) x(__VA_ARGS__) + void f() { OVM(printf, "%s %d\n", "Three args for ", 1); } + /* Expands to: printf("%s %d\n", "Three args for ", 1) */ + + | During expansion the special identifier ``__VA_ARGS__`` will be replaced by + the trailing arguments of the macro invocation. If variadic macros are + enabled, this special identifier can appear only in the replacement list of + variadic macros. + | Extended variadic macros (as implemented by certain pre-C99 compilers) use + a slightly different syntax and allow the name of the variadic parameter to + be chosen (instead of ``...``/``__VA_ARGS__``): + + .. code:: c++ + + #define EVM(x, args...) x(args) + void f() { EVM(printf, "%s %d\n", "Three args for ", 1); } + /* Same expansion as previous example. */ + + | In addition, enabling extended variadic macros adds a special behavior to + the token pasting operator ## when it is followed by an empty or omitted + macro argument: A preceding comma (possibly followed by white space) is + erased. Hence, + + .. code:: c++ + + #define EVM2(fmt, args) printf(fmt , ## args) + EVM2("Hello World\n") + + | expands to ``printf("Hello World\n")`` and the extraneous comma is erased. +* | If the ``LONG_LONG_ALLOWED`` switch is TRUE, + + * | the ``long long`` and ``unsigned long long`` types are accepted; + * | integer constants suffixed by ``LL`` are given the type ``long long``, + and those suffixed by ``ULL`` are given the type ``unsigned long long`` + (any of the suffix letters may be written in lower case); + * | the specifier ``%lld`` is recognized in ``printf`` and ``scanf`` + formatting strings; and + * | the ``long long`` types are accommodated in the usual arithmetic + conversions. +* | ``restrict`` may be used as a type qualifier for object pointer types and + function parameter arrays that decay to pointers. Its presence is recorded + in the IL so that back ends can perform optimizations that would otherwise + be prevented because of possible aliasing. The keyword is enabled by + ``--restrict``; this is also available in C++. +* | If ``VLA_ALLOWED`` is TRUE, variable length arrays (VLAs) are supported. + VLA types may appear only in the declaration of an identifier that belongs + to a block or function-prototype scope. For example: + + .. code:: c++ + + void addscalar(int n, int m, double a[n][m], double x) { + int i, j; + for (i=0; i.`` The form of + the macro reference is: + + .. code:: c++ + + __generic(x, y, z, func_d, func_f, func_l, func_cd, func_cf, func_cl) + + | where ``x`` and the optional ``y`` and ``z`` are the arguments with which a + type-generic function is called, and the remaining 6 arguments are the + names of functions from which is selected the actual function to be called. + The suffixes with which the function names are supplied here correspond to + function parameter types of ``double``, ``floa``\ t, ``long double``, + ``double _Complex``, ``float _Complex``, and ``long double _Complex``, + respectively. The order is fixed. Function names may be omitted. For + example, ```` may have the following macros defined: + + .. code:: c++ + + #define sin(x) __generic(x,,, sin, sinf, sinl, csin, csinf,csinl)(x) + #define fmax(x,y) __generic(x, y,,fmax, fmaxf, fmaxl,,,)(x, y) + #define conjg(x) __generic(x,,, ,,, conjg, conjgf, conjgl)(x) + + | Note that ``sin`` and ``conjg`` take only one argument, that ``fmax`` has + no forms that accept complex arguments, and that ``conjg`` has no forms + that accept real arguments. + | There is also a ``__genericfx`` pseudo-macro that provides a similar + capability for fixed-point types. The form of the macro reference is: + + .. code:: c++ + + __genericfx(x, fnc_hr, fnc_uhr, fnc_r, fnc_ur, fnc_lr, fnc_ulr, + fnc_hk, fnc_uhk, fnc_k, fnc_uk, fnc_lk, fnc_ulk) + + | where ``x`` is as above and the remaining 12 arguments are the names of + functions, with the suffixes corresponding to function parameter types of + ``short``\ ``_Fract``, ``unsigned``\ ``short``\ ``_Fract``, ``_Fract``, + ``unsigned``\ ``_Fract``, ``long``\ ``_Fract``, ``unsigned``\ ``long``\ + ``_Fract``, ``short``\ ``_Accum``, ``unsigned``\ ``short``\ ``_Accum``, + ``_Accum``, ``unsigned`` _Accum, ``long``\ ``_Accum``, ``unsigned``\ + ``long``\ ``_Accum``, respectively. +* | The keywords ``__I__``, ``__NAN__``, and ``__INFINITY__`` are defined as, + respectively, a float _Imaginary *i*, a float Not-a-Number, and a float + positive Infinity. These are intended to be used by library writers to + implement the C99 macros ``I``, ``NAN``, and ``INFINITY``. ``__NAN__`` and + ``__INFINITY__`` are also available in all modes, not just C99 mode. +* | A trailing array member of unspecified length in a struct type is called a + flexible array member. Such members are a standard feature in C99. In + default C99 mode (but not in strict C99 mode) trailing struct members can + also have a type containing a flexible array member. For example: + + .. code:: c++ + + struct F { + int i; + int f[]; // OK in default and strict C99 modes + }; + struct X { + F x; // OK in default C99 mode (but not in strict mode) + }; + +ANSI C Extensions +----------------- + +The following extensions are accepted (these are flagged if the ``-A`` or +``-a`` option is specified): + +* | A translation unit (input file) can contain no declarations. +* | Comment text can appear at the ends of preprocessing directives. +* | ``__ALIGNOF__`` (or ``__alignof__``) is similar to ``sizeof``, but returns + the alignment requirement value for a type, or ``1`` if there is no + alignment requirement. It may be followed by a type or expression in + parentheses: + + ``__ALIGNOF__(``\ *type*\ ``) __alignof__(``\ *type*\ ``)`` + + ``__ALIGNOF__(``\ *expression*\ ``) __alignof__(``\ *expression*\ ``)`` + + | The expression in the second form is not evaluated. +* | ``__INTADDR__(``\ *expression*\ ``)`` scans the enclosed expression as a + constant expression, and converts it to an integer constant (it is used in + the ``offsetof`` macro). +* | A number of "type traits pseudo-functions" (taking one or more type + names) are accepted: ``__has_nothrow_assign``, + ``__has_nothrow_constructor``, ``__has_nothrow_copy``, + ``__has_nothrow_move_assign``, ``__has_trivial_assign``, + ``__has_trivial_constructor``, ``__has_trivial_copy``, + ``__has_trivial_destructor``, ``__has_trivial_move_assign``, + ``__has_trivial_move_constructor``, ``__has_virtual_destructor``, + ``__is_abstract``, ``__is_base_of``, ``__is_class``, + ``__is_constructible``, ``__is_convertible_to``, ``__is_destructible``, + ``__is_empty``, ``__is_enum``, ``__is_literal_type``, + ``__is_nothrow_assignable``, ``__is_nothrow_constructible``, + ``__is_nothrow_destructible``, ``__is_pod``, ``__is_polymorphic``, + ``__is_standard_layout``, ``__is_trivial``, + ``__is_trivially_assignable``, ``__is_trivially_constructible``, + ``__is_trivially_copyable``, ``__is_trivially_destructible``, and + ``__is_union``. + + .. code:: c++ + + double x[__is_union(union U)]; // Okay. + + | These are silently accepted even in strict modes. They ease the + implementation C++11 metaprogramming templates (many of which were first + introduced by ISO/IEC TR 19768). +* | Bit fields may have base types that are ``enum``\ s or integral types + besides ``int`` and ``unsigned int``. This matches A.6.5.8 in the ANSI + Common Extensions appendix. +* | If the ``ADDR_OF_BIT_FIELD_ALLOWED`` flag is TRUE, the address of a bit + field may be taken if the bit field has the same size and alignment as one + of the integral types. A warning is issued. +* | The last member of a ``struct`` may have an incomplete array type. It may + not be the only member of the struct (otherwise, the struct would have zero + size). +* | A file-scope array may have an incomplete ``struct``, ``union``, or + ``enum`` type as its element type. The type must be completed before the + array is subscripted (if it is), and by the end of the compilation if the + array is not ``extern``. In C++, an incomplete ``class`` is also allowed. +* | Static functions may be declared in function and block scopes. Their + declarations are moved to the file scope. +* | ``enum`` tags may be incomplete: one may define the tag name and resolve it + (by specifying the brace-enclosed list) later. +* | The values of enumeration constants may be given by expressions that + evaluate to unsigned quantities that fit in the ``unsigned int`` range but + not in the ``int`` range. A warning is issued for suspicious cases. + + .. code:: c++ + + /* When ints are 32 bits: */ + enum a {w = -2147483648}; /* No warning */ + enum b {x = 0x80000000}; /* No warning */ + enum c {y = 0x80000001}; /* No warning */ + enum d {z = 2147483649}; /* Warning */ + +* | An extra comma is allowed at the end of an ``enum`` list. A remark is + issued except in ``pcc`` mode. +* | The final semicolon preceding the closing ``}`` of a struct or union + specifier may be omitted. A warning is issued except in ``pcc`` mode. +* | A label definition may be immediately followed by a right brace. + (Normally, a statement must follow a label definition.) A warning is + issued. +* | An empty declaration (a semicolon with nothing before it) is allowed. A + remark is issued. +* | An initializer expression that is a single value and is used to initialize + an entire static array, struct, or union need not be enclosed in braces. + ANSI C requires the braces. +* | In an initializer, a pointer constant value may be cast to an integral type + if the integral type is big enough to contain it. +* | The address of a variable with ``register`` storage class may be taken. A + warning is issued. +* | In an integral constant expression, an integer constant may be cast to a + pointer type and then back to an integral type. +* | ``long float`` is accepted as a synonym for ``double``. +* | If ``PTR_TO_INCOMP_ARRAY_ARITHMETIC_ALLOWED`` is TRUE, pointers to + incomplete arrays may be used in pointer addition, subtraction, and + subscripting: + + .. code:: c++ + + int (*p)[]; + ... + q = p[0]; + + | A warning is issued if the value added or subtracted is anything other than + a constant zero. Since the type pointed to by the pointer has zero size, + the value added to or subtracted from the pointer is multiplied by zero and + therefore has no effect on the result. +* | Benign redeclarations of ``typedef`` names are allowed. That is, a typedef + name may be redeclared in the same scope as the same type. A warning is + issued. +* | Dollar signs can be accepted in identifiers through use of a command line + option or by setting a configuration parameter. The default is to not + allow dollar signs in identifiers. +* | Numbers are scanned according to the syntax for numbers rather than the + ``pp-number`` syntax. Thus, ``0x123e+1`` is scanned as three tokens + instead of one invalid token. (If the ``-A`` or ``-a`` option is + specified, of course, the ``pp-number`` syntax is used.) +* | Assignment and pointer difference are allowed between pointers to types + that are interchangeable but not identical, for example, ``unsigned char + *`` and ``char *``. This includes pointers to same-sized integral types + (e.g., typically, ``int *`` and ``long *``). A warning is issued except in + ``pcc`` mode. Assignment of a string constant to a pointer to any kind of + character is allowed without a warning. +* | Assignment of pointer types is allowed in cases where the destination type + has added type qualifiers that are not at the top level (e.g., ``int **`` + to ``const int **``). Comparisons and pointer difference of such pairs of + pointer types are also allowed. A warning is issued. +* | In operations on pointers, a pointer to ``void`` is always implicitly + converted to another type if necessary, and a null pointer constant is + always implicitly converted to a null pointer of the right type if + necessary. In ANSI C, some operators allow such things, and others + (generally, where it does not make sense) do not allow them. +* | Pointers to different function types may be assigned or compared for + equality (``==``) or inequality (``!=``) without an explicit type cast. A + warning is issued. This extension is not allowed in C++ mode. +* | A pointer to ``void`` may be implicitly converted to or from a pointer to a + function type. +* | If the ``ATT_PREPROCESSING_EXTENSIONS_ALLOWED`` switch is TRUE, the + ``#assert`` preprocessing extensions of AT&T System V release 4 are + allowed. These allow definition and testing of predicate names. Such + names are in a name space distinct from all other names, including macro + names. A predicate name is given a definition by a preprocessing directive + of the form + + | ``#assert`` *name* + | ``#assert`` *name*\ ``(``\ *token-sequence*\ ``)`` + + | which defines the predicate *name*. In the first form, the predicate + is not given a value. In the second form, it is given the value + *token-sequence*. Such a predicate can be tested in a ``#if`` + expression, as follows: + + | ``#``\ *name*\ ``(``\ *token-sequence*\ ``)`` + + | which has the value 1 if a ``#assert`` of that *name* with that + *token-sequence* has appeared, and 0 otherwise. A given predicate may be + given more than one value at a given time. + + | A predicate may be deleted by a preprocessing directive of the form + + | ``#unassert`` *name* + | ``#unassert`` *name*\ ``(``\ *token-sequence*\ ``)`` + + | The first form removes all definitions of the indicated predicate name; the + second form removes just the indicated definition, leaving any others there + may be. +* | GNU line directive flags are accepted on ``#line`` directives. The system + header flag is recognized, and the associated code is treated as if found + in a system include directory. +* | ``asm`` statements and declarations are accepted. This is disabled in + strict ANSI C mode (``-A`` or ``-a`` and ``-m`` options) since it conflicts + with the ANSI C standard for something like + + .. code:: c++ + + asm("xyz"); + + | which ANSI C interprets as a call of an implicitly-defined function ``asm`` + and which by default the front end interprets as an ``asm`` statement. +* | When ``ASM_FUNCTION_ALLOWED`` is TRUE, ``asm`` functions are accepted, and + ``__asm`` is recognized as a synonym for ``asm``. An ``asm`` function body + is represented in the IL by an uninterpreted null-terminated string + containing the text that appears in the source (including the text of + source comments when ``INCLUDE_COMMENTS_IN_ASM_FUNC_BODY`` is TRUE). An + ``asm`` function must be declared with no storage class, with a prototyped + parameter list, and with no omitted parameters: + + .. code:: c++ + + asm void f(int,int) { + ... + } + + | If ``asm`` functions are recognized and the C-generating back end is used, + it is required that ANSI-C be generated, not K&R C, because the ``asm`` + function must be put out with a prototyped parameter list. +* | If ``ALLOW_NONSTANDARD_ANONYMOUS_UNIONS`` is TRUE, an extension is + supported to allow constructs similar to C++ anonymous unions, including + the following: + + * | not only anonymous unions but also anonymous structs are allowed -- that + is, their members are promoted to the scope of the containing struct and + looked up like ordinary members; + * | they can be introduced into the containing struct by a ``typedef`` name + -- they needn't be declared directly, as with true anonymous unions; and + * | a tag may be declared (C mode only). + + | Among the restrictions: the extension only applies to constructs within + structs. +* | If ``DEFAULT_ADDRESS_OF_ELLIPSIS_ALLOWED`` is TRUE, the expression ``&...`` + is accepted in the body of a function in which an ellipsis appears in the + parameter list. It is needed to support some versions of macro + ``va_start`` in ``stdarg.h``. +* | If ``DEFAULT_ALLOW_ELLIPSIS_ONLY_PARAM_IN_C_MODE`` is TRUE, an ellipsis may + appear by itself in the parameter list of a function declaration -- e.g., + ``f(...)``. A diagnostic is issued in strict ANSI C mode. +* | External entities declared in other scopes are visible. A warning is + issued. + + .. code:: c++ + + void f1(void) { extern void f(); } + void f2() { + f(); /* Using out of scope declaration */ + } + +* | A non-lvalue array expression is converted to a pointer to the first + element of the array when it is subscripted or similarly used. +* | The nonstandard preprocessing directive ``#include_next`` is supported. + This is a variant of the ``#include`` directive. It searches for the named + file only in the directories on the search path that follow the directory + in which the current source file (the one containing the ``#include_next`` + directive) is found. (This is an extension found in the GNU C compiler.) +* | The nonstandard preprocessing directive ``#warning`` is supported. It is + similar to the ``#error`` directive, but results in a warning instead of a + catastrophic error when processed. This directive is not recognized in + strict mode. (This is an extension found in GNU C compilers.) + +In the following areas considered "undefined behavior" by the ANSI C standard, +the front end does the following: + +* | Adjacent wide and non-wide string literals are not concatenated unless + ``wchar_t`` and ``char`` are the same type. (In C++ mode, when ``wchar_t`` + is a keyword, adjacent wide and non-wide string literals are never + concatenated.) +* | In character and string escapes, if the character following the ``\`` has + no special meaning, the value of the escape is the character itself. Thus + ``"\s" == "s"``. A warning is issued. +* | A ``struct`` that has no named fields but at least one unnamed field is + accepted by default, but a diagnostic (a warning or error) is issued in + strict ANSI C mode. + +K&R/pcc Mode +------------ + +When ``pcc`` mode is specified, the front end accepts the traditional C +language defined by *The C Programming Language*, first edition, by +Kernighan and Ritchie (K&R), Prentice-Hall, 1978. In addition, it provides +almost complete compatibility with the Reiser ``cpp`` and Johnson ``pcc`` +widely used as part of UNIX systems; since there is no documentation of the +exact behavior of those programs, complete compatibility cannot be +guaranteed. + +In general, when compiling in ``pcc`` mode, the front end attempts to interpret +a source program that is valid to ``pcc`` in the same way that ``pcc`` would. +However, ANSI features that do not conflict with this behavior are not +disabled. + +In some cases where ``pcc`` allows a highly questionable construct, the front +end will accept it but give a warning, where ``pcc`` would be silent (for +example: ``0x``, a degenerate hexadecimal number, is accepted as zero). + +The known cases where the front end is not compatible with ``pcc`` are the +following: + +* | Token pasting is not done outside of macro expansions (i.e., in the primary + source line) when two tokens are separated only by a comment. That is, + ``a/**/b`` is not considered to be ``ab``. The ``pcc`` behavior in that + case can be gotten by preprocessing to a text file and then compiling that + file. + | + | The textual output from preprocessing is also equivalent but not identical: + the blank lines and white space will not be exactly the same. +* | ``pcc`` will consider the result of a ``?:`` operator to be an lvalue if + the first operand is constant and the second and third operands are + compatible lvalues. This front end will not. +* | ``pcc`` mis-parses the third operand of a ``?:`` operator in a way that + some programs exploit: + + .. code:: c++ + + i ? j : k += l + + | is parsed by ``pcc`` as + + .. code:: c++ + + i ? j : (k += l) + + | which is not correct, since the precedence of ``+=`` is lower than the + precedence of ``?:``. This front end will generate an error for that case. +* | ``lint`` recognizes the keywords for its special comments anywhere in a + comment, regardless of whether or not they are preceded by other text in + the comment. The front end only recognizes the keywords when they are the + first identifier following an optional initial series of blanks and/or + horizontal tabs. ``lint`` also recognizes only a single digit of the + ``VARARGS`` count; the front end will accumulate as many digits as appear. + +The differences in ``pcc`` mode relative to the default ANSI mode are as +follows: + +* | The keywords ``signed``, ``const``, and ``volatile`` are disabled, to avoid + problems with items declared with those names in old-style code. Those + keywords were ANSI C inventions. The other non-K&R keywords (``enum`` and + ``void``) are judged to have existed already in code and are not disabled. +* | Declarations of the form + + .. code:: c++ + + typedef some-type void; + + | are ignored. +* | Assignment is allowed between pointers and integers, and between + incompatible pointer types, without an explicit cast. A warning is issued. +* | A field selection of the form *p*\ ``->``\ *field* is allowed even if + *p* does not point to a ``struct`` or ``union`` that contains *field*. + *p* must be a pointer or an integer. Likewise, *x*\ ``.``\ *field* is + allowed even if *x* is not a ``struct`` or ``union`` that contains + *field*. *x* must be an lvalue. For both cases, all definitions of + *field* as a field must have the same offset within their ``struct`` or + ``union``. +* | If the configuration flag ``TARG_NO_ERROR_ON_INTEGER_OVERFLOW`` is TRUE, + overflows detected while folding signed integer operations on constants + will cause warnings rather than errors. Usually this should be set to + match the desired target machine behavior on integer operations in C. +* | If the configuration flag ``SAME_REPR_INTS_INTERCHANGEABLE_IN_IL`` is TRUE, + integral types with the same representation (size, signedness, and + alignment) will be considered identical and may be used interchangeably. + For example, this means that ``int`` and ``long`` will be interchangeable + if they have the same size. +* | A warning will be issued for a ``&`` applied to an array. The type of such + an operation is "address of array element" rather than "address of array". +* | For the shift operators ``<<`` and ``>>``, the usual arithmetic conversions + are done, the right operand is converted to ``int``, and the result type is + the type of the left operand. In ANSI C, the integral promotions are done + on the two operands, and the result type is the type of the left operand. + The effect of this difference is that, in ``pcc`` mode, a ``long`` shift + count will force the shift to be done as ``long``. +* | When preprocessing output is generated, the line-identifying directives + will have the ``pcc`` form instead of the ANSI form. +* | String literals will not be shared. Identical string literals will cause + multiple copies of the string to be allocated. +* | ``sizeof`` may be applied to bit fields; the size is that of the underlying + type (e.g., ``unsigned int``). +* | lvalues cast to a type of the same size remain lvalues, except when they + involve a floating-point conversion. +* | When a function parameter list begins with a ``typedef`` identifier, the + parameter list is considered prototyped only if the ``typedef`` identifier + is followed by something other than a comma or right parenthesis: + + .. code:: c++ + + typedef int t; + int f(t) {} /* Old-style list */ + int g(t x) {} /* Prototyped list, parameter x of type t */ + + | That is, function parameters are allowed to have the same names as + ``typedef``\ s. In the normal ANSI mode, of course, any parameter list + that begins with a ``typedef`` identifier is considered prototyped, so the + first example above would give an error. +* | The names of functions and of external variables are always entered at the + file scope. +* | A function declared ``static``, used, and never defined is treated as if + its storage class were ``extern``. +* | A file-scope array that has an unspecified storage class and remains + incomplete at the end of the compilation will be treated as if its storage + class is ``extern`` (in ANSI mode, the number of elements is changed to 1, + and the storage class remains unspecified). +* | The empty declaration + + | ``struct`` *x*; + + | will not hide an outer-scope declaration of the same tag. +* | In a declaration of a member of a ``struct`` or ``union``, no diagnostic is + issued for omitting the declarator list; nevertheless, such a declaration + has no effect on the layout. For example, + + .. code:: c++ + + struct s {char a; int; char b[2];} v; /* sizeof(v) is 3 */ + +* | ``enum``\ s are always given type ``int``. In ANSI mode, and depending on + the configuration flag ``enum_types_can_be_smaller_than_int``, smaller + integral types will be used if possible. +* | No warning is generated for a storage specifier appearing in other than the + first position in a list of specifiers (as in ``int static``). +* | ``short``, ``long``, and ``unsigned`` are treated as "adjectives" in type + specifiers, and they may be used to modify a ``typedef`` type. +* | A "plain" ``char`` is considered to be the same as either ``signed char`` + or ``unsigned char``, depending on the installation default and + command-line options. In ANSI C, "plain" ``char`` is a third type distinct + from both ``signed char`` and ``unsigned char``. +* | Free-standing tag declarations are allowed in the parameter declaration + list for a function with old-style parameters. +* | ``float`` function parameters are promoted to ``double`` function + parameters. +* | ``float`` functions are promoted to ``double`` functions. +* | Declaration specifiers are allowed to be completely omitted in declarations + (ANSI C allows this only for function declarations). Thus + + .. code:: c++ + + i; + + | declares ``i`` as an ``int`` variable. A warning is issued. +* | The ``=`` preceding an initializer may be omitted. A warning is issued. + See K&R first edition, Appendix A, section 17 (anachronisms). This is + accepted only if ``C_ANACHRONISMS_ALLOWED`` is TRUE. +* | All ``float`` operations are done as ``double``. +* | ``__STDC__`` is left undefined. +* | Extra spaces to prevent pasting of adjacent confusable tokens are not + generated in textual preprocessing output. +* | The first directory searched for include files is the directory containing + the file containing the ``#include`` instead of the directory containing + the primary source file. +* | Trigraphs are not recognized. +* | Comments are deleted entirely (instead of being replaced by one space) in + preprocessing output. +* | ``0x`` is accepted as a hexadecimal ``0``, with a warning. +* | ``1E+`` is accepted as a floating-point constant with an exponent of ``0``, + with a warning. +* | The compound assignment operators may be written as two tokens (e.g., + ``+=`` may be written ``+ =``). +* | The compound assignment operators may be written in their old-fashioned + reversed forms (e.g., ``-=`` may be written ``=-``). A warning is issued. + This is described in K&R first edition, Appendix A, section 17 + (anachronisms). This is accepted only if ``C_ANACHRONISMS_ALLOWED`` is + TRUE. +* | The digits ``8`` and ``9`` are allowed in octal constants. +* | A warning rather than an error is issued for integer constants that are + larger than can be accommodated in an ``unsigned long``. The value is + truncated to an acceptable number of low-order bits. +* | The types of large integer constants are determined according to the K&R + rules (they won't be ``unsigned`` in some cases where ANSI C would define + them that way). Integer constants with apparent values larger than + ``LONG_MAX`` are typed as ``long`` and are also marked as "non-arithmetic", + which suppresses some warnings when using them. +* | The escape ``\a`` (alert) is not recognized in character and string + constants. +* | Macro expansion is done differently. Arguments to macros are not + macro-expanded before being inserted into the expansion of the macro. Any + macro invocations in the argument text are expanded when the macro + expansion is rescanned. With this method, macro recursion is possible and + is checked for. +* | Token pasting inside macro expansions is done differently. End-of-token + markers are not maintained, so tokens that abut after macro substitution + may be parsed as a single token. +* | Macro parameter names inside character and string constants are recognized + and substituted for. +* | Macro invocations having too many arguments are flagged with a warning + rather than an error. The extra arguments are ignored. +* | Macro invocations having too few arguments are flagged with a warning + rather than an error. A null string is used as the value of the missing + parameters. +* | Extra ``#else``\ s (after the first has appeared in an ``#if`` block) are + ignored, with a warning. +* | Expressions in a ``switch`` statement are cast to ``int``; this differs + from the ANSI C definition in that a ``long`` expression is (possibly) + truncated. +* | The promotion rules for integers are different: ``unsigned char`` and + ``unsigned short`` are promoted to ``unsigned int``. +* | An identifier in a function is allowed to have the same name as a parameter + of the function. A warning is issued. + +Extensions Accepted in SVR4 Compatibility Mode +---------------------------------------------- + +The following extensions are accepted in SVR4 C compatibility mode: + +* | Macro invocations having too many arguments are flagged with a warning + rather than an error. The extra arguments are ignored. +* | Macro invocations having too few arguments are flagged with a warning + rather than an error. A null string is used as the value of the missing + parameters. +* | The sequence ``/**/`` in a macro definition is treated as equivalent to the + token-pasting operator ``##``. +* | lvalues cast to a type of the same size remain lvalues, except when they + involve a floating-point conversion. +* | Assignment is allowed between pointers and integers, and between + incompatible pointer types, without an explicit cast. A warning is issued. +* | A field selection of the form *p*\ ``->``\ *field* is allowed even if + *p* does not point to a ``struct`` or ``union`` that contains *field*. + *p* must be a pointer. Likewise, *x*\ ``.``\ *field* is allowed even + if *x* is not a ``struct`` or ``union`` that contains *field*. *x* + must be an lvalue. For both cases, all definitions of *field* as a + field must have the same offset within their ``struct`` or ``union``. +* | In an integral constant expression, an integer constant may be cast to a + pointer type and then back to an integral type. +* | Incompatible external object declarations are allowed if the object types + share the same underlying representation. +* | Certain incompatible function declarations are allowed. A warning is + issued. + + .. code:: c++ + + typedef unsigned int size_t; + extern size_t strlen(const char *); + extern int strlen(); /* Warning */ + +Namespace Support +================= + +Namespaces are enabled by default (see ``DEFAULT_NAMESPACES_ENABLED``) except +in the cfront modes. The command-line options ``--namespaces`` and +``--no_namespaces`` can be used to enable or disable the features. + +When doing name lookup in a template instantiation, some names must be found in +the context of the template definition while others may also be found in the +context of the template instantiation. The front end implements two different +instantiation lookup algorithms: the one mandated by the standard (referred to +as "dependent name lookup"), and the one that existed before dependent name +lookup was implemented. + +Dependent name lookup is done in strict mode (unless explicitly disabled by +another command-line option) or when dependent name processing is enabled by +either a configuration flag or command-line option. + +Dependent Name Processing +------------------------- + +When doing dependent name lookup, the front end implements the instantiation +name lookup rules specified in the standard. This processing requires that +nonclass prototype instantiations be done. This in turn requires that the code +be written using the ``typename`` and ``template`` keywords as required by the +standard. + +Lookup Using the Referencing Context +------------------------------------ + +When not using dependent name lookup, the front end uses a name lookup +algorithm that approximates the two-phase lookup rule of the standard, but does +so in such a way that is more compatible with existing code and existing +compilers. + +When a name is looked up as part of a template instantiation but is not found +in the local context of the instantiation, it is looked up in a synthesized +instantiation context that includes both names from the context of the template +definition and names from the context of the instantiation. Here's an example: + +.. code:: c++ + + namespace N { + int g(int); + int x = 0; + template struct A { + T f(T t) { return g(t); } + T f() { return x; } + }; + } + namespace M { + int x = 99; + double g(double); + N::A ai; + int i = ai.f(0); // N::A::f(int) calls N::g(int) + int i2 = ai.f(); // N::A::f() returns 0 (= N::x) + N::A ad; + double d = ad.f(0); // N::A::f(double) calls M::g(double) + double d2 = ad.f(); // N::A::f() also returns 0 (= N::x) + } + +The lookup of names in template instantiations does not conform to the rules in +the standard in the following respects: + +* | Although only names from the template definition context are considered for + names that are not functions, the lookup is not limited to those names + visible at the point at which the template was defined. +* | Functions from the context in which the template was referenced are + considered for all function calls in the template. Functions from the + referencing context should only be visible for "dependent" function calls. + +For details of the algorithm implemented, see the :ref:`symbol-table` +chapter (in particular the :ref:`instantiation-context-lookup` section). + +Argument Dependent Lookup +-------------------------- + +When argument-dependent lookup is enabled, functions made visible using +argument-dependent lookup overload with those made visible by normal lookup. +The standard requires that this overloading occur even when the name found by +normal lookup is a block ``extern`` declaration. The front end does this +overloading, but in default mode, argument-dependent lookup is suppressed when +the normal lookup finds a block ``extern``. + +This means a program can have different behavior, depending on whether it is +compiled with or without argument-dependent lookup, even if the program makes +no use of namespaces. For example: + +.. code:: c++ + + struct A { }; + A operator+(A, double); + void f() { + A a1; + A operator+(A, int); + a1 + 1.0; // calls operator+(A, double) with arg-dependent + // lookup enabled but otherwise calls + // operator+(A, int); + } + +Runtime Support +--------------- + +The headers and runtime provided with the EDG front end support two different +versions (i.e., with and without namespaces) under control of +``__EDG_RUNTIME_USES_NAMESPACES``, a preprocessing option defined by the front +end. + +.. _template-instantiation: + +Template Instantiation +====================== + +The C++ language includes the concept of *templates*. A template is a +description of a class or function that is a model for a family of related +classes or functions. [#f3]_ For example, one can write a template for a +``Stack`` class, and then use a stack of integers, a stack of floats, and a +stack of some user-defined type. In the source, these might be written +``Stack``, ``Stack``, and ``Stack``. From a single source +description of the template for a stack, the compiler can create +*instantiations* of the template for each of the types required. + +The instantiation of a class template is always done as soon as it is needed in +a compilation. However, the instantiations of template functions, template +variables, member functions of template classes, and static data members of +template classes (hereafter referred to as template entities) are not +necessarily done immediately, for several reasons: + +* | One would like to end up with only one copy of each instantiated entity + across all the object files that make up a program. (This of course + applies to entities with external linkage.) +* | The language allows one to write a *specialization* of a template entity, + i.e., a specific version to be used in place of a version generated from + the template for a specific data type. (One could, for example, write a + version of ``Stack``, or of just ``Stack::push``, that replaces + the template-generated version; often, such a specialization provides a + more efficient representation for a particular data type.) Since the + compiler cannot know, when compiling a reference to a template entity, if a + specialization for that entity will be provided in another compilation, it + cannot do the instantiation automatically in any source file that + references it. (The modern C++ language requires that a specialization be + declared in every compilation in which it is used, but for compatibility + with existing code and older compilers the EDG front end does not require + that in some modes. See the command-line option + ``--no_distinct_template_signatures``.) +* | C++ templates can be *exported* (i.e., declared with the keyword + ``export``). Such templates can be used in a translation unit that does + not contain the definition of the template to instantiate. The + instantiation of such a template must be delayed until the template + definition has been found. +* | The language also dictates that template functions that are not referenced + should not be compiled, that, in fact, such functions might contain + semantic errors that would prevent them from being compiled. Therefore, a + reference to a template class should not automatically instantiate all the + member functions of that class. + +(It should be noted that certain template entities are always instantiated when +used, e.g., inline functions.) + +From these requirements, one can see that if the compiler is responsible for +doing all the instantiations automatically, it can only do so on a program-wide +basis. That is, the compiler cannot make decisions about instantiation of +template entities until it has seen all the source files that make up a +complete program. + +The EDG C++ front end provides an instantiation mechanism that does automatic +instantiation at link time. For cases where the programmer wants more explicit +control over instantiation, the front end also provides instantiation modes and +instantiation pragmas, which can be used to exert fine-grained control over the +instantiation process. + +Automatic Instantiation +----------------------- + +The goal of an automatic instantiation mode is to provide painless +instantiation. The programmer should be able to compile source files to object +code, then link them and run the resulting program, and never have to worry +about how the necessary instantiations get done. + +In practice, this is hard for a compiler to do, and different compilers use +different automatic instantiation schemes with different strengths and +weaknesses: + +* | AT&T/USL/Novell/SCO's *cfront* product saves information about each file it + compiles in a special directory called ``ptrepository``. It instantiates + nothing during normal compilations. At link time, it looks for entities + that are referenced but not defined, and whose mangled names indicate that + they are template entities. For each such entity, it consults the + ``ptrepository`` information to find the file containing the source for the + entity, and it does a compilation of the source to generate an object file + containing object code for that entity. This object code for instantiated + objects is then combined with the "normal" object code in the link step. + | + | The programmer using *cfront* must follow a particular coding + convention: all templates must be declared in "``.h``" files, and for + each such file there must be a corresponding "``.C``" file containing + the associated definitions. The compiler is never told about the + "``.C``" files explicitly; one does not, for example, compile them in + the normal way. The link step looks for them when and if it needs + them, and does so by taking the "``.h``" file name and replacing its + suffix. [#f4]_ + | + | This scheme has the disadvantage that it does a separate compilation for + each instantiated function (or, at best, one compilation for all the member + functions of one class). Even though the function itself is often quite + small, it must be compiled along with the declarations for the types on + which the instantiation is based, and those declarations can easily run + into many thousands of lines. For large systems, these compilations can + take a very long time. The link step tries to be smart about recompiling + instantiations only when necessary, but because it keeps no fine-grained + dependency information, it is often forced to "recompile the world" for a + minor change in a "``.h``" file. In addition, *cfront* has no way of + ensuring that preprocessing symbols are set correctly when it does these + instantiation compilations, if preprocessing symbols are set other than on + the command line. +* | Borland's C++ compiler instantiates everything referenced in a compilation, + then uses a special linker to remove duplicate definitions of instantiated + functions. + | + | The programmer using Borland's compiler must make sure that every + compilation sees all the source code it needs to instantiate all the + template entities referenced in that compilation. That is, one cannot + refer to a template entity in a source file if a definition for that entity + is not included by that source file. In practice, this means that either + all the definition code is put directly in the "``.h``" files, or that each + "``.h``" file includes an associated "``.C``" (actually, "``.CPP``") file. + | + | This scheme is straightforward, and works well for small programs. For + large systems, however, it tends to produce very large object files, + because each object file must contain object code (and symbolic debugging + information) for each template entity it references. + +EDG's approach is a little different. It requires that, for each instantiation +of a non-exported template, there is some (normal, top-level, +explicitly-compiled) source file that contains the definition of the template +entity, a reference that causes the instantiation, and the declarations of any +types required for the instantiation. [#f5]_ This requirement can be met in +various ways: + +* | The Borland convention: each "``.h``" file that declares a template entity + also contains either the definition of the entity or includes another file + containing the definition. +* | Implicit inclusion: when the compiler sees a template declaration in a + "``.h``" file and discovers a need to instantiate that entity, it is + given permission to go off looking for an associated definition file + having the same base name and a different suffix, and it implicitly + includes that file at the end of the compilation. This method allows + most programs written using the *cfront* convention to be compiled with + EDG's approach. See :ref:`implicit-inclusion`. +* | The ad hoc approach: the programmer makes sure that the files that define + template entities also have the definitions of all the available types, and + adds code or pragmas in those files to request instantiation of the + entities there. + +Exported templates are also supported by the EDG automatic instantiation +method, but they require additional mechanisms explained further on. + +The EDG automatic instantiation method works as follows for non-exported +templates: [#f6]_ + +#. | The first time the source files of a program are compiled, no template + entities are instantiated. However, template information files (with, by + default, a "``.ti``" suffix) are generated and contain information about + things that *could* have been instantiated in each compilation [#f7]_. +#. | When the object files are linked together, a program called the + *prelinker* is run. It examines the object files, looking for + references and definitions of template entities, and for the added + information about entities that could be instantiated. +#. | If the prelinker finds a reference to a template entity for which there + is no definition anywhere in the set of object files, it looks for a file + that indicates that it could instantiate that template entity. When it + finds such a file, it assigns the instantiation to it. The set of + instantiations assigned to a given file is recorded in an associated + instantiation request file (with, by default, a "``.ii``" suffix). +#. | The prelinker then executes the compiler again to recompile each file for + which the instantiation request file was changed. The original + compilation command-line options (saved in the template information file) + are used for the recompilation. +#. | When the compiler compiles a file, it reads the instantiation request + file for that file and obeys the requests therein. It produces a new + object file containing the requested template entities (and all the other + things that were already in the object file). The compiler also receives + a definition list file, which lists all the instantiations for which + definitions already exist in the set of object files. If during the + compilation the compiler has the opportunity to instantiate a referenced + entity that is not on that list, it goes ahead and does the instantiation. + It passes back to the prelinker (in the definition list file) a list of + the instantiations that it has "adopted" in this way, so the prelinker can + assign them to the file. This adoption process allows rapid instantiation + and assignment of instantiations referenced from new instantiations, and + reduces the need to recompile a given file more than once during the + prelinking process. +#. | The prelinker repeats steps 3-5 until there are no more instantiations to + be adjusted. +#. | The object files are linked together. + +Once the program has been linked correctly, the instantiation request files +contain a complete set of instantiation assignments. From then on, whenever +source files are recompiled, the compiler will consult the instantiation +request files and do the indicated instantiations as it does the normal +compilations. That means that, except in cases where the set of required +instantiations changes, the prelink step from then on will find that all the +necessary instantiations are present in the object files and no instantiation +assignment adjustments need be done. That's true even if the entire program is +recompiled. + +If the programmer provides a specialization of a template entity somewhere in +the program, the specialization will be seen as a definition by the prelinker. +Since that definition satisfies whatever references there might be to that +entity, the prelinker will see no need to request an instantiation of the +entity. If the programmer adds a specialization to a program that has +previously been compiled, the prelinker will notice that too and remove the +assignment of the instantiation from the proper instantiation request file. + +The instantiation request files should not, in general, require any manual +intervention. One exception: if a definition is changed in such a way that +some instantiation no longer compiles (it gets errors), and at the same time a +specialization is added in another file, and the first file is being recompiled +before the specialization file and is getting errors, the instantiation request +file for the file getting the errors must be deleted manually to allow the +prelinker to regenerate it. + +If the prelinker changes an instantiation assignment, it will issue a message +like + +.. code:: text + + C++ prelinker: A::f() assigned to file test.o + C++ prelinker: executing: /edg/bin/eccp -c test.c + +The automatic instantiation scheme can coexist with partial explicit control of +instantiation by the programmer through the use of pragmas or command-line +specification of the instantiation mode. See the following sections. + +Instantiations are normally generated as part of the object file of the +translation unit in which the instantiations are performed. But when "one +instantiation per object" mode is specified, each instantiation is placed in +its own object file. One-instantiation-per-object mode is useful when +generating libraries that need to include copies of the instances referenced +from the library. If each instance is not placed in its own object file, it +may be impossible to link the library with another library containing some of +the same instances. Without this feature it is necessary to create each +individual instantiation object file using the manual instantiation mechanism. + +The automatic instantiation mode can be configured out altogether by setting +the configuration flag ``AUTOMATIC_TEMPLATE_INSTANTIATION`` to FALSE. It can +be turned on or off using the ``--auto_instantiation`` and +``--no_auto_instantiation`` command-line options. If automatic instantiation +is turned off, the template information file is not generated. + +Instantiation Modes +------------------- + +Normally, when a file is compiled, no template entities are instantiated +(except those assigned to the file by automatic instantiation). The overall +instantiation mode can, however, be changed by a command line option: + +.. list-table:: + + * - | ``-tnone`` + - | Do not automatically create instantiations of any template entities. + This is the default. It is also the usually appropriate mode when + automatic instantiation is done. + * - | ``-tused`` + - | Instantiate those template entities that were used in the compilation. + This will include all static data members for which there are template + definitions. + * - | ``-tall`` + - | Instantiate all template entities declared or referenced in the + compilation unit. For each fully instantiated template class, all of + its member functions and static data members will be instantiated + whether or not they were used. Nonmember template functions will be + instantiated even if the only reference was a declaration. + * - | ``-tlocal`` + - | Similar to ``-tused`` except that the functions are given internal + linkage. This is intended to provide a very simple mechanism for + those getting started with templates. The compiler will instantiate + the functions that are used in each compilation unit as local + functions, and the program will link and run correctly (barring + problems due to multiple copies of local static variables.) However, + one may end up with many copies of the instantiated functions, so this + is not suitable for production use. ``-tlocal`` can not be used in + conjunction with automatic template instantiation. If automatic + instantiation is enabled by default, it will be disabled by the + ``-tlocal`` option. If automatic instantiation is not enabled by + default, use of ``-tlocal`` and ``-T`` is an error. + +In the case where the ``eccp`` script is given a single file to compile and +link, e.g., + +.. code:: text + + eccp t.c + +the compiler knows that all instantiations will have to be done in the single +source file. Therefore, it uses the ``-tused`` mode and suppresses automatic +instantiation. + +Instantiation ``#pragma`` Directives +------------------------------------ + +Instantiation pragmas can be used to control the instantiation of specific +template entities or sets of template entities. There are three instantiation +pragmas: + +* | The ``instantiate`` pragma causes a specified entity to be instantiated. +* | The ``do_not_instantiate`` pragma suppresses the instantiation of a + specified entity. It is typically used to suppress the instantiation of an + entity for which a specific definition will be supplied. +* | The ``can_instantiate`` pragma indicates that a specified entity can be + instantiated in the current compilation, but need not be; it is used in + conjunction with automatic instantiation, to indicate potential sites for + instantiation if the template entity turns out to be required. [#f8]_ + +The argument to the instantiation pragma may be: + +.. list-table:: + + * - | a template class name + - | ``A`` + * - | a template class declaration + - | ``class A`` + * - | a member function name + - | ``A::f`` + * - | a static data member name + - | ``A::i`` + * - | a static data member decl. + - | ``int A::i`` + * - | a member function declaration + - | ``void A::f(int, char)`` + * - | a template function declaration + - | ``char* f(int, float)`` + * - | a template variable name + - | ``x`` + +A pragma in which the argument is a template class name (e.g., ``A`` or +``class A``) is equivalent to repeating the pragma for each member +function and static data member declared in the class. When instantiating an +entire class a given member function or static data member may be excluded +using the ``do_not_instantiate`` pragma. For example, + +.. code:: c++ + + #pragma instantiate A + #pragma do_not_instantiate A::f + +The template definition of a template entity must be present in the compilation +for an instantiation to occur. If an instantiation is explicitly requested by +use of the ``instantiate`` pragma and no template definition is available or a +specific definition is provided, an error is issued. + +.. code:: c++ + + template void f1(T); // No body provided + template void g1(T); // No body provided + void f1(int) {} // Specific definition + void main(){ + int i; + double d; + f1(i); + f1(d); + g1(i); + g1(d); + } + #pragma instantiate void f1(int) // error - specific definition + #pragma instantiate void g1(int) // error - no body provided + +``f1(double)`` and ``g1(double)`` will not be instantiated (because no bodies +were supplied) but no errors will be produced during the compilation (if no +bodies are supplied at link time, a linker error will be produced). + +A member function name (e.g., ``A::f``) can only be used as a pragma +argument if it refers to a single user defined member function (i.e., not an +overloaded function). Compiler-generated functions are not considered, so a +name may refer to a user defined constructor even if a compiler-generated copy +constructor of the same name exists. Overloaded member functions can be +instantiated by providing the complete member function declaration, as in + +.. code:: c++ + + #pragma instantiate char* A::f(int, char*) + +The argument to an instantiation pragma may not be a compiler-generated +function, an inline function, or a pure virtual function. + +Implicit Inclusion +------------------ + +When implicit inclusion is enabled, the front end is given permission to assume +that if it needs a definition to instantiate a template entity declared in a +"``.h``" file it can implicitly include the corresponding "``.C``" file to get +the source code for the definition. For example, if a template entity +``ABC::f`` is declared in file ``xyz.h``, and an instantiation of ``ABC::f`` is +required in a compilation but no definition of ``ABC::f`` appears in the source +code processed by the compilation, the compiler will look to see if a file +``xyz.C`` exists, and if so it will process it as if it were included at the +end of the main source file. + +To find the template definition file for a given template entity the front end +needs to know the path name specified in the original include of the file in +which the template was declared and whether the file was included using the +system include syntax (e.g., ``#include ``). This information is not +available for preprocessed source containing ``#line`` directives. +Consequently, the front end will not attempt implicit inclusion for source code +containing ``#line`` directives. + +The file to be implicitly included is found by replacing the file suffix with +each of the suffixes specified in the instantiation file suffix list. The +normal include search path mechanism is then used to look for the file to be +implicitly included. + +``DEFAULT_INSTANTIATION_FILE_SUFFIX_LIST`` defines the set of definition-file +suffixes tried. By default, the list is "``.c``", "``.C``", "``.cpp``", +"``.CPP``", "``.cxx``", "``.CXX``", and "``.cc``". + +Implicit inclusion works well alongside automatic instantiation, but the two +are independent. They can be enabled or disabled independently, and implicit +inclusion is still useful when automatic instantiation is not done. + +The implicit inclusion mode can be configured out altogether by setting the +configuration flag ``INSTANTIATION_BY_IMPLICIT_INCLUSION`` to FALSE. It can be +turned on or off using the ``--implicit_include`` and ``--no_implicit_include`` +command-line option\ ``s``. + +Implicit inclusions are only performed during the normal compilation of a file, +(i.e., not when doing only preprocessing). A common means of investigating +certain kinds of problems is to produce a preprocessed source file that can be +inspected. When using implicit inclusion it is sometimes desirable for the +preprocessed source file to include any implicitly included files. This may be +done using the ``--no_preproc_only`` command line option. This causes the +preprocessed output to be generated as part of a normal compilation. When +implicit inclusion is being used, the implicitly included files will appear as +part of the preprocessed output in the precise location at which they were +included in the compilation. + +Exported Templates +------------------ + +Exported templates are templates declared with the keyword ``export``. +Exporting a class template is equivalent to exporting each of its static data +members and each of its non-inline member functions. An exported template is +special because its definition does not need to be present in a translation +unit that uses that template. In other words, the definition of an exported +(non-class) template does not need to be explicitly or implicitly included in a +translation unit that instantiates that template. For example, the following +is a valid C++ program consisting of two separate translation units: + +.. code:: c++ + + // File 1: + #include + static void trace() { printf("File 1\n"); } + + export template T const& min(T const&, T const&); + int main() { + trace(); + return min(2, 3); + } + +.. code:: c++ + + // File 2: + #include + static void trace() { printf("File 2\n"); } + + export template T const& min(T const &a, T const &b) { + trace(); + return a T const& min(T const &a, T const &b) { + return a`` header file to get the proper definitions of + ``CHAR_MAX`` and ``CHAR_MIN``. + * - | ``__FUNCTION__`` + - | Defined in all modes to the name of the current function. An error is + issued if it is used outside of a function. An EDG, GNU, and + Microsoft extension. (Depending on the current mode, this identifier + behaves as a variable or as a string literal; never as a preprocessor + macro.) + * - | ``__func__`` + - | Same as ``__FUNCTION__`` in C99, C++11, and GNU modes. (This + identifier behaves as a variable; not as a preprocessor macro.) + * - | ``__PRETTY_FUNCTION__`` + - | Defined in all modes to the name of the current function. This + includes the return type and parameter types of the function. An + error is issued if it is used outside of a function. An EDG and GNU + extension. (Depending on the current mode, this identifier behaves as + a variable or as a string literal; never as a preprocessor macro.) + * - | ``__FUNCSIG__`` + - | Same as ``__PRETTY_FUNCTION__`` in Microsoft mode. (This identifier + behaves as a string literal; not as a preprocessor macro.) + * - | ``__FUNCDNAME__`` + - | Defined to the "decorated" name of the current function (i.e., its + mangled name) in Microsoft mode. (This identifier behaves as a string + literal; not as a preprocessor macro.) + * - | ``__BASE_FILE__`` + - | Defined in all modes. Similar to ``__FILE__`` but indicates the + primary source file rather than the current one (i.e., when the + current file is an included file). + * - | ``_WCHAR_T`` + - | Defined in C++ mode when ``wchar_t`` is a keyword. The name of this + macro and whether it is predefined are specified by configuration + options. ``_WCHAR_T`` is the default. + * - | ``_WCHAR_T_DEFINED`` + - | Defined in Microsoft C++ mode when ``wchar_t`` is a keyword. + * - | ``_NATIVE_WCHAR_T_DEFINED`` + | + - | Defined in Microsoft C++ mode when ``wchar_t`` is a keyword (Microsoft + version 1300 and above). + * - | ``_BOOL`` + - | Defined in C++ mode when ``bool`` is a keyword. The name of this + macro and whether it is predefined are specified by configuration + options. ``_BOOL`` is the default. + * - | ``__BOOL_DEFINED`` + - | Defined in Microsoft C++ mode when ``bool`` is a keyword. + * - | ``__ARRAY_OPERATORS`` + - | Defined in C++ mode when array new and delete are enabled. The name + of this macro and whether it is predefined are specified by + configuration options. ``__ARRAY_OPERATORS`` is the default. + * - | ``__EXCEPTIONS`` + - | Defined in C++ mode when exception handling is enabled. The name of + this macro and whether it is predefined are specified by configuration + options. ``__EXCEPTIONS`` is the default. + * - | ``__RTTI`` + - | Defined in C++ mode when RTTI is enabled. The name of this macro and + whether it is predefined are specified by configuration options. + ``__RTTI`` is the default. + * - | ``__PLACEMENT_DELETE`` + - | Defined in C++ mode when placement delete is enabled. The name of + this macro and whether it is predefined are specified by configuration + options. ``__PLACEMENT_DELETE`` is the default. Placement delete is + enabled when ``ABI_CHANGES_FOR_PLACEMENT_DELETE`` is TRUE and + exception handling is enabled. + * - | ``__NO_LONG_LONG`` + - | Defined in all modes when the ``long long`` type is not supported. + The name of this macro and whether it is predefined are specified by + configuration options. ``__NO_LONG_LONG`` is the default. + * - | ``__EDG_RUNTIME_USES_NAMESPACES`` + | + - | Defined in C++ mode when the configuration flag + ``RUNTIME_USES_NAMESPACES`` is TRUE. The name of this macro and + whether it is predefined are specified by configuration options. + ``__EDG_RUNTIME_USES_NAMESPACES`` is the default. + * - | ``__EDG_IMPLICIT_USING_STD`` + | + - | Defined in C++ mode when the configuration flag + ``RUNTIME_USES_NAMESPACES`` is TRUE and when ``implicit_using_std`` + has been set to TRUE, either by a command line option or by the + configuration flag ``DEFAULT_IMPLICIT_USING_STD``, indicating that the + standard header files should implicitly do a using-directive on the + ``std`` namespace. The name of this macro and whether it is + predefined are specified by configuration options. + ``__EDG_IMPLICIT_USING_STD`` is the default. + * - | ``__EDG_TYPE_TRAITS_ENABLED`` + | + - | Defined in non-Microsoft modes when type traits pseudo-functions (to + ease the implementation of ISO/IEC TR 19768; e.g., "``__is_union``") + are enabled. The name of this predefined macro is specified by a + configuration option. ``__EDG_TYPE_TRAITS_ENABLED`` is the default. + * - | ``__EDG__`` + - | Always defined. + * - | ``__EDG_VERSION__`` + - | Defined to an integral value that represents the version number of the + front end. For example. version 2.30 is represented as 230. + * - | ``__EDG_IA64_ABI`` + - | Defined as 1 when using a front end configured to use the IA-64 ABI. + * - | ``__embedded_cplusplus`` + - | Defined as 1 in Embedded C++ mode. + * - | ``_CHAR_UNSIGNED`` + - | Defined in Microsoft mode when ``char`` is unsigned. + * - | ``_MSC_VER`` + - | Defined in Microsoft mode to the version number of the Microsoft + compiler that is to be emulated. For example, 1100 is the value that + corresponds to Visual C++ version 5.0. + * - | ``_MSC_BUILD`` + - | Defined in Microsoft mode to the value of ``microsoft_build_number``. + * - | ``_M_CEE`` + - | Defined in Microsoft mode when C++/CLI mode is in effect (e.g., when + ``--cppcli`` is specified). + * - | ``_MSC_EXTENSIONS`` + - | Defined in Microsoft mode. + * - | ``_WIN32`` + - | Defined (unconditionally) in Microsoft mode. + * - | ``_WIN64`` + - | Defined in Microsoft mode when ``targ_supports_x86_64`` is TRUE. + * - | ``_INTEGRAL_MAX_BITS`` + - | Defined in Microsoft mode to the number of bits in the largest + integral type that is supported. The value depends on the way in + which the front end was configured. + * - | ``_CPPRTTI`` + - | Defined in Microsoft mode C++ when RTTI is enabled. + * - | ``__GNUC__`` + - | Defined in GNU mode to the value specified by the ``GCC_VERSION`` + configuration macro. + * - | ``__GNUC_MINOR__`` + - | Defined in GNU mode to the value specified by the + ``GCC_MINOR_VERSION`` configuration macro. + * - | ``__VERSION__`` + - | Defined in GNU mode to the value specified by the + ``GCC_VERSION_STRING`` configuration macro. + * - | ``__PRAGMA_REDEFINE_EXTNAME`` + | + - | Defined if all modes when the configuration flag + ``REDEFINE_EXTNAME_PRAGMA_ENABLED`` is TRUE. + * - | ``__upc__`` + - | Defined when UPC extensions are enabled. + * - | ``__COUNTER__`` + - | Defined in Microsoft mode. Returns an integer value, starting with + zero and incremented each time the macro is used. + * - | ``__TIMESTAMP__`` + - | Defined in Microsoft mode. Returns a string literal containing the + modification date and time of the source file in which it is + specified. + * - | ``__EDG_IA64_ABI`` + - | Defined in C++ mode when using the IA-64 ABI. The name of this + predefined macro is specified by a configuration option. + ``__EDG_IA64_ABI`` is the default. + * - | ``__EDG_IA64_ABI_USE_INT_STATIC_INIT_GUARD`` + - | Defined in C++ mode when using the IA-64 ABI when guard variables are + ``int``-sized (i.e., in the ARM EABI). The name of this predefined + macro is specified by a configuration option. + ``__EDG_IA64_ABI_USE_INT_STATIC_INIT_GUARD`` is the default. + * - | ``__EDG_IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS`` + - | Defined in C++ mode when using the IA-64 ABI when constructors and + destructors return the ``this`` pointer (i.e., in the ARM EABI). The + name of this predefined macro is specified by a configuration option. + ``__EDG_IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS`` is the default. + * - | ``__EDG_SIZE_TYPE__`` + - | Defined to be the type of ``size_t``. + | ``__EDG_PTRDIFF_TYPE__`` + | Defined to be the type of ``ptrdiff_t``. + * - | ``__CHAR16_T_AND_CHAR32_T`` + | + - | Defined in C++ mode when ``char16_t`` and ``char32_t`` are keywords. + The name of this macro and whether it is predefined are specified by + configuration options. ``__CHAR16_T_AND_CHAR32_T`` is the default. + * - | ``__CHAR16_TYPE__`` + - | Defined in GNU mode as the underlying type for ``char16_t`` (GNU + version 40400 and above). + * - | ``__CHAR32_TYPE__`` + - | Defined in GNU mode as the underlying type for ``char32_t`` (GNU + version 40400 and above). + * - | ``__VARIADIC_TEMPLATES`` + | + - | Defined in C++ mode when variadic templates are supported. The name + of this macro and whether it is predefined are specified by + configuration options. ``__VARIADIC_TEMPLATES`` is the default. + * - | ``__STDCPP_THREADS__`` + - | Defined in C++ mode when the implementation supports multiple threads + (i.e., when ``IMPLEMENTATION_SUPPORTS_MULTIPLE_THREADS`` is TRUE + and the global variable ``std_thread_local_storage_specifier_enabled`` + is TRUE). + +Pragmas +======= + +``#pragma`` directives are used within the source program to request certain +kinds of special processing. The ``#pragma`` directive is part of the standard +C and C++ languages, but the meaning of any pragma is implementation-defined. + +Instantiation Pragmas +--------------------- + +The following are described in detail in the template instantiation section of +this chapter: + +.. code:: c++ + + #pragma instantiate + #pragma do_not_instantiate + #pragma can_instantiate + +Precompiled Header Pragmas +-------------------------- + +The following are described in the section on precompiled header processing: + +.. code:: c++ + + #pragma hdrstop + #pragma no_pch + +Once Pragma +----------- + +The front end also recognizes ``#pragma once``, which, when placed at the +beginning of a header file, indicates that the file is written in such a way +that including it several times has the same effect as including it once. +Thus, if the front end sees ``#pragma once`` at the start of a header file, it +will skip over it if the file is ``#include``\ d again. + +A typical idiom is to place an ``#ifndef`` guard around the body of the file, +with a ``#define`` of the guard variable after the ``#ifndef``: + + | ``#pragma once // optional`` + | ``#ifndef FILE_H`` + | ``#define FILE_H`` + | ``...`` *body of the header file* ``...`` + | ``#endif`` + +The ``#pragma once`` is marked as optional in this example, because the front +end recognizes the ``#ifndef`` idiom and does the optimization even in its +absence. ``#pragma once`` is accepted for compatibility with other compilers +and to allow the programmer to use other guard-code idioms. + +Diagnostic Pragmas +------------------ + +The following pragmas may be used to control the error severity used when a +given diagnostic message is issued. + +.. code:: c++ + + #pragma diag_suppress + #pragma diag_remark + #pragma diag_warning + #pragma diag_error + #pragma diag_default + #pragma diag_once + +These are similar in function to the equivalent command-line options. Uses of +these pragmas have the following form: + + | ``#pragma diag_``\ *xxx* ``[=]`` *error_number_or_tag*\ ``,`` *error_number_or_tag* ... + +The diagnostic affected is specified using either an error number or an error +tag name. The "``=``" is optional. Any diagnostic may be overridden to be an +error, but only diagnostics with a severity of discretionary error or below may +have their severity reduced to a warning or below, or be suppressed. The +``diag_default`` pragma is used to return the severity of a diagnostic to the +one that was in effect before any pragmas were issued (i.e., the normal +severity of the message as modified by any command-line options). The +following example suppresses the "pointless friend declaration" warning on the +declaration of class ``A``: + +.. code:: c++ + + #pragma diag_suppress 522 + class A { friend class A; }; + #pragma diag_default 522 + class B { friend class B; }; + +The ``diag_once`` pragma causes the specified diagnostics to be issued only +once as a warning or remark. + +Pack Pragma +----------- + +When ``USER_CONTROL_OF_STRUCT_PACKING`` is TRUE, ``#pragma pack`` is +recognized. It is used to specify the maximum alignment allowed for nonstatic +data members of structs and classes, even if that alignment is less than the +alignment dictated by the member's type. + +The basic syntax is: + + | ``#pragma pack(``\ *n*\ ``)`` + | ``#pragma pack()`` + +where argument *n*, a power-of-2 value within the range defined by +``TARG_MINIMUM_PACK_ALIGNMENT`` and ``TARG_MAXIMUM_PACK_ALIGNMENT``, is the new +packing alignment that is to go into effect for subsequent declarations, until +another ``#pragma pack`` is seen. The second form cancels the effect of a +preceding ``#pragma pack(``\ *n*\ ``)`` and either restores the default packing +alignment specified by the ``--pack_alignment`` command-line option or, if the +option was not used, disables the packing of structs and classes. + +An enhanced syntax (intended to be compatible with the similar facility offered +by Microsoft C/C++ compilers) is also supported in which keywords ``push`` and +``pop`` can be used to manage a stack of packing alignment values -- for +instance: + +.. code:: c++ + + #pragma pack (push, xxx, 16) + /* Packing alignment set to 16. */ + #include "xxx.h" + #pragma pack (pop, xxx) + /* Packing alignment reset to what it was prior to the + above #pragma pack directive, even if the included header + left some unrelated pragma pack entries on the stack. */ + +which has the effect saving the current packing alignment value and +establishing a new one, processing the include file (which may leave the +packing alignment with an unknown setting), and restoring the original value. +Finally, the form + +.. code:: c++ + + #pragma pack(show) + +causes the front end to emit a warning describing the current setting of the +maximum member alignment (if any). + +In C++ a ``#pragma pack`` directive has "local" effect when it appears inside a +function template, an instantiation of a class template, or the body of a +member function or friend function that is defined within a class definition. +When such a context is entered, the current pack alignment state is saved, so +that it can be restored when the context is exited. For example, + +.. code:: c++ + + template class A { + : + #pragma pack(1) + : + }; + #pragma pack(4) + main() { + A a; // #pragma pack(1) is local to A + struct S { char c; int i; }; // sizeof(S) == 8, not 5 + } + +Moreover, within an instantiation of a class or function template, the default +pack alignment is that which is in effect at the point of the template's +definition, not at the point of its instantiation. Here is an example: + +.. code:: c++ + + #pragma pack(1) + template int f(T) { + struct S { char c; int i; }; // default pack alignment is 1 for each + return sizeof(S); // instance of f + } + #pragma pack(4) + main() { + int i = f(0); // i = 5, not 8 + } + +These rules apply to inline-defined member functions, too, because their bodies +are also scanned "out of order" relative to the textual order of the source +program (i.e., not till all the class members have been declared). + +.. code:: c++ + + #pragma pack(4) + struct A { + int f() { + #pragma pack(1) // #pragma pack(1) is local to A::f + struct S { char c; int i; }; // sizeof(S) is 5 + } + int g() { + struct S { char c; int i; }; // sizeof(S) is 8 + } + #pragma pack(1) + int h() { + struct S { char c; int i; }; // sizeof(S) is 5 + } + }; + +When ``IDENT_DIRECTIVE_AND_PRAGMA`` is TRUE, ``#pragma ident`` is recognized, +as is ``#ident``: + +.. code:: c++ + + #pragma ident "string" + #ident "string" + +Both are implemented by recording the string in a pragma entry and passing it +to the back end. + +When ``PRAGMA_WEAK_ALLOWED`` is TRUE, ``#pragma weak`` is recognized. Its form +is: + + | ``#pragma weak`` *name1* [ ``=`` *name2* ] + +where *name1* is the name to be given "weak binding" and is a synonym for +*name2* if the latter is specified. The entire argument string is recorded +in the pragma entry and passed to the back end. + +Microsoft Pragmas +----------------- + +The following pragmas are accepted in Microsoft mode: + +.. code:: c++ + + #pragma push_macro("identifier") + #pragma pop_macro("identifier") + #pragma include_alias("a_long_file_name.h", "short.h") + +In addition, when ``NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE`` is TRUE, +the ``setlocale`` pragma is accepted: + +.. code:: c++ + + #pragma setlocale("locale name") + +The ``pack`` pragma is also accepted by the Microsoft compiler, but its +acceptance by the front end is controlled by a separate configuration flag, not +by whether or not Microsoft mode is being used. + +IL Display Pragma +----------------- + +As a debugging aid, in configurations where ``NEED_IL_DISPLAY`` is TRUE, +the ``il_display`` pragma can be used to display the underlying IL for the IL +entity that the pragma is attached to. The ``il_display`` pragma is a +``pbk_next_construct`` pragma that attaches to the subsequent declaration or +statement and displays the IL associated with that entity. Note that the IL +displayed represents the IL at the current point in the compilation and may not +accurately reflect the eventual IL. This can be useful for displaying source +location information. For example: + +.. code:: c++ + + struct A { int x, y; }; + void f(int i) { + #pragma il_display + A a = { 1, 2 }; + #pragma il_display + i++; + } + +.. _precompiled-headers: + +Precompiled Headers +=================== + +It is often desirable to avoid recompiling a set of header files, +especially when they introduce many lines of code and the primary source +files that ``#include`` them are relatively small. The EDG front end +provides a mechanism for, in effect, taking a snapshot of the state of the +compilation at a particular point and writing it to a disk file before +completing the compilation; then, when recompiling the same source file or +compiling another file with the same set of header files, it can recognize +the "snapshot point," verify that the corresponding precompiled header +("PCH") file is reusable, and read it back in. Under the right +circumstances, this can produce a dramatic improvement in compilation time; +the trade-off is that PCH files can take a lot of disk space. Because of +potential memory conflicts between threads, precompiled header processing +is disabled in multi-threaded configurations. In particular, a PCH file +cannot be created if ``MULTIPLE_THREAD_COMPILATION`` is TRUE and, because +the configurations must match, a PCH file by a single-threaded +configuration cannot be used. + +Automatic Precompiled Header Processing +--------------------------------------- + +When ``--pch`` appears on the command line, automatic precompiled header +processing is enabled. This means the front end will automatically look for a +qualifying precompiled header file to read in and/or will create one for use on +a subsequent compilation. + +The PCH file will contain a snapshot of all the code preceding the "header +stop" point. The header stop point is typically the first token in the primary +source file that does not belong to a preprocessing directive, but it can also +be specified directly by ``#pragma hdrstop`` (see below) if that comes first. +For example: + +.. code:: c++ + + #include "xxx.h" + #include "yyy.h" + int i; + +The header stop point is ``int`` (the first non-preprocessor token) and the PCH +file will contain a snapshot reflecting the inclusion of ``xxx.h`` and +``yyy.h``. If the first non-preprocessor token or the ``#pragma hdrstop`` +appears within a ``#if`` block, the header stop point is the outermost +enclosing ``#if``. To illustrate, here's a more complicated example: + +.. code:: c++ + + #include "xxx.h" + #ifndef YYY_H + #define YYY_H 1 + #include "yyy.h" + #endif + #if TEST + int i; + #endif + +Here, the first token that does not belong to a preprocessing directive is +again ``int``, but the header stop point is the start of the ``#if`` block +containing it. The PCH file will reflect the inclusion of ``xxx.h`` and +conditionally the definition of ``YYY_H`` and inclusion of ``yyy.h``; it will +not contain the state produced by ``#if TEST``. + +A PCH file will be produced only if the header stop point and the code +preceding it (mainly, the header files themselves) meet certain requirements: + +* | The header stop point must appear at file scope -- it may not be within an + unclosed scope established by a header file. For example, a PCH file will + not be created in this case: + + .. code:: c++ + + // xxx.h + class A { + + // xxx.C + #include "xxx.h" + int i; }; + +* | The header stop point may not be inside a declaration started within a + header file, nor (in C++) may it be part of a declaration list of a linkage + specification. For example, in the following case the header stop point is + ``int``, but since it is not the start of a new declaration, no PCH file + will be created: + + .. code:: c++ + + // yyy.h + static + + // yyy.C + #include "yyy.h" + int i; + +* | Similarly, the header stop point may not be inside a ``#if`` block or a + ``#define`` started within a header file. +* | The processing preceding the header stop must not have produced any errors. + (Note: warnings and other diagnostics will not be reproduced when the PCH + file is reused.) +* | No references to predefined macros ``__DATE__`` or ``__TIME__`` may have + appeared. +* | No use of the ``#line`` preprocessing directive may have appeared. +* | ``#pragma no_pch`` (see below) must not have appeared. +* | The code preceding the header stop point must have introduced a sufficient + number of declarations to justify the overhead associated with precompiled + headers. This is configurable -- see ``PCH_DECL_SEQ_THRESHOLD``. + +When the host system does not support memory mapping, so that everything to be +saved in the precompiled header file is assigned to preallocated memory (i.e., +when ``USE_MMAP_FOR_MEMORY_REGIONS`` is FALSE), two additional restrictions +apply: + +* | The total memory needed at the header stop point cannot exceed the size of + the block of preallocated memory. +* | No single program entity saved can exceed ``HOST_ALLOCATION_INCREMENT``, + the preallocation unit. + +When a precompiled header file is produced, it contains, in addition to the +snapshot of the compiler state, some information that can be checked to +determine under what circumstances it can be reused. This includes: + +* | The compiler version, including the date and time the compiler was built. +* | The current directory (i.e., the directory in which the compilation is + occurring). +* | The command line options. +* | The initial sequence of preprocessing directives from the primary source + file, including ``#include`` directives. +* | The date and time of the header files specified in ``#include`` directives. + +This information comprises the PCH "prefix." The prefix information of a given +source file can be compared to the prefix information of a PCH file to +determine whether the latter is applicable to the current compilation. + +As an illustration, consider two source files: + +.. code:: c++ + + // a.C + #include "xxx.h" + ... // Start of code + + // b.C + #include "xxx.h" + ... // Start of code + +When ``a.C`` is compiled with ``--pch``, a precompiled header file named +``a.pch`` is created. Then, when ``b.C`` is compiled (or when ``a.C`` is +recompiled), the prefix section of ``a.pch`` is read in for comparison with the +current source file. If the command line options are identical, if ``xxx.h`` +has not been modified, and so forth, then, instead of opening ``xxx.h`` and +processing it line by line, the front end reads in the rest of ``a.pch`` and +thereby establishes the state for the rest of the compilation. + +It may be that more than one PCH file is applicable to a given compilation. If +so, the largest (i.e., the one representing the most preprocessing directives +from the primary source file) is used. For instance, consider a primary source +file that begins with: + +.. code:: c++ + + #include "xxx.h" + #include "yyy.h" + #include "zzz.h" + +If there is one PCH file for ``xxx.h`` and a second for ``xxx.h`` *and* +``yyy.h``, the latter will be selected (assuming both are applicable to the +current compilation). Moreover, after the PCH file for the first two headers +is read in and the third is compiled, a new PCH file for all three headers may +be created. + +When a precompiled header file is created, it takes the name of the primary +source file, with the suffix replaced by an implementation-specified suffix +(see ``PCH_FILE_SUFFIX``, which is set to ``pch`` by default). Unless +``--pch_dir`` is specified (see below), it is created in the directory of the +primary source file. + +When a precompiled header file is created or used, a message such as + +.. code:: text + + "test.C": creating precompiled header file "test.pch" + +is issued. The user may suppress the message by using the command-line option +``--no_pch_messages``. + +When the ``--pch_verbose`` option is used the front end will display a message +for each precompiled header file that is considered that cannot be used giving +the reason that it cannot be used. + +In automatic mode (i.e., when ``--pch`` is used) the front end will deem a +precompiled header file obsolete and delete it under the following +circumstances: + +* | if the precompiled header file is based on at least one out-of-date header + file but is otherwise applicable for the current compilation; or +* | if the precompiled header file has the same base name as the source file + being compiled (e.g., ``xxx.pch`` and ``xxx.C``) but is not applicable for + the current compilation (e.g., because of different command-line options). + +This handles some common cases; other PCH file clean-up must be dealt with by +other means (e.g., by the user). + +Support for precompiled header processing is not available when multiple source +files are specified in a single compilation: an error will be issued and the +compilation aborted if the command line includes a request for precompiled +header processing and specifies more than one primary source file. + +Manual Precompiled Header Processing +------------------------------------ + +Command-line option ``--create_pch`` *file-name* specifies that a precompiled +header file of the specified name should be created. + +Command-line option ``--use_pch`` *file-name* specifies that the indicated +precompiled header file should be used for this compilation; if it is invalid +(i.e., if its prefix does not match the prefix for the current primary source +file), a warning will be issued and the PCH file will not be used. + +When either of these options is used in conjunction with ``--pch_dir``, the +indicated file name (which may be a path name) is tacked on to the directory +name, unless the file name is an absolute path name. + +The ``--create_pch``, ``--use_pch``, and ``--pch`` options may not be used +together. If more than one of these options is specified, only the last one +will apply. Nevertheless, most of the description of automatic PCH processing +applies to one or the other of these modes -- header stop points are determined +the same way, PCH file applicability is determined the same way, and so forth. + +Other Ways for Users to Control Precompiled Headers +--------------------------------------------------- + +There are several ways in which the user can control and/or tune how +precompiled headers are created and used. + +* | ``#pragma hdrstop`` may be inserted in the primary source file at a point + prior to the first token that does not belong to a preprocessing directive. + It enables the user to specify where the set of header files subject to + precompilation ends. For example, + + .. code:: c++ + + #include "xxx.h" + #include "yyy.h" + #pragma hdrstop + #include "zzz.h" + + | Here, the precompiled header file will include processing state for + ``xxx.h`` and ``yyy.h`` but not ``zzz.h``. (This is useful if the user + decides that the information added by what follows the ``#pragma hdrstop`` + does not justify the creation of another PCH file.) +* | ``#pragma no_pch`` may be used to suppress precompiled header processing + for a given source file. +* | Command-line option ``--pch_dir`` *directory-name* is used to specify the + directory in which to search for and/or create a PCH file. + +Moreover, when the host system does not support memory mapping and preallocated +memory is used instead (i.e., when ``USE_MMAP_FOR_MEMORY_REGIONS`` is FALSE) +then one of the command-line options ``--pch``, ``--create_pch``, or +``--use_pch``, if it appears at all, must be the *first* option on the command +line; and in addition: + +* | Command-line option ``--pch_mem`` *size* may be used to change the size + of the preallocated block of memory from its default value. The + argument *size* is the number of 1024-byte units. (``--pch_mem`` must + also be among the first options on the command line.) + +Performance Issues +------------------ + +The relative overhead incurred in writing out and reading back in a precompiled +header file is quite small for reasonably large header files. (An +implementation can adjust ``PCH_DECL_SEQ_THRESHOLD`` to avoid creating +precompiled header files with too little information in them.) + +In general, it doesn't cost much to write a precompiled header file out even if +it does not end up being used, and if it *is* used it almost always produces a +significant speedup in compilation. The problem is that the precompiled header +files can be quite large (from a minimum of about 250K bytes to several +megabytes or more), and so one probably doesn't want many of them sitting +around. + +Thus, despite the faster recompilations, precompiled header processing is not +likely to be justified for an arbitrary set of files with nonuniform initial +sequences of preprocessing directives. Rather, the greatest benefit occurs +when a number of source files can share the same PCH file. The more sharing, +the less disk space is consumed. With sharing, the disadvantage of large +precompiled header files can be minimized, without giving up the advantage of a +significant speedup in compilation times. + +Consequently, to take full advantage of header file precompilation, users +should expect to reorder the ``#include`` sections of their source files and/or +to group ``#include`` directives within a commonly used header file. + +The EDG front end source provides an example of how this can be done. A common +idiom is this: + +.. code:: c++ + + #include "fe_common.h" + #pragma hdrstop + #include ... + +where ``fe_common.h`` pulls in, directly and indirectly, a few dozen header +files; the ``#pragma hdrstop`` is inserted to get better sharing with fewer PCH +files. The PCH file produced for ``fe_common.h`` is a bit over a megabyte in +size. Another idiom, used by the source files involved in declaration +processing, is this: + +.. code:: c++ + + #include "fe_common.h" + #include "decl_hdrs.h" + #pragma hdrstop + #include ... + +``decl_hdrs.h`` pulls in another dozen header files, and a second, somewhat +larger, PCH file is created. In all, the fifty-odd source files of the EDG +front end share just six precompiled header files. If disk space were at a +premium, one could decide to make ``fe_common.h`` pull in *all* the header +files used -- then, a single PCH file could be used in building the EDG +front end. + +Different environments and different projects will have different needs, but in +general, users should be aware that making the best use of the precompiled +header support will require some experimentation and probably some minor +changes to source code. + +.. [#f1] This is not recommended in general, since diagnostic messages and the + like will then not include a file name or will refer to the file name + "``-``". +.. [#f2] However, if ``STACK_REFERENCED_INCLUDE_DIRECTORIES`` is TRUE, the + directories of all the source input files currently in use are + searched, in reverse order of ``#include`` nesting. +.. [#f3] Since templates are descriptions of entities (typically, classes) + that are parameterizable according to the types they operate upon, + they are sometimes called *parameterized types*. +.. [#f4] The actual implementation allows for several different suffixes and + provides a command-line option to change the suffixes sought. +.. [#f5] Isn't this always the case? No. Suppose that file A contains a + definition of class ``X`` and a reference to ``Stack::push``, and + that file B contains the definition for the member function ``push``. + There would be no file containing both the definition of ``push`` and + the definition of ``X``. +.. [#f6] It should be noted that automatic instantiation, more than most + aspects of the C++ language, requires environmental support outside + of the compiler. This is likely to be operating-system and + object-format dependent. The front end is delivered with an + implementation that works under certain UNIX systems, and that + involves code in the front end proper, in IL lowering, in a separate + prelinker program, and in the ``eccp`` driver script. Because the + environmental issues vary so much from system to system, this code + should be viewed as a sample implementation that may need adaptation + to work on other systems. +.. [#f7] As a configuration option, and in older versions of the front end, + the information about entities that could be instantiated, etc. can + be represented in the names of generated variables added to the object + program. For example, a name ``__CBI__``\ *mangled-name* indicates + that the entity with the given mangled name could be instantiated, but + wasn't. This alternate scheme has the advantage that the object file + and the asssociated instantiation flags can never be out of sync. It + has the disadvantage that the object files produced can be quite a bit + larger because of the name strings for these generated external + variables. +.. [#f8] At the moment, the ``can_instantiate`` pragma ends up forcing the + instantiation of the template instance even if it isn't referenced + somewhere else in the program; that's a weakness of the initial + implementation which we expect to address. +.. [#f9] As a consequence, using exported templates may require considerably + more memory that similar uses of regular (included) templates. diff --git a/doc/_sources/il.rst.txt b/doc/_sources/il.rst.txt new file mode 100644 index 0000000..3bddb98 --- /dev/null +++ b/doc/_sources/il.rst.txt @@ -0,0 +1,3562 @@ +.. _intermediate-language: + +===================== +Intermediate Language +===================== + +The Intermediate Language is the output of the front end. It is a +representation of the source program that is passed to the back end, and +from which the back end can perform analyses, make transformations, and/or +generate object code. + +The intermediate language is a "high-level" intermediate language, that is, a +representation that is close in spirit to the original source language, rather +than a "low-level" intermediate language that is close to any typical computer +architecture. That fits the EDG philosophy of the function of a front end, +i.e., that a front end should determine the meaning of a source program and +produce an intermediate language representation of the source program that: + +* | accurately represents the meaning of the program; +* | does not destroy information; +* | does not add constraints that are not present in the source program; and +* | makes explicit any implicit or overloaded operations in the source program, + so that the back end does not have to have a deep understanding of the + source language and does not have to search or interpret the intermediate + language. It follows from this that the front end does not do + optimization, does not rewrite source constructs in "simpler" forms, and + does not use a machine-dependent representation. It also follows that + ambiguity and overloading resolution are completely handled by the front + end and a back end need do nothing to deal with them. The intermediate + language is a tree-structured in-memory data structure. Both declarative + and executable constructs are represented in tree form, and in fact all + declarative and executable information at all levels is tied together into + one tree. Having a pointer to the root of this tree gives one all the + information necessary to generate object code for the source program. (In + other words, the intermediate language data structure is the only + information that needs to be passed from the front end to the back end. + There is no additional hidden information.) The source code definitions of + the intermediate language tables are in the file ``il_def.h``. However, + some introductory information is necessary before one dives into that file. + +Memory Management +================= + +Memory management may seem like a strange place to begin an overview of the +intermediate language. However, an understanding of the memory management +structure is necessary to get a feeling for the overall shape of the +intermediate language tree. + +Memory Regions +-------------- + +It was decided early in the design of the front end that the intermediate +language would be an in-memory data structure. That is, it exists in +directly-addressable memory and can be examined without recourse to special +access routines. This is beneficial from the point of view of compilation +speed and ease of programming. However, it could be problematic from the point +of view of memory use, especially when processing extremely large source files. +To deal with that problem, it was decided that the intermediate language should +be set up so that the parts of the tree associated with different top-level +functions are placed in separate blocks of memory that need not all be in +memory at the same time. A top-level function is any function that is not a +lambda defined in a function scope, or the instantiation of a generic lambda +defined in a function scope. Functions that are not top-level are placed in +the memory region of the enclosing function. During the processing of a single +function, the intermediate language for that function (and for other functions +in the same memory region) and for the global declarations visible to that +function must be in memory. The intermediate language for all other functions, +however, is not needed at that time, and can be written out to a file or +otherwise removed from the active address space. As a result, a large source +program looks more like a sequence of reasonably-sized functions and uses +memory accordingly. + +These blocks of memory are called "memory regions". There is a memory region +for the file scope intermediate language and one for the intermediate language +of each top-level function of the source program. + +The memory region scheme is a two-level scheme: there is a file scope memory +region which is always in memory, and a set of function scope memory regions of +which only one is guaranteed to be in memory at a given time. C++ lambdas +defined in function scopes are handled by placing them in the same memory +region as the enclosing function. Member functions of local classes in C++, +while somewhat similar to lambdas, are treated (with some careful allocation of +entities) as top-level functions and have their own memory regions. + +Memory Regions and Pointers +--------------------------- + +The memory management structure has an effect on pointers in the intermediate +language. Clearly, a pointer to an entry in a function scope memory region is +valid only if the associated memory region is actually in memory. Rather than +requiring dynamic checking of pointer legality, we decided to make a rule about +how pointers may be used. Specifically, entries within a function scope memory +region may only be pointed to from within that memory region. Entries in the +file scope memory region may, of course, be pointed to from anywhere, since +they are always in memory. + +This rule has some consequences. The most important one is that anything that +must be referenced from more than one memory region must be allocated in the +file scope memory region. Specifically, since functions may be called from +many other functions, they must have some representation in the file scope +memory region. Of course, since the whole point of the function scope memory +regions is to avoid having everything in memory at one time, it wouldn't make +sense to put the entire routine into the file scope memory region. What's done +instead is to put the description of the interface to the routine (i.e., what's +needed to call it) in the file scope memory region, and the description of the +implementation of the routine (i.e., what's needed to execute it) in the +function scope memory region. Similarly, local static variables of functions +must be allocated in the file scope memory region because they are potentially +referenced from member functions of classes local to the function. + +A second consequence is that anything referenced from the file scope memory +region must also be allocated in the file scope memory region. [#f1]_ This +second consequence becomes significant when combined with another intermediate +language decision, that of placing all entities with external visibility at the +file scope. [#f2]_ Placing the declaration of an external entity at the file +scope means placing all of the entities it references in the file scope memory +region, and that means placing all the entities they reference in the file +scope memory region. The practical consequence of all that is that all types +must be allocated in the file scope memory region, since it is not possible to +know at the time they are allocated whether or not they will be used as part of +the type of some external entity. In C++, that means in particular that all +classes are allocated in the file scope memory region (except for the bodies of +member functions). Likewise, all namespaces are allocated in the file scope +memory region except for the bodies of namespace member functions. + +It is important to bear in mind that the *file scope memory region* is not the +same thing as the *file scope*. They are similar but not identical. The *file +scope* is a language concept: it is the outermost scope in a C or C++ program. +The *file scope memory region* is a memory management concept referring to a +block of memory whose contents must always be accessible. All entities in the +file scope are allocated in the file scope memory region, but some entities +allocated in the file scope memory region are function-scope entities, some are +function-scope entities moved to the file scope because they are externally +visible, and some are class or namespace members allocated in the file scope +memory region because all classes and namespaces are allocated there. + +Intermediate Language Files +=========================== + +The intermediate language and memory management scheme are set up to allow but +not require the use of files to save the intermediate language. The front +end's connection to a back end can be configured in a number of ways: + +* | The entire intermediate language tree can be passed in memory to the back + end. This is fastest but uses the most memory. +* | The intermediate language can be written to a file on a + per-top-level-function basis and read back in on a per-top-level-function + basis in the back end. (Only one file is used, but the intermediate + language for each function is written separately and the memory involved is + reclaimed immediately.) This is slowest but uses the least memory. +* | The intermediate language can be processed on a per--top-level-function + basis in some other way, then thrown away. For example, the intermediate + language can be translated to another intermediate language used by the + back end, and the original intermediate language can be discarded. + +C versus C++ Intermediate language +================================== + +The intermediate language generated for C++ is a superset of the intermediate +language generated for C. + +For the sake of customers that have an existing C back end, EDG provides a +optional and separate "IL lowering" pass that translates the C++ intermediate +language into the C intermediate language. Note that although the process is +called "lowering," the resulting C intermediate language is still "high-level"; +it's just not as high-level as it was. Also note that the IL lowering process +does some implementation of C++ features (e.g., virtual function tables, name +mangling, pointers-to-members, constructor and destructor wrapper code) which +are just abstractions in the unlowered IL. Clearly, a back end has the most +latitude in generating code for C++ if it starts with the unlowered C++ IL, but +it also has quite a bit more work to do. On the other hand, an extra pass over +the intermediate language takes time, so a configuration that uses the IL +lowering pass will not be as fast as one that does not use it. + +The IL lowering pass is useful because + +#. it allows customers to get a C++ compiler going in minimal time; +#. if the features implemented by IL lowering require some minor changes, + the changes can be made in IL lowering, which is relatively small, rather + than in the front end as a whole, which is quite large; and +#. if a customer wants to attach a back end to the unlowered IL (either + initially or for an improved release of a compiler), the IL lowering code + serves as a guide to the tasks that must be done. + +The description of the intermediate language in this chapter is for the +unlowered IL. All C++-specific features are rewritten or removed by the IL +lowering, which means that some of the description in this chapter is of no +interest to a back end that uses the lowered IL. If there is some question +about whether or not a feature would remain in the lowered IL, the description +will indicate what effect IL lowering has. + +There is no way at present to compile the C++ front end so that the IL that it +generates includes only the C IL definitions. Even though IL lowering will +eliminate uses of non-C features, the C++-specific fields and enumeration +values are still present in the source code. Back ends should ignore those +fields (they are not necessarily cleared) and should expect to get IL that is +valid C when one considers (only) the fields that C uses. + +One catch: Dynamic initialization of entities in the middle of blocks is left +in its original form. This is not "incorrect" C IL, but is something that does +not come up in C(89) programs. It was judged that back ends would be capable +of dealing with the ``stmk_init`` statements even if they appear after other +executable statements in a block, and the alternative was to make lowering of +initialization of aggregates to constants quite messy. + +Similarly, the initialization statement attached to an ``stmk_for`` is always a +simple ``stmk_expr`` in C, but in C IL generated by IL lowering, it can be an +arbitrary statement. + +C99 and the Intermediate Language +================================= + +The ANSI/ISO C standard was updated in 1999, and the resulting version of C +is referred to as C99. The C/C++ front end supports C99 (as well as later +versions). In some cases, the IL has been extended to support newly-added +features of C99. + +The IL extensions for C99 and later revisions are enabled by the macro +``C99_IL_EXTENSIONS_SUPPORTED``. If that macro is set to FALSE, C99 and +later modes can still be enabled, but all features that require the IL +extensions are disabled. Note, in particular, that if your interest is +only in supporting C++, or only C89, turning off these features will make +it slightly easier to write a back end, because you will have to implement +fewer IL constructs. + +There is a lowering phase for C99, which rewrites many of the extensions into +standard C89 IL. This lowering phase is enabled by the macro +``DO_IL_LOWERING``. + +See :ref:`il-c99-features` for a detailed list of C99 IL constructs. That list +summarizes the lowering done for each construct; there is more detail in the IL +Lowering chapter of this document. + +C++/CLI and the Intermediate Language +===================================== + +The front end supports the Microsoft C++/CLI language, a set of extensions to +C++ to allow programmers to interface to Microsoft's .NET, which is a +heap-based garbage-collected environment in the style of Java or C#. There is +an ECMA standard for the C++/CLI language (ECMA 372), but the real standard is +the MSVC compiler, as it diverges from the ECMA document in significant ways. + +The C++/CLI extensions involve new types, new expression operators, new member +function kinds, new declarations, and new statements. Those are covered in +detail in the appropriate sections of this document. The data structures and +code for those features are included when ``MICROSOFT_EXTENSIONS_ALLOWED`` is +TRUE; there is no separate macro for C++/CLI to control their inclusion. The +features are enabled only when ``cppcli_enabled`` is TRUE, and there is a macro +``CPPCLI_ENABLING_POSSIBLE`` that when FALSE (the default) prevents the C++/CLI +features from being enabled. So if you do not want to support C++/CLI, leave +``CPPCLI_ENABLING_POSSIBLE`` set to FALSE and you will never see any of its +features in the IL. + +Note that C++/CLI is supported only when the front end is hosted on Windows. +Also note that C++/CLI is Microsoft's second version of a C++ interface for +.NET; there was a previous set of extensions called "Managed C++". The front +end does not support those features (and Microsoft is moving away from +supporting them as well). + +Memory Region Processing Order +============================== + +When a file is compiled, the processing order of memory regions will look like: + +* | Start file scope memory region (1). + + * | Start function scope memory region (2). + * | End function scope memory region (2). + * | Start function scope memory region (3). + * | End function scope memory region (3). + * | Etc. +* | End file scope memory region (1). + +When IL lowering is done, it is done as each memory region is ended. When IL +files are written, they are written as each memory region is ended (after IL +lowering, if any). + +When the front end instantiates functions or generates routines (like +constructors), there can be brief periods when multiple function scope memory +regions are active. The function scope memory region for the instantiated or +generated routine is started and ended while the primary function scope memory +region is still active. If this process kicks off instantiation or generation +of other routines, there can be many active function scope memory regions. + +General Information +=================== + +Each major type of entity in the C/C++ language has a corresponding +intermediate language entry. For example: ``a_constant``, ``a_type``, +``a_variable``, ``a_routine``, ``a_label``, ``a_statement``, and +``an_expr_node``. Each entry kind has a fixed size except for the entries +representing strings (used for literal strings and names), which have a +variable length. The IL entries are not self-labeling; one must know the kind +of thing pointed to to make sense of a pointer. + +The intermediate language is high-level, meaning that the entities in it +correspond fairly closely to C and C++ language constructs. For example, all +of the C and C++ expression operators are present in their original forms. +There is no remapping of complex operators (like "``?``") to lower-level +operations. Statements are kept in their original structured form, and not +flattened to ``if``\ s and ``goto``\ s. + +Since the structure of the intermediate language corresponds so closely to the +original C or C++ form, it implies no ordering of evaluation that was not in +the original program. Timing of side effects for post-increment operations, +for example, which must be completed by the next sequence point, is not +specified explicitly. It is up to the back end to adhere to the C and C++ +language rules when generating object code for such constructs. + +By convention, there can be multiple pointers to any given declarative entity +(for example, many places can point to the constant entry for ``1``), but only +a single pointer to any executable entity (each use of ``1`` in an expression +requires a distinct expression node pointing to the common constant entry for +``1``). + +The intermediate language tables are designed to keep memory requirements +reasonably low. There are several cases where ``enum`` values are stored as +``a_byte``\ s (which means as ``char``\ s of some kind), in order to ensure +that only one byte is used for those rather than whatever the host C compiler +might choose for an ``enum``. An example of such a type is +``a_constant_repr_kind``. This has the unfortunate side effect that explicit +casts are often required when dealing with values of these types. There are +also several cases where, in a union that has one case that is larger than all +the others, the extra information for the unusual case is broken out as a +separate supplement that is pointed to from the union (e.g., +``a_routine_type_supplement``). + +As mentioned, all of the intermediate language is tree-structured. The +expression ``i+1`` is a tree with a ``+`` expression node pointing to two +expression nodes representing ``i`` and ``1``; the statement + +.. code:: c++ + + if (i) i=1; else i=2; + +is a tree with an ``if`` statement node pointing to two statement nodes for +``i=1`` and ``i=2``; and the declaration + +.. code:: c++ + + int *m[5]; + +is a variable node for ``m`` pointing to a tree defining the type "array of +pointer to ``int``". All the statements of a function are bundled into one +tree which is pointed to by the function definition, and all the type, +variable, and function definitions for a given scope are on a list pointed to +by the header for the scope. At the top of the entire tree for a compilation +there is a header that points to the entry for the outermost scope. Beginning +there, one can get to all of the functions and therefore all of the functions' +scopes; one can also get to all of the classes and therefore all of the +classes' scopes. In other words, beginning at the IL header one can reach the +entire IL tree for the compilation. + +The IL Header +============= + +The top of the intermediate language tree is ``il_header``, which contains +several important pointers: + +* | A pointer to the scope entry defining the primary scope of the compilation. + This is the root of the IL tree proper. +* | A pointer to the top of a tree of entries describing the source files from + which the source program came. +* | A pointer to the ``scope_region_entry`` array, which gives pointers to the + scope entries that are the top of the IL tree in each of the function scope + memory regions. +* | A pointer to the ``function_def_table`` array, which gives the pointers to + the scope entries and memory region numbers for a given function + definition. + +Source File Information +======================= + +The source file information structure describes the primary source input file +and the include files of the compilation, and the relationship between them. +It is a structure distinct from the IL tree proper because the file structure +of a program need not have any relationship to its syntactic structure. An +include file, for example, could include half of a routine, or the end of one +routine and the start of another. (This is of course not typical, but it's +possible.) Within the IL tree proper, a source line's position is given by a +*sequence number*, which is the ordinal position of the source line in the +sequence of lines read by the front end, starting at the beginning of the +primary source file and switching into include files when directed to by +``#include`` directives. The sequence number is compact and unambiguous for +internal use, and can be translated easily to a file name and line number for +external use by referring to the source line information structure. The +routine ``conv_seq_to_file_and_line`` in ``il.c`` does that translation. + +Source Correspondence Information +================================= + +Constructs that declare constants, types, variables, routines, fields, labels, +namespaces, templates, template parameters, and macros have information on the +associated source name and the source location of the declaration. This +information is given by the ``source_corresp`` field, which is a ``struct`` of +type ``a_source_correspondence``. A source location is specified by an entry +of type ``a_source_position``, which consists of a sequence number and a column +number. The column number is the 1-origined column number in the original +source line (*not* the logical source line that results after processing +trigraphs and line splices). Tab characters count as one column, so the +"column number" may not match the apparent display position on a terminal or +printer. If multibyte characters appear, including characters that come from +files in formats such as UTF-16, they count as a single column. The node for +statements has a source location as well, but (to save space) it contains only +a sequence number and no column number (see, however, the configuration flag +``FULL_SOURCE_POS_IN_IL_STATEMENT``). + +Aside from a pointer to the name string and the source position, the source +correspondence information contains an ``assoc_info`` pointer. This is +intended to be used by the front end and other components to store a pointer to +information maintained locally about the entity. However, the information does +not survive into the next pass. In the front end, the pointer points back to +an associated symbol entry. That pointer is no longer valid once the front end +is finished (since the space for symbol entries may have been released), but +the pointer can be set in the back end as desired. + +Compiler-generated entities have no source correspondence information +(since they do not appear in the program source). Their source +correspondence name pointer is NULL. + +The source correspondence information also contains the ``name_linkage`` field, +which indicates the kind of linkage the entity has (e.g., is it externally +visible? Should C++ name mangling be done on it?), an access field (which +indicates the access for class members in C++), a ``parent_scope`` pointer to +the containing scope, and a ``referenced`` field. + +When ``IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS`` is TRUE, the name string +in the source correspondence entry can contain multibyte character +sequences (e.g., UTF-8 when ``UNICODE_SOURCE_SUPPORTED`` is TRUE). When it +is FALSE, multibyte characters will be represented as ``\m``\ *XXXX* or +``\M``\ *XXXXXXXX* escape sequences. When a universal-character-name +(e.g., ``\u00d6``) appears in a name, the name string will contain the`` +\u``\ *XXXX* or ``\U``\ *XXXXXXXX* escape sequence, except that when +``UNICODE_SOURCE_SUPPORTED`` and +``IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS`` are both TRUE the UCN value +will be represented directly. IL lowering can do some limited rewriting of +such escape sequences; see ``REWRITE_UCN_ESCAPE_CHAR_IN_LOWERING``. Note +that these flags do not control whether or not multibyte characters are +allowed in identifiers, only how they are represented; see +``MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED``. + +``referenced`` and ``needed`` Flags +----------------------------------- + +The ``referenced`` flag in a source correspondence entry indicates whether an +entity is referenced. All entities that have no source correspondence have +``referenced`` set to TRUE. For named entities, ``referenced`` is TRUE if the +entity is referenced in the intermediate language. The reference can be +implicit: in a case like + +.. code:: c++ + + struct s {int a;} v; + +the ``struct`` type is referenced, but not through the name ``s``. + +The referenced flag is set correctly but simplistically. More precise +information is available in the ``needed`` flag (and, in classes and routines, +the ``definition_needed`` flag). These are optional and are selected by the +configuration switch ``MAINTAIN_NEEDED_FLAGS``. When present, they indicate +whether or not an entity is "really" needed, and whether the definition of a +class is really needed, or merely its declaration. This is determined by +marking as needed all externally-defined functions and variables, and all the +things they reference, and all the things those things reference, etc. + +Depending on the setting of ``DEFAULT_REMOVE_UNNEEDED_ENTITIES``, possibly as +overridden by a command-line option, unneeded entities and unneeded class +definitions will be removed from the IL tree. This process, however, does not +remove all unneeded entities, because some end up being required for IL +consistency even though they are not "needed." One example: if a class and its +definition are needed, all the members of the class must be kept in the IL even +though some of the members may not be "needed" (in the sense of being +referenced directly or indirectly from an externally defined routine or +variable). The IL after removal of unneeded entities will be self-consistent, +in that a back end that does not use the needed flags will find nothing +surprising. If a back end uses the ``needed`` flag, it should also pay +attention to the class ``definition_needed`` flag or it may find some apparent +inconsistencies in the IL tree. + +The setting of the "needed" flags and the removal of unneeded IL entries work +both with and without IL lowering. When IL lowering is done, the setting is +done after lowering, so that the flags reflect the lowered code. + +When ``ONE_INSTANTIATION_PER_OBJECT`` is TRUE, a more complicated set of +"needed" flags is maintained. In that mode, each instantiation is put out as a +separate object file. There is still only one IL tree, but it is marked so +that a back end can sweep through it several times and put out a different +"slice" each time, each slice containing one instantiated entity (function, +variable, or static data member) plus exactly the set of other entities needed +by that entity. This is done via a set of per-instantiation "needed" flags, +represented as a bit vector implemented as a linked list of entries of type +``a_per_instantiation_needed_flags_entry`` attached to the +``per_instantiation_needed_flags`` field of the source correspondence. Each +slice is assigned one bit in that bit vector, and if the bit is 1 the +associated entity is needed in the slice. + +See the :ref:`needed-flags` section. + +Source positions +---------------- + +Source position information is recorded in the IL in various ways. The +``decl_position`` field in the source correspondence indicates the source +position of the primary declaration of an entity. When an entity has more than +one declaration, ``decl_position`` corresponds to the defining declaration or, +if there is no defining declaration, the first declaration. When +``GENERATE_SOURCE_SEQUENCE_LISTS`` is TRUE, source positions on declarations +other than the primary declaration are recorded in the source-sequence list -- +see ``decl_position`` in ``a_src_seq_secondary_decl``. As noted previously, +position information is also recorded in ``a_statement``; in addition, source +position information is recorded in other IL entries that have no source +correspondence field, e.g., ``a_base_class``, ``a_using_decl``, +``an_instantiation_directive``, ``a_static_assertion``, and ``a_pragma``. + +In applications for which additional source position information is needed, +``EXTRA_SOURCE_POSITIONS_IN_IL`` can be configured to TRUE. Note, however, +that this information can take a lot of extra space, so the feature is disabled +by default. + +When ``EXTRA_SOURCE_POSITIONS_IN_IL`` is TRUE, source range information +(beginning and ending source positions of various syntactic constructs) is +supplied. Each source correspondence has a pointer to +``a_decl_position_supplement``, which includes the source range of the complete +identifier (including namespace and class qualifiers, if present), as well as +the source range of the declaration-specifiers and the declarator. For +instance, the source position information for this declaration of ``foo`` is +indicated: + +.. code:: text + + inline void A::foo(A *pa) { /* ... */ } + ^ decl_position + ^^^^^^ identifier_range + ^^^^^^^^^^^ specifiers_range + ^^^^^^^^^^^^^ declarator_range + +Moreover, though the param-type entry for parameter ``pa`` has no source +correspondence entry, it does have a pointer to ``a_decl_position_supplement``, +which records its source range information: + +.. code:: text + + inline void A::foo(A *pa) { /* ... */ } + ^^ identifier_range + ^ specifiers_range + ^^^ declarator_range + +Source range information is supplied for ``a_base_class`` and +``a_constructor_init``, as well as for the initializer construct of explicitly +initialized variables. Moreover, when ``GENERATE_SOURCE_SEQUENCE_LISTS`` is +TRUE, pointers to ``a_decl_position_supplement`` also appear in +``a_src_seq_secondary_decl`` entries; this provides source range information on +declarations that are not the primary declaration of an entity (e.g., +``friend`` declarations). + +Source range information is also provided for expression nodes when +``EXTRA_SOURCE_POSITIONS_IN_IL`` is TRUE. The source positions of the start +and end of the expression, along with the source position of the operator (if +present) are recorded. + +Name Linkage +------------ + +The ``name_linkage`` field of the source correspondence structure indicates the +kind of linkage the name of an entity (routine, variable, class or enumeration +type, or class member) has: + +* | External linkage, used in C mode and for ``extern "C"`` entities in C++ + mode, indicates that the name is visible outside its compilation unit. +* | C++ external linkage, for normal entities in C++ mode, indicates that the + name is visible outside its compilation unit. The name may be subjected to + some kind of name mangling. +* | Internal linkage indicates that the entity name is visible throughout its + compilation unit (e.g., a file-scope static variable). +* | No linkage indicates that the entity name has no connection to other + entities with the same name (e.g., a local variable). + +From a C perspective, the name linkage information seems to be redundant, in +that it would seem that one could decide the name linkage on the basis of a +variable or routine's storage class. In C++, however, class names (i.e., +types) have linkage, and in some compatibility modes if a class is used in the +type of an external entity, it acquires external linkage, and its static data +members and member functions also get external linkage. It gets to be very +complicated to try to encode the storage class (including whether or not it can +be changed on subsequent declarations) and the name linkage in just the storage +class field. + +In addition, the ``routine_name_linkage`` field in the routine type supplement +is significant. The linkage specification in a routine type declaration can +correspond to the routine's calling convention -- for example, when ``extern +"C++"`` and ``extern "C"`` imply distinct calling conventions or an +implementation-defined linkage specification has its own calling convention. +Among other things, this means that in C++ otherwise identical functions are +distinguished for purposes of overloading based on the linkages associated with +their parameter types: + +.. code:: c++ + + typedef void (*PF)(); // Pointer to an extern "C++" function + extern "C" typedef void (*PFC)() // Pointer to an extern "C" function + void f(PF); + void f(PFC); // Overloads f + +Note, moreover, that the linkage specification of a function's *name* need not +be identical to the linkage specification of its *type*. The former might +affect how its external name is generated and the latter might affect its +calling convention. + +Access Control +============== + +Access control information appears in several places: + +* | The ``access`` field of ``a_source_correspondence``, which appears in most + declarative entities. +* | ``using``-declarations and access declarations in classes, which may adjust + the accessibility of inherited members. +* | Base class entries, which indicate the kind of derivation from the base + class to the derived class. +* | Lists of the friend classes and friend functions of a class. These are + also available in reversed form as befriending lists for classes and + functions, which indicate the classes which have named the befriended class + or function as a friend. + +This information is useful to the back end only for generating symbolic +debugging information. The necessary access control checks will have been done +by the front end, and access control does not have an effect on code +generation. + +Only class members are subject to access control. All other entities (and all +entities in C) will have access of ``as_public``. + +The Scope Entry +=============== + +Each scope in the source program is represented by a scope entry in the IL +(type ``a_scope``). There are scope entries for: + +* | the file scope; +* | each function definition scope; +* | each block within a function; +* | each "prototype" scope (for function prototypes in function declarations); +* | each class, struct, and union type (when the type has a body); +* | each namespace (in C++); and +* | each condition (tested initialized variable in C++, e.g., in an "``if``" + statement). + +The scope entry for the file scope is pointed to from ``il_header``; it +contains lists of the file-scope entities in the compilation. In particular, +it points to a list of the functions in the compilation. Each function is +represented by an ``a_routine`` entry. A function without a body (i.e., an +``extern`` function) has just a routine entry. For a function with a body, the +field ``assoc_scope`` in the routine entry gives the region number for the +memory region containing the function, which allows one to get a pointer to the +scope entry for the function scope. That scope entry points to the statements +for the function, and to lists of its parameter definitions and of local +constants, types, variables, labels, and block scopes. + +One can see that the scope entry is the most important entry in terms of the +overall structure of the IL tree, in that it groups entities together into a +scope and also points down to the subscopes. Conversely, many IL entries point +back to their containing scope via the ``parent_scope`` field of their source +correspondence entry. (The scope entries themselves also contain a ``parent`` +pointer to their enclosing scope; this parent pointer is null for the file +scope.) + +A scope entry points to lists of the entities that are defined in the scope: +constants, types, variables, routines, sub-scopes, etc. The lists may be used +or not depending on the type of scope: + +* | File scope (allocated in the file scope memory region): + + * | types: used for tags (``class``, ``struct``, ``union``, and ``enum``) and + ``typedef``\ s. Top-level class definitions appear here. + * | variables: used for static and external variables at the file scope. + * | routines: used for functions both with and without definitions + (bodies). + * | dynamic initializations: used for variables that have dynamic + initializations (eliminated by IL lowering). +* | Function or block scope (allocated in a function scope memory region): + + * | types: used for tags (``class``, ``struct``, ``union``, and ``enum``) and + ``typedef``\ s that are local to the function or block. This pointer is + unusual in that it will point to a list of entries allocated in the file + scope memory region. Local classes appear here. + * | variables: used for local static variables (one list; this pointer is + unusual in that it will point to a list of entries allocated in the file + scope memory region) and automatic/register variables (another list). + * | scopes: for subscopes (blocks that have declarations). Note that every + ``{ }`` has an associated block statement, but a block statement only has + an associated scope if it contains local declarations. +* | Function prototype scope (allocated in the file scope memory region): + + * | types: used for tags (``class``, ``struct``, ``union``, and ``enum``) and + ``typedef``\ s that are local to the prototype scope. + + | Used only in C, not C++. Function prototype scopes are used to contain + types defined in prototyped parameter lists. When the function type is + part of a function declaration (i.e., there is no body), there's nowhere + else to put the types. When the function type is part of a definition, the + prototype scope is effectively part of the function scope, but it must be + kept separate so that it can be available in the file scope memory region + as part of the information on the interface to the function. +* | Class scope (allocated in the file scope memory region): + + * | constants: used for class constants (an extension). + * | types: used for tags (``class``, ``struct``, ``union``, and ``enum``) and + ``typedef``\ s. Nested types appear here. + * | variables: used for static data members of the class. + * | routines: used for member functions of the class. This includes all + member functions: static and non-static, virtual and non-virtual, inline + and non-inline, constructors, destructors, operator functions, and + conversion functions. Friend functions are not listed here (see the + friend and befriending lists under the class type and routine entries). +* | Namespace scope (allocated in the file scope memory region): + + * | types: used for tags (``class``, ``struct``, ``union``, and ``enum``) and + ``typedef``\ s. Type members of the namespace appear here. + * | variables: used for variable members of the namespace. + * | routines: used for function members of the namespace. + * | namespaces: used for nested namespaces. + +The entries appear on the lists in the order of declaration in the source +program, with the exception that tags and routines appear at the point where +the full definition occurs, not where the first forward reference appears. +Unreferenced entities *do* appear on the lists. + +Not all intermediate language entities appear directly on the lists. An entity +appears on a list if: + +* | it is named in the source program; or +* | it is a tag (``class``, ``struct``, ``union``, or ``enum``); or +* | it is a front-end-generated temporary variable or parameter. + +Note that enumerated constants appear as part of the definition of the ``enum`` +tag and not ever on a constants list. + +The type lists will also contain "placeholder typerefs," which are +``tk_typeref`` types with no name and no type qualifiers which provide +information about corresponding positions in different type lists. These are +useful to IL lowering in promoting types out of classes and namespaces. See +the section on placeholder typerefs in the IL lowering chapter of this +document. + +For function scopes, the scope entry contains additional information: + +* | A pointer to the routine entry (in the file scope memory region). +* | A list of parameter variables, and (for a nonstatic member function) a + "``this``" parameter variable. +* | For constructors and destructors, a list of ``a_constructor_init`` entries + indicating initialization or destruction to be done. +* | Labels within the function. +* | A list of entries for computing the bounds of variable length array types. + +.. _il-types: + +Types +===== + +``a_type`` describes a type, which can be ``void``, an integral or enumeration +type, a real, complex, or imaginary floating-point type, a fixed-point type, a +pointer, a reference, ``std::nullptr_t`` (the type of the ``nullptr`` keyword +in C++), an array, a GNU vector type, a ``class`` or ``struct``, a ``union``, a +function type, a pointer-to-member type, a ``typeref``, or a fully generic +template-dependent type. Some of these type kinds -- including fixed-point and +vector types -- are optional (i.e., available only in specific configurations). + +``void``, ``std::nullptr_t``, the fixed-point types, and the floating types are +self-contained. Integer types and enumeration types point to a supplement +entry of type ``an_integer_type_supplement`` (conveniently accessed with the +macro ``integer_type_supp``). Enumeration types are basically integer types, +with an additional pointer to either a list of ``a_constant`` entries that +define the members of the enumeration (for unscoped enumeration types), or a +scope entry (for scoped enumeration types; the scope entry then points to the +list of enumerator constants). The entries representing the enumerator +constants may, e.g., be of interest to a back end for generating symbol +debugging information. + +The integral, fixed-point, and floating types are provided in a fixed set of +sizes, e.g., ``float``, ``double``, and ``long double`` for floating. The +sizes of the types can be configured easily, but they remain essentially +symbolic. That is, ``int`` remains ``int`` and not "integral type of size 4". + +A special type kind is used to represent "template parameters" in a broad +sense. This includes normal template parameters, but also otherwise unknown +template-dependent types like ``typename T::X`` where ``T`` is a template +parameter. This general concept "template parameter type" is also used to +represent the ``auto`` type specifier in modes that support it. The general +type kind for template-dependent types is ``tk_template_param``. + +The other kinds of types are *derived* types -- they point to one or more other +types, and are used to build up type trees. For example, the type entry for +``int`` can be pointed to by an array type entry to build an array of ``int``. +A pointer type entry could be put on top of that to make a pointer to array of +``int``. + +Derived types are built up from their constituent types in the obvious way: + +* | Array types point to the element type and indicate the number of elements. +* | Function types point to the return type. Parameters of prototyped cases + (and of the types of defined unprototyped functions) are represented by a + list of ``a_param_type`` entries (pointed to indirectly by the type entry + via an entry of type ``a_routine_type_supplement``). +* | Pointer and reference types point to the underlying type. Pointers and + references are represented as variants of a common type kind. +* | Pointer-to-member types point to the class type and the underlying type. +* | ``class``, ``struct``, and ``union`` types point to a list of ``a_field`` + entries that define the members. There is a class type supplement that + provides a great deal of additional information, especially in C++. (See + below.) +* | typedefs, type qualifiers (e.g., const and volatile), type operators such + as decltype, and various other types are represented by an entry called a + typeref, described in more detail in a subsection below. + +Simple types are shared. For example, there would only be one type entry for +the type ``int``, and it would be pointed to in all cases where it is needed. +There is also sharing of pointer types, reference types, pointer-to-member +types, and qualified types: the based types list pointer in a type entry points +to a list of types based on the type (e.g., pointer-to the type); when a based +type is created, it is placed on the list and can thereafter be found and +reused. + +Types include information indicating their size and alignment (but beware of +``typeref``\ s, which normally have no size or alignment of their own [#f3]_, +and function types, which have no size or alignment). The sizes and alignments +are set by routines in ``types.c`` and ``class_decl.c`` and are taken on faith +in the rest of the front end. Incomplete types have size zero and have the +flag ``incomplete`` set to TRUE. Other types (including classes that contain +no nonstatic data members) normally have sizes greater than zero (some C and +C++ dialects treat some completely defined types as having size 0). + +When support for ``near`` and ``far`` is enabled (e.g., in 16-bit Microsoft +mode), the ``near`` and ``far`` memory attributes are encoded as type +qualifiers. A qualifier appears only if it is not the default. For example, +if the source specifies ``far`` and the default in that context is ``far``, no +qualifier is added. Back ends that need to know about memory attributes can +check the size of individual pointers (i.e., does the pointer have the size of +a ``far`` pointer) or use the function ``is_far_type`` (e.g., to determine the +calling method for function types). The memory attributes appear only when +``il_header.near_and_far_enabled`` is TRUE; see also ``NEAR_AND_FAR_ALLOWED``. + +When support for named address spaces is enabled (a feature of Embedded C), +named address spaces are also encoded as type qualifiers. Unlike other +qualifiers, named address spaces are *not* encoded as a bit vector (e.g., a bit +per address space) but as a small integer indicating which address space is +selected (zero represents "no specific address space" which is sometimes +referred to as "the generic address space"). This small integer can be used as +an index in the array ``named_address_spaces``; this array is defined in +``targ_def.h`` and can be configured to describe the address spaces of a +particular target. + +Variable length array types are a special case, because the number of elements +in the array is computed at run time, and so the dimension is represented as an +expression. However, the type itself cannot point to the dimension expression, +since the former belongs to the file-scope memory region and the latter to a +function-scope memory region. Instead, the flag ``has_assoc_vla_dimension`` is +set in the type entry, and the dimension expression is stored in an entry of +type ``a_vla_dimension``, which appears on a linked list pointed to by the +routine's IL scope entry (see ``find_vla_dimension`` in ``il.c``). When the +bound of a VLA is unspecified (e.g., because it was declared with the ``[*]`` +syntax), ``is_vla`` will be TRUE but ``has_assoc_vla_dimension`` will be FALSE. + +Typerefs +-------- + +Typerefs are used to record additional information for existing types: + +* | typedefs giving a name for a type, +* | type qualifiers such as ``const`` and ``volatile``, +* | typeof (a GNU extension) and decltype (a C++11 feature) constructs, +* | specializations of alias templates, +* | type splices (a C++26 feature), +* | type-returning traits, +* | type-transforming attributes, +* | dependent type pack index specifiers, and +* | (when configured with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE) + lexical information such as nested name qualifiers and alternative template + arguments. + +Typeref type entries point to a typeref type supplement containing additional +information such as template argument lists, nested name qualifiers, and +operands of type operators. + +For qualified pointer types, the typeref indicating the qualifier is on the +type of the pointer type: for ``int *const q`` the type is a const typeref +pointing to a pointer type entry, which points to an entry for ``int``. +(By comparison, ``const int *q`` produces a pointer type entry pointing to +a const typeref, which points to an entry for ``int``.) + +It is often necessary for code that deals with types to access the target of a +typeref or chain of typerefs. Various convenience functions are provided for +this purpose, including ``skip_typerefs``, ``skip_typerefs_not_typedefs``, +``skip_lexical_typerefs``, etc. + +Class Types +----------- + +Class types are ``class``, ``struct``, and ``union`` types [#f4]_. Their +associated type entry always points to a class type supplement (conveniently +accessed with the macro ``class_type_supp``), which carries additional +information especially relevant to C++. + +In C, a ``struct`` or ``union`` type is relatively simple, and is defined by a +list of ``a_field`` entries. Each entry defines one field (member) of the +``struct`` or ``union``. The offset of a field is given as the combination of +a byte offset (the ``offset`` field) and a bit offset (the +``offset_bit_remainder`` field). The latter is nonzero only for bit fields +(i.e., when ``is_bit_field`` is TRUE); a bit field also has a nonzero +``bit_size``, and its type (an integral type) is significant only as an +indication of the base type specified in the source program. Enum types and +integral types smaller than ``int`` can appear as the base type for a bit +field. A separate flag ``bit_field_is_signed`` indicates whether or not the +bit field is signed. Unnamed fields in the source program, which affect the +offsets of the fields that follow them (i.e., they introduce gaps), also appear +in the list of fields for the ``struct``. + +An associated scope is defined for a ``struct`` or ``union`` in C even though +the C language doesn't really associate a scope with those constructs. The +scope is used only to represent the parent of the type's fields. The type does +have a class type supplement, but that's mostly necessary so that the pointer +to the associated scope can be recorded; the rest of the class type supplement +is irrelevant in C. + +In C++, the fields are the nonstatic data members of the class, and the class +type supplement gives additional information about the class: + +* | A list of the base classes of the class (both direct and indirect). +* | A list of the ``using``-declarations (and access adjustments, from access + declarations), of friend classes and functions, and of classes that have + befriended the class. These are of interest to a back end only for + generating symbolic debugging information. Note that the friendship + information is available in normal and reversed forms: the "befriending" + information is backwards from the source form -- it appears on the class + that is befriended, not the one that granted the friendship with a + ``friend`` declaration. +* | A scope entry for the class, which contains the definitions of the static + data members (as variables) and member functions (as routines) of the + class. The scope is present only if the class has been defined. + +The nonstatic data members are listed in declaration order, which (with the +default class allocation scheme) is the same as allocation order. Members of +base classes are not listed in the derived classes, even though they are in +some sense present by inheritance. + +Base Class Entries +^^^^^^^^^^^^^^^^^^ + +A base class entry describes a specific base class of a specific derived class. +It's more than just the type of a base class -- it describes how that class +type relates to the derived class: + +* | Where the storage for the base class appears in the derived class. +* | The derivation path from the derived class to the base class; for virtual + base classes there may be more than one such path. +* | The type of derivation, e.g., is the base class a virtual base class? +* | The list of virtual functions of the base class that are overridden in the + derived class. (This information is useful for generating virtual function + tables.) + +Base class entries are used for indirect base classes (i.e., base classes of +base classes) as well as for direct base classes. + +The base classes list for a given class lists all of the base classes of the +class all the way down, in depth-first left-to-right order (i.e., an indirect +base class precedes the direct base class derived from it; not coincidentally, +this is the order defined by the language as initialization order.) A +nonvirtual base class can appear more than once on the list -- it is marked as +ambiguous -- but a virtual base class will appear only once, though it may have +more than one derivation path. + +Base class entries are used in the IL wherever it is necessary to provide an +unambiguous specification of a base class instance. + +Class Scopes +^^^^^^^^^^^^ + +If a class is defined, its class type supplement will point to a scope entry +that defines the contents of the class (except the nonstatic data members, +which are provided by the field list of the class type). The class scope will +contain: + +* | Constants, for class constants (an extension). +* | Types, for types defined within the class (including nested classes). +* | Variables, for static data members and instances of variable templates. +* | Routines, for member functions, including static and non-static, virtual + and non-virtual, inline and non-inline, constructors, destructors, operator + functions, and conversion functions, but not friend functions. The routine + entries indicate any special attributes of each function, but the routine + list is just a list in declaration order. It's not broken into sections or + indexed in any way. The only way to find all virtual functions, for + example, is to go through the list and examine each routine to see if it is + virtual. + +Class Member Declaration Lists +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The lists described above group the members of a class by category, and none of +them accounts for constructs like a ``static_assert`` declaration, which +declares nothing. When ``MAINTAIN_CLASS_MEMBER_LIST`` is configured to TRUE, +the class type supplement of every defined class also points to the +``member_declarations`` list, which has one ``an_il_entity_list_entry`` per +declaration that appeared in the body of the class, in the order in which the +declarations appeared. For example, the list built for + +.. code:: c++ + + struct S { + static_assert(sizeof(int) == 4); + int a, b; + template void f(T); + friend void g(); + enum E { e1, e2 }; + }; + +identifies, in order, a static assertion, a field (``a``), a field (``b``), a +template, a routine, and a type. + +Note that: + +* | A friend declaration that appears in the body is included even though the + entity it declares is not a member of the class. +* | Entities that are not explicitly declared in the body are not included: + that is the case for members that the front end generates (e.g., an + implicitly-declared default constructor) and for template instantiations + that are triggered while the body is being processed. A member that is + explicitly defaulted or deleted is declared, and is therefore included. +* | An anonymous union is represented by the entry for its type; no entry is + created for the unnamed field through which the members of the union are + accessed (that field can be reached through the + ``anonymous_union_field`` pointer of the class type supplement). +* | The closure class of a lambda expression that appears in the body (e.g., + in a default member initializer) is not included; that class is reached + through the ``a_lambda`` entry for the expression. +* | An enumerator is not included because the declaration of its enumeration + type is; the enumerators can be reached through that type. +* | A member template is represented by the entry for its template, not by an + entry for the prototype instantiation of the templated entity (see + :ref:`templates-in-the-il`). +* | A *using-declaration* that names an overload set (or, with ``using + enum``, an enumeration) produces several ``a_using_decl`` entries but only + one entry on the list. +* | An entity that is declared more than once in the body is represented by one + entry per declaration. For example, a nested class that is first declared + and later defined in the same body appears twice. + +The list of an instantiated class template specialization describes the +declarations of the instantiated body. + +Class Layout +^^^^^^^^^^^^ + +Class layout is done by routines in ``layout.c``, and the decisions made are +recorded in the IL in the form of offsets, sizes, and alignments. The class +layout can be configured in various ways, or can be replaced in its entirety. +Class layout decides on: + +* | Offsets of nonstatic data members (fields) within the class. +* | Offsets of base classes within the class. For virtual base classes, + offsets of the information that allows access to the virtual base classes + (typically, a pointer to the virtual base class). +* | Offsets of virtual function information (typically, a pointer to a virtual + function table). +* | Ordering of base classes and members, and insertion of necessary alignment + between them. + +Virtual function table pointers and virtual base class pointers can be shared +with base classes. That is, space for such pointers need not be allocated in a +derived class if they are present in a base class; the derived class can use +the pointer in the base class. + +There are many configuration macros that control class layout. See +``targ_def.h``. + +C++/CLI Types +^^^^^^^^^^^^^ + +In addition to the standard types, C++/CLI has + +* | handle and tracking reference types, which are represented as + ``tk_pointer`` types, but aren't considered to be standard pointers or + standard references; +* | ``interior_ptr`` and ``pin_ptr`` types, which are variants of standard + pointer types with certain added attributes and restrictions (they only + appear as the types of local variables, parameters, or return types); +* | managed class types (``ref``\ ``struct``, ``ref``\ ``class``, ``value``\ + ``class``, ``interface``\ ``class``), which are represented like standard + class types, with a value in the ``cli_class_type_kind`` field that + indicates the kind of managed class; +* | ``enum``\ ``class`` types, which are similar to C++11 scoped enum types and + similarly represented; +* | CLI array types, which are represented as managed class types tagged with + the ``is_cli_array`` field; and +* | delegate types, which are represented as managed class types tagged with + the ``is_delegate_class`` field. + +Fundamental types usually have corresponding value class types (e.g., ``int`` +corresponds to the ``System::Int32`` value class type). In general, types +written in the source in either form are converted to the fundamental type +version. In cases where a managed type is required, the fundamental type is +converted to the value class, so for example "``int ^``" becomes "handle to +``System::Int32``" as soon as it is created. Otherwise, conversions between +the two kinds of types are always indicated explicitly. In particular, in +expressions a conversion from one form to the other will be indicated +explicitly, e.g., with a box or unbox operator. + +Namespaces +========== + +Namespaces are represented by entries of type ``a_namespace``. Such an entry +is used for a namespace definition, in which case it points to a scope entry +that describes the contents of the namespace, and also for a namespace alias, +in which case it points to another namespace entry. + +Entries of type ``a_using_decl`` describe ``using-directive``\ s and +``using-declaration``\ s that appear in the source program. This +information is not needed for code generation, but may be useful in the +generation of symbolic debug information or for source-to-source +translation. + +Constants +========= + +``a_constant`` describes a target machine constant, which can be an integer, a +string, a fixed-point constant, a floating-point constant, a complex or +imaginary constant, an address, or a pointer-to-member. Nontype template +parameters and the UPC identifiers ``THREADS`` and ``MYTHREAD`` are also +represented using ``a_constant`` entries. The constants are kept in target +form, and should not be manipulated without using the target-specific routines +for that purpose. Fixed-point constants are stored as ``a_fixed_point_value``\ +s. Floating-point constants are stored as ``an_internal_float_value``. String +constants are stored as a string of bytes in the target character set with an +associated length (to avoid any question about extra or missing null characters +in the string). The text of string constants is always allocated in the file +scope memory region to avoid some memory region problems. + +Integers are usually maintained in a host large integer +(``a_host_large_integer``/``a_host_large_unsigned``) regardless of the size +or signedness of their actual integral type. They are always properly +masked and sign extended. If a host large integer is insufficiently large, +the front end can be configured to use a more general (but computationally +less efficient) representation of integer values (see the configuration +macro ``INTEGER_VALUE_REPR_IS_A_HOST_INTEGER``). In either case, +``an_integer_value`` is the type to use internally to represent an integer +constant. + +Constants are also used as initial values of variables. When those variables +are aggregates (arrays or classes), some special kinds of constant entries are +used to represent aggregates of constants and repetition of constants within +those aggregates. Such constants are acting more as a structuring entity than +as simple constants; it's just convenient to use the ``a_constant`` entry for +that function as well. Getting even farther afield, there is even a constant +kind (``ck_dynamic_init``) that indicates an element in an aggregate constant +that is in fact not a constant at all, and must be computed at run time and +placed at that position in the aggregate. The structure of the aggregate +constant will match the structure of the variable being initialized. For +example, the initial value for a variable whose type is "array of 4 structures +containing 2 integer fields" will be an aggregate constant containing a list of +four constants, each of those an aggregate constant containing a list of two +integer constants. Aggregate constants need not fully initialize an aggregate +(i.e., there may be fewer constants than there are members of the aggregate); +any members not explicitly initialized are implicitly initialized to zero (even +when the variable being initialized is non-static). + +Most constants, specifically those used in expressions, are shared and reused, +so that only one constant ``0``, for example, need be allocated. Constants +used as constant initial values, however, are (and must be) unshared. [#f5]_ +Since the aggregating kinds of constant entries are only used in initial +values, it follows that they are always unshared. In ``pcc`` mode, string +constants are considered writable and are not shared. + +In some cases, a program may include a cast of a constant value to another +type, and the result (clearly constant) may be unrepresentable in any of the +normal forms. An example is an integer constant cast to a pointer type. For +these situations, the ``a_constant`` entry has the ``implicit_cast`` field. +When set, it indicates that the value of the overall constant is to be the +constant value cast to the type indicated by the ``type`` field. The back end +must determine the exact value to be used. + +Address constants are used to refer to the addresses of variables, +functions, string literals, etc. The offset in address constants is +expressed in bytes and is not scaled by the size of the object pointed to +(unlike in the C and C++ languages). Address constants are only used for +addresses that are truly constant, not, for example, for the addresses of +``auto`` variables. Note, however, that the constant value may not be +known until link time, i.e., it might not be a compile-time constant. + +Pointer-to-member constants represent the location of a particular data member +or member function of a class within an arbitrary instance of that class, i.e., +what is written in source as something like ``&A::xx`` (with ``xx`` a nonstatic +member of ``A``). They are defined in a high-level form rather than (for +example) as an offset within the class, to leave it to IL lowering or the back +end to choose an implementation for pointers to members. + +Wide character constants are represented as integral constants. Wide string +literals are represented as string constants. There are routines in +``literals.c`` that do the necessary packing. + +When character or string literals contain a universal-character-name (e.g., +``\u00d6``), the UCN value is converted from Unicode to the appropriate +character value or multibyte character sequence and stored in the string. + +In C++/CLI, string literals start out as standard C++ string constants, and are +converted to C++/CLI strings if the context requires it. So, for example, if a +standard string literal is passed as an argument to a function that takes a +parameter of type "``System::String``\ ``^``", the string will be converted to +a C++/CLI string. This is done by setting the constant type to "handle to +``System::String``" without setting the ``implicit_cast`` flag. There is no +conversion of the characters in the string to Unicode (or in any other way), in +spite of what the ECMA standard seems to require. Wide string literals can +also be converted to C++/CLI strings in this way, and in that case the string +contents are treated as Unicode (as they always are in Microsoft mode, and +therefore in C++/CLI mode; but still no conversion is done). Having C++/CLI +strings represented as constants is a little strange, since ultimately they +have to result in creation of a class object on the heap, and use of its -- +non-constant -- address; however, MSVC treats such strings as constants, so +emulating the Microsoft compiler is easier when they are represented as +constants. It is left to back ends to transform these constants into +executable code as needed. + +The front end generally attempts to fold constant-expressions into a single +``a_constant`` node. The expression that led to the constant is also recorded +in the ``expr`` field in the ``a_constant`` entry. If this field is nonnull, +it points to the expression tree which produced the constant when folded; the +resulting constant is not shareable. + +Variables +========= + +``a_variable`` describes a variable, parameter, static data member, instance of +a variable template, temporary, or structured binding. It indicates the type +and storage class. The storage class can be ``sc_auto``, ``sc_register``, +``sc_static``, ``sc_extern`` (meaning a reference to an external variable +defined in another compilation), or ``sc_unspecified`` (meaning a definition of +a variable visible to other compilations). The storage class is standardized +during declaration processing. Parameter variables can only have storage +classes of ``sc_auto`` or ``sc_register``. File-scope and namespace scope +variables, instances of variable templates, and static data members can only +have storage classes of ``sc_static``, ``sc_extern``, or ``sc_unspecified``. +Function- and block-local variables can only have storage classes of +``sc_auto``, ``sc_register``, or ``sc_static``. + +Variables declared with a named-register storage class (an Embedded C +extension) have storage class ``sc_unspecified`` (not ``sc_register``) but also +have the flag ``has_named_register_storage_class`` set to TRUE. The register +is described using a small integer stored in the variant field +``asm_name_or_reg.id``, which can be used to index the array +``named_register_storage_classes``. This array is defined in ``targ_def.h`` +and can be customized to describe the named-register storage classes available +on a particular target. + +If the variable has an initial value, the field ``init_kind`` indicates whether +the variable should be statically initialized to a constant value (simple or +aggregate) or dynamically initialized to a constant or non-constant value +(simple or aggregate). In the dynamic initialization case, the variable points +to a dynamic initialization entry that indicates the initialization to be done. +(More on this below.) Note that static initialization is never used for +non-static local variables, even ones initialized with a constant value: static +initialization initializes the entity once, at program startup time, whereas an +automatic local variable must be initialized each time the function is invoked +and the variable declaration is reached. Structured bindings (a C++17 feature) +that refer to array elements or to fields are represented as variables, but +they are really aliases for simple expressions referring to parts of the +associated (unnamed) container variable. These bindings have an +``initk_binding`` initializer kind and point to the aliased expression via +``initializer.binding``. Structured bindings that bind to a +``std::tuple``-like container are ordinary reference variables with +``initk_dynamic`` initializers. + +An uninitialized static variable is considered to be implicitly initialized to +zero. There is also an ``initk_zero`` initialization kind, which can be used +to explicitly initialize a variable to zero, statically or dynamically. On an +external variable, such initialization has the added function of indicating +that the variable is a true definition rather than a tentative definition. + +If the address of the variable has been taken anywhere (implicitly by +conversion of an array to a pointer or in binding of a reference, or explicitly +by use of the ``&`` operator), the flag ``address_taken`` will be set. + +If a variable is a local static variable of a function, +``referenced_non_locally`` is TRUE if the variable is referenced from a +different function, specifically from a member function of a local class. This +may have an effect on aliasing analysis. + +Local static variables create a memory-region difficulty: the variable entry +must be allocated in the file scope memory region, because the variable can be +referenced from the bodies of member functions of local classes. Dynamic +initialization of the variable, however, can be based on an expression +referencing a local (nonstatic) variable of the function, and therefore the +dynamic initialization must be allocated in the function scope memory region. +The ``a_local_static_variable_init`` entry solves this problem. When a local +static variable has initialization that must be allocated in the function scope +memory region, the variable ``init_kind`` is set to ``initk_function_local``. +This is an indication that the variable is initialized, but details of the +initialization are not available in the file scope. In the function or block +scope in which the variable is defined, there will be +``a_local_static_variable_init`` entry on the ``local_static_variable_inits`` +list of the scope. That entry will point to the variable, and give the +initialization details. Conceptually, the initialization information in the +local initialization entry is part of the variable information (it provides the +true values for the ``init_kind`` and ``initializer`` fields of the variable); +it's in a different place because of memory region issues. The routine +``get_variable_initializer`` can be used to fetch the complete initializer +information for a variable. It will search for and retrieve the function-local +information when necessary. Local static variables with initial values that +are simple (non-aggregate) constants always use ``initk_static`` initialization +rather than the ``initk_function_local`` form. This is done so that the values +of integral constant variables can be retrieved as constants while compiling +local classes. ``initk_function_local`` is used for dynamic initialization and +for aggregate constant initialization. + +Temporary variables are generated by IL lowering, for class temporaries and +when initializing references. Temporary variables are also generated for +anonymous unions; see :ref:`anonymous-unions` for more information. + +.. _il-dynamic-init: + +Dynamic Initialization +====================== + +A dynamic initialization entry (type ``a_dynamic_init``) is used to represent +initializations that require the execution of code at runtime, i.e., that +cannot be done as static initializations to a constant. + +The ``kind`` field of the entry indicates the kind of initialization to be +done: + +* | Initialization to a constant. Note that this is different than static + initialization to a constant, in that it gets done at a particular time and + possibly more than once. The constant here is unshared and may be an + aggregate (one that is completely constant). +* | Initialization to an expression. An expression is evaluated and its value + is the initial value. +* | Initialization by a constructor. A constructor routine is called to + initialize the entity. +* | Initialization by a routine returning a class object. A routine is called + and the value it returns (by calling a copy constructor) initializes the + entity. + +A dynamic initialization entry can also indicate a destructor that must be +called to destroy the entity initialized. [#f6]_ Such dynamic +initialization entries will be linked onto the destructions list of an +object lifetime entry. The destruction is to be done any time the region +of the object lifetime is exited, and IL lowering generates the appropriate +destructions. See :ref:`object-lifetimes`. + +A dynamic initialization entry indicates *what* the initialization is to +do, but it does not indicate *where* the initialization is to be done +(except if the entity being initialized is a complete variable), and it +does not indicate *when* the initialization is to be done. Dynamic +initialization entries are used in several cases, and the context in each +case provides the additional information needed: + +* | For initialization of file-scope variables, instances of variable + templates, or static data members, the variable points to the dynamic + initialization entry, and the ``dynamic_inits`` list from the scope entry + for the file scope indicates the order in which the initializations should + be performed. Variables from namespaces also appear on this same list, + since their initializations are intermixed with those of the file-scope + variables. +* | For initialization of function and block variables, the variable points to + the dynamic initialization entry, and there is an ``stmk_init`` statement + in the executable code of the function that points to the same dynamic + initialization entry and indicates the point at which the initialization + should be done. An ``stmk_init`` statement can appear in the same block as + the variable declaration or in a nested block. If the variable is a local + static variable, the initialization is to be done only the first time the + ``stmk_init`` is reached, and corresponding end-of-program destruction must + be done only if the initialization was done. Note that if a local variable + uses dynamic initialization it *must* have an associated ``stmk_init`` + statement. +* | For initialization of temporaries in the middle of expressions, an + ``enk_temp_init`` node points to a dynamic initialization entry that + indicates the initialization to be done. +* | For initialization of storage allocated by ``new``, an ``enk_new_delete`` + node points to a dynamic initialization entry that indicates the + initialization to be done. These dynamic initialization entries never + indicate destruction. +* | For destruction of storage in a ``delete``, an ``enk_new_delete`` node + points to a dynamic initialization entry that indicates the destruction to + be done. These dynamic initialization entries never indicate + initialization. +* | For initialization of members in a constructor-initializer (either + user-written or front-end-generated), an entry of type + ``a_constructor_init`` indicates the member or base class to initialize and + points to a dynamic initialization entry to indicate what to do. The order + of the ``a_constructor_init`` entries gives the order in which the + initializations should be done. These dynamic initialization entries never + indicate destruction (except when exceptions are enabled, in which case the + destructions indicated are to be done if an exception is thrown before the + constructor completes). +* | Similarly, for destruction of members in a destructor (which can only be + front-end-generated), an entry of type ``a_constructor_init`` indicates the + member or base class to destroy and points to a dynamic initialization + entry to indicate what to do. The order of the ``a_constructor_init`` + entries gives the order in which the destruction should be done (i.e., if + one looks at a constructor and destructor for a class, the entries on the + destructor will be in the reverse order of those on the constructor). + These dynamic initialization entries never indicate initialization. +* | For non-static data member initializers (NSDMIs), more recently renamed + as default member initializers (DMIs), the field entry ``initializer`` + field points to a dynamic initialization entry giving the initializer. + If such an initialization is not overridden in a given constructor, the + ``a_constructor_init`` entry for the field will have + ``use_field_initializer`` TRUE to indicate that the initial value comes + from the field initializer. +* | For dynamic initialization of entities within an aggregate, for example + + .. code:: c++ + + int i[3] = {1, 2, j+k}; + + | dynamic initialization entries at two levels are needed. The variable + ``i`` will point to a dynamic initialization entry that indicates the + overall initialization. Because the initialization is an aggregate + initialization containing a non-constant value, the dynamic initialization + will have the kind ``dik_nonconstant_aggregate`` and will point to a + ``ck_aggregate`` constant. That constant points to a list of the constants + in the aggregate, beginning with the constants ``1`` and ``2``. Following + that is another constant entry of kind ``ck_dynamic_init`` which indicates + "this position in the aggregate is not really a constant; here's what needs + to be done to compute it" and points to another dynamic initialization + entry, this one of kind ``dik_expression`` and indicating that the value to + use for the initialization is the expression ``j+k``. + | + | Within the aggregate constant list, ``ck_init_repeat`` constants are used + to repeat a particular ``ck_dynamic_init`` initialization a specified + number of times. This is needed to do constructor initialization of arrays + of classes. + | + | In this aggregate case, the top-level dynamic initialization entry serves + as more of an aggregating construct than as a specification of a dynamic + initialization. It shouldn't come as much of a surprise, then, to learn + that to specify only destruction for an aggregate, one uses a top-level + ``dik_nonconstant_aggregate`` dynamic initialization entry as is done in + the initialization case, and the destruction is specified in the + lower-level dynamic initialization entry. The troublesome thing about this + form is that one cannot tell just by looking at the top-level dynamic + initialization whether the overall construct does initialization, + destruction, or both. One must find and examine the lower-level dynamic + initialization entry. +* | For returns from routines that return a class by value, the ``stmk_return`` + statement points to a dynamic initialization that indicates the way to + create the class being passed back to the caller. +* | For expressions that are operands of ``throw``, the ``throw`` expression + node points to a dynamic initialization that indicates the way to copy the + value for use by the runtime. +* | For parameters of ``catch`` clauses, the catch clause points to a dynamic + initialization that describes the way to initialize the parameter from the + runtime's copy of the thrown object. + +IL lowering rewrites all dynamic initializations that are not valid in C, and +therefore constructor and destructor calls and non-constant aggregates do not +appear in the lowered IL. + +.. _object-lifetimes: + +Object Lifetimes +================ + +In C++, class types can have associated destructors, which are called to +destroy objects of the class type at the ends of their lifetimes. These calls +are implicit: the programmer does not write them, and the compiler generates +them in the appropriate places. For example, on a ``goto`` out of a block +containing a class variable, the destructor for the variable must be called. +If there are several possible ways to exit the block (e.g., flowing off the +end, ``goto``\ s, exceptions), the destructor must be called in each case. + +The IL does not make the needed destructor calls explicit (in fact, for +exception handling, the needed destructor calls would be done by the runtime, +so there's no way to put them in the IL without dictating a particular +implementation of exception handling). Instead, it gives information about +needed destructions and the associated object lifetimes in such a way that a +back end can easily generate the required destructor calls. (IL lowering puts +in those calls, so a back end working from the lowered IL need not deal with +object lifetimes.) + +The IL concept of an "object lifetime" is modeled on a source language concept, +the idea that an object's lifetime (the time during which it has a meaningful +value) might be different than the lifetime of the storage for the object. +That is, the object is constructed, used, and destroyed, and then the storage +that contained the object might remain around for some time longer, but it no +longer contains meaningful information and is no longer an object. + +It should be noted that from an IL point of view, the concept of object +lifetime is only applied to objects of class types having destructors. From a +strict language point of view, other kinds of objects do have object lifetimes, +but those object lifetimes are not very interesting because they always match +the lifetime of the object storage; more precisely, in the absence of a +destructor there is no way to tell the difference between an object whose +lifetime has ended and one that is still active, as long as the storage remains +allocated to the entity. Therefore there is no benefit in associating IL +object lifetimes with entities that do not need destruction, and there *is* a +benefit -- space savings -- in not doing so. Note that this means that IL for +C programs, which by definition involve no constructors, never includes object +lifetimes. + +The IL entry ``an_object_lifetime`` represents and defines an object lifetime. +There are several kinds of object lifetimes, each associated with a certain +kind of entity in the IL: [#f7]_ + +* | A static object lifetime, which lasts until the termination of the program. + For packaging reasons, there is a global static object lifetime and + possibly several function static object lifetimes (one for each function + that contains destructible local static entities). Such lifetimes are + bound to the file scope and function scopes. +* | A block object lifetime, which lasts until the termination of a function or + block scope. Such a lifetime is bound to a function or block scope. There + is also a variant of this kind of lifetime, referred to as a + block-after-label lifetime, that lasts from a label or (in + long-lifetime-temporaries mode) a switch case or default label to the end + of the scope. The block-after-label lifetime points to a statement that is + or contains a label or to a ``stmk_switch_case`` statement, respectively. +* | A try-block object lifetime, which surrounds the execution of a ``try`` + statement and its associated ``catch`` clauses, and is bound to a + try-supplement. +* | An expression temporary object lifetime, which lasts until the end of a + full expression, and is bound to an expression node of kind + ``enk_object_lifetime``, or to a dynamic initialization entry. + +Each dynamic initialization in the IL that requires end-of-lifetime destruction +is placed on the linked list of destructions attached to the proper object +lifetime entry. The destructions in a given lifetime are linked together by +the ``next_in_destruction_list`` pointer, in the order in which they should be +destroyed (that is, the reverse of the order of construction). The +``destructions`` pointer in the object lifetime entry points to the first +initialization on the list (the last one constructed and the first one to be +destroyed). + +Not all dynamic initializations are placed on a lifetime list. Initializations +of nonclass objects, or objects of class types that have no destructors, +clearly do not need to go on lifetime lists. Even initializations of objects +of class types with destructors are put on lifetime lists only if the +destruction of the object is automatic at the end of the lifetime, e.g., not +for ``new`` (the programmer controls the time of destruction) or ``return`` by +constructor (the destruction is done by the caller, not the subroutine). + +Each object lifetime has a ``parent_lifetime`` pointer, and also a +``parent_destruction_sublist`` pointer giving the position of the child +lifetime relative to the destructions in the parent. This makes a tree +structure that one can enter at some inner lifetime and follow upward. The +path upward from a given starting point is referred to as the "cleanup chain" +starting at that point. For example: + +.. code:: c++ + + struct A { A(); ~A(); }; + void () { // Lifetime 1 associated with this block + A x; + A y; + { // Lifetime 2 associated with this block + A xx; + // Position R + A yy; + } + A z; + } + +Lifetime 1 has the destructions list ``(z, y, x)`` and lifetime 2 has the +destructions list ``(yy, xx)``. Lifetime 2's ``parent_lifetime`` pointer +points to lifetime 1, and its ``parent_destruction_sublist`` pointer points to +the initialization entry for ``y``. + +One can see that if a ``return`` statement appeared at position R above, one +would want to destroy ``xx`` from the inner lifetime and ``y`` and ``x`` from +the outer lifetime. How would a back end figure that out? Well, as the back +end processes the IL, it would keep track of the latest +initialization-with-destruction encountered, i.e., the one for ``xx`` when at +position R. The pointer to that initialization defines the cleanup chain that +applies at position R. Starting with that initialization, the back end would +follow the ``next_in_destruction`` list to the end, generating destructions for +the entities on that list. Then, using the ``lifetime`` pointer in the last +dynamic initialization and the ``parent_lifetime`` pointer in the lifetime +pointed to, it would go to the parent lifetime, entering its destructions list +at the point indicated by ``parent_destruction_sublist``. It would then +generate destructions for the entities on that list. The process would +continue upward through parent lifetimes until the lifetime for the function is +processed. + +Generating destructions at a ``goto`` is almost as easy. The ``goto`` +statement has a ``common_lifetime`` field set by the front end. It indicates +the first object lifetime that the ``goto`` and the label have in common, that +is, the innermost object lifetime that appears on the cleanup chains for both +the goto and the label. The destructions for the ``goto`` are generated by +working upward through the cleanup chain, as for the ``return`` case, except +that processing stops when the common lifetime is reached (before generating +any destructions in that lifetime; if the ``goto`` is directly in the common +lifetime, then no destructions are generated). + +When labels appear, and are followed by declarations for destructible objects, +a new block-after-label lifetime is begun at the label. This is necessary for +backwards ``goto``\ s: + +.. code:: c++ + + struct A { A(); ~A(); }; + void () { // Lifetime 1 begins + A x; + L:; // Lifetime 2 begins after label + A y; + if (i) goto L; + } + +The destruction of ``x`` will be in lifetime 1, and the destruction of ``y`` +will be in lifetime 2. The ``goto`` is in lifetime 2, and the label is in +lifetime 1 (the parent of lifetime 2), so the common lifetime for the ``goto`` +is lifetime 1. The cleanup code at the ``goto`` therefore destroys ``y`` as it +exits lifetime 2, but it does not destroy ``x``. + +Switch case labels are treated like other labels and can begin new object +lifetimes if necessary. The labels generated for ``break`` and ``continue`` +statements do not ever begin new lifetimes. + +Destructible temporaries are treated much the same way as destructible +variables, and their initializations are likewise placed on lifetime lists. In +its choice of which lifetime to use in each case, the front end represents its +decisions on the lifetimes of temporaries. For example, when a reference +variable is bound to a temporary, the C++ language dictates that the lifetime +of the temporary is extended to match the lifetime of the reference (e.g., for +a static reference the temporary lasts until the end of the program). The +front end would represent this in the IL by placing the temporary on the same +lifetime as the reference variable. + +In the modern C++ language, normal temporaries last until the end of the full +expression within which they occur. In the front end, this is represented by +placing an expr-temporary lifetime around the full expression and placing the +destructions of any temporaries therein. In older dialects of C++, however, +including the dialect implemented by cfront, temporaries lasted until end of +scope. This mode is implemented by the EDG C++ front end in cfront +compatibility mode and when ``--long_lifetime_temps`` is specified. To be more +precise, in long-lifetime-temporaries mode temporaries survive until end of +scope or until a label, and they are limited to a single statement when the +statement is a conditional dependent statement, or to a full expression when +the expression is the tested expression in a conditional or loop statement, or +the initializer for a local static variable. Since long-lifetime temporaries +are destroyed at a label, when walking a cleanup chain and going from a +block-after-label lifetime to its parent one should ignore destructions for +temporaries until one reaches and exits from a block lifetime (all temporaries +in the block lifetime and any intervening block-after-label lifetimes were +destroyed at some label, and are no longer active). Because of the destruction +of temporaries at labels, in this mode block-after-label lifetimes are required +at some labels even when there are no destructible objects created after the +label. + +In addition to its use in generating destructions on programmed exit from +lifetimes, the block object lifetime information is also intended to be useful +in generating the cleanup description information needed by the runtime support +for exception handling. With the default configuration, IL lowering will use +the object lifetime information to generate data structures that support EDG's +implementation of exception handling. Those who wish to create a +higher-performance version of exception handling may find it useful to turn off +lowering of exception handling features and to use the object lifetime +information directly in the back end to generate the required cleanup +information. In either case, because the object lifetime information is used +to generate exception handling information, it includes some information beyond +what is required to generate cleanup on block exits: + +* | There is information about the mem-initializers (both user-written and + front-end-generated) in constructors, and about the similar + (front-end-generated) data structure in destructors. +* | For each ``new`` that does allocation inline (rather than letting a + constructor do it), a dynamic initialization entry is generated to indicate + the freeing of the storage to be done if an exception is thrown before the + storage is fully initialized. +* | For local static variables, a block object lifetime is placed around the + entire initialization and bound to the local static variable initialization + IL entry. Exiting this lifetime via an exception causes the runtime to + reset the state so that the local variable is marked as uninitialized. If + its declaration is encountered again on a subsequent call, the + initialization will be attempted anew. +* | For aggregate classes or arrays initialized by a brace-enclosed list, + individual sub-initializations will indicate destructions to be done if an + exception is thrown before the complete aggregate is initialized. Once the + aggregate has been completely initialized, these destructions to undo + partial construction no longer apply. + +One of the unfortunate consequences of using dynamic initialization entries to +represent destructions is that the contextual nature of dynamic initialization +entries (they don't indicate the entity to be initialized; it's implied by the +context) -- which is an advantage when the entries are used to do +initializations -- is somewhat of a disadvantage when the entries are used to +do destructions. Specifically, unless one saves some information in the +dynamic initialization entry at the time it is processed as an initialization, +it is very hard to know what to destroy when one processes it as a destruction. +However, it's not hard to solve this problem from a practical point of view: +one just adds a field to the dynamic initialization entry to point to +back-end-specific information recorded at the time that the initialization is +processed, and that information is then available, and in just the right form, +when the destruction is processed. That's the technique used by IL lowering. + +Routines +======== + +``a_routine`` describes a function. It indicates the type and storage class. +The storage class can be ``sc_static``, ``sc_extern`` (meaning a reference to a +function defined in another compilation), or ``sc_unspecified`` (meaning a +definition of a function visible to other compilations). The storage class is +standardized during declaration processing. A function with a body will have +storage class ``sc_unspecified`` or ``sc_static``; a function without a body +will have storage class ``sc_extern``. + +The type of a function is always a function type, which describes the +external interface to the function: its return type, its parameter types, +etc. A nonstatic member function will also have an implicit "``this``" +parameter, with a type of ``const`` pointer-to (possibly qualified) class. +The parameter types might have associated default argument value +expressions, although that information is useful to a back end only for +generation of symbolic debugging information, since calls of the routine +will have the default argument values supplied. + +The routine entry also indicates whether or not the routine is inline, virtual, +and/or front-end-generated. (The front end generates routines for constructors +and destructors, assignment operator functions, and, when IL lowering is done, +for global initialization and termination routines, runtime routines, and +wrappers for constructors with default arguments.) The ``special_kind`` field +indicates whether or not the function is a C++ special function such as a +constructor. If the ``special_kind`` indicates that the routine is an operator +function, ``opname_kind`` indicates the kind of operator function it is. The +``special_kind`` is significant to a back end using the unlowered C++ +intermediate code in that wrapper code needs to be generated for constructors +and destructors. Other than that, ``special_kind`` and ``opname_kind`` are +mostly of interest for generating symbolic debugging information and mangled +names. + +The routine entry points to a list of classes that have befriended the +function. Those classes will have the function on their friend lists. + +If the function is a virtual function, the routine entry indicates a virtual +function number assigned to the routine. Typically, this will be used as the +function's index into a virtual function table, but since the unlowered C++ IL +leaves virtual function access as an abstraction, it's only a helpful +identifying number at that level. + +If the function has a body, the routine entry indicates the function +definition number and the memory region that contains the function +definition. By indexing through ``il_header.function_def_table``, one can +get to the scope entry for the function (in the proper function scope +memory region). That scope entry points to the statements and local +declarations of the function. It also points to variables for the +parameters of the function, including a "``this``" parameter variable if +necessary. The parameter and "``this``" variables will match the parameter +and "``this``" types in the function type. (In non-prototyped functions, the +function type parameters might be promoted versions of the parameter +variable types.) For parameters that are passed using a copy constructor +(indicated by a flag in the parameter type entry), a back end using the +unlowered C++ IL may have to expect to receive the address of the class +entity rather than its value, and to do implicit indirections on the +references to the parameter. + +The ``address_taken`` flag in the routine entry will be set if the address of +the function has been taken. Merely calling the function does not cause the +``address_taken`` flag to be set, even though the IL for a call refers to the +routine address. + +An exception specification that appears on a function declaration is +represented by an entry of type ``an_exception_specification``, referred to +by means of the ``exception_specification`` field of the routine type +supplement. When the function is declared with no exception specification +(meaning that *any* exception might be thrown) the +``exception_specification`` pointer will be NULL. The exception +specification entry representing a dynamic exception specification has a +pointer to a linked list of entries of type +``an_exception_specification_type``, each of which indicates a type of +exception that will be thrown from the given routine; that pointer is NULL +to indicate that *no* exceptions will be thrown. An exception +specification representing a ``noexcept`` specification points to an entry +of type ``a_constant`` representing its operand (or NULL if no operand is +specified). + +When ``ASM_FUNCTION_ALLOWED`` is TRUE, ``asm`` functions are recognized and +passed uninterpreted to the back end. They are represented in the IL like +ordinary functions, except that they have a storage class of ``sc_asm`` and the +function body (pointed to from the associated scope entry) is represented by an +``stmk_asm`` statement. The asm entry to which the latter refers points is a +null-terminated string containing the text that appeared in the source; +comments are removed unless ``INCLUDE_COMMENTS_IN_ASM_FUNC_BODY`` is TRUE. + +In order to save space in the ``a_routine`` structure, some (mostly +GNU-specific) fields with default values that are rarely changed are located in +the ``a_gnu_routine_supplement`` struct, which is pointed to by the +``gnu_extra_info`` field. This supplement is only allocated when one of the +fields has a non-default value. + +The GNU function multiversioning feature (available in GNU C++ modes where +``gnu_version`` >= 40800), allows for declarations/definitions of multiple +routines with the same signature but with different ``target`` attributes. The +``target`` attributes specify which CPU architecture is applicable for each of +the functions in the group. Internally, the entire group of functions is +represented by a "representative" function (whose ``is_representative`` field +is TRUE). All target-specific functions are have the +``is_target_specific`` field set to TRUE and are queued on the +``mv_info.representative.targeted_versions`` list. Although each of the +routines (both representative and target-specific) have associated symbols, +only the symbol for the representative routine is entered into the symbol +table. This feature is controlled by the ``GNU_FUNCTION_MULTIVERSIONING`` +configuration macro. + +Constructors and Destructors +============================ + +Constructor and destructor routines must do additional processing beyond what +appears in the body of the routine. Since this processing surrounds the code +in the definition of the routine, it is called "wrapper" code. + +Some of the wrapper code is implicit: there must be code that initializes +the information in the class used to access virtual base classes and +virtual functions (typically, virtual base class pointers and virtual +function table pointers). The wrapper code must also control whether or +not virtual base classes are initialized or destroyed (they should be for a +complete object, but not for a subobject). If a ``new`` or ``delete`` +operation can be folded into a constructor or destructor (a configuration +option, but always true if assignment to "``this``" is supported), the +wrapper code may have to provide for calling a ``new`` or ``delete`` +routine. + +The wrapper code must also do any necessary initialization or destruction for +base classes and members. The required actions are described explicitly by a +list of ``a_constructor_init`` entries which indicate the initialization or +destruction to be done, in the correct order. If the source program contains +constructor-initializer clauses, they will appear on the list in the right +positions. For any base class or member that requires initialization and for +which the source does not provide an initializer, a default initializer is +generated. In a front-end-generated copy constructor, the default +"initialization" will in fact be a copy. In a destructor, there is no source +construct for indicating specific destruction for base classes and members, so +the list is always front-end-generated in its entirety. It is also in the +correct order, i.e., the reverse of the order in the corresponding constructor +list. + +IL lowering modifies constructor and destructors to provide all the necessary +wrapper code. + +Calls of "destructors" for classes that do not have them or for simple types, +as in + +.. code:: c++ + + p->int::~int(); + +are rendered as ``eok_dot_vacuous_destructor_call`` or +``eok_points_to_vacuous_destructor_call`` expression nodes in the IL. No +routine entry is created for the ersatz destructor. Such nodes are rewritten +as casts to ``void`` in IL lowering. + +Labels +====== + +``a_label`` is a declarative entity that describes a label (user-written or +front-end-generated) in a function. It is pointed to by the ``goto`` and label +definition statements in the executable code of the function. + +``asm`` Statements +================== + +An ``asm`` statement (or declaration, whichever way you care to look at them) +can appear in two contexts: + +* | Within the bodies of functions, where it is considered to be executable + code and is represented by an ``stmk_asm`` statement pointing to + ``an_asm_entry`` that gives the ``asm`` statement string. +* | At file or namespace scope, where it is considered to be a declaration and + is represented as ``an_asm_entry`` on a list of such entries attached to + the file or namespace scope ``a_scope`` entry. If such ``asm`` + declarations are supposed to affect declarations that immediately follow + them, the back end must consider the source positions of variables, + routines, and ``asm`` entries and do a merge of those lists. + +Statements +========== + +``a_statement`` describes a statement, which can be an expression, an ``if``, a +``while``, a ``do``-``while``, a ``for``, a ``switch``, a ``goto``, a +``break``, a ``continue``, a label definition, a ``return``, a block (with or +without an associated scope), a ``try`` block, or a declaration statement. + +The representation of ``switch`` statements (``stmk_switch``) matches the +language definition, but the ``case`` and ``default`` labels are represented +using a separate statement entry kind ``stmk_switch_case``. Each +``stmk_switch_case`` entry points to an entry of type ``a_switch_case_entry`` +(which describes the label's value, among other things). An ``stmk_switch`` +statement points to a list of all switch case entries associated with that +statement (via an entry of type ``a_switch_stmt_descr``). A list of switch +case entries in sorted order of label value is usually also available (this +list excludes the ``default`` case), but not if any of the cases is +template-dependent. ``break`` statements to transfer out of a ``switch`` +statement are ``stmk_goto`` statements pointing to a label entry whose +``switch_break_label`` flag is TRUE. + +The ``stmk_init`` statement indicates the point in a sequence of executable +statements where the dynamic initialization of a variable should be done. It +points to the same dynamic initialization entry that the variable does. This +is particularly useful in C++ where variables can be declared and initialized +in the middle of a block. + +The ``stmk_block`` statement is used both for a simple compound statement and +for a block (i.e., a compound statement containing local declarations). The +``a_block`` entry pointed to from the statement indicates whether or not the +block has an associated scope. In C++, a block statement is always generated +for the dependent statement of conditionals (e.g., ``if``), even if no ``{ }`` +are present. However, the block will not have an associated scope unless +something is actually declared inside the block. + +The ``stmk_try_block`` statement is used to represent a ``try`` block. It +points to a compound statement block and a linked list of handlers. The latter +are entries of type ``a_handler``; each points to a (possibly unnamed) +parameter (the local variable to which the thrown object will be copied when +the handler is invoked) and to an ``stmk_block`` statement, the body of the +handler; for a default handler (i.e., the ``catch(...)`` case) the parameter +pointer in the handler entry is NULL. + +The ``stmk_decl`` statement is used to represent a declaration statement. This +could be the declaration of one or more variables and/or functions (using one +of more comma-separated declarators), one or more typedef types, a local class +or enum type, a using-declaration, etc. + +The C++/CLI "for each" statement is represented by an ``stmk_for_each`` +statement. Its representation includes an indication of which "pattern" the +loop matches (the CLI collection pattern, the CLI array pattern, the STL +pattern, or the native array pattern), and for each of those patterns +expressions that give the worked-out expansion for the pieces of the loop, so +that a code-generating back end does not need to figure out the expansion. + +When support for variable length arrays is enabled, two additional statements +may appear. + +* | An ``stmk_set_vla_size`` statement is associated with a VLA declaration and + indicates exactly where the dimension expression for a VLA should be + evaluated. +* | An ``stmk_vla_decl`` statement will refer to a variable of variably + modified type or to a ``tk_typeref`` type to indicate the location of the + corresponding variable or ``typedef`` declaration. This is generally + important because a VLA type has run-time dependencies that need to be + honored. Moreover, when the variable referred by an ``stmk_vla_decl`` + statement has a VLA type (not just a type that "contains" a VLA type), the + ``stmk_vla_decl`` statement indicates the point at which the storage for + the variable should be allocated. Note that a single ``stmk_vla_decl`` + statement may be preceded by multiple ``stmk_set_vla_size`` statements if + the type associated with the ``stmk_vla_decl`` statement has multiple + variable-length dimensions. (See also :ref:`il-types` and + :ref:`il-operation-exprs`.) In C modes, expression statements with a single + node of kind ``enk_vla_dealloc`` (see also :ref:`il-vla-dealloc`) may be + generated to indicate the point at which a variable of VLA type should be + deallocated (e.g., preceding a ``goto`` out of a scope containing a VLA + variable). Such deallocation constructs are generated only when + ``VLA_DEALLOCATIONS_IN_IL`` is TRUE. + +Note that variable-length array types can also appear in ``sizeof`` +expressions. None of the above statement kinds are generated for those cases +since statements cannot in general appear within expressions. Instead, such +expressions result in ``enk_sizeof`` expression nodes. Back ends can find and +examine the ``a_vla_dimension`` entries associated with such nodes to evaluate +the result of the ``sizeof`` expression. + +.. _src-seq-lists: + +Source Sequence Lists +===================== + +When ``GENERATE_SOURCE_SEQUENCE_LISTS`` is TRUE, lists of +``a_source_sequence_entry`` are generated, ordered strictly according to +the order in the source program. This is useful for applications that care +about the exact order of declarations, redeclarations, and definitions in +the source code, e.g., source analysis applications. Each list entry +represents a declaration, a statement, a macro, a pragma, a template, or a +template specialization that represents an instantiation (if either of the +deprecated configuration macros +``CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS`` or +``NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS`` is TRUE). +Those entities representing declarations and statements point to the +corresponding IL entry, and the latter have pointers back (fields +``source_sequence_entry`` in ``a_source_correspondence`` and in +``a_statement``). + +The lists appear in the IL via the ``source_sequence_list`` pointer in +``a_scope`` entries for the file scope and for each function scope. (The +pointer will always be NULL for other scope kinds.) Source sequence entries +themselves have both forward and backward pointers to facilitate list traversal +and management. + +Logically, there is a single source-sequence list in a translation unit. +Actually, however, a number of lists may be involved. The file-scope +source-sequence list is pointed to from the scope entry for the file scope, but +when a function definition appears, another list, pointed to from the scope +entry for the function, is produced. The logical successor of the +source-sequence entry for the function (which is in the file-scope list) is the +first entry on the function-scope list, and the logical successor of the last +entry on the function-scope list is the entry pointed to by the ``next`` +pointer of the function's source-sequence entry. + +The reason for representing the logically continuous source-sequence list by +many discontinuous lists is that source-sequence entries appear in different +memory regions, just as the IL entries they point to do. Thus, the entries on +the file-scope source-sequence list are allocated in the file-scope memory +region, but the entries on a function-scope source-sequence list are usually +allocated in the memory region of that particular function. + +Some declarations within a function, however, create entities that are +allocated at file scope. This is the case for types, static variables, and +variables and functions declared ``extern``. The source-sequence entries for +such entries must also be in the file-scope memory region, but that means they +cannot be on the same linked list with entries allocated in the function-scope +memory region. Therefore, additional side branches are used: entries of type +``a_src_seq_sublist`` ("sublist headers") establish such branches by pointing +to the head and tail of a list of file-scope source-sequence entries that are +logically within the source-sequence list of the function scope. + +The sublist headers for a given function, as well as being pointed to by +entries ("sublist parents") in the function-scope source-sequence list, are +also chained together; the head of the linked list is pointed to by +``src_seq_sublist_list`` in the function's scope entry, and its tail is pointed +to by ``last_src_seq_sublist`` in the corresponding scope stack entry. + +Entries of type ``a_src_seq_end_of_construct`` are inserted into the +source-sequence list to mark the point at which certain constructs terminate +(the entries point back to the associated IL entry). This includes class and +enum definitions and statement blocks. Such entries are also used to mark the +end of a set of source sequence entries for constructs embedded in a variable +or function declaration. For example, in: + +.. code:: c++ + + int x[sizeof(struct S { int i; })]; + +(which is accepted in some modes only), the source sequence list contains an +entry for the definition of variable ``x``, followed by entries for the +definition of struct ``S``, followed by an entry marking the end-of-construct +of variable ``x``\ 's definition. An end-of-construct marker is similarly used +to mark the appearance of the "``while (...)``" part of a do-while statement +(this is, e.g., significant to be able to record whether a pragma appeared +before the statement as a whole, or just before the ``while`` keyword). + +When a declaration is not a definition (e.g., a function declaration with no +body or a variable declared ``extern``), it is represented by an entity of type +``a_src_seq_secondary_decl``, which is pointed to by the source-sequence entry +and points in turn to the corresponding IL entry. Therefore, when an entity +has more than one declaration, multiple source-sequence entries are created, +but only the one that represents the definition points directly to the IL +entry; the others point to secondary declaration entries. If there is no +definition of the entity in the compilation, all of the source sequence entries +for that entity will be secondary declarations. + +(Source sequence lists are not actually added to the IL tree until +``pop_scope`` is called for a function scope or the file scope. During front +end processing, the source sequence lists as described above are assembled from +smaller lists that are managed on a per-scope basis; whenever a scope stack +entry is popped, its list is typically merged into the list of the immediately +enclosing scope. Moreover, the source sequence list describing a function +definition may temporarily be a simple linked list containing a mix of entries +from the memory regions of the function scope and the file scope; the +representation involving sublist headers, as described above, is produced by a +fixup pass when the function scope is popped.) + +Many implementations will not need the kind of information provided by +source-sequence lists and will choose to avoid the processing overhead and +especially the memory overhead they introduce. By default, therefore, +``GENERATE_SOURCE_SEQUENCE_LISTS`` (defined in ``host_envir.h``) is set to +FALSE. + +Expressions +=========== + +``an_expr_node`` describes an expression node, which can be an operator node, a +reference to a constant, variable, or function, an initialization of a +temporary, or a few other things like ``new`` or ``delete``. + +Each expression node has a type, indicated by its ``type`` field. + +The simplest expression nodes are leaf nodes. The most common leaf node kind +are: + +* | ``enk_variable`` refers to a variable. +* | ``enk_routine`` refers to a function. +* | ``enk_constant`` refers to a constant. +* | ``enk_field`` refers to a field. + +Lvalues and Rvalues (Value Categories) +-------------------------------------- + +Each expression node has an ``is_lvalue`` flag, which is TRUE if the node +represents an lvalue and FALSE if it represents an rvalue. (It is also TRUE +for what is called a function designator in C, which is simply called an lvalue +in C++.) + +So, an ``enk_variable`` node with ``is_lvalue`` TRUE indicates an lvalue for +the variable, and the same node with ``is_lvalue`` FALSE indicates an rvalue +for the variable, i.e., the value of the variable. In the statement + +.. code:: c++ + + i = j; + +the left operand would have ``is_lvalue`` TRUE and the right operand would have +``is_lvalue`` FALSE. + +Similarly, an ``enk_routine`` with ``is_lvalue`` is TRUE indicates an lvalue +for the function (which has a function type), and one with ``is_lvalue`` FALSE +indicates an rvalue for the function (which is the address of the function, and +has pointer-to-function type). + +``enk_constant`` nodes are usually rvalues, representing the value of an +indicated constant. The one exception is that an ``enk_constant`` for a +string constant (``ck_string``) can be an lvalue for the string. + +C++11 adds the concept of "xvalues," which are eXpiring values produced by +certain rvalue reference operations. They are indicated by the ``is_xvalue`` +flag in the node being TRUE (``is_lvalue`` and ``is_xvalue`` are never both +TRUE). Lvalues and xvalues are collectively called "glvalues." The things that +were called "rvalues" in pre-C++11 C++ and in C are known in C++11 as +"prvalues," and the term "rvalue" becomes a collective term for prvalues plus +xvalues. [#f8]_ In the IL, xvalues in general can be viewed as funny versions +of lvalues. + +Glvalue nodes shouldn't be considered to have values. They're just a +description of an object in memory. Because they don't have values, they also +can't be considered to be constant or to have constant values, though some +lvalues will have constant addresses (see ``constant_glvalue_address``). + +When a glvalue with a cv-qualified type is converted to a prvalue, the type +qualifiers are dropped (except for class-typed prvalues in C++). In the IL, +this is reflected in the fact that the expression node for the prvalue will +have the unqualified type. When an lvalue with a function type is converted to +a prvalue, its type becomes pointer-to-function. + +Clearing the ``is_lvalue`` flag in an expression node where initially the flag +would be expected to be TRUE indicates a fetch from memory. This is obvious on +the ``enk_variable`` node, but it also applies to many other nodes, such as +field selection and subscripting operators. Nodes that can be made to include +a fetch merely by clearing the ``is_lvalue`` flag (or, similarly, the +``is_xvalue`` flag) are referred to as "rvalueable". One can test for the +presence of an implicit fetch (also known as an lvalue-to-rvalue conversion) in +an expression node by calling ``node_includes_glvalue_to_prvalue_conv``. + +.. _il-operation-exprs: + +Operation Expressions +--------------------- + +Expression nodes of kind ``enk_operation`` are operations. They are the +non-leaf nodes of expression trees, the ones that apply an operator to a set of +operands, to do operations like ``i+j``. + +The operands of an operation are linked together as a list, and the operation +node points to the first expression on the list. + +Most operations take a fixed number of operands. The various forms of calls +are exceptions and take a variable number of operands. + +The operator kind (addition, assignment, call, etc.) is described by the +``variant.operation.kind`` field, which is mostly independent of the type of +the operands. For example, an addition is described with kind ``eok_add`` +independently of the operand type. There are a few exceptions to this when the +semantics of the operation vary sufficiently from the generic case to warrant a +separate operator. For example, pointer arithmetic uses dedicated operators +``eok_padd``, ``eok_psubtract``, and ``eok_pdiff`` instead of the generic +``eok_add`` and ``eok_subtract``. Where applicable, an additional field +``variant.operation.type_kind`` describes the class of types an operation acts +on. For example, this will be ``tk_float`` for the multiplication of two +floating-point values, or ``tk_template_param`` for a multiplication involving +a template-dependent operand. For operations that don't apply to a particular +type kind (e.g., ``eok_call``), the ``type_kind`` field is set to +``tk_unknown``. The ``type_kind`` field is set automatically when calling +``make_operator_node`` or ``set_node_operator`` (it is ultimately computed by +``operation_type_kind``). + +In the case of scalar controlling expressions, the several different cases +(integer, float, and pointer) are reduced to a single case (integer) by +standardizing the expression. Specifically, for the expression of a +``stmk_if``, ``stmk_while``, ``stmk_end_test_while``, or ``stmk_for``, and for +the controlling operands of the ``eok_not``, ``eok_land``, ``eok_lor``, and +``eok_question`` operators, the expression will always be either an integer +constant ``0`` or ``1``, or an expression whose top operator is defined to +yield a ``0`` or ``1`` result. Where necessary, a constant value will be +standardized (e.g., ``5.3`` will be changed to ``1``), or a ``!= 0`` operation +of the proper type (integer, float, or pointer) will be added to the top of the +expression. + +The operands of an expression may be evaluated in any order consistent with +the C and C++ "as-if" rule. By default, parentheses are not directly +represented in the IL; their effect is simply reflected in the operands of +the operators in the expression tree or, in cases where they have semantic +implications, by flags in various IL entries (e.g., +``an_expr_node::is_parenthesized``). Applications that need to be aware of +source-level parentheses can set the ``PARENS_IN_IL`` configuration option; +see :ref:`parentheses`. + +In general, operator nodes that do not correspond directly to something that +appeared in the source, and were added by the front end, are marked by having +``compiler_generated`` set to true. + +Addressing operators +-------------------- + +There are several addressing operators (note that when we refer to ``eok_...`` +names we mean those under the ``enk_operation`` expression variant): + +* | ``eok_address_of`` is the "``&``" operator. Its operand is an lvalue, and + its result is a prvalue of pointer type that is the address of the lvalue. +* | ``eok_indirect`` is the "``*``" operator. Its operand is a prvalue + pointer, and its result is an lvalue that is the object pointed to. It + is rvalueable. +* | ``eok_array_to_pointer`` converts its operand, an array (lvalue, xvalue, or + prvalue), to a prvalue pointer to the first element of the array. + +The "restrict" qualifier on pointers, originally introduced in C99, is a type +qualifier on pointer types that indicates that they can be considered to be +unaliased (nothing else in scope points at what they point at). The function +``node_is_pointer_with_restrict_semantics`` can be used to test an expression +node that is a pointer (e.g., the operand of an ``eok_indirect`` operation) to +see whether it has the "restrict" semantics. + +References +---------- + +References are not pointers, but they are treated as somewhat pointer-like in +the IL, with their own versions of the addressing operators: + +* | ``eok_reference_to`` is the reference version of "``&``". Its operand is a + glvalue, and its result is a prvalue of reference type that is the + "address" of (reference to) the glvalue. Its operand can also be a class + prvalue, in which case its result is the "address" of the underlying class + object. +* | ``eok_ref_indirect`` is the reference version of "``*``". Its operand is a + prvalue with reference type, and its result is an lvalue that is the object + referenced. It is rvalueable. + +These operators do not, of course, appear in the source code; they are added by +the front end where needed. No operations are allowed on references other than +the above, or storing a reference somewhere, or passing it as an argument. + +An example: for something like + +.. code:: c++ + + int i; + int &r = i; + r = r; + +the left operand of the assignment is an ``eok_ref_indirect`` with +``is_lvalue`` TRUE over an ``enk_variable`` for ``r`` with ``is_lvalue`` FALSE, +and the right operand is an ``eok_ref_indirect`` with ``is_lvalue`` FALSE over +an ``enk_variable`` for ``r`` with ``is_lvalue`` FALSE. + +Note that reference type values are typically dealt with as prvalues, in the +same way that pointers are. In the example above, the ``enk_variable`` for +``r`` is effectively fetching the pointer-like value stored in the reference +variable, so its ``is_lvalue`` flag is FALSE. An ``enk_variable`` node with +``is_lvalue`` TRUE for a reference variable would mean an lvalue for the cell +containing the reference value, but there's no real use for that in the C++ +language, since you can't take the address of the cell nor can you change its +value after initialization. + +Address constants with kind ``ck_address`` can have reference type when they +are used to initialize a reference-typed variable. They represent a constant +reference value. + +Rvalue references (source form like "``int``\ ``&&r``") are similar to the +traditional "lvalue" references. ``eok_reference_to`` and ``eok_ref_indirect`` +can be used with them also, and ``ck_address`` constants can have rvalue +reference type. An rvalue reference is always bound to an rvalue (i.e., an +xvalue or prvalue). See :ref:`casts` for information on casts to +rvalue reference types. + +Field Selection +--------------- + +There are several operators that implement field selection: + +* | ``eok_dot_field`` is the "``.``" operator. The left operand is a class + glvalue or prvalue, the right operand is an ``enk_field``, and the result + is a glvalue or prvalue of the type of the selected field (with + cv-qualifier adjustment). When the left operand is an lvalue, the result + is an lvalue (rvalueable), and similarly for an xvalue. When the left + operand is a prvalue, the result is a prvalue. +* | ``eok_points_to_field`` is the "``->``" operator. The left operand is a + prvalue pointer to class, the right operand is an ``enk_field``, and the + result is an lvalue (rvalueable) of the type of the selected field (with + cv-qualifier adjustment). +* | ``eok_pm_field`` is the "``.*``" operator. The left operand is a class + glvalue or prvalue, the right operand is a pointer to data member, and the + result is a glvalue or prvalue of the type of the pointed-to member (with + cv-qualifier adjustment). When the left operand is an lvalue, the result + is an lvalue (rvalueable), and similarly for an xvalue. When the left + operand is a prvalue, the result is a prvalue. +* | ``eok_pm_points_to_field`` is the "``->*``" operator. The left operand is + a prvalue pointer to class, the right operand is a pointer to data member, + and the result is an lvalue (rvalueable) of the type of the pointed-to + member (with cv-qualifier adjustment). +* | ``eok_dot_static`` is the "``.``" operator when the entity selected is + static. The first operand is a class glvalue or prvalue (and it *is* + evaluated) and the second operand is an ``enk_variable`` for a static data + member, an ``enk_routine`` for a static member function, or an + ``enk_constant`` identifying a member constant (e.g., an enumerator). The + result is the second operand. +* | ``eok_points_to_static`` is the "``->``" operator when the entity selected + is static. The first operand is a prvalue pointer to class (and it *is* + evaluated) and the second operand is an ``enk_variable`` for a static data + member, an ``enk_routine`` for a static member function, or an + ``enk_constant`` identifying a member constant (e.g., an enumerator). The + result is the second operand. + +Note that most of the selection operators are rvalueable in some cases, but the +static variants are not; for those, the lvalue-to-rvalue conversion, if there +is one, has to be indicated on the second operand, and not in the +``eok_dot_static`` or ``eok_points_to_static`` operation itself. + +Also note that there are no variants of the pointer-to-member selections for +pointer-to-member-function cases. Those can be used only in calls, and the two +operands of the selection are simply folded into the ``eok_pm_call``. +Likewise, the "``.``" or "``->``" operation in a member function call is simply +folded into the call. + +Subscripting +------------ + +``eok_subscript`` is the array subscripting "``[]``" operator. One operand is +a prvalue pointer to the first element of the array, and the other is an +integral subscript value. The result is an lvalue (rvalueable) for the +specified element of the array. Usually, the pointer operand is first, but +that's not actually a requirement of the language, and the operands can appear +in either order, as for the expression "``1[a]``". See the +``pointer_operand_is_second`` field, which indicates this unusual case, and the +macro ``subscript_or_padd_pointer_operand``, which can be used to extract the +pointer operand. As you will note from the name of that macro, this is also an +issue for the pointer addition (``eok_padd``) operator. + +.. _casts: + +Casts +----- + +The ``eok_cast`` operator is used to indicate simple casts. + +Casting a derived class pointer to a base class pointer is represented by an +``eok_base_class_cast`` operator. Casting a base class pointer to a derived +class pointer uses an ``eok_derived_class_cast`` operator. These casts differ +from ordinary pointer casts in that they may add or subtract an offset to the +pointer, and they must preserve a NULL pointer. They can also be applied +directly to a class glvalue or prvalue, rather than a pointer to a class +object, or to a C++/CLI handle. + +``eok_pm_base_class_cast`` and ``eok_pm_derived_class_cast`` are the similar +casts for pointers-to-members. The same operators are used for +pointers-to-data-members and pointers-to-member-functions, even though the +implementations of those are likely to be different. + +The anachronism of casting a bound pointer-to-member-function to a normal +pointer (which is similar to the processing done by an +``eok_points_to_pm_call`` to determine the function to call) is rendered as an +``eok_virtual_function_ptr`` operation. + +In ``pcc`` mode and in some Microsoft and GNU C++ modes, certain casts to +like-sized types (like ``int`` to ``unsigned int``) leave a result that is +still an lvalue. For these cases, the lvalue is cast to the appropriate type +using the ``eok_lvalue_cast`` operator. The result is still an lvalue. + +The C++ ``dynamic_cast`` operator is rendered as an ``eok_dynamic_cast`` +(pointer or handle case) or ``eok_ref_dynamic_cast`` (reference case), but only +for cases that require runtime processing. The rest are rendered as ordinary +casts. + +Casts to ``bool`` are rendered as an ``eok_bool_cast``, which has the same +effect as a "``!= 0``" test. + +The ``eok_lvalue_adjust`` operator adjusts the type of a glvalue. Its operand +is a glvalue, and its result is a glvalue for the same object but with a +different type. + +The ``eok_class_rvalue_adjust`` operator adjusts the type of a class prvalue. +It is limited to adjusting the cv-qualifiers of the type. Its operand is a +class prvalue, and its result is the same value with a different type. When +``LOWER_CLASS_RVALUE_ADJUST`` is TRUE, IL lowering will rewrite these +adjustments by taking the address of the class rvalue, casting the pointer to +the proper type, and indirecting to get back to a class object. + +Casts to reference types are represented as glvalue-to-glvalue operations. The +simplest cases are represented by the ``eok_ref_cast`` operator. The node type +is the underlying type of the reference, e.g., the node for a cast ``(T &)x`` +has type ``T``, not type ``T&``. The operand is a glvalue, and the result is a +glvalue for the same object but with the type ``T``. More complicated +reference casts that involve related-class adjustments are represented by +``eok_base_class_cast`` and ``eok_derived_class_cast`` operators operating on +class glvalues. Nodes that represent a cast to a reference type are marked +with the ``is_reference_cast`` flag. If several nodes are required (e.g., +multiple casts to base classes) only the topmost node will be marked. Note +that ``eok_ref_cast`` nodes are rvalueable, and when the ``is_lvalue`` flag is +cleared to indicate the presence of an lvalue-to-rvalue conversion the node +type becomes the cv-unqualified type (for non-class lvalues) or pointer-to the +lvalue type (for function lvalues). That means, for a function type ``F``, a +cast to ``F&`` with an included lvalue-to-rvalue conversion is represented by a +node with type ``F*``. + +Casts to rvalue reference types are similarly represented by ``eok_ref_cast``, +``eok_base_class_cast``, and ``eok_derived_class_cast`` nodes. They are marked +with the ``is_rvalue_reference_cast`` flag in addition to the +``is_reference_cast`` flag. Although in the C++ language such reference casts +take an rvalue as their operand, in the IL the operand is always converted to a +glvalue and then cast. The node or nodes that do the cast are then exactly the +same as those that would be used for an lvalue reference cast. The final +(topmost) cast node will always be an ``eok_ref_cast`` node, and it will have +``is_lvalue`` FALSE to indicate the result is an rvalue (unless the result +needs to be converted back to an lvalue for some reason). + +Assignments +----------- + +There are assignment operators for integral types, fixed-point types, floating +types, classes (bitwise copy, or C ``struct`` assignment), pointers, and +pointers-to-members. + +There is also a block-copy assignment, ``eok_bassign``, which is only generated +by IL lowering and inside front-end-generated assignment operator functions, +and is needed to do bitwise copies of arrays when copying classes. It is +unusual in that its second operand is in lvalue form and its result type is +``void``. + +In C++, assignment operators can return lvalues instead of rvalues. Such cases +are indicated by the ``returns_lvalue_instead_of_usual_rvalue`` flag in the +expression node. The expression type matches the type of thing returned (i.e., +it matches the first operand's type). The same flag is used for prefix ``++`` +and ``--`` and the "``?``" and "``,``" operators when they return an lvalue. +When that flag is set, ``is_lvalue`` will also always be set as well (in other +words, they are not rvalueable). + +Compound Assignments +-------------------- + +In cases where a compound assignment operator (e.g., ``+=``) is applied to +operands of two different types, the right side operator will be cast as +necessary to the type of the operation (as it would be for other operators). +The left side operand (the destination, an lvalue), however, is left in its +original type, which is also the type of the entire expression. The back end +must provide a cast of the value of the left operand to the operation type +(generally the type of the right operand, but see below) before performing the +operation on the operands. For example: in ``i-=f`` (``i`` an ``int``, ``f`` a +``float``), the back end must provide the cast of ``i`` to ``float`` before +doing the subtraction; the operation type is ``float``; the result type (and +the type of the expression node) is ``int``. + +As mentioned above, the operation type for the operation is generally the right +operand type. There are two exceptions in which the underlying type of the +left operand is the operation type: shift assignments (``<<=`` and ``>>=``) and +pointer ``+=`` and ``-=`` (for those cases, the right operand is not cast to +the operation type). Fixed-point ``+=``, ``-=``, ``*=``, and ``/=`` are yet +more complicated; the function ``compound_assignment_operation_type`` should be +called to determine the operation type for those (it also works for all the +simpler cases). + +GNU vector cases are even weirder, as no attempt is made to bring the operands +to a common type. + +Binary Conditional Operator +--------------------------- + +In some configurations, the front end supports a GNU extension known as the +"binary conditional operator". The operator has the form ``expr1``\ ``?``\ +``:``\ ``expr2`` (i.e., similar to the regular conditional operator, but with +an omitted middle operand). Such expressions result in the value of ``expr1`` +if ``expr1`` converted to a boolean is true, or the value of ``expr2`` +otherwise. In the IL, this is represented by the usual ``eok_question`` +operator, but with the flag ``is_gnu_two_operand_question_mark`` set to TRUE. +The expression includes a synthesized second operand, which may use an +``enk_reuse_value`` expression node to reuse the value of the first operand +without evaluating it a second time. + +Calls +----- + +The normal call is rendered as an ``eok_call`` operation. The first operand +gives the address of the routine to call, and the rest of the operands are the +arguments for the call. + +For nonstatic member function calls, the operation is ``eok_dot_member_call`` +(for calls in the ``x.f()`` form) or ``eok_points_to_member_call`` (for calls +in the ``p->f()`` form). The first operand is the routine address (as a normal +pointer, not a pointer-to-member); the second operand is the selector object (a +class glvalue or prvalue for ``eok_dot_member_call``, or a pointer to a class +object for ``eok_points_to_member_call``). The remaining operands are the +arguments to the call. In either case, a call with virtual semantics is +indicated by the ``is_virtual_call`` flag in the expression node. + +For pointer-to-member-function calls, the operation is ``eok_dot_pm_call`` (for +calls in the ``(x.*pmf)()`` form) or ``eok_points_to_pm_call`` (for calls in +the ``(p->*pmf)()`` form). The first operand is the pointer-to-member-function +(i.e., a value of pointer-to-member-function type, not a normal pointer type); +the second is the selector object (a class glvalue or prvalue for +``eok_dot_pm_call``, or a pointer to class for ``eok_points_to_pm_call``); the +rest are the actual arguments, as above. + +If a routine has default arguments, the front end will supply the default +expressions if no explicit arguments are provided. The back end need not do +any special handling. + +If a parameter of class type must be passed by using a copy constructor, a call +of the copy constructor into a temporary will be generated on the calling side. +Somewhat arbitrarily, the ``enk_temp_init`` node for that is marked as an +lvalue. + +For routines that return a class object via a copy constructor, the call will +always be immediately underneath a ``dik_call_returning_class_via_cctor`` +dynamic initialization entry. The entity being initialized by the dynamic +initialization entry should be taken as the destination for the copy +constructor call. (IL lowering makes this explicit.) + +Note that uses of operator functions and conversion functions are rendered as +routine calls even through they use operator syntax or are implicit in the +source program. Constructor and destructor "calls" generally only show up in +dynamic initialization entries, and not as standard calls in expressions. + +Inlining is considered to be a back end issue. The front end does not do +inlining of calls. IL lowering optionally offers a limited form of inlining, +but it's intended only for those who have no better alternative. + +Returns +------- + +The ``stmk_return`` statement is used to represent all returns, whether +explicitly written by the programmer or generated by the front end. In +addition to the expected + +.. code:: c++ + + return; + return expr; + +(which are distinguished by a NULL or non-NULL ``expr`` pointer), there is also +a special form of return used for returns in routines that return a class value +by calling a copy constructor. For those, the ``stmk_return`` statement has a +pointer to a dynamic initialization entry, which indicates the initializing +operation to be done to return the class object. IL lowering implements this +by having the caller pass an extra argument that provides the address at which +the class object should be placed, and having the called routine call the copy +constructor using the implicit parameter as its destination address. + +Pointers to Members +------------------- + +Pointer-to-member types are represented as an abstraction in the unlowered C++ +intermediate language. It is up to IL lowering or a back end to translate them +into a particular implementation. Typically, pointers to data members are +implemented as a small integral offset (the offset of the member within the +class) and pointers to member functions are rendered as a structure (see the +ARM, 8.1.2.c). + +Pointer-to-member types are represented by a ``tk_ptr_to_member`` type entry. + +Pointer-to-member constants are represented by a constant entry of kind +``ck_ptr_to_member``. These represent source constructs like ``&A::x``, +meaning some sort of representation of the location of ``x`` in a class object +of type ``A`` (not a pointer to that member in a specific object, but rather a +representation of how to find that member in an arbitrary entity of that +class). + +Operands of pointer-to-member type can be assigned (``eok_assign``) and +compared (``eok_eq`` and ``eok_ne``). They can also be cast to base or derived +classes (``eok_pm_base_class_cast`` and ``eok_pm_derived_class_cast``). + +Temporary Initialization +------------------------ + +The ``enk_temp_init`` node is used to introduce a temporary in the middle of an +expression. It points to a dynamic initialization entry and an expression. +The initialization indicated in the dynamic initialization entry is performed +on the temporary, and then the temporary is returned as the value of the +``enk_temp_init`` node, as an lvalue, xvalue, or prvalue. Any destruction +indicated in the dynamic initialization entry must be done to the temporary at +the end of the object lifetime to which the dynamic initialization is bound. + +Condition Declarations +---------------------- + +In ``if``, ``while``, ``for``, and ``switch`` statements in C++, the expression +tested can be a condition declaration. For example: + +.. code:: c++ + + if (float x = f()) { ... } + +This is represented in the IL as an expression node of kind ``enk_condition``. +The condition has its own associated scope, which contains just the one +variable, and which wraps around the statement. Note that the initializations +for conditions in loops are done each time around the loop; if destruction is +also required, it too must be done each time around the loop. + +New and Delete +-------------- + +A ``new`` operator allocates storage and optionally initializes it. It is +represented by an ``enk_new_delete`` expression node. The supplement to that +node provides information about the ``new`` routine to be called, the arguments +for that call, and optionally a dynamic initialization entry that describes any +initialization to be done. If the allocation fails (i.e., the ``new`` routine +returns NULL), the initialization is not done. + +A ``delete`` operator deallocates storage after optionally calling a +destructor. It is represented by an ``enk_new_delete`` expression node. The +supplement to that node provides information about the ``delete`` routine to be +called, the pointer to the object to be deleted, and optionally a dynamic +initialization entry that describes destruction to be done. + +In both the ``new`` and the ``delete`` cases, the routine indicated in the +new/delete supplement may be NULL to indicate that the allocation or +deallocation should be done by the constructor or destructor. The dynamic +initialization entry in those cases indicates the appropriate constructor +or destructor. This alternative is controlled by configuration options +``NEW_CAN_BE_FOLDED_INTO_CTOR`` and ``DELETE_CAN_BE_FOLDED_INTO_DTOR``, +which must be true if assignment to "``this``" (an anachronism) is +supported, because the constructor or destructor must have control of +allocation and deallocation in that case. + +When a ``delete`` contains the count of array elements (an anachronism), the +expression between ``[]`` is scanned and thrown away; it does not appear in the +IL. + +The C++/CLI ``gcnew`` operator is represented by an ``enk_gcnew`` expression +node. For CLI array cases, the supplment provides both the bound sizes +(whether explicitly specified or determined from the size of the initializer) +and an initializer aggregate for the element values. + +Lambda Expression +----------------- + +A lambda expression -- which produces a temporary "closure object" of a +class type with an ``operator()`` member -- is represented by an +``enk_lambda`` expression node. Such a node points to a supplement entry +of type ``a_lambda`` and to an ``a_dynamic_init`` entry describing the +initialization and (if applicable) the destruction of the temporary +"closure object" resulting from the expression. The ``a_lambda`` entry +describes the static properties of the lambda expression, such as the local +variables it captures (and how they are captured), the closure type, +relevant source positions, etc. + +Throw Expression +---------------- + +A ``throw`` expression is represented by an ``enk_throw`` expression node. It +points to a supplement that points to a dynamic initialization entry that +describes the object to be thrown (or rather, how to make a copy of it, since a +copy is what's actually thrown); the supplement pointer is NULL in the case of +a "rethrow". + +Sizeof +------ + +When a ``sizeof`` operator cannot be evaluated at compile time (for instance, +when it is applied to a variable length array), an ``enk_sizeof`` expression +node is put out. Such nodes are also used to represent dependent ``sizeof`` +expressions in prototype instantiations. + +typeid +------ + +The ``typeid`` operator is represented by an ``enk_typeid`` expression node. +It points to the type whose type information is wanted. For cases that require +runtime type determination (e.g., ``typeid(*p)`` where ``p`` points to a +polymorphic class type), there is also a pointer to an expression whose dynamic +type is to be determined at runtime. + +``enk_typeid`` is also used for the C++/CLI *X*\ ``::typeid`` feature. That's +indicated by the ``is_cli_typeid`` flag. The result value in that case is a +handle to a ``System::Type`` entry. + +.. _il-vla-dealloc: + +VLA Deallocation +---------------- + +In C mode, the front end may generate ``enk_vla_dealloc`` nodes to indicate +where VLAs should be deallocated. Such nodes may also be created when lowering +C++ IL for VLAs (when ``DO_IL_LOWERING`` is TRUE). The nodes are eliminated +from the IL altogether (both in C and C++ modes) if +``LOWER_VARIABLE_LENGTH_ARRAYS`` is TRUE; the nodes are translated to calls +into the run-time support library. + +Parameters +---------- + +When an identifier in an expression refers to a parameter, the resulting IL is +an ``enk_variable`` node if the parameter is referenced in the body of a +function. However, it is possible to refer to parameters in expressions that +appear *outside* the function body. For example, in C++11, a function template +declaration might be as follows: + +.. code:: c++ + + template auto f(T p)->decltype(*p); + +Such uses always appear in unevaluated contexts and are represented with +``enk_param_ref`` nodes, which, like ``enk_variable`` nodes, are rvalueable. + +An ``enk_param_ref`` node doesn't point directly to IL representing a +parameter (e.g., ``a_param_type`` entries) because such a pointer might +become invalid when, e.g., two function types are combined through +``composite_routine_type``. Instead, the parameter is represented by two +integers: The parameter position in its enclosing parameter list, and the +"level" of the parameter list relative to the point of reference (function +declarators may be nested and an inner declarator may refer to a parameter +of an enclosing declarator). + +Fixed-point operations +---------------------- + +Operations on fixed-point values are represented using the usual expression +operators (``eok_negate``, ``eok_post_incr``, ``eok_add``, ``eok_divide``, +``eok_eq``, ``eok_assign``, etc.). For mixed-type arithmetic (i.e., operations +involving two different fixed-point types, or a fixed-point type and an integer +type), these operators are different from most of the other (more common) +operators in that their operands are not converted to a common type. For +example, when adding a ``short int`` to a ``long _Accum``, the operator is +applied directly to the unconverted operands without "usual arithmetic +conversions." A back end is then responsible for performing the operation with +maximum precision and converting the result to the result type indicated in the +operator expression node. This arrangement is necessary to meet the +requirements of the Embedded C extensions (ISO/IEC TR 18037). + +Note that while mixed-type fixed-point arithmetic does not in general attempt +to convert the operands to a common type, a conversion from unsigned to signed +may be applied if one operand is signed and the other not. Furthermore, an +operation involving a fixed-point operand and a floating-point operand is a +floating-point operation: The fixed-point operand is converted to a +floating-point type. + +.. _parentheses: + +Parentheses +----------- + +Parentheses are represented in the IL as expression operation nodes with an +operator of ``eok_parens``. Those are not usually generated; ``PARENS_IN_IL`` +must be set to TRUE to request them. When that flag is TRUE, each pair of +parentheses in a source program expression is represented by an ``eok_parens`` +node in the IL for the expression. If ``EXTRA_SOURCE_POSITIONS_IN_IL`` is also +TRUE, those expression nodes will include position information on the opening +and closing parenthesis tokens. + +``eok_parens`` nodes are not used or allowed in versions that use IL lowering. +They are intended mostly for source-analysis applications. Note that enabling +``PARENS_IN_IL`` should not be done without reason, because it complicates the +code that deals with expressions. Every bit of code that wants to check for a +specific operator in an expression may have to check for and strip parentheses +off the expression before doing the check. That can be done by calling +``skip_parens``, but it's hard to always remember to do that. (This problem is +very similar to the ``skip_typerefs`` problem for types, and that is widely +known as a pain and a source of bugs.) + +Fold Expressions +---------------- + +A C++17 fold-expression like "``(ps + ... + 1)``" where ``ps`` contains an +unexpanded parameter pack is represented in generic template contexts (i.e., +"prototype instantiations") using an ``enk_fold`` node. The expansion of the +construct (in real template instantiations), however, uses the ordinary binary +operator representations. For example, if ``ps`` expands to a sequence of +integer parameter variables, the expanded representation will involve a tree of +``enk_operation``/``eok_add`` nodes. + +Boxing and Unboxing +------------------- + +C++/CLI boxing and unboxing is implemented by several operators: + +* | ``eok_box`` takes an operand of a value type (e.g., ``int``) and returns a + handle to a boxed version of the value on the CLR heap (e.g., handle to + ``System::Int32``). +* | ``eok_handle_to_box`` has the same runtime meaning as ``eok_box``, but is + generated for source uses of the unary ``%`` operator applied to a value + class. +* | ``eok_unbox`` takes an operand that is a handle to a boxed value class or + boxed enum and returns an lvalue (in place on the heap) or rvalue (copied) + for the contained value, depending on the ``is_lvalue`` flag. +* | ``eok_unbox_lvalue`` is similar, but the operand is an lvalue for the value + class or boxed enum. It is always compiler-generated, e.g., on top of an + ``eok_indirect`` applied to a handle to a value class. + +Pragmas +======= + +A ``#pragma`` directive may be represented in the IL by an entry of type +``a_pragma``, which appears on a linked list pointed to by the ``pragmas`` +field of an IL scope entry. It includes a pointer (see the ``entity`` field) +if it is specifically associated with a statement, routine, etc.; the entity +does not point back, but rather has its ``has_associated_pragma`` flag set, +since more than one pragma entry may be associated with a given IL entity. For +additional information, see :ref:`pragmas-and-attributes`. + +.. _anonymous-unions: + +Anonymous Unions +================ + +Anonymous unions are unions that have no name, either for the union type or for +the singular instance of the union. The names of the members of the union are +promoted into the surrounding context. There are two kinds of anonymous +unions: + +* | Anonymous unions within classes, as in + + .. code:: c++ + + class A { + union { + int i; + float j; + }; + } x; + + | Here, the fields of the anonymous union are promoted into the surrounding + class, so one can refer to ``x.i``. +* | Anonymous unions as variables, as in + + .. code:: c++ + + union { + int i; + float j; + }; + + | Here, ``i`` can be used as if it were a variable. Such constructs can + appear at file and namespace scope and within function and block scopes. + +For the first (field) case, the IL reflects the source form: class ``A`` will +contain an unnamed field whose type is an unnamed union, which in turn contains +the fields ``i`` and ``j``. A reference like ``x.i`` appears as a selection of +``i`` directly from ``x``. By looking at the field for ``i``, one can tell +that it is a member of an anonymous union, and infer the additional field +selection. (IL lowering adds the extra field selection.) + +For the second (variable) case, there will be an unnamed variable whose type is +the unnamed union. A reference like ``i`` appears as a selection of ``i`` out +of the unnamed variable, so it is more explicit (and less like the source +program) than the field case. + +Virtual Function Tables +======================= + +There are no "virtual function tables" *per se* in the unlowered IL. There is +only the information that is part of the definition of virtual functions in the +language: + +* | Functions are marked as being virtual, including when they are implicitly + virtual because they override a virtual function from a base class. + Virtual functions are assigned ordinal numbers within a class, which can be + used as their indexes into a virtual function table. +* | Calls to virtual functions use a special operator, ``eok_virtual_call``. +* | Base class entries contain information on virtual function overrides, i.e., + on which virtual functions of a base class are overridden by virtual + functions in derived classes (either the one the base class entry is + attached to or some class on the derivation path between the base class and + that one). + +One can generate a virtual function table for ``A`` in ``B`` by scanning the +member functions of ``A`` looking for virtual functions, along with the +override list for base class ``A`` of ``B``. If a function in ``A`` does not +appear on the override list, the function from ``A`` goes into the virtual +function table. Otherwise, the function from the override list goes into the +virtual function table. More detail can be found in the code in IL lowering +that generates virtual function tables. + +.. _il-c99-features: + +C99 features +============ + +The C99 IL extensions over C89 are as follows: + +* | For variable-length arrays (VLAs), the front end generates two additional + statement kinds (``stmk_set_vla_size`` and ``stmk_vla_decl``) and + optionally one additional expression node kind (``enk_vla_dealloc``; see + :ref:`il-vla-dealloc`). Types and variables are also marked as being VLAs + when appropriate. This feature can be enabled also in C89 and C++ modes + (by ``--vla``), and is controlled by the macro ``VLA_ALLOWED`` (which is + set by default if ``C99_IL_EXTENSIONS_SUPPORTED`` is set). If + ``LOWER_VARIABLE_LENGTH_ARRAYS`` is TRUE, the VLA-specific constructs are + eliminated from the IL (this requires the run-time support library). +* | For compound literals, an ``enk_temp_init`` node is generated. Such a node + generates a temporary, and is otherwise used only in C++ mode. This + feature can be enabled also in C89 mode (by ``--compound_literals``), and + is controlled by the macro ``COMPOUND_LITERAL_ENABLING_POSSIBLE`` (which is + set by default if ``C99_IL_EXTENSIONS_SUPPORTED`` is set). C99 lowering + eliminates compound literals by rewriting them as initialized generated + variables. +* | For designators in initializers, ``ck_designator`` constants are + generated in aggregate initializers. This feature can be enabled also + in C89 mode (by ``--designators``), and is controlled by the macro + ``DESIGNATED_INITIALIZER_ENABLING_POSSIBLE`` (which is set by default + if ``C99_IL_EXTENSIONS_SUPPORTED`` is set). If + ``LOWER_DESIGNATED_INITIALIZERS`` is TRUE (which it is by default if + C99 lowering is done), designators are almost completely eliminated; + they remain only for initializations of members other than the first in + unions, which are not possible in C89. +* | For ``_Bool``, the type is represented as in C++ (the ``bool_type`` flag is + set in the integral type). C99 lowering eliminates ``_Bool`` by rewriting + the type as a typedef to the underlying integer type. +* | For complex and imaginary types, there are new type kinds (``tk_complex`` + and ``tk_imaginary``), new constant kinds (``ck_complex`` and + ``ck_imaginary``), and some new operator kinds (e.g., ``eok_jfadd`` and + ``eok_jmultiply``) and conversions. If ``LOWER_COMPLEX`` is TRUE, C99 + lowering rewrites complex types as structs and imaginary types as + floating-point types, rewrites the constants as aggregate or floating-point + constants, and rewrites the operators and conversions as runtime routine + calls. +* | For flexible array members, the last member of a struct type may have an + array type with an unknown bound. No lowering is done. +* | For non-constant expressions in aggregate initializers, the aggregate + constants contain ``ck_dynamic_init`` constants, as in C++. C99 lowering + rewrites those as executable code. +* | For inline functions, the function is marked with the ``is_inline`` and + ``suppress_inline_body`` flags, as in C++. If ``MINIMAL_INLINING`` is + TRUE, C99 lowering replaces inline function calls with the expansions where + possible (as is done in C++). +* | For ``long``\ ``long``, there are two new integer kinds (``ik_long_long`` + and ``ik_unsigned_long_long``) and new constants of these kinds. This + feature can be enabled also in C89 mode and in C++ mode, and is controlled + by the macro ``LONG_LONG_ALLOWED`` (which is set by default if + ``C99_IL_EXTENSIONS_SUPPORTED`` is set). No lowering is done. +* | For mixed statements and declarations, the statements and declarations + appear intermixed in the statement list of a compound statement, as in C++. + No lowering is done. + +Entry Prefix +============ + +Each IL entry is preceded by a prefix, which is not part of the IL entry proper +but contains information about the entry that is useful to tree walking +routines and the like: + +* | Is the entry allocated in the file-scope memory region? +* | Has the entry been encountered yet on a tree walk of the IL? +* | Has the entry been encountered yet by IL lowering? +* | What entry number has been assigned to the entry (for the alternate IL file + format)? + +This prefix is allocated in space preceding the beginning of the entry (that +is, one has to do special address arithmetic to get to the prefix; see the +macro ``il_entry_prefix_of``). Some of the flags mentioned above are present +only when required by the front end configuration. + +Orphans +======= + +Type entries and static variables that are local to a function require some +special handling. All type entries and all static variables are allocated in +the file scope memory region. However, types and static variables that are +local to a function are placed on the types and static variables list of a +function or block scope. Those are unusual lists: the scope entry (in a +function scope memory region) points to a list that is entirely in the file +scope memory region. Yet, the entries pointed to are not really part of the +file scope. They might, in fact, not be referenced from anywhere except the +function scope memory region. Such entries are "orphaned" in the file scope: +their parents can be processed, written out, and removed from memory, but the +children remain in the file scope, unattached to the rest of the file scope IL +tree. + +A similar problem occurs when an IL entry such as a type is allocated in the +file scope memory region because it might be shared. If the entity is +referenced only from function scope memory regions, it too will be an orphan. + +Orphans are a problem if one wants to process the intermediate language on a +per-memory-region basis. One needs to be able to find all of the orphans when +processing the file scope memory region. There are two mechanisms that help +with this: + +* | ``il_header`` points to a list of entries of type + ``a_scope_orphaned_list_header``. Each entry on this list holds a copy of + the local type and static variable list pointers for a function or block + scope that has such entries. The ``a_scope_orphaned_list_header`` entries + are allocated in the file scope memory region, so they can be used to find + all such lists if the function and block scopes are no longer in memory. + | + | See the routine ``add_scope_orphaned_il_lists``. +* | Each file-scope IL entry is preceded by space for a pointer. (This space + precedes the entry prefix.) The pointer is used to chain potential orphans + onto a list of entries of the same kind headed by an element of the global + array ``orphaned_file_scope_il_entries``. Those lists can be traversed + after processing the file scope to find entries that might otherwise be + lost. Note that entries are placed on the list if they are potential + orphans, i.e., if they are allocated in the file scope memory region and + are referenced from a function scope memory region. Most of the entries on + the lists will not be orphans, but all orphans will appear on the list. + | + | See the routine ``add_orphaned_file_scope_il_entry``. + +All orphan processing is included only if needed. It is needed if IL lowering +is done or if an IL file is written. + +Relationship of the IL and the Symbol Table +=========================================== + +The symbol table of the front end is not part of the intermediate language +structure and is not passed to the back end. It is really mostly a name lookup +mechanism, which one can use to look up a name to get to the associated +intermediate language entry. By the time a back end receives the IL, all +references to entries are simply pointers to the proper entries, and therefore +no name lookup mechanism is needed. + +The symbol table also contains some information that is only needed in the +front end (for error checking or searching) and is not passed to the back end, +or information that has no IL representation (for example, symbol entries for +keywords). + +The symbol table also always reflects the true C and C++ idea of name scoping, +which may not exactly match the IL representation. For example, if we have the +declaration ``extern int xx`` in two scopes, each declares a name ``xx`` whose +visibility is limited to the scope in which it is declared, but the object (an +integer variable) associated with the name exists over the entire program. +During the front end compilation process there would be two different symbol +entries for ``xx`` in two different scopes, but in the intermediate language +there would be only one variable entry for ``xx``, and it would appear at the +file scope level. All references to either ``xx`` of the source program would +point to that one entity, and would not indicate which of the original ``xx``\ +s was referenced. + +.. _templates-in-the-il: + +Templates +========= + +The front end generates IL for instances of templates. For example, class +types are generated for instances of class templates and routines are +generated for instances of function templates. A back end can view a +template as a sort of powerful macro expanded by the front end, and can +deal with the generated IL for instances exactly as if the instances were +non-template classes and routines. A code generator need not, in general, +care that the source program contained templates. + +Each template declaration or definition in the source program is +represented by an IL entry of type ``a_template``. A list of those is +attached to the ``templates`` field of ``a_scope``. A separate +``a_template`` entry is included for each declaration or definition of a +given template (i.e., there can be more that one ``a_template`` entry +associated with a single template; if there is, the first such entry is the +canonical one, and is used when referring to the template itself as opposed +to a given declaration of the template). When the macro +``ALL_TEMPLATE_INFO_IN_IL`` is set to TRUE, ``a_template`` entries are also +generated for member functions, static data members, and member classes +nested in class templates. If ``RECORD_TEMPLATE_STRINGS`` is TRUE, the +``a_template`` entry contains a pointer to a null-terminated string that is +a textual representation of the template declaration or definition. + +The generated IL for an instance generated from a template does preserve some +indications of the fact that the entity came from a template: + +* | The type entry variant for class/struct/union has an ``is_template_class`` + flag that is set for template classes. If the class is an instance of a + template, rather than a member of a class that is a template, the class + type supplement's ``template_arg_list`` field gives the list of template + arguments for the template. +* | The routine entry has an ``is_template_function`` flag that is set for + template functions. If the function is an instance of a template, rather + than a member of a class that is a template, the routine entry's + ``template_arg_list`` field gives the list of template arguments for the + template. +* | The variable entry has an ``is_variable_template`` flag that is set for + template variables and template static data members. +* | The variable and routine entries have instantiation information flags. + +Template argument lists are represented by a list of ``a_template_arg`` +entries. Each entry points to an argument value: an IL type for a type +template argument, an IL constant for a nontype template argument, or an +``a_template`` entry for a template template argument. + +More information about templates is available when the macro +``ALL_TEMPLATE_INFO_IN_IL`` is set to TRUE. With that setting: + +* | The ``assoc_template`` field (in a class type supplement, routine, or + variable) points to the (canonical) ``a_template`` entry for the associated + template. +* | A ``canonical_template`` field of ``a_template`` points the canonical + ``a_template`` entry for the associated template. +* | A ``definition_template`` field of ``a_template`` is set in the canonical + entry to point to the ``a_template`` entry associated with the template + definition (if any). In other entries it is NULL. + +When ``ALL_TEMPLATE_INFO_IN_IL`` is TRUE and, in addition, the variable +``prototype_instantiations_in_il`` is TRUE, the IL tree includes IL for +templates themselves (as opposed to IL for instances of templates). This IL is +produced by doing a "prototype instantiation" of the template, which means +doing syntax and (partial) semantic analysis of the template definition without +the use of actual template argument values. Of necessity, such analysis is +incomplete; the meaning of certain constructs cannot be determined until the +actual template argument values are known. Therefore, the IL for prototype +instantiations can contain special generic operators and variants of other IL +constructs that do not appear in normal IL (e.g., ``eok_lvalue``). + +Prototype instantiations of classes are always done. Prototype instantiations +of functions are done when the variable ``nonclass_prototype_instantiations`` +is TRUE (see the command-line option ``--parse_templates``). The variable +``prototype_instantiations_in_il`` controls whether prototype instantiations +are *preserved* in the IL. If the flag is FALSE, the instantiations -- if done +-- are thrown away and not linked into the IL tree. If the flag is TRUE, the +prototype instantiations are done *and* preserved, and + +* | The ``a_template`` entry for each template poimts to IL for its prototype + instantiation: a class type for a class template, a routine for a function + template, or a variable for a variable template or static data member + template. +* | The ``a_template`` entry points to an entry of type ``a_template_decl``, + which provides information about the template header (source position, + parameter list). The information on parameters is given by a list of + entries of type ``a_template_parameter``. (The pointer is NULL for + a_template entries for member functions, static data members and member + classes nested in class templates.) + +Note that when ``prototype_instantiations_in_il`` is TRUE and +``nonclass_prototype_instantiations`` is FALSE only class prototype +instantiations are included in the IL. + +While the front end is processing templates, it is convenient for it to be able +to generate IL versions of entities (like class members) that are not "real," +i.e., that exist only as part of some template abstraction that will never be +seen by the back end. For those cases, it is helpful to be able to represent +types and constants which are not known but which nevertheless have a certain +identity, e.g., they're derived from template parameters of a current template. +The ``tk_template_param`` type and the ``ck_template_param`` constant are used +for those cases. Likewise, a special ``a_template`` entry is created to +represent the unknown value of a template template parameter inside a prototype +instantiation. These entities will appear in the IL tree only inside prototype +instantiations. + +C++/CLI generics are represented as templates with an extra flag +(``is_generic_definition`` in both class types and routines). They can also +have additional constraint information, provided by entries of type +``a_generic_constraint`` and ``a_generic_constraint_clause``. + +Macros +====== + +If ``RECORD_MACROS_IN_IL`` is set to TRUE, entries of type ``a_macro`` are +created and added to the ``macros`` list of the IL header. The entries +contain a textual version of the macro definition (e.g., a string like +"``#define x(a) a+1``"), except for predefined macros like ``__LINE__`` and +``__FILE__`` whose replacement text varies from one invocation to the next. +The entries for these macros contain an empty (zero-length) text string +instead of a fixed definition. If a macro is redefined (to a different +string), there is another macro entry for the new definition. Macro +entries are also used to represent ``#undef`` directives. + +The front end can also be configured to maintain detailed information regarding +macro invocations. For instance, it is possible to determine the original +source position of text that appears in the expansion of a macro invocation. +This extra position information can be used to produce more-detailed diagnostic +messages regarding such text, and source analysis tools can more accurately +identify the positions and ranges associated with declarations, expressions, +and statements. It is also possible to determine the chain of macro +invocations that led to a particular macro expansion or to obtain a macro +invocation tree (similar to a function call tree) for an entire translation +unit. + +If ``FULLY_RESOLVED_MACRO_POSITIONS`` is TRUE, ``a_source_position`` has an +extra sequence/column pair, ``orig_seq`` and ``orig_column``. For text +appearing directly in the source, both pairs will indicate the same position. +For text that occurs in a macro expansion, however, +``orig_seq``/``orig_column`` will be the source position at which the text +originally appeared before being copied into the macro expansion -- either in +the definition of some macro or in the argument list of the top-level macro +invocation. (Regardless of the value of ``FULLY_RESOLVED_MACRO_POSITIONS``, +the ``seq``/``column`` pair for all positions in a macro expansion indicate the +initial position of the top-level macro invocation.) + +If ``MACRO_INVOCATION_TREE_IN_IL`` is set to TRUE, a flattened macro +invocation tree is kept in the file scope memory region. Because +variably-sized data is awkward to represent in the IL, the list of macro +invocation records is broken into fixed-size blocks of type +``a_macro_invocation_record_block``, each containing +``MACRO_INVOCATIONS_PER_BLOCK`` records, and these blocks are organized +into a binary tree to reduce the cost of accessing an arbitrary invocation +record. + +There is one record in the tree (of type ``a_macro_invocation_record``) for +each macro invocation that was performed. Each such record indicates the +parent invocation, the macro that was invoked, and the (original) source +position of the macro name that introduced the invocation. Furthermore, if +``EXTRA_SOURCE_POSITIONS_IN_IL`` is TRUE, the record will contain the +(original) ending position of the macro invocation (the last character of the +name of an object-like macro or the closing parenthesis in the invocation of a +function-like macro). + +In addition, when ``MACRO_INVOCATION_TREE_IN_IL`` is TRUE, +``a_source_position`` contains the index of the macro invocation record in +whose expansion that position occurs (or ``NO_PARENT_MACRO_INVOCATION`` if the +position refers to text that appears directly in source code). + +The ``macro_context`` field in ``a_source_position`` and +``parent_macro_index`` in ``a_macro_invocation_record`` enable +reconstruction of the stack of macro invocations that resulted in the text +at that position. Each macro invocation record is uniquely identified by +an index value of type ``a_macro_invocation_index``, so the macro +invocation stack can be traced simply by following the chain of +``parent_macro_index`` values. (An invocation of macro ``C`` is considered +to be a child of an invocation of macro ``P`` if ``C``'s invocation appears +in the argument list or the expansion of that invocation of ``P``.) + +For convenience in accessing macro invocation records by index, +``il_def.h`` defines the macro ``set_macro_inv_record_ptr_to_index(``\ +*root*\ ``,`` *index*\ ``,`` *mirp*\ ``)``, which sets a pointer *mirp* of +type ``a_macro_invocation_record_ptr`` to the address of the record at the +specified index, given the tree root (which is found in +``il_header.root_macro_invocation_record_block``). + +In addition to direct access into the tree by record index, it is possible to +scan the tree sequentially; the records are stored in the same order that the +invocations were performed during preprocessing. To facilitate reconstruction +of the invocation tree during such a traversal without the necessity of +maintaining a separate invocation stack, the array contains certain +"placeholder" records that do not denote macro invocations. Such records are +identified by a negative value (other than ``NO_PARENT_MACRO_INVOCATION``) for +the parent invocation. + +To understand the use of these placeholder records, consider two records +*M* and *N* reflecting successive macro invocations. If the parent +invocation of *N* is the same as that of *M*, the two invocations are +siblings and the transition from *M* to *N* implies no change to the +conceptual invocation stack. If the parent invocation of *N* is *M* +itself, then *N* is a child of *M* (i.e., invocation *M* is assumed to be +pushed onto the stack). Otherwise, a non-negative parent index in *N* is +assumed to be a single-level pop of the conceptual stack -- that is, the +parent of *N* is the parent of *M*'s parent. In all these cases, the +invocation records for *M* and *N* will be at consecutive indices. If, on +the other hand, the parent of *N* is a more remote ancestor of *M*, a +placeholder record will be inserted between *M* and *N* with a negative +parent index whose absolute value is the number of invocations to pop from +the conceptual stack in order to restore that remote ancestor to the top of +the stack. + +Attributes +========== + +C++11 ("standard"), GNU, and Microsoft ``__declspec`` attributes are +represented in the IL by entries of type ``an_attribute``. If such attributes +appear on a declaration, they are pointed to by the ``attributes`` field of the +corresponding entry's source correspondence; otherwise, a dedicated attributes +field is used (e.g., in ``a_param_type``). When +``RECORD_UNRECOGNIZED_ATTRIBUTES`` is TRUE, unrecognized attributes are +recorded in the IL with kind ``ak_unrecognized`` (when the macro is FALSE, +unrecognized attributes are not recorded and a warning is issued). All +attributes specified in the same "group" point to an entry of type +``an_attribute_group``. Empty groups contain a pseudo-attribute of kind +``ak_empty_attr`` (or more than one, for a GNU construct like +"``__attribute((,,,))``"). + +If an attribute includes an argument list, the corresponding attribute entry +points to a list of ``an_attribute_arg`` entries. An empty argument list -- as +in ``__attribute((nonnull()))`` -- is represented with an argument entry of +kind ``aak_empty``. Otherwise, the entries in the argument list represent a +constant (``aak_constant``), a type (``aak_type``) or an uninterpreted token +(``aak_token`` or ``aak_raw_token``). ``aak_token`` entries represent single +tokens that may be followed by other arguments separated by a comma. In +contrast, ``aak_raw_token`` entries represent one or more tokens including the +commas; a sequence of ``aak_raw_token`` entries is always followed by a +terminating ``aak_empty`` entry (used primarily to record the position of the +token that follows in the source -- this is useful for diagnostic purposes). +If an unrecognized attribute is followed by a non-empty argument list, that +list consists of ``aak_raw_token`` entries (including entries for any commas in +the list). E.g., the unrecognized C++ attribute ``[[ unrecog(x, y) ]]`` has +three ``aak_raw_token`` argument entries for "``x``", "``,``", and "``y``" +(followed by a ``aak_empty`` entry). + +Microsoft attributes (delimited by single brackets) are represented in the IL +by entries of type ``an_ms_attribute``. Depending on the configuration of the +front end, a given Microsoft attribute may be either "recognized" or +"unrecognized". All attributes include a string representation of the +attribute from the source. In addition, recognized attributes include an +argument list representing the arguments that were specified in the attribute +reference. + +Microsoft attributes that apply to function parameters are pointed to by the +param type entry. All other attributes are pointed to by the ``ms_attributes`` +field of an IL scope entry. Attributes that apply to a particular entity +include a pointer (see the ``entity`` field) to that entity. The entity does +not point back, but rather has its ``has_associated_attribute`` flag in its +source correspondence set. + +Properties +========== + +Microsoft properties come in two kinds: + +* | Old-style properties indicated by the ``__declspec(property(``... )) + attribute. The accessor functions are only loosely associated with the + property, by being named in the attribute. +* | New-style properties in C++/CLI, which begin with the "``property``" + context-dependent keyword. The accessor functions are declared as part of + the property declaration, in a form that looks vaguely like a nested class. + +In both cases, the IL has a description of the property declaration, so that is +retained in something close to the source form (that information is held in +``a_property_or_event_descr`` entry). However, also in both cases, references +to the properties are expanded by the front end, so they are not retained in +source form. A bit of source code like "``p``\ ``+=``\ ``1``" might be +expanded into a series of calls something like "call the get accessor for +``p``, call ``operator+`` on the fetched value and 1, and call the put accessor +to store the computed value." The generated IL contains some tags on various +nodes in the expansion that help source-analysis code recover the original +meaning, though in a cumbersome way. + +C++/CLI events are very similar to the new-style properties, in representation +and in the fact that references are expanded by the front end. + +Microsoft ``__if_exists`` blocks +================================ + +Representing ``__if_exists`` (and ``__if_not_exists``) blocks in the IL is +problematic because, although the Microsoft documentation describes the +contents of an ``__if_exists`` block as a statement, the Microsoft compiler +actually accepts any fragment of a statement or declaration in the block (as +does our front end in Microsoft mode). + +The front end provides a mechanism that can represent ``__if_exists`` blocks +that appear in class definitions, and which surround complete declarations of +the class. When an ``__if_exists`` appears in a valid location in a class +definition, an IL entry (``an_ms_if_exists``) and source sequence entry are +created for the start and end of the block. ``__if_exists`` blocks in other +scopes are not represented in the IL (but are still included in the textual +representation of templates). If an ``__if_exists`` appears in an invalid +context in a class definition, an error is issued. + +IL entries are only created for ``__if_exists`` blocks that appear in the +prototype instantiation of class templates and classes nested within class +templates. In non-template contexts, the ``__if_exists`` is simply evaluated +when it is encountered. + +IL Use Within the Front End +=========================== + +Some aspects of the IL are used only during the front end processing and are +not seen by back ends. + +Most of the primary table types have a kind used to represent errors (e.g., an +error constant, an error expression). These are used to replace parts of the +IL tree that contain errors. Since the back end is not run if there are +errors, a back end will never see these kinds of entries. + +There are also a few table kinds used for unknown entities (not known yet, but +not an error), for example the unknown type kind ``tk_unknown``. These are +replaced by actual kinds by the time a back end sees the IL. + +Constant expressions are generally folded to a single constant value and +the front end uses that folded value for its processing. In scanning +``1+2``, for example, the ``1`` and ``2`` will be folded into a constant +entry for ``3``, and that value will be used internally. The original +expression that was folded is generally preserved via the ``expr`` field of +``a_constant``. + +.. _il-extension-guide: + +How To Extend the IL +==================== + +Extending the intermediate language involves making a coordinated set of +changes in several files. Three kinds of changes are discussed below: + +* | adding a field to an existing IL entry (typically quite straightforward), +* | adding a new operator kind (usually also straightforward), and +* | adding a brand new IL entry (only a little more complicated). + +Note, however, that what is covered is the typical case. There may be +additional complications. And, of course, nothing of a general nature can be +said about how a field or entity is set and used or how it interacts with other +parts of the IL. + +Adding a Field to an Existing IL Entry +-------------------------------------- + +This is what you need to do to add a field *f* of type *T* to existing IL +entry *E* with ``an_il_entry_kind iek_``\ *e*: + +.. list-table:: + + * - | in ``il_def.h``: + - | Add *f* to *E*. + * - | in ``il_alloc.c``: + - | Initialize field *f* in the routine that allocates *E* objects. + * - | in ``il_display.c``: + - | Add code to display the value of *f*. This will typically appear + in a function called ``disp_``\ *e*, and the display will depend + on the type *T*. For example, ``disp_boolean`` will be called for + a flag, ``disp_ptr`` will be called if *T* is of type + pointer-to-IL-entry, and so forth. + +and in addition, if *T* is of type pointer-to-IL-entry: + +.. list-table:: + + * - | in ``walk_entry.h``: + - | In ``WALK_ENTRY_ROUTINE_NAME``, there will be a ``case`` clause + for ``iek_``\ *e* within the main ``switch`` statement. Here you + will usually need to add a call to ``walk_ptr`` or ``remap_ptr``. + (The latter is typically used if *f* is a secondary reference to + the object it points to, but ``walk_ptr`` can be used in any + case.) There are some special cases to look out for, however. For + example, if *f* points to a linked list, instead of ``walk_ptr`` + call either ``walk_list`` (if ``*``\ *T* uses a ``next`` pointer) + or ``walk_list_on_link_field``. + +If *f* is an addition to the ``a_type`` entry, update ``traverse_type_tree`` +accordingly. + +If *f* is an addition to the ``an_expr_node`` entry, update ``traverse_expr`` +accordingly. + +If *f* is an addition to the ``a_statement`` entry, update +``traverse_statement`` accordingly. + +If *f* is an addition to the ``a_dynamic_init`` entry, update +``traverse_dynamic_init`` accordingly. + +If *f* is an addition to the ``a_constant`` entry in its function as the +description of an initializer, update ``traverse_constant`` accordingly. + +Adding a New Operator +--------------------- + +Most expression nodes (``an_expr_node``) represent operations +(``enk_operation``) like additions, assignments, calls, casts, etc. Each of +these operation kinds is identified by an enumeration constant (``eok_add``, +``eok_call``, ...). To add a new operation kind, it is not sufficient to add +another constant; the following updates are also required: + +.. list-table:: + + * - | in ``il_def.h``: + - | Add a string constant to ``db_operator_names``. + * - | in ``il_display.c``: + - | Add a case for the new operator in ``disp_expr_operator_name``. + * - | in ``cp_gen_be.c``: + - | Update ``generated_precedence`` to cover the new operator. + * - | in ``il.c``: + - | Update ``lvalue_rvalue_test`` and ``operation_type_kind``, and if the + operator has side effects, also ``operation_has_side_effects``. + +Furthermore, if the operator may produce an lvalue (``is_lvalue`` is TRUE) or +xvalue (``is_xvalue`` is TRUE), additional functions must know about the new +operator kind: + +.. list-table:: + + * - | in ``il.c``: + - | ``is_rvalueable_node``, ``node_does_fetch``, and + ``operator_takes_lvalue_operand``. + * - | in ``exprutil.c``: + - | ``conv_prvalue_expr_to_glvalue``, and (if ``is_rvalueable_node`` + indicates that the operator is not "rvalueable") + ``conv_glvalue_expr_to_prvalue``. + +Finally, if the operator is an addressing operator, a few other routines +require updating: + +.. list-table:: + + * - | in ``folding.c``: + - | ``constant_glvalue_address`` and ``constant_prvalue_pointer``. + * - | in ``il_walk.c``: + - | ``traverse_addressing_subtree``. + +Adding a new expression node kind (new ``enk_...``\ variant) is harder. That +requires looking at all code that handles expressions, in particular switch +statements that case out on the expression kind, and making appropriate +changes. If the new variant includes an embedded type, be sure to update +``examine_expr_for_dependent_type``. + +Adding an IL Entry +------------------ + +This is what you need to do to add an IL entry of ``struct`` type *X*, +where *X* is a name with the form ``a_``\ *xxx*: + +.. list-table:: + + * - | in ``il_def.h``: + - | Add the definition of *X*. Add ``iek_``\ *xxx* to the enumeration + ``an_il_entry_kind``. Update the initialization of + ``il_entry_kind_names`` and ``sizeof_il_entry``. + * - | in ``walk_entry.h``: + - | Add a ``case`` clause for ``iek_``\ *xxx* in + ``WALK_ENTRY_ROUTINE_NAME``. Add calls to process orphans in + ``WALK_ORPHANED_ENTRY_ROUTINE_NAME``. + * - | in ``il_walk.c``: + - | Add calls to process orphans in + ``remap_first_ptr_of_orphaned_file_scope_entry_array`` and in + ``remap_last_ptr_of_orphaned_file_scope_entry_array``. + * - | in ``il_alloc.c``: + - | Add an ``alloc_``\ *xxx* routine. If the entity should always be + allocated in the file scope memory region, call ``alloc_il``; to use + the current memory region, call ``alloc_cil``. (Do not use + ``alloc_fe`` for entities in the IL.) If the entity is a supplement to + some other entry (to keep down the size of the containing entry), the + space for the supplement should be allocated when the containing entry + kind is set to that variant. See examples in ``set_type_kind``. In + such cases, you should also change the copy routine for the containing + entity so that it copies the supplement as well. See ``copy_type`` + and ``copy_node`` for examples. If you want to track the number of + entities of type *X* that are allocated and how much space they use, + define a static variable ``num_``\ *xxx*\ ``es_allocated``, initialize + it in ``il_alloc_init``, register it in ``il_alloc_one_time_init`` in + case precompiled headers are used, increment it in ``alloc_``\ *xxx*, + and display it by adding code to ``show_il_alloc_space_used``. + * - | in ``il_display.c``: + - | Add a ``disp_``\ *xxx* routine. Add a ``case`` clause for + ``iek_``\ *xxx* in ``disp_entry``. If the entity is a supplement, + add its kind to the list at the beginning of ``disp_entry`` (a + list of entity kinds for which the entity is displayed with the + containing entity), and put the call of ``disp_``\ *xxx* in the + clause for the containing entity. + * - | in ``il.c``: + - | If the entry might be an orphan (allocated in the file-scope memory + region, pointed to from something in a function-scope memory region, + but not pointed to from anything in the file-scope memory region), add + the entry kind as a case in + ``f_possibly_add_orphaned_file_scope_il_entry``. + +This is what is required in the general case, but there are potentially many +other issues to consider. For example, if *X* has a substructure of type +``a_source_correspondence``: + +.. list-table:: + + * - | in ``il_alloc.c``: + - | Be sure ``alloc_``\ *xxx* calls ``set_default_source_corresp``. + Add a ``case`` clause for ``iek_``\ *xxx* in + ``source_corresp_for_il_entry``. + * - | in ``il_display.c``: + - | Add a ``case`` clause for ``iek_``\ *xxx* in ``disp_ptr``. + +If *X* is added to ``a_class_type_supplement``, and the field is one that is +meaningful even if the class does not have a definition: + +.. list-table:: + + * - | in ``il.c``: + - | If you use "needed" flags (``MAINTAIN_NEEDED_FLAGS`` is TRUE), modify + ``turn_class_definition_into_declaration`` to copy *X* when clearing + the class type supplement. + +.. [#f1] The obvious exception to that -- the reference from the interface to a + routine down to the function scope that defines its implementation -- + is handled as a special case. What is stored in the interface is not + a pointer, but rather a function definition number, which can be + looked up in ``function_def_table`` in ``il_header`` to get a pointer + to the scope entry if it is in memory. +.. [#f2] Why do that? Because we need the type of the entities to check other + declarations of the same name and to check calls to external entities + that are functions. +.. [#f3] One exception: GNU and Microsoft allow the alignment of a typedef to + be set explicitly, and that alignment is recorded in the associated + ``tk_typeref`` entry. For this reason, the macro + ``alignment_of_type`` should always be used to retrieve the alignment + of a type. +.. [#f4] A Microsoft ``__interface`` type is treated as a special kind of C++ + ``struct`` type. A C++11 lambda closure type is a generated C++ + class type. +.. [#f5] One compelling reason: constants used as part of aggregate constants + are linked together using their ``next`` pointers, so a unique copy of + the constant is necessary for each initializer list. +.. [#f6] Because dynamic initialization entries can do destruction without + initialization, there is a ``dik_none`` value for ``kind`` to indicate + that no initialization should be done. +.. [#f7] There are some additional kinds of bindings generated by IL lowering; + see ``il_def.h`` for details. +.. [#f8] Following the implementation of C++11 value categories in version + 4.8, the front end has tried to use the C++11 terms in general + internally. That caused a lot of renaming of routines and fields; for + example, ``conv_lvalue_to_rvalue`` became ``conv_glvalue_to_prvalue``. + Ugly until you get used to it, but very helpful in reminding you to + consider xvalues when you write code that deals with expressions. diff --git a/doc/_sources/includes.rst.txt b/doc/_sources/includes.rst.txt new file mode 100644 index 0000000..1a72da1 --- /dev/null +++ b/doc/_sources/includes.rst.txt @@ -0,0 +1,55 @@ +============================ +ANSI C and C++ Include Files +============================ + +Standard C++ Include Files +========================== + +The following include files are supplied with the front end: + +* | ``compare.stdh`` +* | ``coroutine.stdh`` +* | ``cxxabi.h`` +* | ``exception.h`` +* | ``exception.stdh`` +* | ``initializer_list.stdh`` +* | ``new.h`` +* | ``new.stdh`` +* | ``source_location.stdh`` +* | ``stdexcept.h`` +* | ``stdexcept.stdh`` +* | ``stdfloat.stdh`` +* | ``typeinfo.h`` +* | ``typeinfo.stdh`` + +The ". ``stdh``" files are basically the same as the definitions in the C++ +standard. The standard specifies header names without a suffix (e.g., +````). The front end, by default, adds the ``stdh`` suffix when searching +for the header file. The "``.h``" versions are supplied so that older code +that uses header names like ```` will continue to work. + +Not all of the header files for the libraries required by the C++ standard are +provided. In general, header files are only supplied for components of the +library for which an implementation is supplied with the front end. + +The ``typeinfo.h`` header file contains the definition of the ``type_info`` +data structure used by the front end and the runtime library. The +``type_info`` structure must not be changed unless corresponding changes are +also made in the front end and runtime. + +The ``cxxabi.h`` header includes declarations of routines and data structures +specified by the IA-64 ABI. + +Namespaces and the Standard Header Files +---------------------------------------- + +When front end configuration flag ``RUNTIME_USES_NAMESPACES`` is TRUE the front +end defines the preprocessing macro ``__EDG_RUNTIME_USES_NAMESPACES``. This +flag is tested by the C++ header files to determine whether the runtime +declarations should appear in the global scope or in the ``std`` namespace. +The C++ header files also test the ``__EDG_IMPLICIT_USING_STD`` flag, which is +defined by the front end when the front end is configured to use namespace in +the runtime and when the ``--using_std`` option is specified when the front end +is invoked. This flag causes the header files to do a ``using namespace std`` +in any header file that contains declarations for entities in the ``std`` +namespace. diff --git a/doc/_sources/index.rst.txt b/doc/_sources/index.rst.txt new file mode 100644 index 0000000..16cf0b8 --- /dev/null +++ b/doc/_sources/index.rst.txt @@ -0,0 +1,117 @@ +C/C++ Front End Documentation +================================= + +.. toctree:: + build + ext_intf + int_overview + il + lower_il + symbol_tbl + lex_pp + tables + expr + decls + class_decl + statements + templates + exceptions + pragma + modules + trans_unit + admin + err_msgs + includes + runtime + utilities + c_gen_be + cp_gen_be + code_style + testing + :maxdepth: 3 + :numbered: + :hidden: + +============ +Introduction +============ + +This document describes the function and internal structure of the Edison +Design Group C/C++ Front End. More precisely, it gives the general overview +necessary as an introduction to the study of the source code of the Front End. +The source code comments provide more detailed information, and that +information is not necessarily repeated here. + +The front end accepts the C++ language as defined by the ISO/IEC 14882:2020 +standard, as well as a number of the features of the ISO/IEC 14882:2024 +standard. The front end can also be configured to accept earlier revisions of +the C++ standard (e.g., ISO/IEC 14882:2003). With the proper command-line +options, it alternatively accepts the C language of the ISO/IEC 9899:1990, +ISO/IEC 9899:1999, ISO/IEC 9899:2011, and ISO/IEC 9899:2018 standards, as well +as a number of features from the ISO/IEC 9899:2024 standard. Certain other +dialects of C++ and C are also accepted, including Microsoft, GNU and Clang +dialects. C++/CLI, the Microsoft extension to C++ in support of Microsoft's +.NET environment (and formalized through the ECMA-372 standard), is also +implemented. + +It is a single pass, including integrated preprocessing. (Preprocessing +alone -- to a textual output file -- can also be done, as in traditional +compilers with a separate preprocessor.) The syntax-analysis technique is +recursive descent, with a precedence modification to speed up the scanning +of expressions. + +The front end does no optimization. Its goal is to produce a complete and +clean parsed form of the source program, and to diagnose errors. It does +complete error checking, produces clear error messages (including the position +of the error within the source line), and avoids cascading of errors. It also +tries to avoid seeming overly finicky to a knowledgeable C or C++ programmer. + +The front end is written in a portable dialect of C++, using features from the +ISO/IEC 14882:2011 standard (i.e., it's written using C++11 features). Host +and target computer characteristics (e.g., command-line interface, character +sets, integer sizes, floating-point representation) are carefully separated +from the main body of code so that they can be easily changed for rehosting or +retargeting. There is extensive debugging and assertion-checking code, which +can be included or excluded by conditional compilation options. + +The output from the front end is a high-level tree-structured in-memory +intermediate language. This intermediate language contains full information on +declarations, statements, and expressions, all in tree form, and all with +source-correspondence information that simplifies the generation of symbolic +debugging information. + +The intermediate language can, if desired, be written to a file, read back from +such a file, or displayed in human-readable form. + +When it translates C programs to intermediate language, the front end uses only +the C subset of the intermediate language. When it translates C++ programs to +intermediate language, it uses the full intermediate language. However, an +optional IL lowering pass can be used translate the C++ intermediate language +constructs into C intermediate language constructs to reduce the work required +of back ends. + +It is expected that the front end will be combined with an appropriate back end +that will generate object code from the intermediate language. A simple back +end is provided that generates C from the intermediate language, and another +that generates C++ from the intermediate language (the latter is intended for +source-to-source applications). + +Also included: minimal runtime, a template prelinker, an IL display utility, a +name demangler, and prototype header files. + +This document covers: + +* The external interface of the front end -- the command-line options, + language dialect, intermediate language, and host/target configuration + issues. (Error messages are listed in an appendix.) +* The design of the front end -- its philosophy and an overview of the source + code. + +Readers of this document should be familiar with the C++ language, with the C +language, and with the basics of compiler theory. + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` diff --git a/doc/_sources/int_overview.rst.txt b/doc/_sources/int_overview.rst.txt new file mode 100644 index 0000000..31b2df4 --- /dev/null +++ b/doc/_sources/int_overview.rst.txt @@ -0,0 +1,1289 @@ +============================== +Overview of Internal Structure +============================== + +Function of the Front End +========================= + +The front end reads source files written in C or C++, diagnoses any errors in +them, and produces an intermediate language tree that represents the source +program. + +The source files are one primary source file (named on the command line) +and zero or more header files (specified by ``#include`` directives). If +``COMPILE_MULTIPLE_SOURCE_FILES`` or ``COMPILE_MULTIPLE_TRANSLATION_UNITS`` +is TRUE, multiple source files may be specified on the command line. + +The intermediate language tree is an in-memory representation of the source +program, from which a back end can generate object code. This intermediate +form is high-level (i.e., its constructs correspond closely to C or C++ +constructs). Implicit transformations in the source language are made explicit +in the intermediate language. Source-correspondence information is preserved +so that symbolic debugging information can be generated. + +When it translates C programs to intermediate language, the front end uses only +the C subset of the intermediate language. When it translates C++ programs to +intermediate language, it uses the full intermediate language. However, an +optional IL lowering pass can be used translate the C++ intermediate language +constructs into C intermediate language constructs (this lowering is not +available for C++/CLI and C++/CX). + +The front end does not do any optimizations. It does not transform the program +in other than trivial ways. + +The front end would usually be run from a *driver*, which invokes the front end +and back end in order, and which validates and distributes the command-line +options. In such a case, the front end would write the intermediate language +information to a file, which would be read by the back end. + +The front end incorporates the preprocessing function of the C and C++ +languages, and does them on the fly as it parses the source program. The front +end can also be run in a preprocessing-only mode, and will generate +preprocessing output as a separate preprocessor would. Comments can be kept or +removed in this process. + +The front end can generate a file containing raw listing information to be used +to assemble a compilation listing. The raw listing file contains raw source +lines, information on transitions into and out of include files, and +diagnostics generated by the front end. A file containing cross-reference +information (information on each reference to an identifier in the source +program) can also be generated in a different file. + +Guide to the Source Files +========================= + +Note that most source files have a ``.c`` file suffix, even though they contain +C++ code and must be compiled with a C++ compiler (with the C++11 dialect). +That naming convention is for historical reasons and for ease in delivering +patches against earlier versions of the front end. Symbolic links (e.g., with +a ``.cpp`` suffix) can be added if required by a build environment. + +The source files are: + +.. list-table:: + + * - | ``attribute.h`` + - | Declarations related to ``attribute.c`` (scanning of attributes). + * - | ``basics.h`` + - | Basic declarations for every compilation. + * - | ``builtin_defs.h`` + - | Declarations related to GCC/clang/Microsoft builtin functions. This + header file is generated automatically by a tool that retrieves the + signatures of these builtin functions from various versions of GCC and + clang compilers (the Microsoft builtin function signatures are + manually input to this automated process). + * - | ``builtin_kinds.h`` + - | Builtin function kinds (split from ``builtin_defs.h`` to improve + compilation times). This header file is generated automatically by a + tool that retrieves the signatures of these builtin functions from + various versions of GCC and clang compilers (the Microsoft builtin + function signatures are manually input to this automated process). + * - | ``c_gen_be.h`` + - | Declarations related to ``c_gen_be.c`` (C-generating back end). + * - | ``cfe_daemon_common.h`` + - | Declarations related to ``cfe_daemon.c`` exposed for utility programs. + * - | ``checking.h`` + - | Fundamental declarations associated with assertion checking. + * - | ``class_decl.h`` + - | Declarations related to ``class_decl.c`` (class declarations + scanning). + * - | ``cmd_line.h`` + - | Declarations related to ``cmd_line.c`` (command-line parsing). + * - | ``const_ints.h`` + - | Declarations related to the manipulation of the internal + representation of integer constants. + * - | ``cp_gen_be.h`` + - | Declarations related to ``cp_gen_be.c`` (C++/C-generating back end). + * - | ``debug.h`` + - | Declarations related to ``debug.c`` (debug output). + * - | ``decl_inits.h`` + - | Declarations related to ``decl_inits.c`` (declaration initializers + scanning). + * - | ``decl_spec.h`` + - | Declarations related to ``decl_spec.c`` (declaration specifiers + scanning). + * - | ``declarator.h`` + - | Declarations related to ``declarator.c`` (declarator scanning). + * - | ``decls.h`` + - | Declarations related to ``decls.c`` (declarations scanning). + * - | ``def_arg.h`` + - | Declarations related to ``def_arg.c`` (default argument scanning). + * - | ``defines.h`` + - | A place to put ``#define``\ s to configure the front end; + ``defines.h`` is included at the beginning of every source file. + * - | ``direct_allocator.h`` + - | Declaration and definition of the ``Direct_allocator`` template. + * - | ``disambig.h`` + - | Declarations related to ``disambig.c`` (C++ expression-declaration + disambiguation). + * - | ``error.h`` + - | Declarations related to ``error.c`` (error reporting). + * - | ``err_codes.h`` + - | Definition of the enumeration of error codes. This file is generated + from the ``error_msg.txt`` file. See :ref:`mk-errinfo`. + * - | ``err_data.h`` + - | Definition of the enumeration of error codes. This file is generated + from the ``error_msg.txt`` and ``error_tag.txt`` files. See + :ref:`mk-errinfo`. + * - | ``expr.h`` + - | Declarations related to ``expr.c`` (expression scanning). + * - | ``exprutil.h`` + - | Declarations related to ``exprutil.c`` (expression scanning + utilities). Also, the data structures used in expression scanning. + * - | ``extasm.h`` + - | Declarations related to ``extasm.c`` (GNU C extended asm statement + scanning). + * - | ``fe_init.h`` + - | Declarations related to ``fe_init.c`` (initialization). + * - | ``fe_wrapup.h`` + - | Declarations related to ``fe_wrapup.c`` (termination). + * - | ``fixed_pt.h`` + - | Declarations related to ``fixed_pt.c`` (manipulation of fixed-point + constants). + * - | ``float_pt.h`` + - | Declarations related to ``float_pt.c`` (manipulation of floating-point + constants). + * - | ``float_type.h`` + - | Definitions of floating-point conversion routines used when + ``USE_HOST_FP_CONVERSION_ROUTINES`` is FALSE. This header file is + included multiple times (once for each distinct floating-point type) + by ``floating.c``. + * - | ``floating.h`` + - | Declarations related to ``floating.c`` (software-based conversion of + floating-point values between binary and decimal). + * - | ``folding.h`` + - | Declarations related to ``folding.c`` (folding of constant + operations). + * - | ``func_def.h`` + - | Declarations related to ``func_def.c`` (processing for function + definitions). + * - | ``header_util.h`` + - | General utility components (mostly templates) intended for use in both + headers and compilation units. + * - | ``host_envir.h`` + - | Declarations related to ``host_envir.c`` (definition of the host + environment, including operating system dependencies). Also, many + host configuration switches. + * - | ``host_util.h`` + - | Definitions of host environment functions that are used by both the + front end and utility programs such as the prelinker. When the front + end is compiled, these routines are included as part of + ``host_envir.c``. + * - | ``ifc_map.h`` + - | Automatically-generated type declarations and definitions for + interacting with the IFC modules format. + * - | ``ifc_map_functions.h`` + - | Automatically-generated function declarations for interacting with the + IFC modules format. + * - | ``ifc_modules_inst.h`` + - | Automatically-generated macro invocations to facilitate instantiations + in ``ifc_modules_templ.c``. + * - | ``ifc_modules_internal.h`` + - | Declarations related only to the internal + implementation files for IFC modules file support. + * - | ``ifc_modules_spec.h`` + - | Automatically-generated macro invocations to facilitate explicit + specializations in ``ifc_modules_templ.c``. + * - | ``ifc_modules.h`` + - | Declarations related to IFC modules files. + * - | ``il.h`` + - | Declarations related to ``il.c`` (intermediate language). + * - | ``il_alloc.h`` + - | Declarations related to ``il_alloc.c`` (allocation of intermediate + language entities). + * - | ``il_def.h`` + - | The definition of the intermediate language. + * - | ``il_display.h`` + - | Declarations related to ``il_display.c`` (display of intermediate + language in human-readable form). + * - | ``il_file.h`` + - | Declarations related to the structure of the intermediate language + file. + * - | ``il_read.h`` + - | Declarations related to ``il_read.c`` (reading the intermediate + language file). + * - | ``il_to_str.h`` + - | Declarations related to ``il_to_str.c`` (creating external string-form + representations for certain IL entries). + * - | ``il_walk.h`` + - | Declarations related to ``il_walk.c`` (walking the intermediate + language tree). + * - | ``il_write.h`` + - | Declarations related to ``il_write.c`` (writing the intermediate + language file). + * - | ``inline.h`` + - | Declarations related to ``inline.c`` (minimal inlining for IL + lowering). + * - | ``interpret.h`` + - | Declarations related to ``interpret.c`` (IL interpreter for + ``constexpr`` functions). + * - | ``lang_feat.h`` + - | Declarations of configuration switches that affect the source language + accepted. + * - | ``layout.h`` + - | Declarations related to ``layout.c`` (class object layout). + * - | ``lexical.h`` + - | Declarations related to ``lexical.c`` (source input and lexical + scanning). Also, the definition of the data structures related to the + current input line. + * - | ``lint.h`` + - | A place to put directives to silence the ``lint`` program. + * - | ``literals.h`` + - | Declarations related to ``literals.c`` (conversion of literal + constants). + * - | ``lookup.h`` + - | Declarations related to ``lookup.c`` (name lookup). + * - | ``lower_c99.h`` + - | Declarations related to ``lower_c99.c`` (C99 IL lowering). + * - | ``lower_eh.h`` + - | Declarations related to ``lower_eh.c`` (IL lowering of exceptions). + * - | ``lower_il.h`` + - | Declarations related to ``lower_il.c`` (IL lowering). + * - | ``lower_init.h`` + - | Declarations related to ``lower_init.c`` (IL lowering of + initializations). + * - | ``lower_name.h`` + - | Declarations related to ``lower_name.c`` (name mangling for IL + lowering). + * - | ``macro.h`` + - | Declarations related to ``macro.c`` (macro definition and invocation). + * - | ``mem_manage.h`` + - | Declarations related to ``mem_manage.c`` (memory management). + * - | ``mem_tables.h`` + - | Declarations related to the memory management data structure. + * - | ``modules.h`` + - | Declarations related to the processing of module files. + * - | ``ms_attrib.h`` + - | Declarations related to Microsoft attribute processing. + * - | ``ms_metadata.h`` + - | Declarations related to ``ms_metadata.cpp`` (reading C++/CLI metadata + from assemblies). + * - | ``overload.h`` + - | Declarations related to ``overload.c`` (overload resolution for + expression processing). + * - | ``pch.h`` + - | Declarations related to ``pch.c`` (precompiled header processing). + * - | ``pragma.h`` + - | Declarations related to ``pragma.c`` (processing of ``#pragma`` + directives). + * - | ``preproc.h`` + - | Declarations related to ``preproc.c`` (preprocessing directives). + * - | ``scope_stk.h`` + - | Declarations related to ``scope_stk.c`` (scope stack management). + * - | ``src_seq.h`` + - | Declarations related to ``src_seq.c`` (source sequence list + management). + * - | ``statements.h`` + - | Declarations related to ``statements.c`` (statement scanning). Also, + the definition of the statement stack. + * - | ``symbol_ref.h`` + - | Declarations related to ``symbol_ref.c`` (symbol references). + * - | ``symbol_tbl.h`` + - | Declarations related to ``symbol_tbl.c`` (symbol table). Also, the + definitions of the symbol table and the scope stack. + * - | ``sys_predef.h`` + - | Declarations related to ``sys_predef.c`` (system-specific predefined + macros). Also declarations related to builtins (and the place to add + user-defined builtins). + * - | ``targ_def.h`` + - | Declarations that define default target machine characteristics, and + target configuration switches. + * - | ``target.h`` + - | Declarations of target configuration variables, initialized to default + values defined in ``targ_def.h``. + * - | ``target_cfg.h`` + - | Definitions of target-specific routines to set and dump target + configurations (included once for each target configuration). + * - | ``target_map.h`` + - | Definition of various routines that map target-specific configuration + macros to global variables in some fashion (included multiple times). + * - | ``templates.h`` + - | Declarations related to ``templates.c`` (class and function + templates). + * - | ``trans_copy.h`` + - | Declarations related to ``trans_copy.c`` (copying of secondary + translation unit IL to primary IL). + * - | ``trans_corresp.h`` + - | Declarations related to ``trans_corresp.c`` (establishment of + correspondences between translation units). + * - | ``trans_unit.h`` + - | Declarations related to ``trans_unit.c`` (driver for translation-unit + processing). + * - | ``types.h`` + - | Declarations related to ``types.c`` (utility routines dealing with + types). + * - | ``util.h`` + - | General utility components. This contains a set of (mostly templated) + utilities that are used in place of those that would normally be found + in a C++ standard library. The declarations are conditionally + enclosed in the ``edg`` namespace (under control of the + ``USE_EDG_NAMESPACE`` configuration macro). + * - | ``version.h`` + - | Definition of the current version number of the front end. + * - | ``walk_entry.h`` + - | Routines used by ``il_walk.c`` to walk through IL entries. + * - | ``attribute.c`` + - | Scanning of attributes. + * - | ``c_gen_be.c`` + - | The C-generating back end (for use in place of a "real" back end; + generates C code which can be compiled by a native target compiler). + * - | ``cp_gen_be.c`` + - | The C++/C-generating back end (for use in source-to-source + transformation). + * - | ``cfe.c`` + - | The main program for the front end. + * - | ``cfe_daemon.c`` + - | The main program for the front end when built as a daemon.. + * - | ``class_decl.c`` + - | Class declarations scanning. + * - | ``cmd_line.c`` + - | Command-line processing. + * - | ``const_ints.c`` + - | Manipulation of the internal representation of integer constants. + * - | ``debug.c`` + - | Debug control routines. + * - | ``decl_inits.c`` + - | Declaration initializers scanning. + * - | ``decl_spec.c`` + - | Declaration specifiers scanning. + * - | ``declarator.c`` + - | Declarator scanning. + * - | ``decls.c`` + - | Declarations scanning. + * - | ``def_arg.c`` + - | Default argument caching and rescanning. + * - | ``disambig.c`` + - | C++ expression-declaration disambiguation. + * - | ``error.c`` + - | Error reporting. + * - | ``expr.c`` + - | Expression scanning. + * - | ``exprutil.c`` + - | Utilities for expression scanning. + * - | ``extasm.c`` + - | Scanning of GNU C extended asm statement. + * - | ``fe_init.c`` + - | Overall initialization. + * - | ``fe_wrapup.c`` + - | Overall termination. + * - | ``fixed_pt.c`` + - | Manipulation of fixed-point constants: conversion to and from internal + form and conversions and operations on the internal form. + * - | ``float_pt.c`` + - | Manipulation of floating-point constants: conversion to and from + internal form and conversions and operations on the internal form. + * - | ``floating.c`` + - | Conversion of floating-point values between binary and decimal + formats. Used only when ``USE_HOST_FP_CONVERSION_ROUTINES`` is + FALSE. + * - | ``folding.c`` + - | Folding of constant operations. + * - | ``func_def.c`` + - | Processing for function definitions. + * - | ``host_envir.c`` + - | Handling of host-environment dependencies (e.g., file name rules and + opening of files). + * - | ``ifc_map_functions.c`` + - | Automatically-generated function definitions for interacting with the + IFC modules format (that do not fit into one of the more specific IFC + map functions files). + * - | ``ifc_map_functions_acc.c`` + - | Automatically-generated accessor function definitions for interacting + with the IFC modules format. + * - | ``ifc_map_functions_dbg.c`` + - | Automatically-generated debug functions for debugging objects of types + declared in ``ifc_map.h``. + * - | ``ifc_map_functions_mut.c`` + - | Automatically-generated mutator function definitions for interacting + with the IFC modules format. + * - | ``ifc_map_functions_val.c`` + - | Automatically-generated validation function definitions for validating + objects of types declared in ``ifc_map.h``. + * - | ``ifc_modules.c`` + - | Handling of operations common to reading and writing IFC module files. + * - | ``ifc_modules_read.c`` + - | Handling of reading IFC modules files. + * - | ``ifc_modules_templ.c`` + - | Template definitions and explicit instantiations shared by + ``ifc_modules.c`` and the IFC map functions files. + * - | ``ifc_modules_write.c`` + - | Handling of writing IFC modules files. + * - | ``il.c`` + - | Low-level manipulation of intermediate language constructs. + * - | ``il_alloc.c`` + - | Allocation and initialization of intermediate language constructs. + * - | ``il_display.c`` + - | Display of the intermediate language in human-readable form. + * - | ``il_read.c`` + - | Reading the intermediate language from a file. + * - | ``il_to_str.c`` + - | Creating textual representations for certain IL entries + (e.g., constants, types). + * - | ``il_walk.c`` + - | Walking the in-memory intermediate language tree. + * - | ``il_write.c`` + - | Writing the intermediate language to a file. + * - | ``inline.c`` + - | Minimal inlining of function calls for IL lowering. + * - | ``interpret.c`` + - | IL interpreter for ``constexpr`` functions. + * - | ``layout.c`` + - | Laying out class objects. + * - | ``lexical.c`` + - | Source input and lexical scanning. + * - | ``literals.c`` + - | Conversion of literal constants to internal form. + * - | ``lookup.c`` + - | Name lookup. + * - | ``lower_c99.c`` + - | IL lowering from C99 to C89. + * - | ``lower_eh.c`` + - | IL lowering of exception handling constructs. + * - | ``lower_il.c`` + - | Intermediate language lowering (C++ constructs are translated to C + constructs). + * - | ``lower_init.c`` + - | IL lowering of initializations, new/delete, and + constructors/destructors. + * - | ``lower_name.c`` + - | Name mangling for IL lowering. + * - | ``macro.c`` + - | Definition of macros (``#define`` directive) and invocation + (expansion) of macros. + * - | ``mem_manage.c`` + - | Memory management (dynamic allocation of storage). + * - | ``modules.c`` + - | Generic module file processing. + * - | ``ms_attrib.c`` + - | Processing of Microsoft attributes. + * - | ``ms_metadata.cpp`` + - | Processing of C++/CLI metadata from assemblies. Contains C++ source + code that can only be compiled on a Microsoft Windows platform. + * - | ``overload.c`` + - | Overload resolution for expression processing. + * - | ``pch.c`` + - | Precompiled header processing. + * - | ``pragma.c`` + - | Processing of ``#pragma`` directives. + * - | ``preproc.c`` + - | Preprocessing directives. + * - | ``scope_stk.c`` + - | Management of the scope stack. + * - | ``src_seq.c`` + - | Management of source sequence lists. + * - | ``statements.c`` + - | Statements scanning. + * - | ``symbol_ref.c`` + - | Processing for symbol references. + * - | ``symbol_tbl.c`` + - | Symbol table entry and look up, maintenance of name scoping. + * - | ``sys_predef.c`` + - | Definitions of system-specific predefined macros and assertions. + * - | ``target.c`` + - | Target configuration support. + * - | ``templates.c`` + - | Declaring and instantiating class and function templates. + * - | ``trans_copy.c`` + - | Copying of secondary translation unit IL to the primary IL. + * - | ``trans_corresp.c`` + - | Establishment of correspondences between externally-linked entities in + different translation units. + * - | ``trans_unit.c`` + - | Driver for translation-unit processing. + * - | ``types.c`` + - | Utility routines dealing with types. + * - | ``unicode_name_fsm.c`` + - | Automatically-generated data file for a finite state machine that + recognizes Unicode character names. + * - | ``error_msg.txt`` + - | Contains the definition of the error codes and error messages and is + used to generate ``err_codes.h`` and ``err_data.h``. See + :ref:`mk-errinfo`. + * - | ``error_tag.txt`` + - | May be used to provide additional error "tags" or aliases that may be + used to reference a given error message in certain command line + options. This is used to generate ``err_data.h``. See + :ref:`mk-errinfo`. + +Note that in general the files are paired. A ``.h`` file containing +declarative information corresponds to a ``.c/.cpp`` file containing +executable code. The file *name*\ ``.h`` contains the declarations of the +data structures and externally-callable routines for the file *name*\ +``.c``, and is, in effect, the definition of the external interface to that +source file. + +There are also some ``.h`` files that contain configuration information and are +not paired with a ``.c`` file (e.g., ``targ_def.h``). + +In addition, there is a set of ``.h`` files that contain ``#include``\ s of +other header files. Their purpose is to group header files -- both to help +manage their often complicated interactions and to make better use of +compilation systems that perform header precompilation. + +.. list-table:: + + * - | ``basic_hdrs.h`` + - | Header files devoted to configuration. + * - | ``fe_common.h`` + - | Header files common to all ``.c`` files. + * - | ``decl_hdrs.h`` + - | Header files used for declaration processing. + * - | ``expr_hdrs.h`` + - | Header files used for expression processing. + * - | ``lower_hdrs.h`` + - | Header files used for IL lowering. + +In rough numbers, the ``.h`` files together are about 320,000 lines, and the +``.c`` files about 1,017,000 lines (including IL lowering, the IL display +utility, and the C- and C++-generating back ends). The utility programs are +another 15,000 lines, and the minimal runtime about 11,000 lines. + +Coding Philosophy +================= + +This section contains miscellaneous information on the coding style and +philosophy used in writing the front end, which may be useful to those who must +maintain it. + +The configuration section of a previous chapter of this document contains some +important information of this type. + +Code should conform to the C++11 standard and not have any dialect-specific +constructs [#f1]_. The environment dialect switches ``__ANSIC__``, +``__SYSV__``, and ``__BSD__`` should used to control inclusion of header files +that are not available in all versions of C++. ``basics.h`` (which should be +included first in every compilation) takes care of the most common header files +and the most common library routines (it will remap them via macros if +necessary). + +The size argument on calls of functions like ``memcpy`` should be wrapped in a +call of the function-like macro ``size_t_arg`` if the size is anything other +than a ``sizeof`` operator. + +Code that is host-dependent should be written only in ``host_envir.c`` and +``cmd_line.c``. + +Target-dependent code should not be written outside of ``const_ints.c``, +``fixed_pt.c`` and ``float_pt.c`` (which are heavily target-dependent) and +``literals.c``, ``folding.c``, and ``layout.c`` (which have some +target-dependent aspects). In particular, be careful about doing anything with +integers without going through the routines in ``const_ints.c``. + +External Names +-------------- + +External routines should always be declared both where the body occurs and in +the corresponding ``.h`` file. The ``.h`` file should be included everywhere +the routine is referenced. + +External variables should be declared in ``.h`` files with ``EXTERN`` as their +storage class. All ``.h`` files that contain external variables must be +included in ``fe_init.c``; there, the macro ``EXTERN``, which ordinarily is +mapped to ``extern``, is mapped to a null string. This makes the same +declarations, when scanned in ``fe_init.c``, external definitions instead of +external references. If an external variable should have an initial value, the +initialization should be included in the ``.h`` file, surrounded by ``#if +VAR_INITIALIZERS``/``#endif``. In ``fe_init.c`` the initializer will be +included. + +Of course, variables should be made ``static`` instead of external if it is +possible to localize them to a single source file. + +All static variables (external, internal, and function-local) must be saved and +restored as necessary when precompiled headers are generated. The point at +which a precompiled header is written or read is outside of any declaration and +at the file scope (etc.); variables that never have interesting values at such +points need not be saved and restored. All others, however (and these cannot +be function-local), must be registered by calling +``register_pch_saved_variables`` so that they will be written to the +precompiled header file and restored. + +Likewise, variables that are translation-unit specific should be registered by +calling ``register_trans_unit_variable``. See the :ref:`multi-tu` chapter. + +Include Files +------------- + +Include files always include any other files on which they depend. They also +define a flag once they have been included, and will skip themselves if +included again. (For example, ``cmd_line.h`` defines ``CMD_LINE_H``). +Therefore, one can include the files in any order and without regard for +whether or not they have been included by other include files. To improve +compilation speed, ``#include``\ s can be surrounded by ``#ifndef`` +*flag*/``#endif``. + +Debug Code +---------- + +Debug code is surrounded by ``#if DEBUG``/``#endif``. In such code, one should +test the value of ``debug_level`` to control output of debug information. +``debug_level`` is zero ordinarily, to indicate that no debug output should be +produced. Debug code should be set to come out at an appropriate level: ``1`` +is for output that comes out once per source line, ``3`` for output that comes +out once per token, and ``5`` for output one would hardly ever want to see. +``2`` and ``4`` lie in between those levels in the expected way. Choosing an +appropriate debug level is more of an art than a science. If in doubt, make a +guess at the best level, run the front end with that level of debug output, and +see if the new messages seem out of place in the overall debug output at that +level. + +One can also use ``db_flag_is_set`` to determine whether specific output should +be generated. For example, calls of ``db_flag_is_set("vtbl")`` are used in IL +lowering to control debug output related to virtual function tables. By +specifying ``-d-vtbl`` on the command line, one can get that particular debug +output and nothing else. A particular "flag" is considered set if the string +of the ``db_flag_is_set`` call is specified in a command-line debug option, so +a new "flag" is added by adding a call of ``db_flag_is_set`` with some new +string; there is no central registry of debug "flags." + +A similar facility for tracing names is provided by the ``--db_name=``\ *xxxx* +command-line option and the ``db_has_traced_name`` macro. This can be used to +control extra output about processing of entities with specific names. +``db_trace`` provides a combination of the features of ``db_flag_is_set`` and +``db_has_traced_name``. + +Debugging options that are specified with the ``-d`` command-line option can +also be specified using the ``db_opt`` pragma. The pragma can be used to +specify a certain debug level or to define a certain debug flag for a portion +of a source program that is being compiled. For example: + +.. code:: c++ + + template void f() { + #pragma db_opt -nondep_call + g(); + #pragma db_opt #nondep_call + } + +When a flag name is preceded by "``#``", the flag is cleared if previously set. + +Debugging options that are specified with the ``--db_name`` command-line option +can also be specified using the ``db_name`` pragma. + +The variable ``db_active`` is TRUE if ``debug_level`` is non-zero or if there +is the potential for it becoming non-zero (i.e., if there is a list of debug +requests from the command line). This can be used to control processing that +may be needed when debug output is generated, but should not be done when no +debugging is requested. + +Diagnostic messages should be written to ``f_error``. This is normally set to +``stderr``, but in some modes is set to ``stdout``, and can be redirected to a +file by use of a command-line option. Debug output should be written to +``f_debug``. This is set to ``f_error``, but is a separate file variable to +allow it to be changed if desired. + +Entries and exits of routines should have calls to ``db_enter`` and +``db_exit``. These provide flow tracing. The ``db_enter`` call looks like + + | ``db_enter(``\ *level*\ ``, "``\ *routine-name*\ ``");`` + +The ``db_exit`` call has no arguments. These calls will cause an entry +message and an exit message when ``debug_level`` is equal to or greater +than the *level* specified. Note that the calls need not be surrounded by +``#if DEBUG``/``#endif``; ``db_enter`` and ``db_exit`` are actually macros, +and when ``DEBUG`` is ``0``, they are defined as null strings. When +``DEBUG`` is non-zero, they expand to calls to ``debug_enter`` and +``debug_exit``. Those calls are surrounded by ``if``\ s testing +``db_active`` so that the routine calls are only done when debug output is +actually being generated (or may be generated, when a list of +routine-related debug requests is specified on the command line). + +It should be clear that for ``db_exit`` to work correctly one should have a +single exit point for each routine, and not have ``return`` statements in the +middle of routines. + +Some routines do not have ``db_enter`` and ``db_exit`` calls for speed +reasons -- even the overhead of two ``if``\ s would be visible. An example is +``skip_white_space`` in ``lexical.c``. + +Checking Code +------------- + +Checking code performs dynamic consistency checking, e.g., verifying the entry +conditions for routines and the consistency of tables. Checking code is always +surrounded by ``#if CHECKING``/``#endif``. When a problem is found, this code +calls + + | ``internal_error("``\ *routine-name*\ ``:`` *problem found*\ ``");`` + +which displays the argument string and causes abnormal termination of the front +end. + +As a concrete example of checking code: *all* ``switch`` statements should +have a default clause; if the default clause does not correspond to any +legal possibility, it should be present as checking code, and should call +``internal_error`` to indicate that a bad value appeared as the switch +selector. (See ``CHECK_SWITCH_DEFAULT_UNEXPECTED`` in ``basics.h`` and +``default_is_unexpected`` in ``checking.h`` for macros that assist in +applying this rule.) + +Several routines are provided as convenient ways to do consistency +checking. Calls of these routines need not be surrounded by ``#if +CHECKING``/``#endif``; they are defined as macros that expand to nothing +when ``CHECKING`` is disabled. ``check_assertion`` can be used to check an +expression to make sure it is true. ``expect_error`` checks that +``total_errors`` is nonzero at the point of invocation or that it becomes +nonzero before the end of the compilation. This is useful to ensure that +situations that are expected to lead to error diagnostics will indeed do so +(only the first invocation will be reported on failure). +``check_assertion_or_expect_error`` combines the previous two routines: it +has no effect if either the given condition is TRUE, or if ``total_errors`` +is nonzero by the end of the compilation. ``unexpected_condition`` is used +when a piece of code is not expected to be reached (for example, the +default clause of a switch). Three versions of each of these routines are +provided: the version described above, a version with a ``_str`` suffix +that accepts a single string argument, and a version with a ``_str2`` +suffix that accepts two strings. The string(s) are printed on error +termination to provide additional information about the cause of the error. + +The consistency checks that are enabled by the ``CHECKING`` flag do not +significantly affect the performance of the front end. There are other +consistency checks whose execution does affect the performance of the front +end. These extra consistency checks are enabled by the ``EXPENSIVE_CHECKING`` +flag. These checks are not intended to be enabled when optimum performance is +required (e.g., in production versions of a product). + +Conventions for Declarations +---------------------------- + +The type ``a_boolean`` (defined by default as ``int``) should be used for +true/false variables, along with the constants ``TRUE`` and ``FALSE``. +These are defined in ``basics.h`` and thus are available everywhere. In +``struct``\ s, ``a_byte_boolean`` is used for boolean fields when there is +just one of them. When there are several, bit fields of length one are +used, to save space. Obviously, these rules will not work on all host +machines, but they will work well enough on most. + +Fields in ``struct``\ s are ordered to some extent to reduce the space wasted +in gaps for alignment. It's assumed that pointers and large integers have +similar size and alignment requirements, and thus a sequence of them will leave +no gaps. When small fields appear, however, they are grouped together to avoid +the gaps one would expect from a series of short/long/short/long fields. + +Bit fields are declared with the type ``a_bit_field``. It is usually +``unsigned int``, but when compiling with a compiler that uses the Microsoft +bit-field layout algorithm it can be set to ``unsigned char`` to get better +packing of the bit fields. + +The type ``a_byte`` should be used for small integer fields (i.e., fields +whose values lie in the range 0-127), rather than ``char`` or ``unsigned +char``. ``enum`` types are often given a base type of ``a_byte`` so that +their size is explicitly controlled to save space in ``struct``\ s. + +For each table type (whether or not it is part of the intermediate +language) there is an associated allocation routine and an associated +routine that will set the fields of the table to default values. (In some +cases, these two functions are provided by one routine.) When a table has a +variant section and an associated tag field, there is also a routine to set +the tag field and set the associated variant fields to default values. A +tag field should never be assigned directly; it should only be set by this +routine. Consistent use of the allocation, clear, and set-kind routines +ensures that no uninitialized fields will cause sporadic problems, and that +new fields can be easily added. In addition, it can be useful to add the +following snippet to ``defines.h`` : + +.. code:: c++ + + #if UNION_AS_STRUCT + #define union struct + #endif + +Setting ``UNION_AS_STRUCT`` in a testing build allocates each variant field +in its own storage. This often allows detection of cases where code +accesses an incorrect variant for a given IL entry. + +The names of macros are written in upper case in the front end source when they +are object-like (e.g., manifest constants), but in lower case when they are +function-like. The names of types and enumerators are written in lower case. + +The names of ``typedef``\ ed, class, and templated types always begin with +``a_`` or ``an_`` (e.g., ``a_type``, ``an_expr_node``). Pointer type names +end in ``_ptr``. The names of constants in enumerations always begin with +a prefix that hints at the enumeration type (e.g., ``enk_`` for +``an_expr_node_kind``). + +Storage Allocation +------------------ + +Allocation of space is never done by calling ``malloc`` or the like directly. +For all table entries, as mentioned earlier, the associated allocation routine +should be called. It will allocate and clear the space, and will also make +sure that the space is allocated in the right area (e.g., intermediate language +constructs must be allocated in the right memory region). For any other +allocation cases, one of the routines in ``mem_manage.c`` should be called +instead. ``alloc_fe`` has an interface like ``malloc``, and allocates storage +that need not survive the execution of the front end. ``alloc_general`` is +similar, and allocates storage that will survive into the back end if the back +end is called as part of the same program (this should not be used ordinarily). + +One case to do carefully: all names that become part of the intermediate +language (file names, directory names, identifier names) should be allocated in +the file-scope intermediate language region, by calling ``alloc_il``. + +Space is never freed by calling ``free`` or related routines. Where tables are +reused, the front end maintains individual lists of available entries for each +type of table, and takes entries off those lists before allocating new ones. +Space can be released on a memory region basis, for example to free up all the +space used for a given function once the function has been processed. When the +front end is configured in such a way that it can be re-initialized (by setting +``MAKE_FRONT_END_CALLABLE``) the front end keeps a record of all memory +allocations and automatically frees the memory when the front end terminates. + +In general, every reasonable attempt is made to not allocate tables unless they +are actually needed. The intermediate language, for example, will contain some +wasted space, but extremely little. + +In order to avoid any fixed limits in the front end, the primary non-IL data +structures are designed so they can be dynamically allocated and expanded +(``curr_source_line``, ``scope_stack``, etc.). An initial allocation is done +that should cover all expected uses; if more space is needed, the table is +reallocated with a larger size. That means that there is a danger inherent in +keeping around pointers into those data structures, because if the table moves, +all pointers to the table become obsolete. In the input line/macro area, such +pointers are necessary, and there is a pointer registration scheme that is used +to make sure that all pointers are updated if a reallocation occurs. In other +areas, pointers can be avoided relatively easily. A simple rule to remember is +that one should never make a local pointer into one of the primary stacks +(``scope_stack``, ``struct_stmt_stack``); one should instead use an index value +into the stack, since an index is not invalidated by a reallocation of a table. +When memory is allocated that may later be resized, it must initially be +allocated using either ``alloc_resizable_buffer`` or ``realloc_buffer``. It +may then be resized later by calling ``realloc_buffer``. + +One can get a summary of space use by having ``debug_level`` non-zero in +``fe_wrapup``. This can be requested by specifying ``-dfe_wrapup=1`` on the +command line. A summary of symbol table and constant sharing efficiency is +also included. + +Typerefs +-------- + +The description of a type in the intermediate language contains a type entry +kind ``tk_typeref``, which is used to define typedefs, and also to add type +qualifiers to a type, e.g., ``const`` in ``const int``. Such an entry is in +some ways not a full-fledged type. For example, it doesn't indicate its size; +one must go to the underlying type to get that. The macro ``skip_typerefs`` +and the function ``f_skip_typerefs`` can be used to strip off typerefs and get +to the underlying type, which can then be processed in the normal way. A very +common cause of bugs in code our customers add is failure to put in +``skip_typerefs`` calls where necessary. (For that matter, it's a common cause +of bugs in our code, though we try hard to find all those bugs before we ship +the code.) The whole ``skip_typerefs`` issue is error-prone and requires +discipline, but you do get used to it, and after many years of working with it +we remain convinced that it's the right way to handle typedefs and type +qualifiers. Just be careful. + +Source Positions +---------------- + +Source positions are represented as a structure of type ``a_source_position`` +(see ``basics.h``). It contains a sequence number and a column number. The +sequence number is a unique number assigned in ascending order to each source +line as it is read. Unlike a file name and line number, the sequence number is +unambiguous. It's also more compact, and can be converted to a file name and +line number for external use (this is done in error messages, for example). + +The column number is a 1-origined character position in the original source +line. The character position is the logical character number in the line, not +simply a byte offset. This is significant if the source file contains +multibyte characters or is in a format such as UTF-16. Tab characters are +counted as a single column. The position of text within a macro expansion is +considered to be the first character of the macro name in the macro call in the +original source line that directly or indirectly generated the text. + +If the front end is configured with ``FULLY_RESOLVED_MACRO_POSITIONS`` set to +TRUE, each source position contains an additional sequence/column number pair. +For text within a macro expansion, this additional position information gives +the location from which the associated text was copied into the macro +expansion, i.e., a macro definition or macro argument. + +If ``MACRO_INVOCATION_TREE_IN_IL`` is configured to TRUE, each source position +referring to text within a macro expansion contains the index of the macro +invocation record that identifies the macro in whose expansion the text at that +position occurs. For text appearing directly in the source, this index will be +``NO_PARENT_MACRO_INVOCATION``. + +A sequence number of zero is used to indicate an unknown position or a +"position" in initialization, in a predefined macro, or in the command-line. +The column number indicates which. See ``basics.h``. + +Importing assembly metadata in C++/CLI is a process that creates a string +containing C++ code that expresses that metadata and then parses the contents +of that string. Each import is associated with a particular sequence number, +and that number is assigned to the position of each token extracted from that +string (with a column number zero). For example, when compiling a C++/CLI +source file, sequence number one will usually correspond to ``mscorlib.dll``. + +Language Dialect +---------------- + +The global variable ``C_dialect`` (in ``cmd_line.h``) indicates the C +dialect to be accepted: the choices are ``C_dialect_cplusplus``, +``C_dialect_ANSI``, and ``C_dialect_pcc``. The macro ``C_mode()`` is +useful as a way of testing for C versus C++. ``cpp``\ *NN*\ ``_mode`` +(where *NN* is the year of the relevant C++ Standard, e.g., ``cpp03_mode``, +``cpp17_mode``, etc.) is TRUE when the features of the corresponding +revision of the language should be accepted, and similarly ``c``\ *NN*\ +``_mode`` for versions of the C language. + +The global variable ``strict_ansi_mode`` is TRUE if use of features that +are not part of the selected C or C++ Standard should cause diagnostics. +``strict_ansi_error_severity`` indicates the level of diagnostic (warning, +discretionary error, or error) that should be produced for such cases. + +``microsoft_mode`` indicates whether a Microsoft dialect (C, C++, C++/CLI, +or C++/CX) is in effect. In configurations that do not allow Microsoft +extensions (i.e., when ``MICROSOFT_EXTENSIONS_ALLOWED`` is FALSE), it is a +macro equivalent to FALSE. This allows many Microsoft-mode-specific bits +of code to be written without surrounding them with conditional compilation +directives testing ``MICROSOFT_EXTENSIONS_ALLOWED``. ``cppcli_enabled`` +and ``cppcx_enabled`` similarly indicate that the Microsoft dialect is +C++/CLI or C++/CX, respectively (if TRUE, ``microsoft_mode`` is TRUE too, +and C_mode() is FALSE). Some C++/CLI- and C++/CX-specific code is +delimited by conditional compilation directives testing +``MICROSOFT_EXTENSIONS_ALLOWED`` because it uses variables, data members, +or functions that are available only when that macro is TRUE. (The macro +``CPPCLI_ENABLING_POSSIBLE`` is tested in a few places for code that deals +with the importing of assembly metadata, but it shouldn't be used to +conditionalize other C++/CLI-specific code. In particular, the IL +extensions representing C++/CLI and C++/CX constructs are only conditioned +on ``MICROSOFT_EXTENSIONS_ALLOWED``.) + +``gpp_mode`` and ``gcc_mode`` indicate that, respectively, GNU C++ or GNU C +emulation is in effect. In configurations where ``GNU_EXTENSIONS_ALLOWED`` is +FALSE, these are macros equivalent to ``FALSE``. + +``clang_mode`` indicates that clang emulation is in effect. Because the +initial emulation of the clang C++ compiler in the front end was very close +to g++, ``clang_mode`` also implies that ``gpp_mode`` or ``gcc_mode`` will +be set. When it is necessary to distinguish between the GNU and clang +emulations, the macros ``gnu_version_is``, ``gpp_version_is``, +``gcc_version_is``, ``clang_version_is``, ``clangcpp_version_is``, and +``clangc_version_is`` (see ``lang_feat.h``) allow finer-grained +discrimination (including the compiler version to be emulated). (There are +also corresponding Microsoft-specific macros, ``ms_version_is``, +``mscpp_version_is``, and ``msc_version_is``.) + +``cfront_2_1_mode`` is TRUE if the cfront 2.1 dialect of C++ is to be compiled. +``cfront_3_0_mode`` indicates the cfront 3.0 dialect. The macro +``any_cfront_mode()`` tests for either of those being set to TRUE. + +(There are other variables/macros that control dialect variations. The ones +mentioned here are among the more frequently used ones.) + +Expression Processing +--------------------- + +See :ref:`rescanning-exprs` for some additional coding rules that apply +only within the expression-processing routines. + +Recursive Descent Parsing +========================= + +"Recursive descent" is an ad-hoc syntax parsing technique. It works well for +languages (like C) where very little lookahead is required to resolve local +ambiguities, and where the language in which the compiler is written is +recursive (as is true for the front end). + +The idea of recursive descent provides a framework and a discipline for parsing +a language, but it is implemented entirely by hand-crafted code. There is +nothing automatic about the parsing. Thus, there is more possibility for error +in developing a recursive-descent parser than there is in developing a +table-driven parser. However, if one writes carefully and tests thoroughly, +the end result is better with a recursive descent parser: faster parsing, +better error recovery, and a clearer compiler (because all of the logic related +to a particular construct appears in one place). + +To implement recursive descent, one writes routines for each non-terminal +construct in the language syntax. For example, one writes a routine to scan an +expression, and one to scan a statement, and one to scan a declaration. The +internal structure of these routines looks a great deal like the syntax of the +constructs they implement. For example, if a declaration is defined as a list +of declaration specifiers followed by a declarator followed by a semicolon, the +routine that scans a declaration would call the routine to scan a list of +declaration specifiers, then the routine to scan a declarator, and then check +for and discard a semicolon. Where the language has recursive constructs, the +routines involved will call each other recursively. + +The terminal tokens that are being parsed come from the lexical routines, +specifically from ``get_token``. At any given moment, there is a current +token (``curr_token``). It is the *next* token of input, the one that +hasn't yet been taken. If the token is an identifier or a literal +constant, there is additional information associated with it. See +``lexical.h``. + +As the recursive descent routines parse the input tokens, they build up +information on what they have parsed, in the intermediate language trees and in +the symbol table. They also check for and recover from errors. + +The scanning of expressions is one area where recursive descent is inefficient +for languages (like C) where the expression syntax has many levels. A naive +recursive descent implementation would provide a routine for each level of the +expression syntax, and thus scanning a simple expression would involve perhaps +a dozen subroutine calls. For this reason, the front end uses a modified +recursive descent technique to scan expressions. Internal calls to the +``scan_expr`` routine (in ``expr.c``) specify a precedence level, and the scan +routine can decide whether to call itself recursively or not based on the +relative precedences of adjacent operators. With this modification, the number +of calls is reduced to very nearly one per operator. See the description of +``expr.c`` later in this document for more detail. + +To reduce the possibilities for errors in writing the parsing routines, one +should not check for the start of constructs by checking directly for all the +possible first tokens in that construct. Such a list of tokens is inherently +error-prone. For constructs of this kind, there are functions that will +indicate whether or not the current token looks like the start of the construct +(see, for example, ``is_decl_start`` in ``decls.c``). Such routines might +themselves call other ``is_``\ *xxx*\ ``_start`` routines if the constructs can +themselves begin with other complex constructs. + +Several utility routines in ``lexical.c`` are useful for recursive descent +parsing. ``required_token`` can be used to check for and discard a required +token, and to issue a specific error message if the token is not present. +``loop_token`` is used to check (at the bottom of the loop implementing an +iterative syntactic construct) for the occurrence of a particular token. The +token is taken if found, but no error is given if the token is not found. +``next_token`` is useful for doing a limited kind of lookahead: it will return +the kind of the token following the current token, without actually getting +that token (actually, it gets it and then puts it back). In many cases, that +one token is enough to allow a decision to be made at a fork in the syntax. +See, for example, the code that recognizes statement labels in ``statement`` in +``statements.c``. + +Consult any of the popular books on compiler theory for a more detailed +overview of recursive descent. + +Error Recovery +============== + +When the front end discovers an error, it has several goals: + +* | To describe the error clearly and indicate its position (including the + position within the source line); +* | to recover from the error without generating extra errors; +* | to preserve as much information as possible about the valid parts of the + construct containing the error, so that detection of other errors is not + needlessly compromised. + +("Error" here of course refers to remarks and warnings as well.) + +Describing an error clearly requires that one not only detect the error, but +detect it at an appropriate level, so that the front end can guess better at +what was intended. Sometimes this requires clever code at decision points in +recursive descent parsing, so that on invalid constructs one goes to the more +likely of two subcases. Within the ``{ }`` for a ``struct``, for example, we +have a series of member declarations separated by semicolons. If a semicolon +is missing, one should not fall out of the loop and leave the scanning of the +``struct``. In other situations, clearly invalid cases should be flagged at +the higher level, and none of the subcases should be entered. For example, at +the beginning of a statement or a declaration, if the first token is not a +valid start for that construct, an error message ("expected a statement" or +"expected a declaration") is more informative than descending into any of the +subcases and letting them issue errors. + +Error Positions +--------------- + +The position of an error is often just as important as the error text. The +front end tries to give useful error positions. This is aided by the fact that +column positions are maintained for each token. A global variable +``error_position`` indicates the position of the beginning of the last language +construct scanned. It is set by ``get_token`` on scanning each token, and it +is also set by each medium-sized language construct (e.g., an expression, a +declarator). Most recursive descent routines save the position of the first +token of the construct they scan, and then set ``error_position`` to that +position on return. ``error_position`` is the default position for errors when +no explicit position is specified, and this protocol for setting it works well +in ensuring that the error positions are right. Some cases take extra work. +For example, in the expression routines, the position of the left operand and +right operand, and the position of the operator itself, are known for each +operation. If an error is due to a problem with one of the operands, the error +position used is the position of that operand. If the problem is with the +combination of those operands (as in adding a pointer and a float), the error +position used is the position of the operator. + +The macro ``set_err_pos_to_curr_token`` is used when one is going forward in +scanning. It sets the error position to the position of the current token. +One would use it, for example, when looking for the ``=`` that indicates an +initializer in a declaration. The previous construct (a declarator) has been +scanned and checked, and its position is in ``error_position``. Now, however, +we are going forward, and the ``=`` that may have ended the expression scan +should once again be the current construct. In practice, there are few cases +like this; they only come up for optional tokens in the middle of constructs. +``required_token`` handles the change of error position in the more usual case +of a required token. + +When an error refers back to something earlier in the source, it often makes +sense to give the position of the other location rather than the current +location. Variables declared but never used, for example (a warning), are +detected at the closing brace of functions. However, that position is much +less informative than the position of the declaration of the variable in +question, so that is used. Likewise, when a comment is unclosed at end of +file, it is more useful to indicate the position of the start of the comment +instead of the location of the end of file, where the error was detected. + +Error Codes +----------- + +Error messages are mapped to values of the enumeration ``an_error_code`` (see +``err_codes.h``, along with ``err_data.h`` for the associated error message +text). For example, ``ec_exp_line_number`` represents the message "expected a +line number". ``ec_no_error`` is first in the enumeration, and therefore has +the value zero. Thanks to it, one can return error codes of type +``an_error_code``, and test them in ``if`` statements (non-zero means an +error). + +Errors with codes beginning ``ec_exp_`` (and texts beginning "expected a ...") +are uniformly syntax errors -- some expected token or construct was not found. + +The severity of an error is determined by the error routine called (e.g., +``error`` instead of ``warning``) and not by the error code. In fact, there +are cases where the same error code is used as both a warning and an error. +The severity of certain diagnostic messages may be overridden using a command +line option. A diagnostic that is issued with a severity that is less than an +error (i.e., remark, warning, or discretionary error) may have its severity +changed, or may be suppressed completely. + +Some error message texts have fill-ins, as in + + | ``could not open source file "``\ *name*\ ``"`` + +For these, variants of the error routines should be called. For the case +above, for example, ``str_error`` would be called. The fill-in string is +passed to the error routine as a null-terminated string, and replaces +``%s`` where it appears in the error text string. See +:ref:`error-reporting` for details on the kinds of fill-ins available. + +Syntax Errors +------------- + +In terms of internal processing, one must distinguish syntax errors from +semantic errors. Syntax errors are discovered when the sequence of tokens +in the source program cannot be parsed according to the language syntax +(for example, ``i=j+;``\ --there's something missing between the ``+`` and +the ``;``). All other errors are semantic errors -- things that can be +parsed but are still nonsensical (for example, use of an undefined +variable, or adding two ``struct``\ s). In error recovery, the important +distinction between the two is that for a syntax error one must decide how +to continue parsing, whereas for a semantic error everything is fine as far +as parsing and there's no question about how to continue. + +Syntax errors should always cause the calling of ``flush_tokens`` in +``lexical.c``, and semantic errors should never call it. The routine +``syntax_error`` records the occurrence of an error, and then calls +``flush_tokens``, which is a convenient combination. + +``flush_tokens`` scans and throws again tokens until it finds one in the +*stop tokens set*, and then returns. Paired tokens are also considered: if +a ``(`` is scanned while flushing tokens, for example, the corresponding +``)`` will be sought before continuing the search for a stop token. There +are some other special cases; see the code in ``lexical.c``. + +The stop tokens set is an array indexed by token kind. Each element of the +array is non-zero if the corresponding token is currently in the stop tokens +set (and thus should halt a flush). As recursive descent routines scan +constructs, they add to the stop tokens set those terminal tokens they expect +to see in their constructs, and then remove those tokens once they are +encountered. The macros ``add_stop_token`` and ``remove_stop_token`` are +called to add and remove tokens from the set by incrementing and decrementing +the associated element of the array. Since syntactic constructs are nested +inside one another, having each recursive descent routine add the tokens it +recognizes produces a stop tokens set that will halt a flush at a token with +which one of the active routines feels it can continue. + +At boundaries where the syntax changes dramatically, ``push_stop_token_stack`` +is called to establish a new set of stop token values. The old values are +restored later by calling ``pop_stop_token_stack``. This is done, for example, +when entering the processing for preprocessing directives, whose syntax is +dramatically different than the context in which they are embedded. + +Uses of ``add_stop_token`` and ``remove_stop_token`` must be very carefully +paired. A missing call of either would probably cause the associated token to +be handled incorrectly in error flushes for the rest of the compilation. +Skipping a ``remove_stop_token`` call is easy to do if one does a ``goto`` out +of an inner loop in a recursive descent routine (say, because there is an +error) and one skips over the point where the ``remove_stop_token`` is done. +The likelihood of such a problem is lessened by having ``debug_enter`` and +``debug_exit`` verify (by means of a checksum) that the contents of +``stop_token_array`` are the same on exit as they were on entry. This check is +only done when debugging is active, however, because it's time-consuming. +Also, ``fe_wrapup`` verifies that all the counts have returned to zero by the +end of the compilation; that check is always done. In addition, when expensive +checking code is enabled, ``pop_stop_token_stack`` verifies that all of the +elements of the stop token set that is being discarded have been reset to zero. + +If ``required_token`` does not find the token it expects, it adds that token to +the stop tokens set, and calls ``syntax_error``. After ``flush_tokens`` +finishes, ``required_token`` checks again to see if the desired token has come +up, and if so, scans over it. + +Error Entries +------------- + +For both syntax and semantic errors, another part of error recovery is +producing something sensible, in spite of the error, in the data structure that +represents the program. This task is eased by having special "error" entries +for all of the major table types. There are, for example, error constants, +error types, and error expression nodes. They are used to take the place of +any part of the program tree that cannot be built because of an error. In +general, the code tries to build as much of the complete tree as possible. An +error in one part of an expression, for example, need not mean that the entire +expression tree will be replaced by an error expression node. Throughout the +front end, code must be capable of dealing with error entries. The basic +philosophy is that an error entry is considered to be compatible with anything +else. No additional errors should be issued on encountering an error entry, +since it is assumed that some error was issued when the entry was created. + +When syntax errors involve missing identifiers, special error symbols are +created. A different error symbol is created for each error case. All error +symbols point to the same special associated symbol header (see the +documentation of ``symbol_tbl.c``). + +When errors involve duplicate declarations of the same symbol, the second +symbol is entered anyway. Both symbols are in the symbol table, but because of +the symbol table structure, the later declaration will the one that is visible, +and it therefore effectively replaces the earlier declaration. + +In general, scanning routines do not need to return indications of success or +failure, since they always return a tree representing the construct scanned. +Some routines must deal with unusual cases where there is no possible +representation for the thing scanned, and so they return an error parameter. +The caller must check it. + +Intelligent Error Diagnosis +--------------------------- + +The front end attempts to diagnose as many errors and warnings as possible. If +one uses header files with function prototypes for all external functions and +variables, it should be possible when writing in ANSI C or in C++ to do away +with ``lint``, or at least to relegate it to use in unusual cases. That is the +goal of the front end: diagnose not only errors but also questionable +constructs such as those flagged by ``lint``. However, since ``lint`` is run +on request and the front end must be run on each compilation, one must take +care that the errors are not overly pedantic. The front end tries to do this +by being selective about errors. It's a good idea, for example, to warn about +value-less ``return`` statements in functions that should return a value. +However, in old-style C, before the keyword ``void`` existed, it was standard +practice to omit the type specifier altogether on a function that returned +nothing. The C language says such a function has type ``int``, but the C +programmer usually thinks of such a function as having type ``void``. So, in +the front end, a warning is issued for a value-less return in a function with +an explicit type, but not for one in a function with an implicit ``int`` type. +In ``pcc`` mode, a warning is never issued. + +A similar issue comes up in expressions. An expression like ``1/0`` looks like +an error (division by zero), but should not necessarily cause a compilation +error. If it occurs in a context where it is not evaluated (such as +``0&&1/0``), it never causes an error; if it occurs in a context where it must +be evaluated at compile time (as in the size of an array), it causes an error; +and if it occurs elsewhere (i.e., in executable code), it causes a warning and +is left as-is to cause a fault (or not) at execution time. + +Likewise, when a constant seems to be part of a bit-oriented operation (it is a +non-decimal constant, or it results from a bit-wise operator applied to +constant operands), the normal warnings about implicit sign changes when the +constant is changed from signed to unsigned or vice-versa are suppressed. + +.. [#f1] Except for ``ms_metadata.cpp`` and its corresponding header: They are + written to be compilable by a current Microsoft C++ compiler and by + the front end in a corresponding Microsoft C++ mode. diff --git a/doc/_sources/lex_pp.rst.txt b/doc/_sources/lex_pp.rst.txt new file mode 100644 index 0000000..f9abd85 --- /dev/null +++ b/doc/_sources/lex_pp.rst.txt @@ -0,0 +1,1896 @@ +================================== +Lexical Analysis and Preprocessing +================================== + +Source Line Data Structure +========================== + +Before describing the routines involved in lexical analysis and preprocessing, +it is necessary to discuss the data structure that represents the current +source line. This data structure is used throughout the lexical routines, and +its form is dictated by the types of processing that must be done in the +lexical and macro routines. The routines and data structures described in this +section are defined in ``lexical.c`` and ``lexical.h``. + +The Current Source Line +----------------------- + +A logical source line, in the ANSI C standard (2.1.2.2), is what results after +trigraphs have been replaced by the corresponding characters (e.g., ``??=`` by +``#``) and line splices have been done (i.e., each line ending with a backslash +is spliced with the following line). The routine ``read_logical_source_line`` +does this processing, and the global array ``curr_source_line`` contains the +result. That is, in ``curr_source_line`` trigraphs have already been replaced, +and several physical source lines may have been spliced into one logical source +line. If any such transformations were made to produce the current source +line, the global variable ``orig_line_modif_list`` points at a list of entries +that describe all the transformations made, in a form such that + +* | the original source lines can be reconstructed from ``curr_source_line``, + if that is necessary (e.g., for error-reporting purposes); and +* | from a location within ``curr_source_line``, one can determine the file + name, line number, and column from which that text came, for + error-reporting purposes. + +.. _lex-src-line-modifications: + +Modifications to the Current Source Line +---------------------------------------- + +When changes to the current logical source line are made because of +preprocessing, they are handled in a different way: ``curr_source_line`` is not +changed (much); instead, the global variable ``source_line_modif_list`` points +to a list of entries that indicate changes that have been made logically to +``curr_source_line``. Each of these changes is a deletion of some number of +characters at a given location, and an insertion of some number of characters +(possibly none) at that location. These entries represent changes due to +deletion of comments and replacement of macro invocations by the expansions of +those macros. (Comments need not be deleted, even logically, if preprocessing +output is not being produced. In ``pcc`` mode, comments are deleted entirely, +but in other modes they are replaced by one blank.) + +The two sets of changes are handled differently, and one might ask why the +trigraphs and line splices are actually rendered in ``curr_source_line`` (with +instructions on undoing them), while the macro changes are not rendered (and +the instructions are for doing them rather than undoing them). The reason is +that the first set of changes is applicable at the character or intra-token +level, and the second set only applies at the inter-token level. It is a basic +goal of the lexical routines that the current position must be representable as +a single pointer, and that one be able to move forward efficiently in the input +by just incrementing that pointer. Trigraphs and line splices can occur within +tokens, and therefore if they were not rendered in ``curr_source_line`` one +would have to check for them in every case where one wants to move forward in +the input. The other modifications, on the other hand, can only occur between +tokens, and therefore they need not be expanded in the source line. They occur +between tokens, and special marker characters in the input stream are used to +indicate their presence. The marker characters cause the termination of +scanning of the previous token, followed (on the next call of ``get_token``) by +interpretation of the marker character to decide where the input goes next. +This makes macro expansion efficient (the source line need not actually be +subjected to insertions and deletions) while preserving the ability to advance +through the input using just one pointer. It also preserves information that +allows one to construct either the original source line or the macro-expanded +line, and to know the origin of any particular part of the resultant line. + +The modification entries can apply to the inserted text of other modifications, +so one can have modifications of modifications. Wherever a modification is +made, the original character (in ``curr_source_line`` or inserted text) is +replaced by a marker character (``ATTENTION_MARKER``) so that if that spot is +reached by sequential scanning from preceding text, one is cued to look at the +modification list to find the text that follows. + +In extreme cases the data structure can get quite complex, with modifications +on modifications. In cases involving real-world macros, however, it remains +fairly simple. + +``ATTENTION_MARKER`` is a one-character lexical escape sequence. It has to be, +because a macro invocation can be as short as a single character, and the +``ATTENTION_MARKER`` overwrites the beginning of the macro invocation. There +are also two-character lexical escape sequences, which begin with the +``LE_ESCAPE`` character (which is zero). The second character of the escape +sequence is one of the following: + +* | ``LE_END_OF_LINE``, which marks the end of the primary source line. +* | ``LE_NEWLINE``, which represents the newline character at the end of the + primary source line. +* | ``LE_END_OF_INSERTION``, which marks the end of the text inserted by a + source line modification. +* | ``LE_END_OF_TOKEN``, which separates tokens in macro text (see below). +* | ``LE_INERT_MACRO``, which indicates a macro name that should not be + expanded (see below). +* | ``LE_NULL``, which indicates a null (zero) character in the source line\ + ``.`` + +To ensure that the ``ATTENTION_MARKER`` and ``LE_ESCAPE`` characters are always +lexical escapes, rather than characters accidentally introduced into the +lexical data structure because of special characters in the input file, the +front end does two rewrites on input: + +* | The newline character at the ends of input lines is transformed into a + lexical escape sequence. This frees up the newline character to be used as + ``ATTENTION_MARKER``. +* | A null (zero) character in an input line is flagged with an error and + replaced by a space. In modes that allow null characters in the source + (e.g., gcc mode), the character is replaced by an ``LE_NULL`` escape + sequence (and an original line modification is created, so that column + numbers can be determined correctly). + +The characters newline and null were selected for use as these reserved +characters because they are already special in the C language and in character +sets in general. No other pair of characters can be guaranteed not to occur in +source files, especially when international character encodings such as SJIS +are considered. + +Note that because ``LE_ESCAPE`` is a zero character, the source line and +inserted text cannot be considered to be simple null-terminated strings. Also +note that the ``ATTENTION_MARKER`` and ``LE_ESCAPE`` characters will naturally +terminate the accumulation of the characters of a token. + +The modification entries of both kinds are dynamically allocated, used, and +then freed when the next logical source line is about to be read. For each +kind, there is an available list (freed entries that are available for reuse), +an allocation routine, and a free routine. See + +* | ``add_orig_line_modif``, +* | ``free_orig_line_modif``, +* | ``add_source_line_modif``, +* | ``free_source_line_modif``, and +* | ``rem_source_line_modif``. + +The majority (75%?) of source lines have no modifications of any kind (not +counting comments), so the code in the lexical routines is optimized to deal +efficiently with that case. + +Routines ``assoc_source_line_modif`` and ``nested_source_line_modif``, along +with the associated macros ``go_into_insertion`` and ``leave_insertion``, +handle the low-level tasks of determining where to go next in the input stream +based on the source modifications. + +The current position in the input stream in given by ``curr_char_loc``. +Ordinarily, it points to somewhere within ``curr_source_line``, but when macros +are expanded it can point to somewhere in ``macro_buffer`` or to a +dynamically-allocated argument. + +In the text of macro arguments and the replacement text for macros, the +individual characters have already been tokenized once. To ensure that the +tokenization is done the same way if and when it is done again, the text of +each token in source line modifications is followed by an ``LE_END_OF_TOKEN`` +lexical escape sequence. That escape sequence terminates the accumulation of +characters to make up a token, and is then ignored as part of the white-space +skip at the start of the next call of ``get_token``. End-of-token sequences +are usually removed by ``gen_pp_output_for_curr_line``, but an individual +end-of-token will be output as a blank if there is the possibility that two +adjacent tokens might be misparsed without one. See the discussion in +``macro.c`` for further information. + +In some obscure cases involving thwarted macro expansion, it is necessary to do +a true insertion into the source line, rather than the usual replacement of +some characters by some others. Fortunately, this only needs to be done at the +beginning of the line, so a simple mechanism suffices: a source line +modification with a NULL location is taken to be an insertion before the first +character of the line. Only one such insertion is allowed per line, and if one +exists, ``line_start_source_line_modif`` points to it. + +``curr_source_line`` and ``macro_buffer`` are actually dynamically-allocated +arrays, and can be expanded (by reallocation) as necessary. Therefore, there +is no limit to the length of source lines or of macros except that imposed by +available memory. + +Lexical Analysis +================ + +"Lexical analysis" includes the reading of source lines and the breaking of +them into lexical tokens. It is also closely tied to preprocessor directives +and to macro processing, since they are invoked at the lexical level, and are +defined in terms of tokens. The source code for lexical processing is in +``lexical.c``, and associated declarations are in ``lexical.h``. + +Getting Tokens +-------------- + +The primary interface to the lexical routines is the routine ``get_token``, +which fetches and returns the next token of input. When compiling C, these +tokens are the input for syntax analysis. When preprocessing only, the tokens +are fetched (by a loop in ``cpp_driver`` in ``preproc.c``), and then discarded; +calling ``get_token`` repeatedly forces the reading of input lines and the +necessary preprocessing on each line, and each modified line is then written +out just before the next line is read. ``do_preprocessing_only`` and +``generate_pp_output`` will be TRUE in that case. ``get_token`` is used in +both cases; in fact, it is used for all fetching of tokens in all contexts. + +When ``get_token`` is called, it scans the next token of input and returns its +kind. The kind of token is also saved in ``curr_token``. See the enumeration +``a_token_kind``, in ``lexical.h``, for the list of token kinds (e.g., +``tok_identifier``, ``tok_lparen``). + +Much of the rest of the processing is dependent on several global switches, as +described in the following paragraphs. Most of these switches are defined in +``preproc.h``. + +If ``fetch_pp_tokens`` is TRUE when ``get_token`` is called, a preprocessing +token (pp-token) is fetched instead of a regular token. Constants are not +converted (and numeric ones are returned as pp-numbers); adjacent string +literals are not concatenated; keywords are not recognized; and errors are not +issued for malformed tokens. Also, ``start_of_curr_token`` and +``end_of_curr_token`` are set to point to the beginning and end of the current +token, and ``len_of_curr_token`` is set to its length. + +If ``expand_macros`` is TRUE, preprocessing macros are expanded as they are +scanned. The caller sees only the tokens after expansion. If a macro name is +preceded by an ``LE_INERT_MACRO`` escape sequence, the macro is not expanded +and the identifier is returned to the caller with ``curr_token_is_inert_macro`` +set to TRUE. + +When ``fetch_pp_tokens`` is FALSE, ``do_string_literal_concatenation`` controls +whether adjacent string literals are concatenated. + +If ``in_preprocessing_directive`` is TRUE, the definition of white space is +changed to that for within preprocessing directives; i.e., keywords are not +recognized, and newline, ``#``, and ``##`` are recognized and returned as +tokens. However, if ``caching_pragma_tokens`` is TRUE, a pragma is being +recoded as a token cache, and this requires disabling some of the processing +that is normally done when ``in_preprocessing_directive`` is TRUE -- +identifiers will be looked up and ``#`` and ``##`` are not returned as tokens. +And if ``recognize_keywords_in_pragma`` is also set, keywords are looked up and +returned as keyword tokens rather than as identifier tokens. (This is required +for dealing with ``#pragma`` directives involving C or C++ constructs that must +be scanned by the compiler's normal scanning routines; for instance, it is used +for processing the pragmas that control template instantiation.) + +If ``in_pp_if_expression`` is TRUE (indicating that we are inside a +preprocessing ``#if`` expression), integer constants will get an implicit ``L`` +suffix, and undefined identifiers will be returned as the integer constant +``0L``. + +If ``exp_header_name`` is TRUE, then ``"..."`` will be scanned as a header name +for an ``#include`` (``tok_header_name``). Other tokens will be processed +normally. ``exp_system_header_name`` is similar, for header names of the form +``<...>``. + +If ``exp_digit_sequence`` is TRUE (indicating a string of decimal digits) then +the digits will be scanned as a ``tok_digit_sequence`` (used in the ``#line`` +directive). Other tokens will be processed normally. + +For tokens that are literal constants, the struct ``const_for_curr_token`` is +set to the value of the constant (if ``fetch_pp_tokens`` is FALSE). This +global variable is also set for the literal portion of user-defined literals +(when user_defined_literals_enabled is TRUE), along with +ud_lit_op_sym_for_cur_token, which designates the symbol for the literal +operator or literal operator template chosen to produce the value of the +user-defined literal. When ud_lit_op_sym_for_curr_token designates a raw +literal operator or a literal operator template, const_for_curr_token is a +ck_string constant whose value is the actual spelling of the literal part of +the toke; otherwise, it is the value of that literal part. + +For tokens that are identifiers, the corresponding symbol header is looked up +in the symbol table and ``locator_for_curr_id`` is set accordingly. For +user-defined literal tokens, ``locator_for_curr_id`` is set to designate the +*literal-operator-id* of the literal operator or literal operator template +denoted by the literal's *ud-suffix*. It can be used later to refer to the +current definition of the identifier or operator (if there is one) or to enter +a new definition for the identifier or operator. + +The routine ``get_token`` is basically one large ``switch`` statement that fans +out based on the current character of input. The various cases are: + +* | For operators and similar special-character tokens, ``get_token`` looks at + the next character or two and selects the appropriate token. +* | For the lexical escape sequences (the ATTENTION_MARKER character or the + two-character LE_ESCAPE sequences), ``skip_white_space`` is called. These + characters are not all actually white space, but it simplifies processing + to let that routine handle them. All reads of new source lines are + requested by ``skip_white_space``. +* | For numbers, ``scan_number`` is called (it handles decimal, octal, and + hexadecimal integer literals, as well as decimal and hexadecimal + fixed-point and float literals). ``scan_number`` will determine the kind + of number, accumulate its characters, and, if appropriate, call the proper + conversion routine in ``literals.c`` to convert the literal constant string + to internal form in ``const_for_curr_token``. It also handles recognition + of numeric user-defined literals and, when one is recognized, setting + ud_lit_op_sym_for_curr_token. +* | For identifiers, the characters are accumulated and ``find_symbol`` is + called. This yields a list of symbols with the given name. The list is + then searched for a definition that is a macro or keyword. If the + identifier is a macro and if macro expansion is required, + ``macro_invocation`` (in ``macro.c``) is called. Note that because this + look-up finds both macros and other uses of identifiers, a symbol only has + to be looked up once; it does not have to be looked up once to see whether + or not it is a macro, and then again later to see if it is something else. +* | For quoted tokens (character constants and string literals, and the wide + versions thereof), an appropriate scanning routine is called, which in turn + calls ``accum_quoted_string``. The latter accumulates the characters of + the string, checking for escapes and the like. When a string literal or + wide string literal is scanned outside of preprocessing mode, ``get_token`` + will call ``concat_adjacent_string_literals``, which will check if the next + token is another string literal. If so, the adjacent strings will be + concatenated into a single string literal token. scan_char_constant + recognizes user-defined character literals and sets + ud_lit_op_sym_for_curr_token, as appropriate. In order to handle merging + of suffixes across concatenated string literals, the similar task for + user-defined string literals is handled by concat_adjacent_string_literals, + except when fetch_pp_tokens is TRUE; in that case, get_token performs the + requisite processing, as string literals are not concatenated in that mode. +* | When a ``#`` appears as the first non-white-space character on a line, a + call to ``pp_directive`` (in ``preproc.c``) is made to process a + preprocessing directive. + +One very important requirement is that ``get_token`` be fast. About 30 percent +of total time time in the front end is likely to be spent in ``get_token`` and +its subordinate routines. Every effort has been made to make those routines +fast, and in particular, to avoid unnecessary subroutine calls. As an example, +simple white space (blanks and horizontal tabs) is skipped in ``get_token`` +itself, rather than incurring the overhead of calling ``skip_white_space``. + +The handling for pp-tokens and normal tokens differs in a number of ways, but +the most fundamental of those is the information returned to the caller. The +kind of token is returned in both cases. However, for identifiers and literal +constants, where additional information must be returned to precisely specify +the token, the returned value in the pp-token case is the actual characters of +the token, and in the normal token case it is something one step removed from +that: a symbol locator for identifiers, or a constant entry for constants. +This is useful, but it's also necessary -- when scanning normal tokens, and in +particular identifiers and literal constants, there are some cases where it is +necessary to skip forward to the next token to see if it has some effect on the +current one. For example, after scanning a string literal, one must look ahead +to see if the next token is another string literal, and if so, one concatenates +the two. Since the next token may be on another line, it's clear that the +original string for the token in the current source line may be gone by the +time the next token is reached. Therefore, the locator or constant entry form +is necessary even inside of ``get_token``. + +Token Lookahead and Caching +--------------------------- + +Sometimes syntactic analysis requires lookahead -- it requires the fetching +of one or more tokens past the current position to discriminate between two +possible parses. + +This comes up even in C, although the lookahead there is limited to a single +token. For example, when a statement begins with an identifier, one must look +past the identifier to see whether or not the next token is a "``:``" -- if so, +the identifier is a label. (The routine ``next_token`` provides this +capability.) + +In C++, lookahead is needed in many more contexts, and is not limited to +one-token lookahead. In addition, there are some language constructs that must +be saved in some lexical form when they appear, and then parsed later on the +basis of the saved information. The most obvious example is the bodies of +member functions declared inside a class: their name binding cannot be done +until the entire class declaration has been scanned, so the easiest +implementation is to save the member function bodies and then parse them when +the closing brace of the class is reached. + +A construct called a *token cache* supports all these needs for lookahead, as +well as recording the tokens of template definitions and other syntactic +elements for delayed use. a_token_cache is a data structure that represents a +sequence of tokens. The tokens in a cache are represented by a list of shared +tokens (a_shared_token), each one describing an immutable token state (this +includes not just the token kind, but also any additional information required +to fully specify the token, e.g., a symbol locator for an identifier or a +constant entry for a literal constant). A similar data structure, +a_reusable_token_cache, is used for the tokens of a template definition or +delayed construct. + +To build a nonreusable token cache, one declares a variable of type +a_token_cache. Then one reads through tokens in the usual way, calling +get_token to fetch each token, and then calls cache_curr_token before advancing +to the next. When enough lookahead or caching has been done, one can put all +the tokens in the token cache back on the front of the input stream by calling +rescan_cached_tokens. + +get_token does not read directly from nonreusable token caches (although it +does do so with reusable token caches; see below). Instead, +rescan_cached_tokens adds the current token to the end of the cache and then +pushes the cached tokens in LIFO order onto the global +cached_token_rescan_stack (implemented as a stack instead of a list for +efficiency reasons), and finally calls get_token to fetch what was the first +token of the cache from the cached token rescan stack as the current token. As +long as the global rescan stack is non-empty, get_token will fetch a token from +the rescan stack (by calling get_token_from_cached_token_rescan_stack) instead +of scanning a new token from the current source line. + +``next_token`` is a simple user of the token caching facility; it caches the +current token, fetches the next and remembers its kind, then pushes the cache +back on the input stream to restore the original token (and also the next one, +behind it). + +``unget_token`` puts the current token back on the front of the input stream, +so that in effect afterwards there is no current token (although it doesn't +actually go so far as to change ``curr_token``). It is used in some unusual +error situations that want to fabricate and insert an identifier token where +one was missing in the source. + +Two routines are available to cache sequences of tokens delimited by given +tokens: + +* ``cache_token_stream_until_matching_token`` +* ``cache_token_stream_with_coalesce_flag`` + +``cache_token_stream_with_coalesce_flag`` is not intended to be called +directly. Instead, it is called by one of two interface routines: + +* ``cache_token_stream`` +* ``cache_token_stream_coalesce_identifiers`` + +``cache_token_stream`` is used to cache tokens until one of a specified set of +stop tokens is found. This is used, for example, when caching the body of a +class or function template when all tokens up to a closing brace should be +cached. In such situations, the only special processing that is needed is to +keep track of paired delimiter tokens (e.g., ``{}``, ``[]``, ``()``) so that, +for example, the closing brace of an inner block is not incorrectly taken as +the end of the template body. + +When the stop token could appear within a template argument list, additional +processing must be done to determine whether a "``<``" that is encountered is +the start of a template argument list or simply a less than sign. In order to +determine this, the identifiers found while the tokens are cached must be +coalesced (the identifier coalescing process is described later in this +chapter). This special kind of token stream caching is done by calling +``cache_token_stream_coalesce_identifiers``. The process of coalescing an +identifier involves fetching some number of tokens. Because these tokens are +not fetched directly by ``cache_token_stream_coalesce_identifiers``, a +mechanism is needed to get access to those tokens. +``begin_caching_of_fetched_tokens`` is called to request that a cache of +fetched tokens be automatically constructed. Each new token returned by +``get_token`` is added to a special cache. The token stream is then cached by +recording the starting token sequence number, getting each token, and +coalescing each identifier that is encountered until the stop token is found. +Once the starting and ending token sequence numbers are known, the tokens in +that range are extracted from the special cache. +``end_caching_of_fetched_tokens`` is then used to indicate that the automatic +caching of tokens is no longer needed. + +As noted above, token caches are also used to represent template definitions +and other syntactic constructs that require delayed processing. The tokens +that comprise the syntactic element are cached when it is scanned and are +rescanned later when needed. While other token caches are rescanned once and +discarded, reusable token caches may be rescanned over and over again. +Reusable token caches should be constructed by calling the factory function +shared_obj with reusable set to TRUE (this acts as a sanity +check to ensure the token cache is used in the intended way, but they are +otherwise built in exactly the same manner as other token caches). The +reusable token cache object (of type a_reusable_token_cache) is then +constructed from the result. + +Various scenarios can cause multiple reusable token caches to be pending rescan +at a given time; calling rescan_reusable_cache pushes a reusable token cache +onto the global reusable_cache_stack. get_token first rescans tokens from the +(nonreusable) cached token rescan stack, as described above. When this stack +is exhausted it rescans tokens from the reusable cache at the top of the +reusable cache stack by calling get_token_from_reusable_cache_stack. When all +of the entries in a reusable cache have been scanned the cached token rescan +stack is restored and the entry is popped off of the reusable cache stack. +Token scanning then resumes with the next token on the cached token rescan +stack. + +Reusable and nonreusable token caches may be freely intermixed; template +instantiations may occur while scanning tokens from a cache and a template +instantiation will usually create new caches, as needed, when doing +look-aheads, as described earlier. + +Source Positions +---------------- + +Each time a token is fetched, the global variable ``pos_curr_token`` is set to +the source position of the first character of the token. A source position +means a sequence number (which can be converted to a file name and line number) +and a column number from the original source line. The position is determined +by the macro ``macro_line_loc_to_source_pos``. In the simplest and most common +case, a pointer to the starting character of the current token can be converted +easily to a source position by using the current sequence number and +determining the column number by taking the difference between the pointer and +the start of ``curr_source_line`` and applying an offset to convert the byte +offset into a logical column number using the macro ``logical_column_offset`` +(which can in some cases result in a call of ``f_logical_column_offset``). In +more complicated cases, ``conv_line_loc_to_source_pos`` is called, and it uses +the information in both ``orig_line_modif_list`` and ``source_line_modif_list`` +to determine the source position. The source position of something in a +preprocessing modification is taken to be the position of the first character +of the original source line that contains the macro invocation that leads to +the given modification. + +The Input Stack +--------------- + +``open_file_and_push_input_stack`` is called to enter both the primary source +file and ``#include`` files -- by ``fe_init`` (in ``fe_init.c``) and by +``proc_include`` (in ``preproc.c``), respectively -- and it in turn calls +``open_file_for_input`` and ``push_input_stack`` to do the work; when end of +file is reached, ``pop_input_stack`` is called. + +``open_file_for_input`` loops to try each possible include file directory when +attempting to open an include file; it also contains code for the (optional) +implicit inclusion feature of automatic template instantiation, permitting a +series of suffixes to be tried in each directory. + +Together, the push/pop routines manage the ``input_stack``, which contains +information about the current nesting of input files. To limit the number of +open files, they will reuse files once a few files have been opened (see +``MAX_INCLUDE_FILES_OPEN_AT_ONCE``). The storage for ``input_stack`` is +dynamically allocated and is reallocated larger as needed. + +If the options requesting ``makefile`` information or a list of header files +were specified on the command line, ``do_preprocessing_only`` will be TRUE but +``generate_pp_output`` will be FALSE. Either ``list_makefile_dependencies`` or +``list_included_files`` will be TRUE. ``push_input_stack`` writes out the +appropriate information to the preprocessing output file. + +The front end recognizes certain idioms used to allow an include file to be +included more than once with all of the includes after the first having no +effect. When one of these idioms is recognized the front end will ignore +subsequent attempts to include the file again. The front end recognizes two +commonly used mechanisms used to allow a file to be included multiple time: +placing the entire contents of a file inside a ``#ifndef`` or ``#ifdef``, and +use of the ``#pragma once`` directive. A simple state machine is used to +determine whether subsequent includes of a given file may be suppressed. The +state information is maintained in the input stack entry. +``suppress_subsequent_include_of_file`` is called for each file to be included. +If it returns TRUE then the call of ``push_input_stack`` is skipped and the +include is suppressed. See the comments that precede ``find_include_history`` +for additional information. + +Skipping White Space +-------------------- + +``skip_white_space`` is called to skip over any white space and get to the +start of the next token (some simple cases of white space are skipped in +``get_token``, for efficiency). Besides the usual white-space characters, it +also handles the skipping of comments, calling ``read_logical_source_line`` to +fetch the next line of input, and going into and leaving source modifications +upon encountering lexical escape sequences (e.g., ``ATTENTION_MARKER`` to go +into a modification, ``LE_ESCAPE/LE_END_OF_INSERTION`` to leave a +modification). + +``skip_white_space`` tracks the kind of white space it has skipped over +(comment/other) and sets global variable ``kind_of_white_space_skipped``. This +information is useful in the macro processing routines, where white space can +be significant. Note that ``kind_of_white_space_skipped`` is not necessarily +set correctly if one calls ``get_token``, since ``get_token`` does some +white-space skipping on its own. + +When ``skip_white_space`` recognizes one of the ``lint`` comments + + | ``/*ARGSUSED*/``, + | ``/*NOTREACHED*/``, + | ``/*VARARGS*/``, or + | ``/*VARARGS`` *n*\ ``*/`` + +``add_curr_token_pseudo_pragma`` is called. It adds a pending pragma entry to +the current token pragma list. Later, the pending pragma entry is removed via +a call to ``extract_specific_pragmas``, and processed (by setting global state +information or flags in IL entries). For ARGSUSED and VARARGS, that's done in +``record_lint_argsused_and_varargs_state``. For NOTREACHED, it's done in +``check_lint_notreached_state``. + +Hanging Delete +-------------- + +If global variable ``delete_source_from_loc`` is non-NULL, the text that +extends from that location in the current line to the position immediately +preceding ``curr_char_loc`` is to be deleted. This is referred to as a +"hanging delete", and is used in deleting macro invocations. This flag is +necessary because the complete text of a macro invocation must be deleted (to +be replaced by the expansion of the macro), but the macro invocation may span +several lines, and the macro routines are not in control when ends of lines are +passed in ``skip_white_space``. By setting this flag, the macro routines can +request that the text of a macro invocation be correctly deleted even if it +spills over onto additional lines. When the deletion is handled at line end, +``delete_source_from_loc`` is updated to point to the start of the new source +line so that the hanging delete remains in effect. + +Whitespace keywords +------------------- + +C++/CLI has "whitespace keywords," which are keywords made up of two words +separated by whitespace but considered a single keyword, for example "``ref``\ +``class``". These are scanned by ``scan_whitespace_keyword``. One interesting +detail is that the characters that make up the token (which can be spread over +multiple lines because of the embedded whitespace) are replaced by a canonical +spelling of the keyword containing a single embedded space, the same way that a +macro is replaced in the input line by its expansion. That allows processing +that deals with tokens on the pp-token level to handle those whitespace keyword +tokens like any others, as a contiguous sequence of characters. + +Textual Preprocessing Output +---------------------------- + +When compiling C to intermediate language, there is no need to assemble the +actual logical source line that results after preprocessing. All that is +required is that the tokens of that line can be extracted. But when +preprocessing only is being done, the preprocessed line is output from +``curr_source_line`` and the information in ``source_line_modif_list``. [#f1]_ +``gen_pp_output_for_curr_line`` assembles and puts out the effective line, +calling ``gen_pp_line_info`` to generate line-identification directives when +the file/line of the current line does not immediately follow that of the line +previously output. ``gen_pp_output_for_curr_line`` is called by +``read_logical_source_line`` right before a new line is read; it is also called +when the input stack is pushed and popped for the starts and ends of input +files. + +There are some special problems in producing the preprocessing output line when +preprocessing directives are passed to output. This must be done for certain +directives (like ``#pragma``) that the preprocessor cannot process. If a +directive of that type contains a multi-line comment, the parts of the +directive preceding and following the comment must be written out on the same +line. In this case, the part preceding the comment will be written without a +terminating newline, and the part following the comment will be written later +on the end of that line. + +Reading Logical Source Lines +---------------------------- + +Aside from its primary function of reading the next logical source line and +processing trigraphs and line splices, ``read_logical_source_line`` also calls +``gen_pp_output_for_curr_line`` to output the previous line (if needed), clears +the modification lists, and handles ends of files. It can be told to stay at +the end of a file (rather than popping out to the enclosing file) on end of +file, if that is desirable (as it is when scanning a comment that is unclosed +at end of file). On the ultimate end of file, it returns a special end-of-file +line (containing just an ``LE_END_OF_LINE`` lexical escape sequence) in +``curr_source_line``, and sets ``after_end_of_all_source``. + +If ``curr_source_line`` is too small, ``expand_curr_source_line`` is called to +reallocate it, and ``adjust_curr_source_line_structure_after_realloc`` (in +``macro.c``) is then called to walk through the data structure associated with +``curr_source_line`` and change any pointers to ``curr_source_line`` to point +to the proper addresses within the new allocation for ``curr_source_line``. + +Multibyte characters in source code +----------------------------------- + +When ``MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED`` is TRUE, multibyte character +sequences are accepted in comments, string literals, character constants, +identifiers, and header names. Multibyte character sequences are not wide +characters (e.g., Unicode); they are sequences of one or more characters, +appearing in a string of characters of the usual ``char`` size, and +representing single logical characters. For example, in the Japanese SJIS +encoding, the sequence 82A9 (in hexadecimal) represents a single Kanji +character: the first character (82) is in a range that indicates it is the +first character of a two-character sequence. Typically, the characters in the +ASCII code set will be accepted as themselves in multibyte character encodings, +i.e., they will be sequences of length one. Since each character sequence in a +multibyte character string need not have the same length (and some encodings +have explicit shift-state-change characters), a multibyte character string can +be understood only by scanning it from beginning to end, advancing over one +logical character at a time. + +Moreover, since characters after the first in a multibyte sequence can look +like simple ASCII characters, it is not generally okay to look for an ASCII +character by doing a simple ``strchr``-type search. The lexical routines count +on being able to do this for only two characters: the zero/null character (this +is guaranteed by the C standard; characters after the first in a multibyte +character sequence are not allowed to be zero) and the newline character (this +is effectively guaranteed by the fact that one must be able to read files +containing multibyte character sequences and discern the ends of lines without +tracking the multibyte character state as each character is read). [#f2]_ + +To advance over logical characters, one needs a routine that will determine the +length of the multibyte character sequence at a given location. This is done +by the macro ``mbc_length`` and routine ``f_mbc_length``. In the usual +configuration, that routine is implemented by calling the standard C library +routine ``mblen``. ``mbc_length`` and related routines are used to do special +processing in the following places: + +* | In ``read_logical_source_line``, the line splice ("``\``") and trigraph + ("``?``") characters are ignored if they appear in the middle of a + multibyte character sequence. +* | In ``skip_white_space``, the closing character for a C-style comment + ("``*``") is ignored if it appears in the middle of a multibyte character + sequence. ("``//``" end-of-line comments require no special handling, + because the end-of-line marker is rendered as a lexical escape + sequence,which cannot appear within a multibyte character sequence.) +* | In ``accum_quoted_string``, ``scan_char_literal``, ``scan_string_literal``, + ``conv_single_char``, and ``conv_single_wide_char``, the characters inside + quoted strings are scanned as multibyte characters as necessary. The + routine ``mbc_to_wide_char`` is used to convert a multibyte character + sequence in a wide string literal or wide character constant to the + appropriate ``wchar_t`` character. In the usual configuration, + ``mbc_to_wide_char`` is implemented by calling the C library routine + ``mbtowc``. +* | In ``get_token``, the scanning for identifiers uses ``is_identifier_char`` + to recognize identifier characters beyond the basic character set. + ``make_canonical_identifier`` handles encoding the multibyte characters + appropriately in the name string for the identifier. + +Note that not all source code is scanned as multibyte characters, because that +would take too much time. The special scanning is done only in the contexts +listed above. For the line-splice and trigraph cases, when the line-read +routine sees those characters it goes to the beginning of the line and steps +through the characters of the line to find out where the character falls in the +multibyte character sequences, but that processing is done only if a potential +line splice or trigraph appears. Note also that there are configuration +options to turn off the special processing for several of the special +characters, for cases where the encoding guarantees no confusion on the +particular character. + +If the encoding has locking state-change characters (e.g., JIS), each C-style +comment and string is assumed to begin in the initial shift state. This +follows a requirement stated in 5.2.1.2 of the ANSI/ISO C standard + +If ``UNICODE_SOURCE_SUPPORTED`` is TRUE, the multibyte encoding selected is the +UTF-8 encoding of Unicode. UTF-16 is also supported, in the little-endian or +big-endian format, and is converted immediately to UTF-8 on input. The type of +source code in a file can be specified by a byte order mark (BOM) at the start +of the file, or by way of the ``--unicode_source_kind`` command-line option. +There is also a macro ``DEFAULT_UNICODE_SOURCE_KIND`` that can be used to +establish the default for files without a byte order mark. + +When ``UNICODE_SOURCE_SUPPORTED`` is set to TRUE, identifiers and file name +strings in the front end are represented in UTF-8. For file names, there is +the expectation that the standard system fopen will be able to deal with UTF-8 +file names. If that isn't the case, some host-specific code may have to be +added to ``fopen_interface``. (For Windows-hosted configurations, specific +code is provided which calls the ``_wfopen`` function.) + +If UTF-8 identifier name strings are somehow undesirable (e.g., a back end or +linker can't handle them), the macro +``IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS`` can be set to FALSE, in which case +characters in identifiers outside of the basic character set will be rendered +in the ``\u``\ *xxxx* or ``\U``\ *xxxxxxxx* form also used for UCNs. Note, +however, that the encoded form will come out in diagnostic messages that name +an entity in the source. + +If ``DEFAULT_UNICODE_SOURCE_KIND`` is ``usk_none``, source files without a byte +order mark are assumed to be encoded in ISO-8859-1 (otherwise known as +Latin-1), which matches the first 256 code points in Unicode. +(``LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED`` should be set to a locale that +matches ISO-8859-1.) Such a mode (which is the default for Windows-hosted +versions) is a hybrid mode in which some files are Unicode and some are not, +and in which therefore a character like a u-umlaut would be encoded differently +depending on the kind of source file it appears in. Such characters in +non-Unicode files are converted to UTF-8 (or the identifier encoding ``\u``\ +*xxxx*) when they appear in identifiers and file names. In hybrid +configurations, characters in textual preprocessing output are always converted +to UTF-8 if ``DEFAULT_UNICODE_SOURCE_KIND`` is not ``usk_none``, and to +ISO-8859-1 otherwise. Characters that cannot be represented in ISO-8859-1 in +the latter case are converted to "``?``". + +When ``UNICODE_SOURCE_SUPPORTED`` is TRUE, +``NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE`` may be set to TRUE to +indicate that non-Unicode files are encoded in some character set other than +ISO-8859-1.This feature requires the ability to translate other character sets +to and from Unicode. Such a facility is provided in newer versions of the +Windows API (Microsoft version 1400 and above) so this feature is enabled when +the front end is built with ``EDG_WIN32`` set to TRUE. In identifiers and file +names, native characters are translated to their UTF-8 equivalent. In wide +strings, native characters are translated to their Unicode equivalent. In +narrow strings, they are left in their original form. + +When Microsoft extensions are enabled and ``EDG_WIN32`` is TRUE, this feature +enables support for the Microsoft setlocale pragma, which specifies the +character encoding to be used for the translation to and from Unicode. + +Raw Listing Output +------------------ + +``gen_raw_listing_output_for_curr_line`` is called to write source lines to +``f_raw_listing`` when raw listing information is requested; it calls +``gen_expanded_raw_listing_output_for_curr_line`` to write out the +macro-expanded form of the source line if the source line has some +modifications. + +``gen_rlisting_line_info`` writes information about transitions into and out of +include files; it is called by ``push_input_stack`` at beginnings of files and +by ``pop_input_stack`` at ends of files. + +Inserting Text into the Token Stream +------------------------------------ + +``insert_string_into_token_stream`` may be called to cause a string to be +scanned as tokens that are processed as part of the input stream either before +or after processing the current token. When scanning tokens from the string, +macros are optionally expanded and adjacent string literals are concatenated. +The string cannot contain preprocessing directives, and trigraphs are not +recognized. + +This mechanism is used is used to internalize C++ code generated by the C++ +metadata reader (see :ref:`cppcli-assembly-decls`) in the functions +``scan_top_level_metadata_declarations`` and ``get_definition_of_class``. + +Utility Routines +---------------- + +There are several routines in ``lexical.c`` that are utility routines for +syntax analysis, and are not directly related to ``get_token``: + +* | ``flush_tokens`` is called on the occurrence of a syntax error, and throws + away tokens (by calling ``get_token``) until a token is found that seems an + appropriate place to restart. The current stop token set pointed to by + ``curr_stop_token_stack_entry`` contains the set of tokens on which to stop + the flush (it is maintained by the macros ``add_stop_token``, + ``remove_stop_token``, and the routines ``push_stop_token_stack`` and + ``pop_stop_token_stack``). Recursive-descent routines place the tokens + they expect in the set of stop tokens; then, if an error occurs, the flush + will stop at a point that one of the recursive descent routines will + recognize. ``flush_tokens`` should not in general be called directly; + ``syntax_error`` should be called to report a syntax error, and it will + call ``flush_tokens``. +* | ``flush_until_matching_token`` is called by ``flush_tokens`` (and can be + called from elsewhere) to flush from an opening token such as a left + parenthesis to the matching closing token. +* | ``loop_token`` is a utility routine that can be called at the bottom of a + loop for a repeated syntactic construct (e.g., a comma-separated list). It + tests for a particular token and takes it if it is found. +* | ``required_token`` is a utility routine that should be called when a + particular token is required to appear next. It checks for that token, and + issues an error if the token is not found. +* | ``next_token`` returns the next token after the current one, without + disturbing the current token. This is used in recursive descent parsing + routines to look ahead at the next token to decide between two paths + through the syntax. +* | ``next_two_tokens`` is similar to ``next_token`` except that if the next + token matches a value supplied by the caller the token after the next token + is fetched and returned to the caller. This is used when scanning vacuous + destructor references in C++ where it is necessary to look for a tilde + following a ``::`` to recognize a nonclass vacuous destructor reference + [#f3]_. +* | ``push_lexical_state_stack`` and ``pop_lexical_state_stack`` are used to + enter and exit a new lexical context. These are used, for example, when + instantiating a template and when switching from fetching normal tokens to + scanning a preprocessing directive. + +Scanning Names in C++ +===================== + +Unlike C, in which all names are simple identifiers, in C++ the names of +entities are often more complicated. Names may be preceded by one or more +qualifiers such as namespace and class qualifiers (e.g., ``A::B::i``) and +global scope qualifiers (e.g., ``::i``); class qualifiers may include template +references (e.g., ``A::i``); and the name that follows these qualifiers +may be more complicated than a simple identifier: it may also be an operator +name (e.g., ``operator+``), a conversion function name (e.g., ``operator +int``), a (C++11) literal operator name (e.g., operator ``""``\ _km), or a +destructor name (e.g., ``~A``). An arbitrarily complex name is referred to as +a "generalized identifier". The process of collecting the tokens of a +generalized identifier and replacing them with a single ``tok_identifier`` +pseudo-token is referred to as "coalescing" the generalized identifier. A +hierarchy of routines is provided that scan generalized identifiers: + +* | ``is_generalized_identifier_start`` determines whether the current token + begins a generalized identifier and, if so, scans the tokens that comprise + the generalized identifier and records its description in + ``locator_for_curr_id``. +* | ``coalesce_and_lookup_qualified_name`` calls + ``is_generalized_identifier_start`` and, if the generalized identifier + includes a qualifier, the name after the qualifier is looked up in the + scope specified by the qualifier. Names without qualifiers are not looked + up. [#f4]_ +* | ``coalesce_and_lookup_generalized_identifier`` is used to scan and look up + a generalized identifier. It calls ``coalesce_and_lookup_qualified_name`` + and looks up the name if it does not include a qualifier. Names that + include qualifiers will have already been looked up by + ``coalesce_and_lookup_qualified_name``. + +The arguments to these routines include options used to specify the kinds of +names that may be accepted and, for the coalesce-and-look-up routines, a lookup +mode that specifies the type of name lookup to be performed. The ``options`` +parameter specifies a set of "generalized identifier" (GID) flags. The GID +flags specify several different types of information: + +* | The kinds of identifiers that should be recognized. For example, ``~A`` + may be recognized as a destructor, or the tilde may be an operator. +* | The kinds of identifiers that are allowed. For example, are qualified + names allowed in this context? Are operator names allowed? The difference + between constructs that are "recognized" and those that are "allowed" is + that constructs that are not recognized (i.e., ``~D``) are not considered + identifiers by ``is_generalized_identifier_start`` while constructs that + are not allowed are considered identifiers but cause errors to be issued + indicating that the particular type of identifier is not permitted in the + current context. + +.. _recognizing-generalized-identifiers: + +Recognizing Generalized Identifiers +----------------------------------- + +``is_generalized_identifier_start`` is the lowest-level generalized identifier +routine and does most of the work. As the name suggests, +``is_generalized_identifier_start`` is used to determine whether the current +token is the beginning of a generalized identifier. + +``is_generalized_identifier_start`` is actually a macro that first checks +whether the current identifier has already been coalesced. If it has, the +macro immediately returns TRUE; otherwise it calls +``f_is_generalized_identifier_start``, which performs the rest of the +processing described here. + +For these examples ``is_generalized_identifier_start`` returns TRUE and sets +the current token to ``tok_identifier``: + + | ``i::iX::i`` + | ``::X::i`` + | ``::A::B::i`` + | ``A::i`` + | ``A::operator =`` + | ``A::operator int`` + | ``A::operator ""_km // When user-defined literals are recognized`` + | ``A::~A`` + | ``NS::i`` + | ``NS::A::i`` + | ``operator =`` + | ``operator int`` + | ``operator ""_km // When user-defined literals are recognized`` + | ``~A // When destructors are recognized`` + | ``A`` + | ``NS::A`` + | ``~int // When nonclass vacuous destructors are recognized`` + | ``int::~int // When nonclass vacuous destructors are recognized`` + | ``A::``\ *anything else except* ``* // Error`` + +For these examples FALSE is returned and current token is set to +``tok_ptr_to_member``: + + | ``X::*`` + | ``A::* // Template reference will be coalesced`` + +For these examples FALSE is returned and the current token is not changed: + + | ``::new`` + | ``::delete`` + | ``~A // When destructors are not recognized`` + | *anything else* + +Determining whether or not the current token is the start of an identifier may +involve scanning all of the tokens that comprise the identifier. Consequently, +all of the tokens that make up an identifier are scanned the first time that +``is_generalized_identifer_start`` is called for a given identifier. The +information needed to describe the generalized identifier is recorded in the +symbol locator, and on subsequent calls the information from the locator is +used to return the appropriate value to the caller. When a sequence of tokens +is coalesced the original tokens are replaced with a single ``tok_identifier`` +or ``tok_ptr_to_member``. The resulting token and related state information in +the locator is referred to as a "pseudo-token". When +``is_generalized_identifier_start`` determines that the thing being scanned is +an identifier, the current token is set to ``tok_identifier``, the locator is +updated with a description of the identifier, and the return value of the +function is TRUE. The fields in the locator that are set are + +* | ``is_qualified_name`` +* | ``is_global_qualified_name`` +* | ``is_file_scope_qualified_name`` +* | ``is_operator_name`` +* | ``is_destructor_name`` +* | ``is_udl_operator_name`` +* | ``is_class_member`` +* | ``parent`` +* | ``has_been_coalesced`` +* | ``is_vacuous_destructor_reference`` +* | ``is_nonclass_destructor`` + +When coalescing a qualified name such as ``A::xxx`` the result is a locator +whose symbol header points to the name ``xxx``, and whose ``parent`` points to +the ``A``. If ``A`` is a class, ``is_class_member`` is TRUE and +``parent.class_type`` points to the type of ``A``. If ``A`` is a namespace, +``is_class_member`` is FALSE and ``parent.namespace_ptr`` points to the +namespace entry for ``A``. The final identifier (``xxx``) is not looked up. +Instead, the information is preserved in the locator so that, if necessary, +``xxx`` can be looked up by ``coalesce_and_lookup_qualified_name``. + +``is_generalized_identifier_start`` coalesces template class references of the +form ``A::i``, [#f5]_ ``A``, and ``A::i`` (but not simply ``A``) by +calling ``coalesce_template_id``. These references must be coalesced to +determine whether the template reference is the beginning of a qualified name +(e.g., ``A::i`` cannot be determined to be a qualified name until +the ``::`` is seen.) The result of a template class reference is an incomplete +instantiation. A complete instantiation is only generated when it is required +for a name to be looked up. A complete instantiation will be generated for +references like ``A::X::Y``, because ``X`` must be looked up in ``A``. A +complete instantiation will not be generated (at least not here) for references +like ``A::X``. The complete instantiation is delayed until ``X`` needs to +be looked up (typically in ``coalesce_and_lookup_qualified_name``.) A template +argument list may also follow a function template name or an overloaded +function name in which one of the members of the overload set is a function +template. This is known as "explicit specification of function template +arguments". Unlike template class references, a template function reference +cannot be resolved to a given template instance when the template argument list +is scanned (because function templates can be overloaded). As a result, when a +function template argument list is scanned, a pointer to the list is retained +in the symbol locator, but the reference is not otherwise resolved at this +point. + +The pointer operator used when declaring a pointer-to-member looks a lot like a +qualified name; the only difference is that the final identifier is replaced +with an asterisk (``*``). For example, a pointer-to-member operator may look +like ``A::B::C::*``. Because of this similarity pointer-to-member +operators are also coalesced by ``is_generalized_identifier_start`` even though +they are not considered identifiers. When a pointer-to-member operator is +coalesced the current token is set to ``tok_ptr_to_member``, the +``parent.class_type`` field of the locator points to the type specified in the +operator (e.g., ``A::A::B::C`` in the previous example), and the return +value of the function is FALSE. + +The operators ``::new`` and ``::delete`` look like qualified names but are +actually operators. When called for these operators, +``is_generalized_identifier_start`` leaves the current token unchanged and +returns FALSE. + +C++ allows a destructor to be called for classes that have no destructor and +for nonclass types. We refer to this kind of destructor call as a "vacuous +destructor" reference. A GID option is used to indicate whether a vacuous +destructor should be recognized and, if so, whether it must be a nonclass +destructor. Vacuous destructor references, which are only allowed in field +selection operations, differ from other generalized identifiers in several +important ways: + +* | the qualifier, if present, and the identifier that follows the tilde may be + a nonclass type. +* | the nonclass type found may be a keyword that names a basic type (e.g., + ``int::~int``). + +When a vacuous destructor reference is coalesced, the ``parent.class_type`` +points to the type specified by the name *after* the ``::~`` because it must be +possible to record the type of the vacuous destructor reference for cases that +do not include a qualifier. + +Coalesce-and-Look-Up Routines +----------------------------- + +The coalesce-and-look-up routines are: + +* ``coalesce_and_lookup_qualified_name`` +* ``coalesce_and_lookup_generalized_identifier`` + +After ``is_generalized_identifier_start`` has determined that the current token +does in fact begin an identifier the coalesce-and-look-up routines are used to +do the appropriate kind of name lookup. The difference between the two +routines is that ``coalesce_and_lookup_qualified_name`` will only perform a +lookup of the final identifier of a qualified name while both qualified names +and names without qualifiers will be handled by +``coalesce_and_lookup_generalized_identifier``. + +One of the arguments passed to these routines is an "identifier lookup mode", +an enumeration that specifies the kind of lookup to be performed. The lookup +mode is translated into a set of "identifier lookup" (IDL) flags that are +passed to the symbol table lookup routines. An error is issued by +``coalesce_and_lookup_qualified_name`` if the name lookup fails, except in +``ilm_tentative_type`` mode. [#f6]_ In all other respects the various +identifier lookup modes are identical as far as the coalesce and lookup +routines are concerned. ``coalesce_and_lookup_generalized_identifier`` does +not issue an error if the lookup of an unqualified name fails. + +Generalized Identifier Errors +----------------------------- + +``check_for_generalized_identifier_errors`` is called by the +coalesce-and-look-up routines and also by ``is_generalized_identifier_start`` +to ensure that the identifier that has been scanned meets the constraints +specified by the GID "allowed" flags. The error tests are done by comparing +the current GID options with the information in the locator. When one +generalized identifier routine calls another, it masks off the error flags so +that the errors are diagnosed only once by the highest-level routine. + +``check_for_template_declarator_errors`` is called by the coalesce-and-look-up +routines to verify that the declarator in a template declaration does actually +refer to a template entity that is permitted in a template declaration. These +checks are done to provide diagnostics that are more helpful than those that +would result if the identifier were simply returned to ``declarator``. + +Template References +------------------- + +``coalesce_template_id`` coalesces references to class and function templates. +The kind of reference to be coalesced is determined based on a symbol that is +provided. If the symbol refers to a function template or an overload set +containing one or more function templates, +``coalesce_template_function_reference`` is called, otherwise +``coalesce_template_class_reference`` is called to handle class template +references or to diagnose the improper use of a template argument list. + +Template Class References +^^^^^^^^^^^^^^^^^^^^^^^^^ + +``coalesce_template_class_reference`` coalesces template class references, such +as ``A``, into identifiers for which the ``specific_symbol`` field of +the locator points to a specific instance of the template. A class template +name is usually, but not always, followed by a template argument list. The +argument list may be omitted in declarations of the class template, + +.. code:: c++ + + template class A; + template class A { /* ... */ }; + +in which case the name refers to the class template (not to one of its +instances), and may also be omitted inside the definition of a class template +or in the definition of a member function or static data member of the class +template, + +.. code:: c++ + + template class A { + A* a; // Equivalent to A* a + int A::* pma; // Equivalent to A::* pma + }; + +in which case the name refers to the current instance of the class template +(e.g., ``A``). + +There are several contexts in which template class references must be +coalesced. Most calls of ``coalesce_template_class_reference`` are from +``is_generalized_identifier_start`` and include a template argument list or are +part of a qualified name. ``coalesce_template_class_reference`` is also called +by ``coalesce_and_lookup_generalized_identifier``, which scans simple class +template names such as ``A``, and by ``scan_tag_name``, which scans specific +definitions of a template classes such as ``class A {}``. Like the +generalized identifier routines, ``coalesce_template_class_reference`` accepts +a set of generalized identifier options as one of its arguments. The only +value actually used is ``GID_TEMPLATE_ARGS_OPTIONAL`` which specifies that the +template argument list may be omitted for a reference that is not within the +class template definition. As described above, the argument list may always be +omitted within the class template definition. + +The template argument list, if present, is scanned by calling either +``scan_template_argument_list`` or ``scan_unknown_template_arg_list:`` + +* | ``scan_unknown_template_arg_list`` is used when scanning the template + argument list associated with a "nonreal" template -- a class template that + is a member of a proxy or nonreal class. A nonreal template is created in + contexts in which a member class template of a template parameter dependent + class is used. For example: + + .. code:: c++ + + template struct A { + typename T::X tx; + }; + + | In such cases, it is assumed that ``T::X`` is a template because there are + no cases in which a less than sign could immediately follow a type name, so + the "``<``" must indicate the beginning of a template argument list. When + scanning a nonreal template argument list there is no information available + about the number of template parameters, their types, etc. All of this + must be inferred by scanning the actual arguments. Consequently, no + attempt is made to determine whether the number of arguments, the types, + etc. are correct. The disambiguation routines are used to determine + whether a given argument is a type or nontype (see below for the use of + this function in scanning function template references.) +* | ``scan_template_argument_list`` is used when scanning the template + arguments of "real" templates. Default values are provided for any omitted + arguments. If the type of a nontype parameter depends on another template + parameter, the type of the parameter is generated by rescanning a token + cache constructed when the template was defined. Similarly, if the type of + the default value, or the default value itself, involves a template + parameter, the default value is also generated by rescanning a token cache + constructed when the template was defined. + +Both routines call ``scan_template_argument_constant_expression`` for nontype +arguments and ``type_name`` for type arguments. ``find_template_class`` is +called, once a complete template argument list has been created, to find the +type that corresponds to the particular set of arguments. If no such type +exists, ``find_template_class`` creates one. In either case the symbol +associated with the type is returned. + +Function Template References +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``coalesce_function_template_reference`` coalesces references to functions that +employ an explicit template argument list. Unlike class templates, function +templates may be overloaded; therefore an explicit template argument list does +not necessarily identify a specific template instance. The function type of +the instance is also needed to determine the actual instance that is being +referenced, but is not available when the template argument list is scanned, so +the argument list must be retained until some later point when the function +type is also available. + +``scan_unknown_template_arg_list`` is used to scan explicit template argument +lists because, in general, there is no template parameter list that can be used +to determine the kind of argument expected (type vs. nontype), or the type of +the argument (for nontype arguments). As with nonreal template argument lists, +the disambiguation routines are used to determine whether a given argument is a +type or nontype. ``type_name`` is used to scan arguments that are types. +``scan_nontype_template_argument`` is used to scan nontype arguments. Function +template argument lists differ from those of class templates in that, for +function templates, the corresponding template parameter list is not available +when the template argument list is scanned. The presence of the template +parameter list for a class template makes it possible to convert nontype +arguments to the type of the corresponding template parameter (or to a special +nonreal type in the case of a nonreal argument list). For function templates, +such conversions cannot be done until the specific function template to be used +has been identified. Consequently, when a nontype argument is scanned it must +be retained in a form that permits the conversion to be done later. +``scan_nontype_template_argument`` returns a pointer to ``an_arg_operand``, a +data structure used by the expression scanning routines to represent an +expression. The ``constant_is_an_arg_operand`` field in the template argument +is set to indicate that the nontype argument is represented in this form. + +Variable Template References +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``coalesce_variable_template_reference`` coalesces references to variable +templates. ``scan_template_argument_list`` is used to scan the template +arguments. ``find_template_variable`` is used to produce a variable symbol for +the instantiation of the given variable template using the specified template +arguments. + +Conversion of Literal Constants +=============================== + +The source file ``literals.c`` contains the code to handle conversion of +literal constants to internal form. The external form is a string of +characters, a token, as accumulated by ``get_token`` and its subroutines; the +internal form is a structure of type ``a_constant``, representing an integer, +fixed-point, float, character, or string constant. + +``conv_integer_literal`` converts decimal, octal, and hexadecimal integer +constants. Aside from computing the value of the constant, it also recognizes +the trailing ``L`` and ``U`` suffixes, and determines the type of the overall +constant (on the basis of its value and the suffixes). For ``pcc`` mode, the +rules for determining the type of a constant are modified slightly. + +``conv_fixed_point_literal`` converts fixed-point constants (an Embedded C +feature), calling ``fxp_string_to_fixed_point`` or +``fxp_hex_string_to_fixed_point`` in ``fixed_pt.c`` to actually do the +conversion. It also recognizes the various suffixes (``k``, ``r``, ...), and +sets the type of the result accordingly. + +``conv_float_literal`` converts float constants, calling ``fp_string_to_float`` +or ``fp_hex_string_to_float_point`` in ``float_pt.c`` to actually do the +conversion. It also recognizes the ``L`` and ``F`` suffixes, and sets the type +of the result accordingly. + +``conv_char_literal`` converts character constants to an integer value. It +uses ``conv_single_char`` to fetch and convert each character. If there is +more than one character, they are assembled into one integer (with ordering +controlled by ``TARG_CHAR_CONSTANT_FIRST_CHAR_MOST_SIGNIFICANT``). + +``conv_string_literal`` converts string literals. It receives a count of +effective characters in the string from its caller (as computed by +``accum_quoted_string``), so it can dynamically allocate the space for the +string before scanning it. It also uses ``conv_single_char`` to convert each +character of the string. + +``conv_single_char`` converts one character to an integer value. This includes +simple characters, escapes like ``\n``, and octal and hexadecimal escapes. At +the moment, this routine assumes that the host and target character sets are +the same. + +``concat_string_literals`` concatenates several string literals (in constant +form in a token cache) into one string. This is used for the concatenation of +adjacent string literals. + +Preprocessing Directives +======================== + +The source file ``preproc.c`` contains the code to handle preprocessing +directives (except for ``#define``, which is handled in ``macro.c``). +Associated declarations are in ``preproc.h``. + +The routine ``cpp_driver`` is the top-level routine when the front end is being +run as a C preprocessor, typically to produce a preprocessed output file. It +calls ``get_token`` repeatedly until end of source, with +``do_preprocessing_only`` set to TRUE to indicate that preprocessing only -- +and not compilation -- is being done. + +Normally, when preprocessing output is required, ``generate_pp_output`` is TRUE +as well. But ``cpp_driver`` is also called when preprocessing is being done to +generate a list of ``#include`` files or a list of ``makefile`` dependencies. +In those cases, ``generate_pp_output`` is FALSE, and either +``list_included_files`` or ``list_makefile_dependencies`` is TRUE. + +``pp_directive`` is called (by ``get_token``) when a ``#`` is encountered at +the beginning of a source line. It sets ``in_preprocessing_directive``, +fetches the directive identifier and identifies it by calling +``identify_dir_keyword`` (which uses a simple linear search), calls the +appropriate routine to process the directive (which may call +``ignore_harmless_trailing_comment`` to ignore extra text at the end of the +directive), calls ``end_of_directive_processing`` (to check for any extra text +that is not harmless), and then resets ``in_preprocessing_directive``. If a +syntax error is detected in a directive, ``some_error_in_curr_directive`` is +set; this suppresses the check for extra text at the end of the directive. + +When the text of a preprocessing directive is not to be written to the +preprocessing output, ``do_not_put_curr_line_in_pp_output`` is set -- initially +in ``pp_directive`` and on each subsequent line, because of multi-line +comments, in ``read_logical_source_line``; the flag is checked by the output +routine, ``gen_pp_output_for_curr_line``. In the rare case that the text of a +preprocessing directive should be passed to output (because some C compiler +should see the directive to handle it), ``pass_pp_directive_to_output`` is set +to TRUE while the directive is scanned. + +Each preprocessing directive has an associated processing routine (for example, +``proc_if`` handles the ``#if`` directive). + +``proc_pragma`` processes the ``#pragma`` directive. This is an area that +would be configured for specific versions. Unrecognized pragmas must be +ignored (no error should be generated). When preprocessing only, ``#pragma`` +directives are passed to output (see ``pass_directive_to_output``). + +``proc_ident`` processes the ``#ident`` directive, although the "processing" it +does is to ignore it. When preprocessing only, ``#ident`` directives are +passed to output (see ``pass_directive_to_output``). + +``proc_error`` passes the rest of the directive to an error reporting routine, +as a catastrophic error, which terminates the compilation. + +``proc_line`` scans a line number, treating it as a digit-sequence rather than +an integer constant; optionally, it also scans a file name, calling +``copy_header_name`` to extract the file name from the header name token. It +puts this information into the input stack and calls routines in ``il.c`` to +remember the proper correspondence between source sequence numbers and file +name/line number pairs. + +``proc_include`` scans the file name (as a header name in one of two forms) and +then calls ``push_input_stack`` to request reading from that include file. It +calls ``copy_header_name`` to extract the file name from the header name token. + +``proc_undef`` scans an identifier, looks it up, and removes any macro +definition under that name. It will not remove predefined macros. (A +predefined macro has a source position with a sequence number of zero, and a +column number of ``SP_COL_PREDEFINED_MACRO``.) + +``#if`` and related directives depend on the ``pp_if_stack``, which is a stack +of entries describing active ``#if`` constructs. The current depth of the +stack is indicated by ``pp_if_stack_depth``. Each ``#if`` that has not yet +been closed by a corresponding ``#endif`` appears on the stack. The stack +entry indicates whether or not the ``#else`` for the ``#if`` has already +appeared, and has the source position of the ``#if`` for use as the error +position if the corresponding ``#endif`` never appears. In ANSI C or C++ mode, +each ``#if`` is required to be ended in the file in which it was begun: to +implement this, the variable ``base_pp_if_stack_depth`` contains the value of +``pp_if_stack_depth`` as of the beginning of the current source file. The part +of the stack between ``base_pp_if_stack_depth`` and ``pp_if_stack_depth`` is +considered the only active part of the stack at any given moment. ``#endif``\ +s encountered must be associated with ``#if``\ s in the active part of the +stack, and all of the ``#if``\ s in the active part of the stack must be closed +by the end of the source file (this is checked by +``verify_that_all_pp_ifs_were_closed``, which is called from +``pop_input_stack``). In ``pcc`` mode, the ``#if``\ s do not have to match up +within each file; they only have to come out right at the end of the +compilation. + +The various if-directives are handled by ``proc_if``, ``proc_ifdef`` (which +also handles ``#ifndef``), ``proc_else``, ``proc_elif``, and ``proc_endif``. +``proc_if`` and ``proc_elif`` call ``scan_if_expr``, which calls +``scan_pp_expression`` (in ``expr.c``) to scan the if-expression (there are +restrictions on what can appear in such an expression). All of the +if-processors call ``perform_if`` once they know whether or not the ``#if`` +should be executed; ``perform_if`` returns if the condition is TRUE, and calls +``skip_to_endif`` if the condition is FALSE. The latter reads lines looking +for preprocessing directives, counts nesting of ``#if``\ s, and looks for an +``#else`` or ``#endif`` that matches the current ``if``. + +A new preprocessing directive can be added by: + +* | Adding an enumeration constant to ``a_pp_directive_kind``; +* | adding a test for the directive keyword in ``identify_dir_keyword``; +* | adding a switch clause for the directive in ``pp_directive``; and +* | adding a routine ``proc_``\ *directive* to process the directive. Note + that the routine must take all the tokens in the directive (up to the + ``tok_newline``) before returning. + +AT&T Preprocessing Extensions +----------------------------- + +When ``ATT_PREPROCESSING_EXTENSIONS_ALLOWED`` is defined some of the AT&T +System V release 4 extensions to the preprocessor are supported. In that case, +the ``#assert`` and ``#unassert`` directives are handled by ``proc_assert`` and +``proc_unassert``. The data structure built for assert predicates is a simple +one: ``assert_predicates`` points to a list of ``an_assert_predicate`` entries, +each of which gives a predicate name and a list of ``an_assert_value`` entries +giving the value or values for the predicate. Entry and lookup are done with a +simple linear search. The token sequences involved are processed into +character strings (containing the token characters with a blank after each +token, and ended with a null character). Such character strings then represent +the token sequences, and can be saved and compared. +``scan_assert_predicate_reference`` is called from ``get_token`` on detection +of a ``#`` inside of an ``#if`` expression; it scans the reference and returns +1 or 0 depending on whether or not the predicate is defined with the indicated +token sequence. ``enter_assert_predicate`` can be called from ``fe_init.c`` to +enter predefined predicate names. + +C++/CLI Assembly Import +----------------------- + +The front supports the C++/CLI ``#using`` directive to import the metadata of +an assembly. This is done in function ``proc_using``. In C++/CLI mode, a +"core library assembly" (usually, ``mscorlib.dll``) is imported before input +source is processed, as well as any assemblies specified with the +``--preusing`` command-line option: Function ``process_preusings`` handles that +part (see also :ref:`cppcli-assembly-decls` and :ref:`cppcli-init`). + +Macro Processing +================ + +``macro.c`` contains the code to handle the ``#define`` preprocessing directive +and invocations of macros. ``macro.h`` contains associated declarations. + +Macro Definition Data Structure +------------------------------- + +When a macro is defined, the symbol created for it points to an entry of type +``a_macro_def`` (defined in ``symbol_tbl.h``). The macro's parameter list is +represented by a linked list of entries of type ``a_macro_param``; these give +the names of the parameters (needed only to verify that, on a benign +redefinition of the macro, the parameter names are the same). The replacement +text of the macro is a sequence of sections, each of which indicates text that +should be placed in the macro expansion at that point. Each section begins +with a byte that identifies the kind of section, as follows: + +.. list-table:: + + * - | ``rt_null`` (0) + - | marks the end of the replacement text. + * - | ``rt_text`` + - | indicates raw text that is part of the macro replacement text. The + next three bytes contain the count of characters following. + * - | ``rt_raw_argument`` + | ``rt_right_raw_argument`` + - | indicate that the raw (non-macro-expanded) text of an argument is to + be inserted at this point. This results from use of the ``##`` + operator, or from parameters scanned in ``pcc`` mode. The next three + bytes contain a number indicating the argument to be used (1 is the + first argument, 2 the second, etc.). ``rt_raw_argument`` is used for + a parameter to the left of ``##`` and for all parameters in pcc mode, + and ``rt_right_raw_argument`` is used for a parameter to the right of + ``##``. + * - | ``rt_stringized_raw_argument`` + | + - | indicates that the "stringized" text of an argument is to be inserted + at this point (this results from use of the ``#`` operator). The next + three bytes contain a number indicating the argument to be used. + * - | ``rt_argument`` + - | indicates that the macro-expanded text of an argument is to be + inserted at this point. The next three bytes contain a number + indicating the argument to be used. + +The ``##`` (paste) operator has no direct representation in the replacement +text; it just results in the two entities being placed next to each other. For +example, + +.. code:: c++ + + #define x(a,b) a ## b + +results in ``rt_raw_argument(1)`` followed by ``rt_right_raw_argument(2)``. + +White space in the replacement text is standardized. Any white space preceding +or following the replacement text is removed, as is any white space preceding +or following a ``##``, and any white space following a ``#``. All other white +space is replaced by a single space. + +Each token in the raw text (except the last, and any token preceding a ``##``) +is followed by an ``LE_END_OF_TOKEN`` lexical escape sequence. The raw text +immediately following insertions of arguments (except immediately following a +``##``) also starts with an end-of-token marker, to terminate the last token of +the inserted argument text. The end-of-token markers ensure that the tokens +will be tokenized the same way each time. For example, one problem comes up in + +.. code:: c++ + + #define z(a) ..##a + +The value of ``z(.)`` should be three "``.``" tokens, not the one token +"``...``". End-of-token markers are not used when in pcc mode, since ``cpp`` +does not operate on a token level. + +Similar standardization of white space and insertion of end-of-token markers is +done when the raw form of macro arguments is accumulated. This standardization +(of replacement text and macro argument text) makes it easier to check for +benign redefinitions and to generate the stringized form of arguments. + +The Macro Buffer +---------------- + +The global variable ``macro_buffer`` points to a large character array used as +a work area during macro processing. During macro definition, it holds the +replacement text. During macro invocation, it holds the expansions of all +macro invocations in the current line. It is dynamically allocated, and can be +expanded as necessary by calling ``expand_macro_buffer``. +``expand_macro_buffer`` will, in turn, call +``adjust_curr_source_line_structure_after_realloc`` to walk through the data +structure associated with ``curr_source_line`` and change pointers to +``macro_buffer`` to reference addresses within the new allocation for +``macro_buffer``. ``adjust_curr_source_line_structure_after_realloc`` +automatically finds such pointers in global variables and the public data +structure, but it has no way of knowing about local pointer variables. +Therefore, routines that have such variables register them by calling +``register_pointer_variable``, so that they will be found and adjusted if +reallocation is done. + +In order to reduce memory consumption when processing very complex and lengthy +macro expansions, the reallocation process for ``macro_buffer`` differs from +that of the other extensible buffers. While the other buffers are simply +reallocated, relying on the C runtime to copy the complete old contents to the +new allocation, ``expand_macro_buffer`` compacts the contents of +``macro_buffer`` by explicitly allocating a new buffer, copying data to the new +allocation only if it might still be in use, and then freeing the old buffer. +First, each existing source line modification (see +:ref:`lex-src-line-modifications`) is processed to copy its inserted text. +Within that text, only the ``ATTENTION_MARKER`` is copied from each portion +that is marked for deletion by another source line modification. (The +``ATTENTION_MARKER``\ s must be copied in order to allow scanning for inert +macro names, as described in :ref:`macro-invocations`.) As a result, the +original text of already-expanded macro invocations and the expanded text of +macro arguments will not occupy space in the new ``macro_buffer`` allocation. + +Second, text that is in the process of being constructed at the end of the +``macro_buffer`` is copied to the end of the data in the new allocation. Any +routines that build data structures incrementally, so that reallocation can +occur before the structure is complete (e.g., macro replacement text in +``proc_define``), must identify the beginning of such data using +``begin_macro_buffer_region`` and its completion with +``release_macro_buffer_region``. + +Macro Definitions +----------------- + +Macro definitions (``#define`` directive) are handled by ``proc_define``. It +scans the macro identifier, and looks it up in the symbol table (predefined +macros may not be redefined, and normal macros may be redefined only if the new +parameters and text match the existing parameters and text -- a "benign" +redefinition). If a "``(``" follows immediately (with no intervening white +space), the macro is function-like; its parameter names are accumulated as a +list. Otherwise, the macro is object-like. ``proc_define`` then scans the +replacement text and builds the replacement text string in ``macro_buffer``. +It calls ``mdefn_get_token`` to fetch tokens of the body and remember whether +or not any white space preceded each. White space is standardized, +end-of-token markers are inserted (if in ANSI C or C++ mode), parameter names +are recognized, and ``#`` and ``##`` are handled as described above. + +If in pcc mode, the opening and closing quoting characters of character +constants and string literals are scanned as single-character tokens, and the +insides of the quoted strings are tokenized. This results in recognition (and +later replacement) of parameter names within strings, as ``cpp`` does it. +Invalid tokens are passed textually to the replacement text (this is necessary +always, not just for this case), and skipped white space is kept in its +original form, so the contents of the string will be accurately rendered in the +final expansion of the macro. + +After the replacement text is accumulated, it is copied to +dynamically-allocated storage, and the macro definition is completed and +attached to the symbol. For a redefinition, the new parameter list and +replacement text are first compared textually against the old. If they match, +the new definition is thrown away. + +.. _macro-invocations: + +Macro Invocations +----------------- + +``macro_invocation`` handles the scanning and replacement of macro invocations. +It is called by ``get_token`` when an identifier that is a macro name is +scanned. + +The first thing that ``macro_invocation`` checks is whether or not the macro +name is "inert". The standard says that when a macro's name is generated in +its own expansion (directly or indirectly), it is forever after protected +against further expansion (it is inert). This is implemented by the +``assoc_macro`` field in the ``a_source_line_modif`` entry. A macro invocation +is replaced by the macro's expansion by creating a modification entry that +indicates the textual changes to be made to the source line or to a previous +modification. The ``assoc_macro`` field records the origin of any given +change, by pointing to the definition of the macro that generated the change. +Given a pointer to the name of a macro at the beginning of a possible macro +invocation, one can therefore determine whether it is in the main source line +or in a modification (or nested in several), and from that one can see whether +the macro name appears as part of its own expansion. If so, the macro name is +inert, and is left as an identifier. (Actually, it is replaced by an +``LE_INERT_MACRO`` lexical escape followed by the macro name. Once a macro +name is preceded by an inert-macro escape, it is considered inert every time it +is scanned, regardless of the context.) In pcc mode, macros are not considered +to be inert, and recursion is checked for by counting the number of nested +invocations of a given macro. + +If the macro name is not inert, processing for expansion continues. +``delete_source_from_loc`` is set to point to the beginning of the macro +identifier. This begins a "hanging delete" which will be closed when the end +of the macro invocation is found. At that point, the text of the hanging +delete will be replaced by the macro expansion, this replacement being +indicated by a source line modification entry. + +If the macro is object-like, no parameters need be scanned. However, there are +several special cases in object-like macros: For ``__FILE__`` and ``__LINE__``, +the proper expansion string is developed from the current position information +in the input stack; for ``defined``, which is an operator allowed in ``#if`` +expressions but handled as a pseudo-macro, the routine +``scan_defined_operator`` is called. It scans both forms of the ``defined`` +operator, and returns ``0`` or ``1``. Alternatively, if the identifier +``defined`` is not followed by appropriate tokens, it is left as an identifier +(see the discussion of ``check_for_following_parenthesis`` below). + +If the macro is function-like, ``check_for_following_parenthesis`` is called to +scan forward looking for a parenthesis that begins the argument list. If the +next token is not a parenthesis, then the macro name is left as an identifier. +However, this is complicated, because in skipping white space while looking for +a left parenthesis, we may have gone onto a new source line. We have to delete +the identifier before leaving the old source line, on the assumption that we +are scanning a macro invocation. If it turns out that the identifier is not +the start of a macro invocation, the identifier must be reinserted into the new +source line. + +Note the field ``sequence_id`` in ``a_source_line_modif``; it is an integer +sequence number indicating the sequence in which source line modifications were +added. This is useful in cases where modifications must be undone (as in +identifier un-deletion when a macro identifier is followed by something other +than a left parenthesis on the same line); one can find all entries with +sequence numbers greater than a certain number, and remove them. + +If a left parenthesis *is* found, the argument list is scanned, and this +requires a new data structure. An entry of type ``a_macro_arg`` contains +the text of a single argument value. That text exists in two forms -- as +"raw" text (not macro-expanded), and as "expanded" text. The +``a_macro_arg`` entries are dynamically allocated, and freed when no longer +needed (see ``alloc_macro_arg``, ``free_macro_arg``, and the variable +``avail_macro_args``). The text of macro arguments is not kept in +``macro_buffer``. + +Each macro argument is initially scanned in raw form. ``arg_get_token`` is +called, with macro expansion turned off, and the characters of each token, with +standardized white space and end-of-token markers, are placed in the array +pointed to by ``raw_text`` in the ``a_macro_arg`` entry (a +dynamically-allocated array, which can be reallocated as needed to expand it). +The scan stops when a comma or right parenthesis is found. A variable is used +to count the nesting of parentheses, so that non-zero-level commas and right +parentheses will not stop the scan. + +After the raw form of the argument has been accumulated, the raw text is +temporarily re-inserted in the source line and is re-scanned with macro +expansion on. The standard says that this must be done as if this text forms +the rest of the source file (i.e., the macro expansion is done in isolation +from the text following the raw argument value). This is implemented by having +the source modification entry that re-inserts the raw text have the field +``is_isolated_text`` TRUE. This will cause ``get_token`` and +``skip_white_space``, upon reaching the ``LE_END_OF_INSERTION`` lexical escape +sequence at the end of the raw text, to return ``tok_end_of_source`` instead of +continuing into the surrounding text. ``macro_invocation`` scans the entire +raw argument again, saving the text of the tokens scanned in the +``expanded_text`` array in the macro argument entry, and stopping when it gets +``tok_end_of_source``. If any modifications of the raw text were done because +of macro expansions (this can be determined by sequence id), they are removed. +This restores the raw text to its original state. In pcc mode, and when the +definition of the macro does not use the parameter in a context that requires +expansion,only the raw form of each argument is needed, so the rescan is not +done. + +In cases where the macro argument is the result of a previous macro expansion, +the rescan begins in the text inserted by the macro expansion modifications +rather than in the ``raw_text`` buffer. That ensures that the inertness test +can be done properly on macro names encountered in the rescanned source. Once +the rescan reaches the end of the insertions and would continue into the +primary source line, the input stream is switched to the tail of the +``raw_text`` buffer. (``raw_text`` is used instead of the primary source line +because macro arguments can be continued to subsequent source lines, and once +the next line is read the only copy of the raw argument text is in the +``raw_text`` array; the previous source line is gone.) + +This process is repeated for each argument. After all arguments are scanned +(or immediately for object-like macros), expansion is done. The length of the +expansion is first determined, and then the textual change is made, by building +up text in ``macro_buffer`` and placing a source line modification to delete +the characters of the macro invocation and insert the characters of the +expansion. + +For the special cases of predefined macros, the replacement text is already +available as a simple null-terminated string. For these cases, determining the +length and building the replacement string are easily done. + +For the other, more normal, cases, the length is determined and the expansion +string is built up by interpreting the sections of the replacement text in +order. For unexpanded uses of parameters, the ``raw_text`` is copied. For +macro-expanded uses of parameters, the ``expanded_text`` is copied. For +stringized parameters, ``stringized_arg`` is called; it copies the +``raw_text``, inserting the surrounding quotes and the additional backslashes +to protect quotes and backslashes in the string. + +The source line modification is then inserted to perform the macro expansion. + +When, in pcc mode, the expansion is for a top-level macro, +``expand_top_level_pcc_macro`` is called to expand any macro calls within the +body of the macro. A complete string for the expanded version is constructed +in an auxiliary buffer (``aux_buffer_for_pcc_macros``) and then copied back +into ``macro_buffer``, replacing the original expansion and any source line +modifications associated with it. Getting a fully-expanded string is necessary +to get pcc-like token pasting behavior across internal macro expansion +boundaries. A variant of this processing is also done in Microsoft mode. + +``macro_invocation`` then returns. It indicates to ``get_token`` whether or +not the inserted text should be rescanned. If ``macro_invocation`` already +knows what the next token should be, it returns it directly (``*rescan`` = +FALSE), thus saving ``get_token`` the time and trouble of scanning the token +text again. + +A utility debug routine ``print_markered_text`` is available for use in +printing out text strings that contain end-of-token markers and/or transitions +into or out of source modifications. + +Macro Position Tracking +----------------------- + +When ``FULLY_RESOLVED_MACRO_POSITIONS`` is TRUE, the front end keeps track of +the original location of text that is copied into macro expansions -- i.e., +either in a ``#define`` line or in an argument to a top-level macro invocation. +This "original position" information is reflected in the ``orig_seq`` and +``orig_column`` fields of ``a_source_position``. + +The principal data structure used in tracking original position information +through the various manipulations performed during macro definition and +invocation is ``a_macro_text_map``, which defines an extensible array of +``a_macro_text_map_entry`` elements (both defined in ``lexical.h``). Each of +the repositories of text associated with macro definition and invocation -- +macro definitions, the raw and expanded forms of macro arguments, and source +line modifications -- has an associated macro text map. + +A macro text map provides an ordered sequence of correspondences between +offsets in the associated text buffer and the original source locations from +which that text was copied. Each map entry defines a region of the associated +text buffer, beginning at offset ``start_of_region`` and extending up to but +not including the ``start_of_region`` of the next entry. The text at offset +``start_of_region`` originally came from the location given by +``corresponding_source_pos``, with a one-to-one correspondence of increasing +offsets and source column positions throughout the entry's buffer region. +Because the entries are ordered by buffer offset, the original source position +for a given offset can be efficiently found using a binary search (the +requisite ``bsearch`` predicate is +``compare_macro_text_map_entry_with_offset``, defined in ``lexical.c``). + +It will be helpful to trace the overall flow of information through the +definition and invocation of a macro before covering the details of how it is +accomplished. When a ``#define`` is processed, ``proc_define`` builds a text +map by incrementally recording the source position and offset in the +replacement text for each token of the definition that will be copied to the +macro expansion. A similar process occurs as each macro argument is copied to +the corresponding raw and expanded text buffers. During the interpretation of +the replacement text by ``macro_invocation``, as each section of text is copied +from the replacement text or macro argument, the corresponding entries from the +associated macro text map are copied, adjusting the offsets to reflect the +location of the text in the macro expansion (but leaving the original source +positions). Finally, when ``conv_line_loc_to_source_pos`` is called to compute +a source position for a given character location in the expanded text, the +macro text map in the source line modification is used to determine the +corresponding original source position. + +There are two principal patterns for adding entries to a text map. The simpler +pattern is when a sequence of map entries is copied from one map to another, +adjusting the offsets from being relative to the start of the source buffer to +being relative to the start of the target buffer. This technique is used to +create the text map for the source line modification containing the macro +expansion by copying portions of the text maps for the macro definition +replacement text and macro arguments. The function that performs this +operation is ``clone_macro_text_map_entries``, defined in ``macro.c``. + +The other pattern occurs when a text buffer is built incrementally by fetching +one token at a time and adding its text to a buffer. In this case, the map +entries are built to reflect either the source position of the token, if the +token is in source text, or a copy of the corresponding text map entry, if the +token comes from a source line modification (e.g., a macro argument in a macro +invocation appearing in the expansion of another macro invocation). This +technique is used to create the replacement text in a macro definition and for +both the raw and expanded text of macro arguments. It is also used when +processing a top-level macro invocation in pcc and Microsoft modes. + +Facilitating this process are the struct ``a_text_map_position_tracker`` and +the functions ``init_text_map_position_tracker``, +``add_token_to_macro_text_map``, and ``terminate_macro_text_map`` (all defined +in ``macro.c``). As each token is added to the text buffer, +``add_token_to_macro_text_map`` is called to determine whether a new entry is +required in the map for the new token: if the token is from the same source +line or source line modification as the preceding token and its offset within +the current buffer region is the same as the column offset from the region's +corresponding source position, then no new map entry is needed. If a new map +entry is required, either the appropriate map entries from the previous token's +source line modification are copied, using ``clone_macro_text_map_entries``, or +(for tokens from the current source line) a new entry is added covering the +appropriate region of the current source line for the preceding token(s). + +One complication in this processing occurs when ``macro_buffer`` is +reallocated, as described earlier. Because ``a_text_map_position_tracker`` +objects in use at the time ``macro_buffer`` is reallocated might contain the +offset of text in a source line modification's inserted text that occurs after +a portion of deleted text, and because that deleted text might be compacted as +part of the reallocation process, it is necessary to keep track of all active +position tracker objects so their current offset values can be adjusted if +necessary. + +This is done using the variable ``active_text_map_position_trackers`` (in +``macro.c``), which is the top of a stack of all trackers currently in use, and +the field ``num_active_position_trackers`` in ``a_source_line_modif``. +Whenever a token scan under control of a text map position tracker enters the +inserted text of a source line modification, its +``num_active_position_trackers`` is incremented, and it is decremented when the +scan leaves that source line modification. + +Whenever ``macro_buffer`` is reallocated, all the entries in each source line +modification's text map are examined and each offset adjusted, if necessary, to +compensate for the removal of deleted text. Furthermore, if the modification's +``num_active_position_trackers`` field is greater than zero, all the trackers +in the ``active_text_map_position_trackers`` stack are checked for references +to that source line modification and their offsets adjusted as needed. + +The text maps for macro definitions and the raw and expanded text of macro +arguments are completely self-contained: each has its own array of text map +entries and is associated with the containing data structure for the duration +of the compilation. (The array of entries for a macro definition is of fixed +size and is allocated in front-end memory, so that it will be stored in a +precompiled header, while the arrays for macro arguments are extensible.) A +different scheme is used for the text maps in source line modifications, +however. The reason for this decision is that the text map for a source line +modification may well be very large, with thousands or tens of thousands of +entries, while source line modifications themselves are ephemeral, generally no +longer needed once processing of the current logical source line has been +completed. The same reasoning led to the use of ``macro_buffer`` for the +inserted text of source line modification, so the memory management for source +line modification text maps is patterned after that of ``macro_buffer``. Just +as each modification's inserted text is simply a subrange of the text in +``macro_buffer``, the entries created during macro expansion are built in a +single map, called ``macro_text_map`` and defined in ``macro.c``, and each +modification's text map simply refers to a subrange of them. Initialization +and truncation of ``macro_text_map`` is done in parallel with the corresponding +operations on ``macro_buffer``. + +Macro Invocation Tree +--------------------- + +Maintaining the macro invocation tree is selected by setting +``MACRO_INVOCATION_TREE_IN_IL`` to TRUE. Each macro invocation is recorded in +an object of type ``a_macro_invocation_record`` (defined in ``il_def.h``), +giving the parent invocation, if any; the macro invoked; and its starting +position (as well as its ending position, if ``EXTRA_SOURCE_POSITIONS_IN_IL`` +is set to TRUE). (The "parent invocation" refers to the macro invocation in +whose argument list or expansion this macro invocation occurred. For macro +invocations occurring in program text and not in a macro argument list, +``parent_macro_index`` will have the value ``NO_PARENT_MACRO_INVOCATION``.) + +Each time ``macro_invocation`` is called to expand a macro, it calls +``register_macro_invocation`` to add an entry to the list and obtain the index +of the newly-added entry. This index and the macro invocation stack depth at +that point are stored into the source line modification created to hold the +macro's expanded text. These values are used by recursive calls of +``macro_invocation`` (to expand macro arguments) and by calls resulting from +rescanning expanded text to maintain the chain of parent invocations when the +macro name comes from a source line modification rather than directly from +source text. + +Because variable-length data is awkward to represent in the IL (and extensible +arrays are not possible in memory regions), the macro invocation records are +grouped into fixed-size blocks (``a_macro_invocation_record_block``, defined in +``il_def.h``). In the IL, these blocks are organized into a binary tree to +facilitate relatively-efficient random access by index. During front-end +processing, however, they are kept in a doubly-linked list: apart from +diagnostic output, which need not be terribly efficient, there is no need for +random access to the invocation records (and even diagnostic output will most +often refer to records near the end of the list, so long linear searches are +uncommon). It is more efficient to create the binary tree form once, after the +total number of records is known, than to balance the tree repeatedly while it +is being created. + +The ``macro_invocation_record_block``\ s are reorganized into a binary tree and +the relevant fields of ``il_header`` are set at the end of the translation unit +by a call to ``copy_macro_invocation_tree_to_il`` (defined in ``macro.c``). + +An additional effect of setting ``MACRO_INVOCATION_TREE_IN_IL`` is that +``a_source_position`` is extended to include the ``macro_context`` field. This +field reflects the macro invocation in whose expansion the source position +resides, i.e., it is logically simply a copy of the ``invocation_record`` field +of the containing source line modification. However, the special treatment +given to top-level macros in pcc and Microsoft mode, in which the expansion of +the macro is rescanned for expansion and the result is copied back into the +source line modification corresponding to the top-level macro invocation, means +that the subsidiary source line modifications are no longer available at the +time source positions are being computed. + +To avoid this problem, the macro invocation index that will be stored by +``macro_invocation`` into source line modifications is also kept in the +``macro_context`` field of each text map entry created for that invocation. +This information is preserved when the text maps for the subsidiary source line +modifications are cloned into the top-level modification by +``expand_top_level_pcc_macro``. This additional information allows the +``macro_context`` field in source positions to be set in the same way as the +original position information, by looking up the offset in the text map of the +top-level modification. (This is the reason that it is not permitted to set +``MACRO_INVOCATION_TREE_IN_IL`` to TRUE without also setting +``FULLY_RESOLVED_MACRO_POSITIONS`` to TRUE.) + +.. [#f1] Trigraphs and line splices are not undone and so do not appear in the + output. +.. [#f2] As mentioned previously, the actual newline character is replaced by + a lexical escape sequence beginning with ``LE_ESCAPE`` (zero) so that + the newline character can be freed up for use as ``ATTENTION_MARKER``. +.. [#f3] See :ref:`recognizing-generalized-identifiers` for more + information regarding vacuous destructors. +.. [#f4] A name is "looked up" by calling the appropriate symbol table lookup + routine, which updates the ``specific_symbol`` field in the symbol + locator. +.. [#f5] ``A`` is equivalent to ``A`` in the scope of a template class + instance. +.. [#f6] Which is used in looking up identifiers that might be types or might + be part of a declarator. diff --git a/doc/_sources/lower_il.rst.txt b/doc/_sources/lower_il.rst.txt new file mode 100644 index 0000000..d662f3e --- /dev/null +++ b/doc/_sources/lower_il.rst.txt @@ -0,0 +1,3916 @@ +.. + The following substitutions are used to align code that must be written + without using a code block because of embedded formatting. |_| is a + Unicode em space, while |.| is an en space. A combination of the two in + the leading white space of a line can closely approximate the desired + alignment of the following text. + +.. |_| unicode:: U+2003 +.. |.| unicode:: U+2002 + +.. _il-lowering: + +=========== +IL Lowering +=========== + + + + +When we started developing the C++ front end, one of the first design decisions +we had to make was what intermediate language it would generate. + +We already had a C front end (supporting the C89 version of the language) and a +Fortran front end. The C front end generated an intermediate language that +looked a lot like C, and the Fortran front end generated an intermediate +language that looked a lot like Fortran. The two intermediate languages were +compatible in the sense that they had the same structure and could be combined +into an intermediate language that is the union of the two. + +It seemed clear that the C++ intermediate language ought to be compatible with +the other two languages in that same sense, and that in fact it should be a +superset of the C intermediate language, since C++ is (almost) a superset of +C89. (When we talk about the C intermediate language or "C IL", we generally +refer to the IL to represent C89 constructs, not to the extensions supporting +the current C99 standard and other dialects like GNU C.) + +But how much of a superset? Since our IL philosophy for Fortran and C had been +to make "high-level" ILs that were very close to the source language, our +initial inclination was to make an intermediate language with lots of new C++ +features that would be the same sort of thing for C++. It seemed like the +obvious approach. When we analyzed that idea, and discussed it with customers, +however, we realized a few things: + +* | There's a big semantic jump from C to C++. Some of the C++ features are + much more complicated than C or Fortran features. Implementing them in a + back end would add a *lot* of work, and requires a lot of knowledge of the + C++ language. + | Since our corporate mission is to deliver front ends that take care of + all of the language issues and the attendant grief so that back ends + can just worry about code generation (and *its* attendant grief), it + didn't seem that we would be doing our full job by generating the + high-level C++ IL. +* | We had customers that had existing C back ends and were interested in + adding C++ with minimum development cost. + +Okay then, what about generating an IL that's very close to the C IL? After +all, because of USL's cfront, people view C++ as a language that can be +translated into C, maybe even as a macro language on top of C. Well, there are +problems with that, too: + +* | It hides information that is useful in generating symbolic debugging + information. (This has historically been a weakness of cfront-based + compilers, forcing programmers to debug using the generated C code.) +* | It makes it harder for a back end to use unconventional or aggressive code + generation techniques for C++ constructs. +* | It makes the front end less suitable for use in source-analysis tools (they + want to analyze the C++ source, not some version of it translated into C). + +We considered various levels of intermediate language between the full C++ and +full C extremes, and all were unsatisfactory in some way. Then David Callahan +of Tera Computer suggested that we do it both ways, that we generate a full C++ +IL and also supply a piece of software that translates that IL into the +existing C IL. + +Thus was born IL lowering. The front end proper generates a true C++ IL, and +IL lowering translates that IL into C IL, which can then be fed into a C back +end or the C-generating back end we use for testing. It should be noted that +although "lowering" is what's done, the output is still "high-level" -- it's +not as high-level as it was, but it's still at the level of the intermediate +language for C89. + +The IL lowering pass is optional. It need not be used if it's not wanted. The +IL utilities work with both versions of the IL. + +Since many C++ features go into IL lowering as abstractions and come out as C +code, IL lowering is actually choosing implementations of those features. The +implementations are at the same level as those in cfront. That is, they are +relatively "standard" implementations. As one would expect, the generated C +has some of the same complex unreadable quality that cfront output has, and the +same ridiculously complex expressions. The front end can even be configured to +produce constructs that are object-code compatible with cfront's. +Alternatively, the front end can generate code compatible with the IA-64 +(Itanium) ABI. + +IL lowering can also do inlining, though we firmly believe that that is +something that only a back end can really do properly. [#f1]_ + +The IL lowering pass seems to solve the problems raised: + +* | Both the C++ and C forms are available for those who prefer one form or the + other. In fact, one can use both forms, e.g., one could generate symbolic + debugging information from the C++ form and object code from the C form. +* | It allows customers to get a C++ compiler going in minimal time. +* | If the features implemented by IL lowering require some minor changes, the + changes can be made in IL lowering, which is relatively small, rather than + in the front end as a whole, which is quite large. +* | If a customer wants to attach a back end to the unlowered IL (either + initially or for an improved release of a compiler), the IL lowering code + serves as a guide to the tasks that must be done. + +Even though IL lowering will rewrite uses of non-C89 features, the C++-specific +fields of the IL are still present in the IL entries. Back ends should not +count on those fields being cleared; rather, they should ignore them and +consider only the fields that C uses. Viewed that way, the lowered IL should +contain nothing that would not show up in a C intermediate language tree. + +One catch: Dynamic initialization of entities in the middle of blocks is left +in its original form. This is not "incorrect" C IL, but is something that does +not come up in C89 programs. It was judged that back ends would be capable of +dealing with the ``stmk_init`` statements even if they appear after other +executable statements in a block, and the alternative was to make lowering of +initialization of aggregates to constants quite messy. + +The code for IL lowering is in ``lower_il.c``, and the associated declarations +are in ``lower_il.h``. Name mangling code is in ``lower_name.c`` and +``lower_name.h``. Code for lowering initializations, new/delete, and +constructors/destructors is in ``lower_init.c`` and ``lower_init.h``. Code for +lowering exception handling features is in ``lower_eh.c`` and ``lower_eh.h``. + +Certain higher-level constructs -- like variable-length arrays and complex +floating-point types -- from more recent C dialects (primarily C99, but also +GNU C) can also be lowered to C89-level IL. The code for this is done +primarily in ``lower_c99.c``. See :ref:`lowering-c-dialects` for an overview +of the constructs in this category that can be lowered. + +Finally, IL lowering can also ensure that boolean controlling expressions +(e.g., the expression controlling which way an if-statement goes) always +produce an integer value 0 or 1 (as opposed to "zero or nonzero" or "null or +nonnull"). This normalization -- enabled by setting +``LOWERING_NORMALIZES_BOOLEAN_CONTROLLING_EXPRESSIONS`` to TRUE -- can occur in +all modes (C++, C89, etc.) and usually involves adding a "``!= 0``" comparison +to the controlling expression. + +ABI support +=========== + +The front end and IL lowering support two ABIs (Application Binary Interfaces). +An ABI is a set of conventions for the runtime environment, which prescribes +class layout, access to virtual functions, name mangling, etc. Code generated +by two compilers that are compatible with a given ABI should, in theory, be +able to interact properly, and with libraries that are compatible with that +ABI. + +Up through version 3.0, the front end supported a single ABI and some minor +variants thereof. This ABI, referred to as the "cfront-like ABI," is an +extended version of the original ABI used by cfront. The extensions were +invented by EDG, and therefore the ABI does not conform to any industry +standard, other than in its general compatibility with what was once a *de +facto* standard. The variants of the cfront-like ABI are: + +* | cfront 3.0.1 compatibility, selected by setting + ``CFRONT_3_0_OBJECT_CODE_COMPATIBILITY`` to TRUE. +* | cfront 2.1 compatibility, selected by setting + ``CFRONT_2_1_OBJECT_CODE_COMPATIBILITY`` to TRUE. +* | If neither of those variants is selected, the default ABI is cfront-like + with some minor quirks eliminated, principally with respect to allocation + of space for virtual base classes. This variant was originally intended as + the default and best ABI, but in practice it hasn't been used very much, + and the IA-64 ABI (see below) is a better choice. + +As of version 3.1, the front end also supports the IA-64 ABI, described by +www.codesourcery.com/cxx-abi/abi.html. This is a modern ABI originally +designed for the Intel IA-64 ("Itanium") architecture, but now an industry +standard widely used on other architectures as well. In particular, the GNU +g++ compiler uses the IA-64 ABI on many platforms. This ABI is selected by +setting ``IA64_ABI`` to TRUE. Note that the fully-lowered implementation of +exception handling provided by EDG works with the IA-64 ABI, but does not +conform to the spec, and that versions using the C-generating back end do not +fully conform because of some layout cases not easily represented in C. + +Note that the IA-64 ABI requires linker support in the form of a feature (often +called COMDAT) that allows different object files to contain (identical) +definitions of certain functions and variables. The linker discards the +duplicates, ending up with a single definition. + +The ABI support in the front end changes from time to time as features are +added and bugs are fixed. The macro ``ABI_COMPATIBILITY_VERSION`` can be set +to a version number of the front end to keep the ABI frozen as it was at that +version. Source language features that require ABI changes made after that +version are disabled. + +What Does C++ IL Lowering Do? +============================= + +IL lowering is called at the end of processing of each "top-level" scope (i.e., +once at the end of each top-level function, and once at the end of the file +scope). It rewrites any C++ IL constructs in the scope as semantically +equivalent C IL constructs. (A similar process occurs for C99 IL; see +:ref:`lowering-c-dialects` for details.) + +IL Lowering is suppressed if there are errors in the source program, if the +dialect of C language being compiled doesn't require it, if preprocessing only +is being done, or if syntax-checking only is being done. + +Name Mangling +------------- + +(Code for name mangling is in ``lower_name.c`` and ``lower_name.h``.) + +"Name mangling" means transforming the names of C++ entities so that the names +include information on aspects of the entity's type and fully qualified name. +This is made necessary by the fact that the object code and C environments into +which a C++ program is translated typically contain fewer and simpler name +spaces than there are in the C++ language. Specifically: + +* | Overloaded function names are not allowed in C, and probably not in object + code. +* | Classes have their own scopes in C++, but not in the generated C form. An + entity ``x`` from inside a class must not conflict with an entity ``x`` + from the file scope, for example. +* | External names in C and (probably) in the object code form a completely + flat name space. The names of C++ entities with external linkage must be + projected onto that name space so that they do not conflict with one + another. A function ``f`` from a class ``A``, for example, must not have + the same external name as a function ``f`` from class ``B``. +* | Some C++ "names" are not names in the conventional sense of the word + (they're not strings of alphanumeric characters), e.g., ``operator=``. + +We can see that there are three problems here: + +* | Generating C code names that will not clash for non-external entities. + This is only a problem when generating C code. +* | Generating external names that will not clash. This is a problem whether + the output is C or object code. +* | Generating alphanumeric names for entities with strange "names" in C++. + This is a problem whether the output is C or object code, at least for + external names. + +As it happens, the name mangling process solves all three problems. It also +solves the problem of generating hidden names for some behind-the-scenes +language support in such a way that they will match up across separate +compilations (e.g., virtual function table names). + +Once name mangling has been done, the name linkage of C++ external entities is +changed to C external. + +Cfront-like ABI name mangling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The cfront-like ABI name mangling algorithm is the same as the one used by +cfront, and also matches the description in 7.2.1c of the ARM (except for some +minor details). The reader is referred there for a complete description. +Here, we just hit the highlights and the things that differ from or are +extensions to that description. + +Each type has a corresponding mangled encoding. For example, a class type +is represented as the class name preceded by the number of characters in +the class name, as in ``5abcde`` for ``abcde``. Simple types are encoded +as lower-case letters, as in ``i`` for ``int`` or ``f`` for ``float``. +``long long``, ``wchar_t``, and ``bool``, which do not appear in the ARM, +are encoded as "``L``", "``w``", and "``b``", respectively. The C++11 +types ``char16_t`` and ``char32_t`` are encoded as "``g``" and "``k``", +respectively. A ``std::nullptr_t`` type is encoded as "``n``", while the +C++/CLI ``__nullptr`` is encoded as "``j``". (In some Microsoft modes, +there are distinct integral types named ``__int8``, ``__int16``, +``__int32`` and ``__int64``. They are encoded as "``m1``", "``m2``", +"``m4``", and "``m8``", respectively.) 128-bit integers (in GNU +compatibility mode) are mangled with "``m16``" and "``Um16``" (signed and +unsigned, respectively). Type modifiers and declarators are encoded as +upper-case letters preceding the types they modify, as in ``U`` for +unsigned or ``P`` for pointer. In GNU C++ mode, complex types are encoded +with an "``x``" preceding the code for the corresponding real +floating-point type (e.g., "``xf``" for "_Complex float"). The ``long +double`` type is indicated by an "``r``" encoding. In addition to the type +declarators mentioned in the ARM (i.e., "``P``" for pointer, "``R``" for +reference, "``A``" for array, "``F``" for function, and "``M``" for +member), an "``E``" encoding has been added to indicate an rvalue +reference. For ref-qualified member function types, an optional "``_R``" +(for an lvalue req-qualifier) or "``_E``" (for an rvalue ref-qualifier) can +follow the "``F``" that indicates a function type. When C++/CLI is +enabled, the "``Ht``" encoding is used for tracking references, "``Hh``" is +used for handles, "``Hi``" is used for ``interior_ptr``, and "``Hp``" is +used for ``pin_ptr``. ``__underlying_type`` (enabled when type trait +helpers are enabled) is mangled as "``o``". See +``mangled_encoding_for_type``. + +Types specified using the C++11 keyword ``decltype`` are encoded in one of +three ways. When a ``decltype`` expression is either type-dependent or +value-dependent (i.e., it has some component that could be affected by the +C++11 SFINAE rules), it is said to be instantiation-dependent and it is +encoded using the character "``y``" or "``Y``" followed by a mangled +encoding of the expression ("``y``" is used when the expression is an +unparenthesized id-expression or a class member access; "``Y``" is used +otherwise). ``decltype`` expressions that are not instantiation-dependent +are encoded using the known underlying type or value (e.g., +``decltype(sizeof(int))`` is mangled using the mangled encoding for the +``size_t`` type, i.e., "``Ui``" in a front end that is configured to use +``unsigned int`` to represent ``size_t``). In a manner similar to +``decltype``, ``typeof``\ (*type*) is mangled using the encoding "``t``" +and ``typeof``\ (*expression*) is mangled using the encoding "``p``". The +"``u``" mangled encoding is also introduced in C++11 to represent the use +of ``auto`` as a type specifier when it appears in a *new-expression* that +is mangled because it appears in the context of an instantiation-dependent +expression (e.g., ``decltype(new auto(p1))``). The letter "``n``" is used +to encode the type for ``nullptr`` (i.e., ``std::nullptr_t``). The "``q``" +mangled encoding is used for the ``decltype(auto)`` notation. + +When a function parameter is a C++11 function parameter pack, its type is +represented by the encoding "``Dp``" followed by the function parameter type. + +Nested class types are encoded as a "``Q``" followed by a digit indicating the +depth of nesting, followed by a "``_``", followed by the mangled-form names of +the class types in the fully-qualified name of the class, from outermost to +innermost: + +.. code:: c++ + + class A { + class B { // Q2_1A1B + }; + }; + +The name of the nested class itself is mangled to the form described above with +a prefix ``__``, which serves to make the class name distinct from all user +names. The same mangling technique is used for namespaces. In cases where the +mangled entity is specified in the source code as being in the global scope +(e.g., ``p->::X::y``), and the entity is a selection or call operand, the +global scope indication is specified using the letter "``G``" as the first +qualifier in a qualified name; for example: + +.. code:: c++ + + int g(int); + template auto f(T p1) -> decltype(::g(p1)); + // f__tm__2_i__FZ1Z_YOcl_2_4g__GI1IO + +Local class names and scoped enumerators are encoded by following the name by +"``__L``" followed by a number (which has no special meaning; it uniquely +identifies the type within the function scope). This example (which requires +--c++11) shows a local class and its mangling within a function template: + +.. code:: c++ + + template void f(T) {} + void x() { + struct A {} a; // __12A__L1__x__Fv + f(a); // f__tm__15_12A__L1__x__Fv__FZ1Z_v + } + +This form is used when encoding the local class name as a type. It's not +actually necessary to mangle the name of the local class itself unless it's +also a nested class. See ``mangled_type_name_full``. This is not in the ARM, +and cfront does it slightly differently. + +The "``__L``" indicator is also used in the names of entities promoted out of +functions. There, the "``__L``" appears between the name of the entity and the +mangled name of the function: + +.. code:: c++ + + void *f() { + struct A {}; // __12A__L1__f__Fv + static struct A a; // a__L0__f__Fv + return &a; + } + +The instance number (after the "``__L``") serves to ensure that the mangled +name is unique (and is chosen so as to make it repeatable across translation +units in cases where the ODR requires it). Note that in configurations where +local types cannot be used in template arguments (i.e., other than --c++11 or +when microsoft_mode >= 1400) and therefore can't appear in external names, the +mangled names may differ slightly from those listed above. + +Unnamed namespace names are mangled as ``__N`` followed by a unique string. +The unique string is the "module id" generated by IL lowering from the source +file name and some other information, but from the perspective of name mangling +it is simply ignored. Such names appear only in contexts where their length is +given, so it's easy to know how much to ignore. + +Template classes have mangled names that encode the arguments of the template: + +.. code:: text + + template class abc {}; + abc x; + abc__tm__3_ii + ^^--- Two template arguments of type int. + ^------ Total length of template argument list string, including + the underscore. + ^^--------- Fixed string, indicates "template". + ^^^------------- The name of the class template. + +When distinct mangling for templates is disabled, "``tm``" is replaced by +"``pt``" (which is what cfront uses). + +The encoding for nontype template arguments encodes both the parameter type and +the actual argument value: + +.. code:: text + + template class def {}; + def<5> x; + def__tm__7_XCiL15 + ^-- Literal constant representation. + ^--- Length of literal constant. + ^---- "L" indicates literal constant, "c" indicates address + of variable, etc. + ^^----- Type of template argument, with "const" added. + ^------- "X" indicates beginning of constant argument. + +Template argument packs are introduced by "``__pk__``": + + .. code:: text + + template int f(); + int x = f(); + f__tm__12_s__pk__3_id__Fv_i <-- encoding for "f()" + ^---- Return type (int). + ^------ Argument list (void). + ^------- Function. + ^---------- Second argument of the pack (double). + ^----------- First argument of the pack (int). + ^------------- Total length of template argument pack. + ^^---------------- Beginning of a template argument pack. + ^-------------------- First template argument type (short). + ^^---------------------- Total length of template argument list. + ^^-------------------------- Introduces template arguments. + ^------------------------------ The name of the function template. + +Constants are encoded with the letter "``C``" followed by the type of the +constant and the encoding of the constant value (e.g., "``CiL_2_59``" +represents the integer constant 59). There are several different encodings +for different kinds of constants: + +* | Integer: + + .. code:: text + + L3n12 <-- encoding for "-12" + ^^----- Literal value. + ^------- "n" indicates negative. + ^-------- Length of the literal. + ^--------- "L" indicates a number. + + | This is compatible with cfront 3.0.1. + | + | The length of the literal uses an encoding compatible with cfront, i.e., + it's either a single digit or two digits followed by an underscore (e.g., + "``L10_1234567890``"). This encoding has some ambiguity problems when the + template argument is followed by an underscore. Such cases did not come up + in the cfront world, but they do come up when template arguments are + applied to template functions (see paragraphs on distinct mangling for + templates, below). To deal with this, a new unambiguous mangling for + literal lengths has been introduced as of version 2.32. It has the length + enclosed in underscores in all cases (single- or multi-digit), e.g., + "``L_1_2``". This form is used in the new contexts that didn't come up for + cfront, and the old form continues to be used in the cfront contexts. +* | Float: + + .. code:: text + + L4n1p5 <-- encoding for "-1.5" + ^^^---- Literal value ("p" for decimal point). + ^------- "n" indicates negative. + ^-------- Length of the literal. + ^--------- "L" indicates a number. + + | cfront 3.0.1 does not implement this, so we made it up. In actuality, the + literal form of the floating constant depends on the ``fp_to_string`` + routine, so the encoding is likely to be longer (for example, it's likely + to include an exponent). +* | Complex floating point literals are mangled like floating point literals + above except that both real and imaginary components are included: + + .. code:: text + + L_3_0d0_3_1d1 <-- encoding for "0.0+1.0i" + ^^^---- Imaginary portion of complex number. + ^^^------- Length of the imaginary portion of the number. + ^^^---------- Real portion of complex number. + ^^^------------- Length of the real portion of the complex number. + ^---------------- "L" indicates a number. + +* | Address of variable or routine: + + .. code:: text + + 4abcd <-- encoding for address of "abcd" + ^^^^---- Name of entity. + ^-------- Length of the name. + + | This is compatible with cfront 3.0.1. +* | For pointers to data members, the offset value encoded as an integer: + + .. code:: text + + L212 <--- encoding for an offset of "12" + ^^------ Literal value. + ^-------- Length of the literal. + ^--------- "L" indicates a number. + + | This is compatible with cfront 3.0.1. +* | For pointers to member functions, the ``__mptr`` triplet of values (delta, + index, function or offset), encoded as follows: + + .. code:: text + + LM0_L2n1_1j + ^^- Function name, or alternatively "0" if the pointer + to member uses an offset (e.g., LM0_L11_0). + ^^^^---- Index value, encoded as an integer. + ^--------- Delta value. + ^^---------- "LM" indicates a pointer to member function. + + | This is compatible with cfront 3.0.1. Note that "``0``" is always used + for the offset, not the actual offset value. This follows cfront. The + idea seems to be that "0" is really a way of saying "there is no + function;" the offset value itself would not be of interest to a name + demangler. +* | For strings, the type of the string is encoded. The character "``S``" + is used to indicate a string literal. The string ``L"xyz"`` is encoded + as "``CA4_CwLS``" (i.e., a string literal of type ``const wchar_t[4]``). +* | ``nullptr`` is encoded using the encoding for integers given above; the + type is always "``n``" (for ``std::nullptr_t``), and the value is + always zero, so the entire mangled encoding for ``nullptr`` is always + "``CnL_1_0``". + +The fact that there are rules for mangling type names seems to suggest that +names of types are mangled. Strictly speaking, except for nested class names, +they are not. It is really only the names of variables and routines that need +to be mangled. The mangled form of type names does have a use, however: it is +used when building the mangled names of variables and routines, to represent +the types referenced by the entity (e.g., parameter types). + +Unnamed (class/struct/union, enums, lambda closure) types are given a generated +name during mangling; that name is then used as described above (e.g., in +mangled names of variables and routines). The names generated for these +unnamed types are constructed so as to ensure that types subject to ODR +constraints across translation units are given the same name; other types are +given names guaranteed not to collide with similar constructs in other +translation units. + +Unnamed class/struct/union and enums are given the name "``__Ut``" followed by +an instance number (within the namespace/class/function scope) which makes the +generated name unique within that scope. A mangled encoding of the type will +include its parent's encoding as well. + +Lambda closure types are a special kind of unnamed class type, and they are +mangled with a similar "``__Ul``" encoding that additionally gives information +about the lambda's parameter types: + + .. code:: text + + __Ul1_Fif <-- [](int, float)->float {return 0.0;}(i, f); + ^^^---- Lambda operator() function type (int, float). + ^-------- Instance (within parent scope). + ^^^^--------- "__Ul" indicates lambda. + +Lambdas defined in certain contexts, specifically some default arguments and +member initializers, are subject to ODR constraints and therefore must get +names that can be generated identically in different compilations. That's +accomplished by making the default argument or member initializer a +"pseudo-parent scope" and encoding the closure type as a member of that +pseudo-scope. + +Lambdas defined in default arguments (and subject to ODR constraints) are given +a name based on this encoding: + + .. code:: text + + __Ud1_2_Fv__L0__f__FiT1 <-- void f(int i=[]{return 0;}(),int k=0) + ^^^^^^^^^^^^^---- Local to function f(int,int). + ^^----------------- Lambda operator() function type. + ^-------------------- Declared in trailing parameter 2. + ^---------------------- Instance 1 (within parameter). + ^^^^----------------------- "__Ud" indicates lambda in default arg. + +Lambdas in member initializers are given a name that is prefixed with +"``__Um``": + + .. code:: text + + __Q3_10S__tm__2_i1x8__Um1_Fv < template int S::x = + []{return 1;}(); + ^^-- Lambda operator() function type. + ^----- Instance (within member initializer). + ^^^^------ "__Um" indicates lambda in initializer. + ^---------- Length of type name that follows. + ^^^^^^^^^^^^^^^^^^^----------- Nested encoding for S::x::. + +The following kinds of entity names (only) are mangled: + +* | Function names. Even non-member function names are mangled, to deal with + overloading. Names of functions with ``extern "C"`` linkage are not + mangled. See ``mangle_function_name``. + | Mangled function names have the function name followed by "``__``" followed + by "``F``" followed by the mangled description of the types of the + parameters of the function. If the function is a member function, the + mangled form of the class name precedes the "``F``". If the member + function is static, an "``S``" also precedes the "``F``". In cases where + the function has ``extern "C"`` linkage on the function type, a "``K``" + modifier immediately follows the "``F``" indication. + + .. code:: c++ + + int f(float); // f__Ff + class A { + int f(float); // f__1AFf + static int g(float); // g__1ASFf + }; + + | Members of namespaces are mangled like member functions. + | For the Microsoft extension that allows explicit specification of a virtual + function to be overridden, name mangling adds the class of the overridden + virtual function as ``O`` followed by the class type encoding, after the + class name. So, for example, a member ``D::f`` that explicitly overrides + ``B::f`` would be encoded as ``f__1DO1BFv``. +* | Special and operator function names, like constructors and ``operator=()``. + The encoding is similar to that for normal functions, but a coded name is + used instead of the routine name: + + .. code:: c++ + + class A { + int operator+(float); // __pl__1AFf + A(float); // __ct__1AFf + }; + int operator+(A, float); // __pl__F1Af + + | The ARM contains a full list of the name encodings. Static constructors, + used in C++/CLI, are encoded with "``__st__``"; finalizers are encoded with + "``__df__``". See ``mangled_operator_name``. +* | Static data member names. The mangled form is the member name followed by + "``__``" followed by the mangled form of the class name: + + .. code:: c++ + + class A { + static int i; // i__1A + }; + + | This type of mangling is also used for variables that are members of + namespaces. Generally speaking, the names of variables at the file scope + don't need to be mangled, but that's not true for variable templates, or + for variables that may have implicit or explicit ``abi_tag``\ s. See + ``mangle_variable_name``. +* | Functions that are instances or specializations of templates. These + are mangled to include the template signature. This is controlled by + the variable ``distinct_template_signatures``. Template parameters + (both type and nontype) are mangled as "``Z``\ *n*\ ``Z``" or "``Z``\ + *n*\ ``_``\ *m*\ ``Z``", where *n* is the template parameter position + number (first is 1) and *m* is the template parameter depth (top level + is 1, which is assumed in the case where it is not specified). The + return type of the function is also included in the mangled name. + "``__S``" can appear either directly after the template name, to + indicate that the template is specialized, or after the template + argument list, to indicate that the instance is specialized. + + .. code:: c++ + + template struct A { + template void f(T2); + }; + template <> template void A::f(T2) {} + template <> template<> void A::f(int) {} + A ai; + A ac; + A af; + int main(){ + ai.f(1); // f__tm__2_i__10A__tm__2_iFZ1_2Z_v + ac.f(1); // f__S__tm__2_i__10A__tm__2_cFZ1_2Z_v + af.f(1); // f__tm__2_i__S__10A__tm__2_fFZ1_2Z_v + } + + | + | The specialization indications are also placed in the names of parent + classes of functions and static data members generated from templates. A + "``__S``" following directly after the class itself indicates that the + class is specialized (and similarly for a class template), and a "``__S``" + after the template argument list of a class template indicates that the + instance is specialized. + + .. code:: c++ + + template struct A { + void f(); + struct B { + void bf(T); + }; + }; + template <> struct A { + void f(); + }; + template <> struct A::B { + void bf(int); + }; + A as; + A::B aib; + main () { + as.f(); // f__13A__tm__2_s__SFv + aib.bf(1); // bf__Q2_10A__tm__2_i4B__SFi + } + + | When a partial specialization of a class template appears, the mangled name + has two template argument lists. The first (which begins with + "``__ps__``") gives the template arguments that appear on the declaration + of the partial specialization, and the second gives the arguments according + to the template parameters of the partial specialization. + + .. code:: c++ + + template struct A {}; + template struct A { + void f(); // f__23A__ps__6_PZ1Zi__tm__2_iFv_v + // A + }; + + | Where expressions appear in template signatures, they are mangled as in the + following example: + + .. code:: text + + Opl_2_Z1ZZ2ZO <-- "Z1 + Z2", Z1/Z2 indicating nontype template + parameters. + ^---- "O" to end the operation encoding. + ^^^----- Second operand. + ^^^-------- First operand. + ^^^----------- Count of operands (with bracketing underscores). + ^^-------------- Operation, using same encoding as for operator + function names. + ^---------------- "O" for operation. + + | The two or three letter operation encodings (e.g., "``pl``" in the example + above) are the same as the operator function encodings specified in the ARM + (without the leading double underscores). + | The operands can be template parameters, constants (using the encoding + described for nontype template arguments, not including the initial + "``X``"), subexpressions (using the expression operation encoding described + above), mangled names (e.g., of variables or routines), or (in ``decltype`` + expressions) function parameter references. + | + | In addition to those operations specified in the ARM, the following + operation encodings have been added as EDG extensions: + + .. code:: text + + "ds" = .* + "dt" = . + "ps" = unary plus + "ng" = unary minus + "de" = * (indirection) + "ao" = & (address of) + "ppe" = prefix increment (pp indicates postfix increment) + "mme" = prefix decrement (mm indicates postfix decrement) + "tw" = throw + "rl" = __real + "im" = __imag + "mn" = GNU min operator (?) + "sp" = ... (pack expansion) + "ht" = % (C++/CLI unary "%" operator which returns a handle) + "sb" = [] (C++/CLI array subscript -- has variable number of operands) + "gc" = gcnew (C++/CLI gcnew -- optional list of dimension expressions + precedes a type operand) + "cp" = () (call operation with ADL suppressed -- has variable number of + operands) + "il" = {} (brace-enclosed initializer list -- has variable number of + initializers) + "tl" = T{} (cast of a brace-enclosed initializer list -- has a type + followed by a variable number of initializers) + "nx" = noexcept + "li" = literal operator (for user-defined literals -- has zero or one + operand and is followed immediately by a count and the ud-suffix + for the literal operator, e.g., operator "" _miles would be + "li6_miles") + + | The following added operations differ from the standard operation encoding + in that they include an initial type before a single operand. The "``cs``" + encoding is used to encode both the old-style cast (where there is one + non-type operand) as well as the functional-notation cast (where there can + be zero or more non-type operands). The case where a functional-notation + cast is used with one argument is indistinguishable from the old-style cast + case: + + .. code:: text + + "sc" = static_cast + "dc" = dynamic_cast + "rc" = reinterpret_cast + "cc" = const_cast + "cs" = old-style (one argument) or functional-notation cast + "sf" = C++/CLI safe_cast + + | The following operation differs in that it takes a single type argument: + + .. code:: text + + "ct" = C++/CLI ::typeid + + | The following operations differ in that their source can specify either a + type or an expression: + + .. code:: text + + "sz" = sizeof + "af" = __ALIGNOF__ + "uu" = __uuidof + "ty" = typeid + "sk" = sizeof... + + | The mangled encodings for these cases are: + + .. code:: text + + OszZ1Z0O <-- "sizeof(Z1)", Z1 indicating a template parameter. + ^---- "O" to end the operation encoding. + ^----- Count of operands, 0 for type and "e" cases, 1 for "X". + ^^^------ Encoding for type or "e" or "X" (for expression cases). + ^^--------- Operation ("sz" for sizeof, "af" for __ALIGNOF__, + "uu" for __uuidof, or "ty" for typeid) + ^----------- "O" for operation. + + | There are three cases. When the operation takes a type, then the type + is encoded after the operation encoding and there are no operands. + Prior to version 4.2, an expression was indicated with an "``e``" in + place of the type (but no expression was contained in the mangled name + and the operand count was still zero). In version 4.2 and later, the + mangled expression is included (operand count is 1), and the type is + replaced with an "``X``" to indicate that an expression follows. | | The + ``new`` and ``delete`` operations (as well as ``new[]`` and + ``delete[]``) are encoded thusly: + + .. code:: text + + v--------------vvvvvvvvvv----- These are optional. + Onwg_1_CiL_2_10Z1Z_1_CiL_1_0O <-- encoding for "::new (10) T (0)" + ^---- "O" to end the encoding. + ^^^^^^^----- Initializers (if any). An optional + "bi" indicates the use of a + brace-enclosed initializer list. + ^^^------------ Optional initializer count (zero + or more). Omitted (along with + initializers) if none were + specified. + ^^^--------------- Type of new operation. + ^^^^^^^^------------------ Placement arguments (if any). + ^^^-------------------------- Placement argument count (zero + or more). + ^----------------------------- "g" indicates global new. + ^^------------------------------ new operation (nw, nwa). + ^-------------------------------- "O" for operation. + + v----------- This is optional. + Odlg_1_I1IO <-- encoding for "::delete p1" + ^---- "O" to end the operation encoding. + ^^^----- Argument to delete. + ^^^-------- Argument count (always one for delete). + ^----------- "g" indicates global delete. + ^^------------ delete operation (dl, dla). + ^-------------- "O" for operation. + + | Builtin operations (i.e., vendor-specific extensions like Microsoft + ``__is_base_of``) use the operation "``bi``", and any operands that are + types are prefixed by "``T``". The encoding "``__dn``" was added to + represent a destructor name (and is followed by a single type name). + See ``mangled_encoding_for_expression`` for details on the mangling of + expressions. | | Where arrays with sizes based on template parameters + appear, they are mangled as "``A_``\ *mangled-expression*\ ``_``\ + *element-type*" (the underscore following the "``A``" differentiates + this case from the usual known-size array case). | | A template + template parameter that is followed by a template argument list, e.g., + ``ttparam`` in source code, is represented by the ``Z...Z`` + encoding, with the template argument list encoding inserted before the + closing ``Z``, as in ``Z1__tm__4_Z2ZZ``. | | References to function + parameters in ``decltype`` expressions (e.g., ``p`` in ``template + auto f(T p) -> decltype(p)``) are mangled as such: + + .. code:: text + + v-vv----- These are optional. + IC1_2I <-- "const param#1 two levels up" + ^---- Terminating non-digit character so parameter number won't run + into an entity with an initial length. + ^^----- Number of "levels up" for this parameter (0-based). Omitted + if zero. + ^------- Parameter number (1-based) or 0 for "this". + ^-------- Optional cv-qualifiers. + ^--------- "I" indicates parameter reference. + +* | The implicit or explicit use of ``this`` in a mangled name is also + represented with the function parameter mangling given above (where the + parameter number is set to zero). +* | Names of variables generated for virtual function tables. These have names + like + + ``__vtbl__``\ *mangled-class-name* + + | or + + ``__vtbl__``\ *mangled-base-class-name*\ ``__``\ *mangled-class-name* + + | In the case of a virtual function table used during construction or + destruction of a subobject, there can be an additional mangled class name + on the end. See ``make_var_for_virtual_function_table``. +* | Names of variables generated to contain runtime type information. These + have names like + + ``__T_``\ *type-encoding* + + | and + + ``__TID_``\ *type-encoding* + + | See ``mangled_typeinfo_name`` and ``mangled_id_object_name``. +* | Names of wrapper routines generated to deal with covariant virtual function + return types. These are pointed to from virtual function tables and have + names of the form + + ``__VFE__``\ *overridden-class*\ ``__``\ *overriding-function* + + | See ``mangle_wrapper_name``. +* | Names of static variables and functions made external, e.g., because they + are referenced from an instantiation and each instantiation is placed in a + separate object file. The form of the mangled names is + + | ``__STV__``\ *variable-name*\ ``__``\ *module-id* + | ``__STF__``\ *mangled-function-name*\ ``__``\ *module-id* + + | where *module-id* is a unique name generated for the current compilation. +* | The GNU ``ifunc`` attribute, when lowered, creates a variable through which + calls to the function are dispatched. The variable uses the ``__IFV__`` + prefix: + + ``__IFV__``\ *variable-name* + +* | When GNU function multiversioning is used, a set of routines with the same + unmangled name are given unique mangled names based on their use. The + following prefixes are used to create these names: + + .. list-table:: + + * - | ``__RES__``\ *mangled-function_name* + - | resolver function + * - | ``__IFC__``\ *mangled-function-name* + - | ifunc function + * - | ``__TGT__``\ *targets*\ ``__``\ *identifier* + - | target-specific function + +* | For classes and function names with the GNU ``abi_tag`` attribute, the + "``__ab``" prefix is used (once for each string literal that is specified + in the ``abi_tag`` attribute list): + + ``__ab``\ ** + + | where ** represents the number of characters in the ** string + literal. + +* | Structured binding container variables (at namespace scope) are given + mangled names based on the binding variable(s) they refer to. The + "``__SBC__``" prefix is used to identify this mangling. Each of the + binding variables, in order, are included in the container's mangled name, + separated by "``__``". A final "``__``" indicates the end of the + structured binding container mangled name. For example, + ``__SBC__x__y______1N`` indicates a structured binding container for + ``[x,y]`` in namespace ``N``. + +Once a mangled name has been generated, a compression step examines it to see +whether it can be shortened by compression. The compression approach is +simple-minded: the sequence "``J``\ *nnn*\ ``J``" means "repeat the sequence +beginning at offset *nnn* in the mangled name." The offset is 0-origined. Only +sequences that begin with a length (e.g., ``7ABCDEFG``) are eligible to be +repeated in this way. Each "``J``" in the original mangled name is replaced by +"``JJ``" to avoid ambiguities. If compression is done, the mangled name is +given a prefix of "``__CPR``\ *nnnn*\ ``__``", where *nnnn* is the length of +the uncompressed form of the name. + +IA-64 ABI name mangling +^^^^^^^^^^^^^^^^^^^^^^^ + +In the IA-64 ABI, name mangling is done according to the ABI spec +(www.codesourcery.com/cxx-abi/abi.html). We will not repeat that description +here. + +There is no compression *per se* in the IA-64 ABI name mangling scheme. +Instead, entities that have appeared earlier in a mangled name can be +referenced again by way of a "substitution," which is essentially the encoding +"``S``" followed by a number (base 36) indicating which of the preceding +entities is repeated. Entities of certain kinds (types, qualified name +prefixes, templates) are assigned numbers in their order of appearance in the +mangled name, and a later substitution can refer to such an entity by number. +Certain types and templates in the standard ``iostream`` header are assigned +predefined substitution codes so that they can be referenced cheaply. For the +implementation of substitutions, see ``add_substitution_if_available`` and +``alloc_substitution``. Note that one consequence of substitutions is that it +is impossible to reuse mangled names for entities as part of a larger mangled +name including that entity, because the substitution numbering in the reused +piece would be wrong for the overall mangled name. + +Mangled names for entities local to a function are distinguished by a trailing +"discriminator," a number that serves to distinguish like-named entities within +one function. Such entities are assigned discriminator numbers in the front +end, in strict order of appearance in the function. For example, the first +variable "``i``" in a function is assigned discriminator number zero, the next +one, etc. regardless of block scope nesting. These discriminator values are +recorded in the symbol table (rather than the IL) and IL lowering retrieves +them and includes them in mangled names. + +Similarly, string literals within (certain) functions are numbered so that +mangled names can be generated for them. The C++ standard requires that if an +``extern inline`` function is implemented by multiple copies, a string literal +that appears in the function has the same address in all copies. This is +implemented by assigning a sequence number to each string in functions that +might exist in multiple copies. Name mangling then uses that number to +generate a mangled name for the variable created to hold the string value. + +For entities "externalized," i.e., static variables or functions made external +because they must be referenced from multiple compilations (e.g., for exported +templates, or in one-instantiation-per-object mode), name mangling uses an +extension to the ABI spec. This is an encoding of the form + + ``B`` *length module_id* + +where *module_id* is a generated string describing the current compilation, +formed from the source file name and some other bits that help make it unique. +This encoding is used as a prefix on the syntax term and is used to make +a local name unique when it is externalized. + +For the Microsoft extension that allows explicit specification of a virtual +function to be overridden, name mangling adds the name of the overridden +virtual function as the encoding ``Q``\ ** following the nested +name for the function, i.e., an ** has an alternative of **\ ``Q``\ * *. So, for example, a member +``D::f`` that explicitly overrides ``B::f`` would be encoded as +``_ZN1D1fEQN1B1fEv``. This is an extension to the ABI spec. + +Builtin operations in expressions (i.e., vendor-specific extensions like the +Microsoft __is_base_of) are encoded as a vendor-specific operator ``builtin``\ +*XX*, where *XX* is the number of the builtin operation. Any type operands are +encode as "``TO``" followed by the encoding for the type. + +When C++/CLI is enabled, tracking references, ``interior_ptr``\ s, ``pin_ptr``\ +s, and handles are mangled using the vendor extended type qualifier: + + ** ::= ``U``\ ** # vendor extended type qualifier + +Tracking references use the encoding "``8__trkref``" for **, +``interior_ptr``\ s are encoded as "``14__interior_ptr``", ``pin_ptr``\ s +as "``9__pin_ptr``", and handles are encoded as "``8__handle``". C++/CLI +static constructors are encoded as "``C8``" and finalizers are "``D7``". +``__nullptr`` is encoded as "``DN``"; ``__underlying_type`` is encoded as +"``Du``". + +C++/CLI operators are generally mangled using the IA-64 ABI vendor extended +operator syntax: + + | ** ::= ``v``\ ** # vendor extended + operator + +The unary "``%``" operation (which produces a handle to its operand) uses the +"``9clihandle``" <*source-name*>; the array subscript operation (which has a +variable number of operands) is encoded with a <*source-name*> of +"``12clisubscript``". Due to the limitation of a single digit in this +encoding, only 8 subscripts can be represented in the mangled name. The +``::typeid`` operation is mangled as "``9clitypeid``"; ``safe_cast`` is +"``12clisafe_cast``". + +The vendor extended operator syntax isn't flexible enough to support ``gcnew``, +so an EDG-specific mangling (patterned after the mangling for ``new``) is used: + + .. list-table:: + + * - | ::= ``gc_``\ **\ ``E`` + - | # gcnew ** + * - | ::= ``gc_``\ ** + - | # gcnew *e* {init} + * - | ::= ``gc``\ **\*\ ``_``\ **\ ``E`` + - | # gcnew array\ **\ (dims) + * - | ::= ``gc``\ **\*\ ``_``\ ** + - | # gcnew array\ **\ (dims) {init} + +The IA-64 ABI specification doesn't specify how to mangle function names that +use the GNU multiversion feature. For these functions, the front end produces +mangled names similar to the names that GNU produces. More specifically, for +the resolver function and for target-specific functions, a suffix is appended +to the name ("``.resolver``" for resolver functions and a string that contains +a sorted list of the canonicalized ``target`` attributes for target-specific +functions). The mangling for an ``ifunc`` function is somewhat different: the +original name is mangled, then "``.ifunc``" is appended, then the name is +mangled again (with the signature of the lowered routine type). Note that +these GNU manglings contain periods which can cause problems in certain back +ends (e.g., C-generating back ends), so a configuration macro, +``REPLACE_SPECIAL_CHARACTERS_IN_MANGLED_NAMES``, is available to change the +periods into underscores. Note also that due to their non-standard nature, +these names cannot be demangled (either with or without the periods). + +.. _dynamic-init: + +Dynamic Initialization +---------------------- + +The ``a_dynamic_init`` entry, which describes a dynamic initialization, is used +both in C and C++. IL lowering rewrites cases that are not valid in C and +leaves the others. See ``lower_dynamic_init``. Cases that must be rewritten +are: + +* | Initialization of a file-scope variable to a nonconstant value. + | + | See ``lower_file_scope_dynamic_inits``. + | + | The initialization is rewritten as executable code in a file-scope + initialization routine (called ``__sti__``\ *module-id*, or ``__tls_init`` + for initialization of objects with ``thread_local`` storage). + | + | The existence of the initialization routine is communicated to the + environment through creation of a file-scope static variable called + ``__link``: + + .. code:: c++ + + void __sti__module_id() {...} + struct __linkl { + struct __linkl *next; + void (*ctor)(); + void (*dtor)(); + }; + static struct __linkl __link = {NULL, __sti__module_id, NULL}; + + | This is compatible with the cfront ``patch`` step. That tool or something + similar to it can find the ``__link`` variable and place it on a list of + entries to be consulted at program startup and termination. It is also + compatible with the alternative cfront ``munch`` tool, which looks for + routines with names beginning with ``__sti__`` and ``__std__``. Note that + the cfront approach allows the specification of a termination routine, but + that facility is not used by this front end (end-of-program destructions + are requested individually by calling a runtime routine, e.g., + ``__record_needed_destruction`` for the cfront-like ABI). This ``__link`` + variable is included in the program even if initialization is handled by + some fancier mechanism (see, for example, + ``USE_INIT_SECTION_IN_GENERATED_C`` for the C-generating back end), and + even in the IA-64 ABI, even though it may not be used in those cases. + | + | See ``make_code_to_invoke_file_scope_init_routine``. + | + | When ``ONE_INSTANTIATION_PER_OBJECT`` is TRUE, each instantiation in a + compilation is put out as a separate object file. There is still only one + IL tree, but it is marked so that a back end can sweep through it several + times and put out a different "slice" each time, each slice containing one + instantiated entity (function, variable, or static data member) plus + exactly the set of other entities needed by that entity. This is done via + a set of per-instantiation "needed" flags. For slices that contain + variable template or static data member instantiations, the slice may + require file-scope initialization code. In these cases, multiple + file-scope initialization routines and multiple ``__link`` variables are + generated, each one marked to be included in the proper slice. Each + file-scope initialization is placed in the initialization routine for the + appropriate slice and any initialization for objects with ``thread_local`` + storage are put out in a ``__tls_init_``\ N routine where the N indicates + the number of the slice). +* | Initialization of a local static variable to a nonconstant value. The + initialization is rewritten as executable code, then surrounded by a + first-time test so that the initialization is done only once: + + .. code:: c++ + + void f() { + static int i = j+k; + } + + | is translated to (cfront-like ABI): + + .. code:: c++ + + static int temp; // Implicitly initialized to zero + void f() { + static int i; + if (temp == 0) { + temp = 1; + i = j+k; + } + } + + | In the IA-64 ABI, the guard variable is set after the initialization. If + ``IA64_ABI_USE_GUARD_ACQUIRE_RELEASE`` is TRUE, the routines given in the + ABI spec are called, making the full (and potentially thread-safe) sequence + + .. code:: c++ + + static long long temp; // Implicitly initialized to zero + void f() { + static int i; + if (temp == 0) { + if (__cxa_guard_acquire(&temp)) { + i = j+k; + __cxa_guard_release(&temp); + } + } + } + + | See ``add_first_time_test``. +* | Initialization by calling a routine that returns a class object via a copy + constructor. The initialization is rewritten as a call of the routine. +* | Initialization using a constructor. The initialization is rewritten as a + call of the constructor. + | + | See ``add_constructor_call``. +* | Initialization to a nonconstant aggregate. The initialization is rewritten + as initialization to a constant aggregate combined with executable code to + initialize the nonconstant positions. + + .. code:: c++ + + void f() { + int a[3] = {1, i+1, 3}; + } + + | is rewritten as + + .. code:: c++ + + void f() { + int a[3] = {1, 0, 3}; + a[1] = i+1; + } + + | See + + * | ``lower_ck_dynamic_init`` + * | ``lower_dynamic_init_aggregate_constant`` + * | ``add_destructor_call`` + +* | Any dynamic initialization requiring a destructor. The required destructor + call will be on a list of destructions to be done at the end of an object + lifetime. See :ref:`object-lifetimes`. + | + | If the dynamic initialization is a valid C initialization except for the + requirement to call a destructor, it is left as-is; otherwise, it is + rewritten as described above. + | + | When a global or local static variable is constructed, and the variable + requires later destruction, this is recorded at runtime by calling the + routine ``__record_needed_destruction`` [#f2]_ (cfront-like ABI) or + ``__cxa_atexit`` (IA-64 ABI) The calls of that routine build a list of + entities to be destroyed at the time of program termination. If a + destruction requires only a destructor call, the data structure passed to + the runtime routine gives the address of the object and the address of the + destructor. Otherwise (for more complex cases, e.g., arrays), a routine is + generated containing the necessary destruction code, and the address of + that routine is passed in the data structure, along with a NULL object + pointer indicating the complex case. + | + | See ``record_needed_destruction``. + +In routines that return a class value by calling a copy constructor, the +``stmk_return`` statement is unusual in that it points to a dynamic +initialization entry that describes the initializing operation to be done to +return a value. The destination of the initialization is taken to be the +address given by the implicit return value parameter added to the routine. The +caller passes in the address of a class object, and the code generated for the +return statement initializes that object before returning. + +Main Program +------------ + +A call of the runtime routine ``_main`` is inserted at the start of the main +program. That routine invokes initialization code for file-scope variables, +and arranges things so that the corresponding termination code will be called +when the program terminates. See ``lower_scope``, and the section on dynamic +initialization in this chapter. + +Class Types +----------- + +The following processing is done on class types: + +* | If the class has virtual base classes, a copy of the class type is made + without the virtual base classes. This copy is given the name of the + original class prefixed with "``__SO__``". This type is attached to the + original type through the ``type_as_subobject`` pointer. If the class has + no virtual base classes, the type-as-subobject is the same as the original + class type. See ``make_subobject_class_type``. +* | The field list of the class is augmented by adding generated fields for the + base classes of the class (using the type-as-subobject of the base classes + for the field types) and pointer to a virtual function table and (for the + cfront-like ABI) any required pointers to virtual base classes . This does + not change the size of the class -- these entities were already part of the + class; they are just made explicit so they can be referenced as fields. + See ``prelower_class_type``. +* | If the class has virtual functions, a variable will be created for a + virtual function table for the class and for each base class of the class + as a subobject of the class. The declaration is created as an ``extern`` + declaration, and is turned into a definition (either external or static) + that is initialized if the virtual function table definition should be put + out. (See next section and ``make_vars_for_virtual_function_tables``). +* | If the class has virtual base classes, in the IA-64 ABI, information needed + to access virtual base classes and to call virtual functions in such bases + is determined and recorded. See + ``compute_vbase_and_vcall_offset_indices``. +* | The members of the class (local constants, local types including nested + classes, static data members, and member functions) are promoted out of the + class into the surrounding context. See ``promote_class_members`` and + ``do_scope_class_member_promotion``. +* | To support the anachronism that allows a static data member to be declared + but never defined, the storage class of static data members that are + externally visible and have no initial value is changed to ``sc_extern``. + See ``lower_scope``. + +Virtual Function Tables +----------------------- + +Each class containing virtual functions has associated with it a virtual +function table. If it has base classes that also contain virtual functions, it +will also have associated with it an instance of each base class's virtual +function table adjusted for use when that base class is a subobject within a +complete object of the derived class. So, associated with a class ``C`` we +might have a virtual function table for ``C`` as a complete object, one for +``B`` as a subobject of a complete object of type ``C``, and one for ``A`` as a +subobject of a complete object of type ``C``. + +In the cfront-like ABI, each of these virtual function tables is embodied in a +variable whose type is an array of entries of type + +.. code:: c++ + + typedef void (*__vptp)(); + struct __mptr { + short d; + short i; + __vptp f; + }; + +``d`` is the "delta" value to be added to the "``this``" pointer to adjust +it to point to the class in which the virtual function is defined; ``f`` +points to the virtual function. For a pure virtual function, the function +pointer points to the runtime routine ``__pure_virtual_called``. In the +case of a deleted virtual function, a pointer to the runtime routine +``__deleted_virtual_called`` is used for the function pointer. + +Note that field ``i`` in the above is not used; it's there for cfront +compatibility. cfront uses the same data structure for pointers to member +functions and virtual function table entries, even though a simpler structure +could have been used for virtual function tables. + +In the IA-64 ABI, each of these virtual function tables is embodied in a +variable whose type is an array of entries of type ``ptrdiff_t``, which is +used to encode function pointers, offsets, etc. There is no "delta" value. +Entries that require such an adjustment point to a thunk routine, which +adjusts the "``this``" pointer and then calls the proper routine. For a +pure virtual function, the function pointer points to the runtime routine +``__cxa_pure_virtual``; a deleted virtual function has its function pointer +initialized to the ``__cxa_deleted_virtual`` runtime routine. + +Each entry defines one virtual function of the class. The routine entry for +the virtual function gives the virtual function number for the function, which +serves as the index into the virtual function table. In the cfront-like ABI, +the code generated uses entry ``[0]`` of the virtual function table to point to +the typeinfo for the class, and the first function is at entry [1]. In the +IA-64 ABI, the first function is at entry [0], but there are also negative +entries: [-1] points to the typeinfo for the class, [-2] gives the offset to +the beginning of the complete object , and [-3], [-4], etc., if needed, give +offsets to virtual base classes and offsets to be added to the "``this``" value +when calling virtual functions. + +When an entity of a class type having virtual functions is initialized (by a +constructor), the virtual function table pointer in the class entity is set to +point to the virtual function table that is appropriate for that object (i.e., +the one that properly reflects whether the class entity is a complete object or +a subobject of some other class). Note that it's the virtual function pointer +that is changed; the virtual function tables themselves are constant and are +not changed. They are not built up, on a per-routine basis or otherwise, for a +given entity. Rather, the proper complete table is chosen and a pointer to it +is put into the class entity. Many class entities can point to the same +virtual function table. + +The variables for virtual function tables are externally visible (except for +classes with internal or no linkage), and they are shared between compilation +units to save space. For the sharing scheme to work correctly, exactly one +compilation unit must define the contents of each virtual function table. The +rest of the compilation units must put out the variable as an ``extern`` +declaration. What IL lowering does is to build every variable as an ``extern`` +declaration first, then change it to a definition (external or static) if the +virtual function table should be defined in the present compilation. The +heuristic used to decide whether or not a virtual function table definition +should be put out is the one described in ARM 10.8.1c: The virtual function +table for a class is put out if the compilation contains a definition for the +first non-inline virtual member function of the class. If the class contains +no non-inline virtual function, the virtual function table is defined as a +local static variable unless the ``--suppress_vtbl`` or ``--force_vtbl`` option +is specified on the command line. This same heuristic is used for the IA-64 +ABI [#f3]_, with the modification that virtual function tables that would be +put out as static are put out as COMDATs, so that the multiple copies can be +joined together by the linker. + +To define a virtual function table, the variable is given a static initial +value that's specified by a ``ck_aggregate`` constant. Each entry in the table +is defined appropriately. For a complete-object virtual function table, the +functions that go into the table are simply the virtual functions of the class +in the order of their virtual function numbers. For a virtual function table +for a subobject of class ``A`` in a complete object of class ``B``, the member +functions of ``A`` are scanned looking for virtual functions, while at the same +time the override list for base class ``A`` of ``B`` is scanned. If a function +in ``A`` does not appear on the override list, the function from ``A`` goes +into the virtual function table. Otherwise, the function from the override +list goes into the virtual function table. + +During the execution of constructors and destructors for base class subobjects, +virtual functions should act as if the complete object has the type of the +constructor or destructor class. That is, functions in classes further out +than the subobject class do not override during the subobject construction or +destruction. When virtual base classes are involved, this means that some +virtual function table instances need to be built to reflect three classes: a +class A (whose virtual function table this is) that is a subobject of a class B +(whose constructor is executing, and which therefore dictates overriding) that +is a subobject of a class C (which is the complete object type, and which +therefore dictates layout). This is necessary when there are virtual base +classes, and not otherwise, because the "delta" field in the virtual function +table is based on the offset between the objects for the classes of the +overridden and overriding functions, and that offset varies depending on the +type of the complete object. + +In the IA-64 ABI, the normal (non-construction) virtual function table variable +for a class contains the primary virtual function table plus the virtual +function tables for the base classes of an object of that type, all +concatenated end-to-end in the single array. This is as required by the ABI +specification. For construction vtables, however, where the spec makes no such +requirement, each vtable is in a separate variable. In the cfront-like ABI, +every vtable is in a separate variable. + +See + +* | ``make_vars_for_virtual_function_tables`` +* | ``make_var_for_virtual_function_table`` +* | ``define_one_virtual_function_table`` +* | ``define_virtual_function_tables`` +* | ``define_scope_virtual_function_tables`` +* | ``add_vtbl_entry_init`` +* | ``virtual_function_table_should_be_defined_here`` +* | ``make_construction_vtbls`` + +Covariant return types on virtual functions +------------------------------------------- + +An overriding virtual function can return a pointer or reference to a +derived class where the overridden function returns a pointer or reference +to a base class. Such an overriding function is said to be *covariant* +with the overridden function. This requires special handling in IL +lowering because a call that appears (statically) to be to the overridden +function may in fact (dynamically) be a call to the overriding function, +and the value returned from the overriding function must undergo a +derived-to-base adjustment before it is returned to the caller. This is +implemented by adding wrapper functions: for each combination of an +overriding function and an overridden function, a wrapper is generated that +calls the overriding function, casts the returned value to the proper type, +and returns it. The virtual function table points to the wrapper function +from slots that need to call the overriding function but need the interface +of the overridden function. + +This mechanism is also used more generally in the IA-64 ABI, for thunks +required for virtual function calls where a "``this``" adjustment is needed. + +The IL representation for a wrapper function is a routine with + +* | ``overriding_function_for_wrapper`` and +* | ``overridden_function_for_wrapper`` + +set appropriately. In the case where a wrapper is being used for a covariant +return type adjustment, the wrapper body is simply a return of an +``enk_result_of_overriding_function`` node cast to the proper +pointer-to-base-class. The ``enk_result_of_overriding_function`` node +represents the value returned from calling the overriding function with the +arguments passed to the wrapper. + +This is controlled by the macro +``ABI_CHANGES_FOR_COVARIANT_VIRTUAL_FUNC_RETURN``. + +While the IL representation is a wrapper function, the underlying +implementation need not be. In fact, for functions with variable-length +argument lists, a wrapper approach may not be feasible. Instead, a back end +can turn the wrapper routines into entry points of the overriding function, or +duplicate the body of the overriding function within each wrapper routine. + +Namespaces +---------- + +The processing for namespaces is simply the promotion of the namespace members +out of the namespaces, with appropriate name mangling. See +``do_namespace_member_promotion``. + +Routines +-------- + +The lowering for routines consists of making two kinds of implicit parameters +explicit: + +* | The implicit "``this``" parameter. This is present on nonstatic member + functions. +* | The implicit parameter that provides the address into which a class value + should be returned, for functions returning a class by value. This + mechanism is not used for simple C-style structures, but is needed for more + complicated classes, because for those it must be possible to take the + address of a class value even if it is an rvalue, e.g., to cast to a base + class or call a member function. In this more complicated calling scheme, + the caller passes in the address of a temporary and the called routine + places the class value there on return. + +Both the ``param_type_list`` in the routine type and the parameter variable +entries in the routine scope are updated to make the implicit parameters +explicit. + +Parameters that are classes passed by value and requiring a copy constructor +require additional processing: Since classes that require a copy constructor +cannot be copied arbitrarily and cannot be moved, the caller actually does the +copy constructor call into a temporary and passes the address of the temporary +as the argument. The parameters on the receiving end must be changed to be +pointers to the class object, and all the references to the parameters must be +changed to add the extra indirection. + +See ``lower_type`` and ``lower_scope``. + +Promotion of Local Entities to File Scope +----------------------------------------- + +If the flag ``PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE`` is TRUE, local static +variables and local types of functions will be promoted out of those functions +into the file scope under some conditions. Such promotion is enabled when the +IL will be fed into the C-generating back end, and may be desirable in other +cases where the output is textual and block-structured in some way. + +The problem addressed by this transformation is shown by the following example: + +.. code:: c++ + + void f() { + static int i; + class A { + void g() { + i = 1; // Reference to variable local to function f + } + }; + } + +The body of ``A::g`` will become a free-standing function at file scope and yet +will have to reference the variable ``i`` of ``f``. Therefore ``i`` must be +promoted out of ``f`` into the file scope so that it will be put out in the +file scope in the generated C code. + +This is not a problem for an ordinary back end, as the reference to ``i`` will +be made in object code form or within the flat name space of an +assembly-language program. + +See + +* | ``local_entities_should_be_promoted`` +* | ``promote_local_entities_to_file_scope`` + +.. _ctor-wrapper: + +Constructor Wrapper Code +------------------------ + +Constructors are modified to add the "wrapper" code that is required. + +The constructor-initializer list indicates all the initializations that must be +done for base classes and members. It is in the language-defined order for +initialization: virtual base classes, then non-virtual base classes, then +members. Each base class or member that requires initialization will appear on +the list, with a front-end-generated default initialization if there is no +user-written one in the source. + +The modifications made are: + +* | In the cfront-like ABI, if the class has virtual base classes, a parameter + is added for each such class. These parameters are used to pass in the + addresses of the virtual base classes when the constructor is called (from + another constructor) to initialize a subobject; when the constructor is + called to initialize a complete object, the parameters are passed as NULL. + In the IA-64 ABI, a single parameter is always added, for the VTT (virtual + table table) pointer passed in. Again, NULL is passed in to indicate a + complete object. +* | In the cfront-like ABI, code is added to set any virtual base class + pointers in the class. The virtual base class pointers in the base classes + are set by the constructor calls for the base classes and therefore need + not be set by code at this level. +* | Code is added to call a constructor for each virtual base class that + appears on the constructor-initializer list if a complete object is being + initialized. +* | Code is added to call a constructor for each non-virtual base class that + appears on the constructor-initializer list. +* | Code is added to initialize each member that appears on the + constructor-initializer list. +* | If the class has any virtual functions, code is added to set the virtual + function table pointers in the current class and all of its base classes + that have virtual functions. +* | If allocation can be folded into the constructor (a configuration + option, but always true if assignment to "``this``" is supported), the + entire routine is surrounded by code that tests the incoming "``this``" + parameter, and if it is NULL calls an appropriate ``new`` routine to + allocate space, which is then initialized. If the constructor actually + contains an assignment to "``this``", the ``new`` code is not inserted and + the wrapper code above is inserted after each assignment to "``this``" + instead of at the beginning of the routine. + +If the class has any virtual functions that are overridden in such a way that +there is a virtual base class step between the class of the overridden function +and the class of the overriding function, special virtual function instances +are required during construction of the class as a subobject. A constructor +for such a class, when called for a subobject, expects to receive an array of +virtual function table pointers from its caller (the constructor for the +derived class). It uses these virtual function table instances when setting +virtual function table pointers, and it passes parts of the array to its own +subobject constructors. In the cfront-like ABI, the pointer to the array is +passed (and received, in the subobject constructor) by setting the so-called +"transfer pointer" (a virtual function table or virtual base class pointer in +the class object that is unset at that point and can be borrowed for this +purpose). In the IA-64 ABI, the pointer to the array is passed in via the +added VTT pointer parameter. + +In the IA-64 ABI, constructors have multiple entry points. The entry for a +complete object has a "``C1``" encoding in its mangled name, and has no added +parameters. The entry for a subobject has "``C2``", and has an added VTT +pointer parameter if the class has virtual bases. The IL lowering +implementation puts the real code for the constructor in one function, which is +the subobject constructor if the class has virtual bases and the complete +object constructor otherwise. The other constructor is referred to as the +alternate entry point. When the class has virtual bases and +``HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS`` is TRUE, the construction of +virtual bases is performed in the complete constructor before invoking the +subobject constructor; otherwise the alternate entry is simply an entry point +that calls the primary routine. Calls from an entry point to the primary +routine can be inlined if appropriate, or a back end can implement the entry +point functions as actual entry points to a single routine. See +``alternate_entry_point``. + +See + +* | ``lower_constructor_code`` +* | ``add_constructor_params`` +* | ``add_constructor_wrapper_code`` +* | ``lower_ctor_init`` + +Destructor Wrapper Code +----------------------- + +Destructors are modified to add the "wrapper" code that is required. + +The constructor-initializer list indicates all the destructions that must be +done for base classes and members. It is in the language-defined order for +destruction, i.e., the reverse of the initialization order. Each base class or +member that requires destruction will appear on the list, with a +front-end-generated destruction (there is no way to explicitly write one in the +source program). + +The modifications made are: + +* | A parameter of type ``int`` is added. This parameter is used by the caller + as a bit mask: the ``0x2`` bit of the parameter set to ``1`` indicates a + complete object, and the ``0x1`` bit set to ``1`` indicates that the + storage for the object should be freed. +* | If the class has any virtual functions, code is added to set the virtual + function table pointer in the class and in all of its base classes, so that + virtual function calls executed during the destruction will not call + functions in further-derived classes. + +The above code is added at the beginning of the routine. The rest of the +wrapper code is added at the end of the routine. To make sure the code at the +end is reached, all ``return``\ s in the routine body are rewritten as +``goto``\ s to the epilogue code. + +* | Code is added to destroy each member that appears on the + constructor-initializer list. +* | Code is added to destroy each non-virtual base class that appears on the + constructor-initializer list. +* | Code is added to destroy each virtual base class that appears on the + constructor-initializer list if a complete object is being destroyed. +* | A ``delete`` routine is called to free the storage if the proper bit in + the implicit parameter is set. The entire routine is also enclosed in + an ``if`` statement so it will do nothing if the "``this``" parameter + passed in is NULL. If an assignment to "``this``" was actually done in the + routine, this ``delete`` is protected by a test to see if the "``this``" + parameter is (still) non-NULL. + +See :ref:`ctor-wrapper` regarding special virtual function tables used +during subobject construction. Similar processing is also needed in +destructor wrappers for subobject destruction. + +In the IA-64 ABI, destructors have multiple entry points. The entry for a +complete object has a "``D1``" encoding in its mangled name, and has no added +parameters. The entry for a subobject has "``D2``", and has an added VTT +pointer parameter if the class has virtual bases. The entry to destroy and +free storage for a complete object has "``D0``" and no added parameters. The +IL lowering implementation puts the real code for the destructor in one +function, which is the subobject destructor if the class has virtual bases and +the complete object destructor otherwise. The other destructors are known as +alternate entry points. When the class has virtual bases and +``HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS`` is TRUE, the destruction of +virtual bases is performed in the complete destructor after invoking the +subobject destructor; otherwise alternate entry points simply call the primary +routine (for the deleting destructor, the entry point also contains the +deallocation code). Calls from an entry point to the primary routine can be +inlined if appropriate, or a back end can implement the entry point functions +as actual entry points to a single routine. See ``alternate_entry_point``. + +See + +* | ``lower_destructor_code`` +* | ``add_destructor_params`` +* | ``lower_dtor_init`` +* | ``lower_destructor_dynamic_init`` + +Calls +----- + +See ``lower_call``. + +Calls of constructors and destructors are altered to add the implicit +parameters described in the previous sections. Except for constructor and +destructor calls in wrapper code, constructor and destructor calls are for +complete objects. + +See ``make_ctor_implied_arg_list`` and ``make_dtor_implied_arg_list``. + +Calls of "vacuous" destructors, as in + +.. code:: c++ + + p->int::~int(); + +are changed from ``eok_vacuous_destructor_call`` or +``eok_points_to_vacuous_destructor_call`` operations to a cast to ``void``. + +Virtual function calls are rewritten from + +.. code:: c++ + + object->func(args ...) + +to (cfront-like ABI) + +.. code:: c++ + + ((vtbl_temp = (object->__vptr)+index), + (object+vtbl_temp->d)->(vtbl_temp->f)(args ...)) + +(Omitting some casting for clarity.) In other words, ``vtbl_temp`` is +assigned the address of the proper virtual function table entry, the +"``this``" pointer is adjusted by the "delta" value in the entry, and the +function indicated in the entry is called. If ``object`` is not a reusable +expression, the first occurrence of ``object`` above is replaced by +``(object_temp = object)``, and the second by ``object_temp``. + +For the IA-64 ABI, the code is + +.. code:: c++ + + (object->__vptr[index])(object, additional_args ...) + +(recall that any required "``this``" adjustment is handled by thunk +routines and therefore is not needed at the call site). + +See ``lower_virtual_function_call``. + +A related case (though not a call) is lowering of ``eok_virtual_function_ptr``, +the operator that implements the anachronism of casting a bound member function +pointer to a normal function pointer. It rewrites + +.. code:: c++ + + (func-type *)(object->func) + +to (cfront-like ABI) + +.. code:: c++ + + (func-type *)((object->__vptr)+index)->f) + +or (IA-64 ABI) + +.. code:: c++ + + (func-type *)*(object->__vptr)+index + +See ``lower_virtual_function_ptr``. + +Return Value Optimization +------------------------- + +Return value optimization applies to functions that return a value via a copy +constructor. It can be done when all ``return`` statements in the function +return the same nonstatic local variable. The optimization is to rewrite all +references to the local variable to refer instead to the return-value address +passed in by the caller, thus avoiding a copy constructor call on exit. For +example: + +.. code:: c++ + + struct A { + A(int); + A(const A&); + }; + A f() { + A a(1); // Constructed into temp passed by caller + return a; // No copy needed + } + +The front end proper detects the possibility of doing the optimization, but the +transformation is done by IL lowering. There are several parts to the +optimization: + +* | References to the address of the local variable are rewritten as references + to the (pointer) value of the return-value address parameter. +* | The local variable is marked as unreferenced, and any initialization on it + is turned into initialization of the object pointed to by the return-value + address parameter. +* | Return statements are transformed into simple returns doing no copy + constructor call and returning no value. + +Expression Temporaries +---------------------- + +``enk_temp_init`` nodes are used to introduce class temporaries in the middle +of expressions. They indicate the initialization to be done on the temporary +and any destruction to be done once the temporary is no longer needed. The +temporary is implicit in the high-level IL; IL lowering allocates a variable +for the temporary and uses it in place of references to the ``enk_temp_init`` +node. + +The initialization and destruction are indicated by a dynamic initialization +entry, which is rewritten in the usual way. See ``lower_expr_full``. + +One special problem: When class temporaries created under a conditional +operator ("``?``", "``&&``", or "``||``") require destruction, the destruction +must be done only if the initialization was done. For each case like this, it +is necessary to create a temporary, initialize it to zero at the start of the +block containing the expression, set it to one if the initialization is done, +and test it on exit from the block to determine whether or not to do the +destruction. See ``add_dyn_init_cleanup, init_conditional_flag_var, +set_conditional_flag_var, add_conditional_flag_test``. + +New and Delete +-------------- + +``new`` and ``delete`` are represented as an ``enk_new_delete`` expression +node. + +There are three main ``new`` cases (see ``lower_new``): + +* | A simple ``new`` is translated to a call of the appropriate ``new`` + routine. If the allocated object must be initialized, the pointer returned + from the allocation is tested to ensure that it is non-NULL, and then the + initialization is done. +* | A simple class ``new`` is often translated to a constructor call, passing a + NULL pointer as an indication that the constructor should do the + allocation. (This is enabled by ``NEW_CAN_BE_FOLDED_INTO_CTOR``. When + that is FALSE, the new routine is called, and if the allocation succeeds + the constructor is called.) +* | An array ``new`` is translated into a call of a runtime routine; see below. + +There are three main ``delete`` cases (see ``lower_delete``): + +* | A simple ``delete`` is translated into a call of the appropriate ``delete`` + routine. If the allocated object must be destroyed, the destructor is + called before the deallocation routine. +* | A simple class ``delete`` is usually translated into a destructor call, + passing a flag indicating that the destructor should do the deallocation. +* | An array ``delete`` is translated into a call of a runtime routine; see + below. + +Calls of ``new`` and ``delete`` that allocate or free arrays of classes that +have constructors or destructors are specially handled. They are converted to +calls of: + + | cfront-like ABI: + + | ``__vec_new(``\ *array, num_elems, elem_size, ctor_routine*\ ``)`` + | ``__vec_delete(``\ *array, num_elems, elem_size, dtor_routine, + free,* ``0)`` + + | IA-64 ABI: + + | ``__cxa_vec_new(``\ *num_elems, elem_size, padding, + ctor_routine, dtor_routine*\ ``)`` + | ``__cxa_vec_delete(``\ *array, elem_size, padding, + dtor_routine*\ ``)`` + +where + +.. list-table:: + + * - | *array* + - | is the address of the first element of the array. For + ``__vec_new``, it may be ``NULL`` to indicate that the space for the + array should be allocated. For ``__vec_delete``, it may be ``NULL`` + to indicate that the routine should do nothing. + * - | *num_elems* + - | is the number of elements in the array. For + ``__vec_delete``, it may be ``-1`` to indicate that the number of + elements given in the corresponding ``__vec_new`` should be used. + * - | *elem_size* + - | is the size in bytes of each array element. + * - | *ctor_routine* or *dtor_routine* + - | is the address of the constructor or destructor routine to call, or + NULL if no routine should be called. + * - | *free* + - | is non-zero to indicate that the storage for the array should + be freed. + * - | *padding* + - | is the size of the array prefix in which the number of elements is + recorded by the runtime. + +The final argument of the ``__vec_delete`` call is not used; it is present for +compatibility with cfront. + +These routines are necessary in order to save the number of elements in the +array from the time of the ``new`` (where it is known) to the time of the +``delete`` (where it is not available), and also to call the constructors and +destructors for all the array elements. + +For the cfront-like ABI, when exception handling is enabled, and only for +classes that have destructors, ``__vec_new_eh`` is called instead of +``__vec_new``. It has an additional final parameter that is a pointer to the +destructor. This is used to destroy any constructed elements if an exception +is thrown while ``__vec_new_eh`` is initializing the array elements. + +For the cfront-like ABI, when value-initialization is to be done for a class +that has a generated constructor, ``__vec_new_eh_zero`` is called. It has the +same parameter list as ``__vec_new_eh``, but it zeroes the storage before +calling the constructor. + +With array new and delete, it is possible to define class-specific + +* | ``operator new[]`` and +* | ``operator delete[]`` + +functions. When those are specified, different runtime routines are called: + + | cfront-like ABI: + + | ``__array_new(``\ *num_elems, elem_size, ctor_routine,* + | |_| |_| |_| |_| |.| |.| + *dtor_routine, new_routine, delete_routine, is_two_arg*\ ``)`` + | ``__array_delete(``\ *entity_node, num_elems, elem_size, dtor_routine,* + | |_| |_| |_| |_| |_| |_| |.| + *delete_routine, is_two_arg*\ ``)`` + + | IA-64 ABI: + + | ``__cxa_vec_new2(``\ *num_elems, elem_size, padding, ctor_routine,* + | |_| |_| |_| |_| |_| |_| |.| + *dtor_routine, new_routine, delete_routine*\ ``)`` + | ``__cxa_vec_new3(``\ *num_elems, elem_size, padding, ctor_routine,* + | |_| |_| |_| |_| |_| |_| |.| + *dtor_routine, new_routine, delete_routine*\ ``)`` + | ``__cxa_vec_delete(``\ *array, elem_size, padding, dtor_routine*\ ``)`` + +Most of the parameters are as described above. The others are: + +.. list-table:: + + * - | *new_routine* + - | is the address of the special ``operator new[]`` + routine, or NULL if the default routine should be used. + * - | *delete_routine* + - | is the address of the special ``operator delete[]`` + routine, or NULL if the default routine should be used. Also NULL on + ``__array_new`` if exceptions are disabled. + * - | *is_two_arg* + - | is ``1`` to indicate that the ``delete_routine`` takes + two arguments, ``0`` otherwise. + +These routines are used only if ``ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE`` is +TRUE. For the cfront-like ABI, if value-initialization is to be done, +``__array_new_zero`` is called in place of ``__array_new``. The IA-64 ABI +"``new3``" routine is used for the two-argument delete case. + +For the cfront-like ABI, when ``ABI_CHANGES_FOR_PLACEMENT_DELETE`` is TRUE, it +is possible to do a placement new of an array type and later deallocate the +storage via the ``delete`` operator. For that case, a special runtime routine +is called to ensure that the array size is recorded: + + | ``__placement_array_new(``\ *entity_node, num_elems, size_elem,* + *ctor_routine, dtor_routine*\ ``)`` + +and the value of the global runtime variable ``__array_new_prefix_size`` is +added to the size of the allocation requested in the placement new to allocate +extra space to contain the array prefix. See +``make_placement_array_new_call``. If value-initialization is to be done, +``__placement_array_new_zero`` is called in place of ``__placement_array_new``. + +See ``lower_array_new`` and ``lower_array_delete``. + +Constructors and Destructors for Arrays +--------------------------------------- + +Construction or destruction of an entire (static or automatic) array is done by +calling runtime routines. For the cfront-like ABI, ``__vec_new`` or +``__vec_delete`` are used (see previous section). The address of the array is +passed into ``__vec_new``, thus suppressing allocation, and ``0`` for the flag +``free`` is passed into ``__vec_delete``, thus suppressing freeing of the +storage. For the IA-64 ABI, there are specific runtime routines for these +functions: + + | ``__cxa_vec_ctor(``\ *array, num_elems, elem_size, ctor_routine,* + *dtor_routine*\ ``)`` + | ``__cxa_vec_dtor(``\ *array, num_elems, elem_size, dtor_routine*\ ``)`` + +Copying of an entire array using a copy constructor is done in the cfront-like +ABI by calling ``__vec_cctor``, passing the array address, the number of +elements, the element size, the address of the routine to call, and the source +array address. [#f4]_ In the IA-64 ABI, the runtime routine is +``__cxa_vec_cctor.`` + +If the constructor involved has default arguments, a wrapper routine is created +that requires no arguments other than the "``this``" parameter and calls the +constructor with the proper default arguments. The wrapper routine is then +passed to the runtime routine, which can call it like a normal constructor. + +See + +* | ``add_array_constructor_call`` +* | ``add_destructor_call`` +* | ``default_version_of_routine`` +* | ``make_vec_delete_call`` + +Pointers to Members +------------------- + +Pointer-to-member types (``tk_ptr_to_member``) are transformed as follows: + +* | Pointers to data members are converted to values of an integral type. The + integer contains a byte offset to the data member in the class. In the + cfront-like ABI, one is added to leave the zero value free to indicate a + NULL pointer to data member. In the IA-64 ABI, nothing is added, and -1 is + used for a NULL pointer to data member. + + .. code:: c++ + + struct A { int i; int j;}; + int A::*pdm = &A::j; // unsigned int pdm = 5(cfront) 4(IA-64) + int A::*pdmn = 0; // unsigned int pdmn = 0(cfront) -1(IA-64) + +* | Pointers to member functions are represented by structures with the form + + * | cfront-like ABI: + + .. code:: c++ + + typedef void (*__vptp)(); + struct __mptr { short d; short i; __vptp f; }; + + | This is essentially the structure described in 8.1.2.c of the ARM. + ``d`` is the offset to be added to the "``this``" pointer; ``i`` is the + index into the virtual function table (or -1 for a nonvirtual function, + or 0 for a NULL pointer); ``f`` is the nonvirtual function pointer when + ``i`` is -1 or the offset to the virtual function table pointer + (appropriately cast) when ``i`` is greater than zero. + + .. code:: c++ + + struct A {int f(); virtual int g();}; + int (A::*pmf)() = &A::f; // struct __mptr pmf = {0, -1, &f__1AFv}; + int (A::*pmg)() = &A::g; // struct __mptr pmg = {0, 1, 0}; + + * | IA-64 ABI: + + .. code:: c++ + + typedef void (*__vptp)(); + struct __mptr { __vptp f; ptrdiff_t d; }; + + | ``f`` is zero for a NULL pointer, is a pointer to a function for the + non-virtual case, and is the vtable offset in bytes plus one for the + virtual function case. ``d`` is the offset to be added to the "``this``" + pointer. When ``IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR`` is + TRUE, an alternate representation is used that works on architectures where + the low-order bit of a function address can be non-zero. In that + representation, ``f`` is zero for a NULL pointer (but you also have to + check that the low-order bit of ``d`` is zero), is a pointer to a function + for the non-virtual case, and is the vtable offset in bytes for the virtual + function case. ``d`` is the offset to be added to the "``this``" pointer, + shifted left one bit, and its low-order bit is one for the virtual function + case. + +See ``lower_type``. + +Pointer-to-member constants (``ck_ptr_to_member``) are transformed to the above +forms. See ``lower_ptr_to_member_constant``. The function case generates a +``ck_aggregate`` constant. Such constants can only be used when the constant +appears as an initializer value; for other kinds of references (e.g., in an +assignment statement), the reference to the constant is changed to a reference +to a temporary variable that is initialized with the aggregate constant. + +Assignment and comparison of pointers to data members are changed to integer +assignment and comparison operators. Assignment of pointers to member +functions is changed to structure assignment. Comparison of pointers to member +functions is changed to + + | cfront-like ABI: + + .. code:: c++ + + (op1.i == op2.i) && (op1.i == 0 || (op1.d == op2.d && op1.f == op2.f)) + + IA-64 ABI: + + .. code:: c++ + + (op1.f == op2.f) && (op1.f == 0 || op1.d == op2.d) + + IA-64 ABI alternate representation: + + .. code:: c++ + + (op1.f == op2.f) && ((op1.f == 0 && (((op1.d | op2.d) & 1) == 0)) + || op1.d == op2.d) + +(That is the code for ``==``; the code for ``!=`` is similar.) If one of the +operands is a constant, the comparisons are done directly against the constant +values of the components of the constant, and unnecessary parts of the +expression above are omitted. A comparison against a null pointer to member +constant, for example, becomes simply + +.. code:: c++ + + (op1.i == 0) + +for the cfront-like ABI. + +Casting a pointer to a data member to a base or derived class is changed to + + | cfront-like ABI: + + .. code:: c++ + + (pdm != 0) ? (pdm + offset) : 0 + + IA-64 ABI: + + .. code:: c++ + + (pdm != -1) ? (pdm + offset) : -1 + +Casting a pointer to a member function to a base or derived class is changed to + + | cfront-like ABI: + + .. code:: c++ + + (temp = pmf, (temp.i != 0) ? (temp.d += offset) : 0, temp) + + IA-64 ABI: + + .. code:: c++ + + (temp = pmf, (temp.f != 0) ? (temp.d += offset) : 0, temp) + + IA-64 ABI alternate representation: + + .. code:: c++ + + (temp = pmf, (temp.f != 0 || temp.d != 0) + ? (temp.d += offset) : 0, temp) + +The tricky issue in both cases is preserving a NULL pointer to member. + +See ``lower_pm_related_class_cast``. + +Casts from one pointer-to-member-function type to another (not related) are +removed since both types will now have the same representation and since the +cast, left in, would be a cast to a structure type. Similar casts between +pointers to data members are casts from an integral type to the same integral +type and are left alone. + +The ``eok_pm_points_to_field`` and\ ``eok_pm_field`` operators, which implement +the ``->*`` and ``.*`` operators for pointers to data members, are rewritten: + +.. code:: c++ + + p->*pdm + +is lowered to + +.. code:: c++ + + (member-type *)(((char *)p)+(pdm-1)) + +The IA-64 ABI version does not need the -1. + +See ``lower_pm_field``. + +The ``eok_pm_call`` operator, which implements calls of functions identified by +a pointer to member, is rewritten: + +.. code:: c++ + + object->pmf(args ...) + +is lowered to (cfront-like ABI) + +.. code:: c++ + + ((this_temp = (object_type *)((char *)object + pmf.d)), + // Adjust "this" pointer by delta from + // pointer-to-member. + (func_temp = (function_type *) + // The computed function address gets cast to the + // proper function type. + ((pmf.i < 0) ? // Check virtual/non-virtual pointer-to-member. + pmf.f : // Function address for non-virtual case. + // Virtual function case: + ((vtbl_temp = // Virtual function table entry address is address + // of virtual function table + offset in table. + *(__vtbl_entry **)((char *)this_temp + + (short)(pmf.f)) + + // Pointer to virtual function table is at offset + // pmf.f in the object. + pmf.i), // + offset into table + this_temp = (object_type *) + ((char *)this_temp + vtbl_temp->d), + // Adjust "this" pointer to get pointer to subobject + // expected by the virtual function. + vtbl_temp->f))), // Address of virtual function. + func_temp( // Call using the function pointer computed. + // Arguments for the call: + this_temp, // "this" pointer. + args ...)) // Additional arguments, if any. + +If ``pmf`` is not a reusable expression, the first occurrence of ``pmf`` above +is replaced by ``(pmf_temp = pmf)``, and the rest by ``pmf_temp``. + +If the class and its base classes have no virtual functions, and the variable +``pointer_to_member_call_optimization_allowed`` is TRUE (which does not conform +to the C++ standard), the following simpler version is used: + +.. code:: c++ + + ((this_temp = (object_type *)((char *)object + pmf.d)), + eok_call((function_type *)pmf.f, + this_temp, + additional_args ...)) + +This seems slightly more complicated than is needed, but it makes sure that if +a reusable copy of ``pmf`` is needed, the temp for it is initialized before the +call is begun. + +For the IA-64 ABI, the code is: + +.. code:: c++ + + ((this_temp = (object_type *)((char *)object + pmf.d)), + // Adjust "this" pointer by delta + // from pointer-to-member. + (func_temp = (function_type *) + // The computed function address gets cast to the + // proper function type. + ((pmf.f & 1) == 0) ? // Check virtual/non-virtual pointer-to-member. + pmf.f : // Function address for non-virtual case. + // Virtual function case: + ((vtbl_temp = // Virtual function table entry address is address + // of virtual function table + offset in table. + *(__vtbl_entry **) + ((char *)this_temp + + // Pointer to virtual function table is at offset + // zero in the object + ((ptrdiff_t)pmf.f - 1)), + // + offset into table, dropping low-order bit. + *vtbl_temp))), // Address of virtual function. + func_temp( // Call using the function pointer computed. + // Arguments for the call: + this_temp, + // "this" pointer. + additional_args ...)) // Additional arguments, if any. + +See ``lower_pm_call``. + +Operations Returning Lvalues +---------------------------- + +Operations that return lvalues in C++ but not in C, i.e., assignment operators, +prefix ``++`` and ``--``, and "``?``" and "``,``" operators, are rewritten in C +form. Often this involves duplication of expressions. This rewriting +operation is enabled or disabled by ``LOWER_LVALUE_RETURNING_OPERATIONS``. + +Lvalue-returning assignments are rewritten from + +.. code:: c++ + + (c1 = c2) + +to + +.. code:: c++ + + ((c1 = c2), rcc2) + +where ``rcc2`` is a reusable copy of ``c2`` (see +``make_lvalue_reusable_copy``). The comma operator is an lvalue-returning +operator, which is then further rewritten (see following). + +Lvalue-returning "``?``" operators are rewritten from + +.. code:: c++ + + ((g1 ? g2 : g3) = c2) + +to + +.. code:: c++ + + (g1 ? (g2 = c2) : (g3 = c2)) + +Lvalue-returning "``,``" operators are rewritten from + +.. code:: c++ + + ((g1 , g2) = c2) + +to + +.. code:: c++ + + (g1 , (g2 = c2)) + +For both the "``?``" and the "``,``" cases, the operations in the rewritten +form are lvalue operations iff the "``=``" operation in the original is an +lvalue operation. The operation indicated as "``=``" can in fact be any +operation (e.g., simple or complex assignment, prefix ``++`` or ``--``, field +selection). ``c2`` isn't present for unary operations. + +Related Class Casts +------------------- + +Base or derived class casts are lowered by replacing the cast with an operation +that adds or subtracts the byte offset required. A few issues require special +handling: + +* | If the offset is zero, which it always is with single inheritance, the cast + can remain a cast between two pointer types. +* | A NULL pointer must pass through a related class cast unaltered. To do + that, a conditional test is required around the code that adds or subtracts + the offset. To avoid putting out this code in too many places, it is put + only once around a sequence of related class casts, and it is suppressed + altogether if (a) all the casts in the sequence have zero offsets, or (b) + the expression is known to be non-NULL (e.g., the "this" pointer in a + member function). +* | Casts to virtual base classes involve fetching the virtual base class + pointer rather than adding or subtracting an offset. + +See ``lower_related_class_cast``. + +.. _il-bool-type: + +bool +---- + +In modern C++, there is a ``bool`` type, and operations like "``!=``" return +``bool`` instead of ``int``. (C99 has a ``_Bool`` type, but the boolean +operation -- like "``!=``" and "``>``" -- produce ``int`` values.) The IL +representation of a boolean type is identical to an ordinary small integer +type, except that the variant field ``variant.integer.bool_type`` is TRUE. +That representation is therefore not lowered: A back end can just ignore the +``bool_type`` field and treat a boolean type as the underlying integer type. + +Several ``bool`` operations are rewritten by IL lowering: + +* | ``eok_bool_cast``, which represents a cast to ``bool`` (or ``_Bool``), is + rewritten as a "``!= 0``" test of the appropriate type. See + ``lower_bool_cast``. +* | An increment of a ``bool`` lvalue is rewritten to set the lvalue to 1 + (``true``). In the postincrement case, this involves saving the original + value, setting the lvalue to 1, and then returning the saved original + value. See ``lower_bool_increment``. +* | The return types of operations that yield a ``bool`` in C++ but an ``int`` + in C, e.g., "``!=``" and "``&&``", are rewritten to yield an ``int``. In + contexts where the result is tested directly, the type is simply changed; + where something else is done with the result (e.g., storing it in a + variable), a cast to the proper type is inserted. See + ``adjust_bool_operation_types``. +* | Compound assignment operators whose left-hand operand has type ``bool`` (or + ``_Bool``) are rewritten to ensure that the result value is restricted to + 0/1. See ``rewrite_compound_assignment``. + +Condition Declarations +---------------------- + +In ``if``, ``while``, ``for``, and ``switch`` statements, the expression tested +can be a condition declaration. For example: + +.. code:: c++ + + if (float x = f()) { ... } + +This is represented in the IL as an expression node of kind ``enk_condition``. + +Loops and non-loops are handled somewhat differently by IL lowering. Non-loops +(``if``, ``switch``) are rewritten as follows: + +.. code:: c++ + + if (A x = y) { ... } + +is transformed into + +.. code:: c++ + + { A x = y; if (x) { ... }} + +The test in the ``if`` actually uses the expression from the ``expr`` field of +the condition, which is the value of the declared variable converted to a +testable type if necessary. + +Loops (``while``, ``for``) are rewritten as follows: + +.. code:: c++ + + for (w; A x = y; z) { ... } + +or + +.. code:: c++ + + while (A x = y) { ... } + +is transformed into + +.. code:: c++ + + { { + for (w;;) { while (1) { + A x = y; A x = y; + if (!x) { if (!x) { + destroy x if necessary; destroy x if necessary; + goto break_label; goto break_label; + } } + { ... } // Original statement { ... } // Original statement + z; // Increment code + destroy x if necessary; destroy x if necessary; + } } + break_label:; break_label:; + } } + +Again, the ``x`` in ``!x`` is the value of the declared variable converted to a +testable type if necessary. If the ``break_label`` exists already, it and the +block around the for/while are not added. + +See ``lower_condition``. + +Anonymous Unions +---------------- + +In the unlowered IL, field selections of fields of anonymous unions that are +embedded in classes elide the field selection(s) for the anonymous union(s). +For example: + +.. code:: c++ + + class A { + union { + int i; + float j; + }; + } x; + +``x.i`` appears as a selection of ``i`` directly out of ``x``. IL lowering +adds the implied field selection through the unnamed union. + +See ``adjust_field_selection_for_anonymous_union_references``. + +Automatic Template Instantiation +-------------------------------- + +When automatic template instantiation is enabled and +``instantiation_flags_in_template_info_file`` is FALSE (an old mode not longer +much used), IL lowering helps the cause by getting certain information about +instantiations passed into the object file. The instantiation information is +recorded in the flags + +* | ``can_be_instantiated``, +* | ``do_not_instantiate``, and +* | ``instance_required`` + +that appear in variable and routine entries. + +IL lowering passes the values of these flags into the object code by generating +tentative definitions of global-scope variables that have names formed by +combining a prefix with the mangled name for the entity for which the flag is +being generated. The prefixes are + +* | ``__CBI__`` for the ``can_be_instantiated`` flag, +* | ``__DNI__`` for the ``do_not_instantiate`` flag, and +* | ``__TIR__`` for the ``instance_required`` flag. + +The routine ``make_instantiation_info_var`` is used to create these variables. + +For template classes with virtual functions, where the decision on whether or +not to output a definition of the virtual function table is based on the +presence of a definition for the first non-inline virtual function of the +class, a reference to the virtual function table causes a ``__TIR__`` for the +first virtual function to be generated (that requests a definition of the +function, and therefore of the virtual function table, somewhere in the +program). When a virtual function definition is generated, it references all +the virtual functions of the class, so ``__TIR__`` variables are generated for +them (except for the first virtual function, to avoid the chicken-and-egg +problem of the first virtual function and the virtual function table each +forcing the other to be instantiated, with neither actually referenced from +anywhere). + +The prelinker phase notices these names in the object files, and from them can +recover the associated instantiation information. + +Guard Code on Variable Template and Template Static Data Member Initializations +------------------------------------------------------------------------------- + +When ``TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE`` (in ``targ_def.h``) is +TRUE, "guard" code is placed around initializations of instances of variable +templates and static data members of templates. Such guard code is necessary +if template instantiation resolution is done by instantiating everything and +then having the (specially-modified) linker discard duplicate copies of +instantiated routines. Dynamically-initialized template variables and static +data members of templates are a particular problem: because the initialization +code is generated in startup routines, and is undifferentiated from other code +in those routines, a flag is needed to indicate that initialization has already +been done. After any one instance of the code does initialization, all other +instances will do nothing. + +The initialization guard code looks like (cfront-like ABI): + +.. code:: c++ + + int guard_var; // Implicitly initialized to 0 + { + if (guard_var == 0) { + guard_var = 1; // Initialization of static data member + } + } + +For the IA-64 ABI, the code sequence is the one generated by +``add_first_time_test``, which has either calls of ``__cxa_guard_acquire`` et +al. or is like the above but with the setting of the guard variable after the +initialization. + +If the template variable or static data member is a specialization, its +initialization should take precedence over any other (non-specialization) +initializations. For that case, the guard variable is put out as a definition +with an initial value of ``-1``. That disables the construction guard code for +all other instances. + +Destruction is not a problem, since all destructions of static entities are put +on a list to be done at the end of program execution. The entry is only put on +the list exactly once when and if the initialization is done. + +Runtime Type Information +------------------------ + +Runtime type information is needed for exception processing and for the RTTI +features of the C++ language. IL lowering generates special ``typeinfo`` +variables for each type that requires such information. + +In the cfront-like ABI, note that the runtime ``typeinfo`` is not the same type +as the programmer-visible ``type_info``; the runtime ``typeinfo`` contains a +``type_info`` structure as a member, and has other information besides. The +``typeinfo`` variables have mangled names of the form + + | ``__T_``\ *mangled-type-encoding* + +(except static ``typeinfo`` variables for non-class types, which are unnamed). + +The variables are ``typeinfo`` structures (this is still for the cfront-like +ABI): + +.. code:: c++ + + struct typeinfo { + type_info tinfo; // User-visible type_info structure + const char *name; // Null-terminated string for name + char *id; // Id object pointer + base_class_spec *bc; // Array of base class information + }; + +Each pointer field is NULL if it is not applicable. In versions preceding +2.38, there was an additional field after ``id`` which contained a destructor +pointer. It was eliminated when the\ ``__throw_setup_dtor`` runtime routine +was added. In versions preceding 2.41, the ``name`` field was not const (it +was made const when const string literals were implemented). + +In the IA-64 ABI, the ``type_info`` type visible to the user is the same as the +implementation type, and it has a number of derived classes that provide +additional information for pointer types, class types, etc. as described in +the ABI spec. ``typeinfo`` variables have mangled names beginning with +"``_ZTI``". + +If the type represented by a ``typeinfo`` variable is a polymorphic class, the +``typeinfo`` variable is external if and only if the virtual function table +variable for the class is external, and the ``typeinfo`` variable is defined +(i.e., initialized) if and only if the virtual function table is defined. For +other cases (non-polymorphic classes and non-classes), the ``typeinfo`` +variable is always static and always defined. + +In the IA-64 ABI, the typeinfo variable is made a COMDAT so that there will be +only one copy in the linked program even when the virtual function table +heuristic does not place the definition in a single file. Likewise, the name +string for a ``typeinfo`` variable is placed in a separate variable with a +predictable mangled name (beginning with "``_ZTS``"), which is made a COMDAT so +that all instances of the name are shared. + +In the cfront-like ABI, when the ``typeinfo`` variable is static, and the +type is not an internally-linked class, it is possible that the same type +is represented by several ``typeinfo`` variables. [#f5]_ In those cases, +the object id pointer is used to indicate that those ``typeinfo`` entries +all correspond to the same type: the object id pointer is non-NULL and +points to an id object variable of type ``char`` whose name has the form + + ``__TID_``\ *mangled-type-encoding* + +This variable is put out as a tentative definition and therefore there will be +only one copy of a given id object variable in the executable program. Two +``typeinfo`` variables are considered to represent the same type if their id +object pointers are non-NULL and equal to one another. + +In the cfront-like ABI, for classes that have base classes, the base class +array field points to a (static) variable initialized to an array of entries +with the following structure: + +.. code:: c++ + + struct base_class_spec { + typeinfo *tinfo; // typeinfo for base class + short offset; // Offset of base class in derived class + unsigned char flags; // Flags + }; + +Only direct, virtual, and ambiguous base classes of the derived class +appear in the base class list. The flags byte contains a bit set: +``0x01`` indicates a virtual base class, ``0x02`` is set to mark the +last entry in the array, ``0x04`` indicates a public base class, ``0x08`` +indicates an ambiguous base class, and ``0x10`` indicates a direct base +class. + +When ``ABI_CHANGES_FOR_RTTI`` is FALSE, an older form of the ``typeinfo`` entry +is generated, which is adequate for exception handling but not for RTTI. The +differences are as follows: + +* | The ``type_info`` and ``name`` fields are not present. +* | ``typeinfo`` variables for nonclass types are put out as tentative + definitions and rely on default initialization to zero. Because of the + name mangling and the fact that the variable is external, there will be + only one copy of the ``typeinfo`` variable for any given nonclass type in + the executable program. No id object variable is needed. +* | The public base class and ambiguous bits in the base class specification + are not set. + +The ``typeid`` operator +^^^^^^^^^^^^^^^^^^^^^^^ + +The C++ ``typeid`` operator is represented by an expression node with kind +``enk_typeid``. + +If the ``typeid`` node has a null expression pointer, the type is known +statically. IL lowering generates a ``typeinfo`` entry for the static type, +and replaces the ``typeid`` node with a field selection that computes the +address of the ``tinfo`` member of the ``typeinfo`` variable. + +If the ``typeid`` node has a non-null expression pointer, the type (a +polymorphic class) must be determined at runtime. + +In the cfront-like ABI, IL lowering replaces the ``typeid`` node with a runtime +routine call + +.. code:: c++ + + __get_typeid((typeid_expr != NULL) ? vptr : NULL) + +where ``typeid_expr`` is the ``typeid`` expression (or more precisely the +address indicated by that expression) and ``vptr`` is an expression for the +value of the virtual function table pointer for the class object pointed to. +If ``typeid_expr`` is not reusable, it will be assigned to a temporary and the +temporary will be used in the ``vptr`` expression. Note that when +``typeid_expr`` is null, a null pointer is passed to ``__get_typeid``; the +latter then throws ``bad_typeid``. + +In the IA-64 ABI, the code sequence is entirely inline: + +.. code:: c++ + + (typeid_expr != NULL) ? (typeinfo*)(vptr[-1]) : + (__cxa_bad_typeid(), NULL) + +The ``dynamic_cast`` operator +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A ``dynamic_cast`` is represented by an expression node with operator +``eok_dynamic_cast``. IL lowering rewrites that into + + cfront-like ABI: + + .. code:: c++ + + (src != NULL) ? __dynamic_cast (src, vptr, desired_type, orig_src, + static_type) : + NULL + + or + + .. code:: c++ + + (src != NULL) ? __dynamic_cast_ref(src, vptr, desired_type, orig_src, + static_type) : + NULL + + IA-64 ABI: + + .. code:: c++ + + (src != NULL) ? __dynamic_cast (src, static_type, desired_type, hint) : + NULL + + or + + .. code:: c++ + + (temp = __dynamic_cast (src, static_type, desired_type, hint)) + ? temp : __cxa_bad_cast() + +The second form in each ABI is for a cast to a reference type. ``src`` is the +expression being cast (or its address, in the reference case); ``vptr`` is the +virtual function pointer for the class (note that it's protected by the +null-pointer check); ``desired_type`` is a pointer to the ``typeinfo`` for the +desired class, or NULL for a dynamic cast to "``void *``"; ``orig_src`` is the +original source pointer in the dynamic cast (the value passed as the first +parameter may have been cast to a base class if the original class has no +virtual function pointer); and ``static_type`` points to the ``typeinfo`` for +the underlying class of the source pointer's static type. + +In the IA-64 ABI, a ``dynamic_cast`` to ``void *`` is done as inline code, by +extracting the offset-to-base from the [-2] entry in the virtual function table +and adding that to the object address. + +Note that ``dynamic_cast``\ s that do not require runtime processing are +translated by the front end into simple casts or base class casts. + +Exceptions +---------- + +The lowering of exception handling (EH) features can be configured three +different ways: + +#. Full lowering: all exception handling features are reduced to C, and + no support for EH features is required in the back end. This solution + is easy to use and highly portable, but entails a fairly significant + overhead in execution cost (15-20%). This mode is required for the + C-generating back end, and is supported by the minimal runtime + provided by EDG. It is enabled by the configuration switch + ``DO_FULL_PORTABLE_EH_LOWERING``. + +#. Partial lowering: the data tables of the portable scheme are generated, + but they use stack offsets for variables (in the portable scheme, all + addresses are computed at runtime and stored in an object address table). + ``try``, ``catch``, and ``throw`` are preserved in the IL. Much of the + minimal runtime provided by EDG would still be applicable, but some + parts would require changes. This mode is enabled by the configuration + switch ``GENERATE_EH_TABLES``. + +#. No lowering: No data tables are generated; the object lifetime + information is preserved for use in generating tables in a back end. + ``try``, ``catch``, and ``throw`` are preserved in the IL. The back + end makes all decisions about the way in which EH features are + implemented. This mode is enabled by having both ``GENERATE_EH_TABLES`` + and ``DO_FULL_PORTABLE_EH_LOWERING`` set to FALSE. + +It should be noted that in all three schemes the statements and expressions +attached under EH constructs are lowered. Even in the partial/no lowering +schemes, lowering generates the code needed for things like copying thrown and +caught objects. Special expression nodes that represent (partially) lowered +exception handling constructs, of kind ``enk_lowered_eh_construct``, are used +to represent the parts of those operations that remain for the back end to +define. + +The portable implementation is the one that involves the most transformations +in IL lowering, and the other two schemes are essentially scaled-back versions +of the full-lowering scheme. Therefore, the description that follows covers +the processing for the full-lowering scheme and indicates differences in the +other schemes. + +Exception handling imposes a nontrivial overhead in time and/or space on +programs, including those that do not make use of exceptions. Accordingly, +exception handling can be enabled or disabled by a command-line option, and +when it is disabled IL lowering will not generate the code or data structures +to support it. + +The fully- and partially-lowered implementations do work with the IA-64 ABI, +but they are not compatible with the ABI spec. For a fully-comforming IA-64 +ABI implementation, it is necessary to do the EH implementation in the back +end. + +Maintaining Context +^^^^^^^^^^^^^^^^^^^ + +When an exception is thrown, the stack is unwound to the catch point, and +destructible objects created in the stack frames removed from the stack must be +destroyed by the runtime. In order to be able to do that, the runtime must +have access to information about the stack frames and the destructible objects +therein. This information is provided by entries linked into an exception +handling stack. There are three kinds of stack entries: + +* | Entries representing a function. These are pushed on entry to a function + and popped on exit from that function, and they point to information about + the destructible objects in the function. No stack frame is needed for any + function that has no destructible objects and no try blocks. +* | Entries for exception specifications of a function. These are pushed at + the beginning of each function having an exception-specification (i.e., a + list of the exception types that the function is permitted to throw), and + popped at the end of each such function. The stack frame points to an + array that describes the types that may be thrown. +* | Entries for ``try`` blocks. These are pushed at the beginning of each + ``try`` block and popped on exit from each such block. The stack frame + provides space for a ``setjmp`` buffer, and a pointer to an array that + describes the types caught at each associated ``catch`` handler clause. + +The code to push and pop stack frames is generated by + +* | ``push_eh_stack_frame`` and +* | ``pop_eh_stack_frame``. + +The function and exception-specification stack frames are requested by +``add_eh_function_prologue`` (which also handles epilogue code). + +The function stack frame points to several data structures that describe the +destructible objects: + +* | The region table, which has entries that describe objects and the cleanup + to be done for them. See ``make_region_table_entry``. The table is an + array, and an index into that array is called a *cleanup region number*. + Each entry contains a cleanup region number for a "next" entry in the + table, which makes it possible to link entries into lists of cleanup + actions. At any given point in a function, one can describe the sequence + of cleanup actions required on termination of that routine by indicating a + cleanup region number, i.e., the index number of the first entry of a + linked list of region table entries that enumerates the destructions and + deallocations to be done, in the order they are to be done. IL lowering + generates code to maintain the global variable ``__eh_curr_region`` + appropriately to indicate the set of cleanup actions necessary at each + point in each function. See ``assign_to_eh_curr_region``. +* | The array table, which provides additional information about destructible + objects that are arrays (for example, the array element size). See + ``make_array_table_entry``. +* | The object address table, which provides the addresses of destructible + objects. The region table identifies objects by indicating their index + numbers in the object address table. This extra level of indirection is + necessary to separate the static parts of the region table, which can be + used for all activations of a function, from the changeable part, which is + different for each activation. (When a function calls itself recursively, + for example, the exception stack entries for the various activations will + point to distinct copies of the object address table but to a common static + copy of the region table.) See ``object_addr_table_index``. + +The exception-specification stack frame indicates the types that may be thrown +by pointing to an array whose elements are exception type specifications. An +exception type specification is a structure defined as follows: + +.. code:: c++ + + struct exception_type_specification { + typeinfo *tinfo; + unsigned char flags; + unsigned char *ptr_flags; + }; + +The ``tinfo`` pointer points to a ``typeinfo`` variable for a type. The +``flags`` value is a bit set that indicates modifications of that type, e.g., +pointer-to the type. One of the bits is used to indicate the last entry in the +array. The ``ptr_flags`` field (added in version 2.41) is non-null for +multi-level pointer types. It points to an array of flags values, each one +describing the cv-qualifiers at one level of a multi-level pointer type. +Again, one of the bits is used to indicate the last entry in the array. + +The try-block stack frame contains space for a ``setjmp`` buffer, and a pointer +to an array in which each entry represents a catch handler. The entries in the +array are exception type specification structures, each one describing the type +to be caught by the associated handler. + +Note that local and global static variables are never handled in normal +exception cleanup. The required destructions for all static entities that have +been constructed are placed on a runtime list, and therefore the cleanup for +those entities need not and should not be described in the region tables. + +In the partial-lowering scheme, the region table and array table are generated, +but the object address table is not used. Instead, the addresses of variables +in the region table and array table are given as stack offsets using +``ck_stack_offset`` constants. Since there is no object address table, the +code that computes addresses and places them in the object address table is +unnecessary. No exception stack is maintained; instead, expression nodes with +subkinds ``leck_function_prologue`` and ``leck_function_epilogue`` are inserted +at the appropriate places to indicate to the back end that appropriate +maintenance should be done at those points, and to identify the variables for +the region table and array table. It is assumed that the back end will also +deal with the exception-specification, if any, for the function. In place of +assignments to ``__eh_curr_region``, expression nodes with subkind +``leck_cleanup_state`` are used to communicate the new region table entry +number to the back end at each place that changes it. ``typeinfo`` information +is still put out for all types involved in exception handling operations, but +there will be no references to those entries in the lowered code. They are +pointed to from the type entries, available for use by a back end. + +In the no-lowering scheme, none of the tables are generated (including the +``typeinfo`` entries). As in the partial-lowering scheme, + +* | ``leck_function_prologue``, +* | ``leck_function_epilogue``, and +* | ``leck_cleanup_state`` + +nodes will be inserted. The latter have a pointer to a dynamic initialization +entry, rather than a region number, as the indication of the cleanup state to +be established at that point. + +When ``INDICATE_CLEANUP_STATE_IN_UNREACHABLE_CODE`` is TRUE, cleanup state +instructions will be emitted even at the unreachable ends of blocks. This may +be desirable if the back end is using the cleanup state information to build a +table of cleanup address ranges rather than leaving them as some kind of +executable code. The instructions generated will have the special kind +``leck_unreachable_cleanup_state``. + +Throwing an Exception +^^^^^^^^^^^^^^^^^^^^^ + +The ``enk_throw`` expression node is rewritten either as + +.. code:: c++ + + __rethrow(); + +for the rethrow case (``throw`` with no operand), or as + +.. code:: c++ + + ((temp = __throw_setup(&typeinfo, size, flags)), + (initialization, __throw())) + +for the normal case. ``typeinfo`` is the runtime type information variable for +the base type being thrown, ``size`` is the size in bytes of the object being +thrown, and ``flags`` is a bit set that indicates the relationship of the type +thrown to the ``typeinfo`` type -- for example, that the type being thrown is a +pointer to the type indicated by the ``typeinfo`` variable. The +``__throw_setup`` call allocates space for a copy of the thrown object; the +initialization code makes a copy of the thrown object in that allocated space; +and the ``__throw`` call actually does the throw (and does not return). If the +thrown object requires destruction, ``__throw_setup_dtor`` is called instead of +``__throw_setup`` (this routine was added in version 2.38). +``__throw_setup_dtor`` has an additional final parameter, which is the +destructor pointer. If the thrown object is a multi-level pointer, +``__throw_setup_ptr`` is called instead of ``__throw_setup`` (this routine was +added in version 2.41). ``__throw_setup_ptr`` has a parameter in place of the +flags parameter, which is a pointer to an array of flag bytes that indicate the +cv-qualifiers at each level of the multi-level pointer type. In cases where +the thrown object is copied to the allocated space using a copy constructor, +and the copy is implicit, ``__exception_started`` is called before the copy +constructor call to tell the runtime to consider the copy constructor call as +"inside" the throw. + +In front end versions preceding 2.29, and when ``ABI_CHANGES_FOR_RTTI`` is +FALSE, a runtime routine ``__throw_alloc`` is called instead of +``__throw_setup``. It has one additional argument: if the ``typeinfo`` +type is a class with base classes, the argument is a character string +containing the letter "``Y``" or "``N``" for each base class to indicate +whether the base class is accessible. Otherwise, it is a NULL pointer. + +In the partial-lowering and no-lowering schemes, the ``enk_throw`` node is +preserved. The dynamic initialization that copies the thrown object is +lowered, using a node with subkind + +* | ``leck_thrown_object_address`` + +to indicate the address in the runtime to which the thrown object should be +copied. A node with subkind ``leck_exception_started`` is used to mark the +point before a copy constructor call. + +See ``lower_throw``. + +Catching an Exception +^^^^^^^^^^^^^^^^^^^^^ + +The routine ``lower_try_block`` lowers the ``stmk_try_block`` statement to +generate code for a ``try`` and its associated ``catch`` clauses. The code +does roughly the following: + +* | Push a try-block entry on the exception stack. This entry points to an + array whose elements describe the types to be caught by each ``catch`` + handler. The index of an entry in the array is the number assigned to + identify the associated ``catch`` handler. +* | Do a ``setjmp`` in an "``if``" surrounding the dependent statement of the + ``try``. This records the address to be jumped back to in the event that + one of the catch handlers is to be executed. When the call to ``setjmp`` + returns (the first time), the ``try`` block is executed. +* | For each ``catch`` handler, test the global variable + ``__catch_clause_number`` (which is set by the runtime before the transfer + back to this code) to see if it matches the number of the catch clause. If + so, copy the value of the caught object (whose address the runtime provides + in ``__caught_object_address``) to the handler parameter (see + ``begin_catch_clause``). Call ``__exception_caught`` to indicate to the + runtime that the exception is fully caught. Execute the dependent + statement of the ``catch``, and, on exit, call ``__free_thrown_object`` + (see ``cleanup_on_exit_from_catch``). +* | At the end of the ``try`` block, whether reached from the ``try`` or from a + ``catch`` handler, pop the try-block entry off the exception stack. + +Note three aspects of using ``setjmp`` to implement ``try``: + +#. The size of the ``setjmp`` buffer must be configured to match the target + environment. See + + * | ``TARG_JMP_BUF_NUM_ELEMENTS``, + * | ``TARG_J _BUF_ELEMENT_INT_KIND``. + * | ``TARG_JMP_BUF_ELEMENTS_ARE_FLOAT``, and + * | ``TARG_JMP_BUF_ELEMENT_FLOAT_KIND`` + + in ``targ_def.h``. +#. The ``setjmp`` is represented as a runtime routine call. This may + necessitate some sleight of hand from a back end if ``setjmp`` is not really + a runtime routine. +#. Some optimization may have to be suppressed for the region of the ``try`` + block. In C, on return from a ``setjmp`` only ``volatile`` variables are + guaranteed to be set correctly. The code generated by IL lowering, however, + assumes that all variables are set correctly, which means that variables + cannot be kept in registers over calls in any code in which exceptions might + be thrown. The ``contains_try_block`` flag in the routine entry is a + partial solution. See also the ``modified_within_try_block`` flag. + +In the partial-lowering and no-lowering schemes, the ``stmk_try_block`` +statement is preserved, with things under it lowered. The initializations of +``catch`` parameters are lowered, with a node with subkind +``leck_caught_object_address`` used to represent the address in the runtime +from which the caught object should be copied. (Note that the implicit +indirection inserted for reference parameters in the full-lowering approach is +not inserted in these modes; a back end can check the handler parameter type +and generate such an indirection if one is necessary.) A node of subkind +``leck_exception_caught`` is used to indicate the point (after the +initialization, if any) where the exception is considered fully caught. On +exit from a ``try`` or ``catch`` (by flowing off the end or by ``goto`` or +``return``), a node of subkind ``leck_try_epilogue`` or ``leck_catch_epilogue`` +is inserted. + +Unordered Evaluation +^^^^^^^^^^^^^^^^^^^^ + +The C and C++ language rules do not fully define the order of evaluation of +parts of expressions. For example, in "``A(1) + A(2)``" the evaluation of +``A(1)`` could occur before or after the evaluation of ``A(2)``. When +destructible temporaries appear in such contexts, the order of construction and +destruction of the temporaries cannot be predicted from the language rules +alone, e.g., the temporary for ``A(1)`` could be constructed before or after +the temporary for ``A(2)``. Such temporaries are called "unordered" +temporaries, and the dynamic initialization entries for them are marked as +such. These temporaries cause a problem for a portable implementation, because +is it necessary when indicating the cleanup to be done at the point of +construction of ``A(1)`` or ``A(2)`` to indicate that the other temporary might +or might not already have been constructed. This is done by adding a +conditional flag for each temporary, which indicates whether or not the +construction has been done, and having the cleanup position in the cleanup +region table include destructions for both temporaries. The runtime then tests +the conditional flags to indicate whether the destructions should actually be +done. This method, of course, involves a time and space overhead, so the flag +``DO_UNORDERED_EH_PROCESSING`` can be set to FALSE to switch it off. It can be +switched off if the back end will do the constructions in the canonical order +indicated by the IL, or if the ``next_in_destruction_list`` linkage of the +initializations is changed before IL lowering to match the order that will +actually be used by the back end, or if the back end will use some different +technique to accomplish the same result. Note that when using the C-generating +back end, the order in which temporaries are constructed depends on the C +compiler that will be used, so if one has detailed information about the order +in which it will evaluate expressions, one may be able to switch off this +processing. The unordered processing is turned off in the no-lowering scheme. + +Placement Delete +^^^^^^^^^^^^^^^^ + +When a placement ``new`` is done, and there exists a corresponding +``operator``\ ``delete`` function (one with the same parameter types as the +``operator``\ ``new``, ignoring the first parameter), if an exception is thrown +before the initialization associated with the ``new`` completes, the +``operator``\ ``delete`` is called to deallocate the storage. This is +implemented by wrapping the code that performs the initialization inside an +internal ``try`` block. If an exception is thrown while executing the ``try`` +expression, the associated ``catch`` expression, a call of the delete routine, +is executed. In the fully-lowered scheme, this internal ``try`` block is +expanded into the same code sequence used for a statement-level ``try`` (but as +part of an expression). In the partial-lowering and no-lowering schemes, the +internal ``try`` is indicated by an expression node with subkind +``leck_internal_try``. See ``make_internal_try_expr``. + +Lowering ``extern inline`` +------------------------------- + +``When LOWER_EXTERN_INLINE`` is TRUE, ``extern inline`` functions are processed +specially. In the cfront-like ABI, they are lowered to normal static inline +functions; this mainly involves just a change of the storage class in the +routine entry. In the IA-64 ABI, they are left external but put into a COMDAT +so that multiple copies are folded into one by the linker. + +The code generated in ``LOWER_EXTERN_INLINE`` mode in the cfront-like ABI does +not quite conform to the standard, because it does not ensure that when the +address of an ``extern inline`` function is taken the address is the same +across different compilation units. Setting ``INSTANTIATE_EXTERN_INLINE`` to +TRUE (instead of setting ``LOWER_EXTERN_INLINE``) provides standard-conforming +behavior: ``extern inline`` functions are treated like template instances, and +the template prelinker assigns the "instantiation" of the function to a single +file, thus ensuring that if its address is taken it is the same everywhere. + +Two transformations that apply to all extern inline functions, whether +``LOWER_EXTERN_INLINE`` is specified or not: + +* | For functions that have local static variables, the static variables are + promoted out of the function and made external (and given mangled names), + so that all copies of the function will refer to a common set of static + variables. If the static variables are initialized, the initialization + guard variables are also made external, with mangled names that begin with + ``__LSG__`` (cfront-like ABI) or ``_ZGV`` (IA-64 ABI). +* | If ``ASSIGN_STRING_LITERAL_SEQUENCE_NUMBERS`` is TRUE, similar processing + is done for string literals: they are moved into external variables with + mangled names so that every copy of the extern inline function gets the + same address for the same string literal. This is off by default in the + cfront-like ABI, even though it should be TRUE for full conformance to the + C++ standard, because it's expensive way out of proportion to its benefit. + Not being able to count on a COMDAT-like mechanism, the cfront-like ABI + must put out the variables for the string literals as tentative definitions + (therefore uninitialized), and initialize them at each point of use. It's + not at all pretty, especially in small inline functions, and it's a feature + that hardly anyone ever counts on. + +Inlining +-------- + +As an option, IL lowering can do inlining of function calls. That is, when it +encounters a call of a function declared ``inline``, it can replace the call +with IL corresponding to the body of the function with the parameters replaced +by the corresponding arguments. When a function call occurs as a statement, +the statements of the function body are inserted in place of the call. When +the function call occurs within an expression, the body of the function is +rewritten as one large expression and that expression is inserted in the proper +place in the containing expression. It is not always possible to do this sort +of inlining: there are certain constructs (e.g., loops) that cannot be rendered +in expression form. Even when the inlining is done at the statement level, +there are certain constructs that are not practical to inline. Calls that +cannot be inlined are left in their original call form, and an out-of-line copy +of the function is used. A remark is issued. + +Inlining of this style has some serious limitations. Aside from the +impossibility of inlining certain function bodies, there is also the problem +that inlining at this level is done without knowledge of the target +architecture, and therefore without the ability to know whether the inlined +version of a call is preferable to the original version. The inlined version +might be ridiculously large, or might be worse in some other way. Inlined +calls produce extremely convoluted expressions, which stress back ends and C +compilers. + +In short, if you want inlining (and you do, for C++), you probably want to do +it some other way. The version EDG supplies is provided as a convenience for +those who use the C-generating back end and whose C compilers do not handle +inlining. It's intended to give roughly the same functionality as cfront, and +EDG does not plan to enhance it in any substantial way. + +The code to perform inlining is contained in ``inline.c``, with the associated +declarations in ``inline.h``. Inlining of function calls is enabled by the +configuration switch ``MINIMAL_INLINING``. The default is to inline only when +using the C-generating back end. + +Inlining is done on code that has already been lowered, which is to say on C +code. When the end of the lowering of a function's body is reached, +``set_up_routine_for_inlining`` is called to determine whether the routine can +be inlined. If so, the ``inlinable`` flag in the routine entry is set. Note +that this means that a routine call cannot be inlined until the full definition +of the function has been seen and lowered. Also note that lowering is not done +if any errors are detected, so inlining is always done using correct code. A +function is disqualified for inlining immediately if any of the following are +true: + +* | The function has local static variables. +* | The function has local constants. +* | The function has local types. +* | The function has block scopes. +* | The function includes pragmas. +* | The function has an ellipsis in its parameter list. + +A function that passes these tests is eligible to be inlined. When a call is +seen, ``do_inlining_of_call`` is invoked to do the expansion. The expansion is +done in three steps: + +#. ``set_up_variable_remapping_for_inlining`` makes temporary variables + for the parameters and local variables of the function, and generates + assignment code to initialize each parameter temporary with the + corresponding argument expression. If the argument is constant-valued + and the parameter is not modified in the function, no temporary is + needed; the constant will be used directly. + +#. ``expand_statement_inline`` does the expansion of the function body. + It makes a copy of the statements and expressions of the function, + replacing references to the parameters and local variables with the + appropriate temporaries or constants. If the function call being + inlined appears at the statement level, the copy is made in statement + form. Otherwise, the function body is translated into expression + form as the copy is made. Expression statements are copied as + expressions; a sequence of statements is formed via comma operations; + and ``if`` statements are rendered as "``?``" operations. Loops cannot + be translated to expression form, and therefore can be inlined only in + the statement mode. ``goto``\ s and labels generally preclude inlining + in both modes, but the special case of a ``goto`` to a label + immediately following it is allowed and eliminated. ``return``\ s + are allowed only at the end of the function at the top level (or as + the last statement in a block that is the last statement in a block + ... that is the last statement of the top-level block of the function). + Dynamic initialization of local variables is translated to + assignments, but aggregate initialization precludes inlining. + +#. ``finish_variable_remapping_for_inlining`` adds the created temporaries + to the calling context scope, and then the statement sequence or + expression tree is inserted into the IL tree, replacing the original + call. + +Since the inlining operation is an attempt to inline the function, one that may +fail, the statement sequence or expression tree for the inlined call is built +off to the side, and attached to the IL tree only once the inlining operation +is completed successfully. Likewise, the temporaries created for parameters +and local variables are not entered into the scope of the call until the end of +the operation. If an inlining operation fails, the original call is left in +place and the routine is marked as requiring an out-of-line copy. (An +out-of-line copy is also required if the address of the routine was taken.) If +inlining of a call fails because of something that precludes *all* inlining of +the function, the ``inlinable`` flag of the routine is cleared so no further +attempts will be made. If the inlining operation failed only because of the +context (e.g., the function includes a loop and the call is inside an +expression), the ``inlinable`` flag is left TRUE. + +As the function body is copied with substitution for the parameters and local +variables, new constant expressions may be created. That is, when a constant +argument is passed for an unmodified parameter, the references to the parameter +in the function body are replaced by the proper constant value. That may +produce operations whose operands are constant (e.g., ``p + 1`` becomes ``1 + +1``, which can be simplified to ``2``). + +This substitution and folding is done by +``adjust_copied_expression_for_inlining``, which is called from +``copy_expr_tree`` as each node in the tree is copied. The list of remappings +to be done is built by ``set_up_variable_remapping_for_inlining`` and pointed +to by the static variable ``variable_remappings_for_inlining``. +``get_var_remapping_for_inlining`` consults the list to find the applicable +remapping for a variable. + +More dramatic simplification is possible for short-circuiting operators like +"``?``" and for ``if`` statements (whether they are rewritten in expression +form or not). If the tested expression is constant, parts of the expression +tree or statement tree are discarded accordingly. For example, when parameter +``p`` is replaced by ``1``, + +.. code:: c++ + + p ? i : (j + 1) + +becomes simply ``i``, and + +.. code:: c++ + + if (p > 0) i = 1; else i = 2; + +becomes simply ``i = 1``. This is handled by +``copy_and_simplify_short_circuited_operation`` for the operator cases, and in +``expand_statement_inline`` for the ``if`` statement. + +Arguments can be considered to be constant even if they are not literally +constants. For example, the address of a local variable is not a compile-time +constant, but it is constant over the duration of a call, and therefore can be +considered constant-valued for purposes of parameter remapping. + +The ``this`` parameter of constructors is given special treatment so that the +allocation sequence at the beginning of constructors will be eliminated when +the constructor is operating on a known variable. According to the normal +parameter rules, ``this`` in a constructor is modified within the function and +therefore a temporary must be used. However, we know how constructors work, +and if there is no assignment to ``this`` in the constructor we know the only +modification is one that will be eliminated when the constructor is called with +a non-null argument for ``this``. In such cases, the ``this`` parameter is +remapped directly to a constant, and the allocation sequence is eliminated by +the normal short-circuit optimization. + +Lowering ``thread_local`` +------------------------- + +The ``thread_local`` keyword was added in C++11 and the dynamic initialization +and destruction of objects with ``thread_local`` storage requires lowering +support. + +If the back end has the capability to execute code at thread creation time, +then it is most efficient to set the configuration macro +``USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES`` to FALSE in which +case lowering creates one or more initialization routines (depending on the +setting of ``SEPARATE_ROUTINES_FOR_FILE_SCOPE_DYNAMIC_INITS``) for each +dynamically-initialized variable with ``thread_local`` storage in the +translation unit and sets ``il_header.thread_local_dynamic_init_routines`` to +point to the list (in the proper order). It is the responsibility of the back +end to ensure that this list of routines is invoked at thread creation time. + +In most cases, however, the compiler won't have the capability to execute code +at thread creation time, in which case +``USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES`` should be set to +TRUE. In such configurations, each use of an object with ``thread_local`` +storage duration that may be dynamically initialized is re-written to invoke +the "wrapper" routine for the object (see ``lower_thread_local_variable``). +Lowering creates a "wrapper" routine (see +``thread_local_wrapper_for_variable``) that invokes an "initialization" routine +(if one exists) and then returns a pointer to the ``thread_local`` object. +This ensures that each ``thread_local`` object is properly initialized (though +at considerable run-time cost). Mangled names for wrapper routines contain the +mangled name of the ``thread_local`` object along with a prefix ( ``_ZTW`` in +the IA-64 ABI and ``__TWR__`` in the Cfront ABI). + +Note that although "wrapper" routines are only required for dynamically +initialized ``thread_local`` variables, the lack of "wrapper" routines for +``thread_local`` variables with external linkage that are not dynamically +initialized results in a non-compliant implementation (i.e., the standard +requires that all ``thread_local`` variables be initialized before the first +odr-use of any ``thread_local`` variable, but the use of a statically +initialized ``thread_local`` circumvented the initialization process). As a +result, the ``all_thread_locals_have_wrappers`` global variable was introduced +in 4.10, and when set to TRUE, results in standard compliant behavior. The +previous behavior matches g++'s behavior and is achieved by setting +``all_thread_locals_have_wrappers`` to FALSE. + +The "initialization" routines that wrappers call perform the actual +initialization for the ``thread_local`` objects (and incorporate a +``thread_local`` guard variable to ensure the initialization is performed only +once per thread). When the back end supports weak references, +``LAZY_INITIALIZATION_USES_WEAK_REFERENCES`` should be set to TRUE, in +which case each "initialization" routine is aliased to the ``__tls_init`` +routine that initializes that particular ``thread_local`` object. In cases +where a ``thread_local`` object is used in one translation unit and defined in +another, a reference to an initialization routine is created in the first +translation unit but there may or may not be a definition for the +initialization routine in the second routine (it will be aliased to the +``__tls_init`` routine in that translation unit only if the ``thread_local`` +object is dynamically initialized). When weak references are used wrapper +routines need to allow for the case where an initialization routine is +``NULL``. For back ends that do not support weak references, a do-nothing +initialization routine is created for this case (see +``make_null_thread_local_init_routine_for_variable``). Mangled names for +initialization routines contain the mangled name of the ``thread_local`` object +along with a prefix (``_ZTH`` in the IA-64 ABI and ``__THI__`` in the Cfront +ABI). + +The ``__tls_init`` routines themselves (or ``__tls_init_N`` in +one-instantiation-per-object mode) are created during the lowering of +file-scope dynamic initializations (see :ref:`dynamic-init`). + +In a manner similar to the handling of destructions of static entities, +destructions of file-scope objects with ``thread_local`` duration are +registered with the run-time library through calls to ``__cxa_thread_atexit`` +(for the IA-64 ABI) or ``__record_needed_thread_destruction`` (for the Cfront +ABI). The run-time library is then responsible for invoking these destructors +when the thread terminates (see ``record_needed_destruction``). + +Lowering ``ifunc`` +------------------ + +The GNU ``ifunc`` attribute maps to the ``STT_GNU_IFUNC`` symbol type in the +ELF standard and is not available on many architectures. The ``STT_GNU_IFUNC`` +symbol type allows a routine's symbol to be determined dynamically at load +time. At load time, the routine specified as the resolver (in the ``ifunc`` +attribute) is invoked (once) and returns a pointer to the routine that will be +used to resolve all instances of that symbol for that execution of the +executable. This provides a very low overhead mechanism to select one of a +family of functions (typically based on the underlying CPU architecture). +Here's an example (with ``--gcc --gnu_version 40600``): + +.. code:: c++ + + int printf(const char *,...); + void target() { + printf("Here\n"); + } + static void (*resolver(void))(void) { + return (void(*)(void))⌖ + } + void source() __attribute__ ((ifunc ("resolver"))); + int main() { + source(); // Prints "Here" + } + +For back ends that don't support the ``STT_GNU_IFUNC`` symbol, an approximation +of the run-time behavior can be achieved by setting ``LOWER_IFUNC`` to +TRUE. In that case, lowering will convert the routine with the ``ifunc`` +attribute into a "wrapper" routine as such: + +.. code:: c++ + + decltype(source) resolver_result = source; + source(args...) { + if (resolver_result == source) { + resolver_result = (decltype(source))resolver(); + } + return *resolver_result(args...); + } + +This has the effect of invoking the resolver only once (though at run time +rather than at load time). Invocations of ``source`` incur an extra function +call and indirection, but lowering re-writes references to ``source`` so they +are dispatched through the resolver variable whenever possible (in which case +the only overhead is an extra indirection). + +Note that there are a few caveats: + +* | The re-writing of calls to avoid the wrapper routine only occurs once the + declaration with the ``ifunc`` attribute has been seen; any reference prior + to that point will be unlowered (and will hence invoke the wrapper). That + can be an issue if, for example, the declaration with the ``ifunc`` + attribute is only in a library's implementation (and not in the shared + header file). In that case, code that is compiled with the shared header + file will contain references to the wrapper routine. +* | Constants (i.e., ``ck_address``/``abk_routine``) that refer to the + ``ifunc`` are not re-written in lowering, so they'll always point to the + wrapper routine. + +See ``lower_ifunc_routine`` and ``lower_ifunc_expr`` for more information. + +Lowering GNU function multiversioning +------------------------------------- + +GNU supports function multiversioning in version 4.8.0 and later via the +``target`` attribute in C++ mode. Detailed documentation is available here: +``http://gcc.gnu.org/wiki/FunctionMultiVersioning``. The ``target`` attribute +allows multiple versions of a function definition to be supplied, and the +choice of which version to call is determined at load time based on +characteristics of the machine where the program is running. The choice is +made by a compiler-generated (when lowering is enabled) "resolver" routine that +selects the best routine from the target-specific versions. The resolver +routine is executed once at load time (because it is associated with an +``ifunc`` routine) to determine which target-specific routine to use for the +particular CPU. For back ends that don't support ``ifunc``, see +``LOWER_IFUNC``. + +For example (assuming ``USE_X86_FUNCTION_MULTIVERSIONING`` is ``TRUE,`` with\ +``--gnu_version 40800``): + +.. code:: c++ + + __attribute__ ((target("default"))) int foo () { return 222; } + __attribute__ ((target("arch=corei7"))) int foo () { return 777; } + __attribute__ ((target("avx"))) int foo () { return 333; } + int main () { + int (*fp)() = foo; + return fp() != foo(); + } + +Would generate lowered pseudo-code like this: + +.. code:: c++ + + int foo_default () { return 222; } // "default" foo + int foo_corei7 () { return 777; } // "corei7" foo + int foo_avx () { return 333; } // "avx" foo + // Resolver function returns address of specific function + static (int *foo.resolver()) { // lowering-generated resolver function + resolved_foo = // one of foo_default, foo_corei7, foo_avx + return resolved_foo; + } + int foo.ifunc() __attribute__((ifunc("foo.resolver")); + int main () { + int (*fp)() = foo.ifunc; // &foo lowered to &foo.ifunc + // Dynamic loader invokes foo.resolver + // to select which specific foo. + // foo.ifunc is invoked once during + // startup. + return fp() != foo.ifunc(); // call of foo is lowered to foo.ifunc + } + +Note that at present, lowering is only performed when +USE_X86_FUNCTION_MULTIVERSIONING is TRUE (the rules that are used to determine +at run-time which of a set of target-specific functions are machine-specific +and only the x86 case is implemented). + +See ``lower_mv_routine``, ``lowered_mv_routine``, and ``create_mv_resolver``. + +How is IL Lowering Done? +======================== + +Sequencing +---------- + +All the individual transformations done by IL lowering are relatively +straightforward. What makes the job of IL lowering so difficult is the fact +that it must operate under some very difficult sequencing constraints. + +They come about because IL lowering must be done on a per-function basis, so +that individual memory regions can be lowered and then written to a file. That +means that when function scope memory regions are lowered, the file scope +entities that they reference are not yet lowered. And they cannot be: since +the file-scope entities are still active entities in the compilation, if they +were modified by IL lowering it would disturb the rest of the compilation. + +To pick an example: to lower a virtual function call in a function scope, one +needs to be able to reference the virtual function pointer field in the class +entity. That field is added by IL lowering. But the class type is in the file +scope memory region, and therefore has not yet been lowered at the time the +virtual function call is lowered. + +Another example: IL lowering changes reference types into pointer types. +However, mangled names of functions must be based on the original types, +including reference types. Therefore, mangled names must be generated before +reference types are changed to pointer types. + +Another example: the variable that contains a virtual function table must be +available when constructors and destructors for classes are lowered. However, +it is not possible to know at that point in the compilation whether or not the +definition of the virtual function table should be put out. In fact, it's not +possible to tell whether it should be internal or external. Therefore, virtual +function table variable definitions cannot be done at the time the variable +declarations are done. + +In short, lots of processing that would be fairly straightforward if the entire +IL tree could be lowered at once becomes convoluted because some parts of the +tree have already been lowered, some haven't, some cannot be yet, etc. + +One technique that helps is the concept of "prelowering" classes. This is +processing that's done as soon as possible on completed class definitions. It +does not modify the class, but it adds information that is needed to use the +class in lowering code: + +* | The type-as-subobject (a copy of the type with any virtual base classes + removed). +* | The fields that make the base classes, virtual base class pointers, and + virtual function table pointer of the class explicit. (Note that this + change affects the field list of the type, which would seem to be a + modification; however, since the fields are not in the symbol table, they + cannot be found by the front end. It does mean that front end code should + not traverse the field list to visit all the fields. It should use the + symbol list instead.) +* | Variables for virtual function tables. These are all created as ``extern`` + declarations, and they are changed to definitions or to static variables + later if that is appropriate. + +See ``prelower_class_type``. + +Another technique is to not clear C++-specific fields when they are +lowered, where that's possible. One example: the implicit "``this``" +parameter type in a routine type entry becomes an explicit first parameter +type when lowered. However, the pointer to the implicit type is not +cleared. That allows code that wants to see whether or not a function is a +nonstatic member function to fetch the "``this``" parameter type without having +to know whether or not the type has already been lowered. One consequence +of this technique is that back ends cannot count on having the C++-specific +fields cleared, and should therefore not look at them. + +The IL Lowering Flag +-------------------- + +The IL lowering flag is a two-state flag that appears in the prefix that +precedes each IL entry. It is flipped from 0 to 1 when the associated entry is +visited during IL lowering. This allows IL lowering to know that it has +already processed a given entry and thereby avoid looping when there are cycles +in the IL graph. + +This flag is similar to the ``il_walk_flag`` used by the IL walk routines, but +is kept separate so that IL lowering is not forced to visit all of the IL tree +even if it knows that certain parts cannot contain entries that will be +modified by lowering. It should be noted that even though every entry has a +flag, not all entries' flags are maintained by IL lowering. For example, IL +lowering does not maintain the flag on expression nodes, because it knows that +it will visit each expression node exactly once. + +Why not use the standard IL walk routines to do the traversal? The problem is +that the IL walk routines cannot co-exist with processing that changes the +structure of the IL tree. Since IL lowering can eliminate entries, move them +around, add entries, and swap entries, the IL walk routines could get into +loops, get lost, or process entries more than once. Therefore they are not +suitable, and IL lowering has its own IL traversal code. + +Orphaned Entries +---------------- + +Type entries and static variables that are local to a function require some +special handling. All type entries and all static variables are allocated in +the file scope memory region. However, types and static variables that are +local to a function are placed on the types and static variables list of a +function or block scope. Those are unusual lists: the function scope entries +(in a function scope memory region) point to lists that are entirely in the +file scope memory region. Yet, the entries pointed to are not really part of +the file scope. They might, in fact, not be referenced from anywhere except +the function scope memory region. Such entries are "orphaned" in the file +scope: their parents are processed, written out, and removed from memory, but +the children remain in the file scope, unattached to the rest of the file scope +IL tree. + +There is special processing in the IL write, read, and walk routines to deal +with such orphans, but special handling is also required in IL lowering. + +Such entries clearly must be lowered at some point. Do we lower them when the +function scope is lowered, or do we lower them when the file scope is lowered? +Well, lowering them with the function scope is impractical, since it's hard to +tell which of the file-scope references are orphans and which are not. Even if +we know that a static variable, say, is an orphan, how much of its subtree do +we process? Is its type an orphan, or just a normal file-scope type? + +So it's easier not to do lowering on orphans. The processing then lowers +entries in the function scope, and leaves all those in the file scope alone. +Whenever a pointer hops into the file scope memory region, IL lowering leaves +that entry alone, regardless of whether or not it might be an orphan. + +This solves one problem but creates another. If there truly are orphaned +entries, how will the IL lowering for the file scope find them to lower them? +The answer is that orphans or potential orphans are recorded on a special list, +using support routines and data structures provided by the IL support +components. When a pointer hops into the file scope memory region, the entry +pointed to is recorded as a potential orphan, and at the end of the lowering +for the file scope all the orphans are visited. If they turn out not to be +orphans, the IL lowering flag will indicate that they have already been visited +and they will not be processed again. + +See ``lower_orphaned_entries``. + +Maintained Context +------------------ + +While IL lowering works through a top-level scope, it maintains a stack that +shows the nesting of scopes for the present position (the spot for which +lowering is being done). This makes it easy to find the innermost enclosing +scope or the innermost enclosing function at any given moment, for example to +create a temporary in the innermost scope. The global variable +``curr_context`` points to the top of the context stack. + +Object Lifetimes +---------------- + +The object lifetime entries in the IL provide information about regions of the +program on exit from which automatic destructions of class objects are done. +The destructions to be done appear in a list attached to the object lifetime +entry (in the form of dynamic initialization entries). IL lowering uses this +information to insert destructor calls on exit from those regions (whether by +flowing off the end of the region or branching out of it via a ``goto`` or the +like), and to build region table information for exception handling. + +As IL lowering works through the IL, it keeps track of the current position in +cleanup terms, which is to say the latest initialization encountered that +requires automatic destruction. This is maintained in the +``latest_initialization`` field of the current context. Given the pointer to +the latest initialization, ``gen_cleanup_actions`` and its subroutines can walk +up the cleanup chain, generating the appropriate destructions. In the case of +a ``return``, the walk up the chain continues until the lifetime for the +function scope is reached. In the case of a ``goto``, the cleanup continues +until the lifetime indicated in the ``goto`` statement is reached (that +lifetime is determined by the front end, and is the innermost lifetime that the +``goto`` and the label have in common). + +At the beginning of lowering of a block, the object lifetime for the block and +for any expression-temporary lifetimes immediately within it are processed. +This processing (which is performed by ``begin_object_lifetime``) involves +allocating an entry of type ``a_destructible_entity_descr`` and attaching it to +each dynamic initialization on the lifetime destructions lists. These entries +are used to record information that will be needed when generating the +initialization and the later destruction. In particular, the position of the +entity (in initialization position form; see below) is determined and recorded +in the entry at the time of initialization. That position is then used when +generating the destruction code. The beginning-of-lifetime processing also +includes deciding whether the entity will require a conditional flag to +indicate that the construction has been done. If one is required, the variable +for it is created and code to initialize it to zero is inserted. + +At the beginning of block-after-label lifetimes, similar processing is done, +but it takes a bit of effort to get it done at the right time, because there is +no explicit indication of a new lifetime on a statement that ushers in a +block-after-label lifetime. One must note, at the beginning of the previous +block or block-after-label lifetime, the next block-after-label lifetime in +sequence, and watch for the appearance of the associated statement during the +normal processing of statements. Also at labels (including switch case +labels), long lifetime temporaries must be destroyed (and when exceptions are +enabled, the region table is adjusted accordingly). (For this reason, +block-after-label lifetimes can begin at ``stmk_switch_case`` statements in +long-lifetime-temporaries mode.) + +Initialization Positions +------------------------ + +``an_init_pos_descr`` is used to contain a description of a position within an +initialization. As an aggregate initialization is processed, such a +description is maintained for the current position. The description can then +be turned into an expression that addresses the indicated position, which is +necessary when generating code to initialize pieces of aggregates: + +.. code:: c++ + + int j; + void f() { + struct {int i; int j;} k[2] = {{1, 1}, {j+1, 2}}; + } + +becomes + +.. code:: c++ + + int j; + void f() { + struct {int i; int j;} k[2] = {{1, 1}, {0, 2}}; + k[1].i = j+1; + } + +Insert Locations +---------------- + +Many transformations work by inserting new pieces of code into expressions or +statement lists. The insert location for such insertions is described by a +structure of type ``an_insert_location``. It can describe an insert location +either within an expression or within a sequence of statements. The code +inserted is typically in units of "statements", even when the insertion is +within expressions. That is, a lowering routine would assemble something like +``temp = 1`` and that construct would be inserted, either as a free-standing +expression statement, or as a clause in a comma operation added within an +expression. For the expression insertion case, for example, + +.. code:: c++ + + i ? (void)A(i) : (void)0 + +might be modified by insertion of an assignment: + +.. code:: c++ + + i ? (temp = 1, (void)A(i)) : (void)0 + +Since the insertion is done in statement units, the callers of the insert +routines need not in general be concerned about whether or not the insert +location is in an expression or a statement. The low-level routines do the +necessary adjustment, including rendering conditional tests as ``if`` +statements or "``?``" operators. + +See + +* | ``insert_expr`` +* | ``insert_statement`` +* | ``insert_if_statement`` + +Reusable Copies +--------------- + +There are a few cases where an expression that is used once in the original IL +tree is used more than once in the lowered IL tree. Without special handling, +such cases might cause problems if the expression involved has side effects. +The routine ``make_reusable_copy`` solves the problem: given an expression +tree, it returns a distinct expression tree that produces the same value. If +the original tree has no side effects, it is simply copied. If it has side +effects, the original expression is modified to assign the expression value to +a temporary, and the new copy is simply a reference to the temporary. + +Note that the new copy does not replace the original expression. The original +expression continues to be used in its original location, and the copy is used +for the second reference. Further copies can be made from either of the +expressions. + +``make_lvalue_reusable_copy`` does a similar operation for expressions that are +lvalues. It handles bit-field lvalues specially. + +.. _lowering-c-dialects: + +Lowering C Dialects +=================== + +In some newer C modes like C99 or GNU C mode, some features create IL +constructs that are not used in IL for C89. In order to make things easier for +back ends, the front end includes a C lowering phase, which can rewrite many +(but not all) of these newer C constructs. Many (but not all) of the +additional IL features are enabled by ``C99_IL_EXTENSIONS_SUPPORTED``. Most of +the code for this lowering is in ``lower_c99.c``, with related declarations in +``lower_c99.h``. + +* | For compound literals, the generated ``enk_temp_init`` node is rewritten as + an initialized generated variable. See ``lower_c99_temp_init``. +* | Designated initializers are processed to produce a C89-style aggregate + initializer. This is done outside of the primary C99 lowering phase, and + is enabled by ``LOWER_DESIGNATED_INITIALIZERS``. ``ck_designator`` + constants remain in the IL after this lowering for initializations of + members other than the first in unions, which are not expressible in C89 + IL. See ``lower_designated_initializers``. Note that there are some + advantages to not doing this lowering and instead handling the designators + in a back end, notably that that can avoid some very large IL structures + for big sparsely-initialized arrays. +* | The ``_Bool`` type is unchanged, but a C89 view of the IL does not consider + the ``bool_type`` flag and therefore sees the underlying integer. Compound + assignment operators whose left-hand operand has type ``_Bool`` are + rewritten to ensure that the result value is restricted to 0/1, via the + same routines that do this processing in C++ lowering; see + ``rewrite_compound_assignment``. Boolean casts are also handled as in C++; + see :ref:`il-bool-type`. +* | Complex types are rewritten as structs, imaginary types are rewritten as + floating-point types, complex constants are rewritten as aggregate + initializers, imaginary constants are rewritten as floating-point + constants, and operators and conversions on complex and imaginary types are + rewritten as runtime routine calls. This is controlled by + ``LOWER_COMPLEX``. See ``lower_c99_nonreal_float_types``, + ``lower_c99_complex_cast``, and ``lower_c99_operator``. Also see the file + ``c99_complex.c`` in the runtime library for descriptions and sample + implementations of the complex runtime routines. Note that a back end + could treat the runtime routines as intrinsics and generate machine + instructions directly for the calls. (Again, the C99-centric names are + historical: These routines also handle complex types appearing in GNU C + source.) + | + | For compound assignment operators, the operation is rewritten in terms + of the underlying operation, and the result is then converted and + stored in the destination variable (e.g., ``x += y`` is rewritten as + ``x = x + y``). If the left side is an expression with side effects, + its address is evaluated and stored in a temporary, and the two + references to the left hand side (to fetch its value as as input to the + operation, and to store the result) are done by way of indirection + through the temporary. See ``rewrite_compound_assignment``. + +* | If ``LOWER_FIXED_POINT`` is TRUE, fixed-point operations, types, and + constants are rewritten into standard C. Fixed-point types are lowered to + typedefs for appropriately-size integral types (see + ``lower_c99_fixed_point_types``). Fixed-point constants are lowered to + integral constants (see ``lower_c99_fixed_point_constant``). Fixed-point + operations and conversions are lowered to calls to runtime routines (see + ``lower_c99_fixed_point_operation``, ``lower_c99_fixed_point_cast``, + ``lower_c99_fixed_point_incr_decr``, and ``rewrite_compound_assignment``). + The runtime routines are not provided by EDG; they are available from + Dinkumware, Ltd. There is a long comment beginning with "Fixed-point + lowering:" in ``lower_c99.c`` that gives more details on the runtime + interface. +* | When ``LOWER_VARIABLE_LENGTH_ARRAYS`` is TRUE variable-length arrays (VLAs) + are rewritten as pointers to storage allocated by the run-time library. + Storage for a VLA is allocated by a call to ``__vla_alloc``, which is + produced by the lowering of certain ``stmk_vla_decl`` statements. The + storage is freed by calls to ``__vla_dealloc``, which are the result of + lowering ``enk_vla_dealloc`` expression nodes (which may be produced + directly by the front end in C modes, or as the result of IL lowering in + C++ modes). + | + | A VLA type can be defined recursively to be either an array type with a + nonconstant bound, or a normal (constant-bound) array whose element is + a VLA type. The lowering process eventually replaces all VLA types and + pointer to VLA types by pointer types pointing to the underlying + (non-array) element type of the VLA type. For example, the type ``int + [3][n][4]`` is replaced by ``int*`` and the type + ``double*(*)[3][n][4]`` is replaced by ``double**``. To avoid certain + subtle ordering problems, this type replacement is done in two stages. + First, all VLA types are collected on a linked list (see + ``record_vla_component_types_for_lowering``) during the main C99 IL + lowering traversal (this is necessary because these types may only be + pointed to from an expression node, unlike, e.g., class types which are + listed on a scope's type list). After the main tree traversal, the + actual replacement is done by a call to the function + ``lower_vla_types``. + | + | The length of VLA types must in general be computed at run time. This + is achieved by evaluating the array bound expression and storing the + result in temporary helper variables. To further simplify the VLA size + computations in expressions, these variables are updated to hold a + total count of the number of (non-array) elements for a particular VLA + type component. For example, the type ``char[n][m]`` would produce two + variables, one holding the value ``m`` and the other holding the value + ``n*m``. Once created, the IL entries for these variables can be + accessed through the ``a_vla_dimension`` entries of the associated VLA + type components. For VLA types appearing in explicit declarations + (variable declarations and typedef declarations), the front end adds + adds explicit ``stmk_set_vla_size`` statement indicating when the value + of these variables ought to be computed. However, in expression + contexts that introduce new VLA types (``sizeof`` and cast expressions, + as well as compound literals) there are no such statements. Either + way, the bulk of the work to produce and compute these variables is + done in ``lower_vla_dimensions``, which creates all the necessary + variables for an arbitrarily complex VLA type and returns an expression + that sets all the variables to their required values. + | + | With those variables available, the lowering of various array-related + operations (subscripting, pointer arithmetic, and run-time ``sizeof`` + expressions) is relatively straightforward. There is a long comment + near the beginning of ``lower_c99.c`` (conditioned on + ``LOWER_VARIABLE_LENGTH_ARRAYS``) that gives more details on the + lowering of VLAs. +* | Extended identifiers containing universal character names (``\u``\ *xxxx*), + whose name strings contain the ``\u`` etc., are rewritten as standard + identifiers if ``REWRITE_UCN_ESCAPE_CHAR_IN_LOWERING`` is TRUE. The + "``\``" character is changed to "``_``". This is the same processing that + is done in C++ lowering. +* | Non-constant expressions in aggregate initializers, i.e., those indicated + by ``ck_dynamic_init`` constants, are rewritten as executable code. This + is done via the same routines that do this processing in C++ lowering. See + ``lower_c99_stmk_init``. +* | Inline function calls are replaced by their expansions if + ``MINIMAL_INLINING`` is TRUE. This is done via the same routines that do + this processing in C++ lowering. +* | Boolean controlling expressions are optionally normalized to always yield + an integer value of 0 or 1. This transformation occurs even in C89 mode + (and the same processing is done in C++ mode). + +Some features are not lowered but use IL constructs that exist in IL produced +by lowering C++, which a back end is likely already to accept: + +* | For mixed statements and declarations, the statements and declarations + appear intermixed in the statement list of a compound statement. +* | For ``long``\ ``long``, there are two new integer kinds (``ik_long_long`` + and ``ik_unsigned_long_long``) and new constants of these kinds. + +One feature is not lowered at all: + +* | For flexible array members, the last member of a struct type may have an + array type with an unknown bound. This probably does not require special + processing in a back end. + + + +.. [#f1] The configuration flag ``MINIMAL_INLINING`` can be used to enable a + minimal version of inlining for those who have no better alternative. +.. [#f2] This routine is not present in the cfront runtime. It would have to + be added to a cfront runtime library to make the library usable with + the EDG front end. +.. [#f3] One nit: a function is considered inline only if it is inline in the + class definition, and not if inline was added on the out-of-class + definition. +.. [#f4] This feature is not implemented in cfront 2.1, and therefore this + runtime routine is not present in the cfront 2.1 runtime library. It + would have to be added to such a library to make the library usable + with the EDG front end. +.. [#f5] In the IA-64 ABI, IL lowering avoids generating duplicate + ``typeinfo`` variables by checking a new needed type against all + previously generated ``typeinfo`` variables. diff --git a/doc/_sources/modules.rst.txt b/doc/_sources/modules.rst.txt new file mode 100644 index 0000000..c37e350 --- /dev/null +++ b/doc/_sources/modules.rst.txt @@ -0,0 +1,2033 @@ +======= +Modules +======= + +The EDG modules implementation is based upon the Microsoft IFC specification. + +The EDG front end has experimental support for both the IFC variant produced by +Microsoft's Visual Studio compiler and an EDG variant produced by the EDG front +end. + +Roles +===== + +To make the system work, every IFC type is understood in terms of a "role". The +type's role in effect defines what semantics it will be generated with. + +The roles are as follows: + +* :ref:`ifc-simple-sort-role` - Any kind of enumeration of named values + unrelated to an index. +* :ref:`ifc-index-sort-role` - A "sort" that encodes a simple sort and an + associated index (e.g., ``DeclIndex`` is the "Index Sort", with a "Simple + Sort" ``DeclSort``). +* :ref:`ifc-bitfield-role` - Any IFC type that encodes things using bit flags. +* :ref:`ifc-raw-numeric-role` - Any IFC type that is an integer with no + associated implicit interpretation (from a format perspective, it's just a + "dumb" number). +* :ref:`ifc-raw-bytes-role` - Similar to Raw Numeric, anything that's just a + raw byte array. +* :ref:`ifc-node-roles` + * :ref:`ifc-partition-node-role` - An IFC Node that can be directly read + from a partition, for instance a ``DeclFunction``. + * :ref:`ifc-basic-node-role` - An IFC Node that only appears as a + sub-node (doesn't have a partition of its own), for instance, a + ``ModuleReference``. + * :ref:`ifc-header-node-role` - Basically what it says, an IFC Node that's + part of the header (``FileHeader`` and ``Partition``). +* :ref:`ifc-foreign-index-role` - A special role for IFC types that represent + an Index in another module file. +* :ref:`ifc-value-category-role` - A role representing several levels of + discriminated values (conceptually similar to an IFC ``std::variant``) + +.. _ifc-simple-sort-role: + +Simple Sort +----------- + +Simple sorts are represented as an enum (sorted in alphabetical order): + +.. code-block:: c++ + + enum an_ifc_access_sort { + ifc_as_none, + ifc_as_private, + ifc_as_protected, + ifc_as_public + }; /* an_ifc_access_sort */ + +Simple sorts can also be converted to a c-string of their respective EDG name +via a call to the respective ``str_for`` function. This can be useful for +debugging and diagnostic purposes. + +.. _ifc-index-sort-role: + +Index Sort +---------- + +Index sorts are represented as an index type (a struct with a module binding, +an associated :ref:`ifc-simple-sort-role` value, and the associated index +value): + +.. code-block:: c++ + + enum an_ifc_decl_sort { + ifc_ds_decl_alias, + ifc_ds_decl_barren, + ifc_ds_decl_bitfield, + ifc_ds_decl_concept, + ifc_ds_decl_constructor, + ifc_ds_decl_deduction_guide, + ifc_ds_decl_destructor, + ifc_ds_decl_enumeration, + ifc_ds_decl_enumerator, + ifc_ds_decl_expansion, + ifc_ds_decl_explicit_instantiation, + ifc_ds_decl_explicit_specialization, + ifc_ds_decl_field, + /* snip */ + }; /* an_ifc_decl_sort */ + + /* + The universal representation for an IFC DeclIndex. + */ + struct an_ifc_decl_index { + an_ifc_module* + mod; + /* The associated module. */ + an_ifc_decl_sort + sort; + /* The associated DeclSort value for this index. */ + uint32_t value; + /* The index value into the associated partition of + "sort" for this index. Represented as the + largest common underlying type. */ + }; /* an_ifc_decl_index */ + +.. _ifc-bitfield-role: + +Bitfield +-------- + +Bitfields are represented as a bitfield type (a struct with a module binding +and the raw value pulled from the module file): + +.. code-block:: c++ + + /* + The universal representation for an IFC FunctionTraitsBitfield. + */ + struct an_ifc_function_traits_bitfield { + an_ifc_module* + mod; + /* The associated module. */ + an_ifc_function_traits_bitfield_storage + value; + /* The raw bit value obtained from the module. + Represented as the largest common underlying + type. */ + }; /* an_ifc_function_traits_bitfield */ + +This is then paired with a (alphabetically sorted) set of bit queries. + +.. code-block:: c++ + + enum an_ifc_function_traits_bitfield_query : uint32_t { + ifc_ftb_constexpr = 1 << 0, + ifc_ftb_constrained = 1 << 1, + ifc_ftb_defaulted = 1 << 2, + ifc_ftb_deleted = 1 << 3, + ifc_ftb_explicit = 1 << 4, + ifc_ftb_hidden_friend = 1 << 5, + ifc_ftb_immediate = 1 << 6, + ifc_ftb_inline = 1 << 7, + ifc_ftb_no_return = 1 << 8, + ifc_ftb_none = 1 << 9, + ifc_ftb_pure_virtual = 1 << 10, + ifc_ftb_virtual = 1 << 11 + }; /* an_ifc_function_traits_bitfield_query */ + +A bitmask can then before formed and tested on a bitfield like so: + +.. code-block:: c++ + + an_ifc_function_traits_bitfield bitfield = ...; + + if (test_bitmask(bitfield)) { + /* matched bitfield & (ifc_ftb_immediate | ifc_ftb_explicit) */ + } else { + /* didn't match */ + } /* if */ + +.. _ifc-raw-numeric-role: + +Raw Numeric +----------- + +Raw numerics are represented as a raw numeric type (a struct with a module +binding and the raw value pulled from the module file, along with a convenience +conversion operator): + +.. code-block:: c++ + + /* + The universal representation for an IFC Index. + */ + struct an_ifc_index { + an_ifc_module* + mod; + /* The associated module. */ + an_ifc_index_storage + value; + /* The raw bit value obtained from the module. + Represented as the largest common underlying + type. */ + + inline operator an_ifc_index_storage() const + { return this->value; } + }; /* an_ifc_index */ + +Thus, the value itself can be passed around safely without concern of changes +in the underlying type, and with access to the module, while being trivial to +work with as an unsigned number: + +.. code-block:: c++ + + an_ifc_index power_idx = ...; + + if (power_idx > 9000) { + /* panic */ + } /* if */ + +.. _ifc-raw-bytes-role: + +Raw Bytes +--------- + +Types generated from the raw bytes role are derived from +:ref:`ifc-byte-buffers`. + +.. code-block:: c++ + + /* + The universal representation of an IFC SHA256 node. + + The representation is declared as a derived struct of an_ifc_Byte_buffer + rather than simply an alias of the instantiation to improve the debugger + experience. + */ + struct an_ifc_sha256 : an_ifc_Byte_buffer { + using storage_type = an_ifc_sha256_storage; + using base_type = an_ifc_Byte_buffer; + using base_type::an_ifc_Byte_buffer; + }; /* an_ifc_sha256 */ + +These types also include an additional table documenting the number of bytes +available (starting from a specific version). For example, if a type has +32 bytes starting with version 0.33, and that doubles to 64 bytes in 0.41 +the following table will be written: + +.. code-block:: text + + |----------------| + | Version | Size | + |---------|------| + | 0.33 | 32 | + | 0.41 | 64 | + |---------|------| + + +.. _ifc-node-roles: + +Nodes +----- + +The node roles (:ref:`ifc-partition-node-role`, :ref:`ifc-basic-node-role`, and +:ref:`ifc-header-node-role`) are all very similar, differing only in their +construction. + +The node types are -- similarly to :ref:`ifc-raw-bytes-role` types -- derived +from :ref:`ifc-byte-buffers`. + +.. code-block:: c++ + + /* + The universal representation of an IFC DeclFunction node. + + The representation is declared as a derived struct of an_ifc_Byte_buffer + rather than simply an alias of the instantiation to improve the debugger + experience. + */ + struct an_ifc_decl_function : + an_ifc_Byte_buffer { + using storage_type = an_ifc_decl_function_storage; + using base_type = an_ifc_Byte_buffer; + using base_type::an_ifc_Byte_buffer; + }; /* an_ifc_decl_function */ + +Additionally, -- again similarly to :ref:`ifc-raw-bytes-role` types -- node +types include a descriptive table to aid in development: + +.. code-block:: text + + |------------------------------------------------------------| + | DeclFunction - 0.33 (32 bytes) | + |-------------|-----------------------------|---------|------| + | Name | Type | Version | Size | + |-------------|-----------------------------|---------|------| + | name | NameIndex | 0.33 | 4 | + | locus | SourceLocation | 0.33 | 8 | + | type | TypeIndex | 0.33 | 4 | + | home_scope | DeclIndex | 0.33 | 4 | + | chart | ChartIndex | 0.33 | 4 | + | traits | FunctionTraitsBitfield | 0.33 | 2 | + | specifiers | BasicSpecifiersBitfield | 0.33 | 1 | + | access | AccessSort | 0.33 | 1 | + | properties | ReachablePropertiesBitfield | 0.33 | 1 | + | __padding__ | uint8_t[3] | | 3 | + |-------------|-----------------------------|---------|------| + + |------------------------------------------------------------| + | DeclFunction - 0.41 (32 bytes) | + |-------------|-----------------------------|---------|------| + | Name | Type | Version | Size | + |-------------|-----------------------------|---------|------| + | name | NameIndex | 0.33 | 4 | + | locus | SourceLocation | 0.33 | 8 | + | type | TypeIndex | 0.33 | 4 | + | home_scope | DeclIndex | 0.41 | 4 | + | chart | ChartIndex | 0.33 | 4 | + | traits | FunctionTraitsBitfield | 0.33 | 2 | + | specifiers | BasicSpecifiersBitfield | 0.33 | 1 | + | access | AccessSort | 0.33 | 1 | + | properties | ReachablePropertiesBitfield | 0.33 | 1 | + | __padding__ | uint8_t[3] | | 3 | + |-------------|-----------------------------|---------|------| + | home_scope | DeclIndex | 0.41 | TF | + |-------------|-----------------------------|---------|------| + +Here, the first table describes ``DeclFunction`` from IFC version 0.33 up until +0.41 (non-inclusive) as a 32 byte structure. Each of the structure's fields are +listed with their name, return type, the interpretation version of the return +type, and the size of the field. Additionally, a ``__padding__`` field is +listed specifying there are 3 bytes of unused (or unknown) data padding the end +of the structure (which would otherwise be 29 bytes). + +The second table describes ``DeclFunction`` for IFC version 0.41+ +(inclusive). This table is very similar to the structure describing the +earlier version of ``DeclFunction``. However, this table specifies that the +home_scope's ``DeclIndex`` has an updated value interpretation, and in the +bottom row of the table sized "TF" that a tacit field is being used to +define (in this case redefine) home_scope (see :ref:`ifc-tacit-field` for +more information on tacit fields). + +The values of these fields can be retrieved via calling the ``get_ifc_``\ *X* +function where *X* is the name of the field (for information on the inner +workings of these functions, see :ref:`ifc-node-versioning`). For instance, to +retrieve the ``home_scope`` (independent of the IFC version and underlying +semantics) the following function can be used: + +.. code-block:: c++ + + an_ifc_decl_function func_decl = /* ... */; + an_ifc_decl_index home_scope = get_ifc_home_scope(func_decl); + +The returned ``home_scope`` is pre-validated during the node's +construction, and ready for usage (for more information, see +:ref:`validation`). + +.. _ifc-partition-node-role: + +Partition Node +^^^^^^^^^^^^^^ + +To get a partition node, in effectively all front end code, ``construct_node`` +should be used (for information on exceptional cases, see +:ref:`skipping-validation`). This looks something like: + +.. code-block:: c++ + + Opt opt_idf; + + construct_node(&opt_idf, index); + +This will load the appropriate value found at the given index, run validation +(if necessary), and (if validation is successful) store the node in the ``Opt`` +variable. + +.. _ifc-basic-node-role: + +Basic Node +^^^^^^^^^^ + +Basic nodes are only obtainable from a ``get_ifc_``\ *X* operation, and used to +represent nodes which are nested in other nodes. For instance, you might have: + +.. code-block:: c++ + + an_ifc_decl_reference decl_ref = ...; + + an_ifc_module_reference module_reference = get_ifc_unit(decl_ref); + +Here the returned ``an_ifc_module_reference`` is a basic node. Note that this +is not wrapped in an optional, as the ``an_ifc_module_reference`` being a +sub-node of ``an_ifc_decl_reference`` was validated when +``an_ifc_decl_reference`` was constructed. + +.. _ifc-header-node-role: + +Header Node +^^^^^^^^^^^ + +Header nodes rarely need new code written for them, there are only two at the +time of writing (and for the foreseeable future): + +* ``an_ifc_file_header`` +* ``an_ifc_partition`` + +To get a header node, the low level ``construct_node_from_module`` is used +directly. Similarly, since header nodes are lower level, validate functions +need called explicitly. + +The flow for interaction with these nodes is typically something like the +following (if not in practice, conceptually): + +.. code-block:: c++ + + Opt get_module_header(an_ifc_module *mod) + { + Opt result; + an_ifc_file_header raw_result; + + init_byte_buffer(4, mod->f_size - 4); + raw_result = construct_node_from_module(mod); + if (validate(raw_result, /*parent=*/NULL)) { + result = raw_result; + } /* if */ + return result; + } /* get_module_header */ + +This is conceptually very similar to what ``construct_node`` is doing behind +the scenes. + +.. _ifc-foreign-index-role: + +Foreign Index +------------- + +Currently in the IFC spec there's a ``DeclSort::Reference`` structure: + ++-----------------+---------------------+ +| Field | Type | ++=================+=====================+ +| ``unit`` | ``ModuleReference`` | ++-----------------+---------------------+ +| ``local_index`` | ``DeclIndex`` | ++-----------------+---------------------+ + +The problem is that the ``local_index`` field uses a ``DeclIndex``, but +that ``DeclIndex`` is valid in a completely different module. This has +caused issues for the front end in the past where the index is accidentally +being used in the current module's code. + +The "Foreign Index" role is used to replace the ``DeclIndex`` type with a +new ``DeclForeignIndex`` type. This new type is more akin to a +:ref:`ifc-raw-numeric-role` than a :ref:`ifc-index-sort-role`. + +The front end thus represents this as the following node structure: + ++-----------------+----------------------+ +| Field | Type | ++=================+======================+ +| ``unit`` | ``ModuleReference`` | ++-----------------+----------------------+ +| ``local_index`` | ``DeclForeignIndex`` | ++-----------------+----------------------+ + +The ``DeclForeignIndex`` type in C++ code looks as follows: + +.. code-block:: c++ + + /* + The universal representation for an IFC DeclForeignIndex. + */ + struct an_ifc_decl_foreign_index { + an_ifc_module* + mod; + /* The associated module. */ + an_ifc_decl_foreign_index_storage + value; + /* The raw bit value obtained from the module. + Represented as the largest common underlying + type. */ + }; /* an_ifc_decl_foreign_index */ + +This allows the index value to be imported into the current module in a +type safe way that can't be accidentally treated as a ``DeclIndex``. Thus, +interacting with the ``DeclReference`` you get something like: + +.. code-block:: c++ + + an_ifc_decl_reference decl_ref = ...; + + an_ifc_decl_foreign_index local_index = get_ifc_local_index(decl_ref); + process_ifc_decl(local_index); /* type error */ + +In terms of correct usage, foreign indexes are typically deserialized via an +associated :ref:`ifc-tacit-field` which reconstructs them as the appropriate +:ref:`ifc-index-sort-role` in the context of their respective module. + +As an example consider the DeclReference type: + +.. code-block:: text + + |-------------------------------------------------| + | DeclReference - 0.33 (12 bytes) | + |-------------|------------------|---------|------| + | Name | Type | Version | Size | + |-------------|------------------|---------|------| + | unit | ModuleReference | 0.33 | 8 | + | local_index | DeclForeignIndex | 0.33 | 4 | + |-------------|------------------|---------|------| + | index | DeclIndex | ANY | TF | + |-------------|------------------|---------|------| + +Using the tacit field ``index``, ``local_index`` can be retrieved in the +context of the associated ``unit`` (i.e., IFC module) transparently: + +.. code-block:: c++ + + an_ifc_decl_reference ref = ...; + an_ifc_decl_index idx = get_ifc_index(ref); + +.. _ifc-value-category-role: + +Value Category +-------------- + +Value categories are roughly equivalent to a variant type. The categories have +a :ref:`ifc-simple-sort-role` which describes which variant is valid. The +actual variants can be any role. + +This allows for handling of nested hierarchies like IFC Operators where an +``OperatorSort`` selects the interpretation of the variant value which may +be one of several different :ref:`Simple Sorts`. + +Versioning +========== + +.. _ifc-simple-sort-versioning: + +Simple Sort +----------- + +The :ref:`ifc-simple-sort-role` versioning system works by converting from a +"versioned sort" (i.e., enumeration) to a "universal sort" (i.e., enumeration). +Each IFC version gets its own unique, and appropriately sized enumeration, like +so: + +.. code-block:: c++ + + enum an_ifc_decl_sort_0_33 : uint32_t { + ifc_0_33_ds_decl_vendor_extension = 0, + ifc_0_33_ds_decl_enumerator = 1, + ifc_0_33_ds_decl_variable = 2, + ifc_0_33_ds_decl_parameter = 3, + ifc_0_33_ds_decl_field = 4, + ifc_0_33_ds_decl_bitfield = 5, + ifc_0_33_ds_decl_scope = 6, + ifc_0_33_ds_decl_enumeration = 7, + /* snip */ + }; /* an_ifc_decl_sort_0_33 */ + + enum an_ifc_decl_sort_0_41 : uint32_t { + ifc_0_41_ds_decl_vendor_extension = 0, + ifc_0_41_ds_decl_enumerator = 1, + ifc_0_41_ds_decl_variable = 2, + ifc_0_41_ds_decl_parameter = 3, + ifc_0_41_ds_decl_field = 4, + ifc_0_41_ds_decl_bitfield = 5, + ifc_0_41_ds_decl_scope = 6, + ifc_0_41_ds_decl_enumeration = 7, + /* snip */ + }; /* an_ifc_decl_sort_0_41 */ + +Note that these versioned enumerators do not follow the typical naming +convention. This is done to reduce the amount of possible completions editor +auto complete has for ``ifc_ds_`` (and similar). + +The universal sort representation by contrast takes all of the unique names, +from all the versioned sorts, and puts them in one enumeration: + +.. code-block:: c++ + + enum an_ifc_decl_sort : uint32_t { + ifc_ds_decl_alias, + ifc_ds_decl_barren, + ifc_ds_decl_bitfield, + ifc_ds_decl_concept, + ifc_ds_decl_constructor, + ifc_ds_decl_deduction_guide, + ifc_ds_decl_destructor, + ifc_ds_decl_enumeration, + ifc_ds_decl_enumerator, + ifc_ds_decl_expansion, + ifc_ds_decl_explicit_instantiation, + ifc_ds_decl_explicit_specialization, + ifc_ds_decl_field, + /* snip */ + }; /* an_ifc_decl_sort */ + +This enumeration is sorted alphabetically to make things easier to find and to +prevent the list from being "shuffled" when new IFC versions are adopted. + +Functions are then added to convert between the versioned sort (read from the +module file) to the universal sort, they look something like this: + +.. code-block:: c++ + + inline an_ifc_decl_sort to_universal_sort(an_ifc_decl_sort_0_33 versioned) + /* + Given the versioned representation of DeclSort, return the corresponding + universal representation. + */ + { + an_ifc_decl_sort result; + + switch (versioned) { + case ifc_0_33_ds_decl_vendor_extension: + result = ifc_ds_decl_vendor_extension; + break; + case ifc_0_33_ds_decl_enumerator: + result = ifc_ds_decl_enumerator; + break; + case ifc_0_33_ds_decl_variable: + result = ifc_ds_decl_variable; + break; + /* snip */ + +This allows for stability in all of our logic despite a number of possible +changes to the sort for a particular version (e.g., numbering changes, removal, +and addition). Effectively, sorts become unique on name rather than unique on +value. + +.. _ifc-index-sort-versioning: + +Index Sort +---------- + +As an :ref:`ifc-index-sort-role` is composed of a :ref:`ifc-simple-sort-role` +and an index value, its versioning relies upon the versioning of the associated +:ref:`ifc-simple-sort-role` (see :ref:`ifc-simple-sort-versioning`). + +.. _ifc-bitfield-versioning: + +Bitfield +-------- + +:ref:`ifc-bitfield-role` versioning works very similarly to +:ref:`ifc-simple-sort-versioning`. + +There's similarly a versioned bitfield enum for each version, of appropriate +size, using the values that are correct for that version: + +.. code-block:: c++ + + enum an_ifc_basic_specifiers_bitfield_0_33 : uint8_t { + ifc_0_33_bsb_cxx = 0, + ifc_0_33_bsb_c = 1 << 0, + ifc_0_33_bsb_internal = 1 << 1, + ifc_0_33_bsb_vague = 1 << 2, + ifc_0_33_bsb_external = 1 << 3, + ifc_0_33_bsb_deprecated = 1 << 4, + ifc_0_33_bsb_initialized_in_class = 1 << 5, + ifc_0_33_bsb_non_exported = 1 << 6, + ifc_0_33_bsb_is_member_of_global_module = 1 << 7 + }; /* an_ifc_basic_specifiers_bitfield_0_33 */ + +Unlike sorts, it's not super practical to try and normalize the representation +itself, so instead the value is captured with a module reference. + +.. code-block:: c++ + + /* + The universal representation for an IFC BasicSpecifiersBitfield. + */ + struct an_ifc_basic_specifiers_bitfield { + an_ifc_module* + mod; + /* The associated module. */ + an_ifc_basic_specifiers_bitfield_storage + value; + /* The raw bit value obtained from the module. + Represented as the largest common underlying + type. */ + }; /* an_ifc_basic_specifiers_bitfield */ + +This is then paired with a universal query enum (similar to the universal sort) +that gives a unique bit value to each possible bitfield and a ``test_bitmask`` +function. + +.. code-block:: c++ + + enum an_ifc_basic_specifiers_bitfield_query : uint32_t { + ifc_bsb_c = 1 << 0, + ifc_bsb_cxx = 1 << 1, + ifc_bsb_deprecated = 1 << 2, + ifc_bsb_external = 1 << 3, + ifc_bsb_initialized_in_class = 1 << 4, + ifc_bsb_internal = 1 << 5, + ifc_bsb_is_member_of_global_module = 1 << 6, + ifc_bsb_non_exported = 1 << 7, + ifc_bsb_vague = 1 << 8 + }; /* an_ifc_basic_specifiers_bitfield_query */ + + + template + inline a_boolean test_bitmask( + const an_ifc_basic_specifiers_bitfield &universal) + /* + Given the universal representation of BasicSpecifiersBitfield, return TRUE + if the universal bitmask specified by a_Query matches; otherwise, return + FALSE. + */ + { + a_boolean result; + + uint8_t mask = to_bitmask_0_33(a_Query); + uint8_t test_value = universal.value & mask; + + result = test_value == mask; + return result; + } /* test_bitmask */ + +At a high level, these functions generate per-version branches. Each of these +branches calls a function that converts the universal query, into a version +specific query (i.e., bitmask) for respective version (in this case there's +only one version of the bitfield, so there are no branches, just a call to +``to_bitmask_0_33``). These bitmask conversion functions look something like +the following: + +.. code-block:: c++ + + uint8_t to_bitmask_0_33(an_ifc_basic_specifiers_bitfield_query query) + /* + Given the universal representation of a BasicSpecifiersBitfield bitmask, + return the corresponding IFC version 0.33 representation of the bitmask. + */ + { + uint8_t result = 0; + + if (query & ifc_bsb_cxx) { + result |= ifc_bsb_0_33_cxx; + } /* if */ + if (query & ifc_bsb_c) { + result |= ifc_bsb_0_33_c; + } /* if */ + /* snip */ + +The versioned specific bitmask is then tested against the version specific +value, returning the result. + +This approach allows the front end to test "the same" bitmasks in a version +agnostic way, with a very small runtime performance overhead. + +Bitwidth Limitations +^^^^^^^^^^^^^^^^^^^^ + +As bitfield versioning relies upon native integer types, there are limitations +imposed, namely there are a limited number of expressible bitfield queries +across all versions of the IFC. + +If this becomes a problem in the future, two approaches are noted as promising. + +The first (and simplest) being, the removal of the ability to create a bitmask +by joining two queries (bit-or) in favor of two (effectively bit-and) +tests. This would allow a much larger number of bitfield queries to be +represented as the bitfield query would no longer require its own bit position. + +The second option being, the usage of a "big integer" type with overloaded +operators in place of a native integer type. As the translation process is +realistically performed at compile time (either via language level guarantees +if the front end moves to C++14 and these functions are made constexpr, or via +the optimizer), while this approach may on the surface seem more expensive, at +runtime it would *likely* be more efficient than the former. + +If this problem is encountered, existing usage will guide the resolution (the +formation and usage of bit-or joined queries has thus far been limited, and may +not be useful long term). + +Raw Values +---------- + +:ref:`ifc-raw-numeric-role` and :ref:`ifc-raw-bytes-role` values effectively +aren't versioned. As raw values have no semantic meaning at the format level, +there's "nothing to be done." + +.. _ifc-node-versioning: + +Nodes +----- + +:ref:`Node` versioning relies upon a number of "field +accessors" (i.e., ``get_ifc_``\ *X*) that read from the underlying byte +representation (abstracted by :ref:`ifc-byte-buffers`). These accessors +additionally, abstract away the exact location and representation of various +field values within the node, allowing for complex changes to the node +representation to be "normalized." + +These accessor functions look something like the following: + +.. code-block:: c++ + + template<> + an_ifc_decl_index get_ifc_decl( + const an_ifc_parameterized_entity &universal) + /* + Given the universal representation of ParameterizedEntity, return the + universal representation of the field "decl". + */ + { + an_ifc_decl_index result; + + /* Ensure the decl field exists in the current module version. */ + check_assertion(has_ifc_decl(universal)); + if (is_at_least(universal.get_module(), 0, 41)) { + /* version specific logic */ + } else { + /* version specific logic */ + } /* if */ + return result; + } /* get_ifc_decl */ + +For every version where the retrieval logic is different, we end up with a +separate branch gated on the lower bound of the version range. Newer values are +always checked first, as it's presumed newer IFC versions will be the common +case. + +.. _ifc-node-stages: + +Stages +^^^^^^ + +The exact logic in a given branch used to read a field value, is represented in +the generator as a sequence of "stages." These stages are setup via a "stage +builder" for the specific IFC node version. The stage builder allocates a +result variable for every stage (and can also allocate some additional +variables with extra name information if necessary). + +In most cases the stages and the associated logic are fairly trivial. As an +example, consider: + +.. code-block:: c++ + + an_ifc_decl_index_0_41 stage_0; + an_ifc_decl_index stage_1; + + /* Copy the field (ParameterizedEntity::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/0); + stage_1 = to_universal_index(universal.get_module(), stage_0); + result = stage_1; + +Here the raw value is copied (via ``copy_ifc_field``) from an offset into a +version specific variable (stage 0). Then, said version specific variable is +converted (via ``to_universal_index``) into a universal representation (stage +1). Finally, the resulting value is assigned to the ``result`` return +variable. + +This is a trivial case of data retrieval where the data is directly stored as +part of the node, and only needs converted to a universal representation. For +more information about this process, and additional similar cases, see +:ref:`ifc-field-deserialization`. + +Additionally, it's important to note that in some cases, more complicated +processing is similarly implemented via stages (for a variety of reasons). For +more information on this process, and advanced uses of the stage builder, see +:ref:`ifc-tacit-field`. + +.. _ifc-field-presence-checking: + +Field Presence Checking +^^^^^^^^^^^^^^^^^^^^^^^ + +The presence of an accessor sometimes depends on the IFC version. In +contexts where this is not obvious ``has_ifc_``\ *X* functions can be used to +check to see if the associated ``get_ifc_``\ *X* is valid. These are fairly +simple calls that return TRUE when field *X* is relevant to the node for +the corresponding IFC version, and FALSE otherwise. + +Foreign Index +------------- + +:ref:`Foreign Indexes`, despite conceptually being an +:ref:`ifc-index-sort-role` are versioned more like :ref:`Raw +Numerics`. This is done as foreign indexes have an +associated module which contains its own revision information. Thus, using the +current (referencing) module's version information to convert the raw value to +a universal understanding would be unreliable at best. + +Value Category +-------------- + +:ref:`Value Categories` rely upon the fact that the +types they're composed of are themselves versioned. Thus, while value +categories are versioned, they do not have any versioning rules specific to +them. + +.. _ifc-deserialization: + +Deserialization +=============== + +IFC deserialization is notable for intricacies introduced by supporting +optional memory mapped IFC reading and support for big-endian and little-endian +byte orders. + +.. _ifc-byte-buffers: + +Byte Buffers +------------ + +The ``an_ifc_Byte_buffer`` class template is the class that's fundamentally +responsible for abstracting away the location of the in memory representation +of a given byte sequences taken from the IFC file. + +The most notable use the byte buffer abstraction being for the representation +of :ref:`ifc-node-roles` but some other IFC roles, such as +:ref:`ifc-raw-bytes-role`, also make use of byte buffers. + +The byte buffer fulfills its duty of abstracting away the memory location for a +given byte sequence via a union. Said union contains either the bytes required +for storage, or a storage_ptr; this determination is made during construction +of the respective byte buffer. + +.. _ifc-endianness: + +Endianness Agnostic Reading +--------------------------- + +Endianness agnostic reading requires considerations for cases that are +and aren't memory mapped. + +Without Memory Mapping +---------------------- + +When memory mapping isn't enabled, the front end resorts to calls to +``get_bytes`` for each field in each node. + +Each call copies the appropriate number of bytes for the field into a +:ref:`Byte Buffer`, reversing the byte order for the bytes +stored in the field if the host and IFC endianness do not match. + +For nodes that contain nested (i.e., :ref:`ifc-basic-node-role`) node +structures, the internal node's fields are copied individually rather than +copying the entire internal node as "one field." + +With Memory Mapping +------------------- + +When memory mapping is enabled, if there is an endianness mismatch, the +non-memory mapped approach described above is used. + +Otherwise, the front end will use only a pointer to the start of the node +(within the broader memory mapped memory region). This pointer is then stored +and dereferenced when retrieving data in place of copying bytes into the +:ref:`Byte Buffer`. + +There is also support for a-typical cases where the front end, even when +operating with memory mapping and matching endianness, explicitly requests an +explicit copy of the data. In practice, this isn't currently used by the front +end and may be removed in the future. + +.. _ifc-field-deserialization: + +Field Deserialization +--------------------- + +Fields are deserialized from the associated :ref:`Byte +Buffer` for the corresponding node. This process makes use +of one of two ``copy_ifc_field`` field functions, and in some cases an adjusted +:ref:`Byte Buffer` pointer instead of a copy. + +Implicit Bounds Copying +----------------------- + +Copying with implicit bounds occurs when the destination object type is exactly +equivalent size. These copies additionally include a static assert as a +functional "sanity check" to ensure the code generation tool is right about the +size of the destination object (not just in theory, but in practice). + +.. code-block:: c++ + + an_ifc_keyword_sort_0_33 stage_0; + an_ifc_keyword_sort stage_1; + + /* Copy the field (KeywordSyntax::value - KeywordSort) into version-specific + storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/8); + + +Explicit Bounds Copying +----------------------- + +Copying with explicit bounds occurs when the destination object type is a +buffer of at least equivalent size. + +.. code-block:: c++ + + enum an_ifc_source_location_part : uint8_t {}; + using an_ifc_source_location_storage = an_ifc_source_location_part[8]; + #if USE_MMAP_FOR_MODULES + using an_ifc_source_location_bytes = const an_ifc_source_location_storage*; + #else /* !USE_MMAP_FOR_MODULES */ + using an_ifc_source_location_bytes = an_ifc_source_location_storage; + #endif /* USE_MMAP_FOR_MODULES */ + + an_ifc_source_location_bytes stage_0; + + /* Copy the field (KeywordSyntax::locus - SourceLocation) into universal + storage. */ + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/0, + /*size=*/8); + +Byte Buffer Adjustment +---------------------- + +:ref:`ifc-byte-buffers` are adjusted in place of a copy when the front end is +operating in memory mapped mode, and the resulting value is a byte buffer based +type. This process allows the front end to avoid unnecessary copies in memory +mapped modes when working with subobjects. + +.. code-block:: c++ + + enum an_ifc_source_location_part : uint8_t {}; + using an_ifc_source_location_storage = an_ifc_source_location_part[8]; + using an_ifc_source_location_bytes = const an_ifc_source_location_storage*; + + an_ifc_source_location_bytes stage_0; + + /* Update the universal storage pointer to the start of the field + (KeywordSyntax::locus - SourceLocation). */ + stage_0 = (an_ifc_source_location_bytes)((*universal.get_storage()) + 0); + +This optimization is only performed when memory mapped mode is available as +otherwise it creates an unsafe implicit dependence. In said case, the value +retrieved from a node via a field accessor depends on the lifetime of the +owning node's storage. In other words, without memory mapping, it's possible +for the memory that owns the subobject to go out of scope. + +.. _field-copying: + +Field Copying +------------- + +The respective implementation of both overloads of ``copy_ifc_field`` perform a +``memcpy`` operation; this is an intentional choice over casting and +dereferencing the pointer. + +This decision is also closely related to the usage of :ref:`ifc-byte-buffers` +over dedicated structs representing each version (which have debugging benefits +over the chosen approach). + +In the case of both decisions, the driving force behind this choice is +alignment. In the former case attempting to dereference an misaligned pointer +is undefined behavior. Thus, attempting to "avoiding the copy" via a +``reinterpret_cast`` paired with a deference could lead to severe portability +issues, and -- ironically -- degraded performance. However, the ``memcpy`` +operation can be safely optimized and used, even for unaligned inputs. Thus, +the approach of usage a ``memcpy`` to copy data into known fixed size types +gives maximum performance without the associated portability concerns. + +In the case of the latter decision specifically, the individual data members +within a struct will be padded differently on different host compilers, +operating systems, and different architectures (to comply with alignment +requirements). Thus, attempting to "overlay" a struct onto the underlying IFC +byte representation, results in similar severe portability issues. + +.. _ifc-tacit-field: + +Tacit Field +----------- + +A "tacit field" is a field that isn't actually part of the official field list +for a node. Tacit fields are regularly used to expose information that's +(indirectly) always present. For instance, a node might have no "home_scope" +field but the home scope can always be resolved via a different field. + +As an example, consider the following made up node "``FooDef``" (which for +the sake of the hypothetical, pairs a declaration with a syntactic +definition): + ++-----------------+----------------------+ +| Field | Type | ++=================+======================+ +| ``declaration`` | ``DeclIndex`` | ++-----------------+----------------------+ +| ``definition`` | ``SyntaxIndex`` | ++-----------------+----------------------+ + +Continuing with the hypothetical, in practice for "``FooDef``" nodes the +``DeclIndex`` for declaration, when valid, *always* points to a node that has a +``home_scope`` field. A tacit field exposes this invariant explicitly. From +the front end's perspective, adding a tacit field for ``home_scope`` is +"as-if" the binary representation defined "``FooDef``" to be: + ++-----------------+----------------------+ +| Field | Type | ++=================+======================+ +| ``declaration`` | ``DeclIndex`` | ++-----------------+----------------------+ +| ``definition`` | ``SyntaxIndex`` | ++-----------------+----------------------+ +| ``home_scope`` | ``DeclIndex`` | ++-----------------+----------------------+ + +This also exposes this invariant to the validator, which will then make sure +declaration points to a node with a ``home_scope`` field containing a valid +``DeclIndex``. + +Not all tacit fields perform this sort of "proxy retrieval" operation, +effectively *any* invariant can be exposed and validated in this way. + +Impact on Versioning +^^^^^^^^^^^^^^^^^^^^ + +This conceptual breadth of functionality allows tacit fields play a large +role in supporting different IFC versions as well. Consider a later +revision of "``FooDef``" changes ``declaration`` so that the ``DeclIndex`` +sometimes points to a new intermediary node "``FooProxyDecl``", which then +itself always points to a third node that has a ``home_scope``. + +Tacit fields allow this change to be "invisible" to existing logic. The +existing ``home_scope`` tacit field can be updated to follow the new rules +and properly retrieve the ``home_scope`` as one might expect. However, +tacit fields can also "replace" (or "override") a field that's explicitly +part of the binary node representation (i.e., "explicitly declared") if +they share the same name. + +In the context of this example, existing code might break -- badly -- when +it encounters the new intermediary "``FooProxyDecl``" node after a call to +the field accessor ``get_ifc_declaration(const an_ifc_foo_decl&)``. A new +``declaration`` tacit field can be added that automatically "sees through" +the wrapper, "as-if" it was never added. The existing logic then goes back +to functioning as it did before, as from its perspective nothing changed. + +Code that then needs to observe the new "``FooProxyDecl``" can then be +accounted for by adding additional tacit fields that either expose the +"true" value of ``declaration`` or information from "``FooProxyDecl``." + +The exact approach taken is situational, however, tacit fields are a powerful +tool for resolving versioning issues. + +Tacit Field Implementation +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As noted in :ref:`ifc-node-versioning`, field accessors work via "stages" +constructed from a "stage builder" in the code generation tool. + +These can get *exceptionally* complicated in terms of implemented +code. Consider the following real example, taken verbatim from the front end: + +.. code-block:: c++ + + template<> + an_ifc_decl_index get_ifc_home_scope( + const an_ifc_decl_enumerator &universal) + /* + Given the universal representation of DeclEnumerator, return the universal + representation of the field "home_scope". + */ + { + an_ifc_decl_index result; + + /* Ensure the home_scope field exists in the current module version. */ + check_assertion(has_ifc_home_scope(universal)); + if (is_at_least(universal.get_module(), 0, 41)) { + an_ifc_type_index_0_33 stage_0; + an_ifc_type_index stage_1; + an_ifc_type_designated stage_2; + an_ifc_decl_index_0_41 stage_3; + an_ifc_decl_index stage_4; + a_boolean stage_5; + an_ifc_decl_index stage_6; + + /* Copy the field (DeclEnumerator::type - TypeIndex) into + version-specific storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12); + stage_1 = to_universal_index(universal.get_module(), stage_0); + /* Use the obtained index to retrieve the appropriate instance of + TypeDesignated (the type tag should have been prechecked by + validation). Then, retrieve and return the desired value held by + the field decl. */ + construct_node_unchecked(&stage_2, stage_1); + /* Copy the field (TypeDesignated::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_3) == 4, + "stage_3 is not properly sized storage!"); + copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0); + stage_4 = to_universal_index(stage_2.get_module(), stage_3); + if (stage_4.sort == ifc_ds_decl_specialization) { + stage_5 = TRUE; + } else { + stage_5 = FALSE; + } /* if */ + if (stage_5) { + an_ifc_decl_index stage_6_0; + an_ifc_decl_specialization stage_6_1; + an_ifc_decl_index_0_41 stage_6_2; + an_ifc_decl_index stage_6_3; + + stage_6_0 = stage_4; + /* Use the obtained index to retrieve the appropriate instance of + DeclSpecialization (the type tag should have been prechecked by + validation). Then, retrieve and return the desired value held by + the field decl. */ + construct_node_unchecked(&stage_6_1, stage_6_0); + /* Copy the field (DeclSpecialization::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_6_2) == 4, + "stage_6_2 is not properly sized storage!"); + copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4); + stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2); + stage_6 = stage_6_3; + } else { + an_ifc_decl_index stage_6_0; + + stage_6_0 = stage_4; + stage_6 = stage_6_0; + } /* if */ + result = stage_6; + } else { + an_ifc_type_index_0_33 stage_0; + an_ifc_type_index stage_1; + an_ifc_type_designated stage_2; + an_ifc_decl_index_0_33 stage_3; + an_ifc_decl_index stage_4; + + /* Copy the field (DeclEnumerator::type - TypeIndex) into + version-specific storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12); + stage_1 = to_universal_index(universal.get_module(), stage_0); + /* Use the obtained index to retrieve the appropriate instance of + TypeDesignated (the type tag should have been prechecked by + validation). Then, retrieve and return the desired value held by + the field decl. */ + construct_node_unchecked(&stage_2, stage_1); + /* Copy the field (TypeDesignated::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_3) == 4, + "stage_3 is not properly sized storage!"); + copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0); + stage_4 = to_universal_index(stage_2.get_module(), stage_3); + result = stage_4; + } /* if */ + return result; + } /* get_ifc_home_scope */ + +Stage Breakdown +~~~~~~~~~~~~~~~ + +This is an intimidating amount of logic, however it's composed of bite sized +pieces of principled logic coming together. At a high level, there are two +cases here, one for IFC version 0.41+ and one for earlier supported versions of +the IFC. + +Consider the " earlier " code (i.e., the code for supporting IFC versions +prior to 0.41, which will be known from this point as the 0.33+ code): + +.. code-block:: c++ + + an_ifc_type_index_0_33 stage_0; + an_ifc_type_index stage_1; + an_ifc_type_designated stage_2; + an_ifc_decl_index_0_33 stage_3; + an_ifc_decl_index stage_4; + + /* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific + storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12); + stage_1 = to_universal_index(universal.get_module(), stage_0); + /* Use the obtained index to retrieve the appropriate instance of + TypeDesignated (the type tag should have been prechecked by validation). + Then, retrieve and return the desired value held by the field decl. */ + construct_node_unchecked(&stage_2, stage_1); + /* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific + storage. */ + static_assert(sizeof(stage_3) == 4, + "stage_3 is not properly sized storage!"); + copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0); + stage_4 = to_universal_index(stage_2.get_module(), stage_3); + result = stage_4; + +The code generation tool represents this as in effect, a directly constructed +expression AST, simplifying a bit: + +.. code-block:: python + + IFCRemoteDelegate( + IFCDirectDelegate('type'), + 'Type', + 'TypeDesignated', + 'decl' + ) + +This is conceptually an "expression" representing the retrieval of the +value. The innermost operation ``IFCDirectDelegate`` is thus the first to be +evaluated. + +While fully documenting the tacit field system within the code generation tool +is out of scope, for purposes of understanding, an ``IFCDirectDelegate`` simply +means "read the type field" from the node. + +Similarly, ``IFCRemoteDelegate`` simply means "take the input value (the +type field value), it's a ``Type(Index)`` that must point to a +``TypeDesignated`` node, read said node's ``decl`` field." + +The "stage builder" takes this expression and transforms it into a series of +"stages." + +Stage 0 +""""""" + +Read the versioned value of the type field: + +.. code-block:: c++ + + an_ifc_type_index_0_33 stage_0; + + /* snip */ + /* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific + storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12); + +Stage 1 +""""""" + +Turn the versioned type field value into a universal value: + +.. code-block:: c++ + + an_ifc_type_index_0_33 stage_0; + an_ifc_type_index stage_1; + + /* snip */ + stage_1 = to_universal_index(universal.get_module(), stage_0); + +Stage 2 +""""""" + +Load the ``TypeDesignated`` node: + +.. code-block:: c++ + + an_ifc_type_index stage_1; + an_ifc_type_designated stage_2; + + /* Use the obtained index to retrieve the appropriate instance of + TypeDesignated (the type tag should have been prechecked by validation). + Then, retrieve and return the desired value held by the field decl. */ + construct_node_unchecked(&stage_2, stage_1); + + +Stage 3 +""""""" + +Read the versioned value of the ``decl`` field from the ``TypeDesignated`` +node: + +.. code-block:: c++ + + an_ifc_type_designated stage_2; + an_ifc_decl_index_0_33 stage_3; + + /* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific + storage. */ + static_assert(sizeof(stage_3) == 4, + "stage_3 is not properly sized storage!"); + copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0); + +Stage 4 +""""""" + +Turn the versioned ``decl`` field value into a universal value: + +.. code-block:: c++ + + an_ifc_decl_index_0_33 stage_3; + an_ifc_decl_index stage_4; + + stage_4 = to_universal_index(stage_2.get_module(), stage_3); + result = stage_4; + +Stage 5 (Wrap-up) +""""""""""""""""" + +Assign the result: + +.. code-block:: c++ + + an_ifc_decl_index stage_4; + + result = stage_4; + +The stage builder facilitates the creation of these stages from the expression, +creating a metaphorical "data retrieval pipeline." The usage of expression +nodes and this system of generating C++ stages from these nodes, allows tacit +fields to be quickly written via reusable building blocks. + +Examination of the validation logic will reveal it's very similar to the logic +generated for field data retrieval, however rather than returning a result, it +performs a number of checks to make sure the would-be result and everything +required in-between is validated as necessary. + +Advanced Stage Breakdown +~~~~~~~~~~~~~~~~~~~~~~~~ + +After establishing an understanding of the flow of the 0.33+ code, consider the +0.41+ code: + +.. code-block:: c++ + + an_ifc_type_index_0_33 stage_0; + an_ifc_type_index stage_1; + an_ifc_type_designated stage_2; + an_ifc_decl_index_0_41 stage_3; + an_ifc_decl_index stage_4; + a_boolean stage_5; + an_ifc_decl_index stage_6; + + /* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific + storage. */ + static_assert(sizeof(stage_0) == 4, + "stage_0 is not properly sized storage!"); + copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12); + stage_1 = to_universal_index(universal.get_module(), stage_0); + /* Use the obtained index to retrieve the appropriate instance of + TypeDesignated (the type tag should have been prechecked by validation). + Then, retrieve and return the desired value held by the field decl. */ + construct_node_unchecked(&stage_2, stage_1); + /* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific + storage. */ + static_assert(sizeof(stage_3) == 4, + "stage_3 is not properly sized storage!"); + copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0); + stage_4 = to_universal_index(stage_2.get_module(), stage_3); + if (stage_4.sort == ifc_ds_decl_specialization) { + stage_5 = TRUE; + } else { + stage_5 = FALSE; + } /* if */ + if (stage_5) { + an_ifc_decl_index stage_6_0; + an_ifc_decl_specialization stage_6_1; + an_ifc_decl_index_0_41 stage_6_2; + an_ifc_decl_index stage_6_3; + + stage_6_0 = stage_4; + /* Use the obtained index to retrieve the appropriate instance of + DeclSpecialization (the type tag should have been prechecked by + validation). Then, retrieve and return the desired value held by the + field decl. */ + construct_node_unchecked(&stage_6_1, stage_6_0); + /* Copy the field (DeclSpecialization::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_6_2) == 4, + "stage_6_2 is not properly sized storage!"); + copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4); + stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2); + stage_6 = stage_6_3; + } else { + an_ifc_decl_index stage_6_0; + + stage_6_0 = stage_4; + stage_6 = stage_6_0; + } /* if */ + result = stage_6; + +Here stages 0 through 4 are identical to the 0.33+ code, however additional +stages have been added (i.e., the "pipeline" has been extended). Stage 6 is +particularly interesting as it works with substages. + +To understand what's going on here, consider the following simplified code from +the code generation tool: + +.. code-block:: python + + existing_logic = IFCRemoteDelegate( + IFCDirectDelegate('type'), + 'Type', + 'TypeDesignated', + 'decl' + ) + source_value = IFCReusableResult(existing_logic) + + IFCConditionalDelegate( + IFCTestSortMatch( + source_value, + 'Decl', + {'DeclSpecialization'} + ), + 'DeclIndex', + IFCRemoteDelegate( + source_value, + 'Decl', + 'DeclSpecialization', + 'decl' + ), + source_value + ) + +The ``existing_logic``, the associated ``IFCRemoteDelegate``, and +``IFCDirectDelegate`` were already covered, so those won't be +revisited. However, ``IFCReusableResult``, ``IFCTestSortMatch``, and +``IFCConditionalDelegate`` are new. + +``IFCReusableResult`` can be thought of like a lazily-evaluated, "memoization +instruction." This allows reuse of the same value without reevaluation. + +``IFCTestSortMatch`` means "take the input value (the possibly memoized +``TypeDesignated decl`` field value), evaluate true if its ``Decl(Sort)`` +value is ``DeclSpecialization``; otherwise, evaluate false." + +``IFCConditionalDelegate`` means "compute a ``DeclIndex`` value one of two +ways, if the input value (the test sort match) evaluates as true use the +first sub-expression, otherwise use the second." + +``IFCConditionalDelegate``\ s are particularly notable as they allow logic +to have branched evaluation. When these branches are translated to C++ +code, these are implemented via substages (effectively stage builders that +inherent a prefix and their input from a parent stage builder's stage). + +Note how this all composes to allow the existing logic to be sanely extended. +Looking at what's new, stage 5 is where things diverge. + +Stage 5 +""""""" + +The resulting ``DeclIndex`` is check to see if its sort is a +``DeclSpecialization``, storing the result as a boolean value: + +.. code-block:: c++ + + an_ifc_decl_index stage_4; + a_boolean stage_5; + + if (stage_4.sort == ifc_ds_decl_specialization) { + stage_5 = TRUE; + } else { + stage_5 = FALSE; + } /* if */ + +Stage 6 (Wrap-up) +""""""""""""""""" + +The previous result of the ``DeclSpecialization`` sort test is used, forking to +evaluate one of two sub-expressions before the result is assigned: + +.. code-block:: c++ + + if (stage_5) { + /* substage content */ + } else { + /* substage content */ + } /* if */ + result = stage_6; + +The first sub-expression (when a ``DeclSpecialization`` is used) unwraps +the ``decl`` field value from the ``DeclSpecialization`` node, storing the +result in stage 6: + +.. code-block:: c++ + + an_ifc_decl_index stage_6_0; + an_ifc_decl_specialization stage_6_1; + an_ifc_decl_index_0_41 stage_6_2; + an_ifc_decl_index stage_6_3; + + stage_6_0 = stage_4; + /* Use the obtained index to retrieve the appropriate instance of + DeclSpecialization (the type tag should have been prechecked by + validation). Then, retrieve and return the desired value held by the + field decl. */ + construct_node_unchecked(&stage_6_1, stage_6_0); + /* Copy the field (DeclSpecialization::decl - DeclIndex) into + version-specific storage. */ + static_assert(sizeof(stage_6_2) == 4, + "stage_6_2 is not properly sized storage!"); + copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4); + stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2); + stage_6 = stage_6_3; + +The second sub-expression (when a ``DeclSpecializtion`` is not used) passes +through the value as a no-op: + +.. code-block:: c++ + + an_ifc_decl_index stage_6_0; + + stage_6_0 = stage_4; + stage_6 = stage_6_0; + +Note that even though the second sub-expression ends up being generated as an +effective no-op case with no special processing of its own, a substage +(stage_6_0) is initialized. There is no special meaning to this, it's merely an +implementation detail that falls out from the semantics of the code generation +tool. This may be improved in future revisions, but it's largely a visual +defect that gets cleaned up during optimization. + +.. _validation: + +Validation +---------- + +The IFC validation system is designed to check all data read from the IFC file +while being "out of the way", performant, and extendable. + +Point of Validation +^^^^^^^^^^^^^^^^^^^ + +Data is validated upon construction of a node, namely within the +``construct_node`` function (via a call to the ``validate`` function +corresponding to the node). This validation covers all ``get_ifc_``\ *X* return +values (and in the case of :ref:`ifc-tacit-field`, any intermediate data). + +The validation system leverages the stage builder (for more information +about stages in general, see :ref:`ifc-node-stages`) system used to create +the ``get_ifc_``\ *X* functions themselves. The stage builder knows how to +create not only the typical "data retrieval pipeline", but one which +validates the intermediate steps, and the returned data. + +The extent of the validation depends on the role associated with the type +being validated. + +Simple Sort +~~~~~~~~~~~ + +:ref:`ifc-simple-sort-role` validation ensures that the input value corresponds +to a valid simple sort value for the current IFC version and simple sort type. + +Index Sort +~~~~~~~~~~ + +:ref:`ifc-index-sort-role` validation first checks the associated +:ref:`ifc-simple-sort-role` for validation issues, then ensures that the +requested element exists in the associated partition. This latter step can be +thought of as a sort of pointer validation, it doesn't ensure the validity of +the data being pointed to, but it does ensure the pointer itself is valid. + +Nodes +~~~~~ + +:ref:`ifc-node-roles` sometimes appear within other nodes (for more +information, see :ref:`ifc-basic-node-role`). In these cases, the validator +recurses into the sub-node and also ensures the validity of its fields. This +reduces the number of calls required to work with sub-nodes, and improves +diagnostics (by providing extra context to work with). + +Value Categories +~~~~~~~~~~~~~~~~ + +:ref:`ifc-value-category-role` validation similar to :ref:`ifc-index-sort-role` +validation first checks the associated :ref:`ifc-simple-sort-role` for +validation issues. The respective variant is then validated as necessary. + +Validation Cache +^^^^^^^^^^^^^^^^ + +The validation system is made more efficient by a bit-based caching mechanism. + +Each partition position in the IFC has its validation status represented as two +bits that are part of a 32-bit integer. The higher 16 bits are used to +represent an "invalid" flag while the lower 16 bits are used to represent a +"validated" flag. The choice to represent "invalid" status instead of "valid" +status is deliberate to minimize the number of writes to the validation cache +for a valid IFC file. + +These 32-bit integers are themselves part of an array that's allocated +per-partition representing all elements in the partition. The cache thus has +both high locality and high space efficiency. + +When a node is constructed via ``construct_node`` the validation cache is +checked, and if the node has already been validated, the cached validation +status will be reused rather than rerunning the ``validate`` function for the +node. + +The caching process also provides -- as an adverse affect -- a guarantee that +validation diagnostics are only emitted once. + +.. _skipping-validation: + +Skipping Validation +^^^^^^^^^^^^^^^^^^^ + +In general, data validation should not be skipped. However, in some cases it's +desirable to skip validation. + +Pre-checked Data +~~~~~~~~~~~~~~~~ + +``construct_node_prechecked`` can be useful as an optimization in places where +it's known -- with certainty -- that the node being constructed has previously +been validated. + +Note that when ``CHECKING`` is enabled this function will check the validation +cache to ensure that the node being constructed truly was previously validated. + +Unchecked Data +~~~~~~~~~~~~~~ + +``construct_node_unchecked`` can be used as part of low level implementation +details that can safely ignored validation status (or code that takes special +care to ensure safe usage). It's important to emphasize, this function truly +bypasses all checks, and thus can introduce unsafe data or crashes if used +improperly. + +An example of a time this function is useful is the ``find_trait`` +function. Traits are found via a binary search, attempting to validate the data +during the search would significantly degrade performance, and might lead to a +large number of unnecessary diagnostics about data that's never used. The usage +is made safe as after the search completes the final result (if any) is +validated. + +.. _ifc-reader-visitors: + +Visitors +-------- + +The visitor system is designed to allow the use of ``get_ifc_``\ *X* +functions on a given :ref:`ifc-index-sort-role` value. As an example, +consider the following: + +.. code-block:: c++ + + an_ifc_decl_index decl_idx = ...; + an_ifc_decl_index home_scope_idx = get_ifc_home_scope(decl_idx); + +This is not a field accessor as described in the :ref:`ifc-node-roles` section. +Instead, this function will load the appropriate node for the index, and then +delegate to that node's field accessor of the same name. It's thus in essence, +equivalent to writing: + +.. code-block:: c++ + + switch (decl_idx.sort) { + case ifc_ds_decl_function: + { an_ifc_decl_function universal; + + construct_node_prechecked(&universal, decl_idx); + home_scope_idx = get_ifc_home_scope(universal); + } + break; + } /* switch */ + +Note that this has some limitations, namely, the sort has to point to a node +that has the given field name for the current IFC version, and the node has to +have been previously validated. + +To accommodate these limitations additional visitors are exposed for the +corresponding ``has_ifc_``\ *X* function (for more information, see: +:ref:`ifc-field-presence-checking`) and for node validation. + +Thus, in most cases the correct usage looks something like the following: + +.. code-block:: c++ + + an_ifc_decl_index decl_idx = ...; + an_ifc_decl_index home_scope_idx; + + /* Check if a valid version of the node pointed to by this decl_idx would + ever have a valid home_scope */ + if (has_ifc_home_scope(decl_idx)) { + /* Make sure we're working with a valid node */ + if (validate(decl_idx)) { + /* Guaranteed retrieval of a valid home scope index. */ + home_scope_idx = get_ifc_home_scope(decl_idx); + } /* if */ + } /* if */ + +This is often just simplified to: + +.. code-block:: c++ + + an_ifc_decl_index decl_idx = ...; + an_ifc_decl_index home_scope_idx; + + if (has_ifc_home_scope(decl_idx) && validate(decl_idx)) { + home_scope_idx = get_ifc_home_scope(decl_idx); + } /* if */ + +Passthrough +^^^^^^^^^^^ + +In the case of certain nodes, a reasonable answer can be obtained, but is not +implicitly present. For these cases, an "implicit dereference" is added to the +code generation tool. These allow visitors to recurse using the "dereferenced" +value. + +As an example, consider the following: + +.. code-block:: python + + # Implicit dereferencing on the DeclIndex. + 'Decl': { + # Implicitly dereference DeclReference via the get_ifc_index function. + 'DeclReference': 'get_ifc_index' + } + +This is an implicit dereference on the Decl :ref:`ifc-index-sort-role`, that +applies the requested traversal to the result of a DeclReference's +``get_ifc_index`` field accessor. + +In generated code, this looks something like the following: + +.. code-block:: c++ + + case ifc_ds_decl_reference: + { an_ifc_decl_reference universal; + + construct_node_prechecked(&universal, idx); + + an_ifc_decl_index remote_idx = get_ifc_index(universal); + result = get_ifc_home_scope(remote_idx); + } + break; + +This notably also applies to the ``has_ifc_``\ *X* function: + +.. code-block:: c++ + + case ifc_ds_decl_reference: + { Opt opt_universal; + + construct_node(&opt_universal, idx); + if (opt_universal.has_value()) { + an_ifc_decl_index remote_idx = get_ifc_index(*opt_universal); + + if (has_ifc_home_scope(remote_idx)) { + result = TRUE; + } /* if */ + } /* if */ + } + break; + +Thus, in contrast to an :ref:`ifc-tacit-field`, a visitor is much more lenient +form of data retrieval, often used both in instances of "may-have" as opposed +to instances of "must-have." + +.. _visitor-implicit-conversion: + +Implicit Conversion +^^^^^^^^^^^^^^^^^^^ + +Some visitors are additionally configured with implicit conversions. These +conversions allow the visitor to return one return type while the underlying +``get_ifc_``\ *X* field accessors return different types. + +As an example, the IFC's ``TextOffset`` can be represented as a +NameIndex. Thus, to allow for one ``get_ifc_name`` visitor, a conversion is +added. + +Limited Scope +^^^^^^^^^^^^^ + +As most fields don't need exposed by visitors, generating every possible +visitor could get quite expensive (both for the code generation tool and for +build times). Thus, instead, the code generation tool requires desired visitors +to be explicitly listed. + +For instance, to define a simple visitor to expose the home_scope DeclIndex: + +.. code-block:: python + + # Add a visitor over the Decl index for get_ifc_home_scope returning + # an_ifc_decl_index with no conversions. + ( + 'Decl', + 'home_scope', + 'an_ifc_decl_index', + {} + ) + +In more advanced cases like the +:ref:`aforementioned` ``get_ifc_name`` visitor, +conversions are specified like so: + +.. code-block:: python + + # Add a visitor over the Decl index for get_ifc_name returning + # an_ifc_name_index with a potential conversion from a an_ifc_text_offset + # to an_ifc_name_index. + ( + 'Decl', + 'name', + 'an_ifc_name_index', + { + 'conversions': { + 'an_ifc_text_offset': IFCTextOffsetToNameIndex() + } + } + ) + +Partition Kinds +=============== + +The generation tool manages a list of partition kinds known to said tool (and +thus the front end). + +These partition kinds are exposed via the ``an_ifc_partition_kind`` enum with +an additional ``ifc_pk_none`` value written to represent invalid states. + +The total number of IFC partition kinds known to the front end (not including +``ifc_pk_none``) can be retrieved via the ``IFC_PARTITION_COUNT`` macro. + +A alphabetically sorted mapping of IFC partition kind names to +``an_ifc_partition_kind`` values (not including ``ifc_pk_none``) named +``ifc_partition_map`` is also maintained to enable binary search based mapping +between a given IFC partition kind name and the corresponding front end value +used for its representation. + +As this mapping is extensive (with the exception of ``ifc_pk_none``) +``ifc_partition_mapping[partition_kind - 1].name`` can be used to retrieve the +name of any ``an_ifc_partition_kind`` value in constant time. + +Additionally, the associated relationships between partition kinds and other +roles is also captured by several utility functions. + +``get_ifc_partition_kind`` +-------------------------- + +Some operations require knowing the partition kind associated with a given node +type. The ``get_ifc_partition_kind`` explicit template specializations +expose this information via template instantiation. + +``get_ifc_partition_element_size`` +---------------------------------- + +Some operations require knowing the expected element size for a given partition +at a given IFC version. The ``get_ifc_partition_element_size`` function +provides this functionality taking a module and partition kind and returning +the expected size. + +``has_partition_kind`` +---------------------- + +Some operations require knowing whether or not a given +:ref:`ifc-simple-sort-role` value has an associated partition kind. The +``has_partition_kind`` functions take a simple sort and return TRUE if the +sort has an associated partition kind, otherwise they return FALSE. + +``to/from_partition_kind`` +--------------------------- + +Some operations require a transition from an :ref:`Index +Sort's` :ref:`ifc-simple-sort-role` to a partition sort or +vice versa. + +The ``to_partition_kind`` functions take a :ref:`ifc-simple-sort-role` and +convert the sort to ``an_ifc_partition_kind``. + +Conversely, the ``to_X`` sort functions take ``an_ifc_partition_kind`` and +convert it to the desired :ref:`ifc-simple-sort-role`. + +Note that in both cases, any conversion failures will result in a crash. + +Debugging +========= + +Nodes +----- + +As noted in the :ref:`field-copying` subsection, to provide a portable +implementation of :ref:`IFC Deserialization`, sacrifices +were made that negatively impact the debugger experience of working with IFC +:ref:`ifc-node-roles`. + +To mitigate this issue, ``DEBUG`` builds of the front end include ``db_node`` +functions which can be invoked to get a pretty-printed summary of the node's +contents from within the debugger. + +Consider the following: + +.. code-block:: c++ + + an_ifc_decl_alias foo = ...; + /* break point */ + +When debugging this code, the ``db_node(const an_ifc_decl_alias &universal)`` +function (in most cases invoked simply as ``db_node(foo)``) can be used to +print the node contents. + +This results in output similar to the following: + +.. code-block:: none + + =============================== DeclAlias ================================ + access: AccessSort::None + aliasee: + sort: TypeSort::TypePointer + value: 0 + home_scope: NULL + locus: + column: 22 + line: 2 + name: 189 + specifiers: + - C + - Cxx + - IsMemberOfGlobalModule + type: + sort: TypeSort::TypeFundamental + value: 0 + +Code Organization +================= + +This system generates a *lot* of code, as a result, to keep the front end build +times down code has been carefully organized and separated to prevent any one +translation unit from having an excessive impact on the build time. + +The code generated files currently include: + +* ``ifc_map.h`` - A forward declaration of all types so they can be used in + ``ifc_module.h`` without polluting ``ifc_module.h`` with a large number of + functions. +* ``ifc_map_functions.h`` - The forward declarations of functions imported in + files that need access to low level IFC reading operations. +* ``ifc_map_functions.c`` - The implementation of functions declared in + ``ifc_map_functions.h`` that do not have a more specific implementation file. +* ``ifc_map_functions_acc.c`` - The implementation of all IFC field accessor + functions. +* ``ifc_map_functions_dbg.c`` - The implementation of all IFC debug functions. +* ``ifc_map_functions_val.c`` - The implementation of all IFC validation + functions. +* ``ifc_modules_inst.h`` - A list of macros imported in ``ifc_modules_templ.c`` + to manage explicit template instantiations. +* ``ifc_modules_spec.h`` - A list of macros imported in ``ifc_modules_templ.c`` + to manage explicit template specializations. + +Note that :ref:`Visitor` implementations are currently +found in ``ifc_map_functions.c``. + +The portion of the front end that handles deserialization is primarily found in +``ifc_modules_read.c``. The portion of the front end that handles +serialization is primarily found in ``ifc_modules_write.c``. Code that is +common between the two is found in ``ifc_modules_internal.h`` and +``ifc_modules.c``. + +All supporting template definitions and instantiations (that used by a mix of +``ifc_modules.c``, ``ifc_modules_read.c``, `ifc_modules_write.c``, and the +``ifc_map_functions*.c`` files) are isolated to ``ifc_modules_templ.c``, +preventing multiple translation units from instantiating the same template. diff --git a/doc/_sources/pragma.rst.txt b/doc/_sources/pragma.rst.txt new file mode 100644 index 0000000..0633761 --- /dev/null +++ b/doc/_sources/pragma.rst.txt @@ -0,0 +1,851 @@ +.. _pragmas-and-attributes: + +====================== +Pragmas and Attributes +====================== + +Support for the processing of ``#pragma`` directives appears in several files +(including ``preproc.c``, ``lexical.c``, and ``il.c``), but the principal +routines are in ``pragma.c``. ``pragma.h`` and ``il_def.h`` contain +definitions of the data structures that are used. + +Standard attributes, GNU attributes, and Microsoft ``__declspec`` attributes +are like pragmas in their semantic scope (i.e., a generic mechanism for small +language extensions), but unlike pragmas they fit in ordinary grammar-based +based front end processing. The principal routines for attribute processing +are in ``attribute.c`` (and ``attribute.h``); the main data structures are in +``il_def.h``. + +Introduction to Pragma Processing +================================= + +Pragma processing differs from other front end processing in several ways. +Pragmas are scanned as part of the inter-token processing of the lexical +routines, yet the actual interpretation of the pragmas must be performed at a +suitable point in the syntactic and semantic processing of the front end. In +fact tokens may need to be scanned far in advance of when they are actually +used, and so pragmas may be encountered at the lexical level when it is +impossible for them to be fully processed. This occurs in scanning the bodies +of template definitions, in doing the lookahead to disambiguate declarations +and expressions, and so forth. + +Moreover, it is clear that the "suitable point in syntactic and semantic +processing" where the pragma is interpreted will be different for different +pragmas. And some pragmas simply carry information for use by the back end and +do not affect front-end processing at all. Each pragma has special +requirements. + +Pragmas are also unusual because, by definition, they are specific to a given +implementation. The mechanism that the EDG front end provides is intended to +make it relatively easy for customers to add pragmas and to customize how they +are processed, from how they are tokenized to how IL pragma entries are +generated. The handful of pragmas that are supplied by default with the EDG +front end can serve as prototypes for such customization. + +A pivotal role in pragma processing is played by an entry of type +``a_pending_pragma``, a front-end-only repository of information about a +specific ``#pragma`` directive in the source. It is "pending" in that it is +awaiting interpretation, after which it is disposed of. Interpreting a pragma +may mean setting a flag in a symbol, causing a diagnostic to be suppressed, +creating an IL pragma entry to pass information on to the back end, and so +forth. + +Pragma processing can be summarized as consisting of three steps: + +#. The ``#pragma`` directive that appears in the source code is identified and + recorded in a pending pragma entry. Although most pragmas are simply + recorded for later interpretation, "preprocessing immediate" pragmas are + dispatched immediately upon being recognized by the preprocessing + routines. + +#. The pending pragma entry is "dispatched" -- i.e., made available for + additional processing by being placed on a list where it can be found + later. + +#. The pending pragma entry is interpreted, with its message transferred to + another form (e.g., a flag is set somewhere), and then it is disposed + of. + +Pragmas must be recognized to be processed, and once they have been recognized +much of the processing is table-driven. The key pieces of information about +every pragma are: + +* | The pragma kind -- an element of the enumeration ``a_pragma_kind`` (defined + in ``il_def.h``). Every pragma that is recognized corresponds to one + pragma kind. +* | The pragma-id -- the identifier string that follows the ``#pragma`` keyword + and that may be looked up in the array ``pragma_ids`` (defined in + ``il_def.h``) to determine the pragma kind. +* | The pragma kind description -- a data structure of type + ``a_pragma_kind_description`` (defined in ``pragma.h`` and available to the + front end only) that summarizes the attributes and processing requirements + of a given pragma. + +When the pragma has been recognized, much of the processing is governed by the +corresponding pragma kind description, which contains information such as how +(and whether) the pragma binds to an IL construct, whether the pragma is +intended to be processed by the front end or back end, and how tokens that +comprise the pragma should be passed from the point at which the pragma is +initially scanned to the point at which the pragma is semantically processed. +The pragma kind description also contains an optional processing function +pointer, which, if present, points to a function to be called to process this +kind of pragma. + +``pragma_description_for_pragma_kind`` is an array of pointers to pragma kind +descriptions that may be indexed by pragma kind. It is initialized in +``pragma_init`` by a series of calls to ``add_pragma_kind_description``. + +Phase One: Recording Pragmas +============================ + +Pragma directives are initially scanned by the routine ``proc_pragma``, which +is one of the preprocessing routines in ``preproc.c``. As mentioned earlier, +the initial scanning of the pragma may occur far too early for the pragma to be +processed in any meaningful way. The most extreme example of this is a +template definition containing a pragma that must be reevaluated for each +instantiation generated from the template. + +To accommodate this kind of use, the initial scanning of a pragma typically +consists simply of identifying the kind of pragma being scanned, and recording +the body of the pragma in a form in which it may easily be processed later. +Preprocessing immediate pragmas are the exception to this rule, and are +dispatched immediately upon being identified by the preprocessing routines. + +Pragmas are expected to have the form + + ``#pragma identifier`` *token1 token2 token3 ...* + +The pragma kind is determined by comparing the identifier with each the +elements of the array ``pragma_ids``. Once the pragma kind has been +determined, the associated pragma kind description determines how the body of +the pragma is to be recorded. The body may be recorded as either a token cache +or a character string. Most pragmas will be recorded as token caches since +this is usually the easiest representation for the front end to use later. +Pragmas that are to be reemitted by the C or C++ generating back end must be +recorded as character strings. + +When a pragma is recorded as a token cache, the pragma kind description +specifies how the lexical routines should tokenize the pragma body. +Specifically, it specifies whether macros should be expanded and whether the +recognition of certain preprocessing tokens (e.g., ``#`` and ``##``) should be +disabled. Typically both of these flags would be FALSE, but when scanning a +pragma containing what looks like a source language construct (as is the case +with the instantiation pragmas) these fields would be TRUE. + +If the configuration parameter ``INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL`` is TRUE, +any pragma identifier that is not recognized is processed using the pragma kind +description associated with the ``pk_unrecognized`` pragma kind. + +To record the pragma a pending pragma entry is allocated (see +``alloc_pending_pragma`` in ``pragma.c``), and the pragma representation (token +cache or text) is attached to it. A pragma is associated with a token that +immediately follows it in the source, so the newly created pending pragma entry +is appended to ``curr_token_pragmas``, a list of pending pragma entries that +are associated with the current token (see ``add_to_curr_token_pragma_list``). + +Since the current token may be cached, the list of pending pragma entries +associated with it is cacheable, too (see ``add_pragma_entry_to_cache`` in +``lexical.c``). When a token is cached, the pragmas associated with it are +recorded in the cache as well, and when the token is retrieved from the cache +the associated pragmas are restored as the ``current_token_pragmas`` list. If +the cache from which the token was retrieved is a reusable cache, a copy of the +pragma list is made (instead of using the original list). + +Pending pragma entries are also created to represent "pseudo pragmas", +constructs that are processed by the front end like pragmas even though they +are not actually represented in the source code by a pragma directive. Thus, +lint comments are implemented as pseudo pragmas; e.g., when a ``/*ARGSUSED*/`` +comment is encountered, the front end generates a ``pk_lint_argsused`` pragma +entry, and all subsequent processing is handled just like a pragma specified +using a ``#pragma`` directive. + +Phase Two: Dispatching Pragmas +============================== + +The result of the initial scanning process is ``curr_token_pragmas``, a list of +pending pragma entries that represent the pragmas immediately preceding the +current token. However, the pragma is not subject to further processing simply +as a consequence of being associated with the current token. For example, with + +.. code:: c++ + + #pragma xyz + int a; + +the ``xyz`` pragma is on the current token pragma list for ``int`` but is not +made available for additional processing until processing begins on the +construct that ``int`` introduces or else until the next token, ``a``, is about +to fetched. This convention is followed to avoid processing the pending pragma +entry prematurely -- we wouldn't want to process pragma ``xyz`` if there is a +chance token ``int`` will end up in a token cache. + +The pending pragma entries on the ``curr_token_pragmas`` list are dispatched +for additional processing either by ``select_curr_construct_pragmas`` or by +``process_curr_token_pragmas``. These routines do most of the middle phase +processing of pending pragma entries. How they differ and how they interact +can be explained in terms of pragma binding kinds. + +Each pragma kind specifies one of three pragma binding kinds [#f1]_; each +binding kind represents a different processing pathway; and each form of +processing implies a different form of dispatching. + +* | Pending pragma entries with a binding kind of ``pbk_immediate`` and + ``pbk_next_token`` are processed immediately at the point the current token + is consumed. Such pragmas may appear anywhere in the program, and though + they may be recorded in the IL, they are not bound to any particular IL + entity (the difference between ``pbk_immediate`` and ``pbk_next_token`` is + described below). +* | Pending pragma entries with a binding kind of ``pbk_next_construct`` are + subject to processing during the processing of the given statement or + declaration. They must appear immediately before the first token of the + construct to which they will be bound. If they appear in the IL, they will + be bound to a particular IL entity. +* | Pending pragma entries with a binding kind of ``pbk_other`` are not subject + to processing at any particular time -- that is up to the implementation. + They may appear anywhere in the source program. They are dispatched onto a + list to wait for a processing function to check for them; if they are not + explicitly handled and removed, they simply remain there until the scope + they belong to is terminated. + +Bound Pragmas +------------- + +``select_curr_construct_pragmas`` is called at the start of each new +declaration or statement. It is always called before advancing past the first +token of the construct; this is to ensure that it is called before +``process_curr_token_pragmas`` is called. Its principal job is go through the +``curr_token_pragmas`` list, removing each ``pbk_next_construct`` entry and +dispatching it to a list specifically reserved for pragmas bound to the current +construct, the ``curr_construct_pragmas`` list in the current scope stack +entry. The pragmas wait on the list to be processed sometime during the +processing of the current construct. + +The pending pragma entries associated with the current construct will remain on +the list to which they are dispatched only for the life of the declaration or +statement. If the current construct cannot be bound to (this is the case, for +example, with the declaration of an unnamed enumeration or a ``break`` +statement), ``cannot_bind_to_curr_construct`` is called to issue diagnostics, +if appropriate, and clear the list. If, usually as a result of an error, the +processing of the pending pragma entries cannot be completed, +``discard_curr_construct_pragmas`` is called to clear the list. + +Normally, therefore, when ``select_curr_construct_pragmas`` is called, the list +it updates will have been cleared, since entries on the list for the previous +construct will already have been disposed of by the time the current construct +is dealt with. An exception is when a pragma precedes a label: such a pragma +is construed as applying not to the label but to the construct following, so it +must be preserved on the ``curr_construct_pragmas`` list as processing advances +past the label. In such situations pending pragma entries may accumulate, +e.g., for this case + +.. code:: c++ + + #pragma some_pragma + l: + #pragma another_pragma + f(); + +both pragmas can end up bound to the call of function ``f``. + +Another job of ``select_curr_construct_pragmas``, when source sequence entries +are being generated, is to add a source sequence entry for each pending pragma +entry on the ``curr_token_pragmas`` list. If an IL entry is subsequently +created for the pragma, it uses the source sequence entry; otherwise, the +source sequence entry is returned to an available list. + +Unbound Pragmas +--------------- + +``process_curr_token_pragmas`` is called each time the current token is about +to be consumed and a new token is about to become the current token. Its job +is to handle pending pragma entries that remain on the ``curr_token_pragmas`` +list and then to clear that list before the next token is taken. + +If it finds a ``pbk_immediate`` or ``pbk_next_token`` pragma on the list, it +initiates the completion of its processing. There is no dispatching of these +pragmas. They are processed immediately and automatically. In non-cached +contexts, ``pbk_immediate`` pragmas will have already been procesed when +``process_curr_token_pragmas`` is called and will be ignored. + +``pbk_other`` pragmas are dispatched to a list of the pragmas that are +currently available for further processing in a given scope -- see +``pending_pragmas`` in ``a_scope_stack_entry``. The pending pragma entry is +placed on the list of the current scope and is discarded when the current scope +terminates. Such a pragma simply waits on the list until some event removes it +to complete its processing; there is no default mechanism to trigger such +processing automatically. + +Since ``select_curr_construct_pragmas`` will already have been called, there +should not be any ``pbk_next_construct`` entries remaining on the +``curr_token_pragmas`` list. If there are, they must have appeared in the +source somewhere other than immediately before a declaration or statement. +``process_curr_token_pragmas`` removes them from the list, optionally issuing a +diagnostic of the severity specified in the corresponding pragma kind +description. + +If source sequence entries are being generated, ``process_curr_token_pragmas`` +will also add source sequence entries for each pending pragma entry that needs +one. If an IL entry is subsequently created for the pragma, it uses that +source sequence entry; otherwise, the source sequence entry is returned to an +available list. + +Phase Three: Interpreting Pragmas +================================= + +The pragma representations that result from the scanning of pragmas are called +"pending pragmas" because, having been created as repositories of uninterpreted +information about a specific pragma directive, they wait around for the right +moment for their processing to be completed. The completion can be described +as the "interpretation" of the pragma -- its translation into another form so +that it will have the intended effect on subsequent compilation. + +The different pragma binding kinds indicate, as noted above, different +processing pathways: + +* | Pending pragma entries with a binding kind of ``pbk_next_token`` are + processed automatically by ``process_curr_token_pragmas``, at the point the + current token is consumed. +* | Pending pragma entries with a binding kind of ``pbk_immediate`` are + processed immediately after they have been scanned. In cached contexts + they are also processed by ``process_curr_token_pragmas`` (in the same way + as ``pbk_next_token`` pragmas) each time the cache is rescanned. +* | Pending pragma entries with a binding kind of ``pbk_next_construct`` are + subject to processing during the processing of the given statement or + declaration. Either they are processed as the result of an explicit action + involving a call to ``extract_specific_pragmas``, or else the processing is + initiated automatically when (at an appropriate point, depending on the + construct they are associated with) ``process_curr_construct_pragmas`` is + called. +* | Pending pragma entries with a binding kind of ``pbk_other`` are subject to + processing only as the result of an explicit action involving a call to + ``extract_specific_pragmas``; otherwise they simply remain on the + ``pending_pragmas`` list of the current scope stack entry and their + processing is never completed. + +``process_curr_construct_pragmas`` is the routine that initiates automatic +processing for the ``pbk_next_construct`` pragmas associated with a given +declaration or statement. It traverses the list of them on the current scope +stack entry, making sure that each pragma binds to the sort of construct +(statement or declaration) that is currently being processed; it (optionally) +issues a diagnostic otherwise. If ``automatically_include_in_il`` (in the +corresponding pragma kind description) is TRUE, it calls +``create_il_entry_for_pragma``. If ``next_construct_processing_function`` is +non-NULL, it calls it do any additional processing that is required. It also +returns all the pending pragma entries to the available list. + +If a pragma should be included in the IL, ``create_il_entry_for_pragma`` is +called; it calls ``add_pragma_to_il``, which in turn calls ``alloc_pragma`` to +create the entry of type ``a_pragma`` and ``add_to_pragmas_list`` to add it to +the end of the ``pragmas`` list of the proper scope. + +``create_il_entry_for_pragma`` is called automatically -- by +``process_curr_token_pragmas`` for ``pbk_immediate`` pragmas and by +``process_curr_construct_pragmas`` for ``pbk_next_construct`` pragmas -- when +the ``automatically_include_in_il`` flag is set. It is also called +automatically by ``extract_specific_pragmas`` when that flag is set. It can be +called directly from pragma-processing code when automatic creation of IL +entries is undesirable. + +The scope to which the IL pragma entry is attached is determined based on +several considerations. If a ``pbk_next_construct`` pragma is bound to a class +member, it belongs to the scope of the class; otherwise, if it is bound to an +IL entry allocated in the file-scope memory region, it belongs to the file +scope; otherwise, it belongs to the current (block or function) scope. A +``pbk_immediate``, ``pbk_next_token``, or ``pbk_other`` pragma belongs to the +file scope if the ``global`` flag in the corresponding pragma kind description +is TRUE; otherwise it belongs to the current scope. + +``pbk_next_construct`` pragmas that are added to the IL have a pointer to the +IL entry with which they are associated (a statement, a variable, etc.), but +the latter has no pointer back to the pragma. Instead, the +``has_associated_pragma`` flag (in ``a_source_correspondence`` and in +``a_statement``) is set, indicating that one or more pragmas is bound to it. +``find_assoc_pragma`` may be called to locate the pragma entry (or entries) +associated with a given IL entry. + +The automatic processing of pending pragma entries may also involve calling a +routine to do whatever special processing is required for the particular pragma +kind. The address of this routine, which must be declared with the appropriate +type (see ``a_next_construct_pragma_function``, +``an_immediate_pragma_function``, and ``an_other_pragma_function``) is recorded +in the pragma kind description. Here are some examples from pragmas supplied +by default by the EDG front end: + +* | ``instantiate_pragma`` is specified as the processing function for the + ``pbk_next_token`` pragma of kind ``pk_instantiate``; it is called by + ``process_curr_token_pragmas`` when such pending pragma entries are + encountered; no IL entry is required. +* | ``record_arg_pragma`` is the processing function for pragmas of kind + ``pk_printf_args`` and ``pk_scanf_args``; it is called from + ``process_curr_construct_pragmas``. Note that a symbol pointer is included + in the interface of the processing functions for ``pbk_next_construct`` + pragmas, and so ``record_arg_pragma`` is able to record the event for the + current routine. + +The timing of the call to ``process_curr_construct_pragmas`` and therefore to +the corresponding processing function may be critical. The rules, in general, +are: + +* | for declarations, ``process_curr_construct_pragma`` is called at the point + the symbol is bound to its corresponding IL entry; +* | for statements, it is called immediately after the statement entry is + created (but before other processing is done). + +For reasons of timing and other considerations it is sometimes inappropriate to +use the automatic mechanisms that are provided. An alternative is to call +``extract_specific_pragmas``, which returns a pending pragma entry of a given +pragma kind, [#f2]_ and to do the required processing directly. For an example +of this style of pragma use see ``record_lint_argsused_and_varargs_state``, +which is called *only* when a function is being defined: if +``extract_specific_pragmas`` returns a pending pragma entry of the specified +kind, it sets a flag in the routine type supplement and, since the entry will +have been removed from the current construct pragma list, calls +``free_pending_pragma_list`` to dispose of it. + +``extract_specific_pragmas`` is also called for ``pbk_other`` pragmas. In +fact, it is essential for completing the processing of such pragmas and should +be included in custom code to implement a specific pragma. Once this routine +has been called for a given pragma kind, the pending pragma entry returned is +no longer on the ``pending_pragmas`` list, so it cannot be found a second time. +Note also that the calling routine is responsible for freeing the pending +pragma entry. + +How to Add A New Pragma +======================= + +The mechanisms provided to support ``#pragma`` directives have been designed +with extensibility in mind. This section is intended to provide some +additional guidance in adding new pragma kinds. In general, this is what you +will need to do to: + +* | Add a new entry to the enumeration ``a_pragma_kind`` in ``il_def.h``, and + add an identifier string to the array ``pragma_ids``. +* | Decide on the binding kind for the pragma. + + * | ``pbk_immediate`` is appropriate when the pragma's effect is quite + independent of the context in which it appears in the source. It is + processed unconditionally immediately after the pragma is scanned. If + the pragma appears in a cached context, the pragma is also processed each + time the cache is rescanned. + * | ``pbk_next_token`` is similar to ``pbk_immediate`` except that the pragma + is not processed until the next regular (non-preprocessing) token is + fetched and if the pragma appears in a cached context it is not processed + when it is first encountered but only each time the cache is rescanned. + * | ``pbk_next_construct`` is appropriate when the pragma is meant to affect + the construct that immediately follows it in the source. Set one or both + of ``may_bind_to_decl`` or ``may_bind_to_statement`` depending on what + sort of construct it applies to. These pragmas are discarded (optionally + with a diagnostic) if they appear in front of the wrong kind of + construct. + * | ``pbk_other`` is appropriate for maximum flexibility, though it requires + additional intervention by you, since the automated mechanisms are not + available. + * | ``pbk_preproc_immediate`` is appropriate when the pragma must be + processed when encountered by the preprocessing routines and cannot be + deferred until the next nonpreprocessing token of the program is scanned. + No pending pragma entry is created for these pragmas and they cannot be + entered into the IL. +* | Create the pragma kind description by adding a call to + ``add_pragma_kind_description`` in ``pragma_init``; the call should be made + using the interface function that is specific to the binding kind. +* | If you want to store information -- say, the value of a pragma argument + that will be used when the pragma is processed -- you can add one or more + variant fields to ``a_pending_pragma``. The switch statement in + ``alloc_pending_pragma`` (where the variant field, if any, is initialized) + should be updated to recognize the new pragma kind. +* | If the pragma is to be entered in the IL and additional information is + needed in the IL entry, you should add variant fields to ``a_pragma`` + (defined in ``il_def.h``) and initialize them in ``alloc_pragma`` (in + ``il_alloc.c``). +* | If the pragma is to be entered in the IL automatically, set + ``automatically_include_in_il`` when creating the pragma kind description + entry. +* | If the pragma binding kind is ``pbk_immediate``, pbk_next_token, or + ``pbk_next_construct``, decide whether you want a processing function to be + called automatically. If so, be sure to include a pointer to it when + creating the pragma kind description entry. + | + | Even if you have specified a processing function, be sure that + ``automatically_include_in_il`` is FALSE if you want control over whether + the IL pragma entry should be created; if you do this, you can call + ``create_il_entry_for_pragma``. If ``automatically_include_in_il`` is + TRUE, the IL pragma entry will already have been created before your + routine is called, but you will still be able to set any variant fields + that are specific to this pragma kind. +* | If the pragma binding kind is ``pbk_other`` -- or if it is + ``pbk_next_construct`` but you don't want to use the automatic facility of + ``process_curr_construct_pragma`` -- you will have to write code to call + ``extract_specific_pragmas`` and to do the required processing. Note that, + if ``automatically_include_in_il`` is set to TRUE, + ``extract_specific_pragmas`` will cause an IL pragma entry to be created; + if you want more control, be sure the flag is FALSE when you create the + pragma kind description entry. +* | If your code uses ``extract_specific_pragmas``, be sure to call + ``free_pending_pragma_list`` to dispose of the pending pragma entry (or + entries) returned to you. +* | If your pragma processing function needs to deal with more than the pragma + identifier, decide whether your code requires the pragma to be represented + as a text string or as a token cache. If the former, set + ``record_pragma_text`` to TRUE when you create the pragma kind description + entry. However, if you choose to deal with tokens, the following + convention should be observed: + + #. Call ``begin_rescan_of_pragma_tokens`` to find the appropriate token + cache for rescanning the tokens that comprise the pragma body; it also + pushes a ``sck_pragma`` scope. The first token you will see is the one + following the pragma identifier. + + #. When you have finished scanning the tokens, call + ``wrapup_rescan_of_pragma_tokens`` to pop the ``sck_pragma`` scope and + check that all of the tokens were scanned from the cache; if the current + token is not the ``tok_end_of_source`` at the end of the pragma + directive, an "extra text in preprocessing directive" error will be + issued. + +* | You should set ``expand_macros`` to FALSE if you want to suppress macro + expansion while the pragma tokens are scanned. Furthermore, setting + ``processing_C_code`` when generating a token cache means keywords will be + recognized and adjacent string literals will be concatenated together. +* | If you are simply passing the pragma on to the back end without processing + it in the front end, be sure that ``make_text_not_tokens`` is TRUE when you + create the pragma kind description entry -- a pragma cannot be passed to + the back end in the form of a token cache. +* | If you want a diagnostic issued when a ``pbk_next_construct`` pragma + appears in the wrong place in the source program or an unprocessed + ``pbk_other`` pragma is encountered when a scope is popped, set the + ``error_severity`` appropriately when you create the pragma kind + description entry; use ``es_none`` to suppress the diagnostic. + +Introduction to Attributes +========================== + +Unlike pragmas, attributes are parsed like other ordinary language features. +This parsing is usually achieved with a call to ``scan_attributes``, which +returns a list of attributes (``an_attribute`` entries) in the order that they +were encountered. Each attribute entry represent a standard attribute, a GNU +attribute, or a Microsoft ``__declspec`` attribute [#f3]_: The specific variant +is recorded in the ``family`` field (which can be ``af_std``, ``af_gnu``, or +``af_ms_declspec``). Whether a specific attribute family syntax is accepted is +determined by the global variables ``std_attributes_enabled``, +``gnu_attributes_enabled``, and ``ms_declspec_attributes_enabled``. The +parsing process also classifies attributes according to their kind +(``ak_align``, ``ak_nothrow``, etc.) and their syntactic location +(``al_prefix``, ``al_declarator_id``, etc.). As with pragmas, the front end +accepts attributes that it doesn't recognize (these are assigned attribute kind +``ak_unrecognized``). + +Attributes appear in "groups". For example: + +.. code:: c++ + + __attribute((align(4))) __attribute((pure,nothrow)) void f(); + +The ``an_attribute`` entry corresponding to the ``align`` attribute will point +to a first entry of type ``an_attribute_group``, whereas the ``an_attribute`` +entries for ``pure`` and ``nothrow`` will both point to a second +``an_attribute_group`` entry. Attribute groups can be empty (typically as the +result of macro expansion). To represent empty groups, an ``ak_empty`` +attribute is created (which then points to an ordinary entry of type +``an_attribute_group``). Attribute group entries do not carry information of +their own other than the position of delimiting tokens: Their principal +function is to indicate how attributes were grouped in the source code. The +"upside-down" arrangement of attributes vs. groups keeps all the attributes +associated with a given entity on a "flat" list, which simplifies traversing +them (the alternative would consist in having to traverse groups and within +each group traversing a list of attributes). + +After attributes have been parsed, they are "attached" and "applied" to an +appropriate IL entity. This is usually done by calling ``attach_attributes``. + +Attaching an attribute means recording its entry in the IL by placing it on a +list pointed to by the IL entry of the entity to which the attribute applies. +Usually, the list is pointed to by the ``attributes`` field in +``a_source_correspondence``. Unrecognized attributes are recorded in the IL +only when the global variable ``record_unrecognized_attributes`` (initialized +with the configuration macro ``RECORD_UNRECOGNIZED_ATTRIBUTES``) is TRUE. If +unrecognized attributes are not recorded in the IL, they elicit a warning. + +Applying an attribute means that the validity of the attribute for its target +entity is checked (e.g., it is an error for a standard ``[[nothrow]]`` +attribute to be applied to a variable) and, possibly, that the IL entry for the +target entity is updated (e.g., the ``noreturn`` attribute causes the +``does_not_return`` flag in the corresponding routine type supplement to be set +to TRUE). Applying an unrecognized or an empty attribute has no effect. + +When simultaneously compiling multiple translation units, the attributes +attached to corresponding declarations are checked. By default, attributes +must match exactly, but alternative policies are possible for specific +attributes and contexts. + +The parsing/classification of attributes, their application to IL entities, and +the checking of corresponding attributes across translation units (when +applicable) is at least in part table-driven. + +Parsing Attributes +================== + +As mentioned above, attributes are usually parsed by calling +``scan_attributes``. However, if only GNU attributes should be considered, +``scan_gnu_attribute_groups`` is called instead. Both functions take an +argument of type ``an_attribute_location``, which specifies the syntactic +context in which the call is made. For example, in the declaration + +.. code:: c++ + + [[nothrow]] int __attribute((pure)) + f [[final]] () __attribute((deprecated)); + +the ``nothrow`` attribute is parsed as ``al_prefix``, the ``pure`` attribute is +parsed as ``al_specifier``, the ``final`` attribute is parsed as +``al_declarator_id``, and the ``deprecated`` attribute is parsed as +``al_post_func``. (I.e., the front end contains calls to ``scan_attributes`` +or ``scan_gnu_attribute_groups`` in various places, each call passing an +argument reflecting the current parsing context.) + +In the case of standard attributes, strict *appertaining rules* allow the +syntactic context to unambiguously determine what entity the attribute applies +to. For example, standard ``al_prefix`` attributes apply to the variables, +functions, or typedefs being declared, while standard ``al_specifier`` +attributes apply to the type specified by the declaration specifiers. + +In contrast, the syntactic location of GNU attributes does not unambiguously +determine the entity they apply to; instead, the affected entity depends on the +attribute kind. For example, in + +.. code:: c++ + + __attribute((align(16))) int f1(); + __attribute((vector_size(16))) int f2(); + +the ``align`` attribute modifies function ``f1``, but the ``vector_size`` +attribute modifies type ``int``. To deal with this, the front end reclassifies +some GNU attributes after they are parsed based on whether the attribute +transforms a type or not. This ensures that the attribute is applied to the +correct entity. For example, the ``vector_size`` attribute in the example +above is parsed as ``al_prefix``, but then reclassified as ``al_specifier`` +(this is done in ``attach_specifier_attributes``). A related example is + +.. code:: c++ + + void f3() __attribute((warn_unused_result)); + void f4() __attribute((pure)); + +These attributes are originally parsed with context ``al_post_func`` +(indicating they appear after a function declarator), which for a C++11 +attribute would imply that the attribute applies to the associated function +type. However, GNU attributes in this syntactic context can apply to the +function type (e.g., ``warn_unused_result``) or to the function itself (e.g., +``pure``). In cases like these, the attributes are reclassified to +``al_postfix`` (in ``scan_declarator_attributes``) and the attribute +application function modifies the function or its type depending on the +attribute (and the same process applies to attributes after array declarators). + +Microsoft ``__declspec`` attributes also lack strict appertaining rules, but +their treatment is simpler because there are no type-transforming +``__declspec`` attributes and ``__declspec`` attributes can appear in fewer +syntactic locations (only ``al_prefix``, ``al_specifier``, and ``al_tag_name`` +contexts are valid, and the former two are usually equivalent). There are some +special cases, however. For example, the ``align`` attribute in + +.. code:: c++ + + __declspec(align(16)) struct S { ... } x; + +is equivalent to + +.. code:: c++ + + struct __declspec(align(16)) S { ... } x; + +and the front end handles this by recording the ``align`` attribute as an +``al_tag_name`` attribute in such cases. + +Unscanning Attributes +--------------------- + +Sometimes, it is not clear at the time of parsing the attribute which context +the attributes will end up in. E.g., GNU attributes can appear after the left +parenthesis introducing function parameters and after the left parenthesis +introducing a nested declarator (see ``r_declarator`` in ``declarator.c``). In +such circumstances, the attributes can be scanned (by calling +``scan_attributes``) with an assumed context, then "unscanned" (with +``unscan_attributes``), and then "rescanned" by calling ``scan_attributes`` +with the correct syntactic location. Note that the call to +``unscan_attributes`` does not restore the tokens that made up the attributes; +it just stores the given attribute entries to be returned by the next call to +``scan_attributes``. + +Recognizing Attributes +====================== + +For an attribute to be recognized in the front end, it must have a description +in the array ``known_attr_table`` defined in ``attribute.c``. The description +(type ``an_attr_descr``) contains four fields: + +* | A string with the source form of the attribute name (e.g., "``section``"). + The optional leading and trailing underscores in the case of GNU attributes + should not be included in this string. +* | A string encoding what kind of arguments (if any) the attribute takes. + This the "signature" of the attribute. The details of this encoding are + described in the definition of ``an_attr_descr`` in ``attribute.c``. For + example, the code ``"(sn+)"`` would indicate that an argument list is + required and that it should contain one or more (narrow) string literals. +* | A string encoding the general conditions (primarily, the mode) in which an + attribute should be accepted, and, in the case of standard attributes, the + attribute namespace for the attribute. This encoding too is described in + the definition of ``an_attr_descr`` in ``attribute.c``. For example, + ``"g+(-39999)"`` indicates that the attribute should be accepted as a GNU + attribute in GNU C++ modes with ``gnu_version`` less than 40000, while + ``"c+[EDG]"`` specifies that the attribute should be accepted with standard + syntax and namespace-prefix ``EDG::`` in modes that accept standard C++11 + attribute syntax. +* | The attribute kind (e.g., ``ak_section``) that should be assigned to the + attribute. + +Note that there can be multiple entries for the same attribute kind. For +example, the ``nothrow`` attribute is accepted as a GNU attribute, as a +Microsoft ``__declspec`` attribute, and as a standard attribute, and therefore +(at the time of this writing) it has three description entries as follows: + +.. code:: c++ + + ... + { "nothrow", "", "1c+", ak_nothrow }, + ... + { "nothrow", "", "gx", ak_nothrow }, + ... + { "nothrow", "", "m+", ak_nothrow }, + ... + +(the prefix "``1``" in ``"1c+"`` indicates that the attribute cannot be +repeated in an attribute group). + +If an attribute name is recognized, but it does not meet other constraints, a +diagnostic is issued and the attribute is reclassified as ``ak_unrecognized`` +(by calling the macro ``make_attr_unrecognized``). This recovery technique is +used throughout attribute processing: Rather than dropping an attribute +altogether, it is generally just reclassified by calling +``make_attr_unrecognized``. + +Applying Attributes +=================== + +The application of attributes is highly dependent on the specific attribute +being applied, but some of the processing is also table-driven. Specifically, +the array ``known_attr_appl_table`` contains an entry of type +``an_attr_appl_descr`` for every attribute kind. Each entry contains the +following fields: + +* | The attribute kind, included only for readability and consistency checking + (the array contents must match the enumeration ``an_attribute_kind``). +* | A string encoding which entity kinds an attribute applies to, and, + optionally, simple constraints for matching entities. The details of the + encoding are described in the definition of ``an_attr_appl_descr`` in + ``attribute.c``. For example, ``"r|v"`` means the attribute applies to + routines and variables only, while ``"r|v:-a"`` means the same thing, but + requires the variable not to have automatic storage duration. (A failure + to meet these constraints causes the attribute to be reclassified as + ``ak_unrecognized``.) +* | A pointer to a callback function (of type ``an_attr_application_fn``). If + this pointer is non-NULL and if the constraints in the previous field are + fullfilled, the indicated function is called with the attribute and the IL + entry it applies to (the "target entity") passed in as arguments. The + callback function can check additional constraints on the target entity and + update the entry (and any other structures) as appropriate. + +A few Microsoft ``__declspec`` attributes require special handling in the front +end. For example, the presence of a ``property(...)`` attribute is detected +soon after being scanned because it affects certain semantic checks performed +by the front end before the complete declaration has been parsed (and, +therefore, before the application callback function can be called). + +Type-Transforming Attributes +---------------------------- + +Most attributes only modify relatively minor properties of the entities to +which they apply, and this modification is to the entity itself. For example, +the standard attribute ``[[final]]`` when applied to a class type ``X`` +prevents other classes from deriving from ``X``; it does not create a new IL +entry. Some GNU attributes, however, can transform a type into a new type +requiring a distinct IL entry [#f4]_. For example, the GNU attribute in: + +.. code:: c++ + + float __attribute((vector_size(16))) vec; + +transforms type ``float`` to a type "vector of ``float``". Such +type-transforming attributes are applied (and attached) using function +``attach_type_attributes``. It uses the array ``known_attr_appl_table`` much +like ``attach_attributes``, but instead of making the resulting type entry +point directly to the attributes list, it adds a ``tk_typeref`` entry on top of +the resulting type for that purpose. + +Because of the possibility of entity transformation, the callback functions +recorded in ``known_attr_appl_table`` must return an IL entry pointer that +represents the entity resulting from the application of the attribute to a +given entity. Except for type-transforming attributes, the returned IL entry +is the same entry as the one passed to the callback function. + +Attributes in Back Ends +======================= + +Most known attributes have an effect on IL fields that provides sufficient +information to a traditional code-generating back end. For example, the +``nothrow`` attribute causes the ``never_throws`` flag in ``a_routine`` to be +set to TRUE. However, since attribute entries are also pointed to by affected +entities, it is not strictly necessary to add separate fields to IL entries. A +specific attribute can be found using the function ``find_attribute``. For +example, the standard attribute ``carries_dependency`` is currently only +represented by its ``an_attribute`` entry. + +The C-generating back end ignores most ``an_attribute`` entries. Instead, it +usually renders GNU attributes (when the target compiler is known to be a +version of GCC) based on other fields in the IL. However, for some attributes +that are only represented in the IL through their ``an_attribute`` entry, the +C-generating back end may emit a GNU attribute construct based on the presence +of the corresponding entry. + +The C++-generating back end, on the other hand, renders attributes based *only* +on applicable ``an_attribute`` entries. To ensure that the rendered code is +close to the original form, attributes specified on a secondary declaration are +recorded twice in the IL (i.e., the entries are duplicated): Once on the list +pointed to by the source correspondence of the target entity, and once on a +list pointed by the associated ``a_src_seq_secondary_decl``. Attributes on +primary declarations are recorded only once, but are marked as having appeared +on the primary declaration (flag ``on_primary_declaration`` in +``an_attribute``). + +How to Add a New Attribute +========================== + +The framework described above make the addition of many common kinds of +attributes relatively simple: + +* | Add an ``ak_``... attribute kind in ``il_def.h``. +* | Add one or more entries to the ``known_attr_table`` in ``attribute.c``. +* | Add an entry in the ``known_attr_appl_table`` in ``attribute.c``. +* | Write the callback function specified in the new ``known_attr_appl_table`` + entry (if such a callback is needed at all). +* | If the attribute is not required to match exactly across translation units, + add one or more entries describing the correspondence handling to the + ``attr_corresp_table`` defined in ``attribute.c``. (In some cases this may + involve adding additional functions or updating the code in + ``trans_corresp.c``.) + +(The attribute may require new IL entry fields or even new IL entry kinds. If +so, see :ref:`il-extension-guide`.) + +If attributes must be recognized in contexts that do not currently allow them, +additional calls to ``scan_attributes`` and ``attach_attributes`` must be added +to the front end (and, most likely, additional enumeration constants for +``an_attribute_location``). If the C++-generating back end is used, it will +also require a matching call to ``gen_attributes``. + +.. [#f1] Pragmas of a fourth kind, ``pbk_preproc_immediate``, are dispatched + when scanned by the preprocessing routines. A pending pragma entry is + never created. +.. [#f2] Actually, it returns a list, though this would seldom be significant. +.. [#f3] Microsoft attributes delimited by single brackets are not handled by + this mechanism (see :ref:`ms-attributes`). +.. [#f4] Currently, this is limited to the GNU attributes ``vector_size`` and + ``mode``. diff --git a/doc/_sources/runtime.rst.txt b/doc/_sources/runtime.rst.txt new file mode 100644 index 0000000..e4273db --- /dev/null +++ b/doc/_sources/runtime.rst.txt @@ -0,0 +1,141 @@ +=============== +Runtime Library +=============== + + + + +The runtime library routines provide basic runtime support. The source for +these routines is in the ``lib_src`` directory of the release structure. + +"Basic" runtime support means support for operations built in to the C++ +language, like ``new`` and ``delete``, and for operations for which code is +generated by IL lowering, e.g., array initialization. (This includes code +generated by the lowering of C99 constructs.) It does not mean support for all +libraries required by the C++ standard, e.g., ``iostream``\ s. + +The front end supports two different runtime models. A configuration macro is +used to select the runtime model to be used. The models supported are the +IA-64 ABI and one that is an extension of the one used with *cfront*. + +The IA-64 model is a complete implementation of the IA-64 ABI, except that the +exception handling implementation does not conform to the ABI (because +producing a conforming implementation of exception handling requires back end +support). + +The *cfront* runtime model is generally compatible with the one used by +*cfront* version 3.0.2, and in fact the code generated by the front end in +*cfront* object code compatibility mode will work with the libraries +supplied with *cfront* (with one exception that is described below). +Another way of saying the same thing: The runtime library is an independent +implementation of the runtime interface defined by *cfront*. + +One incompatibility between our runtime support library and the one provided +with *cfront* is the handling of static destructors. The *cfront* static +destruction mechanism does not conform to the C++ standard, which requires all +static objects, including local static objects, to be destroyed in the reverse +order of construction. The EDG static destruction mechanism relies on a new +data structure called the needed destructions list. If a *cfront* runtime +library is to be used, the ``dtor_list.o`` file from the EDG library must be +included when a program is linked. This may be done by explicitly including +``dtor_list.o`` in the link command generated by the driver, or by adding +``dtor_list.o`` to the library file containing the *cfront* libraries. + +In the area of exception handling, there is no standard *cfront* runtime +model (because no version of *cfront* that supports exception handling was +released by USL), so the model is invented by EDG, drawing on some +published aspects of the implementation done by Hewlett-Packard. + +The runtime routines should be considered to be a sample implementation of a +runtime library. They are believed to be complete and to work correctly, but +they might require adaptation to make them work correctly in a given +environment, or to make them compatible with other runtime libraries or +conventions on the target system. In particular, if runtime compatibility with +*cfront* is not required, there are probably better ways of doing some of these +things. Also, the target system may provide efficient support for things that +can only be done in a clumsy way in a portable runtime library, e.g., getting +start-up initialization code run automatically at the beginning of execution. + +The ``--building_runtime`` option +================================= + +Like the front end, the runtime contains a number of configuration flags. In +many cases, it is essential that the same values be used by both the front end +and the runtime with which the generated code will be linked. To help make +sure the runtime is configured properly the ``--building_runtime`` option +should be specified when compiling the runtime. This causes additional +preprocessing macros to be defined that pass the value of certain configuration +flags from the front end to the runtime. The following preprocessing macros +are defined when the ``--building_runtime`` option is used: + +.. list-table:: + + * - | ``__EDG_JMP_BUF_ELEMENT_TYPE`` + | + - | The name of the integer or floating point type that is used as the + element type of the ``jmp_buf`` array used by ``setjmp``. + * - | ``__EDG_JMP_BUF_NUM_ELEMENTS`` + | + - | The number of elements in the ``jmp_buf`` array used by ``setjmp``. + * - | ``__EDG_DELTA_TYPE`` + - | The name of the integer type that is used to represent the offset in a + virtual function table entry. + * - | ``__EDG_VIRTUAL_FUNCTION_INDEX_TYPE`` + | + - | The name of the integer type that is used to represent the index field + in a virtual function table entry. + * - | ``__EDG_VAR_HANDLE_TYPE`` + | + - | The name of the integer type that is used to represent a "handle" in + exception handling tables. Defined only when ``GENERATE_EH_TABLES`` + is TRUE. + * - | ``__EDG_REGION_NUMBER_TYPE`` + | + - | The type of a region number field in the exception handling tables. + Defined only when ``GENERATE_EH_TABLES`` is TRUE. + * - | ``__EDG_ETS_FLAG_TYPE`` + | + - | The type used to pass exception types flags to the runtime library. + Defined only when ``GENERATE_EH_TABLES`` is TRUE. + * - | ``__EDG_NULL_EH_REGION_NUMBER`` + | + - | The value used as the null region number value in the exception + handling tables. Defined only when ``GENERATE_EH_TABLES`` is TRUE. + * - | ``__EDG_LOWER_VARIABLE_LENGTH_ARRAYS`` + | + - | Indicates whether or not the front end is configured to lower + variable-length arrays. Set to the value of ``(VLA_ALLOWED && + LOWER_VARIABLE_LENGTH_ARRAYS)`` in the front end. + * - | ``__EDG_IA64_ABI_USE_VARIANT_ARRAY_COOKIES`` + | + - | Non-zero when the variant representation of array cookies is used in + the IA-64 ABI. Defined only when ``IA64_ABI`` is TRUE. + * - | ``__EDG_ELEM_COUNT_PARAM_TYPE`` + | + - | The type used to represent the ``number_of_elements`` argument in the + Cfront-like ABI. Defined only when ``IA64_ABI`` is FALSE. + * - | ``__EDG_ABI_COMPATIBILITY_VERSION`` + | + - | The value of ``ABI_COMPATIBILITY_VERSION`` used when the front end was + built. + * - | ``__EDG_ABI_CHANGES_FOR_RTTI`` + | + - | The value of ``ABI_CHANGES_FOR_RTTI`` used when the front end was + built. + * - | ``__EDG_ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE`` + | + - | The value of ``ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE`` used when the + front end was built. + * - | ``__EDG_ABI_CHANGES_FOR_PLACEMENT_DELETE`` + | + - | The value of ``ABI_CHANGES_FOR_PLACEMENT_DELETE`` used when the front + end was built. + * - | ``__EDG_BSD`` + - | The value of the ``__BSD__`` macro when the front end was built. + * - | ``__EDG_SYSV`` + - | The value of the ``__SYSV__`` macro when the front end was built. + * - | ``__EDG_ANSIC`` + - | The value of the\ ``__ANSIC__`` macro when the front end was built. + * - | ``__EDG_CPP11_IL_EXTENSIONS_SUPPORTED`` + - | The value of ``CPP11_IL_EXTENSIONS_SUPPORTED`` when the front end was + built. diff --git a/doc/_sources/statements.rst.txt b/doc/_sources/statements.rst.txt new file mode 100644 index 0000000..0c811db --- /dev/null +++ b/doc/_sources/statements.rst.txt @@ -0,0 +1,259 @@ +================== +Statement Scanning +================== + +``statements.c`` contains the code to scan statements, and ``statements.h`` +contains the associated declarations. + +The top-level routine here is ``compound_statement``, which scans a +brace-enclosed list of statements. This is used for the bodies of functions +and for blocks (with and without local declarations) that appear within +functions. In C mode, it first calls ``opt_declaration_list`` to scan the +optional list of declarations; then, in C or C++ mode, it calls ``statement`` +(in a loop) to scan the statements. + +``statement`` scans one statement, with an optional preceding label or labels. +Its job is mostly to call the appropriate statement-scanning routine based on +the first token of the statement. For most statements, the first token is a +keyword that identifies the statement. Otherwise, the statement is an +expression statement (in C or C++) or a declaration (in C++ only; +``is_decl_not_expr`` is called to decide whether the construct is an expression +or a declaration). + +A stack of active statements is maintained in ``struct_stmt_stack``. For each +active statement, it contains the kind of statement and some information about +what has been scanned so far in the statement. ``push_stmt_stack`` and +``pop_stmt_stack`` manage the stack. ``find_enclosing_struct_stmt`` can be +used to find the nearest enclosing structured statement of a given type; this +is used in finding the construct associated with a ``break`` or ``continue``. + +One important function of the statement stack is that it points to the +intermediate language for the associated statement. The top-most entry +contains enough information to enable one to find the "current" location in the +intermediate language being generated, the point at which one would like to add +a statement. This is, in fact, exactly what ``add_statement_list`` does: it +links the given list of statements (possibly just a single statement) into the +growing tree of statements for the function. Usually, this is called through\ +``add_statement_at_stmt_pos`` , which allocates a statement of a given kind and +also maintains the ``code_reachable`` flag, indicating whether or not the +current location in the code is reachable. This flag is used to check for +unreachable code and issue appropriate warnings. Code is attached to the +statement tree even if it is unreachable. As statements are pushed onto and +popped off the stack, the ``code_reachable`` flag is maintained accordingly, +based on whether or not the beginning of the statement can be reached, whether +the end can be reached from the beginning, and whether the end can be reached +from the inside. The ``lint_notreached_flag`` is also consulted. For +statements that have several clauses (``if`` and ``switch``) +``start_stmt_clause`` and ``term_stmt_clause`` are called at the appropriate +locations in processing to keep the ``code_reachable`` flag up to date. + +The statement stack contains pointers to ``break`` and ``continue`` labels for +the statement. These are initialized to ``NULL``, and later made to point to a +label if a ``goto`` is actually generated for a ``break`` or ``continue``. At +``pop_stmt_stack`` time, the definition for the ``break`` label is generated if +one is needed. The statement scanning routine must handle the ``continue`` +label is there is one. + +If a statement is labeled with a simple label, ``statement`` calls +``scan_label`` to look up or enter the label, then ``define_label`` to add a +label definition statement to the intermediate language. + +Nothing tricky is involved in statement processing routines ``if_statement``, +``while_statement``, ``do_statement``, ``goto_statement``, ``break_statement``, +and ``continue_statement``. ``asm_statement`` is called for asm statements; it +in turn calls ``asm_declaration``. + +``dependent_statement`` is called to scan statements that are dependent +statements of ``if``, ``switch``, ``while``, ``do while``, and ``for`` +statements. In C mode, it just scans a statement. In C++ mode, it creates a +block statement and places the dependent statement under it, unless the +dependent statement is a block statement. That ensures that if anything is +declared in the dependent statement, its scope will be limited to the dependent +statement (this is a post-ARM C++ language rule). + +``for_statement`` scans a ``for`` or range-based ``for`` statement (or, in UPC +mode, a ``upc_forall`` statement). Since it is unknown at the beginning of +scanning whether a ``for`` or range-based ``for`` statement is being scanned, +two block scopes (used to contain the range-based ``for`` temporary variables) +are pushed in preparation for the range-based ``for`` case (they're discarded +if scanning reveals a ``for`` statement). The first entity inside the +parentheses (initialization) is scanned by calling ``for_init_statement``, +which allows an expression (in C or C++), a declaration (in C++ only), or a +``for-range-declaration`` (in C++11). ``for_init_statement`` also determines +(through a call to ``decl_statement_full``) which type of statement is being +scanned. If the ``for-init`` is a declaration (and a ``for`` statement is +being scanned), ``start_for_init_block`` is called to push an ``sck_block`` +scope (with ``is_for_init_block`` set to TRUE) onto the scope stack, where +it remains till after the dependent statement of the loop is scanned (see +``finish_for_init_block``). If the second expression (test) is present, it is +scanned by calling ``can_boolean_controlling_expression``. The third +expression (increment) is scanned by calling ``scan_void_expression``. For any +of those expressions/statements that is omitted, a ``NULL`` pointer is used in +the ``stmk_for`` statement. In the range-based ``for`` case, the statement +kind is set to ``stmk_range_based_for`` (this is somewhat unusual since the +statement kind is typically known earlier) and +``scan_range_based_for_expression`` is called to scan the range expression. +Semantic checks, determination of the type of range-based ``for`` (see header +comments), and IL generation are handled by +``check_range_based_for_statement``. + +The Microsoft for-each statement (available in C++/CLI emulation mode, as well +as when ``microsoft_version`` >= 1400) is scanned by ``for_each_statement``. +If the for-each statement contains a previously declared iterator variable, it +is scanned by ``scan_previously_decl_iterator_name``, otherwise the iterator +declaration is scanned by ``for_each_iterator_declaration``. Two block scopes +are pushed (an outer block scope for the loop temporary variables, and an inner +scope for the iterator variable). The collection expression is scanned by +``scan_for_each_expression`` and semantic checks (and IL generated) by +``check_for_each_statement``. ``check_for_each_statement`` handles the various +types of for-each statements (see the header comment for details). Much of the +underlying code is shared with the range-based ``for`` statement. + +``return_statement`` scans the ``return`` statement. It examines the type of +the current function. A ``void`` function should have ``return``\ s that +return no value; other functions should return a value. +``check_void_return_okay`` checks whether or not a value-less ``return`` is +okay in the current function. It is also used at the final closing brace of +the function if that position is reachable (since there is an implicit +``return`` there). + +``switch`` statements cause the most problems. ``switch_statement`` itself is +not too complicated: it just pushes an entry on the statement stack, scans the +selector expression, and scans the dependent statement. The complex processing +comes with ``case_label`` (which also handles the GNU extension of case ranges; +e.g., "``case 1 ... 3:``") and ``default_label``, or more precisely, with the +subroutine those two cases call, ``add_switch_clause``. That routine +determines whether or not the label can be added to the list of labels for the +currently-active clause, or whether instead a new clause must be begun. It +also determines where the case value (or the default) belongs in the list of +constants for the clause. The configuration macro +``RECORD_SWITCH_CASE_ENTRIES`` determines how individual case labels are +represented. When TRUE (the default), all the labels (including the default +case and any GNU case ranges) are represented using type +``a_switch_case_entry``. When FALSE (an option maintained primarily for +backward compatibility purposes), the labels within a clause are usually +represented as a list of ``a_constant`` entries, but in a clause labeled with +``default``, any specific values from ``case`` labels are superfluous and are +removed. In the latter approach, GNU case ranges are represented as a list +containing all the constants in the range (which doesn't scale well for large +ranges). Because the intermediate language idiom for ``switch`` statements is +slightly different from the C language idiom, a bit of translation from one +idiom to the other is necessary: + +* | A ``break`` in a ``switch`` usually just ends the current clause and makes + the code following it unreachable. Since the intermediate language + ``switch`` clauses end with a ``break`` by default, no ``goto`` to a + ``break`` label is usually needed. +* | Fall-through from one clause into the next is translated as a ``goto`` to a + generated label at the start of the next clause. +* | When ``case`` or ``default`` labels are not at the top level in the + ``switch`` body (i.e., they are defined within structured statements inside + the ``switch``), the ``switch`` clause is just a ``goto`` to a generated + label at the right location, and the unusual statement(s) inside the + ``switch`` body go into the body statement attached to the intermediate + language ``switch``. +* | Likewise, when there are local declarations in the compound statement that + is the body of the ``switch``, those declarations go into the body + statement. + +There is also processing to detect and report cases in which a declaration that +involves implicit or explicit initialization is bypassed by a transfer of +control (by means of a ``goto`` or ``switch``). A separate data structure is +maintained to assist in this checking: variable ``control_flow_descr_list`` +identifies a doubly linked list of entries of type ``a_control_flow_descr`` +that represents a view of the static control flow pattern of a given function. +Blocks, ``goto``\ s, labels, ``case`` labels, and initializing declarations are +all represented by entries on the list. Some of these entries point to IL +entries, but the IL does not point back. + +The list is dynamically pruned -- it has only enough information on it for the +checking that is required. For instance, once a forward goto has been checked, +it is no longer interesting and is removed, and entire blocks may be removed +once they become irrelevant to subsequent analysis. (See +``remove_control_flow_descr`` and ``remove_list_of_flow_control_descrs``, which +place entries onto an available list, and ``alloc_control_flow_descr``, which +reuses freed entries in preference to allocating new ones.) + +``add_to_control_flow_descr_list`` is called (from ``add_stmt_at_stmt_pos`` for +initializations, from ``push_stmt_stack`` for blocks, etc.) to add a new entry +to the end of the list, though in some cases the entry will not be +added -- because it is not required after all -- and sometimes it will even +cause other entries to be removed -- for instance, if a completed block turns +out to have no labels or gotos, the entire block can be eliminated. + +At the end of a block within a ``switch`` statement, +``add_to_control_flow_descr_list`` may call ``report_switch_past_init``, which +examines the entries on the list for initializing declarations that may be +bypassed by a transfer of control to a ``case`` label. An error is issued in +C++ mode, a warning otherwise. + +``check_for_jump_over_initialization`` is called from ``goto_statement`` and +from ``statement`` when a label definition is seen. For a forwards ``goto`` it +calls ``add_to_control_flow_descr_list`` to record information that will be +used for checking when the label is processed. For a label it calls +``check_goto_and_label`` to report any previously recorded ``goto``\ s that may +now be recognized to involve bypassing an initializing declaration (see +``report_goto_past_init``, which issues an error in C++ and a warning +otherwise); and an entry representing the label is added to the list. For a +backwards ``goto`` it again calls ``check_goto_and_label``, which in turn calls +``report_goto_past_init``, if appropriate. + +The control flow descriptor list is also used by +``check_for_branch_into_handler``, which reports attempts to branch into an +exception handler from code outside the handler. + +An important part of statement processing is the management of object +lifetimes. For example, each time a compound statement starts, a new object +lifetime begins; and it ends when the compound statement terminates. In other +words, objects (e.g., automatic variables and long-lifetime expression +temporaries) created inside the compound statement have lifetimes that +terminate when it does. The destructor (if any) for such an object must be +called in the event of the normal termination of the scope, a branch out of it, +or unwinding through it as the result of an exception. The information +enabling back ends to support these implicit destructor calls, in the right +place and in the right order, is provided by entries of type +``an_object_lifetime``, discussed in detail in the chapter on the intermediate +language. + +Each time a new function or block scope is created, a new object lifetime is +pushed on the object lifetime stack -- ``push_object_lifetime`` is called in +``push_scope``, and the object lifetime is bound to the scope entry for block +scopes in ``ensure_il_scope_exists`` (in ``il.c``). In addition, an object +lifetime is pushed for try blocks in ``try_block_statement`` and for cfront +dependent statements in ``start_block_statement``; in the latter case, since +there is no scope, the lifetime entry is bound to the block entry associated +with the block statement. + +When a label is defined, a block-after-label object lifetime is pushed. Such +lifetimes are effectively subblocks of the current lifetime that run from the +label to the end of the block in which the label appears. When a label is +defined inside an inner block, a block-after-label lifetime is also pushed in +the containing block when the inner block terminates. (See +``terminate_curr_block_object_lifetime`` and +``reset_curr_block_object_lifetime``.) Block-after-label lifetimes are also +pushed for case labels. + +The object lifetime that is current at the point of the label's definition is +recorded in the label statement. A ``goto`` statement that references that +label will point to the innermost object lifetime shared by the label and the +``goto``; this is computed by ``common_object_lifetime``. + +The general strategy is always to create an object lifetime at standard +transitions in the source code (e.g., upon entering a block or when a label is +seen) and then, when the construct it belongs to terminates, to decide whether +there is justification for retaining that lifetime entry in the IL. If not (as +determined by ``is_useless_object_lifetime``), it is removed from the IL tree. + +Consequently, a label or ``goto`` statement may be assigned an object lifetime +that subsequently proves "useless". In that case the object lifetime pointers +of the statement entries are promoted (see +``fixup_curr_block_labels_and_gotos``, which calls +``promote_label_and_goto_lifetimes``; this is also where +``pop_object_lifetime`` is called for block-after-label lifetimes). This +processing is driven by management of the control flow description list (see +``add_to_control_flow_descr_list``). + +If all the labels and ``goto``\ s in a function end up pointing to the function +scope lifetime but the function scope lifetime itself turns out to be useless, +then the lifetime pointers in the label and ``goto`` statements are cleared +(see ``wrapup_control_flow_processing``). diff --git a/doc/_sources/symbol_tbl.rst.txt b/doc/_sources/symbol_tbl.rst.txt new file mode 100644 index 0000000..92d8a98 --- /dev/null +++ b/doc/_sources/symbol_tbl.rst.txt @@ -0,0 +1,1967 @@ +.. _symbol-table: + +============ +Symbol Table +============ + +The primary function of the symbol table is to provide a mechanism for +associating names and entities: a name can be entered into the symbol table in +association with a particular definition and then later looked up to get back +to the same definition. Name visibility is controlled by an implementation of +nested name scopes and class member inheritance. Provision is also made for +overloaded operators and user-defined conversion functions, which are not +looked up by name. In addition, the symbol table serves as a repository of +information that is needed for front-end processing but is of no use to back +ends. ``symbol_tbl.c`` contains the code to manage the symbol table, +``lookup.c`` contains the code that looks up identifiers, ``scope_stk.c`` +contains the code that manages the scope stack, and ``symbol_ref.c`` contains +the code that manages the recording of references to symbols. +``symbol_tbl.h``, ``lookup.h``, ``scope_stk.h``, and ``symbol_ref.h`` contain +the associated declarations. + +Basic Organization +================== + +Symbols and Symbol Headers +-------------------------- + +The key components of the symbol table are entries of type ``a_symbol`` and +``a_symbol_header``. Typically, symbols represent specific uses of a name +(e.g., the same name may be declared in different name scopes or belong to +different name spaces), but all symbols for a particular name share the same +symbol header. Each symbol entry points to a header which identifies the name +associated with it; the symbol header points in turn to symbols that share its +name. Symbols with the same name from different translation units (see +:ref:`multi-tu`) share the same symbol header. + +For certain special cases (overloaded operators and user-defined conversions) +the symbol header has no actual name but can be thought of as representing a +family of virtual names to be constructed for the associated symbols: a single +symbol header is shared by all symbols that overload a given operator or, for +user-defined conversions, a given return type. (The names generated by the +compiler to assure type-safe linkage are not produced by the front end and so +do not appear in the symbol table.) + +At the gross level the symbol table has three distinct pieces, each of which +has its own "root", a global variable that is accessed in the lookup process: + +* | For named symbols ``symbol_table`` is a hash table where each bucket points + to a linked list of symbol headers. The name is reduced to a hash value + that is used to index the array. +* | For overloaded operator symbols ``opname_symbol_table`` is an array of + symbol header pointers that is indexed by members of the enumeration + ``an_opname_kind``. There will be one symbol header for each overloaded + operator. +* | For user-defined conversion symbols ``conversion_header_list`` points to a + linked list of entities of type ``a_conversion_header``, one for each + result type for which the user has declared a conversion routine. Each + conversion header points to a single symbol header. + +Active, Inactive, and "Other" Symbols +------------------------------------- + +Each symbol header contains pointers to three lists of symbols of the same name +(or that otherwise share the symbol header): the active symbol list, the +inactive symbol list, and the other symbol list. + +The Active Symbol List +^^^^^^^^^^^^^^^^^^^^^^ + +The list of active symbols includes all symbols that are still in scope. The +order of the symbols on the list is significant since certain of the lookup +mechanisms take the first symbol found. When symbols are entered into the +symbol table, their entries are always placed at the beginning of the list, so +that declarations in inner scopes will eclipse outer-scope declarations of the +same names. An exception is made when a tag and a nontype with the same name +exist in the same scope in C++. In such cases the tag is always placed on the +list following the nontype so that it will be hidden except when accessed using +an elaborated type specifier. When the inner scope ends, its symbol entries +are removed, which exposes the outer declarations. + +Note, however, that symbols from the same scope can coexist on the active list, +since different kinds of symbols can belong to different name spaces. For +instance, a variable, a macro, and (in ordinary C) a tag can all share the same +name. The array ``name_space_for_symbol_kind`` maps a symbol kind into +``a_name_space_kind`` (e.g., ``nsk_label``, ``nsk_macro``, ``nsk_other``). The +lookup mechanism must check for name-space compatibility: in most cases, it +takes the first in the active list whose kind maps into the appropriate name +space. The name space kind ``nsk_other`` is the normal name space for types, +variables, enumeration constants, and functions. + +The Inactive Symbol Lists +^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a scope terminates, the symbol for each name declared in that scope is +removed from the active list of the associated symbol header. In most cases, +this means the symbol is removed from the symbol table (i.e., that it can no +longer be found by any lookup mechanism). But for some symbols (e.g., class +and namespace members) it must remain possible to look up a name even after it +passes out of scope, and so its symbol is moved from the symbol header's active +list to its inactive list. The order of symbols on the inactive list is not +significant. + +Thus, the inactive symbol list will comprise symbols for class members that are +no longer in scope but are still indirectly accessible, whenever the class is +accessed. + +Similarly, when the template declaration scope terminates, its symbols +representing the template parameters are also added to the inactive list. This +enables them to be accessible during instantiation of the template. + +Namespace scopes are not terminated when the namespace is closed because the +namespace may be extended later in the compilation. Namespaces may be extended +either explicitly by opening a namespace extension scope, or implicitly as a +side-effect of a namespace member definition in the file scope or as a +side-effect of the instantiation of a template entity defined in a namespace +scope. When the original namespace definition scope is closed, the namespace +members are moved from the active list to the inactive list. If the namespace +scope is later extended, new symbols for the namespace are entered directly on +to the inactive list. + +The file scope is popped when the scanning of a translation unit is completed +so that its symbols are not on the active list if any other translation units +must be processed. As with namespaces, the symbols are moved to the inactive +list to permit the file scope to be reactivated later, if additional processing +of the original translation unit is required (e.g., to generate template +instantiations). + +The "Other" Symbol List +^^^^^^^^^^^^^^^^^^^^^^^ + +The "other" symbols list is used for symbols that are never found using the +normal lookup routines. Specifically, the "other" symbols list includes +"extern" symbols and synthesized namespace projection symbols, both of which +are described below. + +Scope List +---------- + +When symbols are entered into the symbol table, they are also entered onto a +list of the symbols declared in the current name scope (discussed in detail +below). [#f1]_ This list preserves the names in declaration order and is +referenced in removing symbols from the active list (and usually from the +symbol table) when the name scope is terminated. + +Typically, this list lasts no longer than the scope stack entry that points to +it -- when the entry is popped off the scope stack, the associated list is +discarded. In some cases, however, the list must be kept around for later use. + +* | For class scopes it is stored in the class symbol supplement for the class + for use in cases in which the declaration order must be observed (e.g., in + doing member initialization). +* | For function prototype scopes it is used to reenter parameter symbols in + the function scope. +* | For namespace scopes it is preserved in the pointers block for the + namespace. +* | For file scopes it is preserved in the translation unit entry (there can be + more than one file scope when processing multiple translation units). + +Special Cases +------------- + +There are several classes of symbol for which special treatment is required. + +Symbol entries for constructors, though they have names, are not entered +directly into the symbol table. That is, they do not appear on the active or +inactive list of the symbol header for the name. Rather, they are accessed +from the ``constructor`` field of the class's supplement entry. Thus the +symbol lookup for constructor ``X::X`` is always by way of the symbol +supplement for class ``X``. + +A tagless class, struct, or union presents an interesting case because it has +no name but must have a symbol to serve as a repository of information for the +front end's processing. Such symbols all share a single symbol header (see +static variable ``unnamed_tag_symbol_header`` in ``symbol_tbl.c``) but are not +entered on any list. + +C++/CLI property accessor functions are members of a property which is itself a +member of a class, but the property is not a nested class; it's a data member. +For the accessors, special symbol headers are generated that are a combination +of the symbol header for the property and the symbol header for the access +name. See ``get_property_or_event_accessor_symbol_header``. Event accessors +are handled similarly. + +Error symbols are created in various cases when errors are detected. They have +no name associated with them, and, like unnamed class symbols, they all share +the same symbol header (see static variable ``error_symbol_header`` in +``symbol_tbl.c``). + +Symbols and IL Entries +---------------------- + +For the most part symbol entries are little more than an indication of the kind +of symbol and a pointer to an IL entry that provides more information. Thus, +``sk_variable`` and ``sk_static_data_member`` symbols point to an entry of type +``a_variable``; constants, types, tags, fields, functions, and labels are +similar. The principal function of most symbol entries is simply to indicate a +mapping between names and the intermediate language constructs to which those +names correspond. + +But symbol entries also serve as repositories of information that the front end +requires for its processing but that back ends do not care about. For +instance, ``sk_keyword`` symbols contain the keyword token value and for +``sk_macro`` symbols there is a pointer to ``a_macro_def``. Most notably, +symbols representing classes, structs, and unions point not only to the +corresponding IL entry but also to an entry of type +``a_class_symbol_supplement``, which contains a number of flags and pointers +(including a pointer to the constructor symbol, as described above). + +Some symbols just point to other symbols: ``sk_projection`` symbols, which +represent names in a derived class that are inherited from a base class, +contain a pointer to the original symbol, and ``sk_overloaded_function`` +symbols point to a linked list of routine symbols that represent instances of +the overloaded name. + +``sk_parameter`` symbols are created during parameter processing. They are +needed because parameter names hide names from containing scopes (e.g., in +default argument expressions). However, they do not refer to any IL entity; +rather, when a function definition is present, they are reentered into the +function scope and turned into ``sk_variable`` symbols which do point to +variable entries. + +Function Overloading +-------------------- + +Each instance of an overloaded function is represented by a symbol -- of kind +``sk_member_function`` for member functions and ``sk_routine`` otherwise. +However, these symbols are not directly present in the symbol table. Rather, +the whole family of functions that share the common name or operator in a given +scope is represented by an ``sk_overloaded_function`` symbol, and that is what +actually appears in the symbol table (i.e., is on the active or inactive list +of a symbol header). Consequently, name lookup finds only the overloaded +function symbol, not the symbol for the particular function required. [#f2]_ + +The actual function symbols appear on a linked list pointed to from the +overloaded function symbol. The order of symbols on the list is not +significant, since the argument matching algorithm requires visiting every +instance anyway. The list may contain function symbols, function template +symbols, projection or namespace projection symbols that point to functions or +function templates, or a combination of any or all of these. + +Name Scopes +=========== + +``push_scope`` and ``pop_scope`` +-------------------------------- + +Aside from the structure described above, the symbol table also has a name +scope structure. Each time a new name scope is entered (for the file scope, a +class, struct, or union, a function, a block, function prototype, namespace, +template declaration, or template instantiation), ``push_scope`` is called to +push a new entry onto the scope stack. (See ``scope_stack``, a global variable +that points to an array of elements of type ``a_scope_stack_entry``. Since the +scope stack is implemented as a dynamically allocated array that can be +extended by reallocation when necessary, elements should always be accessed by +indexing into the array rather than by reusing a pointer.) + +There are actually a number of different routines used to push different kinds +of scopes (e.g., ``push_template_instantiation_scope``). The various routines +all call ``push_scope_full``, which does most of the processing. +``push_scope`` is used for pushing "normal" scopes that don't require that +extra arguments be supplied when called. This section uses the name +``push_scope`` to refer to the set of functions that add scopes to the scope +stack. Most of the actions described here are performed by +``push_scope_full``. + +``push_scope`` assigns a unique number to each scope, and when an identifier is +entered into the symbol table, the scope number is recorded in its symbol +(field ``decl_scope``); this number may be referenced during symbol lookup, and +it is used to detect multiple declaration errors during symbol entry. When the +name scope ends, ``pop_scope`` is called to remove its symbols from the symbol +table (class member symbols are an exception, as described above) and to pop +the scope stack entry off the stack. ``pop_scope`` calls ``wrapup_scope``, +which removes the symbol entries for the scope from the active list and +reenters them on the inactive list when appropriate (for class, namespace, and +template declaration scopes). ``wrapup_scope`` also calls +``end_of_scope_symbol_check``, which issues diagnostics on incomplete types and +on entities that were declared and never referenced or set and never used. +When the file scope is popped at the end of the translation unit, ``pop_scope`` +calls ``wrapup_namespace_scopes``, which in turn calls ``wrapup_scope`` for all +of the namespace scopes in the translation unit. + +The ``previous_scope`` field of the scope stack entry is used to determine the +order in which scopes on the scope stack are to be considered for name lookup +purposes. For most scopes, this field is set by ``push_scope_full``. + +``push_scope`` and ``pop_scope`` maintain a number of state variables, some +global and some local to ``symbol_tbl.c``: + +* | ``depth_scope_stack`` gives the depth of the current name scope in the + scope stack. [#f3]_ +* | ``decl_scope_level`` gives the scope depth of the scope entry with which + declarations should be associated. [#f4]_ +* | ``depth_innermost_function_scope`` is the depth of a ``sck_routine`` scope + stack entry that is or contains the current scope; if there is none or if a + class scope intervenes its value is ``NO_SCOPE_DEPTH``. +* | ``num_classes_on_scope_stack`` is the number of class entries currently on + the scope stack (including ``sck_class_reactivation`` as well as + ``sck_class_struct_union`` scopes). +* | ``depth_of_innermost_scope_that_affects_access_control`` is used in + determining whether a piece of code has member access privileges to a given + class (e.g., in a ``friend`` function). +* | ``depth_innermost_namespace_scope`` is the depth of the innermost namespace + scope that is visible on the scope stack, or the depth of the file scope if + no namespace scopes are visible. +* | ``depth_innermost_instantiation_scope`` is the depth of the current + template instantiation scope or ``NO_SCOPE_DEPTH`` if no instantiations are + active. + +``push_scope`` also causes new memory regions to be created for the file scope +and for function scopes. When the scope is popped, the following processing is +done: + +* | If IL lowering is being performed, ``should_delay_lowering_on_function`` is + called to determine whether the function should be lowered at this point. + A number of circumstances can cause lowering to be delayed, such as the + need to preserve unlowered IL for ``constexpr`` evaluations, the need for a + module-id that has not yet been determined, etc. +* | ``should_delay_finishing_of_function_body`` is called to determine whether + a function body should be "finished" at this point. If so, + ``finish_function_body_processing`` is called. This will lower the + function, if it has not already been lowered, do needed flag processing (if + necessary), and any other operations that may be needed before the memory + is potentially freed. +* | ``check_for_done_with_memory_region`` is called either to write out the + entries in the memory region to a file and reclaim the entire region for + reuse or, if the interface to the back end is in memory, to reclaim only + the unused portion of it. In some cases the memory must be kept and IL + file generation deferred. This is done, for example, when a function body + is kept for potential inlining, or if the function contains a generic + lambda that may be instantiated later. + +The name scope for a class whose definition is completed must be reinstated to +process the definition of a member function of that class or the initializer of +static data member of that class. This is accomplished by calling +``push_class_reactivation_scope``, which has the effect of making the symbols +on a symbol header's inactive list visible (that is, those inactive list +symbols whose ``decl_scope`` value matches the scope number of the reactivated +scope become visible). When the class to be reactivated is a nested class, +``push_class_reactivation_scope`` reactivates its enclosing class first to +create the required name visibility and hiding. If the class being reactivated +is from a namespace, the namespace will also be reactivated (see below). A +matching call to ``pop_class_reactivation_scope`` is required once processing +for the member function definition or static member initializer is finished. + +The ``assoc_type`` field in ``sck_class_struct_union`` and +``sck_class_reactivation`` scope stack entries points to the type entry for the +corresponding class, struct, or union. + +Namespace scopes, like class scopes, are reactivated when processing the +declarations of namespace members outside of their namespace. As mentioned +earlier, namespace scopes are unique in that they are not actually closed +when the end of a namespace definition is reached. The namespace can be +extended later either by a namespace extension declaration or by a name +that is injected while processing the definition of a member of a namespace +outside of the namespace (including the instantiation of templates defined +in the namespace). Namespaces are reactivated by calling +``push_namespace_reactivation_scope``. +``pop_namespace_reactivation_scope`` is called when the reactivated +namespace is no longer required. Reactivating a namespace causes any +namespaces that enclose the reactivated namespace also to be reactivated. +Namespaces are extended by calling ``push_namespace_extension_scope``. +When the namespace extension scope is no longer required, +``pop_namespace_extension_scope`` must be called. Extending a namespace +causes any namespaces that enclose the extended namespace also to be +extended. A namespace is *reactivated* in contexts in which the names from +the namespace must be visible but new names cannot be added to the +namespace. A namespace is *extended* in contexts in which names from the +namespace must be visible and new names can be added. + +The scope stack contains a set of pointers that are used to track the symbols +for the scope and the "last" pointers that point to the end of the each of the +lists of IL entries associated with the scope. For most scope kinds, this +information is no longer needed when the scope stack entry is popped off of the +stack. Because namespace scopes can be extended, this information must be +preserved for those scopes. Furthermore, a given namespace can appear on the +scope stack more than once when templates are being instantiated. When more +than one scope stack entry exists for a given namespace, they must share the +same set of symbol and IL entry pointers. The pointers that must be preserved +between extensions of the namespace and shared between scope stack entries for +the namespace are in a structure called ``a_scope_pointers_block``. Each scope +stack entry contains a pointers block structure and field named +``assoc_pointers_block`` that points to a pointers block structure. For all +scopes except namespace and namespace extension scopes, the +``assoc_pointers_block`` pointer is NULL, indicating that the pointers block +within the scope stack entry should be used. For namespace and namespace +extension scopes, the ``assoc_pointers_block`` pointer points to a pointers +block in the namespace symbol supplement for the namespace. The macro +``assoc_pointers_block_of`` should be used to obtain a pointer to the +appropriate pointers block for a given scope stack entry. + +``push_template_instantiation_scope`` is called when the appropriate context in +which a given template can be instantiated needs to be established. When a +template instantiation scope is pushed, the sequence of scopes used for name +lookup purposes is changed. In fact, there are four distinct sets of scopes +used for name lookup when a template instantiation in progress: + +* | the scopes associated with the local context of the template: These include + the template instantiation scope (with which the template parameters are + associated), the scope associated with the class or function being + instantiated, and any scopes nested within the class or function being + instantiated. +* | the template definition context scopes: The scopes that are only part of + the context in which the template was defined. +* | the referencing context scopes: The scopes that are only part of the + context in which the template reference that caused the instantiation + occurred, beginning with the innermost namespace scope. +* | the common scopes: The scopes that enclose both the definition context and + the referencing context. This always contains at least the file scope. + +``push_instantiation_context`` determines which of the required namespace +scopes are already present on the scope stack and pushes those entries that are +not already present. It then calls +``reactivate_class_and_instantiation_scopes`` to reactivate any classes that +may enclose the template that is being instantiated. If an enclosing class is +itself a template class, an instantiation scope for that class is also pushed +so that its template parameters will be visible to the entity being +instantiated. + +``fixup_instantiation_scopes`` is called after all of the scopes have been +pushed. It performs the following functions: + +* | All of the instantiation scopes that were pushed, except for the outermost + one, are flagged as nested instantiations. Only nonnested instantiation + scopes are considered for special instantiation context lookups, as + described later. +* | The context and common scope depths are recorded in the nonnested + instantiation scope. +* | The previous scope pointers of the outermost definition context scope and + the referencing context scope are set to point to the common scope. +* | The ``next_scope_that_affects_access_control`` field is updated to make + sure that it does not point at a scope that is not part of the current + context. +* | In the set of instantiation scopes pushed by a call to + ``push_template_instantiation_scope``, all except the innermost one have + their ``exclude_from_context_output`` flag set. This prevents unnecessary + context information from being generated during diagnostic output. + +The ``previous_scope`` field is also updated when a namespace reactivation +scope is pushed within a template declaration scope. In such cases, the names +from the namespace extension scope must not be considered until after the +template parameters. For example, in the following case the ``T`` in the +function parameter list must refer to the template parameter and not ``N::T``. + +.. code:: c++ + + namespace N { typedef int T;} + template void N::f(T); + +If ``GENERATE_SOURCE_SEQUENCE_LISTS`` is configured to TRUE, source sequence +lists for active scopes are recorded in the scope stack entry (see +``source_sequence_list`` and ``end_of_source_sequence_list`` in +``a_scope_stack_entry``). When ``pop_scope`` is called for the file scope or a +function scope, the list is moved to the corresponding IL scope. Otherwise, +the list is merged into the list of a containing scope, which usually means +that the list is simply appended to the list of the immediately containing +scope; for ``sck_template_instantiation`` scopes, however (when a +compiler-generated specialization represents an automatic instantiation -- that +is, when either ``CLASS``- or +``NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS`` is configured to +TRUE), ``insert_instantiation_src_seq_list`` is called to move the list to an +appropriate location in the list of an enclosing scope. + +Connection With IL Scope Entries +-------------------------------- + +While not all scope stack entries correspond to an intermediate language scope +entry, all intermediate language scope entries have a corresponding scope stack +entry. Every scope stack entry has a (possibly NULL) pointer to an +intermediate language scope entry; every intermediate language scope entry +refers back to the corresponding scope stack entry by means of a scope number. + +For example, a new scope stack entry is pushed for a statement block whether or +not it contains any declarations, but the intermediate language scope is not +created until it is needed, and not till then is the ``IL_scope`` pointer in +the scope stack entry updated. + +The scope stack entries for the file scope, namespaces, classes, routines, and +blocks are closely tied to a corresponding intermediate language scope entry: +the latter has pointers to the lists of types, variables, etc. for that scope, +and the pointers block has the pointers to the ends of those lists. The +pointers block in the scope stack entry is used for all scopes except for +namespace and namespace extension scopes, for which the pointers block is +located in the namespace symbol supplement. These tail pointers are only +needed while the scope is active, to add entries at the end of the list, and +having them in the pointers block reduces the size of the intermediate language +scope entry. + +Classes +======= + +Classes (in the generic sense, including structs and unions) require the +management of quite a lot of information. Some of this must reside in the +intermediate language. For instance, the entities that represent members of a +class are kept on lists pointed to from the intermediate language scope entry +associated with the class; and the base classes from which the class is derived +are associated with the class's type entry. In these and other cases +information associated with a class is stored in intermediate language +declarative constructs, and appropriately so, since the information is of use +to back ends. + +However, there is a great deal of information that the front end needs but back +ends do not care about, and it would be wasteful to store it in the +intermediate language. Instead, it is kept in the symbol table so that it can +be thrown away when front-end processing is complete. + +Class Symbol Supplement +----------------------- + +Entities of type ``a_class_symbol_supplement``, pointed to from all class, +struct, and union tag symbols, constitute the main repository for +front-end-only information about classes. + +Among the fields in class symbol supplements are: + +* | ``symbols``, the symbol list pointed to from the scope stack entry for the + class, retained even after the scope stack entry disappears. The symbols + are in declaration order, which is the order in which initialization is to + be performed. +* | ``constructor``, a pointer to the ``sk_member_function`` or + ``sk_overloaded_function`` symbol that represents the constructor(s) for + the class. As noted above, the constructor symbol cannot be accessed + directly by normal name lookup, but only via this pointer. +* | ``destructor`` and ``assignment_operator``, pointers to the symbols + representing the destructor and ``operator=()`` functions for the class. + Both could also be accessed by normal name lookup, but having the pointers + directly available makes some processing, especially implicit invocations + of these functions, more efficient and facilitates deciding whether the + compiler needs to generate one. +* | ``conversion_list``, a linked list of entries that provide quick access to + the symbols for the user-defined conversion functions for the class (i.e., + that define a conversion from the class to some other type). The list + includes symbols for inherited conversion functions. +* | ``routine_fixup_list``, a pointer to entities that store cached tokens to + allow for delayed scanning of default arguments and the bodies of member + functions that are defined inline. + | + | ``operator_lookup_namespaces``, a pointer to a list of namespaces that are + the parent namespaces of the class or one of its base classes. The global + scope is explicitly represented on this list by an entry with a NULL + namespace pointer. This list is used to specify the namespaces to be + searched for operator functions when an overloaded operator function is + called with an operand of the class. +* | A number of flags to summarize attributes of the class. Most of these + flags are redundant -- the attributes could also be computed by examining + other data. For instance, ``any_ref_member`` is checked when putting out + warnings on variables that should be initialized; its value could also be + determined by looking at all the nonstatic data members to see if any have + reference types. + +Class Member Projection Symbols +------------------------------- + +Symbols of kind ``sk_projection`` provide a mechanism to represent names that +are visible in a derived class having been declared in a base class. Each +projection symbol has a supplementary entity of type ``a_projection_descr`` +which identifies the fundamental base class member by pointing to the base +class entry and to a symbol from that base class. [#f5]_ + +Projection symbols are created as needed (in the course of looking up a name) +and are added to the scope of the derived class. Once entered in a class +scope, they permanently associate the name in the derived class with a +declaration in a base class. The next time the name is looked up in the +lexical context of the class, the projection symbol will be found directly, +without the more expensive search of the base classes. + +A projection symbol records a name's accessibility in the current scope (e.g., +it may have been declared ``public`` originally but be less accessible in the +context of the derived class). It also notes whether a name is ambiguous. +These attributes of name inheritance are computed on the initial lookup, when +the projection symbol is created, and thus need not be recomputed on subsequent +references to the name. + +Projection symbols are also used to represent base class member names that are +explicitly incorporated into the derived class by means of a +``using``-declaration; for these cases the flag ``is_using_decl`` is set to +TRUE. + +When a ``using``-declaration in a derived class specifies an overloaded member +function from a base class, each member of the original overload set will be +projected into the base class independently and recorded in an overload set +created in the derived class. The latter may contain a mix of +``sk_member_function`` symbols from the derived class and ``sk_projection`` +symbols referring to member functions in one or more base classes. For +example: + +.. code:: c++ + + struct A { + void f(int); + void f(); + }; + struct B { + void f(double); + }; + struct C : public A, public B { + using A::f; + using B::f; + void f(char); + }; + +Here, the overload set for ``C::f`` will include ``C::f(char)`` along with +projections into ``C`` of ``A::f(int)``, ``A::f()``, and ``B::f(double)``. + +On the other hand, when ``is_using_decl`` is FALSE in an ``sk_projection`` +symbol, the projection may refer to an entire overload set and not to any +particular instance of the name. In such cases the ``access`` value will +represent the greatest access available; a particular function may turn out to +have less accessibility. + +Namespace Projection Symbols +---------------------------- + +Symbols of kind ``sk_namespace_projection`` are used to represent names made +visible by ``using``-declarations that refer to namespace members +(``using``-declarations that refer to class members are described above). As +with class member ``using``-declarations, when a ``using``-declaration +specifies a overloaded function from another namespace, each member of the +overload set is projected into the current scope separately. The resulting +overload set may contain a mix of function, function template and namespace +projection symbols. + +Template Symbols +================ + +Symbols of kind ``sk_class_template`` and ``sk_function_template`` have an +associated entry of kind ``a_template_symbol_supplement``. Template processing +is discussed in detail in another chapter. + +Namespace Symbols +================= + +Symbols of kind ``sk_namespace`` have an associated entry of kind +``a_namespace_symbol_supplement``. As described above, the namespace symbol +supplement contains the pointers block used by scope stack entries that refer +to the namespace. It is possible for more than one scope stack entry for a +namespace or namespace extension scope to refer to a single namespace. In such +cases the scope stack entries all refer to the one pointers block structure in +the namespace symbol supplement. The namespace symbol supplement also contains +information used by the name lookup routines when doing lookups in the presence +of ``using``-directives. + +Symbol Lookup +============= + +Symbol Locator +-------------- + +Symbol lookup is the process whereby a name, a qualified name, an operator +token, or a conversion result type is used to search for a symbol in the symbol +table and, if it exists, return it to the caller. A key intermediary construct +in this process is the entity of type ``a_symbol_locator``. It consists of + +* | A pointer to a symbol header. (Sometimes error locators have a NULL symbol + header pointer; in all other cases a locator will point to a valid symbol + header.) +* | A source position, the line and column in the source program at which the + reference starts. +* | ``specific_symbol``, a pointer to a symbol. This is usually NULL, but if + preliminary processing happens to turn up a symbol (e.g., in validating a + qualified name), it is saved here so that the lookup need not be done + again. +* | The ``is_qualified_name``, ``is_global_qualified_name``, + ``is_file_scope_qualified_name``, and ``is_super_qualified`` flags, which + specify the kind of qualifier, if any, that preceded the name. +* | ``is_class_member``, a flag that is TRUE for qualified names for which the + qualifier names a class. Note that the qualifier may also contain a + namespace specifier, but the last qualifier specifies a class name. +* | ``parent``, a union that, for qualified names, contains a pointer to either + the class or namespace specified by the qualifier. The ``is_class_member`` + field is used to specify whether the qualifier is a class or a namespace. + This field is also used to specify the class type associated with a vacuous + destructor reference. +* | ``The is_template_id`` flag is TRUE if the name was followed by a template + argument list that has been coalesced. If the name is a class template + name, the ``specific_symbol`` will point to the template class designated + by the template argument list. The ``do_not_clear_specific_symbol`` flag + is set to TRUE when a class template argument list is coalesced because the + template argument list is not retained in the locator, and it would be + impossible to recompute the ``specific_symbol`` value if it were cleared. +* | ``template_arg_list`` is used when an explicit function template argument + list is specified, and points to the template argument list that was + scanned. The ``is_template_id`` flag is also set. An empty template + argument list may be specified (e.g., "``<>``"), so the ``is_template_id`` + flag should be used to check for the presence of an explicit function + template argument list, not the ``template_arg_list`` field. +* | The ``is_operator_name`` flag and the operator name kind. This flag is + TRUE and the associated field is defined only when it is an operator name + that is being looked up. +* | The ``is_conversion_name`` flag and the conversion result type. This flag + is TRUE and the associated field is defined only when it is a user-defined + conversion that is being looked up. +* | The ``is_destructor_name`` flag is TRUE when the name is a destructor name. +* | The ``is_vacuous_destructor_reference`` and ``is_nonclass_destructor`` + flags, which are used to identify explicit destructor references for + classes without destructors or for nonclass types. +* | The ``is_semivisible_nested_class`` flag is TRUE when the name is not + visible by standard scoping rules but only by a special search that + implements the "nested class anachronism" (ARM 18.3.5). +* | The ``access_control_error_reported`` flag is TRUE if an accessibility + error has already been issued on the symbol. +* | The ``is_error`` flag is TRUE when the locator represents an error. +* | The ``do_not_clear_specific_symbol`` flag is TRUE if the + ``specific_symbol`` points to a value that should be retained because it + cannot or should not be reproduced by a repeated lookup. This is primarily + used for coalesced class template references, as described above, but is + also used for specific symbol error locators (error locators that refer to + a specially created error symbol). + +Symbol locators are necessary because symbol lookup sometimes occurs in several +stages at separate points of processing. They provide a way to save and use +the intermediate results. For instance, when an identifier is scanned by +``get_token``, the locator is stored in ``locator_for_curr_id``. Often a local +copy is made so that the information can be preserved as additional tokens are +scanned. Then when it comes time to actually enter the symbol in the symbol +table, all the information needed is right there in the locator. + +Identifiers and Symbol Headers +------------------------------ + +Each name in the source program is looked up as it is scanned. This is +necessary in part so that ``get_token`` processing can distinguish identifiers +from keywords. + +``find_symbol`` is called to look up the names in the hash table pointed to by +global variable ``symbol_table``. The interface to ``find_symbol`` uses a name +string with a length rather than a null-terminated string because the string in +question is usually part of the source line buffer. + +After the bucket number is computed, it searches the list of symbol headers +pointed to by the bucket till it finds a matching name. If it finds a match, +it moves the symbol header to the front of its bucket list so that +frequently-used entries will cluster near the beginning. If no match is found, +a new symbol header is created and entered. A pointer to the symbol header +(whether newly created or not) is returned in the symbol locator, and a pointer +to the list of active symbols associated with the symbol header is also +returned. + +``normal_id_lookup`` +-------------------- + +``find_symbol`` locates a symbol header but does not actually find the symbol +itself. For simple names (e.g., not qualified names) that is done by +``normal_id_lookup``, which searches the symbol header's active list -- and, if +appropriate, its inactive list -- to find a symbol in the appropriate name +space and lexical scope. + +``normal_id_lookup`` uses one of two search algorithms. The fast search (which +is the only one used in ordinary C mode) simply searches the active list: the +first symbol found which meets the search requirements is returned; in C++ mode +this search may only be used when there are no scopes on the scope stack that +alter the sequence in which scopes are considered for name lookup, and when the +lookup is not one of a number of special lookups that disregard certain kinds +of symbols. + +The second and slower algorithm is required when + +* | A class or class reactivation scope is present, in which case one must look + for inactive symbols for the class members and for member names that are + inherited from base classes. +* | A namespace, namespace extension, or namespace reactivation scope is + present, in which case one must look for inactive symbols for the namespace + members. +* | A template instantiation scope is present, in which case inactive symbols + for the template parameters must be considered, and the scopes must be + searched in an irregular order (as described earlier). +* | A ``using``-directive is in effect, in which case one must look for symbols + for the namespaces referenced directly or indirectly by the + ``using``-directive. +* | A special lookup option has been specified for a given lookup. For + example, the lookup may optionally ignore class scopes, etc. + +In such cases each scope must be considered individually, since there is no +single list that summarizes the visibility of names. + +This comes up, for instance, in the non-inline definition of a member function: +the class definition has been completed and its names have been removed from +the active list, so those names must be searched for on the inactive list. For +example, + +.. code:: c++ + + int i; + struct S { int i; int f(); }; + int S::f() { return i; } + +Here, when the body of ``S::f()`` is being scanned, the symbol for ``::i`` will +be on the active list of the symbol header for ``i``, whereas the symbol for +``S::i`` will no longer be in scope, having been moved over to the inactive +list when the definition of ``S`` was completed. However, since the scope for +``S`` is reactivated before the member function body is scanned, and since the +reactivated scope is examined before the file scope, it is ``S::i`` rather than +``::i`` that will be found. + +Similarly, when a namespace member is defined outside of its namespace a +namespace extension scope is pushed onto the scope stack at the point at which +names from the namespace should be visible. + +.. code:: c++ + + int i; + namespace N { int i; int f(); } + void N::f() { return i; } + +Here, as with the class member example shown above, the namespace member +``N::i`` is found, hiding ``::i``. + +Slow Lookup Processing (``scope_stack_lookup)`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``scope_stack_lookup`` and the routines it calls are used to implement the slow +lookup. It is passed a range of scope depths to be included in the lookup. +Each scope is examined separately. The lookup begins with the scope stack +entry indicated by the global variable ``depth_of_initial_lookup_scope`` and +proceeds by following the ``previous_scope`` link in the scope stack entry +until a scope entry with no previous scope is found. ``active_scope_lookup`` +is called for scopes whose symbols are still on the active list and +``inactive_scope_lookup`` is called for scopes whose symbols have been +transferred to the inactive list. When a class or class reactivation scope is +processed, a flag is returned that specifies whether ``scope_stack_lookup`` +should look for a projection symbol for the class as described below. + +When a template instantiation scope has been processed, and a symbol has not +yet been found, names from both the context in which the template was defined +and from the context in which the template was used must be considered. This +is done by calling ``instantiation_context_lookup``, which is described below. + +A ``using``-directive can cause names from other namespaces to be visible in a +namespace scope (including the global scope) that is currently on the scope +stack. The ``using_directives_apply`` flag in the scope stack entry is used to +indicate that such processing is required. When this flag is set for a +namespace scope or the global scope, ``do_using_directive_lookup`` is called to +search for applicable symbols from namespaces named in ``using``-directives. + +The presence of ``using``-directives can result in more than one symbol +being found that satisfies the lookup. In such cases +``do_using_directive_lookup`` creates a synthesized namespace projection +symbol that represents the set of symbols found (See :ref:`using-dir` and +:ref:`namespace-proj`). The lookup could determine that the name is +ambiguous in the current context, in which case a synthesized namespace +projection symbol that is flagged as ambiguous is returned. + +Looking for Class Member Projection Symbols +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a name is not found in a class, the classes from which it is derived must +be searched before the containing scope is examined. This is done by +``find_projected_symbol``, which looks for the name among the base classes (see +``find_progenitor_symbol`` and ``symbol_projected_from_base_class``) and if +successful creates an ``sk_projection`` symbol in the derived class and adds it +to either the active or the inactive list of the symbol header for the name. A +pointer to the projection symbol, which (as described previously) represents +the inheritance, is returned to ``normal_id_lookup``, where it is placed in the +locator (field ``specific_symbol``); a pointer to the symbol of which it is the +projection is returned from ``normal_id_lookup`` as the function return value. +Consider this example: + +.. code:: c++ + + int i; + struct S { int i; }; + struct T : public S { int f(); }; + int T::f() { return i; } + +In this case the scope for ``T`` is reactivated when the body of ``T::f()`` is +scanned. No ``T::i`` is found in the scope of ``T``, but before the containing +scope (namely the file scope) is searched, the base class must be examined, and +so ``normal_id_lookup`` calls ``find_projected_symbol``. This search turns up +``S::i``, so again ``::i`` is eclipsed. In addition, a projection symbol for +``i`` is created in class ``T`` (it points to ``S::i`` since it represents the +"projection" of ``i`` from ``S`` into ``T``). Thus, on subsequent searches for +``i`` in the scope of ``T`` a ``T::i`` *will* be found, namely the projection +symbol referring to ``S::i``, and so the base class search will not have to be +repeated. + +``find_projected_symbol`` and its subroutines also compute the accessibility of +the inherited name and determine whether it is ambiguous. No errors are put +out at this point, since the name lookup routines are interested in name +*visibility* only; instead, the status is recorded in the projection symbol and +diagnostics can be issued later if appropriate. + +.. _instantiation-context-lookup: + +Instantiation Context Lookup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a name is looked up as part of a template instantiation, and the name is +not found in the local context of the instantiation (the template parameters +and the scope(s) associated with the class or function being instantiated) it +must be looked up in the instantiation context. The front end implements two +different instantiation context lookup algorithms: the one mandated by the +standard (referred to as "dependent name lookup"), and the one that existed +before dependent name lookup was implemented that more closely reflects +existing practice and is more compatible with other compilers. + +As described earlier, ``push_template_instantiation_scope`` configures the +scope stack so that three distinct contexts exist outside of the local context +of the instantiation: the template definition scopes, the referencing context +scopes, and the scopes common to both. + +When doing dependent name lookup, the following steps are used to produce the +final result of the lookup: + +* | The name is looked up in the context of the template definition and only + names visible at the point of the template definition are considered. +* | Only those base classes that do not depend on template parameters are + considered. + +When not doing dependent name lookup, the following steps are used to produce +the final result of the lookup: + +* | The name is looked up in both the template definition context and the + referencing context by calling ``scope_stack_lookup`` with the appropriate + starting and ending scope depths. The lookup in the referencing context is + suppressed if the lookup in the definition context finds a class member. +* | If none or only one of the lookups produces a symbol, and if the lookup in + the definition context did not find a class member, ``scope_stack_lookup`` + is called again to look in the common scopes. +* | If no symbols were found by the two context lookups, the result of the + common scope lookup is used. +* | If only one of the two context lookups produced a symbol, the result of the + common scope lookup is used as the value of the context lookup that did not + produce a symbol, and the next rule is followed. +* | If the symbol from the referencing context is not a function or function + template, it is discarded. +* | If there is still only one symbol from the two context lookups, that symbol + is used. +* | If there are two symbols, a synthesized namespace projection symbol is + created that represents the result of the lookup. + +Note that in both cases, these algorithms describe the result of the "normal" +lookup of the name. In addition to the entities made visible by the normal +lookup, additional functions and/or function templates may be made visible by +argument-dependent lookup. + +Nested Class Anachronism Lookup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the processing described thus far in ``normal_id_lookup`` fails to find a +qualifying symbol, an additional search implementing the "nested class +anachronism" (ARM 18.3.5) is performed by calling ``find_nested_class_symbol``, +which finds names of nested classes which, strictly speaking, should not be +visible. For example, + +.. code:: c++ + + struct S { + struct T { + int a; + }; + int b; + }; + struct T x; + +After the normal search for ``T`` is exhausted without turning up a symbol, an +additional search is made through the inactive list of the corresponding symbol +header for a symbol of a nested class whose innermost non-class containing +scope (in this case, the file scope) is still an active scope (in this case, it +is). When such a symbol is found, and it is the only symbol that qualifies, it +is returned to ``normal_id_lookup`` and a warning is issued. [#f6]_ + +Nonreal and Proxy Class Lookup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the processing described thus far in ``normal_id_lookup`` fails to find a +qualifying symbol, and one or more of the classes included in the lookup has a +"nonreal" base class, a nonreal class member is created by calling +``add_member_to_proxy_or_nonreal_class``, and the symbol for the newly created +class member is returned. + +.. code:: c++ + + typedef int Y; + template struct A : T { + X x; // assumed to be T::X + Y y; // ::Y + }; + +The nonreal lookup is only done when the normal lookup fails to find a symbol. +In the example above, ``::Y`` is found, so no nonreal member is created. The +lookup of ``X`` fails to find a symbol, so a nonreal member is created. + +Hide-by-sig lookup +^^^^^^^^^^^^^^^^^^ + +C++/CLI has a special kind of lookup used for members of managed classes, +called "hide-by-sig" lookup. In normal C++ name lookup, a name in a derived +class hides all instances of the same name in a base class; this is called +"hide-by-name" lookup. In hide-by-sig lookup, on the other hand, a member +function in a derived class hides a member in a base class only if their +signatures match. A function "``void``\ ``f(int)``" in a derived class, for +example, would not hide a function "``void``\ ``f(char)``" in a base class; +both would appear in an overload set and might compete with each other. In +addition, hide-by-sig lookup considers access -- inaccessible members of base +classes are not seen by the lookup. And there are special rules regarding +interfaces, which are too arcane to describe here. Hide-by-sig lookup only +applies to functions. + +Hide-by-sig lookup is implemented by building a list of +``a_hide_by_sig_list_entry``\ s that enumerates all the symbols that co-exist +with a given symbol in an overload set. The list is built by +``use_hide_by_sig_lookup`` and saved in the symbol's +``hide_by_sig_lookup_result`` field so it only needs to be constructed the +first time a hide-by-sig lookup is done on the symbol. Overload resolution +traverses that list to build up the set of functions in an overload resolution +set. Access is checked while the overload set is built up, and inacessible +functions are discarded at that point (different places in the program may have +differing access to the base class members; this allows a single general +hide-by-sig list to be built and then used with different access contexts). + +Lookup of Entities Imported from C++/CLI Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When C++/CLI metadata files are imported by way of a ``#using`` directive or +implicitly for the entities in ``mscorlib``, only the namespace-scope-level +names in the file are added to the symbol table. For a class, for example, the +class name is entered as an incomplete type, and its definition and members are +not immediately entered. Later, if a lookup is done in the class scope, the +members of the class are fetched from metadata and added to the symbol table. +This "lazy" lookup makes the use of metadata files much more efficient, since +things are not loaded until they are actually needed. This is implemented by +piggy-backing on the mechanism that instantiates templates when a member of the +template is required: ``f_instantiate_template_class`` (often invoked from the +macro ``complete_class_type_is_needed)``\ will call ``get_definition_of_class`` +to fill in the definition of an entity imported from metadata. This is done +automatically whenever a class-scope lookup is done in a class that came from +metadata. The definition is loaded, the lookup is then done, and the result is +returned to the caller, who has no need to know that the class definition had +to be loaded to be able to perform the name lookup. + +C mode out-of-scope declarations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When compiling C code, if the processing described thus far in +``normal_id_lookup`` fails to find a qualifying symbol, +``find_out_of_scope_declaration`` is called to look for an external variable or +function that was declared in a scope that is no longer visible. If such a +symbol is found, it is reentered in the current scope and returned as the +result of the lookup. + +.. code:: c++ + + void g1(void) { + extern void f(int); + f(1); + } + void g2(void) { + f(2); + } + +A symbol for ``void f(int)`` is reentered in ``g2``, even though ``f`` is no +longer visible. This lookup is not performed in strict mode. + +Lookup Options +^^^^^^^^^^^^^^ + +Options flags may be supplied to ``normal_id_lookup`` that affect the kinds of +symbols that are visible and other aspects of the name lookup process. In +certain contexts a name lookup is required to determine whether a given name is +a type. In this context a projection symbol should not be created unless the +name is a type. The flag ``IDL_TENTATIVE_TYPE_LOOKUP`` is used to suppress the +creation of a projection symbol in this instance. + +A special lookup is also required when scanning a constructor initializer list +that may include member names and base class names but may not reference the +names of parameters of the constructor. The ``IDL_SKIP_CURR_FUNCTION_SCOPE`` +flag is used to request this kind of lookup. + +``IDL_LINKAGE_LOOKUP`` indicates that the lookup is being used to find a +previous declaration of a name and that certain special lookup features should +be suppressed and that the lookup should terminate at the nearest enclosing +namespace scope. This option suppresses nested class anachronism, nonreal +member lookup, and out-of-scope declaration processing. + +``IDL_SKIP_CLASS_SCOPES`` causes class and class reactivation scopes to be +ignored. This is used when looking up nonmember operator functions. + +``IDL_INSTANTIATION_CONTEXT`` is used to indicate that a lookup operation is +part of a special instantiation lookup that looks in both the template +definition and reference contexts. + +Looking Up Names in the Current Scope +------------------------------------- + +``curr_scope_id_lookup`` looks up a name in the current scope and returns the +symbol found or NULL if no symbol is found. The symbol must be a name declared +in the scope. ``using``-directives are not considered and projection symbols +to base class members are not considered unless the +``IDL_PROJECTION_SYMBOL_ALLOWED`` option is specified. + +Looking Up Class Members +------------------------ + +``class_qualified_id_lookup`` is used to look up a name in the scope of a class +and its base classes. As with ``normal_id_lookup``, the caller provides a +symbol locator that contains a pointer to the symbol header for the identifier +being looked up. The search begins by looking through the inactive list for a +symbol from the scope associated with the class type passed by the caller. If +the symbol is not found on the inactive list, the active list is also checked. +The active list check is needed when a class-qualified lookup is done while the +class is being defined. For example, + +.. code:: c++ + + struct A { + struct B {}; + A::B f(); // the A:: is not necessary, but is allowed + }; + +If the symbol has still not been found, and the lookup is being done in a +nonreal class, a symbol for a nonreal class member is created by calling +``add_member_to_proxy_or_nonreal_class``, and the newly created symbol is +returned (see :ref:`nonreal-and-proxy-members` for more information). + +If the symbol has still not been found, the name is checked to see if it is a +constructor or destructor for the class. If so, the symbol for the constructor +or destructor from the class symbol supplement is returned. + +Finally, if the symbol has still not been found, ``find_projected_symbol`` is +called to search the base classes for a member that may be projected into the +class. + +.. _nonreal-and-proxy-members: + +Nonreal and Proxy Class Members +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A nonreal class is a template class that has one or more template arguments +that depend on template parameters. A proxy class is a class that stands in +for a template parameter when that template parameter is used in a context that +requires a class type. For example: + +.. code:: c++ + + template struct A { + typename T::A a; + typename A::X b; + typename T::Z c; + int n[T::B]; + }; + +In this example a proxy class is created for ``T`` so that ``A`` and ``B`` may +be looked up in ``T``. A nonreal class for ``A`` is created, a nonreal +template named ``T::Z`` is created, and the nonreal instance ``T::Z`` is +created. + +``proxy_class_for_template_param`` creates a proxy class associated with a +given template parameter. The proxy class is created the first time that it is +needed + +``create_proxy_or_nonreal_class_member`` creates a member of a nonreal or proxy +class. It is called by ``add_member_to_proxy_or_nonreal_class`` which also +adds the newly created symbol to the inactive list so that it may be found by +subsequent lookups. The kind of entity that is created (type, constant, or +template) depends on the kind of lookup that is done, and on whether the +"implicit typename" option is enabled. ``nonreal_member_symbol_kind`` is used +to determine the kind of symbol to be created for a given set of lookup +options. + +Looking Up Namespace Members +---------------------------- + +``namespace_qualified_id_lookup`` is used to look up a name in the scope of a +namespace. If the name is not found in the namespace, the name is also sought +in any namespaces referenced by ``using``-directives in the specified +namespace. ``lookup_in_namespace`` is called to look for the name in the +specified namespace. If a symbol is found, it is returned; otherwise +``lookup_in_namespace`` calls ``qualified_using_directive_lookup``, which loops +though the ``using``-directives found in the original namespace and calls +``lookup_in_namespace`` recursively to look for the name in those namespaces. +``qualified_using_directive_lookup`` always considers all namespaces named in +``using``-directives within a given namespace (i.e., it does not stop searching +when a symbol is found in a given namespace). For example, the hierarchy below +would be created by the following example: + +.. code:: c++ + + // D E + // \ / + // B C + // \ / + // A + namespace E { } + namespace D { } + namespace C { using namespace E; } + namespace B { using namespace D; } + namespace A { using namespace B; using namespace C;} + +In such a hierarchy, when looking up a name in namespace ``A`` + +* | If the name is found in ``A``, the lookup will not look in any other + namespace. +* | If the name is not found in ``A``, the lookup will always look in both + ``B`` and ``C``. +* | If the name is not found in ``B``, the lookup will look in ``D``. +* | If the name is not found in ``C``, the lookup will look in ``E``. + +The presence of ``using``-directives can result in more than one symbol +being found that satisfies the lookup. In such cases +``qualified_using_directive_lookup`` creates a synthesized namespace +projection symbol that represents the set of symbols found (see +:ref:`using-dir` and :ref:`namespace-proj`). The lookup could determine +that the name is ambiguous in the current context, in which case a +synthesized namespace projection symbol that is flagged as ambiguous is +returned. + +When a namespace contains an inline namespace (a C++11 feature), or a namespace +named in a GNU strong using-diirective, namespace lookup is done slightly +differently. Normally, if a name is found in a namespace, other namespaces +made visible in that namespace by using-directives are not searched, but a +namespace was made visible as an inline namespace (or strong using-directive) +is searched even when a symbol was found in the original namespace. + +Looking Up Names in the File Scope +---------------------------------- + +The file scope is also known as the global scope, and, with the addition of +namespaces, as the "global namespace". The same qualified name lookup rules +apply to both namespace qualified lookups and file scope qualified lookups. +``file_scope_id_lookup`` looks on the active list for a name declared at the +file scope. If the name is not found on the active list, the inactive list is +seached. If the name is not found in the file scope, +``qualified_using_directive_lookup`` is called to look in scopes named by +using-directives in the file scope. + +In the presence of multiple translation units there can be more than one file +scope. The scope pointer for the file scope to be used is passed to +``file_scope_id_lookup``. + +Argument-Dependent Lookup +------------------------- + +When an unqualified name is used as the function name in a function call, the +name is looked up using both the normal lookup mechanism and also using what is +known as "argument-dependent lookup". Argument-dependent lookup uses the types +of the function arguments to produce a set of "associated classes" and +"associated namespaces" to be searched for candidate functions. + +``argument_dependent_lookup`` is called to perform an argument-dependent +lookup. It calls ``determine_assoc_namespaces_and_classes`` to determine the +associated namespaces and classes to be used for the lookup. Normally, only +names from the current translation unit are considered by the +argument-dependent lookup process, but when instantiating exported templates +(and non-exported templates whose instantiation results from the instantiation +of an exported template) argument-dependent lookup is done in each of the +translation units on the translation unit stack and the results of the lookups +are combined. + +Argument-dependent lookup returns a list of symbols representing the candidate +functions being found. The symbol list may contain functions, function +templates, and overload sets. Argument-dependent lookup is normally done in +conjunction with a normal lookup. The symbol representing the normal lookup +result is passed to ``argument_dependent_lookup`` and is returned as an element +of the resulting symbol list. The resulting symbol list may directly or +indirectly (as part of an overload set) include multiple instances of a given +function or function template. This occurs for several reasons: + +* | The symbol list includes the result of both the normal and + argument-dependent lookups, which may produce overlapping results. +* | The symbol list includes overload sets which may, as a result of + using-directives, include the same functions or function templates. +* | The argument-dependent lookup may be done in multiple translation units + when exported templates are used. The same functions or templates may be + found in more than one of the translation units. + +.. _using-dir: + +``using``-Directive Processing +------------------------------ + +``using``-directives are used to make names from a namespace visible at a +certain point in the unqualified lookup process (i.e., the lookup performed by +``normal_id_lookup``). ``using``-directives that appear in namespace scopes +can also affect qualified lookups in the namespace in which they appear. +Qualified ``using``-directive lookups simply make use of the +``using``-directives list found in the scope entry. Unqualified +``using``-directive lookups, on the other hand, rely on additional data +structures that are maintained to optimize the process of finding names made +visible by ``using``-directives during the ``normal_id_lookup`` process. + +A ``using``-directive can appear in a namespace scope (including the files +scope), or in a block scope. The scope that contains the ``using``-directive +is often not the scope at which the ``using``-directive "applies", however. A +``using``-directive "applies" at the nearest enclosing scope that is or +contains the namespace named in the ``using``-directive, and contains the +``using``-directive. For example, + +.. code:: c++ + + namespace A {} + namespace B { + namespace C { + using namespace A; // applies to the file scope + } + using namespace C; // applies to B + } + using namespace B::C; // applies to the file scope + +The primary piece of information that is maintained to optimize unqualified +``using``-directive lookups is a field in the namespace symbol supplement that +indicates the scope depth of the scope at which a ``using``-directive for that +namespace applies, or contains ``NO_SCOPE_DEPTH`` if there is no +``using``-directive in effect that makes symbols from the associated namespace +visible. + +``do_using_directive_lookup`` simply looks through the inactive symbols for a +symbol whose parent namespace has a ``using``-directive that applies at the +scope depth currently being processed by ``scope_stack_lookup``. + +The problem with this kind of state information is that it needs to be reset +each time a template instantiation begins and restored each time an +instantiation ends. To make the process of clearing and restoring the state +information as efficient as possible, the scope stack entry contains a list of +"active" ``using``-directives for the scope. An active ``using``-directive is +one that appeared in the scope or appeared in one of the namespaces named by a +``using``-directive in the scope. + +When a ``using``-directive appears, ``add_active_using_directive`` is called to +add it to the active ``using``-directive list for the current scope. It then +calls ``add_active_using_directive_to_scope``, which actually adds it to the +list. + +``using``-directives are transitive, meaning that any ``using``-directives that +appear in the namespace nominated by a ``using``-directive are treated as if +they also appeared in ``using``-directives in the scope containing the original +``using``-directive. ``add_active_using_directives_for_namespace`` is called +to add the namespaces that appear in ``using``-directives in the nominated +namespace to the active ``using``-directive list, which it does by recursively +calling ``add_active_using_directive_to_scope``. When +``add_active_using_directive`` adds a ``using``-directive to a namespace scope +it searches through the scope stack to find active ``using``-directive lists +that refer to the namespace containing the new ``using``-directive. If such +scopes are found, ``add_active_using_directive_to_scope`` is called to add the +newly nominated namespace to those scopes. + +``add_active_using_directive_to_scope`` determines the scope depth at which a +``using``-directive applies. This scope depth is recorded in the namespace +symbol supplement of the namespace being added. The scope stack entry +associated with that scope depth is updated to indicate that there are +``using``-directives that apply when that scope is reached in an unqualified +lookup. + +``set_active_using_list_scope_depths`` is called to reset and restore the state +of the scope depth information in the namespace symbol supplement and the +``using_directives_apply`` field in the scope stack entry. This is done at the +beginning and end of a template instantiation scope, and is also done whenever +a scope containing active ``using``-directives is popped off of the stack. + +.. _namespace-proj: + +Synthesized Namespace Projection Symbols +---------------------------------------- + +The addition of namespaces creates situations in which the result of a lookup +can be a set of symbols from different scopes. A synthesized namespace +projection symbol is created to represent the result of such a lookup. +Synthesized namespace projection symbols are created + +* | by an unqualified lookup in which the symbols found were made visible by a + ``using``-directive, +* | by an qualified lookups in which the symbols found were made visible by a + ``using``-directive, and +* | by an instantiation context lookup in which symbols were found in both the + definition and referencing contexts. + +The ``synthesized_namespace_projection`` flag in the symbol entry identifies a +symbol as a synthesized namespace projection. Such symbols can be of kind +``sk_namespace_projection`` or ``sk_overloaded_function``. In the latter case, +each of the entries on the list of overloaded functions points to a +``sk_namespace_projection`` symbol. + +Where synthesized namespace projection symbols are used, the lookup must result +in at most one symbol being found, or, all of the symbols found must be +functions that can be combined into an overload set. If more than one symbol +is found and they are not all functions, the lookup is ambiguous. The +``ambiguous`` flag in the symbol entry is set in that case. + +The following steps are used to construct a synthesized namespace projection +symbol for a given lookup: + +#. ``find_synthesized_projection_symbol`` is called to find a previously + created namespace projection symbol. This is done so that the space used + by a previously created synthesized projection symbol can be reused. + The actual information pointed to by the symbol is not reused because it + may have changed since the last lookup was done. More specifically, a + set of overloaded functions is assumed always to contain at least the + functions that were previously in the set. When looking for a previously + created symbol, the lookup options used for the new lookup must match + the options used when the symbol was created. A number of symbols with + the same name but with different lookup options may be created in a + given scope. Some combinations of lookup options are considered to be + sufficiently unusual that they are not entered in the symbol header for + reuse. Such symbols are identified by setting the ``do_not_reuse`` flag in + the symbol entry. ``find_synthesized_projection_symbol`` suppresses the + search and returns NULL when asked to find a symbol with a set of lookup + options for which symbols cannot be reused. The lookup options used when + a synthesized namespace projection symbol is created are stored in a set + of flags in the symbol entry. The flags used for this purpose are + + * | ``qualified_lookup`` + * | ``must_be_class_or_namespace_lookup`` + * | ``must_be_tag_lookup`` + * | ``tentative_type_lookup`` + * | ``do_not_reuse`` + * | ``instantiation_context_lookup`` + +#. | As symbols are found that match the lookup criteria, + ``add_symbol_to_lookup_set`` is called with a pointer to the previously + created synthesized projection symbol (if any) and the symbol to be added. + The symbol returned is used as the new synthesized projection symbol. +#. | ``add_symbol_to_lookup_set`` calls ``merge_function_into_lookup_set`` + when the symbol being added is a function or function template. Before a + function is actually added, the current lookup set is examined, by calling + ``already_in_lookup_set``, to make sure it is not already present. +#. | ``add_symbol_to_lookup_set`` determines whether the symbol being added + can coexist with any symbols already in the lookup set, whether the new + symbol should hide a previous symbol, or whether the lookup is ambiguous. + +Reusable synthesized projection symbols are entered on the "other" symbols list +in the symbol header and on the ``synth_namespace_projection_symbols`` list in +the pointers block for the scope with which they are associated. Symbols that +are not reusable are only entered on the list in the pointers block. +Synthesized projection symbols that are created by a qualified lookup are +entered in the scope of the namespace of the qualifier. All other synthesized +projection symbols are entered into the current scope. + +Overloaded Operators +-------------------- + +Overloaded operators are not looked up by name, so ``find_symbol`` cannot be +used to locate the symbol header. Instead, the header is found by indexing +into the array of symbol header pointers ``opname_symbol_table``. The index +value will be a member of the enumeration ``an_opname_kind``, which maps to the +subset of the enumeration ``a_token_kind`` that comprises those operators +subject to overloading. [#f7]_ + +When an overloaded operator is explicitly named (for instance, ``operator+`` or +``A::operator new``), it is represented by a ``tok_identifier`` "pseudo-token" +somewhat like qualified names. The symbol locator's ``is_operator_name`` flag +will be set and the field ``opname`` will identify the operator being +overloaded. ``make_opname_locator`` is called to set these fields and as well +to create and enter the symbol header if one does not yet exist. Scanning the +token sequence representing an overloaded operator is handled by +``f_get_opname`` , [#f8]_ which does error checking and also deals with +conversion operators (discussed below). + +``nonmember_operator_function_lookup`` is used to find the set of nonmember +overloaded operator functions for a given operator kind and a pair of operand +types. When looking for a nonmember operator function, one must do a normal +(i.e, unqualified) lookup of the operator name, and one must also look up the +operator name in the namespaces of the operand types and the base classes of +the operand types. For each class type, there is a list of namespaces in which +to look for nonmember operator functions. The list is pointed to by the +``operator_lookup_namespaces`` field of the class symbol supplement. The +search is done by looking at both the active and inactive lists from the +appropriate symbol header and checking whether the parent namespace of the +symbol is on the operator lookup namespaces list of one of the operand class +types. Note that only immediate members of the namespaces on the operator +lookup namespaces list are considered. ``using``-directives in those +namespaces have no effect on the lookup. The result of the lookup is a pointer +to a list of entry of kind ``a_symbol_list_entry`` or NULL if no such operator +functions have been declared. Each entry points to a symbol that meets the +lookup criteria. The caller is responsible for freeing the symbol list when it +is no longer needed by calling ``free_list_of_symbol_list_entries``. +``opname_function_symbol`` is a simplified version of +``nonmember_operator_function_lookup`` that is used for looking up new and +delete operators, which cannot be declared in namespaces. + +``global_operator_new_or_delete_symbol`` looks up symbols for the default +versions of operator new and delete at file scope (i.e., ``::operator +new(size_t)`` and ``::operator delete(void*)``), but unlike +``opname_function_symbol`` it will, if no such symbol exists yet, implicitly +declare the function, creating and entering its symbol and adding the routine +entry to the IL. + +Template Conversion Operators +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When a class contains a template conversion operator, the lookup of a +particular conversion operator may require the partial instantiation of the +conversion operator template. For example: + +.. code:: c++ + + struct A { + template operator T(); + }; + int main(){ + A a; + a.operator int(); + } + +Class ``A`` does not contain an ``operator int`` conversion function that can +be found by the normal lookup mechanism. Instead, the lookup operation must +match the required type (``int``) with the available conversion templates to +see if a match can be found. ``look_up_conversion_template_instance`` is +called to look for the matching conversion template. If more than one matching +template is found a symbol that is marked as ambiguous is returned. + +If the result type of the conversion depends on a template parameter, or if the +class type on which the conversion operator is being called is a nonreal class, +it is not possible to find a matching conversion operator. In such cases an +"unknown conversion function" entry is created. This is represented by a +special kind of template parameter constant that contains a pointer to the +conversion result type. + +Constructors and Destructors +---------------------------- + +Several routines search for a constructor or destructor of a particular kind in +a given class. + +``select_default_constructor`` finds the default constructor for a given class. +A default constructor is one that can be called with no arguments. If the +class has no default constructor, an error is issued. + +``select_destructor`` finds the destructor for a given class. If the class has +no destructor, it returns NULL. + +``select_copy_constructor`` finds a copy constructor for a given class. It can +be told to look for a copy constructor that will accept ``const``- or +``volatile``-qualified objects. If no appropriate copy constructor exists, an +error is issued. + +User-Defined Conversions +------------------------ + +Like overloaded operators user-defined conversion functions (or "conversion +operators") cannot be looked up by name. Rather, the symbol header is looked +up by result type, using the linked list of entries of type +``a_conversion_header`` and pointed to by ``conversion_header_list``, as +described earlier. Since all user-defined conversion functions are member +functions, once the symbol header is found, searching for a symbol simply +involves discriminating on the basis of the ``parent.class_type`` field. + +An explicitly named conversion function (e.g., ``operator int()``), is +represented (like overloaded operators) by an identifier token; in its +associated symbol locator ``is_conversion_name`` is TRUE and +``conversion_result_type`` points to a type entry for the result of the +conversion. The routine called to find the conversion header (and thereby the +symbol header) and to set these fields is ``make_type_conversion_locator``. It +also creates the conversion header (as well as the symbol header) if none +exists yet. The token sequence representing a conversion function is scanned +by ``scan_conversion_operator``, which is called from ``f_get_opname``. + +Sometimes the question to be answered in processing an expression is, "What +user-defined conversion function exists to convert an object of class ``A`` to +type ``T``?" In such cases it would be straightforward to find the appropriate +symbol by using the result type to identify the conversion header and then the +class type to choose among the associated conversion function symbols. But at +other times -- for instance, when looking for the best implicit conversion or +when there are inherited conversion functions -- the question is subtly +different: "Which, if any, of the user-defined conversion functions that exist +for class ``A`` is most suitable for converting to type ``T``?" To optimize +answering this question, another construct appears in the symbol table, +``a_conversion_list_entry``, each instance of which points to a symbol entry +representing a conversion function. A class's symbol supplement contains a +pointer to such a list, which is updated in ``decl_member_function`` each time +a conversion function is declared; the list also contains projection symbols to +represent inherited conversion functions (see +``project_base_class_conversion_functions``). + +"Extern" Symbols +================ + +When it is required that distinct declarations in different name scopes refer +to the same entity, an extra symbol is created to represent the shared entity. +For instance, + +.. code:: c++ + + void f() { + extern int i; + } + void g() { + extern int i; + } + extern int i; + +In this example, although all three declarations of ``i`` refer to the same +variable, three independent ``sk_variable`` symbols are created to represent +it, one in the scope of function ``f``, one in the scope of function ``g``, and +one in the file scope. So a fourth symbol is created at file scope to +represent ``i`` -- its kind is ``sk_extern_variable``, and it is created at the +first declaration of ``i``. Then, even after the ``sk_variable`` symbol for +the declaration of ``i`` in function ``f`` goes out of scope, the +``sk_extern_variable`` symbol is still around to be found again on the +subsequent declarations of ``i``; this assures that all three ``i`` symbols +point to the same IL entity. A similar technique, using ``sk_extern_function`` +symbols, is employed for functions. These "extern" symbols are put on the +"other" symbols list instead of being put on either the active or inactive list +and so are not found during normal name lookup. + +The routine that manages all this is ``find_external_symbol``. It also has +special logic, subject to configurable control, to deal with instances in which +different source names resolve to the same "external" name because of object +language constraints -- e.g., where linkers can handle only so many characters +or are not case sensitive. + +Symbol Management +================= + +It remains to describe briefly some of the other low-level routines and macros +used to manage the symbol table and return information about symbols. + +* | ``alloc_symbol`` is called to allocate a symbol entry of a specified kind. + When a NULL symbol header is passed, it allocates an error symbol, one + whose header is ``error_symbol_header``. It calls ``clear_symbol`` and + ``set_symbol_kind`` to initialize the new entities; the latter also + allocates the supplementary constructs for class and projection symbols. + Other routines called to allocate and initialize the entities from which + the symbol table is constructed are + + * | ``alloc_symbol_header``, + * | ``alloc_conversion_header``, and + * | ``alloc_conversion_list_entry`` + +* | ``enter_namespace_projection_symbol`` is called to create new namespace + projection symbols and enter them in the symbol table. Passed a pointer to + the fundamental symbol, it allocates and initializes the symbol and links + it into the symbol table and scope list. This routine is needed because a + namespace projection symbol cannot be entered into the symbol table via + ``enter_symbol`` because that doesn't allow specification/setting of the + fundamental symbol and the fundamental symbol is used by ``enter_symbol`` + for checking compatibility with previous declarations of the name in the + current scope. +* | ``enter_synthesized_namespace_projection_symbol`` creates new synthesized + namespace projection symbols and enters them on the "other" symbols list if + they can be reused. This routine also determines the scope list on which + the symbol should be placed based on the lookup options and the qualifier + namespace, and sets the lookup option fields in the symbol entry. +* | ``enter_symbol`` is called to create new symbols and enter them in the + symbol table. Passed a symbol kind, it allocates and initializes the + symbol, marks it as having been referenced, and links it onto the symbol + header's active list and onto the current scope's symbol list. +* | ``reenter_symbol`` takes an existing symbol (one that may have been entered + already and then removed) and links it into the symbol table. +* | ``full_enter_symbol`` calls ``find_symbol`` to locate the symbol header for + a name and then calls ``enter_symbol``. This is convenient when creating + symbols for the reserved names of keywords and predefined macros (see + ``enter_keyword`` and ``enter_predef_macro`` in ``fe_init.c``). +* | ``link_symbol_into_symbol_table``, called from ``enter_symbol`` and + elsewhere, links a symbol onto the symbol header's active list. Though it + normally ends up adding the symbol to the front of the list, it is careful + to account for special cases by determining the precise location based on + the scope number and name space overloading. It will issue a redeclaration + error when it detects that the name has already been declared in the + current scope. +* | ``add_symbol_to_scope_list`` is also called from ``enter_symbol``; it adds + a symbol to the end of the symbol list [#f9]_ of the scope stack entry at + the specified scope depth. +* | ``enter_overloaded_symbol`` is called to enter a function symbol in the + symbol table when its name is overloaded. First, it allocates and + initializes the ``sk_routine`` or ``sk_member_function`` symbol. Then, if + an ``sk_overloaded_function`` symbol already exists for the name, the new + symbol is added to its list. If not, a new ``sk_overloaded_function`` + symbol must also be created; it will replace the existing function symbol + in the symbol table. +* | ``make_namespace_projection_symbol`` allocates and initializes namespace + projection symbols. A pointer to the fundamental symbol is provided. +* | ``make_projection_symbol`` allocates and initializes ``sk_projection`` + symbols, leaving it to the caller, ``find_projected_symbol``, to add the + new symbol to the symbol table, since it may be inserted in either the + active list or the inactive list of the symbol header. +* | ``make_template_class_symbol`` creates and initializes a symbol for an + instance of a class template. It is linked in the template's instantiation + list rather than added directly to the symbol table. +* | ``make_unnamed_tag_symbol`` is invoked to allocate and initialize a tagless + class, struct, and union symbol. It is not actually entered into the + symbol table since, like error symbols, it uses a special symbol header + (see static variable ``unnamed_tag_symbol_header``). If the class + subsequently acquires a name, ``relink_unnamed_tag_symbol`` is called to + modify the symbol entry and add it to the symbol table. +* | ``unlink_symbol_from_symbol_table`` is called from ``pop_scope`` for each + name that passes out of scope: it removes the symbol from the symbol + header's active symbol list, but the symbol remains on the scope list. +* | ``remove_symbol`` removes a symbol from the symbol table, e.g., for a macro + definition when a ``#undef`` is encountered. + ``unlink_symbol_from_symbol_table`` is called to remove a symbol from the + active list and ``remove_symbol_from_scope_list`` is called to remove it + from the symbol list of the scope stack entry. +* | When cross-reference information is being generated, ``write_xref_entry`` + is called to create a record describing a reference and to write it to the + file indicated by ``f_xref_info``. +* | ``record_symbol_declaration`` is called for every declaration and + definition of a name. It sets the source sequence number if this is the + initial declaration, may set the source position (for initial declarations + and for definitions), optionally calls ``write_xref_entry``, and (when + ``GENERATE_SOURCE_SEQUENCE_LISTS`` is TRUE) calls + ``sym_update_source_sequence_list``. +* | ``mark_defined`` and ``mark_declared`` are macro interfaces to + ``record_symbol_declaration``, for definitions and non-defining + declarations, respectively. +* | ``record_symbol_reference`` is called for nondeclarative references to + symbols. It optionally calls ``write_xref_entry``, specifying the + *kind* of reference (see ``a_symbol_reference_kind``), sets the + symbol's ``referenced`` flag, and may set the ``referenced`` flag in + the IL entry. For variables, it checks for the need to issue a + "used-before-set" warning and calls ``mark_variable_value_set`` if + appropriate. +* | ``mark_variable_value_set`` is called to set the ``value_has_been_set`` + flag in the symbol of a variable or static data member. For a variable + entry that represents function parameter or a handler parameter it also + sets ``param_value_has_been_changed``. +* | ``sym_update_source_sequence_list`` is called (when + ``GENERATE_SOURCE_SEQUENCE_LISTS`` is TRUE) to generate a source sequence + entry for a declaration. (Source sequence lists are discussed in greater + detail in the context of the intermediate language.) +* | ``clear_locator`` is a macro used to clear the fields of a locator and + initialize ``source_position`` to a specified value; + ``set_to_error_locator`` is similar but is used when errors are + encountered. +* | ``set_to_named_error_locator`` turns a locator into an error locator -- but + one that preserves information about the identifier with which the locator + is associated. +* | ``tildize_locator`` takes the locator for an identifier token, turns the + name into a destructor name by prepending a ``~``, calls ``find_symbol`` to + find (or create) the associated symbol header, and returns a locator for + new name. +* | ``change_class_locator_into_constructor_locator`` takes a locator for a + class name (its ``specific_symbol`` field will point to the class, struct, + or union symbol) and modifies it to point to a separate header of the same + name that serves as the header for a constructor. [#f10]_ +* | ``make_opname_locator`` creates a locator to represent a token sequence + consisting of ``operator`` and the token (or token pair) for an + overloadable operator. It looks for the corresponding header in the + ``opname_symbol_header`` array; if none is found, it creates one and adds + it to the array. +* | ``make_type_conversion_locator`` creates a locator to represent a token + sequence consisting of ``operator`` and tokens making up a type name. It + looks for the corresponding header by scanning ``conversion_header_list``; + if none is found, it creates one, along with a new conversion header entry, + and adds the latter to the head of the linked list. +* | ``make_locator_for_symbol`` is called to initialize a locator based on an + already existing symbol. +* | ``set_source_corresp`` is called to establish a correspondence between an + IL entry and a symbol. It links the IL entry back to the symbol. +* | ``set_decl_sequence_number`` is called to set a declaration sequence number + for a symbol. Such numbers identify the sequential position of one + declaration relative to others in the same translation unit. When a name + is multiply declared, the position of its definition is recorded in the + declaration sequence number. +* | A number of macros in ``symbol_tbl.h`` provide the preferred method of + identifying a given symbol's special characteristics: + + * | ``is_class_symbol`` + * | ``is_tag_symbol`` + * | ``is_type_symbol`` + * | ``is_function_symbol`` + * | ``is_member_function_symbol`` + * | ``is_constructor_symbol`` + * | ``is_destructor_symbol`` + * | ``is_copy_constructor_symbol`` + +* | ``type_symbol_type`` is a macro that may be invoked for symbols for which + ``is_type_symbol`` is TRUE; it returns a pointer to the associated type + entry. +* | ``symbol_supplement_for_class`` takes a type entry of kind ``tk_class``, + ``tk_struct``, or ``tk_union`` and returns a pointer to the associated + symbol's class symbol supplement entry. + +Access Control +============== + +The function of access control is to determine whether or not a given name can +be accessed from the current location in the source program. Every reference +to a name, whether qualified or not, whether part of an expression or a type, +is checked to make sure the identifier is unambiguous and accessible. There +are several things to remember about access control: + +* | Only class members are subject to access control. Non-class members are + always accessible. +* | Access control is site-specific. A given member can be accessible from one + place in a program and not accessible from somewhere else. In particular, + members and friends of a class have special access to the members of the + class and its base classes. +* | Access control limits access, not visibility. Members that are not + accessible are still visible. They are found, the access error is issued, + and then (the way the front end does it) they are used anyway. +* | When members are inherited into derived classes, the access to the members + in the derived class is affected by the type of derivation of the derived + class (see ARM 11.2). +* | The same member may have different access in different classes, and may be + accessible at a given point in the program through one qualified name and + not through another. In other words, access control applies to names + rather than objects. +* | A name is ambiguous if the name refers to two or more entities, with no + reason to prefer one over the others. Only inherited class members can be + ambiguous. Ambiguity checking is done before access control checking. + +The problem of access control, then, reduces to "given a symbol for a class +member, which might be a projection symbol, is the member unambiguous and do we +have access to it from the current location in the program?" + +The ambiguity aspect is easily dealt with: the ``ambiguous`` flag in the symbol +indicates whether or not it is ambiguous. The flag can be set only in +projection symbols and in symbols for sets of overloaded functions synthesized +for lookups done in the presence of ``using``-directives. + +Access checking is harder. + +The access to a class member, in its simplest form, is given by the +``source_corresp.access`` field in the member's IL entry. + +When the member is a direct member of a class, there will be a symbol entry +pointing directly to the IL entry, and the access to that symbol is simply the +access indicated in the IL entry. When the member is inherited, however, each +derived class will have a projection symbol that points to the fundamental +symbol. The access to the member through a projection symbol is filtered +through the class derivations that lead to the derived class containing the +projection symbol; that access is indicated in the projection symbol. + +If the simple access in the symbol or in the projection symbol is +``as_public``, then the member is accessible. Otherwise, some kind of member +access privilege is required to access it. + +Member access privileges are available when the current position is inside a +class or a function. Being inside a class confers special access to members of +the class and to classes that have befriended the class. Being inside a +function confers special access to classes that have befriended the function, +and, if the function is a member function, to the class of which it is a member +(and classes that have befriended it). + +The ``scope_stack`` provides the necessary information about the functions +and/or classes that the current position is inside of. + +For there to be special access to a member ``x`` across the derivation +represented by a projection symbol, there must exist a class ``A`` somewhere on +the derivation (including either of the endpoints) such that: + +#. ``A`` is accessible (meaning that its public members are accessible) from + the current position in the program, starting from the most-derived + class on the derivation. In other words, we can implicitly cast a pointer + to the derived class we start with to a pointer to ``A``. + +#. We have member access to ``A``. + +#. ``x`` is accessible in ``A``, meaning that if one starts with the access + to ``x`` in the fundamental class and works outward through the + derivation steps until one gets to ``A``, there is some remaining access + at that point. + +The implementation of the above is broken up as follows: + +* | ``access_for_symbol`` extracts the simple access for a symbol. +* | ``access_to_end_of_path`` determines the effect of a set of derivation + steps on such an access. +* | ``have_access_to_symbol`` determines whether or not there is access to a + symbol. Most of the work is done in ``have_access_across_path``. +* | The macro ``is_accessible_imm_base_class`` determines whether or not a base + class is accessible (ARM 4.6). The macro is also used directly in + determining whether or not base class casts and the like are valid. The + function ``is_accessible_base_class`` is similar, but is not limited to + immediate base classes. +* | ``have_member_access_privilege`` determines whether or not there is member + access privilege to a given class. + | + | When there are ``protected`` members or ``protected`` derivation steps + involved, derived classes can have a limited form of member access (see + ``have_protected_member_access_privilege``). + | + | The additional restrictions on access to protected members of ARM 11.5 + require special processing in the expression routines over and above the + access checking done here. The checking there ends up calling the macro + ``check_protected_member_access``, which in turn calls the function + ``f_check_protected_member_access``. +* | ``check_ambiguity_and_verify_access`` (a macro) is the main interface to + access checking. It in turn calls + ``member_check_ambiguity_and_verify_access`` for class members. + +Overloaded functions pose some special problems, because they are represented +as several symbols (which may have distinct accesses) clustered under one +overloaded function symbol. When the cluster is inherited into a derived +class, a single projection symbol points to the overloaded function symbol. +This means that: + +* | One cannot determine the access to a name in a set of overloaded functions + until one has determined which specific function is being referenced. For + that reason, when an overloaded function symbol is passed through the + normal access checking routines, it is always judged to be accessible. + Note that ambiguity checking can still be done in the usual way. +* | Once one has determined which function is being referenced, one cannot use + the normal interface to the access checking routines, because the + projection symbol does not point to the specific function. + | + | ``overload_check_ambiguity_and_verify_access`` does the access check in + this case on the basis of a projection symbol and a (not directly attached) + specific function symbol. In the presence of member + ``using``-declarations, the specific function symbol can be a projection + symbol. + +It is not possible to determine the access to certain names used in namespace +scope declarations at the point at which the name is seen. In the following +example, the accessibility of ``A::B`` in the declaration of ``A::f`` cannot be +determined until we know we are scanning a declaration of a member of class +``A``. In the friend case, we cannot determine the access to ``A::B`` until we +know the signature of the function being declared, because we have to determine +that it has been befriended by class ``A``. + +.. code:: c++ + + class A { + class B {}; + B f(); + friend B g(B); + }; + A::B A::f(){ B b; return b; } + A::B g(A::B b){ return b; } + +When a namespace scope declaration is processed, a flag is set in the scope +stack indicating that any access errors that occur should, instead of being +issued, be recorded in a list pointed to by the scope stack entry. Later, when +more information about the declaration is available, the accessibility is +rechecked. If the name is now accessible, the entry is removed from the list +of deferred access checks. If it is still not accessible, it will either +remain on the list if the defer access checks flag is still set, otherwise the +error will be issued. + +``begin_deferral_of_access_checks`` and ``end_deferral_of_access_checks`` are +macros used to bracket the processing of a declaration that requires deferred +access checking. + +``perform_deferred_access_checks`` is used to retry the access checks that had +failed earlier, and is called during declarator processing to check the +accessibility of member declarations. This is done after the class +reactivation scope for the member declaration has been pushed. + +For the accessibility of friend declarations to be checked, the scope stack +must contain information about the function that is being declared. The +function access scope fulfills this need. After a complete function +declaration has been scanned, ``perform_deferred_access_checks_for_function`` +is called with a pointer to the routine that has been declared. It pushes a +function access scope and then calls ``perform_deferred_access_checks`` to +determine whether the names are now accessible. + +.. [#f1] Note that symbol entries need two "``next``" pointers: the ``next`` + field is for linking symbols in the active and inactive lists of the + symbol header, and the ``next_in_scope`` field links symbols in the + scope list. +.. [#f2] The selection of a particular function based on function type is not + part of *name* lookup but belongs to another phase of processing. +.. [#f3] Note that it is the depth of the scope entry, not its uniquely + identifying number, that is saved; this value permits indexing + directly into the scope stack array rather than searching through the + scope stack. +.. [#f4] It almost always has the same value as ``depth_scope_stack``. + However, in C mode the scope of a struct or union is not a "real" + scope, in which case ``decl_scope_level`` identifies the block, + function, or namespace scope to which the struct or union belongs. + The depth of the pseudo-scope itself is recorded in + ``depth_scope_stack``. +.. [#f5] Both the symbol and the base class entry are required since it is + legal for a class to be derived from a base class more than once + (even though unqualified member references may be ambiguous); since + each instance of derivation is represented by a unique base class + entry, its presence makes clear which derivation is involved in the + projection. +.. [#f6] Note that a nested class name is treated as hidden by a name that is + visible according to standard lookup rules, even if the latter belongs + to an outer scope. Moreover, no error is reported when there is more + than one qualifying nested class symbol. +.. [#f7] Given a token, one finds the corresponding ``an_opname_kind`` value + with the array ``opname_kind_for_token``. +.. [#f8] ``f_get_opname`` is always invoked by macro ``get_opname``. +.. [#f9] Adding the symbol to the end of the list assures that the list + preserves the declaration order for the scope. +.. [#f10] As described above, the constructor header is not in the symbol + table and consequently will not be found by ``find_symbol``. diff --git a/doc/_sources/tables.rst.txt b/doc/_sources/tables.rst.txt new file mode 100644 index 0000000..059ba21 --- /dev/null +++ b/doc/_sources/tables.rst.txt @@ -0,0 +1,665 @@ +================ +Table Management +================ + + + + +For a description of the intermediate language itself, see +:ref:`intermediate-language`. + +The source file ``il_alloc.c`` contains routines to allocate and clear the +intermediate language tables, and ``il.c`` contains routines to debug-print +them. These routines should always be used, so that new tables are always set +to the proper default values and problems with undefined fields are avoided. +``il_def.h``, ``il_alloc.h``, and ``il.h`` contain associated declarations. + +Note that some of these routines should not be called from a back end, because +the front end data structures they need are no longer set up properly at that +point. In general, routines that allocate new storage or new entries should +not be called, and routines that answer questions about existing entries are +okay to call. The + +.. code:: c++ + + #if !STANDALONE_UTILITY_PROGRAM + +guards indicate routines that should not be called by back ends. + +Storage Allocation +------------------ + +``alloc_cil`` has an interface like ``malloc``; it allocates space in the +current intermediate language memory region. ``new_il_region`` begins a new +intermediate language memory region. ``switch_il_region`` switches to a +previously-created region. ``alloc_il`` allocates space in the file-scope +intermediate language memory region. + +When the alternate IL file format is used, space is reserved preceding each IL +entry so that the IL entry number can be stored there. + +Constant Entries +---------------- + +Constant entries (type ``a_constant``) are usually allocated by +``alloc_constant``; ``fs_constant`` is similar to it but allocates the constant +entry at the file scope. ``make_zero_of_proper_type`` makes a zero constant of +a given type. ``clear_constant`` and ``set_constant_kind`` are called to +re-initialize existing constant entries, and ``set_error_constant`` changes an +existing constant entry to an error constant. + +In most cases, a constant entry need not be unique -- the same entry can be +used for all occurrences of a given literal constant. For these cases, one +should call ``alloc_shareable_constant`` instead of ``alloc_constant``. (The +interface is slightly different; one passes a filled-in constant entry rather +than just a kind.) ``alloc_shareable_constant`` maintains +``shareable_constants_table``, a hash table that is searched by hashing a +constant entry to a bucket number (routine ``hash_constant``), then searching a +linked list of constants in that bucket to see if there is a match (comparison +is done by ``eq_constants``). If an entry is found, it is reused. If none is +found, one is entered into the table. + +In cases where the constant entry cannot be shared (as when it must be linked +into an initializer list), ``alloc_unshared_constant`` should be called +instead. It basically just calls ``alloc_constant``, but adjusts a few things +in the constant entry. + +Type Entries +------------ + +Type entries (type ``a_type``) are allocated by ``alloc_type``. + +``integer_type``, ``fixed_point_type``, ``float_type``, ``string_type``, +``void_type``, and ``error_type`` can be called to create type entries for the +most common types; these routines will reuse the entries once they have created +them. ``make_pointer_type`` creates a pointer type pointing to a given base +type. It uses the routine ``get_based_type`` to determine if a pointer to the +type has already been created, and it calls ``add_based_type_list_member`` to +record the fact that a pointer type has been allocated. +``make_reference_type`` is the similar routine for (lvalue) reference types, +and ``make_rvalue_reference_type`` is the similar routine for rvalue reference +types. ``ptr_to_member_type`` is the similar routine for pointer-to-member +types. + +``make_qualified_type`` is used to add type qualifiers to an existing type; +``make_unqualified_type`` is used to remove them. + +``unknown_type`` creates an unknown type entry; such an entry is used as a +place-holder within the front end and the references to it must be eliminated +before the back end is called. Another type that is normally not seen by the +back end (unless prototype instantiations are recorded in the IL) is the +template parameter type, which is used in processing template declarations. + +There are several routines that allocate various pieces of the description of a +class type: + +* | ``alloc_derivation_step`` +* | ``alloc_base_class_derivation`` +* | ``alloc_overriding_virtual_function`` +* | ``alloc_base_class`` +* | ``alloc_list_entry_for_class`` +* | ``alloc_class_type_supplement`` + +Other Declarative Entries +------------------------- + +``alloc_variable``, ``alloc_field``, ``alloc_label``, and ``alloc_routine`` +allocate variable, field, label, and routine entries. They do nothing terribly +interesting. ``remove_from_routines_list`` can be used to remove a routine +from the routines list so that it can be added again at the position where its +actual definition appears. + +Routines that allocate other IL entities resulting from declarations include: + +* | ``alloc_param_type`` allocates a param-entry pointed to from the routine + type supplement of a ``tk_routine`` type entry. +* | ``alloc_template``, ``alloc_template_arg`` and + ``alloc_template_param_type_descr`` are used in template processing. +* | ``alloc_namespace`` allocates an entry to represent either a namespace or a + namespace alias. +* | ``alloc_using_decl`` allocates an entry to represent a ``using``-directive, + a member ``using``-declaration, or a nonmember ``using``-declaration. +* | ``alloc_macro`` allocates an entry representing a macro definition (when + ``RECORD_MACROS_IN_IL`` is set). +* | ``alloc_pragma`` allocates an entry representing a ``#pragma`` declaration. +* | ``alloc_asm_entry`` allocates an entry representing an ``asm`` declaration. + To support certain extensions (i.e., when ``ASM_FUNCTION_ALLOWED`` is set) + ``alloc_asm_function_body`` is also available. +* | ``alloc_scope`` allocates a scope entry. +* | ``alloc_ctor_init`` allocates a constructor-initializer entry, a list of + which is recorded in the scope entry associated with a constructor. +* | ``alloc_temporary_variable`` allocates a variable entry for a temporary. +* | ``alloc_dynamic_init`` allocates a dynamic initialization entry, used + (among other things) to represent dynamic initialization on variable + declarations. +* | ``alloc_local_static_variable_init`` allocates an entry used to represent + the initialization of a function-local variable with static storage class. +* | ``alloc_list_entry_for_routine`` allocates an entry used to record a list + of routine entries (used to support ``friend`` declarations). +* | ``alloc_exception_specification`` allocates an entry that represents an + exception specification in a function declaration. +* | ``alloc_accessible_base_class`` allocates an accessible base class entry + (unused in implementations in which ``ABI_CHANGES_FOR_RTTI`` is set). +* | ``alloc_hidden_name`` allocates a hidden-name entry (for use by the + C++-generating back end, when ``RECORD_HIDDEN_NAMES_IN_IL`` is set). + +Expressions +----------- + +``alloc_expr_node`` allocates an expression node. + +``set_expr_node_kind`` and ``clear_expr_node`` re-initialize existing entries. +``make_operator_node`` creates an expression node for an operation. + +``set_node_operator`` changes the operator or type in an existing operation +expression node. + +``error_node`` makes an error expression node (a new one on each call, since +executable constructs cannot be shared). + +There are several utility routines that help in constructing expressions: + +* | ``alloc_node_for_constant`` builds an expression node that points to a + constant entry. +* | ``node_for_integer_constant`` builds an expression node for an integer + constant. +* | ``var_lvalue_expr`` builds an expression node for a variable as an lvalue. +* | ``var_rvalue_expr`` builds an expression node for a variable as an rvalue. +* | ``var_addr_expr`` builds an expression node for the address of a variable. + The ``address_taken`` flag is set. +* | ``function_lvalue_expr`` builds an expression node for a function as an + lvalue. +* | ``function_rvalue_node`` builds an expression node for a function as an + rvalue, i.e., for the address of the function. This is suitable for + calling the function, but not for the "``&``" operator applied to the + function, because the ``address_taken`` flag is not set. +* | ``function_addr_expr`` builds an expression node for the address of a + function. The ``address_taken`` flag is set. +* | ``rvalue_expr_for_lvalue`` converts an lvalue expression to an rvalue. It + also works for function lvalues, but not for arrays. +* | ``add_indirection_to_node`` adds an indirection ("``*``" operator) to an + expression. +* | ``add_ref_indirection_to_node`` adds the reference equivalent of + "``*``" to an expression. +* | ``add_address_of_to_node`` adds a "``&``" operator to an expression. +* | ``add_reference_to_to_node`` adds the reference equivalent of "``&``" to an + expression. (Note that that is not a typo; the name really does have + "``to_to_``" in it.) +* | ``field_lvalue_selection_expr`` builds an expression for a field selection + that produces an lvalue. +* | ``field_rvalue_selection_expr`` builds an expression for a field selection + that produces an rvalue. + +``copy_expr_tree`` makes a copy of an expression tree. When it does so, it can +optionally "clone" any temporary variables found within the tree so that the +copy uses different but equivalent temporaries. + +In addition, ``alloc_lowered_eh_construct_node`` allocates an expression node +to represent one of several (partially) lowered exception handling constructs +(used only when IL lowering is enabled and ``DO_FULL_PORTABLE_EH_LOWERING`` is +configured to FALSE. + +Statements +---------- + +``alloc_statement`` allocates a statement (which may allocate a supplement of +type ``a_for_loop``, ``a_switch_stmt_descr``, etc.). +``alloc_switch_case_entry`` allocates the entry used to represent one case +(possibly, the "``default:``" case) of a ``switch`` statement. + +Object Lifetimes +---------------- + +``alloc_object_lifetime`` allocates an object lifetime entry, and +``bind_object_lifetime`` binds it to a specified IL entry (a scope, an +expression, a dynamic init, etc.). + +A dynamic init entry with a destructor is added to the destructions list of an +object lifetime by ``record_end_of_lifetime_destruction``, which calls +``add_to_destructions_list``. Conversely, it is removed from the list by +``remove_from_destructions_list``. + +During front-end processing object lifetime entries are pushed onto the object +lifetime stack (see ``push_object_lifetime`` and global variable +``curr_object_lifetime``, which is the top of the stack) and popped off the +stack when appropriate (see ``pop_object_lifetime``). + +If, when it is popped off the object lifetime stack, the entry is not actually +required in the IL (see ``is_useless_object_lifetime``), it is unbound from the +IL entry with which it is associated (see ``unbind_object_lifetime``) and +placed on an available list for reuse (see ``free_object_lifetime``). + +Source Sequence Entries +----------------------- + +Source-sequence entries are created only when +``GENERATE_SOURCE_SOURCE_SEQUENCE_LISTS`` is configured to TRUE. See +:ref:`intermediate-language` for additional information. + +``f_update_source_sequence_list`` creates new source sequence entries and adds +them to the appropriate list. + +* | For declarations it is called by ``sym_update_source_sequence_list`` (in + ``symbol_ref.c``), which also calls ``alloc_src_seq_secondary_decl`` when + the declaration is not a primary declaration. +* | For statements it is called by ``stmt_update_source_sequence_list`` (in + ``statements.c``). +* | In certain other cases -- e.g., for the declaration of unnamed ``enum`` + types, for which there is no symbol -- it is called via macros + ``update_source_sequence_list`` and ``add_to_source_sequence_list``. + +Other functions called to create and manage source sequence lists include: + +* | ``alloc_source_sequence_entry`` allocates and initializes a source-sequence + entry. +* | ``add_source_sequence_entry_to_list`` is called to add entries to the end + of the list of the current scope stack entry (see ``source_sequence_list`` + in ``a_scope_stack_entry``). When ``pop_scope`` is called, the list for a + given scope stack entry is either appended to the list of the enclosing + scope stack entry or, for function scopes and the file scope, moved to the + associated IL scope (see ``source_sequence_list`` in ``a_scope).`` +* | ``add_empty_source_sequence_entry`` creates and adds a source sequence + entry that does not yet point to an IL entry. Such entries are + placeholders to reserve a position in the list for a declarator when the + particular IL entry it represents is not yet known; they do not persist + beyond the front end. +* | ``add_end_of_construct_source_sequence_entry`` creates a source sequence + entry to mark the end of a construct for a given entity (see + ``alloc_src_seq_end_of_construct)`` and adds it to the current source + sequence list. (See also :ref:`src-seq-lists`.) +* | ``make_source_sequence_secondary_decl`` creates a source sequence entry to + represent a non-defining declaration (see ``a_src_seq_secondary_decl``), + and ``set_src_seq_secondary_decl_fields`` can be called to locate the entry + on the current source sequence list (see + ``last_matching_source_sequence_entry``) and to update various of its + pointers and flags. +* | When either ``CLASS``- or + ``NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS`` is TRUE, + ``add_source_sequence_entry_for_partial_instantiation`` is called to enter + a secondary declaration entry to represent the declaration of a + compiler-generated template specialization that stands for a template + instantiation, and when the body of such a specialization is generated, its + source sequence list is added by ``insert_instantiation_src_seq_list``; in + both cases, ``find_instantiation_insert_scope`` is called to locate the + point at which the instantiation should be inserted in the source sequence + list (since it is not necessarily at the end of the list for the current + scope stack entry). +* | ``insert_src_seq_list`` inserts a list into another list at a specified + point; it is also called to append a list to another list. +* | ``remove_from_source_sequence_list`` removes a given source sequence entry + from its list; see also macros ``unlink_src_seq_entries`` and + ``unlink_src_seq_entry`` (which operate on source sequence lists and single + entries, respectively). +* | ``fixup_function_scope_source_sequence_list`` creates both a sublist header + (see ``alloc_src_seq_sublist``) and the source sequence entry that points + to it. + +Lists of Entries +---------------- + +The routines + +* | ``add_to_constants_list``, +* | ``add_to_types_list``, +* | ``add_to_variables_list``, +* | ``add_to_parameters_list``, +* | ``add_to_dynamic_inits_list``, +* | ``add_to_routines_list``, and +* | ``add_to_labels_list`` +* | ``add_to_namespaces_list`` +* | ``add_to_using_decls_list`` +* | ``add_to_asm_entries_list`` +* | ``add_to_templates_list`` +* | ``add_to_macros_list`` +* | ``add_to_pragma_list`` + +add entries of the indicated type to end of the list of similar entries under a +scope entry. The scope will vary depending on the type of entry and what the +caller specifies. In many cases it is either the current scope or the +innermost namespace scope that is used (e.g., variables, constants, types). +Routines that are not class members are added to the list for the file scope or +a namespace scope. Labels are always added to an ``sck_function`` scope. And +so forth. + +There is also an ``add_to_scopes_list``; it is called by ``create_block_scope`` +when a scope for a statement block is created. Special handling is required +because the IL scope for a block is not created until there is some declaration +in that block. + +Orphaned Entries +---------------- + +Orphans are entries in the file scope memory region that are referenced only +from function scope memory regions. When the parents of such entries are +written out and then removed from memory, the entries are orphaned because they +are not attached to the rest of the file-scope IL tree. + +The orphan mechanism makes lists of such entries so that they can be found +during traversal of the file-scope IL. In the file scope, each entry is +preceded by space for an orphan-list pointer. When a potential orphan entry is +encountered, for example when an entry in a function scope memory region points +to an entry in the file scope memory region, +``add_orphaned_file_scope_il_entry`` is called. It adds the potential orphan +to a list of entries of its type headed by the proper element of the array +``orphaned_file_scope_il_entries`` and linked by the hidden pointer. An entry +is ignored if it is already on the list (which can be discerned from the fact +that the orphan-list pointer is already non-NULL or the fact that the entry +address matches the last-on-list pointer for that entry type). + +There is also a special mechanism for keeping track of the lists of local +static variables and types in function and block scopes. These are lists that +are entirely in the file scope memory region but originate with a pointer that +is in a function scope memory region. To keep track of these, entries of type +``a_scope_orphaned_list_header`` are allocated in the file scope memory region +and attached to the ``il_header``. Each entry contains a copy of the static +variables and types pointers from a function or block scope, so that the lists +can be visited in the file scope memory region even if the associated function +scope memory region is no longer in memory. See +``add_scope_orphaned_il_lists``. + +Source File Information +----------------------- + +``record_start_of_source_file`` and ``record_end_of_source_file`` build +information about the correspondence between source files and sequence numbers. +Basically, this is a tree that shows the nesting of include files, with added +entries to show the information provided by ``#line`` directives. These +routines are called from ``push_input_stack`` and ``pop_input_stack`` in +``lexical.c``, and ``proc_line`` in ``preproc.c``. +``conv_seq_to_file_and_line`` uses that data structure to map sequence numbers +into file names and line numbers. + +Debug Print Routines +-------------------- + +The following debug-print routines can be used to display intermediate language +constructs for debugging purposes: + +* | ``db_name`` +* | ``db_type_name`` +* | ``db_name_linkage`` +* | ``db_type`` +* | ``db_abbreviated_type`` +* | ``db_access_control`` +* | ``db_field`` +* | ``db_static_data_member`` +* | ``db_member_function`` +* | ``db_virtual_function_info`` +* | ``db_constant`` +* | ``db_variable`` +* | ``db_expression`` +* | ``db_dynamic_initializer`` +* | ``db_initializer`` +* | ``db_statement`` +* | ``db_statement_list`` +* | ``db_object_lifetime`` +* | ``db_object_lifetime_stack`` +* | ``db_scope`` +* | ``db_source_sequence_entry`` + +Types +===== + +The routines and data structures described in this section are defined in +``types.c`` and ``types.h``. These are routines that manipulate intermediate +language types in various ways. They answer questions about them, and do +various language transformations on them. + +Typerefs +-------- + +In type trees, typedefs, type qualifiers (e.g., const and volatile), type +operators such as decltype, and various other types are represented by an entry +called a typeref. It indicates a reference to an existing type. For qualified +pointer types, the ``typeref`` indicating the qualifier is on top of the +pointer type: for ``int *const q`` the type is a ``const``\ ``typeref`` +pointing to a pointer type entry, which points to an entry for ``int``. Macros +``get_type_qualifiers`` and ``get_top_level_type_qualifiers`` (the former may +check for qualifiers on the underlying array element type, the latter does not) +call ``f_get_type_qualifiers`` when appropriate, returning a bit set (see +``a_type_qualifier_set``). + +It is often necessary for code that deals with types to access the target of a +typeref or chain of typerefs. Various convenience functions are provided for +this purpose, including skip_typerefs, skip_typerefs_not_typedefs, +skip_lexical_typerefs, etc. + +Asking Questions About Types +---------------------------- + +There are many predicates that determine whether or not a given type is of a +given kind. Having predicate functions (instead of doing the testing by direct +coding) is necessary because of the possibility of there being ``typeref`` +entries on a type. These predicates are implemented as functions, although +they could be implemented as macros for any cases where it seems desirable. +Within ``types.c``, macros are used so as to avoid having one predicate routine +call a half-dozen others to get an answer. The predicate macros have the same +names as the corresponding predicate functions, with the final ``_type`` of the +name removed (i.e., ``is_integral`` corresponds to ``is_integral_type``). They +do not call ``skip_typerefs``. + +The predicate functions are + +* | ``is_error_type`` +* | ``is_function_type`` +* | ``is_incomplete_type`` +* | ``is_object_type`` +* | ``is_void_type`` +* | ``is_integral_type`` +* | ``is_signed_integral_type`` +* | ``is_enum_typeis_integral_or_enum_type`` +* | ``is_character_type`` +* | ``is_fixed_point_type`` +* | ``is_floating_type`` +* | ``is_arithmetic_or_enum_type`` +* | ``is_pointer_type`` +* | ``is_reference_type`` +* | ``is_lvalue_reference_type`` +* | ``is_rvalue_reference_type`` +* | ``is_ptr_or_ref_type`` +* | ``is_scalar_type`` +* | ``is_array_type`` +* | ``is_char_array_type`` +* | ``is_class_struct_union_type`` +* | ``is_complete_class_struct_union_type`` +* | ``is_union_type`` +* | ``is_aggregate_or_union_type`` +* | ``is_polymorphic_class_type`` +* | ``is_ptr_to_member_type`` +* | ``is_template_class_type`` +* | ``is_template_param_type`` +* | ``is_nullptr_type`` + +Macros that may be called to get information about the type (when +``skip_typerefs`` is not to be called) include + +* | ``is_immediate_error_type`` +* | ``is_immediate_class_type`` +* | ``is_qualified_type`` +* | ``is_const_qualified_type`` +* | ``is_volatile_qualified_type`` +* | ``is_top_level_qualified_type`` +* | ``is_top_level_const_qualified_type`` +* | ``is_top_level_volatile_qualified_type`` + +(Among those that check type qualifiers, the ``is_top_level_``\ *xxx* versions +differ from the others in not checking for qualifiers on underlying array +element types.) Other type qualifiers besides ``const`` and ``volatile`` may be +recognized; for instance, when support for ``restrict`` is enabled, +``is_restrict_qualified_type`` and ``is_top_level_restrict_qualified_type`` are +also defined. + +``is_illegal_abstract_class_type`` returns TRUE if the type is that of an +abstract class, struct, or union, or if it is an array of abstract class +objects, or if it is pointer or reference to an array of abstract class +objects. + +``int_kind_is_signed`` determines whether a given integer kind is a signed +type. + +There are in addition some predicate functions that examine an entire type +tree, if necessary, to return information about a type: + +* | ``is_or_contains_local_type`` +* | ``is_or_contains_unnamed_or_local_type`` +* | ``is_or_contains_template_param`` +* | ``is_or_contains_specific_template_param`` + +These routines call ``traverse_type_tree``, a generic type-walking routine; it +is passed the address of a service routine that examines a node in the type +tree, and its detailed behavior is governed by setting some combination of +flags (see ``a_type_tree_traversal_flag_set``). + +Another set of predicates tests C++/CLI types and can be used only inside +``#if`` guards for ``MICROSOFT_EXTENSIONS_ALLOWED:`` + +* | ``is_handle_type`` +* | ``is_managed_nullptr_type`` +* | ``is_ref_class_type`` +* | ``is_value_class_type`` +* | ``is_managed_class_type`` +* | ``is_standard_class_type`` +* | ``is_cli_interface_type`` +* | ``is_tracking_reference_type`` +* | ``is_handle_or_tracking_ref_type`` +* | ``is_interior_ptr_type`` +* | ``is_pin_ptr_type`` +* | ``is_cli_array_type`` +* | ``is_handle_to_cli_array_type`` +* | ``is_cli_generic_param_type`` +* | ``is_cli_generic_constraint_type`` +* | ``is_boxable_type`` +* | ``is_delegate_type`` +* | ``is_cli_system_object_type`` +* | ``is_cli_system_string_type`` + +To ease pointer/reference/handle tests in code that might have to deal with +C++/CLI types, the following test certain general categories of pointers and +references: + +* | ``is_any_reference_type`` +* | ``is_any_ptr_or_ref_type`` +* | ``is_pointer_or_handle_type`` +* | ``types_are_both_pointers_or_both_handles`` + +Taking Apart Types +------------------ + +Given an array type, ``array_element_type`` and +``underlying_array_element_type`` return the type of an element; the second +deals with multidimensional arrays. ``type_pointed_to`` is used to get the +base type from a pointer or reference type. ``pm_member_type`` and +``pm_class_type`` extract the base types from pointer-to-member types. +``underlying_type_of_derived_type`` extracts the underlying type for all +derived types (pointer, pointer-to-member, array, etc.). + +Given a C++/CLI array type, ``cli_array_element_type`` returns the type of the +element. ``cli_array_rank_constant`` and ``cli_array_rank`` return the rank +(number of dimensions) of the array in different forms. + +Setting Sizes and Alignments of Types +------------------------------------- + +The size and alignment for a type are recorded in the type entry (except for +``typeref``\ s, which have their sizes and alignments dictated by the type they +refer to). These values, however, are not set all over the front end, but only +by isolated routines. The main routine is ``set_type_size``, which will set +the size of an arbitrary type. The type must be completely built by the time +this routine is called. ``set_type_size`` calls ``set_array_type_size`` for +arrays. Size and alignment for class types are set by code in ``layout.c``. + +Modifying Type Trees +-------------------- + +``set_used_in_exception_or_rtti_flag`` is called for types that appear as the +type of a throw object, in an exception specification list, as the type of a +handler, or in a ``typeid`` operator. It sets the type entry's +``used_in_exception_or_rtti`` flag. To assure that such types have external +linkage, it also calls ``set_force_external_linkage_flag``, which in turn calls +``traverse_type_tree`` to mark all the components of the type tree that have +linkage. + +``strip_local_typedefs`` is called to remove all local ``typedef`` components +of a type tree. It calls ``traverse_and_modify_type_tree`` to help accomplish +this task. If a subtree of the type tree is modified, a new type tree is built +to accommodate the change. + +Getting Information About Base Classes +-------------------------------------- + +``find_base_class_of`` returns a pointer to a base class entry if a given class +type is represented on the base classes list of another class type. Similar +functionality, but with the implied restrictions, is provided by +``find_direct_base_class_of`` and ``find_direct_or_virtual_base_class_of``. +``related_class_pointers`` will do the same for pointers to classes. + +``corresponding_base_class``, given a base class belonging to one class, +searches the base classes of another class, finds the corresponding entry, and +returns a pointer to it. + +``is_on_any_derivation_of`` returns TRUE if a given base class is on the +derivation of another base class. + +Routines that Implement Language Concepts +----------------------------------------- + +The routines described in this section implement concepts of the C or C++ +languages. + +Two routines handle type promotions: ``type_after_integral_promotion`` +determines the type that results from integral promotion done in an expression, +and ``default_argument_promotion`` determines the type of an argument to a +function with old-style parameter declarations after default promotion. See +also ``type_after_bit_field_integral_promotion`` in ``exprutil.c`` for a +special case involving bit-fields. + +Several routines compare two types to see if they are compatible in some way. +``identical_types`` determines whether the two types are structurally identical +(they don't have to be the same pointer). ``il_identical_types`` sees if the +two types are identical from an IL perspective (e.g., ``int`` and ``long`` +might be identical if the front end is configured that way). +``types_are_compatible`` sees if two types are compatible (C standard, +3.1.2.6). (Those three names are actually macros which call +``f_identical_types`` and ``f_types_are_compatible`` only if the type pointers +are not exactly the same.) ``interchangeable_types`` sees if two types are +interchangeable as arguments to functions (basically, this is true if they are +compatible except for signedness issues). + +``impl_pointer_conversion`` determines whether or not an implicit conversion +from a given type to a given pointer type is valid, with some special cases for +pointers to ``void`` and for null pointer constants. + +``impl_conversion_possible`` determines whether or not an implicit conversion +from a given type to another is valid. ``impl_ptr_to_member_conversion`` +handles the subcase of implicit conversion of one pointer-to-member type to +another. + +``expl_conversion_possible`` determines whether or not an explicit conversion +(cast) from a given type to another is valid. It relies on two subroutines for +the major subcases: + +* | ``static_cast_conversion_possible`` and +* | ``reinterpret_cast_conversion_possible``. + +``composite_type`` develops a composite type from two types (C standard, +3.1.2.6). + +``overload_distinguishable`` determines whether or not two function types are +sufficiently different that they can be distinguished by overload processing +(and therefore routines with those types can be overloaded). + +``impl_handle_conversion`` determines whether or not an implicit conversion +from a given type to a given C++/CLI handle type is valid. + +``boxing_conversion_possible`` determines whether a conversion from one given +type to another is a C++/CLI boxing conversion. The cases accepted convert a +value type to a handle to that value type. + +``unboxing_conversion_possible`` determines whether a conversion from one given +type to another is a C++/CLI unboxing conversion. The cases accepted convert a +handle type to a value type. + +``system_type_from_fundamental_type`` and ``fundamental_type_from_system_type`` +are a pair of functions that convert back and forth between fundamental types +and the corresponding C++/CLI value class types (e.g., between ``int`` and +``System::Int32``). diff --git a/doc/_sources/templates.rst.txt b/doc/_sources/templates.rst.txt new file mode 100644 index 0000000..91535b9 --- /dev/null +++ b/doc/_sources/templates.rst.txt @@ -0,0 +1,2823 @@ +.. _templates: + +========= +Templates +========= + +Support for template declarations and the instantiation of classes and objects +based on templates is found principally in ``templates.c``; ``templates.h`` +contains the associated declarations. + +Overview +======== + +Template support is almost entirely a front-end issue. By default, templates +themselves are not represented in the IL, and classes and functions that are +generated on the basis of templates look just like any other class or function. +The exceptions to this rule are: + +* | Classes, functions, variables, and aliases generated from templates + identify the associated template arguments, because those arguments may + be needed in generating the name of the entity. +* | In automatic instantiation mode additional flags are provided in the + variable and routine entries so that the information provided by the flags + may be represented in the resulting object file in some form. +* | A template IL entry is created for each template declaration. When + ``PROTOTYPE_INSTANTIATIONS_IN_IL`` is TRUE, the entry points to a + "prototype instantiation", which is an IL entry that represents the entity + declared by the template. When ``RECORD_TEMPLATE_STRINGS`` is TRUE, the + entry contains a null-terminated string that represents the template + declaration. The IL template entry is also used to represent the value of + a template template argument. +* | The template instantiation mechanism may require support in the back end. + For example, if each instantiation is placed in its own object file, the + back end must recognize the data structures provided to accomplish this. + +Generally speaking, when a template definition is scanned, the definition of +the template is saved and then used later to generate instances of the +template. There are two common techniques used by compilers to save the +definition of a template: in the first technique, the template is parsed +(without semantic analysis) and the parse tree is saved; in the second, some +unparsed (more or less textual) representation of the template is saved. A +parse tree may be a reasonable choice for a multi-pass front-end featuring a +separate parser. However, in the EDG C++ front end (which uses a single pass +approach in which parsing and semantic analysis are done together), a textual +representation, which we call a "token cache", is more appropriate. Correctly +implemented, the two techniques are semantically equivalent. + +When using exported templates (see :ref:`exported-templates`) the front end +reloads the translation unit(s) that define the exported templates that require +instantiation so that the information from all of the translation units is +available to the front end. Even though there is a great deal of special +processing required to make exported templates work properly, the underlying +mechanism of rescanning tokens from a token cache is still used to produce the +actual instantiation. + +Since the method one chooses to record the definition of the template affects +the data structures used in the implementation and also influences the +terminology used to describe them, it will be helpful to introduce some terms +that are used in the EDG C++ front end: + +* | A *template* denotes a sequence of tokens that, along with one or more + template parameters and a declarative context, is used as the basis for + generating an *instance* of the template. + | + | A template entity may be + + * | a class template (e.g., class ``A``), + * | a function template (e.g., function ``f``), + * | a member function of a class template (e.g., ``A::f``), + * | a static data member of a class template (e.g., ``A::t``), + * | a nested class of a class template (e.g., ``A::B``), + * | a member class template (e.g., ``A::C``), + * | a member function template (e.g., ``A::g``), + * | a variable template (e.g., ``x``), + * | an alias template, or + * | a partial specialization of a class template, member class template, + or variable template. + + | For example, + + .. code:: c++ + + template void f(T); // function template + template class A { // class template + T f() { return t; } // member function of class template + static T t; // static data member of class template + struct B {}; // nested class of class template + template void g(U); // member function template + template struct C {}; // member class template + template struct C {}; // partial specialization + template static U vt; // member variable template + }; + template T x = 1; // variable template + template using B = A; // alias template + +* | A *template parameter* refers to a template formal argument, and a + *template argument* is a template actual argument. +* | A *template instance* is a class (sometimes called a *template class*) + generated on the basis of a class template, an alias (i.e., typedef, + sometimes called a *template alias*) generated on the basis of an alias + template, a function (sometimes called a *template function*) generated on + the basis of a function template, or a variable (sometimes called a + *template variable*) generated on the basis of a variable template. In + addition, a member function or static data member of a template class is + itself an instance of the corresponding member function or static data + member of the class template. For example, + + .. code:: c++ + + template class A { + static T t; + T f() { return t; } + }; + A ai; + template T g(T t) { return t; } + int i = g(0); + + | With the declaration of ``ai`` an instance of class template ``A``, namely, + ``A``, is generated, and in the process instances ``A::f`` and + ``A::t`` are also generated. Similarly, the reference to ``g(int)`` + causes an instance of function template ``g`` to be generated. +* | In many cases instances of variable templates and static data members of + template classes are treated similarly. The term "template variable" is + used to refer to both cases, unless otherwise specified. +* | The generation of an instance of a template is called *instantiation*. + (Sometimes the result of instantiation, namely an instance, is also called + an instantiation.) +* | An instantiation may be either a *partial instantiation* or a *full + instantiation*. A partial instantiation of a class template is like a + declaration of an ordinary class when no body is supplied; similarly, a + partial instantiation of a function template is like a declaration of a + function without a function body. On the other hand, a full instantiation + is the generation of a class or function definition -- i.e., it includes + the body. For instance, + + .. code:: c++ + + template class A {}; + A *pal; + A ai; + + | In this case the declaration of ``pal`` causes the partial instantiation of + ``A`` -- that is, no body needs to be generated -- whereas the + declaration of ``ai`` causes the full instantiation of ``A``. The + instantiation of an alias template is always a full instantiation. +* | The first time a class template is scanned -- partly to record its member + functions, static data members, nested classes, and friend declarations, + and partly to check for errors -- the result is referred to as a *prototype + instantiation* of the class template, and the class produced is called a + *"nonreal" class*; in general, a template class based on template arguments + that include at least one template parameter is called "nonreal". In + addition, a template class based on a template that is a member of a + nonreal class is also called "nonreal". Consider this example: + + .. code:: c++ + + template struct A { + template struct X {}; + }; + template struct B { + A a; + typename T::X x; + }; + B > b; + + | In this example, when class template ``A`` is scanned, the prototype + instantiation produces nonreal class ``A``, and during the scanning of + class template ``B`` nonreal classes ``A`` and ``T::X`` are + generated. Subsequently, when ``b`` is declared and ``B >`` is + instantiated, ``A``, a real class, is instantiated to serve as the + type for member ``B::a``, and ``A::X`` is instantiated to + serve as the type for member ``B::x``. +* | A prototype instantiation is also performed for alias templates resulting + in a nonreal alias. Nonreal aliases are also created for instantiations of + alias templates if the template argument list depends on a template + parameter. Unlike nonreal classes, nonreal aliases are actually + instantiated by rescanning the tokens of the alias. +* | Nested classes of class templates are not themselves referred to as + templates, but their member functions and static data members are, + respectively, member functions of class templates and static data members + of class templates, and a member function or static data member of a class + nested within a template class is handled as an instance of the + corresponding member function or static data member from the class + template. A class nested within a nonreal class is considered a nonreal + class. +* | The definition of a template instance may be supplied explicitly by the + user instead of being generated based on the template. Such instances are + referred to as *explicit specializations* of the template. +* | A class template or variable template may be *partially specialized*. A + partial specialization is an alternate version of the template that is used + to generate instances whose template argument lists match a specified + pattern. For example, a partial specialization could be provided that will + be used to generate all instances for which a specified template argument + is a pointer type. + + .. code:: c++ + + template struct A {}; // primary template + template struct A {}; // partial specialization + + | The template that is specialized by a partial specialization is called + the *primary template*. +* | Function templates may be overloaded with normal functions and with other + function templates. Overload resolution is used to select the function or + template to be used for a given call. If, as a result of overload + resolution, there are two or more templates that could generate equivalent + functions, *partial ordering* rules are used to select the template to be + used. Partial ordering is different from partial specialization in that + there is no relationship between the function templates being ordered (i.e, + one is not considered to be a specialization of the other). +* | In some modes, prototype instantiations are performed for entities other + than classes and aliases. When semantic analysis of nonclass templates has + been requested, prototype instantiations are done for the bodies and + default arguments of function templates and member functions of class + templates, the initializers of template static data members, and the + default values of template arguments. +* | Template template parameters are class templates for which the template + definition to be used for a given reference is supplied by a template + template argument. + +By default, prototype instantiations and entries associated with nonreal +classes and aliases do not appear in the IL. When +``PROTOTYPE_INSTANTIATIONS_IN_IL`` is TRUE, IL entries for prototype +instantiations are generated. See :ref:`templates-in-the-il` for more +information. + +Template definitions are typically placed in header files that are included by +the programs that make use of the templates. Alternatively, the definitions of +template static data members and non-inline template functions may be provided +using the "export" facility of the C++ language (see +:ref:`exported-templates`). + +The major part of template support falls into several phases. The first is +processing the declaration of the template, which for a class template also +involves doing a prototype instantiation. The second phase is recognizing a +reference to an instance of a template and producing a partial template +instantiation, which can be thought of as an on-the-fly declaration of the +instance. The third phase is the full instantiation of the template instance; +typically, a template class is fully instantiated at the first point of +reference in a given translation unit, but a template function presents special +complications, since the full instantiation of a noninline template function +may occur only once in a program, no matter how many translation units it may +appear in. + +Each of these phases of template processing will be examined in detail, but +first it is necessary to describe the data structures that are built to +represent templates and their instances. + +Data Structures +=============== + +Each collection of tokens that is stored so that the tokens may be rescanned +later is represented by an entry of type ``a_template_cache``. The fields of +the template cache entry are: + +* | ``tokens``, where the tokens are kept on which an instantiation of the + template is to be based. + + * | For classes the tokens comprise the base specifiers list as well as the + body of the class. + * | For functions, including member functions, they extend from the opening + left brace to the closing right brace of the function body, except that + for templates of constructors the *ctor-initializer* list, if present, is + also included. + * | For static data members the tokens identify the initializer, if any. + + | The last token in the token cache is always a ``tok_end_of_source`` token. +* | ``decl_info``, a pointer to an entry of type ``a_template_decl_info``, + which describes the context in which the tokens stored in the token cache + appeared. + +The template declaration information entry (``a_template_decl_info``) in turn +includes the following fields: + +* | ``parameters``, a pointer to list of entries of type ``a_template_param``; + they record the template parameters declared in the template declaration. + + * | For type parameters a template param entry points to an ``sk_type`` + symbol (which in turn refers to a ``tk_template_param`` type entry). + * | For nontype parameters a template param entry points to an + ``sk_constant`` symbol (which refers to a ``ck_template_param`` constant + entry). + * | For template template parameters a template param entry pointed to an + ``sk_class_template`` symbol. The template symbol supplement for which + the ``template_template_param`` field is TRUE. +* | ``declaration_scope``, identifying the ``sck_template_declaration`` scope + in which the template parameter symbols were declared. +* | ``enclosing_scope``, a pointer to the scope containing the template + declaration. This is important, for example, when a function template is + defined in a friend declaration within a class, in which case the class + must be reactivated when instantiations of that function template are + generated. +* | ``enclosing_template_decl``, a pointer to the template declaration + information for an enclosing template declaration. This is used for member + class templates and member function templates when one needs to know, for + example, not only the template parameters of the member template, but also + the template parameter lists of any enclosing class templates. +* | ``decl_seq``, the declaration sequence number at the point of the template + declaration. This is used when doing dependent name lookup to exclude + names not visible at the point of the template definition. +* | ``nondependent_calls``, used when doing dependent name processing to record + the result of overload resolution for nondependent calls that were + evaluated during a prototype instantiation. + +A template (of whatever flavor) is represented by the combination of a symbol +and an associated entry of type ``a_template_symbol_supplement`` (defined in +``symbol_tbl.h``). An instance of the template is then represented by an entry +that appears on a list pointed to from the template symbol supplement. That is +the basic pattern for representing a template and its instances -- a template +symbol, a supplement, and a list of instances -- but each sort of template +presents a different version of the pattern. + +The template symbol supplement contains a template cache entry for the template +body and also has fields that are specific to the kind of template it is +associated with; these are discussed below. + +In most cases the instantiation of a template creates one or more classes, +functions, and/or static data members. However, when a class template contains +members that are themselves templates (i.e, member function templates or member +class templates) the instantiation of the enclosing class template results in +the creation of entities that are templates. When this happens, it is +necessary to record the template from which the new template was generated. +The template symbol supplement field named ``prototype_template`` contains a +pointer to the symbol associated with the template from which a given member +template was generated. Similarly the prototype template contains a field +named ``subordinate_templates`` that points to a list of templates that were +generated from the prototype template. + +Class Templates +--------------- + +An ``sk_class_template`` symbol represents a class template; it contains a +pointer to a template symbol supplement. The supplement for a class template +includes the variant field ``instantiations``, a pointer to a list of the +symbols (of kind ``sk_class_or_struct_tag`` or ``sk_union_tag``) that represent +instances of the template. The symbol for the prototype instantiation is +pointed to by the field ``prototype_instantiation``. + +For each template class represented by a symbol on the instantiations list the +class symbol supplement has several important fields: + +* | ``class_template`` is a pointer back to the ``sk_class_template`` symbol + that represents the template upon which its instantiation is based. + However, for a nested class of a template class the ``class_template`` + pointer will always be NULL. +* | ``corresp_prototype_sym`` is a pointer to the template class symbol for the + prototype instantiation and is present for template class instances and + classes nested within template classes. +* | ``is_nonreal_class`` is TRUE for template classes produced by prototype + instantiations (and in general for template classes for which the template + argument list contains at least one template parameter reference). It is + also TRUE for a class that is a nested class of a nonreal template class. + +A class symbol for a template class (i.e., for an instance of a class template) +does not otherwise appear in the symbol table. It cannot be looked up directly +but rather must be looked up via the class template symbol. + +The type entry associated with a template class is like that of any other class +except that it contains the following additional information about template +classes: + +* | ``template_arg_list`` points to the template argument used to generate the + type (the template arguments are incorporated in the type so that back ends + can use them to generate names for template classes). +* | ``is_template_class`` TRUE for template class instances and classes nested + within template class instances. +* | ``is_nonreal_class`` is TRUE for nonreal instantiations and for local + classes of prototype instantiations. +* | ``is_prototype_instantiation`` is TRUE for prototype instantiations of + class templates and nested classes of class templates. +* | ``is_specialized`` is TRUE for template classes declared or defined in an + explicit specialization declaration. +* | ``specialized_with_old_syntax`` was specialized, but not with the + "``template <>``" syntax that is now required by the standard. +* | ``partial_spec_template_arg_list`` is used when a partial specialization is + used to generate the definition of the template class. It points to the + template argument list that is specified with respect to the partial + specialization's template parameter list. + +A class template may have associated with it a set of partial specializations +that may be used instead of the primary template when generating full +instantiations of instances of the class template. The template symbol +supplement contains a field named ``partial_specializations`` that points to a +list of ``sk_class_template`` symbols for any partial specializations that may +exist. Instances created from partial specializations go on the instantiations +list of the primary template. Each partial specialization has its own +prototype instantiation, which also goes on the instantiations list of the +primary template. The class type supplement field +``partial_spec_template_arg_list`` is used in class types generated from class +template partial specializations (including the prototype instantiation). It +contains the template argument list with respect to the partial specialization, +while the ``template_arg_list`` field contains the template argument list with +respect to the primary template. In the following example, the template +argument list with respect to the primary template is "````", while +the template argument list with respect to the partial specialization is +"````". + +.. code:: c++ + + template struct A {}; + template struct A {}; + A a; + +As mentioned previously, it is here that the type entries of real and nonreal +template classes differ -- the template arguments of a nonreal template class +involve at least one ``tk_template_param`` type or ``ck_template_param`` +constant. In addition, the type entry for a nonreal class does not appear in +the IL that is passed on to the back end for further processing. + +When an instance of a class template is fully instantiated, partial +instantiations for all of its member functions, static data members, and nested +classes are generated. Because these entities are not themselves templates, +they do not have their own template argument lists. The template argument list +for their enclosing class is used when a full instantiation is performed. + +Alias Templates +--------------- + +Alias templates are represented in much the same way as class templates. An +``sk_class_template`` symbol is used to represent the alias template, however +the instantiation list and prototype instantiation fields of the template +symbol supplement point to ``sk_type`` symbols. The ``is_alias_template`` +field of the template symbol supplement is used to identify alias templates. + +The typeref type created for instantiations of alias templates (with typeref +kind trk_is_template_alias) is like that of normal aliases except that it +contains additional information, including the template argument list and flags +such as ``is_template_alias``, ``is_nonreal``, and +``is_prototype_instantiation``. + +Function Templates +------------------ + +An ``sk_function_template`` symbol is used to represent a function template, +including member function templates, but not member functions of class +templates. It contains a pointer to a template symbol supplement whose variant +field ``instantiations`` points to a list of entries of type +``a_template_instance``: each time a partial instantiation is performed on the +function template, the resulting instance is recorded in this list. + +Entries of type ``a_template_instance`` are also utilized to record instances +of member function of class templates and static data members of class +templates, but they are used somewhat differently in those cases (as described +later). When a template instance is used to record an instance of a function +template, the following use is made of its fields: + +* | ``instance_sym`` points to the ``sk_routine`` symbol that represents the + instance. That symbol will in turn point to the routine entry created to + represent the instantiated function. A full instantiation need not have + been done. The routine entry contains a pointer to the template arguments + on which the instance is based. +* | ``template_sym`` points to the ``sk_function_template`` symbol that + represents the template. +* | ``instantiation_required`` is TRUE if the routine instance was actually + called or had its address taken. It means that a *full* instantiation + needs to be performed -- i.e., that the function body needs to be + generated. When this flag is set, the instance is placed on the + ``instantiations_required`` list, to assure that it is checked for + additional processing once the entire translation unit has been + scanned. +* | ``is_guiding_decl`` is TRUE if this routine was explicitly declared by the + user (whether or not a body was supplied). When this flag is set, the + symbol pointed to by ``instance_sym`` will have been added to the overload + list for this name. Note that a "specific declaration" is different than + an "explicit specialization". A specifically declared function + participates in overload resolution, but need not be explicitly + specialized. + | + | Here's an example: + + .. code:: c++ + + template void f(T) {} + void f(int); + + | The second declaration assures that ``f(int)`` is represented both in the + instantiations list for function template ``f`` and on the overload list + associated with an ``sk_overloaded_function`` symbol with an identifier + ``f``. Such a declaration affects how the function is found during + overload resolution, but it does not prevent a body from being generated + for it based on the function template. +* | ``explicit_instantiation`` is TRUE if the user has explicitly requested + full instantiation by means of an explicit instantiation directive or + ``#pragma instantiate`` directive. +* | ``referencing_namespace`` points to the namespace in which the use that + first required the instantiation of the template was encountered, or NULL + if the first reference was in the global namespace. This field is set when + the ``instantiation_required`` flag is set to TRUE. + +In addition to the pointer to the instantiations list, the template symbol +supplement for a function template makes use of some other variant fields: + +* | ``routine`` is a pointer to a routine entry. This entry is generated when + the function template declaration is scanned, but it doesn't actually map + to a real routine (and does not appear in the IL proper). Rather, it + serves as a convenient place to store the routine type and other + information about the function (e.g., the storage class, the special + function kind, and whether inlining was specified in the original + declaration). +* | ``func_info`` is a field of type ``a_func_info_block`` and stores + information picked up during declaration processing that needs to be reused + during instantiation (e.g., the names of the function parameters). +* | ``def_arg_expr_list`` is a list of entries containing information about + default arguments to be applied to the function parameters when the + instantiation is done. + +Whereas, as noted previously, an instance of a class template cannot be looked +up independently of its template, the same is not necessarily the case for an +instance of a function template. When there has been a guiding declaration, +the template function's symbol may be found during ordinary overload +resolution. However, when there is no guiding declaration, the symbol can only +be found via the function template symbol and its list of instantiations. +Consider this example: + +.. code:: c++ + + template T f(T t) { return t; } + char f(char); // Guiding declaration + int i = f(0); // Instantiation of f(int) + void f(int, int); // Unrelated to the template + +Symbols are arrayed under the symbol header for "``f``" as follows: + +* | overloaded function symbol with overload list: +* | template function symbol ``f(T)`` with instantiation list: +* | instance entry pointing to routine symbol ``f(char)`` +* | instance entry pointing to routine symbol ``f(int)`` +* | routine symbol ``f(char)`` +* | routine symbol ``f(int,int)`` + +Notice that the symbol for ``f(char)`` appears both on the overload list and on +the instantiation list (there are not two different symbols), whereas +``f(int)`` appears only on the instantiation list. The former, consequently, +is subject to the ordinary lookup rules, whereas the latter must be looked up +using the stricter rules for template functions. Guiding declarations have +been removed from the standard language, but are still supported by the front +end depending on the command line options and configuration flags being used. +When guiding declarations are disabled, declarations such as ``f(char)`` are +simply declarations of normal functions that are unrelated to the template. + +Member Function of Class Templates +---------------------------------- + +A member function of a class template is represented by an +``sk_member_function`` symbol created during the prototype instantiation of the +class template. These symbols look like ordinary member function symbols, +which among other things means they do not have their own pointer to a template +symbol supplement; rather they point to a template instance entry, and it has a +pointer to a template symbol supplement. + +The problem being addressed with this somewhat roundabout arrangement is that a +member function of a class template is really a "quasi-template" whose partial +instantiation is in fact always part of any full instantiation of the class +template to which it belongs. A consequence of this approach is that the +instantiations list from the associated template symbol supplement includes +both + +#. ordinary instance entries that point to ordinary member function symbols + (members of *real* instantiations of the class template) and + +#. one special instance entry that represents the quasi-template by + pointing to a member function symbol of the *nonreal* prototype + instantiation of the class template. + +The template instance entries for member functions are similar to those for +ordinary template functions: + +* | ``instance_sym`` points to the ``sk_member_function`` symbol that + represents the instance. +* | ``template_sym`` points to the ``sk_member_function`` symbol that + represents the template. +* | When ``instance_sym`` and ``template_sym`` are identical, the + ``template_info`` field is non-NULL and points to the template symbol + supplement belonging to this member function of a class template. +* | The flags are used as for nonmember function instances, except that + ``specific_decl`` is always TRUE. + +Variable Templates +------------------ + +A variable template is represented by an ``sk_variable_template`` symbol. +Instantiations of the template result in variable entries and associated +``sk_variable`` symbols. Variable templates declared in class scopes are, from +a language point of view, static data members, but they and their +instantiations are represented in the same way as non-member variable +templates. When a variable template is instantiated using a dependent template +argument list, the ``is_nonreal`` flag is set in the variable entry. The +``variable`` variant of the template symbol supplement contains information +used for both variable templates and static data members of class templates +(although some fields are only used for one or the other). The +``instantiations`` field points to a list of symbols for the real +instantiations of the variable template. Template instance entries are created +for the real instantiations of a variable template. + +Static Data Members of Class Templates +-------------------------------------- + +Static data members of class templates are represented much like member +functions of class templates. The template symbol, an +``sk_static_data_member`` symbol from the prototype instantiation of the class +template, points to an instance entry whose ``template_sym`` field points back +to it and whose ``template_info`` field points on to a template symbol +supplement. The latter has a ``definitions`` field that points to the instance +list. The fields in the instance entries are used just like those for member +functions. + +Template Declaration Information +-------------------------------- + +As described earlier, each token cache that is used in the template +instantiation process is associated with a pointer to an entry of type +``a_template_decl_info``, which contains information about the template +parameters, the scope in which the template was declared, and a pointer to an +enclosing template declaration information entry, if applicable. An enclosing +template declaration information pointer is used when a member function +template or member class template is declared within another class template. A +function template, or member function of a class template, contains a token +cache that contains the function declaration and a separate token cache +containing the function body. Each token cache has associated with it a +separate template declaration information pointer, because the two caches may +have come from different declarations with different template parameter lists, +etc. + +There is one template declaration information entry for each ``template <...>`` +clause that is scanned (except for those with empty parameter lists, which are +used in explicit specializations). When there is more than one template clause +in a given declaration, the inner template clauses contain a pointer to the +enclosing template declaration clause (the one to the left of a given template +clause). + +When a template is defined within another template the enclosing template +declaration information pointer is NULL indicating that the template +declaration information for the enclosing template should be obtained by +consulting its template symbol supplement. + +Template Declarations +===================== + +Overview +-------- + +``template_directive_or_declaration`` is the top-level routine for handling +template directives and template declarations. It is called when the +``template`` or ``export`` keyword is encountered during declaration +processing. This occurs for template declarations, explicit specialization +declarations, and explicit instantiation directives. For example: + +.. code:: c++ + + template struct A {}; // template declaration + export template void f(T){} // exported template declaration + template <> class A {}; // explicit specialization + template class A; // explicit instantiation + +When no template parameter list is present ``explicit_instantiation`` is +called. See :ref:`explicit-instantiation` for further information. When a +template parameter list is present, including an empty one (e.g., ``<>``), +``template_or_specialization_declaration`` is called. + +It first calls ``cache_template_declaration`` to create a token cache +containing the entire template declaration, including both the template +parameter list(s) and the declaration that follows. The definition of the +template (e.g., the class or function body) is not included in this cache. An +initial scan of the tokens in the cache is done to determine whether the +declaration is a full specialization, and whether it is a friend declaration. + +Template Parameter Clauses +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A template declaration or template specialization declaration contains one or +more "template parameter clauses". A template parameter clause consists of the +``template`` keyword followed by a possibly empty template parameter list. The +initial declaration of a template always has a single template parameter clause +(although a template declaration may be nested within another template +declaration). Multiple template parameter clauses are used only when a member +template of a class template is defined or specialized outside of its class. + +Each template parameter list has associated with it a template "nesting depth". +The nesting depth of the parameter list and the position within the template +parameter list are the attributes used when comparing two template parameters +to see if they represent the same parameter. The names of the template +parameters are not significant. The nesting depth and position are +collectively called the template parameter's "coordinates". + +For example: + +.. code:: c++ + + template struct A { + template void f(T1, T2, T3); + }; + template template void A::f(X,Y,Z){} + +where + +* | ``T1`` and ``X`` both have a nesting depth of 1 and a position of 1 +* | ``T2`` and ``Y`` both have a nesting depth of 2 and a position of 1 +* | ``T3`` and ``Z`` both have a nesting depth of 2 and a position of 2 + +The nesting depth of a template parameter clause in a namespace scope is 1, a +template parameter clause declared within one enclosing class template is 2, +etc. When scanning a template friend declaration any enclosing class templates +are ignored and the template parameter clauses are numbered beginning with 1. +This is necessary so that any types declared in the friend declaration match up +correctly with the template that is being made a friend. For example, to make +the template in the example above a friend of another template, you would do +the following: + +.. code:: c++ + + template struct B { + template + template friend void A::f(X,Y,Z); + }; + +The declaration of a template template parmeter also includes a template +parameter clause. The template parameters in the template parameter clause for +a template template parameter have a nesting depth of zero. + +For each nonempty template parameter list, the template parameters from the +parameter list are scanned. This process includes the following steps: + +* | An ``sck_template_declaration`` scope is pushed. This will be the + declaration scope to which the template parameter names belong. +* | ``scan_template_param_list`` is called to scan the template parameters and + build a linked list of entries of type ``a_template_param`` to represent + them. Each template parameter has an associated symbol. These symbols + initially point to special "prototype argument" values that, for class + templates, are used during the prototype instantiation. During real + instantiation these symbols are modified to point to the actual argument + values to be used. + + * | A type parameter points to an ``sk_type`` symbol that initially points to + a ``tk_template_param`` type. The type symbol points to the actual + argument type during an instantiation. + * | A nontype parameter points to an ``sk_constant`` symbol that initially + points to a ``ck_template_param`` constant. The constant symbol points + to the actual argument constant during an instantiation. + * | A template template parameter points to an ``sk_class_template`` symbol. + Unlike the type and nontype cases, the template template parameter symbol + always points to the template symbol supplement for that template + template parameter. The ``argument_template`` field of the template + symbol supplement points to the actual argument to be used during an + instantiation. Template template parameters differ from other template + parameters in that they have certain properties that must persist through + real instantiations. For example, the default template argument values + used for a template template parameter are always the ones specified in + the template template parameter declaration, never those associated with + the actual template template argument. +* | If the template parameter has a default argument, the type or expression is + scanned on the spot if possible. However, if the default argument depends + on another template parameter, the default argument must be rescanned when + its value is needed using the actual argument values for the template + parameters on which it depends. Therefore, its tokens are cached so that + they may be scanned later (see ``prescan_default_arg_expr``). There are a + number of ways in which a default argument can depend on another template + parameter: + + * | The type of a nontype parameter may make use of another template type + parameter. + * | The value of a default nontype argument may depend on a template type + parameter or nontype parameter. + * | The type used as the default argument for a type parameter may make use + of another template parameter. + + | For example: + + .. code:: c++ + + template class A {} + + | The default type of ``T`` and the default constant value for ``I`` can + be known when the template parameters are scanned, but the default type + of ``T2`` and the value for ``J`` are dependent upon whatever type + ``T`` takes on, and the value of ``J`` depends on the value used for + ``I``. + +Classifying the Template Declaration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When processing specializations a distinction is made between a "full +specialization" and a "template specialization". A full specialization is one +in which the entity being declared is a class, function, variable, or static +data member, while a template specialization is one in which the entity being +declared is still a template. For example: + +.. code:: c++ + + template struct A { + void f(); + template void g(T2); + template struct B {}; + struct C {}; + }; + // Full specializations + template <> void A::f(); + template <> struct A::C {}; + // Template specializations + template <> template void A::g(T2); + template <> template struct A::B {}; + +A partial specialization of a template is treated as a normal template +declaration, not as a template specialization. A template specialization is a +template with one or more empty template parameter clauses. + +Full specializations are handled by calling ``full_specialization``. See +:ref:`explicit-specializations` for more information. The rest of this +section describes ``template_declaration``, which is responsible for +processing template declarations and template specializations. + +Earlier, a token cache was built that contains the template parameter clauses +and the declaration that follows them. We are now at the point in the token +stream that marks the division between the two components. Because the +declaration component must be prescanned to determine the kind of template +being declared, and because the declaration may be needed later for the purpose +of generating partial instantiations of functions, the existing cache is split +into a template parameter cache and a template declaration cache. In certain +error cases, such as the presence of a syntax error in the template parameter +list, the template declaration may not have been cached correctly when the +initial cache was built. When this occurs, the template declaration is +recached now that the true position of the beginning of the declaration is +known. + +Next, ``is_class_template_decl`` is called. If the declaration is in fact of a +class template, TRUE is returned. If it is not a class template declaration, +FALSE is returned to signal that processing for other kinds of template +declarations should be done. + +The template parameters are checked to ensure that they are compatible with any +previous declaration of the template, and for class members, that the template +parameter lists that correspond to enclosing class templates are compatible +with the template parameter lists of those class templates. + +Class Templates +--------------- + +``class_template_declaration`` is called to process class template +declarations. This includes normal class templates, partial specializations, +and template specializations. It is also called to process declarations of +nested classes of class templates that are defined outside of the class. +``class_template_declaration`` performs the following functions: + +* | Looks up and verifies the template name. +* | Creates the ``sk_class_template`` symbol and enters it into the symbol + table, if necessary. The symbols for partial specializations are not + entered into the symbol table. +* | Calls ``create_prototype_type`` to create the symbol and type for the + prototype instantiation, and to create the template argument list(s) for + the prototype instantiation. +* | If a definition is provided, collects the tokens for the base class + specifiers and the class body and caches them for use later. +* | For partial specializations, the template parameters of the partial + specialization must appear in the template argument list associated with + the partial specialization in such a way that their values can be deduced. + In addition, nontype arguments cannot have types that depend on other + template parameters, nor may they be used in expressions. These error + tests are accomplished by calling + ``check_partial_spec_nontype_param_usage``. +* | If the template is a partial specialization, + ``check_for_prior_use_of_partial_spec`` is called to determine whether the + newly declared partial specialization would have been used to generate any + existing full instantiations of the primary template, had it been declared + when the full instantiation had been done. If any such full instantiations + are found, an error is issued. + +Then the template declaration scopes that were pushed when the template +parameter clauses were scanned are popped, and ``instantiate_class_template`` +is called to do a prototype instantiation -- i.e., to scan the template +definition even though the template parameters have not yet been given "real" +values. Because declaration/expression disambiguation often cannot be done +based on dummy types, only declarative information is scanned; inline function +bodies and default argument expressions are cached and, in some modes, have +their prototype instantiations done later. Most syntax errors and some +semantic errors are detected, but some errors cannot be reported until a real +instantiation is done. + +The main benefit of prototype instantiation is to record the names and types of +member functions and static data members -- in effect, to create symbols to +represent member functions of class templates and static data members of class +templates. ``instantiate_class_template`` accomplishes its work in the +following steps: + +* | An ``sck_template_instantiation`` scope is pushed onto the scope stack. +* | The token cache for the class template body is activated. +* | ``scan_class_definition`` is called to process the tokens. Special + provisions are made for prototype instantiations: + + * | Diagnostics are suppressed where appropriate. + * | ``decl_member_function`` and ``decl_static_data_member`` create template + instance entries, template symbol supplements, and whatever else is + needed to make the member symbols serve as templates. + * | ``delayed_scan_fixup_for_class`` moves the tokens cached for member + function bodies into the appropriate template symbol supplement; it also + moves the entries describing default argument expressions onto a list in + the appropriate template symbol supplement. The cached tokens for + inline-defined friend functions are discarded -- they will be picked up + during real instantiation. +* | The starting and ending token positions of any nested classes, member + functions whose definitions were provided in the class, and member + templates (functions or classes) whose definitions were provided in the + class are recorded. These token positions will be used to remove the + definitions from the token cache for the class template body. +* | The template instantiation scope is popped. +* | The bodies of nested classes, etc. are removed from the class template + body token cache. Nested classes, member functions, and member templates + may all be specialized. In other words, the definitions provided in the + class template definition may not be the ones actually used for a given + instance of the class template, so there is no sense in scanning them while + instantiating the class. As with class templates and function templates, + nested classes of class templates, member functions of class templates, and + member class and function templates are only instantiated when needed, and + may be specialized any time before the point at which they are first used + in a way that requires their instantiation. + +Alias templates +--------------- + +``alias_template_declaration`` is called to process alias template declarations +and performs the following functions: + +* | Verifies the template name. +* | Creates the ``sk_class_template`` symbol and enters it into the symbol + table. +* | Calls ``create_prototype_type`` to create the symbol and type for the + prototype instantiation, and to create the template argument list(s) for + the prototype instantiation. +* | Collects the tokens for the type defined by the alias and caches them for + use later. + +After calling ``alias_template_declaration``, ``template_declaration`` calls +``alias_prototype_instantiation`` to create the prototype instantiation of the +alias. + +Function Templates +------------------ + +The above is what happens when ``is_class_template_decl`` does in fact +determine that the declaration is a class declaration. However, if it returns +FALSE, ``template_declaration`` proceeds to examine what must be a template +declaration for something other than a class template. + +If the template declaration appears within the definition of a class it must be +a member function template declaration or a template friend declaration. If it +is a member function template declaration ``class_member_template_declaration`` +(in ``class_decl.c``) is called to scan its declaration, then +``complete_function_template_decl`` is called to create the necessary template +data structures and to scan the template body, if present. + +For all other cases, ``scan_template_declaration`` is called to scan the +declaration, which it does by calling ``decl_specifiers`` and ``declarator``. +If that produces a function type, the declaration is processed as a function +template or member function of a class template declaration; otherwise, it is +processed as a variable template or static data member of a class template +declaration or reported as an error. + +``function_template_declaration`` is called for function templates. It, in +turn, calls either ``decl_function_template`` (in ``decls.c``) or +``template_specialization``. + +``decl_function_template`` does for member and nonmember template declarations +more or less what ``decl_routine`` does for ordinary function declarations. +The processing for nonmember function templates includes the following: + +* | ``id_linkage`` is called to determine whether this is a redeclaration of a + function template that is already in the symbol table and whether the name + of the function template is overloaded. +* | If this is not a redeclaration, then: + + * | An ``sk_function_template`` symbol is entered into the symbol table + (either directly or into an overload set). + * | A routine entry is allocated and its fields are set to record the type, + storage class, and so forth specified in the declaration. It is not + added to the IL, however, because it does not designate a "real" routine. + +Member functions, for which a qualified name must be present, will already have +been declared in the class template definition. Their processing includes a +call to ``member_function_redecl_sym``, which returns the member function +symbol with a matching type signature. + +``decl_function_template`` returns to ``function_template_declaration`` an +already existing or newly created symbol that represents the function template. +Then, as with member function template declarations, +``complete_function_template_decl`` is called. + +Completing the Function Template +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The next step is to collect the tokens of the function body (including, for +a constructor, the *ctor-initializer*\ s) and store them in a cache in the +template symbol supplement. For both member and nonmember function +templates the new template declaration information (parameter list, etc.) +is recorded in the associated template symbol supplement. + +When doing nonclass prototype instantiations, +``function_prototype_instantiation`` is called to perform a prototype +instantiation on the body of a function template or member function of a class +template, and ``default_arg_prototype_instantiation`` is called to perform a +prototype instantiation on the default arguments of such functions. + +Variable Templates and Static Data Member Templates +--------------------------------------------------- + +Variable template declarations can be either ``extern`` declarations, or are +definitions. Static data member declarations are always definitions. For +definitions, the template parameter list is recorded in the template symbol +supplement, and the tokens comprising the initializer, if any, are cached. In +some cases, some or all of the initializer may have already been cached as part +of the template declaration. In such cases, ``split_token_cache`` is used to +move the initializer tokens from the declaration cache to the initializer +cache; the remaining initializer tokens are then appended to the initializer +cache. + +When doing nonclass prototype instantiations, +``variable_template_prototype_instantiation`` is called to perform a prototype +instantiation on the initializer of the variable template or template static +data member. + +Variadic Templates +------------------ + +The C++11 standard adds "variadic templates," which are templates that take a +variable number of arguments. For example: + +.. code:: c++ + + template void f(T ...args) { + int a[] = {0, args..., 5}; + } + int main() { + f(1, 2, 3, 4); + } + +The template ``f`` can be called with zero or more arguments. For a given +call, the parameter pack ``T`` is deduced to be a list of types, matching the +types of the arguments supplied, and ``args`` is a function parameter pack that +is a series of parameters of the types given by ``T``. + +The front end implements variadic templates by storing, along with the tokens +of the template, information on the location and details of any pack references +and expansions. When the template is instantiated, the cached tokens of its +declaration or definition are scanned, and in places where there are pack +expansions, the processing loops over a sequence of tokens, substituting a +different value for the pack name on each iteration, thus producing an expanded +version of the source text. + +The language definition of variadic templates uses a syntax-based trick: in +contexts that allow a list of items (usually, a comma-separated list), an item +in the list can be suffixed by "``...``" to indicate that it is a pack +expansion. In an instantiation of the template, that pack expansion is +replaced by, in effect, a list of entities generated by the expansion of the +pack. So, in the above example, the aggregate initialization expands to the +equivalent of + +.. code:: c++ + + int a[] = {0, 1, 2, 3, 4, 5}; + +with the elements of the pack expansion inserted into the surrounding list. + +Such expansions are allowed in parameter lists, call argument lists, +brace-enclosed aggregate initializers, base class specifiers, +*mem-initializer*\ s, template argument lists, exception specifications, +attributes, and capture lists. + +The front end uses its own trick to expand these patterns. In each of those +contexts, the code that handles the normal, non-variadic, case is enclosed in a +loop with the following general structure: + +.. code:: c++ + + a_pack_expansion_stack_entry_ptr pesep; + a_boolean any_more; + + any_more = begin_potential_pack_expansion_context(&pesep); + while (any_more) { + a_pack_expansion_descr_ptr pedep; + + /* Normal processing for one item is done here. */ + ... + pedep = end_potential_pack_expansion_context(pesep, + /*is_declarator=*/FALSE); + if (pedep != NULL) { + /* Mark the IL created as being for a pack expansion. */ + } /* if */ + any_more = advance_to_next_pack_element(pesep); + } /* while */ + +When no pack expansions are present, the "``begin...``" call returns TRUE, the +"``end...``" call returns NULL, and the "``advance...``" call returns FALSE, so +the loop goes around exactly once and handles one item on the list. + +When a pack expansion is present, in the prototype instantiation the +"``begin...``" call returns TRUE, the "``end...``" call swallows the "``...``" +indicating the pack expansion and returns a pointer to a structure that +describes the pack expansion, and the "``advance...``" call returns FALSE. +Again, the loop goes around exactly once, but information about the pack +expansion is recorded in the IL and in data structures attached to the +template. + +In a real instantiation, the loop goes around as many times as the pack being +expanded has values. Each time through, the source token position is reset to +the start of the expansion, the pack identifier is given an appropriate value +for that iteration, and the tokens are scanned again. After the right number +of iterations, the "``advance...``" call returns FALSE and the loop exits. If +the pack has zero elements, the "``begin...``" call advances the source token +position to after the "``...``" at the end of the expansion, and returns FALSE, +and the loop goes around zero times, thus producing no items on the list for +the pack expansion. + +The pattern above appears in every place where a pack expansion could occur. +In a call argument list, for example, it must be done around the scanning of +every argument, which means in a lot of places. (Or, at least, in a lot of +places when inside a template that has variadic parameters.) Almost all the +time, the variadic processing notes a starting position and starts a potential +expansion context, but then finds out later that there is no trailing "``...``" +and therefore no pack expansion, and discards the information saved. This has +to be done, however, so that we can recall the starting position of a pack +expansion in the cases where one does occur. + +The information saved for a pack expansion in the prototype scope (and, +incidentally, prototype instantiations are forced for variadic templates, so +that such information can be recorded) includes the starting position of the +pack expansion, so that, in a real instantiation, the "``begin...``" call can +look up the current token position and see whether a pack expansion starts at +the current token, and what the details of the expansion are. The saved +information includes the list of pack names that were referenced and are to be +iterated over in the loop. With that information, the "``begin...``" routine +can set up the proper looping over the proper sequence of tokens. + +There are variant versions of these variadic-loop-management routines that are +used for expression rescan contexts (no source tokens are consumed; pack +identifiers are updated and the right number of iterations of the loop are +done) and prescan and disambiguation contexts (where we don't know yet the +context of the code, and therefore can't be certain about what pack expansions +mean, so we don't want to record anything permanent). + +Template argument lists need to contain some extra information when variadic +templates are used. For example, for a case like + +.. code:: c++ + + template void f(U p, T ...args) { + } + int main() { + f(1, 2.0, 3.0f); + } + +the complete deduced template argument list for ``f`` has ``int`` for ``U``, +and then a list of ``double`` and ``float`` for T. In diagnostics, this is +displayed as ``>``. Internally, it requires a way to +indicate that part of the list is a pack expansion. That's the function of the +``tak_start_of_pack_expansion`` kind of template argument: it marks the start +of a sequence of template arguments associated with a pack expansion (and each +member of that sequence is marked with the ``is_pack_element`` flag). + +That causes problems for lots of code in the front end that traverses template +argument lists. In most cases, that code does not want to worry about +start-of-pack-expansion entries. It just wants the "real" entries on the list. +That's what the traversal routines ``begin_template_arg_list_traversal``, +``advance_to_next_template_arg``, and the "``..._simple``" versions of those +routines do. They allow easy set up of a traversal of a template argument list +that ignores the start-of-pack-expansion entries. They should be used in +general to process template argument lists, to avoid problems. + +Deduction does special processing to handle parameter packs, matching up +template parameters with multiple types, or nontype values, or template +template parameters. Zero-length packs are a particular problem, in that they +are deduced from an absense of information (e.g., no arguments corresponding to +that parameter pack). + +Overload resolution does special processing for parameter packs, and in +particular has to be careful because the normal one-to-one correspondence +between arguments and parameters does not always hold. + +Initializer processing deals with pack expansions by using expresison caches. +The initializer routines call to fetch one expression. If the expression +scanned is a pack expansion, the first expresison of the expansion is returned, +and the rest are pushed into an expression cache. They are then returned on +subsequent calls at the same or a higher or lower level. If the pack expansion +produces zero expressions, another expression is scanned, unless we hit the end +of the initializer (e.g., a closing brace). In some cases an expression is +prescanned so we can decide whether the expression-list is over before going +down a path in the code that will expects to be able to fetch an expression. + +Partial ordering and partial specialization processing also deal specially with +variadic templates. + +Templates in the IL +=================== + +An entry of type ``a_template`` is created for each template declaration (see +``make_il_template_entry``). By default, no information about the template +itself is preserved in the IL. There are two different optional mechanisms +that can be used to record information about templates: + +* | If ``PROTOTYPE_INSTANTIATIONS_IN_IL`` is TRUE, any prototype instantiation + is recorded in the IL. If nonclass prototype instantiations have been + requested, prototype instantiations will be generated for each template + entity declared; otherwise, prototype instantiations will be recorded only + for class templates. A prototype instantiation is an IL entry whose kind + corresponds to the kind of entry being declared, but that represents the + template itself and not any particular instantiation thereof. In other + words, it still contains references to the template parameters. A type + entry is used to represent a class template, a routine entry is used to + represent a function template, and a variable entry is used to represent a + variable template or template static data member. +* | If ``RECORD_TEMPLATE_STRINGS`` to TRUE, the IL template entry will point to + a null-terminated string that reproduces the text (minus comments, after + preprocessing) of the template declaration in the source program (see + ``make_template_string``). If a template has more than one declaration + (e.g., a nondefining declaration followed by a definition), an IL template + entry is produced for each declaration. + +Both of these mechanisms can be used at the same time. Note that while all +templates can be represented as template strings, only those templates that +make use of the standard-mandated ``typename`` and ``template`` keywords +can have prototype instantiation IL entries generated (because without such +keywords it is not possible to parse the template definitions in the +absence of a set of actual template argument values). See +:ref:`templates-in-the-il` for more information. + +Partial Instantiation +===================== + +Partial instantiation occurs automatically for nested classes, member +functions, and static data members when the class of which they are members is +instantiated. That is to say, the full instantiation of a class necessarily +entails the implicit declaration of all its members: symbols are introduced +into the symbol table, type entries are created as required, IL entries are +created and added to the IL, and so forth. The partial instantiation of class +templates and function templates, on the other hand, is triggered by a +reference. + +Class Templates +--------------- + +When a class template reference -- *class-template-name*\ ``<``\ +*template-arg-list*\ ``>`` -- is encountered, a call is made to +``coalesce_template_class_reference`` to scan the template argument list and +look up the reference. Having verified that types in the template argument +list correspond to type template parameters and constants correspond to nontype +template parameters, it builds a linked-list representation of the template +arguments. If there are more template parameters than template arguments and +if the template parameters have default values, entries are supplied for the +default values as well, whether from a saved constant value or after rescanning +the cached tokens comprising the default argument expression. + +The template argument list is then passed to ``find_template_class``, which +searches among the instantiations that already exist for the class template, +calling ``equiv_template_arg_lists`` to compare the template arguments scanned +for the current reference against the template arguments associated with +existing instantiations. If an instance with matching template arguments is +located, the symbol for it is returned. If no match is found, a new symbol is +created (see ``make_template_class_sym`` in ``symbol_tbl.c``) and added to the +instantiations list for the class template. A new class type is also created, +but, since this is a partial instantiation, no body is generated for it yet. + +A reference to an instance of a class template *always* causes a partial +instantiation, but not all references cause full instantiation. Partial +instantiation occurs during the *lexical* scan of a template class reference, +whereas the decision whether to do full instantiation occurs during *semantic* +processing. Partial and full instantiation are always separate steps in +template processing. + +Note that a partial instantiation can be generated on the basis of an +incomplete class template. For example: + +.. code:: c++ + + template class A; + A *x; + +Even though no body has been supplied for class template ``A``, a partial +instantiation of ``A`` can be produced. On the other hand, ``A`` is +an incomplete (and incompletable) type, and so an error would be issued if it +were used in a context that required a complete type. Similarly, partial +specializations are not relevant when a partial instantiation is generated. +They are only considered when a full instantiation is done. + +Function Templates +------------------ + +A function template may be referenced in several different ways: + +* | as a function call, +* | by taking the address of a function, +* | and by declaring a function in an explicit specialization, explicit + instantiation, or friend instance declaration. + +In each case, determining which function template is to be used, and which +instance of the template is being referenced, requires the evaluation of an +explicitly specified template argument list, deducing template arguments from +the function template's parameters, or some combination of the two. This +process involves the following steps for each of the candidate function +templates: + +* | If an explicit template argument list was specified, + ``substitute_template_arguments`` is called. Note that an explicit + template argument list is completely scanned before + ``substitute_template_arguments`` is called. When it is scanned, the + number of parameters, and their types are not known. Consequently, the + template argument list needs to be converted into one that matches the + template parameter list of the candidate template. This is done by calling + ``create_initial_template_arg_list``. If the specified template arguments + cannot be converted to the types of the corresponding parameters, or if + there are more template arguments than template parameters, no template + argument list is created and the candidate template is disqualified. Note + that an error is not issued because there may be another candidate template + that is actually the one intended to be used. +* | Once an appropriate template argument list has been produced, + ``substitute_template_arguments`` calls ``copy_type_with_substitution`` to + create a function type that represents the function type of the candidate + template with the template parameters that correspond to the explicitly + specified template arguments replaced with the specified template argument + values. If the substitution process would result in an invalid type (e.g., + a pointer to a reference type, or an array of void) the candidate template + is disqualified. +* | Template argument deduction is done using the substituted function type + created above in an attempt to deduce the template arguments that were not + explicitly specified. Template argument deduction is done by calling + ``matches_template_type``, which is described below. +* | If template argument deduction succeeds, + ``wrapup_function_template_argument_deduction`` is called to verify that + values have been deduced for all of the template parameters, and that the + types of any deduced nontype parameters match the types of the + corresponding template parameters. ``copy_type_with_substitution`` is + called once again to create a new function type in which all of the + template parameters have been replaced with the corresponding template + argument values. + +When the reference is from a function call, the routines described above are +called from the overload resolution routines. When the reference is from the +address of a function or from a declaration, these routines are called by +``is_match_for_function_template``, which in turn is called from either +``matching_template_function`` or ``has_matching_template_function``. + +There are several routines in ``templates.c`` that directly and indirectly +support the process described above: + +* | ``matches_template_type`` is designed to be called successively to build a + template argument list while checking for a match between a type from the + function template routine type and a type from a new routine type; it also + calls itself recursively to apply the processing to type trees. When a + template parameter type is found, the "real" type with which it is paired + is recorded in the corresponding template argument entry -- unless it + already has some other type, in which case an inconsistency has been found. + As long as there are no inconsistencies or type incongruities, this process + of augmenting the template argument list continues; otherwise, + ``matches_template_type`` returns FALSE to halt further processing and + invalidate the template argument list built thus far. + | + | After ``matches_template_type`` has indicated that each of the arguments + match the template, ``verify_template_nontype_args`` must be called to + verify that nontype parameters whose types depend on a template parameter + are consistent with the deduced types. It also supplies types for nontype + parameters that are deduced entirely from array bounds. +* | ``compare_function_templates`` is used to determine whether one function + template is *more specialized* than another based on the partial ordering + rules for function templates. It is called by the overload resolution + routines to compare two function templates that are otherwise identical + from the point of view of overload resolution. +* | ``add_to_partial_order_candidates_list`` is used in contexts other than + overload resolution in which a function template must be selected from a + set of function templates using the partial ordering rules. This is done + when taking the address of a function that is determined to be an instance + of a function template, and when the lookup of a conversion operator name + results in the partial instantiation of a template (e.g., when ``operator + int*`` is a reference to an instance of a function template such as + ``operator T*``). After this routine has been called for each candidate + template, ``select_best_partial_order_candidate`` is called to return the + best matching template. +* | ``find_template_function`` is passed a function template symbol and a + template argument list. After checking for the use of a local type among + the template arguments (an error), it goes through the instances that + already exist for the template, calling ``equiv_template_arg_lists`` until + a match is found. If none of the existing instances match the new template + argument list, it creates a new instance by calling + ``make_template_function``, to which the new template argument list is + passed. +* | ``is_match_for_function_template`` is passed a function template symbol and + a new routine type. It returns TRUE if the type fits the type signature of + the template and FALSE if not. First, obvious mismatches are detected, + such as mismatches in the number of function parameters. Next, if an + explicit template argument list was specified, the template arguments are + compared with the corresponding template parameters. Type arguments must + be associated with type parameters, nontype arguments must be associated + with nontype parametersm, and the specific nontype value specified must + match the type of the nontype parameter or must be capable of being + converted to the type of the nontype parameter. It then tries to find + among the instances of the template one whose type signature exactly + matches the new routine type. If it finds such an instance, it returns + TRUE, along with the symbol it found. Otherwise, it makes successive calls + to ``matches_template_type`` in an attempt to construct a template argument + list based on any explicitly specified template arguments, the template + parameter types, the template routine type, and the new routine type; if + this is successful, it returns TRUE, along with the new template argument + list, but otherwise it returns FALSE. +* | ``matching_template_function`` is passed a function template symbol and a + routine type. It calls ``is_match_for_function_template`` which checks for + a match between the routine type and the template. If there is a match but + no instance already exists, it creates a new instance by calling + ``make_template_function``, to which the routine type is passed. +* | ``has_matching_template_function`` is similar to + ``matching_template_function`` in that it determines whether a given + routine type matches a potential instance of the specified template, but it + does not create an instance of the template. It is primarily used when + issuing diagnostics, to choose the most appropriate of several possible + messages. In the following example, the error "specializing overloaded + function ``"A::f"`` requires ``template <>`` syntax" is used because the + function type matches the template declared in the class. + + .. code:: c++ + + struct A { + template void f(T); + }; + void A::f(int) {} + +* | ``make_template_function`` is the routine that actually does the partial + instantiation. When it is passed a non-NULL routine type, it simply uses + that type; otherwise, it activates the declaration token cache (see the + ``decl_token_cache`` field in the template symbol supplement) and calls + either ``scan_member_declaration`` or ``scan_template_declaration``, for + member and nonmember function templates, respectively, to assure that + template arguments are correctly substituted for template parameters in the + new routine type; and then, if there are default arguments, it calls + ``delayed_scan_for_function_template_default_args``. In addition, it + creates the ``sk_member_funciont`` or ``sk_routine`` symbol entry, the + routine entry, and the template instance, setting all their pointers and + other fields appropriately. The symbol is not entered directly into the + symbol table -- it is accessible to lookup via the instantiation list only. + +Variable Templates +------------------ + +A reference to a variable template results in a full instantiation of the +instance if a definition is available. The only exception is when the variable +template is used in a declarative context (i.e., to declare an explicit +specialization of the variable template). In a partial instantiation the +initializer is not scanned. + +Full Instantiation +================== + +Full instantiation of a template means providing an instance of the template +with a defining body (or, in the case of a static data member, a definition +with an implicit or explicit initializer). Typically, this occurs +automatically, on the basis of the template provided. However, it can also +occur when the user provides an explicit specialization definition. Both cases +are discussed in this section. + +.. _explicit-specializations: + +Explicit Specializations +------------------------ + +Two forms of explicit specialization are supported by the front end: the new +explicit specialization syntax (e.g., ``template <> ...``), and the old form +that used the normal declaration syntax. The new form is accepted in all +modes, while acceptance of the old form is controlled by a command line option. +Member function templates and member class templates may only be explicitly +specialized using the new syntax. + +For example: + +.. code:: c++ + + template void f(T); + template class A {}; + template <> class A; // new specialization declaration + template <> class A {}; // new specialization definition + class A; // old specialization declaration + class A {}; // old specialization definition + template <> void f(int); // new specialization declaration + template <> void f(int){} // new specialization definition + void f(char); // guiding declaration + void f(double){} // old specialization + +Explicit specializations that use the new syntax begin with one or more +template parameter clauses in which the parameter list is empty. An explicit +specialization can be a declaration or a definition. The language requires +that an explicit specialization be declared before its first use in a +translation unit. + +When using the old syntax, only classes can be declared as specializations. +For all other kinds of entities, specializations can only be supplied as +definitions. A function declaration that looks like an old-style +specialization declaration is actually what is known as a "guiding +declaration", whose only purpose is to cause a template instance to be treated +like a normal function for overload resolution purposes. There are no member +guiding declarations. + +Old-style explicit specializations look like normal class, function, and static +data member declarations and are handled by the same routines that handle +normal declarations. + +``full_specialization`` processes new-style explicit specializations and is +called after the template parameter clauses have been scanned. +``decl_specifiers`` and ``declarator`` are called to scan the declaration that +follows the template parameter clauses. If the entity being specialized is a +class, the call to ``declarator`` is bypassed. ``full_specialization`` then +identifies the template instance that is being specialized. + +Class Templates +^^^^^^^^^^^^^^^ + +An explicit specialization of a class template occurs when the explicit +specialization syntax is used, or when old specializations are enabled, when an +ordinary class definition is provided in which the class name is a template +class reference, for example: + +.. code:: c++ + + template class A {}; + template <> class A {}; + class A {}; + A x; + +In this example the bodies for ``A`` and ``A`` are the ones +provided by the user's explicit definitions. The bodies for all other +instances of template class ``A``, such as ``A``, are based on the +template definition. + +The processing of class template explicit specializations is done within +``class_specifier``, even when the new specialization syntax is used. This is +necessary because only when ``class_specifier`` is called is it possible to +determine whether the class is being specialized or whether the class specifier +is part of an elaborated type specifier in some other kind of declaration. + +When the template class reference is encountered as a tag name (see +``scan_tag_name``), a partial instantiation is done automatically and the +symbol is entered on the instantiations list of the class template. Then +``class_specifier`` marks the class as being explicitly specialized by setting +the ``is_specialized`` flag in the type entry, and adds the definition, if one +has been supplied. Because the ``is_specialized`` flag is set, no subsequent +automatic instantiation will be attempted. + +The same processing applies to both class templates and member class templates. +The processing for nested classes of class templates is basically the same +except that, as with other members of class templates, the partial +instantiation of the nested class is done when the enclosing class is +instantiated. + +Function Templates and Member Functions of Class Templates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An instance of a function template may be explicitly specialized using the +explicit specialization syntax, or when old specializations are enabled, by +providing a function definition that happens to match the type signature of a +function template. For example: + +.. code:: c++ + + template void f(T) {} + template <> void f(char); // explicit specialization + void f(int) {} // old explicit specialization + void f(int,int} {} // Unrelated to the template + +In both the old and new style specializations, the ``is_specialized`` flag in +the routine entry is set, which suppresses the full instantiation of the +template. The old-style specialization of a function also acts as a guiding +declaration for overload resolution purposes. + +When the new specialization syntax is used, ``find_matching_template_instance`` +is called to find the template instance that matches the routine type returned +by ``declarator``. This is done not only for instances of function templates +and member function templates, but also for member functions of class +templates. + +Processing for old-style explicit specializations follows the track for +ordinary function definitions. The primary difference appears in +``find_linked_symbol`` (called from ``decl_routine`` via ``id_linkage``), which +searches for previous declarations of the entity being declared. If the +ordinary search fails to turn up a matching function but does find a function +template with the given name, a call is made to ``matching_template_function``, +which extends the search to instances of the template function and, as +described above, creates a new one when appropriate. In other words, this +search in ``id_linkage`` may have the effect of doing a partial instantiation +of a new template function. Once the instance symbol has been found (or +created by means of a partial instantiation), attaching the function definition +to the routine involves no special processing. + +It can happen that an old-style explicit specialization of a function template +precedes the declaration of the template itself. For example: + +.. code:: c++ + + void f(int) {} // Specific definition + template void f(T) {} + +When the function template declaration is encountered, +``decl_function_template`` goes back through existing functions of the same +name and calls ``record_predeclared_template_function`` for each -- if the +function turns out to match the new template, it is retroactively entered as an +instance. + +Old-style explicit specializations of member functions or static data members +of instances of a class templates involve little special handling beyond what +is normally done for definitions of member functions and static data members of +nontemplate classes. Here's an example: + +.. code:: c++ + + template class A { + void f(T); + static T s; + }; + void A::f(int) {} + int A::s = 0; + +The reason no special processing is required is that the full instantiation of +``A`` entails the partial instantiation of its members ``f(int)`` and +``s``. After that it's just a matter of marking the symbols as ``defined`` and +adding the function body or initializer. + +Variable Templates +^^^^^^^^^^^^^^^^^^ + +The use of a variable template in an expression context results in a full +instantiation if a definition is available. If a definition is not available, +the normal instantiation processing is done as for template functions and +static data members of template classes (e.g., an instantiation could be done +later in the translation unit if a definition was provided, depending on the +instantiation mode). Even though a full instantiation may be done, an external +definition of the instance may or may not be emitted depending on the +instantiation mode. + +Automatically Generated Definitions +----------------------------------- + +Class Templates +^^^^^^^^^^^^^^^ + +The full instantiation of a template class occurs at the first point in the +translation unit where a reference to the instance requires it to be a complete +type. In other words, it is done as soon as necessary, but no sooner. For +example: + +.. code:: c++ + + template class A {}; + A *p; // Partial instantiation of A + A a; // Full instantiation of A + +The first declaration involving ``A`` does not require that it be a +complete type, but the second one does, and so that is the point at which the +full instantiation occurs. At points in the front end where a complete type is +required, the macro ``complete_class_type_is_needed`` is invoked, resulting, if +appropriate, in a call to ``instantiate_template_class`` to generate the full +instantiation. + +Partial Specializations +~~~~~~~~~~~~~~~~~~~~~~~ + +A class or variable template may be partially specialized. A partial +specialization is a version of the template that should be used for certain +instantiations. The template to be used is selected based on the template +argument list on which the instantiation is to be based. + +When a full instantiation is required, ``check_partial_specializations`` is +called to match the template argument list of the class being instantiated with +each of the partial specializations that have been declared for the template. +``matches_partial_specialization`` is called to perform the actual matching. + +The matching is done using the same process and routines that are used to do +function template argument deduction (see ``matches_template_type`` above). If +the template parameters for a given partial specialization can be deduced from +the actual template arguments, then the template class matches the partial +specialization. For example: + +.. code:: c++ + + template struct A {}; // #1 + template struct A {}; // #2 + template struct A {}; // #3 + template struct A {}; // #4 + A a1; // uses primary template (#1) + A a2; // uses #2 + A a3; // uses #3 + +The declaration of ``a1`` does not match any of the partial specializations, so +the primary template is used. The declaration of ``a2`` matches the partial +specialization labeled #2 because ``U1`` and ``U2`` can be deduced from +```` (as ``int`` and ``int``, respectively). Partial specialization +#3 is used when the two template arguments are the same, as in the declaration +of ``a3``. + +Each partial specialization that matches the argument list is added to a list +of candidate partial specializations using the routine +``add_to_partial_order_candidates_list``, which compares the new entry with any +entries already on the candidates list. The comparison is done by +``is_more_specialized``, which determines whether a given partial +specialization is "more specialized" than another. If the entry being added is +not as specialized as an entry already on the list, the new entry is not added. +If the new entry is more specialized than an entry already on the list, that +entry is removed from the list. After all of the partial specializations have +been evaluated, the candidates list contains a set of partial specializations +that match the template argument list of the class being instantiated and which +are unordered relative to one another. If there are no entries on the list, +the primary template is used to generate the class. If there is exactly one +entry on the list, that partial specialization is used to generate the class or +variable. If there is more than one entry on the list, the instantiation is +ambiguous and an error is issued. + +.. code:: c++ + + A a4; // ambiguous - could be #2 or #3 + A a5; // uses #4 + +The declaration of ``a5`` uses partial specialization #4, even though both #2 +and #4 match. #4 is preferred because it is "more specialized" than #2. +Whether a given partial specialization is more specialized than another is +determined in much the same way in which a partial specialization is determined +to match a given actual template argument list, i.e., though use of the +argument deduction routines. In the example above, if the argument list of #4 +was considered to be the actual argument list and the argument list of #2 was +considered to be the parameter list, the parameters of #2 could be deduced as +``U1=X1`` and ``U2=short``. If the roles of the two partial specializations +are reversed, making #2 the actual argument list and #4 the formal parameter +list, the type deduction fails. Therefore, #4 is considered more specialized +than #2. + +Generating the Template Class +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once the appropriate template has been selected (i.e., either the primary +template or a partial specialization), the body of the template class is +generated. These are the steps: + +* | The ``pending_instantiations`` value in the template symbol supplement for + the class template is incremented. This allows the compiler to catch and + report "runaway recursive instantiation," as the following example would + produce: + + .. code:: c++ + + template class A { A a; }; + A<0> x; + + | Once the pending instantiations counter reaches + ``max_pending_instantiation`` (a global variable that can be set by a + command-line option, and whose default is defined in ``lang_feat.h``), an + error is issued and the recursion is halted. +* | ``push_template_instantiation_scope`` is called to push a template + instantiation scope onto the scope stack and to do some special processing + for template instantiations: + + * | Pointers to the template symbol, the instance symbol, and the template + argument list are recorded in the scope stack entry. + * | ``depth_innermost_instantiation_scope`` is updated with the current scope + stack depth. + * | ``update_template_param_symbols`` is called to bind the symbols for + template parameters to the values in the corresponding template + arguments. For example: + + .. code:: c++ + + template class A {}; + A x; + + | By default the ``sk_type`` symbol for template parameter ``T`` refers to a + ``tk_template_param`` type entry and the ``sk_constant`` symbol for ``I`` + refers to a ``ck_template_param`` constant. But during the instantiation + of ``A`` -- that is, while the template instantiation scope is + active -- any reference to ``T`` or ``I`` should be translated into a + reference to the value of the corresponding template argument, namely, to + ``int`` or ``0``, respectively. This is done by modifying the pointers in + the symbols; the default pointers are restored when the template + instantiation scope is popped. +* | The cache containing the tokens for class template definition is activated. +* | ``scan_class_definition`` is called. In most respects processing is + identical to the processing for any class definition. The differences have + mainly to do with recording member functions and static data members as + instances: + + * | ``find_corresp_prototype_tag_sym`` is called to find the symbol for the + prototype instantiation of the class. (When a nested class within a + template class is scanned, the symbol returned is the corresponding + nested class of the prototype instantiation.) That symbol is required for + calling the two routines described next. + * | ``find_member_function_template`` is called for member functions of the + new template class. It locates the template symbol (i.e., the symbol for + the corresponding member function in prototype instantiation), creates a + template instance entry for the new member function, and adds it to the + instantiation list of the template. The template argument list for the + new template class serves for the instance, too. + * | ``find_variable_member_template`` is called for variable templates and + static data members of the new template class. The processing is similar + to what is done for member functions. + * | ``find_function_template_member`` is called for member function templates + of the new template class. The processing is similar to what is done for + member functions. + * | ``find_class_template_member`` is called for member class templates of + the new template class. The processing is similar to what is done for + member functions. + * | ``set_nested_template_class_symbol_info`` is called for nested classes of + the new template class. This call is made by ``class_specifier`` when + the nested class is first encountered. The processing is otherwise + similar to what is done for member function. + * | ``delayed_scan_fixup_for_class``, called at the end of scanning the class + definition, provides somewhat special handling for template classes. For + inline-defined member functions the function bodies are not scanned at + this time; such functions are only instantiated if they are called, so + that errors are not issued on functions that are not actually used. + Also, ``delayed_scan_for_function_template_default_args`` is called to + process the default arguments on the function parameters: the token cache + to be used is accessed through the template symbol supplement. +* | ``set_instantiation_required_for_template_class_members`` is invoked; for + each member function and static data member, both of the template class and + of any classes nested within the template class, it calls + ``update_instantiation_required_flag``. +* | ``pop_template_instantiation_scope`` is called to pop the template + instantiation scope. The template parameter symbols and + ``depth_innermost_instantiation_scope`` are restored to the values they had + before the scope was pushed. (Note that the possibility of recursive + instantiation prohibits restoring these values to default values.) +* | The ``pending_instantiations`` value in the template symbol supplement for + the class template is decremented. + +Alias Templates +^^^^^^^^^^^^^^^ + +When an instance of an alias template is referenced, ``find_template_class`` is +called to look for a previously created template alias or instantiate a new +alias if no previously created instance exists. Template aliases are +instantiated by ``instantiate_template_alias``. Note that unlike class +templates, there are no partial instantiations of alias templates + +Function Templates +^^^^^^^^^^^^^^^^^^ + +The timing for the instantiation of member and nonmember template functions is +partly controlled by the user (as discussed in the next section). A function +may end up being instantiated + +* | at the point of first reference in a given translation unit (e.g., + functions declared ``inline``); +* | at the end of the translation unit; or +* | externally to the current translation unit. + +Wherever it occurs, it is ``instantiate_template_function`` that is called to +generate a function body based on a template. These are the steps in the +process: + +* | The function's storage class and name linkage are set, along with its + ``is_inline`` flag if required. +* | The ``pending_instantiations`` value in the template symbol supplement is + incremented. As for class templates, this field is used to catch runaway + recursive instantiation. +* | ``push_template_instantiation_scope`` is called to push a template + instantiation scope onto the scope stack. +* | The token cache is activated. +* | ``push_scope`` is called again to push a function scope onto the scope + stack. +* | On the basis of the ``param_id`` list saved in the template symbol + supplement the function parameters are entered into the symbol table (in + the function scope) by ``decl_parameter``. +* | For constructors a call is made to ``ctor_initializer`` to process the + *ctor-initializer* list, if any, as well as to do default processing, + and for destructors a call is made to ``dtor_initializer``. +* | In case a function is being instantiated "on the fly" in the midst of + executable code, the structured statement stack is suspended and a new one + begun by a call to ``new_struct_stmt_stack``. +* | ``compound_statement`` is called to process the tokens comprising the + function body. The IL produced is recorded in the function scope. +* | If appropriate, ``restore_struct_stmt_stack`` is called. +* | ``pop_scope`` is called for the function scope. +* | ``pop_template_instantiation_scope`` is called for the template + instantiation scope. +* | The ``pending_instantiations`` value in the template symbol supplement for + the class template is decremented. + +Variable Templates and Static Data Members of Class Templates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``instantiate_template_variable`` is invoked to handle full instantiation of +static data members and for partial and full instantiations of variable +templates. It performs the following: + +* | Static data members are marked as defined. Variable templates are marked + as defined if the declaration is a definition. +* | If an explicit initializer was specified in the static data member template + declaration, then: + + * | ``push_template_instantiation_scope`` is called to push a template + instantiation scope onto the scope stack. + * | The token cache is activated. + * | The type is scanned to determine the type of a template variable, or to + make sure the type agrees with the declaration in the class for static + data members. + * | For a full instantiation, if a definition is available, ``initializer`` + is called to process the tokens comprising the initializer. + * | ``pop_template_instantiation_scope`` is called for the template + instantiation scope. +* | If no initializer was specified for a defined variable template or static + data member, ``def_initializer`` is called. + +Constrained Templates +===================== + +C++20 introduces the notion of "constrained templates", which is often referred +to as "concepts" (although concepts are just one feature in support of +constrained templates). For example: + +.. code:: c++ + + template requires(sizeof(T)<4*sizeof(int*)) + int hash(T *p); + +Constraints are boolean predicates. In the example above, it's just a normal +expression. Whenever template instance is considered (e.g., for overload +resolution or for a partial instantiation), its constraint predicates are +substituted and evaluated: If the predicates evaluates to ``false``, the +template is discarded. For functions and partial specializations, that may not +be an error (assuming other candidates satisfy their constraint or are +unconstrained), but other cases will then elicit an error that will indicate +which constraint failed to be satisfied. + +Concepts +-------- + +A constraint expression can be abstracted through a *concept template*. For +example: + +.. code:: c++ + + template concept SmallHashable = sizeof(T)<4*sizeof(int*); + +After that definition, the declaration of hash above can instead be rewritten +as: + +.. code:: c++ + + template requires SmallHashable(T) + int hash(T *p); + +or + +.. code:: c++ + + template + int hash(T *p) requires SmallHashable(T); + +or + +.. code:: c++ + + template int hash(T *p); + +or even + +.. code:: c++ + + int hash(SmallHashable auto *p); + +Although concept template are a kind of template, they are not (partially or +fully) instantiated. Instead, they are "substituted" somewhat like function +templates are substituted during the deduction process. + +Concept templates are represented in the IL using ``a_template`` entries of +``templk_concept`` kind, and in the symbol table using ``sk_concept_template`` +symbols (that point to ``a_template_symbol_supplement`` entries with no variant +fields). A ``templk_concept`` template points to the predicate, which is +represented as an ordinary expression tree (``an_expr_node`` structure). + +Concept templates can also be "invoked" directly to produce a boolean value. +For example: + +.. code:: c++ + + auto cond = SmallHashable; + +Such expressions are represented using ``enk_concept_id`` nodes: They point to +a ``templk_concept``\ ``a_template`` entry and, optionally, to a list of +template arguments. + +Representation of constraints +----------------------------- + +As hinted above, there are four possible syntactic locations for constraints: + +* | A concept name used to introduce a template type parameter. Such + constraints -- called *type constraints* -- are represented as + ``enk_concept_id`` nodes pointed to by the + ``a_template_param_type_supplement`` associated with the constrained + template parameter. The first template argument for such + ``enk_concept_id`` nodes are implied (it's the template parameter being + constrained) and that is indicated by the ``is_type_constraint`` flag in + the ``enk_concept_id`` node. +* | A *requires clause* following a ``template<...>`` header, as in our + original example. Such constrains are represented using + ``a_requires_clause`` entries pointed to from ``a_template_decl``, + itself pointed to from ``a_template``. ``a_requires_clause`` is itself + mostly a structure pointing to an expression tree. +* | An implicit template type parameter introduces by a so-called "abbreviated + function template declaration", as in the example ``int hash(SmallHashable + auto *p);`` above. This case is represented very much as the first case + (concept name used to introduce a template type parameter): By having the + associated ``a_template_param_type_supplement`` entry point to an + ``enk_concept_id`` node representing the constraint. However, in this + case, the ``a_param_type`` entry corresponding to the parameter that + introduced the constrained also has the flag ``is_auto_param`` set to TRUE. + +* | A trailing requires clause following the function declaration itself, as we + showed in the second variation of our example: + + .. code:: c++ + + template + int hash(T *p) requires SmallHashable(T); + + | This is represented by having the ``a_routine`` entry for the prototype + instantiation of the function template point to an entry of type + ``a_requires_clause``. It's worth noting that this variation of a + constraint can also be applied to ordinary member functions of class + templates (hence the need to point to it from an ``a_routine`` entry rather + than a template-specific entry). + + | To ease the description of constraints, C++20 also introduces + *requires-expression*\ s (not to be confused with *requires-clause*\ s, + which were described above). For example: + +.. code:: c++ + + template void f() { + bool b = requires { typename T::node; }; + } + +Such expressions are represented by an ``enk_requires`` node, which points to a +list of expression nodes: Entries on that list that are of kind +``enk_type_operand``, ``enk_compound_req``, and ``enk_nested_req`` are of +special significance. See ``il_def.h`` and ``expr.c`` for details. + +Important Constrained-Template Functions +---------------------------------------- + +The following are some functions that are central to the handling of +constrained templates: + +* | ``scan_requires_clause`` and ``scan_concept_expression`` (both in + ``expr.c``). These are the functions that parse constraint expressions, + which requires special treatment of the logical operators (``&&`` and + ``||``). +* | ``scan_requires_expr`` (``expr.c``), which parses *requires-expression*\ s. +* | ``check_template_constraints`` (``templates.c``), which determines if a + given template's constraints are satisfied by a given set of template + arguments. +* | ``requires_clause_satisfied`` (``exprutil.c``). This function performs + substitution of constraint expression, which is subject to various subtle + rules. It leans heavily on the expression rescanning facilities (see + :ref:`rescanning-exprs`). +* | ``compare_constraints`` (``exprutil.c``). When determining the partial + order of function templates or partial specializations, constraint can play + a special role. This function, is the main function for comparing the + constraints on templates (to determine whether a template is more or less + constrained than another, or maybe neither is more constrained than the + other). The algorithm for this comparison is relatively complex and + described in great detail in ``exprutil.c``. + +Managing Instantiation of Functions, Variables, and Static Data Members +======================================================================= + +As noted previously, the full instantiation of template classes occurs as soon +as necessary, but no sooner. The timing for the automatic instantiation of +template functions, variables and members of template classes is more +complicated. + +For example, if a member function of a template class is not referenced, +there is no reason to instantiate it. But even if it is referenced, its +instantiation may occur elsewhere. The EDG C++ front end supports several +methods whereby the user can manage the instantiation of templates: +automatic instantiation, instantiation modes that are specified on the +command line, and explicit instantiation directives included in the source +code of the program. Explicit instantiation directives are supported in +both the form specified by the C++ standard and as ``#pragma`` directives. +For a detailed description of how the instantiation modes and pragmas are +used, see :ref:`template-instantiation`. + + +The ``instantiation_required`` flag in template instance entries is set to +indicate that a function, variable, or static data member has been referenced +in such a way as to require its definition (i.e., full instantiation) somewhere +in the program, even if not in the current translation unit. For example, +calling a template function causes the flag to be set. + +``update_instantiation_required_flag`` is called to set the flag and to place +the instance on a linked list (see ``add_to_instantiations_required_list``) so +that it can be readily found later, when the actual instantiation is done. +Sometimes the routine to do full instantiation is called immediately, however +(e.g., for calls to template functions that are declared as ``inline`` or when +in the midst of instantiation wrapup processing); in such cases the instance is +not placed on the list. + +It is ``do_any_needed_instantiations``, called by +``template_and_inline_function_wrapup``, as part of the ``fe_wrapup`` process, +that goes through the ``instantiations_required`` list. It determines for each +instance whether full instantiation is actually required in the current +translation unit as a result of the instantiation mode being used, explicit +instantiation and ``#pragma`` directives found in the program (see +``should_be_instantiated``, which checks instantiation modes and directives), +and whether the instantiation has been assigned to the current translation unit +by the automatic instantiation mechanism. It then will call +``instantiate_entity``, if appropriate. + +Instantiations are normally generated as part of the object file of the +translation unit in which the instantiations are performed. But when "one +instantiation per object" mode is specified, each instantiation is placed in +its own object file, and the names of those object files are written to the +template information file (which is described below). One instantiation per +object mode is useful when generating libraries that need to include copies of +the instances referenced from the library. If each instance is not placed in +its own object file it may be impossible to link the library with another +library containing some of the same instances. Without this feature it is +necessary to create each individual instantiation object file using the manual +instantiation mechanism. + +.. _template-auto-instantiation: + +Automatic Instantiation +----------------------- + +The EDG C++ front end provides a complete prototype implementation of an +automatic instantiation mechanism. The EDG automatic instantiation mechanism +is a "linker feedback" mechanism. It works by providing additional information +in the object file that is used by a "prelinker" to determine which template +entities require instantiation so that the program can be linked successfully. +Unlike most aspects of the front end the automatic instantiation mechanism is, +by its nature, dependent on certain operating system and object file format +properties. In particular the prelinker is a separate program that makes use +of the UNIX ``nm`` command to access information about the symbols defined in +object files. Furthermore it relies on features implemented in the ``eccp`` +driver script. Consequently, this code should be viewed as a sample +implementation that may need adaptation to work on other systems. + +This section describes the steps involved in automatic instantiation. The +steps are described in the sequence in which they would occur while compiling +and linking an application and not necessarily the sequence in which they occur +in a given execution of the front end. While one might expect the two +sequences to be the same the automatic instantiation mechanism may, in fact, +compile a given file a number of times while determining the set of +instantiations that are needed to link the application. + +Initial Compilation +^^^^^^^^^^^^^^^^^^^ + +When a program is compiled, the front end generates a set of flags that are +provided to the back end and are ultimately either output as a separate file by +the front end or are encoded in some form in the generated object file. The +flags are stored in the IL variable and routine entries. + +* | The ``can_be_instantiated`` flag indicates that this translation unit is + capable of generating an instantiation for a given function, variable, or + static data member (hereafter referred to as a "template entity"). This is + used by the prelinker to determine which source files are possible + instantiation sites for the template entity. This flag is set even if the + translation unit provides an instantiation of the template entity. +* | The ``instance_required`` flag indicates that a definition of the template + entity must be supplied by some translation unit (but not necessarily this + one). Both the ``instance_required`` and the ``can_instantiate`` flags + indicate that the entity is one that can potentially be defined by a + generated template instantiation. This information allows the prelinker to + distinguish between an unresolved template reference and a plain undefined + symbol. These flags are also used by the prelinker to distinguish class + specializations, whose members cannot be defined by generated + instantiations, from regular template classes whose members may be defined + by generated instantiations. +* | The ``do_not_instantiate`` flag indicates that instantiation of the + template entity has been explicitly prohibited by use of the + ``do_not_instantiate``\ ``#pragma`` directive. When automatic + instantiation is used, the ``do_not_instantiate`` pragma prohibits + instantiation not only in the file in which the pragma was included but + anywhere within the application with which the resulting object file is + being linked. + +In the default configuration, these flags are written to the template +information file, which is descibed below. In earlier versions of the front +end these flags were translated by IL lowering into tentative definitions of +specially named symbols. The old behavior can be selected using the +``INSTANTIATION_FLAGS_IN_TEMPLATE_INFO_FILE`` configuration flag. The flags +were removed from the object file because the amount of space consumed by the +names of the flags could be excessive, because the mangled names of template +entities can be very long. When the flags are generated as part of the object +file, the symbol names include a code that indicates the flag kind and also +includes the name of the symbol being described. The special symbol includes a +prefix of ``__CBI__`` (can be instantiated), ``__TIR__`` (template instance +required), or ``__DNI__`` (do not instantiate) followed by the mangled name of +the entity. For example, a template function of type ``void f(int)`` could +have the following flags generated. + +.. code:: text + + __CBI__f__fi__TIR__f__fi__DNI__f__fi`` + +Because they are generated as tentative definitions, they may each appear in +any or all of the object files being linked into an application while only +appearing once in the generated executable file + +When a template class contains noninline virtual functions, the instantiation +mechanism must ensure that the virtual function table is defined. IL lowering +does this by generating a "template instance required" flag for the first +noninline virtual function of any template class, because it's the presence or +absence of a definition for that function that controls whether or not IL +lowering puts out a definition for the virtual function table. By requiring +the first noninline virtual function to be defined we ensure that the virtual +function table will also be defined + +The Template Information and Instantiation Request Files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Information is exchanged between the front end and prelinker using the +"template information" and "instantiation request" files. These files are also +known respectively as the ``.ti`` and ``.ii`` files [#f1]_. The template +information file is used for infomation produced by the front end for use by +the prelinker. The instantiation request file is produced by the prelinker for +use by the front end. The template information file was added in version 2.37 +of the front end to support features such as one-instantiation-per-object mode, +and generation of instantiation flags in a separate file instead of the object +file. The front end can be configured to not use a template information file +in order to be compatible with earlier versions of the front end, but this +requires that the features that use the template information file be disabled. + +The template information file provides several diferent kinds of information to +the prelinker. Each line of the file contains a type code followed by a +string. The type code indicates the type of information being provided. The +following types of lines are generated by either the front end or driver: + +* | ``cmd:`` command line (supplied by the driver) +* | ``dir:`` compilation directory (supplied by the driver) +* | ``fnm:`` compilation file name (supplied by the driver) +* | ``idn:`` instantiation directory (in one-instantiation-per-object mode, + supplied by the driver) +* | ``flg:`` instantiation flags (when not encoded in the object file) +* | ``ifn:`` instantiation file names (in one-instantiation-per-object mode) +* | ``stu:`` secondary translation units (supplied by the driver) +* | ``tnm:`` export templates defined in this file +* | ``dep:`` dependency information when exported instantiations have been + generated + +The order in which these are specified is not, in general, significant except +that the prelinker currently requires that the instantiation directory entry +precede any instantiation file name entries. + +The template information and instantiation request files have the same base +name as the source file, but use special suffixes specified by configuration +parameters in ``host_envir.h``, with the default values indicated above. + +At the end of each compilation the front end determines whether any template +entities were referenced in the translation unit. If so a template information +file is created (or an instantiation request file, if template information +files are not being used). If no template entities were referenced in the +translation unit the file will not be created and any existing file will be +removed. When template information files are being used, the instantiation +request file is also removed if the template information file is removed. + +After invoking the front end the driver checks for the existence of either the +template information or instantiation request file, depending on the +configuration. If one exists, the driver updates it with the command line used +to compile the source file, the name of the current directory when the +compilation was done, and the name of the file that was compiled. This +information is used later if the prelinker needs to recompile the file. + +Prelinker +^^^^^^^^^ + +Once a complete set of object files has been generated, including the +appropriate flags, the prelinker is invoked to determine whether any new +instantiations are required or if any existing instantiations are no longer +required. The command line arguments to the prelinker include a list of input +files to be analyzed. The input files are the object files and libraries that +constitute the application. The prelinker begins by looking for template +information files for each of the object files (or instantiation request files, +if template information files are not being used). If no template information +(or instantiation request) files are present, the prelinker concludes that no +further action is required. + +If there are template information (or instantiation request) files, the +prelinker reads the template information file and the current instantiation +list from the instantiation request file. The instantiation list is the list +of instantiations assigned to a given source file by a previous invocation of +the prelinker. The prelinker uses the UNIX ``nm`` command to produce a list of +the global symbols that are referenced or defined by each of the input files. +The prelinker then simulates a link operation to determine which symbols must +be defined for the application to link successfully. + +When the link simulation has been completed, the prelinker processes each input +file to determine whether any new instantiations should be assigned to the +input file or if any existing instantiations should be removed. The prelinker +goes through the current instantiation list from the instantiation request file +to determine whether any of the existing instantiations are no longer needed. +An instantiation may be no longer needed because the template entity is no +longer referenced by the program or because a user supplied specialization has +been provided. If the instantiation is no longer needed, it is removed from +the list (internally; the file will be updated later) and the file is flagged +as requiring recompilation. + +The prelinker then examines any symbols referenced by the input file. The +responsibility for generating an instantiation of a given entity that has not +already been defined is assigned to the first file that is capable of +generating that instantiation. + +If a given file contains instantiations of exported templates, the template +information file contains dependency information. If a source file that is +part of an exported template translation unit changes, the dependency +information is used to detect such a change so that the prelinker can recompile +the file and regenerate the instantiations of the exported templates. + +Recompilation +^^^^^^^^^^^^^ + +Once all of the assignments have been updated, the prelinker once again goes +through the list of object files. For each, if the corresponding instantiation +request file must be updated, the new file is written. Only source files whose +corresponding instantiation request file has been modified will be recompiled. + +At this point the combination of the template information and instantiation +request files contains the information needed to recompile the source file, and +a list of instantiations assigned to the source file (in the form of mangled +function, variable and static data member names). + +Then, during recompilation the front end reads the entries from the +instantiation request file produced by the prelinker and checks them against +entries on its own "instantiations required" list. Whenever a match is found, +based on comparing the mangled name from the instantiation request file and the +name returned by either ``get_mangled_function_name`` or +``get_mangled_variable_name`` (in ``lower_il.c``), the +``automatically_instantiated`` flag is set in the template instance entry. + +When the prelinker invokes the front end, it provides a "definition list file", +which contains a list of all the external definitions found in the object files +and libraries specified on the prelinker command line. The front end reads the +definition list file and determines whether each of the entries on its +instantiations required list has already been defined elsewhere. If an entity +is found that is not defined elsewhere, its ``automatically_instantiated`` flag +is set. + +Later, in ``instantiation_wrapup``, instantiations will be generated for all +instances for which the ``automatically_instantiated`` flag is set, whether as +a result of being included in the instantiation request file or "adopted" by +the front end when it was determined that the instance was not defined +elsewhere. A list of the entities adopted by the front end is written to the +definition list file. This list is used by the prelinker to add the adopted +entities to the adopting translation unit's instantiation request file. + +The definition list file permits the front end to perform instantiations that +have become necessary as a result of other instantiations that were assigned by +the prelinker, without requiring that the prelinker invoke the front end an +additional time to perform those instantiations. This reduces the number of +iterations of the prelinker and front end that are required to generate a +complete set of instantiations for a program. + +If an error occurs during a recompilation, the prelinker exits without updating +the remaining information files and without attempting any additional +compilations. + +Iteration and Termination +^^^^^^^^^^^^^^^^^^^^^^^^^ + +If all recompilations complete without error, the prelink process is repeated, +since an instantiation can produce the demand for another instantiation. This +prelink cycle (finding uninstantiated templates, updating the appropriate +instantiation request files, and dispatching recompilations) continues until no +further recompilations are required. [#f2]_ + +When the prelinker is finished, the linker is invoked. Note that simply +because the prelinker completes successfully does not assure that the linker +will not detect errors. Unresolvable template references and other linker +errors will not be diagnosed by the prelinker. + +In many cases, once the application has been successfully linked, the +recompilation overhead will have become a one-time-only expense, because the +next time the source file is compiled, the instantiation request file will +provide precisely the right list of instantiations to be done. Recompilation +will be required again only if the instantiation request file is invalidated, +that is: + +* | if additional instantiations come to be needed (in this or another file); +* | if existing instantiations are not longer referenced; +* | if a different set of command-line options is used to compile the file; or +* | if the instantiation request file is deleted. + +Except in such cases, once the complete set of instantiation request files has +been generated, the prelinker should not need to force recompilation for any +source files in the application. + +Implementing Alternative Automatic Instantiation Mechanisms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The default automatic instantiation implementation uses the instantiation +request file as described above. The routines in ``templates.c`` are designed +to permit an alternative mechanism to be used (e.g., querying a database) to +determine whether a given entity should be instantiated. This may be done by +modifying the following routines: + +* | ``init_auto_instantiation_information`` is called at the beginning of the + automatic instantiation processing. The default version calls + ``read_auto_instantiation_information``, which opens the instantiation + request file and reads its contents. +* | ``check_if_entity_should_be_automatically_instantiated`` is called for each + instantiatable entity (external function, variable, or static data member). + It sets the ``automatically_instantiated`` flag if the entity is to be + instantiated in this translation unit, and the ``add_to_request_file`` flag + if the instantiation was "adopted" by this translation unit and must be + added to the instantiation request file by the prelinker. The default + version calls ``check_if_present_in_request_file`` to determine whether the + specified entity was named in the instantiation request file and/or the + definition list file. +* | ``wrapup_auto_instantiation_information`` is called by ``fe_wrapup``. The + default version calls ``create_or_remove_instantiation_information_file`` + and ``close_or_remove_template_info`` file. + +Instantiation Modes +------------------- + +The instantiation mode is specified by a command line option and determines +whether the compiler should automatically generate instances of template +entities (function templates, variable templates, member function of template +classes, and static data members of template classes.) The command line option +is used to set the global variable ``instantiation_mode`` to one of the +following values: + +.. list-table:: + + * - | ``tim_none`` + - | Do not automatically create instantiations of any template entities. + This is the default. + * - | ``tim_used`` + - | Instantiate those template entities that were used in the compilation. + This will include all static data members for which there are template + definitions. + * - | ``tim_all`` + - | Instantiate all template entities declared or referenced in the + compilation unit. For each fully instantiated template class, all of + its member functions and static data members will be instantiated + whether or not they were used. Nonmember template functions will be + instantiated even if the only reference was a declaration. + * - | ``tim_local`` + - | Similar to ``tim_used`` except that the functions are given internal + linkage. This is intended to provide a very simple mechanism for + those getting started with templates. The compiler will instantiate + the functions, variables and static data members used in the + compilation as local (static) functions and local (static) variables. + +Inline functions are usually instantiated when they are first referenced, and +so unreferenced inline functions are usually not instantiated. However, in +``tim_all`` mode they are always instantiated -- either during +``instantiation_wrapup`` or, for member functions for which the body is +supplied in the class template definition, when the class is instantiated. + +``#pragma`` Directives +---------------------- + +There are three instantiation pragmas, ``instantiate``, which causes the +specified entity to be instantiated, ``do_not_instantiate``, which causes +instantiation of the specified entity to be suppressed, and +``can_instantiate``, which indicates that the specified entity can be +instantiated by an automatic instantiation mechanism, but need not be. [#f3]_ +The ``do_not_instantiate`` pragma is typically used with the manual +instantiation mechanisms when a specific definition will be supplied elsewhere. + +The argument to the instantiation pragmas may be a template class name, a +member function name, a variable name, a static data member name, a member +function declaration, a function declaration, an elaborated type specifier for +a class, or a static data member declaration. When a class name or elaborated +type specifier is specified, the directive is applied to all member functions +and static data members of the class. + +Processing the pragmas results in setting some flags in the template instance. +They are later checked by ``should_be_instantiated`` (called from +``instantiation_wrapup``) to determine whether the entity requires full +instantiation. The ``instantiate`` pragma sets the ``instantiation_required`` +and ``explicit_instantiation`` flags and records the current source position +(for reporting errors later). The ``do_not_instantiate`` pragma clears +``instantiation_required`` and sets ``specific_def`` to block instantiation +based on the instantiation mode. + +Explicit instantiations are processed by ``instantiation_wrapup`` in much the +same way as instantiations that may be generated depending on the instantiation +mode. The only difference is that certain conditions that are ignored for +nonexplicit instantiations cause errors to be issued for explicit +instantiation. If no template definition has been supplied from which to +generate an instantiation, an error is issued for explicit instantiation +requests. Likewise, if a specific definition has been supplied and an explicit +instantiation was requested, an error is also issued. + +.. _explicit-instantiation: + +Explicit Instantiation Directives +--------------------------------- + +Explicit instantiation directives are processed in nearly the same way as +instantiation pragmas. The differences between the handling of the +instantiation pragma and an explicit instantiation directive are as follows: + +* | Inline functions may be specified in explicit instantiation directives, + even though doing so is meaningless. +* | An entity may not appear in more than one explicit instantiation directive. +* | Explicit instantiation directives require that a declaration follow the + ``template`` keyword, while the instantiation pragmas permit a simple name + to be specified. + +.. _implicit-inclusion: + +Implicit Inclusion +------------------ + +In the *cfront* model of programming with templates the template +declarations are placed in a header (e.g., "``.h``") file while the +definitions of noninline functions and static data members are placed in a +source (e.g., "``.c``") file. To support this style of programming the +front end provides an optional "implicit inclusion" feature. When this +feature is enabled, the front end will implicitly include a source file +when needed to provide definitions of template entities declared in a given +header file. + +When a header file is included, information about the kind of include statement +used is stored in the IL source file structure. This specifies whether the +include statement was a "normal" include (e.g., ``#include "file.h"``) or a +system include (e.g., ``#include ``). + +At the end of compilation, during instantiation wrapup processing, the source +file associated with a given header file will be included if needed. A file is +"needed" if an instantiation of an entity is required as a result of a command +line option, pragma directive, or instantiation list file. In automatic +instantiation mode implicit inclusions of template definition files will +essentially always be done so that accurate "can be instantiated" flags may be +generated. + +The implicit inclusion is done by searching through each of the directories in +the appropriate search path list (based on the kind of include statement used +to include the header file). A configuration parameter specifies a list of +file suffixes to be used during the search for a file to be implicitly +included. In each directory on the search path each of the possible suffixes +will be tried in sequence. If no matching file is found, the next directory in +the list is used. If no matching file is found in any directory, no error is +reported (unless the instantiation was explicitly requested using an +``instantiate`` pragma in which case an error will be issued indicating that no +template definition was supplied). + +Instantiating Non-Template Inline Functions +------------------------------------------- + +The front end provides two implementations of C++``extern inline`` functions, +referred to as "lower extern inline" and "instantiate extern inline". The +"lower" version is the default, and causes extern inline functions to be +translated into static functions with special care taken to ensure that +entities such as local static variables have the proper semantics. (See the +comments on the definition of ``INSTANTIATE_EXTERN_INLINE`` in ``targ_def.h`` +for the advantages and disadvantages of each implementation.) + +The "instantiate" version, which is enabled by setting the +``INSTANTIATE_EXTERN_INLINE`` configuration flag, ensures that only a single +external out-of-line copy of the inline function is generated, and then only if +one is required by the program. The automatic template instantiation mechanism +is used to implement this mechanism. + +When an inline function is defined, ``add_to_inline_function_list`` is called +to add the function to a list of all of the inline functions in the translation +unit. During the wrapup processing at the end of the compilation, +``inline_function_wrapup`` uses the inline function list to determine which +inline functions should have their bodies emitted as part of this compilation. +The ``suppress_inline_body`` flag in the routine entry is cleared if a back end +should emit an out-of-line body of an inline function. +``update_inline_function_flags`` emits instantiation flags as is done for +template entities. The prelinker will then assign the "instantiation" of +inline functions for which out-of-line bodies are required. + +.. _exported-templates: + +Exported Templates +================== + +The C++ standard specifies that the definition of certain templates (static +data members and non-inline functions) can be separately compiled. This +feature is generally referred to as "export" as such templates are declared +using the ``export`` keyword. The definition of an exported template is +provided in a single translation unit. Other translation units that use the +template require only a declaration of the template. + +Exported templates require special processing not needed for normal +(non-exported) templates: + +* | When the definition of an exported template is encountered, a record of the + translation unit containing the exported template must be made so that the + definition can be found later when an instantiation is needed. +* | When an instantiation of an exported template is generated, the front end + must be able to search for a definition of the template. +* | Generating an instantiation of an exported template requires that the front + end have access to information about the translation unit containing the + template definition and the translation unit containing the reference. One + exported template may call another, which may call another, and so on. As + a result, the front end must be able to simultaneously process an arbitrary + number of translation units at the same time (see :ref:`multi-tu`). +* | Whenever a partial or full instantiation of an entity must be done, the + front end must update its context information so that the translation unit + containing the template is the current translation unit + (see :ref:`multi-tu-dispatch`). + +When an exported template is defined, information about the definition must be +recorded. ``add_to_exported_templates_list`` is called when an exported +definition is encountered. This information is used at the end of the +compilation to create a file that provides a list of the exported templates +defined in the translation unit. This file is known as the "exported template" +file and, by default, has a suffix of ``.et``. The following is an example of +an exported template file: + +.. code:: text + + fnm:t.c + tnm:f__tm__4_Z1Z__FZ1Z_v + tnm:f2__tm__4_Z1Z__FZ1Z_v + mid:t_c_ee131b0b + def:XXX=3 + und:YYY + end: + +The following types of lines appear in such a file: + +* | ``fnm:`` The name of the primary source file to be used when reloading the + translation unit. +* | ``tnm:`` The mangled name of a template defined in the translation unit. +* | ``mid:`` The module ID to be used when instantiating templates from the + file. +* | ``def:`` A command-line macro definition to be used when reloading the + translation unit. +* | ``und:`` A command-line macro un-definition to be used when reloading the + translation unit. +* | ``end:`` The end of the entries associated with the previous ``fnm:`` + entry. + +The information for a given file always begins with "``fnm:``" and ends with +"``end:``". This makes it possible to concatenate a group of exported template +files together, which is useful when creating a library that defines exported +templates. + +When the front end compiles a file that makes use of exported templates, a +search path of exported template directories is used to locate the file that +defines a given exported template. The entries on the search path are +specified with the ``--template_directory`` command-line option. The front end +searches each of the directories in the search path to find any exported +template files that exist there. Each of the exported template files is read +to determine which exported templates are defined, and the name of the file +that defines each template. An exported template directory can also contain a +file named ``export_info``, which provides information used when reloading +exported template translation units. The export info file contains the include +search path to be used when reloading a translation unit. If no export info +file is present, the include search path associated with the primary +translation unit is used. + +A translation unit may contain entities that must be given unique names (e.g., +unnamed namespace members). A "module ID" is used as part of the name in such +cases to ensure that the name is unique. The instantiation of an exported +template must be able to refer to, and generate additional, entities with +appropriate unique names. To accomplish this, the module ID is saved in the +exported template file and that module ID is re-used when the translation unit +containing the exported template definitions is reloaded. + +When an exported template translation unit is reloaded, it undergoes what is +basically the normal compilation process, except that none of the external +entities defined in the translation unit are emitted. Only the instantiations +of exported templates, and other templates or inline functions referenced as a +result of such instantiations (directly or indirectly) are emitted. The +entities that are emitted are copied into the IL of the primary file being +compiled (see :ref:`multi-tu-copy`). The command-line options used when the +exported template translation unit is loaded are the same options used to +compile the primary translation unit. The only exceptions are command-line +macro definitions/undefinitions, and the include search path to be used. The +command-line macro definitions/undefinitions are saved in the exported template +file, and those values are used when the exported template translation unit is +loaded (include search path handling is described above). + +A mangled name is generated for each exported template. It is this mangled +name that is used to match a reference to an exported template with the +definition found elsewhere. A hash table of exported template definitions is +built as the exported template files are read. When an instantiation is +needed, the mangled name is looked up in the hash table to see if a definition +is available. If a definition is available, ``process_translation_unit`` is +called to load the translation unit that defines the exported template. + +A template instance entry is created for each function, variable, or static +data member instance that is partially or fully instantiated. If a given +instance is declared in more than one translation unit, there will be multiple +template instance entries created. In addition, a "master instance" entry is +created to represent the information that is shared among translation units. +For template instances in the primary translation unit, the master instance is +created when the template instance is added to the instantiation required list. +For template instances in secondary translation units, the correspondence +information is used to find a master instance entry that may have been already +created for an earlier translation unit. Because the correspondence +information is not set until a translation unit has been completely scanned, +the master instance information cannot be established until after scanning has +completed. The master instance entry points to the template instance entry +associated with the canonical copy of the instance (see +:ref:`canonical-entries`). Each template instance contains a pointer to the +associated master instance. + +Instantiations of exported templates are generated during the "instantiation +wrapup" process, which is performed by ``template_and_inline_function_wrapup``. +The instantiations required list for each translation unit is examined, and +instantiations are generated if appropriate. An instantiation in one +translation unit may result in the need for an instantiation in another +translation unit. Because the other translation unit may already have been +processed, the wrapup process must iterate over the set of translation units +until no additional instantiations are added for during an iteration. + +The instantiation of a function, variable, or static data member is initiated +by calling ``instantiate_entity`` with the template instance entry of the +instance to be generated. For exported templates defined in other translation +units, the translation unit is loaded and ``find_corresponding_instance`` is +called to find or create the template instance entry in the exported template +translation unit that corresponds to the one for which the instantiation is +being generated. The corresponding instance is then used for the remainder of +the instantiation process. + +A "translation unit stack" is maintained when instantiating an entities defined +in other translation units. This stack serves two purposes: it provides a +sequence of lookup contexts for resolving dependent function names during the +instantiation process, and it provides a record of the translation unit +switches that have taken place so that the prior translation unit state can be +restored when an instantiation has completed. + +C++/CLI Generics +================ + +C++/CLI generics are sort of like templates, and sort of not. They have +arguments, but the arguments are more constrained than for templates, being +effectively only managed class types or handles to them, value classes, +fundamental types, or scoped enum types. (And types only: No nontype +arguments, no template template arguments.) In addition, generics can have +user-written constraint clauses that further restrict the valid argument values +to certain kinds of class types. Generic classes do get instantiated for each +set of template arguments, much like template classes, but generic functions +effectively have just one instantiation, which corresponds to a single routine +body that can operate on all types. That's possible because the function can +only perform those operations that are valid based on the declared constraints. +That allows the instantiation of generic functions to be delayed until runtime +and for most references to share a single instantiation (for example, all +instantiations based on handles to ref classes share a single instantiation at +runtime). That in turn forces some restrictions on the code that can be +written in generic functions. + +Generics are represented as templates marked with the ``is_generic_definition`` +flag in the class type or routine entry. If they have constraints, those are +represented by entries of type ``a_generic_constraint`` and +``a_generic_constraint_clause``. + +Generic classes and generic functions don't get the standard prototype +instantiations. Instead, they undergo a process similar to prototype +instantiation (and kicked off by the same routine that does prototype +instantiations) using invented types based on the constraints. The result is +marked as a "generic definition" instead of a prototype instantiation. The +same process applies to static data members as well. + +During the generic definition instantiation, a "constraint type" is created for +each generic parameter. It is a class type that reflects the constraints, +e.g., if the generic parameter is required to be derived from a class X, the +constraint type has X as a base class. The constraint type is a real type (not +a nonreal type), and lookups can be done in it. Such lookups in fact +significantly define what can be done with an object of that generic parameter +type, in the sense, for example, that a "``+``" operation can be done only if a +lookup finds an appropriate "``operator+``" function in the constraint type. + +The actual type that is used for a given generic parameter type during the +generic defintition instantiation is known as the "generic definition argument +type." It is a handle to the constraint type except in cases when the generic +parameter is constrained to be a value class type, in which case it is the same +as the constraint type. + +During the generic definition instantiation, the template parameter symbols for +the generic are set to the generic definition argument type. That makes a lot +of processing, in declarations and expressions, work out fine without special +handling: uses of the template parameter name produce the generic definition +argument type, and for the most part that that can be processed without +difficulty. In particular, the generic definition argument type is not a +dependent type, and therefore real types can be built (instead of unknown +template parameter types), real results of overload resolution can be +determined, etc. However, there are also cases where one wants to think of the +type as being the generic parameter type. There's a duality here: the template +parameter type and the generic definition argument type are really equivalent +types, and sometimes we want one and sometimes the other. We chose to make the +default value be the generic definition argument type, because that seemed to +work out better in terms of requiring less special-case code, but whichever way +we had decided that there would be cases that wanted to look at the type the +other way. Fortunately, because the types point to each other, it's easy to +flip to the other representation if one has the wrong one. See, for example, +``generic_param_if_generic_definition_argument``. + +Because the rules for valid generic template arguments are different than those +for normal template arguments, a special routine is used to scan generic +template argument lists: ``scan_generic_argument_list``. It calls +``is_valid_generic_argumen``\ t to check that each argument is valid for any +kind of generic. Later, when one has a full set of generic type arguments +(whether from an explicit list or through type deduction), +``verify_generic_arg_list_satisfies_constraints`` is called to check that the +arguments satisfy their constraints. + +Generic classes can overload on arity, meaning that there can be multiple +generic classes with the same name, but differing numbers of type arguments, +declared in the same scope. That is not valid in source code, but it does come +up in libraries written in other languages and imported via metadata. When +such overloading occurs, the first generic that is declared is what is entered +into the symbol table and what is returned by lookup. The template symbol +supplement for that symbol has a pointer to a list of any other generic classes +with the same name and different arities in the same scope. If there is also a +non-generic class in the same scope, it is pointed to by another pointer there. +With this information, references to the name can be resolved to the proper +instance of the generic or to the non-generic. + +Template deduction for generics is done in the usual way; there are no special +tricks to speak of. + +.. [#f1] The instantiation request file was formerly known as the + "instantiation information" file, before the template information file + came into existence. The name of the instantiation information file + was changed to avoid confusion, but the ``.ii`` suffix was retained + for compatibility reasons. +.. [#f2] The number of iterations is limited by a parameter defined in + ``edg_prelink.h``. The default is 30 iterations. This prevents the + prelinker from getting in an infinite loop if a recursive + instantiation is encountered. +.. [#f3] At the moment, the ``can_instantiate`` pragma ends up forcing the + instantiation of the template instance even if it isn't referenced + somewhere else in the program; that's a weakness of the initial + implementation which we expect to address. diff --git a/doc/_sources/testing.rst.txt b/doc/_sources/testing.rst.txt new file mode 100644 index 0000000..9274d96 --- /dev/null +++ b/doc/_sources/testing.rst.txt @@ -0,0 +1,965 @@ +===================== +EDG Testing Framework +===================== + +The EDG front end testing framework is fundamentally based on process exit +codes and recorded "expected output." + +Writing a Test File +=================== + +Test files are written using a series of directives at the start of the test +file. + +The following is a sample single-file test (the common case) to help illustrate +some of the features described below: + +.. code:: c++ + + //remark:Simple friend functions in class template + //options::;cn + template class A { + friend int f(A); + int i; + }; + + A a; + + int f(A a) { + return a.i; // Should be OK + } + + #if TEST_NUMBER==2 + int f(A a, int i) { + return a.i; // No access -- should fail + } + #endif + +Single-file Testing +------------------- + +Individual test files end in either ``.sft.c`` or ``.sft.cpp`` depending on +the programming language being tested. The testing directives that can be +used in a single-file test are enumerated below. Additional directives +have meaning in multi-file tests and are described in :ref:`mtu-testing`. + + | ``//remark:``\ *A string that gets printed on the output* + | ``//type:``\ *xx* + | ``//name:``\ *xxx* + | ``//options:-a:-b=xx:-c=`` + | ``//options_all:-A`` + | ``//options_sep:``\ *x* + | ``//match_regex:``\ *regular expression* + | ``//cases:``\ *n* + | ``//eccp_command:``\ *compile-command* + | ``//ulimit:``\ *options* + | ``//linker_options:``\ *options* + | ``//execution_args:``\ *command line arguments* + | ``//use_system_includes:``\ *true/false* + | ``//edg_header_pack:``\ *string* + | ``//require:``\ *string* + | ``//filter:``\ *pipe-command* + +*xx* is a type identifier. The accepted values are: + ++------------+--------------------------------------------------------------+ +| Identifier | Meaning | ++============+==============================================================+ +| ``fn`` | front end only negative | ++------------+--------------------------------------------------------------+ +| ``fp`` | front end only positive | ++------------+--------------------------------------------------------------+ +| ``fc`` | front end - expect catastrophic error | ++------------+--------------------------------------------------------------+ +| ``cn`` | compile negative | ++------------+--------------------------------------------------------------+ +| ``cp`` | compile positive (including compiling generated C) - DEFAULT | ++------------+--------------------------------------------------------------+ +| ``cc`` | compile - expect catastrophic error | ++------------+--------------------------------------------------------------+ +| ``ln`` | compile and link negative | ++------------+--------------------------------------------------------------+ +| ``lp`` | compile and link positive | ++------------+--------------------------------------------------------------+ +| ``rn`` | runtime negative | ++------------+--------------------------------------------------------------+ +| ``rp`` | runtime positive | ++------------+--------------------------------------------------------------+ +| ``ra`` | runtime - expect abort | ++------------+--------------------------------------------------------------+ +| ``cppbe`` | a special C++-generating back end only mode that dumps the | +| | generated code for review and validation | ++------------+--------------------------------------------------------------+ +| ``s`` | skip the test | ++------------+--------------------------------------------------------------+ + +Positive tests expect a return code of zero. Negative tests expect a +non-zero return code. + +The ``//name:`` directive specifies the name to be used when the file is +compiled. This is useful for tests that need to test platform support for +Unicode file names and similar file name-dependent scenarios. + +The ``//options:`` directive specifies a set of command line options to be +used, separated (by default) by colons. The compiler will be invoked once +for each set of options. An option set can override the type specified by +appending the optional string ``;``\ *xx* on the end of an option +specification. + +If the options need to include a colon, the ``//options_sep:`` directive +can be used to specify a different separator. For example, +``//options_sep:!`` will change the separator to ``!``. The separator can +be multiple characters. + +The ``//options_all:`` directive specifies a set of command line options +that will be provided on every compilation. This is useful for tests with +a single case and for options that don't vary from case to case. This may +be used in conjunction with the ``//options:`` directive. The options from +each option set are put in the command line after the ``//options_all:`` +string so that they can override values in the ``//options_all:`` string. + +The ``//match_regex:`` directive allows specification of a regular +expression (expressed in the Python regex dialect) that must be found in +the output for the test to pass. Matches will additionally add sections to +the captured output highlighting the matching lines (thus serving as a +further sanity check against unintended changes). This directive is +particularly useful if wanting to require fine grained details like +specific diagnostics, IL output fragments, or generated C++ code (when +using a ``cppbe`` test). + +The ``//linker_options:`` directive specifies an additional set of options +that are placed at the end of the command used to compile and link the +program and is intended to be used for library names. + +The string specified in the ``//remark:`` directive is printed in the test +results output to help identify what a test is doing. + +As shown in the initial testing example, it is often useful to be able to have +code conditionally compiled for each of the different compilations specified by +the options string. The test driver defines a preprocessor variable named +``TEST_NUMBER``. This variable has the value "1" for the first set of options, +"2" for the second, and so on. + +If you have a number of test cases that don't require different command +line options and that have the same result type you can use the +``//cases:``\ *n* directive to specify that the compiler should by invoked +*n* times, with ``TEST_NUMBER`` set to the current invocation number. + +``//options:`` and ``//cases:`` can be used together. For example, you may +have five test cases but only need to specify options for the first two. + +.. code:: c++ + + //options:-A;cn:-O;cn + //cases:5 + +The ``//ulimit:`` directive specifies command-line options passed to a +``ulimit`` command prior to compiling, linking, and running the test. This +can be used to prevent a test from exhausting system resources or running +in a non-terminating loop. + +Special characters can be incorporated into the test case by using special +escape sequences. The escapes are of the form ``???``\ *nnn* where *n* is +a decimal digit. + +If ``//require:`` is specified, the string that follows is searched for in the +output of ``--dump_configuration``; if not found, the test is skipped. If +multiple ``//require:`` cases are specified, all strings must be found or the +test will be skipped. + +If ``//use_system_includes:`` is set to ``true``, the system headers +associated with the current EDG base will be added to the default include +paths. Additionally, EDG compiler emulation modes will be enabled as +appropriate. For instance, if the test is run using a GCC 15.1 base this will +add the include paths for system headers associated with GCC 15.1 and +``--gnu_version 150100`` to the command line. Otherwise, if this directive is +set to ``false``, EDG headers in ``include_c99`` (for C programs) and +``include_c++`` (for C++ programs) will be added to the default include paths. + +The ``//edg_header_pack:`` directive specifies an "EDG header pack" to include +as system headers for testing. Header packs are include directories that are +themselves subdirectories of ``$TEST_ROOT/.includes/``. For instance, +``//edg_header_pack: foo`` will result in a hidden +``--sys_include $TEST_ROOT/.includes/foo`` command line argument. + +If ``//filter:`` is specified, the specified command will be used to filter +the ``run_test`` output before ``diff``-ing it. By default, a test driver +uses in-process test normalization logic as a filter. + +.. _mtu-testing: + +Multi-file Testing +------------------ + +Multi-file tests work similarly to single-file tests; however, they end +with either ``.mft.c`` or ``.mft.cpp``. Additionally, for correct +operation, these tests live in their own test directory, typically +following the convention of ``test-name/test.mft.cpp``. This allows the +test to live alongside its supporting files. + +For instance, testing a simple C++ ``#include`` might using the following +structure: + +.. code:: text + + simple-include/ + test.h + test.mft.cpp + +Similarly, for testing an import of a module, the test might use the +following structure: + +.. code:: text + + modules-function/ + exporting-module.ixx + test.mft.cpp + +where ``test.mft.cpp`` contains the testing directives (described below) that +compile ``exporting-module.ixx``. + +As previously noted, there are additional directives which are useful for +multi-file testing: + + | ``//header_unit_files:t.h t2.h`` + | ``//module_files:i-part.ixx internal:i-internal.cpp i.ixx obj:msvc-module.ixx`` + | ``//script:``\ *script_file* + +The ``//header_unit_files:`` directive specifies any header files that should +be compiled via ``--create_header_unit`` and passed to the test invocation via +a ``--header_unit`` mapping. + +The ``//module_files:`` directive specifies any module files to be compiled for +the test. + +In most cases these files should be listed without a prefix; such files are +presumed to be module interface source files and will be compiled with the +``--module_interface`` flag to generate both an IFC and a ``.obj`` file for +the module source file. + +If given the ``obj:`` prefix it's assumed the IFC file is already present and +only the ``.obj`` file should be compiled. + +If given the ``internal:`` prefix this is a module implementation unit that an +IFC file should be force-generated for (this is unusual). These module +source files are compiled under the ``--module_internal_partition`` flag to +generate both an IFC and a ``.obj`` file. + +If ``//script:`` is specified, that script is executed instead of any other +commands. In general, the test type does not matter for script files except +for checking the return code. For example, a ``cp`` test will expect a zero +return code, while a ``cn`` will expect a non-zero. The script will be passed +command-line arguments in the same way that the compile command would. + +Advanced Concepts +----------------- + +The directives are processed in the following sequence: + +- those specified in ``$TEST_ROOT/.run_test_flags`` +- (for multi-file tests) the ``flags.txt`` file in the directory of the test +- those specified at the start of the test file + +In some cases later directives overwrite earlier ones (e.g., ``//type:``). +In other cases, a list of the specified values is accumulated (in the order in +which the various lists are specified above). The directives for which the +values are accumulated are: + +- ``options`` +- ``options_all`` +- ``match_regex`` +- ``linker_options`` +- ``execution_args`` +- ``require`` +- ``header_unit_files`` +- ``module_files`` + +Compile tests are processed through ``eccp -c``. Runtime tests are +compiled and linked using ``eccp``. Compile and link tests are also +compiled and linked using ``eccp``, however a ``ln`` test is expected to +return a non-zero status from ``eccp`` where a ``rn`` test is expected to +return a zero status from ``eccp`` and a nonzero status when the program is +executed. If the ``//eccp_command:`` directive is used, the command +specified is used instead of the ``eccp`` command. + + +Testing Tools +============= + +There are two primary tools for testing, ``edgy`` and ``edg-run-test``. +Both of these tools rely on the same internal ``edgtest`` Python library, +they just provide a different interface to it. + +In most cases ``edgy`` is the preferred testing tool as it's designed for +large-scale testing. However, when authoring a new test ``edg-run-test`` +can be a great way to get immediate feedback. + +``edgy`` +-------- + +Usage information: + +.. code:: text + + usage: edgy [-h] [-c RUN_CONFIGS] [--runs-dir TEST_RUNS_DIRECTORY] + [--run-timestamp TEST_RUN_TIMESTAMP] [-j JOB_COUNT] [-T TIMEOUT_SECONDS] + [-A] [-D] [-E] [-M] [-R] [-n MAX_FAIL_COUNT] [--pick PICK_COUNT] + [--disp-run-dir] [-W] [--crash-avoidance] [--no-flakey-tests] + [--replay {all-failing,output-mismatch,regress,unexpected}] + [--slow-tests NUM_SLOW_TESTS_REPORTED] [--fully-random-order] + [--cmd] [--verbose] [filters] + + EDG test runner. + + positional arguments: + filters the test filter to apply; "all" for all suites + + options: + -h, --help show this help message and exit + -c, --config RUN_CONFIGS + the run configurations to apply + --runs-dir TEST_RUNS_DIRECTORY + override the directory where tests runs are stored + --run-timestamp TEST_RUN_TIMESTAMP + override the timestamp when creating a new test run (does + not apply to replay runs) + -j, --jobs JOB_COUNT the number of concurrent jobs + -T, --timeout TIMEOUT_SECONDS + the number of seconds to wait for tests before killing them + (0 to disable) + -A include slow tests (marked by an "_" prefix) + -D, --debug-failures print debug commands for failures + -E, --no-expectations + disable expectations + -M, --meticulous disable faster mode (on by default) and run all expensive + checking + -R, --regress silence non-regressive changes + -n, --max-failure-count MAX_FAIL_COUNT + the maximum number of failures + --pick PICK_COUNT the maximum number of tests to run (this option implies + --fully-random-order) + --disp-run-dir print the directory where the run output is being stored + -W, --record record tests + --crash-avoidance avoid tests that are likely to crash the compiler (this option + also implies --no-flakey-tests) + --no-flakey-tests do not run tests that are known to be flakey + --replay {all-failing,output-mismatch,regress,unexpected} + rerun tests from the last run + --slow-tests NUM_SLOW_TESTS_REPORTED + the number of the slowest tests to report + --fully-random-order completely randomize test execution order (this can help lower + system pressure by mixing more "intensive" test suites with + less intensive test suites) + --cmd print all run test commands + --verbose enable verbose mode + +Setup Requirements +^^^^^^^^^^^^^^^^^^ + +``edgy`` was designed to be usable from any directory. To facilitate this, +the ``EDG_TEST_HOME`` environment variable must be set to the directory +where the tests subdirectory and ``.edgy/config.json`` are. + +In the typical configuration, ``CPFE`` should be set to the C-generating +back end binary being tested and ``CPFE_CP`` should be set to the +C++-generating back end binary being tested. + +Filtering +^^^^^^^^^ + +```edgy`` works off of one or more (comma-separated) filters. These +filters are typically test suite names, e.g., + +.. code:: bash + + edgy regressions,stdlib + +Filter Reduction +~~~~~~~~~~~~~~~~ + +These can be reduced by adding addition path components. For instance, if +you want to run the tests in the ``modules`` directory of the +``regressions`` test suite, you can do so via + +.. code:: bash + + edgy regressions/modules + +You can also elaborate on this to dive down to a single test, e.g., +``regressions/foo.sft.cpp``: + +.. code:: bash + + edgy regressions/modules/foo.sft.cpp + +Special Filters +~~~~~~~~~~~~~~~ + +There are also a couple of special filters, the primary one is ``all`` +(which simply means all the test suites ``edgy`` knows about), e.g., + +.. code:: bash + + edgy all + +An additional very useful one is the ``mine`` filter. This filter is +configured by setting the ``EDGY_MY_TESTS`` environment variable to a +comma-separated list of test suites. For instance, if concerned primarily +with ``regressions`` and the ``stdlib`` impact in your work, this might be +a reasonable use: + +.. code:: bash + + export EDGY_MY_TESTS=regressions,stdlib + edgy mine + +Note that special filters cannot be reduced (e.g., ``edgy mine/xyz`` +does not work). + +Negative Filters +~~~~~~~~~~~~~~~~ + +Negative filters can be applied as well. These start with a ``!`` and are +applied as a reduction of positive filters, e.g., + +.. code:: bash + + edgy regressions,!regressions/modules + +Here we're running all tests in the ``regressions`` suite except for the +tests in the ``modules`` subdirectory. + +File-Loaded Filters +~~~~~~~~~~~~~~~~~~~ + +Filters can also be loaded from a file: + +.. code:: bash + + $> cat my_filters.txt + regressions + !regressions/modules + $> edgy @my_filters.txt + +The above is logically equivalent to the above negative filter example (the +filters are just spelled out in a file on a line-separated basis). + +This feature is particularly useful for working with fine-grained lists of +tests (such as ``edgy``'s ``.elog`` files). + +Live Feedback +^^^^^^^^^^^^^ + +Test Run Status +~~~~~~~~~~~~~~~ + +Progress reporting is provided by a (fairly rapidly) updating status line: + +.. code:: text + + 588/83,651 (0%) in 00:00:04 ~127/sec (00:10:54 remaining) + +This status line shows: + +.. code:: text + + / + (%) in + ~/sec + ( remaining) + +Problem Reporting +~~~~~~~~~~~~~~~~~ + +Any encountered problems are reported above the status line as they're +discovered. + +A completed run might look something like:: + + - regressions/foo.sft.cpp cp::ABORT: + + regressions/foo.sft.cpp cp::PASS--OUTPUT MISMATCH: + +"+" is used to indicate an unexpected problem, while "-" is used to indicate an +unsatisfied expectation (the above is an example of what might happen if there +was a regression resulting in a crash that has been resolved). + +When multiple configurations are in use, the configuration is specified in +parens prior to the test "name", e.g.:: + + + (edg_x86_64) regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH: + + (edg_x86_64_cp) regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH: + +``edgy`` also will print "commentary" in this output without using a marking +character. These are used to report extra information that might be +good to know (e.g., that a particular test ran very slowly), e.g., + +.. code:: text + + + regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH: + Consider marking regressions/foo.sft.cpp slow (Took: 00:01:04) + +Test Termination +~~~~~~~~~~~~~~~~ + +``edgy`` supports early termination when it receives ``SIGINT`` (Ctrl + C +in most shells) or ``SIGTERM``. Early termination will make edgy quickly +terminate all spawned process groups (and thus their processes). Any tests +terminated in this fashion will be reported to the user with an "X" prefix, +e.g., + +.. code:: text + + X regressions/foo.sft.cpp + X stdlib/bar/test.mft.cpp + X regressions/baz/test.mft.cpp + +Note: This is particularly helpful both for killing (and finding) tests that +are stuck in an infinite loop if your tests aren't terminating. + +Failure Debug Mode +^^^^^^^^^^^^^^^^^^ + +``edgy`` has a failure debug mode (enabled via ``-D`` or +``--debug-failures``) that enables additional "commentary" for failed +tests, aimed at debugging issues with said tests. + +For exposition purposes the below section uses ```` for the path +represented by ``EDG_TEST_HOME`` and ```` for the location of +the directory containing the front end ``cpfe`` binary. Additionally ``\`` +lines have been added to wrap lines. + +As an example, commentary from this option typically looks something like: + +.. code:: text + + RUN_TEST_DEFAULT_CONFIG="edg_x86_64" LC_ALL="C" CDISP="" \ + edg-run-test -o \ + /runs/2026.06.25-17.14.55/edg_x86_64/regressions + --driver-debug --faster -t \ + /tests/regressions \ + /tests/regressions/foo.sft.cpp + +This can be copied verbatim and when executed will print something like +the following: + +.. code:: text + + Source file clone: + cd $(clone-test-to-tmp /tests/regressions/foo.sft.cpp) + /cpfe -DTEST_NUMBER=1 --c++20 Test_name.c + +This combined information can then be used to set up a test directory, and a +debug command, following the general setup: + +.. code:: text + + + + +Using the above sample output, that would look something like: + +.. code:: text + + cd $(clone-test-to-tmp /tests/regressions/foo.sft.cpp) + RUN_TEST_DEFAULT_CONFIG="edg_x86_64" LC_ALL="C" CDISP="" \ + gdb --args /cpfe -DTEST_NUMBER=1 --c++20 Test_name.c + +This will quickly give you a debugger invocation (modulo any bugs/missing +features for test directory setup driver debug) that should exactly reproduce +the circumstances that resulted in ``edgy`` seeing what it saw. + +Note that many tests may not have a ``Source file clone`` line reported by +the test executor. In these cases it's perfectly safe to omit this (i.e., +```` may not always be a part of the pattern). + +.. _regress-mode: + +Regress Mode +^^^^^^^^^^^^ + +``edgy`` has a test regression reporting mode (enabled via ``-R`` or +``--regress``). This is aimed at reporting only those tests whose status +changed to something worse and is particularly useful for noisy tests where +there may be lots of valid ``--OUTPUT-MISMATCH``\ s. The severity ranking +used to determine what's "worse" is represented in the following table: + ++-------------------+------------------+ +| Test Status | Severity Ranking | ++===================+==================+ +| ``PASS`` | 0 | ++-------------------+------------------+ +| ``FAIL`` | 1 | ++-------------------+------------------+ +| ``BADC`` | 1 | ++-------------------+------------------+ +| ``CATASTROPHE`` | 2 | ++-------------------+------------------+ +| ``ABORT`` | 3 | ++-------------------+------------------+ +| ``RUNTIME ABORT`` | 3 | ++-------------------+------------------+ + +As an example, a ``FAIL`` to an ``ABORT`` will be reported, but an +``ABORT`` to a ``FAIL`` will not be reported. Similarly, ``FAIL`` to +``BADC`` (or vice versa) will not be reported. + +Failure Limiting +^^^^^^^^^^^^^^^^ + +``edgy`` has a failure limit mode (enabled via ``-n`` *MAX_FAIL_COUNT* or +``--max-failure-count`` *MAX_FAIL_COUNT*, where *MAX_FAIL_COUNT* is an +integer) that stops test execution after *MAX_FAIL_COUNT* tests have +been reported as problematic. This is compatible with regression mode, and +will only count reported regressions. + +Re-record Mode +^^^^^^^^^^^^^^ + +``edgy`` has a mode for updating test recordings and patching expectations +in the process (enabled via ``-W`` or ``--record``). + +As this mode is intended for usage only to update output, ``edgy`` does not +check expectations or otherwise report test status during re-recording. +The process for using re-record mode is something akin to the following: + +1. Run the tests +2. Review the changes +3. Determine if any tests' expectations or output need to be updated +4. Rerecord the tests that need to be updated (e.g, + ``edgy -W regressions/foo.sft.cpp``) + +No Expectations Mode +^^^^^^^^^^^^^^^^^^^^ + +``edgy`` has a no expectations mode (enabled via ``-E`` or +``--no-expectations``) which as the name implies disables expectations. +This is useful for seeing true test statuses (i.e., seeing all failures, +including failures that were previously marked as expected). + +No Flakey Tests Mode +^^^^^^^^^^^^^^^^^^^^ + +``edgy`` has a "no flakey tests" mode (enabled via ``--no-flakey-tests``) +which, as the name implies, skips known flakey tests. This is useful for +avoiding problematic tests that are known to regularly misdiagnose problems +in your configuration. + +For this to work, the configuration in use must have the flakey tests +listed in the ``$EDG_TEST_HOME/flakey-tests`` directory. For example, to +mark ``regressions/baz/foo.sft.cpp`` flakey in the ``foo-bar`` +configuration, one would add a file +``$EDG_TEST_HOME/flakey-tests/foo-bar/regressions.txt`` with the contents: + +.. code:: text + + baz/foo.sft.cpp + +Note: It's recommended (but not required) to organize this file alphabetically +for easier maintenance. + +Replay mode +^^^^^^^^^^^ + +``edgy`` has a mode for replaying a portion of the previous test run +(enabled via ``--replay``). It's important to note that the "runs" that +are replayed are the original "run" not a "replay", i.e., replay 2 is not +run against replay 1 but is run against the last run that wasn't a replay +run. + +Replay mode is compatible with the normal ``edgy`` options (e.g., filters). +Replay mode itself supports the following sub-options: + ++---------------------+-------------------------------------------------------+ +| Option | Description | ++=====================+=======================================================+ +| ``all-failing`` | All tests without ``PASS`` status/all tests that | +| | appear in the previous run's log files. | ++---------------------+-------------------------------------------------------+ +| ``output-mismatch`` | All tests with ``OUTPUT MISMATCH`` status (including | +| | tests that are otherwise passing). | ++---------------------+-------------------------------------------------------+ +| ``regress`` | All tests that had a status regression vs the current | +| | configuration's expectations (see the | +| | :ref:`regress-mode` section for more information | +| | about status regressions). | ++---------------------+-------------------------------------------------------+ +| ``unexpected`` | All tests that are reporting a status differing from | +| | the current configuration's expectations. | ++---------------------+-------------------------------------------------------+ + +Replay results are stored in the last test execution's run output directory +(typically ``tests/runs/``\ *some-timestamp*) in their own ``replays`` +subdirectory. Every time a replay is performed a new subdirectory will be +created within the respective replays subdirectory for the replay output. +This gives replay runs a few special characteristics: + +- Test selections are stable across all replay runs (in other words, if you + have run "T" you're replaying, replay "{N, N + 1, ...}" will not affect each + other's output/test selections). +- Replays can be run many times without resulting in ``edgy``'s test run + cleanup deleting anything. + +As a visual aid, this is the expected directory structure for a run with two +replays in the ``runs`` directory: + +.. code:: text + + . + ├── 2026.06.07-16.19.15 + │ ├── replays + │ │ ├── 1 + │ │ │ └── edg_x86_64 + │ │ │ ├── regressions + │ │ │ │ ├── test-a.rt + │ │ │ │ ├── test-b.rt + │ │ │ │ └── test-c.rt + │ │ │ └── regressions.log + │ │ └── 2 + │ │ └── edg_x86_64 + │ │ ├── regressions + │ │ │ ├── test-a.rt + │ │ │ ├── test-b.rt + │ │ │ └── test-c.rt + │ │ └── regressions.log + │ └── edg_x86_64 + │ ├── regressions + │ │ ├── test-a.rt + │ │ ├── test-b.rt + │ │ └── test-c.rt + │ └── regressions.log + ... + +Replaying Failed Test +~~~~~~~~~~~~~~~~~~~~~ + +As an example, consider you've run a test suite: + +.. code:: text + + edgy regressions + +This then revealed 5 of the 500 tests are failing. You then make a change, and +then want to run those 5 tests again to see if you've fixed the problem: + +.. code:: text + + edgy --replay all-failing + +This runs only the 5 failing tests. + +Replaying Subset of Failed Test +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As an example, consider you've run a test suite: + +.. code:: text + + edgy regressions + +This then revealed 50 of the 500 tests are failing, but you're only +interested in the 10 tests in ``regressions/foo``. You then make a change, +and then want to run those 10 tests again to see if you've fixed the +problem: + +.. code:: text + + edgy --replay all-failing regressions/foo + +This runs only the 10 failing tests. + +Replaying Mismatched +~~~~~~~~~~~~~~~~~~~~ + +As an example, consider you've run a test suite: + +.. code:: text + + edgy regressions + +This then revealed 5 of the 500 tests have an output mismatch due to changes +you made. You review the changes, and decide you want to rerecord these +tests: + +.. code:: text + + edgy --replay output-mismatch -W + +This runs only the 5 tests with the output mismatch, rerecording them and +updating expectations in the process. + +Replaying Regressions +~~~~~~~~~~~~~~~~~~~~~ + +As an example, consider you're working with volatile code that's failing many +tests, and you're using regression mode to focus down the reported tests: + +.. code:: text + + edgy -R regressions + +This then revealed 5 of the 500 tests are regressing while 50 are unexpected +status changes, and 200 are failing. The other replay modes will not help you +realistically narrow down the set of test output being reviewed. This is where +regress replays shine: + +.. code:: text + + edgy --replay regress + +This runs only the 5 tests that actually have regressive status changes, +allowing you to evaluate much more effectively whether your iterative +changes are improvements. + +Replaying Unexpected +~~~~~~~~~~~~~~~~~~~~ + +As an example, consider you've run a test suite: + +.. code:: text + + edgy regressions + +This then revealed 5 of the 500 tests differ from their expected status or +otherwise have an output mismatch. You review the changes, and decide you want +to rerecord these tests: + +.. code:: text + + edgy --replay unexpected -W + +This runs only the 5 tests, rerecording them and updating expectations in the +process. + +Slow Test Reporting +^^^^^^^^^^^^^^^^^^^ + +``edgy`` has a slow test reporting mode (enabled via ``--slow-tests`` +*NUM_SLOW_TESTS_REPORTED*, where *NUM_SLOW_TESTS_REPORTED* is an integer) +that reports the *NUM_SLOW_TESTS_REPORTED* slowest test executions. This +is compatible with all modes (with the exception of re-record mode which does +not record the necessary timings). + +Verbose Mode +^^^^^^^^^^^^ + +``edgy`` has a verbose mode (enabled via ``--verbose``) that enables +printing of additional details. Verbose mode provides additional +information about environment variables, what cleanup actions are being +taken, and remarks for failure debugging are turned on for every tests +(regardless of its pass/fail status). This can be useful for initial +setup, or when attempting to get a debug invocation for one or more test(s) +that aren't currently failing. + +Copying Tested Binaries +^^^^^^^^^^^^^^^^^^^^^^^ + +By default ``edgy`` copies the executables being tested for each test run. +This allows for (some degree of) working on the front end while testing +occurs as updated binaries will not impact testing. + +If the environment variable ``EDG_TEST_NO_COPY_``\ *X* is set or +``TEST_``\ *X* (where *X* is the environment variable corresponding +to the tested binary -- typically ``CPFE`` or ``CPFE_CP``) is set, this +functionality is disabled. + +Test Run Cleanup +^^^^^^^^^^^^^^^^ + +If the environment variable ``EDG_TEST_RUNS_KEPT`` is set to a valid +integer *N* (e.g., 10), ``edgy`` will only keep the last *N* entries in the +run directory. + +Note: This does not take into account directory names, it simply deletes +directories in the ``runs`` directory based on their modification time. +Make sure you don't have any subdirectories in the ``runs`` directory that +should be kept around before setting this environment variable. + +Multi-Configuration Support +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``edgy``, as previously noted, has support for simultaneous testing of +different configurations. The configurations that can be tested, as well as +the default set of configurations to test, is configured in the +``.edgy/config.json`` file. + +To manually specify which configurations to run, the ``-c`` flag can be +used with a comma-separated list of configurations, e.g.: + +.. code:: text + + edgy -c edg_x86_64,edg_x86_64_cp regressions + +This will run the regression test suite, in both the ``edg_x86_64`` and +``edg_x86_64_cp`` configurations (which is also the default as edgy is +typically configured). + +edg-run-test +------------ + +Usage information: + +.. code:: text + + usage: edg-run-test [-h] [-d] [-r] [--driver-debug] [--faster] [-q] [-t TOP_DIR] + [-o OUTPUT_DIR] test_files [test_files ...] + + EDG Python based test executor. + + positional arguments: + test_files the paths to the test files to run + + options: + -h, --help show this help message and exit + -d, --debug keep the output files + -r, --record, --silent-record + update the expected test output to be the output from this run. + --driver-debug add --driver_debug to the test's command line arguments. The + resulting additional output will be printed to stdout with the + original test file replacing the generic name. This makes the + underlying command more easily accessible so that it may be + more easily fed to a debugger (e.g., gdb) or checked for + correctness. + --faster enable command line flags that might speed up the compilation + of the test files + -q only display log output for errors + -t, --top-dir TOP_DIR + the path to the contextually "top" directory + -o OUTPUT_DIR the path where output will be stored + +``edg-run-test`` is a considerably simpler tool than ``edgy``. Consider +the following edgy command: + +.. code:: bash + + edgy regressions + +Assuming ``EDG_TEST_HOME`` is ``/edg/tests``, the corresponding +``edg-run-test`` invocation would be approximately the following: + +.. code:: bash + + edg-run-test -t /edg/tests/tests/regressions \ + /edg/tests/tests/regressions/**/*.sft.c \ + /edg/tests/tests/regressions/**/*.sft.cpp \ + /edg/tests/tests/regressions/**/*.mft.c \ + /edg/tests/tests/regressions/**/*.mft.cpp + +Here ``TEST_ROOT`` is specified by ``-t`` so that any ``.run_test_flags`` file +can be correctly processed. + +Of note, ``edg-run-test`` does not support expectations or have a notion of +configuration, so this will report the status of all tests regardless of +expected output. + +Additionally, by default all statuses are reported; ``-q`` can be used to +reduce the output to something closer to what's given by ``edgy``. + +The tested binary is the binary found at the ``CPFE`` environment variable by +default. However, alternative environment variables can be tested by +specifying the ``PRIMARY_CPFE`` environment variable to a different environment +variable (e.g., ``CPFE_CUSTOM``). + +The occasional advantage of ``edg-run-test`` over ``edgy`` is simplicity. +It's possible to author a new test outside of the test tree and quickly +execute and iterate on the test before moving the file(s) to include the +test in a test suite. diff --git a/doc/_sources/trans_unit.rst.txt b/doc/_sources/trans_unit.rst.txt new file mode 100644 index 0000000..6ec6d1b --- /dev/null +++ b/doc/_sources/trans_unit.rst.txt @@ -0,0 +1,562 @@ +.. _multi-tu: + +========================== +Multiple Translation Units +========================== + +A *translation unit* is a set of source files translated as a unit, comprising +a primary source file and all of the source files included by that file. +Sometimes, the front end has to deal with more than one translation unit at a +time: + +* | When exported templates are used, the source file in which a template is + defined may be different than the one in which is it used. The front end + has to read in a translation unit for the defining source file while + retaining the translation unit for the referencing source file, and then + perform the instantiation in a merged context that includes both + translation units. Additional translation units may be read in for + instantiations of other templates. +* | When ``COMPILE_MULTIPLE_TRANSLATION_UNITS`` is TRUE, multiple files can be + specified on the command line for the front end. Each file is read in turn + as the primary file of a translation unit. + +In both these cases, the first translation unit read is called the *primary +translation unit*, and any translation units read after the first are called +*secondary translation units*. The translation units are kept separate within +the front end. They have separate intermediate language (IL) trees and +conceptually separate symbol tables. After all translation units have been +processed, the IL for each secondary translation unit is merged into the IL for +the primary translation unit. Duplicate copies of entities that appear in more +than one translation unit are eliminated during the merge, and errors are +issued for conflicts between entities that have incompatible definitions in +different translation units. The final merged primary IL tree is then passed +to a back end, looking much like an IL tree from a simple one-translation-unit +compilation. + +The process of translating a primary translation unit and zero or more +secondary translation units into an IL tree is called a *compilation*. + +Note that when ``COMPILE_MULTIPLE_SOURCE_FILES`` [#f1]_ is TRUE and the front +end is given several source file names on the command line, each translation +unit is treated as a separate compilation. It is read separately and its IL +tree is written to a separate IL file. No merging is done on the translation +unit IL trees, and no checking for matching between translation units. There +are no secondary translation units in this mode (except those that might be +brought in for exported templates). + +The principal source files of the front end involved in +multiple-translation-unit processing are ``trans_unit.c``, ``trans_unit.h``, +``trans_corresp.c``, ``trans_corresp.h``, ``trans_copy.c``, and +``trans_copy.h``. + +.. _multi-tu-dispatch: + +Initialization, Termination, and Keeping Translation Units Separate +=================================================================== + +By and large, the code in the front end is written as if there is only one +translation unit. Global variables and tables indicate the state at the +current point in the input, which is a particular point within a single +translation unit. For the handling of multiple translation units, this global +state must be carefully managed, and updated when one switches between +translation units. + +The process of initialization in the front end is broken down into three parts: + +* | Initialization that is done only once in the entire front end invocation. + Initialization routines in this class have names that have the suffix + "``_one_time_init``". +* | Initialization that is redone for each compilation. Initialization + routines in this class have names that have the suffix "``_init``". +* | Initialization that is redone for each translation unit. Initialization + routines in this class have names that have the suffix + "``_trans_unit_init``". + +It can be seen that in ``COMPILE_MULTIPLE_TRANSLATION_UNITS`` mode, the front +end does one-time initialization, compilation initialization, and then, for +each source file specified on the command line, translation unit +initialization. In ``COMPILE_MULTIPLE_SOURCE_FILES`` mode, on the other hand, +the front end does one-time initialization and then, for each source file +specified on the command line, compilation initialization and then +translation-unit initialization. See the top-level routines in ``fe_init.c``. + +Similarly, termination is done in several parts: + +* | ``pop_scope`` for the file scope does necessary processing at the end of + the file scope for a translation unit. +* | ``translation_unit_wrapup`` does necessary processing at the end of a + translation unit. +* | ``fe_wrapup`` does necessary processing at the end of a compilation. This + includes calling ``template_and_inline_function_wrapup``, which does most + template instantiation. +* | ``wrap_up_file_scopes`` finishes up each translation unit and merges the + IL. + +The instantiation process (during the third step above) can bring in additional +secondary translation units for exported templates, which go through their own +initialization, reading/parsing, and termination phases. Eventually, all +necessary templates have been instantiated, which means all necessary +translation units have been created and processed, and ``wrap_up_file_scopes`` +is called. + +The source code for a secondary translation unit is read, and the corresponding +IL is generated, all at one time. There is no switching between translation +units while the source code is being read. Once a secondary translation unit +has been read, additional processing may be done in that translation unit that +will add more IL to it, but that is done through template instantiations, and +never by going back and reading more source code. Likewise, instantiations can +add additional IL to the primary translation unit, but no additional source +code will be read into it. + +A structure of type ``a_translation_unit`` contains information about a single +translation unit within a compilation, and the global variable +``curr_translation_unit`` points to the entry for the translation unit that is +currently active. By calling ``switch_translation_unit``, one can switch to a +different translation unit, i.e., make another translation unit the "active" +one. This is a relatively expensive process that changes the values of many +global variables to match the new translation unit. + +How does ``switch_translation_unit`` know what to update? It updates the +variables recorded by calling ``register_trans_unit_variable`` during one-time +initialization. Variables registered in that way are known as *trans unit +variables*, and their per-translation-unit values are recorded in a data +structure associated with the ``a_translation_unit`` structure: They are saved +when the translation unit becomes inactive, and restored when the translation +unit is reactivated. Certain values that need to be accessed efficiently even +when the corresponding translation unit is not the active one are stored +directly in the ``a_translation_unit`` structure (e.g., +``file_scope_pointers_block``), or are pointed to by fields in that structure +(e.g., ``module_id_ptr``; variables of this kind are registered via +``register_trans_unit_variable_with_field``). + +``process_translation_unit`` is the driver for the reading/parsing of a single +translation unit. + +Some data structures and numbering sequences are deliberately shared across +multiple translation units. The source file data structure and source line +sequence numbers, for example, are shared, so that a source position consisting +of a sequence number and column number is unique across the entire compilation. +Likewise, the symbol table and scope number sequence is shared, which ensures +that scopes always have unique numbers, and therefore that one can do a lookup +in the symbol table by scope number and find only entities from a single scope +from a single translation unit. + +Memory Regions and Intermediate Language +======================================== + +Each secondary translation unit has its own set of IL memory regions, one for +its file scope and one for each top-level function definition. The global +variable ``file_scope_region_number`` indicates the region number of the file +scope of the current translation unit, whether it is a primary or secondary +translation unit. + +The function ``alloc_primary_file_scope_il`` allocates space in the primary +translation unit IL even if the current translation unit is a secondary +translation unit. + +The macro ``is_secondary_trans_unit`` returns true for an IL entry allocated in +a memory region that is part of a secondary translation unit. The global array +``trans_unit_for_scope`` maps a scope number back to a pointer to the +translation unit that contains that scope. Note that when IL is moved from +secondary translation units to the primary IL at the end of the compilation, +the value of ``is_secondary_trans_unit`` will change, but that of +``trans_unit_for_scope`` stays as it was. + +The front end memory region is shared across all translation units. + +Translation Unit Correspondences +================================ + +Each IL entry with external linkage is assigned to a correspondence set +containing all of the related IL entries from different translation units, +i.e., all the entries that represent the same entity. So, for example, all +external global variables called "``i``" will be in one correspondence set. + +A correspondence set is represented by an entry of type +``a_trans_unit_corresp``, which is allocated in front end memory (so it is not +really part of the IL). Each entry that is a member of the correspondence set +points to the appropriate ``a_trans_unit_corresp`` entry via the +``trans_unit_corresp`` pointer in its ``source_corresp`` field. These pointers +are set when secondary translation units are processed, and therefore in a +compilation consisting only of a single translation unit the pointers will be +NULL and the correspondence-set entries will not be allocated. [#f2]_ For +entries without linkage, or with internal linkage, the ``trans_unit_corresp`` +pointer is always NULL. + +IL entries of type ``a_base_class`` are also matched up in correspondence sets +and therefore contain a ``trans_unit_corresp`` pointer (though it is not part +of a ``source_corresp`` field in that case). + +.. _canonical-entries: + +Canonical Entries +================= + +In each correspondence set, one entry is chosen as the *canonical* entry, and +the ``canonical`` field in the ``a_trans_unit_corresp`` points to it. The +entry chosen as the canonical entry is an instance that contains the most +detailed information available about the entity: one with a definition if a +definition is available, and a specialization if both specialized and +unspecialized versions of a template instance are available. All other things +being e qual, an entry in the primary IL is chosen over one in a secondary +translation unit, because that means less copying later. + +The canonical entry chosen can change as the compilation progresses. The first +instance seen will generally be chosen as the canonical entry, but it may be +replaced afterwards by a better choice from some other secondary translation +unit scanned later. + +Note that it is possible for a class or namespace not to be the canonical entry +in its correspondence set while at the same time some of its members are the +canonical entries in their sets. + +The macro ``canonical_il_entry_of`` can be used to fetch the address of the +canonical entry corresponding to a given entry. For an entry without linkage, +the entry itself is returned. + +The Copy Address Pointer +======================== + +All IL entries have a prefix that contains various flags and numbers. IL +entries in the file scope of a secondary translation unit have, in addition, a +copy address pointer, which is set during the copy process to indicate the +address in the primary IL to which the entry should be copied or remapped. + +For entries in correspondence sets, generally the canonical entry will be +copied to the primary IL and its copy address pointer will be set to the +address of the copy. The other members of the correspondence set will not be +copied, but their copy address pointers will be set to the same copy address so +that references to them can be remapped to the unique copy in the primary IL. + +For entries not in correspondence sets, including non-declarative entries like +statement and expression nodes, no copy address is pre-assigned. When the +entry is encountered during the copy process, it is copied to the primary IL +and the copy address pointer is set to the address of the copy. All references +to the entry encountered thereafter are remapped to the established copy +address. + +In some cases, entries in the secondary IL are "merged" into the primary IL. +This is necessary, for example, if the canonical entry for a correspondence set +is in a secondary translation unit but there is also a member of that +correspondence set in the primary IL. The address in the primary IL must be +preserved (because there are references to it from elsewhere in the primary IL, +which will not be rewritten), so the canonical entity must be copied on top of +the existing primary IL entry. In such cases, the copy address pointer is used +to form a two-element list: The copy address pointer of the entry in the +secondary translation unit points to allocated space for a copy (also in the +secondary translation unit IL), and the copy address pointer of that copy entry +points in turn to the address of the existing entry in the primary IL. The +copy process copies the original entry to the intermediate copy, with pointer +remapping, and then later overwrites the primary IL entry, carefully preserving +certain information (e.g., next-on-list pointers). + +The macro ``trans_unit_copy_address_of`` gives access to the correspondence +pointer of an IL entry (for both fetching and setting). The macro +``checked_trans_unit_copy_address_of`` does the same thing, but also checks +that the entry pointer provided is actually in the file scope of a secondary +translation unit. + +Correspondence Checking +======================= + +The code in ``trans_corresp.c`` establishes correspondences between entities in +a secondary translation unit and similar entities in the primary translation +unit and in other secondary translation units. It sets the correspondence +pointer of IL entries to indicate the correspondences found. While +establishing these correspondences, it checks that linked entities are in fact +compatible, and issues errors when they are not. The entities that have +correspondences set in this way are types, routines, variables, fields, +namespaces, base classes (i.e., ``a_base_class`` entries), using-declarations +appearing in class scopes, and templates (including template instances). + +Correspondence checking can occur in three stages of the compilation: + +* | Built-in types have their correspondences set by ``record_builtin_type`` as + soon as they are created. +* | When a translation unit has been processed, + ``set_trans_unit_correspondences`` is called from + ``translation_unit_wrapup`` to establish correspondences for the entities + that were created in that translation unit. The global variable + ``correspondence_checking_underway`` is TRUE during this stage (and only + during this stage); after that ``correspondence_checking_done`` is TRUE. +* | The correspondence checking process is notified of every template + instantiation by calls to ``record_instantiation``. When this occurs in a + translation unit after its ``translation_unit_wrapup`` call, the + correspondence pointer is established for the new instantiation. The + instantiation process also notifies the correspondence checking process of + template instantiations being completed, through calls to + ``establish_class_instantiation_corresp``, + ``establish_function_instantiation_corresp``, + ``establish_variable_instantiation_corresp``, + ``establish_block_extern_function_correspondence``, + ``establish_block_extern_variable_correspondence`` and + ``establish_friend_type_correspondence``. + +Finding Corresponding Pairs +--------------------------- + +Several different mechanisms are used to find an entity in another translation +unit that corresponds to a given entity: + +* | For named entities in namespace scope, the symbol table is used. The + search process simply traverses the list of symbols attached to the symbol + header of the entity for which a correspondence is being searched. This is + done in functions with the prefix ``find_`` (e.g., + ``find_type_correspondence``). +* | For class members, we can rely on the fact that the lists of IL entities + representing the members should have their elements correspond on a + one-to-one basis. Hence no search is needed, although care must be taken + with compiler-generated members that may not appear in every translation + unit. This principle is implemented by + ``establish_trans_unit_correspondences_for_class``. A similar process can + be used for enumeration constants. +* | Correspondences for instantiations of templates are usually established + after the templates from which they are generated have been matched up. To + support the search for a matching instantiation, a field + ``all_instantiations`` was added to ``a_template_symbol_supplement``. This + field is set only in the supplement for the canonical template entry and + points to a list of all the instantiation symbols for the template, + including those for corresponding templates in other translation units. + Some of the key functions manipulating this list are ``add_instantiation``, + ``find_class_template_instantiation`` and + ``find_function_template_instantiation``. +* | Correspondences are also sometimes established between unnamed types. This + happens when matching up declarations of entities with linkage involving + unnamed types. For example: + + .. code:: c++ + + struct { float a, b; } *p, q; // Could appear in two translation units + + | In such cases, the correspondence is first established for the entities + with linkage (variables or routines), and the correspondence between the + types is sought by comparing the two types using ``f_types_are_compatible`` + with the option ``TCF_SEEK_CORRESP``. + +Ordering Dependencies +--------------------- + +Determining whether two entities from different translation units correspond +may require that other correspondences are known. For example, suppose we have +two namespace scope functions ``f`` that are declared as + +.. code:: c++ + + extern R N::f(); + +then the two must correspond if the entities denoted by ``N`` correspond, and +if that is the case the entities denoted by ``R`` must correspond too. The +ordering of corresponding checks must therefore be managed carefully. + +To reduce the magnitude of this issue, correspondences are determined in two +steps. In the first step, correspondences are *established*: Only those +components of the entity that uniquely identify it are compared (e.g., the +entity's name, its enclosing classes and namespaces, parameter types of +functions, etc.) and if they match the correspondence pointer is set. Some +diagnostics may be issued at this time. This process is mostly done in +functions with the prefix ``establish_``. In the second step, which starts +after all the correspondences for the translation unit have been established, +the correspondences are *verified*. This involves comparing the remaining +relevant attributes of entities that were found to correspond after the first +step; diagnostics are issued if the entities do not match. Most of the +verification work is done in functions with the prefix ``verify_``. This +separation into two steps makes sure that in our example above the +correspondence for ``R`` has been established by the time it is needed. + +To deal with other ordering issues, such as the requirement that the +correspondence of ``N`` be established in our example, the correspondence +checking process may be stacked. For example, while searching for a +correspondence for ``N::f`` above, another search for a correspondence for +``N`` may be initiated. This is driven by calls to functions named +``canonical_``\ *entity*\ ``_entry_of`` where *entity* is one of +``namespace``, ``type``, ``field``, ``routine``, ``variable`` or ``template``. +If a correspondence was already established, these functions return the +requested canonical entry; if not, they first determine the correspondence by +calling ``determine_correspondence`` [#f3]_. + +Other ordering issues sometimes arise because establishing a correspondence for +a template instantiation seemingly leads to infinite recursion. Such +situations are resolved in part by placing appropriate markers in the +``all_instantiations`` list and in part by as much as possible establishing the +correspondences of all templates before attempting to match their +instantiations. To that end, the front end maintains a list of instantiations +whose correspondences are yet to be determined (the list is pointed to by +``instantiations_to_process``). That list is processed at appropriate times +(i.e., when the correspondences of the various templates have been found) by +calls to ``process_pending_instantiations``. + +Finally, we should note that the verification process always compares an entity +with its canonical counterpart. If a canonical entry (from an already +processed translation unit) is replaced by a new entry (from the current +translation unit) the former will need to be compared with the latter when all +the correspondences have been established in the current translation unit. +This is done in ``process_verification_list``. + +Debugging Facilities +-------------------- + +When the preprocessor symbol ``DEBUG`` is TRUE,a few facilities are provided by +``trans_corresp.c`` to help identify problems during correspondence checking. +First, the command-line option "``-d-trans_corresp``" will cause a line of +output to be produced for each correspondence pointer being set (or cleared), +as well as for certain operations on the ``all_instantiations`` lists. Second, +the function ``db_corresp`` can be called from a debugger to examine the +correspondence of a given entity. Finally, the modification of a +correspondence pointer for a specific entity can easily be intercepted in a +debug environment where addresses are reproducible from run to run. To enable +this, set breakpoints on ``main`` and on ``corresp_intercept``. Rerun the +front end and at the stop in ``main``, set the static variable +``trace_corresp_ptr`` to the address of the entity whose correspondence value +should be tracked: ``corresp_intercept`` will be called (triggering the +breakpoint) when that value is modified. + +.. _multi-tu-copy: + +Copying from Secondary Translation Units +======================================== + +The code in ``trans_copy.c`` copies IL from a secondary translation unit to the +primary translation unit IL. It is run after elimination of unneeded entries +in the secondary translation unit, so it copies only entries that are actually +"needed." It also runs after correspondence checking has established the +correspondences between externally-linked entities, so it does not copy entries +for which there is already an instance in the primary translation unit IL; for +such cases, all references to the entity are simply rewritten to point to the +primary IL instance. + +The secondary translation unit IL consists of a file scope memory region and +zero or more function scope memory regions. The file scope memory region is +actually copied into the primary IL, via a tree walk, with duplicates +eliminated as indicated above. The function scope memory regions, on the other +hand, are not copied. Instead, they are walked to update pointers +appropriately, and then the memory region numbers are simply reassigned to the +primary IL. + +The copy process is handled by ``copy_secondary_trans_unit_IL_to_primary``, +which has five main phases: + +* | ``prepare_for_trans_unit_copy`` walks through the declaration lists of the + file scope of a secondary translation unit and its subscopes, and puts each + entry into one of four categories: (a) entries that should be copied to the + primary IL; (b) entries that should overwrite a corresponding entry in the + primary IL (e.g., a function in the secondary translation unit that has a + definition, where the corresponding function in the primary IL has only a + declaration); (c) entries that are in a correspondence set but are not the + canonical entry, which should be removed from the lists and discarded; and + (d) entries in a correspondence set that provide additional (minor) + information over what is present in the canonical entry, which should be + merged into the corresponding entry. +* | ``copy_from_secondary_to_primary_IL`` uses the IL-walking routines to walk + the IL tree, copy over entries that need to be copied, and update pointers + so that the copied IL refers only to copies or to pre-existing entries in + the primary IL. +* | ``copy_function_bodies_to_primary_IL`` processes the bodies of any + functions that are to be moved over, by using the IL-walking routines to + walk the IL tree and update pointers appropriately. +* | ``finish_trans_unit_copy`` walks through the declaration lists again, and + links copied entries into the declaration lists of the primary IL. A + struct type copied over, for example, would be linked into the types list + of the primary scope of the primary IL. Variables, types, and routines + that must be merged into the corresponding entries are also copied onto the + corresponding entries at this point. This part of the processing runs + while switched into the primary translation unit. See also + ``finish_moved_entity_processing``, which is similar but reaches all copied + or merged entities, even those from non-merged scopes. +* | ``finish_processing_for_function_bodies`` calls + ``finish_function_body_processing`` for each copied function scope memory + region, and kicks off IL lowering for the function if it's needed. This + part of the processing runs while switched into the primary translation + unit. + +For entries that are being merged into the primary IL, the copy process sets +the ``il_lowering`` flag in the IL entry prefix to indicate merging rather than +copying. (The flag is available for this use because IL lowering is never done +on secondary translation units.) For merged entries, the copy process uses an +extra copy of the entity allocated in the secondary translation unit: The +entity's copy address pointer points to the copy, whose copy address pointer +points to the corresponding entity in the primary IL. During the copy, the +original entry is copied to the copy space, and its pointers are remapped +there. This allows ``finish_trans_unit_copy`` later to have access to both the +original entity in the primary IL and the entity from the secondary translation +unit as updated for the copy. This is often important because some flags from +the two entries need to be merged. + +The bodies of functions not copied over are eliminated, and likewise for the +initializers of variables. See ``clear_body_for_routine`` and +``clear_variable_definition``. Non-template functions and variables in +secondary translation units included only to get exported templates are turned +into external declarations, because the definition of those entities is put out +when the file is compiled as a primary translation unit. + +The IL for secondary translation units can contain references to other +translation units. In some ways, the IL trees for all secondary translation +units have to be viewed as one big somewhat interconnected tree. For this +reason, each of the processing phases described above is done for all secondary +translation units before advancing to the next phase. + +Part of the function of the copy process is to produce a primary IL tree that +contains no references to IL entries in secondary translation units, and this +is done by making sure that every entity copied over has only pointers that +refer to the primary IL. Sometimes, however, the instantiation of a template +that is defined in the primary translation unit introduces exactly the kind of +mixed-translation-unit IL that we are trying to avoid. To eliminate such +references, a pair of routines in ``trans_copy.c`` is called: + +* | ``mark_secondary_trans_unit_IL_entities_used_from_primary_as_needed`` + sweeps the primary translation unit IL and looks for references to + secondary translation unit entries. When it finds them, it marks the + secondary translation unit entries as needed so that they will be copied to + the primary IL when the secondary translation unit is copied. +* | ``rewrite_secondary_trans_unit_IL_entity_pointers_used_in_primary`` sweeps + the primary translation unit IL after the secondary translation units have + been copied in, and looks for references to secondary translation unit + entries. When it finds them, it rewrites them either as references to the + corresponding entity in the primary translation unit (if there is one) or + it copies them and rewrites the pointer to the copy. + +In some (relatively rare) cases, the merged IL produced by the copy process has +some type entries out of order on the type lists, where "out of order" is +defined according to the peculiar ordering required by the C-generating back +end so that it can generate compilable C code. +``fix_type_list_ordering_problems`` is called after IL lowering to examine the +file-scope types list to look for ordering problems and to move types to fix +those problems. If there are no ordering problems (which is almost always the +case), the checking is done fairly quickly and efficiently. + +Externalization of statics +========================== + +When a source file includes exported templates, it is possible that the +exported templates will refer to static entities in the file. Because the +template instances may be generated as part of the translation of other source +files, and be included in the object code for those files, it may be necessary +to refer to the static entities from another compilation. Therefore, the front +end externalizes all statics when a compilation includes exported templates. +This gives the static functions and variables external linkage and special +mangled names. This has a number of consequences, such as that static inline +functions become extern inline functions, which in some configurations makes +them instantiatable. See ``externalize_statics_for_exported_templates``. + +One-instantiation-per-object mode +================================= + +In one-instantiation-per-object mode, each instantiated template is put into a +separate "slice" of the IL, so that a back end can put out each instantiation +in a separate object file. The slices are defined by having a separate +"needed" flag for each slice (there's an array of them attached to each IL +entity), and setting the slice-specific needed flags so that each slice +contains only the types, variables, etc. referenced by the template +instantiation in that slice. + +When there are multiple translation units, the per-instantiation needed flags +are not maintained in the secondary translation unit IL. Once the IL is copied +to the primary IL, the flags are built up and maintained appropriately there. + +.. [#f1] Not ``COMPILE_MULTIPLE_TRANSLATION_UNITS``. +.. [#f2] There are some circumstances involving templates where the + correspondence pointer is set even if there is only a primary + translation unit. The important point is simply that one shouldn't + count on the pointer being set when there is only one translation + unit. +.. [#f3] Note that this is different from ``canonical_il_entry_of`` which does + not attempt to establish a correspondence. diff --git a/doc/_sources/utilities.rst.txt b/doc/_sources/utilities.rst.txt new file mode 100644 index 0000000..55e3868 --- /dev/null +++ b/doc/_sources/utilities.rst.txt @@ -0,0 +1,309 @@ +.. _utility-programs: + +================ +Utility Programs +================ + +Several utility programs are provided with the front end. Most of the utility +programs help with various link-time issues and are meant to be called from a +driver program or script. One (``mk_errinfo``) is a tool program used when +modifying the front end. The source for these programs is in the ``util`` +directory of the release structure. + +``edg_prelink`` +=============== + +``edg_prelink.c`` contains the "prelinker" program. ``edg_prelink.h`` contains +related declarations. The prelinker is invoked at link time to manage +automatic instantiation of template entities. It is given a complete list of +the object files and libraries that are to be linked together. It examines the +external names defined and referenced within those files, and finds cases where +template entities are referenced but not defined. It then examines information +in the object files that describes instantiations that could have been done +during compilation, and assigns the needed instantiations to appropriate files. +``edg_prelink`` then invokes the compiler again to compile those files, which +will do the necessary instantiations. + +The prelinker uses UNIX commands like ``nm`` to extract information about +object files, so it may need adaptation to run in other environments. + +The invocation of the prelinker looks like + + | ``edg_prelink`` [ *options* ] *files* + +where the *files* list includes all object files and libraries, and the +*options* are: + +.. list-table:: + + * - | ``-a`` *n* + - | Specify whether a definition list file should be created. A + definition list file is created if *n* is nonzero. The default is + specified by the ``PL_DEFAULT_USE_DEFINITION_LIST_FILE`` configuration + flag. + * - | ``-b`` + - | List object files mode. This mode is used when the driver needs to + get a list of object files including any instantiation object files + created in one instantiation perobject mode. The prelinker simply + creates an object file list that is written to the file specified by + the ``-o`` option. + * - | ``-c`` *command* + - | Specify the version of the ``nm`` command to be used. + * - | ``-D`` + - | Do not assign instantiation to nonlocal object files. Instantiations + may only be assigned to object files in the current directory. + * - | ``-f`` *fmt* + - | Specify the ``nm`` format to be used. *fmt* is one of ``solaris``, + ``SGI``, ``SVR4``, ``HPUX``, ``gnu``, ``CLIX, MacOSX``, or\ + ``MacOSX64``. + * - | ``-i`` + - | Ignore ``nm`` output lines that are not formatted properly. + * - | ``-L`` *directory* + - | Specify a library directory to be searched for libraries. + * - | ``-m`` + - | Do not demangle identifier names that are displayed. + * - | ``-n`` + - | Update the instantiation list but don't recompile the files. + * - | ``-N`` + - | If a file from a nonlocal directory needs to be recompiled, do the + compilation in the current directory. An updated list of object files + and library names is written to the file specified by the ``-o`` + option so that the driver program can tell that alternate versions of + some of the object files should be used. + * - | ``-o`` *file-name* + - | Write an updated list of object files and library names is written to + the file specified by *file-name*. This option must be specified when + the ``-N`` or -O option is used. + * - | ``-O`` + - | One instantiation per object mode is being used. A list of object + files, including the instantiation object files associated with the + object files specified on the prelinker command line, is written to + the file specified by the ``-o`` option. + * - | ``-q`` + - | Turns off verbose mode. + * - | ``-r`` + - | Don't stop after a certain number of iterations. (The instantiation + process is iterative: a recompilation may bring up new template + entities that need to be instantiated, which requires another + recompilation, etc. Some recursive templates can cause iteration that + never terminates, because each iteration introduces another new entity + that wasn't previously there. By default, this process is stopped + after a certain number of iterations.) + * - | ``-R`` *number* + - | Override the number of reserved instantiation information file lines + to be used. + * - | ``-s`` *number* + - | Specifies whether the prelinker should check for entities that are + referenced as both explicit specializations and generated + instantiations. If *number* is zero the check is disabled, otherwise + the check is enabled. + * - | ``-S`` + - | Suppress instantiation flags in the object files. This causes the + prelinker to recompile all of the local object files with the + ``--suppress_instantiation_flags`` option. + * - | ``-u`` + - | Specify whether external names have an added leading underscore. The + command-line option selects the opposite of the configuration flag + ``TARG_EXTERNAL_NAMES_GET_UNDERSCORE_ADDED``. + * - | ``-v`` + - | Verbose mode. + * - | ``-d``\ *n* + - | Set the debug level to *n*. + +The *files* list may also have the following options intermixed with the file +names: + +.. list-table:: + + * - | ``-l``\ *xxx* + - | Specify a library (e.g., ``-lstd``). + * - | ``-B``\ *linkage* + - | Specify the kind of linking to be done (e.g., static or dynamic). The + linkage kind is not checked for validity. + * - | ``--`` + - | Marks the end of the list of file names that is passed back to the + driver when the ``-N`` option is used. + +``edg_munch`` +============= + +``edg_munch`` is the EDG version of the USL ``munch`` utility. Its source +code is in ``edg_munch.c``, with associated declarations in +``edg_munch.h``. ``edg_munch`` implements a lowest-common-denominator +method for getting global initialization and termination code executed on +systems that have no special support for that. [#f1]_ + +``edg_munch`` operates by reading as input a file that is the output of ``nm`` +run on a linked executable program. It looks for names beginning with +``__sti__`` or ``__std__``, those being, respectively, initialization and +termination routines to be called at runtime. It generates a C program that +defines a data structure containing a list of pointers to the initialization +and termination routines. This generated program is then compiled and linked +in with the executable. The data structure is consulted at runtime by startup +code invoked from ``_main``, and the routines on the list are invoked at the +appropriate times. + +``edg_munch`` takes only a single option: ``-u``, if used, specifies whether +external names have an added leading underscore. The command-line option +selects the opposite of the configuration flag +``TARG_EXTERNAL_NAMES_GET_UNDERSCORE_ADDED``. + +``edg_decode`` +============== + +``edg_decode`` is a name demangler. The demangling code is in ``decode.c``, +with associated declarations in ``decode.h``. A main program that uses the +demangling code is provided in ``edg_decode.c``. + +``edg_decode`` reads input from ``stdin`` and writes output to ``stdout``. +Things that look like mangled names in the input are demangled. Everything +else is passed through unchanged. This makes the program suitable, for +example, as a filter for the output of a linker: error messages in general are +passed through unaltered, but mangled names are demangled. For example, using +the cfront-like ABI, + +.. code:: text + + ld: Undefined symbol + _f__Fif + +is turned into + +.. code:: text + + ld: Undefined symbol + f(int, float) + +Mangled names that are ill-formed in some way are also passed through +unchanged. + +``edg_decode`` usually has only a single option: ``-u``, if used, specifies +whether external names have an added leading underscore. The command-line +option selects the opposite of the configuration flag +``TARG_EXTERNAL_NAMES_GET_UNDERSCORE_ADDED``. When the IA-64 ABI is used, +however, there is also a ``-g`` option, which selects the opposite of the +configuration flag DEFAULT_EMULATE_GNU_ABI_BUGS, which when TRUE extends the +demangling to cover some invalid mangled names put out by g++ 3.2 (and the EDG +front end, when configured to emulate those bugs). + +The demangling is intended to work only on names of external entities. There +is some name mangling done for internal entities, or by the C-generating back +end, that this program does not try to decode. + +In the cfront-like ABI, names that contain double underscores in the source +code will probably not be demangled correctly. This is an unfortunate +consequence of using a mangling scheme that is based on the one used by cfront. +The standard forbids use of double underscores in names in user code, reserving +such names for the implementation, so the effect of this shortcoming is +limited. Implementors should try to avoid using such names for entities with +external linkage. Double underscores at the beginnings of external names do, +however, work correctly. In the IA-64 ABI, a similar problem applies to names +that begin with "``_Z``". + +The name demangling is also available through a callable interface, which is +used in ``edg_prelink``. See routine ``decode_identifier``. + +.. _mk-errinfo: + +``mk_errinfo`` +============== + +``mk_errinfo`` translates a text file containing error message codes and +associated descriptions into a pair of header files that represent this +information in a manner more readily used by the front end. + +The invocation of the ``mk_errinfo`` is typically + +.. code:: bash + + mk_errinfo error_msg.txt error_tag.txt err_codes.h err_data.h + +The ``error_msg.txt`` file defines the diagnostic messages generated by the +front end. This file, along with ``error_tag.txt``, is processed by +``mk_errinfo`` to generate the ``err_codes.h`` and ``err_data.h`` include +files. ``mk_errinfo`` may also be used to automatically generate the file used +to generate the :ref:`error-messages` appendix of this manual. + +When used to generate a documentation file, the invocation is typically one of +the following: + + | ``mk_errinfo -d error_msg.txt error_tag.txt`` *generated.tex* + | ``mk_errinfo -mml error_msg.txt error_tag.txt`` *generated.mml* + | ``mk_errinfo -rst error_msg.txt error_tag.txt`` *generated.rst* + +*generated.tex* is the name of the generated output file containing the +documentation in LaTeX format. *generated.mml* is the name of the generated +output file containing the documentation in MML (Maker Markup Language), which +can be used to create a FrameMaker document. *generated.rst* is the name of +the generated output file containing the documentation in reStructuredText +format, which can be used with Sphinx and various other tools. + +``error_msg.txt`` contains lines that have the following form: + +.. code:: text + + error_code;tag;"text" + +The error code is the enumeration element name that is used by the front end. +The file must be specified in enumeration order. To preserve the numbering of +error codes, errors may not be inserted in the middle of the file, nor may +lines be removed. If an error message is no longer in use, the line on which +it is defined should be prefixed with the string ``REMOVED``. This will retain +its sequence number but eliminate it from the generated tables. + +The tag is an alias for a given error code to be used by the end-user to name +that error in the command-line options that change the severities of +diagnostics. If no tag is specified, the error code (with the ``ec_`` removed) +is used as the tag. + +Some messages are used as part of the formatting of other messages (for +example, the messages used to provide error context information). These +messages should have a tag of ``INTERNAL``. This prevents the message from +being entered in the tag table and also prevents the message from appearing in +the automatically generated documentation file. + +The text string contains a quoted string similar to one that would be used in a +C program to define the equivalent string. Any quote characters within the +text string must be escaped. + +The text string includes markers indicating the location of fill-ins in the +message (e.g., ``%t`` for a type). Full information on those fill-in codes can +be found in :ref:`error-reporting`. + +The message text may include supplementary information that is only used to +improve the automatically generated documentation file (which is formatted +into the :ref:`error-messages` appendix of this manual). For example, an +error text string might look like this + +.. code:: text + + "a message with %s\='fill-in' included" + +The string ``\='fill-in'`` is used when creating the documentation file as the +value to be substituted for the ``%s``. This string is removed from the error +text information when the ``err_data.h`` file is created. + +``error_tag.txt`` is used to supply additional tags that may be used as aliases +for diagnostic messages. This mechanism is intended to be used by customers +who are packaging the front end as part of their product and allows them to +assign their own set of error tags without the need to modify the distributed +``error_msg.txt`` file. Note that these tags are used in addition to (not in +place of) the default tags specified in the ``error_msg.txt`` file. + +Each line should be formatted as: + +.. code:: text + + error_code;tag + +The error code is the enumeration element name used by the front end. The tag +is the alias being assigned. There may be more than one alias that references +a given enumerator. + +In both ``error_msg.txt`` and ``error_tag.txt``, blank lines are ignored and +lines that begin with a "``#``" are treated as comments. + +.. [#f1] The *patch* approach, by comparison, is more machine-dependent and + more efficient, but still doesn't require special linker support. + The code generated by the EDG front end will work with USL's + ``patch``, but EDG does not provide its own version of ``patch``. diff --git a/doc/_static/base-stemmer.js b/doc/_static/base-stemmer.js new file mode 100644 index 0000000..e6fa0c4 --- /dev/null +++ b/doc/_static/base-stemmer.js @@ -0,0 +1,476 @@ +// @ts-check + +/**@constructor*/ +BaseStemmer = function() { + /** @protected */ + this.current = ''; + this.cursor = 0; + this.limit = 0; + this.limit_backward = 0; + this.bra = 0; + this.ket = 0; + + /** + * @param {string} value + */ + this.setCurrent = function(value) { + this.current = value; + this.cursor = 0; + this.limit = this.current.length; + this.limit_backward = 0; + this.bra = this.cursor; + this.ket = this.limit; + }; + + /** + * @return {string} + */ + this.getCurrent = function() { + return this.current; + }; + + /** + * @param {BaseStemmer} other + */ + this.copy_from = function(other) { + /** @protected */ + this.current = other.current; + this.cursor = other.cursor; + this.limit = other.limit; + this.limit_backward = other.limit_backward; + this.bra = other.bra; + this.ket = other.ket; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.in_grouping = function(s, min, max) { + /** @protected */ + if (this.cursor >= this.limit) return false; + var ch = this.current.charCodeAt(this.cursor); + if (ch > max || ch < min) return false; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false; + this.cursor++; + return true; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_in_grouping = function(s, min, max) { + /** @protected */ + while (this.cursor < this.limit) { + var ch = this.current.charCodeAt(this.cursor); + if (ch > max || ch < min) + return true; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) + return true; + this.cursor++; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.in_grouping_b = function(s, min, max) { + /** @protected */ + if (this.cursor <= this.limit_backward) return false; + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch > max || ch < min) return false; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false; + this.cursor--; + return true; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_in_grouping_b = function(s, min, max) { + /** @protected */ + while (this.cursor > this.limit_backward) { + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch > max || ch < min) return true; + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return true; + this.cursor--; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.out_grouping = function(s, min, max) { + /** @protected */ + if (this.cursor >= this.limit) return false; + var ch = this.current.charCodeAt(this.cursor); + if (ch > max || ch < min) { + this.cursor++; + return true; + } + ch -= min; + if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) == 0) { + this.cursor++; + return true; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_out_grouping = function(s, min, max) { + /** @protected */ + while (this.cursor < this.limit) { + var ch = this.current.charCodeAt(this.cursor); + if (ch <= max && ch >= min) { + ch -= min; + if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) != 0) { + return true; + } + } + this.cursor++; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.out_grouping_b = function(s, min, max) { + /** @protected */ + if (this.cursor <= this.limit_backward) return false; + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch > max || ch < min) { + this.cursor--; + return true; + } + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) { + this.cursor--; + return true; + } + return false; + }; + + /** + * @param {number[]} s + * @param {number} min + * @param {number} max + * @return {boolean} + */ + this.go_out_grouping_b = function(s, min, max) { + /** @protected */ + while (this.cursor > this.limit_backward) { + var ch = this.current.charCodeAt(this.cursor - 1); + if (ch <= max && ch >= min) { + ch -= min; + if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) != 0) { + return true; + } + } + this.cursor--; + } + return false; + }; + + /** + * @param {string} s + * @return {boolean} + */ + this.eq_s = function(s) + { + /** @protected */ + if (this.limit - this.cursor < s.length) return false; + if (this.current.slice(this.cursor, this.cursor + s.length) != s) + { + return false; + } + this.cursor += s.length; + return true; + }; + + /** + * @param {string} s + * @return {boolean} + */ + this.eq_s_b = function(s) + { + /** @protected */ + if (this.cursor - this.limit_backward < s.length) return false; + if (this.current.slice(this.cursor - s.length, this.cursor) != s) + { + return false; + } + this.cursor -= s.length; + return true; + }; + + /** + * @param {Among[]} v + * @return {number} + */ + this.find_among = function(v) + { + /** @protected */ + var i = 0; + var j = v.length; + + var c = this.cursor; + var l = this.limit; + + var common_i = 0; + var common_j = 0; + + var first_key_inspected = false; + + while (true) + { + var k = i + ((j - i) >>> 1); + var diff = 0; + var common = common_i < common_j ? common_i : common_j; // smaller + // w[0]: string, w[1]: substring_i, w[2]: result, w[3]: function (optional) + var w = v[k]; + var i2; + for (i2 = common; i2 < w[0].length; i2++) + { + if (c + common == l) + { + diff = -1; + break; + } + diff = this.current.charCodeAt(c + common) - w[0].charCodeAt(i2); + if (diff != 0) break; + common++; + } + if (diff < 0) + { + j = k; + common_j = common; + } + else + { + i = k; + common_i = common; + } + if (j - i <= 1) + { + if (i > 0) break; // v->s has been inspected + if (j == i) break; // only one item in v + + // - but now we need to go round once more to get + // v->s inspected. This looks messy, but is actually + // the optimal approach. + + if (first_key_inspected) break; + first_key_inspected = true; + } + } + do { + var w = v[i]; + if (common_i >= w[0].length) + { + this.cursor = c + w[0].length; + if (w.length < 4) return w[2]; + var res = w[3](this); + this.cursor = c + w[0].length; + if (res) return w[2]; + } + i = w[1]; + } while (i >= 0); + return 0; + }; + + // find_among_b is for backwards processing. Same comments apply + /** + * @param {Among[]} v + * @return {number} + */ + this.find_among_b = function(v) + { + /** @protected */ + var i = 0; + var j = v.length + + var c = this.cursor; + var lb = this.limit_backward; + + var common_i = 0; + var common_j = 0; + + var first_key_inspected = false; + + while (true) + { + var k = i + ((j - i) >> 1); + var diff = 0; + var common = common_i < common_j ? common_i : common_j; + var w = v[k]; + var i2; + for (i2 = w[0].length - 1 - common; i2 >= 0; i2--) + { + if (c - common == lb) + { + diff = -1; + break; + } + diff = this.current.charCodeAt(c - 1 - common) - w[0].charCodeAt(i2); + if (diff != 0) break; + common++; + } + if (diff < 0) + { + j = k; + common_j = common; + } + else + { + i = k; + common_i = common; + } + if (j - i <= 1) + { + if (i > 0) break; + if (j == i) break; + if (first_key_inspected) break; + first_key_inspected = true; + } + } + do { + var w = v[i]; + if (common_i >= w[0].length) + { + this.cursor = c - w[0].length; + if (w.length < 4) return w[2]; + var res = w[3](this); + this.cursor = c - w[0].length; + if (res) return w[2]; + } + i = w[1]; + } while (i >= 0); + return 0; + }; + + /* to replace chars between c_bra and c_ket in this.current by the + * chars in s. + */ + /** + * @param {number} c_bra + * @param {number} c_ket + * @param {string} s + * @return {number} + */ + this.replace_s = function(c_bra, c_ket, s) + { + /** @protected */ + var adjustment = s.length - (c_ket - c_bra); + this.current = this.current.slice(0, c_bra) + s + this.current.slice(c_ket); + this.limit += adjustment; + if (this.cursor >= c_ket) this.cursor += adjustment; + else if (this.cursor > c_bra) this.cursor = c_bra; + return adjustment; + }; + + /** + * @return {boolean} + */ + this.slice_check = function() + { + /** @protected */ + if (this.bra < 0 || + this.bra > this.ket || + this.ket > this.limit || + this.limit > this.current.length) + { + return false; + } + return true; + }; + + /** + * @param {number} c_bra + * @return {boolean} + */ + this.slice_from = function(s) + { + /** @protected */ + var result = false; + if (this.slice_check()) + { + this.replace_s(this.bra, this.ket, s); + result = true; + } + return result; + }; + + /** + * @return {boolean} + */ + this.slice_del = function() + { + /** @protected */ + return this.slice_from(""); + }; + + /** + * @param {number} c_bra + * @param {number} c_ket + * @param {string} s + */ + this.insert = function(c_bra, c_ket, s) + { + /** @protected */ + var adjustment = this.replace_s(c_bra, c_ket, s); + if (c_bra <= this.bra) this.bra += adjustment; + if (c_bra <= this.ket) this.ket += adjustment; + }; + + /** + * @return {string} + */ + this.slice_to = function() + { + /** @protected */ + var result = ''; + if (this.slice_check()) + { + result = this.current.slice(this.bra, this.ket); + } + return result; + }; + + /** + * @return {string} + */ + this.assign_to = function() + { + /** @protected */ + return this.current.slice(0, this.limit); + }; +}; diff --git a/doc/_static/basic.css b/doc/_static/basic.css new file mode 100644 index 0000000..4738b2e --- /dev/null +++ b/doc/_static/basic.css @@ -0,0 +1,906 @@ +/* + * Sphinx stylesheet -- basic theme. + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin-top: 10px; +} + +ul.search li { + padding: 5px 0; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/doc/_static/custom.css b/doc/_static/custom.css new file mode 100644 index 0000000..2f80bab --- /dev/null +++ b/doc/_static/custom.css @@ -0,0 +1,7 @@ +.yue code span.pre { + white-space: preserve nowrap; +} + +.line-block .line { + margin-bottom: 5px; +} diff --git a/doc/_static/doc-logo-dark.png b/doc/_static/doc-logo-dark.png new file mode 100644 index 0000000..554d2bf Binary files /dev/null and b/doc/_static/doc-logo-dark.png differ diff --git a/doc/_static/doc-logo-light.png b/doc/_static/doc-logo-light.png new file mode 100644 index 0000000..3654181 Binary files /dev/null and b/doc/_static/doc-logo-light.png differ diff --git a/doc/_static/doctools.js b/doc/_static/doctools.js new file mode 100644 index 0000000..807cdb1 --- /dev/null +++ b/doc/_static/doctools.js @@ -0,0 +1,150 @@ +/* + * Base JavaScript utilities for all Sphinx HTML documentation. + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})`, + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)), + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS + && !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) + return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/doc/_static/documentation_options.js b/doc/_static/documentation_options.js new file mode 100644 index 0000000..af32e4c --- /dev/null +++ b/doc/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '7.0', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'dirhtml', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/doc/_static/english-stemmer.js b/doc/_static/english-stemmer.js new file mode 100644 index 0000000..056760e --- /dev/null +++ b/doc/_static/english-stemmer.js @@ -0,0 +1,1066 @@ +// Generated from english.sbl by Snowball 3.0.1 - https://snowballstem.org/ + +/**@constructor*/ +var EnglishStemmer = function() { + var base = new BaseStemmer(); + + /** @const */ var a_0 = [ + ["arsen", -1, -1], + ["commun", -1, -1], + ["emerg", -1, -1], + ["gener", -1, -1], + ["later", -1, -1], + ["organ", -1, -1], + ["past", -1, -1], + ["univers", -1, -1] + ]; + + /** @const */ var a_1 = [ + ["'", -1, 1], + ["'s'", 0, 1], + ["'s", -1, 1] + ]; + + /** @const */ var a_2 = [ + ["ied", -1, 2], + ["s", -1, 3], + ["ies", 1, 2], + ["sses", 1, 1], + ["ss", 1, -1], + ["us", 1, -1] + ]; + + /** @const */ var a_3 = [ + ["succ", -1, 1], + ["proc", -1, 1], + ["exc", -1, 1] + ]; + + /** @const */ var a_4 = [ + ["even", -1, 2], + ["cann", -1, 2], + ["inn", -1, 2], + ["earr", -1, 2], + ["herr", -1, 2], + ["out", -1, 2], + ["y", -1, 1] + ]; + + /** @const */ var a_5 = [ + ["", -1, -1], + ["ed", 0, 2], + ["eed", 1, 1], + ["ing", 0, 3], + ["edly", 0, 2], + ["eedly", 4, 1], + ["ingly", 0, 2] + ]; + + /** @const */ var a_6 = [ + ["", -1, 3], + ["bb", 0, 2], + ["dd", 0, 2], + ["ff", 0, 2], + ["gg", 0, 2], + ["bl", 0, 1], + ["mm", 0, 2], + ["nn", 0, 2], + ["pp", 0, 2], + ["rr", 0, 2], + ["at", 0, 1], + ["tt", 0, 2], + ["iz", 0, 1] + ]; + + /** @const */ var a_7 = [ + ["anci", -1, 3], + ["enci", -1, 2], + ["ogi", -1, 14], + ["li", -1, 16], + ["bli", 3, 12], + ["abli", 4, 4], + ["alli", 3, 8], + ["fulli", 3, 9], + ["lessli", 3, 15], + ["ousli", 3, 10], + ["entli", 3, 5], + ["aliti", -1, 8], + ["biliti", -1, 12], + ["iviti", -1, 11], + ["tional", -1, 1], + ["ational", 14, 7], + ["alism", -1, 8], + ["ation", -1, 7], + ["ization", 17, 6], + ["izer", -1, 6], + ["ator", -1, 7], + ["iveness", -1, 11], + ["fulness", -1, 9], + ["ousness", -1, 10], + ["ogist", -1, 13] + ]; + + /** @const */ var a_8 = [ + ["icate", -1, 4], + ["ative", -1, 6], + ["alize", -1, 3], + ["iciti", -1, 4], + ["ical", -1, 4], + ["tional", -1, 1], + ["ational", 5, 2], + ["ful", -1, 5], + ["ness", -1, 5] + ]; + + /** @const */ var a_9 = [ + ["ic", -1, 1], + ["ance", -1, 1], + ["ence", -1, 1], + ["able", -1, 1], + ["ible", -1, 1], + ["ate", -1, 1], + ["ive", -1, 1], + ["ize", -1, 1], + ["iti", -1, 1], + ["al", -1, 1], + ["ism", -1, 1], + ["ion", -1, 2], + ["er", -1, 1], + ["ous", -1, 1], + ["ant", -1, 1], + ["ent", -1, 1], + ["ment", 15, 1], + ["ement", 16, 1] + ]; + + /** @const */ var a_10 = [ + ["e", -1, 1], + ["l", -1, 2] + ]; + + /** @const */ var a_11 = [ + ["andes", -1, -1], + ["atlas", -1, -1], + ["bias", -1, -1], + ["cosmos", -1, -1], + ["early", -1, 5], + ["gently", -1, 3], + ["howe", -1, -1], + ["idly", -1, 2], + ["news", -1, -1], + ["only", -1, 6], + ["singly", -1, 7], + ["skies", -1, 1], + ["sky", -1, -1], + ["ugly", -1, 4] + ]; + + /** @const */ var /** Array */ g_aeo = [17, 64]; + + /** @const */ var /** Array */ g_v = [17, 65, 16, 1]; + + /** @const */ var /** Array */ g_v_WXY = [1, 17, 65, 208, 1]; + + /** @const */ var /** Array */ g_valid_LI = [55, 141, 2]; + + var /** boolean */ B_Y_found = false; + var /** number */ I_p2 = 0; + var /** number */ I_p1 = 0; + + + /** @return {boolean} */ + function r_prelude() { + B_Y_found = false; + /** @const */ var /** number */ v_1 = base.cursor; + lab0: { + base.bra = base.cursor; + if (!(base.eq_s("'"))) + { + break lab0; + } + base.ket = base.cursor; + if (!base.slice_del()) + { + return false; + } + } + base.cursor = v_1; + /** @const */ var /** number */ v_2 = base.cursor; + lab1: { + base.bra = base.cursor; + if (!(base.eq_s("y"))) + { + break lab1; + } + base.ket = base.cursor; + if (!base.slice_from("Y")) + { + return false; + } + B_Y_found = true; + } + base.cursor = v_2; + /** @const */ var /** number */ v_3 = base.cursor; + lab2: { + while(true) + { + /** @const */ var /** number */ v_4 = base.cursor; + lab3: { + golab4: while(true) + { + /** @const */ var /** number */ v_5 = base.cursor; + lab5: { + if (!(base.in_grouping(g_v, 97, 121))) + { + break lab5; + } + base.bra = base.cursor; + if (!(base.eq_s("y"))) + { + break lab5; + } + base.ket = base.cursor; + base.cursor = v_5; + break golab4; + } + base.cursor = v_5; + if (base.cursor >= base.limit) + { + break lab3; + } + base.cursor++; + } + if (!base.slice_from("Y")) + { + return false; + } + B_Y_found = true; + continue; + } + base.cursor = v_4; + break; + } + } + base.cursor = v_3; + return true; + }; + + /** @return {boolean} */ + function r_mark_regions() { + I_p1 = base.limit; + I_p2 = base.limit; + /** @const */ var /** number */ v_1 = base.cursor; + lab0: { + lab1: { + /** @const */ var /** number */ v_2 = base.cursor; + lab2: { + if (base.find_among(a_0) == 0) + { + break lab2; + } + break lab1; + } + base.cursor = v_2; + if (!base.go_out_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + if (!base.go_in_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + } + I_p1 = base.cursor; + if (!base.go_out_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + if (!base.go_in_grouping(g_v, 97, 121)) + { + break lab0; + } + base.cursor++; + I_p2 = base.cursor; + } + base.cursor = v_1; + return true; + }; + + /** @return {boolean} */ + function r_shortv() { + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + if (!(base.out_grouping_b(g_v_WXY, 89, 121))) + { + break lab1; + } + if (!(base.in_grouping_b(g_v, 97, 121))) + { + break lab1; + } + if (!(base.out_grouping_b(g_v, 97, 121))) + { + break lab1; + } + break lab0; + } + base.cursor = base.limit - v_1; + lab2: { + if (!(base.out_grouping_b(g_v, 97, 121))) + { + break lab2; + } + if (!(base.in_grouping_b(g_v, 97, 121))) + { + break lab2; + } + if (base.cursor > base.limit_backward) + { + break lab2; + } + break lab0; + } + base.cursor = base.limit - v_1; + if (!(base.eq_s_b("past"))) + { + return false; + } + } + return true; + }; + + /** @return {boolean} */ + function r_R1() { + return I_p1 <= base.cursor; + }; + + /** @return {boolean} */ + function r_R2() { + return I_p2 <= base.cursor; + }; + + /** @return {boolean} */ + function r_Step_1a() { + var /** number */ among_var; + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab0: { + base.ket = base.cursor; + if (base.find_among_b(a_1) == 0) + { + base.cursor = base.limit - v_1; + break lab0; + } + base.bra = base.cursor; + if (!base.slice_del()) + { + return false; + } + } + base.ket = base.cursor; + among_var = base.find_among_b(a_2); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + switch (among_var) { + case 1: + if (!base.slice_from("ss")) + { + return false; + } + break; + case 2: + lab1: { + /** @const */ var /** number */ v_2 = base.limit - base.cursor; + lab2: { + { + /** @const */ var /** number */ c1 = base.cursor - 2; + if (c1 < base.limit_backward) + { + break lab2; + } + base.cursor = c1; + } + if (!base.slice_from("i")) + { + return false; + } + break lab1; + } + base.cursor = base.limit - v_2; + if (!base.slice_from("ie")) + { + return false; + } + } + break; + case 3: + if (base.cursor <= base.limit_backward) + { + return false; + } + base.cursor--; + if (!base.go_out_grouping_b(g_v, 97, 121)) + { + return false; + } + base.cursor--; + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_1b() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_5); + base.bra = base.cursor; + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + switch (among_var) { + case 1: + /** @const */ var /** number */ v_2 = base.limit - base.cursor; + lab2: { + lab3: { + /** @const */ var /** number */ v_3 = base.limit - base.cursor; + lab4: { + if (base.find_among_b(a_3) == 0) + { + break lab4; + } + if (base.cursor > base.limit_backward) + { + break lab4; + } + break lab3; + } + base.cursor = base.limit - v_3; + if (!r_R1()) + { + break lab2; + } + if (!base.slice_from("ee")) + { + return false; + } + } + } + base.cursor = base.limit - v_2; + break; + case 2: + break lab1; + case 3: + among_var = base.find_among_b(a_4); + if (among_var == 0) + { + break lab1; + } + switch (among_var) { + case 1: + /** @const */ var /** number */ v_4 = base.limit - base.cursor; + if (!(base.out_grouping_b(g_v, 97, 121))) + { + break lab1; + } + if (base.cursor > base.limit_backward) + { + break lab1; + } + base.cursor = base.limit - v_4; + base.bra = base.cursor; + if (!base.slice_from("ie")) + { + return false; + } + break; + case 2: + if (base.cursor > base.limit_backward) + { + break lab1; + } + break; + } + break; + } + break lab0; + } + base.cursor = base.limit - v_1; + /** @const */ var /** number */ v_5 = base.limit - base.cursor; + if (!base.go_out_grouping_b(g_v, 97, 121)) + { + return false; + } + base.cursor--; + base.cursor = base.limit - v_5; + if (!base.slice_del()) + { + return false; + } + base.ket = base.cursor; + base.bra = base.cursor; + /** @const */ var /** number */ v_6 = base.limit - base.cursor; + among_var = base.find_among_b(a_6); + switch (among_var) { + case 1: + if (!base.slice_from("e")) + { + return false; + } + return false; + case 2: + { + /** @const */ var /** number */ v_7 = base.limit - base.cursor; + lab5: { + if (!(base.in_grouping_b(g_aeo, 97, 111))) + { + break lab5; + } + if (base.cursor > base.limit_backward) + { + break lab5; + } + return false; + } + base.cursor = base.limit - v_7; + } + break; + case 3: + if (base.cursor != I_p1) + { + return false; + } + /** @const */ var /** number */ v_8 = base.limit - base.cursor; + if (!r_shortv()) + { + return false; + } + base.cursor = base.limit - v_8; + if (!base.slice_from("e")) + { + return false; + } + return false; + } + base.cursor = base.limit - v_6; + base.ket = base.cursor; + if (base.cursor <= base.limit_backward) + { + return false; + } + base.cursor--; + base.bra = base.cursor; + if (!base.slice_del()) + { + return false; + } + } + return true; + }; + + /** @return {boolean} */ + function r_Step_1c() { + base.ket = base.cursor; + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + if (!(base.eq_s_b("y"))) + { + break lab1; + } + break lab0; + } + base.cursor = base.limit - v_1; + if (!(base.eq_s_b("Y"))) + { + return false; + } + } + base.bra = base.cursor; + if (!(base.out_grouping_b(g_v, 97, 121))) + { + return false; + } + lab2: { + if (base.cursor > base.limit_backward) + { + break lab2; + } + return false; + } + if (!base.slice_from("i")) + { + return false; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_2() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_7); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + if (!r_R1()) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_from("tion")) + { + return false; + } + break; + case 2: + if (!base.slice_from("ence")) + { + return false; + } + break; + case 3: + if (!base.slice_from("ance")) + { + return false; + } + break; + case 4: + if (!base.slice_from("able")) + { + return false; + } + break; + case 5: + if (!base.slice_from("ent")) + { + return false; + } + break; + case 6: + if (!base.slice_from("ize")) + { + return false; + } + break; + case 7: + if (!base.slice_from("ate")) + { + return false; + } + break; + case 8: + if (!base.slice_from("al")) + { + return false; + } + break; + case 9: + if (!base.slice_from("ful")) + { + return false; + } + break; + case 10: + if (!base.slice_from("ous")) + { + return false; + } + break; + case 11: + if (!base.slice_from("ive")) + { + return false; + } + break; + case 12: + if (!base.slice_from("ble")) + { + return false; + } + break; + case 13: + if (!base.slice_from("og")) + { + return false; + } + break; + case 14: + if (!(base.eq_s_b("l"))) + { + return false; + } + if (!base.slice_from("og")) + { + return false; + } + break; + case 15: + if (!base.slice_from("less")) + { + return false; + } + break; + case 16: + if (!(base.in_grouping_b(g_valid_LI, 99, 116))) + { + return false; + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_3() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_8); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + if (!r_R1()) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_from("tion")) + { + return false; + } + break; + case 2: + if (!base.slice_from("ate")) + { + return false; + } + break; + case 3: + if (!base.slice_from("al")) + { + return false; + } + break; + case 4: + if (!base.slice_from("ic")) + { + return false; + } + break; + case 5: + if (!base.slice_del()) + { + return false; + } + break; + case 6: + if (!r_R2()) + { + return false; + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_4() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_9); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + if (!r_R2()) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_del()) + { + return false; + } + break; + case 2: + lab0: { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab1: { + if (!(base.eq_s_b("s"))) + { + break lab1; + } + break lab0; + } + base.cursor = base.limit - v_1; + if (!(base.eq_s_b("t"))) + { + return false; + } + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_Step_5() { + var /** number */ among_var; + base.ket = base.cursor; + among_var = base.find_among_b(a_10); + if (among_var == 0) + { + return false; + } + base.bra = base.cursor; + switch (among_var) { + case 1: + lab0: { + lab1: { + if (!r_R2()) + { + break lab1; + } + break lab0; + } + if (!r_R1()) + { + return false; + } + { + /** @const */ var /** number */ v_1 = base.limit - base.cursor; + lab2: { + if (!r_shortv()) + { + break lab2; + } + return false; + } + base.cursor = base.limit - v_1; + } + } + if (!base.slice_del()) + { + return false; + } + break; + case 2: + if (!r_R2()) + { + return false; + } + if (!(base.eq_s_b("l"))) + { + return false; + } + if (!base.slice_del()) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_exception1() { + var /** number */ among_var; + base.bra = base.cursor; + among_var = base.find_among(a_11); + if (among_var == 0) + { + return false; + } + base.ket = base.cursor; + if (base.cursor < base.limit) + { + return false; + } + switch (among_var) { + case 1: + if (!base.slice_from("sky")) + { + return false; + } + break; + case 2: + if (!base.slice_from("idl")) + { + return false; + } + break; + case 3: + if (!base.slice_from("gentl")) + { + return false; + } + break; + case 4: + if (!base.slice_from("ugli")) + { + return false; + } + break; + case 5: + if (!base.slice_from("earli")) + { + return false; + } + break; + case 6: + if (!base.slice_from("onli")) + { + return false; + } + break; + case 7: + if (!base.slice_from("singl")) + { + return false; + } + break; + } + return true; + }; + + /** @return {boolean} */ + function r_postlude() { + if (!B_Y_found) + { + return false; + } + while(true) + { + /** @const */ var /** number */ v_1 = base.cursor; + lab0: { + golab1: while(true) + { + /** @const */ var /** number */ v_2 = base.cursor; + lab2: { + base.bra = base.cursor; + if (!(base.eq_s("Y"))) + { + break lab2; + } + base.ket = base.cursor; + base.cursor = v_2; + break golab1; + } + base.cursor = v_2; + if (base.cursor >= base.limit) + { + break lab0; + } + base.cursor++; + } + if (!base.slice_from("y")) + { + return false; + } + continue; + } + base.cursor = v_1; + break; + } + return true; + }; + + this.stem = /** @return {boolean} */ function() { + lab0: { + /** @const */ var /** number */ v_1 = base.cursor; + lab1: { + if (!r_exception1()) + { + break lab1; + } + break lab0; + } + base.cursor = v_1; + lab2: { + { + /** @const */ var /** number */ v_2 = base.cursor; + lab3: { + { + /** @const */ var /** number */ c1 = base.cursor + 3; + if (c1 > base.limit) + { + break lab3; + } + base.cursor = c1; + } + break lab2; + } + base.cursor = v_2; + } + break lab0; + } + base.cursor = v_1; + r_prelude(); + r_mark_regions(); + base.limit_backward = base.cursor; base.cursor = base.limit; + /** @const */ var /** number */ v_3 = base.limit - base.cursor; + r_Step_1a(); + base.cursor = base.limit - v_3; + /** @const */ var /** number */ v_4 = base.limit - base.cursor; + r_Step_1b(); + base.cursor = base.limit - v_4; + /** @const */ var /** number */ v_5 = base.limit - base.cursor; + r_Step_1c(); + base.cursor = base.limit - v_5; + /** @const */ var /** number */ v_6 = base.limit - base.cursor; + r_Step_2(); + base.cursor = base.limit - v_6; + /** @const */ var /** number */ v_7 = base.limit - base.cursor; + r_Step_3(); + base.cursor = base.limit - v_7; + /** @const */ var /** number */ v_8 = base.limit - base.cursor; + r_Step_4(); + base.cursor = base.limit - v_8; + /** @const */ var /** number */ v_9 = base.limit - base.cursor; + r_Step_5(); + base.cursor = base.limit - v_9; + base.cursor = base.limit_backward; + /** @const */ var /** number */ v_10 = base.cursor; + r_postlude(); + base.cursor = v_10; + } + return true; + }; + + /**@return{string}*/ + this['stemWord'] = function(/**string*/word) { + base.setCurrent(word); + this.stem(); + return base.getCurrent(); + }; +}; diff --git a/doc/_static/file.png b/doc/_static/file.png new file mode 100644 index 0000000..a858a41 Binary files /dev/null and b/doc/_static/file.png differ diff --git a/doc/_static/language_data.js b/doc/_static/language_data.js new file mode 100644 index 0000000..5776786 --- /dev/null +++ b/doc/_static/language_data.js @@ -0,0 +1,13 @@ +/* + * This script contains the language-specific data used by searchtools.js, + * namely the set of stopwords, stemmer, scorer and splitter. + */ + +const stopwords = new Set(["a", "about", "above", "after", "again", "against", "all", "am", "an", "and", "any", "are", "aren't", "as", "at", "be", "because", "been", "before", "being", "below", "between", "both", "but", "by", "can't", "cannot", "could", "couldn't", "did", "didn't", "do", "does", "doesn't", "doing", "don't", "down", "during", "each", "few", "for", "from", "further", "had", "hadn't", "has", "hasn't", "have", "haven't", "having", "he", "he'd", "he'll", "he's", "her", "here", "here's", "hers", "herself", "him", "himself", "his", "how", "how's", "i", "i'd", "i'll", "i'm", "i've", "if", "in", "into", "is", "isn't", "it", "it's", "its", "itself", "let's", "me", "more", "most", "mustn't", "my", "myself", "no", "nor", "not", "of", "off", "on", "once", "only", "or", "other", "ought", "our", "ours", "ourselves", "out", "over", "own", "same", "shan't", "she", "she'd", "she'll", "she's", "should", "shouldn't", "so", "some", "such", "than", "that", "that's", "the", "their", "theirs", "them", "themselves", "then", "there", "there's", "these", "they", "they'd", "they'll", "they're", "they've", "this", "those", "through", "to", "too", "under", "until", "up", "very", "was", "wasn't", "we", "we'd", "we'll", "we're", "we've", "were", "weren't", "what", "what's", "when", "when's", "where", "where's", "which", "while", "who", "who's", "whom", "why", "why's", "with", "won't", "would", "wouldn't", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves"]); +window.stopwords = stopwords; // Export to global scope + + +/* Non-minified versions are copied as separate JavaScript files, if available */ +BaseStemmer=function(){this.current="",this.cursor=0,this.limit=0,this.limit_backward=0,this.bra=0,this.ket=0,this.setCurrent=function(t){this.current=t,this.cursor=0,this.limit=this.current.length,this.limit_backward=0,this.bra=this.cursor,this.ket=this.limit},this.getCurrent=function(){return this.current},this.copy_from=function(t){this.current=t.current,this.cursor=t.cursor,this.limit=t.limit,this.limit_backward=t.limit_backward,this.bra=t.bra,this.ket=t.ket},this.in_grouping=function(t,r,i){return!(this.cursor>=this.limit||i<(i=this.current.charCodeAt(this.cursor))||i>>3]&1<<(7&i))||(this.cursor++,0))},this.go_in_grouping=function(t,r,i){for(;this.cursor>>3]&1<<(7&s)))return!0;this.cursor++}return!1},this.in_grouping_b=function(t,r,i){return!(this.cursor<=this.limit_backward||i<(i=this.current.charCodeAt(this.cursor-1))||i>>3]&1<<(7&i))||(this.cursor--,0))},this.go_in_grouping_b=function(t,r,i){for(;this.cursor>this.limit_backward;){var s=this.current.charCodeAt(this.cursor-1);if(i>>3]&1<<(7&s)))return!0;this.cursor--}return!1},this.out_grouping=function(t,r,i){return!(this.cursor>=this.limit)&&(i<(i=this.current.charCodeAt(this.cursor))||i>>3]&1<<(7&i)))&&(this.cursor++,!0)},this.go_out_grouping=function(t,r,i){for(;this.cursor>>3]&1<<(7&s)))return!0;this.cursor++}return!1},this.out_grouping_b=function(t,r,i){return!(this.cursor<=this.limit_backward)&&(i<(i=this.current.charCodeAt(this.cursor-1))||i>>3]&1<<(7&i)))&&(this.cursor--,!0)},this.go_out_grouping_b=function(t,r,i){for(;this.cursor>this.limit_backward;){var s=this.current.charCodeAt(this.cursor-1);if(s<=i&&r<=s&&0!=(t[(s-=r)>>>3]&1<<(7&s)))return!0;this.cursor--}return!1},this.eq_s=function(t){return!(this.limit-this.cursor>>1),o=0,a=e=(l=t[r])[0].length){if(this.cursor=s+l[0].length,l.length<4)return l[2];var g=l[3](this);if(this.cursor=s+l[0].length,g)return l[2]}}while(0<=(r=l[1]));return 0},this.find_among_b=function(t){for(var r=0,i=t.length,s=this.cursor,h=this.limit_backward,e=0,n=0,c=!1;;){for(var u,o=r+(i-r>>1),a=0,l=e=(u=t[r])[0].length){if(this.cursor=s-u[0].length,u.length<4)return u[2];var g=u[3](this);if(this.cursor=s-u[0].length,g)return u[2]}}while(0<=(r=u[1]));return 0},this.replace_s=function(t,r,i){var s=i.length-(r-t);return this.current=this.current.slice(0,t)+i+this.current.slice(r),this.limit+=s,this.cursor>=r?this.cursor+=s:this.cursor>t&&(this.cursor=t),s},this.slice_check=function(){return!(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>this.current.length)},this.slice_from=function(t){var r=!1;return this.slice_check()&&(this.replace_s(this.bra,this.ket,t),r=!0),r},this.slice_del=function(){return this.slice_from("")},this.insert=function(t,r,i){r=this.replace_s(t,r,i);t<=this.bra&&(this.bra+=r),t<=this.ket&&(this.ket+=r)},this.slice_to=function(){var t="";return t=this.slice_check()?this.current.slice(this.bra,this.ket):t},this.assign_to=function(){return this.current.slice(0,this.limit)}}; +var EnglishStemmer=function(){var a=new BaseStemmer,c=[["arsen",-1,-1],["commun",-1,-1],["emerg",-1,-1],["gener",-1,-1],["later",-1,-1],["organ",-1,-1],["past",-1,-1],["univers",-1,-1]],o=[["'",-1,1],["'s'",0,1],["'s",-1,1]],u=[["ied",-1,2],["s",-1,3],["ies",1,2],["sses",1,1],["ss",1,-1],["us",1,-1]],t=[["succ",-1,1],["proc",-1,1],["exc",-1,1]],l=[["even",-1,2],["cann",-1,2],["inn",-1,2],["earr",-1,2],["herr",-1,2],["out",-1,2],["y",-1,1]],n=[["",-1,-1],["ed",0,2],["eed",1,1],["ing",0,3],["edly",0,2],["eedly",4,1],["ingly",0,2]],f=[["",-1,3],["bb",0,2],["dd",0,2],["ff",0,2],["gg",0,2],["bl",0,1],["mm",0,2],["nn",0,2],["pp",0,2],["rr",0,2],["at",0,1],["tt",0,2],["iz",0,1]],_=[["anci",-1,3],["enci",-1,2],["ogi",-1,14],["li",-1,16],["bli",3,12],["abli",4,4],["alli",3,8],["fulli",3,9],["lessli",3,15],["ousli",3,10],["entli",3,5],["aliti",-1,8],["biliti",-1,12],["iviti",-1,11],["tional",-1,1],["ational",14,7],["alism",-1,8],["ation",-1,7],["ization",17,6],["izer",-1,6],["ator",-1,7],["iveness",-1,11],["fulness",-1,9],["ousness",-1,10],["ogist",-1,13]],m=[["icate",-1,4],["ative",-1,6],["alize",-1,3],["iciti",-1,4],["ical",-1,4],["tional",-1,1],["ational",5,2],["ful",-1,5],["ness",-1,5]],b=[["ic",-1,1],["ance",-1,1],["ence",-1,1],["able",-1,1],["ible",-1,1],["ate",-1,1],["ive",-1,1],["ize",-1,1],["iti",-1,1],["al",-1,1],["ism",-1,1],["ion",-1,2],["er",-1,1],["ous",-1,1],["ant",-1,1],["ent",-1,1],["ment",15,1],["ement",16,1]],k=[["e",-1,1],["l",-1,2]],g=[["andes",-1,-1],["atlas",-1,-1],["bias",-1,-1],["cosmos",-1,-1],["early",-1,5],["gently",-1,3],["howe",-1,-1],["idly",-1,2],["news",-1,-1],["only",-1,6],["singly",-1,7],["skies",-1,1],["sky",-1,-1],["ugly",-1,4]],d=[17,64],v=[17,65,16,1],i=[1,17,65,208,1],w=[55,141,2],p=!1,y=0,h=0;function q(){var r=a.limit-a.cursor;return!!(a.out_grouping_b(i,89,121)&&a.in_grouping_b(v,97,121)&&a.out_grouping_b(v,97,121)||(a.cursor=a.limit-r,a.out_grouping_b(v,97,121)&&a.in_grouping_b(v,97,121)&&!(a.cursor>a.limit_backward))||(a.cursor=a.limit-r,a.eq_s_b("past")))}function z(){return h<=a.cursor}function Y(){return y<=a.cursor}this.stem=function(){var r=a.cursor;if(!(()=>{var r;if(a.bra=a.cursor,0!=(r=a.find_among(g))&&(a.ket=a.cursor,!(a.cursora.limit)a.cursor=i;else{a.cursor=e,a.cursor=r,(()=>{p=!1;var r=a.cursor;if(a.bra=a.cursor,!a.eq_s("'")||(a.ket=a.cursor,a.slice_del())){a.cursor=r;r=a.cursor;if(a.bra=a.cursor,a.eq_s("y")){if(a.ket=a.cursor,!a.slice_from("Y"))return;p=!0}a.cursor=r;for(r=a.cursor;;){var i=a.cursor;r:{for(;;){var e=a.cursor;if(a.in_grouping(v,97,121)&&(a.bra=a.cursor,a.eq_s("y"))){a.ket=a.cursor,a.cursor=e;break}if(a.cursor=e,a.cursor>=a.limit)break r;a.cursor++}if(!a.slice_from("Y"))return;p=!0;continue}a.cursor=i;break}a.cursor=r}})(),h=a.limit,y=a.limit;i=a.cursor;r:{var s=a.cursor;if(0==a.find_among(c)){if(a.cursor=s,!a.go_out_grouping(v,97,121))break r;if(a.cursor++,!a.go_in_grouping(v,97,121))break r;a.cursor++}h=a.cursor,a.go_out_grouping(v,97,121)&&(a.cursor++,a.go_in_grouping(v,97,121))&&(a.cursor++,y=a.cursor)}a.cursor=i,a.limit_backward=a.cursor,a.cursor=a.limit;var e=a.limit-a.cursor,r=((()=>{var r=a.limit-a.cursor;if(a.ket=a.cursor,0==a.find_among_b(o))a.cursor=a.limit-r;else if(a.bra=a.cursor,!a.slice_del())return;if(a.ket=a.cursor,0!=(r=a.find_among_b(u)))switch(a.bra=a.cursor,r){case 1:if(a.slice_from("ss"))break;return;case 2:r:{var i=a.limit-a.cursor,e=a.cursor-2;if(!(e{a.ket=a.cursor,o=a.find_among_b(n),a.bra=a.cursor;r:{var r=a.limit-a.cursor;i:{switch(o){case 1:var i=a.limit-a.cursor;e:{var e=a.limit-a.cursor;if(0==a.find_among_b(t)||a.cursor>a.limit_backward){if(a.cursor=a.limit-e,!z())break e;if(!a.slice_from("ee"))return}}a.cursor=a.limit-i;break;case 2:break i;case 3:if(0==(o=a.find_among_b(l)))break i;switch(o){case 1:var s=a.limit-a.cursor;if(!a.out_grouping_b(v,97,121))break i;if(a.cursor>a.limit_backward)break i;if(a.cursor=a.limit-s,a.bra=a.cursor,a.slice_from("ie"))break;return;case 2:if(a.cursor>a.limit_backward)break i}}break r}a.cursor=a.limit-r;var c=a.limit-a.cursor;if(!a.go_out_grouping_b(v,97,121))return;if(a.cursor--,a.cursor=a.limit-c,!a.slice_del())return;a.ket=a.cursor,a.bra=a.cursor;var o,c=a.limit-a.cursor;switch(o=a.find_among_b(f)){case 1:return a.slice_from("e");case 2:var u=a.limit-a.cursor;if(a.in_grouping_b(d,97,111)&&!(a.cursor>a.limit_backward))return;a.cursor=a.limit-u;break;case 3:return a.cursor!=h||(u=a.limit-a.cursor,q()&&(a.cursor=a.limit-u,a.slice_from("e")))}if(a.cursor=a.limit-c,a.ket=a.cursor,a.cursor<=a.limit_backward)return;if(a.cursor--,a.bra=a.cursor,!a.slice_del())return}})(),a.cursor=a.limit-r,a.limit-a.cursor),r=(a.ket=a.cursor,e=a.limit-a.cursor,(a.eq_s_b("y")||(a.cursor=a.limit-e,a.eq_s_b("Y")))&&(a.bra=a.cursor,a.out_grouping_b(v,97,121))&&a.cursor>a.limit_backward&&a.slice_from("i"),a.cursor=a.limit-i,a.limit-a.cursor),e=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(_))&&(a.bra=a.cursor,z()))switch(r){case 1:if(a.slice_from("tion"))break;return;case 2:if(a.slice_from("ence"))break;return;case 3:if(a.slice_from("ance"))break;return;case 4:if(a.slice_from("able"))break;return;case 5:if(a.slice_from("ent"))break;return;case 6:if(a.slice_from("ize"))break;return;case 7:if(a.slice_from("ate"))break;return;case 8:if(a.slice_from("al"))break;return;case 9:if(a.slice_from("ful"))break;return;case 10:if(a.slice_from("ous"))break;return;case 11:if(a.slice_from("ive"))break;return;case 12:if(a.slice_from("ble"))break;return;case 13:if(a.slice_from("og"))break;return;case 14:if(!a.eq_s_b("l"))return;if(a.slice_from("og"))break;return;case 15:if(a.slice_from("less"))break;return;case 16:if(!a.in_grouping_b(w,99,116))return;if(a.slice_del())break}})(),a.cursor=a.limit-r,a.limit-a.cursor),i=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(m))&&(a.bra=a.cursor,z()))switch(r){case 1:if(a.slice_from("tion"))break;return;case 2:if(a.slice_from("ate"))break;return;case 3:if(a.slice_from("al"))break;return;case 4:if(a.slice_from("ic"))break;return;case 5:if(a.slice_del())break;return;case 6:if(!Y())return;if(a.slice_del())break}})(),a.cursor=a.limit-e,a.limit-a.cursor),r=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(b))&&(a.bra=a.cursor,Y()))switch(r){case 1:if(a.slice_del())break;return;case 2:var i=a.limit-a.cursor;if(!a.eq_s_b("s")&&(a.cursor=a.limit-i,!a.eq_s_b("t")))return;if(a.slice_del())break}})(),a.cursor=a.limit-i,a.limit-a.cursor),e=((()=>{var r;if(a.ket=a.cursor,0!=(r=a.find_among_b(k)))switch(a.bra=a.cursor,r){case 1:if(!Y()){if(!z())return;var i=a.limit-a.cursor;if(q())return;a.cursor=a.limit-i}if(a.slice_del())break;return;case 2:if(!Y())return;if(!a.eq_s_b("l"))return;if(a.slice_del())break}})(),a.cursor=a.limit-r,a.cursor=a.limit_backward,a.cursor);(()=>{if(p)for(;;){var r=a.cursor;r:{for(;;){var i=a.cursor;if(a.bra=a.cursor,a.eq_s("Y")){a.ket=a.cursor,a.cursor=i;break}if(a.cursor=i,a.cursor>=a.limit)break r;a.cursor++}if(a.slice_from("y"))continue;return}a.cursor=r;break}})(),a.cursor=e}}return!0},this.stemWord=function(r){return a.setCurrent(r),this.stem(),a.getCurrent()}}; +window.Stemmer = EnglishStemmer; diff --git a/doc/_static/minus.png b/doc/_static/minus.png new file mode 100644 index 0000000..d96755f Binary files /dev/null and b/doc/_static/minus.png differ diff --git a/doc/_static/plus.png b/doc/_static/plus.png new file mode 100644 index 0000000..7107cec Binary files /dev/null and b/doc/_static/plus.png differ diff --git a/doc/_static/print.css b/doc/_static/print.css new file mode 100644 index 0000000..bd88769 --- /dev/null +++ b/doc/_static/print.css @@ -0,0 +1,42 @@ +.sy-head { + position: static; + border-bottom: 1px solid var(--sy-c-divider); +} + +.sy-head-inner { + padding: 0; +} + +.sy-breadcrumbs { + display: none; +} + +h1, h2, h3, h4, h5, h6 { + page-break-inside: avoid; + page-break-after: avoid; +} + +.code-block-caption, +pre, code { + page-break-inside: avoid; + white-space: pre-wrap; + + -webkit-print-color-adjust: exact; +} + +.yue a.headerlink { + display: none; +} + +.highlight .linenos { + box-shadow: none; +} + +.admonition, +.sd-sphinx-override { + -webkit-print-color-adjust: exact; +} + +.sd-card { + page-break-inside: avoid; +} diff --git a/doc/_static/pygments.css b/doc/_static/pygments.css new file mode 100644 index 0000000..352b22c --- /dev/null +++ b/doc/_static/pygments.css @@ -0,0 +1,278 @@ +:root { +--syntax-light-background: #ffffff; +--syntax-light-highlight: #4ac26b40; +--syntax-light-text: #1F2328; +--syntax-light-escape: #0A3069; +--syntax-light-error: #82071E; +--syntax-light-keyword: #CF222E; +--syntax-light-keyword-constant: #0550AE; +--syntax-light-keyword-type: #953800; +--syntax-light-name-attribute: #0550AE; +--syntax-light-name-builtin: #0550AE; +--syntax-light-name-class: #953800; +--syntax-light-name-constant: #0550AE; +--syntax-light-name-decorator: #0550AE; +--syntax-light-name-entity: #0550AE; +--syntax-light-name-exception: #0550AE; +--syntax-light-name-function: #8250DF; +--syntax-light-name-function-magic: #0550AE; +--syntax-light-name-property: #0550AE; +--syntax-light-name-label: #0A3069; +--syntax-light-name-tag: #116329; +--syntax-light-name-variable-class: #953800; +--syntax-light-literal: #0A3069; +--syntax-light-literal-string: #0A3069; +--syntax-light-literal-string-affix: #CF222E; +--syntax-light-literal-string-backtick: #0550AE; +--syntax-light-literal-string-interpol: #CF222E; +--syntax-light-literal-string-regex: #0A3069; +--syntax-light-literal-string-symbol: #0550AE; +--syntax-light-literal-number: #0550AE; +--syntax-light-operator: #CF222E; +--syntax-light-operator-word: #0550AE; +--syntax-light-comment: #6E7781; +--syntax-light-comment-preproc: #CF222E; +--syntax-light-comment-preprocfile: #0A3069; +--syntax-light-generic-deleted: #82071E; +--syntax-light-generic-emph: #1F2328; +--syntax-light-generic-error: #82071E; +--syntax-light-generic-heading: #0550AE; +--syntax-light-generic-inserted: #116329; +--syntax-light-generic-output: #0A3069; +--syntax-light-generic-prompt: #CF222E; +--syntax-light-generic-strong: #1F2328; +--syntax-light-generic-subheading: #0550AE; +--syntax-light-generic-emphstrong: #1F2328; +--syntax-light-generic-traceback: #82071E; +--syntax-light-text-whitespace: #1F2328; +--syntax-light-keyword-declaration: #CF222E; +--syntax-light-keyword-namespace: #CF222E; +--syntax-light-keyword-pseudo: #CF222E; +--syntax-light-keyword-reserved: #CF222E; +--syntax-light-name-builtin-pseudo: #0550AE; +--syntax-light-literal-date: #0A3069; +--syntax-light-literal-string-char: #0A3069; +--syntax-light-literal-string-delimiter: #0A3069; +--syntax-light-literal-string-doc: #0A3069; +--syntax-light-literal-string-double: #0A3069; +--syntax-light-literal-string-escape: #0A3069; +--syntax-light-literal-string-heredoc: #0A3069; +--syntax-light-literal-string-other: #0A3069; +--syntax-light-literal-string-single: #0A3069; +--syntax-light-literal-number-bin: #0550AE; +--syntax-light-literal-number-float: #0550AE; +--syntax-light-literal-number-hex: #0550AE; +--syntax-light-literal-number-integer: #0550AE; +--syntax-light-literal-number-integer-long: #0550AE; +--syntax-light-literal-number-oct: #0550AE; +--syntax-light-comment-hashbang: #6E7781; +--syntax-light-comment-multiline: #6E7781; +--syntax-light-comment-single: #6E7781; +--syntax-light-comment-special: #6E7781; +} +html.light .highlight .c { color: var(--syntax-light-comment) } +html.light .highlight .err { color: var(--syntax-light-error) } +html.light .highlight .esc { color: var(--syntax-light-escape) } +html.light .highlight .k { color: var(--syntax-light-keyword) } +html.light .highlight .l { color: var(--syntax-light-literal) } +html.light .highlight .o { color: var(--syntax-light-operator) } +html.light .highlight .ch { color: var(--syntax-light-comment-hashbang) } +html.light .highlight .cm { color: var(--syntax-light-comment-multiline) } +html.light .highlight .cp { color: var(--syntax-light-comment-preproc) } +html.light .highlight .cpf { color: var(--syntax-light-comment-preprocfile) } +html.light .highlight .c1 { color: var(--syntax-light-comment-single) } +html.light .highlight .cs { color: var(--syntax-light-comment-special) } +html.light .highlight .gd { color: var(--syntax-light-generic-deleted) } +html.light .highlight .ge { color: var(--syntax-light-generic-emph); font-style: italic } +html.light .highlight .ges { color: var(--syntax-light-generic-emphstrong); font-weight: bold; font-style: italic } +html.light .highlight .gr { color: var(--syntax-light-generic-error) } +html.light .highlight .gh { color: var(--syntax-light-generic-heading); font-weight: bold } +html.light .highlight .gi { color: var(--syntax-light-generic-inserted) } +html.light .highlight .go { color: var(--syntax-light-generic-output) } +html.light .highlight .gp { color: var(--syntax-light-generic-prompt) } +html.light .highlight .gs { color: var(--syntax-light-generic-strong); font-weight: bold } +html.light .highlight .gu { color: var(--syntax-light-generic-subheading) } +html.light .highlight .gt { color: var(--syntax-light-generic-traceback) } +html.light .highlight .kc { color: var(--syntax-light-keyword-constant) } +html.light .highlight .kd { color: var(--syntax-light-keyword-declaration) } +html.light .highlight .kn { color: var(--syntax-light-keyword-namespace) } +html.light .highlight .kp { color: var(--syntax-light-keyword-pseudo) } +html.light .highlight .kr { color: var(--syntax-light-keyword-reserved) } +html.light .highlight .kt { color: var(--syntax-light-keyword-type) } +html.light .highlight .ld { color: var(--syntax-light-literal-date) } +html.light .highlight .m { color: var(--syntax-light-literal-number) } +html.light .highlight .s { color: var(--syntax-light-literal-string) } +html.light .highlight .na { color: var(--syntax-light-name-attribute) } +html.light .highlight .nb { color: var(--syntax-light-name-builtin) } +html.light .highlight .nc { color: var(--syntax-light-name-class) } +html.light .highlight .no { color: var(--syntax-light-name-constant) } +html.light .highlight .nd { color: var(--syntax-light-name-decorator) } +html.light .highlight .ni { color: var(--syntax-light-name-entity) } +html.light .highlight .ne { color: var(--syntax-light-name-exception) } +html.light .highlight .nf { color: var(--syntax-light-name-function) } +html.light .highlight .nl { color: var(--syntax-light-name-label) } +html.light .highlight .py { color: var(--syntax-light-name-property) } +html.light .highlight .nt { color: var(--syntax-light-name-tag) } +html.light .highlight .ow { color: var(--syntax-light-operator-word) } +html.light .highlight .w { color: var(--syntax-light-text-whitespace) } +html.light .highlight .mb { color: var(--syntax-light-literal-number-bin) } +html.light .highlight .mf { color: var(--syntax-light-literal-number-float) } +html.light .highlight .mh { color: var(--syntax-light-literal-number-hex) } +html.light .highlight .mi { color: var(--syntax-light-literal-number-integer) } +html.light .highlight .mo { color: var(--syntax-light-literal-number-oct) } +html.light .highlight .sa { color: var(--syntax-light-literal-string-affix) } +html.light .highlight .sb { color: var(--syntax-light-literal-string-backtick) } +html.light .highlight .sc { color: var(--syntax-light-literal-string-char) } +html.light .highlight .dl { color: var(--syntax-light-literal-string-delimiter) } +html.light .highlight .sd { color: var(--syntax-light-literal-string-doc) } +html.light .highlight .s2 { color: var(--syntax-light-literal-string-double) } +html.light .highlight .se { color: var(--syntax-light-literal-string-escape) } +html.light .highlight .sh { color: var(--syntax-light-literal-string-heredoc) } +html.light .highlight .si { color: var(--syntax-light-literal-string-interpol) } +html.light .highlight .sx { color: var(--syntax-light-literal-string-other) } +html.light .highlight .sr { color: var(--syntax-light-literal-string-regex) } +html.light .highlight .s1 { color: var(--syntax-light-literal-string-single) } +html.light .highlight .ss { color: var(--syntax-light-literal-string-symbol) } +html.light .highlight .bp { color: var(--syntax-light-name-builtin-pseudo) } +html.light .highlight .fm { color: var(--syntax-light-name-function-magic) } +html.light .highlight .vc { color: var(--syntax-light-name-variable-class) } +html.light .highlight .il { color: var(--syntax-light-literal-number-integer-long) } +:root { +--syntax-dark-background: #0d1117; +--syntax-dark-highlight: #3fb95040; +--syntax-dark-text: #E6EDF3; +--syntax-dark-escape: #A5D6FF; +--syntax-dark-error: #FFA198; +--syntax-dark-keyword: #FF7B72; +--syntax-dark-keyword-constant: #79C0FF; +--syntax-dark-keyword-type: #FFA657; +--syntax-dark-name-attribute: #79C0FF; +--syntax-dark-name-builtin: #79C0FF; +--syntax-dark-name-class: #FFA657; +--syntax-dark-name-constant: #79C0FF; +--syntax-dark-name-decorator: #79C0FF; +--syntax-dark-name-entity: #79C0FF; +--syntax-dark-name-exception: #79C0FF; +--syntax-dark-name-function: #D2A8FF; +--syntax-dark-name-function-magic: #79C0FF; +--syntax-dark-name-property: #79C0FF; +--syntax-dark-name-label: #A5D6FF; +--syntax-dark-name-tag: #7EE787; +--syntax-dark-name-variable-class: #FFA657; +--syntax-dark-literal: #A5D6FF; +--syntax-dark-literal-string: #A5D6FF; +--syntax-dark-literal-string-affix: #FF7B72; +--syntax-dark-literal-string-backtick: #79C0FF; +--syntax-dark-literal-string-interpol: #FF7B72; +--syntax-dark-literal-string-regex: #A5D6FF; +--syntax-dark-literal-string-symbol: #79C0FF; +--syntax-dark-literal-number: #79C0FF; +--syntax-dark-operator: #FF7B72; +--syntax-dark-operator-word: #79C0FF; +--syntax-dark-comment: #8B949E; +--syntax-dark-comment-preproc: #FF7B72; +--syntax-dark-comment-preprocfile: #A5D6FF; +--syntax-dark-generic-deleted: #FFA198; +--syntax-dark-generic-emph: #E6EDF3; +--syntax-dark-generic-error: #FFA198; +--syntax-dark-generic-heading: #79C0FF; +--syntax-dark-generic-inserted: #7EE787; +--syntax-dark-generic-output: #A5D6FF; +--syntax-dark-generic-prompt: #FF7B72; +--syntax-dark-generic-strong: #E6EDF3; +--syntax-dark-generic-subheading: #79C0FF; +--syntax-dark-generic-emphstrong: #E6EDF3; +--syntax-dark-generic-traceback: #FFA198; +--syntax-dark-text-whitespace: #E6EDF3; +--syntax-dark-keyword-declaration: #FF7B72; +--syntax-dark-keyword-namespace: #FF7B72; +--syntax-dark-keyword-pseudo: #FF7B72; +--syntax-dark-keyword-reserved: #FF7B72; +--syntax-dark-name-builtin-pseudo: #79C0FF; +--syntax-dark-literal-date: #A5D6FF; +--syntax-dark-literal-string-char: #A5D6FF; +--syntax-dark-literal-string-delimiter: #A5D6FF; +--syntax-dark-literal-string-doc: #A5D6FF; +--syntax-dark-literal-string-double: #A5D6FF; +--syntax-dark-literal-string-escape: #A5D6FF; +--syntax-dark-literal-string-heredoc: #A5D6FF; +--syntax-dark-literal-string-other: #A5D6FF; +--syntax-dark-literal-string-single: #A5D6FF; +--syntax-dark-literal-number-bin: #79C0FF; +--syntax-dark-literal-number-float: #79C0FF; +--syntax-dark-literal-number-hex: #79C0FF; +--syntax-dark-literal-number-integer: #79C0FF; +--syntax-dark-literal-number-integer-long: #79C0FF; +--syntax-dark-literal-number-oct: #79C0FF; +--syntax-dark-comment-hashbang: #8B949E; +--syntax-dark-comment-multiline: #8B949E; +--syntax-dark-comment-single: #8B949E; +--syntax-dark-comment-special: #8B949E; +} +html.dark .highlight .c, html.light .dark-code .highlight .c { color: var(--syntax-dark-comment) } +html.dark .highlight .err, html.light .dark-code .highlight .err { color: var(--syntax-dark-error) } +html.dark .highlight .esc, html.light .dark-code .highlight .esc { color: var(--syntax-dark-escape) } +html.dark .highlight .k, html.light .dark-code .highlight .k { color: var(--syntax-dark-keyword) } +html.dark .highlight .l, html.light .dark-code .highlight .l { color: var(--syntax-dark-literal) } +html.dark .highlight .o, html.light .dark-code .highlight .o { color: var(--syntax-dark-operator) } +html.dark .highlight .ch, html.light .dark-code .highlight .ch { color: var(--syntax-dark-comment-hashbang) } +html.dark .highlight .cm, html.light .dark-code .highlight .cm { color: var(--syntax-dark-comment-multiline) } +html.dark .highlight .cp, html.light .dark-code .highlight .cp { color: var(--syntax-dark-comment-preproc) } +html.dark .highlight .cpf, html.light .dark-code .highlight .cpf { color: var(--syntax-dark-comment-preprocfile) } +html.dark .highlight .c1, html.light .dark-code .highlight .c1 { color: var(--syntax-dark-comment-single) } +html.dark .highlight .cs, html.light .dark-code .highlight .cs { color: var(--syntax-dark-comment-special) } +html.dark .highlight .gd, html.light .dark-code .highlight .gd { color: var(--syntax-dark-generic-deleted) } +html.dark .highlight .ge, html.light .dark-code .highlight .ge { color: var(--syntax-dark-generic-emph); font-style: italic } +html.dark .highlight .ges, html.light .dark-code .highlight .ges { color: var(--syntax-dark-generic-emphstrong); font-weight: bold; font-style: italic } +html.dark .highlight .gr, html.light .dark-code .highlight .gr { color: var(--syntax-dark-generic-error) } +html.dark .highlight .gh, html.light .dark-code .highlight .gh { color: var(--syntax-dark-generic-heading); font-weight: bold } +html.dark .highlight .gi, html.light .dark-code .highlight .gi { color: var(--syntax-dark-generic-inserted) } +html.dark .highlight .go, html.light .dark-code .highlight .go { color: var(--syntax-dark-generic-output) } +html.dark .highlight .gp, html.light .dark-code .highlight .gp { color: var(--syntax-dark-generic-prompt) } +html.dark .highlight .gs, html.light .dark-code .highlight .gs { color: var(--syntax-dark-generic-strong); font-weight: bold } +html.dark .highlight .gu, html.light .dark-code .highlight .gu { color: var(--syntax-dark-generic-subheading) } +html.dark .highlight .gt, html.light .dark-code .highlight .gt { color: var(--syntax-dark-generic-traceback) } +html.dark .highlight .kc, html.light .dark-code .highlight .kc { color: var(--syntax-dark-keyword-constant) } +html.dark .highlight .kd, html.light .dark-code .highlight .kd { color: var(--syntax-dark-keyword-declaration) } +html.dark .highlight .kn, html.light .dark-code .highlight .kn { color: var(--syntax-dark-keyword-namespace) } +html.dark .highlight .kp, html.light .dark-code .highlight .kp { color: var(--syntax-dark-keyword-pseudo) } +html.dark .highlight .kr, html.light .dark-code .highlight .kr { color: var(--syntax-dark-keyword-reserved) } +html.dark .highlight .kt, html.light .dark-code .highlight .kt { color: var(--syntax-dark-keyword-type) } +html.dark .highlight .ld, html.light .dark-code .highlight .ld { color: var(--syntax-dark-literal-date) } +html.dark .highlight .m, html.light .dark-code .highlight .m { color: var(--syntax-dark-literal-number) } +html.dark .highlight .s, html.light .dark-code .highlight .s { color: var(--syntax-dark-literal-string) } +html.dark .highlight .na, html.light .dark-code .highlight .na { color: var(--syntax-dark-name-attribute) } +html.dark .highlight .nb, html.light .dark-code .highlight .nb { color: var(--syntax-dark-name-builtin) } +html.dark .highlight .nc, html.light .dark-code .highlight .nc { color: var(--syntax-dark-name-class) } +html.dark .highlight .no, html.light .dark-code .highlight .no { color: var(--syntax-dark-name-constant) } +html.dark .highlight .nd, html.light .dark-code .highlight .nd { color: var(--syntax-dark-name-decorator) } +html.dark .highlight .ni, html.light .dark-code .highlight .ni { color: var(--syntax-dark-name-entity) } +html.dark .highlight .ne, html.light .dark-code .highlight .ne { color: var(--syntax-dark-name-exception) } +html.dark .highlight .nf, html.light .dark-code .highlight .nf { color: var(--syntax-dark-name-function) } +html.dark .highlight .nl, html.light .dark-code .highlight .nl { color: var(--syntax-dark-name-label) } +html.dark .highlight .py, html.light .dark-code .highlight .py { color: var(--syntax-dark-name-property) } +html.dark .highlight .nt, html.light .dark-code .highlight .nt { color: var(--syntax-dark-name-tag) } +html.dark .highlight .ow, html.light .dark-code .highlight .ow { color: var(--syntax-dark-operator-word) } +html.dark .highlight .w, html.light .dark-code .highlight .w { color: var(--syntax-dark-text-whitespace) } +html.dark .highlight .mb, html.light .dark-code .highlight .mb { color: var(--syntax-dark-literal-number-bin) } +html.dark .highlight .mf, html.light .dark-code .highlight .mf { color: var(--syntax-dark-literal-number-float) } +html.dark .highlight .mh, html.light .dark-code .highlight .mh { color: var(--syntax-dark-literal-number-hex) } +html.dark .highlight .mi, html.light .dark-code .highlight .mi { color: var(--syntax-dark-literal-number-integer) } +html.dark .highlight .mo, html.light .dark-code .highlight .mo { color: var(--syntax-dark-literal-number-oct) } +html.dark .highlight .sa, html.light .dark-code .highlight .sa { color: var(--syntax-dark-literal-string-affix) } +html.dark .highlight .sb, html.light .dark-code .highlight .sb { color: var(--syntax-dark-literal-string-backtick) } +html.dark .highlight .sc, html.light .dark-code .highlight .sc { color: var(--syntax-dark-literal-string-char) } +html.dark .highlight .dl, html.light .dark-code .highlight .dl { color: var(--syntax-dark-literal-string-delimiter) } +html.dark .highlight .sd, html.light .dark-code .highlight .sd { color: var(--syntax-dark-literal-string-doc) } +html.dark .highlight .s2, html.light .dark-code .highlight .s2 { color: var(--syntax-dark-literal-string-double) } +html.dark .highlight .se, html.light .dark-code .highlight .se { color: var(--syntax-dark-literal-string-escape) } +html.dark .highlight .sh, html.light .dark-code .highlight .sh { color: var(--syntax-dark-literal-string-heredoc) } +html.dark .highlight .si, html.light .dark-code .highlight .si { color: var(--syntax-dark-literal-string-interpol) } +html.dark .highlight .sx, html.light .dark-code .highlight .sx { color: var(--syntax-dark-literal-string-other) } +html.dark .highlight .sr, html.light .dark-code .highlight .sr { color: var(--syntax-dark-literal-string-regex) } +html.dark .highlight .s1, html.light .dark-code .highlight .s1 { color: var(--syntax-dark-literal-string-single) } +html.dark .highlight .ss, html.light .dark-code .highlight .ss { color: var(--syntax-dark-literal-string-symbol) } +html.dark .highlight .bp, html.light .dark-code .highlight .bp { color: var(--syntax-dark-name-builtin-pseudo) } +html.dark .highlight .fm, html.light .dark-code .highlight .fm { color: var(--syntax-dark-name-function-magic) } +html.dark .highlight .vc, html.light .dark-code .highlight .vc { color: var(--syntax-dark-name-variable-class) } +html.dark .highlight .il, html.light .dark-code .highlight .il { color: var(--syntax-dark-literal-number-integer-long) } diff --git a/doc/_static/searchtools.js b/doc/_static/searchtools.js new file mode 100644 index 0000000..e29b1c7 --- /dev/null +++ b/doc/_static/searchtools.js @@ -0,0 +1,693 @@ +/* + * Sphinx JavaScript utilities for the full-text search. + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename, kind] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +// Global search result kind enum, used by themes to style search results. +// prettier-ignore +class SearchResultKind { + static get index() { return "index"; } + static get object() { return "object"; } + static get text() { return "text"; } + static get title() { return "title"; } +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _escapeHTML = (text) => { + return text + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); +}; + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename, kind] = item; + + let listItem = document.createElement("li"); + // Add a class representing the item's type: + // can be used by a theme's CSS selector for styling + // See SearchResultKind for the class names. + listItem.classList.add(`kind-${kind}`); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = _escapeHTML(title); + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + ` (${_escapeHTML(descr)})`; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) + // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js + highlightTerms.forEach((term) => + _highlightText(listItem, term, "highlighted"), + ); + } else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor), + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) + // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js + highlightTerms.forEach((term) => + _highlightText(listItem, term, "highlighted"), + ); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.", + ); + else + Search.status.innerText = Documentation.ngettext( + "Search finished, found one page matching the search query.", + "Search finished, found ${resultCount} pages matching the search query.", + resultCount, + ).replace("${resultCount}", resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5, + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename, kind]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => + query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter((term) => term); // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString( + htmlString, + "text/html", + ); + for (const removalQuery of [".headerlink", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { + el.remove(); + }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector( + `[role="main"] ${anchor}`, + ); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.`, + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template.", + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.setAttribute("role", "list"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords set is from language_data.js + if (stopwords.has(queryTermLower) || queryTerm.match(/^\d+$/)) return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { + // SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js + localStorage.setItem( + "sphinx_highlight_terms", + [...highlightTerms].join(" "), + ); + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: ( + query, + searchTerms, + excludedTerms, + highlightTerms, + objectTerms, + ) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename, kind]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if ( + title.toLowerCase().trim().includes(queryLower) + && queryLower.length >= title.length / 2 + ) { + for (const [file, id] of foundTitles) { + const score = Math.round( + (Scorer.title * queryLower.length) / title.length, + ); + const boost = titles[file] === title ? 1 : 0; // add a boost for document titles + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score + boost, + filenames[file], + SearchResultKind.title, + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && queryLower.length >= entry.length / 2) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round((100 * queryLower.length) / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + SearchResultKind.index, + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)), + ); + + // lookup as search terms in fulltext + normalResults.push( + ...Search.performTermsSearch(searchTerms, excludedTerms), + ); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result + .slice(0, 4) + .concat([result[5]]) + .map((v) => String(v)) + .join(","); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [ + searchQuery, + searchTerms, + excludedTerms, + highlightTerms, + objectTerms, + ] = Search._parseQuery(query); + const results = Search._performSearch( + searchQuery, + searchTerms, + excludedTerms, + highlightTerms, + objectTerms, + ); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4]; + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + SearchResultKind.object, + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => objectSearchCallback(prefix, array)), + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + // find documents, if any, containing the query word in their text/title term indices + // use Object.hasOwnProperty to avoid mismatching against prototype properties + const arr = [ + { + files: terms.hasOwnProperty(word) ? terms[word] : undefined, + score: Scorer.term, + }, + { + files: titleTerms.hasOwnProperty(word) ? titleTerms[word] : undefined, + score: Scorer.title, + }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, new Map()); + const fileScores = scoreMap.get(file); + fileScores.set(word, record.score); + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2, + ).length; + if ( + wordList.length !== searchTerms.size + && wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file + || titleTerms[term] === file + || (terms[term] || []).includes(file) + || (titleTerms[term] || []).includes(file), + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file).get(w))); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + SearchResultKind.text, + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = + top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/doc/_static/shibuya.css b/doc/_static/shibuya.css new file mode 100644 index 0000000..859edaa --- /dev/null +++ b/doc/_static/shibuya.css @@ -0,0 +1,2 @@ +/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--container-6xl:72rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.relative{position:relative}.order-last{order:9999}.mx-auto{margin-inline:auto}.mr-3{margin-right:calc(var(--spacing) * 3)}.ml-1{margin-left:var(--spacing)}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline-flex{display:inline-flex}.table{display:table}.w-8{width:calc(var(--spacing) * 8)}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.max-w-6xl{max-width:var(--container-6xl)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.gap-1{gap:var(--spacing)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-1{padding-block:var(--spacing)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pt-12{padding-top:calc(var(--spacing) * 12)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}@media not all and (min-width:40rem){.max-sm\:max-w-full{max-width:100%}}@media (min-width:48rem){.md\:sticky{position:sticky}.md\:flex{display:flex}.md\:hidden{display:none}.md\:inline{display:inline}.md\:w-72{width:calc(var(--spacing) * 72)}.md\:shrink-0{flex-shrink:0}}@media (min-width:64rem){.lg\:absolute{position:absolute}.lg\:top-8{top:calc(var(--spacing) * 8)}.lg\:right-6{right:calc(var(--spacing) * 6)}}@media (min-width:80rem){.xl\:sticky{position:sticky}.xl\:top-16{top:calc(var(--spacing) * 16)}.xl\:right-12{right:calc(var(--spacing) * 12)}.xl\:hidden{display:none}.xl\:px-12{padding-inline:calc(var(--spacing) * 12)}.xl\:pl-0{padding-left:0}}@media print{.print\:hidden{display:none}.print\:pt-6{padding-top:calc(var(--spacing) * 6)}}}@font-face{font-family:Twemoji Country Flags;unicode-range:U+1F1E6-1F1FF,U+1F3F4,U+E0062-E0063,U+E0065,U+E0067,U+E006C,U+E006E,U+E0073-E0074,U+E0077,U+E007F;src:url(https://cdn.jsdelivr.net/npm/country-flag-emoji-polyfill@0.1/dist/TwemojiCountryFlags.woff2)format("woff2")}::selection{color:var(--accent-contrast);background-color:var(--accent-a8)}html{scroll-behavior:smooth}body{font-family:var(--sy-f-text);color:var(--sy-c-text)}.win{font-family:"Twemoji Country Flags", var(--sy-f-text)}h1,h2,h3,h4,h5{color:var(--sy-c-heading);font-family:var(--sy-f-heading)}strong,em{color:var(--sy-c-bold)}.sy-container{max-width:90rem}.sy-scrollbar{scrollbar-gutter:stable;overflow-y:auto}.sy-scrollbar::-webkit-scrollbar{width:.75rem;height:.75rem}.sy-scrollbar::-webkit-scrollbar-thumb{border-radius:10px}.sy-scrollbar::-webkit-scrollbar-track{background-color:#0000}.sy-scrollbar:hover::-webkit-scrollbar-thumb{background-color:var(--gray-a3);background-clip:content-box;border:3px solid #0000}iconify-icon{vertical-align:middle}.i-lucide{-webkit-mask:var(--icon-url) no-repeat;-webkit-mask:var(--icon-url) no-repeat;mask:var(--icon-url) no-repeat;vertical-align:middle;background-color:currentColor;width:1em;height:1em;font-style:normal;display:inline-block;-webkit-mask-size:100% 100%;mask-size:100% 100%}.theme-switch .theme-icon,[data-color-mode=auto] .theme-switch .theme-icon{--icon-url:var(--lucide-sun-moon-url)}[data-color-mode=light] .theme-switch .theme-icon{--icon-url:var(--lucide-sun-url)}[data-color-mode=dark] .theme-switch .theme-icon{--icon-url:var(--lucide-moon-url)}:root,.light,.light-theme{--tomato-1:#fffcfc;--tomato-2:#fff8f7;--tomato-3:#feebe7;--tomato-4:#ffdcd3;--tomato-5:#ffcdc2;--tomato-6:#fdbdaf;--tomato-7:#f5a898;--tomato-8:#ec8e7b;--tomato-9:#e54d2e;--tomato-10:#dd4425;--tomato-11:#d13415;--tomato-12:#5c271f}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--tomato-1:color(display-p3 .998 .989 .988);--tomato-2:color(display-p3 .994 .974 .969);--tomato-3:color(display-p3 .985 .924 .909);--tomato-4:color(display-p3 .996 .868 .835);--tomato-5:color(display-p3 .98 .812 .77);--tomato-6:color(display-p3 .953 .75 .698);--tomato-7:color(display-p3 .917 .673 .611);--tomato-8:color(display-p3 .875 .575 .502);--tomato-9:color(display-p3 .831 .345 .231);--tomato-10:color(display-p3 .802 .313 .2);--tomato-11:color(display-p3 .755 .259 .152);--tomato-12:color(display-p3 .335 .165 .132)}}}.dark,.dark-theme{--tomato-1:#181111;--tomato-2:#1f1513;--tomato-3:#391714;--tomato-4:#4e1511;--tomato-5:#5e1c16;--tomato-6:#6e2920;--tomato-7:#853a2d;--tomato-8:#ac4d39;--tomato-9:#e54d2e;--tomato-10:#ec6142;--tomato-11:#ff977d;--tomato-12:#fbd3cb}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--tomato-1:color(display-p3 .09 .068 .067);--tomato-2:color(display-p3 .115 .084 .076);--tomato-3:color(display-p3 .205 .097 .083);--tomato-4:color(display-p3 .282 .099 .077);--tomato-5:color(display-p3 .339 .129 .101);--tomato-6:color(display-p3 .398 .179 .141);--tomato-7:color(display-p3 .487 .245 .194);--tomato-8:color(display-p3 .629 .322 .248);--tomato-9:color(display-p3 .831 .345 .231);--tomato-10:color(display-p3 .862 .415 .298);--tomato-11:color(display-p3 1 .585 .455);--tomato-12:color(display-p3 .959 .833 .802)}}}:root,.light,.light-theme{--tomato-a1:#ff000003;--tomato-a2:#ff200008;--tomato-a3:#f52b0018;--tomato-a4:#ff35002c;--tomato-a5:#ff2e003d;--tomato-a6:#f92d0050;--tomato-a7:#e7280067;--tomato-a8:#db250084;--tomato-a9:#df2600d1;--tomato-a10:#d72400da;--tomato-a11:#cd2200ea;--tomato-a12:#460900e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--tomato-a1:color(display-p3 .675 .024 .024/.012);--tomato-a2:color(display-p3 .757 .145 .02/.032);--tomato-a3:color(display-p3 .831 .184 .012/.091);--tomato-a4:color(display-p3 .976 .192 .004/.165);--tomato-a5:color(display-p3 .918 .192 .004/.232);--tomato-a6:color(display-p3 .847 .173 .004/.302);--tomato-a7:color(display-p3 .788 .165 .004/.389);--tomato-a8:color(display-p3 .749 .153 .004/.499);--tomato-a9:color(display-p3 .78 .149 0/.769);--tomato-a10:color(display-p3 .757 .141 0/.8);--tomato-a11:color(display-p3 .755 .259 .152);--tomato-a12:color(display-p3 .335 .165 .132)}}}.dark,.dark-theme{--tomato-a1:#f1121208;--tomato-a2:#ff55330f;--tomato-a3:#ff35232b;--tomato-a4:#fd201142;--tomato-a5:#fe332153;--tomato-a6:#ff4f3864;--tomato-a7:#fd644a7d;--tomato-a8:#fe6d4ea7;--tomato-a9:#fe5431e4;--tomato-a10:#ff6847eb;--tomato-a11:#ff977d;--tomato-a12:#ffd6cefb}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--tomato-a1:color(display-p3 .973 .071 .071/.026);--tomato-a2:color(display-p3 .992 .376 .224/.051);--tomato-a3:color(display-p3 .996 .282 .176/.148);--tomato-a4:color(display-p3 1 .204 .118/.232);--tomato-a5:color(display-p3 1 .286 .192/.29);--tomato-a6:color(display-p3 1 .392 .278/.353);--tomato-a7:color(display-p3 1 .459 .349/.45);--tomato-a8:color(display-p3 1 .49 .369/.601);--tomato-a9:color(display-p3 1 .408 .267/.82);--tomato-a10:color(display-p3 1 .478 .341/.853);--tomato-a11:color(display-p3 1 .585 .455);--tomato-a12:color(display-p3 .959 .833 .802)}}}:root,.light,.light-theme{--red-1:#fffcfc;--red-2:#fff7f7;--red-3:#feebec;--red-4:#ffdbdc;--red-5:#ffcdce;--red-6:#fdbdbe;--red-7:#f4a9aa;--red-8:#eb8e90;--red-9:#e5484d;--red-10:#dc3e42;--red-11:#ce2c31;--red-12:#641723}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--red-1:color(display-p3 .998 .989 .988);--red-2:color(display-p3 .995 .971 .971);--red-3:color(display-p3 .985 .925 .925);--red-4:color(display-p3 .999 .866 .866);--red-5:color(display-p3 .984 .812 .811);--red-6:color(display-p3 .955 .751 .749);--red-7:color(display-p3 .915 .675 .672);--red-8:color(display-p3 .872 .575 .572);--red-9:color(display-p3 .83 .329 .324);--red-10:color(display-p3 .798 .294 .285);--red-11:color(display-p3 .744 .234 .222);--red-12:color(display-p3 .36 .115 .143)}}}.dark,.dark-theme{--red-1:#191111;--red-2:#201314;--red-3:#3b1219;--red-4:#500f1c;--red-5:#611623;--red-6:#72232d;--red-7:#8c333a;--red-8:#b54548;--red-9:#e5484d;--red-10:#ec5d5e;--red-11:#ff9592;--red-12:#ffd1d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--red-1:color(display-p3 .093 .068 .067);--red-2:color(display-p3 .118 .077 .079);--red-3:color(display-p3 .211 .081 .099);--red-4:color(display-p3 .287 .079 .113);--red-5:color(display-p3 .348 .11 .142);--red-6:color(display-p3 .414 .16 .183);--red-7:color(display-p3 .508 .224 .236);--red-8:color(display-p3 .659 .298 .297);--red-9:color(display-p3 .83 .329 .324);--red-10:color(display-p3 .861 .403 .387);--red-11:color(display-p3 1 .57 .55);--red-12:color(display-p3 .971 .826 .852)}}}:root,.light,.light-theme{--red-a1:#ff000003;--red-a2:#ff000008;--red-a3:#f3000d14;--red-a4:#ff000824;--red-a5:#ff000632;--red-a6:#f8000442;--red-a7:#df000356;--red-a8:#d2000571;--red-a9:#db0007b7;--red-a10:#d10005c1;--red-a11:#c40006d3;--red-a12:#55000de8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--red-a1:color(display-p3 .675 .024 .024/.012);--red-a2:color(display-p3 .863 .024 .024/.028);--red-a3:color(display-p3 .792 .008 .008/.075);--red-a4:color(display-p3 1 .008 .008/.134);--red-a5:color(display-p3 .918 .008 .008/.189);--red-a6:color(display-p3 .831 .02 .004/.251);--red-a7:color(display-p3 .741 .016 .004/.33);--red-a8:color(display-p3 .698 .012 .004/.428);--red-a9:color(display-p3 .749 .008 0/.675);--red-a10:color(display-p3 .714 .012 0/.714);--red-a11:color(display-p3 .744 .234 .222);--red-a12:color(display-p3 .36 .115 .143)}}}.dark,.dark-theme{--red-a1:#f4121209;--red-a2:#f22f3e11;--red-a3:#ff173f2d;--red-a4:#fe0a3b44;--red-a5:#ff204756;--red-a6:#ff3e5668;--red-a7:#ff536184;--red-a8:#ff5d61b0;--red-a9:#fe4e54e4;--red-a10:#ff6465eb;--red-a11:#ff9592;--red-a12:#ffd1d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--red-a1:color(display-p3 .984 .071 .071/.03);--red-a2:color(display-p3 .996 .282 .282/.055);--red-a3:color(display-p3 1 .169 .271/.156);--red-a4:color(display-p3 1 .118 .267/.236);--red-a5:color(display-p3 1 .212 .314/.303);--red-a6:color(display-p3 1 .318 .38/.374);--red-a7:color(display-p3 1 .4 .424/.475);--red-a8:color(display-p3 1 .431 .431/.635);--red-a9:color(display-p3 1 .388 .384/.82);--red-a10:color(display-p3 1 .463 .447/.853);--red-a11:color(display-p3 1 .57 .55);--red-a12:color(display-p3 .971 .826 .852)}}}:root,.light,.light-theme{--ruby-1:#fffcfd;--ruby-2:#fff7f8;--ruby-3:#feeaed;--ruby-4:#ffdce1;--ruby-5:#ffced6;--ruby-6:#f8bfc8;--ruby-7:#efacb8;--ruby-8:#e592a3;--ruby-9:#e54666;--ruby-10:#dc3b5d;--ruby-11:#ca244d;--ruby-12:#64172b}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--ruby-1:color(display-p3 .998 .989 .992);--ruby-2:color(display-p3 .995 .971 .974);--ruby-3:color(display-p3 .983 .92 .928);--ruby-4:color(display-p3 .987 .869 .885);--ruby-5:color(display-p3 .968 .817 .839);--ruby-6:color(display-p3 .937 .758 .786);--ruby-7:color(display-p3 .897 .685 .721);--ruby-8:color(display-p3 .851 .588 .639);--ruby-9:color(display-p3 .83 .323 .408);--ruby-10:color(display-p3 .795 .286 .375);--ruby-11:color(display-p3 .728 .211 .311);--ruby-12:color(display-p3 .36 .115 .171)}}}.dark,.dark-theme{--ruby-1:#191113;--ruby-2:#1e1517;--ruby-3:#3a141e;--ruby-4:#4e1325;--ruby-5:#5e1a2e;--ruby-6:#6f2539;--ruby-7:#883447;--ruby-8:#b3445a;--ruby-9:#e54666;--ruby-10:#ec5a72;--ruby-11:#ff949d;--ruby-12:#fed2e1}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--ruby-1:color(display-p3 .093 .068 .074);--ruby-2:color(display-p3 .113 .083 .089);--ruby-3:color(display-p3 .208 .088 .117);--ruby-4:color(display-p3 .279 .092 .147);--ruby-5:color(display-p3 .337 .12 .18);--ruby-6:color(display-p3 .401 .166 .223);--ruby-7:color(display-p3 .495 .224 .281);--ruby-8:color(display-p3 .652 .295 .359);--ruby-9:color(display-p3 .83 .323 .408);--ruby-10:color(display-p3 .857 .392 .455);--ruby-11:color(display-p3 1 .57 .59);--ruby-12:color(display-p3 .968 .83 .88)}}}:root,.light,.light-theme{--ruby-a1:#ff005503;--ruby-a2:#ff002008;--ruby-a3:#f3002515;--ruby-a4:#ff002523;--ruby-a5:#ff002a31;--ruby-a6:#e4002440;--ruby-a7:#ce002553;--ruby-a8:#c300286d;--ruby-a9:#db002cb9;--ruby-a10:#d2002cc4;--ruby-a11:#c10030db;--ruby-a12:#550016e8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--ruby-a1:color(display-p3 .675 .024 .349/.012);--ruby-a2:color(display-p3 .863 .024 .024/.028);--ruby-a3:color(display-p3 .804 .008 .11/.079);--ruby-a4:color(display-p3 .91 .008 .125/.13);--ruby-a5:color(display-p3 .831 .004 .133/.185);--ruby-a6:color(display-p3 .745 .004 .118/.244);--ruby-a7:color(display-p3 .678 .004 .114/.314);--ruby-a8:color(display-p3 .639 .004 .125/.412);--ruby-a9:color(display-p3 .753 0 .129/.679);--ruby-a10:color(display-p3 .714 0 .125/.714);--ruby-a11:color(display-p3 .728 .211 .311);--ruby-a12:color(display-p3 .36 .115 .171)}}}.dark,.dark-theme{--ruby-a1:#f4124a09;--ruby-a2:#fe5a7f0e;--ruby-a3:#ff235d2c;--ruby-a4:#fd195e42;--ruby-a5:#fe2d6b53;--ruby-a6:#ff447665;--ruby-a7:#ff577d80;--ruby-a8:#ff5c7cae;--ruby-a9:#fe4c70e4;--ruby-a10:#ff617beb;--ruby-a11:#ff949d;--ruby-a12:#ffd3e2fe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--ruby-a1:color(display-p3 .984 .071 .329/.03);--ruby-a2:color(display-p3 .992 .376 .529/.051);--ruby-a3:color(display-p3 .996 .196 .404/.152);--ruby-a4:color(display-p3 1 .173 .416/.227);--ruby-a5:color(display-p3 1 .259 .459/.29);--ruby-a6:color(display-p3 1 .341 .506/.358);--ruby-a7:color(display-p3 1 .412 .541/.458);--ruby-a8:color(display-p3 1 .431 .537/.627);--ruby-a9:color(display-p3 1 .376 .482/.82);--ruby-a10:color(display-p3 1 .447 .522/.849);--ruby-a11:color(display-p3 1 .57 .59);--ruby-a12:color(display-p3 .968 .83 .88)}}}:root,.light,.light-theme{--crimson-1:#fffcfd;--crimson-2:#fef7f9;--crimson-3:#ffe9f0;--crimson-4:#fedce7;--crimson-5:#facedd;--crimson-6:#f3bed1;--crimson-7:#eaacc3;--crimson-8:#e093b2;--crimson-9:#e93d82;--crimson-10:#df3478;--crimson-11:#cb1d63;--crimson-12:#621639}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--crimson-1:color(display-p3 .998 .989 .992);--crimson-2:color(display-p3 .991 .969 .976);--crimson-3:color(display-p3 .987 .917 .941);--crimson-4:color(display-p3 .975 .866 .904);--crimson-5:color(display-p3 .953 .813 .864);--crimson-6:color(display-p3 .921 .755 .817);--crimson-7:color(display-p3 .88 .683 .761);--crimson-8:color(display-p3 .834 .592 .694);--crimson-9:color(display-p3 .843 .298 .507);--crimson-10:color(display-p3 .807 .266 .468);--crimson-11:color(display-p3 .731 .195 .388);--crimson-12:color(display-p3 .352 .111 .221)}}}.dark,.dark-theme{--crimson-1:#191114;--crimson-2:#201318;--crimson-3:#381525;--crimson-4:#4d122f;--crimson-5:#5c1839;--crimson-6:#6d2545;--crimson-7:#873356;--crimson-8:#b0436e;--crimson-9:#e93d82;--crimson-10:#ee518a;--crimson-11:#ff92ad;--crimson-12:#fdd3e8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--crimson-1:color(display-p3 .093 .068 .078);--crimson-2:color(display-p3 .117 .078 .095);--crimson-3:color(display-p3 .203 .091 .143);--crimson-4:color(display-p3 .277 .087 .182);--crimson-5:color(display-p3 .332 .115 .22);--crimson-6:color(display-p3 .394 .162 .268);--crimson-7:color(display-p3 .489 .222 .336);--crimson-8:color(display-p3 .638 .289 .429);--crimson-9:color(display-p3 .843 .298 .507);--crimson-10:color(display-p3 .864 .364 .539);--crimson-11:color(display-p3 1 .56 .66);--crimson-12:color(display-p3 .966 .834 .906)}}}:root,.light,.light-theme{--crimson-a1:#ff005503;--crimson-a2:#e0004008;--crimson-a3:#ff005216;--crimson-a4:#f8005123;--crimson-a5:#e5004f31;--crimson-a6:#d0004b41;--crimson-a7:#bf004753;--crimson-a8:#b6004a6c;--crimson-a9:#e2005bc2;--crimson-a10:#d70056cb;--crimson-a11:#c4004fe2;--crimson-a12:#530026e9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--crimson-a1:color(display-p3 .675 .024 .349/.012);--crimson-a2:color(display-p3 .757 .02 .267/.032);--crimson-a3:color(display-p3 .859 .008 .294/.083);--crimson-a4:color(display-p3 .827 .008 .298/.134);--crimson-a5:color(display-p3 .753 .008 .275/.189);--crimson-a6:color(display-p3 .682 .004 .247/.244);--crimson-a7:color(display-p3 .62 .004 .251/.318);--crimson-a8:color(display-p3 .6 .004 .251/.408);--crimson-a9:color(display-p3 .776 0 .298/.702);--crimson-a10:color(display-p3 .737 0 .275/.734);--crimson-a11:color(display-p3 .731 .195 .388);--crimson-a12:color(display-p3 .352 .111 .221)}}}.dark,.dark-theme{--crimson-a1:#f4126709;--crimson-a2:#f22f7a11;--crimson-a3:#fe2a8b2a;--crimson-a4:#fd158741;--crimson-a5:#fd278f51;--crimson-a6:#fe459763;--crimson-a7:#fd559b7f;--crimson-a8:#fe5b9bab;--crimson-a9:#fe418de8;--crimson-a10:#ff5693ed;--crimson-a11:#ff92ad;--crimson-a12:#ffd5eafd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--crimson-a1:color(display-p3 .984 .071 .463/.03);--crimson-a2:color(display-p3 .996 .282 .569/.055);--crimson-a3:color(display-p3 .996 .227 .573/.148);--crimson-a4:color(display-p3 1 .157 .569/.227);--crimson-a5:color(display-p3 1 .231 .604/.286);--crimson-a6:color(display-p3 1 .337 .643/.349);--crimson-a7:color(display-p3 1 .416 .663/.454);--crimson-a8:color(display-p3 .996 .427 .651/.614);--crimson-a9:color(display-p3 1 .345 .596/.832);--crimson-a10:color(display-p3 1 .42 .62/.853);--crimson-a11:color(display-p3 1 .56 .66);--crimson-a12:color(display-p3 .966 .834 .906)}}}:root,.light,.light-theme{--pink-1:#fffcfe;--pink-2:#fef7fb;--pink-3:#fee9f5;--pink-4:#fbdcef;--pink-5:#f6cee7;--pink-6:#efbfdd;--pink-7:#e7acd0;--pink-8:#dd93c2;--pink-9:#d6409f;--pink-10:#cf3897;--pink-11:#c2298a;--pink-12:#651249}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--pink-1:color(display-p3 .998 .989 .996);--pink-2:color(display-p3 .992 .97 .985);--pink-3:color(display-p3 .981 .917 .96);--pink-4:color(display-p3 .963 .867 .932);--pink-5:color(display-p3 .939 .815 .899);--pink-6:color(display-p3 .907 .756 .859);--pink-7:color(display-p3 .869 .683 .81);--pink-8:color(display-p3 .825 .59 .751);--pink-9:color(display-p3 .775 .297 .61);--pink-10:color(display-p3 .748 .27 .581);--pink-11:color(display-p3 .698 .219 .528);--pink-12:color(display-p3 .363 .101 .279)}}}.dark,.dark-theme{--pink-1:#191117;--pink-2:#21121d;--pink-3:#37172f;--pink-4:#4b143d;--pink-5:#591c47;--pink-6:#692955;--pink-7:#833869;--pink-8:#a84885;--pink-9:#d6409f;--pink-10:#de51a8;--pink-11:#ff8dcc;--pink-12:#fdd1ea}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--pink-1:color(display-p3 .093 .068 .089);--pink-2:color(display-p3 .121 .073 .11);--pink-3:color(display-p3 .198 .098 .179);--pink-4:color(display-p3 .271 .095 .231);--pink-5:color(display-p3 .32 .127 .273);--pink-6:color(display-p3 .382 .177 .326);--pink-7:color(display-p3 .477 .238 .405);--pink-8:color(display-p3 .612 .304 .51);--pink-9:color(display-p3 .775 .297 .61);--pink-10:color(display-p3 .808 .356 .645);--pink-11:color(display-p3 1 .535 .78);--pink-12:color(display-p3 .964 .826 .912)}}}:root,.light,.light-theme{--pink-a1:#ff00aa03;--pink-a2:#e0008008;--pink-a3:#f4008c16;--pink-a4:#e2008b23;--pink-a5:#d1008331;--pink-a6:#c0007840;--pink-a7:#b6006f53;--pink-a8:#af006f6c;--pink-a9:#c8007fbf;--pink-a10:#c2007ac7;--pink-a11:#b60074d6;--pink-a12:#59003bed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--pink-a1:color(display-p3 .675 .024 .675/.012);--pink-a2:color(display-p3 .757 .02 .51/.032);--pink-a3:color(display-p3 .765 .008 .529/.083);--pink-a4:color(display-p3 .737 .008 .506/.134);--pink-a5:color(display-p3 .663 .004 .451/.185);--pink-a6:color(display-p3 .616 .004 .424/.244);--pink-a7:color(display-p3 .596 .004 .412/.318);--pink-a8:color(display-p3 .573 .004 .404/.412);--pink-a9:color(display-p3 .682 0 .447/.702);--pink-a10:color(display-p3 .655 0 .424/.73);--pink-a11:color(display-p3 .698 .219 .528);--pink-a12:color(display-p3 .363 .101 .279)}}}.dark,.dark-theme{--pink-a1:#f412bc09;--pink-a2:#f420bb12;--pink-a3:#fe37cc29;--pink-a4:#fc1ec43f;--pink-a5:#fd35c24e;--pink-a6:#fd51c75f;--pink-a7:#fd62c87b;--pink-a8:#ff68c8a2;--pink-a9:#fe49bcd4;--pink-a10:#ff5cc0dc;--pink-a11:#ff8dcc;--pink-a12:#ffd3ecfd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--pink-a1:color(display-p3 .984 .071 .855/.03);--pink-a2:color(display-p3 1 .2 .8/.059);--pink-a3:color(display-p3 1 .294 .886/.139);--pink-a4:color(display-p3 1 .192 .82/.219);--pink-a5:color(display-p3 1 .282 .827/.274);--pink-a6:color(display-p3 1 .396 .835/.337);--pink-a7:color(display-p3 1 .459 .831/.442);--pink-a8:color(display-p3 1 .478 .827/.585);--pink-a9:color(display-p3 1 .373 .784/.761);--pink-a10:color(display-p3 1 .435 .792/.795);--pink-a11:color(display-p3 1 .535 .78);--pink-a12:color(display-p3 .964 .826 .912)}}}:root,.light,.light-theme{--plum-1:#fefcff;--plum-2:#fdf7fd;--plum-3:#fbebfb;--plum-4:#f7def8;--plum-5:#f2d1f3;--plum-6:#e9c2ec;--plum-7:#deade3;--plum-8:#cf91d8;--plum-9:#ab4aba;--plum-10:#a144af;--plum-11:#953ea3;--plum-12:#53195d}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--plum-1:color(display-p3 .995 .988 .999);--plum-2:color(display-p3 .988 .971 .99);--plum-3:color(display-p3 .973 .923 .98);--plum-4:color(display-p3 .953 .875 .966);--plum-5:color(display-p3 .926 .825 .945);--plum-6:color(display-p3 .89 .765 .916);--plum-7:color(display-p3 .84 .686 .877);--plum-8:color(display-p3 .775 .58 .832);--plum-9:color(display-p3 .624 .313 .708);--plum-10:color(display-p3 .587 .29 .667);--plum-11:color(display-p3 .543 .263 .619);--plum-12:color(display-p3 .299 .114 .352)}}}.dark,.dark-theme{--plum-1:#181118;--plum-2:#201320;--plum-3:#351a35;--plum-4:#451d47;--plum-5:#512454;--plum-6:#5e3061;--plum-7:#734079;--plum-8:#92549c;--plum-9:#ab4aba;--plum-10:#b658c4;--plum-11:#e796f3;--plum-12:#f4d4f4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--plum-1:color(display-p3 .09 .068 .092);--plum-2:color(display-p3 .118 .077 .121);--plum-3:color(display-p3 .192 .105 .202);--plum-4:color(display-p3 .25 .121 .271);--plum-5:color(display-p3 .293 .152 .319);--plum-6:color(display-p3 .343 .198 .372);--plum-7:color(display-p3 .424 .262 .461);--plum-8:color(display-p3 .54 .341 .595);--plum-9:color(display-p3 .624 .313 .708);--plum-10:color(display-p3 .666 .365 .748);--plum-11:color(display-p3 .86 .602 .933);--plum-12:color(display-p3 .936 .836 .949)}}}:root,.light,.light-theme{--plum-a1:#aa00ff03;--plum-a2:#c000c008;--plum-a3:#cc00cc14;--plum-a4:#c200c921;--plum-a5:#b700bd2e;--plum-a6:#a400b03d;--plum-a7:#9900a852;--plum-a8:#9000a56e;--plum-a9:#89009eb5;--plum-a10:#7f0092bb;--plum-a11:#730086c1;--plum-a12:#40004be6}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--plum-a1:color(display-p3 .675 .024 1/.012);--plum-a2:color(display-p3 .58 .024 .58/.028);--plum-a3:color(display-p3 .655 .008 .753/.079);--plum-a4:color(display-p3 .627 .008 .722/.126);--plum-a5:color(display-p3 .58 .004 .69/.177);--plum-a6:color(display-p3 .537 .004 .655/.236);--plum-a7:color(display-p3 .49 .004 .616/.314);--plum-a8:color(display-p3 .471 .004 .6/.42);--plum-a9:color(display-p3 .451 0 .576/.687);--plum-a10:color(display-p3 .42 0 .529/.71);--plum-a11:color(display-p3 .543 .263 .619);--plum-a12:color(display-p3 .299 .114 .352)}}}.dark,.dark-theme{--plum-a1:#f112f108;--plum-a2:#f22ff211;--plum-a3:#fd4cfd27;--plum-a4:#f646ff3a;--plum-a5:#f455ff48;--plum-a6:#f66dff56;--plum-a7:#f07cfd70;--plum-a8:#ee84ff95;--plum-a9:#e961feb6;--plum-a10:#ed70ffc0;--plum-a11:#f19cfef3;--plum-a12:#feddfef4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--plum-a1:color(display-p3 .973 .071 .973/.026);--plum-a2:color(display-p3 .933 .267 1/.059);--plum-a3:color(display-p3 .918 .333 .996/.148);--plum-a4:color(display-p3 .91 .318 1/.219);--plum-a5:color(display-p3 .914 .388 1/.269);--plum-a6:color(display-p3 .906 .463 1/.328);--plum-a7:color(display-p3 .906 .529 1/.425);--plum-a8:color(display-p3 .906 .553 1/.568);--plum-a9:color(display-p3 .875 .427 1/.69);--plum-a10:color(display-p3 .886 .471 .996/.732);--plum-a11:color(display-p3 .86 .602 .933);--plum-a12:color(display-p3 .936 .836 .949)}}}:root,.light,.light-theme{--purple-1:#fefcfe;--purple-2:#fbf7fe;--purple-3:#f7edfe;--purple-4:#f2e2fc;--purple-5:#ead5f9;--purple-6:#e0c4f4;--purple-7:#d1afec;--purple-8:#be93e4;--purple-9:#8e4ec6;--purple-10:#8347b9;--purple-11:#8145b5;--purple-12:#402060}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--purple-1:color(display-p3 .995 .988 .996);--purple-2:color(display-p3 .983 .971 .993);--purple-3:color(display-p3 .963 .931 .989);--purple-4:color(display-p3 .937 .888 .981);--purple-5:color(display-p3 .904 .837 .966);--purple-6:color(display-p3 .86 .774 .942);--purple-7:color(display-p3 .799 .69 .91);--purple-8:color(display-p3 .719 .583 .874);--purple-9:color(display-p3 .523 .318 .751);--purple-10:color(display-p3 .483 .289 .7);--purple-11:color(display-p3 .473 .281 .687);--purple-12:color(display-p3 .234 .132 .363)}}}.dark,.dark-theme{--purple-1:#18111b;--purple-2:#1e1523;--purple-3:#301c3b;--purple-4:#3d224e;--purple-5:#48295c;--purple-6:#54346b;--purple-7:#664282;--purple-8:#8457aa;--purple-9:#8e4ec6;--purple-10:#9a5cd0;--purple-11:#d19dff;--purple-12:#ecd9fa}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--purple-1:color(display-p3 .09 .068 .103);--purple-2:color(display-p3 .113 .082 .134);--purple-3:color(display-p3 .175 .112 .224);--purple-4:color(display-p3 .224 .137 .297);--purple-5:color(display-p3 .264 .167 .349);--purple-6:color(display-p3 .311 .208 .406);--purple-7:color(display-p3 .381 .266 .496);--purple-8:color(display-p3 .49 .349 .649);--purple-9:color(display-p3 .523 .318 .751);--purple-10:color(display-p3 .57 .373 .791);--purple-11:color(display-p3 .8 .62 1);--purple-12:color(display-p3 .913 .854 .971)}}}:root,.light,.light-theme{--purple-a1:#aa00aa03;--purple-a2:#8000e008;--purple-a3:#8e00f112;--purple-a4:#8d00e51d;--purple-a5:#8000db2a;--purple-a6:#7a01d03b;--purple-a7:#6d00c350;--purple-a8:#6600c06c;--purple-a9:#5c00adb1;--purple-a10:#53009eb8;--purple-a11:#52009aba;--purple-a12:#250049df}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--purple-a1:color(display-p3 .675 .024 .675/.012);--purple-a2:color(display-p3 .443 .024 .722/.028);--purple-a3:color(display-p3 .506 .008 .835/.071);--purple-a4:color(display-p3 .451 .004 .831/.114);--purple-a5:color(display-p3 .431 .004 .788/.165);--purple-a6:color(display-p3 .384 .004 .745/.228);--purple-a7:color(display-p3 .357 .004 .71/.31);--purple-a8:color(display-p3 .322 .004 .702/.416);--purple-a9:color(display-p3 .298 0 .639/.683);--purple-a10:color(display-p3 .271 0 .58/.71);--purple-a11:color(display-p3 .473 .281 .687);--purple-a12:color(display-p3 .234 .132 .363)}}}.dark,.dark-theme{--purple-a1:#b412f90b;--purple-a2:#b744f714;--purple-a3:#c150ff2d;--purple-a4:#bb53fd42;--purple-a5:#be5cfd51;--purple-a6:#c16dfd61;--purple-a7:#c378fd7a;--purple-a8:#c47effa4;--purple-a9:#b661ffc2;--purple-a10:#bc6fffcd;--purple-a11:#d19dff;--purple-a12:#f1ddfffa}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--purple-a1:color(display-p3 .686 .071 .996/.038);--purple-a2:color(display-p3 .722 .286 .996/.072);--purple-a3:color(display-p3 .718 .349 .996/.169);--purple-a4:color(display-p3 .702 .353 1/.248);--purple-a5:color(display-p3 .718 .404 1/.303);--purple-a6:color(display-p3 .733 .455 1/.366);--purple-a7:color(display-p3 .753 .506 1/.458);--purple-a8:color(display-p3 .749 .522 1/.622);--purple-a9:color(display-p3 .686 .408 1/.736);--purple-a10:color(display-p3 .71 .459 1/.778);--purple-a11:color(display-p3 .8 .62 1);--purple-a12:color(display-p3 .913 .854 .971)}}}:root,.light,.light-theme{--violet-1:#fdfcfe;--violet-2:#faf8ff;--violet-3:#f4f0fe;--violet-4:#ebe4ff;--violet-5:#e1d9ff;--violet-6:#d4cafe;--violet-7:#c2b5f5;--violet-8:#aa99ec;--violet-9:#6e56cf;--violet-10:#654dc4;--violet-11:#6550b9;--violet-12:#2f265f}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--violet-1:color(display-p3 .991 .988 .995);--violet-2:color(display-p3 .978 .974 .998);--violet-3:color(display-p3 .953 .943 .993);--violet-4:color(display-p3 .916 .897 1);--violet-5:color(display-p3 .876 .851 1);--violet-6:color(display-p3 .825 .793 .981);--violet-7:color(display-p3 .752 .712 .943);--violet-8:color(display-p3 .654 .602 .902);--violet-9:color(display-p3 .417 .341 .784);--violet-10:color(display-p3 .381 .306 .741);--violet-11:color(display-p3 .383 .317 .702);--violet-12:color(display-p3 .179 .15 .359)}}}.dark,.dark-theme{--violet-1:#14121f;--violet-2:#1b1525;--violet-3:#291f43;--violet-4:#33255b;--violet-5:#3c2e69;--violet-6:#473876;--violet-7:#56468b;--violet-8:#6958ad;--violet-9:#6e56cf;--violet-10:#7d66d9;--violet-11:#baa7ff;--violet-12:#e2ddfe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--violet-1:color(display-p3 .077 .071 .118);--violet-2:color(display-p3 .101 .084 .141);--violet-3:color(display-p3 .154 .123 .256);--violet-4:color(display-p3 .191 .148 .345);--violet-5:color(display-p3 .226 .182 .396);--violet-6:color(display-p3 .269 .223 .449);--violet-7:color(display-p3 .326 .277 .53);--violet-8:color(display-p3 .399 .346 .656);--violet-9:color(display-p3 .417 .341 .784);--violet-10:color(display-p3 .477 .402 .823);--violet-11:color(display-p3 .72 .65 1);--violet-12:color(display-p3 .883 .867 .986)}}}:root,.light,.light-theme{--violet-a1:#5500aa03;--violet-a2:#4900ff07;--violet-a3:#4400ee0f;--violet-a4:#4300ff1b;--violet-a5:#3600ff26;--violet-a6:#3100fb35;--violet-a7:#2d01dd4a;--violet-a8:#2b00d066;--violet-a9:#2400b7a9;--violet-a10:#2300abb2;--violet-a11:#1f0099af;--violet-a12:#0b0043d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--violet-a1:color(display-p3 .349 .024 .675/.012);--violet-a2:color(display-p3 .161 .024 .863/.028);--violet-a3:color(display-p3 .204 .004 .871/.059);--violet-a4:color(display-p3 .196 .004 1/.102);--violet-a5:color(display-p3 .165 .008 1/.15);--violet-a6:color(display-p3 .153 .004 .906/.208);--violet-a7:color(display-p3 .141 .004 .796/.287);--violet-a8:color(display-p3 .133 .004 .753/.397);--violet-a9:color(display-p3 .114 0 .675/.659);--violet-a10:color(display-p3 .11 0 .627/.695);--violet-a11:color(display-p3 .383 .317 .702);--violet-a12:color(display-p3 .179 .15 .359)}}}.dark,.dark-theme{--violet-a1:#4422ff0f;--violet-a2:#853ff916;--violet-a3:#8354fe36;--violet-a4:#7d51fd50;--violet-a5:#845ffd5f;--violet-a6:#8f6cfd6d;--violet-a7:#9879ff83;--violet-a8:#977dfea8;--violet-a9:#8668ffcc;--violet-a10:#9176fed7;--violet-a11:#baa7ff;--violet-a12:#e3defffe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--violet-a1:color(display-p3 .282 .141 .996/.055);--violet-a2:color(display-p3 .51 .263 1/.08);--violet-a3:color(display-p3 .494 .337 .996/.202);--violet-a4:color(display-p3 .49 .345 1/.299);--violet-a5:color(display-p3 .525 .392 1/.353);--violet-a6:color(display-p3 .569 .455 1/.408);--violet-a7:color(display-p3 .588 .494 1/.496);--violet-a8:color(display-p3 .596 .51 1/.631);--violet-a9:color(display-p3 .522 .424 1/.769);--violet-a10:color(display-p3 .576 .482 1/.811);--violet-a11:color(display-p3 .72 .65 1);--violet-a12:color(display-p3 .883 .867 .986)}}}:root,.light,.light-theme{--iris-1:#fdfdff;--iris-2:#f8f8ff;--iris-3:#f0f1fe;--iris-4:#e6e7ff;--iris-5:#dadcff;--iris-6:#cbcdff;--iris-7:#b8baf8;--iris-8:#9b9ef0;--iris-9:#5b5bd6;--iris-10:#5151cd;--iris-11:#5753c6;--iris-12:#272962}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--iris-1:color(display-p3 .992 .992 .999);--iris-2:color(display-p3 .972 .973 .998);--iris-3:color(display-p3 .943 .945 .992);--iris-4:color(display-p3 .902 .906 1);--iris-5:color(display-p3 .857 .861 1);--iris-6:color(display-p3 .799 .805 .987);--iris-7:color(display-p3 .721 .727 .955);--iris-8:color(display-p3 .61 .619 .918);--iris-9:color(display-p3 .357 .357 .81);--iris-10:color(display-p3 .318 .318 .774);--iris-11:color(display-p3 .337 .326 .748);--iris-12:color(display-p3 .154 .161 .371)}}}.dark,.dark-theme{--iris-1:#13131e;--iris-2:#171625;--iris-3:#202248;--iris-4:#262a65;--iris-5:#303374;--iris-6:#3d3e82;--iris-7:#4a4a95;--iris-8:#5958b1;--iris-9:#5b5bd6;--iris-10:#6e6ade;--iris-11:#b1a9ff;--iris-12:#e0dffe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--iris-1:color(display-p3 .075 .075 .114);--iris-2:color(display-p3 .089 .086 .14);--iris-3:color(display-p3 .128 .134 .272);--iris-4:color(display-p3 .153 .165 .382);--iris-5:color(display-p3 .192 .201 .44);--iris-6:color(display-p3 .239 .241 .491);--iris-7:color(display-p3 .291 .289 .565);--iris-8:color(display-p3 .35 .345 .673);--iris-9:color(display-p3 .357 .357 .81);--iris-10:color(display-p3 .428 .416 .843);--iris-11:color(display-p3 .685 .662 1);--iris-12:color(display-p3 .878 .875 .986)}}}:root,.light,.light-theme{--iris-a1:#0000ff02;--iris-a2:#0000ff07;--iris-a3:#0011ee0f;--iris-a4:#000bff19;--iris-a5:#000eff25;--iris-a6:#000aff34;--iris-a7:#0008e647;--iris-a8:#0008d964;--iris-a9:#0000c0a4;--iris-a10:#0000b6ae;--iris-a11:#0600abac;--iris-a12:#000246d8}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--iris-a1:color(display-p3 .02 .02 1/.008);--iris-a2:color(display-p3 .024 .024 .863/.028);--iris-a3:color(display-p3 .004 .071 .871/.059);--iris-a4:color(display-p3 .012 .051 1/.099);--iris-a5:color(display-p3 .008 .035 1/.142);--iris-a6:color(display-p3 0 .02 .941/.2);--iris-a7:color(display-p3 .004 .02 .847/.279);--iris-a8:color(display-p3 .004 .024 .788/.389);--iris-a9:color(display-p3 0 0 .706/.644);--iris-a10:color(display-p3 0 0 .667/.683);--iris-a11:color(display-p3 .337 .326 .748);--iris-a12:color(display-p3 .154 .161 .371)}}}.dark,.dark-theme{--iris-a1:#3636fe0e;--iris-a2:#564bf916;--iris-a3:#525bff3b;--iris-a4:#4d58ff5a;--iris-a5:#5b62fd6b;--iris-a6:#6d6ffd7a;--iris-a7:#7777fe8e;--iris-a8:#7b7afeac;--iris-a9:#6a6afed4;--iris-a10:#7d79ffdc;--iris-a11:#b1a9ff;--iris-a12:#e1e0fffe}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--iris-a1:color(display-p3 .224 .224 .992/.051);--iris-a2:color(display-p3 .361 .314 1/.08);--iris-a3:color(display-p3 .357 .373 1/.219);--iris-a4:color(display-p3 .325 .361 1/.337);--iris-a5:color(display-p3 .38 .4 1/.4);--iris-a6:color(display-p3 .447 .447 1/.454);--iris-a7:color(display-p3 .486 .486 1/.534);--iris-a8:color(display-p3 .502 .494 1/.652);--iris-a9:color(display-p3 .431 .431 1/.799);--iris-a10:color(display-p3 .502 .486 1/.832);--iris-a11:color(display-p3 .685 .662 1);--iris-a12:color(display-p3 .878 .875 .986)}}}:root,.light,.light-theme{--indigo-1:#fdfdfe;--indigo-2:#f7f9ff;--indigo-3:#edf2fe;--indigo-4:#e1e9ff;--indigo-5:#d2deff;--indigo-6:#c1d0ff;--indigo-7:#abbdf9;--indigo-8:#8da4ef;--indigo-9:#3e63dd;--indigo-10:#3358d4;--indigo-11:#3a5bc7;--indigo-12:#1f2d5c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--indigo-1:color(display-p3 .992 .992 .996);--indigo-2:color(display-p3 .971 .977 .998);--indigo-3:color(display-p3 .933 .948 .992);--indigo-4:color(display-p3 .885 .914 1);--indigo-5:color(display-p3 .831 .87 1);--indigo-6:color(display-p3 .767 .814 .995);--indigo-7:color(display-p3 .685 .74 .957);--indigo-8:color(display-p3 .569 .639 .916);--indigo-9:color(display-p3 .276 .384 .837);--indigo-10:color(display-p3 .234 .343 .801);--indigo-11:color(display-p3 .256 .354 .755);--indigo-12:color(display-p3 .133 .175 .348)}}}.dark,.dark-theme{--indigo-1:#11131f;--indigo-2:#141726;--indigo-3:#182449;--indigo-4:#1d2e62;--indigo-5:#253974;--indigo-6:#304384;--indigo-7:#3a4f97;--indigo-8:#435db1;--indigo-9:#3e63dd;--indigo-10:#5472e4;--indigo-11:#9eb1ff;--indigo-12:#d6e1ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--indigo-1:color(display-p3 .068 .074 .118);--indigo-2:color(display-p3 .081 .089 .144);--indigo-3:color(display-p3 .105 .141 .275);--indigo-4:color(display-p3 .129 .18 .369);--indigo-5:color(display-p3 .163 .22 .439);--indigo-6:color(display-p3 .203 .262 .5);--indigo-7:color(display-p3 .245 .309 .575);--indigo-8:color(display-p3 .285 .362 .674);--indigo-9:color(display-p3 .276 .384 .837);--indigo-10:color(display-p3 .354 .445 .866);--indigo-11:color(display-p3 .63 .69 1);--indigo-12:color(display-p3 .848 .881 .99)}}}:root,.light,.light-theme{--indigo-a1:#00008002;--indigo-a2:#0040ff08;--indigo-a3:#0047f112;--indigo-a4:#0044ff1e;--indigo-a5:#0044ff2d;--indigo-a6:#003eff3e;--indigo-a7:#0037ed54;--indigo-a8:#0034dc72;--indigo-a9:#0031d2c1;--indigo-a10:#002ec9cc;--indigo-a11:#002bb7c5;--indigo-a12:#001046e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--indigo-a1:color(display-p3 .02 .02 .51/.008);--indigo-a2:color(display-p3 .024 .161 .863/.028);--indigo-a3:color(display-p3 .008 .239 .886/.067);--indigo-a4:color(display-p3 .004 .247 1/.114);--indigo-a5:color(display-p3 .004 .235 1/.169);--indigo-a6:color(display-p3 .004 .208 .984/.232);--indigo-a7:color(display-p3 .004 .176 .863/.314);--indigo-a8:color(display-p3 .004 .165 .812/.432);--indigo-a9:color(display-p3 0 .153 .773/.726);--indigo-a10:color(display-p3 0 .137 .737/.765);--indigo-a11:color(display-p3 .256 .354 .755);--indigo-a12:color(display-p3 .133 .175 .348)}}}.dark,.dark-theme{--indigo-a1:#1133ff0f;--indigo-a2:#3354fa17;--indigo-a3:#2f62ff3c;--indigo-a4:#3566ff57;--indigo-a5:#4171fd6b;--indigo-a6:#5178fd7c;--indigo-a7:#5a7fff90;--indigo-a8:#5b81feac;--indigo-a9:#4671ffdb;--indigo-a10:#5c7efee3;--indigo-a11:#9eb1ff;--indigo-a12:#d6e1ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--indigo-a1:color(display-p3 .071 .212 .996/.055);--indigo-a2:color(display-p3 .251 .345 .988/.085);--indigo-a3:color(display-p3 .243 .404 1/.223);--indigo-a4:color(display-p3 .263 .42 1/.324);--indigo-a5:color(display-p3 .314 .451 1/.4);--indigo-a6:color(display-p3 .361 .49 1/.467);--indigo-a7:color(display-p3 .388 .51 1/.547);--indigo-a8:color(display-p3 .404 .518 1/.652);--indigo-a9:color(display-p3 .318 .451 1/.824);--indigo-a10:color(display-p3 .404 .506 1/.858);--indigo-a11:color(display-p3 .63 .69 1);--indigo-a12:color(display-p3 .848 .881 .99)}}}:root,.light,.light-theme{--blue-1:#fbfdff;--blue-2:#f4faff;--blue-3:#e6f4fe;--blue-4:#d5efff;--blue-5:#c2e5ff;--blue-6:#acd8fc;--blue-7:#8ec8f6;--blue-8:#5eb1ef;--blue-9:#0090ff;--blue-10:#0588f0;--blue-11:#0d74ce;--blue-12:#113264}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--blue-1:color(display-p3 .986 .992 .999);--blue-2:color(display-p3 .96 .979 .998);--blue-3:color(display-p3 .912 .956 .991);--blue-4:color(display-p3 .853 .932 1);--blue-5:color(display-p3 .788 .894 .998);--blue-6:color(display-p3 .709 .843 .976);--blue-7:color(display-p3 .606 .777 .947);--blue-8:color(display-p3 .451 .688 .917);--blue-9:color(display-p3 .247 .556 .969);--blue-10:color(display-p3 .234 .523 .912);--blue-11:color(display-p3 .15 .44 .84);--blue-12:color(display-p3 .102 .193 .379)}}}.dark,.dark-theme{--blue-1:#0d1520;--blue-2:#111927;--blue-3:#0d2847;--blue-4:#003362;--blue-5:#004074;--blue-6:#104d87;--blue-7:#205d9e;--blue-8:#2870bd;--blue-9:#0090ff;--blue-10:#3b9eff;--blue-11:#70b8ff;--blue-12:#c2e6ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--blue-1:color(display-p3 .057 .081 .122);--blue-2:color(display-p3 .072 .098 .147);--blue-3:color(display-p3 .078 .154 .27);--blue-4:color(display-p3 .033 .197 .37);--blue-5:color(display-p3 .08 .245 .441);--blue-6:color(display-p3 .14 .298 .511);--blue-7:color(display-p3 .195 .361 .6);--blue-8:color(display-p3 .239 .434 .72);--blue-9:color(display-p3 .247 .556 .969);--blue-10:color(display-p3 .344 .612 .973);--blue-11:color(display-p3 .49 .72 1);--blue-12:color(display-p3 .788 .898 .99)}}}:root,.light,.light-theme{--blue-a1:#0080ff04;--blue-a2:#008cff0b;--blue-a3:#008ff519;--blue-a4:#009eff2a;--blue-a5:#0093ff3d;--blue-a6:#0088f653;--blue-a7:#0083eb71;--blue-a8:#0084e6a1;--blue-a9:#0090ff;--blue-a10:#0086f0fa;--blue-a11:#006dcbf2;--blue-a12:#002359ee}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--blue-a1:color(display-p3 .024 .514 1/.016);--blue-a2:color(display-p3 .024 .514 .906/.04);--blue-a3:color(display-p3 .012 .506 .914/.087);--blue-a4:color(display-p3 .008 .545 1/.146);--blue-a5:color(display-p3 .004 .502 .984/.212);--blue-a6:color(display-p3 .004 .463 .922/.291);--blue-a7:color(display-p3 .004 .431 .863/.393);--blue-a8:color(display-p3 0 .427 .851/.55);--blue-a9:color(display-p3 0 .412 .961/.753);--blue-a10:color(display-p3 0 .376 .886/.765);--blue-a11:color(display-p3 .15 .44 .84);--blue-a12:color(display-p3 .102 .193 .379)}}}.dark,.dark-theme{--blue-a1:#004df211;--blue-a2:#1166fb18;--blue-a3:#0077ff3a;--blue-a4:#0075ff57;--blue-a5:#0081fd6b;--blue-a6:#0f89fd7f;--blue-a7:#2a91fe98;--blue-a8:#3094feb9;--blue-a9:#0090ff;--blue-a10:#3b9eff;--blue-a11:#70b8ff;--blue-a12:#c2e6ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--blue-a1:color(display-p3 0 .333 1/.059);--blue-a2:color(display-p3 .114 .435 .988/.085);--blue-a3:color(display-p3 .122 .463 1/.219);--blue-a4:color(display-p3 0 .467 1/.324);--blue-a5:color(display-p3 .098 .51 1/.4);--blue-a6:color(display-p3 .224 .557 1/.475);--blue-a7:color(display-p3 .294 .584 1/.572);--blue-a8:color(display-p3 .314 .592 1/.702);--blue-a9:color(display-p3 .251 .573 .996/.967);--blue-a10:color(display-p3 .357 .631 1/.971);--blue-a11:color(display-p3 .49 .72 1);--blue-a12:color(display-p3 .788 .898 .99)}}}:root,.light,.light-theme{--cyan-1:#fafdfe;--cyan-2:#f2fafb;--cyan-3:#def7f9;--cyan-4:#caf1f6;--cyan-5:#b5e9f0;--cyan-6:#9ddde7;--cyan-7:#7dcedc;--cyan-8:#3db9cf;--cyan-9:#00a2c7;--cyan-10:#0797b9;--cyan-11:#107d98;--cyan-12:#0d3c48}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--cyan-1:color(display-p3 .982 .992 .996);--cyan-2:color(display-p3 .955 .981 .984);--cyan-3:color(display-p3 .888 .965 .975);--cyan-4:color(display-p3 .821 .941 .959);--cyan-5:color(display-p3 .751 .907 .935);--cyan-6:color(display-p3 .671 .862 .9);--cyan-7:color(display-p3 .564 .8 .854);--cyan-8:color(display-p3 .388 .715 .798);--cyan-9:color(display-p3 .282 .627 .765);--cyan-10:color(display-p3 .264 .583 .71);--cyan-11:color(display-p3 .08 .48 .63);--cyan-12:color(display-p3 .108 .232 .277)}}}.dark,.dark-theme{--cyan-1:#0b161a;--cyan-2:#101b20;--cyan-3:#082c36;--cyan-4:#003848;--cyan-5:#004558;--cyan-6:#045468;--cyan-7:#12677e;--cyan-8:#11809c;--cyan-9:#00a2c7;--cyan-10:#23afd0;--cyan-11:#4ccce6;--cyan-12:#b6ecf7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--cyan-1:color(display-p3 .053 .085 .098);--cyan-2:color(display-p3 .072 .105 .122);--cyan-3:color(display-p3 .073 .168 .209);--cyan-4:color(display-p3 .063 .216 .277);--cyan-5:color(display-p3 .091 .267 .336);--cyan-6:color(display-p3 .137 .324 .4);--cyan-7:color(display-p3 .186 .398 .484);--cyan-8:color(display-p3 .23 .496 .6);--cyan-9:color(display-p3 .282 .627 .765);--cyan-10:color(display-p3 .331 .675 .801);--cyan-11:color(display-p3 .446 .79 .887);--cyan-12:color(display-p3 .757 .919 .962)}}}:root,.light,.light-theme{--cyan-a1:#0099cc05;--cyan-a2:#009db10d;--cyan-a3:#00c2d121;--cyan-a4:#00bcd435;--cyan-a5:#01b4cc4a;--cyan-a6:#00a7c162;--cyan-a7:#009fbb82;--cyan-a8:#00a3c0c2;--cyan-a9:#00a2c7;--cyan-a10:#0094b7f8;--cyan-a11:#007491ef;--cyan-a12:#00323ef2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--cyan-a1:color(display-p3 .02 .608 .804/.02);--cyan-a2:color(display-p3 .02 .557 .647/.044);--cyan-a3:color(display-p3 .004 .694 .796/.114);--cyan-a4:color(display-p3 .004 .678 .784/.181);--cyan-a5:color(display-p3 .004 .624 .733/.248);--cyan-a6:color(display-p3 .004 .584 .706/.33);--cyan-a7:color(display-p3 .004 .541 .667/.436);--cyan-a8:color(display-p3 0 .533 .667/.612);--cyan-a9:color(display-p3 0 .482 .675/.718);--cyan-a10:color(display-p3 0 .435 .608/.738);--cyan-a11:color(display-p3 .08 .48 .63);--cyan-a12:color(display-p3 .108 .232 .277)}}}.dark,.dark-theme{--cyan-a1:#0091f70a;--cyan-a2:#02a7f211;--cyan-a3:#00befd28;--cyan-a4:#00baff3b;--cyan-a5:#00befd4d;--cyan-a6:#00c7fd5e;--cyan-a7:#14cdff75;--cyan-a8:#11cfff95;--cyan-a9:#00cfffc3;--cyan-a10:#28d6ffcd;--cyan-a11:#52e1fee5;--cyan-a12:#bbf3fef7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--cyan-a1:color(display-p3 0 .647 .992/.034);--cyan-a2:color(display-p3 .133 .733 1/.059);--cyan-a3:color(display-p3 .122 .741 .996/.152);--cyan-a4:color(display-p3 .051 .725 1/.227);--cyan-a5:color(display-p3 .149 .757 1/.29);--cyan-a6:color(display-p3 .267 .792 1/.358);--cyan-a7:color(display-p3 .333 .808 1/.446);--cyan-a8:color(display-p3 .357 .816 1/.572);--cyan-a9:color(display-p3 .357 .82 1/.748);--cyan-a10:color(display-p3 .4 .839 1/.786);--cyan-a11:color(display-p3 .446 .79 .887);--cyan-a12:color(display-p3 .757 .919 .962)}}}:root,.light,.light-theme{--teal-1:#fafefd;--teal-2:#f3fbf9;--teal-3:#e0f8f3;--teal-4:#ccf3ea;--teal-5:#b8eae0;--teal-6:#a1ded2;--teal-7:#83cdc1;--teal-8:#53b9ab;--teal-9:#12a594;--teal-10:#0d9b8a;--teal-11:#008573;--teal-12:#0d3d38}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--teal-1:color(display-p3 .983 .996 .992);--teal-2:color(display-p3 .958 .983 .976);--teal-3:color(display-p3 .895 .971 .952);--teal-4:color(display-p3 .831 .949 .92);--teal-5:color(display-p3 .761 .914 .878);--teal-6:color(display-p3 .682 .864 .825);--teal-7:color(display-p3 .581 .798 .756);--teal-8:color(display-p3 .433 .716 .671);--teal-9:color(display-p3 .297 .637 .581);--teal-10:color(display-p3 .275 .599 .542);--teal-11:color(display-p3 .08 .5 .43);--teal-12:color(display-p3 .11 .235 .219)}}}.dark,.dark-theme{--teal-1:#0d1514;--teal-2:#111c1b;--teal-3:#0d2d2a;--teal-4:#023b37;--teal-5:#084843;--teal-6:#145750;--teal-7:#1c6961;--teal-8:#207e73;--teal-9:#12a594;--teal-10:#0eb39e;--teal-11:#0bd8b6;--teal-12:#adf0dd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--teal-1:color(display-p3 .059 .083 .079);--teal-2:color(display-p3 .075 .11 .107);--teal-3:color(display-p3 .087 .175 .165);--teal-4:color(display-p3 .087 .227 .214);--teal-5:color(display-p3 .12 .277 .261);--teal-6:color(display-p3 .162 .335 .314);--teal-7:color(display-p3 .205 .406 .379);--teal-8:color(display-p3 .245 .489 .453);--teal-9:color(display-p3 .297 .637 .581);--teal-10:color(display-p3 .319 .69 .62);--teal-11:color(display-p3 .388 .835 .719);--teal-12:color(display-p3 .734 .934 .87)}}}:root,.light,.light-theme{--teal-a1:#00cc9905;--teal-a2:#00aa800c;--teal-a3:#00c69d1f;--teal-a4:#00c39633;--teal-a5:#00b49047;--teal-a6:#00a6855e;--teal-a7:#0099807c;--teal-a8:#009783ac;--teal-a9:#009e8ced;--teal-a10:#009684f2;--teal-a11:#008573;--teal-a12:#00332df2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--teal-a1:color(display-p3 .024 .757 .514/.016);--teal-a2:color(display-p3 .02 .647 .467/.044);--teal-a3:color(display-p3 .004 .741 .557/.106);--teal-a4:color(display-p3 .004 .702 .537/.169);--teal-a5:color(display-p3 .004 .643 .494/.24);--teal-a6:color(display-p3 .004 .569 .447/.318);--teal-a7:color(display-p3 .004 .518 .424/.42);--teal-a8:color(display-p3 0 .506 .424/.569);--teal-a9:color(display-p3 0 .482 .404/.702);--teal-a10:color(display-p3 0 .451 .369/.726);--teal-a11:color(display-p3 .08 .5 .43);--teal-a12:color(display-p3 .11 .235 .219)}}}.dark,.dark-theme{--teal-a1:#00deab05;--teal-a2:#12fbe60c;--teal-a3:#00ffe61e;--teal-a4:#00ffe92d;--teal-a5:#00ffea3b;--teal-a6:#1cffe84b;--teal-a7:#2efde85f;--teal-a8:#32ffe775;--teal-a9:#13ffe49f;--teal-a10:#0dffe0ae;--teal-a11:#0afed5d6;--teal-a12:#b8ffebef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--teal-a1:color(display-p3 0 .992 .761/.017);--teal-a2:color(display-p3 .235 .988 .902/.047);--teal-a3:color(display-p3 .235 1 .898/.118);--teal-a4:color(display-p3 .18 .996 .929/.173);--teal-a5:color(display-p3 .31 1 .933/.227);--teal-a6:color(display-p3 .396 1 .933/.286);--teal-a7:color(display-p3 .443 1 .925/.366);--teal-a8:color(display-p3 .459 1 .925/.454);--teal-a9:color(display-p3 .443 .996 .906/.61);--teal-a10:color(display-p3 .439 .996 .89/.669);--teal-a11:color(display-p3 .388 .835 .719);--teal-a12:color(display-p3 .734 .934 .87)}}}:root,.light,.light-theme{--jade-1:#fbfefd;--jade-2:#f4fbf7;--jade-3:#e6f7ed;--jade-4:#d6f1e3;--jade-5:#c3e9d7;--jade-6:#acdec8;--jade-7:#8bceb6;--jade-8:#56ba9f;--jade-9:#29a383;--jade-10:#26997b;--jade-11:#208368;--jade-12:#1d3b31}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--jade-1:color(display-p3 .986 .996 .992);--jade-2:color(display-p3 .962 .983 .969);--jade-3:color(display-p3 .912 .965 .932);--jade-4:color(display-p3 .858 .941 .893);--jade-5:color(display-p3 .795 .909 .847);--jade-6:color(display-p3 .715 .864 .791);--jade-7:color(display-p3 .603 .802 .718);--jade-8:color(display-p3 .44 .72 .629);--jade-9:color(display-p3 .319 .63 .521);--jade-10:color(display-p3 .299 .592 .488);--jade-11:color(display-p3 .15 .5 .37);--jade-12:color(display-p3 .142 .229 .194)}}}.dark,.dark-theme{--jade-1:#0d1512;--jade-2:#121c18;--jade-3:#0f2e22;--jade-4:#0b3b2c;--jade-5:#114837;--jade-6:#1b5745;--jade-7:#246854;--jade-8:#2a7e68;--jade-9:#29a383;--jade-10:#27b08b;--jade-11:#1fd8a4;--jade-12:#adf0d4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--jade-1:color(display-p3 .059 .083 .071);--jade-2:color(display-p3 .078 .11 .094);--jade-3:color(display-p3 .091 .176 .138);--jade-4:color(display-p3 .102 .228 .177);--jade-5:color(display-p3 .133 .279 .221);--jade-6:color(display-p3 .174 .334 .273);--jade-7:color(display-p3 .219 .402 .335);--jade-8:color(display-p3 .263 .488 .411);--jade-9:color(display-p3 .319 .63 .521);--jade-10:color(display-p3 .338 .68 .555);--jade-11:color(display-p3 .4 .835 .656);--jade-12:color(display-p3 .734 .934 .838)}}}:root,.light,.light-theme{--jade-a1:#00c08004;--jade-a2:#00a3460b;--jade-a3:#00ae4819;--jade-a4:#00a85129;--jade-a5:#00a2553c;--jade-a6:#009a5753;--jade-a7:#00945f74;--jade-a8:#00976ea9;--jade-a9:#00916bd6;--jade-a10:#008764d9;--jade-a11:#007152df;--jade-a12:#002217e2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--jade-a1:color(display-p3 .024 .757 .514/.016);--jade-a2:color(display-p3 .024 .612 .22/.04);--jade-a3:color(display-p3 .012 .596 .235/.087);--jade-a4:color(display-p3 .008 .588 .255/.142);--jade-a5:color(display-p3 .004 .561 .251/.204);--jade-a6:color(display-p3 .004 .525 .278/.287);--jade-a7:color(display-p3 .004 .506 .29/.397);--jade-a8:color(display-p3 0 .506 .337/.561);--jade-a9:color(display-p3 0 .459 .298/.683);--jade-a10:color(display-p3 0 .42 .271/.702);--jade-a11:color(display-p3 .15 .5 .37);--jade-a12:color(display-p3 .142 .229 .194)}}}.dark,.dark-theme{--jade-a1:#00de4505;--jade-a2:#27fba60c;--jade-a3:#02f99920;--jade-a4:#00ffaa2d;--jade-a5:#11ffb63b;--jade-a6:#34ffc24b;--jade-a7:#45fdc75e;--jade-a8:#48ffcf75;--jade-a9:#38feca9d;--jade-a10:#31fec7ab;--jade-a11:#21fec0d6;--jade-a12:#b8ffe1ef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--jade-a1:color(display-p3 0 .992 .298/.017);--jade-a2:color(display-p3 .318 .988 .651/.047);--jade-a3:color(display-p3 .267 1 .667/.118);--jade-a4:color(display-p3 .275 .996 .702/.173);--jade-a5:color(display-p3 .361 1 .741/.227);--jade-a6:color(display-p3 .439 1 .796/.286);--jade-a7:color(display-p3 .49 1 .804/.362);--jade-a8:color(display-p3 .506 1 .835/.45);--jade-a9:color(display-p3 .478 .996 .816/.606);--jade-a10:color(display-p3 .478 1 .816/.656);--jade-a11:color(display-p3 .4 .835 .656);--jade-a12:color(display-p3 .734 .934 .838)}}}:root,.light,.light-theme{--green-1:#fbfefc;--green-2:#f4fbf6;--green-3:#e6f6eb;--green-4:#d6f1df;--green-5:#c4e8d1;--green-6:#adddc0;--green-7:#8eceaa;--green-8:#5bb98b;--green-9:#30a46c;--green-10:#2b9a66;--green-11:#218358;--green-12:#193b2d}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--green-1:color(display-p3 .986 .996 .989);--green-2:color(display-p3 .963 .983 .967);--green-3:color(display-p3 .913 .964 .925);--green-4:color(display-p3 .859 .94 .879);--green-5:color(display-p3 .796 .907 .826);--green-6:color(display-p3 .718 .863 .761);--green-7:color(display-p3 .61 .801 .675);--green-8:color(display-p3 .451 .715 .559);--green-9:color(display-p3 .332 .634 .442);--green-10:color(display-p3 .308 .595 .417);--green-11:color(display-p3 .19 .5 .32);--green-12:color(display-p3 .132 .228 .18)}}}.dark,.dark-theme{--green-1:#0e1512;--green-2:#121b17;--green-3:#132d21;--green-4:#113b29;--green-5:#174933;--green-6:#20573e;--green-7:#28684a;--green-8:#2f7c57;--green-9:#30a46c;--green-10:#33b074;--green-11:#3dd68c;--green-12:#b1f1cb}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--green-1:color(display-p3 .062 .083 .071);--green-2:color(display-p3 .079 .106 .09);--green-3:color(display-p3 .1 .173 .133);--green-4:color(display-p3 .115 .229 .166);--green-5:color(display-p3 .147 .282 .206);--green-6:color(display-p3 .185 .338 .25);--green-7:color(display-p3 .227 .403 .298);--green-8:color(display-p3 .27 .479 .351);--green-9:color(display-p3 .332 .634 .442);--green-10:color(display-p3 .357 .682 .474);--green-11:color(display-p3 .434 .828 .573);--green-12:color(display-p3 .747 .938 .807)}}}:root,.light,.light-theme{--green-a1:#00c04004;--green-a2:#00a32f0b;--green-a3:#00a43319;--green-a4:#00a83829;--green-a5:#019c393b;--green-a6:#00963c52;--green-a7:#00914071;--green-a8:#00924ba4;--green-a9:#008f4acf;--green-a10:#008647d4;--green-a11:#00713fde;--green-a12:#002616e6}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--green-a1:color(display-p3 .024 .757 .267/.016);--green-a2:color(display-p3 .024 .565 .129/.036);--green-a3:color(display-p3 .012 .596 .145/.087);--green-a4:color(display-p3 .008 .588 .145/.142);--green-a5:color(display-p3 .004 .541 .157/.204);--green-a6:color(display-p3 .004 .518 .157/.283);--green-a7:color(display-p3 .004 .486 .165/.389);--green-a8:color(display-p3 0 .478 .2/.55);--green-a9:color(display-p3 0 .455 .165/.667);--green-a10:color(display-p3 0 .416 .153/.691);--green-a11:color(display-p3 .19 .5 .32);--green-a12:color(display-p3 .132 .228 .18)}}}.dark,.dark-theme{--green-a1:#00de4505;--green-a2:#29f99d0b;--green-a3:#22ff991e;--green-a4:#11ff992d;--green-a5:#2bffa23c;--green-a6:#44ffaa4b;--green-a7:#50fdac5e;--green-a8:#54ffad73;--green-a9:#44ffa49e;--green-a10:#43fea4ab;--green-a11:#46fea5d4;--green-a12:#bbffd7f0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--green-a1:color(display-p3 0 .992 .298/.017);--green-a2:color(display-p3 .341 .98 .616/.043);--green-a3:color(display-p3 .376 .996 .655/.114);--green-a4:color(display-p3 .341 .996 .635/.173);--green-a5:color(display-p3 .408 1 .678/.232);--green-a6:color(display-p3 .475 1 .706/.29);--green-a7:color(display-p3 .514 1 .706/.362);--green-a8:color(display-p3 .529 1 .718/.442);--green-a9:color(display-p3 .502 .996 .682/.61);--green-a10:color(display-p3 .506 1 .682/.66);--green-a11:color(display-p3 .434 .828 .573);--green-a12:color(display-p3 .747 .938 .807)}}}:root,.light,.light-theme{--grass-1:#fbfefb;--grass-2:#f5fbf5;--grass-3:#e9f6e9;--grass-4:#daf1db;--grass-5:#c9e8ca;--grass-6:#b2ddb5;--grass-7:#94ce9a;--grass-8:#65ba74;--grass-9:#46a758;--grass-10:#3e9b4f;--grass-11:#2a7e3b;--grass-12:#203c25}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--grass-1:color(display-p3 .986 .996 .985);--grass-2:color(display-p3 .966 .983 .964);--grass-3:color(display-p3 .923 .965 .917);--grass-4:color(display-p3 .872 .94 .865);--grass-5:color(display-p3 .811 .908 .802);--grass-6:color(display-p3 .733 .864 .724);--grass-7:color(display-p3 .628 .803 .622);--grass-8:color(display-p3 .477 .72 .482);--grass-9:color(display-p3 .38 .647 .378);--grass-10:color(display-p3 .344 .598 .342);--grass-11:color(display-p3 .263 .488 .261);--grass-12:color(display-p3 .151 .233 .153)}}}.dark,.dark-theme{--grass-1:#0e1511;--grass-2:#141a15;--grass-3:#1b2a1e;--grass-4:#1d3a24;--grass-5:#25482d;--grass-6:#2d5736;--grass-7:#366740;--grass-8:#3e7949;--grass-9:#46a758;--grass-10:#53b365;--grass-11:#71d083;--grass-12:#c2f0c2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--grass-1:color(display-p3 .062 .083 .067);--grass-2:color(display-p3 .083 .103 .085);--grass-3:color(display-p3 .118 .163 .122);--grass-4:color(display-p3 .142 .225 .15);--grass-5:color(display-p3 .178 .279 .186);--grass-6:color(display-p3 .217 .337 .224);--grass-7:color(display-p3 .258 .4 .264);--grass-8:color(display-p3 .302 .47 .305);--grass-9:color(display-p3 .38 .647 .378);--grass-10:color(display-p3 .426 .694 .426);--grass-11:color(display-p3 .535 .807 .542);--grass-12:color(display-p3 .797 .936 .776)}}}:root,.light,.light-theme{--grass-a1:#00c00004;--grass-a2:#0099000a;--grass-a3:#00970016;--grass-a4:#009f0725;--grass-a5:#00930536;--grass-a6:#008f0a4d;--grass-a7:#018b0f6b;--grass-a8:#008d199a;--grass-a9:#008619b9;--grass-a10:#007b17c1;--grass-a11:#006514d5;--grass-a12:#002006df}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--grass-a1:color(display-p3 .024 .757 .024/.016);--grass-a2:color(display-p3 .024 .565 .024/.036);--grass-a3:color(display-p3 .059 .576 .008/.083);--grass-a4:color(display-p3 .035 .565 .008/.134);--grass-a5:color(display-p3 .047 .545 .008/.197);--grass-a6:color(display-p3 .031 .502 .004/.275);--grass-a7:color(display-p3 .012 .482 .004/.377);--grass-a8:color(display-p3 0 .467 .008/.522);--grass-a9:color(display-p3 .008 .435 0/.624);--grass-a10:color(display-p3 .008 .388 0/.659);--grass-a11:color(display-p3 .263 .488 .261);--grass-a12:color(display-p3 .151 .233 .153)}}}.dark,.dark-theme{--grass-a1:#00de1205;--grass-a2:#5ef7780a;--grass-a3:#70fe8c1b;--grass-a4:#57ff802c;--grass-a5:#68ff8b3b;--grass-a6:#71ff8f4b;--grass-a7:#77fd925d;--grass-a8:#77fd9070;--grass-a9:#65ff82a1;--grass-a10:#72ff8dae;--grass-a11:#89ff9fcd;--grass-a12:#ceffceef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--grass-a1:color(display-p3 0 .992 .071/.017);--grass-a2:color(display-p3 .482 .996 .584/.038);--grass-a3:color(display-p3 .549 .992 .588/.106);--grass-a4:color(display-p3 .51 .996 .557/.169);--grass-a5:color(display-p3 .553 1 .588/.227);--grass-a6:color(display-p3 .584 1 .608/.29);--grass-a7:color(display-p3 .604 1 .616/.358);--grass-a8:color(display-p3 .608 1 .62/.433);--grass-a9:color(display-p3 .573 1 .569/.622);--grass-a10:color(display-p3 .6 .996 .6/.673);--grass-a11:color(display-p3 .535 .807 .542);--grass-a12:color(display-p3 .797 .936 .776)}}}:root,.light,.light-theme{--orange-1:#fefcfb;--orange-2:#fff7ed;--orange-3:#ffefd6;--orange-4:#ffdfb5;--orange-5:#ffd19a;--orange-6:#ffc182;--orange-7:#f5ae73;--orange-8:#ec9455;--orange-9:#f76b15;--orange-10:#ef5f00;--orange-11:#cc4e00;--orange-12:#582d1d}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--orange-1:color(display-p3 .995 .988 .985);--orange-2:color(display-p3 .994 .968 .934);--orange-3:color(display-p3 .989 .938 .85);--orange-4:color(display-p3 1 .874 .687);--orange-5:color(display-p3 1 .821 .583);--orange-6:color(display-p3 .975 .767 .545);--orange-7:color(display-p3 .919 .693 .486);--orange-8:color(display-p3 .877 .597 .379);--orange-9:color(display-p3 .9 .45 .2);--orange-10:color(display-p3 .87 .409 .164);--orange-11:color(display-p3 .76 .34 0);--orange-12:color(display-p3 .323 .185 .127)}}}.dark,.dark-theme{--orange-1:#17120e;--orange-2:#1e160f;--orange-3:#331e0b;--orange-4:#462100;--orange-5:#562800;--orange-6:#66350c;--orange-7:#7e451d;--orange-8:#a35829;--orange-9:#f76b15;--orange-10:#ff801f;--orange-11:#ffa057;--orange-12:#ffe0c2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--orange-1:color(display-p3 .088 .07 .057);--orange-2:color(display-p3 .113 .089 .061);--orange-3:color(display-p3 .189 .12 .056);--orange-4:color(display-p3 .262 .132 0);--orange-5:color(display-p3 .315 .168 .016);--orange-6:color(display-p3 .376 .219 .088);--orange-7:color(display-p3 .465 .283 .147);--orange-8:color(display-p3 .601 .359 .201);--orange-9:color(display-p3 .9 .45 .2);--orange-10:color(display-p3 .98 .51 .23);--orange-11:color(display-p3 1 .63 .38);--orange-12:color(display-p3 .98 .883 .775)}}}:root,.light,.light-theme{--orange-a1:#c0400004;--orange-a2:#ff8e0012;--orange-a3:#ff9c0029;--orange-a4:#ff91014a;--orange-a5:#ff8b0065;--orange-a6:#ff81007d;--orange-a7:#ed6c008c;--orange-a8:#e35f00aa;--orange-a9:#f65e00ea;--orange-a10:#ef5f00;--orange-a11:#cc4e00;--orange-a12:#431200e2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--orange-a1:color(display-p3 .757 .267 .024/.016);--orange-a2:color(display-p3 .886 .533 .008/.067);--orange-a3:color(display-p3 .922 .584 .008/.15);--orange-a4:color(display-p3 1 .604 .004/.314);--orange-a5:color(display-p3 1 .569 .004/.416);--orange-a6:color(display-p3 .949 .494 .004/.455);--orange-a7:color(display-p3 .839 .408 0/.514);--orange-a8:color(display-p3 .804 .349 0/.62);--orange-a9:color(display-p3 .878 .314 0/.8);--orange-a10:color(display-p3 .843 .29 0/.836);--orange-a11:color(display-p3 .76 .34 0);--orange-a12:color(display-p3 .323 .185 .127)}}}.dark,.dark-theme{--orange-a1:#ec360007;--orange-a2:#fe6d000e;--orange-a3:#fb6a0025;--orange-a4:#ff590039;--orange-a5:#ff61004a;--orange-a6:#fd75045c;--orange-a7:#ff832c75;--orange-a8:#fe84389d;--orange-a9:#fe6d15f7;--orange-a10:#ff801f;--orange-a11:#ffa057;--orange-a12:#ffe0c2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--orange-a1:color(display-p3 .961 .247 0/.022);--orange-a2:color(display-p3 .992 .529 0/.051);--orange-a3:color(display-p3 .996 .486 0/.131);--orange-a4:color(display-p3 .996 .384 0/.211);--orange-a5:color(display-p3 1 .455 0/.265);--orange-a6:color(display-p3 1 .529 .129/.332);--orange-a7:color(display-p3 1 .569 .251/.429);--orange-a8:color(display-p3 1 .584 .302/.572);--orange-a9:color(display-p3 1 .494 .216/.895);--orange-a10:color(display-p3 1 .522 .235/.979);--orange-a11:color(display-p3 1 .63 .38);--orange-a12:color(display-p3 .98 .883 .775)}}}:root,.light,.light-theme{--brown-1:#fefdfc;--brown-2:#fcf9f6;--brown-3:#f6eee7;--brown-4:#f0e4d9;--brown-5:#ebdaca;--brown-6:#e4cdb7;--brown-7:#dcbc9f;--brown-8:#cea37e;--brown-9:#ad7f58;--brown-10:#a07553;--brown-11:#815e46;--brown-12:#3e332e}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--brown-1:color(display-p3 .995 .992 .989);--brown-2:color(display-p3 .987 .976 .964);--brown-3:color(display-p3 .959 .936 .909);--brown-4:color(display-p3 .934 .897 .855);--brown-5:color(display-p3 .909 .856 .798);--brown-6:color(display-p3 .88 .808 .73);--brown-7:color(display-p3 .841 .742 .639);--brown-8:color(display-p3 .782 .647 .514);--brown-9:color(display-p3 .651 .505 .368);--brown-10:color(display-p3 .601 .465 .344);--brown-11:color(display-p3 .485 .374 .288);--brown-12:color(display-p3 .236 .202 .183)}}}.dark,.dark-theme{--brown-1:#12110f;--brown-2:#1c1816;--brown-3:#28211d;--brown-4:#322922;--brown-5:#3e3128;--brown-6:#4d3c2f;--brown-7:#614a39;--brown-8:#7c5f46;--brown-9:#ad7f58;--brown-10:#b88c67;--brown-11:#dbb594;--brown-12:#f2e1ca}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--brown-1:color(display-p3 .071 .067 .059);--brown-2:color(display-p3 .107 .095 .087);--brown-3:color(display-p3 .151 .13 .115);--brown-4:color(display-p3 .191 .161 .138);--brown-5:color(display-p3 .235 .194 .162);--brown-6:color(display-p3 .291 .237 .192);--brown-7:color(display-p3 .365 .295 .232);--brown-8:color(display-p3 .469 .377 .287);--brown-9:color(display-p3 .651 .505 .368);--brown-10:color(display-p3 .697 .557 .423);--brown-11:color(display-p3 .835 .715 .597);--brown-12:color(display-p3 .938 .885 .802)}}}:root,.light,.light-theme{--brown-a1:#aa550003;--brown-a2:#aa550009;--brown-a3:#a04b0018;--brown-a4:#9b4a0026;--brown-a5:#9f4d0035;--brown-a6:#a04e0048;--brown-a7:#a34e0060;--brown-a8:#9f4a0081;--brown-a9:#823c00a7;--brown-a10:#723300ac;--brown-a11:#522100b9;--brown-a12:#140600d1}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--brown-a1:color(display-p3 .675 .349 .024/.012);--brown-a2:color(display-p3 .675 .349 .024/.036);--brown-a3:color(display-p3 .573 .314 .012/.091);--brown-a4:color(display-p3 .545 .302 .008/.146);--brown-a5:color(display-p3 .561 .29 .004/.204);--brown-a6:color(display-p3 .553 .294 .004/.271);--brown-a7:color(display-p3 .557 .286 .004/.361);--brown-a8:color(display-p3 .549 .275 .004/.487);--brown-a9:color(display-p3 .447 .22 0/.632);--brown-a10:color(display-p3 .388 .188 0/.655);--brown-a11:color(display-p3 .485 .374 .288);--brown-a12:color(display-p3 .236 .202 .183)}}}.dark,.dark-theme{--brown-a1:#91110002;--brown-a2:#fba67c0c;--brown-a3:#fcb58c19;--brown-a4:#fbbb8a24;--brown-a5:#fcb88931;--brown-a6:#fdba8741;--brown-a7:#ffbb8856;--brown-a8:#ffbe8773;--brown-a9:#feb87da8;--brown-a10:#ffc18cb3;--brown-a11:#fed1aad9;--brown-a12:#feecd4f2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--brown-a1:color(display-p3 .855 .071 0/.005);--brown-a2:color(display-p3 .98 .706 .525/.043);--brown-a3:color(display-p3 .996 .745 .576/.093);--brown-a4:color(display-p3 1 .765 .592/.135);--brown-a5:color(display-p3 1 .761 .588/.181);--brown-a6:color(display-p3 1 .773 .592/.24);--brown-a7:color(display-p3 .996 .776 .58/.32);--brown-a8:color(display-p3 1 .78 .573/.433);--brown-a9:color(display-p3 1 .769 .549/.627);--brown-a10:color(display-p3 1 .792 .596/.677);--brown-a11:color(display-p3 .835 .715 .597);--brown-a12:color(display-p3 .938 .885 .802)}}}:root,.light,.light-theme{--sky-1:#f9feff;--sky-2:#f1fafd;--sky-3:#e1f6fd;--sky-4:#d1f0fa;--sky-5:#bee7f5;--sky-6:#a9daed;--sky-7:#8dcae3;--sky-8:#60b3d7;--sky-9:#7ce2fe;--sky-10:#74daf8;--sky-11:#00749e;--sky-12:#1d3e56}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sky-1:color(display-p3 .98 .995 .999);--sky-2:color(display-p3 .953 .98 .99);--sky-3:color(display-p3 .899 .963 .989);--sky-4:color(display-p3 .842 .937 .977);--sky-5:color(display-p3 .777 .9 .954);--sky-6:color(display-p3 .701 .851 .921);--sky-7:color(display-p3 .604 .785 .879);--sky-8:color(display-p3 .457 .696 .829);--sky-9:color(display-p3 .585 .877 .983);--sky-10:color(display-p3 .555 .845 .959);--sky-11:color(display-p3 .193 .448 .605);--sky-12:color(display-p3 .145 .241 .329)}}}.dark,.dark-theme{--sky-1:#0d141f;--sky-2:#111a27;--sky-3:#112840;--sky-4:#113555;--sky-5:#154467;--sky-6:#1b537b;--sky-7:#1f6692;--sky-8:#197cae;--sky-9:#7ce2fe;--sky-10:#a8eeff;--sky-11:#75c7f0;--sky-12:#c2f3ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sky-1:color(display-p3 .056 .078 .116);--sky-2:color(display-p3 .075 .101 .149);--sky-3:color(display-p3 .089 .154 .244);--sky-4:color(display-p3 .106 .207 .323);--sky-5:color(display-p3 .135 .261 .394);--sky-6:color(display-p3 .17 .322 .469);--sky-7:color(display-p3 .205 .394 .557);--sky-8:color(display-p3 .232 .48 .665);--sky-9:color(display-p3 .585 .877 .983);--sky-10:color(display-p3 .718 .925 .991);--sky-11:color(display-p3 .536 .772 .924);--sky-12:color(display-p3 .799 .947 .993)}}}:root,.light,.light-theme{--sky-a1:#00d5ff06;--sky-a2:#00a4db0e;--sky-a3:#00b3ee1e;--sky-a4:#00ace42e;--sky-a5:#00a1d841;--sky-a6:#0092ca56;--sky-a7:#0089c172;--sky-a8:#0085bf9f;--sky-a9:#00c7fe83;--sky-a10:#00bcf38b;--sky-a11:#00749e;--sky-a12:#002540e2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sky-a1:color(display-p3 .02 .804 1/.02);--sky-a2:color(display-p3 .024 .592 .757/.048);--sky-a3:color(display-p3 .004 .655 .886/.102);--sky-a4:color(display-p3 .004 .604 .851/.157);--sky-a5:color(display-p3 .004 .565 .792/.224);--sky-a6:color(display-p3 .004 .502 .737/.299);--sky-a7:color(display-p3 .004 .459 .694/.397);--sky-a8:color(display-p3 0 .435 .682/.542);--sky-a9:color(display-p3 .004 .71 .965/.416);--sky-a10:color(display-p3 .004 .647 .914/.444);--sky-a11:color(display-p3 .193 .448 .605);--sky-a12:color(display-p3 .145 .241 .329)}}}.dark,.dark-theme{--sky-a1:#0044ff0f;--sky-a2:#1171fb18;--sky-a3:#1184fc33;--sky-a4:#128fff49;--sky-a5:#1c9dfd5d;--sky-a6:#28a5ff72;--sky-a7:#2badfe8b;--sky-a8:#1db2fea9;--sky-a9:#7ce3fffe;--sky-a10:#a8eeff;--sky-a11:#7cd3ffef;--sky-a12:#c2f3ff}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sky-a1:color(display-p3 0 .282 .996/.055);--sky-a2:color(display-p3 .157 .467 .992/.089);--sky-a3:color(display-p3 .192 .522 .996/.19);--sky-a4:color(display-p3 .212 .584 1/.274);--sky-a5:color(display-p3 .259 .631 1/.349);--sky-a6:color(display-p3 .302 .655 1/.433);--sky-a7:color(display-p3 .329 .686 1/.526);--sky-a8:color(display-p3 .325 .71 1/.643);--sky-a9:color(display-p3 .592 .894 1/.984);--sky-a10:color(display-p3 .722 .933 1/.992);--sky-a11:color(display-p3 .536 .772 .924);--sky-a12:color(display-p3 .799 .947 .993)}}}:root,.light,.light-theme{--mint-1:#f9fefd;--mint-2:#f2fbf9;--mint-3:#ddf9f2;--mint-4:#c8f4e9;--mint-5:#b3ecde;--mint-6:#9ce0d0;--mint-7:#7ecfbd;--mint-8:#4cbba5;--mint-9:#86ead4;--mint-10:#7de0cb;--mint-11:#027864;--mint-12:#16433c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--mint-1:color(display-p3 .98 .995 .992);--mint-2:color(display-p3 .957 .985 .977);--mint-3:color(display-p3 .888 .972 .95);--mint-4:color(display-p3 .819 .951 .916);--mint-5:color(display-p3 .747 .918 .873);--mint-6:color(display-p3 .668 .87 .818);--mint-7:color(display-p3 .567 .805 .744);--mint-8:color(display-p3 .42 .724 .649);--mint-9:color(display-p3 .62 .908 .834);--mint-10:color(display-p3 .585 .871 .797);--mint-11:color(display-p3 .203 .463 .397);--mint-12:color(display-p3 .136 .259 .236)}}}.dark,.dark-theme{--mint-1:#0e1515;--mint-2:#0f1b1b;--mint-3:#092c2b;--mint-4:#003a38;--mint-5:#004744;--mint-6:#105650;--mint-7:#1e685f;--mint-8:#277f70;--mint-9:#86ead4;--mint-10:#a8f5e5;--mint-11:#58d5ba;--mint-12:#c4f5e1}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mint-1:color(display-p3 .059 .082 .081);--mint-2:color(display-p3 .068 .104 .105);--mint-3:color(display-p3 .077 .17 .168);--mint-4:color(display-p3 .068 .224 .22);--mint-5:color(display-p3 .104 .275 .264);--mint-6:color(display-p3 .154 .332 .313);--mint-7:color(display-p3 .207 .403 .373);--mint-8:color(display-p3 .258 .49 .441);--mint-9:color(display-p3 .62 .908 .834);--mint-10:color(display-p3 .725 .954 .898);--mint-11:color(display-p3 .482 .825 .733);--mint-12:color(display-p3 .807 .955 .887)}}}:root,.light,.light-theme{--mint-a1:#00d5aa06;--mint-a2:#00b18a0d;--mint-a3:#00d29e22;--mint-a4:#00cc9937;--mint-a5:#00c0914c;--mint-a6:#00b08663;--mint-a7:#00a17d81;--mint-a8:#009e7fb3;--mint-a9:#00d3a579;--mint-a10:#00c39982;--mint-a11:#007763fd;--mint-a12:#00312ae9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--mint-a1:color(display-p3 .02 .804 .608/.02);--mint-a2:color(display-p3 .02 .647 .467/.044);--mint-a3:color(display-p3 .004 .761 .553/.114);--mint-a4:color(display-p3 .004 .741 .545/.181);--mint-a5:color(display-p3 .004 .678 .51/.255);--mint-a6:color(display-p3 .004 .616 .463/.334);--mint-a7:color(display-p3 .004 .549 .412/.432);--mint-a8:color(display-p3 0 .529 .392/.581);--mint-a9:color(display-p3 .004 .765 .569/.381);--mint-a10:color(display-p3 .004 .69 .51/.416);--mint-a11:color(display-p3 .203 .463 .397);--mint-a12:color(display-p3 .136 .259 .236)}}}.dark,.dark-theme{--mint-a1:#00dede05;--mint-a2:#00f9f90b;--mint-a3:#00fff61d;--mint-a4:#00fff42c;--mint-a5:#00fff23a;--mint-a6:#0effeb4a;--mint-a7:#34fde55e;--mint-a8:#41ffdf76;--mint-a9:#92ffe7e9;--mint-a10:#aefeedf5;--mint-a11:#67ffded2;--mint-a12:#cbfee9f5}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mint-a1:color(display-p3 0 .992 .992/.017);--mint-a2:color(display-p3 .071 .98 .98/.043);--mint-a3:color(display-p3 .176 .996 .996/.11);--mint-a4:color(display-p3 .071 .996 .973/.169);--mint-a5:color(display-p3 .243 1 .949/.223);--mint-a6:color(display-p3 .369 1 .933/.286);--mint-a7:color(display-p3 .459 1 .914/.362);--mint-a8:color(display-p3 .49 1 .89/.454);--mint-a9:color(display-p3 .678 .996 .914/.904);--mint-a10:color(display-p3 .761 1 .941/.95);--mint-a11:color(display-p3 .482 .825 .733);--mint-a12:color(display-p3 .807 .955 .887)}}}:root,.light,.light-theme{--lime-1:#fcfdfa;--lime-2:#f8faf3;--lime-3:#eef6d6;--lime-4:#e2f0bd;--lime-5:#d3e7a6;--lime-6:#c2da91;--lime-7:#abc978;--lime-8:#8db654;--lime-9:#bdee63;--lime-10:#b0e64c;--lime-11:#5c7c2f;--lime-12:#37401c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--lime-1:color(display-p3 .989 .992 .981);--lime-2:color(display-p3 .975 .98 .954);--lime-3:color(display-p3 .939 .965 .851);--lime-4:color(display-p3 .896 .94 .76);--lime-5:color(display-p3 .843 .903 .678);--lime-6:color(display-p3 .778 .852 .599);--lime-7:color(display-p3 .694 .784 .508);--lime-8:color(display-p3 .585 .707 .378);--lime-9:color(display-p3 .78 .928 .466);--lime-10:color(display-p3 .734 .896 .397);--lime-11:color(display-p3 .386 .482 .227);--lime-12:color(display-p3 .222 .25 .128)}}}.dark,.dark-theme{--lime-1:#11130c;--lime-2:#151a10;--lime-3:#1f2917;--lime-4:#29371d;--lime-5:#334423;--lime-6:#3d522a;--lime-7:#496231;--lime-8:#577538;--lime-9:#bdee63;--lime-10:#d4ff70;--lime-11:#bde56c;--lime-12:#e3f7ba}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--lime-1:color(display-p3 .067 .073 .048);--lime-2:color(display-p3 .086 .1 .067);--lime-3:color(display-p3 .13 .16 .099);--lime-4:color(display-p3 .172 .214 .126);--lime-5:color(display-p3 .213 .266 .153);--lime-6:color(display-p3 .257 .321 .182);--lime-7:color(display-p3 .307 .383 .215);--lime-8:color(display-p3 .365 .456 .25);--lime-9:color(display-p3 .78 .928 .466);--lime-10:color(display-p3 .865 .995 .519);--lime-11:color(display-p3 .771 .893 .485);--lime-12:color(display-p3 .905 .966 .753)}}}:root,.light,.light-theme{--lime-a1:#66990005;--lime-a2:#6b95000c;--lime-a3:#96c80029;--lime-a4:#8fc60042;--lime-a5:#81bb0059;--lime-a6:#72aa006e;--lime-a7:#61990087;--lime-a8:#559200ab;--lime-a9:#93e4009c;--lime-a10:#8fdc00b3;--lime-a11:#375f00d0;--lime-a12:#1e2900e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--lime-a1:color(display-p3 .412 .608 .02/.02);--lime-a2:color(display-p3 .514 .592 .024/.048);--lime-a3:color(display-p3 .584 .765 .008/.15);--lime-a4:color(display-p3 .561 .757 .004/.24);--lime-a5:color(display-p3 .514 .698 .004/.322);--lime-a6:color(display-p3 .443 .627 0/.4);--lime-a7:color(display-p3 .376 .561 .004/.491);--lime-a8:color(display-p3 .333 .529 0/.624);--lime-a9:color(display-p3 .588 .867 0/.534);--lime-a10:color(display-p3 .561 .827 0/.604);--lime-a11:color(display-p3 .386 .482 .227);--lime-a12:color(display-p3 .222 .25 .128)}}}.dark,.dark-theme{--lime-a1:#11bb0003;--lime-a2:#78f7000a;--lime-a3:#9bfd4c1a;--lime-a4:#a7fe5c29;--lime-a5:#affe6537;--lime-a6:#b2fe6d46;--lime-a7:#b6ff6f57;--lime-a8:#b6fd6d6c;--lime-a9:#caff69ed;--lime-a10:#d4ff70;--lime-a11:#d1fe77e4;--lime-a12:#e9febff7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--lime-a1:color(display-p3 .067 .941 0/.009);--lime-a2:color(display-p3 .584 .996 .071/.038);--lime-a3:color(display-p3 .69 1 .38/.101);--lime-a4:color(display-p3 .729 1 .435/.16);--lime-a5:color(display-p3 .745 1 .471/.215);--lime-a6:color(display-p3 .769 1 .482/.274);--lime-a7:color(display-p3 .769 1 .506/.341);--lime-a8:color(display-p3 .784 1 .51/.416);--lime-a9:color(display-p3 .839 1 .502/.925);--lime-a10:color(display-p3 .871 1 .522/.996);--lime-a11:color(display-p3 .771 .893 .485);--lime-a12:color(display-p3 .905 .966 .753)}}}:root,.light,.light-theme{--yellow-1:#fdfdf9;--yellow-2:#fefce9;--yellow-3:#fffab8;--yellow-4:#fff394;--yellow-5:#ffe770;--yellow-6:#f3d768;--yellow-7:#e4c767;--yellow-8:#d5ae39;--yellow-9:#ffe629;--yellow-10:#ffdc00;--yellow-11:#9e6c00;--yellow-12:#473b1f}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--yellow-1:color(display-p3 .992 .992 .978);--yellow-2:color(display-p3 .995 .99 .922);--yellow-3:color(display-p3 .997 .982 .749);--yellow-4:color(display-p3 .992 .953 .627);--yellow-5:color(display-p3 .984 .91 .51);--yellow-6:color(display-p3 .934 .847 .474);--yellow-7:color(display-p3 .876 .785 .46);--yellow-8:color(display-p3 .811 .689 .313);--yellow-9:color(display-p3 1 .92 .22);--yellow-10:color(display-p3 .977 .868 .291);--yellow-11:color(display-p3 .6 .44 0);--yellow-12:color(display-p3 .271 .233 .137)}}}.dark,.dark-theme{--yellow-1:#14120b;--yellow-2:#1b180f;--yellow-3:#2d2305;--yellow-4:#362b00;--yellow-5:#433500;--yellow-6:#524202;--yellow-7:#665417;--yellow-8:#836a21;--yellow-9:#ffe629;--yellow-10:#ffff57;--yellow-11:#f5e147;--yellow-12:#f6eeb4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--yellow-1:color(display-p3 .078 .069 .047);--yellow-2:color(display-p3 .103 .094 .063);--yellow-3:color(display-p3 .168 .137 .039);--yellow-4:color(display-p3 .209 .169 0);--yellow-5:color(display-p3 .255 .209 0);--yellow-6:color(display-p3 .31 .261 .07);--yellow-7:color(display-p3 .389 .331 .135);--yellow-8:color(display-p3 .497 .42 .182);--yellow-9:color(display-p3 1 .92 .22);--yellow-10:color(display-p3 1 1 .456);--yellow-11:color(display-p3 .948 .885 .392);--yellow-12:color(display-p3 .959 .934 .731)}}}:root,.light,.light-theme{--yellow-a1:#aaaa0006;--yellow-a2:#f4dd0016;--yellow-a3:#ffee0047;--yellow-a4:#ffe3016b;--yellow-a5:#ffd5008f;--yellow-a6:#ebbc0097;--yellow-a7:#d2a10098;--yellow-a8:#c99700c6;--yellow-a9:#ffe100d6;--yellow-a10:#ffdc00;--yellow-a11:#9e6c00;--yellow-a12:#2e2000e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--yellow-a1:color(display-p3 .675 .675 .024/.024);--yellow-a2:color(display-p3 .953 .855 .008/.079);--yellow-a3:color(display-p3 .988 .925 .004/.251);--yellow-a4:color(display-p3 .98 .875 .004/.373);--yellow-a5:color(display-p3 .969 .816 .004/.491);--yellow-a6:color(display-p3 .875 .71 0/.526);--yellow-a7:color(display-p3 .769 .604 0/.542);--yellow-a8:color(display-p3 .725 .549 0/.687);--yellow-a9:color(display-p3 1 .898 0/.781);--yellow-a10:color(display-p3 .969 .812 0/.71);--yellow-a11:color(display-p3 .6 .44 0);--yellow-a12:color(display-p3 .271 .233 .137)}}}.dark,.dark-theme{--yellow-a1:#d1510004;--yellow-a2:#f9b4000b;--yellow-a3:#ffaa001e;--yellow-a4:#fdb70028;--yellow-a5:#febb0036;--yellow-a6:#fec40046;--yellow-a7:#fdcb225c;--yellow-a8:#fdca327b;--yellow-a9:#ffe629;--yellow-a10:#ffff57;--yellow-a11:#fee949f5;--yellow-a12:#fef6baf6}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--yellow-a1:color(display-p3 .973 .369 0/.013);--yellow-a2:color(display-p3 .996 .792 0/.038);--yellow-a3:color(display-p3 .996 .71 0/.11);--yellow-a4:color(display-p3 .996 .741 0/.152);--yellow-a5:color(display-p3 .996 .765 0/.202);--yellow-a6:color(display-p3 .996 .816 .082/.261);--yellow-a7:color(display-p3 1 .831 .263/.345);--yellow-a8:color(display-p3 1 .831 .314/.463);--yellow-a9:color(display-p3 1 .922 .22);--yellow-a10:color(display-p3 1 1 .455);--yellow-a11:color(display-p3 .948 .885 .392);--yellow-a12:color(display-p3 .959 .934 .731)}}}:root,.light,.light-theme{--amber-1:#fefdfb;--amber-2:#fefbe9;--amber-3:#fff7c2;--amber-4:#ffee9c;--amber-5:#fbe577;--amber-6:#f3d673;--amber-7:#e9c162;--amber-8:#e2a336;--amber-9:#ffc53d;--amber-10:#ffba18;--amber-11:#ab6400;--amber-12:#4f3422}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--amber-1:color(display-p3 .995 .992 .985);--amber-2:color(display-p3 .994 .986 .921);--amber-3:color(display-p3 .994 .969 .782);--amber-4:color(display-p3 .989 .937 .65);--amber-5:color(display-p3 .97 .902 .527);--amber-6:color(display-p3 .936 .844 .506);--amber-7:color(display-p3 .89 .762 .443);--amber-8:color(display-p3 .85 .65 .3);--amber-9:color(display-p3 1 .77 .26);--amber-10:color(display-p3 .959 .741 .274);--amber-11:color(display-p3 .64 .4 0);--amber-12:color(display-p3 .294 .208 .145)}}}.dark,.dark-theme{--amber-1:#16120c;--amber-2:#1d180f;--amber-3:#302008;--amber-4:#3f2700;--amber-5:#4d3000;--amber-6:#5c3d05;--amber-7:#714f19;--amber-8:#8f6424;--amber-9:#ffc53d;--amber-10:#ffd60a;--amber-11:#ffca16;--amber-12:#ffe7b3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--amber-1:color(display-p3 .082 .07 .05);--amber-2:color(display-p3 .111 .094 .064);--amber-3:color(display-p3 .178 .128 .049);--amber-4:color(display-p3 .239 .156 0);--amber-5:color(display-p3 .29 .193 0);--amber-6:color(display-p3 .344 .245 .076);--amber-7:color(display-p3 .422 .314 .141);--amber-8:color(display-p3 .535 .399 .189);--amber-9:color(display-p3 1 .77 .26);--amber-10:color(display-p3 1 .87 .15);--amber-11:color(display-p3 1 .8 .29);--amber-12:color(display-p3 .984 .909 .726)}}}:root,.light,.light-theme{--amber-a1:#c0800004;--amber-a2:#f4d10016;--amber-a3:#ffde003d;--amber-a4:#ffd40063;--amber-a5:#f8cf0088;--amber-a6:#eab5008c;--amber-a7:#dc9b009d;--amber-a8:#da8a00c9;--amber-a9:#ffb300c2;--amber-a10:#ffb300e7;--amber-a11:#ab6400;--amber-a12:#341500dd}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--amber-a1:color(display-p3 .757 .514 .024/.016);--amber-a2:color(display-p3 .902 .804 .008/.079);--amber-a3:color(display-p3 .965 .859 .004/.22);--amber-a4:color(display-p3 .969 .82 .004/.35);--amber-a5:color(display-p3 .933 .796 .004/.475);--amber-a6:color(display-p3 .875 .682 .004/.495);--amber-a7:color(display-p3 .804 .573 0/.557);--amber-a8:color(display-p3 .788 .502 0/.699);--amber-a9:color(display-p3 1 .686 0/.742);--amber-a10:color(display-p3 .945 .643 0/.726);--amber-a11:color(display-p3 .64 .4 0);--amber-a12:color(display-p3 .294 .208 .145)}}}.dark,.dark-theme{--amber-a1:#e63c0006;--amber-a2:#fd9b000d;--amber-a3:#fa820022;--amber-a4:#fc820032;--amber-a5:#fd8b0041;--amber-a6:#fd9b0051;--amber-a7:#ffab2567;--amber-a8:#ffae3587;--amber-a9:#ffc53d;--amber-a10:#ffd60a;--amber-a11:#ffca16;--amber-a12:#ffe7b3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--amber-a1:color(display-p3 .992 .298 0/.017);--amber-a2:color(display-p3 .988 .651 0/.047);--amber-a3:color(display-p3 1 .6 0/.118);--amber-a4:color(display-p3 1 .557 0/.185);--amber-a5:color(display-p3 1 .592 0/.24);--amber-a6:color(display-p3 1 .659 .094/.299);--amber-a7:color(display-p3 1 .714 .263/.383);--amber-a8:color(display-p3 .996 .729 .306/.5);--amber-a9:color(display-p3 1 .769 .259);--amber-a10:color(display-p3 1 .871 .149);--amber-a11:color(display-p3 1 .8 .29);--amber-a12:color(display-p3 .984 .909 .726)}}}:root,.light,.light-theme{--gold-1:#fdfdfc;--gold-2:#faf9f2;--gold-3:#f2f0e7;--gold-4:#eae6db;--gold-5:#e1dccf;--gold-6:#d8d0bf;--gold-7:#cbc0aa;--gold-8:#b9a88d;--gold-9:#978365;--gold-10:#8c7a5e;--gold-11:#71624b;--gold-12:#3b352b}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--gold-1:color(display-p3 .992 .992 .989);--gold-2:color(display-p3 .98 .976 .953);--gold-3:color(display-p3 .947 .94 .909);--gold-4:color(display-p3 .914 .904 .865);--gold-5:color(display-p3 .88 .865 .816);--gold-6:color(display-p3 .84 .818 .756);--gold-7:color(display-p3 .788 .753 .677);--gold-8:color(display-p3 .715 .66 .565);--gold-9:color(display-p3 .579 .517 .41);--gold-10:color(display-p3 .538 .479 .38);--gold-11:color(display-p3 .433 .386 .305);--gold-12:color(display-p3 .227 .209 .173)}}}.dark,.dark-theme{--gold-1:#121211;--gold-2:#1b1a17;--gold-3:#24231f;--gold-4:#2d2b26;--gold-5:#38352e;--gold-6:#444039;--gold-7:#544f46;--gold-8:#696256;--gold-9:#978365;--gold-10:#a39073;--gold-11:#cbb99f;--gold-12:#e8e2d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gold-1:color(display-p3 .071 .071 .067);--gold-2:color(display-p3 .104 .101 .09);--gold-3:color(display-p3 .141 .136 .122);--gold-4:color(display-p3 .177 .17 .152);--gold-5:color(display-p3 .217 .207 .185);--gold-6:color(display-p3 .265 .252 .225);--gold-7:color(display-p3 .327 .31 .277);--gold-8:color(display-p3 .407 .384 .342);--gold-9:color(display-p3 .579 .517 .41);--gold-10:color(display-p3 .628 .566 .463);--gold-11:color(display-p3 .784 .728 .635);--gold-12:color(display-p3 .906 .887 .855)}}}:root,.light,.light-theme{--gold-a1:#55550003;--gold-a2:#9d8a000d;--gold-a3:#75600018;--gold-a4:#6b4e0024;--gold-a5:#60460030;--gold-a6:#64440040;--gold-a7:#63420055;--gold-a8:#633d0072;--gold-a9:#5332009a;--gold-a10:#492d00a1;--gold-a11:#362100b4;--gold-a12:#130c00d4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--gold-a1:color(display-p3 .349 .349 .024/.012);--gold-a2:color(display-p3 .592 .514 .024/.048);--gold-a3:color(display-p3 .4 .357 .012/.091);--gold-a4:color(display-p3 .357 .298 .008/.134);--gold-a5:color(display-p3 .345 .282 .004/.185);--gold-a6:color(display-p3 .341 .263 .004/.244);--gold-a7:color(display-p3 .345 .235 .004/.322);--gold-a8:color(display-p3 .345 .22 .004/.436);--gold-a9:color(display-p3 .286 .18 0/.589);--gold-a10:color(display-p3 .255 .161 0/.62);--gold-a11:color(display-p3 .433 .386 .305);--gold-a12:color(display-p3 .227 .209 .173)}}}.dark,.dark-theme{--gold-a1:#91911102;--gold-a2:#f9e29d0b;--gold-a3:#f8ecbb15;--gold-a4:#ffeec41e;--gold-a5:#feecc22a;--gold-a6:#feebcb37;--gold-a7:#ffedcd48;--gold-a8:#fdeaca5f;--gold-a9:#ffdba690;--gold-a10:#fedfb09d;--gold-a11:#fee7c6c8;--gold-a12:#fef7ede7}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gold-a1:color(display-p3 .855 .855 .071/.005);--gold-a2:color(display-p3 .98 .89 .616/.043);--gold-a3:color(display-p3 1 .949 .753/.08);--gold-a4:color(display-p3 1 .933 .8/.118);--gold-a5:color(display-p3 1 .949 .804/.16);--gold-a6:color(display-p3 1 .925 .8/.215);--gold-a7:color(display-p3 1 .945 .831/.278);--gold-a8:color(display-p3 1 .937 .82/.366);--gold-a9:color(display-p3 .996 .882 .69/.551);--gold-a10:color(display-p3 1 .894 .725/.601);--gold-a11:color(display-p3 .784 .728 .635);--gold-a12:color(display-p3 .906 .887 .855)}}}:root,.light,.light-theme{--bronze-1:#fdfcfc;--bronze-2:#fdf7f5;--bronze-3:#f6edea;--bronze-4:#efe4df;--bronze-5:#e7d9d3;--bronze-6:#dfcdc5;--bronze-7:#d3bcb3;--bronze-8:#c2a499;--bronze-9:#a18072;--bronze-10:#957468;--bronze-11:#7d5e54;--bronze-12:#43302b}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--bronze-1:color(display-p3 .991 .988 .988);--bronze-2:color(display-p3 .989 .97 .961);--bronze-3:color(display-p3 .958 .932 .919);--bronze-4:color(display-p3 .929 .894 .877);--bronze-5:color(display-p3 .898 .853 .832);--bronze-6:color(display-p3 .861 .805 .778);--bronze-7:color(display-p3 .812 .739 .706);--bronze-8:color(display-p3 .741 .647 .606);--bronze-9:color(display-p3 .611 .507 .455);--bronze-10:color(display-p3 .563 .461 .414);--bronze-11:color(display-p3 .471 .373 .336);--bronze-12:color(display-p3 .251 .191 .172)}}}.dark,.dark-theme{--bronze-1:#141110;--bronze-2:#1c1917;--bronze-3:#262220;--bronze-4:#302a27;--bronze-5:#3b3330;--bronze-6:#493e3a;--bronze-7:#5a4c47;--bronze-8:#6f5f58;--bronze-9:#a18072;--bronze-10:#ae8c7e;--bronze-11:#d4b3a5;--bronze-12:#ede0d9}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--bronze-1:color(display-p3 .076 .067 .063);--bronze-2:color(display-p3 .106 .097 .093);--bronze-3:color(display-p3 .147 .132 .125);--bronze-4:color(display-p3 .185 .166 .156);--bronze-5:color(display-p3 .227 .202 .19);--bronze-6:color(display-p3 .278 .246 .23);--bronze-7:color(display-p3 .343 .302 .281);--bronze-8:color(display-p3 .426 .374 .347);--bronze-9:color(display-p3 .611 .507 .455);--bronze-10:color(display-p3 .66 .556 .504);--bronze-11:color(display-p3 .81 .707 .655);--bronze-12:color(display-p3 .921 .88 .854)}}}:root,.light,.light-theme{--bronze-a1:#55000003;--bronze-a2:#cc33000a;--bronze-a3:#92250015;--bronze-a4:#80280020;--bronze-a5:#7423002c;--bronze-a6:#7324003a;--bronze-a7:#6c1f004c;--bronze-a8:#671c0066;--bronze-a9:#551a008d;--bronze-a10:#4c150097;--bronze-a11:#3d0f00ab;--bronze-a12:#1d0600d4}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--bronze-a1:color(display-p3 .349 .024 .024/.012);--bronze-a2:color(display-p3 .71 .22 .024/.04);--bronze-a3:color(display-p3 .482 .2 .008/.083);--bronze-a4:color(display-p3 .424 .133 .004/.122);--bronze-a5:color(display-p3 .4 .145 .004/.169);--bronze-a6:color(display-p3 .388 .125 .004/.224);--bronze-a7:color(display-p3 .365 .11 .004/.295);--bronze-a8:color(display-p3 .341 .102 .004/.393);--bronze-a9:color(display-p3 .29 .094 0/.546);--bronze-a10:color(display-p3 .255 .082 0/.585);--bronze-a11:color(display-p3 .471 .373 .336);--bronze-a12:color(display-p3 .251 .191 .172)}}}.dark,.dark-theme{--bronze-a1:#d1110004;--bronze-a2:#fbbc910c;--bronze-a3:#faceb817;--bronze-a4:#facdb622;--bronze-a5:#ffd2c12d;--bronze-a6:#ffd1c03c;--bronze-a7:#fdd0c04f;--bronze-a8:#ffd6c565;--bronze-a9:#fec7b09b;--bronze-a10:#fecab5a9;--bronze-a11:#ffd7c6d1;--bronze-a12:#fff1e9ec}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--bronze-a1:color(display-p3 .941 .067 0/.009);--bronze-a2:color(display-p3 .98 .8 .706/.043);--bronze-a3:color(display-p3 .988 .851 .761/.085);--bronze-a4:color(display-p3 .996 .839 .78/.127);--bronze-a5:color(display-p3 .996 .863 .773/.173);--bronze-a6:color(display-p3 1 .863 .796/.227);--bronze-a7:color(display-p3 1 .867 .8/.295);--bronze-a8:color(display-p3 1 .859 .788/.387);--bronze-a9:color(display-p3 1 .82 .733/.585);--bronze-a10:color(display-p3 1 .839 .761/.635);--bronze-a11:color(display-p3 .81 .707 .655);--bronze-a12:color(display-p3 .921 .88 .854)}}}:root,.light,.light-theme{--gray-1:#fcfcfc;--gray-2:#f9f9f9;--gray-3:#f0f0f0;--gray-4:#e8e8e8;--gray-5:#e0e0e0;--gray-6:#d9d9d9;--gray-7:#cecece;--gray-8:#bbb;--gray-9:#8d8d8d;--gray-10:#838383;--gray-11:#646464;--gray-12:#202020}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--gray-1:color(display-p3 .988 .988 .988);--gray-2:color(display-p3 .975 .975 .975);--gray-3:color(display-p3 .939 .939 .939);--gray-4:color(display-p3 .908 .908 .908);--gray-5:color(display-p3 .88 .88 .88);--gray-6:color(display-p3 .849 .849 .849);--gray-7:color(display-p3 .807 .807 .807);--gray-8:color(display-p3 .732 .732 .732);--gray-9:color(display-p3 .553 .553 .553);--gray-10:color(display-p3 .512 .512 .512);--gray-11:color(display-p3 .392 .392 .392);--gray-12:color(display-p3 .125 .125 .125)}}}.dark,.dark-theme{--gray-1:#111;--gray-2:#191919;--gray-3:#222;--gray-4:#2a2a2a;--gray-5:#313131;--gray-6:#3a3a3a;--gray-7:#484848;--gray-8:#606060;--gray-9:#6e6e6e;--gray-10:#7b7b7b;--gray-11:#b4b4b4;--gray-12:#eee}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gray-1:color(display-p3 .067 .067 .067);--gray-2:color(display-p3 .098 .098 .098);--gray-3:color(display-p3 .135 .135 .135);--gray-4:color(display-p3 .163 .163 .163);--gray-5:color(display-p3 .192 .192 .192);--gray-6:color(display-p3 .228 .228 .228);--gray-7:color(display-p3 .283 .283 .283);--gray-8:color(display-p3 .375 .375 .375);--gray-9:color(display-p3 .431 .431 .431);--gray-10:color(display-p3 .484 .484 .484);--gray-11:color(display-p3 .706 .706 .706);--gray-12:color(display-p3 .933 .933 .933)}}}:root,.light,.light-theme{--gray-a1:#00000003;--gray-a2:#00000006;--gray-a3:#0000000f;--gray-a4:#00000017;--gray-a5:#0000001f;--gray-a6:#00000026;--gray-a7:#00000031;--gray-a8:#0004;--gray-a9:#00000072;--gray-a10:#0000007c;--gray-a11:#0000009b;--gray-a12:#000000df}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--gray-a1:color(display-p3 0 0 0/.012);--gray-a2:color(display-p3 0 0 0/.024);--gray-a3:color(display-p3 0 0 0/.063);--gray-a4:color(display-p3 0 0 0/.09);--gray-a5:color(display-p3 0 0 0/.122);--gray-a6:color(display-p3 0 0 0/.153);--gray-a7:color(display-p3 0 0 0/.192);--gray-a8:color(display-p3 0 0 0/.267);--gray-a9:color(display-p3 0 0 0/.447);--gray-a10:color(display-p3 0 0 0/.486);--gray-a11:color(display-p3 0 0 0/.608);--gray-a12:color(display-p3 0 0 0/.875)}}}.dark,.dark-theme{--gray-a1:#0000;--gray-a2:#ffffff09;--gray-a3:#ffffff12;--gray-a4:#ffffff1b;--gray-a5:#fff2;--gray-a6:#ffffff2c;--gray-a7:#ffffff3b;--gray-a8:#fff5;--gray-a9:#ffffff64;--gray-a10:#ffffff72;--gray-a11:#ffffffaf;--gray-a12:#ffffffed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gray-a1:color(display-p3 0 0 0/0);--gray-a2:color(display-p3 1 1 1/.034);--gray-a3:color(display-p3 1 1 1/.071);--gray-a4:color(display-p3 1 1 1/.105);--gray-a5:color(display-p3 1 1 1/.134);--gray-a6:color(display-p3 1 1 1/.172);--gray-a7:color(display-p3 1 1 1/.231);--gray-a8:color(display-p3 1 1 1/.332);--gray-a9:color(display-p3 1 1 1/.391);--gray-a10:color(display-p3 1 1 1/.445);--gray-a11:color(display-p3 1 1 1/.685);--gray-a12:color(display-p3 1 1 1/.929)}}}:root,.light,.light-theme{--mauve-1:#fdfcfd;--mauve-2:#faf9fb;--mauve-3:#f2eff3;--mauve-4:#eae7ec;--mauve-5:#e3dfe6;--mauve-6:#dbd8e0;--mauve-7:#d0cdd7;--mauve-8:#bcbac7;--mauve-9:#8e8c99;--mauve-10:#84828e;--mauve-11:#65636d;--mauve-12:#211f26}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--mauve-1:color(display-p3 .991 .988 .992);--mauve-2:color(display-p3 .98 .976 .984);--mauve-3:color(display-p3 .946 .938 .952);--mauve-4:color(display-p3 .915 .906 .925);--mauve-5:color(display-p3 .886 .876 .901);--mauve-6:color(display-p3 .856 .846 .875);--mauve-7:color(display-p3 .814 .804 .84);--mauve-8:color(display-p3 .735 .728 .777);--mauve-9:color(display-p3 .555 .549 .596);--mauve-10:color(display-p3 .514 .508 .552);--mauve-11:color(display-p3 .395 .388 .424);--mauve-12:color(display-p3 .128 .122 .147)}}}.dark,.dark-theme{--mauve-1:#121113;--mauve-2:#1a191b;--mauve-3:#232225;--mauve-4:#2b292d;--mauve-5:#323035;--mauve-6:#3c393f;--mauve-7:#49474e;--mauve-8:#625f69;--mauve-9:#6f6d78;--mauve-10:#7c7a85;--mauve-11:#b5b2bc;--mauve-12:#eeeef0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mauve-1:color(display-p3 .07 .067 .074);--mauve-2:color(display-p3 .101 .098 .105);--mauve-3:color(display-p3 .138 .134 .144);--mauve-4:color(display-p3 .167 .161 .175);--mauve-5:color(display-p3 .196 .189 .206);--mauve-6:color(display-p3 .232 .225 .245);--mauve-7:color(display-p3 .286 .277 .302);--mauve-8:color(display-p3 .383 .373 .408);--mauve-9:color(display-p3 .434 .428 .467);--mauve-10:color(display-p3 .487 .48 .519);--mauve-11:color(display-p3 .707 .7 .735);--mauve-12:color(display-p3 .933 .933 .94)}}}:root,.light,.light-theme{--mauve-a1:#55005503;--mauve-a2:#2b005506;--mauve-a3:#30004010;--mauve-a4:#20003618;--mauve-a5:#20003820;--mauve-a6:#14003527;--mauve-a7:#10003332;--mauve-a8:#08003145;--mauve-a9:#05001d73;--mauve-a10:#0500197d;--mauve-a11:#0400119c;--mauve-a12:#020008e0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--mauve-a1:color(display-p3 .349 .024 .349/.012);--mauve-a2:color(display-p3 .184 .024 .349/.024);--mauve-a3:color(display-p3 .129 .008 .255/.063);--mauve-a4:color(display-p3 .094 .012 .216/.095);--mauve-a5:color(display-p3 .098 .008 .224/.126);--mauve-a6:color(display-p3 .055 .004 .18/.153);--mauve-a7:color(display-p3 .067 .008 .184/.197);--mauve-a8:color(display-p3 .02 .004 .176/.271);--mauve-a9:color(display-p3 .02 .004 .106/.451);--mauve-a10:color(display-p3 .012 .004 .09/.491);--mauve-a11:color(display-p3 .016 0 .059/.612);--mauve-a12:color(display-p3 .008 0 .027/.879)}}}.dark,.dark-theme{--mauve-a1:#0000;--mauve-a2:#f5f4f609;--mauve-a3:#ebeaf814;--mauve-a4:#eee5f81d;--mauve-a5:#efe6fe25;--mauve-a6:#f1e6fd30;--mauve-a7:#eee9ff40;--mauve-a8:#eee7ff5d;--mauve-a9:#eae6fd6e;--mauve-a10:#ece9fd7c;--mauve-a11:#f5f1ffb7;--mauve-a12:#fdfdffef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--mauve-a1:color(display-p3 0 0 0/0);--mauve-a2:color(display-p3 .996 .992 1/.034);--mauve-a3:color(display-p3 .937 .933 .992/.077);--mauve-a4:color(display-p3 .957 .918 .996/.111);--mauve-a5:color(display-p3 .937 .906 .996/.145);--mauve-a6:color(display-p3 .953 .925 .996/.183);--mauve-a7:color(display-p3 .945 .929 1/.246);--mauve-a8:color(display-p3 .937 .918 1/.361);--mauve-a9:color(display-p3 .933 .918 1/.424);--mauve-a10:color(display-p3 .941 .925 1/.479);--mauve-a11:color(display-p3 .965 .961 1/.712);--mauve-a12:color(display-p3 .992 .992 1/.937)}}}:root,.light,.light-theme{--slate-1:#fcfcfd;--slate-2:#f9f9fb;--slate-3:#f0f0f3;--slate-4:#e8e8ec;--slate-5:#e0e1e6;--slate-6:#d9d9e0;--slate-7:#cdced6;--slate-8:#b9bbc6;--slate-9:#8b8d98;--slate-10:#80838d;--slate-11:#60646c;--slate-12:#1c2024}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--slate-1:color(display-p3 .988 .988 .992);--slate-2:color(display-p3 .976 .976 .984);--slate-3:color(display-p3 .94 .941 .953);--slate-4:color(display-p3 .908 .909 .925);--slate-5:color(display-p3 .88 .881 .901);--slate-6:color(display-p3 .85 .852 .876);--slate-7:color(display-p3 .805 .808 .838);--slate-8:color(display-p3 .727 .733 .773);--slate-9:color(display-p3 .547 .553 .592);--slate-10:color(display-p3 .503 .512 .549);--slate-11:color(display-p3 .379 .392 .421);--slate-12:color(display-p3 .113 .125 .14)}}}.dark,.dark-theme{--slate-1:#111113;--slate-2:#18191b;--slate-3:#212225;--slate-4:#272a2d;--slate-5:#2e3135;--slate-6:#363a3f;--slate-7:#43484e;--slate-8:#5a6169;--slate-9:#696e77;--slate-10:#777b84;--slate-11:#b0b4ba;--slate-12:#edeef0}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--slate-1:color(display-p3 .067 .067 .074);--slate-2:color(display-p3 .095 .098 .105);--slate-3:color(display-p3 .13 .135 .145);--slate-4:color(display-p3 .156 .163 .176);--slate-5:color(display-p3 .183 .191 .206);--slate-6:color(display-p3 .215 .226 .244);--slate-7:color(display-p3 .265 .28 .302);--slate-8:color(display-p3 .357 .381 .409);--slate-9:color(display-p3 .415 .431 .463);--slate-10:color(display-p3 .469 .483 .514);--slate-11:color(display-p3 .692 .704 .728);--slate-12:color(display-p3 .93 .933 .94)}}}:root,.light,.light-theme{--slate-a1:#00005503;--slate-a2:#00005506;--slate-a3:#0000330f;--slate-a4:#00002d17;--slate-a5:#0009321f;--slate-a6:#00002f26;--slate-a7:#00062e32;--slate-a8:#00083046;--slate-a9:#00051d74;--slate-a10:#00071b7f;--slate-a11:#0007149f;--slate-a12:#000509e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--slate-a1:color(display-p3 .024 .024 .349/.012);--slate-a2:color(display-p3 .024 .024 .349/.024);--slate-a3:color(display-p3 .004 .004 .204/.059);--slate-a4:color(display-p3 .012 .012 .184/.091);--slate-a5:color(display-p3 .004 .039 .2/.122);--slate-a6:color(display-p3 .008 .008 .165/.15);--slate-a7:color(display-p3 .008 .027 .184/.197);--slate-a8:color(display-p3 .004 .031 .176/.275);--slate-a9:color(display-p3 .004 .02 .106/.455);--slate-a10:color(display-p3 .004 .027 .098/.499);--slate-a11:color(display-p3 0 .02 .063/.62);--slate-a12:color(display-p3 0 .012 .031/.887)}}}.dark,.dark-theme{--slate-a1:#0000;--slate-a2:#d8f4f609;--slate-a3:#ddeaf814;--slate-a4:#d3edf81d;--slate-a5:#d9edfe25;--slate-a6:#d6ebfd30;--slate-a7:#d9edff40;--slate-a8:#d9edff5d;--slate-a9:#dfebfd6d;--slate-a10:#e5edfd7b;--slate-a11:#f1f7feb5;--slate-a12:#fcfdffef}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--slate-a1:color(display-p3 0 0 0/0);--slate-a2:color(display-p3 .875 .992 1/.034);--slate-a3:color(display-p3 .882 .933 .992/.077);--slate-a4:color(display-p3 .882 .953 .996/.111);--slate-a5:color(display-p3 .878 .929 .996/.145);--slate-a6:color(display-p3 .882 .949 .996/.183);--slate-a7:color(display-p3 .882 .929 1/.246);--slate-a8:color(display-p3 .871 .937 1/.361);--slate-a9:color(display-p3 .898 .937 1/.42);--slate-a10:color(display-p3 .918 .945 1/.475);--slate-a11:color(display-p3 .949 .969 .996/.708);--slate-a12:color(display-p3 .988 .992 1/.937)}}}:root,.light,.light-theme{--sage-1:#fbfdfc;--sage-2:#f7f9f8;--sage-3:#eef1f0;--sage-4:#e6e9e8;--sage-5:#dfe2e0;--sage-6:#d7dad9;--sage-7:#cbcfcd;--sage-8:#b8bcba;--sage-9:#868e8b;--sage-10:#7c8481;--sage-11:#5f6563;--sage-12:#1a211e}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sage-1:color(display-p3 .986 .992 .988);--sage-2:color(display-p3 .97 .977 .974);--sage-3:color(display-p3 .935 .944 .94);--sage-4:color(display-p3 .904 .913 .909);--sage-5:color(display-p3 .875 .885 .88);--sage-6:color(display-p3 .844 .854 .849);--sage-7:color(display-p3 .8 .811 .806);--sage-8:color(display-p3 .725 .738 .732);--sage-9:color(display-p3 .531 .556 .546);--sage-10:color(display-p3 .492 .515 .506);--sage-11:color(display-p3 .377 .395 .389);--sage-12:color(display-p3 .107 .129 .118)}}}.dark,.dark-theme{--sage-1:#101211;--sage-2:#171918;--sage-3:#202221;--sage-4:#272a29;--sage-5:#2e3130;--sage-6:#373b39;--sage-7:#444947;--sage-8:#5b625f;--sage-9:#63706b;--sage-10:#717d79;--sage-11:#adb5b2;--sage-12:#eceeed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sage-1:color(display-p3 .064 .07 .067);--sage-2:color(display-p3 .092 .098 .094);--sage-3:color(display-p3 .128 .135 .131);--sage-4:color(display-p3 .155 .164 .159);--sage-5:color(display-p3 .183 .193 .188);--sage-6:color(display-p3 .218 .23 .224);--sage-7:color(display-p3 .269 .285 .277);--sage-8:color(display-p3 .362 .382 .373);--sage-9:color(display-p3 .398 .438 .421);--sage-10:color(display-p3 .453 .49 .474);--sage-11:color(display-p3 .685 .709 .697);--sage-12:color(display-p3 .927 .933 .93)}}}:root,.light,.light-theme{--sage-a1:#00804004;--sage-a2:#00402008;--sage-a3:#002d1e11;--sage-a4:#001f1519;--sage-a5:#00180820;--sage-a6:#00140d28;--sage-a7:#00140a34;--sage-a8:#000f0847;--sage-a9:#00110b79;--sage-a10:#00100a83;--sage-a11:#000a07a0;--sage-a12:#000805e5}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sage-a1:color(display-p3 .024 .514 .267/.016);--sage-a2:color(display-p3 .02 .267 .145/.032);--sage-a3:color(display-p3 .008 .184 .125/.067);--sage-a4:color(display-p3 .012 .094 .051/.095);--sage-a5:color(display-p3 .008 .098 .035/.126);--sage-a6:color(display-p3 .004 .078 .027/.157);--sage-a7:color(display-p3 0 .059 .039/.2);--sage-a8:color(display-p3 .004 .047 .031/.275);--sage-a9:color(display-p3 .004 .059 .035/.471);--sage-a10:color(display-p3 0 .047 .031/.51);--sage-a11:color(display-p3 0 .031 .02/.624);--sage-a12:color(display-p3 0 .027 .012/.895)}}}.dark,.dark-theme{--sage-a1:#0000;--sage-a2:#f0f2f108;--sage-a3:#f3f5f412;--sage-a4:#f2fefd1a;--sage-a5:#f1fbfa22;--sage-a6:#edfbf42d;--sage-a7:#edfcf73c;--sage-a8:#ebfdf657;--sage-a9:#dffdf266;--sage-a10:#e5fdf674;--sage-a11:#f4fefbb0;--sage-a12:#fdfffeed}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sage-a1:color(display-p3 0 0 0/0);--sage-a2:color(display-p3 .976 .988 .984/.03);--sage-a3:color(display-p3 .992 .945 .941/.072);--sage-a4:color(display-p3 .988 .996 .992/.102);--sage-a5:color(display-p3 .992 1 .996/.131);--sage-a6:color(display-p3 .973 1 .976/.173);--sage-a7:color(display-p3 .957 1 .976/.233);--sage-a8:color(display-p3 .957 1 .984/.334);--sage-a9:color(display-p3 .902 1 .957/.397);--sage-a10:color(display-p3 .929 1 .973/.452);--sage-a11:color(display-p3 .969 1 .988/.688);--sage-a12:color(display-p3 .992 1 .996/.929)}}}:root,.light,.light-theme{--olive-1:#fcfdfc;--olive-2:#f8faf8;--olive-3:#eff1ef;--olive-4:#e7e9e7;--olive-5:#dfe2df;--olive-6:#d7dad7;--olive-7:#cccfcc;--olive-8:#b9bcb8;--olive-9:#898e87;--olive-10:#7f847d;--olive-11:#60655f;--olive-12:#1d211c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--olive-1:color(display-p3 .989 .992 .989);--olive-2:color(display-p3 .974 .98 .973);--olive-3:color(display-p3 .939 .945 .937);--olive-4:color(display-p3 .907 .914 .905);--olive-5:color(display-p3 .878 .885 .875);--olive-6:color(display-p3 .846 .855 .843);--olive-7:color(display-p3 .803 .812 .8);--olive-8:color(display-p3 .727 .738 .723);--olive-9:color(display-p3 .541 .556 .532);--olive-10:color(display-p3 .5 .515 .491);--olive-11:color(display-p3 .38 .395 .374);--olive-12:color(display-p3 .117 .129 .111)}}}.dark,.dark-theme{--olive-1:#111210;--olive-2:#181917;--olive-3:#212220;--olive-4:#282a27;--olive-5:#2f312e;--olive-6:#383a36;--olive-7:#454843;--olive-8:#5c625b;--olive-9:#687066;--olive-10:#767d74;--olive-11:#afb5ad;--olive-12:#eceeec}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--olive-1:color(display-p3 .067 .07 .063);--olive-2:color(display-p3 .095 .098 .091);--olive-3:color(display-p3 .131 .135 .126);--olive-4:color(display-p3 .158 .163 .153);--olive-5:color(display-p3 .186 .192 .18);--olive-6:color(display-p3 .221 .229 .215);--olive-7:color(display-p3 .273 .284 .266);--olive-8:color(display-p3 .365 .382 .359);--olive-9:color(display-p3 .414 .438 .404);--olive-10:color(display-p3 .467 .49 .458);--olive-11:color(display-p3 .69 .709 .682);--olive-12:color(display-p3 .927 .933 .926)}}}:root,.light,.light-theme{--olive-a1:#00550003;--olive-a2:#00490007;--olive-a3:#00200010;--olive-a4:#00160018;--olive-a5:#00180020;--olive-a6:#00140028;--olive-a7:#000f0033;--olive-a8:#040f0047;--olive-a9:#050f0078;--olive-a10:#040e0082;--olive-a11:#020a00a0;--olive-a12:#010600e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--olive-a1:color(display-p3 .024 .349 .024/.012);--olive-a2:color(display-p3 .024 .302 .024/.028);--olive-a3:color(display-p3 .008 .129 .008/.063);--olive-a4:color(display-p3 .012 .094 .012/.095);--olive-a5:color(display-p3 .035 .098 .008/.126);--olive-a6:color(display-p3 .027 .078 .004/.157);--olive-a7:color(display-p3 .02 .059 0/.2);--olive-a8:color(display-p3 .02 .059 .004/.279);--olive-a9:color(display-p3 .02 .051 .004/.467);--olive-a10:color(display-p3 .024 .047 0/.51);--olive-a11:color(display-p3 .012 .039 0/.628);--olive-a12:color(display-p3 .008 .024 0/.891)}}}.dark,.dark-theme{--olive-a1:#0000;--olive-a2:#f1f2f008;--olive-a3:#f4f5f312;--olive-a4:#f3fef21a;--olive-a5:#f2fbf122;--olive-a6:#f4faed2c;--olive-a7:#f2fced3b;--olive-a8:#edfdeb57;--olive-a9:#ebfde766;--olive-a10:#f0fdec74;--olive-a11:#f6fef4b0;--olive-a12:#fdfffded}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--olive-a1:color(display-p3 0 0 0/0);--olive-a2:color(display-p3 .984 .988 .976/.03);--olive-a3:color(display-p3 .992 .996 .988/.068);--olive-a4:color(display-p3 .953 .996 .949/.102);--olive-a5:color(display-p3 .969 1 .965/.131);--olive-a6:color(display-p3 .973 1 .969/.169);--olive-a7:color(display-p3 .98 1 .961/.228);--olive-a8:color(display-p3 .961 1 .957/.334);--olive-a9:color(display-p3 .949 1 .922/.397);--olive-a10:color(display-p3 .953 1 .941/.452);--olive-a11:color(display-p3 .976 1 .965/.688);--olive-a12:color(display-p3 .992 1 .992/.929)}}}:root,.light,.light-theme{--sand-1:#fdfdfc;--sand-2:#f9f9f8;--sand-3:#f1f0ef;--sand-4:#e9e8e6;--sand-5:#e2e1de;--sand-6:#dad9d6;--sand-7:#cfceca;--sand-8:#bcbbb5;--sand-9:#8d8d86;--sand-10:#82827c;--sand-11:#63635e;--sand-12:#21201c}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sand-1:color(display-p3 .992 .992 .989);--sand-2:color(display-p3 .977 .977 .973);--sand-3:color(display-p3 .943 .942 .936);--sand-4:color(display-p3 .913 .912 .903);--sand-5:color(display-p3 .885 .883 .873);--sand-6:color(display-p3 .854 .852 .839);--sand-7:color(display-p3 .813 .81 .794);--sand-8:color(display-p3 .738 .734 .713);--sand-9:color(display-p3 .553 .553 .528);--sand-10:color(display-p3 .511 .511 .488);--sand-11:color(display-p3 .388 .388 .37);--sand-12:color(display-p3 .129 .126 .111)}}}.dark,.dark-theme{--sand-1:#111110;--sand-2:#191918;--sand-3:#222221;--sand-4:#2a2a28;--sand-5:#31312e;--sand-6:#3b3a37;--sand-7:#494844;--sand-8:#62605b;--sand-9:#6f6d66;--sand-10:#7c7b74;--sand-11:#b5b3ad;--sand-12:#eeeeec}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sand-1:color(display-p3 .067 .067 .063);--sand-2:color(display-p3 .098 .098 .094);--sand-3:color(display-p3 .135 .135 .129);--sand-4:color(display-p3 .164 .163 .156);--sand-5:color(display-p3 .193 .192 .183);--sand-6:color(display-p3 .23 .229 .217);--sand-7:color(display-p3 .285 .282 .267);--sand-8:color(display-p3 .384 .378 .357);--sand-9:color(display-p3 .434 .428 .403);--sand-10:color(display-p3 .487 .481 .456);--sand-11:color(display-p3 .707 .703 .68);--sand-12:color(display-p3 .933 .933 .926)}}}:root,.light,.light-theme{--sand-a1:#55550003;--sand-a2:#25250007;--sand-a3:#20100010;--sand-a4:#1f150019;--sand-a5:#1f180021;--sand-a6:#19130029;--sand-a7:#19140035;--sand-a8:#1915014a;--sand-a9:#0f0f0079;--sand-a10:#0c0c0083;--sand-a11:#080800a1;--sand-a12:#060500e3}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--sand-a1:color(display-p3 .349 .349 .024/.012);--sand-a2:color(display-p3 .161 .161 .024/.028);--sand-a3:color(display-p3 .067 .067 .008/.063);--sand-a4:color(display-p3 .129 .129 .012/.099);--sand-a5:color(display-p3 .098 .067 .008/.126);--sand-a6:color(display-p3 .102 .075 .004/.161);--sand-a7:color(display-p3 .098 .098 .004/.208);--sand-a8:color(display-p3 .086 .075 .004/.287);--sand-a9:color(display-p3 .051 .051 .004/.471);--sand-a10:color(display-p3 .047 .047 0/.514);--sand-a11:color(display-p3 .031 .031 0/.632);--sand-a12:color(display-p3 .024 .02 0/.891)}}}.dark,.dark-theme{--sand-a1:#0000;--sand-a2:#f4f4f309;--sand-a3:#f6f6f513;--sand-a4:#fefef31b;--sand-a5:#fbfbeb23;--sand-a6:#fffaed2d;--sand-a7:#fffbed3c;--sand-a8:#fff9eb57;--sand-a9:#fffae965;--sand-a10:#fffdee73;--sand-a11:#fffcf4b0;--sand-a12:#fffffded}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--sand-a1:color(display-p3 0 0 0/0);--sand-a2:color(display-p3 .992 .992 .988/.034);--sand-a3:color(display-p3 .996 .996 .992/.072);--sand-a4:color(display-p3 .992 .992 .953/.106);--sand-a5:color(display-p3 1 1 .965/.135);--sand-a6:color(display-p3 1 .976 .929/.177);--sand-a7:color(display-p3 1 .984 .929/.236);--sand-a8:color(display-p3 1 .976 .925/.341);--sand-a9:color(display-p3 1 .98 .925/.395);--sand-a10:color(display-p3 1 .992 .933/.45);--sand-a11:color(display-p3 1 .996 .961/.685);--sand-a12:color(display-p3 1 1 .992/.929)}}}:root{--black-a1:#0000000d;--black-a2:#0000001a;--black-a3:#00000026;--black-a4:#0003;--black-a5:#0000004d;--black-a6:#0006;--black-a7:#00000080;--black-a8:#0009;--black-a9:#000000b3;--black-a10:#000c;--black-a11:#000000e6;--black-a12:#000000f2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root{--black-a1:color(display-p3 0 0 0/.05);--black-a2:color(display-p3 0 0 0/.1);--black-a3:color(display-p3 0 0 0/.15);--black-a4:color(display-p3 0 0 0/.2);--black-a5:color(display-p3 0 0 0/.3);--black-a6:color(display-p3 0 0 0/.4);--black-a7:color(display-p3 0 0 0/.5);--black-a8:color(display-p3 0 0 0/.6);--black-a9:color(display-p3 0 0 0/.7);--black-a10:color(display-p3 0 0 0/.8);--black-a11:color(display-p3 0 0 0/.9);--black-a12:color(display-p3 0 0 0/.95)}}}:root{--white-a1:#ffffff0d;--white-a2:#ffffff1a;--white-a3:#ffffff26;--white-a4:#fff3;--white-a5:#ffffff4d;--white-a6:#fff6;--white-a7:#ffffff80;--white-a8:#fff9;--white-a9:#ffffffb3;--white-a10:#fffc;--white-a11:#ffffffe6;--white-a12:#fffffff2}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root{--white-a1:color(display-p3 1 1 1/.05);--white-a2:color(display-p3 1 1 1/.1);--white-a3:color(display-p3 1 1 1/.15);--white-a4:color(display-p3 1 1 1/.2);--white-a5:color(display-p3 1 1 1/.3);--white-a6:color(display-p3 1 1 1/.4);--white-a7:color(display-p3 1 1 1/.5);--white-a8:color(display-p3 1 1 1/.6);--white-a9:color(display-p3 1 1 1/.7);--white-a10:color(display-p3 1 1 1/.8);--white-a11:color(display-p3 1 1 1/.9);--white-a12:color(display-p3 1 1 1/.95)}}}:root{--tomato-contrast:white;--red-contrast:white;--ruby-contrast:white;--crimson-contrast:white;--pink-contrast:white;--plum-contrast:white;--purple-contrast:white;--violet-contrast:white;--iris-contrast:white;--indigo-contrast:white;--blue-contrast:white;--cyan-contrast:white;--teal-contrast:white;--jade-contrast:white;--green-contrast:white;--grass-contrast:white;--orange-contrast:white;--brown-contrast:white;--sky-contrast:#1c2024;--mint-contrast:#1a211e;--lime-contrast:#1d211c;--yellow-contrast:#21201c;--amber-contrast:#21201c;--gold-contrast:white;--bronze-contrast:white;--gray-contrast:white}:root,.light,.light-theme{--gray-surface:#fffc;--mauve-surface:#fffc;--slate-surface:#fffc;--sage-surface:#fffc;--olive-surface:#fffc;--sand-surface:#fffc;--tomato-surface:#fff6f5cc;--red-surface:#fff5f5cc;--ruby-surface:#fff5f6cc;--crimson-surface:#fef5f8cc;--pink-surface:#fef5facc;--plum-surface:#fdf5fdcc;--purple-surface:#faf5fecc;--violet-surface:#f9f6ffcc;--iris-surface:#f6f6ffcc;--indigo-surface:#f5f8ffcc;--blue-surface:#f1f9ffcc;--cyan-surface:#eff9facc;--teal-surface:#f0faf8cc;--jade-surface:#f1faf5cc;--green-surface:#f1faf4cc;--grass-surface:#f3faf3cc;--brown-surface:#fbf8f4cc;--bronze-surface:#fdf5f3cc;--gold-surface:#f9f8efcc;--sky-surface:#eef9fdcc;--mint-surface:#effaf8cc;--lime-surface:#f6f9f0cc;--yellow-surface:#fefbe4cc;--amber-surface:#fefae4cc;--orange-surface:#fff5e9cc}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){:root,.light,.light-theme{--gray-surface:color(display-p3 1 1 1/.8);--mauve-surface:color(display-p3 1 1 1/.8);--slate-surface:color(display-p3 1 1 1/.8);--sage-surface:color(display-p3 1 1 1/.8);--olive-surface:color(display-p3 1 1 1/.8);--sand-surface:color(display-p3 1 1 1/.8);--tomato-surface:color(display-p3 .9922 .9647 .9608/.8);--red-surface:color(display-p3 .9961 .9647 .9647/.8);--ruby-surface:color(display-p3 .9961 .9647 .9647/.8);--crimson-surface:color(display-p3 .9922 .9608 .9725/.8);--pink-surface:color(display-p3 .9922 .9608 .9804/.8);--plum-surface:color(display-p3 .9843 .9647 .9843/.8);--purple-surface:color(display-p3 .9804 .9647 .9922/.8);--violet-surface:color(display-p3 .9725 .9647 .9961/.8);--iris-surface:color(display-p3 .9647 .9647 .9961/.8);--indigo-surface:color(display-p3 .9647 .9725 .9961/.8);--blue-surface:color(display-p3 .9529 .9765 .9961/.8);--cyan-surface:color(display-p3 .9412 .9765 .9804/.8);--teal-surface:color(display-p3 .9451 .9804 .9725/.8);--jade-surface:color(display-p3 .9529 .9804 .9608/.8);--green-surface:color(display-p3 .9569 .9804 .9608/.8);--grass-surface:color(display-p3 .9569 .9804 .9569/.8);--brown-surface:color(display-p3 .9843 .9725 .9569/.8);--bronze-surface:color(display-p3 .9843 .9608 .9529/.8);--gold-surface:color(display-p3 .9765 .9725 .9412/.8);--sky-surface:color(display-p3 .9412 .9765 .9843/.8);--mint-surface:color(display-p3 .9451 .9804 .9725/.8);--lime-surface:color(display-p3 .9725 .9765 .9412/.8);--yellow-surface:color(display-p3 .9961 .9922 .902/.8);--amber-surface:color(display-p3 .9922 .9843 .902/.8);--orange-surface:color(display-p3 .9961 .9608 .9176/.8)}}}.dark,.dark-theme{--gray-surface:#21212180;--mauve-surface:#22212380;--slate-surface:#1f212380;--sage-surface:#1e201f80;--olive-surface:#1f201e80;--sand-surface:#21212080;--tomato-surface:#2d191580;--red-surface:#2f151780;--ruby-surface:#2b191d80;--crimson-surface:#2f151f80;--pink-surface:#31132980;--plum-surface:#2f152f80;--purple-surface:#2b173580;--violet-surface:#25193980;--iris-surface:#1d1b3980;--indigo-surface:#171d3b80;--blue-surface:#11213d80;--cyan-surface:#11252d80;--teal-surface:#13272580;--jade-surface:#13271f80;--green-surface:#15251d80;--grass-surface:#19231b80;--brown-surface:#271f1b80;--bronze-surface:#27211d80;--gold-surface:#25231d80;--sky-surface:#13233b80;--mint-surface:#15272780;--lime-surface:#1b211580;--yellow-surface:#231f1380;--amber-surface:#271f1380;--orange-surface:#271d1380}@supports (color:color(display-p3 1 1 1)){@media (color-gamut:p3){.dark,.dark-theme{--gray-surface:color(display-p3 .1255 .1255 .1255/.5);--mauve-surface:color(display-p3 .1333 .1255 .1333/.5);--slate-surface:color(display-p3 .1176 .1255 .1333/.5);--sage-surface:color(display-p3 .1176 .1255 .1176/.5);--olive-surface:color(display-p3 .1176 .1255 .1176/.5);--sand-surface:color(display-p3 .1255 .1255 .1255/.5);--tomato-surface:color(display-p3 .1569 .0941 .0784/.5);--red-surface:color(display-p3 .1647 .0863 .0863/.5);--ruby-surface:color(display-p3 .1569 .0941 .1098/.5);--crimson-surface:color(display-p3 .1647 .0863 .1176/.5);--pink-surface:color(display-p3 .1725 .0784 .149/.5);--plum-surface:color(display-p3 .1647 .0863 .1725/.5);--purple-surface:color(display-p3 .149 .0941 .1961/.5);--violet-surface:color(display-p3 .1333 .102 .2118/.5);--iris-surface:color(display-p3 .1098 .102 .2118/.5);--indigo-surface:color(display-p3 .0941 .1098 .2196/.5);--blue-surface:color(display-p3 .0706 .1255 .2196/.5);--cyan-surface:color(display-p3 .0784 .1412 .1725/.5);--teal-surface:color(display-p3 .0863 .149 .1412/.5);--jade-surface:color(display-p3 .0863 .149 .1176/.5);--green-surface:color(display-p3 .0941 .1412 .1098/.5);--grass-surface:color(display-p3 .102 .1333 .102/.5);--brown-surface:color(display-p3 .1412 .1176 .102/.5);--bronze-surface:color(display-p3 .1412 .1255 .1176/.5);--gold-surface:color(display-p3 .1412 .1333 .1098/.5);--sky-surface:color(display-p3 .0863 .1333 .2196/.5);--mint-surface:color(display-p3 .0941 .149 .1412/.5);--lime-surface:color(display-p3 .1098 .1255 .0784/.5);--yellow-surface:color(display-p3 .1333 .1176 .0706/.5);--amber-surface:color(display-p3 .1412 .1176 .0784/.5);--orange-surface:color(display-p3 .1412 .1098 .0706/.5)}}}[data-accent-color=tomato]{--color-surface-accent:var(--tomato-surface);--accent-1:var(--tomato-1);--accent-2:var(--tomato-2);--accent-3:var(--tomato-3);--accent-4:var(--tomato-4);--accent-5:var(--tomato-5);--accent-6:var(--tomato-6);--accent-7:var(--tomato-7);--accent-8:var(--tomato-8);--accent-9:var(--tomato-9);--accent-contrast:var(--tomato-contrast);--accent-10:var(--tomato-10);--accent-11:var(--tomato-11);--accent-12:var(--tomato-12);--accent-a1:var(--tomato-a1);--accent-a2:var(--tomato-a2);--accent-a3:var(--tomato-a3);--accent-a4:var(--tomato-a4);--accent-a5:var(--tomato-a5);--accent-a6:var(--tomato-a6);--accent-a7:var(--tomato-a7);--accent-a8:var(--tomato-a8);--accent-a9:var(--tomato-a9);--accent-a10:var(--tomato-a10);--accent-a11:var(--tomato-a11);--accent-a12:var(--tomato-a12)}[data-accent-color=red]{--color-surface-accent:var(--red-surface);--accent-1:var(--red-1);--accent-2:var(--red-2);--accent-3:var(--red-3);--accent-4:var(--red-4);--accent-5:var(--red-5);--accent-6:var(--red-6);--accent-7:var(--red-7);--accent-8:var(--red-8);--accent-9:var(--red-9);--accent-contrast:var(--red-contrast);--accent-10:var(--red-10);--accent-11:var(--red-11);--accent-12:var(--red-12);--accent-a1:var(--red-a1);--accent-a2:var(--red-a2);--accent-a3:var(--red-a3);--accent-a4:var(--red-a4);--accent-a5:var(--red-a5);--accent-a6:var(--red-a6);--accent-a7:var(--red-a7);--accent-a8:var(--red-a8);--accent-a9:var(--red-a9);--accent-a10:var(--red-a10);--accent-a11:var(--red-a11);--accent-a12:var(--red-a12)}[data-accent-color=ruby]{--color-surface-accent:var(--ruby-surface);--accent-1:var(--ruby-1);--accent-2:var(--ruby-2);--accent-3:var(--ruby-3);--accent-4:var(--ruby-4);--accent-5:var(--ruby-5);--accent-6:var(--ruby-6);--accent-7:var(--ruby-7);--accent-8:var(--ruby-8);--accent-9:var(--ruby-9);--accent-contrast:var(--ruby-contrast);--accent-10:var(--ruby-10);--accent-11:var(--ruby-11);--accent-12:var(--ruby-12);--accent-a1:var(--ruby-a1);--accent-a2:var(--ruby-a2);--accent-a3:var(--ruby-a3);--accent-a4:var(--ruby-a4);--accent-a5:var(--ruby-a5);--accent-a6:var(--ruby-a6);--accent-a7:var(--ruby-a7);--accent-a8:var(--ruby-a8);--accent-a9:var(--ruby-a9);--accent-a10:var(--ruby-a10);--accent-a11:var(--ruby-a11);--accent-a12:var(--ruby-a12)}[data-accent-color=crimson]{--color-surface-accent:var(--crimson-surface);--accent-1:var(--crimson-1);--accent-2:var(--crimson-2);--accent-3:var(--crimson-3);--accent-4:var(--crimson-4);--accent-5:var(--crimson-5);--accent-6:var(--crimson-6);--accent-7:var(--crimson-7);--accent-8:var(--crimson-8);--accent-9:var(--crimson-9);--accent-contrast:var(--crimson-contrast);--accent-10:var(--crimson-10);--accent-11:var(--crimson-11);--accent-12:var(--crimson-12);--accent-a1:var(--crimson-a1);--accent-a2:var(--crimson-a2);--accent-a3:var(--crimson-a3);--accent-a4:var(--crimson-a4);--accent-a5:var(--crimson-a5);--accent-a6:var(--crimson-a6);--accent-a7:var(--crimson-a7);--accent-a8:var(--crimson-a8);--accent-a9:var(--crimson-a9);--accent-a10:var(--crimson-a10);--accent-a11:var(--crimson-a11);--accent-a12:var(--crimson-a12)}[data-accent-color=pink]{--color-surface-accent:var(--pink-surface);--accent-1:var(--pink-1);--accent-2:var(--pink-2);--accent-3:var(--pink-3);--accent-4:var(--pink-4);--accent-5:var(--pink-5);--accent-6:var(--pink-6);--accent-7:var(--pink-7);--accent-8:var(--pink-8);--accent-9:var(--pink-9);--accent-contrast:var(--pink-contrast);--accent-10:var(--pink-10);--accent-11:var(--pink-11);--accent-12:var(--pink-12);--accent-a1:var(--pink-a1);--accent-a2:var(--pink-a2);--accent-a3:var(--pink-a3);--accent-a4:var(--pink-a4);--accent-a5:var(--pink-a5);--accent-a6:var(--pink-a6);--accent-a7:var(--pink-a7);--accent-a8:var(--pink-a8);--accent-a9:var(--pink-a9);--accent-a10:var(--pink-a10);--accent-a11:var(--pink-a11);--accent-a12:var(--pink-a12)}[data-accent-color=plum]{--color-surface-accent:var(--plum-surface);--accent-1:var(--plum-1);--accent-2:var(--plum-2);--accent-3:var(--plum-3);--accent-4:var(--plum-4);--accent-5:var(--plum-5);--accent-6:var(--plum-6);--accent-7:var(--plum-7);--accent-8:var(--plum-8);--accent-9:var(--plum-9);--accent-contrast:var(--plum-contrast);--accent-10:var(--plum-10);--accent-11:var(--plum-11);--accent-12:var(--plum-12);--accent-a1:var(--plum-a1);--accent-a2:var(--plum-a2);--accent-a3:var(--plum-a3);--accent-a4:var(--plum-a4);--accent-a5:var(--plum-a5);--accent-a6:var(--plum-a6);--accent-a7:var(--plum-a7);--accent-a8:var(--plum-a8);--accent-a9:var(--plum-a9);--accent-a10:var(--plum-a10);--accent-a11:var(--plum-a11);--accent-a12:var(--plum-a12)}[data-accent-color=purple]{--color-surface-accent:var(--purple-surface);--accent-1:var(--purple-1);--accent-2:var(--purple-2);--accent-3:var(--purple-3);--accent-4:var(--purple-4);--accent-5:var(--purple-5);--accent-6:var(--purple-6);--accent-7:var(--purple-7);--accent-8:var(--purple-8);--accent-9:var(--purple-9);--accent-contrast:var(--purple-contrast);--accent-10:var(--purple-10);--accent-11:var(--purple-11);--accent-12:var(--purple-12);--accent-a1:var(--purple-a1);--accent-a2:var(--purple-a2);--accent-a3:var(--purple-a3);--accent-a4:var(--purple-a4);--accent-a5:var(--purple-a5);--accent-a6:var(--purple-a6);--accent-a7:var(--purple-a7);--accent-a8:var(--purple-a8);--accent-a9:var(--purple-a9);--accent-a10:var(--purple-a10);--accent-a11:var(--purple-a11);--accent-a12:var(--purple-a12)}[data-accent-color=violet]{--color-surface-accent:var(--violet-surface);--accent-1:var(--violet-1);--accent-2:var(--violet-2);--accent-3:var(--violet-3);--accent-4:var(--violet-4);--accent-5:var(--violet-5);--accent-6:var(--violet-6);--accent-7:var(--violet-7);--accent-8:var(--violet-8);--accent-9:var(--violet-9);--accent-contrast:var(--violet-contrast);--accent-10:var(--violet-10);--accent-11:var(--violet-11);--accent-12:var(--violet-12);--accent-a1:var(--violet-a1);--accent-a2:var(--violet-a2);--accent-a3:var(--violet-a3);--accent-a4:var(--violet-a4);--accent-a5:var(--violet-a5);--accent-a6:var(--violet-a6);--accent-a7:var(--violet-a7);--accent-a8:var(--violet-a8);--accent-a9:var(--violet-a9);--accent-a10:var(--violet-a10);--accent-a11:var(--violet-a11);--accent-a12:var(--violet-a12)}[data-accent-color=iris]{--color-surface-accent:var(--iris-surface);--accent-1:var(--iris-1);--accent-2:var(--iris-2);--accent-3:var(--iris-3);--accent-4:var(--iris-4);--accent-5:var(--iris-5);--accent-6:var(--iris-6);--accent-7:var(--iris-7);--accent-8:var(--iris-8);--accent-9:var(--iris-9);--accent-contrast:var(--iris-contrast);--accent-10:var(--iris-10);--accent-11:var(--iris-11);--accent-12:var(--iris-12);--accent-a1:var(--iris-a1);--accent-a2:var(--iris-a2);--accent-a3:var(--iris-a3);--accent-a4:var(--iris-a4);--accent-a5:var(--iris-a5);--accent-a6:var(--iris-a6);--accent-a7:var(--iris-a7);--accent-a8:var(--iris-a8);--accent-a9:var(--iris-a9);--accent-a10:var(--iris-a10);--accent-a11:var(--iris-a11);--accent-a12:var(--iris-a12)}[data-accent-color=indigo]{--color-surface-accent:var(--indigo-surface);--accent-1:var(--indigo-1);--accent-2:var(--indigo-2);--accent-3:var(--indigo-3);--accent-4:var(--indigo-4);--accent-5:var(--indigo-5);--accent-6:var(--indigo-6);--accent-7:var(--indigo-7);--accent-8:var(--indigo-8);--accent-9:var(--indigo-9);--accent-contrast:var(--indigo-contrast);--accent-10:var(--indigo-10);--accent-11:var(--indigo-11);--accent-12:var(--indigo-12);--accent-a1:var(--indigo-a1);--accent-a2:var(--indigo-a2);--accent-a3:var(--indigo-a3);--accent-a4:var(--indigo-a4);--accent-a5:var(--indigo-a5);--accent-a6:var(--indigo-a6);--accent-a7:var(--indigo-a7);--accent-a8:var(--indigo-a8);--accent-a9:var(--indigo-a9);--accent-a10:var(--indigo-a10);--accent-a11:var(--indigo-a11);--accent-a12:var(--indigo-a12)}[data-accent-color=blue]{--color-surface-accent:var(--blue-surface);--accent-1:var(--blue-1);--accent-2:var(--blue-2);--accent-3:var(--blue-3);--accent-4:var(--blue-4);--accent-5:var(--blue-5);--accent-6:var(--blue-6);--accent-7:var(--blue-7);--accent-8:var(--blue-8);--accent-9:var(--blue-9);--accent-contrast:var(--blue-contrast);--accent-10:var(--blue-10);--accent-11:var(--blue-11);--accent-12:var(--blue-12);--accent-a1:var(--blue-a1);--accent-a2:var(--blue-a2);--accent-a3:var(--blue-a3);--accent-a4:var(--blue-a4);--accent-a5:var(--blue-a5);--accent-a6:var(--blue-a6);--accent-a7:var(--blue-a7);--accent-a8:var(--blue-a8);--accent-a9:var(--blue-a9);--accent-a10:var(--blue-a10);--accent-a11:var(--blue-a11);--accent-a12:var(--blue-a12)}[data-accent-color=cyan]{--color-surface-accent:var(--cyan-surface);--accent-1:var(--cyan-1);--accent-2:var(--cyan-2);--accent-3:var(--cyan-3);--accent-4:var(--cyan-4);--accent-5:var(--cyan-5);--accent-6:var(--cyan-6);--accent-7:var(--cyan-7);--accent-8:var(--cyan-8);--accent-9:var(--cyan-9);--accent-contrast:var(--cyan-contrast);--accent-10:var(--cyan-10);--accent-11:var(--cyan-11);--accent-12:var(--cyan-12);--accent-a1:var(--cyan-a1);--accent-a2:var(--cyan-a2);--accent-a3:var(--cyan-a3);--accent-a4:var(--cyan-a4);--accent-a5:var(--cyan-a5);--accent-a6:var(--cyan-a6);--accent-a7:var(--cyan-a7);--accent-a8:var(--cyan-a8);--accent-a9:var(--cyan-a9);--accent-a10:var(--cyan-a10);--accent-a11:var(--cyan-a11);--accent-a12:var(--cyan-a12)}[data-accent-color=teal]{--color-surface-accent:var(--teal-surface);--accent-1:var(--teal-1);--accent-2:var(--teal-2);--accent-3:var(--teal-3);--accent-4:var(--teal-4);--accent-5:var(--teal-5);--accent-6:var(--teal-6);--accent-7:var(--teal-7);--accent-8:var(--teal-8);--accent-9:var(--teal-9);--accent-contrast:var(--teal-contrast);--accent-10:var(--teal-10);--accent-11:var(--teal-11);--accent-12:var(--teal-12);--accent-a1:var(--teal-a1);--accent-a2:var(--teal-a2);--accent-a3:var(--teal-a3);--accent-a4:var(--teal-a4);--accent-a5:var(--teal-a5);--accent-a6:var(--teal-a6);--accent-a7:var(--teal-a7);--accent-a8:var(--teal-a8);--accent-a9:var(--teal-a9);--accent-a10:var(--teal-a10);--accent-a11:var(--teal-a11);--accent-a12:var(--teal-a12)}[data-accent-color=jade]{--color-surface-accent:var(--jade-surface);--accent-1:var(--jade-1);--accent-2:var(--jade-2);--accent-3:var(--jade-3);--accent-4:var(--jade-4);--accent-5:var(--jade-5);--accent-6:var(--jade-6);--accent-7:var(--jade-7);--accent-8:var(--jade-8);--accent-9:var(--jade-9);--accent-contrast:var(--jade-contrast);--accent-10:var(--jade-10);--accent-11:var(--jade-11);--accent-12:var(--jade-12);--accent-a1:var(--jade-a1);--accent-a2:var(--jade-a2);--accent-a3:var(--jade-a3);--accent-a4:var(--jade-a4);--accent-a5:var(--jade-a5);--accent-a6:var(--jade-a6);--accent-a7:var(--jade-a7);--accent-a8:var(--jade-a8);--accent-a9:var(--jade-a9);--accent-a10:var(--jade-a10);--accent-a11:var(--jade-a11);--accent-a12:var(--jade-a12)}[data-accent-color=green]{--color-surface-accent:var(--green-surface);--accent-1:var(--green-1);--accent-2:var(--green-2);--accent-3:var(--green-3);--accent-4:var(--green-4);--accent-5:var(--green-5);--accent-6:var(--green-6);--accent-7:var(--green-7);--accent-8:var(--green-8);--accent-9:var(--green-9);--accent-contrast:var(--green-contrast);--accent-10:var(--green-10);--accent-11:var(--green-11);--accent-12:var(--green-12);--accent-a1:var(--green-a1);--accent-a2:var(--green-a2);--accent-a3:var(--green-a3);--accent-a4:var(--green-a4);--accent-a5:var(--green-a5);--accent-a6:var(--green-a6);--accent-a7:var(--green-a7);--accent-a8:var(--green-a8);--accent-a9:var(--green-a9);--accent-a10:var(--green-a10);--accent-a11:var(--green-a11);--accent-a12:var(--green-a12)}[data-accent-color=grass]{--color-surface-accent:var(--grass-surface);--accent-1:var(--grass-1);--accent-2:var(--grass-2);--accent-3:var(--grass-3);--accent-4:var(--grass-4);--accent-5:var(--grass-5);--accent-6:var(--grass-6);--accent-7:var(--grass-7);--accent-8:var(--grass-8);--accent-9:var(--grass-9);--accent-contrast:var(--grass-contrast);--accent-10:var(--grass-10);--accent-11:var(--grass-11);--accent-12:var(--grass-12);--accent-a1:var(--grass-a1);--accent-a2:var(--grass-a2);--accent-a3:var(--grass-a3);--accent-a4:var(--grass-a4);--accent-a5:var(--grass-a5);--accent-a6:var(--grass-a6);--accent-a7:var(--grass-a7);--accent-a8:var(--grass-a8);--accent-a9:var(--grass-a9);--accent-a10:var(--grass-a10);--accent-a11:var(--grass-a11);--accent-a12:var(--grass-a12)}[data-accent-color=orange]{--color-surface-accent:var(--orange-surface);--accent-1:var(--orange-1);--accent-2:var(--orange-2);--accent-3:var(--orange-3);--accent-4:var(--orange-4);--accent-5:var(--orange-5);--accent-6:var(--orange-6);--accent-7:var(--orange-7);--accent-8:var(--orange-8);--accent-9:var(--orange-9);--accent-contrast:var(--orange-contrast);--accent-10:var(--orange-10);--accent-11:var(--orange-11);--accent-12:var(--orange-12);--accent-a1:var(--orange-a1);--accent-a2:var(--orange-a2);--accent-a3:var(--orange-a3);--accent-a4:var(--orange-a4);--accent-a5:var(--orange-a5);--accent-a6:var(--orange-a6);--accent-a7:var(--orange-a7);--accent-a8:var(--orange-a8);--accent-a9:var(--orange-a9);--accent-a10:var(--orange-a10);--accent-a11:var(--orange-a11);--accent-a12:var(--orange-a12)}[data-accent-color=brown]{--color-surface-accent:var(--brown-surface);--accent-1:var(--brown-1);--accent-2:var(--brown-2);--accent-3:var(--brown-3);--accent-4:var(--brown-4);--accent-5:var(--brown-5);--accent-6:var(--brown-6);--accent-7:var(--brown-7);--accent-8:var(--brown-8);--accent-9:var(--brown-9);--accent-contrast:var(--brown-contrast);--accent-10:var(--brown-10);--accent-11:var(--brown-11);--accent-12:var(--brown-12);--accent-a1:var(--brown-a1);--accent-a2:var(--brown-a2);--accent-a3:var(--brown-a3);--accent-a4:var(--brown-a4);--accent-a5:var(--brown-a5);--accent-a6:var(--brown-a6);--accent-a7:var(--brown-a7);--accent-a8:var(--brown-a8);--accent-a9:var(--brown-a9);--accent-a10:var(--brown-a10);--accent-a11:var(--brown-a11);--accent-a12:var(--brown-a12)}[data-accent-color=sky]{--color-surface-accent:var(--sky-surface);--accent-1:var(--sky-1);--accent-2:var(--sky-2);--accent-3:var(--sky-3);--accent-4:var(--sky-4);--accent-5:var(--sky-5);--accent-6:var(--sky-6);--accent-7:var(--sky-7);--accent-8:var(--sky-8);--accent-9:var(--sky-9);--accent-contrast:var(--sky-contrast);--accent-10:var(--sky-10);--accent-11:var(--sky-11);--accent-12:var(--sky-12);--accent-a1:var(--sky-a1);--accent-a2:var(--sky-a2);--accent-a3:var(--sky-a3);--accent-a4:var(--sky-a4);--accent-a5:var(--sky-a5);--accent-a6:var(--sky-a6);--accent-a7:var(--sky-a7);--accent-a8:var(--sky-a8);--accent-a9:var(--sky-a9);--accent-a10:var(--sky-a10);--accent-a11:var(--sky-a11);--accent-a12:var(--sky-a12)}[data-accent-color=mint]{--color-surface-accent:var(--mint-surface);--accent-1:var(--mint-1);--accent-2:var(--mint-2);--accent-3:var(--mint-3);--accent-4:var(--mint-4);--accent-5:var(--mint-5);--accent-6:var(--mint-6);--accent-7:var(--mint-7);--accent-8:var(--mint-8);--accent-9:var(--mint-9);--accent-contrast:var(--mint-contrast);--accent-10:var(--mint-10);--accent-11:var(--mint-11);--accent-12:var(--mint-12);--accent-a1:var(--mint-a1);--accent-a2:var(--mint-a2);--accent-a3:var(--mint-a3);--accent-a4:var(--mint-a4);--accent-a5:var(--mint-a5);--accent-a6:var(--mint-a6);--accent-a7:var(--mint-a7);--accent-a8:var(--mint-a8);--accent-a9:var(--mint-a9);--accent-a10:var(--mint-a10);--accent-a11:var(--mint-a11);--accent-a12:var(--mint-a12)}[data-accent-color=lime]{--color-surface-accent:var(--lime-surface);--accent-1:var(--lime-1);--accent-2:var(--lime-2);--accent-3:var(--lime-3);--accent-4:var(--lime-4);--accent-5:var(--lime-5);--accent-6:var(--lime-6);--accent-7:var(--lime-7);--accent-8:var(--lime-8);--accent-9:var(--lime-9);--accent-contrast:var(--lime-contrast);--accent-10:var(--lime-10);--accent-11:var(--lime-11);--accent-12:var(--lime-12);--accent-a1:var(--lime-a1);--accent-a2:var(--lime-a2);--accent-a3:var(--lime-a3);--accent-a4:var(--lime-a4);--accent-a5:var(--lime-a5);--accent-a6:var(--lime-a6);--accent-a7:var(--lime-a7);--accent-a8:var(--lime-a8);--accent-a9:var(--lime-a9);--accent-a10:var(--lime-a10);--accent-a11:var(--lime-a11);--accent-a12:var(--lime-a12)}[data-accent-color=yellow]{--color-surface-accent:var(--yellow-surface);--accent-1:var(--yellow-1);--accent-2:var(--yellow-2);--accent-3:var(--yellow-3);--accent-4:var(--yellow-4);--accent-5:var(--yellow-5);--accent-6:var(--yellow-6);--accent-7:var(--yellow-7);--accent-8:var(--yellow-8);--accent-9:var(--yellow-9);--accent-contrast:var(--yellow-contrast);--accent-10:var(--yellow-10);--accent-11:var(--yellow-11);--accent-12:var(--yellow-12);--accent-a1:var(--yellow-a1);--accent-a2:var(--yellow-a2);--accent-a3:var(--yellow-a3);--accent-a4:var(--yellow-a4);--accent-a5:var(--yellow-a5);--accent-a6:var(--yellow-a6);--accent-a7:var(--yellow-a7);--accent-a8:var(--yellow-a8);--accent-a9:var(--yellow-a9);--accent-a10:var(--yellow-a10);--accent-a11:var(--yellow-a11);--accent-a12:var(--yellow-a12)}[data-accent-color=amber]{--color-surface-accent:var(--amber-surface);--accent-1:var(--amber-1);--accent-2:var(--amber-2);--accent-3:var(--amber-3);--accent-4:var(--amber-4);--accent-5:var(--amber-5);--accent-6:var(--amber-6);--accent-7:var(--amber-7);--accent-8:var(--amber-8);--accent-9:var(--amber-9);--accent-contrast:var(--amber-contrast);--accent-10:var(--amber-10);--accent-11:var(--amber-11);--accent-12:var(--amber-12);--accent-a1:var(--amber-a1);--accent-a2:var(--amber-a2);--accent-a3:var(--amber-a3);--accent-a4:var(--amber-a4);--accent-a5:var(--amber-a5);--accent-a6:var(--amber-a6);--accent-a7:var(--amber-a7);--accent-a8:var(--amber-a8);--accent-a9:var(--amber-a9);--accent-a10:var(--amber-a10);--accent-a11:var(--amber-a11);--accent-a12:var(--amber-a12)}[data-accent-color=gold]{--color-surface-accent:var(--gold-surface);--accent-1:var(--gold-1);--accent-2:var(--gold-2);--accent-3:var(--gold-3);--accent-4:var(--gold-4);--accent-5:var(--gold-5);--accent-6:var(--gold-6);--accent-7:var(--gold-7);--accent-8:var(--gold-8);--accent-9:var(--gold-9);--accent-contrast:var(--gold-contrast);--accent-10:var(--gold-10);--accent-11:var(--gold-11);--accent-12:var(--gold-12);--accent-a1:var(--gold-a1);--accent-a2:var(--gold-a2);--accent-a3:var(--gold-a3);--accent-a4:var(--gold-a4);--accent-a5:var(--gold-a5);--accent-a6:var(--gold-a6);--accent-a7:var(--gold-a7);--accent-a8:var(--gold-a8);--accent-a9:var(--gold-a9);--accent-a10:var(--gold-a10);--accent-a11:var(--gold-a11);--accent-a12:var(--gold-a12)}[data-accent-color=bronze]{--color-surface-accent:var(--bronze-surface);--accent-1:var(--bronze-1);--accent-2:var(--bronze-2);--accent-3:var(--bronze-3);--accent-4:var(--bronze-4);--accent-5:var(--bronze-5);--accent-6:var(--bronze-6);--accent-7:var(--bronze-7);--accent-8:var(--bronze-8);--accent-9:var(--bronze-9);--accent-contrast:var(--bronze-contrast);--accent-10:var(--bronze-10);--accent-11:var(--bronze-11);--accent-12:var(--bronze-12);--accent-a1:var(--bronze-a1);--accent-a2:var(--bronze-a2);--accent-a3:var(--bronze-a3);--accent-a4:var(--bronze-a4);--accent-a5:var(--bronze-a5);--accent-a6:var(--bronze-a6);--accent-a7:var(--bronze-a7);--accent-a8:var(--bronze-a8);--accent-a9:var(--bronze-a9);--accent-a10:var(--bronze-a10);--accent-a11:var(--bronze-a11);--accent-a12:var(--bronze-a12)}[data-accent-color=gray]{--color-surface-accent:var(--gray-surface);--accent-1:var(--gray-1);--accent-2:var(--gray-2);--accent-3:var(--gray-3);--accent-4:var(--gray-4);--accent-5:var(--gray-5);--accent-6:var(--gray-6);--accent-7:var(--gray-7);--accent-8:var(--gray-8);--accent-9:var(--gray-9);--accent-contrast:var(--gray-contrast);--accent-10:var(--gray-10);--accent-11:var(--gray-11);--accent-12:var(--gray-12);--accent-a1:var(--gray-a1);--accent-a2:var(--gray-a2);--accent-a3:var(--gray-a3);--accent-a4:var(--gray-a4);--accent-a5:var(--gray-a5);--accent-a6:var(--gray-a6);--accent-a7:var(--gray-a7);--accent-a8:var(--gray-a8);--accent-a9:var(--gray-a9);--accent-a10:var(--gray-a10);--accent-a11:var(--gray-a11);--accent-a12:var(--gray-a12)}:root{--sy-f-sys:-apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Droid Sans, Helvetica Neue;--sy-f-cjk:Noto Sans;--sy-f-heading:var(--sy-f-sys), var(--sy-f-cjk), sans-serif;--sy-f-text:var(--sy-f-sys), var(--sy-f-cjk), sans-serif;--sy-f-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--sy-s-banner-height:0rem;--sy-s-navbar-height:56px;--sy-s-offset-top:calc(var(--sy-s-navbar-height) + var(--sy-s-banner-height));--sy-c-divider:var(--gray-4);--sy-c-border:var(--gray-5);--sy-c-text:var(--gray-12);--sy-c-light:var(--gray-11);--sy-c-bold:var(--slate-12);--sy-c-heading:var(--sage-12);--sy-c-link:var(--accent-9);--sy-c-link-hover:var(--accent-a11);--sy-c-background:white;--sy-c-surface:var(--gray-a2);--sy-c-overlay:var(--black-a5);--sy-c-background-contrast:black;--sy-c-background-dropback:#fffc;--sy-c-foot-text:var(--sy-c-text);--sy-c-foot-background:var(--slate-2);--sy-c-foot-divider:var(--sy-c-divider);--sy-dropdown-shadow:0 12px 32px var(--gray-a6), 0 2px 6px var(--gray-a4)}[lang^=zh-Hans],[lang=zh],[lang=zh-CN]{--sy-f-cjk:PingFang SC, Hiragino Sans GB, Noto Sans SC, Microsoft YaHei}[lang^=zh-Hant],[lang=zh-TW]{--sy-f-cjk:PingFang TC, Noto Sans TC, Microsoft JhengHei}[lang=zh-HK],[lang=zh-Hant-HK]{--sy-f-cjk:PingFang HK, Noto Sans HK, Microsoft JhengHei}[lang=ja]{--sy-f-cjk:Hiragino Sans, Noto Sans JP, Yu Gothic}[data-accent-color=sky],[data-accent-color=mint],[data-accent-color=lime],[data-accent-color=yellow],[data-accent-color=amber]{--sy-c-link:var(--accent-a10)}html.light{color-scheme:light;--sy-c-background:white;--sy-c-background-contrast:black}html.dark{color-scheme:dark;--sy-c-background:var(--slate-1);--sy-c-overlay:var(--white-a2);--sy-c-background-contrast:var(--white-a10);--sy-c-foot-background:var(--black-a11);--sy-c-foot-divider:var(--black-a12);--sy-c-background-dropback:#212328cc}html{color:var(--sy-c-text);background-color:var(--sy-c-background)}:root{--lucide-alert-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3zM12 9v4m0 4h.01'/%3E%3C/svg%3E");--lucide-arrows-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m7 15 5 5 5-5M7 9l5-5 5 5'/%3E%3C/svg%3E");--lucide-award-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='8' r='6'/%3E%3Cpath d='M15.477 12.89 17 22l-5-3-5 3 1.523-9.11'/%3E%3C/svg%3E");--lucide-bell-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9m-4.27 13a2 2 0 0 1-3.46 0'/%3E%3C/svg%3E");--lucide-bookmark-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z'/%3E%3C/svg%3E");--lucide-calendar-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='18' height='18' x='3' y='4' rx='2' ry='2'/%3E%3Cpath d='M16 2v4M8 2v4m-5 4h18'/%3E%3C/svg%3E");--lucide-check-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");--lucide-chevron-down-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-down'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");--lucide-chevron-left-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-left'%3E%3Cpath d='m15 18-6-6 6-6'/%3E%3C/svg%3E");--lucide-chevron-right-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-right'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E");--lucide-chevron-up-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-chevron-up'%3E%3Cpath d='m18 15-6-6-6 6'/%3E%3C/svg%3E");--lucide-close-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");--lucide-copy-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-copy-icon lucide-copy' viewBox='0 0 24 24'%3E%3Crect width='14' height='14' x='8' y='8' rx='2' ry='2'/%3E%3Cpath d='M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2'/%3E%3C/svg%3E");--lucide-external-link-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M13 5h6v6m0-6L5 19'/%3E%3C/svg%3E");--lucide-flame-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z'/%3E%3C/svg%3E");--lucide-git-fork-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='18' r='3'/%3E%3Ccircle cx='6' cy='6' r='3'/%3E%3Ccircle cx='18' cy='6' r='3'/%3E%3Cpath d='M18 9v1a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V9m6 3v3'/%3E%3C/svg%3E");--lucide-help-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3m.08 4h.01'/%3E%3C/svg%3E");--lucide-languages-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-languages'%3E%3Cpath d='m5 8 6 6m-7 0 6-6 2-3M2 5h12M7 2h1m14 20-5-10-5 10m2-4h6'/%3E%3C/svg%3E");--lucide-laptop-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='18' height='12' x='3' y='4' rx='2' ry='2'/%3E%3Cpath d='M2 20h20'/%3E%3C/svg%3E");--lucide-link-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71'/%3E%3Cpath d='M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71'/%3E%3C/svg%3E");--lucide-loader-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-loader-icon lucide-loader' viewBox='0 0 24 24'%3E%3Cpath d='M12 2v4M16.2 7.8l2.9-2.9M18 12h4M16.2 16.2l2.9 2.9M12 18v4M4.9 19.1l2.9-2.9M2 12h4M4.9 4.9l2.9 2.9'/%3E%3C/svg%3E");--lucide-menu-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-menu'%3E%3Cpath d='M4 12h16M4 6h16M4 18h16'/%3E%3C/svg%3E");--lucide-milestone-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M18 6H5a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h13l4-3.5L18 6zm-6 7v8m0-18v3'/%3E%3C/svg%3E");--lucide-moon-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M12 3a6.364 6.364 0 0 0 9 9 9 9 0 1 1-9-9z'/%3E%3C/svg%3E");--lucide-outdent-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m7 8-4 4 4 4m14-4H11m10-6H11m10 12H11'/%3E%3C/svg%3E");--lucide-rocket-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09zM12 15l-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z'/%3E%3Cpath d='M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0m1 7v5s3.03-.55 4-2c1.08-1.62 0-5 0-5'/%3E%3C/svg%3E");--lucide-skull-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='9' cy='12' r='1'/%3E%3Ccircle cx='15' cy='12' r='1'/%3E%3Cpath d='M8 20v2h8v-2m-3.5-3-.5-1-.5 1h1z'/%3E%3Cpath d='M16 20a2 2 0 0 0 1.56-3.25 8 8 0 1 0-11.12 0A2 2 0 0 0 8 20'/%3E%3C/svg%3E");--lucide-star-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'/%3E%3C/svg%3E");--lucide-sun-moon-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' class='lucide lucide-sun-moon-icon lucide-sun-moon' viewBox='0 0 24 24'%3E%3Cpath d='M12 2v2M14.837 16.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715M16 12a4 4 0 0 0-4-4M19 5l-1.256 1.256M20 12h2'/%3E%3C/svg%3E");--lucide-sun-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32 1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/svg%3E");--lucide-zap-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M13 2 3 14h9l-1 8 10-12h-9l1-8z'/%3E%3C/svg%3E")}.i-lucide.alert{--icon-url:var(--lucide-alert-url)}.i-lucide.arrows{--icon-url:var(--lucide-arrows-url)}.i-lucide.award{--icon-url:var(--lucide-award-url)}.i-lucide.bell{--icon-url:var(--lucide-bell-url)}.i-lucide.bookmark{--icon-url:var(--lucide-bookmark-url)}.i-lucide.calendar{--icon-url:var(--lucide-calendar-url)}.i-lucide.check{--icon-url:var(--lucide-check-url)}.i-lucide.chevron-down{--icon-url:var(--lucide-chevron-down-url)}.i-lucide.chevron-left{--icon-url:var(--lucide-chevron-left-url)}.i-lucide.chevron-right{--icon-url:var(--lucide-chevron-right-url)}.i-lucide.chevron-up{--icon-url:var(--lucide-chevron-up-url)}.i-lucide.close{--icon-url:var(--lucide-close-url)}.i-lucide.copy{--icon-url:var(--lucide-copy-url)}.i-lucide.external-link{--icon-url:var(--lucide-external-link-url)}.i-lucide.flame{--icon-url:var(--lucide-flame-url)}.i-lucide.git-fork{--icon-url:var(--lucide-git-fork-url)}.i-lucide.help{--icon-url:var(--lucide-help-url)}.i-lucide.languages{--icon-url:var(--lucide-languages-url)}.i-lucide.laptop{--icon-url:var(--lucide-laptop-url)}.i-lucide.link{--icon-url:var(--lucide-link-url)}.i-lucide.loader{--icon-url:var(--lucide-loader-url)}.i-lucide.menu{--icon-url:var(--lucide-menu-url)}.i-lucide.milestone{--icon-url:var(--lucide-milestone-url)}.i-lucide.moon{--icon-url:var(--lucide-moon-url)}.i-lucide.outdent{--icon-url:var(--lucide-outdent-url)}.i-lucide.rocket{--icon-url:var(--lucide-rocket-url)}.i-lucide.skull{--icon-url:var(--lucide-skull-url)}.i-lucide.star{--icon-url:var(--lucide-star-url)}.i-lucide.sun-moon{--icon-url:var(--lucide-sun-moon-url)}.i-lucide.sun{--icon-url:var(--lucide-sun-url)}.i-lucide.zap{--icon-url:var(--lucide-zap-url)}:root{--simpleicons-bitbucket-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M.778 1.213a.768.768 0 0 0-.768.892l3.263 19.81c.084.5.515.868 1.022.873H19.95a.772.772 0 0 0 .77-.646l3.27-20.03a.768.768 0 0 0-.768-.891zM14.52 15.53H9.522L8.17 8.466h7.561z'/%3E%3C/svg%3E");--simpleicons-discord-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z'/%3E%3C/svg%3E");--simpleicons-git-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.546 10.93 13.067.452a1.55 1.55 0 0 0-2.188 0L8.708 2.627l2.76 2.76a1.838 1.838 0 0 1 2.327 2.341l2.658 2.66a1.838 1.838 0 0 1 1.9 3.039 1.837 1.837 0 0 1-2.6 0 1.846 1.846 0 0 1-.404-1.996L12.86 8.955v6.525c.176.086.342.203.488.348a1.848 1.848 0 0 1 0 2.6 1.844 1.844 0 0 1-2.609 0 1.834 1.834 0 0 1 0-2.598c.182-.18.387-.316.605-.406V8.835a1.834 1.834 0 0 1-.996-2.41L7.636 3.7.45 10.881c-.6.605-.6 1.584 0 2.189l10.48 10.477a1.545 1.545 0 0 0 2.186 0l10.43-10.43a1.544 1.544 0 0 0 0-2.187'/%3E%3C/svg%3E");--simpleicons-github-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E");--simpleicons-gitlab-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m23.6 9.593-.033-.086L20.3.98a.851.851 0 0 0-.336-.405.875.875 0 0 0-1 .054.875.875 0 0 0-.29.44L16.47 7.818H7.537L5.332 1.07a.857.857 0 0 0-.29-.441.875.875 0 0 0-1-.054.859.859 0 0 0-.336.405L.433 9.502l-.032.086a6.066 6.066 0 0 0 2.012 7.01l.01.009.03.021 4.977 3.727 2.462 1.863 1.5 1.132a1.008 1.008 0 0 0 1.22 0l1.499-1.132 2.461-1.863 5.006-3.75.013-.01a6.068 6.068 0 0 0 2.01-7.002z'/%3E%3C/svg%3E");--simpleicons-linkedin-url:url("data:image/svg+xml;utf8,%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3ELinkedIn%3C/title%3E%3Cpath d='M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z'/%3E%3C/svg%3E");--simpleicons-mastodon-url:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z'/%3E%3C/svg%3E");--simpleicons-readthedocs-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.732 0a59.316 59.316 0 0 0-4.977.218V24a62.933 62.933 0 0 1 3.619-.687c.17-.028.34-.053.509-.078.215-.033.43-.066.644-.096l.205-.03zm1.18.003V22.96a61.042 61.042 0 0 1 12.333-.213V1.485A60.859 60.859 0 0 0 8.912.003zm1.707 1.81a.59.59 0 0 1 .015 0c3.06.088 6.125.404 9.167.95a.59.59 0 0 1 .476.686.59.59 0 0 1-.569.484.59.59 0 0 1-.116-.009 60.622 60.622 0 0 0-8.992-.931.59.59 0 0 1-.573-.607.59.59 0 0 1 .592-.572zm-4.212.028a.59.59 0 0 1 .578.565.59.59 0 0 1-.564.614 59.74 59.74 0 0 0-2.355.144.59.59 0 0 1-.04.002.59.59 0 0 1-.595-.542.59.59 0 0 1 .54-.635c.8-.065 1.6-.114 2.401-.148a.59.59 0 0 1 .035 0zm4.202 2.834a.59.59 0 0 1 .015 0 61.6 61.6 0 0 1 9.167.8.59.59 0 0 1 .488.677.59.59 0 0 1-.602.494.59.59 0 0 1-.076-.006 60.376 60.376 0 0 0-8.99-.786.59.59 0 0 1-.584-.596.59.59 0 0 1 .582-.583zm-4.211.097a.59.59 0 0 1 .587.555.59.59 0 0 1-.554.622c-.786.046-1.572.107-2.356.184a.59.59 0 0 1-.04.003.59.59 0 0 1-.603-.533.59.59 0 0 1 .53-.644c.8-.078 1.599-.14 2.4-.187a.59.59 0 0 1 .036 0zM10.6 7.535a.59.59 0 0 1 .015 0c3.06-.013 6.125.204 9.167.65a.59.59 0 0 1 .498.67.59.59 0 0 1-.593.504.59.59 0 0 1-.076-.006 60.142 60.142 0 0 0-8.992-.638.59.59 0 0 1-.592-.588.59.59 0 0 1 .573-.592zm1.153 2.846a61.093 61.093 0 0 1 8.02.515.59.59 0 0 1 .509.66.59.59 0 0 1-.586.514.59.59 0 0 1-.076-.005 59.982 59.982 0 0 0-8.99-.492.59.59 0 0 1-.603-.577.59.59 0 0 1 .578-.603c.382-.008.765-.012 1.148-.012zm1.139 2.832a60.92 60.92 0 0 1 6.871.394.59.59 0 0 1 .52.652.59.59 0 0 1-.577.523.59.59 0 0 1-.076-.004 59.936 59.936 0 0 0-8.991-.344.59.59 0 0 1-.61-.568.59.59 0 0 1 .567-.611c.765-.028 1.53-.042 2.296-.042z'/%3E%3C/svg%3E");--simpleicons-reddit-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5.373 0 0 5.373 0 12c0 3.314 1.343 6.314 3.515 8.485l-2.286 2.286A.72.72 0 0 0 1.738 24H12c6.627 0 12-5.373 12-12S18.627 0 12 0Zm4.388 3.199a1.999 1.999 0 1 1-1.947 2.46v.002a2.368 2.368 0 0 0-2.032 2.341v.007c1.776.067 3.4.567 4.686 1.363a2.802 2.802 0 1 1 2.908 4.753c-.088 3.256-3.637 5.876-7.997 5.876-4.361 0-7.905-2.617-7.998-5.87a2.8 2.8 0 0 1 1.189-5.34c.645 0 1.239.218 1.712.585 1.275-.79 2.881-1.291 4.64-1.365v-.01a3.229 3.229 0 0 1 2.88-3.207 2 2 0 0 1 1.959-1.595Zm-8.085 8.376c-.784 0-1.459.78-1.506 1.797-.047 1.016.64 1.429 1.426 1.429.786 0 1.371-.369 1.418-1.385.047-1.017-.553-1.841-1.338-1.841Zm7.406 0c-.786 0-1.385.824-1.338 1.841.047 1.017.634 1.385 1.418 1.385.785 0 1.473-.413 1.426-1.429-.046-1.017-.721-1.797-1.506-1.797Zm-3.703 4.013c-.974 0-1.907.048-2.77.135a.222.222 0 0 0-.183.305 3.199 3.199 0 0 0 2.953 1.964 3.2 3.2 0 0 0 2.953-1.964.222.222 0 0 0-.184-.305 27.75 27.75 0 0 0-2.769-.135Z'/%3E%3C/svg%3E");--simpleicons-slack-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zm0-1.268a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z'/%3E%3C/svg%3E");--simpleicons-x-twitter-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z'/%3E%3C/svg%3E");--simpleicons-youtube-url:url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z'/%3E%3C/svg%3E")}.i-icon.bitbucket,.i-simpleicons.bitbucket{--icon-url:var(--simpleicons-bitbucket-url)}.i-icon.discord,.i-simpleicons.discord{--icon-url:var(--simpleicons-discord-url)}.i-icon.git,.i-simpleicons.git{--icon-url:var(--simpleicons-git-url)}.i-icon.github,.i-simpleicons.github{--icon-url:var(--simpleicons-github-url)}.i-icon.gitlab,.i-simpleicons.gitlab{--icon-url:var(--simpleicons-gitlab-url)}.i-icon.linkedin,.i-simpleicons.linkedin{--icon-url:var(--simpleicons-linkedin-url)}.i-icon.mastodon,.i-simpleicons.mastodon{--icon-url:var(--simpleicons-mastodon-url)}.i-icon.readthedocs,.i-simpleicons.readthedocs{--icon-url:var(--simpleicons-readthedocs-url)}.i-icon.reddit,.i-simpleicons.reddit{--icon-url:var(--simpleicons-reddit-url)}.i-icon.slack,.i-simpleicons.slack{--icon-url:var(--simpleicons-slack-url)}.i-icon.x-twitter,.i-simpleicons.x-twitter{--icon-url:var(--simpleicons-x-twitter-url)}.i-icon.youtube,.i-simpleicons.youtube{--icon-url:var(--simpleicons-youtube-url)}:root{--yue-c-text:var(--sy-c-text);--yue-c-heading:var(--sy-c-heading);--yue-c-bold:var(--sy-c-bold);--yue-c-link-1:var(--sy-c-text);--yue-c-link-2:var(--sy-c-bold);--yue-c-link-border:var(--sy-c-link);--yue-c-ol-marker:var(--gray-9);--yue-c-ul-marker:var(--sage-a5);--yue-c-hr:var(--sy-c-border);--yue-c-quote:var(--sy-c-text);--yue-c-quote-border:var(--accent-a3);--yue-c-quote-symbol:var(--accent-9);--yue-c-caption:var(--sy-c-light);--yue-c-code-text:var(--accent-a11);--yue-c-code-background:var(--accent-a3);--yue-c-table-border:var(--gray-a5);--yue-c-th-background:var(--color-surface-accent);--yue-c-th-border:var(--gray-a5);--yue-c-td-border:var(--gray-a4);--yue-c-row-background:var(--sy-c-surface)}.yue{color:var(--yue-c-text);font-size:1rem;line-height:1.75}.yue p{margin-top:1rem;margin-bottom:1.25rem}.yue a{color:var(--yue-c-link-1);text-decoration:underline;-webkit-text-decoration-color:var(--yue-c-link-border);-webkit-text-decoration-color:var(--yue-c-link-border);text-decoration-color:var(--yue-c-link-border);font-weight:500;text-decoration-thickness:1px}.yue a:hover{color:var(--yue-c-link-2);text-decoration-thickness:2px}.yue pre{overflow:auto}.yue pre a,.yue pre a:hover{border-bottom:none;text-decoration:none}.yue strong{color:var(--yue-c-bold);font-weight:600}.yue a strong,.yue blockquote strong,.yue thead th strong{color:inherit}.yue ol{margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em;list-style-type:decimal}.yue ol[type="1"]{list-style-type:decimal}.yue ol[type=A],.yue ol.upperalpha{list-style-type:upper-alpha}.yue ol[type=a],.yue ol.loweralpha{list-style-type:lower-alpha}.yue ol[type=I],.yue ol.upperroman{list-style-type:upper-roman}.yue ol[type=i],.yue ol.lowerroman{list-style-type:lower-roman}.yue ul{margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em;list-style-type:disc}.yue ol>li::marker{color:var(--yue-c-ol-marker);font-weight:400}.yue ul>li::marker{color:var(--yue-c-ul-marker)}.yue dl{margin-top:1.5rem;margin-bottom:1.5rem}.yue dt{color:var(--yue-c-bold);font-weight:600}.yue dd{margin-left:1.5rem}.yue hr{border-color:var(--yue-c-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.yue blockquote{color:var(--yue-c-quote);border-left-width:.25rem;border-left-color:var(--yue-c-quote-border);margin-top:1.2rem;margin-bottom:1.2rem;padding-left:1rem}.yue blockquote .attribution{font-size:.85em;font-style:italic}[lang^=zh] .yue blockquote .attribution,[lang=ko] .yue blockquote .attribution,[lang=ja] .yue blockquote .attribution{font-style:normal}.yue h1{color:var(--yue-c-heading);margin-top:0;margin-bottom:.888889em;font-size:2.25em;font-weight:800;line-height:1.11111}.yue h1 strong{color:inherit;font-weight:900}.yue h2{color:var(--yue-c-heading);margin-top:2em;margin-bottom:1em;font-size:1.5em;font-weight:700;line-height:1.33333}.yue h2 strong{color:inherit;font-weight:800}.yue h3{color:var(--yue-c-heading);margin-top:1.6em;margin-bottom:.6em;font-size:1.25em;font-weight:600;line-height:1.6}.yue h3 strong{color:inherit;font-weight:700}.yue h4{color:var(--yue-c-heading);margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.5}.yue h4 strong{color:inherit;font-weight:700}.yue h5,.yue h6{color:var(--yue-c-heading);font-weight:600}.yue img{max-width:100%;display:inline}.yue img.rounded{border-radius:.5rem}.yue a>img,.yue figure>*,.yue figure img{margin-top:0;margin-bottom:0}.yue figcaption{color:var(--yue-c-caption);margin-top:.857143em;font-size:.875em;line-height:1.42857}.yue figcaption>p{margin-top:0}.yue code{color:var(--yue-c-code-text);font-size:.875em;font-weight:600}.yue a code,.yue h1 code,.yue h2 code,.yue h3 code,.yue h4 code,.yue blockquote code,.yue th code{color:inherit}.yue h2 code{font-size:.875em}.yue li>code,.yue p>code{background-color:var(--yue-c-code-background);border-radius:3px;padding:2px 4px;font-weight:500}.yue h3 code{font-size:.9em}.yue kbd{font-family:var(--sy-f-mono)}.yue video,.yue figure{margin-top:2em;margin-bottom:2em}.yue li{margin-top:.5em;margin-bottom:.5em}.yue ol>li,.yue ul>li{padding-left:.375em}.yue ul ul,.yue ul ol,.yue ol ul,.yue ol ol{margin-top:.75em;margin-bottom:.75em}.yue hr+*,.yue h2+*,.yue h3+*,.yue h4+*{margin-top:0}.yue table{table-layout:auto;text-align:left;width:100%;margin-top:2em;margin-bottom:2em;font-size:.86em;line-height:1.7}.yue table>caption{color:var(--yue-c-caption);margin-bottom:.4rem}.yue thead tr{border-bottom-width:1px;border-bottom-color:var(--yue-c-th-border)}.yue thead th{color:var(--yue-c-heading);vertical-align:middle;font-weight:600}.yue tbody tr{border-bottom-width:1px;border-bottom-color:var(--yue-c-td-border)}.yue tbody tr:last-child{border-bottom-width:0}.yue tbody td{vertical-align:middle}.yue tfoot{border-top-width:1px;border-top-color:var(--yue-c-th-border)}.yue tfoot td{vertical-align:top}.yue td>p{margin:.25rem 0}.yue thead th>p{margin:0}.yue thead th,.yue tbody td,.yue tfoot td{padding:.5rem}.yue section{clear:both}.yue section>div{margin-bottom:2rem}.yue dd>p:first-child{margin-top:0}.yue p.lead{color:var(--sy-c-light);margin-bottom:0;font-size:1.2rem}.yue p.lead+hr{margin-top:1rem}.yue p.rubric{color:var(--yue-c-heading);margin-top:2rem;font-weight:600}.yue .sidebar{background-color:var(--sy-c-surface);border:1px solid var(--sy-c-border);clear:right;float:right;border-radius:6px;width:30%;margin-bottom:1rem;margin-left:1rem;margin-right:0}@media (max-width:767px){.yue .sidebar{float:none;width:100%;margin-left:0}}.yue .sidebar>*{padding-left:1rem;padding-right:1rem}.yue .sidebar img{margin-top:1rem;margin-bottom:1rem}.yue .sidebar-title{border-bottom:1px solid var(--sy-c-border);margin:0;padding-top:.5rem;padding-bottom:.5rem;font-weight:500}.yue dl.simple>dd>p{margin:0}.yue ul.simple p,.yue ol.simple p{margin-top:.85rem;margin-bottom:.85rem}.yue a.headerlink{visibility:hidden;vertical-align:middle;opacity:.5;color:var(--sy-c-light);font-size:85%;font-weight:300;font-family:var(--sy-f-mono);border-bottom:none;margin-left:6px;font-style:normal;text-decoration:none;display:inline-block}.yue a.headerlink:hover{opacity:1}.yue .math-wrapper{width:100%;margin-top:2rem;margin-bottom:2rem;overflow-x:auto}.yue .math a.headerlink{opacity:1;visibility:visible}.yue a.headerlink:hover,dt:hover a.headerlink,h1:hover a.headerlink,h2:hover a.headerlink,h3:hover a.headerlink,h4:hover a.headerlink,h5:hover a.headerlink,h6:hover a.headerlink{visibility:visible}.yue a.image-reference,.yue .toctree-wrapper a{border-bottom:none;text-decoration:none}.yue .toctree-wrapper p.caption{font-size:.86rem;font-weight:500;font-family:var(--sy-f-heading);color:var(--sy-c-light);text-transform:uppercase;letter-spacing:.4px;border-bottom:1px solid var(--sy-c-divider);padding:.8rem 0 .4rem}.yue .align-left{clear:left;float:left;margin:0 1rem 1rem}.yue .align-right{clear:right;float:right;margin:0 1rem 1rem}.yue .align-center{text-align:center;margin-left:auto;margin-right:auto;display:block}.yue figure.align-center img{margin-left:auto;margin-right:auto}a.footnote-reference{vertical-align:top;font-size:.65rem}aside.footnote>span,div.citation>span{float:left;padding-right:.25rem;font-weight:500}aside.footnote>p,div.citation>p{margin-top:.5rem;margin-bottom:.5rem;margin-left:2rem}.yue kbd.kbd:not(.compound){border-radius:3px;margin-right:.25rem;padding:2px 5px;font-size:.86rem}.yue kbd.compound>kbd{margin-left:.25rem}.yue .menuselection{font-size:.86rem;font-weight:500}.light .searchbox kbd,.light .yue kbd.kbd:not(.compound){background:linear-gradient(-225deg,#e6e6e6,#f8f8f8);border:0;box-shadow:inset 0 -2px #dbdbdb,inset 0 0 1px 1px #fff,0 1px 2px 1px #50505066}.dark .searchbox kbd,.dark .yue kbd.kbd:not(.compound){background:linear-gradient(-225deg,#353434,#141414);border:0;box-shadow:inset 0 -2px #373737,inset 0 0 1px 1px #222,0 1px 2px 1px #000}.yue p.centered{text-align:center}.yue section>img{margin-bottom:1rem}.hlist td{vertical-align:top}.light .light-hidden,.dark .dark-hidden,.light .dark-only,.dark .light-only{display:none}.yue .genindex-jumpbox,.yue .modindex-jumpbox{border-top:1px solid var(--sy-c-border);border-bottom:1px solid var(--sy-c-border);padding:2px .4rem}.yue table.modindextable td:first-of-type{width:28px}.yue table.modindextable img.toggler{margin:0}.yue table.modindextable tr.cap{background:var(--sy-c-surface);font-size:1.12rem;font-family:var(--sy-f-mono)}.yue h2+table.indextable,.yue table.indextable ul{margin-top:0}:root{--attention-icon:var(--lucide-alert-url);--attention-1:var(--crimson-surface);--attention-2:var(--crimson-a3);--attention-3:var(--crimson-9);--attention-4:var(--crimson-a11);--caution-icon:var(--lucide-zap-url);--caution-1:var(--amber-surface);--caution-2:var(--amber-a3);--caution-3:var(--amber-9);--caution-4:var(--amber-11);--danger-icon:var(--lucide-skull-url);--danger-1:var(--ruby-surface);--danger-2:var(--ruby-a3);--danger-3:var(--ruby-9);--danger-4:var(--ruby-a11);--error-icon:var(--lucide-close-url);--error-1:var(--red-surface);--error-2:var(--red-a3);--error-3:var(--red-9);--error-4:var(--red-a11);--hint-icon:var(--lucide-bell-url);--hint-1:var(--cyan-surface);--hint-2:var(--cyan-a3);--hint-3:var(--cyan-9);--hint-4:var(--cyan-a11);--important-icon:var(--lucide-flame-url);--important-1:var(--violet-surface);--important-2:var(--violet-a3);--important-3:var(--violet-9);--important-4:var(--violet-a11);--note-icon:var(--lucide-calendar-url);--note-1:var(--blue-surface);--note-2:var(--blue-a3);--note-3:var(--blue-9);--note-4:var(--blue-a11);--tip-icon:var(--lucide-rocket-url);--tip-1:var(--green-surface);--tip-2:var(--green-a3);--tip-3:var(--green-9);--tip-4:var(--green-a11);--warning-icon:var(--lucide-zap-url);--warning-1:var(--orange-surface);--warning-2:var(--orange-a3);--warning-3:var(--orange-9);--warning-4:var(--orange-a11);--seealso-icon:var(--lucide-link-url);--seealso-1:var(--gold-surface);--seealso-2:var(--gold-a3);--seealso-3:var(--gold-9);--seealso-4:var(--gold-a11);--todo-icon:var(--lucide-bookmark-url);--todo-1:var(--bronze-surface);--todo-2:var(--bronze-a3);--todo-3:var(--bronze-9);--todo-4:var(--bronze-a11);--versionadded-icon:var(--lucide-flame-url);--versionadded-1:var(--green-surface);--versionadded-2:var(--green-9);--versionchanged-icon:var(--lucide-zap-url);--versionchanged-1:var(--amber-surface);--versionchanged-2:var(--amber-9);--versionremoved-icon:var(--lucide-skull-url);--versionremoved-1:var(--red-surface);--versionremoved-2:var(--red-9);--deprecated-icon:var(--lucide-alert-url);--deprecated-1:var(--orange-surface);--deprecated-2:var(--orange-9)}.admonition{--icon-url:var(--lucide-bell-url);--color-1:var(--color-surface-accent);--color-2:var(--accent-a3);--color-3:var(--accent-9);--color-4:var(--accent-a11);border-left:4px solid var(--color-3);background-color:var(--color-1);flex-direction:column;margin-top:1rem;margin-bottom:1rem;padding:.825rem 1rem;display:flex;position:relative}.admonition:before{content:"";background-color:var(--color-3);border-radius:100%;width:20px;height:20px;position:absolute;top:6px;left:-12px}.admonition:after{content:"";-webkit-mask:var(--icon-url) no-repeat;-webkit-mask:var(--icon-url) no-repeat;mask:var(--icon-url) no-repeat;background-color:#fff;width:12px;height:12px;font-style:normal;position:absolute;top:10px;left:-8px;-webkit-mask-size:100% 100%;mask-size:100% 100%}.admonition p.admonition-title{color:var(--color-4);background-color:var(--color-2);--yue-c-code:var(--color-4);--yue-c-bold:var(--color-4);margin:-.825rem -1rem .825rem -19px;padding:4px 18px;font-size:.85rem;font-weight:600;line-height:1.72;position:relative}.admonition p.admonition-title svg{display:inline-block}.admonition.attention{--icon-url:var(--attention-icon);--color-1:var(--attention-1);--color-2:var(--attention-2);--color-3:var(--attention-3);--color-4:var(--attention-4)}.admonition.caution{--icon-url:var(--caution-icon);--color-1:var(--caution-1);--color-2:var(--caution-2);--color-3:var(--caution-3);--color-4:var(--caution-4)}.admonition.danger{--icon-url:var(--danger-icon);--color-1:var(--danger-1);--color-2:var(--danger-2);--color-3:var(--danger-3);--color-4:var(--danger-4)}.admonition.error{--icon-url:var(--error-icon);--color-1:var(--error-1);--color-2:var(--error-2);--color-3:var(--error-3);--color-4:var(--error-4)}.admonition.hint{--icon-url:var(--hint-icon);--color-1:var(--hint-1);--color-2:var(--hint-2);--color-3:var(--hint-3);--color-4:var(--hint-4)}.admonition.important{--icon-url:var(--important-icon);--color-1:var(--important-1);--color-2:var(--important-2);--color-3:var(--important-3);--color-4:var(--important-4)}.admonition.note{--icon-url:var(--note-icon);--color-1:var(--note-1);--color-2:var(--note-2);--color-3:var(--note-3);--color-4:var(--note-4)}.admonition.tip{--icon-url:var(--tip-icon);--color-1:var(--tip-1);--color-2:var(--tip-2);--color-3:var(--tip-3);--color-4:var(--tip-4)}.admonition.warning{--icon-url:var(--warning-icon);--color-1:var(--warning-1);--color-2:var(--warning-2);--color-3:var(--warning-3);--color-4:var(--warning-4)}.admonition.seealso{--icon-url:var(--seealso-icon);--color-1:var(--seealso-1);--color-2:var(--seealso-2);--color-3:var(--seealso-3);--color-4:var(--seealso-4)}.admonition.admonition-todo{--icon-url:var(--todo-icon);--color-1:var(--todo-1);--color-2:var(--todo-2);--color-3:var(--todo-3);--color-4:var(--todo-4)}.yue .admonition>*{margin-top:0;margin-bottom:1rem}.yue .admonition>:last-child{margin-bottom:0!important}span.versionmodified{color:var(--sy-c-bold);font-weight:600}div.versionadded,div.versionchanged,div.versionremoved,div.deprecated{border-left:4px solid var(--color-2);background-color:var(--color-1);margin:1rem 0;padding:6px 1rem;line-height:1.72;position:relative}div.versionadded:before,div.versionchanged:before,div.versionremoved:before,div.deprecated:before{content:"";color:#fff;background-color:var(--color-2);text-align:center;width:20px;height:20px;font:normal bold 14px/20px var(--sy-f-mono);border-radius:100%;position:absolute;top:10px;left:-12px}div.versionadded:after,div.versionchanged:after,div.versionremoved:after,div.deprecated:after{content:"";-webkit-mask:var(--icon-url) no-repeat;-webkit-mask:var(--icon-url) no-repeat;mask:var(--icon-url) no-repeat;background-color:#fff;width:12px;height:12px;font-style:normal;position:absolute;top:14px;left:-8px;-webkit-mask-size:100% 100%;mask-size:100% 100%}div.versionadded{--color-1:var(--versionadded-1);--color-2:var(--versionadded-2);--icon-url:var(--versionadded-icon)}div.versionchanged{--color-1:var(--versionchanged-1);--color-2:var(--versionchanged-2);--icon-url:var(--versionchanged-icon)}div.versionremoved{--color-1:var(--versionremoved-1);--color-2:var(--versionremoved-2);--icon-url:var(--versionremoved-icon)}div.deprecated{--color-1:var(--deprecated-1);--color-2:var(--deprecated-2);--icon-url:var(--deprecated-icon)}div.versionadded>p,div.versionchanged>p,div.versionremoved>p,div.deprecated>p{margin:0}.yue blockquote.epigraph{text-align:center;border-left:0;padding:1rem 2.4rem}.yue blockquote.highlights{background-color:var(--sy-c-surface);border-left-width:4px;padding-top:.2rem;padding-bottom:.2rem}.yue blockquote.pull-quote{border-left:0;padding:2.4rem 3.6rem 1.2rem;font-size:1.24rem;position:relative}.yue blockquote.pull-quote:before{content:"“";color:var(--yue-c-quote-symbol);font:700 4rem/1 Times New Roman,Georgia,Palatino,Times,serif;position:absolute;top:0;left:.5rem}.yue blockquote.pull-quote .attribution{text-align:right}:root{--code-block-background:var(--accent-a2);--code-block-caption-background:var(--accent-a3);--code-block-highlight:var(--accent-a3);--code-block-linenos-divider:var(--gray-a6)}html.light{--syntax-text:var(--syntax-light-text);--syntax-comment:var(--syntax-light-comment)}html.dark,html.light .dark-code{--syntax-text:var(--syntax-dark-text);--syntax-comment:var(--syntax-dark-comment)}.light .dark-code{--code-block-background:var(--black-a12);--code-block-caption-background:#1c2024;--code-block-highlight:var(--white-a2);--code-block-linenos-divider:var(--white-a4)}.highlight{color:var(--syntax-text)}.highlight .hll{background-color:var(--code-block-highlight);display:block}pre.literal-block{background-color:var(--code-block-background);border-radius:6px;padding:1rem;font-size:.96rem;line-height:1.48;overflow:auto}.highlight,.literal-block-wrapper{--margin:1rem;--radius:6px}.literal-block-wrapper div[class^=highlight-]{display:flex}.literal-block-wrapper .highlight{width:100%}.highlight>pre{padding:var(--margin);font-size:.96rem;line-height:1.48;font-family:var(--sy-f-mono);background-color:var(--code-block-background);border-radius:var(--radius);overflow:auto}.win .highlight>pre{font-family:"Twemoji Country Flags", var(--sy-f-mono)}.highlight .gp,.highlight .linenos{-webkit-user-select:none;user-select:none}.highlight .linenos{box-shadow:-.05rem 0 var(--code-block-linenos-divider) inset;opacity:.6;margin-right:.8rem;padding-right:.8rem;display:inline-block}.highlight .hll{margin-left:calc(0rem - var(--margin));margin-right:calc(0rem - var(--margin));padding:0 var(--margin)}.code-block-caption{color:var(--syntax-text);background-color:var(--code-block-caption-background);padding:.4rem var(--margin);border-radius:var(--radius) var(--radius) 0 0;font-size:.84rem;font-weight:600;display:flex}.code-block-caption+div>.highlight>pre{border-top-left-radius:0;border-top-right-radius:0}div[class^=highlight]>.highlight>pre{display:grid}.yue .table-wrapper{border:1px solid var(--yue-c-table-border);border-radius:6px;width:100%;margin-top:2rem;margin-bottom:2rem;overflow-x:auto}.yue .table-wrapper table{margin:0}.yue .table-wrapper thead tr{border-top:1px solid var(--yue-c-td-border)}.yue .table-wrapper thead tr:first-child{border-top:0}.yue .table-wrapper th{background-color:var(--yue-c-th-background);border-left:1px solid var(--yue-c-td-border);padding:.725rem 1rem}.yue .table-wrapper td{border-left:1px solid var(--yue-c-td-border);padding:.5rem 1rem}.yue .table-wrapper tr>th:first-child,.yue .table-wrapper tr>td:first-child{border-left:0}.yue .table-wrapper caption{border-bottom:1px solid var(--yue-c-th-border);margin:0;padding:.5rem}.yue .table-wrapper tbody tr.row-odd{background-color:var(--yue-c-row-background)}.yue table.hlist td{vertical-align:top}.table-wrapper{scrollbar-gutter:auto;overflow-x:auto}.table-wrapper::-webkit-scrollbar{width:.75rem;height:.75rem}.table-wrapper::-webkit-scrollbar-thumb{border-radius:10px}.table-wrapper::-webkit-scrollbar-track{background-color:#0000}.table-wrapper:hover::-webkit-scrollbar-thumb{background-color:#9b9b9b33;background-clip:content-box;border:3px solid #0000}.yue table.ghost th,.yue table.ghost td{background-color:#0000;border-left:0;border-right:0}.yue table.ghost caption{border-bottom:3px solid var(--yue-c-td-border);margin-bottom:0;padding-bottom:.5rem}.yue table.ghost thead tr:first-child{border-top:0;border-bottom-width:3px}.yue .table-wrapper.ghost{border:0}.yue .table-wrapper.sphinx-datatable{overflow-x:hidden}.yue .table-wrapper:not(.ghost) .dt-layout-row{margin:0}.table-wrapper .dt-layout-row:not(.dt-layout-table){padding:.5rem 1rem}.table-wrapper .dt-layout-row.dt-layout-table{border-top:1px solid var(--yue-c-th-border);border-bottom:1px solid var(--yue-c-th-border);overflow-x:auto}.table-wrapper .dt-layout-table th,.yue .table-wrapper div.dt-container.dt-empty-footer td{border-bottom:0}.yue .table-wrapper .dt-layout-table th:hover{outline-color:var(--accent-a3)}.table-wrapper div.dt-container .dt-search input{border-color:var(--sy-c-border);font-size:.92rem;line-height:1.4}.table-wrapper div.dt-container .dt-input{border-color:var(--sy-c-border)}.table-wrapper div.dt-container .dt-paging .dt-paging-button{justify-content:center;align-items:center;width:32px;height:32px;padding:0;font-size:.875rem;display:inline-flex}.table-wrapper div.dt-container .dt-paging .dt-paging-button:hover{background:var(--accent-a3);border-color:var(--accent-a3);color:var(--accent-a11)!important}.table-wrapper div.dt-container .dt-paging .dt-paging-button.current{border-color:var(--gray-a4);background:0 0}.table-wrapper div.dt-container .dt-paging .dt-paging-button.current:hover{background:var(--accent-a3)}.table-wrapper .dt-info{font-size:.875rem}:root{--sig-property:var(--gray-12);--sig-name:var(--accent-10);--sig-typehint:var(--indigo-9);--sig-param:var(--gray-11)}dt.sig{text-indent:-2.4rem;border-radius:6px;padding:.25rem .5rem .25rem 3rem;font-size:.92rem;position:relative}dt.sig:after{content:"";clear:both;display:table}dt.sig:hover{background:var(--sy-c-surface)}dt.sig+dd{margin-left:2rem;font-size:.92rem}dt.sig>em.property:first-child{color:var(--sig-property)}dl.field-list{margin-top:0}dl.field-list a{font-weight:400}dt.sig+dd>div{margin-bottom:1rem}dt.sig+dd>dl.field-list>dt{text-transform:uppercase;font-size:.76rem}em.property,em.sig-param{font-style:normal}em.sig-param{color:var(--sig-param)}.sig-param a.reference{font-weight:400}span.sig-prename{color:var(--sig-name);font-weight:400}span.sig-name{color:var(--sig-name);font-weight:600}span.sig-return-icon{color:var(--sy-c-light)}span.sig-return-typehint,span.sig-return-typehint>a{color:var(--sig-typehint)}span.sig-paren,span.pre{font-family:var(--sy-f-mono)}dt.sig>a.internal{color:var(--sy-c-light);border:0;font-size:.82rem}dt.sig>a.internal:before{content:"\a ";white-space:pre}.viewcode-block{position:relative}.viewcode-back{font-size:.8rem;position:absolute;top:-1.5rem}.classifier{font-style:oblique;font-weight:400}.classifier:before{content:":";margin-left:.1rem;margin-right:.5rem;font-style:normal;display:inline-block}.yue .table-wrapper.autosummary{border-left:0;border-right:0;border-radius:0}.yue .table-wrapper table.autosummary td{border:none;padding-top:.25rem;padding-bottom:.25rem}.yue p.rubric+div.autosummary{margin-top:0}.hamburger{cursor:pointer;width:16px;height:14px;display:inline-block;position:relative;overflow:hidden}.hamburger>span{background-color:var(--sy-c-text);width:16px;height:2px;transition:top .25s,transform .25s;position:absolute;left:0}.hamburger_1{top:0}.hamburger_2{top:6px;transform:translate(-.5rem)}.hamburger_3{top:12px;transform:translate(-.25rem)}button[aria-expanded=true] .hamburger .hamburger_1{top:6px;transform:translate(0)rotate(225deg)}button[aria-expanded=true] .hamburger .hamburger_2{top:6px;transform:translate(18px)}button[aria-expanded=true] .hamburger .hamburger_3{top:6px;transform:translate(0)rotate(135deg)}.searchbox{position:relative}.searchbox input{appearance:none;width:100%;font-size:.92rem;font-family:var(--sy-f-text);background:var(--sy-c-surface);border-radius:6px;outline:0;padding:6px 12px}.searchbox kbd,.searchbox button{font-size:.68rem;font-weight:600;font-family:var(--sy-f-mono);border:1px solid var(--sy-c-border);background-color:var(--sy-c-background);opacity:1;border-radius:3px;margin:6px;padding:2px 6px;transition:opacity .2s;position:absolute;right:0}.searchbox input:focus+kbd{opacity:0}.searchform{align-items:center;display:flex;position:relative}.searchform input[name=q]{appearance:none;width:100%;font-size:.92rem;font-family:var(--sy-f-text);background:var(--sy-c-surface);border-radius:6px;outline:0;padding:6px 12px}.searchform input[name=q]+button{font-size:.68rem;font-weight:600;font-family:var(--sy-f-text);border:1px solid var(--sy-c-divider);background-color:var(--sy-c-background);opacity:1;border-radius:3px;margin:6px;padding:2px 6px;transition:opacity .2s;position:absolute;right:0}.search .highlighted{background-color:var(--accent-a4)}#search-results{border-top:1px solid var(--sy-c-border)}#search-results h2{margin-top:2rem;margin-bottom:.725rem}#search-results .search-summary{color:var(--sy-c-light);font-weight:500}#search-results ul.search{margin-left:0;padding-top:.625rem;padding-bottom:2rem;padding-left:0;list-style-type:none}#search-results ul.search>li{padding-left:0}#search-results ul.search>li+li{border-top:1px solid var(--sy-c-divider);padding-top:1rem}#search-results ul.search li>a{font-weight:600}#search-results ul.search p.context{margin-top:.5rem;font-size:.875rem}.demo{border:1px solid var(--sy-c-border);border-radius:6px}.demo-code .highlight>pre{border-bottom-right-radius:0;border-bottom-left-radius:0}.demo-result{padding:1rem}.container.image-1,.container.video-1{border:.5rem solid var(--accent-a3);border-radius:6px}.container.image-1>img{border-radius:4px;margin:0}.container.video-1 video,.container.video-1 iframe{border-radius:4px;width:100%;margin:0}.container.image-2,.container.video-2{border:1px solid var(--sy-c-border);border-radius:6px;padding:1rem}.container.image-2>img,.container.video-2>video{margin:0}.container.buttons{margin:2rem 0 4.2rem}.container.buttons>p{flex-wrap:wrap;gap:1rem;display:flex}.container.buttons a{border:2px solid var(--sy-c-border);background-color:var(--sy-c-surface);border-radius:2.6rem;padding:0 2rem;font-weight:600;line-height:2.6rem;text-decoration:none;transition:all .2s;display:inline-block}.container.buttons a:first-child{color:var(--accent-contrast);background-color:var(--accent-9);border-color:var(--accent-9)}.container.buttons a:hover{color:var(--sy-c-bold);border-color:var(--accent-9);background-color:var(--sy-c-background)}.container.rounded-image img{border-radius:99999px}#ethical-ad-placement .ethical-sidebar{background-color:var(--sy-c-surface);border:none;padding:.8rem;position:relative}#ethical-ad-placement .ethical-text a{color:var(--sy-c-text)!important}#ethical-ad-placement .ethical-text a:hover{color:var(--sy-c-link-hover)!important}.sy-main #ethical-ad-placement .ethical-sidebar{max-width:380px;margin-left:0}.sy-main #ethical-ad-placement .ethical-image-link{flex-shrink:0;margin-right:.4rem}.sy-main #ethical-ad-placement .ethical-content{display:flex}.sy-main #ethical-ad-placement .ethical-text{margin-top:0}.sy-main #ethical-ad-placement .ethical-callout{position:absolute;bottom:.4rem;right:.4rem}#carbonads{background-color:var(--sy-c-surface);border:none;border-radius:8px;margin:1rem 0;padding:.8rem .8rem 1.6rem;display:block;position:relative}#carbonads a{border:0;font-weight:400}#carbonads img{margin:0}.carbon-wrap{flex-direction:column;justify-content:space-between;align-items:center;display:flex}.carbon-text{text-align:center;margin:.5rem 0;font-size:.78rem;line-height:1.42;display:block}.carbon-text:hover{color:var(--sy-c-link-hover)}.carbon-poweredby{opacity:.68;text-transform:uppercase;font-size:.68rem;position:absolute;bottom:.5rem;right:.8rem}.carbon-poweredby:hover{text-decoration:underline}.sy-main #carbonads{max-width:380px;margin-top:1.6rem;padding:1rem}.sy-main .carbon-wrap{flex-direction:row;align-items:flex-start}.sy-main .carbon-text{text-align:left;margin-top:0;margin-left:1rem;font-size:.86rem}#bsa-custom-container{text-align:right}.yue a.bsa-container{text-align:left;border-bottom:0;border-radius:6px;flex-flow:row;justify-content:space-between;align-items:center;padding:15px 20px;text-decoration:none;display:flex;box-shadow:inset 0 0 0 1px #0000001a}.yue a.bsa-ad-via{background:var(--gray-a3);border:none;border-radius:2px;padding:3px 10px;font-size:10px;font-weight:300}.bsa-main{flex-flow:row;flex-grow:1;justify-content:center;align-items:center;margin:0 auto;display:flex}.bsa-img{max-height:40px;margin-right:20px;line-height:0}.yue a.bsa-container .bsa-img{margin-top:0;margin-bottom:0}.bsa-details{flex-flow:column;margin-right:20px;display:flex}.bsa-tagline{letter-spacing:1.5px;text-transform:uppercase;margin-bottom:3px;font-size:9px;font-weight:600;line-height:1}.bsa-desc{letter-spacing:1px;max-width:600px;font-size:12px;font-weight:400;line-height:1.4}.bsa-cta{letter-spacing:1px;text-transform:uppercase;white-space:nowrap;border-radius:3px;padding:10px 16px;font-size:10px;font-weight:600;line-height:1;transition:all .3s ease-in-out;transform:translateY(-1px)}@media (max-width:940px){.bsa-details{margin-right:0;font-size:14px}.bsa-cta{display:none}}@media (min-width:768px) and (max-width:820px){.bsa-img{display:none}}@media (max-width:480px){.bsa-img{display:none}}.repo-stats{border:1px solid var(--sy-c-divider);border-radius:6px;margin-bottom:1rem;padding:.5rem}.repo-stats:hover{background-color:var(--sy-c-surface)}.repo-stats-count{color:var(--sy-c-light)}.repo-stats strong{font-weight:500;font-family:var(--sy-f-mono);color:inherit}.edit-this-page{border-top:1px solid var(--sy-c-divider);margin:1rem 0;padding:.5rem 0;font-size:.8rem;font-weight:600}.repo-stats+.edit-this-page{border-top:0;margin-top:0;padding-top:0}.edit-this-page a{color:var(--sy-c-text)}.edit-this-page a:hover{color:var(--sy-c-link-hover)}.edit-this-page a:after{content:" →"}.back-to-top{z-index:10;background:var(--sy-c-background);border-radius:2rem;align-items:center;gap:.25rem;padding:.4rem .8rem .4rem .6rem;font-size:.8rem;display:none;position:fixed;bottom:68px;left:50%;transform:translate(-50%);box-shadow:0 .2rem .5rem #0000000d,0 0 1px #6b728080}.dark .back-to-top{background:var(--slate-2);box-shadow:0 .2rem .5rem #ffffff0d,0 0 1px #9aa4b880}.back-to-top:hover{color:var(--accent-contrast);background:var(--accent-9)}.back-to-top svg{fill:currentColor;width:1rem;height:1rem;display:inline-block}.back-to-top[data-visible=true]{display:flex}.icon-link{display:inline-block}.icon-link span{vertical-align:middle;display:inline-block}.icon-link .icon{border:1px solid var(--sy-c-border);opacity:.8;border-radius:6px;margin-right:.4rem;padding:.1rem}.icon-link svg{width:1.5rem;height:1.5rem}.icon-link:hover .icon{opacity:1}#copy-page-trigger{border:1px solid var(--gray-a4);background-color:var(--sy-c-background);border-radius:.625rem;align-items:center;font-size:.875rem;display:inline-flex;overflow:hidden}#copy-page-trigger i.i-lucide{transition:transform .2s}#copy-page-trigger button[aria-expanded=true]>i{transform:rotate(-180deg)}#copy-page-trigger button{background-color:var(--sy-c-background);vertical-align:middle;height:32px;transition:background-color .2s}#copy-page-trigger button:hover{background-color:var(--sy-c-surface)}#copy-page-trigger button+button{border-left:1px solid var(--gray-a4)}#copy-page-content{z-index:9;border:1px solid var(--gray-a4);box-shadow:var(--sy-dropdown-shadow);background:var(--sy-c-background);border-radius:.625rem;min-width:200px;margin-top:.25rem;padding:.75rem .5rem;position:absolute}#copy-page-content[aria-hidden=true]{display:none}#copy-page-content button,#copy-page-content a{white-space:nowrap;border-radius:.25rem;align-items:center;padding:.4rem .5rem;font-size:.875rem;display:inline-flex}#copy-page-content button:hover,#copy-page-content a:hover{background:var(--gray-a3)}#copy-page-content .iconify-icon,#copy-page-content iconify-icon{border:1px solid var(--gray-a4);border-radius:.25rem;justify-content:center;align-items:center;width:28px;height:28px;margin-right:.5rem;font-size:.825rem;display:inline-flex}#copy-page-content a:after{content:"";-webkit-mask:var(--lucide-external-link-url) no-repeat;-webkit-mask:var(--lucide-external-link-url) no-repeat;mask:var(--lucide-external-link-url) no-repeat;vertical-align:top;background-color:var(--gray-a9);width:.625em;height:.625em;margin-left:.1rem;font-style:normal;display:inline-block;position:relative;top:-2px;-webkit-mask-size:100% 100%;mask-size:100% 100%}#copy-page-trigger .i-lucide[data-icon=copy],#copy-page-content .i-lucide[data-icon=copy]{--icon-url:var(--lucide-copy-url)}#copy-page-trigger .i-lucide[data-icon=check],#copy-page-content .i-lucide[data-icon=check]{--icon-url:var(--lucide-check-url)}#copy-page-trigger .i-lucide[data-icon=loader],#copy-page-content .i-lucide[data-icon=loader]{--icon-url:var(--lucide-loader-url)}@media (min-width:64rem){.copy-page-wrapper+.yue>section>h1:first-of-type{padding-right:180px}#copy-page-content{right:0}}.announcement{width:100%;color:var(--sy-c-banner,var(--accent-contrast));background-color:var(--sy-c-banner-bg,var(--accent-a11));z-index:20;align-items:center;padding:.8rem 2rem;display:flex;position:sticky;top:0;left:0}.announcement a{text-decoration:underline}.announcement ::selection{color:var(--sy-c-banner,var(--accent-contrast))}.announcement-inner{width:100%}.announcement-close{position:absolute;top:.8rem;right:1rem}.sy-head{top:var(--sy-s-banner-height);height:var(--sy-s-navbar-height);z-index:20;background-color:#0000;position:sticky}.sy-head-blur{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);background-color:var(--sy-c-background-dropback);width:100%;height:100%;box-shadow:0 0 var(--sy-c-background-contrast), 0 2px 4px var(--gray-a1), 0 1px 0 var(--sy-c-divider);z-index:-1;position:absolute;top:0;left:0}.sy-head-inner{padding-left:max(env(safe-area-inset-right), 1.5rem);padding-right:max(env(safe-area-inset-right), 1rem);height:var(--sy-s-navbar-height);justify-content:space-between;align-items:center;display:flex}.sy-head-brand img{height:28px}.sy-head-brand img+strong,.sy-head-brand .dark-logo{display:none}.dark .sy-head-brand .dark-logo{display:inline}.dark .sy-head-brand .light-logo{display:none}.light .sy-head-brand .light-logo{display:inline}.light .sy-head-brand .dark-logo{display:none}.sy-head-links button,.sy-head-links a{white-space:nowrap;padding:.5rem;font-size:.95rem;font-weight:500}.sy-head-links .link i.external-link{opacity:.6;color:var(--sy-c-light);margin-left:2px;font-size:68%}.sy-head-links .link>ul a{white-space:normal;display:block}.sy-head-links .link>ul a:hover{background:var(--sy-c-surface);border-radius:6px}.sy-head-links .link>ul small{color:var(--sy-c-light);font-weight:400;display:block}.sy-head-socials{align-items:center;display:flex}.sy-head-socials a{align-items:center;padding:.5rem;display:flex}.sy-head-actions button{height:var(--sy-s-navbar-height);padding:0 .5rem}@media (max-width:767px){body[data-expanded*=head-nav]{overflow:hidden}.sy-head-nav{top:var(--sy-s-offset-top);box-sizing:border-box;border-top:1px solid var(--sy-c-divider);background-color:var(--sy-c-background);width:100%;padding:4rem 1.8rem 0;display:none;position:fixed;bottom:0;left:0;right:0;overflow-y:auto}.sy-head-nav[aria-hidden=false]{display:block}.sy-head-links{margin-left:auto;margin-right:auto}.sy-head-links .link{margin:.5rem 0}.sy-head-links .link i.chevron{display:none}.sy-head-links .link>ul{margin:.5rem 0 .5rem 1rem}.sy-head-extra form.searchbox{position:absolute;top:1rem;left:1.8rem;right:1.8rem}.sy-head-extra{flex-direction:column;width:100%;padding:2rem 0 1rem}}@media (min-width:768px){.sy-head-inner{padding-right:max(env(safe-area-inset-right), 1.5rem)}.sy-head-nav{flex-grow:1;justify-content:space-between;align-items:center;display:flex}.sy-head-links[data-align=right]{--head-links-justify-content:flex-end}.sy-head-links[data-align=center]{--head-links-justify-content:center}.sy-head-links{white-space:nowrap;justify-content:var(--head-links-justify-content,flex-start);flex-grow:1;padding:0 1rem;display:flex;overflow:auto}.sy-head-links .link{height:var(--sy-s-navbar-height);align-items:center;display:inline-flex}.sy-head-links a:hover{color:var(--sy-c-link-hover)}.sy-head-links .link:hover>a{background-color:var(--sy-c-surface);border-radius:6px}.sy-head-links .link i.chevron-down{color:var(--sy-c-light)}.sy-head-links .link>ul{visibility:hidden;background-color:var(--sy-c-background);height:0;top:var(--sy-s-navbar-height);border:1px solid var(--sy-c-divider);box-shadow:var(--sy-dropdown-shadow);z-index:9;border-radius:6px;max-width:320px;margin-top:-10px;padding:15px;position:absolute}.sy-head-links .link>ul[aria-hidden=false],.sy-head-links .link:hover>ul{visibility:visible;height:auto}.sy-head-links .link>ul>li{padding:.2rem 0}.sy-head-socials{margin-left:.5rem}}.sy-foot{border-top:1px solid var(--sy-c-foot-divider);color:var(--sy-c-foot-text);background-color:var(--sy-c-foot-background);padding-top:1.5rem;padding-bottom:1rem}.sy-foot-inner{padding-left:max(env(safe-area-inset-right), 1.5rem);padding-right:max(env(safe-area-inset-right), 1.5rem)}.sy-foot-copyright{font-size:.84rem}.sy-foot-copyright a{font-weight:500}.sy-foot-copyright a:hover{text-decoration:underline}.sy-foot-socials a{color:var(--sy-c-foot-text);font-size:1.4rem}.sy-foot-socials a+a{margin-left:.5rem}.sy-foot-socials a svg{width:1.4rem;height:1.4rem;display:inline-block}.sy-lside .sidebar-links{margin-bottom:2rem}@media (min-width:768px){.sy-lside .sy-lside-inner{top:var(--sy-s-offset-top)}.sy-lside .sy-scrollbar{max-height:calc(100vh - var(--sy-s-offset-top));overflow-x:hidden}}.yue *{scroll-margin-top:calc(var(--sy-s-offset-top) + 68px)}.sy-main{min-height:calc(100vh - var(--sy-s-offset-top) - 80px)}.sy-content{max-width:64rem;min-height:calc(100vh - var(--sy-s-offset-top) - 80px)}@media (max-width:767px){#lside{z-index:18;top:var(--sy-s-offset-top);width:300px;max-width:100%;height:calc(100vh - var(---sy-s-offset-top));background:var(--sy-c-background);transition:transform .2s;position:fixed;bottom:0;left:0;overflow:auto;transform:translate(-100%)}#lside[aria-hidden=false]{transform:translate(0)}.lside-overlay{top:var(--sy-s-offset-top);background-color:var(--sy-c-overlay);opacity:0;width:0;height:0;transition:width 0 .25s, height 0 .25s, opacity .25s;position:fixed;left:0}#lside[aria-hidden=false]+.lside-overlay{opacity:1;z-index:16;width:100%;height:100%}}@media (max-width:1279px){.sy-rside{z-index:25;background:var(--sy-c-background);width:20rem;max-width:100%;box-shadow:0 0 var(--sy-c-background-contrast), -12px 0 16px var(--gray-a1);padding-top:2rem;padding-bottom:1rem;transition:transform .2s;position:fixed;top:0;bottom:0;right:0;overflow:auto;transform:translate(110%)}#rside[aria-hidden=false]{transform:translate(0)}.rside-close{justify-content:center;align-items:center;width:2rem;height:2rem;font-size:1.4rem;display:flex;position:absolute;top:16px;right:16px}.rside-overlay{background-color:var(--sy-c-overlay);opacity:0;width:0;height:0;transition:width 0 .25s, height 0 .25s, opacity .25s;position:fixed;top:0;left:0}#rside[aria-hidden=false]+.rside-overlay{opacity:1;z-index:22;width:100%;height:100%}}@media (min-width:768px){.sy-main{width:calc(100% - 18rem);max-width:52rem}}@media (min-width:1280px){.sy-main{width:calc(100% - 34rem);max-width:none}.sy-rside .sy-scrollbar{max-height:calc(100vh - var(--sy-s-offset-top) - env(safe-area-inset-bottom))}.yue *{scroll-margin-top:calc(var(--sy-s-offset-top) + 24px)}}.nav-languages button,.nav-versions button{cursor:pointer;white-space:nowrap;background:0 0;border:0;margin:0;padding:0}.nav-versions .chevron-down{color:var(--sy-c-light)}@media (max-width:767px){.nav-versions,.nav-languages{background-color:var(--sy-c-surface);border-radius:6px;width:100%;margin-bottom:1rem;padding-bottom:.6rem}.nav-versions button,.nav-languages button{color:var(--sy-c-light);padding:.5rem 1rem;font-size:.76rem;font-weight:500}.nav-versions button>i,.nav-languages button>i{display:none}.nav-versions ul{padding:0 .6rem}.nav-versions li{padding:.2rem .4rem;display:inline-block}.nav-languages li{padding:.32rem 1rem;font-size:.94rem}}@media (min-width:768px){.nav-versions,.nav-languages{width:auto;height:var(--sy-s-navbar-height);color:var(--sy-c-text);background:0 0;align-items:center;display:flex;position:relative}.nav-languages button,.nav-versions button{border-right:1px solid var(--gray-3);padding:0 .5rem}.nav-versions-choices,.nav-languages-choices{visibility:hidden;box-sizing:border-box;background-color:var(--sy-c-background);min-width:120px;max-height:60vh;box-shadow:var(--sy-dropdown-shadow);border-radius:6px;padding:.8rem 1rem;position:absolute;top:3rem;right:-.6rem;overflow:hidden auto}.nav-versions:hover .nav-versions-choices,.nav-languages:hover .nav-languages-choices{visibility:visible}.nav-versions li,.nav-languages li{padding:.1rem 0}.nav-versions a,.nav-languages a{color:var(--sy-c-text);white-space:nowrap;padding:.2rem .6rem;display:block}.nav-versions a:hover,.nav-languages a:hover{color:var(--sy-c-link-hover);background:var(--sy-c-surface);border-radius:6px}}.sy-breadcrumbs{top:var(--sy-s-offset-top);background-color:var(--sy-c-background);z-index:5;padding:0 1.5rem;position:sticky}.sy-breadcrumbs-inner{border-bottom:1px solid var(--sy-c-divider);padding:.8rem 0}.sy-breadcrumbs ol{white-space:nowrap;font-size:.94rem;display:flex;overflow:auto}.sy-breadcrumbs button{align-items:center;display:flex}.sy-breadcrumbs ol a{color:var(--sy-c-light)}.sy-breadcrumbs ol a:hover{color:var(--sy-c-bold)}.sy-breadcrumbs ol a+span{color:var(--sy-c-light);padding:0 .4rem;font-weight:300}@media (min-width:1280px){.sy-breadcrumbs{display:none}}@media (min-width:768px){.sy-breadcrumbs-inner{padding:1.5rem 0 1rem}}.globaltoc{padding-bottom:20px}.globaltoc .caption{font-size:.86rem;font-weight:500;font-family:var(--sy-f-heading);color:var(--sy-c-light);text-transform:uppercase;letter-spacing:.4px;border-top:1px solid var(--sy-c-divider);padding:.8rem 0 .4rem}.globaltoc>p.caption:first-of-type{border-top:none;padding-top:0}.globaltoc .caption+ul{margin-bottom:1.5rem}.globaltoc ul+.caption{margin-top:2.5rem}.globaltoc li{margin:.6rem 0}.globaltoc li>ul{margin-left:.6rem;font-size:.96rem}.globaltoc li.toctree-l1>ul{border-left:1px solid var(--gray-3);margin-left:.2rem}.globaltoc li.toctree-l2{border-left:1px solid #0000;margin-left:-1px;padding-left:.9rem}.globaltoc li.toctree-l2.current{border-color:var(--sy-c-link)}.globaltoc>ul a.current{color:var(--sy-c-link);font-weight:500}.globaltoc>ul a:hover{color:var(--sy-c-link-hover)}.globaltoc a.external:after{content:"";-webkit-mask:var(--lucide-external-link-url) no-repeat;-webkit-mask:var(--lucide-external-link-url) no-repeat;mask:var(--lucide-external-link-url) no-repeat;vertical-align:middle;background-color:var(--sy-c-light);width:.825rem;height:.825rem;margin-left:.2rem;font-style:normal;display:inline-block;-webkit-mask-size:100% 100%;mask-size:100% 100%}.globaltoc li{position:relative}.globaltoc li>button{border-radius:3px;justify-content:center;align-items:center;width:1.2rem;height:1.2rem;display:flex;position:absolute;top:.2rem;right:0}.globaltoc li>button:hover{background-color:var(--sy-c-surface)}.globaltoc li.current>ul,.globaltoc li._expand>ul{display:block}.globaltoc li>ul,.globaltoc li._collapse>ul{display:none}.globaltoc li>button>i{transition:transform .2s;transform:rotate(0)}.globaltoc li.current>button>i,.globaltoc li._expand>button>i{transform:rotate(90deg)}.globaltoc li._collapse>button>i{transform:rotate(0)}.sy-deprecated{background-color:#ffdd001a;border-radius:6px;padding:.8rem;font-size:.85rem}.sy-deprecated a{color:var(--sy-c-link);text-decoration:underline}.sy-deprecated a:hover{color:var(--sy-c-link-hover)}.sy-rside-inner>div{margin-bottom:1rem}.sy-rside-inner>div>h3{letter-spacing:.4px;text-transform:uppercase;margin-bottom:1rem;font-size:.8rem;font-weight:500}html[lang=zh] .sy-rside-inner>div>h3,html[lang=zh-TW] .sy-rside-inner>div>h3,html[lang=ja] .sy-rside-inner>div>h3,html[lang=ko] .sy-rside-inner>div>h3{letter-spacing:0;font-size:.86rem;font-weight:600}.localtoc>ul li{margin-top:.36rem;margin-bottom:.36rem}.localtoc>ul li>a:hover{color:var(--sy-c-link-hover)}.localtoc>ul li.active>a{color:var(--sy-c-link)}.localtoc>ul>li ul{padding-left:.8rem}.sy-rside ul.this-page-menu{margin-top:-.6rem}.sy-rside ul.this-page-menu a{font-size:.96rem}.sy-rside ul.this-page-menu a:hover{color:var(--sy-c-link-hover)}.navigation{border-top:1px solid var(--sy-c-divider);gap:2rem;margin-top:2rem;padding-top:1rem}.navigation>div{width:100%}.navigation a{align-items:center;display:inline-flex}.navigation a:hover{color:var(--sy-c-link-hover)}.navigation-next{text-align:right}.navigation-next a{justify-content:end}.navigation .page-info{padding:0 8px}.navigation .page-info>span{color:var(--sy-c-light);font-size:.8rem}:root{--readthedocs-search-font-family:var(--sy-f-text);--readthedocs-search-color:var(--sy-c-text);--readthedocs-search-input-background-color:var(--gray-3);--readthedocs-search-content-border-color:var(--gray-4);--readthedocs-search-content-background-color:var(--sy-c-background);--readthedocs-search-result-section-color:var(--sy-c-text);--readthedocs-search-result-section-subheading-color:var(--sy-c-heading);--readthedocs-search-result-section-highlight-color:var(--accent-9);--readthedocs-search-result-section-border-color:var(--sy-c-border)}.yue button.copybtn{color:var(--syntax-text);background-color:#0000;border:none;justify-content:center;align-items:center}.yue button.copybtn>svg{width:1.4rem;height:1.4rem}.yue button.copybtn:hover{color:var(--syntax-comment)}.yue .highlight button.copybtn:hover{background-color:#0000}.yue button.copybtn:after{color:var(--syntax-text);background-color:#0000}.yue button.copybtn.success{border-color:var(--green-a10);color:var(--green-a10)}.yue button.copybtn.success:after{color:var(--green-a10)}.code-block-caption+div>.highlight .copybtn{opacity:.5;top:-2em}html.light .sd-tab-content{--code-block-background:var(--color-surface-accent);--code-block-caption-background:var(--accent-3)}.yue{--sd-color-primary:var(--accent-a11);--sd-color-secondary:var(--gold-a11);--sd-color-success:var(--green-a11);--sd-color-info:var(--blue-a11);--sd-color-warning:var(--orange-a11);--sd-color-danger:var(--red-a11);--sd-color-light:var(--sand-a2);--sd-color-muted:var(--gray-8);--sd-color-dark:#212122;--sd-color-black:black;--sd-color-white:white;--sd-color-primary-highlight:var(--accent-a8);--sd-color-secondary-highlight:var(--gold-a8);--sd-color-success-highlight:var(--green-a8);--sd-color-info-highlight:var(--blue-a8);--sd-color-warning-highlight:var(--orange-a8);--sd-color-danger-highlight:var(--red-a8);--sd-color-light-highlight:var(--gray-4);--sd-color-muted-highlight:var(--gray-11);--sd-color-dark-highlight:#121211;--sd-color-black-highlight:black;--sd-color-white-highlight:#d9d9d9;--sd-color-primary-text:var(--accent-contrast);--sd-color-secondary-text:var(--gold-contrast);--sd-color-success-text:var(--green-contrast);--sd-color-info-text:var(--blue-contrast);--sd-color-warning-text:var(--orange-contrast);--sd-color-danger-text:var(--red-contrast);--sd-color-light-text:var(--sy-c-text);--sd-color-muted-text:#fff;--sd-color-dark-text:#fff;--sd-color-black-text:#fff;--sd-color-white-text:#212529;--sd-color-shadow:var(--gray-1);--sd-color-card-border:var(--sy-c-border);--sd-color-card-border-hover:var(--accent-a9);--sd-color-tabs-label-inactive:var(--sy-c-bold);--sd-color-tabs-label-active:var(--sd-color-primary);--sd-color-tabs-underline-active:var(--sd-color-primary);--sd-color-tabs-label-hover:var(--accent-9);--sd-color-tabs-underline-hover:var(--accent-9)}.yue .surface{--sd-color-card-text:var(--sy-c-light);--sd-color-card-border:transparent;--sd-color-card-background:var(--sy-c-surface)}.yue a.sd-badge,.yue a.sd-badge:hover{border-bottom:0}.yue .sd-badge{border-radius:3px;font-weight:600}.yue .sd-btn{border-color:var(--sy-c-border)}.yue .sd-tab-set.outline{border:1px solid var(--sy-c-border);border-radius:4px;overflow:auto}.yue .sd-tab-set>label{padding:1rem .25rem .5rem;font-size:.84rem;font-weight:500}.yue .sd-tab-set.outline>label{margin-left:1rem;padding-top:.5rem}.yue .sd-tab-set>label~label{margin-left:1rem}.yue .sd-tab-content{box-shadow:0 -.0625rem var(--sy-c-divider);padding:0}.yue .sd-tab-content .code-block-caption,.yue .sd-tab-content .highlight pre{border-radius:0}.yue .sd-card-title{color:var(--sy-c-text)}.yue .sd-card-title a{border-bottom:0}.yue .sd-card-title>svg,.yue .sd-card-title>iconify-icon{margin-right:.25rem;position:relative;top:-1px}.yue .sd-card-hover:hover{transform:scale(1)}.yue .sd-card-hover:hover .sd-card-title{color:var(--sy-c-link-hover)}.yue .sd-card a.sd-hide-link-text,.yue .sd-card a.sd-hide-link-text:hover{border-bottom:0}.yue .surface .sd-card-header,.yue .surface .sd-card-body,.yue .surface .sd-card-footer{padding-left:1.5rem;padding-right:1.5rem}.yue .surface .sd-card-header,.yue .surface .sd-card-footer{border-color:var(--sy-c-border)}@media (print){.yue .sd-card{page-break-inside:avoid}}.yue a.sd-text-wrap:hover{border-bottom-width:1px}.sphinx-tabs [role=tablist]{border-color:var(--sy-c-divider)}.yue .sphinx-tabs-tab{color:var(--sy-c-text);line-height:inherit;border:none;border-bottom:.125rem solid #0000;padding:1rem .25rem .5rem;font-size:.84rem;font-weight:500}.yue .sphinx-tabs-tab:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.yue .sphinx-tabs-tab[aria-selected=true]{border:none;border-bottom:.125rem solid var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active);background-color:#0000}.yue .sphinx-tabs-tab+.sphinx-tabs-tab{margin-left:1rem}.yue .sphinx-tabs-panel{background-color:#0000;border:none;border-radius:0;margin:0;padding:0}.yue .sphinx-tabs-panel.code-tab{padding:0}.yue .sphinx-tabs-panel.code-tab .code-block-caption,.yue .sphinx-tabs-panel.code-tab .highlight pre{border-radius:0}html.light .jupyter_container .cell_output{--code-block-background:var(--color-surface-accent);--code-block-caption-background:var(--accent-3)}.yue{--jp-widgets-input-border-color:var(--gray-5);--jp-widgets-input-focus-border-color:var(--gray-8);--jp-widgets-slider-active-handle-color:var(--gray-4);--jp-widgets-slider-handle-border-color:var(--sy-c-border)}.yue .jupyter_container{background-color:var(--sy-c-background);border:3px solid var(--sy-c-border);box-shadow:none;border-radius:6px;overflow:hidden}.sy-main .yue .jupyter_container div[class^=highlight]{padding:0}.yue .jupyter_container div.highlight{background-color:var(--code-block-background)}.yue .jupyter_container div.cell_input{background-color:var(--code-block-background);border:0;border-radius:0}.yue .jupyter_container div.code_cell pre{padding:0}.jupyter_container div.cell_output .output,.jupyter_container div.cell_output .stderr,.jupyter_container div.cell_output .widget-subarea{padding:.5rem}.jupyter_container div.cell_output .stderr .stderr{padding:0}.widget-hslider .slider-container,.jupyter-widget-hslider .slider-container{align-items:center;display:flex}.widget-slider .noUi-target,.jupyter-widget-slider .noUi-target{width:100%}.jupyter_container div.code_cell .highlight>pre{padding:1rem}.jupyter_container div.code_cell .highlight .hll{margin-left:-1rem;margin-right:-1rem;padding:0 1rem}.jupyter_container div.code_cell .highlight .linenos{margin-right:.8rem}.yue .jupyter_container .stderr{color:var(--red-a11);background-color:var(--red-a3)}.yue .jupyter_container .stderr .stderr{background-color:#0000}.nbinput .highlight{--radius:1px}.yue div.nblast.container{padding-top:5px}.yue div.nbinput.container div.input_area{border-color:var(--sy-c-border)}.yue div.nboutput.container div.output_area.stderr{color:var(--red-a11);background-color:var(--red-a3)}.yue div.nboutput.container div.output_area>.math-wrapper>div.math{padding-top:0}.yue .jp-RenderedHTMLCommon thead,.yue div.rendered_html thead{border-color:var(--sy-c-border)}.yue .jp-RenderedHTMLCommon tbody tr,.yue div.rendered_html tbody tr{color:var(--sy-c-text)}.yue .jp-RenderedHTMLCommon tbody tr:nth-child(odd),.yue div.rendered_html tbody tr:nth-child(odd){background-color:var(--sy-c-surface)}.yue .jp-RenderedHTMLCommon tbody tr:hover,.yue div.rendered_html tbody tr:hover{background-color:var(--color-surface-accent)}.yue{--sg-text-color:var(--sy-c-text);--sg-background-color:var(--sy-c-background);--sg-code-background-color:var(--code-block-background);--sg-tr-hover-color:var(--accent-a3);--sg-tr-odd-color:var(--sy-c-surface);--sg-tooltip-foreground:var(--sy-c-background-contrast);--sg-tooltip-background:var(--sy-c-background);--sg-tooltip-border:var(--gray-7) transparent;--sg-thumb-box-shadow-color:var(--gray-a4);--sg-thumb-hover-border:var(--accent-a9);--sg-script-out:var(--sy-c-light);--sg-script-pre:var(--code-block-background);--sg-pytb-foreground:var(--syntax-text);--sg-pytb-background:var(--red-a2);--sg-pytb-border-color:var(--red-a8);--sg-download-a-background-color:var(--accent-a3);--sg-download-a-background-image:none;--sg-download-a-border-color:1px solid var(--accent-a3);--sg-download-a-color:var(--accent-a11);--sg-download-a-hover-background-color:var(--accent-a4);--sg-download-a-hover-box-shadow-1:transparent;--sg-download-a-hover-box-shadow-2:transparent}.yue .sphx-glr-thumbnails a,.yue .sphx-glr-download a,.yue .sphx-glr-download a:hover{border-bottom:0}.yue p.sphx-glr-signature a{border-bottom:0;border-radius:0;text-decoration:underline}.yue p.sphx-glr-signature a:hover{color:var(--sy-c-link-hover)}.yue .sphx-glr-footer img{margin:0;display:inline}html.light,html.dark{--docsearch-background-color:var(--sy-c-background);--docsearch-icon-color:var(--gray-11);--docsearch-secondary-text-color:var(--gray-11);--docsearch-modal-background:var(--sy-c-background);--docsearch-footer-background:var(--sy-c-surface);--docsearch-primary-color:var(--accent-9);--docsearch-soft-primary-color:var(--accent-a2);--docsearch-subtle-color:var(--gray-4);--docsearch-text-color:var(--sy-c-text);--docsearch-key-background:var(--gray-1);--docsearch-searchbox-background:var(--gray-3);--docsearch-searchbox-focus-background:var(--sy-c-background);--docsearch-muted-color:var(--gray-10);--docsearch-focus-color:var(--accent-a8);--docsearch-highlight-color:var(--accent-a11);--docsearch-hit-color:var(--sy-c-text);--docsearch-hit-background:var(--gray-a2);--docsearch-hit-highlight-color:var(--accent-a3);--docsearch-hit-shadow:inset 0 0 1px 0 var(--gray-a11);--docsearch-container-background:var(--gray-a5)}html.dark{--docsearch-modal-shadow:inset 1px 1px 0 0 #373737,0 3px 8px 0 #141414}#docsearch .DocSearch-Button{box-sizing:border-box;width:auto;height:32px;margin:0}#docsearch .DocSearch-Search-Icon{width:1rem;height:1rem}@media (max-width:767px){html.light,html.dark{--docsearch-searchbox-background:transparent}#docsearch{position:absolute;top:1rem;left:1.8rem;right:1.8rem}#docsearch .DocSearch-Button{width:100%;margin-left:0}}dl.sqla dt{color:var(--sig-name);margin-bottom:.5rem}dl.sqla dt>em{color:var(--sig-param);font-style:normal;font-weight:400}dl.sqla dd>p.rubric{text-transform:uppercase;margin-top:1.5rem;font-size:.76rem}dl.sqla dd>p.rubric+.table-wrapper{border-left:0;border-right:0;border-radius:0;margin-top:.75rem}dl.sqla p.rubric+.table-wrapper th,dl.sqla p.rubric+.table-wrapper td{background-color:#0000;border-left:0;border-right:0}dl.sqla p.rubric+.table-wrapper td>p{margin:0}dl.sqla p.rubric+.table-wrapper tr.row-odd{background-color:#0000}dl.sqla p.rubric+.table-wrapper tr.row-even{background-color:var(--yue-c-row-background)}.yue details.toggle-details{background-color:var(--slate-a2);border-radius:.2em;padding:0 1rem}.yue details.toggle-details summary{border-left-color:var(--accent-a9);background-color:var(--gray-a2);margin-left:-1rem;margin-right:-1rem}.yue details.toggle-details[open] summary{border-radius:.2em .2em 0 0}.yue .toggle-details__container{margin-top:0;margin-bottom:0;padding-top:1rem;padding-bottom:1rem}.yue .toggle-details__container :first-child{margin-top:0}.yue .toggle-details__container :last-child{margin-bottom:0}.yue .admonition.toggle-hidden .admonition-title~*{margin-bottom:0!important}.sphinx-contributors{container:contributors/inline-size}.sphinx-contributors .sphinx-contributors_list__item{margin:0;padding:0}.sphinx-contributors .sphinx-contributors_contributor__username,.sphinx-contributors .sphinx-contributors_contributor__contributions{margin:0}.sphinx-contributors.sphinx-contributors--avatars .sphinx-contributors_list{justify-content:flex-start;gap:1rem;padding:0}.sphinx-contributors--avatars .sphinx-contributors_contributor__username{margin-top:.5rem}.sphinx-contributors--avatars .sphinx-contributors_contributor__contributions{font-size:.875rem}.sphinx-contributors--avatars .sphinx-contributors_contributor__contributions:before{content:"";padding:0}.sphinx-contributors--avatars .sphinx-contributors_contributor{align-items:center}@container contributors (max-width:800px){.sphinx-contributors.sphinx-contributors--avatars .sphinx-contributors_list{column-gap:0}.sphinx-contributors--avatars .sphinx-contributors_list__item{flex-basis:25%}}@container contributors (max-width:700px){.sphinx-contributors--avatars img.sphinx-contributors_contributor__image{width:120px}}@container contributors (max-width:600px){.sphinx-contributors--avatars .sphinx-contributors_list__item{flex-basis:33.33%}}@container contributors (max-width:500px){.sphinx-contributors--avatars img.sphinx-contributors_contributor__image{width:120px}}@container contributors (max-width:400px){.sphinx-contributors--avatars .sphinx-contributors_list__item{flex-basis:50%}}.sphinx-sponsors--2xl{--sponsor-avatar-size:120px;--sponsor-item-padding:20px}.sphinx-sponsors--xl{--sponsor-avatar-size:90px;--sponsor-item-padding:15px}.sphinx-sponsors--lg{--sponsor-avatar-size:70px;--sponsor-item-padding:15px}.sphinx-sponsors--md{--sponsor-avatar-size:50px;--sponsor-item-padding:10px}.sphinx-sponsors--base{--sponsor-avatar-size:40px;--sponsor-item-padding:6px}.sphinx-sponsors--sm{--sponsor-avatar-size:35px;--sponsor-item-padding:5px}.sphinx-sponsors--xs{--sponsor-avatar-size:25px;--sponsor-item-padding:4px}.sphinx-sponsors{margin:2rem 0}.sphinx-sponsors .rubric{font-size:1.25em}ul.sphinx-sponsors_container{gap:var(--sponsor-item-padding);flex-wrap:wrap;margin:0;padding:0;list-style-type:none;display:flex}.sphinx-sponsors li.sphinx-sponsors_item{flex-direction:column;align-items:center;margin:0;padding:0;display:flex}.sphinx-sponsors_avatar{width:var(--sponsor-avatar-size);background:var(--gray-a3);display:inline-flex}.sphinx-sponsors_name{margin-top:.25rem;font-size:.875rem}.sphinx-sponsors--center{text-align:center}.sphinx-sponsors--center ul.sphinx-sponsors_container{gap:0}.sphinx-sponsors--center li.sphinx-sponsors_item{padding:var(--sponsor-item-padding)}.sphinx-sponsors--center .sphinx-sponsors_container{justify-content:center}.sphinx-sponsors--rounded .sphinx-sponsors_avatar,.sphinx-sponsors--rounded img{border-radius:100%}.yue{--xr-font-color0:var(--sy-c-heading);--xr-font-color2:var(--sy-c-text);--xr-font-color3:var(--sy-c-light);--xr-border-color:var(--sy-c-border);--xr-disabled-color:var(--gray-a6);--xr-background-color:var(--sy-c-background);--xr-background-color-row-even:var(--sy-c-background);--xr-background-color-row-odd:var(--gray-2)}.yue .xr-array-data pre{margin:0}.yue iconify-icon[data-accent-color]{color:var(--accent-9)}.dark pre.mermaid>svg{filter:brightness(.8)invert(.82)contrast(1.2)}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false} \ No newline at end of file diff --git a/doc/_static/shibuya.js b/doc/_static/shibuya.js new file mode 100644 index 0000000..be39892 --- /dev/null +++ b/doc/_static/shibuya.js @@ -0,0 +1,43 @@ +(()=>{var ie=Object.create;var ft=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var ce=Object.getPrototypeOf,ae=Object.prototype.hasOwnProperty;var le=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,n)=>(typeof require<"u"?require:e)[n]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var ue=(t,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of se(e))!ae.call(t,o)&&o!==n&&ft(t,o,{get:()=>e[o],enumerable:!(i=re(e,o))||i.enumerable});return t};var de=(t,e,n)=>(n=t!=null?ie(ce(t)):{},ue(e||!t||!t.__esModule?ft(n,"default",{value:t,enumerable:!0}):n,t));var Lt=Object.freeze({left:0,top:0,width:16,height:16}),R=Object.freeze({rotate:0,vFlip:!1,hFlip:!1}),j=Object.freeze({...Lt,...R}),K=Object.freeze({...j,body:"",hidden:!1}),fe=Object.freeze({width:null,height:null}),Et=Object.freeze({...fe,...R});function he(t,e=0){let n=t.replace(/^-?[0-9.]*/,"");function i(o){for(;o<0;)o+=4;return o%4}if(n===""){let o=parseInt(t);return isNaN(o)?0:i(o)}else if(n!==t){let o=0;switch(n){case"%":o=25;break;case"deg":o=90}if(o){let r=parseFloat(t.slice(0,t.length-n.length));return isNaN(r)?0:(r=r/o,r%1===0?i(r):0)}}return e}var pe=/[\s,]+/;function ge(t,e){e.split(pe).forEach(n=>{switch(n.trim()){case"horizontal":t.hFlip=!0;break;case"vertical":t.vFlip=!0;break}})}var Tt={...Et,preserveAspectRatio:""};function ht(t){let e={...Tt},n=(i,o)=>t.getAttribute(i)||o;return e.width=n("width",null),e.height=n("height",null),e.rotate=he(n("rotate","")),ge(e,n("flip","")),e.preserveAspectRatio=n("preserveAspectRatio",n("preserveaspectratio","")),e}function me(t,e){for(let n in Tt)if(t[n]!==e[n])return!0;return!1}var Ot=/^[a-z0-9]+(-[a-z0-9]+)*$/,N=(t,e,n,i="")=>{let o=t.split(":");if(t.slice(0,1)==="@"){if(o.length<2||o.length>3)return null;i=o.shift().slice(1)}if(o.length>3||!o.length)return null;if(o.length>1){let s=o.pop(),a=o.pop(),l={provider:o.length>0?o[0]:i,prefix:a,name:s};return e&&!M(l)?null:l}let r=o[0],c=r.split("-");if(c.length>1){let s={provider:i,prefix:c.shift(),name:c.join("-")};return e&&!M(s)?null:s}if(n&&i===""){let s={provider:i,prefix:"",name:r};return e&&!M(s,n)?null:s}return null},M=(t,e)=>t?!!((e&&t.prefix===""||t.prefix)&&t.name):!1;function be(t,e){let n=t.icons,i=t.aliases||Object.create(null),o=Object.create(null);function r(c){if(n[c])return o[c]=[];if(!(c in o)){o[c]=null;let s=i[c]&&i[c].parent,a=s&&r(s);a&&(o[c]=[s].concat(a))}return o[c]}return Object.keys(n).concat(Object.keys(i)).forEach(r),o}function ye(t,e){let n={};!t.hFlip!=!e.hFlip&&(n.hFlip=!0),!t.vFlip!=!e.vFlip&&(n.vFlip=!0);let i=((t.rotate||0)+(e.rotate||0))%4;return i&&(n.rotate=i),n}function pt(t,e){let n=ye(t,e);for(let i in K)i in R?i in t&&!(i in n)&&(n[i]=R[i]):i in e?n[i]=e[i]:i in t&&(n[i]=t[i]);return n}function ve(t,e,n){let i=t.icons,o=t.aliases||Object.create(null),r={};function c(s){r=pt(i[s]||o[s],r)}return c(e),n.forEach(c),pt(t,r)}function jt(t,e){let n=[];if(typeof t!="object"||typeof t.icons!="object")return n;t.not_found instanceof Array&&t.not_found.forEach(o=>{e(o,null),n.push(o)});let i=be(t);for(let o in i){let r=i[o];r&&(e(o,ve(t,o,r)),n.push(o))}return n}var we={provider:"",aliases:{},not_found:{},...Lt};function J(t,e){for(let n in e)if(n in t&&typeof t[n]!=typeof e[n])return!1;return!0}function Nt(t){if(typeof t!="object"||t===null)return null;let e=t;if(typeof e.prefix!="string"||!t.icons||typeof t.icons!="object"||!J(t,we))return null;let n=e.icons;for(let o in n){let r=n[o];if(!o||typeof r.body!="string"||!J(r,K))return null}let i=e.aliases||Object.create(null);for(let o in i){let r=i[o],c=r.parent;if(!o||typeof c!="string"||!n[c]&&!i[c]||!J(r,K))return null}return e}var F=Object.create(null);function xe(t,e){return{provider:t,prefix:e,icons:Object.create(null),missing:new Set}}function v(t,e){let n=F[t]||(F[t]=Object.create(null));return n[e]||(n[e]=xe(t,e))}function Pt(t,e){return Nt(e)?jt(e,(n,i)=>{i?t.icons[n]=i:t.missing.add(n)}):[]}function Ie(t,e,n){try{if(typeof n.body=="string")return t.icons[e]={...n},!0}catch{}return!1}function Ae(t,e){let n=[];return(typeof t=="string"?[t]:Object.keys(F)).forEach(i=>{(typeof i=="string"&&typeof e=="string"?[e]:Object.keys(F[i]||{})).forEach(o=>{let r=v(i,o);n=n.concat(Object.keys(r.icons).map(c=>(i!==""?"@"+i+":":"")+o+":"+c))})}),n}var T=!1;function Mt(t){return typeof t=="boolean"&&(T=t),T}function O(t){let e=typeof t=="string"?N(t,!0,T):t;if(e){let n=v(e.provider,e.prefix),i=e.name;return n.icons[i]||(n.missing.has(i)?null:void 0)}}function qt(t,e){let n=N(t,!0,T);if(!n)return!1;let i=v(n.provider,n.prefix);return e?Ie(i,n.name,e):(i.missing.add(n.name),!0)}function gt(t,e){if(typeof t!="object")return!1;if(typeof e!="string"&&(e=t.provider||""),T&&!e&&!t.prefix){let i=!1;return Nt(t)&&(t.prefix="",jt(t,(o,r)=>{qt(o,r)&&(i=!0)})),i}let n=t.prefix;return M({prefix:n,name:"a"})?!!Pt(v(e,n),t):!1}function Se(t){return!!O(t)}function Ce(t){let e=O(t);return e&&{...j,...e}}function Rt(t,e){t.forEach(n=>{let i=n.loaderCallbacks;i&&(n.loaderCallbacks=i.filter(o=>o.id!==e))})}function ke(t){t.pendingCallbacksFlag||(t.pendingCallbacksFlag=!0,setTimeout(()=>{t.pendingCallbacksFlag=!1;let e=t.loaderCallbacks?t.loaderCallbacks.slice(0):[];if(!e.length)return;let n=!1,i=t.provider,o=t.prefix;e.forEach(r=>{let c=r.icons,s=c.pending.length;c.pending=c.pending.filter(a=>{if(a.prefix!==o)return!0;let l=a.name;if(t.icons[l])c.loaded.push({provider:i,prefix:o,name:l});else if(t.missing.has(l))c.missing.push({provider:i,prefix:o,name:l});else return n=!0,!0;return!1}),c.pending.length!==s&&(n||Rt([t],r.id),r.callback(c.loaded.slice(0),c.missing.slice(0),c.pending.slice(0),r.abort))})}))}var _e=0;function Le(t,e,n){let i=_e++,o=Rt.bind(null,n,i);if(!e.pending.length)return o;let r={id:i,icons:e,callback:t,abort:o};return n.forEach(c=>{(c.loaderCallbacks||(c.loaderCallbacks=[])).push(r)}),o}function Ee(t){let e={loaded:[],missing:[],pending:[]},n=Object.create(null);t.sort((o,r)=>o.provider!==r.provider?o.provider.localeCompare(r.provider):o.prefix!==r.prefix?o.prefix.localeCompare(r.prefix):o.name.localeCompare(r.name));let i={provider:"",prefix:"",name:""};return t.forEach(o=>{if(i.name===o.name&&i.prefix===o.prefix&&i.provider===o.provider)return;i=o;let r=o.provider,c=o.prefix,s=o.name,a=n[r]||(n[r]=Object.create(null)),l=a[c]||(a[c]=v(r,c)),u;s in l.icons?u=e.loaded:c===""||l.missing.has(s)?u=e.missing:u=e.pending;let f={provider:r,prefix:c,name:s};u.push(f)}),e}var X=Object.create(null);function mt(t,e){X[t]=e}function Z(t){return X[t]||X[""]}function Te(t,e=!0,n=!1){let i=[];return t.forEach(o=>{let r=typeof o=="string"?N(o,e,n):o;r&&i.push(r)}),i}function ot(t){let e;if(typeof t.resources=="string")e=[t.resources];else if(e=t.resources,!(e instanceof Array)||!e.length)return null;return{resources:e,path:t.path||"/",maxURL:t.maxURL||500,rotate:t.rotate||750,timeout:t.timeout||5e3,random:t.random===!0,index:t.index||0,dataAfterTimeout:t.dataAfterTimeout!==!1}}var B=Object.create(null),_=["https://api.simplesvg.com","https://api.unisvg.com"],q=[];for(;_.length>0;)_.length===1||Math.random()>.5?q.push(_.shift()):q.push(_.pop());B[""]=ot({resources:["https://api.iconify.design"].concat(q)});function bt(t,e){let n=ot(e);return n===null?!1:(B[t]=n,!0)}function H(t){return B[t]}function Oe(){return Object.keys(B)}var je={resources:[],index:0,timeout:2e3,rotate:750,random:!1,dataAfterTimeout:!1};function Ne(t,e,n,i){let o=t.resources.length,r=t.random?Math.floor(Math.random()*o):t.index,c;if(t.random){let d=t.resources.slice(0);for(c=[];d.length>1;){let b=Math.floor(Math.random()*d.length);c.push(d[b]),d=d.slice(0,b).concat(d.slice(b+1))}c=c.concat(d)}else c=t.resources.slice(r).concat(t.resources.slice(0,r));let s=Date.now(),a="pending",l=0,u,f=null,h=[],g=[];typeof i=="function"&&g.push(i);function w(){f&&(clearTimeout(f),f=null)}function x(){a==="pending"&&(a="aborted"),w(),h.forEach(d=>{d.status==="pending"&&(d.status="aborted")}),h=[]}function p(d,b){b&&(g=[]),typeof d=="function"&&g.push(d)}function z(){return{startTime:s,payload:e,status:a,queriesSent:l,queriesPending:h.length,subscribe:p,abort:x}}function I(){a="failed",g.forEach(d=>{d(void 0,u)})}function y(){h.forEach(d=>{d.status==="pending"&&(d.status="aborted")}),h=[]}function m(d,b,k){let P=b!=="success";switch(h=h.filter(A=>A!==d),a){case"pending":break;case"failed":if(P||!t.dataAfterTimeout)return;break;default:return}if(b==="abort"){u=k,I();return}if(P){u=k,h.length||(c.length?G():I());return}if(w(),y(),!t.random){let A=t.resources.indexOf(d.resource);A!==-1&&A!==t.index&&(t.index=A)}a="completed",g.forEach(A=>{A(k)})}function G(){if(a!=="pending")return;w();let d=c.shift();if(d===void 0){if(h.length){f=setTimeout(()=>{w(),a==="pending"&&(y(),I())},t.timeout);return}I();return}let b={status:"pending",resource:d,callback:(k,P)=>{m(b,k,P)}};h.push(b),l++,f=setTimeout(G,t.rotate),n(d,e,b.callback)}return setTimeout(G),z}function Ft(t){let e={...je,...t},n=[];function i(){n=n.filter(c=>c().status==="pending")}function o(c,s,a){let l=Ne(e,c,s,(u,f)=>{i(),a&&a(u,f)});return n.push(l),l}function r(c){return n.find(s=>c(s))||null}return{query:o,find:r,setIndex:c=>{e.index=c},getIndex:()=>e.index,cleanup:i}}function yt(){}var Y=Object.create(null);function Pe(t){if(!Y[t]){let e=H(t);if(!e)return;Y[t]={config:e,redundancy:Ft(e)}}return Y[t]}function Dt(t,e,n){let i,o;if(typeof t=="string"){let r=Z(t);if(!r)return n(void 0,424),yt;o=r.send;let c=Pe(t);c&&(i=c.redundancy)}else{let r=ot(t);if(r){i=Ft(r);let c=Z(t.resources?t.resources[0]:"");c&&(o=c.send)}}return!i||!o?(n(void 0,424),yt):i.query(e,o,n)().abort}function vt(){}function Me(t){t.iconsLoaderFlag||(t.iconsLoaderFlag=!0,setTimeout(()=>{t.iconsLoaderFlag=!1,ke(t)}))}function qe(t){let e=[],n=[];return t.forEach(i=>{(i.match(Ot)?e:n).push(i)}),{valid:e,invalid:n}}function L(t,e,n){function i(){let o=t.pendingIcons;e.forEach(r=>{o&&o.delete(r),t.icons[r]||t.missing.add(r)})}if(n&&typeof n=="object")try{if(!Pt(t,n).length){i();return}}catch(o){console.error(o)}i(),Me(t)}function wt(t,e){t instanceof Promise?t.then(n=>{e(n)}).catch(()=>{e(null)}):e(t)}function Re(t,e){t.iconsToLoad?t.iconsToLoad=t.iconsToLoad.concat(e).sort():t.iconsToLoad=e,t.iconsQueueFlag||(t.iconsQueueFlag=!0,setTimeout(()=>{t.iconsQueueFlag=!1;let{provider:n,prefix:i}=t,o=t.iconsToLoad;if(delete t.iconsToLoad,!o||!o.length)return;let r=t.loadIcon;if(t.loadIcons&&(o.length>1||!r)){wt(t.loadIcons(o,i,n),l=>{L(t,o,l)});return}if(r){o.forEach(l=>{wt(r(l,i,n),u=>{L(t,[l],u?{prefix:i,icons:{[l]:u}}:null)})});return}let{valid:c,invalid:s}=qe(o);if(s.length&&L(t,s,null),!c.length)return;let a=i.match(Ot)?Z(n):null;if(!a){L(t,c,null);return}a.prepare(n,i,c).forEach(l=>{Dt(n,l,u=>{L(t,l.icons,u)})})}))}var it=(t,e)=>{let n=Ee(Te(t,!0,Mt()));if(!n.pending.length){let s=!0;return e&&setTimeout(()=>{s&&e(n.loaded,n.missing,n.pending,vt)}),()=>{s=!1}}let i=Object.create(null),o=[],r,c;return n.pending.forEach(s=>{let{provider:a,prefix:l}=s;if(l===c&&a===r)return;r=a,c=l,o.push(v(a,l));let u=i[a]||(i[a]=Object.create(null));u[l]||(u[l]=[])}),n.pending.forEach(s=>{let{provider:a,prefix:l,name:u}=s,f=v(a,l),h=f.pendingIcons||(f.pendingIcons=new Set);h.has(u)||(h.add(u),i[a][l].push(u))}),o.forEach(s=>{let a=i[s.provider][s.prefix];a.length&&Re(s,a)}),e?Le(e,n,o):vt},Fe=t=>new Promise((e,n)=>{let i=typeof t=="string"?N(t,!0):t;if(!i){n(t);return}it([i||t],o=>{if(o.length&&i){let r=O(i);if(r){e({...j,...r});return}}n(t)})});function xt(t){try{let e=typeof t=="string"?JSON.parse(t):t;if(typeof e.body=="string")return{...e}}catch{}}function De(t,e){if(typeof t=="object")return{data:xt(t),value:t};if(typeof t!="string")return{value:t};if(t.includes("{")){let r=xt(t);if(r)return{data:r,value:t}}let n=N(t,!0,!0);if(!n)return{value:t};let i=O(n);if(i!==void 0||!n.prefix)return{value:t,name:n,data:i};let o=it([n],()=>e(t,n,O(n)));return{value:t,name:n,loading:o}}var Bt=!1;try{Bt=navigator.vendor.indexOf("Apple")===0}catch{}function Be(t,e){switch(e){case"svg":case"bg":case"mask":return e}return e!=="style"&&(Bt||t.indexOf("=0;){let o=t.indexOf(">",i),r=t.indexOf("",r);if(c===-1)break;n+=t.slice(o+1,r).trim(),t=t.slice(0,i).trim()+t.slice(c+1)}return{defs:n,content:t}}function Ve(t,e){return t?""+t+""+e:e}function Ue(t,e,n){let i=Qe(t);return Ve(i.defs,e+i.content+n)}var ze=t=>t==="unset"||t==="undefined"||t==="none";function Ht(t,e){let n={...j,...t},i={...Et,...e},o={left:n.left,top:n.top,width:n.width,height:n.height},r=n.body;[n,i].forEach(x=>{let p=[],z=x.hFlip,I=x.vFlip,y=x.rotate;z?I?y+=2:(p.push("translate("+(o.width+o.left).toString()+" "+(0-o.top).toString()+")"),p.push("scale(-1 1)"),o.top=o.left=0):I&&(p.push("translate("+(0-o.left).toString()+" "+(o.height+o.top).toString()+")"),p.push("scale(1 -1)"),o.top=o.left=0);let m;switch(y<0&&(y-=Math.floor(y/4)*4),y=y%4,y){case 1:m=o.height/2+o.top,p.unshift("rotate(90 "+m.toString()+" "+m.toString()+")");break;case 2:p.unshift("rotate(180 "+(o.width/2+o.left).toString()+" "+(o.height/2+o.top).toString()+")");break;case 3:m=o.width/2+o.left,p.unshift("rotate(-90 "+m.toString()+" "+m.toString()+")");break}y%2===1&&(o.left!==o.top&&(m=o.left,o.left=o.top,o.top=m),o.width!==o.height&&(m=o.width,o.width=o.height,o.height=m)),p.length&&(r=Ue(r,'',""))});let c=i.width,s=i.height,a=o.width,l=o.height,u,f;c===null?(f=s===null?"1em":s==="auto"?l:s,u=tt(f,a/l)):(u=c==="auto"?a:c,f=s===null?tt(u,l/a):s==="auto"?l:s);let h={},g=(x,p)=>{ze(p)||(h[x]=p.toString())};g("width",u),g("height",f);let w=[o.left,o.top,a,l];return h.viewBox=w.join(" "),{attributes:h,viewBox:w,body:r}}function rt(t,e){let n=t.indexOf("xlink:")===-1?"":' xmlns:xlink="http://www.w3.org/1999/xlink"';for(let i in e)n+=" "+i+'="'+e[i]+'"';return'"+t+""}function Ge(t){return t.replace(/"/g,"'").replace(/%/g,"%25").replace(/#/g,"%23").replace(//g,"%3E").replace(/\s+/g," ")}function Je(t){return"data:image/svg+xml,"+Ge(t)}function $t(t){return'url("'+Je(t)+'")'}var Ye=()=>{let t;try{if(t=fetch,typeof t=="function")return t}catch{}},D=Ye();function We(t){D=t}function Ke(){return D}function Xe(t,e){let n=H(t);if(!n)return 0;let i;if(!n.maxURL)i=0;else{let o=0;n.resources.forEach(c=>{o=Math.max(o,c.length)});let r=e+".json?icons=";i=n.maxURL-o-n.path.length-r.length}return i}function Ze(t){return t===404}var tn=(t,e,n)=>{let i=[],o=Xe(t,e),r="icons",c={type:r,provider:t,prefix:e,icons:[]},s=0;return n.forEach((a,l)=>{s+=a.length+1,s>=o&&l>0&&(i.push(c),c={type:r,provider:t,prefix:e,icons:[]},s=a.length),c.icons.push(a)}),i.push(c),i};function en(t){if(typeof t=="string"){let e=H(t);if(e)return e.path}return"/"}var nn=(t,e,n)=>{if(!D){n("abort",424);return}let i=en(e.provider);switch(e.type){case"icons":{let r=e.prefix,c=e.icons.join(","),s=new URLSearchParams({icons:c});i+=r+".json?"+s.toString();break}case"custom":{let r=e.uri;i+=r.slice(0,1)==="/"?r.slice(1):r;break}default:n("abort",400);return}let o=503;D(t+i).then(r=>{let c=r.status;if(c!==200){setTimeout(()=>{n(Ze(c)?"abort":"next",c)});return}return o=501,r.json()}).then(r=>{if(typeof r!="object"||r===null){setTimeout(()=>{r===404?n("abort",r):n("next",o)});return}setTimeout(()=>{n("success",r)})}).catch(()=>{n("next",o)})},on={prepare:tn,send:nn};function rn(t,e,n){v(n||"",e).loadIcons=t}function sn(t,e,n){v(n||"",e).loadIcon=t}var W="data-style",Qt="";function cn(t){Qt=t}function It(t,e){let n=Array.from(t.childNodes).find(i=>i.hasAttribute&&i.hasAttribute(W));n||(n=document.createElement("style"),n.setAttribute(W,W),t.appendChild(n)),n.textContent=":host{display:inline-block;vertical-align:"+(e?"-0.125em":"0")+"}span,svg{display:block;margin:auto}"+Qt}function Vt(){mt("",on),Mt(!0);let t;try{t=window}catch{}if(t){if(t.IconifyPreload!==void 0){let n=t.IconifyPreload,i="Invalid IconifyPreload syntax.";typeof n=="object"&&n!==null&&(n instanceof Array?n:[n]).forEach(o=>{try{(typeof o!="object"||o===null||o instanceof Array||typeof o.icons!="object"||typeof o.prefix!="string"||!gt(o))&&console.error(i)}catch{console.error(i)}})}if(t.IconifyProviders!==void 0){let n=t.IconifyProviders;if(typeof n=="object"&&n!==null)for(let i in n){let o="IconifyProviders["+i+"] is invalid.";try{let r=n[i];if(typeof r!="object"||!r||r.resources===void 0)continue;bt(i,r)||console.error(o)}catch{console.error(o)}}}}return{iconLoaded:Se,getIcon:Ce,listIcons:Ae,addIcon:qt,addCollection:gt,calculateSize:tt,buildIcon:Ht,iconToHTML:rt,svgToURL:$t,loadIcons:it,loadIcon:Fe,addAPIProvider:bt,setCustomIconLoader:sn,setCustomIconsLoader:rn,appendCustomStyle:cn,_api:{getAPIConfig:H,setAPIModule:mt,sendAPIQuery:Dt,setFetch:We,getFetch:Ke,listAPIProviders:Oe}}}var et={"background-color":"currentColor"},Ut={"background-color":"transparent"},At={image:"var(--svg)",repeat:"no-repeat",size:"100% 100%"},St={"-webkit-mask":et,mask:et,background:Ut};for(let t in St){let e=St[t];for(let n in At)e[t+"-"+n]=At[n]}function Ct(t){return t?t+(t.match(/^[-0-9.]+$/)?"px":""):"inherit"}function an(t,e,n){let i=document.createElement("span"),o=t.body;o.indexOf("");let r=t.attributes,c=rt(o,{...r,width:e.width+"",height:e.height+""}),s=$t(c),a=i.style,l={"--svg":s,width:Ct(r.width),height:Ct(r.height),...n?et:Ut};for(let u in l)a.setProperty(u,l[u]);return i}var E;function ln(){try{E=window.trustedTypes.createPolicy("iconify",{createHTML:t=>t})}catch{E=null}}function un(t){return E===void 0&&ln(),E?E.createHTML(t):t}function dn(t){let e=document.createElement("span"),n=t.attributes,i="";n.width||(i="width: inherit;"),n.height||(i+="height: inherit;"),i&&(n.style=i);let o=rt(t.body,n);return e.innerHTML=un(o),e.firstChild}function nt(t){return Array.from(t.childNodes).find(e=>{let n=e.tagName&&e.tagName.toUpperCase();return n==="SPAN"||n==="SVG"})}function kt(t,e){let n=e.icon.data,i=e.customisations,o=Ht(n,i);i.preserveAspectRatio&&(o.attributes.preserveAspectRatio=i.preserveAspectRatio);let r=e.renderedMode,c;r==="svg"?c=dn(o):c=an(o,{...j,...n},r==="mask");let s=nt(t);s?c.tagName==="SPAN"&&s.tagName===c.tagName?s.setAttribute("style",c.getAttribute("style")):t.replaceChild(c,s):t.appendChild(c)}function _t(t,e,n){let i=n&&(n.rendered?n:n.lastRender);return{rendered:!1,inline:e,icon:t,lastRender:i}}function fn(t="iconify-icon"){let e,n;try{e=window.customElements,n=window.HTMLElement}catch{return}if(!e||!n)return;let i=e.get(t);if(i)return i;let o=["icon","mode","inline","noobserver","width","height","rotate","flip"],r=class extends n{_shadowRoot;_initialised=!1;_state;_checkQueued=!1;_connected=!1;_observer=null;_visible=!0;constructor(){super();let s=this._shadowRoot=this.attachShadow({mode:"open"}),a=this.hasAttribute("inline");It(s,a),this._state=_t({value:""},a),this._queueCheck()}connectedCallback(){this._connected=!0,this.startObserver()}disconnectedCallback(){this._connected=!1,this.stopObserver()}static get observedAttributes(){return o.slice(0)}attributeChangedCallback(s){switch(s){case"inline":{let a=this.hasAttribute("inline"),l=this._state;a!==l.inline&&(l.inline=a,It(this._shadowRoot,a));break}case"noobserver":{this.hasAttribute("noobserver")?this.startObserver():this.stopObserver();break}default:this._queueCheck()}}get icon(){let s=this.getAttribute("icon");if(s&&s.slice(0,1)==="{")try{return JSON.parse(s)}catch{}return s}set icon(s){typeof s=="object"&&(s=JSON.stringify(s)),this.setAttribute("icon",s)}get inline(){return this.hasAttribute("inline")}set inline(s){s?this.setAttribute("inline","true"):this.removeAttribute("inline")}get observer(){return this.hasAttribute("observer")}set observer(s){s?this.setAttribute("observer","true"):this.removeAttribute("observer")}restartAnimation(){let s=this._state;if(s.rendered){let a=this._shadowRoot;if(s.renderedMode==="svg")try{a.lastChild.setCurrentTime(0);return}catch{}kt(a,s)}}get status(){let s=this._state;return s.rendered?"rendered":s.icon.data===null?"failed":"loading"}_queueCheck(){this._checkQueued||(this._checkQueued=!0,setTimeout(()=>{this._check()}))}_check(){if(!this._checkQueued)return;this._checkQueued=!1;let s=this._state,a=this.getAttribute("icon");if(a!==s.icon.value){this._iconChanged(a);return}if(!s.rendered||!this._visible)return;let l=this.getAttribute("mode"),u=ht(this);(s.attrMode!==l||me(s.customisations,u)||!nt(this._shadowRoot))&&this._renderIcon(s.icon,u,l)}_iconChanged(s){let a=De(s,(l,u,f)=>{let h=this._state;if(h.rendered||this.getAttribute("icon")!==l)return;let g={value:l,name:u,data:f};g.data?this._gotIconData(g):h.icon=g});a.data?this._gotIconData(a):this._state=_t(a,this._state.inline,this._state)}_forceRender(){if(!this._visible){let s=nt(this._shadowRoot);s&&this._shadowRoot.removeChild(s);return}this._queueCheck()}_gotIconData(s){this._checkQueued=!1,this._renderIcon(s,ht(this),this.getAttribute("mode"))}_renderIcon(s,a,l){let u=Be(s.data.body,l),f=this._state.inline;kt(this._shadowRoot,this._state={rendered:!0,icon:s,inline:f,customisations:a,attrMode:l,renderedMode:u})}startObserver(){if(!this._observer&&!this.hasAttribute("noobserver"))try{this._observer=new IntersectionObserver(s=>{let a=s.some(l=>l.isIntersecting);a!==this._visible&&(this._visible=a,this._forceRender())}),this._observer.observe(this)}catch{if(this._observer){try{this._observer.disconnect()}catch{}this._observer=null}}}stopObserver(){this._observer&&(this._observer.disconnect(),this._observer=null,this._visible=!0,this._connected&&this._forceRender())}};o.forEach(s=>{s in r.prototype||Object.defineProperty(r.prototype,s,{get:function(){return this.getAttribute(s)},set:function(a){a!==null?this.setAttribute(s,a):this.removeAttribute(s)}})});let c=Vt();for(let s in c)r[s]=r.prototype[s]=c[s];return e.define(t,r),r}var hn=fn()||Vt(),{iconLoaded:Nn,getIcon:Pn,listIcons:Mn,addIcon:qn,addCollection:Rn,calculateSize:Fn,buildIcon:Dn,iconToHTML:Bn,svgToURL:Hn,loadIcons:$n,loadIcon:Qn,setCustomIconLoader:Vn,setCustomIconsLoader:Un,addAPIProvider:zn,_api:Gn}=hn;function pn(t){let e=t.getAttribute("aria-controls"),n=document.getElementById(e);n&&(n.addEventListener("click",i=>{i.stopPropagation()}),t.addEventListener("click",i=>{i.stopPropagation();let o=Gt(),r=o.indexOf(e);n.getAttribute("aria-hidden")==="false"?(o.splice(r,1),document.body.setAttribute("data-expanded",o.join(" ")),n.setAttribute("aria-hidden","true"),st(e,"false")):(o.push(e),document.body.setAttribute("data-expanded",o.join(" ")),n.setAttribute("aria-hidden","false"),st(e,"true"))}))}function st(t,e){let n=document.querySelectorAll('[aria-controls="'+t+'"]');for(let i=0;i{let t=Gt();document.body.setAttribute("data-expanded",""),t.forEach(e=>{document.getElementById(e).setAttribute("aria-hidden","true"),st(e,"false")})});var Jt=new Map;function gn(t){t.addEventListener("click",()=>{let e=t.querySelector("i");e.setAttribute("data-icon","loader");let n=t.getAttribute("data-url");n?mn(e,n):bn(e)})}function mn(t,e){let n=Jt.get(e);if(n){navigator.clipboard.writeText(n),ct(t);return}navigator.clipboard.write([new ClipboardItem({"text/plain":fetch(e).then(i=>i.text()).then(i=>(Jt.set(e,i),ct(t),i))})]).catch(()=>{t.setAttribute("data-icon","copy")})}function bn(t){import("https://esm.sh/turndown").then(e=>{let n=new e.default({headingStyle:"atx",bulletListMarker:"-",codeBlockStyle:"fenced"});return n.addRule("highlight",{filter:i=>i.nodeName==="DIV"&&i.classList.contains("highlight"),replacement:function(i,o){let r=Yt(o.parentNode.className),c="```";return r&&(c+=r),c+` +`+o.textContent.trim()+"\n```"}}),n.addRule("literal-block-wrapper",{filter:i=>i.nodeName==="DIV"&&i.classList.contains("literal-block-wrapper")&&i.querySelector(".highlight"),replacement:function(i,o){let r=o.querySelector(".highlight"),c=Yt(r.parentNode.className),s="```";if(c){let a=o.querySelector(".caption-text");s+=c,a&&(s+=' "'+a.textContent.trim()+'"')}return s+` +`+r.textContent+"\n```"}}),n}).then(e=>{let n=document.querySelector(".yue").cloneNode(!0),i=e.turndown(yn(n));return navigator.clipboard.writeText(i)}).then(()=>{ct(t)})}function ct(t){t.setAttribute("data-icon","check"),setTimeout(()=>{t.setAttribute("data-icon","copy")},500)}function yn(t){return t.querySelectorAll(".headerlink").forEach(e=>{e.remove()}),t.querySelectorAll(".copybtn").forEach(e=>{e.remove()}),t.querySelectorAll("span.linenos").forEach(e=>{e.remove()}),t.innerHTML}function Yt(t){let e=t.match(/highlight-(\S+)/);if(e)return e[1]}var Wt=document.querySelectorAll(".js-copy");for(let t=0;t{$.parentNode.removeChild($),document.head.removeChild(t)}),e(),window.addEventListener("resize",e)}var wn;var Q=["auto","light","dark"],V=document.querySelector(".js-theme");function xn(){let t=Xt();t+=1,Q[t]||(t=0);let e=Q[t];setColorMode(e),localStorage._theme=e,Zt(e)}function Kt(){return document.documentElement.getAttribute("data-color-mode")||"auto"}function Xt(){return Q.indexOf(Kt())}function Zt(t){let e=V.getAttribute("data-aria-"+t);V.setAttribute("aria-label",e)}V&&(V.addEventListener("click",xn),Zt(Q[Xt()]||"auto"));window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{Kt()==="auto"&&setColorMode("auto")});function In(){let t=document.querySelector(".globaltoc");if(!t)return;let e=parseInt(t.getAttribute("data-expand-depth"),10),n=o=>{if(!e)return!1;let r=0;for(;o.parentNode&&o.parentNode!==t;)o=o.parentNode,o.nodeName==="UL"&&(r+=1);return e>=r};t.querySelectorAll("li > ul").forEach(o=>{let r=o.parentNode;r.classList.contains("current")||n(r)?r.classList.add("_expand"):r.classList.add("_collapse");let c=An(o);r.appendChild(c)})}function An(t){let e=document.createElement("button");e.innerHTML='';let n=t.parentNode,i=t.previousSibling,o=i.textContent,r=()=>{n.classList.contains("_expand")?e.setAttribute("aria-label","Collapse "+o):e.setAttribute("aria-label","Expand "+o)};r();let c=s=>{s.preventDefault(),n.classList.contains("_expand")?(n.classList.remove("_expand"),n.classList.add("_collapse")):(n.classList.remove("_collapse"),n.classList.add("_expand")),r()};return i.getAttribute("href")==="#"&&i.addEventListener("click",c),e.addEventListener("click",c),e}var at=document.querySelector(".globaltoc a.current");at&&at.scrollIntoViewIfNeeded&&at.scrollIntoViewIfNeeded();In();var te=0,lt=200,S=[],C=document.querySelector(".back-to-top");function ee(){let t=document.querySelector(".yue > section");if(t){let e=window.getComputedStyle(t);lt=parseInt(e.scrollMarginTop,10)||0}}function Sn(t){let e;return t.nodeName==="DT"?e=t.parentNode.getBoundingClientRect():e=t.getBoundingClientRect(),e.top<=lt&&e.bottom>=lt}function Cn(){document.querySelectorAll(".localtoc li.active").forEach(t=>{t.classList.remove("active")})}function ne(t){let e=document.querySelector(`.localtoc a[href="#${t}"]`);if(!e)return;let n=e.parentNode;n.classList.contains("active")||(Cn(),n.classList.add("active"),n.scrollIntoViewIfNeeded&&n.scrollIntoViewIfNeeded(!1))}function oe(){let t;for(let e=0;e=t){let e=S[S.length-1];e&&ne(e.id)}else oe();C&&(window.scrollY&&window.scrollY{window.scrollTo(0,0)});document.querySelector(".localtoc")&&(window.addEventListener("scroll",kn),window.addEventListener("DOMContentLoaded",()=>{S=[...document.querySelectorAll(".yue > section section[id]"),...document.querySelectorAll(".yue dt.sig[id]")],ee(),oe()}),window.addEventListener("resize",ee));var U=document.querySelector(".js-repo-stats");async function _n(t,e){let n=`https://api.github.com/repos/${t}/${e}`,o=await(await fetch(n)).json(),r={stars:o.watchers,forks:o.forks};ut(r),sessionStorage.setItem("_sy/repo/stats",JSON.stringify(r))}async function Ln(t,e){let n="https://gitlab.com/api/v4/projects/"+encodeURIComponent(t+"/"+e),o=await(await fetch(n)).json(),r={stars:o.star_count,forks:o.forks_count};ut(r),sessionStorage.setItem("_sy/repo/stats",JSON.stringify(r))}function ut({stars:t,forks:e}){t&&(document.querySelector(".js-repo-stars").textContent=t),e&&(document.querySelector(".js-repo-forks").textContent=e)}function En(){let t=sessionStorage.getItem("_sy/repo/stats");if(t)ut(JSON.parse(t));else{let e=U.getAttribute("data-user"),n=U.getAttribute("data-repo"),i=U.getAttribute("data-type");i==="github"?_n(e,n):i==="gitlab"&&Ln(e,n)}}U&&En();function Tn(t,e){let n=document.createElement("script");n.id="_carbonads_js",n.src=`//cdn.carbonads.com/carbon.js?serve=${t}&placement=${e}`;let i=document.querySelector(".yue > section"),o=document.querySelector(".yue > section > section");if(o)i.insertBefore(n,o);else{let r=document.querySelector(".yue > section > p");r?i.insertBefore(n,r.nextSibling):i.appendChild(n)}}var dt=document.querySelector(".js-carbon");if(dt){let t=dt.getAttribute("data-carbon-code"),e=dt.getAttribute("data-carbon-placement");t&&e&&Tn(t,e)}var On=` +:host > div .results .hit h2 { + color: var(--sy-c-heading); + margin-bottom: 0; + border-bottom: 0; + font-weight: 600; +} +:host > div .results .hit .hit-block .content { + color: var(--sy-c-text); +} +:host > div .results .hit-block a.hit:hover, :host > div .results .hit-block .hit.active { + background-color: var(--gray-5); + border-radius: 4px; +} + +:host > div div.hit-block a.hit-block-heading:hover { + text-decoration: underline; +} + +:host > div div.hit-block a.hit-block-heading i, +:host > div div.hit-block .hit-block-heading-container .close-icon { + color: var(--sy-c-light); + margin-bottom: 0; + display: flex; +} +`;document.addEventListener("readthedocs-addons-data-ready",function(t){document.querySelector(".searchbox input").addEventListener("focusin",()=>{let e=new CustomEvent("readthedocs-search-show");document.dispatchEvent(e)}),setTimeout(()=>{let e=document.querySelector("readthedocs-search");if(e){let n=document.createElement("style");n.textContent=On,e.shadowRoot.appendChild(n)}},1e3)});/windows/i.test(navigator.userAgent)&&document.body.classList.add("win");})(); +/*! Bundled license information: + +iconify-icon/dist/iconify-icon.mjs: + (** + * (c) Iconify + * + * For the full copyright and license information, please view the license.txt + * files at https://github.com/iconify/iconify + * + * Licensed under MIT. + * + * @license MIT + * @version 3.0.2 + *) +*/ diff --git a/doc/_static/sphinx_highlight.js b/doc/_static/sphinx_highlight.js new file mode 100644 index 0000000..a74e103 --- /dev/null +++ b/doc/_static/sphinx_highlight.js @@ -0,0 +1,159 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true; + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 + && !parent.classList.contains(className) + && !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore(span, parent.insertBefore(rest, node.nextSibling)); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect", + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target), + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms"); + // Update history only if '?highlight' is present; otherwise it + // clears text fragments (not set in window.location by the browser) + if (url.searchParams.has("highlight")) { + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + } + + // get individual terms from highlight string + const terms = highlight + .toLowerCase() + .split(/\s+/) + .filter((x) => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '", + ), + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms"); + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) + return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) + return; + if ( + DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + && event.key === "Escape" + ) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/doc/admin/index.html b/doc/admin/index.html new file mode 100644 index 0000000..8e2e91b --- /dev/null +++ b/doc/admin/index.html @@ -0,0 +1,2015 @@ + + + + + 18. Administrative Functions - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    18. Administrative Functions#

    +

    The source file cfe.c contains the main program. It calls +proc_command_line (in cmd_line.c) to parse the command line; +fe_init (in fe_init.c) to do global initialization; +translation_unit (in decls.c) to compile or cpp_driver (in +preproc.c) to do preprocessing; and fe_wrapup (in fe_wrapup.c) +to do global termination. If a back end should be called, and there were no +errors, it also calls back_end. Then, it calls fe_wrapup_part_2 +(also in fe_wrapup.c) to do post-back-end wrapup. Finally, it calls +exit_compilation to exit with the exit status appropriate to the +severity of the errors detected.

    +

    If multiple source files can be compiled, the main program includes a loop +around the steps from fe_init to back_end. It calls +get_next_source_file to see if there are any more source file names in +the command line.

    +

    Usually, the front end has its own main program, but it can instead be used +as part of some other main program. This is done by setting the +MAKE_FRONT_END_CALLABLE configuration macro. The name of the main entry +point into the front end is specified by the EDG_MAIN macro, and is +edg_main by default. When the front end is callable, +exit_compilation does not actually exit the program, but instead +returns control to the routine that called the front end.

    +
    +

    18.1. Initialization and Wrapup#

    +

    fe_init.c contains one-time initialization. Declarations of external +variables in .h files, which must begin with EXTERN, are compiled +here with EXTERN defined as an empty string, so storage is actually +allocated. Likewise, VAR_INITIALIZERS is defined as 1, so that +initializers on those variables are put out. The main routine is +fe_init; it calls other routines to initialize predefined macros, +keywords, and assorted state variables. In particular, it calls some +initialization routines in other files (e.g., lexical_init, +sym_tbl_init). There are several different kinds of initialization +routines:

    +
      +
    • +
      “early” initialization routines (e.g., cmd_line_early_init), which +are called before command-line processing is done.
      +
      +
    • +
    • +
      “one time” initialization routines (e.g., lexical_one_time_init), +which are called only once per invocation of the front end, even if +multiple source files have been specified on the command-line (when +COMPILE_MULTIPLE_SOURCE_FILES is enabled).
      +
      +
    • +
    • +
      “per-compilation” initialization routines (e.g., lexical_init), +which are called for each source file specified on the command-line +(when COMPILE_MULTIPLE_SOURCE_FILES is enabled).
      +
      +
    • +
    • +
      “trans-unit” initialization routines (e.g., +lexical_trans_unit_init), which are called once for each +translation unit processed when processing exported template definition +files or when COMPILE_MULTIPLE_TRANSLATION_UNITS is enabled.
      +
      +
    • +
    +

    Because the front end can be reinitialized (when +MAKE_FRONT_END_CALLABLE is used), most variables must be initialized +dynamically, not statically. Variables that are modified by command-line +processing must be initialized in early initialization routines.

    +

    Command-line -D and -U options are also handled here (see +preproc_init).

    +

    If multiple source files are accepted, fe_init is called at the start +of compilation of each file.

    +

    fe_wrapup.c contains one-time wrapup code. This involves popping the +file name scope, checking for errors on files written, and dumping debug +statistics, such as information on symbol table efficiency and on total +memory used. fe_wrapup is called after the front end is done but before +the back end (if any) is executed, and fe_wrapup_part_2 is called after +the back end (if any) is executed.

    +
    +

    18.1.1. C++/CLI Initialization#

    +

    The C++/CLI language depends in some essential ways on its core library, +which is loaded from assembly metadata (usually a file called +mscorlib.dll). The initialization process therefore preloads that +library and any others specified via the --preusing command-line option +with a call to process_preusings.

    +

    Immediately after loading the top-level declarations of the core library, +process_preusings also initializes a number of global variables (and +global array elements) to point to the symbols for special entities from +the core library (for example, the ref class System::Object). This is +done in init_cli_symbols.

    +

    init_cli_symbols also creates templates for cli::array, +cli::interior_ptr, and cli::pin_ptr. This is achieved by running +ordinary front end processing on string literals (via calls to +scan_top_level_metadata_declarations) containing the declarations for +those templates. The symbols representing these templates are recorded at +this time (for ease of reference in later contexts).

    +

    The symbol for namespace ::cli itself is created even earlier by a call +to make_symbol_for_namespace_cli.

    +
    +
    +
    +

    18.2. Debug Routines#

    +

    The source file debug.c contains the routine that processes the +command-line debug request option (-d), and also the routines +debug_enter and debug_exit which are called for flow tracing. When +the command-line debug request includes routine names, debug_enter +checks the name of the routine entered against the names on the request +list. If the name is found, the associated modification of debug_level +is done. An internal stack is used to preserve information from +debug_enter time to debug_exit time for a function. One trick: A +checksum of the stop tokens set is computed and stored on entry, and +recomputed and checked on exit. This helps catch mismatched +add_stop_token and remove_stop_token calls in recursive descent +scanning routines.

    +

    debug_enter and debug_exit are not called if there is no +command-line debug request (i.e., if db_active is FALSE).

    +
    +
    +

    18.3. Generating Strings from IL Types and Constants#

    +

    il_to_str.c contains code that converts IL types and constants into +C/C++-form strings. Associated declarations are in il_to_str.h.

    +

    To use these routines, one needs to declare a control block of type +an_il_to_str_output_control_block, call +clear_il_to_str_output_control_block to initialize it, and then set +applicable fields to describe how the string output should be done. The +control block includes, among other things, a pointer to a routine to +output a string, so one can establish a control block that provides an +output routine that writes to a file, or a control block that provides a +routine that puts the output string into a buffer, etc. Other fields in the +control block control the style of output and provide other (optional) +callback routines to do specialized output (instead of the default version) +for certain constructs.

    +

    form_type produces a string for a type. It does this by calling

    +
      +
    • +
      form_type_first_part, which outputs the type specifiers and the +part of the declarator that precedes the name, and then
      +
      +
    • +
    • +
      form_type_second_part, which outputs the part of the declarator +following the name.
      +
      +
    • +
    +

    So, for example, for the type

    +
    +
    +
    array [10] of pointer to const int
    +
    +
    +

    the “first part” would be

    +
    const int *
    +
    +
    +

    and the second part would be

    +
    [10]
    +
    +
    +

    If one wants to put out a declaration of an identifier, one can do so by

    +
      +
    1. calling form_type_first_part, then

    2. +
    3. outputting the identifier, then

    4. +
    5. calling form_type_second_part.

    6. +
    +

    producing an overall output string like “const int *a[10]”.

    +

    form_type_first_part descends through any derived types that are at the +top of the type by calling itself recursively. When it reaches a +non-derived type, it calls form_type_specifier to output the specifiers +part of the type (e.g., “const int” for the above example). Then, while +reascending, it puts out the parts of the declarator that appear on the +left-hand side of the declarator (pointers, references, +pointers-to-members, and any required parentheses).

    +

    form_type_second_part also descends through any derived types by +calling itself recursively. While descending, it puts out the parts of the +declarator that appear on the right-hand side of the declarator (arrays, +functions, and any required parentheses). form_array_declarator puts +out array declarators. form_function_declarator puts out function +declarators; it can be replaced by a user-provided routine if desired. One +reason to replace it: It does not handle putting out function declarators +for function definitions.

    +

    form_type_specifier puts out non-derived types. Most cases are simple +(see, for example, form_int_kind_name and +form_float_kind_name). Typedef names are put out as such. class, +struct, union, and enum types are always put out as references +to those types, i.e., a definition is never put out.

    +

    form_name puts out names; it can be replaced by a user-provided routine +if desired. It handles qualified names (see +form_class_or_namespace_qualifier), unnamed entities, and template +argument lists on classes (see form_template_args).

    +

    form_constant produces a string for a constant. It does some processing +itself, and has several important helper routines:

    +
      +
    • +
      form_integer_constant puts out integer constants, including sign, +suffix, and implicit casts. It also handles integer constants cast to +pointer types (e.g., null pointers).
      +
      +
    • +
    • +
      form_address_constant puts out address constants, including the +“&” and optimizations for arrays and for adding a byte offset to +the base address.
      +
      +
    • +
    • +
      form_pm_constant puts out pointer-to-member constants, including +null constants and any required implicit casts.
      +
      +
    • +
    • +
      form_char puts out a single character of a string or character +constant, dealing with unprintable characters and the like.
      +
      +
    • +
    +
    +
    +

    18.4. Error Reporting#

    +

    error.c contains code that handles reporting of errors. error.h +contains the declarations needed to use the error +routines. error_msg.txt defines the error codes and associated error +message text for all of the error messages, and, along with +error_tag.h, is used by mk_errinfo to generate the err_codes.h +and err_data.h files. It is the generated files that are actually used +by the front end to define the an_error_code enumeration and the array +of error message text. See mk_errinfo for a description.

    +

    an_error_code defines enumeration constants that represent each error +message (for example, ec_unclosed_string represents the error message +“missing closing quote”). ec_no_error is the first member of the +enumeration, and therefore has the value 0, which has the effect of +allowing flags with the value 0 for no error, and a non-zero value to +indicate a specific error.

    +

    Within the error message texts, fill-in codes beginning with “%” +indicate points at which information is to be inserted:

    +
    + + + + + + + + + + + + + + + + + + +
    +
    %%
    +
    +
    +
    A “%” is inserted into the message.
    +
    +
    +
    %d
    +
    +
    +
    A number is inserted into the message.
    +
    +
    +
    %s
    +
    +
    +
    A character string is inserted into the message. %sq indicates +that the inserted string should be placed in quotes, e.g.,
    +
    +
    +

    could not open source file "abc.h"

    +
    +
    +
    %t
    +
    +
    +
    A description of a type is inserted into the message. It is always +placed in quotes, e.g.,
    +
    +
    +

    cast to array type is nonstandard (treated as cast to +"int *")

    +
    +
    +
    %n
    +
    +
    +
    A description of an entity in the program (identified by a symbol) +is inserted into the message. The default %n (“name”) can be +modified by appending an “o” (%no, “name only”) to get just +the name of the entity, a “p” (%np, “name with function +parameters”) to force parameter information on a function, an +“f” (%nf, “name full”) to get full type information on the +name, an “a” (%na, “name with template arguments”) to get +arguments on a template, “t” to force the “A<T> with T=int” +form of template name to be used, or a “T” to get the translation +unit in which the symbol was declared.
    +
    +
    + + + + + + + + + + + + + + + + + + + + + +
    +
    %n
    +
    +
    +
    function "A::f"
    +
    +
    +
    %no
    +
    +
    +
    "A::f"
    +
    +
    +
    %np
    +
    +
    +
    "A::f(int, float)"
    +
    +
    +
    %na
    +
    +
    +
    "A<int>"
    +
    +
    +
    %nt
    +
    +
    +
    "A<T> with T=int"
    +
    +
    +
    %nT
    +
    +
    +
    function "f(int)" (from translation unit "x.c")
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + +
    +
    %p
    +
    +
    +
    A source position is inserted into the message.
    +
    +
    +
    %[label]
    +
    +
    +
    The specified label is looked up in the label_fill_ins array +and one of two error messages is substituted depending on the +value of a boolean variable associated with the label. The +substituted error messages cannot themselves have fill-ins. See +the definition of label_fill_ins to determine the list of +valid label fill-ins (or to add a new one).
    +
    +
    +
    %T
    +
    +
    +
    A template argument list is inserted into the message.
    +
    +
    +
    +

    In the default mode, the entity description is preceded by a keyword that +identifies the type of the entity (e.g., function above). That is also +done in the “full” mode for entities that are not variable-like or +function-like. The normal “%n” displays function parameter types only +for overloaded functions. Any of the %n codes can be modified by +appending a “d” to request information on the point of declaration of +the symbol:

    +
    declaration is incompatible with "int f(char)" (declared at line 17)
    +
    +
    +

    Following the optional “d” modifier, the “T” modifier may be used +to display the translation unit associated with the symbol (”from +translation unit "x.c"”). When compiling a primary translation unit, this +will cause the translation unit to be displayed for symbols from secondary +translation units. When compiling a secondary translation unit, this will +cause the translation unit to be displayed for all symbols.

    +

    There can be more than one fill-in code in a message. When there is, each +fill-in code can be numbered (e.g., %t1, %t2) to tie it to a +corresponding fill-in argument. Note that this technique allows one to +reorder the fill-ins in a message (say, when changing the error messages to +a language other than English) without changing the order of the fill-in +arguments on error calls throughout the front end.

    +

    Each normal diagnostic includes four kinds of information:

    +
      +
    • +
      the error code, which is a value from the enumeration just mentioned, +and indicates the error message text;
      +
      +
    • +
    • +
      a severity (remark, warning, discretionary error, error, or +catastrophic error);
      +
      +
    • +
    • +
      the error position (a sequence number and column); and
      +
      +
    • +
    • +
      optionally, some information that goes into fill-in spots in the error +message text.
      +
      +
    • +
    +

    The severity is usually indicated by the routine called (e.g., warning +instead of error). There are also routines that accept the severity as +an argument. A given message can be (and is, in many cases) output with +different severities in different modes or different places.

    +

    The severity of a given error code may be overridden through the use of a +command line option or pragma. For example, the option +--diag_error=extra_semicolon may be used to cause the extra semicolon +diagnostic to be issued as an error, even if the warning function was +actually called to report the error. Only diagnostics that would by default +be issued as remarks, warnings, or discretionary errors may have their +severities overridden (i.e., nondiscretionary errors and catastrophic +errors may not have their severities overridden). When a severity is +overridden by a pragma, the default severity can be restored by use of the +diag_default pragma. The default severity is the severity as would +normally be used for the message as adjusted by any command-line options.

    +

    The error severity may be overridden by specifying either an error “tag” or +an error number. The error tag is a name assigned to each error code. The +error number is the numeric value of the error code enumerator that +represents the message. By default, the error tag is the same as the error +code enumerator name with the ec_ prefix removed. The error tag may be +changed by specifying an alternate tag in the error_msg.txt +file. Additional tags may be provided by creating entries in the +error_tag.txt file. set_severity_for_error_tag and +set_severity_for_error_number are used to override the severity for a +given diagnostic. These routines are called to process the error severity +options during command line processing.

    +

    The error position is usually given by the global variable +error_position, but it can also be explicitly +supplied. error_position is set to the start of each token as it is +scanned, and is set on exit from recursive descent routines to the start of +the entity just scanned, unless that entity is extremely large (like +several lines). This usually results in the correct position in +error_position, at least for syntax errors.

    +

    When the sequence number of a_source_position is 0, the column has +special meaning (for example, it can indicate that the error occurred in +the command line). See basics.h.

    +

    The error routines themselves have names that encode the severity (one of +remark, warning, error, catastrophe or the generic +diagnostic), and the particular combination of fill-ins and a source +position that they accept. That is, an error routine name may be as simple +as error or as complicated as pos_ty2_warning. pos indicates +that a source position is provided; str or st indicates that a +string fill-in is provided; sym or sy indicates that a symbol +fill-in is provided; type or ty indicates that a type fill-in is +provided. These can be followed by a number if more than one fill-in is +needed, e.g., ty2 for two types. So, for example, pos_ty2_warning +issues a warning, and the caller is expected to provide the error code, the +source position, and two fill-in types. See error.c for the full list +of routines. Not all combinations exist, but it is easy to add any routine +that does not exist.

    +

    For a syntax error, one can instead call

    +
    syntax_error(error_code);
    +
    +
    +

    which will call error and then flush_tokens (see lexical.c).

    +

    For complicated errors that may have to list an arbitrary number of items, +for example diagnostics for overloading ambiguity, one can make an initial +call to issue the initial line of the error (calling start_error or one +of its variants such as type_start_error), then any number of calls to +add individual lines of additional information (calling add_diag_info +or one of its variants such as sym_add_diag_info), and then a call to +end_error to finish the error processing (including writing the source +line in error). The end result is illustrated by

    +
    "test.C", line 7: more than one constructor applies to convert from
    +          "double" to "A":
    +            function "A::A(int)"
    +            function "A::A(float)"
    +    f(2.0);
    +      ^
    +
    +
    +

    The usual fill-in processing is available on both the initial line and any +lines of additional information. The additional lines are described by an +error code, so they can also contain arbitrary text.

    +

    The error formatting and processing is done by construct_message. It +fetches the error message text, builds a linked list of message segments +describing the message and its fill-in codes, expands each fill-in +appropriately, and writes the full message.

    +

    If an error is detected while processing a template instantiation or during +implicit generation of a routine (e.g., a constructor), it is helpful to +provide additional information on the context in which the error was +detected:

    +
    "test.c", line 7: error: "A::A()" is inaccessible
    +  B x;
    +     ^
    +          detected during implicit generation of "B::B()" at line 7
    +
    +
    +

    The context is deduced from the entries in the scope +stack. include_in_context_output identifies the scope stack entries +that merit extra context information. If there are any such entries, +diag_message outputs an extra context line for each, in order from +innermost context to outermost.

    +

    format_output_line is the routine that actually prints the diagnostic +messages; it is the routine to change to modify the error output. To output +the source line associated with the diagnostic, write_source_line is +called. If the error is in the current line, write_orig_source_line +reconstructs and writes out the original source line, with a caret under +the column position of the error. If the error is not in the current line, +write_error_source_line reads the line from the source file, if +possible, and writes out the source line. Long diagnostic messages are +wrapped across multiple lines. If raw listing information is requested, +similar information is written to f_raw_listing (in encoded form). The +diagnostic routines count the number of diagnostics of each severity so +that the compilation can be ended with an appropriate exit status. They +suppress diagnostics that are below the error display threshold. If an +error is catastrophic or if the error limit is reached, the compilation is +terminated.

    +

    The severity of diagnostics for strict ANSI violations and C++ anachronisms +can be specified by command line options. To simplify handling of these +diagnostics the global variables strict_ansi_error_severity and +strict_ansi_discretionary_severity contain the error severity to be +used for strict ANSI violations. The former is either es_warning or +es_error, while the latter is either es_warning or +es_discretionary_error, depending on which strict mode was selected on +the command line. anachronism_error_severity contains the error +severity to be used when anachronistic features are used. These global +variables can be used as arguments to the diagnostic reporting +routines.

    +

    command_line_error and str_command_line_error are the routines +called for command-line errors (without or with fill-in text, +respectively). They do not return.

    +

    The routine internal_error should be called for internal errors, such +as failures of consistency checks. It should not be called for anything +that is due to a source program error or some environmental error (like a +missing file). The call should look like

    +
    +

    internal_error("routine-name: problem found");

    +
    +

    Several routines are provided as convenient ways to do consistency +checking. Calls of these routines need not be surrounded by #if +CHECKING/#endif; they are defined as macros that expand to nothing +when CHECKING is disabled. check_assertion can be used to check an +expression to make sure it is true; check_assertion_str is similar, but +includes a string to be printed on error +termination. unexpected_condition is used when a piece of code is not +expected to be reached (for example, the default clause of a switch); +unexpected_condition_str is similar, but includes a string to be +printed on error termination.

    +
    +
    +

    18.5. Memory Management#

    +

    mem_manage.c contains memory management routines. mem_manage.h +contains the associated declarations.

    +

    Memory is allocated in memory regions. File-scope intermediate language +information is put in memory region 1, and the functions in the source +program will each have one of the memory regions 2, 3, and so forth. Memory +region 0 is used for storage that need not survive the front end, like the +symbol table.

    +

    Before using a memory region, one calls either init_memory_region (for +regions 0 and 1) or new_memory_region (for regions for functions) to +initialize the new region.

    +

    alloc_in_region is then called when needed to allocate space in a given +region. (alloc_fe can be called for the special case of allocation in +region 0, the front-end-only region.) alloc_in_region allocates a large +block of memory for each memory region by calling malloc, then parcels +out that storage as it is needed. When the block is exhausted, a new block +is allocated and put on a linked list of blocks for that memory region.

    +

    When one is done with an IL memory region, +check_for_done_with_memory_region is called; it will either write the +information to a file and free the block, or trim the end of the memory +region to reclaim any unused space (depending on whether an IL file is +being generated), or defer this processing until later if the memory is +potentially needed for operations such as inlining or generic lambda +instantiation. “Trimming” means making a separate available block from the +remaining space at the end of the last block in the region. Since the +blocks are large (typically, 64K) and a typical function will use less than +10K of the block, this is an important feature. The combination of using a +large block size and reusing the remaining space improves efficiency (in +reducing the number of calls to malloc) and avoids the need to guess at +the amount of storage a particular memory region is likely to +need. Eventually, when the partial blocks created in this way are released, +they are recombined into the original large blocks allocated via +malloc, and freed using the system free. Thus storage used is +freed, but only on a large-block basis, so fragmentation is not a problem.

    +

    alloc_general is a more-or-less direct interface to malloc to be +used in the infrequent cases where storage must be allocated that will +survive into the back end if the back end is called in the same program. An +example of such storage is the debug option control list, which holds +information about the command-line debug option.

    +

    alloc_resizable_buffer and realloc_buffer are used to allocate +tables that can be enlarged (e.g., input_stack).

    +

    When MAKE_FRONT_END_CALLABLE is used, the front end keeps a record of +all memory allocations so that all of the memory allocated can be freed +before returning control to the caller.

    +

    When precompiled headers are used, the memory management routines work to +allocate the IL memory region blocks at reproducible addresses, so that the +information in a precompiled header file can be read back in without the +need to walk the IL and remap pointer references. See +Memory Management Issues.

    +
    +
    +

    18.6. File Variables#

    +

    Normally, any open files are closed when the front end exits, but when +MAKE_FRONT_END_CALLABLE is used, any open files must be closed if the +front-end were to terminate abnormally. This is accomplished by having a +special cleanup routine (e.g., templates_cleanup) in any file that +opens and closes files. The cleanup routine is present only when +MAKE_FRONT_END_CALLABLE is used. File variables must be set to NULL +when they do not refer to an open file. The cleanup routine generally calls +close_file_if_open, to close any files that may be open. The cleanup +routines are called by fe_cleanup (in fe_wrapup.c).

    +
    +
    +

    18.7. Command-line Parsing#

    +

    cmd_line.c contains code to parse the command line; cmd_line.h +contains the associated declarations. The main routine is +proc_command_line. Aside from setting switches, proc_command_line +establishes the primary source file, the preprocessing output file if there +is one, the raw listing output file if there is one, the cross-reference +output file if there is one, and the include file search list.

    +

    If multiple source files can be compiled, get_next_source_file is +called after each source file is compiled to see if there is another file +name on the command line. It also does some minor initialization.

    +

    proc_command_line is called only once, even if multiple source files +are specified on the command line. Since the IL memory for each source file +is separate and self-contained, proc_command_line cannot allocate +anything in the IL memory: For one thing, it does not exist yet, and for +another, there will be a distinct copy for each source file +compiled. Therefore, file names and other information saved by +proc_command_line must be saved in general memory, and copied into IL +memory later (e.g., in fe_init) for each source file.

    +
    +
    +

    18.8. Host-dependent Routines#

    +

    host_envir.c contains host-dependent routines; host_envir.h +contains the associated declarations.

    +

    The following routines are used to maintain the list of directory names to +be searched for include files:

    +
      +
    • +
      add_default_include_search_path
      +
      +
    • +
    • +
      add_to_include_search_path
      +
      +
    • +
    • +
      add_to_front_of_include_search_path
      +
      +
    • +
    • +
      push_primary_include_search_dir
      +
      +
    • +
    • +
      pop_primary_include_search_dir
      +
      +
    • +
    • +
      change_primary_include_search_dir
      +
      +
    • +
    +

    The following routines are used to tear apart and build up file names:

    +
      +
    • +
      directory_of
      +
      +
    • +
    • +
      gs_directory_of
      +
      +
    • +
    • +
      derived_name
      +
      +
    • +
    • +
      replace_file_name_suffix
      +
      +
    • +
    • +
      combine_dir_and_file_name
      +
      +
    • +
    +

    The following routines are used to open files in various ways:

    +
      +
    • +
      open_source_file
      +
      +
    • +
    • +
      reopen_source_file
      +
      +
    • +
    • +
      okay_as_output_file
      +
      +
    • +
    • +
      open_output_file
      +
      +
    • +
    • +
      reopen_error_output_file
      +
      +
    • +
    +

    delete_file is used to delete files (specifically, files that were +partially generated and are to be canceled because of detection of an +error).

    +

    open_temp_file and close_temp_file provide support for creating +temporary files. (Note: At the present time, the front end only uses +temporary files when generating an intermediate language file for immediate +use by a back end called in the same program, and in the C-generating back +end.)

    +

    normal_termination and term_compilation are used for termination of +the compilation. The low-level functions of term_compilation are +available individually through write_signoff and exit_compilation.

    +

    identify_source_file is called from fe_init at the start of +compilation of each source file when there are multiple source files on the +command line. It outputs a message identifying the start of the compilation +of the file.

    +

    set_signal_handlers is called during initialization to set up handling +for signals that should abort the compilation.

    +

    This file is likely to be modified for different hosts. See the section on +host configuration for more information.

    +
    +
    +

    18.9. Intermediate Language Traversal#

    +

    il_walk.c contains the routines that walk the intermediate language +tree, and il_walk.h contains the associated +declarations. walk_entry.h contains the detailed code to process the +fields of each IL entry kind.

    +

    “Walking” the tree means traversing the in-memory form of the IL and +calling a supplied routine for each node in the tree. This is used in +displaying the IL in human-readable form, in writing the IL to a file, and +in reading the IL from a file.

    +

    The walking is done on a memory region basis, i.e., for the file-scope +memory region or the memory region for a function. The routines for those +cases are walk_file_scope_il and walk_routine_scope_il. They call +walk_entry_and_subtree or walk_string_entry for each entry, and +those in turn call the user-supplied entry processing functions. There are +two separate entry processing functions supplied for each traversal: one +for strings, and one for non-strings. The main reason for the difference is +that string entries do not have fixed sizes, so the string routine has an +extra parameter for the size.

    +

    Since the tree is actually a graph and has cycles, there needs to be a way +to tell when the traversal returns to an entry that has already been +visited. This is provided by the il_walk_flag in the prefix that +precedes each IL entry. This flag starts out as 0 in all entries. On the +first traversal, it is changed to 1 in all entries, and it keeps +alternating between 0 and 1 on each subsequent traversal. Therefore, on a +given traversal, the entries already seen have one value, and those not yet +seen have the other value.

    +

    While the tree is traversed, one can also request that all the pointers in +the tree be remapped in some way. For example, when writing to an IL file +in the alternate form, each pointer is replaced by an entry number. Such +remapping can be requested by providing a pointer remap function for the IL +walk, or explicitly by calling remap_pointers_in_il_entry or +remap_il_header_pointers.

    +

    Special handling is required for “orphan” entries. These are entries +allocated in the file scope memory region that are referenced only from +function scope memory regions. When the parents of such entries are written +out and then removed from memory, the entries are orphaned because they are +not attached to the rest of the file-scope IL tree.

    +

    The orphan mechanism makes lists of such entries so that they can be found +during traversal of the file-scope IL.

    +

    The array orphaned_file_scope_il_entries heads lists of orphaned +entries linked together by a hidden orphan-list pointer that precedes the +storage for each file-scope IL entry. (It also precedes the +an_il_entry_prefix structure.)

    +

    The orphan lists are built up while the function scope memory regions are +walked. Each time an entry in a function scope memory region contains a +pointer into the file scope memory region, the entry pointed to is recorded +as a potential orphan. Later, at the end of the walk of the file scope IL, +the entries on the orphan lists are visited. If the entries are not in fact +orphans, they will have been previously visited, and the IL walk flag will +indicate that fact.

    +

    A separate mechanism exists for orphaned lists, specifically the lists of +local types and local static variables in function and block scopes. Those +are unusual in that the list is completely in the file scope memory region +but the pointer to the list is in a function scope memory region +entry. Each of the entries on those lists is placed on the orphaned entries +list, but there needs in addition to be a way to remember the head-of-list +pointers so that the next pointers in the entries can be +remapped. That’s done with a list of entries of type +a_scope_orphaned_list_header pointed to by the +scope_orphaned_list_headers field of il_header. Each entry on the +list points to a list of types and a list of static variables preserved +from a function or block scope.

    +

    Obviously, the code in walk_entry.h must be kept up-to-date whenever +the IL definition in il_def.h is changed.

    +

    il_walk.c also contains some special-purpose walking routines: +walk_declarative_entities_in_scope can be used to walk entities like +variables in a given scope; traverse_expr can be used to walk an +expression tree; and traverse_statement can be used to walk a statement +tree. In each case, user-provided callback routines can be called for each +node of the tree.

    +
    +
    +

    18.10. Needed Flags#

    +

    When the configuration switch MAINTAIN_NEEDED_FLAGS is TRUE, the front +end will maintain the needed flag in the source-correspondence entry, +and the definition_needed flag in class types and routines. The code to +do this is in il_walk.c, walk_entry.h, il.c, and +scope_stk.c. The needed flags are a more sophisticated version of the +referenced flag. They are set by beginning with all externally-defined +variables, static data members, and functions in the compilation unit, and +marking those as needed. Then the entities referenced by those are marked +as needed, and so on. The resulting needed flag setting indicates +whether something is “really” needed, as opposed to referenced from +something that is itself unneeded. For example:

    +
    static int i;         // i is referenced, not needed
    +static void f() {     // f is not referenced, not needed
    +  i = 1;
    +}
    +int main () {}        // main is needed, not referenced
    +
    +
    +

    The definition_needed flag indicates whether the definition of a class +is needed, as opposed to merely a declaration. For example:

    +
    struct A { };
    +struct B { };
    +A *p;      // forces needed on A, but not definition_needed
    +B b;       // forces needed and definition_needed on B
    +
    +
    +

    There is a similar flag for functions as well.

    +

    If DEFAULT_REMOVE_UNNEEDED_ENTITIES is TRUE, and that setting is not +overridden via a command-line option, unneeded entities are removed from +the IL. Classes that have needed TRUE and definition_needed FALSE +are modified to eliminate their definitions. Function-local entities are +never affected by this process (they are not removed, and local classes are +never turned into declarations). The IL tree after alteration is +self-consistent, in that a back end that does not use the “needed” flags +will find all the IL entries it expects. A back end that does use the +“needed” flags should be sure to use both of them, i.e., +definition_needed as well as needed.

    +

    The “needed” flags processing and removal of unneeded entries works with +and without IL lowering, and for both C and C++. When IL lowering is used, +the “needed” flag information is determined on the basis of the lowered +code. When the C++-generating back end is used, and the source program has +templates, elimination of unneeded entities is disabled, because the +template bodies may contain references to apparently unneeded +entities. This can be changed, carefully, if one has a situation where all +template instantiation will be done by the EDG front end rather than by +some compiler operating on the source code generated by the C++-generating +back end.

    +

    The setting of the “needed” flags is done as follows:

    +
      +
    • +
      At the end of scanning a function definition, if the function is +externally defined, pop_scope calls mark_as_needed on the +routine, which in turn calls set_routine_definition_needed. These +use a specialized version of the walk_entry.h IL-walking code to +sweep through the IL tree and set the needed flag on all +transitively-referenced entities. If the type of reference requires a +complete type, and the type is a class, set_class_definition_needed +is called to set the definition_needed flag on the class. If a +reference to a routine requires that the routine have a definition, +set_routine_definition_needed is called for the routine.
      +

      +
      When a routine’s definition is needed, the definition is also walked, +and then the memory region for the function can be disposed +of. (mark_to_keep_in_il is also called for the function memory +region; more on this below.) That means the memory region can be +written to a file and then freed, if an IL file is being +used. Conversely, as long as a function is not known to be needed, its +body must be retained. If the function is still marked as unneeded at +the end of the compilation, it is then clear that the function truly is +unneeded. It is deleted and its memory region is freed (without writing +it to the IL file, if there is one).
      +
      +
    • +
    • +
      When the file scope is being +popped from the scope stack, several things are done. First, +set_needed_flags_at_end_of_file_scope is called. It visits all +variables (including static data members), and calls mark_as_needed +for those that are externally-defined. This causes the variables and +everything they reference to be marked as “needed.”
      +
      +
    • +
    • +
      Then, +mark_to_keep_in_il is called for the file scope. This uses another +variant of the walk_entry.h IL-walking code to sweep through the IL +tree and set the keep_in_il flags in the IL entry prefix and the +keep_definition_in_il flag in classes and routines. These flags +have meanings similar to the needed and definition_needed +flags, but they are set in more cases, to deal with the fact that some +entities in the IL tree must be retained (for consistency) even if they +are “unneeded.” In this sweep, entities that can and will be removed +(based on the needed and definition_needed flags and the +context where the entities appear) will not be visited. The +keep_in_il sweep also notes whether complete class types are +needed, and calls set_class_keep_definition_in_il when appropriate, +and whether routine definitions are needed, and calls +set_routine_keep_definition_in_il.
      +

      +
      All decisions about +removing IL entries from the IL tree are based on the keep_in_il +and keep_definition_in_il flags, rather than on needed and +definition_needed.
      +
      +
    • +
    • +
      Then, +eliminate_bodies_of_unneeded_functions is called. It eliminate the +bodies (but not the declarations) of functions that are not needed.
      +
      +
    • +
    • +
      Then, eliminate_unneeded_il_entries is called. It removes types, +variables, and routines in the file scope that are unneeded, and +reduces classes to declarations where appropriate (by calling +turn_class_definition_into_declaration). Auxiliary parts of the IL +data structure, such as source sequence entries and the hidden-name +table, are updated as necessary.
      +
      +
    • +
    +

    The IL-walk process used to set these “needed” flags stops when it +encounters an entry with the flag already set. This is desirable for +compilation speed reasons, and necessary to avoid loops for parts of the IL +structure that are graphs instead of trees, but it also makes certain kinds +of problems possible. Variables, routines, and types that are not +function-local have the potential to be redeclared after the “needed” flag +is initially set. For example, a class A might be declared, then marked +as needed, then defined. Or, a function might be defined, then declared to +add an additional default argument. In all such cases, The needed or +keep_in_il flag would be set already on the entry, and therefore an +attempt to set it again would result in an immediate return, rather than a +sweep through the updated subtree. To avoid this problem, the subtrees of +these redeclarable entities are not swept ordinarily; the appropriate flag +is set on the entry itself, but its subtree is not visited. At the end of +the file scope, when no more redeclarations are possible, the global flag +end_of_file_scope_needed_flags_phase is set to TRUE, and that enables +the subtree walks. set_needed_flags_at_end_of_file_scope and +mark_to_keep_in_il, as they are doing the needed and keep_in_il +walks respectively, look for these delayed-subtree-processing entries, and +handle them by clearing the needed or keep_in_il flag and then +calling the subroutine to set them again, which this time will visit the +subtree. For the needed flag walk, remark_as_needed provides a +convenient way of doing this.

    +

    When ONE_INSTANTIATION_PER_OBJECT is TRUE, a more complicated set of +“needed” flags is maintained. In that mode, each instantiation is put out +as a separate object file. There is still only one IL tree, but it is +marked so that a back end can sweep through it several times and put out a +different “slice” each time, each slice containing one instantiated entity +(function, variable, or static data member) plus exactly the set of other +entities needed by that entity. This is done via a set of per-instantiation +“needed” flags, represented as a bit vector implemented as a linked list of +entries of type a_per_instantiation_needed_flags_entry attached to the +per_instantiation_needed_flags field of the source correspondence. Each +slice is assigned one bit in that bit vector, and if the bit is 1 the +associated entity is needed in the slice.

    +

    The per-instantiation “needed” flags are tested and set by the macros +needed_flag_is_set and set_needed_flag. The global variable +needed_flag_bit_number indicates the bit number to be tested or set. +If it is zero, the needed flag is tested or set instead of the bit +vector.

    +

    Each instantiation is actually assigned two bits in the bit vector, the +second one used for the per-instantiation versions of the class and +function definition_needed flags. These are tested and set by +class_definition_needed_flag_is_set, +set_class_definition_needed_flag, +routine_definition_needed_flag_is_set, and +set_routine_definition_needed_flag. As with the needed-flag macros, +these macros depend on the value of needed_flag_bit_number and use the +definition_needed flags if that variable is zero.

    +

    The bit number assigned to a given instantiation entity is recorded in the +instantiation_needed_bit_number field in the variable or routine. When +mark_as_needed is called for the entity, after the standard “needed” +flag processing has been done, another sweep is done to set the proper bit +in the per-instantiation “needed” flag bit vectors of all entities +referenced from the instantiation. The class and function per-instantiation +definition-needed bits are also set in this sweep.

    +

    All externally-defined entities that are not instantiations are assigned to +the slice numbered 1 (though their instantiation_needed_bit_number +fields are left as zero), and a similar sweep is done for them. By the end +of the compilation, therefore, every externally-defined entity has been +assigned to a slice, and the per-instantiation bits show what must be +included in each slice. The “1” slice includes everything that isn’t in an +instantiation slice.

    +

    Some entities are present in multiple slices. Constants, types, and class +definitions appear in each slice as needed. Inline functions are also +present in a slice if they are referenced in that slice. In general, +however, functions and variables can only appear in one slice, or more +precisely, their definitions can only appear in one slice. If other slices +reference them, they appear only as declarations in those slices. This +causes a problem for static functions and variables, which by definition +cannot be referenced from other object files. This is handled by making +those entities external with generated names. The sweeping routines will +set the static_used_by_instantiation flag in static entities that are +used by an instantiation, and IL lowering will turn such routines and +variables into external entities.

    +

    The simple needed and definition_needed flags end up being in +effect the unions of the corresponding per-instantiation sets. That is, if +any per-instantiation “needed” flag is set on an entity, then the +needed flag will be set, and likewise for the definition-needed +flags. Therefore, when the normal processing to remove unneeded entities is +done, it will remove only entities that are unneeded in all slices.

    +
    +
    +

    18.11. Intermediate Language Display#

    +

    il_display.c contains routines to display the IL in human-readable +form. il_display.h contains the associated declarations. The code is +currently set up to be compiled as a standalone utility program: It reads +the IL from a file (by calling the IL read routines), then traverses the +in-memory form using the IL walk routines, producing output on +stdout. il_display could be set up as a subroutine to be called +from within the front end.

    +

    The processing is very simple: Using the IL walk routines, it walks the +file scope and displays it, then walks each routine scope and displays +that. The IL walk routines are told to call disp_entry for each +non-string entry, and to call nothing for string entries (string entries +are displayed when pointers pointing to them are displayed). Most of the +display routines are very straightforward. When pointers are displayed, an +attempt is made to show what is pointed to. That is, if the entity pointed +to is named, or if it is a string, a constant, or a type, a brief summary +of the entity is given so one does not have to look at, say, a type entry +to find out that it is the entry for int.

    +

    If there are errors in the IL, they are highlighted (e.g., +“BAD-TYPE-SPECIFIER-KIND”) and the display continues as well as it +can. An internal error is not generated.

    +

    Obviously, the code in il_display.c must be kept up-to-date whenever +the IL definition in il_def.h is changed.

    +
    +
    +

    18.12. Writing the Intermediate Language to a File#

    +

    il_write.c contains routines that write the intermediate language to a +file, and il_write.h contains associated declarations.

    +

    IL writing takes the in-memory IL and writes it to a file for later +reading.

    +

    start_il_file is called to open the IL file, and finish_il_file to +close it. Alternatively, cancel_il_file can be called to delete the IL +file and suppress further IL file generation if an error is detected during +the compilation.

    +

    write_memory_region is called to write out each memory region, i.e., +the file-scope memory region or a memory region for a function. It writes +the memory region at the end of the intermediate language file.

    +

    There are two IL file formats. The switch ALTERNATE_IL_FILE_FORMAT in +host_envir.h indicates which is to be used. The file header is the same +in both formats:

    +
      +
    • +
      A special string identifying the file as an IL file, and including the +version number of the IL (see il_file.h).
      +
      +
    • +
    • +
      The number of memory regions.
      +
      +
    • +
    • +
      The number of function definitions.
      +
      +
    • +
    • +
      The file position of the file index (at the end of the file).
      +
      +
    • +
    • +
      The file position of the file-scope memory region.
      +
      +
    • +
    • +
      The il_header struct, which is the root of the IL tree.
      +
      +
    • +
    • +
      The array of orphan-list pointers.
      +
      +
    • +
    +

    In terms of processing, the space for the header information is reserved at +start_il_file time, but the full information is not known until all +regions have been written. At finish_il_file time, the file pointer is +repositioned and the final information is overwritten on the reserved +space.

    +

    The file index is also the same in both formats: It is an array of file +positions, such that file-index[i] gives the file position of the start of +the information for memory region i. The index is the last thing written in +the file. No entry 0 is written; the first entry is entry 1 (i.e., for the +file scope), which is at the position indicated by the file index position +in the header. The other entries follow. There are as many entries as the +“number of memory regions” given in the header.

    +

    Between the header and the file index is a sequence of one or more memory +regions. Since the file-scope region is not complete until the end of the +compilation, the file contains all the function regions first, in order of +definition, and then the file-scope region at the end.

    +

    In both formats, the information for a memory region begins with the memory +region number, and the overall sequence of regions is followed by a zero +which serves as an end marker if the regions are read sequentially.

    +

    Beyond that, the information for a memory region is quite different in the +two file formats.

    +

    The default file format involves writing out the memory blocks for each +region exactly as they appear in memory – i.e., large blocks, in memory image +form. On the reading side, these blocks are read back in, and since they +are probably not read in at the same address they had when written out, the +IL tree is walked to find and remap all the pointers. A tree walk is also +required on the writing side, at least for function scope memory regions, +to get the data structure for orphaned entries built. The process is fairly +fast on both the writing side and the reading side; although the tree walk +takes time, at least the I/O for reading the blocks can be done +efficiently, in large blocks.

    +

    The information for a region in the default format is as follows:

    +
      +
    • +
      The memory region number.
      +
      +
    • +
    • +
      The original memory address for the first block header.
      +
      +
    • +
    • +
      The original memory address for the primary scope entry for the region.
      +
      +
    • +
    • +
      The total size in bytes of the information following (i.e., the total +size of all blocks and their associated headers).
      +
      +
    • +
    • +
      For each memory block, the block header and block data. The header +contains pointers that point to the next block and to the data (all as +original memory addresses).
      +
      +
    • +
    +

    In the alternate file format, each entry is assigned an entry number (which +is recorded in the prefix preceding the entry), all pointers are changed to +the corresponding entry numbers, and each entry is written individually to +the file, preceded by an indication of the entry kind and by the entry +number. On the reading side, the entries are read individually and the +pointers in them are changed to the proper new pointer values. This format +is less efficient than the default format, because the actual I/O is done +one entry at a time for both writing and reading (there is of course +buffering under this, but it is still less efficient to make thousands of +calls to fwrite and fread than to make dozens of calls). The +advantage of the alternate file format is that it allows resizing or other +alteration of the entries on the reading side. If one wants to add +back-end-specific information, for example, one can do so.

    +

    The information for a region in the alternate file format is as follows:

    +
      +
    • +
      The memory region number.
      +
      +
    • +
    • +
      An array giving, for all the IL entry kinds (see il_walk.h), the +number of entries of each kind in this memory region.
      +
      +
    • +
    • +
      A sequence of entries, giving for each entry the entry kind, the entry +number, the entry length (only for string entries), the orphan-list +pointer (only for non-string file-scope memory region entries), and the +entry itself. After the last entry, a zero entry kind marks the end of +the sequence.
      +
      +
    • +
    +

    Entry numbers are assigned from 1 for each kind of table; there can be, for +example, a type entry 27 and a constant entry 27. 0 is used to represent a +NULL pointer. The entry numbers in each function scope start again from 1, +but in addition they have the top bit on, i.e., they effectively start with +LONG_MAX+2. Thus there can be identical entry numbers in two function +scopes (and that is not a problem), but a file-scope entry number can +always be distinguished from a function-scope number.

    +

    For string entries, the “entry number” used is an offset into a conceptual +block formed by concatenating all the strings of that kind, including the +terminating null if any, and with space reserved between the strings for +the entry prefix and for any required alignment. The offsets start from 1 +to preserve 0 as a NULL pointer. In the array of entry counts, the values +for string entries indicate the total size of the conceptual block, in +bytes, rather than an entry count. Thus, if there were three strings “abc”, +“de”, and “fghi” in a region, the prefix takes 4 bytes, and the host +machine requires 4-byte alignment, the strings’ entry numbers would be 5, +13, and 21, respectively, and the entry in the count array would be 25.

    +
    +
    +

    18.13. Reading the Intermediate Language from a File#

    +

    il_read.c contains routines that read the intermediate language from a +file, and il_read.h contains associated declarations.

    +

    File reading takes the IL in file form and reads it in to re-create the +in-memory form.

    +

    The routine il_read reads the file header and the file index, then +calls read_memory_region to read the file-scope memory region. Other +(function-scope) regions must be read explicitly by calling +read_memory_region directly. This allows the back end to read each +function, process it, and then free its IL by calling +free_memory_region, to reduce overall memory requirements.

    +

    With the default file format, the information for each memory region is +read with one large read, and the pointers in the region are then remapped +to the proper values by calling walk_file_scope_il or +walk_routine_scope_il with a pointer remap function. If all the memory +blocks are read back in at their original addresses (an attempt is made to +do this), the IL walk is not needed.

    +

    With the alternate file format, the array of entry counts is read at the +beginning of processing the region. For each entry kind, an area is +allocated that is large enough to contain all the entries of that kind (its +size is the number of entries times the size of each entry). This area is +then considered an array of entries of that kind, and the entry number is +an index into the area. (For string entries, the “entry count” is the +actual total size, and the “entry number” is still an index – with the area +treated as an array of characters.) Each entry is then read, placed at the +right place in the allocated space, and its pointers changed from entry +numbers back to real pointers. Note that no overall tree walk is done, and +no special orphan processing is required: Since each entry is read +individually, one can do all the processing for each entry when it is read, +and be sure no entries were missed.

    +

    As each region is read, the associated entry of region_scope_entry in +il_header is set to point to the primary scope entry for the region.

    +
    +
    +

    18.14. Precompiled Headers#

    +

    The precompiled headers (“PCH”) facility is intended to speed up +compilations that include relatively stable header files. It does this by +writing a precompiled header file that is a snapshot of the front end’s +internal state at a point in the compilation process immediately following +the initial sequence of #includes. On a recompilation of that file +(or another that begins with the same sequence of #includes), the front +end checks to see if all the header files are unchanged since the +precompiled header file was generated, and if so reads in the precompiled +header file to re-establish the front end state as it would be after +reading and compiling the header files. Reading in the PCH file takes less +time than compiling the header files from source, so there is a net savings +in compilation time.

    +

    Since the point of this feature is saving time, it is important that the +process of writing and reading the PCH files be as fast as possible. One +would like to see savings of 80% or the like (comparing the time to restore +a PCH file to the time to compile the original source code); an improvement +of only 30% or so would barely be worth the extra complexity. In addition, +one should not have to pay a large price to write out the precompiled +header file; it’s okay to slow compilations a little to get the benefits of +precompiled headers on later compilations, but if it takes too long to +write the file, the net gain is marginal or negative.

    +

    These speed issues suggest some basic design decisions:

    +
      +
    • +
      The information written to the precompiled header file must not require +a tree walk, because visiting every entry takes a lot of time. (It also +requires code or data structures that describe how to do the tree walk, +which exist for IL entries but not for the front-end-only data +structures.) Therefore, the information must be written out and read +back in as large chunks (rather than one entry at a time), and it must +not be necessary to remap all pointers in the information to new values +(i.e., it must be possible to bring the information back in at the same +address). These requirements also make it possible to exploit memory +mapping on systems that support it.
      +
      +
    • +
    • +
      Precompiled header files should contain snapshots of compilation +states, and not information about individual header files. While it’s +tempting to imagine writing precompiled header files for individual +header files, the work required in carving out the right information +and the description of dependencies so that the information can be +written to a file, and the work to bring it back in and merge it with +the front end state, will make substantial time savings unlikely.
      +
      +
    • +
    +

    An unfortunate consequence of this latter design decision is that users are +probably forced to change their source code to get any meaningful benefit +from the PCH facility. In average source code, the order of inclusion of +header files is essentially random. The net effect of the various orders of +inclusion is often the same, because of the way header files tend to be +written, but it is difficult to deduce that fact, and time-consuming. So we +have a dilemma: If we strive for maximum save/restore speed, we will find +few “natural” common sequences, and therefore generate many PCH files for +little benefit. On the other hand, if we try for maximum ability to reuse +precompiled headers from unaltered source files, we lose something +significant on save/restore speed.

    +

    We’ve chosen to go in the direction of maximum save/restore speed. We +believe that users are willing to make small changes in their source code +to get large reductions in compilation time, and that given a choice +between

    +
      +
    1. +
      You don’t have to change your source, and precompiled headers will +give you a 15% savings, or
      +
      +
    2. +
    3. +
      You may have to reorder your initial #includes or add the +equivalent of
      +
      +
      +

      #include <everything.h>

      +
      +
      +
      to the beginning of your source files, and precompiled headers will +give you a 50% savings,
      +
      +
    4. +
    +

    users will choose option 2. This, of course, is a matter of opinion, and +the percentages are fictitious. But for better or worse, this is what we +decided.

    +

    Because PCH processing is not likely to be helpful on arbitrary files, it +is disabled by default.

    +

    The code for precompiled header processing is mostly in pch.c, with +associated declarations in pch.h.

    +
    +

    18.14.1. Prefix and Header Stop Point#

    +

    The initial sequence of the source code of the primary source file that is +subject to the PCH optimization is referred to as the prefix. It consists +of the preprocessing directives preceding the header stop point. The header +stop point is determined as follows:

    +
      +
    • +
      Start at the first token of the primary source file that is not part of +a preprocessing directive (or the end of the file if there is no such +token).
      +
      +
    • +
    • +
      If there is a #pragma hdrstop preceding that token, back up to the +pragma position.
      +
      +
    • +
    • +
      If the position determined by the first two steps is inside a +preprocessing directive like an #if, back up to (just after) the +previous top-level preprocessing directive.
      +
      +
    • +
    +

    For example:

    +
    /* Comments. */
    +#define flag 1
    +#if flag
    +#include "abc.h"
    +#else
    +#include "def.h"
    +#endif
    +#include <stdio.h>
    +/* header-stop point. */
    +int i = 1;
    +#include "abc.h"
    +/* header-stop point. */
    +#if xyz
    +#include "def.h"
    +#pragma hdrstop
    +#endif
    +
    +
    +

    Note that, while determining the prefix, #ifs and the like are not +evaluated, so code that will be skipped in the actual compilation can +nevertheless serve as a header stop point. This is particularly important +with #pragma hdrstop.

    +

    At the beginning of compilation, if precompiled headers are enabled, the +prefix for the primary source file is accumulated. This is done by opening +the primary source file, reading the beginning of it in a special mode +while building an in-memory representation of the preprocessing directives +read, and closing the source file. This is a separate process from the +normal compilation of the file, and is a necessary first step whether the +front end ends up using an existing PCH file or creating a new one. See +build_prefix_information.

    +

    The prefix scan is done by setting building_pch_prefix and calling +get_token once. That causes the scanning of all of the preprocessing +directives preceding the first “real” token of the primary source file. The +preprocessing directives are not evaluated in the usual way; they are just +placed on the prefix event list. (In particular, #include directives +are just accumulated like the others; the included files are not read.) +Each such event contains an enumeration code for the preprocessing +directive and a null-terminated string giving the text of the directive +following the directive keyword.

    +

    After the initial prefix list is built up, the list is trimmed down by +discarding anything after a #pragma hdrstop and then, if the end is +inside an #if or the like, discarding preprocessing directives back to +the last top-level directive.

    +

    If the primary source for the compilation is coming from stdin instead +of a file, the prefix construction cannot be done (and therefore PCH files +cannot be created or used).

    +

    A list of the command-line options for the current compilation is also +built. It is also a linked list, and each entry on the list indicates one +command-line option. Options that have no effect on the state preserved by +PCH processing are not put on the list, but the rest (most of them) +are. The option code is represented by an enumeration, so the difference +between the single-letter form of the option and the keyword form is +erased, but in all other respects the list built up will have to match the +corresponding list for a PCH file exactly – same options, same order.

    +
    +
    +

    18.14.2. Using a PCH file#

    +

    Once the prefix has been created, the front end will look to see if any of +the existing PCH files can be used to avoid some part of the compilation +for the current file. A host-dependent routine is used to fetch the names +of all PCH files in the appropriate directory (the directory can be +specified via the --pch_dir command-line option). Each file is checked +to make sure it is a regular file (not, say, a directory), that it has the +right header string identifying it as a PCH file, that the compiler version +number and generation date/time are the same, and that the flag indicating +that the file is completely written has been set. If any of those checks +fails, the file is closed and not considered further; in effect, it’s +considered not to be a PCH file.

    +

    The next round of checks seeks to determine whether the PCH file is +applicable to the current compilation. The front end checks that the +current directory and the one recorded in the PCH file are the same; that +the command-line event lists are the same; and that the preprocessing +directive event lists are the same (or the current file’s prefix list is +longer than the prefix list in the PCH file). If those are okay, the front +end checks that the header files included in the PCH file have not changed +since the PCH file was built (this is done by checking the timestamps of +the files against the timestamps recorded in the PCH file). If the +timestamps indicate that the PCH file is out of date, it is deleted.

    +

    A PCH file that makes it this far can be used, but it might not be the best +choice: There might be another PCH file that also matches but includes more +of the prefix preprocessing directives. Therefore, if the match is not +perfect, other PCH files are considered and the best-matching PCH file is +chosen. Each PCH file is closed after it is considered and must be reopened +later if selected as the best file.

    +

    If the user has used the --use_pch command-line option, the indicated +PCH file is chosen directly. No other PCH files are considered, and the +applicability test is not done (at this point; see below).

    +

    Once the best-matching PCH file is selected for a file called (say) +x.C, if the PCH file selected is not x.pch, and there exists an +x.pch, x.pch is deleted. This is a simple way of getting rid of PCH +files that are no longer needed.

    +

    Once a PCH file is selected, the front end state is restored from the +file. The PCH file is opened again and the prefix check is done again to +make sure the file has not changed since the first check. For a PCH file +specified via a --use_pch command-line option, this is the only +applicability test done (and if the file fails, a warning is issued and the +compilation continues without using the PCH file); for other cases, this is +a repetition of the applicability test already done. Next, the global +variables registered via register_pch_saved_variables are read and +restored. Finally, the contents of the various memory regions (IL and front +end) are restored. These are restored at the original addresses, so it is +not necessary to walk through the restored data to adjust pointers. (See +the section on memory management issues below for more information on this +aspect.)

    +

    The restoration process occurs after most initialization of the front end, +so some variables are initialized then overwritten by the restoration from +the PCH file.

    +

    Once the front end state has been restored from the PCH file, the lexical +routines are reset and the primary source file is opened again. The prefix +is skipped by doing a get_token in a special lexical mode. This is very +similar to the scan done to accumulate the prefix, in that initial +preprocessing directives are passed over uninterpreted. However, once the +preprocessing directive that marks the end of the matched part of the +prefix is processed, normal processing of preprocessing directives is +re-enabled. Shortly thereafter, the initial get_token finishes, and +normal compilation continues from that point (we know we are between +top-level declarations, so we can continue simply by entering the main +compilation-unit loop).

    +

    The PCH restoration process restores the front end state after compilation +of the precompiled headers, but it doesn’t duplicate the output that would +have been done on auxiliary files during the skipped part of the +compilation. Diagnostics that would have been written, and output lines on +the raw listing and cross-reference output files that would have been +generated, are not put out when a PCH file is used. If the front end is +configured to use an IL file, that file also is not generated as this +point. However, the IL file does get generated by a catch-up process done +after the point where a PCH file is generated or a decision is made not to +generate one; see below.

    +

    Because the source sequence numbers of the original compilation may not +exactly match the sequence numbers in the current compilation (e.g., +because of whitespace differences), the source file mapping information in +the IL in the PCH file is restored as, in effect, the first include file on +the list under the primary source file of the current compilation.

    +
    +
    +

    18.14.3. Creating a PCH File#

    +

    After the front end has read in a PCH file or chosen not to use one, the +“normal” compilation process begins. When the compilation reaches the +header stop point, we have the option of creating a PCH file that +encapsulates the front end’s state at that point for later restoration.

    +

    Note that it is possible to both use and create a PCH file in the same +compilation, because the best-matching PCH file might contain only the head +of the full prefix. In that case, the internal state is restored from the +PCH file, then the rest of the prefix is compiled in the normal way, and at +the header stop point the compiled form of the full prefix is saved to a +new PCH file.

    +

    The position of the header stop point was determined by the prefix scan at +the very beginning of the compilation. Its position is defined in terms of +a preprocessing directive, more specifically as the end of the processing +for that directive. Compilation starts up or continues in a mostly normal +way, with the header stop position set as a sort of breakpoint. When the +end of the indicated preprocessing directive is reached, the front end will +check to see whether a PCH file can be generated.

    +

    On the way to the header stop point, some things may happen to preclude +generation of a PCH file:

    +
      +
    • +
      A reference to one of the macros __DATE__ or __TIME__. Since +these would change from compilation to compilation, there is no point +to saving the state of a compilation that uses them.
      +
      +
    • +
    • +
      A #pragma no_pch. This is an explicit request not to generate a PCH +file.
      +
      +
    • +
    • +
      A #line directive. (Such directives could probably be allowed but +are not accommodated at present.)
      +
      +
    • +
    +

    When the header stop point is reached, generate_precompiled_header is +called. It starts by making several checks that the current position is +acceptable:

    +
      +
    • +
      The current position is not inside a declaration, i.e., it is between +two file-scope declarations, or before the first such declaration, or +after the last. next_token_is_top_level_decl_start, maintained by +the declaration-scanning routines, gives this information.
      +
      +
    • +
    • +
      The preprocessing #if stack is empty, i.e., the current position is +not inside a conditionally-compiled section.
      +
      +
    • +
    • +
      There have been no errors.
      +
      +
    • +
    • +
      The global variable cannot_create_pch_file is not set. It is set +for things that preclude generation of a PCH file (e.g., referencing +__DATE__).
      +
      +
    • +
    +

    If the current position is acceptable, a precompiled header file can be +written, and the front end will write out a file xxx.pch, where “xxx” +is the base file name of the file being compiled. The user can specify a +different file name via the --create_pch command-line option. If a file +with the chosen name already exists, it is deleted. Precompiled header +files are written in the current directory by default, but another +directory can be specified via the --pch_dir command-line option.

    +

    The following information is written to the PCH file, in the order given:

    +
      +
    • +
      An string that identifies the file as a PCH file, and gives the front +end version number and generation date/time.
      +
      +
    • +
    • +
      The current directory name (this may affect the include file search +order, etc.).
      +
      +
    • +
    • +
      The list of command-line events, i.e., all the command-line options +that could have an effect on PCH files.
      +
      +
    • +
    • +
      The list of preprocessing directive events, i.e., the sequence of +preprocessing directives whose compiled form is encapsulated in the PCH +file.
      +
      +
    • +
    • +
      Timestamps for all the header files referenced by the compilation (this +includes all files, not just those included directly from the primary +source file).
      +
      +
    • +
    • +
      The values of all front end variables registered with +register_pch_saved_variables.
      +
      +
    • +
    • +
      The contents of all memory regions, i.e., the front end memory region +and all IL memory regions.
      +
      +
    • +
    • +
      Once the rest of the information has been written, the front end goes +back to the header and writes a flag indicating that the PCH file is +complete. This flag prevents other compilations from using a PCH file +that is not yet completely written.
      +
      +
    • +
    +

    After writing out the PCH file, the front end continues with +compilation. Because the header-stop point has been passed, no further +precompiled-header checking or processing is done in the rest of the +compilation.

    +

    If an IL file is being generated, function scope memory regions that are +completed before the header stop point are held in memory and neither +written to the IL file nor freed. Once the header stop point has been +reached, and a PCH file has been written or a decision made not to write +one, those memory regions are written to the IL file and freed.

    +
    +
    +

    18.14.4. Memory Management Issues#

    +

    As was mentioned earlier, one of the prerequisites for fast PCH processing +is the ability to bring memory regions back into memory at the same +addresses they had when written out. Clearly, that requires that (a) +nothing else happens to have been allocated at the desired addresses, and +(b) there is some way to request allocation or assignment of those +addresses so that no later allocation uses them.

    +

    The front end provides two schemes that accomplish this goal. The first and +better scheme requires memory mapping support from the underlying operating +system (UNIX and Windows NT versions are provided). A fixed set of +addresses is chosen for all memory regions (the exact addresses are either +left to the discretion of the operating system or chosen in the +configuration of the front end; see +USE_FIXED_ADDRESS_FOR_MMAP). Initially, these memory addresses are +mapped onto a temporary file. When a PCH file is created, the memory is +written to the PCH file (using normal file I/O). On restoration of a PCH +file, the default mapping to the temporary file is released, and the +reserved memory addresses are mapped onto the PCH file being restored. This +brings the saved information into the front end’s address space without any +immediate I/O. (In the actual implementation, the memory addresses are +tentatively mapped once to verify that the mapping can be done, and then, +once it is known that all the mappings will be successful, they are done +again with the official mappings.) All dynamically allocated memory that is +not part of a memory region is just allocated in the normal way through +malloc, since it need not be at any particular addresses. This means, +in effect, that there are two completely separate pools of memory – memory +region allocations are done at the fixed mappable addresses, and everything +else is done more casually in the traditional way.

    +

    The other implementation does not require memory mapping, but it is +slightly less friendly to users. Very early in the execution of the front +end a large amount of memory is preallocated in large blocks and saved off +to the side for use exclusively for memory regions. This is done early so +that the allocated addresses are reproducible (i.e., one can get the same +addresses on all compilations). If the allocations were done later, their +addresses would be affected by minor variations in the amount of memory +used during the command-line processing, and perhaps by memory allocated by +runtime routines of the host C compiler (e.g., printf formatting). As +the compilation proceeds, requests for memory for memory region blocks are +satisfied by taking blocks from this preallocated list. All other +allocations (for things not in memory regions) are done directly through +malloc. When a PCH file is created, the memory addresses of blocks are +written to the PCH file along with the block contents. Also written is an +array of the preallocated memory block addresses used, serving as a sort of +allocation history (this array is written to the file also in the +memory-mapped mode). Once the header stop point is passed, and either a PCH +file was written or a decision was made not to write one, the remaining +preallocated memory is freed, and subsequent allocation for all purposes is +done directly through malloc.

    +

    If the preallocated space is too small to hold the memory regions created +up to the header stop point, the precompiled header cannot be created +(since the remaining required space cannot be allocated at predictable +addresses). A warning is issued, telling the programmer that the +--pch_mem option can be used (on a subsequent invocation of the front +end) to request a larger preallocation to avoid the problem. The +compilation continues normally – the PCH file cannot be created, but the +compilation can be completed regardless.

    +

    Since the preallocated blocks have a fixed (though large) size, any +requirement to allocate a single entity larger than that fixed size cannot +be satisfied from the preallocated pool, and therefore precludes generation +of a PCH file. This could happen, for example, if a user program contains a +single literal string containing 200,000 characters. Again, the compilation +continues without difficulty, but a warning is issued that a PCH file could +not be generated.

    +

    When a PCH file is read back in the non-memory-mapped mode, the allocation +history information history is read in from the PCH file and used to check that +the preallocated blocks are indeed at the same addresses (on some systems, in +spite of the care taken to allocate the blocks early, the addresses still +change; for example, under MS-DOS, the addresses can be affected by placing a +new TSR program in memory). If the addresses are not right, it is still +possible to give up on using the PCH file and continue with normal compilation. +If the history information matches, the memory regions are read in: The address +for each block is read from the file, the preallocated block at the right +address is assigned, and the memory region contents are read from the PCH file +into the proper addresses.

    +

    It should be noted that if a given environment provides a (nonstandard) way +of allocating memory from a pool distinct from the normal malloc +allocation pool, the non-memory-mapped approach can be made to work without +preallocation and without the --pch_mem command-line option.

    +

    When multiple source files are specified in one invocation of the front +end, the preallocation scheme breaks down: The first file can be processed +okay, but on subsequent files the preallocated memory has been used and +reclaimed and is no longer in quite the right predictable state. This can +probably be solved in some way, but the current implementation takes the +easy way out and disallows PCH file use on compilations where more than one +source file is specified on the command line.

    +
    +
    +
    +

    18.15. Predefined Macro Definition File#

    +

    Macros may be predefined either by explicit calls of +enter_predef_macro, and/or through use of a predefined macro definition +file. Whether or not the front end reads a predefined macro definition file +is controlled by the DEFAULT_USE_PREDEFINED_MACRO_FILE macro. The file +EDG_BASE/EDG_AUXILIARY_INFO_DIR_NAME/PREDEFINED_MACRO_FILE_NAME is read +to provide the macro definitions. The EDG_BASE directory can be +specified by an environment variable (EDG_BASE), build-time macro +(DEFAULT_EDG_BASE), or command-line option +(--edg_base_dir). EDG_AUXILIARY_INFO_DIR_NAME and +PREDEFINED_MACRO_FILE_NAME are configuration macros with default values +of “lib” and “predefined_macros.txt”. If +EDG_AUXILIARY_INFO_DIR_NAME is null, the EDG_BASE directory is used +directly. The format of the entries in the file is:

    +
    mode,!mode,mode   cannot_redefine   macro_name   macro_value
    +
    +
    +
      +
    • +
      mode is a label from the predefined macro modes table. The macro is +defined if the mode is set, or if the mode is not set when !mode is +used. The macro is defined if any of the mode tests is TRUE. The set of +mode values is specified in host_envir.h.
      +
      +
    • +
    • +
      cannot_redefine indicates whether the predefined macro may later be +redefined. The value must be “yes” or “no”.
      +
      +
    • +
    • +
      macro_name is the name of the macro to be defined.
      +
      +
    • +
    • +
      macro_value is the value to which the macro should be defined. All +of the characters until the end of the line are used as the macro +value.
      +
      +
    • +
    +

    For example:

    +
    gcc no  __HAVE_BUILTIN_SETJMP__ 1
    +gpp no  __CHAR_BIT__ 8
    +gnu no  __GNUC_PATCHLEVEL__ 0
    +gnu no  __WINT_TYPE__ unsigned int
    +gnu,microsoft __IS_GNU_OR_MICROSOFT_MODE 1
    +
    +
    +

    A script (make_predefined_macro_file) is provided that automatically +generates the predefined_macros.txt file for a given version of gcc/g++ +or clang. It does this by invoking gcc and g++ or clang and capturing the +predefined macro information.

    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/build/index.html b/doc/build/index.html new file mode 100644 index 0000000..801303d --- /dev/null +++ b/doc/build/index.html @@ -0,0 +1,1439 @@ + + + + + 1. Configuring and Building the C++ Front End - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    1. Configuring and Building the C++ Front End#

    +

    This chapter is an introduction to configuring and building the front end and +the various tools that come with it. Bringing up the front end on a new +platform typically can be done in a few hours, and if the platform is close +enough to a system for which sample configurations are available (e.g., Linux, +Windows, etc.) that initial process can be reduced to a matter of minutes.

    +

    The front end can be configured for a variety of uses. For example, it could +be part of a compiler with a custom code generator, or a compiler with a +portable C-generating back end (the latter is provided). Alternatively, it +could be part of a source analysis tool (without a code generator) or of a +source transformation/translation tool (using the supplied C/C++-generating +back end). Some of the tools supplied with the front end will not be needed +for some of these applications. For example, a source analysis tool is +unlikely to need the supplied prelinker tool to perform automatic +instantiations. The details of the build process are therefore likely going to +depend on the application. However, the overall structure of the source code +is simple enough that customizing the build process should be straightforward.

    +

    The source code implementing the front end and associated tools is written in +C++11 (i.e., ISO/IEC 14882:2011) and can be compiled using relatively current +C++ compilers. The front end has been compiled with g++ 4.8.1, clang 3.3, and +Microsoft Visual Studio 2015 (build 19.00.24215.1). The front end does not +explicitly throw or catch exceptions and does not use C++ features that would +requite runtime type information (RTTI), so those features can be disabled when +compiling the front end (for compilers that support that). (The sample +run-time support library is written in C++ and (if needed) is normally compiled +using the front end itself. When building on Microsoft Windows, a component is +also available to read metadata in C++/CLI mode: This is written in C++ for the +Microsoft C++ compiler.)

    +
    +

    1.1. Directories and Files in a Release#

    +

    After unpacking a release, its top-level directory should contain the following +directories and files:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    Makefile
    +
    +
    +
    In a Unix-like environment (including Windows-hosted environments like +Cygwin or MinGW), the make utility can be used to build the front +end and its supporting tools and components. This top-level +Makefile runs the make tool in the various subdirectories as +needed. It is geared primarily toward building a compiler using the +C-generating back end along with the sample run-time support library. +A make process using this top-level Makefile may therefore +terminate with errors for other situations; in that case, the +Makefiles in the appropriate subdirectories (especially +misc/ and src/) are still likely to be useful.
    +
    +
    +
    src/
    +
    +
    +
    The directory containing the source files of the C++ front end and its +optional components (such as the C- and C++-generating back ends). +This directory contains a subdirectory disp/ used to build the +stand-alone IL display utility. In addition to source code, the +src/ directory also holds the Changes file, which describes +the various changes made to the front end in the current and previous +releases. Note that most of the source files have the .c suffix +that would normally indicate a C source file. Starting with the 6.0 +release, these files contain C++ source code and must be compiled +using a C++ compiler (with the C++11 dialect). The original filenames +have been maintained to make patching files easier. If desired, +symbolic links can be added to accommodate build environments as +necessary.
    +
    +
    +
    bin/
    +
    +
    +
    Initially, this directory contains a script eccp that can be used +to run the front end much like typical C++ compilers in Unix-like +environments (such as CC and g++). See +“The eccp script” for details. Once the front end is built (in +the src/ directory), it can be moved here for invocation by +eccp (this is done automatically if the top-level Makefile is +used).
    +
    +
    +
    sample_edg_eccp_config/
    +
    +
    +
    The eccp script can be configured in various ways. This directory +contains sample configuration files for some popular Unix-like +operating systems (Linux, MacOS X, and Solaris). It also includes a +script make_g++_incl_paths (to be run from the lib/ directory) +to establish the location of g++‘s header files (in cases where +eccp should rely on a native g++ installation for system and +standard header files).
    +
    +
    +
    include/
    +
    +
    +
    This directory contains prototype implementations for a few standard +C++ header files that are closely tied to the compiler’s internals. +(For example, the contents of the <typeinfo> header must match the +compiler’s understanding of the std::type_info type.)
    +
    +
    +
    lib_src/
    +
    +
    +
    This directory contains C++ source code implementing a minimal C++ +run-time support library (in support of C++ features like exception +handling, the dynamic_cast operator, and operator new). The +library also includes support for certain extensions to the C89 +language (like operations on complex floating-point types and support +for variable-length arrays). All of this code is primarily meant for +demonstration purposes, and is probably not suitable for end-user +products: It is very portable, but not very efficient. It is usually +not needed for non-compiler applications such as source analysis or +source-to-source translation. This directory also contains a +Changes file describing the history of the run-time support +library.
    +
    +
    +
    lib/
    +
    +
    +
    Initially, this directory only contains a file +predefined_macros.txt. This file is read by the front end to +predefine certain macros. It is typically used to define macros that +are defined by compilers being emulated (see +make_predef_macro_table and make_win_predef_macro_table.c for +utilities that automatically generate a set of predefined macros for +GNU and Microsoft compilers, respectively). Once the run-time support +library is built (in the lib_src/ directory), it can be moved here +so the eccp script can find it (this is done automatically if the +top-level Makefile is used). Note that this directory is only +used when an unnamed “legacy” target configuration is specified – see +lib_target/ below for cases where a named target +configuration is used.
    +
    +
    +
    lib_target/
    +
    +
    +
    Target-specific version of the lib/ directory described above +used when the “--target target” command-line option is +specified. This directory can have the same +predefined_macros.txt and libC.a files as lib/, or can +be different as required by the specific target. If a +target-specific version of libC.a is required, it must be +built manually (see lib_src/Makefile).
    +
    +
    +
    misc/
    +
    +

    This directory contains sources for four utility programs (and a +Makefile to build them) to build and configure the front end:

    +
      +
    • make_predef_macro_table: A script to generate a predefined macros +file (like lib/predefined_macros.txt) to match a given version of +gcc/g++.

    • +
    • make_win_predef_macro_table.c: A program to generate a +predefined macros file (like lib/predefined_macros.txt) to match +a given version of Microsoft Visual Studio. Note that this program +is not built by the Makefile (and must be built manually if +required).

    • +
    • mk_errinfo.c: A program to translate the files describing the +diagnostics emitted by the front end to plain C++ code.

    • +
    • dettarg.c: A utility to determine basic configuration settings for +a target platform (e.g., the size and alignment of various integer +types). See “The dettarg Utility” below.

    • +
    +
    +
    util/
    +
    +

    This directory contains sources for three utility programs (and a +Makefile to build them) that can be used in conjunction with the +front end (e.g., by the eccp script):

    +
      +
    • edg_prelink.c: A program that implements automatic template +instantiation by re-running the front end to generate missing +instantiations.

    • +
    • edg_decode.c: A name demangler (which can, for example, be used on +the output of a linker to make that output more readable). It is +an interface for the actual demangling logic, which is contained +in decode.c to allow its use in other programs as well.

    • +
    • edg_munch.c: A utility that generates a C program that will call +all required start-up initialization routines. This is needed only +if your linker does not provide a way to invoke code automatically at +program start-up time.

    • +
    +
    +
    doc/
    +
    +
    +
    This directory contains a PDF version of this document (plm.pdf).
    +
    +
    +
    README
    +
    +
    +
    A plain text file summarizing some of the information in this chapter.
    +
    +
    +
    +
    +
    +

    1.2. Configuring the Front End#

    +

    A large number of behaviors of the front end can be configured by appropriately +defining various configuration macros. These macros can affect which +components of the front end are enabled, which dialects are supported, what +host and target platform characteristics are assumed, and so forth. See +lang_feat.h, host_envir.h, targ_def.h, and target.h below for information about where all the macros are +documented.

    +

    Beginning with version 4.10.1 of the front end, a facility to provide for +run-time selection of a target configuration (through the use of the +--target command-line option) is provided. To support this run-time +target-configuration feature, a number of the configuration macros have +been designated as “target-specific”. See +Target-Specific Configuration for more information.

    +
    +

    1.2.1. The defines.h File#

    +

    It is highly recommended that the front end be configured by defining the +appropriate macros in the src/defines.h file. Occasionally, it may be +expedient to set the macros directly through src/Makefile or a similar +build-system mechanism (e.g., to enable debugging facilities), but modifying +other front end sources to set the configuration macros is not a recommended +option.

    +

    Sample configuration files are provided in the src/ directory for Linux, +MacOS X, Solaris, and Windows (defines.h.linux, defines.h.macosx, +defines.h.solaris, and defines.h.win32, respectively). These are +recommended starting points when building the front end on these platforms: For +example, to build the front end on MacOS X, one can start by copying +src/defines.h.macosx to src/defines.h.

    +

    A partial configuration file src/defines.h.proto is also provided: It +contains the macros needed to enable the modern IA-64 ABI (also called the +Itanium ABI), but it must be complemented by additional target characteristics +(which can be obtained by running the dettarg utility described next).

    +
    +
    +

    1.2.2. The dettarg Utility#

    +

    File misc/dettarg.c is a simple C++ program that can be compiled, linked, +and run on a system for which the compiler is targeted to determine some basic +characteristics (like endianness, size and alignment of fundamental types, and +so forth) of that target platform. The output produced by dettarg is in a +form suitable for addition to the src/defines.h file.

    +
    +
    +

    1.2.3. lang_feat.h, host_envir.h, targ_def.h, and target.h#

    +

    A typical src/defines.h file will not explicitly set all the configuration +macros available in the front end. Instead, most macros are just left to their +default values. These defaults are specified in four header files. Perhaps +more importantly, these header files are also the place where all the +configuration macros are documented (in comments preceding the directives +determining the default values). The header files are as follows:

    +
    + + + + + + + + + + + + +
    +
    src/lang_feat.h
    +
    +
    +
    Configuration macros controlling language features. Some macros +control a single language feature detail, whereas others control whole +dialects.
    +
    +
    +
    src/host_envir.h
    +
    +
    +
    Configuration macros that determine characteristics of the host +platform (the platform on which the front end runs).
    +
    +
    +
    src/targ_def.h
    +
    src/target.h
    +
    +
    +
    Configuration macros describing characteristics of the target platform +(the platform for which code must be generated). Many of these macros +have names that begin with TARG_. Characteristics that are +entirely fixed at the time the front end is built are normally +documented in targ_def.h, whereas target.h describes target +characteristics that can be overridden for every invocation of the +front end.
    +
    +
    +
    +

    These descriptions are generally correct, but occasionally a configuration +macro may need to be placed in a header that doesn’t quite match that macro’s +function. For example, targ_def.h contains some macros that would more +naturally belong to lang_feat.h, but the default value of the macro depends +on a target platform characteristic.

    +

    Note that these files should not be modified to set configuration options. +Instead, the appropriate macros should be defined in src/defines.h or +perhaps in a Makefile or similar build system tool.

    +
    +
    +

    1.2.4. basics.h and Build Environment Configuration#

    +

    The front end is written in portable C++11 (except for one file in the +Microsoft dialect if the capability of reading Microsoft metadata for +C++/CLI is needed). The basics.h header adds abstractions to allow +most of the remainder of the front end source code to be written without +concern for variations in system headers. The build environment type can +often be determined by the preprocessor tests in basics.h, but when +that is not the case, one should define one of the following build +environment macros (on the command-line or in src/defines.h): +__ANSIC__ (for ANSI C; also used for Borland and Microsoft C under +MS-DOS and Windows), __SYSV__ (for System V), __BSD__ (for Berkeley +4.n), __VMS__ (for VAX/VMS C; this will cause __SYSV__ to be +defined, but the __VMS__ flag will control some minor variations from +System V).

    +

    Some ANSI library functions do not exist in all system libraries. This problem +is handled by remapping such function calls (via macros) to functions that do +exist. For example, traditional Berkeley UNIX does not have memcpy, but +does have bcopy; the front end source is written using calls to memcpy, +but when it is compiled with the __BSD__ flag set, a macro memcpy +transforms those calls into calls to bcopy. Another function of the build +environment macros is controlling inclusion of appropriate header files. Even +when identical functions exist on different host systems, they are sometimes +defined by different header files (e.g., Berkeley systems use <strings.h> +instead of the ANSI/System V <string.h>). basics.h includes the +appropriate definitions for the most common functions (standard I/O, string and +block operations, and character typing); any other required headers are +included only in those source files that need them, with appropriate +conditional compilation surrounding the #includes.

    +

    Very occasionally, the macro definitions in basics.h must be modified +directly (i.e., by editing basics.h). Specifically, when __ANSIC__ is +not set, some #defines in basics.h must establish values for about a +dozen of the most useful values (specifically, CHAR_BIT, CHAR_MIN, +CHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, +LONG_MIN, and ULONG_MAX). These should be set to proper values for the +host. sizeof_t should also be defined as the integral type to be used for +sizes of things. Usually this is the same as size_t, but it might be +different if size_t is too small (e.g., 16 bits). These values cannot be +set in defines.h or on the compilation command line.

    +

    Finally, basics.h also determines the default values of some macros that +control the presence of code aiding in the development of the front end (e.g., +DEBUG for debugging aids and CHECKING for internal consistency checks).

    +

    The front end requires a minimal C++ standard library. Prior to release 6.0, +the front end was written in C and used various host C standard library +functions (e.g., for file I/O). When switching to C++, it was decided not to +use the additional portions of the C++ standard library that became available +(e.g., std::string) as this would add a burden to our customers and would +require testing against many versions of the C++ standard library. Instead, a +small subset of library-like utility functions was developed for the front end +(in util.h). As a result, the portion of a C++ standard library that the +front end requires is about the same as that provided by a C standard library.

    +
    +
    +

    1.2.5. Commonly-used Configuration Macros#

    +

    The following subsections describe a selection of macros that commonly appear +in src/defines.h. This list is not meant to be exhaustive. Many (but not +all) configuration macros are used to initialize global variables with a +similar name, and it is the value of the variable that controls a particular +behavior. For example, GCC_IS_GENERATED_CODE_TARGET (described below) +initializes the global variable gcc_is_generated_code_target. This allows +particular behaviors to be controlled at run time (via the command line or via +custom code additions).

    +

    Note that none of the configuration macros described below are +“target-specific” (so, for example, there can’t be one target configuration +where DO_IL_LOWERING is TRUE and another where it is FALSE).

    +
    +

    1.2.5.1. Optional Components#

    +
    + + + + + + + + + + + + + + + + + + +
    +
    BACK_END_SHOULD_BE_CALLED
    +
    +
    +
    TRUE if a back end should be called (the call is to a function +back_end).
    +
    +
    +
    DO_IL_LOWERING
    +
    +
    +
    TRUE if IL lowering (rewriting C++-specific constructs in the +intermediate language in C form) should be done.
    +
    +
    +
    BACK_END_IS_C_GEN_BE
    +
    +
    +
    TRUE if the C-generating back end should be used. If FALSE, some +other back end must be supplied or BACK_END_SHOULD_BE_CALLED must +be FALSE. The C-generating back end takes the lowered IL for a +translation unit and generates a C source file suitable for +compilation to binary code by a native C compiler.
    +
    +
    +
    BACK_END_IS_CP_GEN_BE
    +
    +
    +
    TRUE if the C++/C-generating back end should be used. If FALSE, some +other back end must be supplied or BACK_END_SHOULD_BE_CALLED must +be FALSE. The C++/C-generating back end is intended for +source-to-source transformation applications. It takes the unlowered +IL for a translation unit and generates a source file that is similar +to the original C or C++ input.
    +
    +
    +
    MINIMAL_INLINING
    +
    +
    +
    TRUE if minimal inlining of function calls should be done during IL +lowering. This option is intended mostly for use with the +C-generating back end, and is limited to inlining calls to very simple +functions that are defined inline in the source.
    +
    +
    +
    +
    +
    +

    1.2.5.2. Support for Source Language Dialects#

    +
    + + + + + + + + + + + + +
    +
    GNU_EXTENSIONS_ALLOWED
    +
    DEFAULT_GNU_COMPATIBILITY
    +

    +
    +
    +
    Control whether compatibility with GNU’s gcc and g++ compilers +should be enabled, either by default or only when the --gcc or +--g++ command-line options are specified.
    +
    +
    +
    MICROSOFT_EXTENSIONS_ALLOWED
    +
    DEFAULT_MICROSOFT_COMPATIBILITY
    +

    +
    +
    +
    Control whether compatibility with Microsoft’s C and C++ compilers +should be enabled, either by default or only when the --microsoft +command-line option is specified.
    +
    +
    +
    SUN_EXTENSIONS_ALLOWED
    +
    DEFAULT_SUN_COMPATIBILITY
    +

    +
    +
    +
    Control whether compatibility with Sun CC should be enabled, either by +default or only when the --sun command-line option is specified.
    +
    +
    +
    +

    Setting an …_ALLOWED macro to TRUE makes the corresponding +DEFAULT_… macro TRUE by default. If the front end is configured to +support multiple dialects, the DEFAULT_… macros must be set explicitly +to avoid selecting more than one dialect as the default.

    +
    + + + + + + + + + +
    +
    CPPCLI_ENABLING_POSSIBLE
    +

    +
    +
    +
    Control whether a mode compatible with Microsoft’s C++/CLI extensions +should be available through the command-line option --cppcli. +Setting this option to TRUE requires that +MICROSOFT_EXTENSIONS_ALLOWED also be TRUE.
    +
    +
    +
    DEFAULT_CPPCLI_ENABLED
    +

    +
    +
    +
    TRUE if C++/CLI extensions should be enabled by default when Microsoft +extensions are enabled.
    +
    +
    +
    +
    +
    +

    1.2.5.3. IL Features#

    +
    + + + + + + + + + + + + + + + +
    +
    EXTRA_SOURCE_POSITIONS_IN_IL
    +

    +
    +
    +
    TRUE if certain additional IL entries, besides those that already have +a_source_correspondence fields, should contain source position +information. For example, expression nodes will record the starting +and ending position of the corresponding expression, as well as the +position of that expression’s top-level operator. Note that this can +increase the size of the IL substantially.
    +
    +
    +
    EXPR_RANGE_MODIFIERS_IN_IL
    +

    +
    +
    +
    TRUE to extend the tracking of source ranges for expressions by +including position information for operators that generally do not +appear in the IL, such as *, &, and ().
    +
    +
    +
    RECORD_MACROS_IN_IL
    +
    FULLY_RESOLVED_MACRO_POSITIONS
    +
    MACRO_INVOCATION_TREE_IN_IL
    +

    +
    +
    +
    Indicate whether extra information should be recorded in the IL to +track macros and their expansions. Setting either of the latter two +configuration macros to TRUE can increase the size of the IL +substantially.
    +
    +
    +
    PROTOTYPE_INSTANTIATIONS_IN_IL
    +

    +
    +
    +
    TRUE if prototype template instantiations (i.e., the parsed generic +form of templates) should be recorded in the main IL tree.
    +
    +
    +
    +
    +
    +

    1.2.5.4. Target Platform Options#

    +

    Note that although these configuration macros deal with issues related to the +target, they are not considered “target-specific” (because these values cannot +differ between target configurations).

    +
    + + + + + + + + + + + + + + + +
    +
    IA64_ABI
    +
    +
    +
    Controls whether the IA-64 ABI standard is used for code generation +and object layout. This is a “modern” C++ object layout (unlike the +cfront layout), and is a good starting point even on architectures +other than IA-64 (Itanium). This ABI is used by many versions of g++ +(3.2 and later). For a complete specification, see +www.codesourcery.com/cxx-abi. See also other macro names +beginning with IA64_ABI, some of which enable compatibility with +the ARM EABI variant of the IA64_ABI. If IA64_ABI is set to +FALSE (or 0), a cfront-like ABI is used instead.
    +
    +
    +
    DEFAULT_GNU_ABI_VERSION
    +
    DEFAULT_EMULATE_GNU_ABI_BUGS
    +

    +
    +
    +
    Control the emulation of the GNU variant of the IA-64 ABI.
    +
    +
    +
    GCC_IS_GENERATED_CODE_TARGET
    +
    GNU_TARGET_VERSION_NUMBER
    +
    MSVC_IS_GENERATED_CODE_TARGET
    +
    MSVC_TARGET_VERSION_NUMBER
    +
    SUN_IS_GENERATED_CODE_TARGET
    +
    SUN_TARGET_VERSION_NUMBER
    +

    +
    +
    +
    Control whether the code generated by the C- or C++-generating back +end should target a specific GNU, Microsoft, or Sun compiler. This is +information is used to avoid limitations of those compilers and to +exploit extensions provided by those compilers.
    +
    +
    +
    CP_GEN_BE_TARGET_MATCHES_SOURCE_DIALECT
    +

    +
    +
    +
    TRUE if the C++-generating back end should generate code that matches +the dialect selected for the front end. (E.g., if the front end is +set to parse GNU code, the back end can generate GNU __attribute +constructs, whereas if the front end is set to accept Microsoft +extensions, the back end might generate __declspec specifiers.)
    +
    +
    +
    +
    +
    +

    1.2.5.5. Front End Behaviors#

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    MAKE_FRONT_END_CALLABLE
    +

    +
    +
    +
    TRUE if, instead of having its own main program, the front end is to +be linked as part of some other main program. When this flag is set, +the EDG_MAIN macro provides the name of the main entry point into +the front end.The front end can then be called repeatedly by the same +process (each call reinitializes the front end’s internal state).
    +
    +
    +
    COMPILE_MULTIPLE_SOURCE_FILES
    +

    +
    +
    +
    Indicates that the front end should be capable of compiling a list of +source files in a single invocation.
    +
    +
    +
    IL_SHOULD_BE_WRITTEN_TO_FILE
    +

    +
    +
    +
    TRUE if the intermediate language should be written to a file; FALSE +if the intermediate language is passed in memory to the back end +(assuming BACK_END_SHOULD_BE_CALLED is TRUE).
    +
    +
    +
    USING_DRIVER
    +
    +
    +
    Indicates that the front end is being run from a driver program. +Setting this flag suppresses termination messages (like +“Compilation terminated.”) written to the error output file +because it is expected that the driver will write those.
    +
    +
    +
    MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED
    +

    +
    +
    +
    TRUE if multibyte character sequences (e.g., like Unicode UTF-8 or +those in the Japanese SJIS encoding) are supported in comments, +string literals, identifiers, and character constants.
    +
    +
    +
    USE_OWN_SJIS_MULTIBYTE_CHAR_PROCESSING
    +

    +
    +
    +
    TRUE if, instead of the routines in the standard C library (e.g., +mblen), custom routines in host_envir.c should be used to deal +with Japanese SJIS multibyte characters in source code.
    +
    +
    +
    LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED
    +

    +
    +
    +
    Indicates the locale to be established by a call to setlocale to +get the desired processing of multibyte characters from the C library +while reading the source code.
    +
    +
    +
    UNICODE_SOURCE_SUPPORTED
    +

    +
    +
    +
    TRUE if the multibyte character set to be supported is Unicode encoded +as UTF-8. UTF-16 is also accepted, and is translated to UTF-8 +immediately on input.
    +
    +
    +
    +
    +
    +

    1.2.5.6. Development Aids#

    +
    + + + + + + + + + + + + + + + +
    +
    DEBUG
    +
    +
    +
    Enables additional code in the front end to simplify debugging. This +includes flow/event tracing options, routines that can be called from +a debugger to examine the IL, and an option to output the settings of +the configuration macros.
    +
    +
    +
    CHECKING
    +
    +
    +
    Enables inexpensive internal consistency checking. Recommended even +in production builds.
    +
    +
    +
    EXPENSIVE_CHECKING
    +
    +
    +
    Enables more expensive internal consistency checking. (Not generally +recommended for production builds.)
    +
    +
    +
    WRITE_CPPCLI_PORTABLE_ASSEMBLIES
    +

    +
    +
    +
    When TRUE, this enables an internal command-line option “--set_flag +generate_portable_assemblies” that causes a front end built with +support for C++/CLI (for Microsoft Windows) to write out all +assemblies used in the compilation (likely including mscorlib.dll) +to be written in the current directory in a format that is readable on +non-Windows platforms (i.e., with a front end not built with +EDG_WIN32 set to TRUE). Since the assemblies are written in the +current directory with their original file name (e.g., +“mscorlib.dll”), care should be taken that no required assemblies +are in the current directory when the front end is invoked in this +way.
    +
    +
    +
    +
    +
    +
    +

    1.2.6. Target-Specific Configuration#

    +

    A target configuration is defined by giving appropriate values to a set of +configuration macros (dubbed the target-specific configuration macros). +Multiple target configurations can be specified when the front end is built; +the --target command-line option is used to select a non-default target +configuration when the front end is invoked. The --dump_legacy_as_target +command-line option can be used to display the set of target-configuration +macros.

    +

    Each target-specific configuration macro has a “legacy” version, i.e., one +without any target-specific suffix, as well as a version for each target +configuration that is specified when the front end is built. Non-legacy +configuration macro names are formed by appending an underscore and the target +configuration name to the legacy configuration macro name. For example, the +legacy macro TARG_LITTLE_ENDIAN would have a corresponding +TARG_LITTLE_ENDIAN_win32 configuration macro for the win32 target +configuration.

    +

    By default, the legacy configuration has no name, but one may be specified by +setting LEGACY_TARGET_CONFIGUATION_NAME to the desired name. The default +target configuration can be specified by giving its name as the definition of +the DEFAULT_TARGET_CONFIGURATION_NAME configuration macro; otherwise, the +legacy target configuration will be used as the default.

    +

    Note that specifying a named target configuration (either explicitly or through +defaults) requires that an $EDG_BASE/lib_target/ directory be +present at run time. Having target-specific $EDG_BASE/lib_target/ directories allows each target configuration to have different predefined +macros (e.g., to define _M_IX86 in one and _M_X64 in another).

    +

    A legacy configuration can be configured manually (by specifying values for +each target-specific macro), or automatically (by using the dettarg tool +and defaults that many configuration macros have). The +--dump_configuration command-line option provides a convenient display of +all configuration macros and their settings.

    +

    A non-legacy target configuration is most easily generated as a derivative from +an existing legacy target configuration using the --dump_legacy_as_target +command-line option. This option takes a target configuration name and +generates a list of the target-specific macro names for the given target +configuration name along with the values of the legacy configuration. This +file (after verifying that TARGET_CONFIGURATION_number is unique) can +then be included in defines.h as the basis for a new target configuration. +Additional target configurations can be generated from different legacy +configurations in the same manner, or by using an existing target configuration +as a template (and changing the target configuration name in each macro, along +with the TARGET_CONFIGURATION_number). Note that all target-specific +configurations must share the same non-target-specific configuration, so for +instance, it’s not possible to have an IA-64 ABI target configuration and a +Cfront target configuration in the same front end configuration (because +IA64_ABI is not a target-specific configuration macro and must have the +same value across all target configurations).

    +

    Note that it is inadvisable to use a target-specific global variable as the +value for a target-specific configuration macro. For example:

    +
    +

    #define TARG_IA64_VTABLE_ENTRY_INT_KIND targ_ptrdiff_t_int_kind

    +
    +

    is subject to race conditions (because targ_ptrdiff_t_int_kind may or may +not have been initialized before its value is used to set +targ_ia64_vtable_entry_int_kind). The following will work as expected:

    +
    +

    #define TARG_IA64_VTABLE_ENTRY_INT_KIND TARG_PTRDIFF_T_INT_KIND

    +
    +

    An important aspect of this architecture is that each legacy configuration +macro has an associated global variable whose value is set at initialization +time to the value of the (legacy or per-target) configuration macro for the +selected target. Because of this, it is imperative that user modifications to +the front end use the run-time value of global variables rather than the +compile-time values of legacy configuration macros.

    +
    +
    +

    1.2.7. Replaceable Code#

    +

    Occasionally, some customizations are needed that cannot simply be expressed +through configuration macros. Those may require instead that various routines +be replaced with custom code. The following files in src/ are written with +such modifications in mind:

    +
    + + + + + + + + + + + + + + + +
    +
    fixed_pt.c
    +
    +
    +
    Routines implementing operations on fixed-point values (only supported +in some configurations).
    +
    +
    +
    float_pt.c
    +
    +
    +
    Routines implementing operations on floating-point values.
    +
    +
    +
    host_envir.c
    +
    +
    +
    Includes routines dealing with operations on files and directories. +Signal handlers can also be set up there.
    +
    +
    +
    sys_predef.c
    +
    +
    +
    Routines to predefine platform-specific entities (macros, types, +routines, etc.)
    +
    +
    +
    +
    +
    +
    +

    1.3. Building the Front End#

    +
    +

    1.3.1. Using the Top-Level Makefile#

    +

    Assuming a Unix-like environment, a complete demonstration compiler can be +configured and built using a sequence of shell commands like the one shown +below (for a typical Linux platform, but other Unix-like environments are +similar). The sequence assumes that the current directory is the top-level +directory of a freshly unpacked release.

    +
    cp sample_edg_eccp_config/edg_eccp_config.linux edg_eccp_config
    +cp src/defines.h.linux src/defines.h
    +cd lib
    +../sample_edg_eccp_config/make_g++_incl_paths
    +../misc/make_predef_macro_table
    +cd ..
    +export EDG_BASE=`pwd` # or setenv EDG_BASE `pwd`
    +make
    +
    +
    +

    This builds a front end with a C-generating back end, along with a run-time +support library and helper tools such as the prelinker and demangler. The +entire toolset can be driven with the eccp script (see +“The eccp script”).

    +
    +
    +

    1.3.2. Building the Front End Only#

    +

    In an environment with a Unix-like make utility, the front end can be +compiled and linked by running

    +
    make edgcpfe
    +
    +
    +

    in the src/ directory (after constructing an appropriate defines.h file +and editing src/Makefile to select the desired compiler and compiler +options for building the front end). This can be useful to update the front +end for modifications after building the complete tool set, or when only the +front end program itself is desired. If make is not available, the front +end can be built using the following manual steps.

    +
      +
    • +
      Configure the defines.h file. For example, under Windows the following +is a useful starting point:
      +
      +
      copy src\defines.h.win32 src\defines.h
      +
      +
      +
    • +
    • +
      In the misc/ directory, compile and link the mk_errinfo program +into a mk_errinfo executable file. For example, using a Windows +command line and the Microsoft C++ compiler:
      +
      +
      cd misc
      +cl /TP /I..\src mk_errinfo.c
      +cd ..
      +
      +
      +
      +
      See mk_errinfo for additional information about mk_errinfo and +the format of its input files.
      +
      +
    • +
    • +
      In the src/ directory, translate the diagnostic messages using the +mk_errinfo program that was built in the previous step. For example, +using a Windows command line
      +
      +
      cd src
      +..\misc\mk_errinfo error_msg.txt error_tag.txt err_codes.h err_data.h
      +
      +
      +
    • +
    • +
      Still in the src/ directory, compile and link all the .c and +.cpp files. For example:
      +
      +
      cl /TP /EHsc /Feedgcpfe.exe *.c *.cpp /link mscoree.lib oleaut32.lib
      +
      +
      +
    • +
    +
    +
    +

    1.3.3. Building Support for C++/CLI and C++/CX Modes#

    +

    C++/CLI is a Microsoft extension to C++ that simplifies writing C++-like +programs for Microsoft’s “.NET” environment. It is formally specified by the +ECMA standard ECMA-372. The front end can support this extension, provided it +is built on a sufficiently recent Microsoft Windows platform with a compiler +that is sufficiently compatible with Microsoft’s “Visual C++” compiler. This +support is currently limited to producing high-level IL. The C++-generating +back end can consume this IL (and render the C++/CLI constructs it describes), +but lowering and the C-generating back end are not available in C++/CLI mode.

    +

    C++/CX is a Microsoft extension to C++ similar to C++/CLI, but it targets the +“Windows Runtime” (WinRT) platform instead of the “.NET” environment. Unlike +C++/CLI, there is no formal document specifying this extension. The front end +can also support C++/CX, with the same caveats as those mentioned for C++/CLI +support (in particular, IL lowering is not available for C++/CX mode).

    +

    To include support for C++/CLI and/or C++/CX the configuration macros +CPPCLI_ENABLING_POSSIBLE and/or CPPCX_ENABLING_POSSIBLE (respectively) +must be set to TRUE. (The macros MICROSOFT_EXTENSIONS_ALLOWED and +EDG_WIN32 must also be TRUE when building such configurations.) In addition +to compiling the C files constituting the front end proper (as explained +above), support for C++/CLI and/or C++/CX requires that the C++ source file +ms_metadata.cpp be compiled as C++ and the resulting object file must be +added to the set of files linked into the final front end executable (or +library). The system libraries mscoree.lib and oleaut32.lib are then +also required in the final executable.

    +

    Compiling ms_metadata.cpp requires Visual C++ 2012 or later (or a C++ +compiler and libraries that are sufficiently compatible with that). The free +“Express” version of Visual C++ is not sufficient because it doesn’t include +the ATLMFC library, which ms_metadata.cpp depends on.

    +
    +
    +

    1.3.4. Building and Using the IL Display Program#

    +

    For educational and debugging purposes, the front end comes with a utility +named edgcpdisp that reads a file containing the IL produced when the front +end compiles one or more source files and displays it in a human-readable form. +(In order to use this facility, of course, the front end must be configured to +write an IL file, i.e., IL_SHOULD_BE_WRITTEN_TO_FILE must be set to TRUE in +defines.h or in src/Makefile.)

    +

    Because the IL file written by the front end is essentially a binary dump of +the IL data structures, it is necessary for the front end and edgcpdisp to +be built on the same platform and using the same configuration options. (Many +of the IL data structures contain fields that are present only in certain +configurations.)

    +

    In an environment with a Unix-like make utility, edgcpdisp is +automatically built (with a configuration that correctly matches that of the +front end) when make is run for the default target in either the top-level +or src/directory. It can also be built separately by using make in +the src/disp/directory.

    +

    If make is not available, edgcpdisp can be built after the front end is +built (as described in the preceding section) in the src/directory by +compiling a subset of the source files with STANDALONE_IL_DISPLAY set to +TRUE. For example, on a Windows platform using the Microsoft C++ compiler, the +command would be (all on one line):

    +
    cl /TP /Feedgcpdisp.exe -DSTANDALONE_IL_DISPLAY const_ints.c  debug.c      \
    +   error.c fixed_pt.c float_pt.c host_envir.c  il.c il_display.c il_read.c \
    +   il_to_str.c il_walk.c  mem_manage.c target.c types.c fe_init.c
    +
    +
    +

    Displaying the IL for a source file x.cpp can be accomplished with the +following commands:

    +
    edgcpfe --output x.cil x.cpp
    +edgcpdisp x.cil
    +
    +
    +

    (In configurations that do IL lowering, x.cil will contain the lowered IL. +To view the unlowered IL, see the --no_il_lowering front-end command-line +option described in the next chapter.)

    +
    +
    +
    +

    1.4. Driving the Front End#

    +

    For many applications, it is useful to invoke the front end through another +“driver” program. One such driver is the bin/eccp script that is part of +every release. Another is the edgcc program that can be downloaded +separately from the EDG download site.

    +
    +

    1.4.1. The eccp script#

    +

    The bin/ directory contains a (Bourne) shell script eccp that +allows the front end to be used much like most Unix-hosted compilers. It +invokes the front end – which must be configured with the C-generating back +end – with various default options, and then compiles any generated C files +through a “native” C compiler (e.g., the GNU gcc compiler) and a native +linker. The script accepts Unix-like compiler options (such as -c, +-o, -O, -g, -I, -L, and -l) and also passes through +most of the options handled by the front end proper (see Command Line).

    +

    The script can be moved anywhere, but it normally looks for various components +(the front end, the prelinker, etc.) under a directory designated by the +environment variable EDG_BASE. The eccp script can be edited to set a +default substitute value for the EDG_BASE variable. Normally, the value of +EDG_BASE is the top level directory of a fully-built release tree (although +the src/ and lib_src/ directories are not used by eccp). eccp +will start by setting various environment variables by executing a script +$EDG_BASE/edg_eccp_config. Sample scripts for various platforms are +provided in the sample_edg_eccp_config/ directory. Two environment +variables commonly customized in the edg_eccp_config script are +EDG_DEFAULT_DEFINES (to add options like -D__unix__) and +EDG_C_TO_OBJ_COMPILER (to establish which “native” compiler to use; e.g., +gcc).

    +

    eccp may also invoke the prelinker (util/edg_prelink) to automatically +instantiate templates (and, with some front end configurations, inline +functions that need an out-of-line copy). See +Automatic Instantiation for notes on this process. The script will +also run util/edg_munch if needed, and filter linker errors through +util/edg_decode.

    +

    See “Utility Programs” for more information on the utility programs +edg_prelink, edg_munch, and edg_decode used by the eccp script.

    +
    +
    +

    1.4.2. The edgcc Driver for Windows#

    +

    A Windows program implementing a subset of eccp‘s functionality can be +downloaded from the EDG download site. The file to download is +nt_util.zip. In addition to source code for the driver program edgcc, +it also contains source code for a Windows-hosted prelinker (pl_nm) and +munch-like program (munch_nm).

    +

    The plain text file src/msinfo contains additional notes for running the +front end in the Windows environment.

    +
    +
    +
    +

    1.5. Configuring and Building the Run-Time Support Library#

    +

    Source code for a sample run-time support library is provided in the +lib_src/ directory. This library is meant to be built using the front end +(i.e., a compiler incorporating the EDG front end). The library is useful for +demonstration and debugging purposes. However, it is normally not suitable for +production compilers because it is written in portable C++ that cannot take +advantage of more efficient platform-specific mechanisms (e.g., to implement +exception handling).

    +

    Similarly to the front end, the library can be configured through macro +definitions placed in lib_src/defines.h. Typically, however, few or no +macros need to be defined because the --build_runtime option to the front +end (used to build this library) causes most or all required macros to be +predeclared.

    +

    The macros that might need manual configuration are documented in +lib_src/config.h.

    +

    When using multiple target configurations, a version of the run-time support +library must be built for each target configuration and installed in the +appropriate lib_target/ directory. See lib_src/Makefile for +directions to build target-specific versions of the library.

    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/c_gen_be/index.html b/doc/c_gen_be/index.html new file mode 100644 index 0000000..00e390b --- /dev/null +++ b/doc/c_gen_be/index.html @@ -0,0 +1,728 @@ + + + + + 23. C-Generating Back End - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    23. C-Generating Back End#

    +

    c_gen_be.c contains code to translate the intermediate language to C; +c_gen_be.h contains the associated declarations. This is a fake “back end” +that is useful as a way of testing the front end in the absence of a real back +end, as a portability aid, and as an example of how to traverse the +intermediate code (which may be helpful to those writing back ends).

    +
    +

    23.1. Function#

    +
    +

    23.1.1. Generated C Code#

    +

    The C code generated can be either ANSI C or old-style K&R C, depending on the +setting of the configuration flag C_GEN_BE_GENERATES_ANSI_C.

    +

    The output contains #line directives that relate the generated code back to +the original source lines that generated it. The #line directives do not +ascend monotonically through the line numbers of the source file; they jump +around as the code generation jumps around. However, since the C-generating +back end tends to process all declarations of entities of one kind in a sweep +through those entities in source order, the output tends to have all the types +in source order, then all the variables in source order, etc.

    +

    Long output lines are broken (between tokens) to avoid unduly stressing C +compilers that must process the generated code.

    +

    Since the generated code is intended to be fed into a C compiler, rather than +read by a human, it is not very readable. The readability can be improved +(slightly) by turning on debugging (e.g., -d0 on the command line); that +will cause the C-generating back end to generate annotation comments and +indentation. Unreferenced entities, which ordinarily are not put out at all, +are generated inside #if 0/#endif delimiters in this mode.

    +
    +
    +

    23.1.2. Transformations#

    +

    For the most part, what the C-generating back end does is just writing out the +C code that corresponds directly to the IL. Since the IL has the same concepts +and constructs as the C language, the processing is pretty straightforward. +However, there are a few complicating transformations.

    +

    The following transformations on names are done:

    +
      +
    • +
      Names that match C reserved words, or words that are likely to mean +something to the underlying C compiler (e.g., unix), are given a prefix +of “__x”.
      +
      +
    • +
    • +
      Names with no linkage (e.g., local variables) are given a prefix that is +the source sequence (line) number and column number of the name’s +declaration, to make sure they do not conflict with similar names from +elsewhere in the program (e.g., “i” is output as “__28_7_i”).
      +
      +
    • +
    • +
      Unnamed entities are given generated names of the form “__Tnnnnnn”, +with nnnnnn generated from the IL entry address.
      +
      +
    • +
    • +
      The “this” parameter, passed through from C++, is given the name +“this”.
      +
      +
    • +
    • +
      Function-local and prototype-scope types are given names formed by +concatenating the original name, “__”, the (mangled) function name, +“__”, and “Lnn”, where nn is a number identifying the +function, prototype, or block scope scope of which the type is a +member. (Renaming is needed because such types are promoted out of +functions; more on this below.)
      +
      +
    • +
    • +
      When generating K&R C, file-scope static variables are given a suffix +formed from the name of the module and the date and time of compilation. +This suffix is needed because initialized file-scope static variables must +be made external to avoid some pcc limitations on declaring static +variables more than once. The suffix helps to ensure that the now-external +name does not conflict with like-named static and external variables from +other compilation units.
      +
      +
    • +
    +

    Another set of transformations is necessitated by the fact that IL lowering +generates “C” IL that actually contains some minor extensions. These +“extensions” are things that a real back end would probably take in its stride +(i.e., it wouldn’t see these cases as being different than normal cases), but +which must be rewritten if standard C code must be generated:

    +
      +
    • +
      Dynamic initializations for declarations can appear in mid-block, after +executable statements have appeared. (These are generated as executable +code. Because of this, “const” type qualifiers are suppressed on +variables initialized dynamically and on all struct members.)
      +
      +
    • +
    • +
      Structs and unions can have no members at all, and aggregate constants used +in initializers can contain empty lists of constants (”{}”). (The +struct/union definition will include a dummy field, and the initialization +puts a zero into that field.)
      +
      +
    • +
    • +
      Enumerations having no enumerator constants are put out as the +corresponding integral type.
      +
      +
    • +
    • +
      The eok_bassign operator is used to do assignment of arrays (e.g., in +generated copy constructors). (A memcpy is generated.)
      +
      +
    • +
    • +
      Prototyped parameter variables may be unnamed. (A name is generated.)
      +
      +
    • +
    • +
      Variables can be indicated to be initialized to zero (the initk_zero +initialization kind). This is used to differentiate real definitions of +external variables from tentative definitions (a distinction that is hazy +in C), and for local aggregate variables that are partially initialized. +(For static variables, the initialization to zero is preserved in the +generated C; for automatic variables, a memset is generated.)
      +
      +
    • +
    • +
      String literals in C++ are const. IL lowering leaves them const, +even though string literals in C are not const. (This does not require +a transformation in the generated C code: the string literals are put out +as such, and the C compiler sees them as non-const, which works out +okay.)
      +
      +
    • +
    +

    When generating K&R C, some transformations are needed to erase ANSI C features +that do not exist in K&R C:

    +
      +
    • +
      Prototyped functions are put out as old-style unprototyped functions.
      +
      +
    • +
    • +
      Type qualifiers (”const” and “volatile”) are not put out.
      +
      +
    • +
    • +
      Enumerations are put out as integral types, and enumeration constants are +put out as integral constants.
      +
      +
    • +
    • +
      “signed” is never put out. “signed char” is put out as “char”, +and “signed int” is not used for the base type of a bit field.
      +
      +
    • +
    • +
      “long double” is put out as “double”.
      +
      +
    • +
    • +
      The suffixes “U” on integral constants and “F” and “L” on +floating constants are not put out; a cast is used instead.
      +
      +
    • +
    • +
      Union initializations are rendered as executable code.
      +
      +
    • +
    • +
      Initializations of automatic aggregates are rendered as executable code.
      +
      +
    • +
    • +
      Bit fields in unions are put out as normal fields.
      +
      +
    • +
    • +
      Signed bit fields are simulated by adding code to sign-extend and truncate +the bit fields on each access.
      +
      +
    • +
    • +
      Second and third operands of “?” of type void are rewritten.
      +
      +
    • +
    • +
      extern void variables are put out with type char.
      +
      +
    • +
    • +
      Labels are given a prefix of “__L_” to accommodate the fact that pcc +does not maintain a separate name space for labels.
      +
      +
    • +
    +

    The following transformations also deal with features missing in K&R C, but +these transformations are done even when generating ANSI C to avoid some +features that might not be implemented (well) in C compilers:

    +
      +
    • +
      Rvalue field selections (e.g., “f(x).i”) are rewritten as lvalue field +selections by using a temporary.
      +
      +
      struct A { int i; };
      +extern struct A f();
      +void m() {
      +  j = f().i;  /* Rewritten as "j = (Tnnnn = f(), Tnnnn.i)" */
      +}
      +
      +
      +
    • +
    • +
      Wide string constants are stored in generated static variables and the +variables are used in place of the constants at each reference.
      +
      +
    • +
    • +
      Character arrays initialized with string constants not containing a +trailing null character are rendered in “exploded” form, e.g., something +like
      +
      +
      int a[4] = "abcd";
      +
      +
      +
      +
      is rendered as
      +
      +
      int a[4] = {'a', 'b', 'c', 'd'};
      +
      +
      +
    • +
    +

    The following transformations are necessary to deal with ordering problems +(i.e., they’re necessary because of the order in which the C-generating back +end outputs entities):

    +
      +
    • +
      Local types of functions are generated at file scope. This avoids problems +with extern declarations written inside functions (the extern entity is on +the file-scope list, but it may refer to local types of the function).
      +
      +
      void f() {
      +  struct A { int i; };
      +  extern void g(struct A);
      +}
      +
      +
      +
      +
      is rewritten as
      +
      +
      struct A { int i; };
      +extern void g(struct A);
      +void f() {}
      +
      +
      +
    • +
    • +
      Types in the prototype scope of a function are promoted out of the +prototype scope. This is because each function and variable is put out +twice, once as a declaration and once as a definition. Without this +promotion, the declaration and definition would be incompatible because the +two copies of the prototype scope types would be considered to be distinct +types.
      +
      +
      void f(struct A { int i; } p) {}
      +
      +
      +
      +
      is rewritten as
      +
      +
      struct A { int i; };
      +void f(struct A);
      +void f(struct A p) {}
      +
      +
      +
      +
      Prototype scopes that are not part of a function or variable definition are +not processed in this way. When generating K&R C, such unprocessed +function types are put out unprototyped, which eliminates the types defined +in the prototype scope. When generating ANSI C, such unprocessed function +types are put out prototyped, and if any structs, unions, or enums are +defined in the prototype scope they are put out inline.
      +

      +
      When a pointer type containing a prototype scope needs to be put out (i.e., +as the type of a constant or in a cast), the type (and cast) is suppressed, +because the conversion must have been implicit in the source program – +it’s not possible to name the types defined in a prototype scope outside of +that scope.
      +
      +
    • +
    +

    When virtual functions with covariant return types appear in the source +program, IL lowering rewrites them in a way that uses wrapper functions. That +is, when an overriding virtual function returns a pointer to a derived class, +and the overridden virtual function returns a pointer to a base, a wrapper +function is generated that calls the overriding function but returns a pointer +appropriate for the overridden function. Such functions have a body that is +simply a return of an enk_result_of_overriding_function node cast to the +proper pointer-to-base-class type. The C-generating back end expands these +wrapper functions by generating the body of the overriding function again, with +the added cast inserted over the expression at each return statement. Note +that the “obvious” implementation technique of replacing the +enk_result_of_overriding_function node by a call of the overriding function +(i.e., implementing these as actual wrapper functions) will not work if the +functions have variable-length argument lists. The same technique is used for +alternate entry points for constructors in the IA64-ABI, but only if the +routine has a variable-length argument list.

    +
    +
    +

    23.1.3. Configuration#

    +

    Although the generated C code is generally portable, there are some +configuration issues that must be attended to.

    +

    The most obvious is to make sure that the sizes and alignments of basic types +defined in targ_def.h match those assumed by the target C compiler.

    +

    Block operations (e.g., memcpy) are generated in either the BSD form or the +System V/ANSI form under control of the __BSD__ configuration option, so +make sure its setting matches the library of the target C compiler.

    +

    If the target C compiler has some way of indicating that a function is inline, +the code in dump_routine_decl should probably be changed to output that +construct.

    +

    Long output lines are wrapped to avoid overly long lines. You can alter the +maximum size by adjusting MAX_OUTPUT_LINE_SIZE. The default is fairly +modest (a few hundred characters).

    +

    If the target C compiler has particular bugs or shortcomings, you may want to +add code to work around them. There is existing code for the Sun, Microsoft, +and gcc C compilers.

    +

    The C-generating back end can emit #pragma directives for IL pragma +entries, but only in a somewhat limited way. For pragmas bound to an entity, +the pragma is emitted right before the declaration of the entity. However, +pragmas not bound to an entity are emitted at the beginning of the scope +containing them, and therefore they may not be where expected. That makes that +kind of pragma suitable only in cases where the exact position of the pragma is +not very significant, e.g., for global-effect pragmas and those that associate +attributes with entities by naming the entities.

    +
    +
    +
    +

    23.2. Operation#

    +

    The code can be compiled either as a subroutine back_end that is called in +the same program as the front end, or as a main program. In either case, +c_gen_be is called to do the C generation. It begins at il_header and +walks through the intermediate language tree, generating C and writing it to a +file with a .int.c suffix. First, it dumps the source correspondence +information (dump_source_file_correspondence_info) and some other header +code (dump_header_code). Then, for the file scope level, it

    +
      +
    • +
      calls dump_scope_constants to dump code for constants on the file-scope +list. This has marginal utility, but dumps class member constants (an +extension) promoted to the file scope by IL lowering. They are put out as +enum declarations.
      +
      +
    • +
    • +
      calls dump_scope_types to dump declarations for all named types – +i.e., typedefs and tags. The tags are output twice: as incomplete +declarations on a first pass, and as complete declarations on the second, +to avoid forward-reference problems. Local and prototype-scope types are +also output here (at the file scope) to avoid some ordering problems.
      +
      +
    • +
    • +
      calls dump_scope_routines to dump routine headers (no bodies).
      +
      +
    • +
    • +
      calls dump_scope_variables twice. The first time dumps variables +without initializers, and tentative declarations for those with +initializers. The second time dumps only the initialized variables, this +time with initializers. This is to avoid forward-reference problems.
      +
      +
    • +
    • +
      calls dump_scope_routines to dump routines with bodies.
      +
      +
    • +
    +

    When ONE_INSTANTIATION_PER_OBJECT is enabled, each instantiation is put +out as a separate object file. There is still only one IL tree, but it is +marked so that the C-generating back end can sweep through it several times +and put out a different C file (a “slice”) each time, each C file +containing one instantiated entity (function or static data member) plus +exactly the set of other entities needed by that entity. The information +on which entities to include on each sweep is provided by the +per-instantiation “needed” flags, which are a bit vector attached to the +source correspondence entry (see Needed Flags). Each slice is +assigned one bit in that bit vector, and if the bit is 1 the associated +entity is needed in the slice. On beginning the generation of the C file +for a slice, the C-generating back end sets the global variable +needed_flag_bit_number to the bit number for the slice, and then goes +through the normal processing to generate C for everything in the IL tree. +The normal test of the “needed” flag, used to exclude things that aren’t +needed, in this mode tests the proper bit in the bit vector, and therefore +excludes all entities that are not in the slice. In addition, when a +variable or function with a definition is encountered, if the variable or +function is not assigned to the current slice (as indicated by the +instantiation_needed_bit_number field in the variable or routine +entry), the variable or function is put out as a declaration instead of a +definition.

    +

    The lower-level routines are as follows:

    +

    dump_type_decl generates a type declaration. It calls

    +
      +
    • +
      dump_enum_definition,
      +
      +
    • +
    • +
      dump_struct_union_definition, or
      +
      +
    • +
    • +
      dump_typedef_decl.
      +
      +
    • +
    +

    Types are written out by dump_type and +dump_general_declaration_using_type. They use routines from +il_to_str.c to produce the output for the type. dump_enum_definition +puts out enum definitions, and dump_struct_union_definition puts out +struct/union definitions.

    +

    dump_variable_decl generates a variable declaration. For a variable with +an initializer, it calls dump_initializer. There’s some fairly complicated +processing under that routine to turn constant aggregate initialization into +executable code. Among other things, it involves writing initialization +assignments to an auxiliary file while processing declarations, then copying +the initialization code to the right place after all the declarations have been +processed. Because initialized static variables are put out twice (on two +calls of dump_variable_decl), they are made external when generating K&R C, +so their names are modified (by dump_variable_name) to avoid name conflicts +with like-named static and external variables in other compilation units.

    +

    Code generated for file-scope initializations (of unions when generating K&R C) +is placed in a separate routine (with a name beginning with “__cgi__”) that +needs to be called at program start-up time. If the compilation contains a +main program, or an initialization routine generated by IL lowering (with a +prefix of “__sti__”), a call to the C-generating back end initialization +routine is inserted there. Otherwise, if the compilation is of C++ source, the +C-generating back end generates an initialization routine of the same form as +that generated by IL lowering (”__sti__” prefix), along with the variables +needed to alert the link phase to the presence of the initialization routine. +If the compilation is of C source, a message is issued to ask the user to +include an appropriate “-i” option elsewhere to request invocation of the +initialization code.

    +

    dump_routine_decl generates a routine declaration. For a routine with a +definition, it calls dump_routine_definition. That in turn calls +dump_func_definition_type to dump the parameters (prototyped or old-style).

    +

    dump_statement is called to generate code for statements.

    +

    The statements and expressions of functions are pre-scanned before code for the +routine is generated, to generate declarations for any temporaries that will be +needed in the generated code. Specifically, temporaries are generated for +rvalue field selections and wide string constants.

    +

    Expressions are dumped by calling dump_expr. It outputs the expression by +walking the tree. It puts in explicit parentheses where necessary to guarantee +the grouping of operators. Taking the address of a function or array must also +be handled carefully, and is done by dump_ampersand.

    +

    Since pcc doesn’t allow signed bit fields, operations on such fields are +surrounded by references to macros to sign-extend them or truncate them for +storing.

    +

    dump_constant dumps out a literal constant or address constant using the +IL-to-string routines in il_to_str.c.

    +

    Actual output of generated code is handled by the following routines:

    +
      +
    • +
      m_write_ch,
      +
      +
    • +
    • +
      write_ch,
      +
      +
    • +
    • +
      m_write_str,
      +
      +
    • +
    • +
      write_str,
      +
      +
    • +
    • +
      m_write_tok_ch,
      +
      +
    • +
    • +
      write_tok_ch,
      +
      +
    • +
    • +
      m_write_tok_str,
      +
      +
    • +
    • +
      write_tok_str,
      +
      +
    • +
    • +
      write_unsigned_num, and
      +
      +
    • +
    • +
      write_num.
      +
      +
    • +
    +

    The “m_” versions are macros; the others are not. One can choose between +them based on the need for speed and/or a single evaluation of the argument. +The “tok_” routines always write a full token (or several); that allows the +output line to be broken before or after the output if the line is too long.

    +

    set_output_position is called to establish the source position of an entity +about to be generated. If necessary, it generates a #line directive or the +right number of empty lines to adjust the output position (see +write_line_directive).

    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/class_decl/index.html b/doc/class_decl/index.html new file mode 100644 index 0000000..a35e8b2 --- /dev/null +++ b/doc/class_decl/index.html @@ -0,0 +1,2236 @@ + + + + + 11. Class Declarations - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    11. Class Declarations#

    +

    All class, struct, and union declarations are scanned in decl_spec.c, and +their definitions, including the declarations of class members, are handled +through a set of routines, most of which are found in class_decl.c. The +layout of classes is handled in layout.c. Associated declarations are in +class_decl.h and layout.h.

    +

    Declarations of structs and unions in C mode are, for the most part, precisely +compatible with C++ declarations; they just make use of a small subset of the +syntactic options.

    +

    C++/CLI managed class add both a number of variant class kinds (collectively +called “managed classes”) and a number of variant member kinds (e.g., events). +These are also mostly implemented in class_decl.c.

    +

    C++11 lambda expressions implicitly define a closure class type. While the +top-level class declaration parsing routines (class_specifier and +scan_class_definition) are not applicable for parsing lambdas, some other +important routines in this area are reused (see Lambdas).

    +

    Similarly, C++/CLI delegate definitions implicitly define a ref class type, +which reuses some important routines supporting the ordinary definitions of +class types, but not the routines that parse such definitions.

    +
    +

    11.1. Overview#

    +
    +

    11.1.1. Class Declarations#

    +

    class_specifier (in decl_spec.c) is called from decl_specifiers +when a class, struct, or union keyword is encountered. [1] In +Microsoft mode, this is also done with the __interface keyword, and in +C++/CLI mode with the “keywords” ref class, ref struct, value +class, value struct, interface class, and interface struct. A +tag name may be present, and if it is declares_something is returned +TRUE. A definition may be present, and if it is defines_something is +returned TRUE. In every case, even when there is an error, a pointer to a +tk_class, tk_struct, or tk_union type entry is returned in +type_ptr.

    +

    The processing of class declarations consists of several steps. The tag name +(if present) is scanned and looked up in the symbol table (see +scan_tag_name). A declaration may be the declaration of a new class, a +reference to an existing class, or the completion of a declaration whereby an +incomplete class is fully defined; it may also be a specialization of a class +template. If this is a brand new class, the type entry is allocated for it; +otherwise, the old one is fetched from the symbol entry.

    +

    If the declaration does not actually define a class, that’s about all that +needs to be done. The type is returned to the caller and declaration +processing continues.

    +
    +
    +

    11.1.2. Class Definitions#

    +

    If a class declaration is a class definition – that is, if the class body is +present – then scan_class_definition is called from class_specifier +(it is also called from other places like f_instantiate_template_class to +create an instance of a template class and instantiate_class_template to do +prototype instantiation of the class template). The creation of a class +definition is tracked using type a_class_def_state; this is true for +ordinary definitions appearing in the source, but also for definitions +generated for, e.g., lambda expressions (i.e., closure types). This structure +records all kinds properties of the definition (e.g., the current accessibility +or whether a member has been seen that requires a nontrivial constructor) and +is passed around to many routines that implement class member declarations.

    +

    Most of the tasks performed by scan_class_definition are done in C++ mode +only:

    +
      +
    • +
      The base class specifiers (if any) are scanned and recorded.
      +
      +
    • +
    • +
      The scope stack is pushed for the class (and the scope stack entry is made +to point to the a_class_def_state structure for the definition).
      +
      +
    • +
    • +
      A loop is entered to scan class members. In ordinary C this means scanning +the declarations of fields. In C++ it means scanning all kinds of member +declarations.
      +
      +
    • +
    • +
      At the top of the loop (in C++ only) an optional access control specifier +is scanned.
      +
      +
    • +
    • +
      When using appears (or there is only a qualified name and no +declaration specifiers), a using declaration (or access declaration) is +scanned.
      +
      +
    • +
    • +
      When template appears template_declaration_or_directive is called +to process a member template.
      +
      +
    • +
    • +
      Otherwise, class_member_declaration is called:
      +
      +
        +
      • +
        A structure of type a_member_decl_info tracks properties of the +declaration. This structure includes a field decl_state of type +a_decl_parse_state (which is the kind of structure used for general +declaration processing).
        +
        +
      • +
      • +
        decl_specifiers (in decl_spec.c) is called to scan the +declaration specifiers.
        +
        +
      • +
      • +
        When there is no declarator following,
        +
        +
          +
        • +
          if it is a friend class declaration, decl_friend_class is called +and declarator processing is skipped.
          +
          +
        • +
        • +
          if it is a nested class, struct, union, or enum +declaration, declarator processing is skipped.
          +
          +
        • +
        • +
          if it is a nested anonymous union declaration, declarator processing is +entered (even though the call to declarator itself is skipped) +since the rest of the processing is done in +decl_nonstatic_data_member.
          +
          +
        • +
        +
      • +
      • +
        A loop is entered to scan a declarator list. In cases where only a +single declarator is permitted, the loop will be exited at the +appropriate point.
        +
        +
      • +
      • +
        declarator (in declarator.c) is called to scan a single +declarator. If default arguments are encountered when a parameter list +for a member function is scanned, they will be cached away to be +rescanned later.
        +
        +
      • +
      • +
        Based on the combined information returned from decl_specifiers and +declarator, one of the following is done:
        +
        +
          +
        • +
          decl_member_function is called to process a member function +declaration (static or nonstatic, virtual or nonvirtual). If the +function body is present, the tokens are cached so that they can +scanned later (see prescan_function_definition). If there is no +function body, a pure specifier (”= 0”) is checked for (see +scan_pure_specifier).
          +
          +
        • +
        • +
          decl_friend_function is called to process a friend function (member +or nonmember). If the function body is present, the tokens are cached +so that they can scanned later (see prescan_function_definition).
          +
          +
        • +
        • +
          decl_member_function_template is called to process a member +function template.
          +
          +
        • +
        • +
          decl_typedef is called to process a typedef declaration.
          +
          +
        • +
        • +
          decl_nonstd_member_constant is called to process a member constant +declaration (an extension).
          +
          +
        • +
        • +
          decl_static_data_member is called if the keyword static was +used in a non-function declaration.
          +
          +
        • +
        • +
          decl_nonstatic_data_member is called to do processing for ordinary +fields.
          +
          +
        • +
        +
      • +
      • +
        At the bottom of the declarator loop, continue looking for declarators if +the next token is a comma.
        +
        +
      • +
      +
    • +
    • +
      At the bottom of the loop, continue looking for member declarations unless +a right brace (or end of file) is encountered.
      +
      +
    • +
    • +
      Once the member declarations have been processed, further error checking is +done, and in addition:
      +
      +
        +
      • +
        In case the class was declared before the current definition, +move_to_end_of_types_list is called to move the type entry for the +class to the end of the scope types list. (It will have been initially +put onto the list in class_specifier.)
        +
        +
      • +
      • +
        set_virtual_function_numbers is called to do the remaining processing +for virtual functions – in typical implementations, the virtual function +number in a routine entry corresponds to its position in the virtual +function table.
        +
        +
      • +
      • +
        check_special_member_functions is called to determine whether a +compiler-generated default constructor, copy constructor, and assignment +operator is needed and, if so, to generate the declarations. (The bodies +are generated if and when the function is referenced.)
        +
        +
      • +
      • +
        do_class_layout is called to allocate space for base classes and +nonstatic data members, as well as for whatever information is needed +(e.g., pointers) to support accessing virtual base classes and calling +virtual functions.
        +
        +
      • +
      • +
        project_base_class_conversion_functions is called to add projection +symbols for inherited conversion functions to the class symbol +supplement’s conversion_list.
        +
        +
      • +
      • +
        report_virtual_function_ambiguities is called to issue diagnostics on +unresolved ambiguities in virtual function declarations.
        +
        +
      • +
      • +
        check_abstract_class is called to mark a class with pure virtual +functions as “abstract.”
        +
        +
      • +
      +
    • +
    • +
      The scope stack is popped, and the closing right brace of the class +definition is bypassed.
      +
      +
    • +
    • +
      For non-nested classes delayed_scan_fixup_for_class is called to rescan +member function default argument declarations and inline member function +definitions.
      +
      +
    • +
    +

    Many of these “class definition completion” tasks are initiated from the +complete_class_definition function. This function is also called for class +types that don’t appear using ordinary class definition syntax in the source +code (for example, closure types for lambda expressions; see Lambdas).

    +

    Ideally, all properties of a class should be known once the definition has been +seen. Unfortunately, that is not always the case. In particular, the C++11 +notion of whether a class type is a “literal type” cannot always be determined +until it is known whether it has a constexpr constructor, which in turn +sometimes requires waiting until all the field initializers have been scanned +(and for template classes that can be arbitrarily delayed). Whether a class +type is a literal type is therefore tracked by two flags in the class symbol +supplement [2] (known_to_be_a_literal_type and +known_not_to_be_a_literal_type), which can be determined “on demand” by a +call to set_literal_type_flag or, more generally, is_literal_type.

    +
    +
    +

    11.1.3. C++/CLI Managed Class Definitions#

    +

    Managed class definitions are parsed using the same framework as standard class +definitions. However, C++/CLI adds many new kinds of members, several of which +are implemented with new top-level mechanisms.

    +

    Several “field-like” managed member kinds rely on “context-sensitive +keywords”, i.e., specific identifiers (event, initonly, +literal, and property) that are keywords only if the rest of the +declaration would not otherwise be valid. The function +check_for_cli_modifier looks ahead through the token stream for such +keywords, and records their presence in the a_decl_parse_state +structure for the current declaration. If the keywords event or +property were found, the member declaration is handled using the +special-purpose function scan_cli_property_or_event_head, after which +the front end proceeds with the next declaration. The other two keywords +(initonly and literal) are consumed by the regular call of +decl_specifiers (which is passed the a_decl_parse_state structure +indicating that these identifiers should be treated as keywords).

    +

    Delegate definitions appearing as member declarations also rely on a +context-sensitive keyword delegate. That case is identified by the +function check_for_cli_delegate_definition, and is then handled by +scan_and_record_cli_delegate_definition.

    +

    Properties and events are represented as fields (a_field) if they are +nonstatic or as static data members (a_variable) if they are static. These +representations are created by calls to decl_nonstatic_data_member or +decl_static_data_member respectively, which is done by the function +decl_property_or_event_member.

    +

    Property and event definitions may include a brace-enclosed list of accessor +declarations (such properties/events are called nontrivial). Accessors are a +special kind of member function (i.e., their a_routine entry has a +special_kind field that is not sfk_none) of the parent class of the +property or event: The braces are for grouping purposes only and do not +introduce a new scope. Accessors declarations are handled as separate member +declarations in the main loop of scan_class_definition; not as part of the +call to scan_cli_property_or_event_head. However, a copy of the +a_member_decl_info structure recorded for the property/event declaration +itself is kept around while scanning the accessors (accessible via the +pe_info field of the current a_class_def_state structure). This is +needed because the exact nature of the property/event may depend on the storage +class specified on the first accessor: If no storage class was specified on the +property/event declaration itself, but the first accessor is declared static, +then the property/event should be treated as static. Hence for a nontrivial +property or events, the call to decl_property_or_event_member is delayed +until parsing of the subsequent accessor has started: At that point a lookahead +for a static specifier (using function static_member_next) is performed +if needed to determine the static/nonstatic nature of the property or event.

    +

    Literal fields (i.e., fields declared with the context-sensitive keyword +literal) are recorded in decl_literal_field: The result is an IL entry +of type a_constant, not a_field (i.e., “literal field” is somewhat of a +misnomer). initonly members, on the other hand, are just treated as +slightly special cases in decl_nonstatic_data_member and +decl_static_data_member.

    +

    Conversion functions and other operators can be static members of managed +classes; such members must have one more explicit parameter than their +nonstatic counterparts. The constraints on those parameters are checked in the +function check_operator_function_params.

    +
    +
    +
    +

    11.2. Names#

    +
    +

    11.2.1. Name Scope#

    +

    When a class is declared with a tag name, an sk_class_or_struct or +sk_union symbol is created to represent the use of the name. Since an +elaborated class specifier appearing in the source may refer to an existing +class, its name must be looked up in the symbol table. Finding a tag name in +the current or a containing scope is handled by scan_tag_name.

    +

    This is not a simple lookup, however. An interesting case occurs when a tag +name has already been declared in an outer scope: a reference to the same name +in an inner scope may or may not be a reference to the same entity. For +instance,

    +
    struct S { int i; };
    +void f() { struct S s; }
    +void g() { struct S { /* ... */ } s; }
    +
    +
    +

    In this example, the S in function f refers to the S defined in the +file scope, whereas the one in function g refers to another S, one +local to the function scope. The difference is that the declaration in g +is a definition and so eclipses the name from the file scope, whereas in f +there no redefinition of S. For this reason scan_tag_name must take +into account whether the class is being defined in the current declaration in +deciding whether to reuse a class defined in a containing scope. A further +complexity is revealed by another example:

    +
    struct S { int i; };
    +void f() { struct S; struct S *p; struct S { } s; }
    +
    +
    +

    Here the first declaration of S in function f, referred to as a +“vacuous declaration” of S because it does not define a class and is not +used in the definition of any other object, has the effect of introducing an +incomplete class S into the routine scope and thereby eclipsing the file +scope S. [3] scan_tag_name also deals with this kind of case.

    +

    When no tag symbol is found, there is still the question of what scope a new +symbol is to be declared in. This too is determined in scan_tag_name; the +answer is returned to the caller by effective_decl_level. In most cases it +is simply the current scope (given in decl_scope_level [4]). However, +in C++ a non-defining initial use of a class name in a function prototype scope +or a class scope is treated as declaring that name in the innermost containing +scope that is not the scope of a function prototype or a class. For example,

    +
    int f(struct S *p) { return (p == 0); }
    +struct S { /* ... */ } s;
    +
    +
    +

    Here (and contrary to the interpretation in ordinary C mode) there is only one +S; the second reference defines the struct to which the first is a kind +of forward reference. Thus scan_tag_name would return the file scope as +the effective_decl_level for S in its initial declaration. Similar +treatment is accorded declarations in classes:

    +
    class A {
    +  class B;
    +  class C *pc;
    +  class D {
    +    class E *pe;
    +  };
    +};
    +
    +
    +

    Here class B is a vacuous declaration (it anticipates a definition of a +nested class B later in the definition of A), whereas class C is a +forward reference to a file scope declaration of C. Similarly, class E +anticipates a file scope declaration as well, even though the file scope is not +the immediately containing scope of class D.

    +

    The tag name can be a qualified name, not only in a reference (e.g., a +friend declaration or the declaration of another entity using an elaborated +type specifier) but also in a definition.

    +
      +
    • +
      It can be a class-qualified name for a “delayed definition” of a nested +class. For example,
      +
      +
      class A {
      +  struct S;
      +  /* ... */
      +};
      +struct A::S { /* ... */ }
      +
      +
      +
      +
      Here scan_tag_name returns a symbol locator specifying the qualified +name; the parent class scope is then reactivated in +scan_class_definition before the body of the class definition is +scanned.
      +
      +
    • +
    • +
      It can also be a namespace-qualified name – most interestingly when a +class declared in a namespace is then defined outside the namespace. (It +is a requirement that the scope in which the definition occurs enclose the +scope in which original declaration occurs.) For example,
      +
      +
      namespace N {
      +  struct S;
      +  /* ... */
      +};
      +struct N::S { /* ... */ }
      +
      +
      +
      +
      scan_tag_name returns a symbol locator specifying the qualified name, +and class_specifier pushes a namespace-extension scope before calling +scan_class_definition.
      +
      +
    • +
    +
    +
    +

    11.2.2. Tagless Classes#

    +

    When classes are declared with no tag name, though obviously no symbol is +needed for lookup on a subsequent reference, one is needed to store +information about the class (see below). Creating such a symbol, which is +not actually added to the symbol table, is done by +make_unnamed_tag_symbol.

    +

    There is a way by which a tagless class can acquire a name retroactively – +when its definition appears within a typedef declaration. Here is an +example,

    +
    typedef struct { /* ... */ } S;
    +
    +
    +

    in which case the tagless struct comes to acquire the name S. This +cannot be anticipated during the processing done by scan_class_definition. +Rather, the situation is detected only after the class definition has been +scanned, in decl_typedef. In general, this means the name is assigned “for +linkage purposes”, which means the name field in the type’s +source-correspondence is updated. Additionally in cfront mode, +relink_unnamed_tag_symbol is called to add the symbol for the unnamed class +to the symbol table after turning it into a symbol of the specified name.

    +
    +
    +

    11.2.3. C++/CLI Accessor Names#

    +

    The names of accessor functions of properties and events (get, set, +add, remove, and raise) are not directly visible in the class of +which they are members (although accessors are members of that class in all +other ways; e.g., they have a this handle). Instead, referring to them +directly requires qualification with the name of the property or event. For +example

    +
    ref struct RS {
    +  int get();  // (1)
    +  property int p[int] {
    +    int get(int);  // (2) Use p::get
    +  }
    +  property int p[double] {
    +    int get(double);  // (3) Use p::get
    +  }
    +  property int q {
    +    int get(int);  // (4) Use q::get
    +  }
    +};
    +
    +
    +

    The accessors marked (2) and (3) form an overload set. The accessors marked +(1) and (4) are not part of overload sets. (See also Delegates (C++/CLI mode).)

    +

    The symbol for an CLI accessor is not linked under the symbol header used for +normal lookups of the accessor’s name. For example, a get accessor for a +property is not linked on the list of the symbol header normally associated +with the identifier get, and hence looking up the identifier get in the +usual way will never find an accessor. Instead, a special symbol header is +synthesized by combining the accessor name and its parent event or property; +see get_property_or_event_accessor_symbol_header for details. (See also +C++/CLI Member Functions for additional notes on accessor functions and their +representation, as well as Properties and Events (Microsoft and C++/CLI modes) for related remarks about +properties and events.)

    +
    +
    +
    +

    11.3. Type, Scope, and Symbol#

    +

    Processing a class declaration involves forming a potentially extensive and +complex description of the class. There are three principal data structures +that serve as repositories for this information: a symbol entry, a type entry, +and an IL scope entry. The information that must be passed on to the back end +(including the IL lowering phase, if applicable) is stored in the type and +scope entries; information that is only of use in front end processing (e.g., +for error detection) is recorded in the symbol.

    +

    Detailed descriptions of these data structures are provided in the files +il_def.h and symbol_tbl.h; introductions painted with a broader brush +may be found in the Intermediate Language and Symbol Table chapters.

    +

    One thing that might be a bit confusing is that both the symbols and type +entries for classes have supplements, entities of type +a_class_symbol_supplement and a_class_type_supplement, respectively.

    +

    Moving among the symbol, type, and scope entries that represent a class is +fairly straightforward:

    +
      +
    • +
      The assoc_type field of the IL scope entries points to the associated +class type.
      +
      +
    • +
    • +
      The assoc_scope field of the class type supplement points to the +corresponding IL scope entry.
      +
      +
    • +
    • +
      In the type entry the source_corresp.assoc_info field is a pointer to +the class’s symbol entry. [5]
      +
      +
    • +
    • +
      The symbol points to the type entry by means of the type field.
      +
      +
    • +
    +

    To make it a bit easier to get from source language categories to the data +structures that represent them, here (from a slightly different slant) is yet +another description of how the symbol, type, and scope divide up the task of +summarizing a class declaration:

    +
      +
    • +
      Nonstatic data members (“fields”) are recorded on a linked list of +a_field that is accessed from the type entry.
      +
      +
    • +
    • +
      Static data members are represented by a_variable entries; a list of +them appears on the scope entry.
      +
      +
    • +
    • +
      Member functions appear on a linked list of a_routine entries which is +also accessed from the scope entry. Static and nonstatic member functions +are intermingled on this list; they can be distinguished by the presence or +absence of an implicit this parameter type in the associated routine +type.
      +
      +
    • +
    • +
      Member function templates are represented by sk_function_template +symbols. (They also appear in the IL, but only very limited information is +available there: see the linked list of a_template pointed to from the +scope entry for the class.) Instances of member function templates, like +ordinary member functions, appear on the routines list of the class +scope entry.
      +
      +
    • +
    • +
      As far as the IL is concerned, constructors, destructors, overloaded +operator routines, and user-defined conversion routines are just like any +other member function. They can be identified by the +special_function_kind value in the routine entry (e.g., for generating +their names). To facilitate front-end processing, however, the symbol’s +class supplement contains pointers to the symbols for the constructor(s), +the destructor, and the assignment operator routine(s).
      +
      +
    • +
    • +
      Member types (including type entries for nested classes) and member +constants also appear on lists hanging off the scope entry.
      +
      +
    • +
    • +
      Member class templates are represented by sk_class_template symbols. +(They also appear in the IL, but only very limited information is available +there: see the linked list of a_template pointed to from the scope +entry for the class.) Instances of member class templates, like ordinary +nested classes, appear on the types list of the class scope entry.
      +
      +
    • +
    • +
      Friendship is represented by a reference to the befriending class in the +routine entry for the friend function (or in the type entry when friendship +is conferred on an entire class).
      +
      +
    • +
    • +
      Derivation is represented by a list of a_base_class entries that is +pointed to from the class type supplement of the derived class. All base +classes (direct, indirect, virtual) appear on this list. The specific ways +the class is derived are given by the a_base_class_derivation entry +associated with each base class; and there may be more than one such entry +for a given base class if it is virtual.
      +
      +
    • +
    • +
      Inherited names are represented by sk_projection symbols. The +projection symbol identifies both the fundamental symbol and the base class +entry with which that instance of the symbol is associated.
      +
      +
    • +
    • +
      Names brought into a derived class from a base class by a +using-declaration (or an access declaration) appear in the symbol table +as projection symbols for which is_using_decl is TRUE. Such +declarations are also recorded in the IL by entries of type +a_using_decl, pointed to from the scope entry.
      +
      +
    • +
    • +
      Accessibility is recorded in IL entries (for front-end use and symbolic +debug purposes only), in projection symbols (which can end up marked +“inaccessible”), and in base class derivation entries. But since +accessibility is generally dynamic, it must usually be computed (e.g., see +access_to_end_of_path and have_access_to_symbol in +symbol_tbl.c).
      +
      +
    • +
    +
    +
    +

    11.4. Base Classes#

    +

    Once the tag symbol and type entry have been created for a class definition, +scan_class_definition calls scan_base_specifier_list to scan any base +classes that may have been specified. It goes through the comma-separated list +of base classes one by one, creating for each (and for each of the indirect +base classes derived through it) an entry of type a_base_class that is +added to the base_classes list of the class type supplement. When all base +classes have been added, wrapup_base_classes is called to establish certain +properties (like the preferred derivation path of virtual bases) that cannot in +general be determined by looking at a single derivation.

    +
    +

    11.4.1. Base Class List#

    +

    The list of base classes associated with any derived class contains a base +class entry for each of its base classes – not just for those from which it is +directly derived. The order of the list is significant: depth-first +left-to-right, following the source code order of declarations. Base classes +contain a direct flag to distinguish direct from indirect base classes; +there is also an is_virtual flag. Consider this example:

    +
    class V { /* ... */ };
    +class A : virtual V { /* ... */ };
    +class B : virtual V { /* ... */ };
    +class C : public B { /* ... */ };
    +class D : public C, public A { /* ... */ };
    +
    +
    +

    Here the base classes list for class D will contain the following entries; +note that the virtual base class appears only once in the list:

    +
      +
    • +
      Indirect virtual base class V
      +
      +
    • +
    • +
      Indirect base class B
      +
      +
    • +
    • +
      Direct base class C
      +
      +
    • +
    • +
      Direct base class A
      +
      +
    • +
    +

    Base class entries are not shared between classes because they contain +information uniquely identifying the relation of a base class to its derived +class. Thus, in the previous example, class C also has its own base +classes list, namely:

    +
      +
    • +
      Indirect virtual base class V
      +
      +
    • +
    • +
      Direct base class B
      +
      +
    • +
    +

    Despite some overlap of information, new copies of the base class entries of +C are made for the base classes list of D.

    +

    In scan_base_specifier_list, for each base specifier in the source the +optional access-specifier and optional virtual keyword are scanned, the +base class name is scanned, and error checking is performed. If the same base +class name appears twice in the base specifier list, an error is issued. +However, if the name of a direct base class is identical to that of an indirect +base class already on the list, no error is reported at this time; rather, both +base classes are marked as ambiguous. This is an example of such a case:

    +
    class A { /* ... */ };
    +class B : public A { /* ... */ };
    +class C : public B, public A { /* ... */ };
    +
    +
    +

    The base classes list for C will contain:

    +
      +
    • +
      Indirect base class A (marked ambiguous)
      +
      +
    • +
    • +
      Direct base class B
      +
      +
    • +
    • +
      Direct base class A (marked ambiguous)
      +
      +
    • +
    +

    Only later, if, say, a qualified name using A appeared within a member +function of C, would the base class ambiguity be reported.

    +

    Creating the base classes list is done by scan_base_specifier_list, which +adds direct base classes, and add_indirect_base_classes, which in recording +indirect base classes calls itself recursively as required. Both routines call +fixup_virtual_base_class when a virtual base class is encountered more than +once among the direct and indirect base classes.

    +
    +
    +

    11.4.2. Derivation Path#

    +

    Each base class entry contains a derivation field, which points to one +or more entries of type a_base_class_derivation. (Nonvirtual base +classes will have only one such entry, but virtual bases may have more.) +Each base class derivation entry points to a linked list of one or more +entities of type a_derivation_step. Such a list is referred to as a +“derivation path” because it records the derivation of the derived class +from the base class: it is the path from a derived class back up its base +class tree to the required base class. Here is a simple example:

    +
    class A { /* ... */ };
    +class B : public A { /* ... */ };
    +class C : public B { /* ... */ };
    +
    +
    +

    The derivation path from derived class C to direct base class B is +=>B, whereas the path to indirect base class A is =>B=>A. (The notation => +can be thought of as a cast from a derived to a direct base class.)

    +

    The first step on a derivation path is either a direct base class, as in the +examples above, or a virtual base class. In the latter case, the paths to the +virtual base class (there may be more than one) are elided and may be found by +examining its base class derivation entries. For example:

    +
    class X { /* ... */ };
    +class A : public X { /* ... */ };
    +class B : virtual public A { /* ... */ };
    +class C : virtual public A { /* ... */ };
    +class D : private B, public C { /* ... */ };
    +
    +
    +

    Here the derivation path for X in D is represented as =>A=>X, whereas +A itself has two derivation paths, =>B=>A and =>C=>A, which are in effect +implicit in the derivation for X.

    +

    Base class ambiguity can be seen as a case in which there are two distinct +paths to nonvirtual base class entries that refer to the same class. Returning +to a previous example,

    +
    class A { /* ... */ };
    +class B : public A { /* ... */ };
    +class C : public B, public A { /* ... */ };
    +
    +
    +

    there are two base class entries for A in class C, with derivation +paths of =>B=>A and =>A.

    +

    add_indirect_base_class takes an existing base class entry and creates a +new one based on it, but to do this it needs a new derivation path as well. +copy_and_extend_path creates a new path based on the derivation path of the +original base class entry.

    +

    For cases in which it is necessary to compare two derivation paths, +congruent_paths returns TRUE if two paths refer, step for step, to the same +classes.

    +
    +
    +

    11.4.3. Virtual Base Class#

    +

    When two or more base classes of the same type are specified virtual, they +share the same base class entry. Its position in the base classes list will be +that of first appearance in the depth-first left-to-right traversal of the base +classes. However, each appearance in the derivation graph is recorded with a +separate derivation entry, and each derivation entry gives a unique derivation +path.

    +

    set_preferred_base_class_derivation is called to identify the “preferred” +path of a virtual base class – tantamount to the sequence of casts that +affords the greatest “normal” accessibility (i.e., without special treatment +for casts in the context of member or friend functions). For example,

    +
    class A { /* ... */ };
    +class B : virtual public A { /* ... */ };
    +class C : virtual public A { /* ... */ };
    +class D : private B, public C { /* ... */ };
    +
    +
    +

    Class D is derived from virtual base class A via two paths, BA and CA. +Therefore A‘s base class entry points to a list of two base class +derivation entries, one for each path. Since the path through C gives +greater accessibility, the base class derivation entry that points to CA is the +one marked “preferred”. (When several entries afford equally good access, a +direct base class is preferred over an indirect, and an indirect base class +with no virtual base classes in its derivation is preferred over one that has +virtual base classes in its derivation.)

    +
    +
    +

    11.4.4. Virtual Functions#

    +

    A final task performed by scan_base_specifier_list and its subroutines is +to accumulate virtual function information for its base classes.

    +

    When a function in a derived class “overrides” a virtual function from one of +its base classes, that information is recorded for later use: [6] A list of +entries of type an_overriding_virtual_function is pointed to from the base +class entry to identify the virtual functions that are members of that class +and that are overridden in some other class derived from it. This information +must be propagated as base classes are copied. Here is an example to make this +a bit clearer:

    +
    class A { virtual void f(); };
    +class B : public A { void f(); };
    +class C : public B { };
    +
    +
    +

    A::f() is a virtual function of the base class A that is overridden +by B::f() in the derived class B. The +overriding_virtual_functions field of the base class entry for A in +B points to an entry that identifies A::f() as the primary +function and B::f() as the overriding function. When C is +derived from B, this information is passed along. At the time the base +class entry for A is created in C, the virtual function override +information is copied from the base class entry for A in B, with an +additional piece of information – a pointer to the base class entry for +B in C. [7]

    +

    The virtual function override list is sorted on the basis of the virtual +function number in the routine entry of the primary function. It can be that +more than one overriding virtual function entry for a given primary function +ends up on the overriding virtual function list – and it needn’t be illegal. +Consider the following example:

    +
    class A { virtual void f(); };
    +class B : virtual public A { void f(); };
    +class C : virtual public B { void f(); };
    +class D : public B, public C { };
    +
    +
    +

    Within both B and C there are an overriding virtual function entries +for base class A specifying that primary function A::f() is overridden, +in the one instance by B::f() and in the other by C::f(). Within D +there is also a base class entry for A, and both the overriding by +B::f() and the overriding by C::f() are recorded in its list; both +overriding function entries will refer to the same primary function, +A::f(). As written above, this example is illegal. But the diagnostic +cannot be issued until the definition of D is complete (see +report_virtual_function_ambiguities), since a declaration D::f() would +override both B::f() and C::f(), making the ambiguity moot and the +program legal.

    +

    copy_virtual_function_override_list copies the overriding virtual function +for a base class from one class to another derived from it, calling +insert_in_virtual_function_override_list to place the copy in the proper +sorted location in the new list.

    +
    +
    +

    11.4.5. C++/CLI Derivations#

    +

    C++/CLI managed classes can derive from base classes in two different ways: +They can “inherit” from one ref class and they can “implement” any number of +interface classes. If the definition of a managed class (other than +System::Object) does not specify a base class explicitly, it inherits +System::ValueType if it is a value class, or it derives virtually from +System::Object otherwise (hence, all managed classes ultimately derive from +a virtual base class System::Object). See add_implicit_cli_bases.

    +

    “Implementing an interface” is modeled as virtual derivation. Inheriting from +a ref class other than System::Object corresponds to regular (i.e., +nonvirtual) derivation.

    +

    Some ref classes must implicitly directly derive from (i.e., “implement”) the +System::IDisposable interface according to a set of rules known as the “CLI +dispose pattern” (see implement_dispose_pattern_if_needed). However, this +cannot be determined until after the complete class definition has been seen: +This is therefore a unique situation where a (virtual) base class is added +after members have been seen. When this is done, wrapup_base_classes must +be called a second time.

    +

    Some generated managed classes implicitly inherit specific ref classes (by +calling add_cli_system_base_class): delegate classes inherit +System::MulticastDelegate and boxed enum types inherit System::Enum.

    +

    Generic parameters are modeled using proxy (managed) class types called +“constraint types”. A type constraint specifying a type C on a parameter +modeled by a constraint type P is modeled by adding C as a base class of P. +Note that Microsoft compilers permit “sealed” classes [8] to be specified as +type constraints, which means that in this context a sealed class can be +derived from (and in that case, the deriving constraint type is marked as +sealed also).

    +
    +
    +
    +

    11.5. Fields#

    +
    +

    11.5.1. Declarations#

    +

    scan_nonstatic_data_member is called from class_member_declaration to +process the declarations of what in ordinary C are called “fields” and in C++ +are “nonstatic data members”. It handles parsing of bit field widths and +C++11-style initializers (see below), and calls decl_nonstatic_data_member +to create the actual IL entry (type a_field) and associated symbol (if any) +as well as to do some error checking and set various flags. [9]

    +

    Field symbols point to their corresponding IL entry and also to a field symbol +supplement that carries some additional (mostly C++-specific) information.

    +

    Processing is straightforward for ordinary fields. There are several special +cases that warrant a little more explanation, however.

    +
      +
    • +
      For bit-fields scan_fs_constant_expression is called to scan the size +specified after the colon. It scans the constant value. This constant is +then used by decl_nonstatic_data_member to perform error checking, and, in +a few unusual cases, to modify the field’s type to accommodate the +bit-field (e.g., when a signed integer kind was specified but the bit-field +is too small for a sign bit).
      +
      +
    • +
    • +
      For unnamed fields a field entry is created and added to the IL tree (the +field entry is needed when set_field_size_and_offset is called), and a +symbol is created for it (see unnamed_field_symbol in +symbol_tbl.c). The space allocated by the unnamed field is represented +as a gap left in the layout of the class.
      +
      +
    • +
    • +
      Anonymous union “parent fields” have no names, but they do have an +associated symbol and a field entry in the IL. In addition, +check_anonymous_union_symbols is called both to do error checking and +to promote the symbols for the fields of the anonymous union into the name +scope of the class of which the anonymous union is a member field. This +produces an inconsistency between the IL representation, which is that of +any nested union, and the symbol table representation, where the names of +the fields of the anonymous union are treated as though they were declared +in the containing class – for example, the parent class of the promoted +sk_field symbol is the containing class, but the IL field entries to +which it points continues to be represented as a member of the nested +anonymous union.
      +
      +
    • +
    +

    In addition to actually doing error checking, decl_nonstatic_data_member +also sets some flags in the symbol to facilitate error checking and other +processing at a later time. For instance, if the field’s type is a reference +type, any_ref_member is set in the class symbol supplement; the setting can +then be checked to determine whether the compiler can generate a default +constructor.

    +
    +
    +

    11.5.2. Offset and Alignment#

    +

    The front end is configurable to use either of two models for assigning offsets +to fields. Either a class is laid out so that the fields are allocated exactly +in the order in which they are declared, or else they are grouped by access, +with first the public fields allocated in order of declaration, then the +protected and finally the private fields.

    +

    Processing for both models is done by set_offsets_for_fields, called from +do_class_layout in layout.c. For each field it calls +set_field_size_and_offset, which takes as input offset values left over +from the previous allocation and uses them to allocate the current field. The +maximum alignment required for the structure as a whole is also tracked. The +computations are done in increment_field_offsets, which does overflow +checking on all calculations.

    +

    By default, fields are assigned offsets in declaration order; the other +model is activated by setting +TARG_FIELD_ALLOC_SEQUENCE_EQUALS_DECL_SEQUENCE to 0. However, at +this time only the default allocation model is supported by the IL lowering +pass.

    +
    +
    +

    11.5.3. Field Initializers#

    +

    C++11 allows a field initializer (also known as a DMI – default member +initializer – or, previously, an NSDMI – non-static data member +initializer) to be specified on a field declaration. For example:

    +
    struct S {
    +  int i = init_val;
    +  static int init_val;
    +};
    +
    +
    +

    The initializer must be parsed in the context of the completed class (which, +e.g., means a field initializer can make use of a member that is declared at a +point that is lexically after the initializer). To achieve this, +scan_nonstatic_data_member caches the initializer for later parsing. In +the case of nontemplate classes, this later parsing is handled by recording a +fixup entry (by calling record_inclass_initializer_fixup) which is later +processed by a call to inclass_initializer_fixup (when the class is +completed), and that in turn calls field_initializer (in decl_inits.c) +to actually parse and record the initializer. For template classes, the +initializers are not parsed until they’re needed. If a field initializer of a +template class must be accessed by the front end, it must call +instantiate_field_initializer_if_needed prior to examining the IL for that +initializer (recorded in a_field::initializer). In the template case also +field_initializer is the routine that performs the actual parsing of the +initializer.

    +

    Field initializers are subject to various error checks. One of the more subtle +checks in this context is for circular dependencies: The initializer for a +field may depend on that field’s value in various indirect ways. The front end +will diagnose this if the circularity affects compile-time evaluation +(particularly, when dealing with constexpr constructors).

    +
    +
    +
    +

    11.6. Static Data Members#

    +

    decl_static_data_member is called to process declarations of static data +members. It creates a variable entry (typically with sc_extern storage +class – it will later be changed to sc_unspecified if it is defined in the +current translation unit) and appends it to the variables list of the IL +scope entry for the current class. It also creates a symbol entry of kind +sk_static_data_member and enters it into the symbol table.

    +

    When a static data member of integral type is declared as const-qualified +and an initializer appears in the in-class declaration, it is usable as a +member constant. The initializer expression is scanned by +scan_member_constant_initializer_expression, and the variable is flagged +with is_member_constant set to TRUE.

    +

    Definitions of static data members, with optional initializer, are handled as +part of normal declaration processing, where define_static_data_member is +called from function_definition. Aside from setting a few flags, little +needs to be done except some error checking.

    +
    +

    11.6.1. C++/CLI Static Data Members#

    +

    Static data members of C++/CLI managed classes can have an initializer when +they’re first declared in the class, and that declaration is then considered to +be a definition. Unlike standard static data members, there are no type +restrictions for this in-class initialization to be permitted and any +initializer that would be allowed in namespace scope can be specified.

    +

    Furthermore, such initializers are by default not processed until the complete +class definition has been seen [10]. This parallels the standard treatment +of in-class function definitions and in-class default arguments. However, if +the value of the static data member is needed to evaluate a +constant-expression, the initializer is processed at that point (i.e., early; +see ensure_inclass_static_member_constant_initializer_is_scanned).

    +
    +
    +
    +

    11.7. Member Functions#

    +

    decl_member_function is called to complete processing a member function +declaration, but the work has already been started by function_declarator, +which needs to recognize member function declarations for two reasons:

    +
      +
    • +
      Default arguments in parameter declarations are not passed to +expression-scanning routines immediately; rather, the tokens are cached and +scanned only once the entire class declaration has been completed.
      +
      +
    • +
    • +
      After the parameters have been scanned, an optional const or +volatile qualifier may be present on nonstatic member functions. And +whether the qualifier is there or not, the type of the implicit this +parameter is determined in function_declarator and the routine type +supplement for the member function’s routine type entry is updated +accordingly.
      +
      +
    • +
    +

    Consequently, even before decl_member_function is called, quite a bit of +processing has been done on member functions. What remains is to create a +symbol entry and a routine entry for the member function, add the symbol to the +symbol table, and append the routine entry to the routines list of the IL +scope entry for the current class. Some special processing is required for +overloaded functions, for virtual functions, for constructors and destructors, +for user-defined conversions, and for operator functions. The field +special_kind of a_routine entries identifies special member functions +(like constructors, destructors, operators, C++/CLI accessors, etc.); it is set +to sfk_none for ordinary member functions (and non-member functions).

    +
    +

    11.7.1. Static vs. Nonstatic#

    +

    As noted above, a nonstatic member function receives special treatment in +function_declarator: the implicit_this_param_type field of the routine +type supplement is updated with a pointer to the (optionally qualified) class +of which the function is a member. In a static member function this pointer +remains NULL. This is the only way static and nonstatic member functions are +distinguished in the IL. routine_type_is_nonstatic_member_function is a +macro that is available to test the field.

    +
    +
    +

    11.7.2. Overloading#

    +

    Function overloading is a matter for name lookup only – that a function is +overloaded is not explicitly represented in the IL. The general technique for +supporting function name overloading with sk_overloaded_function symbols is +discussed in detail in the chapter on the Symbol Table.

    +

    Entering a new member function symbol in a way that takes overloading into +account is handled by symbol_for_member_function. One of the subroutines +it calls is member_function_redecl_sym, which checks for type +compatibility, recognizing when the type of the implicit this parameter +should be ignored and when it must be taken into account.

    +

    In addition to sk_member_function symbols, the overload set may include +sk_projection symbols representing using-declarations and +sk_function_template symbols representing member function templates.

    +
    +
    +

    11.7.3. Virtual Functions#

    +

    A member function may be explicitly declared virtual, or it may be a +virtual function implicitly, because of having the same name and type as a +virtual function from a base class. In either case, for every member function +it is necessary to go through all the base classes and look for functions with +the same name and type. Then, if the original function is virtual for either +reason, not only must it be so marked, but it is also necessary to record the +fact that a virtual function from a base class is overridden by a function from +a derived class. This, as already described in another context, is done with +entries of type an_overriding_virtual_function.

    +

    decl_member_function calls check_for_virtual_override to accomplish all +this. The latter does the search through the base classes for overridden +virtual functions, and when it finds one it calls +record_virtual_function_override to add an entry to the +overriding_virtual_functions list in the base class. When an entry that +refers to the same primary function is already there (as a result of an +override by an inherited function), that entry is updated to record the +override by the current class’s member. When more than one such entry is on +the list, the extras are removed, since the ambiguity is resolved by the +current declaration.

    +

    After all declarations of the current class have been processed, +scan_class_definition calls set_virtual_function_numbers to assign +sequential numbers to nonoverriding virtual functions declared in the current +class. (Overriding virtual functions will have already been assigned the +number of the associated base class function.)

    +

    Then it calls report_virtual_function_ambiguities, which makes another pass +over the base classes to look for ambiguous virtual function overriding – it +issues errors when such ambiguities, caused by merging overriding virtual +function lists from several base classes, are not resolved by a member function +declaration in the current class.

    +
    +
    +

    11.7.4. Default Arguments#

    +

    Default arguments specified for parameter declarations in member function +declarations require special handling, because the expressions must not be +scanned until all the member declarations in the class have been scanned. +Parameter declarations are scanned in function_declaration. When a default +argument is encountered in a member function declaration that is part of a +class definition, prescan_default_arg_expr is called to cache the tokens +that make up the expression; the cache resides in an entry of type +a_def_arg_expr_fixup, which is kept on a list pointed to by an entry of +type a_routine_fixup that is accessed from the class symbol supplement. +When the class’s member declarations are complete, that list is revisited and +the default argument expression is rescanned (see +delayed_scan_of_default_arg_expr, which is called from +delayed_scan_fixup_for_class).

    +
    +
    +

    11.7.5. Inline Definitions#

    +

    When a member function body appears within a class definition, it is handled +somewhat like default argument expressions: prescan_function_definition is +called to cache the tokens that comprise the function body (the cache resides +in an entry of type a_routine_fixup), and when the class definition is +complete, delayed_scan_fixup_for_class calls scan_function_body (in +func_def.c) to process the function body retroactively. (For constructors +that are defined inline, the constructor initializer list is included among the +cached tokens, and ctor_initializer (in decl_inits.c) is later called +to scan it.)

    +

    A somewhat special case occurs when inline definitions and default argument +expressions appear within a nested class: the language definition requires that +a reference to a name in the enclosing class be found even if that name is +declared after the nested class definition is complete. For instance,

    +
    struct Outer {
    +  struct Inner {
    +    static int f() { return i; }
    +  };
    +  static int i;
    +};
    +
    +
    +

    Since a call to Inner::f() should return the current value of Outer::i, +the body of Inner::f() cannot be processed until all the members of +Outer have been seen. Therefore the delayed scan fixup list for a nested +class is not rescanned until its outermost containing class has been completely +scanned. Only then does scan_class_definition call +delayed_scan_fixup_for_class, which in turn calls itself recursively for +nested classes before processing the tokens cached for the members of the class +passed to it.

    +
    +
    +

    11.7.6. User-Defined Conversions#

    +

    When decl_member_function is called for a user-defined conversion, it +creates an entry of type a_conversion_list_entry to record the existence of +the conversion routine in the class symbol supplement for the current class. +The entry simply points to the symbol for the user-defined conversion; all such +routines for a given class are accumulated on a linked list.

    +

    Since conversion functions are functions that convert an object of the current +class to a specified result type, the list that is created can serve as a list, +for a given source type, of all the target types for which a user-defined +conversion exists. This kind of list can be useful in selecting the +appropriate implicit cast during expression processing.

    +

    User-defined conversion functions are inherited, so after all member +declarations have been seen, the list is augmented by projection symbols for +inherited conversion functions that result in types that are not already +present in the list (see project_base_class_conversion_functions which goes +through the conversion lists for each of the direct base classes of the current +class looking for unrepresented result types).

    +
    +
    +

    11.7.7. Compiler-Generated Functions#

    +

    A default constructor or a copy constructor is created by the compiler when it +is required in a class but was not explicitly declared by the user. Likewise a +compiler-generated destructor may be needed, or an assignment operator which +effectively copies an object of a given class onto another object of the same +class. Even if one of these functions is needed, only a declaration is +generated at first, not a function body. The body is generated only when there +is an actual invocation of the function. The functions will be declared as +extern inline member functions, just as if they had been explicitly defined in +the class definition.

    +

    After all member declarations have been scanned, +check_special_member_functions is called. For each compiler-generated +function determined to be needed, it calls generate_special_function, which +creates a routine type entry and calls decl_member_function to create the +symbol and the routine entry.

    +

    reference_to_implicitly_invoked_function is called when a +compiler-generated function is implicitly invoked. If the function has no +body, define_special_member_function (in func_def.c) is called, which +in turn calls make_default_constructor_body, +make_default_destructor_body, or make_default_assignment_body. The +compiler-generated assignment function is created only when a simple struct +copy is insufficient, i.e., when memberwise copying must be done explicitly.

    +

    Trivial default constructors present a special problem. They are “trivial” +because calling them has no actual effect, so an obvious optimization is to +eliminate them. When the symbol supplement for a class has a NULL +constructor pointer, that means the implicitly declared default constructor +for the class (always present in principle) is trivial and can generally be +ignored. There is an exception, however, when the definition of a trivial +default constructor would be ill-formed: then, even though no call is put out +in the IL, a diagnostic must still be issued. Here’s an example:

    +
    class A {
    +  const int i;
    +};
    +A var;
    +
    +
    +

    Since class A is not a “POD-struct”, var is default-initialized, which +means the default constructor A::A() is supposed to be called, and calling +an implicitly-declared constructor normally triggers its definition. The call +can be optimized away since it has no effect, but the definition would be +ill-formed (because A::i is const-qualified). So to preserve the +behavior as if A::A() were called, its declaration is saved in the symbol +(see trivial_default_constructor in the class symbol supplement) and its +definition is generated at the point of implicit reference by a call to +reference_to_trivial_default_constructor in symbol_ref.c.

    +
    +
    +

    11.7.8. C++/CLI Member Functions#

    +

    C++/CLI adds several variations for member function declarations in managed +classes.

    +

    Syntactically, a static constructor is like a default constructor (i.e., with +no parameters) declared with the storage class static. The two can +coexist, but they don’t create an overload set. In expression contexts, +default construction always refers to the nonstatic constructor kind. In +declaration contexts, the static constructor is only found if the declaration +includes static (which is communicated to the lookup functions with the +flag IDL_IS_STATIC_DECL). Static constructors are the only members that +can be defined outside their parent class with an explicit storage class +specifier (and such definitions must include that static specifier).

    +

    Managed classes can contain finalizers: Their handling is completely parallel +to that of destructors. The syntax uses “!X” instead of “~X”.

    +

    User-declared accessor functions for properties and events are explained in +C++/CLI Managed Class Definitions. For trivial properties and events (which don’t +include user-declared accessors), accessors are generated by calls to +generate_trivial_accessor. Whether generated or user-declared, the +a_routine for an accessor function points to the +a_property_or_event_descr entry associated with the corresponding event or +property.

    +

    The member function modifiers sealed, abstract, and override are +accepted in both ordinary Microsoft mode and in C++/CLI mode. They can appear +after the optional const and/or volatile at the end of a nonstatic member +function declarator (see scan_microsoft_function_modifiers), but in C++/CLI +override is not optional for derived class members that override a member +in a base ref class. The modifier new is also accepted at this grammatical +location to indicated that a function does not implicitly override a virtual +base member with the same name and type.

    +

    A virtual member function can also specify specific base members it overrides +using a specifier like “= B::m, C::n” where B and C are the base +classes or interfaces whose respective members m and n are +overridden/implemented. This is called “named overriding” (in contrast to +“implicit overriding”).

    +

    Named overriding and the requirements of the override and new modifiers +are mostly handled in check_for_virtual_override and its helper functions. +These features add considerable complexity to that function.

    +
    +
    +
    +

    11.8. Member Function Templates#

    +

    scan_class_definition calls template_declaration_or_directive (in +templates.c) when a member declaration begins with the keyword +template. When the declaration designates a function template, this +results in a call to class_member_template_declaration, which in turn calls +class_member_declaration. Once processing by decl_specifiers and +declarator has been done, decl_member_function_template is called to +create the sk_function_template symbol. A routine entry is also created, +but (as with nonmember template functions) it is not added to the IL. Rather, +it is attached to the template symbol supplement and is for front-end use only.

    +
    +
    +

    11.9. Member Constant Extension#

    +

    As an extension to C++ the EDG front end allows “member constant” declarations. +[11] Member constants may be of any scalar type. For integers such a +declaration is similar to declaring a constant name in an enum declaration. +For example, instead of this:

    +
    class A {
    +  enum { MAX = 100 };
    +  int array[MAX];
    +};
    +
    +
    +

    the program may declare and use a member constant:

    +
    class A {
    +  const int MAX = 100;
    +  int array[MAX];
    +};
    +
    +
    +

    Qualified-name references to member constants (e.g., to A::MAX) are also +permitted, subject to the same access and ambiguity constraints imposed on any +class member.

    +

    class_member_declaration calls decl_nonstd_member_constant to process +such a declaration. It adds to the IL an entry of type a_constant (it is +appended to the constants list of the IL scope associated with the current +class), and it enters an sk_constant symbol that points to it. Note that a +member constant is not equivalent to an initialized const static data +member, which is represented as a variable in the IL.

    +
    +
    +

    11.10. Friend Declarations#

    +

    A friend declaration involves (1) a class which gives friend access to +nonmembers and (2) the routine or class to which that access is given; and so +one may refer to the former as the befriending class and the latter as the +befriended routine or class.

    +

    The class type supplement of the befriending class contains pointers +(friend_routines and friend_classes) to linked lists of entries +identifying the routines and classes to which friendship is given. This +corresponds to the way in which a friend declaration actually appears in the +source.

    +

    In addition, the befriending-befriended relationship is represented the other +way around as well, with the befriending class also recorded in the befriended +routine or class. Specifically, routine entries have a pointer to a list of +entries that point to classes; the linked list identifies the befriending +classes, those that afford friend access to the specified routine. A +similar befriending_classes field can be found in the type supplement for a +befriended class.

    +

    decl_friend_function is called by class_member_declaration to process a +friend function declaration. For a member function +member_function_redecl_sym is called to get the symbol; otherwise, +decl_routine in decls.c is called (where, if this is the first +declaration of the function, the symbol will be created in the appropriate +non-class scope). Once the symbol is retrieved, the current class is recorded +as a befriending class in the routine entry.

    +

    decl_friend_class is called to process a friend class declaration. +This is just a matter of recording the current class as a befriending class in +the type supplement of the befriended class.

    +

    A class- or namespace-qualified friend declaration must refer to a +previously declared entity, but it may be that the first declaration of an +entity is an unqualified friend declaration. The lookup for an +unqualified friend declaration begins in the innermost enclosing +nonclass scope and continues to (but no farther than) the innermost +enclosing namespace scope, and if it is not found a declaration is +“injected” into the innermost enclosing nonclass scope. [12] For +instance:

    +
    namespace N {
    +  class S {
    +    friend void f();
    +    /* ... */
    +  };
    +  void f() { /* ... */ }   // Same "f" as declared a friend by N::S
    +}
    +
    +
    +

    This approach is taken even when the specified name is visible in a scope +enclosing the innermost namespace scope – in the above example, f would be +injected into namespace N even if a ::f were visible.

    +
    +
    +

    11.11. Using Declarations and Access Declarations#

    +

    A using-declaration inside a class definition is processed by +member_using_declaration, which is also called when +scan_class_definition encounters a declaration that is a class-qualified +name followed by a semicolon, interpreted to be an old-style access declaration +of an inherited member. member_using_declaration performs error checking +and causes a projection symbol to be created to reserve the name in the current +class. The flag is_using_decl is set in the projection symbol, since this +is not an ordinary kind of projection and is subject to somewhat different +rules for computing accessibility; [13] it can also be added to an overload +set if it refers to an inherited member function. In addition, the declaration +is recorded in the IL by adding an entry of type a_using_decl to the scope +associated with this class, in case a symbolic debugger would need the +information (see make_using_decl indecls.c).

    +
    +
    +

    11.12. Delegates (C++/CLI mode)#

    +

    A C++/CLI delegate is a managed function object (i.e., a “callable” object) +that encapsulates an invocation list. A delegate type is introduced by a +delegate definition, which looks like a typedef for a function type where the +keyword typedef is replaced by a context-sensitive keyword delegate. +The front end represents a delegate type as a mostly ordinary ref class type +synthesized from the signature provided in the definition. For example, a +definition like

    +
    delegate void D(System::Object^);
    +
    +
    +

    causes the front end to synthesize (in create_cli_delegate_definition) +a ref class called D, implementing the interface +System::MulticastDelegate with (among others) a member function called +Invoke with the signature of the delegate definition (to which “calls” +of delegate objects are dispatched), a constructor, and static member +operators + and - (to add or remove targets from the encapsulated +invocation list).

    +
    +
    +

    11.13. Properties and Events (Microsoft and C++/CLI modes)#

    +

    Microsoft C++ includes a notion of “property” members for (otherwise +standard) class types. Syntactically, this is a field declared with an +attribute of the form __declspec(property(get=func_name1, +put=func_name2)). The result is not really a field: No storage +is allocated for it, but every “read” operation on the pseudo-field is +mapped to a call of func_name1 and every “write” operation is mapped to a +call of func_name2 (either operation name may be omitted from the +attribute to create a read-only or write-only property). The IL +representation of this kind of property members uses a_field entries, +which point to entries of type a_property_or_event_descr, and those +entries in turn record the name of the specified get and/or put functions. +func_name1 and func_name2 are looked up at every point that requires +their use, which may not always yield consistent results. Therefore, the +rewriting of property-field accesses is done right away in the front end +proper (and not, for example, in a later lowering pass since the symbol +table might have changed by then).

    +

    C++/CLI provides a similar notion of properties for managed class types, but +instead of indicating the “accessor functions” (named get and set in +this case) by name in an attribute, they are part of the property definition +syntax. For example:

    +
    ref struct RS {
    +  property int p { int get(); void set(int); }
    +};
    +
    +
    +

    The IL representation is similar to that of the first kind of property (i.e., +the non-C++/CLI variant described above), but since the accessor functions are +independent from the point of use in this case, the corresponding a_routine +entries are pointed to directly from the a_property_or_event_descr entry +and vice versa. Also, since C++/CLI properties can be static or nonstatic, +their representation can be entries of type a_field and a_variable (the +latter corresponding to a pseudo-static-data-member).

    +

    C++/CLI properties can be “indexed” to model a sort of “array field” (but +unlike regular fields, indexed properties can be truly multidimensional). +Furthermore, such indexed properties can be overloaded:

    +
    ref class RC {
    +  property double ip[double, int] {
    +    double get(double, int);
    +    set(double, int, double);
    +  }
    +  property float ip[float, int] {
    +    float get(float, int);
    +  }
    +};
    +
    +
    +

    Because of this possibility, the symbol representing a property in a class has +a kind sk_property_set, which reflects that it potentially represents a set +of properties (unlike function symbols, there is no separate symbol kind for +single properties and overloaded sets). sk_property_set symbols point to a +structure of type a_property_set_symbol_supplement, which in turn points +both to the associated pseudo-data-members (sk_field or +sk_static_data_member) and to the overload sets formed by their get and +set accessors respectively.

    +

    Indexed properties can have the name default: Applying a subscript to such +a property’s parent object amounts to a use of such a property (this has some +similarity to the more traditional operator[]). If any such +default-indexed properties are present in a class, the corresponding +sk_property_symbol is pointed to from the class’ symbol supplement.

    +

    C++/CLI has a notion of “event” members. These are similar to C++/CLI +properties, but they cannot be indexed, must have handle-to-delegate type, and +they allow only three operations: +=, -=, and “call”. An event +definition can declare up to three accessors (matching the aforementioned three +operations) called add, remove, and raise, or it can be “trivial” +(in which case those accessors are generated by the front end). Since events +cannot be indexed, they cannot be overloaded, and no separate symbol kind is +needed for them: They’re simply associated with the sk_field or +sk_static_data_member symbol for their pseudo-data-member.

    +
    +
    +

    11.14. Class Object Layout#

    +

    Laying out the storage for a class means computing the overall size of an +object of that type and assigning to each of its components an offset +representing its position in the object. Nonstatic data members are +represented by entries of type a_field, each of which has an offset +value that represents the byte offset from the beginning of the object and a +offset_bit_remainder value (nonzero for bit fields only) that represents +the additional bits that must be taken into consideration if the field is not +aligned on a byte boundary. Base classes have an offset field that +contains the byte offset from the beginning of storage for the class as a whole +to the beginning of storage for the base class’s data section; for virtual base +classes there is also a pointer_offset field, which is the offset of the +pointer to the data section. The class type supplement also has a +virtual_function_info_offset field. All these offset values together make +up the abstraction we refer to as the class’s layout.

    +
    +

    11.14.1. Object Layout Models#

    +

    The front end provides by default two distinct object models: a “classic” model +based on the original cfront implementation and a more modern “IA-64” model +based on specifications drafted by a group of vendors for the 64-bit Itanium +Architecture of Intel. At the time of this writing, the latter specifications +can be found at:

    +
    +
    +

    The implementation of both models can be found in layout.c. Where +convenient, the same routines are used to implement the two models (e.g., there +is only one do_class_layout function).

    +

    The front end can also be configured to implement small variations of both the +cfront-like and IA-64 models. For the cfront-like model, increased +compatibility with the original cfront implementation can be achieved by +setting CFRONT_OBJECT_CODE_COMPATIBILITY to TRUE (this involves routines +whose names start with cfc_). Similarly, by setting +DEFAULT_EMULATE_GNU_ABI_BUGS to TRUE, improved compatibility is achieved +with the default IA-64-based ABI implemented by GNU C++ 3.2 (and this involves +routines in layout.c whose names start with the gnu_ prefix).

    +
    +
    +

    11.14.2. General Layout Steps#

    +

    All classes are laid out in the same general way, following this pattern (in +the sequence indicated):

    +
      +
    • +
      First, in the IA-64 model, storage is reserved for the so-called primary +base class (if it exists) or for a pointer to a virtual table (if the +class is polymorphic without having a primary base):
      +
      +
        +
      • +
        There is no primary base class concept in the cfront-like object model.
        +
        +
      • +
      • +
        The primary base class shares a “virtual pointer” at offset zero with the +complete class. Usually, the primary base class is a nonvirtual direct +base class, but it can also be indirect and/or virtual in less common +situations. If none of the base classes are polymorphic, the derived +class has no primary base class. The primary base class is also pointed +to from the class type supplement (by the field primary_base_class).
        +
        +
      • +
      • +
        No storage is allocated for non-primary virtual bases of the primary base +class at this point.
        +
        +
      • +
      +
    • +
    • +
      Next, storage is allocated for all the remaining direct base classes +(which implicitly includes storage for nonvirtual indirect base +classes as well):
      +
      +
        +
      • +
        In the cfront-like model, when the direct base class is also virtual, +only enough space is set aside for a pointer to the actual storage, +which appears later. In the IA-64 model, no such pointer is used and +– unless it is also the primary base – the direct virtual base is +allocated later on.
        +
        +
      • +
      • +
        In the case of a nonvirtual direct base class, enough storage is set +aside for its own primary base class (if any), its nonvirtual base +classes, its virtual base class pointers (in the cfront-like model), its +own fields, and its virtual function information, but no space is +allocated for its virtual base classes.
        +
        +
      • +
      • +
        In the cfront-like model, nonvirtual direct base classes that are empty +(no own or inherited nonstatic data members and no virtual functions or +direct or indirect virtual base classes) are allocated in a separate pass +when targ_optimize_empty_base_class_layout is TRUE. In the IA-64 +model, direct empty bases are allocated in the same pass as nonempty +bases. (See The Empty Base Class Layout Optimization).
        +
        +
      • +
      +
    • +
    • +
      Next, storage is reserved for the class’s own fields.
      +
      +
    • +
    • +
      Next, in the cfront-like model, storage for virtual function information +(typically, a pointer to a virtual function table).
      +
      +
    • +
    • +
      Finally, storage for its virtual base classes, with space enough in each +case for its own primary and nonvirtual base classes, virtual base class +pointers (cfront-like model only), fields, and virtual function +information.
      +
      +
    • +
    +

    The storage and alignment for all the items but the last are recorded in the +class’s type supplement as size_without_virtual_base_classes and +alignment_without_virtual_base_classes; the size and alignment +fields of the type entry itself record the values for the entire object. +Except in an incomplete type, both size values will be at least 1.

    +

    This general sequence is implemented by do_class_layout, which is called by +scan_class_definition once all the members have been scanned. +do_class_layout calls several subroutines:

    +
      +
    • +
      set_offsets_for_nonvirtual_base_classes to assign the offsets for +nonvirtual base classes;
      +
      +
    • +
    • +
      set_offsets_for_fields to set the offset and +offset_bit_remainder values of each field;
      +
      +
    • +
    • +
      set_offset_for_virtual_function_info to record the position at which +(typically) the virtual function table pointer will be found;
      +
      +
    • +
    • +
      set_offsets_for_virtual_base_classes to lay out the part of the class +object where the data sections of virtual bases classes are kept; and
      +
      +
    • +
    • +
      set_offsets_for_indirect_base_classes to record the offsets of indirect +nonvirtual base classes (this phase is really just a fixup pass – no new +storage is reserved).
      +
      +
    • +
    +
    +
    +

    11.14.3. The Empty Base Class Layout Optimization#

    +

    The C++ language specifications allow an implementation to allocate an empty +base subobject at the same location as another subobject provided this does not +cause two objects or subobjects of the same type to be allocated at the same +address. For example:

    +
    struct E {};
    +struct A: E { char c; };
    +struct B: E { E e; };
    +
    +
    +

    In A, the base class E can be allocated at the same offset as the field +c, but in B the optimization cannot be applied because two subobjects +of the same type (the field and the base) would occupy the same address.

    +

    In the cfront-like model, the front end implements this optimization when +targ_optimize_empty_base_class_layout is TRUE and most of the required work +is performed in set_offsets_for_empty_nonvirtual_base_classes. The +cfront-like optimization heuristic uses a two-pass algorithm:

    +
      +
    • +
      First the direct nonvirtual nonempty direct base classes are allocated as +usual; i.e. empty base classes are skipped.
      +
      +
    • +
    • +
      Next, an additional pass is made in +set_offsets_for_empty_nonvirtual_base_classes to place the direct +nonvirtual empty base classes. The first offset to be attempted is the +origin of the object (i.e., zero). If a situation is detected that +would cause two subobjects with the same type to be allocated at the +same offset, a new offset is sought after the next allocated base (if +one is available). This is repeated for every empty base – without +backtracking the offset – until there are no more empty bases.
      +
      Another example illustrates how the second pass is a single pass (i.e., +the offset if not backtracked):
      +
      +
      struct E1 {}; // Empty
      +struct E2: E1 {}; // Empty
      +struct E3 {};
      +struct B { E1 e; } // Not empty
      +struct D: E1, E2, E3, B { char c; };
      +// Layout:
      +//   B : this+0. (a nonempty base is allocated in the first pass)
      +//   E1: after B because at this+0 it conflicts with B::e.
      +//   E2: at least one byte farther than direct base E1 because else
      +//          E2::E1 conflicts with base E1.
      +//   E3: same offset as E2 since there is no type conflict; there is,
      +//       however, no backing up to the offset of direct base E1.
      +//   c : same offset as E2 and E3.
      +
      +
      +
      +
      The optimization can only be applied to empty base classes and not to empty +(nonstatic) data members. Hence, B cannot be considered empty in this +last example.
      +
      +
    • +
    +

    In the IA-64 model, empty base classes are allocated in the same pass as other +direct nonvirtual base classes. In this case the heuristic is different: If +the base can be allocated at offset zero without causing a conflict with a +subobject that has already been allocated there, then that is where the empty +base class is allocated. Otherwise, it is allocated at the next available +offset. Every time a base class is allocated (whether empty or not), +base_subobject_conflict is called: If a conflict is detected, the +allocation is retried at the next alignment boundary. This process is repeated +until there is no conflict. A similar process is needed for the first field +(to avoid having an empty base of a field end up at the same offset as an empty +base of the complete class).

    +

    The IA-64 model also handles the concept of a nearly-empty base class: This +is a virtual base class whose storage requirement is limited to a virtual table +pointer and (optionally) its own virtual base classes. Such a class can be +selected as a primary base class, in which case it is allocated at offset zero.

    +
    +
    +
    +

    11.15. Deferred Class Fixup#

    +

    As mentioned above, default arguments, inline member function bodies, and field +initializers are not processed until the entire class definition has been seen; +and when the class is a nested class, the processing is deferred until the +definition of the outermost containing class has been completed.

    +

    However, it gets even more complicated when templates are involved. Consider +this example:

    +
    template <class T> class A {
    +  void f(T* = new T) { ... }
    +};
    +class B {
    +  A<B> x;
    +} b;
    +
    +
    +

    Here, the instantiation of A<B> is kicked off before the definition of +B has finished, but the default argument expression for A<B>::f(B*) +requires that B be complete.

    +

    To accommodate cases like this, the default argument and inline function body +processing is deferred until all pending class definitions have completed. +(The definition of B is pending when the definition of A<B> is +finished, so the fixup for the latter is deferred.)

    +

    scan_class_definition calls +process_deferred_class_fixups_and_instantiations, and if global variable +pending_class_definitions is zero, +process_deferred_instantiation_requests (in templates.c) and +process_deferred_class_fixups are called.

    +

    The latter calls delayed_scan_fixup_for_class, which scans the token caches +saved for default arguments and function bodies. First it pushes a class +reactivation scope. Then, for default arguments it pushes a function prototype +scope and calls delayed_scan_of_default_arg_expr (or, for class template +instances, delayed_scan_for_function_template_default_args). For function +bodies it calls scan_function_body – except that the scanning of inline +member function bodies inside a class template instance is further deferred +until the member function has actually been referenced.

    +

    A similar mechanism is also used to delay processing of in-class initializers +for nonstatic data members in C++11 mode and of static data members of C++/CLI +managed classes; see record_inclass_initializer_fixup and +inclass_initializer_fixup_for_class.

    +
    +
    +

    11.16. Class Linkage#

    +

    Like functions and variables, a class has linkage recorded in the +source_corresp.name_linkage field of its type entry. Ordinarily (i.e., +except in cfront-compatibility mode), when a class is first created, it is +given external linkage by default, except for local classes (which have no +linkage) and classes declared inside an unnamed namespace (which have internal +linkage). This setting in turn determines the linkage and storage class +applied to class members.

    +

    In cfront mode, however, when a class is first created, it is given internal +linkage by default, and, since the class and its members are supposed to have +the same linkage, its members also have internal linkage (and correspondingly a +storage class of static). These are provisional settings, however, since +the presence of a non-inline member function or a static data member requires a +class to become externally linked. Moreover, if a class is referenced in a +declaration of an externally linked entity, it needs to have external linkage. +Thus, at the end of translation unit processing check_class_linkage is +called (in cfront-compatibility mode only) to make a pass over all the classes +defined in the translation unit and, where appropriate, to fix up the linkage +and storage class of classes and their members.

    +
    +
    +

    11.17. Lambdas#

    +

    A C++11 lambda expression is essentially a shortcut to define a “function +object” class and initialize a temporary object of that class. For example:

    +
    int f(int x) {
    +  auto f_impl = [x]()->int { return x*2; };
    +  return f_impl();
    +}
    +
    +
    +

    is largely equivalent to:

    +
    int f(int x) {
    +  class _Closure {
    +    int x;
    +  public:
    +    int operator()() const { return x*2; };
    +  };
    +  _Closure f_impl = (_Closure){ x };
    +  return f_impl();
    +}
    +
    +
    +

    The implementation of lambdas in the front end exploits this equivalence: When +expression processing encounters the beginning of a lambda expression, it hands +over the task of parsing the construct to scan_lambda (see +Scanning Operations). This routine calls make_closure_class, pushes +an associated class scope on the stack (after captures have been scanned – see +below), and records a synthetic a_class_def_state structure to go along +with the class definition scope. This allows the lambda to be parsed much as +if it were an in-class definition of a member function.

    +

    scan_lambda also creates the a_lambda entry and records it in the scope +stack entry for the closure class. That allows, e.g., expression and statement +processing to be aware of the lambda context. The convenience function +get_current_lambda is also useful for this purpose. The type entry for the +closure class does not itself directly point to the associated lambda (due to +memory region constraints), but its class type supplement has a flag indicating +that it is a lambda closure class type (rather than a user-defined class type).

    +
    +

    11.17.1. Explicit and Implicit Captures#

    +

    The C++11 lambda syntax allows for the optional specification of an implicit +capture mode and explicitly captured local variables and expressions (the +latter are often referred to as “init-captures”). scan_lambda_capture_list +parses this construct and records it in the a_lambda entry. Explicitly +captured variables are recorded with a call to add_lambda_capture and +explicitly captured expressions are handled by a call to scan_init_capture. +The fields associated with these explicit captures are added by a call to +decl_lambda_capture_fields (after the closure class definition scope has +been pushed and after the optional lambda declarator has been processed).

    +

    If an implicit capture mode has been specified (using the “[= … ]” +or “[& … ]” forms of the lambda capture list), +add_lambda_capture is also the routine that records the capture (it also +creates the associated field in the implicit capture case). However, in such +cases we get there via lambda_capture_for_variable, which is called from +the expression scanning routines while parsing the lambda body (ultimately, via +scan_identifier–see Scanning Identifiers).

    +
    +
    +

    11.17.2. The “Lambda Declarator”#

    +

    The syntax to describe lambda parameters, return type, and mutability is +optional and, when present, it differs from the ordinary member function +declaration syntax. Still, the function scan_lambda_declarator is much +simplified by reusing function_declarator. (function_declarator is +also used when parsing ordinary functions/operators, and is aware of the +enclosing class definition environment.) Similarly, +decl_call_operator_for_lambda – which creates the operator() member of +the closure class – mostly relies on decl_member_function and +decl_member_function_template.

    +

    For generic lambdas (a C++14 feature), the lambda declarator corresponds to the +declarator of a function template, where the template parameters are created +implicitly from the use of auto as a parameter type. For example:

    +
    [](auto p) { return p*2; }
    +
    +
    +

    creates a closure class with an operator() that is a member template +corresponding to:

    +
    template<typename _T> auto operator()(_T p) { return p*2; }
    +
    +
    +

    The front end implements this by prescanning the lambda declarator to record +information about auto parameters. If there are any such parameters, +set_up_generic_lambda_declarator_scan then proceeds to set up a member +function template declaration environment. decl_specifiers also uses the +information gathered during the prescan to map occurrences of auto in +the parameter list to the appropriate template parameter type (see +process_generic_lambda_param_type).

    +

    a_func_info_block has been augmented with a pointer to the associated +a_lambda when applicable, and some lambda-specific behaviors of +function_declarator (e.g., mutable as a function qualifier instead of +cv-qualifiers) make use of it.

    +

    If no return type is specified explicitly for the lambda, the return type is +temporarily set to the unknown type (tk_unknown). +scan_return_expression is aware of this arrangement, and it will update the +return type if appropriate. After the lambda body has been scanned +scan_lambda sets the return type to void if no return statement was +seen (through check_implicit_lambda_return_type, which also performs other +language-mandated checks if the return type was implicitly determined by a +return statement).

    +
    +
    +

    11.17.3. Scanning the Lambda Body#

    +

    The lambda body is parsed by scan_function_body as would the body of a +member function of a user-defined class type (or via +function_prototype_instantiation, in the case of a generic lambda). There +are however a few subtle differences involved for the lambda case.

    +

    First, scan_function_body is called while the class scope is still active. +This is needed so that closure fields associated with implicit captures can be +generated. So the option SFB_NO_CLASS_REACTIVATION is passed to +scan_function_body to avoid reactivating the scope of the not-yet-completed +closure class.

    +

    Second, if IL lowering is enabled, the function body is not lowered when the +associated function scope is popped. Instead, that lowering is triggered by a +call from scan_lambda to finish_function_processing_for_memory_region. +This is a consequence of the previous observation: Lowering of the member +function cannot happen when the associated member function is popped because +the parent (closure) class hasn’t been completed yet.

    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/code_style/index.html b/doc/code_style/index.html new file mode 100644 index 0000000..a163a99 --- /dev/null +++ b/doc/code_style/index.html @@ -0,0 +1,875 @@ + + + + + 25. Coding Style Guide - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    25. Coding Style Guide#

    +
    +

    25.1. General Whitespace Rules#

    +
      +
    • Maximum line length is 79 characters.

    • +
    • Indentation is by 2 spaces.

    • +
    • Editors should be set to use an 8 space tab width.

    • +
    +
    +
    +

    25.2. General Line Wrapping#

    +
    +

    25.2.1. General Condition Rules#

    +

    Conditions that cause the line length to exceed 79 characters are wrapped via a +line break following an operator. The continuation is left aligned with the +opening paren:

    +
    if (/* something very long */ &&
    +    /* something else */) {
    +  /* etc... */
    +}  /* if */
    +
    +if ((a || b) &&
    +    (/* something very long */ ||
    +     /* something else */)) {
    +  /* etc... */
    +}  /* if */
    +
    +if ((a || b) && (/* something very long */ ||
    +                 /* something else */)) {
    +  /* etc... */
    +}  /* if */
    +
    +
    +
    +
    +

    25.2.2. General Statement Rules#

    +

    Expressions that cause the line length to exceed 79 characters are wrapped via +a line break following an operator. The continuation is right-aligned:

    +
    int x = /* something very long */ &&
    +                        /* something else (right-aligned to column 79) */;
    +
    +
    +
    +
    +
    +

    25.3. General Line Breaks#

    +

    Line breaks are prioritized as follows:

    +
      +
    • 1 line for a conditional preprocessor directives (e.g., #if, #ifdef, etc.) +unless adding whitespace would break a visual “grouping” (e.g., conditional +inclusion of a header in a list of headers, conditionally enabling a single +statement in a function, etc.).

    • +
    • 1 line for a namespace declaration and its associated closing comments.

    • +
    • 2 lines for a function definition.

    • +
    • 1 line for a function, variable, or type declaration.

    • +
    +
    +
    +

    25.4. Naming Convention#

    +

    The EDG naming convention can be broadly described as “snake case” (with an +exception for templates). In snake case, names are composed of lower case +letters and underscores.

    +

    For types, the naming convention additionally adds a “a_/an_” +prefixed to the typename. For instance, what (in many projects) would be +spelled struct thing is called struct a_thing.

    +
    +
    +

    25.5. Writing a Variable#

    +

    Variables appearing in “global” (these technically shouldn’t exist as +there’s a conditional “edg” namespace around all file contents) or +namespace scope are indented using tabs in older files which make use of +tabs and the equivalent +(8) spaces in newer files. The type is not indented, the name is indented by +2 tabs, and a comment should be added at 3 tabs:

    +
    a_variable_type_name
    +        my_variable;
    +                /* A descriptive comment. */
    +
    +
    +

    If a variable type or name ends before the next tab stop, the lines should be +collapsed:

    +
    a_variable_type_name
    +        x;      /* A descriptive comment. */
    +int     my_variable;
    +                /* A descriptive comment. */
    +int     x;      /* A descriptive comment. */
    +
    +
    +
    +
    +

    25.6. Writing a Function#

    +
    +

    25.6.1. Parameter Alignment#

    +

    Functions declarations that fit within a single line should do so:

    +
    void foo(int a, int b, int c);
    +
    +
    +

    If a function declaration does not fit on a single line, it should be broken up +with the parameters broken up into two left-aligned columns, one column of +parameter types, and one column of parameter names:

    +
    void foo(a_variable_type        thing,
    +         an_other_variable_type other_thing,
    +         a_thingy               thingy);
    +
    +
    +
    +
    +

    25.6.2. Wrapping Function Declarations#

    +

    Particularly for function definitions with lots of qualifiers and long names +(member functions are particularly guilty), simply wrapping the parameters can +be insufficient. In these cases, there are two accepted techniques for keeping +the function within the required line length.

    +

    If the function has qualifiers like static and inline these can be +moved to the preceding line along with the return type:

    +
    static inline void
    +very_long_long_long_long_foo(a_variable_type        thing,
    +                             a_nother_variable_type other_thing,
    +                             a_thingy               thingy);
    +
    +
    +

    If this is still insufficient, the parameters can be moved to a new line and +right-aligned:

    +
    void very_long_long_long_long_long_foo(
    +                                    a_variable_type        thing,
    +                                    a_nother_variable_type other_thing,
    +                                    a_thingy               thingy);
    +
    +
    +
    +
    +

    25.6.3. Documentation#

    +

    In a function definition, a comment should be added after the closing paren but +before the opening curly brace. This comment should describe all of the +parameters, the return value, and any actions it takes, and the closing +} of the function should be followed by a comment giving the name +of the function, separated from the } by two spaces:

    +
    a_boolean foo(int num_l_parens, int num_r_parens)
    +/*
    +Given the number of left parens (num_l_parens) and the number of right
    +parens (num_r_parens), display the values and return TRUE if the
    +numbers are equivalent; otherwise, return FALSE.
    +*/
    +{
    +  printf("lparens=%d, rparens= %d\n", num_l_parens, num_r_parens);
    +  return num_l_parens == num_r_parens;
    +}  /* foo */
    +
    +
    +

    This also applies to void functions that use output parameters:

    +
    void foo(a_boolean *result, int num_l_parens, int num_r_parens)
    +/*
    +Given the number of left parens (num_l_parens) and the number of right
    +parens (num_r_parens), assign *result to TRUE if the numbers are equivalent;
    +otherwise, assign *result to FALSE.
    +*/
    +{
    +  *result = (num_l_parens == num_r_parens);
    +}  /* foo */
    +
    +
    +
    +
    +

    25.6.4. Return Value#

    +

    If a function requires a variable to hold the result, it should be the first +variable in the function, and it should be named “result”:

    +
    int foo()
    +/*
    +A descriptive comment.
    +*/
    +{
    +  int result;
    +
    +  /* etc... */
    +  return result;
    +}  /* foo */
    +
    +
    +
    +
    +

    25.6.5. Variable Grouping#

    +

    Variables should be grouped into blocks with their types and names aligned. +The first block of variables should have a trailing newline, and any following +blocks should use a preceding newline:

    +
    int foo()
    +/*
    +A descriptive comment.
    +*/
    +{
    +  int       result;
    +  a_boolean temp_state;
    +
    +  /* etc... */
    +
    +  a_state_catcher secondary_state;
    +  a_boolean       state_catcher_used = FALSE;
    +  /* etc... */
    +  return result;
    +}  /* foo */
    +
    +
    +
    +
    +
    +

    25.7. Writing a Lambda#

    +

    Lambdas are a case that’s a mix of variable and function rules. Lambda +parameters – similar to function parameters – should be broken up into two +left-aligned columns, one column of parameter types, and one column of +parameter names:

    +
    auto x = [](int num_l_parens,
    +            int num_r_parens) -> a_boolean {
    +  return num_l_parens == num_r_parens;
    +};
    +
    +
    +

    Unlike functions, lambdas do not require a documentation comment, or a closing +comment. For this reason, lambdas should be reserved for fairly trivial +operations.

    +

    If a lambda appears in a block of other variables, the lambda should follow the +name alignment of the variables in the same block, e.g.,

    +
    a_long_type_name y = /* etc... */;
    +auto             x = [](int num_l_parens,
    +                        int num_r_parens) -> a_boolean {
    +  return num_l_parens == num_r_parens;
    +};
    +
    +
    +
    +
    +

    25.8. Writing a Class#

    +

    Classes should be preceded by a descriptive comment, and terminated by a +closing comment giving the class name and separated from the ; by two +spaces:

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  /* etc... */
    +};  /* foo */
    +
    +
    +
    +

    25.8.1. Data Members#

    +

    Data members should be written at the end of the class. In terms of +indentation, data members are indented similarly to variables in global & +namespace scope, with the exception that the type is always indented by two +spaces:

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  /* etc... */
    +private:
    +  a_variable_type_name
    +                my_var_a;
    +                        /* A descriptive comment. */
    +  a_variable_type_name
    +                b;      /* A descriptive comment. */
    +  int           my_var_c;
    +                        /* A descriptive comment. */
    +  int           d;      /* A descriptive comment. */
    +};  /* foo */
    +
    +
    +
    +
    +

    25.8.2. Member Functions#

    +

    Member functions (including special member functions like constructors and +destructors) that do not exceed 1 line can be written inline:

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  void bar()
    +    { this->x += 1; }
    +private:
    +  int           x;      /* A descriptive comment. */
    +};  /* foo */
    +
    +
    +

    If the member function is empty it should be spelled “{}” (no space):

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  void foo()
    +    {}
    +};  /* foo */
    +
    +
    +

    Member functions that exceed 1 line should be written out-of-line:

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  void complex_bar();
    +private:
    +  int           x;      /* A descriptive comment. */
    +};  /* foo */
    +
    +
    +void foo::complex_bar()
    +/*
    +A descriptive comment about complex_bar.
    +*/
    +{
    +  /* etc... */
    +};  /* foo::complex_bar */
    +
    +
    +

    Additionally see Writing a Function as those rules also apply to member +functions.

    +
    +
    +

    25.8.3. Member Initializer#

    +

    If initializing using a passed value, the data members and parameters +should have names that differ (e.g., for a data member x, x_val can +be an appropriate parameter name).

    +

    Additionally, the introducing colon and all member initializers should be +indented two spaces, e.g.,

    +
    /*
    +A descriptive comment about class foo.
    +*/
    +struct foo {
    +  void foo()
    +    : x(1), y(2), z(3)
    +    {}
    +  inline void foo(int x_val, int y_val, int z_val);
    +  int           x;      /* A descriptive comment. */
    +  int           y;      /* A descriptive comment. */
    +  int           z;      /* A descriptive comment. */
    +};  /* foo */
    +
    +
    +void foo::foo(int x_val, int y_val, int z_val)
    +/*
    +A descriptive comment about foo::foo.
    +*/
    +  : x(x_val + 100), y(y_val + 1000),
    +    z(z_val + 10000)
    +{
    +  /* etc... */
    +};  /* foo::foo */
    +
    +
    +
    +
    +
    +

    25.9. Statements#

    +
    +

    25.9.1. for Statements#

    +
    +

    25.9.1.1. C-style#

    +

    “C-style” for loops should be formatted with their contents indented by 2 +spaces, and a closing comment (with two preceding spaces):

    +
    for (int x = 0; x < 10; ++x) {
    +  /* etc... */
    +}  /* for */
    +
    +
    +

    If the condition of the for loop causes the line length to exceed 79 +characters, it should be broken up at the semicolons:

    +
    for (int long_variable = 0;
    +     long_variable < another_long_variable;
    +     ++long_variable) {
    +  /* etc... */
    +}  /* for */
    +
    +
    +
    +
    +

    25.9.1.2. Range-based#

    +

    Range-based for loops should be formatted as “C-style” for loops +are, with the exception that, if the condition cause the line length to +exceed 79 characters, it should be broken at the colon and right aligned:

    +
    for (a_long_type &&x :
    +         some_container) {
    +  /* etc... */
    +}  /* for */
    +
    +
    +
    +
    +
    +

    25.9.2. if Statements#

    +

    if statements should be formatted with their contents indented by 2 +spaces. else and else if clauses should be preceded and followed by +braces, aligned with the if, and the closing brace aligned with the +if and followed by an if comment (with two preceding spaces):

    +
    if (argument) {
    +  /* something */
    +} else if (other_argument) {
    +  /* something else */
    +} else {
    +  /* default action */
    +}  /* if */
    +
    +
    +
    +
    +

    25.9.3. switch Statements#

    +

    switch statements should be formatted with their case labels indented +by 2 spaces, the contents further indented by two spaces, and a closing +comment (with two preceding spaces). The opening brace of a scoping block +can be immediately followed on the same line by the first statement of the +block, and its closing brace should have no comment:

    +
    switch (argument) {
    +  case a:
    +    { int y = 10;
    +
    +      x += y;
    +    }
    +    break;
    +  case b:
    +    x += 1;
    +    break;
    +  case c:
    +    /* no-op */
    +    break;
    +  default_is_unexpected();
    +}  /* switch */
    +
    +
    +
    +
    +

    25.9.4. while Statements#

    +
    +

    25.9.4.1. Pre-condition#

    +

    “Pre-condition” while statements should be formatted with their contents +indented by 2 spaces, and a closing comment (with two preceding spaces):

    +
    while (argument) {
    +  /* etc... */
    +}  /* while */
    +
    +
    +
    +
    +

    25.9.4.2. Post-condition#

    +

    “Post-condition” (i.e., do) while statements should similarly be +formatted with their contents indented by 2 spaces. However, unlike +“pre-condition” while statements, no closing comment is required:

    +
    do {
    +  /* etc... */
    +} while (argument);
    +
    +
    +
    +
    +
    +
    +

    25.10. Preprocessor Directives#

    +
    +

    25.10.1. #if and #endif#

    +

    #if should have its closing #endif commented with the condition used +(preceded by a single space):

    +
    #if MACRO_IS_ENABLED
    +/* etc... */
    +#endif /* MACRO_IS_ENABLED */
    +
    +
    +

    If the condition is complicated, the closing comment can be abbreviated:

    +
    #if MACRO_IS_ENABLED && (OTHER_MACRO_IS_ENABLED || \
    +                         OTHER_OTHER_MACRO_IS_ENABLED)
    +/* etc... */
    +#endif /* MACRO_IS_ENABLED && (OTHER_MACRO...) */
    +
    +
    +
    +
    +

    25.10.2. #else#

    +

    If an #if makes use of an #else a comment should express the negated +condition (preceded by a single space):

    +
    #if MACRO_IS_ENABLED
    +/* etc... */
    +#else /* !MACRO_IS_ENABLED */
    +/* etc... */
    +#endif /* MACRO_IS_ENABLED */
    +
    +
    +
    +
    +

    25.10.3. #elif#

    +

    If an #if makes use of an #elif, no change to comments is performed:

    +
    #if MACRO_IS_ENABLED
    +/* etc... */
    +#elif OTHER_MACRO_IS_ENABLED
    +/* etc... */
    +#endif /* MACRO_IS_ENABLED */
    +
    +
    +
    +
    +
    +

    25.11. Templates#

    +

    Templates follow the rules of the respective thing being templated, with +the exception that the name for templates declaring a type should not +follow the normal naming convention. For class and alias templates, no +a_ or an_ qualifier is used, instead an uppercase letter starts the +name (e.g., Dyn_array).

    +
    +

    25.11.1. Template Parameters#

    +

    Template parameters, like template declarations, have their own naming +convention. They should be named a_/an_ followed by a capital +letter, and then a descriptive name, e.g.,

    +
    template<typename an_Elem>
    +struct My_template;
    +
    +
    +

    If multiple template parameters need to be denoted as the “1st, 2nd, 3rd, +etc.” version of a parameter, capital letters can be used to denote this, +e.g.,

    +
    template<typename a_Type_A, typename a_Type_B>
    +struct Thingy_helper;
    +
    +
    +
    +
    +
    +

    25.12. Special Cases#

    +
    +

    25.12.1. Pointer & Reference Types#

    +

    The rule for pointer and reference types is that the pointer or ref qualifier +accompanies the name being typed (for purposes of a function, consider the +return type the “type” of the function) e.g.,

    +
    void foo(int *result, const thingy &a)
    +/*
    +A descriptive comment.
    +*/
    +{
    +  int &c = a.value;
    +
    +  *result = c;
    +}  /* foo */
    +
    +
    +a_thingy *alloc_thingy();
    +
    +
    +
    +
    +

    25.12.2. Empty Loop Bodies#

    +

    Empty compound statements (e.g., function bodies and loop bodies) should be +spelled “{}” (no space) and follow the looping statement on the same line, +e.g.,

    +
    for (x = 0; x < y; x *= 2) {}
    +
    +while (try_op(x)) {}
    +
    +
    +
    +
    +

    25.12.3. Annotating Function Arguments#

    +

    When a function is called with an argument of a fixed value (e.g., a +TRUE or FALSE value for a “flag” argument) the argument should be +annotated with a comment naming the associated parameter, e.g.,

    +
    int chars = count_characters(str, /*include_whitespace=*/FALSE);
    +
    +
    +

    When NULL is passed, it should either follow the same convention or +be cast to the parameter’s type, e.g.,

    +
    some_func(one_thing, /*associated_thing=*/NULL);
    +other_func(something_else, (a_foo*)NULL);
    +
    +
    +
    +
    +

    25.12.4. Wrapping Function Calls#

    +

    Function calls that cause the line length to exceed 79 characters can be +handled one of two ways.

    +

    If the function call is initializing a variable, and would otherwise fit on the +line, it can be moved down a line and right aligned:

    +
    int x =
    +     my_very_long_function(a, b, c, d, e, f, g, h);
    +
    +
    +

    Otherwise, the function call should be wrapped on the arguments, aligning +continuation lines with the “(” of the function call; if there is a +single argument that cannot fit between the “(” column and the right +margin, the call should be broken after the “(” and all continuation lines +aligned with the position resulting from right-justifying the longest +argument. The exact style for wrapping the arguments is not specified, but +in general developers should, in the interest of compact code, flow as many +arguments together as will fit on each line:

    +
    int x = my_very_long_function(a, b, c, d, e, f,
    +                              g, h);
    +
    +
    +

    If arguments have some logical relation, e.g., for an area function, these +arguments can be grouped to emphasize the relation instead of flowing for +maximal compactness:

    +
    compute_area_of_points(x1, y1, z1,
    +                       x2, y2, z2);
    +
    +
    +

    In cases where the arguments are annotated with embedded comments, it may be +desirable to distribute them across multiple lines for clarity and neatness, +e.g.,

    +
    f(a, b, c, d, /*is_foo_bar=*/FALSE,
    +  /*needs_more_squirrels=*/VERY_FALSE);
    +
    +
    +

    instead of:

    +
    f(a, b, c, d, /*is_foo_bar=*/FALSE, /*needs_more_squirrels=*/VERY_FALSE);
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/cp_gen_be/index.html b/doc/cp_gen_be/index.html new file mode 100644 index 0000000..d02bf33 --- /dev/null +++ b/doc/cp_gen_be/index.html @@ -0,0 +1,615 @@ + + + + + 24. C++-Generating Back End - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    24. C++-Generating Back End#

    +

    The C++-generating back end is a “back end” that turns C or C++ intermediate +language back into source text in C or C++. It is designed for +source-to-source-transformation applications, i.e., processors that read in +source code, make some modifications to its meaning (e.g., adding profiling +code), and then write it out as modified.

    +

    The C++-generating back end handles C++, ANSI/ISO C, and K&R C [1]. The +output is in the same language as the input, and means the same thing, but +is not expected to be identical. At the very least, comments are +eliminated and preprocessing is done, which means #include files are +merged in, macros are expanded, and #ifs and the like are processed. +The output will match the input exactly with regard to entity names and +source line numbers (the latter by use of #line directives, if +necessary), and in the order of declarations and statements in the source. +In short, it should be possible to compile the output file with a C or C++ +compiler, execute it to get the same results as the original program, and +debug it using the original source text.

    +

    The source code for the C++-generating back end is in cp_gen_be.c; +cp_gen_be.h contains the associated declarations.

    +
    +

    24.1. Source Sequence Lists#

    +

    The C++-generating back end requires the source sequence list, which is a +construct that lists all declarations and statements of the source program in +the order of their appearance. It is optional, and must be enabled by the +configuration flag GENERATE_SOURCE_SEQUENCE_LISTS. The source sequence +list stands alongside the “normal” tree-structured intermediate language, as a +sort of table of contents for the IL tree. That is, for a program fragment +that declares variable i, function f, and variable j, the source +sequence list would be a list of three entries, pointing to the IL entries for +i, f, and j, and the tree-structured information under those +entries would provide full information on the entities.

    +

    The list is conceptually a single list that runs through the whole compilation +unit, though in actuality it is implemented by a somewhat more complicated data +structure that snakes between the file scope memory region and the function +scope memory regions. That is, however, merely the low-level representation +dictated by the restrictions on pointers between memory regions, and is hidden +by access functions, e.g., adv_to_signif_source_sequence_entry.

    +

    Some entities in the source program may be declared or defined more than once. +For example, a function can be declared and then later defined. For such +cases, one of the occurrences (the definition if there is one) is selected as +the primary declaration, and the source sequence entry for that declaration +points directly at the IL entry for the entity. For all the other +declarations, the source sequence entry on the list points to a source sequence +secondary declaration entry, which points to the IL entry for the entity and +also gives information about that particular declaration, e.g., the source +position and the specific type used (which may differ from that of the +definition by use of typedefs, array bounds, etc.).

    +

    The C++-generating back end operates by traversing the list and generating code +for each construct it encounters. A program is considered to be made up of an +alternation of declarative regions and executable regions.

    +

    In declarative regions, the C++-generating back end steps through the +entries on the source sequence list, each of which points to a declared +entity, and generates declarations. Source sequence entries for class, +struct, union, and enum types that are declared as part of some other +declaration (e.g., “struct A {int i;} x;”), called non-autonomous +declarations, are skipped over without generating a declaration for the +type, but the type is marked to be put out when encountered while putting +out the type of the containing entity (e.g., “x” above). All other +declarative source sequence entries are processed immediately.

    +

    In executable regions, the C++-generating back end steps through the source +sequence entries (a flat list) and the IL statement entries (a tree) in tandem, +and generates code for the statements.

    +
    +
    +

    24.2. Declarations#

    +

    The top-level routine for declaration processing is gen_declaration. It +calls routines like

    +
      +
    • +
      gen_variable_decl,
      +
      +
    • +
    • +
      gen_routine_decl,
      +
      +
    • +
    • +
      gen_namespace,
      +
      +
    • +
    • +
      gen_type_decl,
      +
      +
    • +
    • +
      gen_template,
      +
      +
    • +
    • +
      gen_using_directive_or_declaration, and
      +
      +
    • +
    • +
      gen_instantiation_directive.
      +
      +
    • +
    +

    gen_type_decl breaks the various type-declaration cases down as calls to

    +
      +
    • +
      gen_class_definition,
      +
      +
    • +
    • +
      gen_enum_definition, or
      +
      +
    • +
    • +
      gen_typedef_decl.
      +
      +
    • +
    +

    gen_declaration_using_type and gen_type output types in general, by +calling routines in il_to_str.c.

    +

    gen_secondary_decl handles secondary declaration source sequence entries.

    +

    gen_initializer handles initializers on variables. It calls +gen_dynamic_init to handle dynamic initialization.

    +

    gen_class_definition uses normal declaration routines like +gen_routine_decl to put out code for the class members, and also the +following, which handle special kinds of members:

    +
      +
    • +
      gen_field_decl,
      +
      +
    • +
    • +
      gen_member_constant_decl, and
      +
      +
    • +
    • +
      gen_using_declaration.
      +
      +
    • +
    +

    gen_type_decl, gen_variable_decl and gen_routine_decl include +special code to deal with declarations within class definitions. In +particular, they deal with friend declarations.

    +
    +
    +

    24.3. Executable Code#

    +

    The top-level routine for executable code processing is gen_statement. +Most statements are straightforward, but the following routines handle the more +complicated cases:

    +
      +
    • +
      gen_block_statement,
      +
      +
    • +
    • +
      gen_try_block_statement,
      +
      +
    • +
    • +
      gen_switch_statement, and
      +
      +
    • +
    • +
      gen_for_statement.
      +
      +
    • +
    +

    Expressions are handled by gen_expr, with some more complicated cases +handled by:

    +
      +
    • +
      gen_new_delete and
      +
      +
    • +
    • +
      gen_temp_init
      +
      +
    • +
    +

    The expression routines always add parentheses around expressions if there is +any chance of precedence confusion.

    +
    +
    +

    24.4. Constants#

    +

    Constants are put out by gen_constant, which calls routines in +il_to_str.c to do the actual output.

    +

    gen_initializer_constant handles initializer constants, which include +aggregate constants, ck_dynamic_init constants, and cases where a reference +is initialized from a constant, as well as the usual kinds of constants.

    +
    +
    +

    24.5. Templates and Macros#

    +

    Templates and macros are strange cases in the IL. Both are macro-like, in +that the source provides a prototype that is expanded by the front end on +each use of the construct. That means that template and macro references +are largely invisible in the IL – one sees only the expanded form and +little evidence that it came from a template or macro reference.

    +

    It is nevertheless desirable to be able to put out the template and macro +definitions in some way so that template instantiation and symbolic debugging +can be done on the generated code. To accommodate this need, the IL optionally +contains entries for templates and macros. These contain normalized textual +representations of the template or macro (e.g., a string like “#define x(a) +a+1”). The C++-generating back just puts those out verbatim. (The macro +entries are all put out at the end of the output file, so they won’t affect the +already-macro-expanded code that is put out, but they will still be available +for symbolic debuggers.) Note that macro entries are also used for #undef +directives. See gen_template and gen_macro.

    +
    +
    +

    24.6. Source Output#

    +

    The effective position for source output is set by calling +set_output_position. That will result in generation of #line +directives as necessary, but not until some text is actually output, at which +point adjust_output_position is called. Note that while line number +correspondence is maintained in the output, there is no attempt to maintain +column number correspondence, or even to do appropriate indentation.

    +

    Actual text output is done through

    +
      +
    • +
      write_ch,
      +
      +
    • +
    • +
      m_write_ch,
      +
      +
    • +
    • +
      write_space,
      +
      +
    • +
    • +
      m_write_space,
      +
      +
    • +
    • +
      write_tok_ch,
      +
      +
    • +
    • +
      m_write_tok_ch,
      +
      +
    • +
    • +
      write_tok_str,
      +
      +
    • +
    • +
      m_write_tok_str,
      +
      +
    • +
    • +
      write_unsigned_num, and
      +
      +
    • +
    • +
      write_num,
      +
      +
    • +
    +

    The names that begin with “m_” are macros and are intended for those cases +where speed is important. The others are functions. The names that include +“_tok_” are used to write complete tokens or sequences of tokens; the +low-level routines are given permission to break long output lines before or +after such text to avoid overly-long lines.

    +
    +
    +

    24.7. Troublesome Cases#

    +
    +

    24.7.1. Names#

    +

    Names are, in general, put out exactly as they appear in the IL. In some +cases, unnamed entities are given generated names. Members of classes are in +general put out as qualified names (e.g., A::x), but sometimes special care +is required:

    +
      +
    • +
      The declaration of a member within its class must not use a qualified name. +To handle this, a name context stack is maintained (see +push_name_context and pop_name_context), tracking the current +scope. When immediately within a class definition, the class qualifier for +that class is suppressed. The same thing is done for namespaces.
      +
      +
    • +
    • +
      A call of a virtual function with a qualified name suppresses the +virtual-ness of the function, so a qualified name must be used only if that +behavior is desired.
      +
      +
    • +
    • +
      In references to nonstatic members of classes (data or function), the +choice of name can have an effect on access control (e.g., for protected +members) and can disambiguate an otherwise ambiguous member name. +gen_simple_field_selection and gen_bound_function handle such +references for data and function cases, and call +optimized_expr_for_selection to determine the class to be used in +naming the member (that’s done by examining any implicit casts used in the +member selection).
      +
      +
    • +
    • +
      Sometimes, a prefix “::” or an elaborated type specifier (e.g., class +X) must be used to distinguish one name from another. One would think +that always generating those would be the appropriate (and easy) thing to +do. It turns out, however, that various compilers have bugs in that area, +and won’t accept some valid code generated in that mechanical way. As a +consequence, the C++-generating back end uses the hidden-name information +developed by the front end to generate prefix “::”, qualified names in +general, and elaborated type specifiers only when they are required. See +alloc_hidden_name_fixup et al. This processing has an additional +benefit: it handles external variables and functions that are declared +extern within a function. References to such entities must not use a +“::” prefix, because although the entity named is external, and thus in +some sense in the global scope, the name used for it is declared local to +the function.
      +
      +
    • +
    +

    See

    +
      +
    • +
      gen_name,
      +
      +
    • +
    • +
      gen_unqualified_name,
      +
      +
    • +
    • +
      gen_decl_name,
      +
      +
    • +
    • +
      gen_class_qualifier, and
      +
      +
    • +
    • +
      gen_namespace_qualifier.
      +
      +
    • +
    +
    +
    +

    24.7.2. References#

    +

    Reference types, or rather uses of entities with such types, require some +special attention. In expressions, eok_reference_to and +eok_ref_indirect occur in order to make explicit the indirection implicit +in the uses of the reference types; these operators are simply ignored when +generating the expressions.

    +

    More subtle is the fact that certain kinds of constants implicitly contain an +“address-of” operation. The ordinary processing of these by form_constant +adds an & to the output before writing the constant’s value; this & +must be suppressed when the constant has a reference type (or, more generally, +is used in an lvalue context). This special processing is provided by +handle_lvalue_constant_node.

    +
    +
    +

    24.7.3. Prototype Scopes#

    +

    Prototype scopes (scopes associated with a prototyped function declarator, in +C) cause a particular set of headaches, because while such types cannot be +named outside of the prototype scope, they do nevertheless show up in the types +of objects outside those scopes. For example:

    +
    void f(struct A {int i;} *p);
    +void g(enum E {e1});
    +main() {
    +  f(0);   /* Really f((struct A *)0) */
    +  g(1);   /* Really g((enum E)1) */
    +  return 0;
    +}
    +
    +
    +

    The C++-generating back end deals with these by noting such cases and +suppressing the explicit casts in those cases. The conversion is then once +again implicit in the output program.

    +

    See is_implicitly_cast_integral_constant.

    +
    +
    +

    24.7.4. Rewritten Property References#

    +

    References to Microsoft properties are rewritten by the front end. Something +like “p+1”, referring to a property p, might have been rewritten as +“call the get accessor function for p, add 1to it, and store the +resulting value by calling the set accessor for p.” The C++-generating back +end recovers the original source form. This is based on a field in expression +nodes called rewritten_property_reference_kind, which is set by the front +end to special values to identify certain key nodes in the expansion. See +gen_prop_event_or_op_synth_call. Event references are similarly +reconstituted.

    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/decls/index.html b/doc/decls/index.html new file mode 100644 index 0000000..2877dd1 --- /dev/null +++ b/doc/decls/index.html @@ -0,0 +1,1394 @@ + + + + + 10. Declarations - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    10. Declarations#

    +

    Declaration scanning is shared among a number of files. What is specific to +class member declarations is found in class_decl.c and is discussed in the +next chapter. The remainder of declaration processing is found in decls.c, +which contains the top level routines and a number of utility functions; +decl_spec.c, which handles declaration specifiers; declarator.c, which +scans declarators; func_def.c, which contains the code to process function +definitions; and decl_inits.c, which contains the code to scan +initializers. decls.h, decl_spec.h, declarator.h, func_def.h, +and decl_inits.h contain associated declarations. In addition, code for +disambiguating C++ declarations and expressions is found in disambig.c, +with associated declarations in disambig.h.

    +
    +

    10.1. Overview#

    +

    The top level routine in declaration scanning, and in fact in the overall +compilation process, is translation_unit, which scans a series of +declarations and stops at end of file. The routine it calls is +scan_nonmember_declaration (via the older declaration interface), which +is also called for local declarations that appear within functions or blocks +(including old-style parameter declarations). (The only declarations that do +not pass through declaration are class member declarations and new-style +parameter declarations.)

    +

    Since a typical declaration looks like this:

    +
    +
    +
    decl-specifiers declarator-list ;
    +
    +
    +

    two principal elements in the structure of scan_nonmember_declaration are

    +
      +
    • +
      a call to decl_specifiers, which scans the type specifier, storage +class keyword, and so forth; and
      +
      +
    • +
    • +
      a loop to handle a comma-separated list of declarators with successive +calls to declarator.
      +
      +
    • +
    +

    There are many details, including a lot of error checking and some special +cases. But in general, after the return from declarator, one of several +routines is called (though not called directly from declaration) to do +additional processing:

    +
      +
    • +
      When a function body is present function_definition is called and the +loop is exited.
      +
      +
    • +
    • +
      decl_variable is called for declarations of variables.
      +
      +
    • +
    • +
      decl_routine is called for declarations of non-member functions without +bodies (it is also called via function_definition when a body is +present).
      +
      +
    • +
    • +
      decl_typedef is called for typedef declarations.
      +
      +
    • +
    • +
      decl_parameter is called for old-style parameter list declarations.
      +
      +
    • +
    • +
      define_static_data_member is called for C++ static data member +definitions.
      +
      +
    • +
    +

    Finally, if an initializer is present in a variable or static data member +declaration, it is scanned by a call to initializer; in cases where default +initialization may be required, def_initializer is called.

    +

    Other sorts of declarations are handled by the following (via +check_special_declaration_form):

    +
      +
    • +
      template_directive_or_declaration is called for template declarations, +template instantiation directives, and template specializations (in other +words, declarations that begin with the keyword template).
      +
      +
    • +
    • +
      namespace_declaration is called for namespace and namespace alias +declarations.
      +
      +
    • +
    • +
      nonmember_using_declaration is called for all using-declarations +except those appearing in a class definition.
      +
      +
    • +
    • +
      using_directive is called for using-directives.
      +
      +
    • +
    • +
      asm_declaration is called for declarations that begin with the keyword +asm.
      +
      +
    • +
    • +
      alias_declaration is called for C++11-style alias declarations.
      +
      +
    • +
    • +
      scan_and_record_cli_delegate_definition is called for C++/CLI delegate +definitions.
      +
      +
    • +
    +
    +

    10.1.1. Declaration Parse State#

    +

    The outline above just lists a few of the many functions involved in parsing +declarations, and many of those functions need to share various bits of state. +The principal structure tracking this state through this process have type +a_decl_parse_state. This keeps track of types (declared type, effective +type, etc.), positions (start of declaration, declarator, certain specifier +keywords, etc.), additional declarative attributes (GNU, Microsoft, etc.), and +so forth.

    +

    For declarations involving a declarator, the declared entity’s symbol, once +available, is pointed to by dps->sym where dps is a pointer to the +declaration parse state for that declaration.

    +

    In most cases the declaration parse state is initialized using the +init_decl_parse_state macro, but when multiple comma-separated declarators +are handled, the state is recycled for each secondary declarator by calling +start_secondary_declarator (which preserves and even restores state +associated with the common declaration specifiers).

    +

    a_decl_parse_state includes a field of type an_init_state to describe +the processing of any initializer associated with the declaration (although +an_init_state variables can also exist independent of a specific +declaration; see also Init Components and Init States).

    +

    The a_decl_parse_state stucture also maintains a list of “actions” +(pointers to functions accepting a pointer to that state) that should be run at +the end of a declaration; this can be useful when a local declaration element +is encountered that cannot be checked until the declaration has been more or +less completely processed. New actions can be registered by calls to +add_end_of_parse_action (they are eventually run by a call to +run_end_of_parse_actions).

    +

    The a_decl_parse_state structure is not only used by declarations handled +by scan_nonmember_declaration, but also for class member declarations, +parameter declarations, and even when parsing type names in contexts such as +casts and template arguments (through function type_name_full), which isn’t +really declaration parsing at all.

    +
    +
    +

    10.1.2. Declarations from C++/CLI Assembly Metadata#

    +

    In C++/CLI mode, the front end is able to import assembly metadata files. This +is achieved by first transforming the metadata into equivalent C++/CLI source +code, and then parsing that code. Whether metadata is imported implicitly +(because it is the core library file), explicitly through a “preusing” +command-line toption, or explicitly through a #using directive, the root +function doing the importing is import_metadata (in preproc.c). This +function sequences the following operations:

    +
      +
    • +
      It prepares a file for importing by calling make_cli_metadata_file and +import_metadata_file.
      +
      +
    • +
    • +
      If all went well, it calls generate_top_level_metadata_code, which +creates a string containing C++/CLI source representing the +declarations – but not the definitions – of the top-level entities +(which are managed class types) in the metadata file. The actual work +for this is done by the “metadata reader” implemented in +ms_metadata.cpp (a C++ file meant to be compiled only in a +Microsoft environment).
      +
      +
    • +
    • +
      Finally, the generated string is passed to +scan_top_level_metadata_declarations, which (much like +translation_unit) repeatedly calls declaration to internalize the +generated code.
      +
      +
    • +
    +

    The definitions of the generated entities [1] aren’t imported until (and +unless) they are needed. When that happens, a process somewhat similar to that +of import_metadata is performed by get_definition_of_class, but this +time routines to process definitions are called instead of declaration: +scan_cli_generic_class_definition_from_assembly_import for generic entities +(including generic delegates), +scan_cli_delegate_definition_from_assembly_import for non-generic delegate +definitions, and scan_class_definition for other non-generic class type +definition. +An imported assembly is assigned a number (the “assembly index”) and that +number is recorded in the IL representation of class and enum types loaded from +the assembly. +While processing code generated from metadata (top-level or needed +definitions), the global variable scanning_generated_code_from_metadata is +TRUE. This is used, for example, to suppress certain diagnostics that do not +apply to code generated from metadata.

    +
    +
    +
    +

    10.2. Linkage Specifications#

    +

    In C++ the first thing declaration must check for is the token extern +followed by a string literal (e.g., extern "C"). This introduces a linkage +specification, which may control a single declaration or a brace-enclosed block +of declarations. In either case linkage_specification is called. It sets +global variable def_external_linkage to describe the kind of linkage that +is to be the default for subsequent declarations, and then it calls +declaration again.

    +
    +
    +

    10.3. Declarations vs. Expressions#

    +

    Inside a function body it is sometimes difficult to determine whether something +is a declaration or an executable statement. In C the presence of a +declaration specifier keyword or a type name is sufficient to disambiguate the +cases, but in C++ it can be more complicated. Similar disambiguation problems +appear in other contexts as well. Here are some examples.

    +
      +
    • +
      a statement vs. a declaration:
      +
      +
      typedef int I;
      +I(i);              // declaration (= I i);
      +I(i)++;            // cast i to I, then increment
      +
      +
      +
    • +
    • +
      with operator new, a parenthesized type vs. a placement expression:
      +
      +
      new (int(1.5)) A   // placement
      +new (int(*  ))     // type
      +
      +
      +
    • +
    • +
      a parenthesized initializer vs. a parameter declaration
      +
      +
      struct A { /* ... */ };
      +A a(int(1));   // declare variable a (initialized by
      +               //    calling A::A() with arg 1)
      +A f(int(i));   // declare function f to take an integer
      +               //    argument and return an A
      +
      +
      +
    • +
    +

    The function is_decl_not_expr is called in cases where disambiguation is +required. This may in turn use the routines prescan_declaration, +prescan_decl_specifiers, prescan_declarator, and +prescan_function_declarator. In general, if a sequence of tokens looks +like a declaration, then it is a declaration, even if it could also be an +expression. The technique requires looking ahead as many tokens as necessary +to confirm or disprove the assumption that the token sequence is a declaration; +tokens are cached so that they can be rescanned by the caller.

    +

    Thus, in statement processing, when is_decl_not_expr returns TRUE the +tokens are scanned as a declaration (declaration is called); otherwise, the +tokens are scanned assuming that they constitute a statement.

    +
    +
    +

    10.4. Declaration Scanning#

    +
    +

    10.4.1. Declaration Specifiers#

    +

    The principal part of the code for processing declaration specifiers appears in +decl_spec.c.

    +

    decl_specifiers scans a list of type specifiers, type qualifiers, and/or +storage class specifiers, and returns (through a a_decl_parse_state object) +a pointer to a type tree. It is passed a vector of input flags (telling it +that a storage class specifier is allowed, that the declaration is of a class +member, etc.) and it returns additional information about the results of the +scan (reporting that inline was scanned, that an explicit type specifier +was present, etc.) via the a_decl_parse_state object that was passed in.

    +

    The specifiers are scanned in a loop. The simple ones are handled directly. +When enum is seen, enum_specifier is called. When class, +struct, or union is scanned, class_specifier is called; the +processing entailed in scanning a class definition (see +scan_class_definition in class_decl.c) is described in the chapter on +Class Declarations.

    +

    A typedef name may appear as a type specifier, as may a class name in C++. +Therefore, to tell whether an identifier (including a qualified name) is a type +name or a declarator, a call is made to curr_type_symbol; it returns a +symbol pointer when the identifier is a type name and NULL otherwise. Since +class name can also be a constructor name under some conditions, that case is +also checked for by is_constructor_decl.

    +

    The loop continues until it reaches something it does not recognize as a +declaration specifier. Then the accumulated information is combined to create +a type entry (see combine_type_specifiers and add_type_qualifiers, and +the output flags are set. When no type is explicitly specified, a default type +is returned; ordinarily it is int, but when the declarator is recognized to +be a constructor, the default is a reference to the class type, and for +destructors it is void.

    +

    decl_specifiers is also called to scan a set of type qualifiers only, e.g., +as part of scanning a pointer-declarator. For such cases +a_type_qualifier_set is always returned independently of the type (even +though in the usual case it is also part of the returned type). (See also +collect_type_qualifiers in declarator.c.)

    +

    The details of an enum declaration are handled by enum_specifier. +First it calls scan_tag_name (which is also called from +class_specifier) to look up the (optional) tag name and return a symbol. +When a brace-enclosed declaration follows the tag name, enum_specifier +scans the list of enumeration constant declarations, calling +scan_integral_constant_expression when a value is specified. Each +declaration is turned into a constant entry with the proper value, and all of +the constant entries are linked together under the type entry for the +enumerated type. The size of the enumerated type is also determined from the +value. [2] Note that in C++, unlike C, the types of the enumeration and its +constants are always the same.

    +
    +
    +

    10.4.2. Declarators#

    +

    Most of the code for scanning declarators is found in declarator.c.

    +

    declarator scans a declarator. It can scan either a real declarator or an +abstract declarator. It receives as input (via the a_decl_parse_state +object tracking that declaration) the type from an associated specifiers list, +and combines that type with the type information in the declarator. It also +returns a symbol locator for the name declared in the middle of the declarator. +For an abstract declarator, it returns an error locator. It takes as input a +vector of flags to direct its processing, and it returns a vector of output +flags to report results to the caller (again via the a_decl_parse_state +object).

    +

    declarator is the top-level interface and calls r_declarator, which is +recursive. Declarator processing has three parts:

    +
      +
    • +
      pointer_declarator is called to handle pointer modifiers (*) and in +C++ references (&) and pointer-to-member syntax. There can be more +than one such modifier, and each can be accompanied by one or more type +qualifiers. These are combined with the type returned by +decl_specifiers; the routines invoked to construct the new types are +make_pointer_type, make_reference_type, +make_rvalue_reference_type, and pointer_to_member_type.
      +
      +
    • +
    • +
      The middle section is either an identifier (or the place where one would +be, for an abstract declarator) or a nested declarator enclosed in +parentheses. The left parenthesis is ambiguous in an abstract declarator, +so the routine looks one token past it to disambiguate the function +declarator case from the nested declarator case. The declarator +identifier, scanned by scan_real_declarator_id, may be a simple +identifier, a qualified name, [3] a destructor name, or a token sequence +representing an overloaded operator or a user-defined conversion (such as +operator+ or operator int).
      +
      +
    • +
    • +
      The third section consists of zero or more function or array declarators, +for which calls are made to function_declarator or +array_declarator.
      +
      +
        +
      • +
        function_declarator scans the parameter list (an old-style id list, a +prototype parameter list, or void) and builds a function type. For a +top-level function type some additional information is returned in a +block called func_info, which is returned to the caller to assist +with later function processing; most notably, this includes a list of the +identifier names in an old-style id list. If the function declarator is +a prototype, and if any tags are declared in the prototype, a prototype +scope is created.
        +
        +
      • +
      • +
        array_declarator scans constant and nonconstant array dimensions (the +latter for variable length arrays in C mode and type names in new +expressions in C++).
        +
        +
      • +
      +
      +
      The processing for VLA declarations has several twists. In the ordinary +case in which a VLA declaration appears at function or block scope, a VLA +dimension entry is created and an stmk_set_vla_size statment is put +out. If the VLA declaration appears in a function prototype, then the +dimension expression may be unspecified (i.e., the[*] syntax is +accepted); this is not permitted, however, when the function prototype +belongs to a function definition, but this check is delayed till +scan_function_body. If the dimension expression is specified in a +function prototype scope, a fixup entry is created and processing is +completed in scan_function_body: once the routine’s IL scope has been +created, the VLA dimension entry can be allocated and any references to +parameter variables can be properly incorporated into the VLA dimension +expression.
      +
      +
    • +
    +

    The type information from the three sections is combined into a single type +tree. The routine that combines derived types is add_to_derived_type_list; +aside from the purely mechanical task of joining types, it also does error +checking, and calls set_type_size once all the parts of a derived type have +come together.

    +

    Information about the declarator-id is returned from declarator in a +symbol locator.

    +
    +
    +

    10.4.3. C++/CLI Type Constructs#

    +

    C++/CLI adds several type composition mechanisms: handles, tracking references, +interior pointers, pin pointers, CLI arrays, and delegates. It also adds new +class type and enum type variations.

    +

    The C++/CLI core library (which is always imported, and is usually +mscorlib.dll) defines a number of special “value class types” (e.g., +System::Int32) that map onto fundamental types (like int). When the +type scanned by decl_specifiers is such a special class type, it is +immediately replaced by the corresponding fundamental type (by a call to +fundamental_type_from_system_type). However, if a handle to a fundamental +type with a corresponding value class type is formed, the fundamental type is +replaced by the class type (through a call to boxed_type_for, which in turn +calls system_type_from_fundamental_type). Handles to enumeration type are +handled similarly: A C++/CLI value class type is created that “boxes” the +enumeration (see make_boxed_enum_type), and the handle is to that class +type.

    +

    Syntactically, handles and tracking references are like pointers and references +that use different declarator operators (”^” and “%” respectively). +They have different semantics and constraints, however. Many of the basic +constraints on their underlying types are checked in +f_check_cli_type_pointed_to.

    +

    Like handles and tracking references, C++/CLI interior pointers and pin +pointers are represented using tk_pointer entries. However, the syntax to +express interior pointers and pin pointers uses template-like angle brackets +(e.g., cli::pin_ptr<X>) instead of declarator operators. The front end +implements support for that syntax by predefining special alias templates +cli::pin_ptr and cli::interior_ptr (see +make_symbol_for_cli_interior_ptr and make_symbol_for_cli_pin_ptr) that +rely on internal __declspec attributes to form the aliased tk_pointer +type.

    +

    CLI arrays are instances of a ref class template cli::array<T, Rank = 1> +(see make_symbol_for_cli_array). Instances of this template have the flag +is_cli_array set (in their class type supplement); this simplifies, among +other things, the implementation of the function is_cli_array_type). CLI +arrays can mostly only be used via handles-to-CLI-arrays (see +check_invalid_use_of_special_cli_class_type).

    +

    A delegate is a special kind of generated reference class type that +encapsulates an “invocation list” (see Delegates (C++/CLI mode) for details). +Like CLI arrays, they can mostly only be used via handles-to-delegates.

    +

    C++/CLI function declarators can include a trailing “parameter array” (with +syntax like “void f(double, ...cli::array<double> ^p)”, where the type must +be a handle to a one-dimensional CLI array). They are akin to traditional C +variadic function arguments (“varargs”), but they are type-safe and limited to +accepting a variadic list of arguments that are all of the same type. A +parameter array is represented with a single a_param_type entry whose +is_cli_param_array flag is TRUE.

    +
    +
    +

    10.4.4. Completing the Declaration#

    +

    Once the declaration specifiers and the declarator have been scanned, it +remains to put the type and other declarative information together and generate +IL and symbol representations for the objects declared.

    +

    If typedef was seen among the declaration specifiers, decl_typedef is +called. It enters a tk_typeref type entry into the IL and an sk_type +symbol in the symbol table. In C++ it has some extra processing when the type +passed in to it is that of a tagless class or enum: the typedef name is +transferred to the class or enum type entry, and in cfront-compatibility mode +the symbol for the class is modified accordingly.

    +

    define_static_data_member is called to process the definition of a static +data member. The IL entry and symbol were created at the original point of +declaration.

    +

    Variables and routines are entered by calling decl_variable or +decl_routine, which are similarly organized functions made fairly +complicated by the need to check the declaration’s compatibility with previous +declarations of the same entity.

    +
      +
    • +
      id_linkage is used to determine whether the declared name has linkage, +and if so, to what (see find_linked_symbol, which returns a symbol if +there is a previous use in scope).
      +
      +
    • +
    • +
      qualified_name_redecl_sym is called instead of id_linkage if the +declarator is a namespace-qualified name (e.g., a friend declaration or a +namespace member definition that appears outside the scope of the namespace +to which it belongs); it also calls find_linked_symbol.
      +
      +
    • +
    • +
      find_linked_symbol not only calls the appropriate lookup routine; it +also deals with function overloading and function template specializations +(see matching_template_function in templates.c).
      +
      +
    • +
    • +
      create_external_symbol_for_linked_entity is called to find any previous +external variable or routine of the same name, even if the previous name +has since gone out of scope; it also checks that the old and new types are +compatible. decl_variable and decl_routine use this information to +decide whether to create a new variable or routine entry or instead to +reuse or complete a previous declaration.
      +
      +
    • +
    +

    “Block-extern” variables and routines have linkage and are always entered at +the file scope or namespace scope in the intermediate language, but their +symbols belong to the current scope in the symbol table (except in pcc +mode, where they are entered at the file scope in the symbol table too). When +a friend declaration introduces a new routine, its symbol is entered in the +innermost enclosing nonclass scope, and the associated routine entry is entered +in the innermost enclosing namespace scope.

    +

    In addition to deciding whether an existing symbol and IL entry can be reused +or new ones need to be created, decl_variable and decl_routine are also +responsible for checking type compatibility, storage class, and name-linkage, +and they call the routines that record cross-reference and source-sequence +information.

    +

    Functions with bodies need additional processing. function_definition +finishes the scanning of a function definition started by declaration. If +there is an old-style parameter list, the declarations are scanned through a +series of calls to declaration. Next, it calls decl_routine (for +normal functions) or define_member_function (for member functions) to +retrieve or create the function’s symbol and routine entry.

    +

    Then, scan_function_body is called. First, the scope stack is fixed up – +if the routine is a member function defined outside the class body, the scope +of the class of which it is a member is reactivated, or, if it is a namespace +member appearing outside the scope of the namespace, a namespace extension +scope is pushed – after which the routine’s own function scope is pushed.

    +

    Function parameter processing is completed within the function scope, so that +parameter variables will be entered into the symbol table correctly. A pass is +made over the linked list of a_param_type entries recorded in the function +type and the linked list of a_param_id entries created from scanning the +parameter declarations (the two lists should be in sync; the latter knows the +name of the parameter, the former only the type), and decl_parameter is +called to create the parameter variable entries.

    +

    When support for variable length arrays is enabled, a fixup is performed on any +VLA declarations that appeared in the function prototype. If the VLA dimension +expression referred to a parameter, a dummy variable is replaced with the +“real” parameter variable that has just been created. Then, the dimension +expression is copied from the file-scope memory region to the function-scope +memory region, and an entry of type a_vla_dimension is created to record it +in the IL.

    +

    If it is a constructor that is being defined, ctor_intializer is called to +scan the constructor initializer list and to enter implicit ctor-initializers; +similar processing is done for a destructor with a call to +dtor_initializer. If this definition appears in the midst of statement +processing (either because it is an inline member function of a local class or +a template instantiation), it is necessary to save the structured statement +stack and start a brand new one (see new_struct_stmt_stack). Then +compound_statement can finally be called to scan the body of the function; +the resulting statement tree is recorded in the assoc_block field of the +function’s scope entry. Before returning, scan_function_body restores the +structured statement stack and pops the various scopes off the scope stack.

    +
    +
    +
    +

    10.5. Initialization#

    +

    Initialization is a broad topic in C and C++. It includes:

    +
      +
    • +
      Setting the initial value of a variable as part of its declaration (the +traditional C notion of initialization)
      +
      +
    • +
    • +
      Initializing members and bases of a class as part of the execution of a +constructor
      +
      +
    • +
    • +
      Initializing a temporary variable as part of a cast or C99-style compound +literal
      +
      +
    • +
    • +
      Passing arguments in a function call (parameter variables are initialized +with argument values)
      +
      +
    • +
    +

    Furthermore, “default” initialization actions may be required even in the +absence of an explicit source construct, and the binding of references, while +treated as a form of initialization, involves a number of rules of its own. +Also, C++17 structured bindings are sometimes “aliases” for expressions and +those are represented as variables with a special kind of “initializer” +(although arguably those do not correspond to actual initialization).

    +

    Source file decl_inits.c is primarily concerned with declaration contexts: +Initializing variables and initializing members of classes as part of +constructor definitions (i.e., the first two bullets). It also includes the +structural handling of aggregate initialization (the traditional brace-enclosed +initializers), and that handling is also used in non-declaration contexts; +particularly, in C99-style compound literals and in various C++11-style list +initialization contexts.

    +
    +

    10.5.1. IL Representation#

    +

    The special case of a variable with static storage duration initialized with a +true constant is represented by associating the a_constant entry directly +with the a_variable entry (via the an_initializer entry embedded in the +variable entry). C++17 structured bindings for array elements and structure +fields are represented as variables with a special kind of “binding” +initializer pointing to the aliased expression (also via the an_initializer +entry). In all other cases, initialization involves a dynamic element and an +entry of type a_dynamic_init is used to represent it (see +Dynamic Initialization).

    +

    In addition, even for entities that are not initialized (or whose +initialization is “trivial”), a dynamic init entry may nonetheless be generated +to represent the eventual destruction of that entity (assuming that entity has +a nontrivial destructor).

    +
    +
    +

    10.5.2. Init Components and Init States#

    +

    It is frequently convenient in the front end to separate the parsing of an +initializer from its actual binding to a target entity. When this is done, the +parsing phase produces an “init component” (type an_init_component, defined +in expr.h). Such a component can represent either

    +
      +
    • +
      an expression, or
      +
      +
    • +
    • +
      a C99-style aggregate member designator, or
      +
      +
    • +
    • +
      a brace-enclosed list of init components.
      +
      +
    • +
    +

    (A fourth kind of “placeholder” init component exists. It represents a +point at which the parsing of a large aggregate initializer has been +suspended for later continuation. This is transparent to the routines +processing initializers because they don’t access the next pointer of +init components directly and instead use macros – like next_elem – that +automatically resume parsing when reaching one of these placeholder +entries.)

    +

    An init component that represents an expression ultimately points to an object +of type an_operand (see Operand Data Structure), as well as other information +needed for the second (“binding”) phase of initializer processing.

    +

    decl_inits.c relies on two functions from expr.c to scan init +components: scan_braced_init_list for list initializers (which in +general will return the top component of a tree representing the braced +structure), and scan_full_initializer_expr_as_component (which will +return a simple expression component). Sometimes, initializers must be +“prescanned” (to deduce the type of a C++11-style auto declaration): +The two aforementioned functions will retrieve the prescanned init +components from a cache if needed. Eventually, +free_init_component_list must be called on the top-level component +produced for every initializer.

    +

    The binding of an initializer as represented by an init component to its target +entity is generally handled by a call to convert_initializer, except for +aggregate initialization where the structure of the initializer is mapped to +that of the target type using a variety of functions (see +Aggregate Initializers) which eventually call the expr.c function +convert_initializer for the non-aggregate “leaf” elements of the aggregate +initializer.

    +

    Initializer processing shares a fair amount of information across calls to a +large number of functions. To facilitate this, the information is recorded in +a structure of type an_init_state. This is both an “input” and an “output” +device: Some fields are used to pass information down the initializer +processing functions, while others are used to return results. In particular, +some input fields inhibit the generation of IL entries +(check_validity_only) and/or the emission of diagnostics +(no_diagnostics): This is needed to handle overload resolution and template +deduction (which requires “tentative” initialization in C++11).

    +

    A declaration parse state block (a_decl_parse_state) embeds an init state +for initialization directly associated with a declaration (variable +initializers, particularly), and in that case, the embedded init state also +contains a pointer back to the associated declaration parse state block.

    +
    +
    +

    10.5.3. Variable Initializers#

    +

    Variable initializers (including initializers for static data members) are +scanned and processed by calling initializer in decl_inits.c. After +checking for errors independently of the initializer itself, and if necessary +deducing the type of the variable from the type of the initializer +(prescan_initializer_for_auto_type_deduction), the function distinguishes +four syntactic cases:

    +
      +
    1. +
      parenthesized initializers (a C++ feature; e.g., “T x(3);”),
      +
      +
    2. +
    3. +
      direct list initializers (a C++11 feature; e.g., “T x{3};”),
      +
      +
    4. +
    5. +
      traditional list initializers (e.g., “T x = {3};”), and
      +
      +
    6. +
    7. +
      simple initializers (e.g., “T x = 3;”).
      +
      +
    8. +
    +

    Parenthesized initializers for class types and for template-dependent types are +the only variations that do not use init components as an intermediate +representation of the initializer: Instead, these cases are handled by calls to +scan_class_parenthesized_initializer and +scan_dependent_type_parenthesized_initializer, respectively. The remaining +parenthesized cases (i.e., those that cannot involve a constructor and +therefore must allow for only a single parenthesized expression) are handled by +expr_direct_init_object.

    +

    Both the C++11-style direct list initialization syntax and the more traditional +list initialization syntax are handled by calls to brace_init_variable, +except that the initialization of a C++/CLI array using traditional list +initialization syntax uses a dedicated routine +aggr_init_cli_array_with_alloc. brace_init_variable calls +braced_initializer

    +

    Finally, initializations of the form “T x = expr” are handled by +expr_init_aggr_variable (for variables of class or array types) and +expr_init_scalar_variable (for scalar variables).

    +

    Structured bindings to array elements and to fields are technically not +variables (they are aliased to components of the unnamed “container” variable +for the binding), but they are represented though a_variable entries in the +front end. These entries have an initk_binding initializer kind and point +to the aliased expression. The routines +record_struct_binding_expr_for_array_element and +record_struct_binding_expr_for_field (both in expr.c) handle this +pseudo-initializers.

    +
    +

    10.5.3.1. Auto type deduction#

    +

    Some modes allow the keyword auto to be used as a type specifier. In such +cases, the actual type must be deduced from the initializer using rules similar +to those for function template argument deduction. This presents an ordering +challenge: The expression handling routines called by initializer must know +the type of the entity being initialized (e.g., to determine appropriate +conversions), but that type is not known until the initializer has been +determined. To address this, the initializer for entities declared with the +auto type specifier is prescanned (routine +prescan_initializer_for_auto_type_deduction in expr.c): That process +deduces the actual type of auto (using the same machinery as that used for +calls of function templates) and records the prescanned init component in the +a_decl_parse_state entity for the current declaration. The routines called +by initializer to scan init components are aware of this record and will +use it instead of actually scanning tokens when appropriate.

    +

    The same mechanism is also used to support the auto type specifier in +new-expressions (scan_new_operator in expr.c) and in +declarations of static const data members with in-class initializers +(decl_static_data_member in class_decl.c).

    +
    +
    +

    10.5.3.2. Default Initialization#

    +

    C++ entities of class type that are declared without an explicit initializer +are “default-initialized” – which means calling the class’s default +constructor (or, for an array, calling the default constructor for each +element):

    +
    struct A { A(); /* ... */ } a;    // a is default-initialized by A::A()
    +
    +
    +

    The routine def_initializer is called for declarations without +initializers, and it generates the default initialization if appropriate. +Default initialization is done only for variables and static data members that +are defined in the current translation unit, and not all classes are subject to +default initialization in the same way:

    +
      +
    1. +
      “POD” structs and unions (roughly, C-style structs: no non-public +members, no user-defined constructor, destructor, or assignment operator, +no base classes, no virtual functions, etc.) are never +default-initialized:
      +
      +
      struct A { int i; };     // POD
      +A a1;                    // a1 goes uninitialized
      +const A a2;              // error -- no explicit initializer
      +
      +
      +
    2. +
    3. +
      Non-POD classes with an implicitly-declared trivial default constructor +(i.e., classes for which each base class or nonstatic data member of +class type, if any, will in turn be initialized with its own trivial +default constructor) are default-initialized only when the object is +non-const:
      +
      +
      struct B { private: int i; };    // implicit trivial B::B()
      +B b1;                            // b1 is default-initialized
      +const B b2;                      // error -- no explicit initializer
      +
      +
      +
    4. +
    5. +
      Classes with an implicitly-declared nontrivial default constructor are +likewise default-initialized only when the object is non-const:
      +
      +
      struct C { int i; virtual void f(); }; // implicit nontrivial C::C()
      +C c1;                                  // c1 is default-initialized
      +const C c2;                            // error -- no explicit initializer
      +
      +
      +
    6. +
    7. +
      Classes with at least one user-declared constructor are default +initialized whether or not the object is const:
      +
      +
    8. +
    +
    +
    struct D { int i; D(); };   // user-declared D::D()
    +D d1;                       // d1 is default-initialized
    +const D d2;                 // d2 is default-initialized
    +
    +
    +
    +

    A further distinction is made between the second and third groups (classes with +trivial vs. nontrivial implicitly declared default constructor): b1 and +c1 differ in how their default initialization is implemented. A call to +the nontrivial default constructor C::C() is actually added to the IL (it +needs to deal with the virtual function info for class C), but the trivial +default constructor B::B() need not actually be called, since calling it +would have no effect. Its definition is generated in case there might be +compile-time side-effects (see reference_to_trivial_default_constructor in +symbol_ref.c), but the IL for a trivial default constructor does not appear +in the IL.

    +
    +
    +
    +

    10.5.4. Aggregate Initializers#

    +

    An aggregate type is an array type or a class type that has no user-provided +constructors. When an entity of such a type is initialized with a +braced-enclosed construct, the front end traverses the initializer structure +and the destination type’s structure mapping one onto the other. The result is +an aggregate constant (ck_aggregate), which may contain elements that are +not actually constants (i.e., ck_dynamic_init “constants”). Four cases are +distinguished:

    +
      +
    • +
      aggregate class types: handled by aggr_init_class, with help from +aggr_init_field_designator to handle C99- and GNU-style designators, +and from aggr_init_class_remainder_if_needed to represent nontrivial +initializations (in C++) of fields that have no explicit initializer.
      +
      +
    • +
    • +
      array types: handled by aggr_init_array, with help from +aggr_init_array_designator to handle designators, and from +aggr_init_array_remainder_if_needed to represent nontrivial +initializations (in C++) of array elements that have no explicit +initializer.
      +
      +
    • +
    • +
      template-dependent types: handled by aggr_init_generic_element; since +the structure of the destination type is not known in that case, the +structure of the resulting constant is entirely determined by the +brace-structure of the initializer.
      +
      +
    • +
    • +
      C++/CLI array types: handled by aggr_init_cli_array with help from +aggr_init_cli_array_level (which deals with the special rules for +deducing CLI array dimensions from the initializer when applicable).
      +
      +
    • +
    +

    The cases can be composed (e.g., an aggregate struct can contain an array of +aggregate structs), which is handled through recursion: aggr_init_element +handles the dispatching of the recursion based on the subaggregate object’s +type. Leaf entities (i.e., entities whose initialization doesn’t fall into one +of the cases above) are handled by aggr_init_simple_element. Cleanup +actions needed in case of an exception occurring during the initialization of a +leaf entity – including default initialization – is handled by calls to +record_partial_aggregate_cleanup_destruction.

    +

    The complete handling of a top-level aggregate initialization is initiated +either by a call to braced_initializer (for the initialization of variables +and static data members, compound literals, and constructor-initializers), or +by a call to prep_aggr_initializer (for all other expression contexts).

    +

    While “aggregate initializer” mainly deals with the initialization of an entity +of aggregate type with a brace-enclosed construct, it also includes the +initialization of a character array with a string literal. This can happen at +the top-level (e.g., “char str[] = "text”;”) or at a subaggregate level +(e.g., “X x = { 1, 2, "three" };”). A central routine for this aspect of +initialization is try_string_literal_init.

    +
    +
    +

    10.5.5. Constructor Initializers#

    +

    Constructor initializers can be written explicitly in the source:

    +
    struct A {
    +  int i, j;
    +  A() : i(1), j{2}  // Constructor initializers with parenthesized
    +    {}              // and braced syntax, respectively.
    +};
    +
    +
    +

    They can also be generated implicitly by the front end for class members and +base classes that must be initialized and are not explicitly initialized in the +source. (This includes, as an extreme case, constructor routines that are +front-end-generated; any needed constructor-initializers would have to be +implicit).

    +

    ctor_initializer builds the proper list of constructor-initializer entries +and attaches it to a constructor routine entry. It is called with a flag that +indicates whether or not it should attempt to scan the source construct (if +not, it just generates a default list without looking at the source).

    +

    The list generated is in the “right” order, that is, the order in which +initialization should be done, which is not necessarily the order in which the +explicit constructor-initializer clauses were written. The list contains three +parts, tracked by the a_ctor_init_block data structure: direct base +entries, virtual base entries, and field entries. Each initialization is +represented in the IL with an entry of type a_constructor_init (which in +turn points to a dynamic init entry).

    +

    The explicit clauses are scanned by calling scan_mem_initializer, which +ultimately calls

    +
      +
    • +
      scan_parenthesized_mem_init_args for parenthesized initializers (often +in turn calling scan_dependent_type_parenthesized_initializer for +template-dependent entities, scan_class_parenthesized_initializer for +class type entities initialized through a constructor call, or +expr_direct_init_object for other initializations not involving a +constructor).
      +
      +
    • +
    • +
      braced_initializer for C++11-style braced initializers.
      +
      +
    • +
    +

    Once any explicit clauses have been scanned, default initializers are generated +for any base classes and members that require them. In addition, in C++11 +mode, implicit constructor initializer entries may be generated for fields with +“field initializers” (see also Field Initializers): Such entries do not decribe +the initialization directly, but defer to the initializer recorded in the +a_field entry by setting the use_field_initializer flag to TRUE.

    +
    +
    +

    10.5.6. Destructor-initializers#

    +

    The destructor-initializers list attached to a destructor indicates any +destructions required for base classes and members of the destructor’s class. +The list is in the order in which the destructions should be done, i.e., the +reverse of the order of the list on the corresponding constructor.

    +

    Unlike in the constructor case, there is no source form for the +destructor-initializers, and therefore all the entries on the list are +front-end generated.

    +
    +
    +
    +

    10.6. Type Names in Expressions#

    +

    When a type name appears in an expression, routines that are used in +declaration processing are invoked to scan the type name.

    +

    type_name is called to scan a type that appears in a cast expression or as +an argument to sizeof. It calls [4] decl_specifiers and, for +abstractor declarators only, declarator. It returns a pointer to a type.

    +

    new_type_name is called to scan a C++ new-type-name or a parenthesized +type-name that may appear in a new expression. Only abstract declarators +are allowed, but a nonconstant bound expression is permitted for the first +array dimension.

    +
    +
    +

    10.7. asm Declarations#

    +

    asm_declaration is called when an asm keyword is encountered. A +parenthesized string literal is scanned and recorded in an entity of kind +an_asm_entry. The asm-string is not parsed or validated by the front +end – it is simply passed as-is to the back end.

    +

    In Microsoft and GNU modes, some syntax variations are accepted, and in GNU +modes, this can involve some limited validation checks.

    +
    +
    +

    10.8. Namespaces#

    +
    +

    10.8.1. Namespace Declarations#

    +

    namespace_declaration is called to process original namespace definitions, +namespace extensions, and declarations of namespace aliases.

    +

    When a namespace is originally declared, an entry of type a_namespace is +created and an sk_namespace symbol is entered in the symbol table. Then, +an sck_namespace scope is pushed, and declarations inside the namespace are +represented by symbols that are entered on the active symbol list of a given +symbol header; when the scope is popped the symbols are moved from the active +list to the inactive list. However, that namespace can be reopened again, in +which case it is an sck_namespace_extension scope that is pushed onto the +scope stack. It points to the same IL scope as the original sck_namespace +scope, but symbols that are entered within this scope are added directly to the +inactive list. This affects how name lookup is done inside a namespace +extension definition – see the Symbol Table chapter.

    +

    For both original and extending namespace definitions, once the appropriate +scope has been pushed, a loop is executed to make a series of calls to +declaration until the closing } of the namespace definition is +encountered. Then the sck_namespace or sck_namespace_extension scope +is popped off the scope stack.

    +

    Unnamed namespace definitions are a special case. For an original unnamed +namespace definition, an sck_namespace scope is immediately pushed and then +popped, a using-directive is simulated, and then an +sck_namespace_extension scope is opened. [5] In other words, an +original unnamed namespace definition that is written like this

    +
    namespace {
    +  int i;
    +}
    +
    +
    +

    is represented internally as if it were

    +
    +
    +
    namespace <unnamed> { }
    +
    using namespace <unnamed>;
    +
    namespace <unnamed> {
    +
    +
    int i;
    +
    +
    }
    +
    +
    +

    namespace_declaration also handles declarations of namespace aliases, for +which a namespace IL entry and a namespace symbol are also created. However, +in this case the namespace IL entry has its is_namespace_alias flag set to +TRUE and points not to an associated IL scope but to the namespace entry it +stands for.

    +
    +
    +

    10.8.2. Using-Directives#

    +

    A using-directive is processed by using_directive, which looks up the +namespace name and calls make_using_directive to create and enter an entry +of type a_using_decl and to “activate” the using directive in the current +scope (see add_active_using_directive in scope_stk.c). The effect of a +using-directive on the lookup algorithm is discussed in the Symbol Table +chapter.

    +
    +
    +

    10.8.3. Using-Declarations#

    +

    A using-declaration that appears in a scope other than that of a class +definition is processed by nonmember_using_declaration. [6] First it +looks up and validates the namespace-qualified or globally qualified name. +Then it enters an sk_namespace_projection symbol to represent the name +pulled into the current scope by the using-declaration.

    +

    When a using-declaration specifies the name of an overloaded function, each +member of the overload set will have its own projection symbol. An overload +set in the current scope may end up with a mix of sk_routine symbols +(declarations from the current scope) and sk_namespace_projection symbols +(referring to declarations from another scope). +conflicts_with_previous_function_decl is called to determine if a function +specified by a using-declaration is not distinguishable, for purposes of +overloading, from functions actually declared in the current scope.

    +

    An IL entry is created to represent the using-declaration (see +make_using_decl); it is available to back ends from the using_decls +list pointed to from the current scope.

    +
    +
    +
    +

    10.9. Standard Attributes, GNU Attributes, and __declspec Attributes#

    +

    In declarative contexts, the processing for standard attributes (delimited by +double square brackets) is very similar to that for GNU attributes +(”__attribute((...))”) and Microsoft __declspec(...) attributes. The +main difference (other than the delimiting tokens) is that standard attributes +have strict “appertaining rules” whereas nonstandard (GNU and Microsoft +__declspec) attributes can be placed more loosely. The standard rules are +basically that an attribute applies to the construct immediately preceding it, +except for “prefix attributes” which apply to all the entities denoted by the +declarators of the prefixed declaration. With nonstandard attributes, the +entity modified by an attribute depends on the attribute. For example:

    +
    [[noreturn]] int [[X]] f [[ nothrow ]] () [[Y]], g();    // (1)
    +#define A __attribute
    +A((noreturn)) int A((nothrow)) f() A((pure)), g();       // (2)
    +
    +
    +

    In (1), the noreturn attribute applies to the functions f and g, +and any attribute in that location would apply to those entities. The unknown +attribute X (in (1)) applies to int, nothrow applies to f, and +Y applies to the function type associated with the function declarator that +precedes it. (There are currently no standard attributes that could appear in +the locations indicated by X and Y, but the language specification does +anticipate their appertainance.)

    +

    While in (2) the noreturn attribute applies as in (1), the nothrow +attribute applies to the type of f (a function type) and the pure +attribute applies to f itself. Furthermore, the locations of the +nothrow and pure attributes can be interchanged with no change of +meaning.

    +

    The principal routines for parsing and applying attributes are described in +detail Pragmas and Attributes. For attributes that apply to +declarations, the attribute application “callback” functions can rely on the +assoc_info field of the attribute entry pointing to the +a_decl_parse_state structure for that declaration.

    +
    +
    +

    10.10. Microsoft Attributes#

    +

    In Microsoft mode, Microsoft attributes delimited by single brackets are +accepted. Attributes may, in general, be specified where a declaration is +accepted. In particular, they are accepted in namespace scopes, class scopes, +and in function parameter lists. Attributes have the form:

    +
    [attribute_name]
    +[attribute_name(args)]
    +
    +
    +

    When the bracket that begins an attribute is encountered, +scan_microsoft_attributes is used to scan the attributes and create the IL +entries used to represent them. A list of attributes is returned. This list +is later passed to one of the following routines that either add the attributes +to the IL or issue the appropriate diagnostics if the attributes appear in +invalid locations:

    +
    apply_microsoft_attributes
    +verify_standalone_attributes
    +dispose_of_unapplied_attributes
    +
    +
    +

    The attribute scanning routines use an attribute description data structure to +describe the attributes that should be recognized and to describe the argument +lists expected by those attributes. When the +RECOGNIZE_MICROSOFT_ATTRIBUTES macro is TRUE, the front end supplies +attribute descriptions for the documented Microsoft attributes. When +SUPPRESS_MICROSOFT_ATTRIBUTE_PROCESSING is TRUE, the Microsoft attributes +are recognized in the sense that no “unrecognized attribute” warning is issued, +but they are otherwise treated as unrecognized attributes (see below).

    +

    Each attribute is represented by an entry of type an_ms_attribute. The +entry contains a string representation of the attribute. In addition, a +structured representation is also created for recognized attributes. In the +structured representation, each attribute has a list of associated argument +values. The argument values are checked to verify that they match the kind of +value expected for a given argument (e.g., for a boolean parameter the value +must be true or false). When processing an unrecognized attribute, no semantic +checking of argument values is performed and no checking is done to verify that +a given attribute is used in an acceptable location.

    +

    Attribute processing results in a list of attribute IL entries, and a flag +in the source correspondence that indicates that attributes apply to a +given entity (see the Intermediate Language chapter for more +information). The source correspondence flag is only available when the +structured attribute representation is being used. Beyond the error +checking described above, no additional semantic processing of attributes +is performed. For example, no code insertion is performed for the COM +attributes.

    +

    C++/CLI makes use of the same attribute syntax. Currently, however, no +C++/CLI-specific attributes are recognized (and as a consequence no associated +semantics are implemented).

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/err_msgs/index.html b/doc/err_msgs/index.html new file mode 100644 index 0000000..30c3bc5 --- /dev/null +++ b/doc/err_msgs/index.html @@ -0,0 +1,23315 @@ + + + + + 19. Error Messages - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    19. Error Messages#

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    0001

    +
    last_line_incomplete:
    +
    last line of file ends without a newline
    +
    +

    0002

    +
    last_line_backslash:
    +
    last line of file ends with a backslash
    +
    +

    0003

    +
    include_recursion:
    +
    #include file “xxxx” includes itself
    +
    +

    0004

    +
    out_of_memory:
    +
    out of memory
    +
    +

    0006

    +
    comment_unclosed_at_eof:
    +
    comment unclosed at end of file
    +
    +

    0007

    +
    bad_token:
    +
    unrecognized token
    +
    +

    0008

    +
    unclosed_string:
    +
    missing closing quote
    +
    +

    0009

    +
    nested_comment:
    +
    nested comment is not allowed
    +
    +

    0010

    +
    bad_use_of_sharp:
    +
    “#” not expected here
    +
    +

    0011

    +
    bad_pp_directive_keyword:
    +
    unrecognized preprocessing directive
    +
    +

    0012

    +
    end_of_flush:
    +
    parsing restarts here after previous syntax error
    +
    +

    0013

    +
    exp_file_name:
    +
    expected a file name
    +
    +

    0014

    +
    extra_text_in_pp_directive:
    +
    extra text after expected end of preprocessing directive
    +
    +

    0017

    +
    exp_rbracket:
    +
    expected a “]”
    +
    +

    0018

    +
    exp_rparen:
    +
    expected a “)”
    +
    +

    0019

    +
    extra_chars_on_number:
    +
    extra text after expected end of number
    +
    +

    0020

    +
    undefined_identifier:
    +
    identifier “xxxx” is undefined
    +
    +

    0021

    +
    useless_type_qualifiers:
    +
    type qualifiers are meaningless in this declaration
    +
    +

    0022

    +
    bad_hex_digit:
    +
    invalid hexadecimal number
    +
    +

    0023

    +
    integer_too_large:
    +
    integer constant is too large
    +
    +

    0024

    +
    bad_octal_digit:
    +
    invalid octal digit
    +
    +

    0025

    +
    zero_length_string:
    +
    quoted string should contain at least one character
    +
    +

    0026

    +
    too_many_characters:
    +
    too many characters in character constant
    +
    +

    0027

    +
    bad_character_value:
    +
    character value is out of range
    +
    +

    0028

    +
    expr_not_constant:
    +
    expression must have a constant value
    +
    +

    0029

    +
    exp_primary_expr:
    +
    expected an expression
    +
    +

    0030

    +
    bad_float_value:
    +
    floating constant is out of range
    +
    +

    0031

    +
    expr_not_integral:
    +
    expression must have integral type
    +
    +

    0032

    +
    expr_not_arithmetic:
    +
    expression must have arithmetic type
    +
    +

    0033

    +
    exp_line_number:
    +
    expected a line number
    +
    +

    0034

    +
    bad_line_number:
    +
    invalid line number
    +
    +

    0035

    +
    error_directive:
    +
    #error directive: xxxx
    +
    +

    0036

    +
    missing_pp_if:
    +
    the #if for this directive is missing
    +
    +

    0037

    +
    missing_endif:
    +
    the #endif for this directive is missing
    +
    +

    0038

    +
    pp_else_already_appeared:
    +
    directive is not allowed – an #else has already appeared
    +
    +

    0039

    +
    divide_by_zero:
    +
    division by zero
    +
    +

    0040

    +
    exp_identifier:
    +
    expected an identifier
    +
    +

    0041

    +
    expr_not_scalar:
    +
    expression must have arithmetic or pointer type
    +
    +

    0042

    +
    incompatible_operands:
    +
    operand types are incompatible (“type” and “type”)
    +
    +

    0044

    +
    expr_not_pointer:
    +
    expression must have pointer type
    +
    +

    0045

    +
    cannot_undef_predef_macro:
    +
    #undef may not be used on this predefined name
    +
    +

    0046

    +
    cannot_redef_predef_macro:
    +
    “entity” is predefined; attempted redefinition ignored
    +
    +

    0047

    +
    bad_macro_redef:
    +
    incompatible redefinition of macro “entity” (declared at line +xxxx)
    +
    +

    0049

    +
    duplicate_macro_param_name:
    +
    duplicate macro parameter name
    +
    +

    0050

    +
    paste_cannot_be_first:
    +
    “##” may not be first in a macro definition
    +
    +

    0051

    +
    paste_cannot_be_last:
    +
    “##” may not be last in a macro definition
    +
    +

    0052

    +
    exp_macro_param:
    +
    expected a macro parameter name
    +
    +

    0053

    +
    exp_colon:
    +
    expected a “:”
    +
    +

    0054

    +
    too_few_macro_args:
    +
    too few arguments in invocation of entity-kind “entity”
    +
    +

    0055

    +
    too_many_macro_args:
    +
    too many arguments in invocation of entity-kind “entity”
    +
    +

    0056

    +
    sizeof_function:
    +
    operand of sizeof may not be a function
    +
    +

    0057

    +
    bad_constant_operator:
    +
    this operator is not allowed in a constant expression
    +
    +

    0058

    +
    bad_pp_operator:
    +
    this operator is not allowed in a preprocessing expression
    +
    +

    0059

    +
    bad_constant_function_call:
    +
    function call is not allowed in a constant expression
    +
    +

    0060

    +
    bad_integral_operator:
    +
    this operator is not allowed in an integral constant expression
    +
    +

    0061

    +
    integer_overflow:
    +
    integer operation result is out of range
    +
    +

    0062

    +
    negative_shift_count:
    +
    shift count is negative
    +
    +

    0063

    +
    shift_count_too_large:
    +
    shift count is too large
    +
    +

    0064

    +
    useless_decl:
    +
    declaration does not declare anything
    +
    +

    0065

    +
    exp_semicolon:
    +
    expected a “;”
    +
    +

    0066

    +
    enum_value_out_of_int_range:
    +
    enumeration value is out of “int” range
    +
    +

    0067

    +
    exp_rbrace:
    +
    expected a “}”
    +
    +

    0068

    +
    integer_sign_change:
    +
    integer conversion resulted in a change of sign
    +
    +

    0069

    +
    integer_truncated:
    +
    integer conversion resulted in truncation
    +
    +

    0070

    +
    incomplete_type_not_allowed:
    +
    incomplete type “type” is not allowed
    +
    +

    0071

    +
    sizeof_bit_field:
    +
    operand of sizeof may not be a bit field
    +
    +

    0075

    +
    bad_indirection_operand:
    +
    operand of “*” must be a pointer but has type “type”
    +
    +

    0076

    +
    empty_macro_argument:
    +
    argument to macro is empty
    +
    +

    0077

    +
    missing_decl_specifiers:
    +
    this declaration has no storage class or type specifier
    +
    +

    0078

    +
    initializer_in_param:
    +
    a parameter declaration may not have an initializer
    +
    +

    0079

    +
    exp_type_specifier:
    +
    expected a type specifier
    +
    +

    0080

    +
    storage_class_not_allowed:
    +
    a storage class may not be specified here
    +
    +

    0081

    +
    mult_storage_classes:
    +
    more than one storage class may not be specified
    +
    +

    0082

    +
    storage_class_not_first:
    +
    storage class is not first
    +
    +

    0083

    +
    dupl_type_qualifier:
    +
    type qualifier specified more than once
    +
    +

    0084

    +
    bad_combination_of_type_specifiers:
    +
    invalid combination of type specifiers
    +
    +

    0085

    +
    bad_param_storage_class:
    +
    invalid storage class for a parameter
    +
    +

    0086

    +
    bad_function_storage_class:
    +
    invalid storage class for a function
    +
    +

    0087

    +
    type_specifier_not_allowed:
    +
    a type specifier may not be used here
    +
    +

    0088

    +
    array_of_function:
    +
    array of functions is not allowed
    +
    +

    0089

    +
    array_of_void:
    +
    array of void is not allowed
    +
    +

    0090

    +
    function_returning_function:
    +
    function returning function is not allowed
    +
    +

    0091

    +
    function_returning_array:
    +
    function returning array is not allowed
    +
    +

    0092

    +
    param_id_list_needs_function_def:
    +
    identifier-list parameters may only be used in a function definition
    +
    +

    0093

    +
    function_type_must_come_from_declarator:
    +
    function type may not come from a typedef
    +
    +

    0094

    +
    array_size_must_be_positive:
    +
    the size of an array must be greater than zero
    +
    +

    0095

    +
    array_size_too_large:
    +
    array is too large
    +
    +

    0096

    +
    empty_translation_unit:
    +
    a translation unit must contain at least one declaration
    +
    +

    0097

    +
    bad_function_return_type:
    +
    a function may not return a value of this type
    +
    +

    0098

    +
    bad_array_element_type:
    +
    an array may not have elements of this type
    +
    +

    0099

    +
    decl_should_be_of_param:
    +
    a declaration here must declare a parameter
    +
    +

    0100

    +
    dupl_param_name:
    +
    duplicate parameter name
    +
    +

    0101

    +
    id_already_declared:
    +
    “xxxx” has already been declared in the current scope
    +
    +

    0102

    +
    nonstd_forward_decl_enum:
    +
    forward declaration of enum type is nonstandard
    +
    +

    0103

    +
    class_too_large:
    +
    class is too large
    +
    +

    0104

    +
    struct_too_large:
    +
    struct or union is too large
    +
    +

    0105

    +
    bad_bit_field_size:
    +
    invalid size for bit field
    +
    +

    0106

    +
    bad_bit_field_type:
    +
    invalid type for a bit field
    +
    +

    0107

    +
    zero_length_bit_field_must_be_unnamed:
    +
    zero-length bit field must be unnamed
    +
    +

    0108

    +
    signed_one_bit_field:
    +
    signed bit field of length 1
    +
    +

    0109

    +
    expr_not_ptr_to_function:
    +
    expression preceding parentheses of apparent call must have +(pointer-to-) function type
    +
    +

    0110

    +
    exp_definition_of_tag:
    +
    expected either a definition or a tag name
    +
    +

    0111

    +
    code_is_unreachable:
    +
    statement is unreachable
    +
    +

    0112

    +
    exp_while:
    +
    expected “while”
    +
    +

    0114

    +
    never_defined:
    +
    entity-kind “entity” was referenced but not defined
    +
    +

    0115

    +
    continue_must_be_in_loop:
    +
    a continue statement may only be used within a loop
    +
    +

    0116

    +
    break_must_be_in_loop_or_switch:
    +
    a break statement may only be used within a loop or switch
    +
    +

    0117

    +
    no_value_returned_in_non_void_function:
    +
    non-void entity-kind “entity” should return a value
    +
    +

    0118

    +
    value_returned_in_void_function:
    +
    a void function may not return a value
    +
    +

    0119

    +
    cast_to_bad_type:
    +
    cast to type “type” is not allowed
    +
    +

    0120

    +
    bad_return_value_type:
    +
    return value type does not match the function type
    +
    +

    0121

    +
    case_label_must_be_in_switch:
    +
    a case label may only be used within a switch
    +
    +

    0122

    +
    default_label_must_be_in_switch:
    +
    a default label may only be used within a switch
    +
    +

    0124

    +
    default_label_appears_more_than_once:
    +
    default label has already appeared in this switch
    +
    +

    0125

    +
    exp_lparen:
    +
    expected a “(”
    +
    +

    0126

    +
    expr_not_an_lvalue:
    +
    expression must be an lvalue
    +
    +

    0127

    +
    exp_statement:
    +
    expected a statement
    +
    +

    0128

    +
    loop_not_reachable:
    +
    loop is not reachable
    +
    +

    0129

    +
    block_scope_function_must_be_extern:
    +
    a block-scope function may only have extern storage class
    +
    +

    0130

    +
    exp_lbrace:
    +
    expected a “{”
    +
    +

    0131

    +
    expr_not_ptr_to_class:
    +
    expression must have pointer-to-class type but it has type “type”
    +
    +

    0132

    +
    expr_not_ptr_to_struct_or_union:
    +
    expression must have pointer-to-struct-or-union type but it has type +“type”
    +
    +

    0133

    +
    exp_member_name:
    +
    expected a member name
    +
    +

    0134

    +
    exp_field_name:
    +
    expected a field name
    +
    +

    0135

    +
    not_a_member:
    +
    entity-kind “entity” has no member “xxxx”
    +
    +

    0136

    +
    not_a_field:
    +
    entity-kind “entity” has no field “xxxx”
    +
    +

    0137

    +
    expr_not_a_modifiable_lvalue:
    +
    expression must be a modifiable lvalue
    +
    +

    0138

    +
    address_of_register_variable:
    +
    taking the address of a register variable is not allowed
    +
    +

    0139

    +
    address_of_bit_field:
    +
    taking the address of a bit field is not allowed
    +
    +

    0140

    +
    too_many_arguments:
    +
    too many arguments in function call
    +
    +

    0141

    +
    all_proto_params_must_be_named:
    +
    unnamed prototyped parameters not allowed when body is present
    +
    +

    0142

    +
    expr_not_pointer_to_object:
    +
    expression must have pointer-to-object type but it has type “type”
    +
    +

    0143

    +
    program_too_large:
    +
    program too large or complicated to compile
    +
    +

    0144

    +
    bad_initializer_type:
    +
    a value of type “type” cannot be used to initialize an entity of +type “type”
    +
    +

    0145

    +
    cannot_initialize:
    +
    entity-kind “entity” may not be initialized
    +
    +

    0146

    +
    too_many_initializer_values:
    +
    too many initializer values
    +
    +

    0147

    +
    not_compatible_with_previous_decl:
    +
    declaration is incompatible with entity-kind “entity” (declared +at line xxxx)
    +
    +

    0148

    +
    already_initialized:
    +
    entity-kind “entity” has already been initialized
    +
    +

    0149

    +
    bad_file_scope_storage_class:
    +
    a global-scope declaration may not have this storage class
    +
    +

    0150

    +
    type_cannot_be_param_name:
    +
    a type name may not be redeclared as a parameter
    +
    +

    0151

    +
    typedef_cannot_be_param_name:
    +
    a typedef name may not be redeclared as a parameter
    +
    +

    0152

    +
    non_zero_int_conv_to_pointer:
    +
    conversion of nonzero integer to pointer
    +
    +

    0153

    +
    expr_not_class:
    +
    expression must have class type but it has type “type”
    +
    +

    0154

    +
    expr_not_struct_or_union:
    +
    expression must have struct or union type but it has type “type”
    +
    +

    0155

    +
    old_fashioned_assignment_operator:
    +
    old-fashioned assignment operator
    +
    +

    0156

    +
    old_fashioned_initializer:
    +
    old-fashioned initializer
    +
    +

    0157

    +
    expr_not_integral_constant:
    +
    expression must be an integral constant expression
    +
    +

    0158

    +
    expr_not_an_lvalue_or_function_designator:
    +
    expression must be an lvalue or a function designator
    +
    +

    0159

    +
    decl_incompatible_with_previous_use:
    +
    declaration is incompatible with previous “entity” (declared at +line xxxx)
    +
    +

    0160

    +
    external_name_clash:
    +
    external name conflicts with external name of entity-kind +“entity” (declared at line xxxx)
    +
    +

    0161

    +
    unrecognized_pragma:
    +
    unrecognized #pragma
    +
    +

    0163

    +
    cannot_open_temp_file_reason:
    +
    could not open temporary file “xxxx”: xxxx
    +
    +

    0165

    +
    too_few_arguments:
    +
    too few arguments in function call
    +
    +

    0166

    +
    bad_float_constant:
    +
    invalid floating constant
    +
    +

    0167

    +
    incompatible_param:
    +
    argument of type “type” is incompatible with parameter of type +“type”
    +
    +

    0168

    +
    function_type_not_allowed:
    +
    a function type is not allowed here
    +
    +

    0169

    +
    exp_declaration:
    +
    expected a declaration
    +
    +

    0170

    +
    pointer_outside_base_object:
    +
    pointer points outside of underlying object
    +
    +

    0171

    +
    bad_cast:
    +
    invalid type conversion
    +
    +

    0172

    +
    linkage_conflict:
    +
    external/internal linkage conflict with previous declaration at line +xxxx
    +
    +

    0173

    +
    float_to_integer_conversion:
    +
    floating-point value does not fit in required integral type
    +
    +

    0174

    +
    expr_has_no_effect:
    +
    expression has no effect
    +
    +

    0175

    +
    subscript_out_of_range:
    +
    subscript out of range
    +
    +

    0177

    +
    declared_but_not_referenced:
    +
    entity-kind “entity” was declared but never referenced
    +
    +

    0178

    +
    pcc_address_of_array:
    +
    “&” applied to an array has no effect
    +
    +

    0179

    +
    mod_by_zero:
    +
    right operand of “%” is zero
    +
    +

    0180

    +
    old_style_incompatible_param:
    +
    argument is incompatible with formal parameter
    +
    +

    0181

    +
    printf_arg_mismatch:
    +
    argument is incompatible with corresponding format string conversion +(expected type “type” but argument has type “type”)
    +
    +

    0182

    +
    empty_include_search_path:
    +
    could not open source file “xxxx” (no directories in search list)
    +
    +

    0183

    +
    cast_not_integral:
    +
    type of cast must be integral
    +
    +

    0184

    +
    cast_not_scalar:
    +
    type of cast must be arithmetic or pointer
    +
    +

    0185

    +
    initialization_not_reachable:
    +
    dynamic initialization in unreachable code
    +
    +

    0186

    +
    unsigned_compare_with_zero:
    +
    pointless comparison of unsigned integer with zero
    +
    +

    0187

    +
    assign_where_compare_meant:
    +
    use of “=” where “==” may have been intended
    +
    +

    0188

    +
    mixed_enum_type:
    +
    enumerated type mixed with another type
    +
    +

    0189

    +
    file_write_error:
    +
    error while writing xxxx file
    +
    +

    0190

    +
    bad_il_file:
    +
    invalid intermediate language file
    +
    +

    0191

    +
    cast_to_qualified_type:
    +
    type qualifier is meaningless on cast type
    +
    +

    0192

    +
    unrecognized_char_escape:
    +
    unrecognized character escape sequence
    +
    +

    0193

    +
    undefined_preproc_id:
    +
    zero used for undefined preprocessing identifier “xxxx”
    +
    +

    0194

    +
    exp_asm_string:
    +
    expected an asm string
    +
    +

    0195

    +
    asm_func_must_be_prototyped:
    +
    an asm function must be prototyped
    +
    +

    0196

    +
    bad_asm_func_ellipsis:
    +
    an asm function may not have an ellipsis
    +
    +

    0219

    +
    file_delete_error_reason:
    +
    error while deleting file “xxxx”: xxxx
    +
    +

    0220

    +
    integer_to_float_conversion:
    +
    integral value does not fit in required floating-point type
    +
    +

    0221

    +
    float_to_float_conversion:
    +
    floating-point value does not fit in required floating-point type
    +
    +

    0222

    +
    bad_float_operation_result:
    +
    floating-point operation result is out of range
    +
    +

    0223

    +
    implicit_func_decl:
    +
    function “xxxx” declared implicitly
    +
    +

    0224

    +
    too_few_printf_args:
    +
    the format string requires additional arguments
    +
    +

    0225

    +
    too_many_printf_args:
    +
    the format string ends before this argument
    +
    +

    0226

    +
    bad_printf_format_string:
    +
    invalid format string conversion
    +
    +

    0227

    +
    macro_recursion:
    +
    macro recursion
    +
    +

    0228

    +
    nonstd_extra_comma:
    +
    trailing comma is nonstandard
    +
    +

    0229

    +
    enum_bit_field_too_small:
    +
    bit field cannot contain all values of the enumerated type
    +
    +

    0230

    +
    nonstd_bit_field_type:
    +
    nonstandard type for a bit field
    +
    +

    0231

    +
    decl_in_prototype_scope:
    +
    declaration is not visible outside of function
    +
    +

    0232

    +
    decl_of_void_ignored:
    +
    old-fashioned typedef of “void” ignored
    +
    +

    0233

    +
    old_fashioned_field_selection:
    +
    left operand is not a struct or union containing this field
    +
    +

    0234

    +
    old_fashioned_ptr_field_selection:
    +
    pointer does not point to struct or union containing this field
    +
    +

    0235

    +
    var_retained_incomp_type:
    +
    variable “xxxx” was declared with a never-completed type
    +
    +

    0236

    +
    boolean_controlling_expr_is_constant:
    +
    controlling expression is constant
    +
    +

    0237

    +
    switch_selector_expr_is_constant:
    +
    selector expression is constant
    +
    +

    0238

    +
    bad_param_specifier:
    +
    invalid specifier on a parameter
    +
    +

    0239

    +
    bad_specifier_outside_class_decl:
    +
    invalid specifier outside a class declaration
    +
    +

    0240

    +
    dupl_decl_specifier:
    +
    duplicate specifier in declaration
    +
    +

    0241

    +
    base_class_not_allowed_for_union:
    +
    a union is not allowed to have a base class
    +
    +

    0242

    +
    access_already_specified:
    +
    multiple access control specifiers are not allowed
    +
    +

    0243

    +
    missing_class_definition:
    +
    class or struct definition is missing
    +
    +

    0244

    +
    name_not_member_of_class_or_base_classes:
    +
    qualified name is not a member of class “type” or its base classes
    +
    +

    0245

    +
    member_ref_requires_object:
    +
    a nonstatic member reference must be relative to a specific object
    +
    +

    0246

    +
    nonstatic_member_def_not_allowed:
    +
    a nonstatic data member may not be defined outside its class
    +
    +

    0247

    +
    already_defined:
    +
    entity-kind “entity” has already been defined
    +
    +

    0248

    +
    pointer_to_reference:
    +
    pointer to reference is not allowed
    +
    +

    0249

    +
    reference_to_reference:
    +
    reference to reference is not allowed
    +
    +

    0250

    +
    reference_to_void:
    +
    reference to void is not allowed
    +
    +

    0251

    +
    array_of_reference:
    +
    array of reference is not allowed
    +
    +

    0252

    +
    missing_initializer_on_reference:
    +
    reference entity-kind “entity” requires an initializer
    +
    +

    0253

    +
    exp_comma:
    +
    expected a “,”
    +
    +

    0254

    +
    type_identifier_not_allowed:
    +
    type name is not allowed
    +
    +

    0255

    +
    type_definition_not_allowed:
    +
    type definition is not allowed
    +
    +

    0256

    +
    bad_type_name_redeclaration:
    +
    invalid redeclaration of type name “entity” (declared at line +xxxx)
    +
    +

    0257

    +
    missing_initializer_on_const:
    +
    const entity-kind “entity” requires an initializer
    +
    +

    0258

    +
    this_used_incorrectly:
    +
    “this” may only be used inside a nonstatic member function
    +
    +

    0259

    +
    constant_value_not_known:
    +
    constant value is not known
    +
    +

    0260

    +
    missing_type_specifier:
    +
    explicit type is missing (“int” assumed)
    +
    +

    0261

    +
    missing_access_specifier:
    +
    access control not specified (“xxxx” by default)
    +
    +

    0262

    +
    not_a_class_or_struct_name:
    +
    not a class or struct name
    +
    +

    0263

    +
    dupl_base_class_name:
    +
    duplicate base class name
    +
    +

    0264

    +
    bad_base_class:
    +
    invalid base class
    +
    +

    0265

    +
    no_access_to_name:
    +
    entity-kind “entity” (declared at line xxxx) is inaccessible
    +
    +

    0266

    +
    ambiguous_name:
    +
    “entity” is ambiguous
    +
    +

    0267

    +
    old_style_parameter_list:
    +
    old-style parameter list (anachronism)
    +
    +

    0268

    +
    declaration_after_statements:
    +
    declaration may not appear after executable statement in block
    +
    +

    0269

    +
    inaccessible_base_class:
    +
    conversion to inaccessible base class “type” is not allowed
    +
    +

    0274

    +
    improperly_terminated_macro_call:
    +
    improperly terminated macro invocation
    +
    +

    0276

    +
    id_must_be_class_or_namespace_name:
    +
    name followed by “::” must be a class or namespace name
    +
    +

    0277

    +
    bad_friend_decl:
    +
    invalid friend declaration
    +
    +

    0278

    +
    value_returned_in_constructor:
    +
    a constructor or destructor may not return a value
    +
    +

    0279

    +
    bad_destructor_decl:
    +
    invalid destructor declaration
    +
    +

    0280

    +
    class_and_member_name_conflict:
    +
    declaration of a member with the same name as its class
    +
    +

    0281

    +
    global_qualifier_not_allowed:
    +
    global-scope qualifier (leading “::”) is not allowed
    +
    +

    0282

    +
    name_not_found_in_file_scope:
    +
    the global scope has no “xxxx”
    +
    +

    0283

    +
    qualified_name_not_allowed:
    +
    qualified name is not allowed
    +
    +

    0284

    +
    null_reference:
    +
    NULL reference is not allowed
    +
    +

    0285

    +
    brace_initialization_not_allowed:
    +
    initialization with “{…}” is not allowed for object of type +“type”
    +
    +

    0286

    +
    ambiguous_base_class:
    +
    base class “type” is ambiguous
    +
    +

    0287

    +
    ambiguous_derived_class:
    +
    derived class “type” contains more than one instance of class +“type”
    +
    +

    0288

    +
    derived_class_from_virtual_base:
    +
    cannot convert pointer to base class “type” to pointer to derived +class “type” – base class is virtual
    +
    +

    0289

    +
    no_matching_constructor:
    +
    no instance of constructor “entity” matches the argument list
    +
    +

    0290

    +
    ambiguous_copy_constructor:
    +
    copy constructor for class “type” is ambiguous
    +
    +

    0291

    +
    no_default_constructor:
    +
    no default constructor exists for class “type”
    +
    +

    0292

    +
    not_a_field_or_base_class:
    +
    “xxxx” is not a nonstatic data member or base class of class +“type”
    +
    +

    0293

    +
    indirect_nonvirtual_base_class_not_allowed:
    +
    indirect nonvirtual base class is not allowed
    +
    +

    0294

    +
    bad_union_field:
    +
    invalid union member – class “type” has a disallowed member +function
    +
    +

    0296

    +
    bad_rvalue_array:
    +
    invalid use of non-lvalue array
    +
    +

    0297

    +
    exp_operator:
    +
    expected an operator
    +
    +

    0298

    +
    inherited_member_not_allowed:
    +
    inherited member is not allowed
    +
    +

    0299

    +
    indeterminate_overloaded_function:
    +
    cannot determine which instance of entity-kind “entity” is +intended
    +
    +

    0300

    +
    bound_function_must_be_called:
    +
    a pointer to a bound function may only be used to call the function
    +
    +

    0301

    +
    duplicate_typedef:
    +
    typedef name has already been declared (with same type)
    +
    +

    0304

    +
    no_matching_function:
    +
    no instance of entity-kind “entity” matches the argument list
    +
    +

    0305

    +
    type_def_not_allowed_in_func_type_decl:
    +
    type definition is not allowed in function return type declaration
    +
    +

    0306

    +
    default_arg_not_at_end:
    +
    default argument not at end of parameter list
    +
    +

    0307

    +
    default_arg_already_defined:
    +
    redefinition of default argument
    +
    +

    0308

    +
    ambiguous_overloaded_function:
    +
    more than one instance of entity-kind “entity” matches the +argument list:
    +
    +

    0309

    +
    ambiguous_constructor:
    +
    more than one instance of constructor “entity” matches the +argument list:
    +
    +

    0310

    +
    bad_default_arg_type:
    +
    default argument of type “type” is incompatible with parameter of +type “type”
    +
    +

    0311

    +
    return_type_cannot_distinguish_functions:
    +
    cannot overload functions distinguished by return type alone
    +
    +

    0312

    +
    no_user_defined_conversion:
    +
    no suitable user-defined conversion from “type” to “type”exists
    +
    +

    0314

    +
    virtual_static_not_allowed:
    +
    only nonstatic member functions may be virtual
    +
    +

    0315

    +
    unqual_function_with_qual_object:
    +
    the object has type qualifiers that are not compatible with the +member function
    +
    +

    0316

    +
    too_many_virtual_functions:
    +
    program too large to compile (too many virtual functions)
    +
    +

    0317

    +
    bad_return_type_on_virtual_function_override:
    +
    return type is not identical to nor covariant with return type +“type” of overridden virtual function “entity”
    +
    +

    0318

    +
    ambiguous_virtual_function_override:
    +
    override of virtual entity-kind “entity” is ambiguous
    +
    +

    0319

    +
    pure_specifier_on_nonvirtual_function:
    +
    pure specifier (”= 0”) allowed only on virtual functions
    +
    +

    0320

    +
    bad_pure_specifier:
    +
    badly-formed pure specifier (only “= 0” is allowed)
    +
    +

    0321

    +
    bad_data_member_initialization:
    +
    data member initializer is not allowed
    +
    +

    0322

    +
    abstract_class_object_not_allowed:
    +
    object of abstract class type “type” is not allowed:
    +
    +

    0323

    +
    function_returning_abstract_class:
    +
    function returning abstract class “type” is not allowed:
    +
    +

    0324

    +
    duplicate_friend_decl:
    +
    duplicate friend declaration
    +
    +

    0325

    +
    inline_and_nonfunction:
    +
    inline specifier allowed on function declarations only
    +
    +

    0326

    +
    inline_not_allowed:
    +
    “inline” is not allowed
    +
    +

    0327

    +
    bad_storage_class_with_inline:
    +
    invalid storage class for an inline function
    +
    +

    0328

    +
    bad_member_storage_class:
    +
    invalid storage class for a class member
    +
    +

    0329

    +
    local_class_function_def_missing:
    +
    local class member entity-kind “entity” requires a definition
    +
    +

    0330

    +
    inaccessible_special_function:
    +
    entity-kind “entity” (declared at line xxxx) is inaccessible
    +
    +

    0332

    +
    missing_const_copy_constructor:
    +
    class “type” has no copy constructor to copy a const object
    +
    +

    0333

    +
    definition_of_implicitly_declared_function:
    +
    defining an implicitly declared member function is not allowed
    +
    +

    0334

    +
    no_suitable_copy_constructor:
    +
    class “type” has no suitable copy constructor
    +
    +

    0335

    +
    linkage_specifier_not_allowed:
    +
    linkage specification is not allowed
    +
    +

    0336

    +
    bad_linkage_specifier:
    +
    unknown external linkage specification
    +
    +

    0337

    +
    incompatible_linkage_specifier:
    +
    linkage specification is incompatible with previous “entity”(declared at line xxxx)
    +
    +

    0338

    +
    overloaded_function_linkage:
    +
    more than one instance of overloaded function “entity” has “C” +linkage
    +
    +

    0339

    +
    ambiguous_default_constructor:
    +
    class “type” has more than one default constructor
    +
    +

    0340

    +
    temp_used_for_ref_init:
    +
    value copied to temporary, reference to temporary used
    +
    +

    0341

    +
    nonmember_operator_not_allowed:
    +
    “operator*xxxx*“ must be a member function
    +
    +

    0342

    +
    static_member_operator_not_allowed:
    +
    operator may not be a static member function
    +
    +

    0343

    +
    too_many_args_for_conversion:
    +
    no arguments allowed on user-defined conversion
    +
    +

    0344

    +
    too_many_args_for_operator:
    +
    too many parameters for this operator function
    +
    +

    0345

    +
    too_few_args_for_operator:
    +
    too few parameters for this operator function
    +
    +

    0346

    +
    no_params_with_class_type:
    +
    nonmember operator requires a parameter with class type
    +
    +

    0347

    +
    default_arg_expr_not_allowed:
    +
    default argument is not allowed
    +
    +

    0348

    +
    ambiguous_user_defined_conversion:
    +
    more than one user-defined conversion from “type” to “type”applies:
    +
    +

    0349

    +
    no_matching_operator_function:
    +
    no operator “xxxx” matches these operands
    +
    +

    0350

    +
    ambiguous_operator_function:
    +
    more than one operator “xxxx” matches these operands:
    +
    +

    0351

    +
    bad_arg_type_for_operator_new:
    +
    first parameter of allocation function must be of type “size_t”
    +
    +

    0352

    +
    bad_return_type_for_op_new:
    +
    allocation function requires “void *” return type
    +
    +

    0353

    +
    bad_return_type_for_op_delete:
    +
    deallocation function requires “void” return type
    +
    +

    0354

    +
    bad_first_arg_type_for_operator_delete:
    +
    first parameter of deallocation function must be of type “void *”
    +
    +

    0356

    +
    type_must_be_object_type:
    +
    type must be an object type
    +
    +

    0357

    +
    base_class_already_initialized:
    +
    base class “type” has already been initialized
    +
    +

    0358

    +
    base_class_init_anachronism:
    +
    base class name required – “type” assumed (anachronism)
    +
    +

    0359

    +
    member_already_initialized:
    +
    entity-kind “entity” has already been initialized
    +
    +

    0360

    +
    missing_base_class_or_member_name:
    +
    name of member or base class is missing
    +
    +

    0361

    +
    assignment_to_this:
    +
    assignment to “this” (anachronism)
    +
    +

    0362

    +
    overload_anachronism:
    +
    “overload” keyword used (anachronism)
    +
    +

    0363

    +
    anon_union_member_access:
    +
    invalid anonymous union – nonpublic member is not allowed
    +
    +

    0364

    +
    anon_union_member_function:
    +
    invalid anonymous union – member function is not allowed
    +
    +

    0365

    +
    anon_union_storage_class:
    +
    anonymous union at global or namespace scope must be declared static
    +
    +

    0366

    +
    missing_initializer_on_fields:
    +
    entity-kind “entity” provides no initializer for:
    +
    +

    0367

    +
    cannot_initialize_fields:
    +
    implicitly generated constructor for class “type” cannot +initialize:
    +
    +

    0368

    +
    no_ctor_but_const_or_ref_member:
    +
    entity-kind “entity” defines no constructor to initialize the +following:
    +
    +

    0369

    +
    var_with_uninitialized_member:
    +
    entity-kind “entity” has an uninitialized const or reference +member
    +
    +

    0370

    +
    var_with_uninitialized_field:
    +
    entity-kind “entity” has an uninitialized const field
    +
    +

    0371

    +
    missing_const_assignment_operator:
    +
    class “type” has no assignment operator to copy a const object
    +
    +

    0372

    +
    no_suitable_assignment_operator:
    +
    class “type” has no suitable assignment operator
    +
    +

    0373

    +
    ambiguous_assignment_operator:
    +
    ambiguous assignment operator for class “type”
    +
    +

    0375

    +
    missing_typedef_name:
    +
    declaration requires a typedef name
    +
    +

    0377

    +
    virtual_not_allowed:
    +
    “virtual” is not allowed
    +
    +

    0378

    +
    static_not_allowed:
    +
    “static” is not allowed
    +
    +

    0379

    +
    bound_function_cast_anachronism:
    +
    cast of bound function to normal function pointer (anachronism)
    +
    +

    0380

    +
    expr_not_ptr_to_member:
    +
    expression must have pointer-to-member type
    +
    +

    0381

    +
    extra_semicolon:
    +
    extra “;” ignored
    +
    +

    0382

    +
    nonstd_const_member:
    +
    in-class initializer for nonstatic member is nonstandard
    +
    +

    0384

    +
    no_matching_new_function:
    +
    no instance of overloaded “entity” matches the argument list
    +
    +

    0386

    +
    no_match_for_addr_of_overloaded_function:
    +
    no instance of entity-kind “entity” matches the required type
    +
    +

    0387

    +
    delete_count_anachronism:
    +
    delete array size expression used (anachronism)
    +
    +

    0389

    +
    cast_to_abstract_class:
    +
    a cast to abstract class “type” is not allowed:
    +
    +

    0390

    +
    bad_use_of_main:
    +
    function “main” may not be called or have its address taken
    +
    +

    0391

    +
    initializer_not_allowed_on_array_new:
    +
    a new-initializer may not be specified for an array
    +
    +

    0392

    +
    member_function_redecl_outside_class:
    +
    member function “entity” may not be redeclared outside its class
    +
    +

    0394

    +
    ref_to_nested_function_var:
    +
    reference to local variable of enclosing function is not allowed
    +
    +

    0395

    +
    single_arg_postfix_incr_decr_anachronism:
    +
    single-argument function used for postfix “xxxx” (anachronism)
    +
    +

    0397

    +
    bad_default_assignment:
    +
    implicitly generated assignment operator cannot copy:
    +
    +

    0398

    +
    nonstd_array_cast:
    +
    cast to array type is nonstandard (treated as cast to “type”)
    +
    +

    0399

    +
    class_with_op_new_but_no_op_delete:
    +
    entity-kind “entity” has an operator new*xxxx*() but no default +operator delete*xxxx*()
    +
    +

    0400

    +
    class_with_op_delete_but_no_op_new:
    +
    entity-kind “entity” has a default operator delete*xxxx*() but +no operator new*xxxx*()
    +
    +

    0401

    +
    base_class_with_nonvirtual_dtor:
    +
    destructor for base class “entity” (declared at line xxxx) is +not virtual
    +
    +

    0403

    +
    member_function_redeclaration:
    +
    invalid redeclaration of member entity-kind “entity” (declared at +line xxxx)
    +
    +

    0404

    +
    inline_main:
    +
    function “main” may not be declared inline
    +
    +

    0405

    +
    class_and_member_function_name_conflict:
    +
    member function with the same name as its class must be a constructor
    +
    +

    0406

    +
    nested_class_anachronism:
    +
    using nested entity-kind “entity” (anachronism)
    +
    +

    0407

    +
    too_many_params_for_destructor:
    +
    a destructor may not have parameters
    +
    +

    0408

    +
    bad_constructor_param:
    +
    copy constructor for class “type” may not have a parameter of +type “type”
    +
    +

    0409

    +
    incomplete_function_return_type:
    +
    entity-kind “entity” returns incomplete type “type”
    +
    +

    0410

    +
    protected_access_problem:
    +
    protected entity-kind “entity” (declared at line xxxx) is not +accessible through a “type” pointer or object
    +
    +

    0411

    +
    param_not_allowed:
    +
    a parameter is not allowed
    +
    +

    0412

    +
    asm_decl_not_allowed:
    +
    an “asm” declaration is not allowed here
    +
    +

    0413

    +
    no_conversion_function:
    +
    no suitable conversion function from “type” to “type” exists
    +
    +

    0414

    +
    delete_of_incomplete_class:
    +
    delete of pointer to incomplete class
    +
    +

    0415

    +
    no_constructor_for_conversion:
    +
    no suitable constructor exists to convert from “type” to +“type”
    +
    +

    0416

    +
    ambiguous_constructor_for_conversion:
    +
    more than one constructor applies to convert from “type” to +“type”:
    +
    +

    0417

    +
    ambiguous_conversion_function:
    +
    more than one conversion function from “type” to “type”applies:
    +
    +

    0418

    +
    ambiguous_conversion_to_builtin:
    +
    more than one conversion function from “type” to a built-in type +applies:
    +
    +

    0424

    +
    addr_of_constructor_or_destructor:
    +
    a constructor or destructor may not have its address taken
    +
    +

    0426

    +
    nonconst_ref_init_anachronism:
    +
    temporary used for initial value of reference to non-const +(anachronism)
    +
    +

    0427

    +
    qualifier_in_member_declaration:
    +
    qualified name is not allowed in member declaration
    +
    +

    0428

    +
    mixed_enum_type_anachronism:
    +
    enumerated type mixed with another type (anachronism)
    +
    +

    0429

    +
    new_array_size_must_be_nonnegative:
    +
    the size of an array in “new” must be non-negative
    +
    +

    0430

    +
    return_ref_init_requires_temp:
    +
    returning reference to local temporary
    +
    +

    0432

    +
    enum_not_allowed:
    +
    “enum” declaration is not allowed
    +
    +

    0433

    +
    qualifier_dropped_in_ref_init:
    +
    qualifiers dropped in binding reference of type “type” to +initializer of type “type”
    +
    +

    0434

    +
    bad_nonconst_ref_init:
    +
    a reference of type “type” (not const-qualified) cannot be +initialized with a value of type “type”
    +
    +

    0435

    +
    delete_of_function_pointer:
    +
    a pointer to function may not be deleted
    +
    +

    0436

    +
    bad_conversion_function_decl:
    +
    conversion function must be a nonstatic member function
    +
    +

    0437

    +
    bad_template_declaration_scope:
    +
    a template declaration is not allowed here
    +
    +

    0438

    +
    exp_lt:
    +
    expected a “<”
    +
    +

    0439

    +
    exp_gt:
    +
    expected a “>”
    +
    +

    0440

    +
    missing_template_param:
    +
    template parameter declaration is missing
    +
    +

    0441

    +
    missing_template_arg_list:
    +
    argument list for entity-kind “entity” is missing
    +
    +

    0442

    +
    too_few_template_args:
    +
    too few arguments for entity-kind “entity”
    +
    +

    0443

    +
    too_many_template_args:
    +
    too many arguments for entity-kind “entity”
    +
    +

    0445

    +
    not_used_in_template_function_params:
    +
    entity-kind “entity” is not used in declaring the parameter types +of entity-kind “entity”
    +
    +

    0446

    +
    cfront_multiple_nested_types:
    +
    two nested types have the same name: “entity” and “entity”(declared at line xxxx) (cfront compatibility)
    +
    +

    0447

    +
    cfront_global_defined_after_nested_type:
    +
    global “entity” was declared after nested “entity” (declared +at line xxxx) (cfront compatibility)
    +
    +

    0449

    +
    ambiguous_ptr_to_overloaded_function:
    +
    more than one instance of entity-kind “entity” matches the +required type
    +
    +

    0450

    +
    nonstd_long_long:
    +
    the type “long long” is nonstandard
    +
    +

    0451

    +
    nonstd_friend_decl:
    +
    omission of “xxxx” is nonstandard
    +
    +

    0452

    +
    return_type_on_conversion_function:
    +
    return type may not be specified on a conversion function
    +
    +

    0456

    +
    runaway_recursive_instantiation:
    +
    excessive recursion at instantiation of entity-kind “entity”
    +
    +

    0457

    +
    bad_template_declaration:
    +
    “xxxx” is not a function or static data member
    +
    +

    0458

    +
    bad_nontype_template_arg:
    +
    argument of type “type” is incompatible with template parameter +of type “type”
    +
    +

    0459

    +
    init_needing_temp_not_allowed:
    +
    initialization requiring a temporary or conversion is not allowed
    +
    +

    0460

    +
    decl_hides_function_parameter:
    +
    declaration of “xxxx” hides function parameter
    +
    +

    0461

    +
    nonconst_ref_init_from_rvalue:
    +
    initial value of reference to non-const must be an lvalue
    +
    +

    0463

    +
    template_not_allowed:
    +
    “template” is not allowed
    +
    +

    0464

    +
    not_a_class_template:
    +
    “type” is not a class template
    +
    +

    0466

    +
    function_template_named_main:
    +
    “main” is not a valid name for a function template
    +
    +

    0467

    +
    union_nonunion_mismatch:
    +
    invalid reference to entity-kind “entity” (union/nonunion +mismatch)
    +
    +

    0468

    +
    local_type_in_template_arg:
    +
    a template argument may not reference a local type
    +
    +

    0469

    +
    tag_kind_incompatible_with_declaration:
    +
    tag kind of xxxx is incompatible with declaration of entity-kind +“entity” (declared at line xxxx)
    +
    +

    0470

    +
    name_not_tag_in_file_scope:
    +
    the global scope has no tag named “xxxx”
    +
    +

    0471

    +
    not_a_tag_member:
    +
    entity-kind “entity” has no tag member named “xxxx”
    +
    +

    0472

    +
    ptr_to_member_typedef:
    +
    member function typedef (allowed for cfront compatibility)
    +
    +

    0473

    +
    bad_use_of_member_function_typedef:
    +
    entity-kind “entity” may be used only in pointer-to-member +declaration
    +
    +

    0475

    +
    nonexternal_entity_in_template_arg:
    +
    a template argument may not reference a non-external entity
    +
    +

    0476

    +
    id_must_be_class_or_type_name:
    +
    name followed by “::~” must be a class name or a type name
    +
    +

    0478

    +
    destructor_type_mismatch:
    +
    type used as destructor name does not match type “type”
    +
    +

    0479

    +
    called_function_redeclared_inline:
    +
    entity-kind “entity” redeclared “inline” after being called
    +
    +

    0481

    +
    bad_storage_class_on_template_decl:
    +
    invalid storage class for a template declaration
    +
    +

    0482

    +
    no_access_to_type_cfront_mode:
    +
    entity-kind “entity” (declared at line xxxx) is an +inaccessible type (allowed for cfront compatibility)
    +
    +

    0484

    +
    invalid_instantiation_argument:
    +
    invalid explicit instantiation declaration
    +
    +

    0485

    +
    not_instantiatable_entity:
    +
    entity-kind “entity” is not an entity that can be instantiated
    +
    +

    0486

    +
    compiler_generated_function_cannot_be_instantiated:
    +
    compiler generated entity-kind “entity” cannot be explicitly +instantiated
    +
    +

    0487

    +
    inline_function_cannot_be_instantiated:
    +
    inline entity-kind “entity” cannot be explicitly instantiated
    +
    +

    0489

    +
    instantiation_requested_no_definition_supplied:
    +
    entity-kind “entity” cannot be instantiated – no template +definition was supplied
    +
    +

    0490

    +
    instantiation_requested_and_specialized:
    +
    entity-kind “entity” cannot be instantiated – it has been +explicitly specialized
    +
    +

    0493

    +
    no_match_for_type_of_overloaded_function:
    +
    no instance of entity-kind “entity” matches the specified type
    +
    +

    0494

    +
    nonstd_void_param_list:
    +
    declaring a void parameter list with a typedef is nonstandard
    +
    +

    0495

    +
    cfront_name_lookup_bug:
    +
    global entity-kind “entity” used instead of entity-kind +“entity” (cfront compatibility)
    +
    +

    0496

    +
    redeclaration_of_template_param_name:
    +
    template parameter “xxxx” may not be redeclared in this scope
    +
    +

    0497

    +
    decl_hides_template_parameter:
    +
    declaration of “xxxx” hides template parameter
    +
    +

    0498

    +
    must_be_prototype_instantiation:
    +
    template argument list must match the parameter list
    +
    +

    0500

    +
    bad_extra_arg_for_postfix_operator:
    +
    extra parameter of postfix “operator*xxxx*“ must be of type “int”
    +
    +

    0501

    +
    function_type_required:
    +
    an operator name must be declared as a function
    +
    +

    0502

    +
    operator_name_not_allowed:
    +
    operator name is not allowed
    +
    +

    0503

    +
    bad_scope_for_specialization:
    +
    entity-kind “entity” cannot be specialized in the current scope
    +
    +

    0504

    +
    nonstd_member_function_address:
    +
    nonstandard form for taking the address of a member function
    +
    +

    0505

    +
    too_few_template_params:
    +
    too few template parameters – does not match previous declaration +(declared at line xxxx)
    +
    +

    0506

    +
    too_many_template_params:
    +
    too many template parameters – does not match previous declaration +(declared at line xxxx)
    +
    +

    0507

    +
    template_operator_delete:
    +
    function template for operator delete(void *) is not allowed
    +
    +

    0508

    +
    class_template_same_name_as_templ_param:
    +
    class template and template parameter may not have the same name
    +
    +

    0510

    +
    unnamed_type_in_template_arg:
    +
    a template argument may not reference an unnamed type
    +
    +

    0511

    +
    enum_type_not_allowed:
    +
    this operation on an enumerated type requires an applicable +user-defined operator function
    +
    +

    0512

    +
    qualified_reference_type:
    +
    type qualifier on a reference type is not allowed
    +
    +

    0513

    +
    incompatible_assignment_operands:
    +
    a value of type “type” cannot be assigned to an entity of type +“type”
    +
    +

    0514

    +
    unsigned_compare_with_negative:
    +
    pointless comparison of unsigned integer with a negative constant
    +
    +

    0515

    +
    converting_to_incomplete_class:
    +
    cannot convert to incomplete class “type”
    +
    +

    0516

    +
    missing_initializer_on_unnamed_const:
    +
    const object requires an initializer
    +
    +

    0517

    +
    unnamed_object_with_uninitialized_field:
    +
    object has an uninitialized const or reference member
    +
    +

    0518

    +
    nonstd_pp_directive:
    +
    nonstandard preprocessing directive
    +
    +

    0519

    +
    unexpected_template_arg_list:
    +
    entity-kind “entity” may not have a template argument list
    +
    +

    0520

    +
    missing_initializer_list:
    +
    initialization with “{…}” expected for aggregate object
    +
    +

    0521

    +
    incompatible_ptr_to_member_selection_operands:
    +
    pointer-to-member selection class types are incompatible (“type”and “type”)
    +
    +

    0522

    +
    self_friendship:
    +
    pointless friend declaration
    +
    +

    0523

    +
    period_used_as_qualifier:
    +
    “.” used in place of “::” to form a qualified name
    +
    +

    0524

    +
    const_function_anachronism:
    +
    non-const function called for const object (anachronism)
    +
    +

    0525

    +
    dependent_stmt_is_declaration:
    +
    a dependent statement may not be a declaration
    +
    +

    0526

    +
    void_param_not_allowed:
    +
    a parameter may not have void type
    +
    +

    0529

    +
    bad_templ_arg_expr_operator:
    +
    this operator is not allowed in a template argument expression
    +
    +

    0530

    +
    missing_handler:
    +
    try block requires at least one handler
    +
    +

    0531

    +
    missing_exception_declaration:
    +
    handler requires an exception declaration
    +
    +

    0532

    +
    masked_by_default_handler:
    +
    handler is masked by default handler
    +
    +

    0533

    +
    masked_by_handler:
    +
    handler is potentially masked by previous handler for type “type”
    +
    +

    0534

    +
    local_type_used_in_exception:
    +
    use of a local type to specify an exception
    +
    +

    0535

    +
    redundant_exception_specification_type:
    +
    redundant type in exception specification
    +
    +

    0536

    +
    incompatible_exception_specification:
    +
    exception specification is incompatible with that of previous +entity-kind “entity” (declared at line xxxx):
    +
    +

    0540

    +
    no_exception_support:
    +
    support for exception handling is disabled
    +
    +

    0541

    +
    omitted_exception_specification:
    +
    allowing all exceptions is incompatible with previous entity-kind +“entity” (declared at line xxxx)
    +
    +

    0542

    +
    cannot_create_instantiation_request_file:
    +
    could not create instantiation request file “xxxx”
    +
    +

    0543

    +
    non_arith_operation_in_templ_arg:
    +
    non-arithmetic operation not allowed in nontype template argument
    +
    +

    0544

    +
    local_type_in_nonlocal_var:
    +
    use of a local type to declare a nonlocal variable
    +
    +

    0545

    +
    local_type_in_function:
    +
    use of a local type to declare a function
    +
    +

    0546

    +
    branch_past_initialization:
    +
    transfer of control bypasses initialization of:
    +
    +

    0548

    +
    branch_into_handler:
    +
    transfer of control into an exception handler
    +
    +

    0549

    +
    used_before_set:
    +
    entity-kind “entity” is used before its value is set
    +
    +

    0550

    +
    set_but_not_used:
    +
    entity-kind “entity” was set but never used
    +
    +

    0551

    +
    bad_scope_for_definition:
    +
    entity-kind “entity” cannot be defined in the current scope
    +
    +

    0552

    +
    exception_specification_not_allowed:
    +
    exception specification is not allowed
    +
    +

    0553

    +
    template_and_instance_linkage_conflict:
    +
    external/internal linkage conflict for entity-kind “entity”(declared at line xxxx)
    +
    +

    0554

    +
    conversion_function_not_usable:
    +
    entity-kind “entity” will not be called for implicit or explicit +conversions
    +
    +

    0555

    +
    tag_kind_incompatible_with_template_parameter:
    +
    tag kind of xxxx is incompatible with template parameter of type +“type”
    +
    +

    0556

    +
    template_operator_new:
    +
    function template for operator new(size_t) is not allowed
    +
    +

    0558

    +
    bad_member_type_in_ptr_to_member:
    +
    pointer to member of type “type” is not allowed
    +
    +

    0559

    +
    ellipsis_on_operator_function:
    +
    ellipsis is not allowed in operator function parameter list
    +
    +

    0560

    +
    unimplemented_keyword:
    +
    “entity” is reserved for future use as a keyword
    +
    +

    0561

    +
    cl_invalid_macro_definition:
    +
    invalid macro definition: xxxx
    +
    +

    0562

    +
    cl_invalid_macro_undefinition:
    +
    invalid macro undefinition: xxxx
    +
    +

    0565

    +
    cl_il_file_must_be_specified:
    +
    IL file name must be specified if input is
    +
    +

    0570

    +
    cl_error_in_debug_option_argument:
    +
    error in debug option argument
    +
    +

    0571

    +
    cl_invalid_option:
    +
    invalid option: xxxx
    +
    +

    0572

    +
    cl_back_end_requires_il_file:
    +
    back end requires name of IL file
    +
    +

    0573

    +
    cl_could_not_open_il_file:
    +
    could not open IL file xxxx
    +
    +

    0574

    +
    cl_invalid_number:
    +
    invalid number: xxxx
    +
    +

    0575

    +
    cl_incorrect_host_id:
    +
    incorrect host CPU id
    +
    +

    0576

    +
    cl_invalid_instantiation_mode:
    +
    invalid instantiation mode: xxxx
    +
    +

    0578

    +
    cl_invalid_error_limit:
    +
    invalid error limit: xxxx
    +
    +

    0585

    +
    cl_vtbl_option_only_in_cplusplus:
    +
    virtual function tables can only be suppressed when compiling C++
    +
    +

    0586

    +
    cl_anachronism_option_only_in_cplusplus:
    +
    anachronism option can be used only when compiling C++
    +
    +

    0587

    +
    cl_instantiation_option_only_in_cplusplus:
    +
    instantiation mode option can be used only when compiling C++
    +
    +

    0588

    +
    cl_auto_instantiation_option_only_in_cplusplus:
    +
    automatic instantiation mode can be used only when compiling C++
    +
    +

    0589

    +
    cl_implicit_inclusion_option_only_in_cplusplus:
    +
    implicit template inclusion mode can be used only when compiling C++
    +
    +

    0590

    +
    cl_exceptions_option_only_in_cplusplus:
    +
    exception handling option can be used only when compiling C++
    +
    +

    0591

    +
    cl_strict_mode_incompatible_with_pcc:
    +
    strict mode is incompatible with K&R mode
    +
    +

    0592

    +
    cl_strict_mode_incompatible_with_cfront:
    +
    strict mode is incompatible with cfront mode
    +
    +

    0593

    +
    cl_missing_source_file_name:
    +
    missing source file name
    +
    +

    0594

    +
    cl_output_file_incompatible_with_multiple_inputs:
    +
    output files may not be specified when compiling several input files
    +
    +

    0595

    +
    cl_too_many_arguments:
    +
    too many arguments on command line
    +
    +

    0596

    +
    cl_no_output_file_needed:
    +
    an output file was specified, but none is needed
    +
    +

    0597

    +
    cl_il_display_requires_il_file_name:
    +
    IL display requires name of IL file
    +
    +

    0598

    +
    void_template_parameter:
    +
    a template parameter may not have void type
    +
    +

    0599

    +
    too_many_unused_instantiations:
    +
    excessive recursive instantiation of entity-kind “entity” due to +instantiate-all mode
    +
    +

    0600

    +
    cl_strict_mode_incompatible_with_anachronisms:
    +
    strict mode is incompatible with allowing anachronisms
    +
    +

    0601

    +
    void_throw:
    +
    a throw expression may not have void type
    +
    +

    0602

    +
    cl_tim_local_conflicts_with_auto_instantiation:
    +
    local instantiation mode is incompatible with automatic instantiation
    +
    +

    0603

    +
    abstract_class_param_type:
    +
    parameter of abstract class type “type” is not allowed:
    +
    +

    0604

    +
    array_of_abstract_class:
    +
    array of abstract class “type” is not allowed:
    +
    +

    0605

    +
    float_template_parameter:
    +
    floating-point template parameter is nonstandard
    +
    +

    0606

    +
    pragma_must_precede_declaration:
    +
    this pragma must immediately precede a declaration
    +
    +

    0607

    +
    pragma_must_precede_statement:
    +
    this pragma must immediately precede a statement
    +
    +

    0608

    +
    pragma_must_precede_decl_or_stmt:
    +
    this pragma must immediately precede a declaration or statement
    +
    +

    0609

    +
    pragma_may_not_be_used_here:
    +
    this kind of pragma may not be used here
    +
    +

    0611

    +
    partial_override:
    +
    overloaded virtual function “entity” is only partially overridden +in entity-kind “entity”
    +
    +

    0612

    +
    specialization_of_called_inline_template_function:
    +
    specific definition of inline template function must precede its +first use
    +
    +

    0613

    +
    cl_invalid_error_tag:
    +
    invalid error tag in diagnostic control option: xxxx
    +
    +

    0614

    +
    cl_invalid_error_number:
    +
    invalid error number in diagnostic control option: xxxx
    +
    +

    0617

    +
    ptr_to_member_cast_to_ptr_to_function:
    +
    pointer-to-member-function cast to pointer to function
    +
    +

    0618

    +
    no_named_fields:
    +
    struct or union declares no named members
    +
    +

    0619

    +
    nonstd_unnamed_field:
    +
    nonstandard unnamed field
    +
    +

    0620

    +
    nonstd_unnamed_member:
    +
    nonstandard unnamed member
    +
    +

    0624

    +
    not_a_type_name:
    +
    “xxxx” is not a type name
    +
    +

    0625

    +
    cannot_open_pch_input_file_reason:
    +
    cannot open precompiled header input file “xxxx”: xxxx
    +
    +

    0626

    +
    invalid_pch_file:
    +
    precompiled header file “xxxx” is either invalid or not generated +by this version of the compiler
    +
    +

    0627

    +
    pch_curr_directory_changed:
    +
    precompiled header file “xxxx” was not generated in this directory
    +
    +

    0628

    +
    pch_header_files_have_changed:
    +
    header files used to generate precompiled header file “xxxx” have +changed
    +
    +

    0629

    +
    pch_cmd_line_option_mismatch:
    +
    the command line options do not match those used when precompiled +header file “xxxx” was created
    +
    +

    0630

    +
    pch_file_prefix_mismatch:
    +
    the initial sequence of preprocessing directives is not compatible +with those of precompiled header file “xxxx”
    +
    +

    0631

    +
    unable_to_get_mapped_memory:
    +
    unable to obtain mapped memory
    +
    +

    0632

    +
    using_pch:
    +
    “xxxx“: using precompiled header file “xxxx“
    +
    +

    0633

    +
    creating_pch:
    +
    “xxxx“: creating precompiled header file “xxxx“
    +
    +

    0634

    +
    memory_mismatch:
    +
    memory usage conflict with precompiled header file “xxxx”
    +
    +

    0635

    +
    cl_invalid_pch_size:
    +
    invalid PCH memory size: xxxx
    +
    +

    0636

    +
    cl_pch_must_be_first:
    +
    PCH options must appear first in the command line
    +
    +

    0637

    +
    out_of_memory_during_pch_allocation:
    +
    insufficient memory for PCH memory allocation
    +
    +

    0638

    +
    cl_pch_incompatible_with_multiple_inputs:
    +
    precompiled header files may not be used when compiling several input +files
    +
    +

    0639

    +
    not_enough_preallocated_memory:
    +
    insufficient preallocated memory for generation of precompiled header +file (xxxx bytes required)
    +
    +

    0640

    +
    program_entity_too_large_for_pch:
    +
    very large entity in program prevents generation of precompiled +header file
    +
    +

    0641

    +
    cannot_chdir:
    +
    “xxxx” is not a valid directory
    +
    +

    0642

    +
    cannot_build_temp_file_name:
    +
    cannot build temporary file name
    +
    +

    0643

    +
    restrict_not_allowed:
    +
    “restrict” is not allowed
    +
    +

    0644

    +
    restrict_pointer_to_function:
    +
    a pointer or reference to function type may not be qualified by +“restrict”
    +
    +

    0646

    +
    calling_convention_not_allowed:
    +
    a calling convention modifier may not be specified here
    +
    +

    0647

    +
    conflicting_calling_conventions:
    +
    conflicting calling convention modifiers
    +
    +

    0648

    +
    cl_strict_mode_incompatible_with_microsoft:
    +
    strict mode is incompatible with Microsoft mode
    +
    +

    0649

    +
    cl_cfront_incompatible_with_microsoft:
    +
    cfront mode is incompatible with Microsoft mode
    +
    +

    0650

    +
    calling_convention_ignored:
    +
    calling convention specified here is ignored
    +
    +

    0651

    +
    calling_convention_may_not_precede_nested_declarator:
    +
    a calling convention may not be followed by a nested declarator
    +
    +

    0652

    +
    calling_convention_ignored_for_type:
    +
    calling convention is ignored for this type
    +
    +

    0654

    +
    decl_modifiers_incompatible_with_previous_decl:
    +
    declaration modifiers are incompatible with previous declaration
    +
    +

    0655

    +
    decl_modifiers_invalid_for_this_decl:
    +
    the modifier “xxxx” is not allowed on this declaration
    +
    +

    0656

    +
    branch_into_try_block:
    +
    transfer of control into a try block
    +
    +

    0657

    +
    incompatible_inline_specifier_on_specific_decl:
    +
    inline specification is incompatible with previous “entity”(declared at line xxxx)
    +
    +

    0658

    +
    template_missing_closing_brace:
    +
    closing brace of template definition not found
    +
    +

    0659

    +
    cl_wchar_t_option_only_in_cplusplus:
    +
    wchar_t keyword option can be used only when compiling C++
    +
    +

    0660

    +
    bad_pack_alignment:
    +
    invalid packing alignment value
    +
    +

    0661

    +
    exp_int_constant:
    +
    expected an integer constant
    +
    +

    0662

    +
    call_of_pure_virtual:
    +
    call of pure virtual function
    +
    +

    0663

    +
    bad_ident_string:
    +
    invalid source file identifier string
    +
    +

    0664

    +
    template_friend_definition_not_allowed:
    +
    a class template cannot be defined in a friend declaration
    +
    +

    0665

    +
    asm_not_allowed:
    +
    “asm” is not allowed
    +
    +

    0666

    +
    bad_asm_function_def:
    +
    “asm” must be used with a function definition
    +
    +

    0667

    +
    nonstd_asm_function:
    +
    “asm” function is nonstandard
    +
    +

    0668

    +
    nonstd_ellipsis_only_param:
    +
    ellipsis with no explicit parameters is nonstandard
    +
    +

    0669

    +
    nonstd_address_of_ellipsis:
    +
    “&…” is nonstandard
    +
    +

    0670

    +
    bad_address_of_ellipsis:
    +
    invalid use of “&…”
    +
    +

    0672

    +
    const_volatile_ref_init_anachronism:
    +
    temporary used for initial value of reference to const volatile +(anachronism)
    +
    +

    0673

    +
    bad_const_volatile_ref_init:
    +
    a reference of type “type” cannot be initialized with a value of +type “type”
    +
    +

    0674

    +
    const_volatile_ref_init_from_rvalue:
    +
    initial value of reference to const volatile must be an lvalue
    +
    +

    0675

    +
    cl_SVR4_C_option_only_in_ansi_C:
    +
    SVR4 C compatibility option can be used only when compiling ANSI C
    +
    +

    0676

    +
    using_out_of_scope_declaration:
    +
    using out-of-scope declaration of entity-kind “entity” (declared +at line xxxx)
    +
    +

    0677

    +
    cl_strict_mode_incompatible_with_SVR4:
    +
    strict mode is incompatible with SVR4 C mode
    +
    +

    0678

    +
    cannot_inline_call:
    +
    call of entity-kind “entity” (declared at line xxxx) cannot +be inlined
    +
    +

    0679

    +
    cannot_inline:
    +
    entity-kind “entity” cannot be inlined
    +
    +

    0680

    +
    cl_invalid_pch_directory:
    +
    invalid PCH directory: xxxx
    +
    +

    0681

    +
    exp_except_or_finally:
    +
    expected __except or __finally
    +
    +

    0682

    +
    leave_must_be_in_try:
    +
    a __leave statement may only be used within a __try
    +
    +

    0688

    +
    not_found_on_pack_alignment_stack:
    +
    “xxxx” not found on pack alignment stack
    +
    +

    0689

    +
    empty_pack_alignment_stack:
    +
    empty pack alignment stack
    +
    +

    0690

    +
    cl_rtti_option_only_in_cplusplus:
    +
    RTTI option can be used only when compiling C++
    +
    +

    0691

    +
    inaccessible_elided_cctor:
    +
    entity-kind “entity” (declared at line xxxx), required for +copy that was eliminated, is inaccessible
    +
    +

    0692

    +
    uncallable_elided_cctor:
    +
    entity-kind “entity”, required for copy that was eliminated, is +not callable because reference parameter cannot be bound to rvalue
    +
    +

    0693

    +
    typeid_needs_typeinfo:
    +
    <typeinfo> must be included before typeid is used
    +
    +

    0694

    +
    cannot_cast_away_const:
    +
    xxxx cannot cast away const or other type qualifiers
    +
    +

    0695

    +
    bad_dynamic_cast_type:
    +
    the type in a dynamic_cast must be a pointer or reference to a +complete class type, or void *
    +
    +

    0696

    +
    bad_ptr_dynamic_cast_operand:
    +
    the operand of a pointer dynamic_cast must be a pointer to a complete +class type
    +
    +

    0697

    +
    bad_ref_dynamic_cast_operand:
    +
    the operand of a reference dynamic_cast must be an lvalue of a +complete class type
    +
    +

    0698

    +
    dynamic_cast_operand_must_be_polymorphic:
    +
    the operand of a runtime dynamic_cast must have a polymorphic class +type
    +
    +

    0699

    +
    cl_bool_option_only_in_cplusplus:
    +
    bool option can be used only when compiling C++
    +
    +

    0701

    +
    array_type_not_allowed:
    +
    an array type is not allowed here
    +
    +

    0702

    +
    exp_assign:
    +
    expected an “=”
    +
    +

    0704

    +
    redeclaration_of_condition_decl_name:
    +
    “xxxx”, declared in condition, may not be redeclared in this scope
    +
    +

    0705

    +
    default_template_arg_not_allowed:
    +
    default template arguments are not allowed for function templates
    +
    +

    0706

    +
    exp_comma_or_gt:
    +
    expected a “,” or “>”
    +
    +

    0707

    +
    missing_template_param_list:
    +
    expected a template parameter list
    +
    +

    0708

    +
    incr_of_bool_deprecated:
    +
    incrementing a bool value is deprecated
    +
    +

    0709

    +
    bool_type_not_allowed:
    +
    bool type is not allowed
    +
    +

    0710

    +
    base_class_offset_too_large:
    +
    offset of base class “entity” within class “entity” is too +large
    +
    +

    0711

    +
    expr_not_bool:
    +
    expression must have bool type (or be convertible to bool)
    +
    +

    0712

    +
    cl_array_new_and_delete_option_only_in_cplusplus:
    +
    array new and delete option can be used only when compiling C++
    +
    +

    0713

    +
    based_requires_variable_name:
    +
    entity-kind “entity” is not a variable name
    +
    +

    0714

    +
    based_not_allowed_here:
    +
    __based modifier is not allowed here
    +
    +

    0715

    +
    based_not_followed_by_star:
    +
    __based does not precede a pointer operator, __based ignored
    +
    +

    0716

    +
    based_var_must_be_ptr:
    +
    variable in __based modifier must have pointer type
    +
    +

    0717

    +
    bad_const_cast_type:
    +
    the type in a const_cast must be a pointer, reference, or pointer to +member to an object type
    +
    +

    0718

    +
    bad_const_cast:
    +
    a const_cast can only adjust type qualifiers; it cannot change the +underlying type
    +
    +

    0719

    +
    mutable_not_allowed:
    +
    mutable is not allowed
    +
    +

    0720

    +
    cannot_change_access:
    +
    redeclaration of entity-kind “entity” is not allowed to alter its +access
    +
    +

    0722

    +
    probable_inadvertent_lbracket_digraph:
    +
    use of alternative token “<:” appears to be unintended
    +
    +

    0723

    +
    probable_inadvertent_sharp_digraph:
    +
    use of alternative token “%:” appears to be unintended
    +
    +

    0724

    +
    namespace_def_not_allowed:
    +
    namespace definition is not allowed
    +
    +

    0725

    +
    missing_namespace_name:
    +
    name must be a namespace name
    +
    +

    0726

    +
    namespace_alias_def_not_allowed:
    +
    namespace alias definition is not allowed
    +
    +

    0727

    +
    namespace_qualified_name_required:
    +
    namespace-qualified name is required
    +
    +

    0728

    +
    namespace_name_not_allowed:
    +
    a namespace name is not allowed
    +
    +

    0729

    +
    bad_combination_of_dll_attributes:
    +
    invalid combination of DLL attributes
    +
    +

    0730

    +
    sym_not_a_class_template:
    +
    entity-kind “entity” is not a class template
    +
    +

    0731

    +
    array_of_incomplete_type:
    +
    array with incomplete element type is nonstandard
    +
    +

    0732

    +
    allocation_operator_in_namespace:
    +
    allocation operator may not be declared in a namespace
    +
    +

    0733

    +
    deallocation_operator_in_namespace:
    +
    deallocation operator may not be declared in a namespace
    +
    +

    0734

    +
    conflicts_with_using_decl:
    +
    entity-kind “entity” conflicts with using-declaration of +entity-kind “entity”
    +
    +

    0735

    +
    using_decl_conflicts_with_prev_decl:
    +
    using-declaration of entity-kind “entity” conflicts with +entity-kind “entity” (declared at line xxxx)
    +
    +

    0736

    +
    cl_namespaces_option_only_in_cplusplus:
    +
    namespaces option can be used only when compiling C++
    +
    +

    0737

    +
    useless_using_declaration:
    +
    using-declaration ignored – it refers to the current namespace
    +
    +

    0738

    +
    class_qualified_name_required:
    +
    a class-qualified name is required
    +
    +

    0742

    +
    not_an_actual_member:
    +
    entity-kind “entity” has no actual member “xxxx”
    +
    +

    0744

    +
    mem_attrib_incompatible:
    +
    incompatible memory attributes specified
    +
    +

    0745

    +
    mem_attrib_ignored:
    +
    memory attribute ignored
    +
    +

    0746

    +
    mem_attrib_may_not_precede_nested_declarator:
    +
    memory attribute may not be followed by a nested declarator
    +
    +

    0747

    +
    dupl_mem_attrib:
    +
    memory attribute specified more than once
    +
    +

    0748

    +
    dupl_calling_convention:
    +
    calling convention specified more than once
    +
    +

    0749

    +
    type_qualifier_not_allowed:
    +
    a type qualifier is not allowed
    +
    +

    0750

    +
    template_instance_already_used:
    +
    entity-kind “entity” (declared at line xxxx) was used before +its template was declared
    +
    +

    0751

    +
    static_nonstatic_with_same_param_types:
    +
    static and nonstatic member functions with same parameter types +cannot be overloaded
    +
    +

    0752

    +
    no_prior_declaration:
    +
    no prior declaration of entity-kind “entity”
    +
    +

    0753

    +
    template_id_not_allowed:
    +
    a template-id is not allowed
    +
    +

    0754

    +
    class_qualified_name_not_allowed:
    +
    a class-qualified name is not allowed
    +
    +

    0755

    +
    bad_scope_for_redeclaration:
    +
    entity-kind “entity” may not be redeclared in the current scope
    +
    +

    0756

    +
    qualifier_in_namespace_member_decl:
    +
    qualified name is not allowed in namespace member declaration
    +
    +

    0757

    +
    sym_not_a_type_name:
    +
    entity-kind “entity” is not a type name
    +
    +

    0758

    +
    explicit_instantiation_not_in_namespace_scope:
    +
    explicit instantiation is not allowed in the current scope
    +
    +

    0759

    +
    bad_scope_for_explicit_instantiation:
    +
    entity-kind “entity” cannot be explicitly instantiated in the +current scope
    +
    +

    0760

    +
    multiple_explicit_instantiations:
    +
    entity-kind “entity” explicitly instantiated more than once
    +
    +

    0761

    +
    typename_not_in_template:
    +
    typename may only be used within a template
    +
    +

    0762

    +
    cl_special_subscript_cost_option_only_in_cplusplus:
    +
    special_subscript_cost option can be used only when compiling C++
    +
    +

    0763

    +
    cl_typename_option_only_in_cplusplus:
    +
    typename option can be used only when compiling C++
    +
    +

    0764

    +
    cl_implicit_typename_option_only_in_cplusplus:
    +
    implicit typename option can be used only when compiling C++
    +
    +

    0765

    +
    nonstd_character_at_start_of_macro_def:
    +
    nonstandard character at start of object-like macro definition
    +
    +

    0766

    +
    exception_spec_override_incompat:
    +
    exception specification for virtual entity-kind “entity” is +incompatible with that of overridden entity-kind “entity”
    +
    +

    0767

    +
    pointer_conversion_loses_bits:
    +
    conversion from pointer to smaller integer
    +
    +

    0768

    +
    generated_exception_spec_override_incompat:
    +
    exception specification for implicitly declared virtual entity-kind +“entity” is incompatible with that of overridden entity-kind +“entity”
    +
    +

    0769

    +
    implicit_call_of_ambiguous_name:
    +
    “entity”, implicitly called from entity-kind “entity”, is +ambiguous
    +
    +

    0770

    +
    cl_explicit_option_only_in_cplusplus:
    +
    option “explicit” can be used only when compiling C++
    +
    +

    0771

    +
    explicit_not_allowed:
    +
    “explicit” is not allowed
    +
    +

    0772

    +
    conflicts_with_predeclared_type_info:
    +
    declaration conflicts with “xxxx” (reserved class name)
    +
    +

    0773

    +
    array_member_initialization:
    +
    only “()” is allowed as initializer for array entity-kind “entity”
    +
    +

    0774

    +
    virtual_function_template:
    +
    “virtual” is not allowed in a function template declaration
    +
    +

    0775

    +
    anon_union_class_member_template:
    +
    invalid anonymous union – class member template is not allowed
    +
    +

    0776

    +
    template_depth_mismatch:
    +
    template nesting depth does not match the previous declaration of +entity-kind “entity”
    +
    +

    0777

    +
    multiple_template_decls_not_allowed:
    +
    this declaration cannot have multiple “template <…>” clauses
    +
    +

    0778

    +
    cl_old_for_init_option_only_in_cplusplus:
    +
    option to control the for-init scope can be used only when compiling +C++
    +
    +

    0779

    +
    redeclaration_of_for_init_decl_name:
    +
    “xxxx”, declared in for-loop initialization, may not be +redeclared in this scope
    +
    +

    0780

    +
    hidden_by_old_for_init:
    +
    reference is to entity-kind “entity” (declared at line xxxx) +– under old for-init scoping rules it would have been entity-kind +“entity” (declared at line xxxx)
    +
    +

    0781

    +
    cl_for_init_diff_warning_option_only_in_cplusplus:
    +
    option to control warnings on for-init differences can be used only +when compiling C++
    +
    +

    0782

    +
    unnamed_class_virtual_function_def_missing:
    +
    definition of virtual entity-kind “entity” is required here
    +
    +

    0783

    +
    svr4_token_pasting_comment:
    +
    empty comment interpreted as token-pasting operator “##”
    +
    +

    0784

    +
    storage_class_in_friend_decl:
    +
    a storage class is not allowed in a friend declaration
    +
    +

    0785

    +
    templ_param_list_not_allowed:
    +
    template parameter list for “entity” is not allowed in this +declaration
    +
    +

    0786

    +
    bad_member_template_sym:
    +
    entity-kind “entity” is not a valid class member template
    +
    +

    0787

    +
    bad_member_template_decl:
    +
    not a valid member class or function template declaration
    +
    +

    0788

    +
    specialization_follows_param_list:
    +
    a template declaration containing a template parameter list may not +be followed by an explicit specialization declaration
    +
    +

    0789

    +
    specialization_of_referenced_template:
    +
    explicit specialization of entity-kind “entity” must precede the +first use of entity-kind “entity”
    +
    +

    0790

    +
    explicit_specialization_not_in_namespace_scope:
    +
    explicit specialization is not allowed in the current scope
    +
    +

    0791

    +
    partial_specialization_not_allowed:
    +
    partial specialization of entity-kind “entity” is not allowed
    +
    +

    0792

    +
    entity_cannot_be_specialized:
    +
    entity-kind “entity” is not an entity that can be explicitly +specialized
    +
    +

    0793

    +
    specialization_of_referenced_entity:
    +
    explicit specialization of entity-kind “entity” must precede its +first use
    +
    +

    0794

    +
    template_param_in_elab_type:
    +
    template parameter “xxxx” may not be used in an elaborated type +specifier
    +
    +

    0795

    +
    old_specialization_not_allowed:
    +
    specializing entity-kind “entity” requires “template<>” syntax
    +
    +

    0798

    +
    cl_old_specializations_option_only_in_cplusplus:
    +
    option “old_specializations” can be used only when compiling C++
    +
    +

    0799

    +
    nonstd_old_specialization:
    +
    specializing entity-kind “entity” without “template<>” syntax is +nonstandard
    +
    +

    0800

    +
    bad_linkage_for_decl:
    +
    this declaration may not have extern “C” linkage
    +
    +

    0801

    +
    not_a_template_name:
    +
    “xxxx” is not a class or function template name in the current +scope
    +
    +

    0802

    +
    nonstd_default_arg_on_function_template_redecl:
    +
    specifying a default argument when redeclaring an unreferenced +function template is nonstandard
    +
    +

    0803

    +
    default_arg_on_function_template_not_allowed:
    +
    specifying a default argument when redeclaring an already referenced +function template is not allowed
    +
    +

    0804

    +
    pm_derived_class_from_virtual_base:
    +
    cannot convert pointer to member of base class “type” to pointer +to member of derived class “type” – base class is virtual
    +
    +

    0805

    +
    bad_exception_specification_for_specialization:
    +
    exception specification is incompatible with that of entity-kind +“entity” (declared at line xxxx):
    +
    +

    0806

    +
    omitted_exception_specification_on_specialization:
    +
    allowing all exceptions is incompatible with entity-kind “entity”(declared at line xxxx)
    +
    +

    0807

    +
    unexpected_end_of_default_arg:
    +
    unexpected end of default argument expression
    +
    +

    0808

    +
    default_init_of_reference:
    +
    default-initialization of reference is not allowed
    +
    +

    0809

    +
    uninitialized_field_with_const_member:
    +
    uninitialized entity-kind “entity” has a const member
    +
    +

    0810

    +
    uninitialized_base_class_with_const_member:
    +
    uninitialized base class “type” has a const member
    +
    +

    0811

    +
    missing_default_constructor_on_const:
    +
    const entity-kind “entity” requires an initializer – class +“type” has no user-provided default constructor
    +
    +

    0812

    +
    missing_default_constructor_on_unnamed_const:
    +
    const object requires an initializer – class “type” has no +user-provided default constructor
    +
    +

    0813

    +
    cl_impl_extern_c_conv_option_only_in_cplusplus:
    +
    option “implicit_extern_c_type_conversion” can be used only when +compiling C++
    +
    +

    0814

    +
    cl_strict_mode_incompatible_with_long_preserving:
    +
    strict mode is incompatible with long preserving rules
    +
    +

    0815

    +
    useless_type_qualifier_on_return_type:
    +
    type qualifier on return type is meaningless
    +
    +

    0816

    +
    type_qualifier_on_void_return_type:
    +
    in a function definition a type qualifier on a “void” return type is +not allowed
    +
    +

    0817

    +
    static_data_member_not_allowed:
    +
    static data member declaration is not allowed in this class
    +
    +

    0818

    +
    invalid_declaration:
    +
    template instantiation resulted in an invalid function declaration
    +
    +

    0819

    +
    ellipsis_not_allowed:
    +
    “…” is not allowed
    +
    +

    0820

    +
    cl_extern_inline_option_only_in_cplusplus:
    +
    option “extern_inline” can be used only when compiling C++
    +
    +

    0821

    +
    extern_inline_never_defined:
    +
    extern inline entity-kind “entity” was referenced but not defined
    +
    +

    0822

    +
    invalid_destructor_name:
    +
    invalid destructor name for type “type”
    +
    +

    0824

    +
    ambiguous_destructor:
    +
    destructor reference is ambiguous – both entity-kind “entity”and entity-kind “entity” could be used
    +
    +

    0825

    +
    virtual_inline_never_defined:
    +
    virtual inline entity-kind “entity” was never defined
    +
    +

    0826

    +
    unreferenced_function_param:
    +
    entity-kind “entity” was never referenced
    +
    +

    0827

    +
    union_already_initialized:
    +
    only one member of a union may be specified in a constructor +initializer list
    +
    +

    0828

    +
    no_array_new_and_delete_support:
    +
    support for “new[]” and “delete[]” is disabled
    +
    +

    0829

    +
    double_for_long_double:
    +
    “double” used for “long double” in generated C code
    +
    +

    0830

    +
    no_corresponding_delete:
    +
    entity-kind “entity” has no corresponding operator delete*xxxx*(to be called if an exception is thrown during initialization of an +allocated object)
    +
    +

    0831

    +
    useless_placement_delete:
    +
    support for placement delete is disabled
    +
    +

    0832

    +
    no_appropriate_delete:
    +
    no appropriate operator delete is visible
    +
    +

    0833

    +
    ptr_or_ref_to_incomplete_type:
    +
    pointer or reference to incomplete type “type” is not allowed
    +
    +

    0834

    +
    bad_partial_specialization:
    +
    invalid partial specialization – entity-kind “entity” is already +fully specialized
    +
    +

    0835

    +
    incompatible_exception_specs:
    +
    incompatible exception specifications
    +
    +

    0836

    +
    returning_ref_to_local_variable:
    +
    returning reference to local variable
    +
    +

    0837

    +
    nonstd_implicit_int:
    +
    omission of explicit type is nonstandard (“int” assumed)
    +
    +

    0838

    +
    ambiguous_partial_spec:
    +
    more than one partial specialization matches the template argument +list of entity-kind “entity”
    +
    +

    0840

    +
    partial_spec_is_primary_template:
    +
    a template argument list is not allowed in a declaration of a primary +template
    +
    +

    0841

    +
    default_not_allowed_on_partial_spec:
    +
    partial specializations may not have default template arguments
    +
    +

    0842

    +
    not_used_in_partial_spec_arg_list:
    +
    entity-kind “entity” is not used in or cannot be deduced from the +template argument list of entity-kind “entity”
    +
    +

    0844

    +
    partial_spec_arg_depends_on_templ_param:
    +
    the template argument list of the partial specialization includes a +nontype argument whose type depends on a template parameter
    +
    +

    0845

    +
    partial_spec_after_instantiation:
    +
    this partial specialization would have been used to instantiate +entity-kind “entity”
    +
    +

    0846

    +
    partial_spec_after_instantiation_ambiguous:
    +
    this partial specialization would have made the instantiation of +entity-kind “entity” ambiguous
    +
    +

    0847

    +
    expr_not_integral_or_enum:
    +
    expression must have integral or enum type
    +
    +

    0848

    +
    expr_not_arithmetic_or_enum:
    +
    expression must have arithmetic or enum type
    +
    +

    0849

    +
    expr_not_arithmetic_or_enum_or_pointer:
    +
    expression must have arithmetic, enum, or pointer type
    +
    +

    0850

    +
    cast_not_integral_or_enum:
    +
    type of cast must be integral or enum
    +
    +

    0851

    +
    cast_not_arithmetic_or_enum_or_pointer:
    +
    type of cast must be arithmetic, enum, or pointer
    +
    +

    0852

    +
    expr_not_object_pointer:
    +
    expression must be a pointer to a complete object type
    +
    +

    0855

    +
    different_return_type_on_virtual_function_override:
    +
    return type is not identical to return type “type” of overridden +virtual function “entity”
    +
    +

    0856

    +
    cl_guiding_decls_option_only_in_cplusplus:
    +
    option “guiding_decls” can be used only when compiling C++
    +
    +

    0857

    +
    member_partial_spec_not_in_namespace:
    +
    a partial specialization of a class template must be declared in the +namespace of which it is a member
    +
    +

    0858

    +
    pure_virtual_function:
    +
    entity-kind “entity” is a pure virtual function
    +
    +

    0859

    +
    no_overrider_for_pure_virtual_function:
    +
    pure virtual entity-kind “entity” has no overrider
    +
    +

    0860

    +
    decl_modifiers_ignored:
    +
    __declspec attributes ignored
    +
    +

    0861

    +
    invalid_char:
    +
    invalid character in input line
    +
    +

    0862

    +
    incomplete_return_type:
    +
    function returns incomplete type “type”
    +
    +

    0863

    +
    local_pragma_pack:
    +
    effect of this “#pragma pack” directive is local to entity-kind +“entity”
    +
    +

    0864

    +
    not_a_template:
    +
    xxxx is not a template
    +
    +

    0865

    +
    friend_partial_specialization:
    +
    a friend declaration may not declare a partial specialization
    +
    +

    0866

    +
    exception_specification_ignored:
    +
    exception specification ignored
    +
    +

    0867

    +
    unexpected_type_for_size_t:
    +
    declaration of “size_t” does not match the expected type “type”
    +
    +

    0868

    +
    exp_gt_not_shift_right:
    +
    space required between adjacent “>” delimiters of nested template +argument lists (“>>” is the right shift operator)
    +
    +

    0869

    +
    bad_multibyte_char_locale:
    +
    could not set locale “xxxx” to allow processing of multibyte +characters
    +
    +

    0870

    +
    bad_multibyte_char:
    +
    invalid multibyte character sequence
    +
    +

    0871

    +
    bad_type_from_instantiation:
    +
    template instantiation resulted in unexpected function type of +“type” (the meaning of a name may have changed since the template +declaration – the type of the template is “type”)
    +
    +

    0872

    +
    ambiguous_guiding_decl:
    +
    ambiguous guiding declaration – more than one function template +“entity” matches type “type”
    +
    +

    0873

    +
    non_integral_operation_in_templ_arg:
    +
    non-integral operation not allowed in nontype template argument
    +
    +

    0874

    +
    cl_embedded_cplusplus_option_only_in_cplusplus:
    +
    option “embedded_c++” can be used only when compiling C++
    +
    +

    0875

    +
    templates_in_embedded_cplusplus:
    +
    Embedded C++ does not support templates
    +
    +

    0876

    +
    exceptions_in_embedded_cplusplus:
    +
    Embedded C++ does not support exception handling
    +
    +

    0877

    +
    namespaces_in_embedded_cplusplus:
    +
    Embedded C++ does not support namespaces
    +
    +

    0878

    +
    rtti_in_embedded_cplusplus:
    +
    Embedded C++ does not support run-time type information
    +
    +

    0879

    +
    new_cast_in_embedded_cplusplus:
    +
    Embedded C++ does not support the new cast syntax
    +
    +

    0880

    +
    using_decl_in_embedded_cplusplus:
    +
    Embedded C++ does not support using-declarations
    +
    +

    0881

    +
    mutable_in_embedded_cplusplus:
    +
    Embedded C++ does not support “mutable”
    +
    +

    0882

    +
    multiple_inheritance_in_embedded_cplusplus:
    +
    Embedded C++ does not support multiple or virtual inheritance
    +
    +

    0883

    +
    cl_invalid_microsoft_version:
    +
    invalid Microsoft version number: xxxx
    +
    +

    0884

    +
    inheritance_kind_already_set:
    +
    pointer-to-member representation “xxxx” has already been set for +entity-kind “entity”
    +
    +

    0885

    +
    bad_constructor_type:
    +
    “type” cannot be used to designate constructor for “type”
    +
    +

    0886

    +
    bad_suffix:
    +
    invalid suffix on integral constant
    +
    +

    0887

    +
    uuidof_requires_uuid_class_type:
    +
    operand of __uuidof must have a class or enum type for which +__declspec(uuid(”…”)) has been specified
    +
    +

    0888

    +
    bad_uuid_string:
    +
    invalid GUID string in __declspec(uuid(”…”))
    +
    +

    0889

    +
    cl_vla_option_only_in_C:
    +
    option “vla” can be used only when compiling C
    +
    +

    0890

    +
    vla_with_unspecified_bound_not_allowed:
    +
    variable length array with unspecified bound is not allowed
    +
    +

    0891

    +
    explicit_template_args_not_allowed:
    +
    an explicit template argument list is not allowed on this declaration
    +
    +

    0892

    +
    variably_modified_type_not_allowed:
    +
    an entity with linkage cannot have a type involving a variable length +array
    +
    +

    0893

    +
    vla_is_not_auto:
    +
    a variable length array cannot have static storage duration
    +
    +

    0894

    +
    sym_not_a_template:
    +
    entity-kind “entity” is not a template
    +
    +

    0896

    +
    expected_template_arg:
    +
    expected a template argument
    +
    +

    0898

    +
    no_params_with_class_or_enum_type:
    +
    nonmember operator requires a parameter with class or enum type
    +
    +

    0899

    +
    cl_enum_overloading_option_only_in_cplusplus:
    +
    option “enum_overloading” can be used only when compiling C++
    +
    +

    0901

    +
    destructor_qualifier_type_mismatch:
    +
    qualifier of destructor name “type” does not match type “type”
    +
    +

    0902

    +
    type_qualifier_ignored:
    +
    type qualifier ignored
    +
    +

    0903

    +
    cl_nonstandard_qualifier_deduction_option_only_in_cplusplus:
    +
    option “nonstd_qualifier_deduction” can be used only when compiling +C++
    +
    +

    0904

    +
    cannot_define_dllimport_function:
    +
    a function declared “dllimport” may not be defined
    +
    +

    0905

    +
    bad_declspec_property:
    +
    incorrect property specification; correct form is +__declspec(property(get=name1,put=name2))
    +
    +

    0906

    +
    dupl_get_or_put:
    +
    property has already been specified
    +
    +

    0907

    +
    declspec_property_not_allowed:
    +
    __declspec(property) is not allowed on this declaration
    +
    +

    0908

    +
    no_get_property:
    +
    member is declared with __declspec(property), but no “get” function +was specified
    +
    +

    0909

    +
    get_property_function_missing:
    +
    the __declspec(property) “get” function “xxxx” is missing
    +
    +

    0910

    +
    no_put_property:
    +
    member is declared with __declspec(property), but no “put” function +was specified
    +
    +

    0911

    +
    put_property_function_missing:
    +
    the __declspec(property) “put” function “xxxx” is missing
    +
    +

    0912

    +
    dual_lookup_ambiguous_name:
    +
    ambiguous class member reference – entity-kind “entity”(declared at line xxxx) used in preference to entity-kind +“entity” (declared at line xxxx)
    +
    +

    0916

    +
    pm_virtual_base_from_derived_class:
    +
    cannot convert pointer to member of derived class “type” to +pointer to member of base class “type” – base class is virtual
    +
    +

    0917

    +
    cl_invalid_instantiation_directory:
    +
    invalid directory for instantiation files: xxxx
    +
    +

    0918

    +
    cl_one_instantiation_per_object_option_only_in_cplusplus:
    +
    option “one_instantiation_per_object” can be used only when compiling +C++
    +
    +

    0921

    +
    cl_ii_file_name_incompatible_with_multiple_inputs:
    +
    an instantiation information file name may not be specified when +compiling several input files
    +
    +

    0922

    +
    cl_one_instantiation_per_object_incompatible_with_multiple_inputs:
    +
    option “one_instantiation_per_object” may not be used when compiling +several input files
    +
    +

    0923

    +
    cl_ambiguous_option:
    +
    more than one command line option matches the abbreviation +“–xxxx“:
    +
    +

    0925

    +
    cv_qualified_function_type:
    +
    type qualifiers on function types are ignored
    +
    +

    0927

    +
    cl_late_tiebreaker_option_only_in_cplusplus:
    +
    late/early tiebreaker option can be used only when compiling C++
    +
    +

    0928

    +
    bad_va_start:
    +
    incorrect use of va_start
    +
    +

    0929

    +
    bad_va_arg:
    +
    incorrect use of va_arg
    +
    +

    0930

    +
    bad_va_end:
    +
    incorrect use of va_end
    +
    +

    0931

    +
    cl_pending_instantiations_option_only_in_cplusplus:
    +
    pending instantiations option can be used only when compiling C++
    +
    +

    0932

    +
    cl_invalid_import_directory:
    +
    invalid directory for #import files: xxxx
    +
    +

    0933

    +
    cl_import_only_in_microsoft:
    +
    an import directory can be specified only in Microsoft mode
    +
    +

    0934

    +
    ref_not_allowed_in_union:
    +
    a member with reference type is not allowed in a union
    +
    +

    0935

    +
    typedef_not_allowed:
    +
    “typedef” may not be specified here
    +
    +

    0936

    +
    redecl_changes_access:
    +
    redeclaration of entity-kind “entity” alters its access
    +
    +

    0937

    +
    qualified_name_required:
    +
    a class or namespace qualified name is required
    +
    +

    0938

    +
    implicit_int_on_main:
    +
    return type “int” omitted in declaration of function “main”
    +
    +

    0939

    +
    invalid_inheritance_kind_for_class:
    +
    pointer-to-member representation “xxxx” is too restrictive for +entity-kind “entity”
    +
    +

    0940

    +
    implicit_return_from_non_void_function:
    +
    missing return statement at end of non-void entity-kind “entity”
    +
    +

    0941

    +
    duplicate_using_decl:
    +
    duplicate using-declaration of “entity” ignored
    +
    +

    0942

    +
    unsigned_enum_bit_field_with_signed_enumerator:
    +
    enum bit fields are always unsigned, but enum “type” includes +negative enumerator
    +
    +

    0943

    +
    cl_class_name_injection_option_only_in_cplusplus:
    +
    option “class_name_injection” can be used only when compiling C++
    +
    +

    0944

    +
    cl_arg_dependent_lookup_option_only_in_cplusplus:
    +
    option “arg_dep_lookup” can be used only when compiling C++
    +
    +

    0945

    +
    cl_friend_injection_option_only_in_cplusplus:
    +
    option “friend_injection” can be used only when compiling C++
    +
    +

    0946

    +
    invalid_name_after_template:
    +
    name following “template” must be a template
    +
    +

    0948

    +
    local_class_friend_requires_prior_decl:
    +
    nonstandard local-class friend declaration – no prior declaration in +the enclosing scope
    +
    +

    0949

    +
    nonstd_default_arg:
    +
    specifying a default argument on this declaration is nonstandard
    +
    +

    0950

    +
    cl_nonstd_using_decl_option_only_in_cplusplus:
    +
    option “nonstd_using_decl” can be used only when compiling C++
    +
    +

    0951

    +
    bad_return_type_on_main:
    +
    return type of function “main” must be “int”
    +
    +

    0952

    +
    template_parameter_has_class_type:
    +
    a nontype template parameter may not have class type
    +
    +

    0953

    +
    default_arg_on_member_decl:
    +
    a default template argument cannot be specified on the definition of +a member of a class template outside the template
    +
    +

    0954

    +
    return_from_ctor_function_try_block_handler:
    +
    a return statement is not allowed in a handler of a function try +block of a constructor
    +
    +

    0955

    +
    no_ordinary_and_extended_designators:
    +
    ordinary and extended designators cannot be combined in an +initializer designation
    +
    +

    0956

    +
    no_negative_designator_range:
    +
    the second subscript must not be smaller than the first
    +
    +

    0958

    +
    cl_extended_designators_option_only_in_C:
    +
    option “extended_designators” can be used only when compiling C
    +
    +

    0959

    +
    extra_bits_ignored:
    +
    declared size for bit field is larger than the size of the bit field +type; truncated to xxxx bits
    +
    +

    0960

    +
    constructor_type_mismatch:
    +
    type used as constructor name does not match type “type”
    +
    +

    0961

    +
    type_with_no_linkage_in_var_with_linkage:
    +
    use of a type with no linkage to declare a variable with linkage
    +
    +

    0962

    +
    type_with_no_linkage_in_function:
    +
    use of a type with no linkage to declare a function
    +
    +

    0963

    +
    return_type_on_constructor:
    +
    return type may not be specified on a constructor
    +
    +

    0964

    +
    return_type_on_destructor:
    +
    return type may not be specified on a destructor
    +
    +

    0965

    +
    malformed_universal_character:
    +
    incorrectly formed universal character name
    +
    +

    0966

    +
    invalid_UCN:
    +
    universal character name specifies an invalid character
    +
    +

    0967

    +
    UCN_names_basic_char:
    +
    a universal character name cannot designate a character in the basic +character set
    +
    +

    0968

    +
    invalid_identifier_UCN:
    +
    this universal character is not allowed in an identifier
    +
    +

    0969

    +
    VA_ARGS_not_allowed:
    +
    the identifier __VA_ARGS__ can only appear in the replacement lists +of variadic macros
    +
    +

    0970

    +
    friend_qualification_ignored:
    +
    the qualifier on this friend declaration is ignored
    +
    +

    0971

    +
    no_range_designator_with_dynamic_init:
    +
    array range designators cannot be applied to dynamic initializers
    +
    +

    0972

    +
    property_name_not_allowed:
    +
    property name cannot appear here
    +
    +

    0973

    +
    inline_qualifier_ignored:
    +
    “inline” used as a function qualifier is ignored
    +
    +

    0974

    +
    cl_compound_literals_option_only_in_C:
    +
    option “compound_literals” can be used only when compiling C
    +
    +

    0975

    +
    vla_not_allowed:
    +
    a variable-length array type is not allowed
    +
    +

    0976

    +
    bad_integral_compound_literal:
    +
    a compound literal is not allowed in an integral constant expression
    +
    +

    0977

    +
    bad_compound_literal_type:
    +
    a compound literal of type “type” is not allowed
    +
    +

    0978

    +
    friend_template_in_local_class:
    +
    a template friend declaration cannot be declared in a local class
    +
    +

    0979

    +
    ambiguous_question_operator:
    +
    ambiguous “?” operation: second operand of type “type” can be +converted to third operand type “type”, and vice versa
    +
    +

    0980

    +
    bad_call_of_class_object:
    +
    call of an object of a class type without appropriate operator() or +conversion functions to pointer-to-function type
    +
    +

    0982

    +
    ambiguous_class_call:
    +
    there is more than one way an object of type “type” can be called +for the argument list:
    +
    +

    0983

    +
    similar_typedef:
    +
    typedef name has already been declared (with similar type)
    +
    +

    0984

    +
    no_internal_linkage_for_new_or_delete:
    +
    operator new and operator delete cannot be given internal linkage
    +
    +

    0985

    +
    no_mutable_allowed_on_anonymous_union:
    +
    storage class “mutable” is not allowed for anonymous unions
    +
    +

    0986

    +
    bad_pch_file:
    +
    invalid precompiled header file
    +
    +

    0987

    +
    abstract_class_catch_type:
    +
    abstract class type “type” is not allowed as catch type:
    +
    +

    0988

    +
    bad_qualified_function_type:
    +
    a qualified function type cannot be used to declare a nonmember +function or a static member function
    +
    +

    0989

    +
    bad_qualified_function_type_parameter:
    +
    a qualified function type cannot be used to declare a parameter
    +
    +

    0990

    +
    ptr_or_ref_to_qualified_function_type:
    +
    cannot create a pointer or reference to qualified function type
    +
    +

    0991

    +
    nonstd_braces:
    +
    extra braces are nonstandard
    +
    +

    0992

    +
    bad_cmd_line_macro:
    +
    invalid macro definition: xxxx
    +
    +

    0993

    +
    nonstandard_ptr_minus_ptr:
    +
    subtraction of pointer types “type” and “type” is nonstandard
    +
    +

    0994

    +
    empty_template_param_list:
    +
    an empty template parameter list is not allowed in a template +template parameter declaration
    +
    +

    0995

    +
    exp_class:
    +
    expected “class”
    +
    +

    0996

    +
    struct_not_allowed:
    +
    the “struct” keyword may not be used when declaring a template +template parameter
    +
    +

    0997

    +
    virtual_function_decl_hidden:
    +
    entity-kind “entity” is hidden by “entity” – virtual +function override intended?
    +
    +

    0998

    +
    no_qualified_friend_definition:
    +
    a qualified name is not allowed for a friend declaration that is a +function definition
    +
    +

    0999

    +
    not_compatible_with_templ_templ_param:
    +
    entity-kind “entity” is not compatible with entity-kind +“entity”
    +
    +

    1000

    +
    storage_class_requires_function_or_variable:
    +
    a storage class may not be specified here
    +
    +

    1001

    +
    member_using_must_be_visible_in_direct_base:
    +
    class member designated by a using-declaration must be visible in a +direct base class
    +
    +

    1003

    +
    cl_sun_incompatible_with_cfront:
    +
    Sun mode is incompatible with cfront mode
    +
    +

    1004

    +
    cl_strict_mode_incompatible_with_sun:
    +
    strict mode is incompatible with Sun mode
    +
    +

    1005

    +
    cl_sun_mode_only_in_cplusplus:
    +
    Sun mode is only allowed when compiling C++
    +
    +

    1006

    +
    template_template_param_same_name_as_templ_param:
    +
    a template template parameter cannot have the same name as one of its +template parameters
    +
    +

    1007

    +
    recursive_def_arg_instantiation:
    +
    recursive instantiation of default argument
    +
    +

    1009

    +
    bad_template_name:
    +
    entity-kind “entity” is not an entity that can be defined
    +
    +

    1010

    +
    destructor_name_must_be_qualified:
    +
    destructor name must be qualified
    +
    +

    1011

    +
    no_typename_in_friend_class_decl:
    +
    friend class name may not be introduced with “typename”
    +
    +

    1012

    +
    no_ctor_or_dtor_using_declaration:
    +
    a using-declaration may not name a constructor or destructor
    +
    +

    1013

    +
    friend_is_nonreal_template:
    +
    a qualified friend template declaration must refer to a specific +previously declared template
    +
    +

    1014

    +
    bad_class_template_decl:
    +
    invalid specifier in class template declaration
    +
    +

    1015

    +
    simple_incompatible_param:
    +
    argument is incompatible with formal parameter
    +
    +

    1016

    +
    cl_dep_name_option_only_in_cplusplus:
    +
    option “dep_name” can be used only when compiling C++
    +
    +

    1017

    +
    op_arrow_loop:
    +
    loop in sequence of “operator->” functions starting at class +“type”
    +
    +

    1018

    +
    not_a_member_class:
    +
    entity-kind “entity” has no member class “xxxx”
    +
    +

    1019

    +
    name_not_class_in_file_scope:
    +
    the global scope has no class named “xxxx”
    +
    +

    1020

    +
    recursive_inst_of_templ_default_arg:
    +
    recursive instantiation of template default argument
    +
    +

    1021

    +
    no_access_or_using_decl_in_union:
    +
    access declarations and using-declarations cannot appear in unions
    +
    +

    1022

    +
    not_class_member:
    +
    “entity” is not a class member
    +
    +

    1023

    +
    nonstd_const_member_decl_not_allowed:
    +
    nonstandard member constant declaration is not allowed
    +
    +

    1024

    +
    cl_ignore_std_option_only_in_cplusplus:
    +
    option “ignore_std” can be used only when compiling C++
    +
    +

    1025

    +
    cl_parse_nonclass_templates_option_only_in_cplusplus:
    +
    option “parse_templates” can be used only when compiling C++
    +
    +

    1026

    +
    cl_dep_name_requires_parse_nonclass_templates:
    +
    option “dep_name” cannot be used with “no_parse_templates”
    +
    +

    1027

    +
    cl_incompatible_language_modes:
    +
    language modes specified are incompatible
    +
    +

    1028

    +
    invalid_nested_class_redecl:
    +
    invalid redeclaration of nested class
    +
    +

    1029

    +
    flexible_array_member_not_allowed:
    +
    type containing an unknown-size array is not allowed
    +
    +

    1030

    +
    static_variable_in_inline_function:
    +
    a variable with static storage duration cannot be defined within an +inline function
    +
    +

    1031

    +
    bad_linkage_of_ref_within_inline_function:
    +
    an entity with internal linkage cannot be referenced within an inline +function with external linkage
    +
    +

    1032

    +
    type_generic_function_mismatch:
    +
    argument type “type” does not match this type-generic function +macro
    +
    +

    1034

    +
    friend_cannot_add_default_arguments:
    +
    friend declaration cannot add default arguments to previous +declaration
    +
    +

    1035

    +
    cannot_be_declared_in_scope:
    +
    entity-kind “entity” cannot be declared in this scope
    +
    +

    1036

    +
    id_can_only_appear_in_function:
    +
    the reserved identifier “xxxx” may only be used inside a function
    +
    +

    1037

    +
    invalid_identifier_start_UCN:
    +
    this universal character cannot begin an identifier
    +
    +

    1038

    +
    exp_string_literal:
    +
    expected a string literal
    +
    +

    1039

    +
    unrecognized_stdc_pragma:
    +
    unrecognized STDC pragma
    +
    +

    1040

    +
    bad_stdc_pragma_arg:
    +
    expected “ON”, “OFF”, or “DEFAULT”
    +
    +

    1041

    +
    stdc_pragma_not_allowed_here:
    +
    a STDC pragma may only appear between declarations in the global +scope or before any statements or declarations in a block scope
    +
    +

    1042

    +
    bad_va_copy:
    +
    incorrect use of va_copy
    +
    +

    1043

    +
    only_applies_to_float_types:
    +
    xxxx can only be used with floating-point types
    +
    +

    1044

    +
    complex_type_not_allowed:
    +
    complex type is not allowed
    +
    +

    1045

    +
    invalid_designator_kind:
    +
    invalid designator kind
    +
    +

    1046

    +
    inexact_fp_conversion:
    +
    floating-point value cannot be represented exactly
    +
    +

    1047

    +
    bad_complex_operation_result:
    +
    complex floating-point operation result is out of range
    +
    +

    1048

    +
    real_imaginary_conversion:
    +
    conversion between real and imaginary yields zero
    +
    +

    1049

    +
    cannot_initialize_flexible_array_member:
    +
    an initializer cannot be specified for a flexible array member
    +
    +

    1050

    +
    imaginary_times_assign:
    +
    imaginary *= imaginary sets the left-hand operand to zero
    +
    +

    1051

    +
    undeclared_parameter:
    +
    standard requires that entity-kind “entity” be given a type by a +subsequent declaration (“int” assumed)
    +
    +

    1052

    +
    inline_never_defined:
    +
    a definition is required for inline entity-kind “entity”
    +
    +

    1053

    +
    conversion_to_pointer_loses_bits:
    +
    conversion from integer to smaller pointer
    +
    +

    1054

    +
    missing_floating_point_type:
    +
    a floating-point type must be included in the type specifier for a +_Complex or _Imaginary type
    +
    +

    1055

    +
    type_decl_in_anon_union:
    +
    types cannot be declared in anonymous unions
    +
    +

    1056

    +
    returning_ptr_to_local_variable:
    +
    returning pointer to local variable
    +
    +

    1057

    +
    returning_ptr_to_local_temp:
    +
    returning pointer to local temporary
    +
    +

    1058

    +
    cl_export_template_option_only_in_cplusplus:
    +
    option “export” can be used only when compiling C++
    +
    +

    1059

    +
    cl_export_template_requires_dep_name:
    +
    option “export” cannot be used with “no_dep_name”
    +
    +

    1060

    +
    cl_export_template_requires_no_implicit_include:
    +
    option “export” cannot be used with “implicit_include”
    +
    +

    1061

    +
    corresp_decl_incompatible:
    +
    declaration of entity-kind “entity” is incompatible with a +declaration in another translation unit
    +
    +

    1062

    +
    corresp_decl_at:
    +
    the other declaration is at line xxxx
    +
    +

    1065

    +
    field_cannot_involve_vla_type:
    +
    a field declaration cannot have a type involving a variable length +array
    +
    +

    1066

    +
    entity_differs_in_other_trans_unit:
    +
    declaration of entity-kind “entity” had a different meaning +during compilation of “xxxx”
    +
    +

    1067

    +
    exp_template:
    +
    expected “template”
    +
    +

    1068

    +
    export_on_instantiation:
    +
    “export” cannot be used on an explicit instantiation
    +
    +

    1069

    +
    bad_decl_for_export:
    +
    “export” cannot be used on this declaration
    +
    +

    1070

    +
    exported_in_unnamed_namespace:
    +
    a member of an unnamed namespace cannot be declared “export”
    +
    +

    1071

    +
    export_after_definition:
    +
    a template cannot be declared “export” after it has been defined
    +
    +

    1072

    +
    labeled_declaration:
    +
    a declaration cannot have a label
    +
    +

    1073

    +
    no_export_support:
    +
    support for exported templates is disabled
    +
    +

    1075

    +
    entity_defined_in_other_trans_unit:
    +
    entity-kind “entity” already defined during compilation of +“xxxx”
    +
    +

    1076

    +
    entity_defined_twice:
    +
    entity-kind “entity” already defined in another translation unit
    +
    +

    1077

    +
    based_var_cannot_be_local:
    +
    a nonstatic local variable may not be used in a __based specification
    +
    +

    1078

    +
    cl_list_make_dependencies_incompatible_with_multiple_trans_units:
    +
    the option to list makefile dependencies may not be specified when +compiling more than one translation unit
    +
    +

    1080

    +
    cl_pp_output_incompatible_with_multiple_trans_units:
    +
    the option to generate preprocessed output may not be specified when +compiling more than one translation unit
    +
    +

    1081

    +
    field_name_conflicts_with_class:
    +
    a field with the same name as its class cannot be declared in a class +with a user-declared constructor
    +
    +

    1082

    +
    cl_implicit_include_incompatible_with_multiple_trans_units:
    +
    “implicit_include” cannot be used when compiling more than one +translation unit
    +
    +

    1083

    +
    corrupted_export_template_file:
    +
    exported template file “xxxx” is corrupted
    +
    +

    1084

    +
    exported_instantiation_and_specialized:
    +
    entity-kind “entity” cannot be instantiated – it has been +explicitly specialized in the translation unit containing the +exported definition
    +
    +

    1086

    +
    unqual_named_function_with_qual_object:
    +
    the object has type qualifiers that are not compatible with the +member entity-kind “entity”
    +
    +

    1087

    +
    no_matching_function_due_to_selector:
    +
    no instance of entity-kind “entity” matches the argument list and +object (the object has type qualifiers that prevent a match)
    +
    +

    1088

    +
    mode_incompatible_with_type:
    +
    an attribute specifies a mode incompatible with “type”
    +
    +

    1089

    +
    no_type_of_specified_width:
    +
    there is no type with the width specified
    +
    +

    1090

    +
    bad_attribute_alignment:
    +
    invalid alignment value specified by attribute
    +
    +

    1091

    +
    attribute_does_not_apply_to_type:
    +
    invalid attribute for “type”
    +
    +

    1094

    +
    arguments_provided_for_attribute:
    +
    attribute “xxxx” does not take arguments
    +
    +

    1096

    +
    exp_attribute_name:
    +
    expected an attribute name
    +
    +

    1097

    +
    unrecognized_attribute:
    +
    unknown attribute “xxxx”
    +
    +

    1098

    +
    attribute_not_allowed:
    +
    attributes may not appear here
    +
    +

    1099

    +
    invalid_argument_to_attribute:
    +
    invalid argument to attribute “xxxx”
    +
    +

    1101

    +
    assigned_goto_requires_void_ptr:
    +
    in “goto *expr”, expr must have type “void *”
    +
    +

    1102

    +
    nonstd_assigned_goto:
    +
    “goto *expr” is nonstandard
    +
    +

    1103

    +
    nonstd_address_of_label:
    +
    taking the address of a label is nonstandard
    +
    +

    1104

    +
    cl_duplicate_file_name:
    +
    file name specified more than once: xxxx
    +
    +

    1105

    +
    warning_directive:
    +
    #warning directive: xxxx
    +
    +

    1107

    +
    transparent_type_is_not_union:
    +
    the “transparent_union” attribute only applies to unions, and +“type” is not a union
    +
    +

    1108

    +
    transparent_attribute_ignored:
    +
    the “transparent_union” attribute is ignored on incomplete types
    +
    +

    1109

    +
    union_cannot_be_transparent_sym:
    +
    “type” cannot be transparent because entity-kind “entity”does not have the same size as the first field
    +
    +

    1110

    +
    union_cannot_be_transparent:
    +
    “type” cannot be transparent because it has a field of type +“type” which is not the same size as the first field
    +
    +

    1112

    +
    attribute_does_not_apply_to_local_variable:
    +
    attribute “xxxx” does not apply to local variables
    +
    +

    1113

    +
    attributes_in_rout_defn:
    +
    attributes are not permitted in a function definition
    +
    +

    1115

    +
    invalid_case_range:
    +
    the second constant in a case range must be larger than the first
    +
    +

    1116

    +
    asm_name_in_rout_defn:
    +
    an asm name is not permitted in a function definition
    +
    +

    1117

    +
    asm_name_in_typedef:
    +
    an asm name is ignored in a typedef
    +
    +

    1118

    +
    bad_reg_name:
    +
    unknown register name “xxxx“
    +
    +

    1120

    +
    bad_asm_constraint_modifier:
    +
    unknown asm constraint modifier ‘xxxx‘
    +
    +

    1121

    +
    bad_asm_constraint_letter:
    +
    unknown asm constraint letter ‘xxxx‘
    +
    +

    1122

    +
    missing_constraint_letter:
    +
    asm operand has no constraint letter
    +
    +

    1123

    +
    asm_output_must_have_output_mod:
    +
    an asm output operand must have one of the ‘=’ or ‘+’ modifiers
    +
    +

    1124

    +
    asm_input_must_not_have_output_mod:
    +
    an asm input operand may not have the ‘=’ or ‘+’ modifiers
    +
    +

    1127

    +
    register_used_twice:
    +
    register “xxxx“ used more than once
    +
    +

    1128

    +
    register_used_and_clobbered:
    +
    register “xxxx“ is both used and clobbered
    +
    +

    1129

    +
    register_clobbered_twice:
    +
    register “xxxx“ clobbered more than once
    +
    +

    1130

    +
    fixed_register_used:
    +
    register “xxxx“ has a fixed purpose and may not be used in an asm +statement
    +
    +

    1131

    +
    fixed_register_clobbered:
    +
    register “xxxx“ has a fixed purpose and may not be clobbered in +an asm statement
    +
    +

    1132

    +
    empty_clobbers_list:
    +
    an empty clobbers list must be omitted entirely
    +
    +

    1133

    +
    exp_asm_operand:
    +
    expected an asm operand
    +
    +

    1134

    +
    exp_asm_clobber:
    +
    expected a register to clobber
    +
    +

    1135

    +
    format_rout_not_varargs:
    +
    “format” attribute requires an ellipsis parameter or parameter pack
    +
    +

    1136

    +
    subst_arg_is_not_variable:
    +
    first substitution argument is not the first variable argument
    +
    +

    1137

    +
    fmt_arg_does_not_exist:
    +
    format argument index is greater than number of parameters
    +
    +

    1138

    +
    fmt_arg_is_not_string:
    +
    format argument does not have string type
    +
    +

    1139

    +
    template_not_in_template:
    +
    the “template” keyword used for syntactic disambiguation may only be +used within a template
    +
    +

    1142

    +
    attr_requires_func_type:
    +
    attribute “xxxx” does not apply to non-function type “type”
    +
    +

    1143

    +
    nonobject_pointer_arithmetic:
    +
    arithmetic on pointer to void or function type
    +
    +

    1144

    +
    invalid_storage_class_in_for_init:
    +
    storage class must be auto or register
    +
    +

    1145

    +
    va_arg_would_have_been_promoted:
    +
    “type” would have been promoted to “type” when passed through +the ellipsis parameter; use the latter type instead
    +
    +

    1146

    +
    not_a_base_class_member:
    +
    “xxxx” is not a base class member
    +
    +

    1147

    +
    super_after_scope:
    +
    __super cannot appear after “::”
    +
    +

    1148

    +
    super_not_in_class:
    +
    __super may only be used in a class scope
    +
    +

    1149

    +
    unqualified_super:
    +
    __super must be followed by “::”
    +
    +

    1151

    +
    mangled_name_too_long:
    +
    mangled name is too long
    +
    +

    1152

    +
    aliased_name_undeclared:
    +
    declaration aliased to undefined entity “xxxx”
    +
    +

    1153

    +
    aliased_name_bad_kind:
    +
    declaration does not match its alias entity-kind “entity”
    +
    +

    1154

    +
    alias_cannot_have_definition:
    +
    entity declared as alias cannot have definition
    +
    +

    1155

    +
    vla_size_ignored:
    +
    variable-length array field type will be treated as zero-length array +field type
    +
    +

    1156

    +
    gcc_lvalue_cast_ignored:
    +
    nonstandard cast on lvalue ignored
    +
    +

    1157

    +
    cl_invalid_flag_name:
    +
    unrecognized flag name: xxxx
    +
    +

    1158

    +
    qualified_void_return_type:
    +
    void return type cannot be qualified
    +
    +

    1159

    +
    auto_ignored:
    +
    the auto specifier is ignored here (invalid in standard C/C++)
    +
    +

    1160

    +
    alignment_reduction_ignored:
    +
    a reduction in alignment without the “packed” attribute is ignored
    +
    +

    1161

    +
    corresp_member_template_is_different_kind:
    +
    a member template corresponding to “entity” is declared as a +template of a different kind in another translation unit
    +
    +

    1162

    +
    excess_initializers_ignored:
    +
    excess initializers are ignored
    +
    +

    1163

    +
    va_start_requires_ellipsis_function:
    +
    va_start can appear only in a function with an ellipsis parameter
    +
    +

    1164

    +
    cl_short_enums_requires_gcc_mode:
    +
    the “short_enums” option is only valid in GNU C and GNU C++ modes
    +
    +

    1165

    +
    bad_export_info_file:
    +
    invalid export information file “xxxx” at line number xxxx
    +
    +

    1166

    +
    statement_expression_in_function_only:
    +
    statement expressions are only allowed in block scope
    +
    +

    1168

    +
    asm_name_on_auto_variable:
    +
    an asm name is ignored on a non-register automatic variable
    +
    +

    1170

    +
    unrecognized_upc_pragma:
    +
    unrecognized UPC pragma
    +
    +

    1171

    +
    mismatched_shared_block_size:
    +
    shared block size does not match one previously specified
    +
    +

    1172

    +
    ambiguous_block_size_spec:
    +
    bracketed expression is assumed to be a block size specification +rather than an array dimension
    +
    +

    1173

    +
    shared_block_size_must_be_positive:
    +
    the block size of a shared array must be greater than zero
    +
    +

    1174

    +
    multiple_block_sizes:
    +
    multiple block sizes not allowed
    +
    +

    1175

    +
    nonshared_strict_relaxed:
    +
    strict or relaxed requires shared
    +
    +

    1176

    +
    threads_constant_not_allowed:
    +
    THREADS not allowed in this context
    +
    +

    1177

    +
    shared_block_size_too_large:
    +
    block size specified exceeds the maximum value of xxxx
    +
    +

    1178

    +
    function_returning_shared:
    +
    function returning shared is not allowed
    +
    +

    1180

    +
    shared_nonthreads_dim:
    +
    one dimension of an array of a shared type must be a multiple of +THREADS when the number of threads is nonconstant
    +
    +

    1181

    +
    shared_inside_struct:
    +
    shared type inside a struct or union is not allowed
    +
    +

    1182

    +
    shared_parameter:
    +
    parameters may not have shared types
    +
    +

    1183

    +
    threads_dimension_requires_definite_block_size:
    +
    a dynamic THREADS dimension requires a definite block size
    +
    +

    1184

    +
    bad_shared_storage_class:
    +
    shared variables must be static or extern
    +
    +

    1185

    +
    nonshared_blocksizeof:
    +
    argument of upc_blocksizeof is a pointer to a shared type (not shared +type itself)
    +
    +

    1186

    +
    nested_upc_forall:
    +
    affinity expression ignored in nested upc_forall
    +
    +

    1187

    +
    exit_forall:
    +
    branching into or out of a upc_forall loop is not allowed
    +
    +

    1188

    +
    bad_affinity:
    +
    affinity expression must have a shared type or point to a shared type
    +
    +

    1189

    +
    shared_affinity_type:
    +
    affinity has shared type (not pointer to shared)
    +
    +

    1190

    +
    upc_shared_void_comparison:
    +
    shared void* types can only be compared for equality
    +
    +

    1191

    +
    cl_upc_requires_ansi_c_dialect:
    +
    UPC mode is incompatible with C++ and K&R modes
    +
    +

    1192

    +
    null_char_ignored:
    +
    null (zero) character in input line ignored
    +
    +

    1193

    +
    null_char_in_string:
    +
    null (zero) character in string or character constant
    +
    +

    1194

    +
    null_char_in_header_name:
    +
    null (zero) character in header name
    +
    +

    1195

    +
    for_init_hides_declaration:
    +
    declaration in for-initializer hides a declaration in the surrounding +scope
    +
    +

    1196

    +
    for_init_hidden_declaration:
    +
    the hidden declaration is at line xxxx
    +
    +

    1197

    +
    prototype_lost:
    +
    the prototype declaration of entity-kind “entity” (declared at +line xxxx) is ignored after this unprototyped redeclaration
    +
    +

    1199

    +
    bad_linkage_for_redefine_extname:
    +
    entity-kind “entity” (declared at line xxxx) must have +external C linkage
    +
    +

    1200

    +
    declaration_hides_for_init:
    +
    variable declaration hides declaration in for-initializer
    +
    +

    1201

    +
    typedef_in_elab_type:
    +
    typedef “xxxx” may not be used in an elaborated type specifier
    +
    +

    1202

    +
    call_of_zero:
    +
    call of zero constant ignored
    +
    +

    1203

    +
    handler_redeclares_parameter:
    +
    parameter “xxxx” may not be redeclared in a catch clause of +function try block
    +
    +

    1204

    +
    specialization_out_of_namespace:
    +
    the initial explicit specialization of entity-kind “entity” must +be declared in the namespace containing the template
    +
    +

    1205

    +
    cc_clobber_ignored:
    +
    “cc” clobber ignored
    +
    +

    1206

    +
    invalid_token_after_template:
    +
    “template” must be followed by an identifier
    +
    +

    1207

    +
    mythread_constant_not_allowed:
    +
    MYTHREAD not allowed in this context
    +
    +

    1208

    +
    bad_upc_shared_pointer_layout_qualifier:
    +
    layout qualifier cannot qualify pointer to shared
    +
    +

    1209

    +
    bad_upc_shared_array_layout_qualifier:
    +
    layout qualifier cannot qualify an incomplete array
    +
    +

    1210

    +
    decl_hides_catch_parameter:
    +
    declaration of “xxxx” hides handler parameter
    +
    +

    1211

    +
    nonstd_ignored_array_cast:
    +
    nonstandard cast to array type ignored
    +
    +

    1212

    +
    invalid_pragma_operator:
    +
    this pragma cannot be used in a _Pragma operator (a #pragma directive +must be used)
    +
    +

    1213

    +
    field_uses_tail_padding:
    +
    field uses tail padding of a base class
    +
    +

    1214

    +
    gnu_may_use_bit_padding:
    +
    GNU C++ compilers may use bit field padding
    +
    +

    1215

    +
    deprecated_entity:
    +
    entity-kind “entity” was declared deprecated
    +
    +

    1216

    +
    field_with_asm_name_not_allowed:
    +
    an asm name is not allowed on a nonstatic member declaration
    +
    +

    1217

    +
    unrecognized_format_function_type:
    +
    unrecognized format function type “xxxx” ignored
    +
    +

    1218

    +
    base_uses_tail_padding:
    +
    base class “entity” uses tail padding of base class “entity”
    +
    +

    1219

    +
    bad_variable_for_init_priority:
    +
    the “init_priority” attribute can only be used for definitions of +static data members and namespace scope variables of class types
    +
    +

    1220

    +
    init_priority_reserved:
    +
    requested initialization priority is reserved for internal use
    +
    +

    1221

    +
    hidden_anonymous_union_field:
    +
    this anonymous union/struct field is hidden by entity-kind +“entity” (declared at line xxxx)
    +
    +

    1222

    +
    invalid_error_number:
    +
    invalid error number
    +
    +

    1223

    +
    invalid_error_tag:
    +
    invalid error tag
    +
    +

    1224

    +
    exp_error_argument:
    +
    expected an error number or error tag
    +
    +

    1225

    +
    size_affected_by_tail_padding:
    +
    size of class is affected by tail padding
    +
    +

    1226

    +
    nonlocal_label_reference:
    +
    labels can be referenced only in function definitions
    +
    +

    1227

    +
    branch_into_statement_expr:
    +
    transfer of control into a statement expression is not allowed
    +
    +

    1229

    +
    bad_statement_in_statement_expr:
    +
    this statement is not allowed inside of a statement expression
    +
    +

    1230

    +
    class_def_in_statement_expr:
    +
    a class that is not trivially copyable cannot be defined inside a +statement expression
    +
    +

    1232

    +
    dyn_local_static_in_statement_expr:
    +
    a dynamically-initialized local static variable is not allowed inside +of a statement expression
    +
    +

    1233

    +
    vla_in_statement_expr:
    +
    a variable-length array is not allowed inside of a statement +expression
    +
    +

    1234

    +
    statement_expr_in_default_arg:
    +
    a statement expression is not allowed inside of a default argument
    +
    +

    1235

    +
    ptr_func_ptr_data_conv:
    +
    nonstandard conversion between pointer to function and pointer to data
    +
    +

    1236

    +
    interface_cannot_have_virtual_base:
    +
    interface types cannot have virtual base classes
    +
    +

    1237

    +
    interface_cannot_have_private_or_protected:
    +
    interface types cannot specify “private” or “protected”
    +
    +

    1238

    +
    interface_must_derive_from_interface:
    +
    interface types can only derive from other interface types
    +
    +

    1239

    +
    type_is_interface:
    +
    “type” is an interface type
    +
    +

    1240

    +
    interface_cannot_have_typedef:
    +
    interface types cannot have typedef members
    +
    +

    1241

    +
    interface_cannot_have_ctor_or_dtor:
    +
    interface types cannot have user-declared constructors or destructors
    +
    +

    1242

    +
    interface_cannot_have_operator:
    +
    interface types cannot have user-declared member operators
    +
    +

    1243

    +
    interface_cannot_be_local:
    +
    interface types cannot be declared in functions
    +
    +

    1245

    +
    interface_cannot_have_data_member:
    +
    interface types cannot have data members
    +
    +

    1246

    +
    interface_cannot_have_friend:
    +
    interface types cannot contain friend declarations
    +
    +

    1248

    +
    interface_cannot_be_nested_class:
    +
    interface types cannot be nested class types
    +
    +

    1249

    +
    interface_cannot_have_member_templates:
    +
    interface types cannot have member templates
    +
    +

    1250

    +
    interface_cannot_have_static_members:
    +
    interface types cannot have static member functions
    +
    +

    1251

    +
    invalid_microsoft_pragma_operator:
    +
    this pragma cannot be used in a __pragma operator (a #pragma +directive must be used)
    +
    +

    1252

    +
    qualifier_must_be_base_class:
    +
    qualifier must be base class of “type”
    +
    +

    1253

    +
    invalid_selective_overrider_declaration:
    +
    declaration must correspond to a pure virtual member function in the +indicated base class
    +
    +

    1254

    +
    integer_overflow_class_internal:
    +
    integer overflow in internal computation due to size or complexity of +“type”
    +
    +

    1255

    +
    integer_overflow_internal:
    +
    integer overflow in internal computation
    +
    +

    1256

    +
    invalid_type_for_w64:
    +
    __w64 can only be specified on int, long, and pointer types
    +
    +

    1257

    +
    ilp64_will_narrow:
    +
    potentially narrowing conversion when compiled in an environment +where int, long, or pointer types are 64 bits wide
    +
    +

    1258

    +
    value_of_pragma_pack_show:
    +
    current value of pragma pack is xxxx
    +
    +

    1259

    +
    pragma_pack_show_args_ignored:
    +
    arguments for pragma pack(show) are ignored
    +
    +

    1262

    +
    multiple_declspec_align:
    +
    earlier __declspec(align(…)) ignored
    +
    +

    1263

    +
    exp_ms_attr_enum_value:
    +
    expected an argument value for the “xxxx” attribute parameter
    +
    +

    1264

    +
    invalid_ms_attr_enum_value:
    +
    invalid argument value for the “xxxx” attribute parameter
    +
    +

    1265

    +
    exp_ms_attr_bool_value:
    +
    expected a boolean value for the “xxxx” attribute parameter
    +
    +

    1266

    +
    positional_after_named:
    +
    a positional argument cannot follow a named argument in an attribute
    +
    +

    1267

    +
    invalid_ms_attr_name:
    +
    attribute “xxxx” has no parameter named “xxxx”
    +
    +

    1268

    +
    exp_ms_attr_arg_list:
    +
    expected an argument list for the “xxxx” attribute
    +
    +

    1269

    +
    exp_comma_or_rbracket:
    +
    expected a “,” or “]”
    +
    +

    1270

    +
    duplicate_ms_attr_arg:
    +
    attribute argument “xxxx” has already been given a value
    +
    +

    1271

    +
    cannot_assign_to_ms_attr:
    +
    a value cannot be assigned to the “xxxx” attribute
    +
    +

    1272

    +
    ptr_incomplete_throw:
    +
    a throw expression may not have pointer-to-incomplete type
    +
    +

    1273

    +
    alignof_incomplete_type:
    +
    alignment-of operator applied to incomplete type
    +
    +

    1274

    +
    invalid_use_of_standalone_ms_attr:
    +
    “xxxx” may only be used as a standalone attribute
    +
    +

    1275

    +
    invalid_use_of_ms_attr:
    +
    “xxxx” attribute cannot be used here
    +
    +

    1277

    +
    ms_attr_not_allowed:
    +
    attributes are not allowed here
    +
    +

    1278

    +
    invalid_ms_attr_uuid_value:
    +
    invalid argument value for the “xxxx” attribute parameter
    +
    +

    1279

    +
    too_many_ms_attr_args:
    +
    too many attribute arguments
    +
    +

    1280

    +
    conv_from_inaccessible_base_class:
    +
    conversion from inaccessible base class “type” is not allowed
    +
    +

    1281

    +
    cl_export_template_requires_distinct_templ_sigs:
    +
    option “export” requires distinct template signatures
    +
    +

    1282

    +
    mixed_string_concatenation:
    +
    string literals with different character kinds cannot be concatenated
    +
    +

    1283

    +
    no_gnu_virtual_base_gap:
    +
    GNU layout bug not emulated because it places virtual base +“entity” outside “entity” object boundaries
    +
    +

    1284

    +
    gnu_virtual_base_gap:
    +
    virtual base “entity” placed outside “entity” object +boundaries
    +
    +

    1285

    +
    nonstd_qualifier_in_namespace_member_decl:
    +
    nonstandard qualified name in namespace member declaration
    +
    +

    1286

    +
    declspec_align_reduction_ignored:
    +
    reduction in alignment ignored
    +
    +

    1287

    +
    const_ignored:
    +
    const qualifier ignored
    +
    +

    1289

    +
    invalid_asm_qualifiers:
    +
    invalid GNU asm qualifiers
    +
    +

    1290

    +
    non_pod_passed_to_ellipsis:
    +
    a class type that is not trivially copyable passed through ellipsis
    +
    +

    1291

    +
    non_pod_va_arg:
    +
    a class type that cannot be trivially copied cannot be fetched by +va_arg
    +
    +

    1292

    +
    nonstd_fixed_point_suffix:
    +
    the ‘u’ or ‘U’ suffix must appear before the ‘l’ or ‘L’ suffix in a +fixed-point literal
    +
    +

    1293

    +
    cl_fixed_point_option_only_in_C:
    +
    option “fixed_point” can be used only when compiling C
    +
    +

    1294

    +
    integer_may_not_fit_in_fixed_point_result:
    +
    integer operand may cause fixed-point overflow
    +
    +

    1295

    +
    bad_fixed_point_value:
    +
    fixed-point constant is out of range
    +
    +

    1296

    +
    inexact_fxp_conversion:
    +
    fixed-point value cannot be represented exactly
    +
    +

    1297

    +
    c99_constant_in_unsigned_long_long_range:
    +
    constant is too large for long long; given unsigned long long type +(nonstandard)
    +
    +

    1298

    +
    bad_upc_shared_void_pointer_layout_qualifier:
    +
    layout qualifier cannot qualify pointer to shared void
    +
    +

    1299

    +
    duplicate_threads_dim:
    +
    duplicate THREADS in multidimensional array type
    +
    +

    1300

    +
    bad_strong_using_scope:
    +
    a strong using-directive may only appear in a namespace scope
    +
    +

    1301

    +
    probable_guiding_friend:
    +
    entity-kind “entity” declares a non-template function – add <> +to refer to a template instance
    +
    +

    1302

    +
    operation_may_not_fit_in_fixed_point_result:
    +
    operation may cause fixed-point overflow
    +
    +

    1303

    +
    expr_not_integral_or_enum_or_fixed_point:
    +
    expression must have integral, enum, or fixed-point type
    +
    +

    1304

    +
    expr_not_integral_or_fixed_point:
    +
    expression must have integral or fixed-point type
    +
    +

    1305

    +
    noreturn_function_does_return:
    +
    function declared with “noreturn” does return
    +
    +

    1306

    +
    asm_name_conflict:
    +
    asm name ignored because it conflicts with a previous declaration
    +
    +

    1307

    +
    duplicate_typedef_in_class:
    +
    class member typedef may not be redeclared
    +
    +

    1308

    +
    taking_address_of_temporary:
    +
    taking the address of a temporary
    +
    +

    1309

    +
    attribute_ignored_on_incomplete_class_decl:
    +
    attributes are ignored on a class declaration that is not also a +definition
    +
    +

    1310

    +
    implicit_fixed_point_to_floating_point_conversion:
    +
    fixed-point value implicitly converted to floating-point type
    +
    +

    1311

    +
    no_classification_for_fixed_point_type:
    +
    fixed-point types have no classification
    +
    +

    1312

    +
    fixed_template_parameter:
    +
    a template parameter may not have fixed-point type
    +
    +

    1313

    +
    hex_fp_constant:
    +
    hexadecimal floating-point constants are not allowed
    +
    +

    1314

    +
    cl_named_address_spaces_option_only_in_C:
    +
    option “named_address_spaces” can be used only when compiling C
    +
    +

    1315

    +
    float_to_fixed_conversion:
    +
    floating-point value does not fit in required fixed-point type
    +
    +

    1316

    +
    inexact_fixed_conversion:
    +
    value cannot be converted to fixed-point value exactly
    +
    +

    1317

    +
    fixed_sign_change:
    +
    fixed-point conversion resulted in a change of sign
    +
    +

    1318

    +
    integer_to_fixed_conversion:
    +
    integer value does not fit in required fixed-point type
    +
    +

    1319

    +
    bad_fixed_operation_result:
    +
    fixed-point operation result is out of range
    +
    +

    1320

    +
    multiple_named_address_spaces:
    +
    multiple named address spaces
    +
    +

    1321

    +
    bad_storage_class_for_named_address_space_variable:
    +
    variable with automatic storage duration cannot be stored in a named +address space
    +
    +

    1322

    +
    type_with_named_address_space_not_allowed:
    +
    type cannot be qualified with named address space
    +
    +

    1323

    +
    named_address_space_on_function_type:
    +
    function type cannot be qualified with named address space
    +
    +

    1324

    +
    field_type_cannot_be_qualified_with_named_address_space:
    +
    field type cannot be qualified with named address space
    +
    +

    1325

    +
    fixed_to_float_conversion:
    +
    fixed-point value does not fit in required floating-point type
    +
    +

    1326

    +
    fixed_to_integer_conversion:
    +
    fixed-point value does not fit in required integer type
    +
    +

    1327

    +
    fixed_to_fixed_conversion:
    +
    value does not fit in required fixed-point type
    +
    +

    1328

    +
    cl_named_registers_option_only_in_C:
    +
    option “named_registers” can be used only when compiling C
    +
    +

    1329

    +
    named_register_not_allowed:
    +
    a named-register storage class is not allowed here
    +
    +

    1330

    +
    register_storage_class_conflict:
    +
    entity-kind “entity” (declared at line xxxx) redeclared with +incompatible named-register storage class
    +
    +

    1331

    +
    aliased_variable_cannot_have_register_storage_class:
    +
    named-register storage class cannot be specified for aliased variable
    +
    +

    1332

    +
    register_in_use:
    +
    named-register storage specifier is already in use
    +
    +

    1333

    +
    embedded_c_option_incompatible_with_individual_feature_options:
    +
    option “embedded_c” cannot be combined with options to control +individual Embedded C features
    +
    +

    1334

    +
    cl_invalid_edg_base_directory:
    +
    invalid EDG_BASE directory: xxxx
    +
    +

    1336

    +
    bad_predef_macro_line:
    +
    invalid predefined macro entry at line xxxx: xxxx
    +
    +

    1337

    +
    bad_macro_mode_name:
    +
    invalid macro mode name “xxxx”
    +
    +

    1338

    +
    bad_predef_macro_redef:
    +
    incompatible redefinition of predefined macro “xxxx”
    +
    +

    1339

    +
    missing_named_register_storage_class:
    +
    redeclaration of entity-kind “entity” (declared at line xxxx) +is missing a named-register storage class
    +
    +

    1340

    +
    register_too_small:
    +
    named register is too small for the type of the variable
    +
    +

    1341

    +
    no_named_register_for_array:
    +
    arrays cannot be declared with named-register storage class
    +
    +

    1342

    +
    enum_const_cast:
    +
    const_cast to enum type is nonstandard
    +
    +

    1343

    +
    cl_embedded_c_option_only_in_C:
    +
    option “embedded_c” can be used only when compiling C
    +
    +

    1344

    +
    named_address_space_not_allowed:
    +
    a named address space qualifier is not allowed here
    +
    +

    1345

    +
    bad_initializer_for_array_with_unspecified_bound:
    +
    an empty initializer is invalid for an array with unspecified bound
    +
    +

    1346

    +
    incomplete_class_return_type:
    +
    function returns incomplete class type “type”
    +
    +

    1347

    +
    out_of_class_initializer_ignored:
    +
    entity-kind “entity” has already been initialized; the +out-of-class initializer will be ignored
    +
    +

    1348

    +
    local_variable_hidden:
    +
    declaration hides entity-kind “entity” (declared at line xxxx)
    +
    +

    1349

    +
    named_address_space_for_parameter:
    +
    a parameter cannot be allocated in a named address space
    +
    +

    1350

    +
    bad_float_or_fixed_suffix:
    +
    invalid suffix on fixed-point or floating-point constant
    +
    +

    1351

    +
    register_in_address_space:
    +
    a register variable cannot be allocated in a named address space
    +
    +

    1352

    +
    bad_stdc_fx_overflow_pragma_arg:
    +
    expected “SAT” or “DEFAULT”
    +
    +

    1353

    +
    no_corresponding_member_delete:
    +
    entity-kind “entity” has no corresponding member operator +delete*xxxx* (to be called if an exception is thrown during +initialization of an allocated object)
    +
    +

    1354

    +
    dll_thread_conflict:
    +
    a thread-local variable cannot be declared with “dllimport” or +“dllexport”
    +
    +

    1355

    +
    function_returning_named_address_space:
    +
    a function return type cannot be qualified with a named address space
    +
    +

    1356

    +
    cannot_initialize_destructible_flexible_array:
    +
    an initializer cannot be specified for a flexible array member whose +elements have a nontrivial destructor
    +
    +

    1357

    +
    cannot_initialize_indirect_flexible_array:
    +
    an initializer cannot be specified for an indirect flexible array +member
    +
    +

    1358

    +
    cl_invalid_gnu_version:
    +
    invalid GNU version number: xxxx
    +
    +

    1359

    +
    attribute_after_parenthesized_initializer:
    +
    variable attributes appearing after a parenthesized initializer are +ignored
    +
    +

    1360

    +
    gcc_use_of_cast_as_lvalue:
    +
    the result of this cast cannot be used as an lvalue
    +
    +

    1361

    +
    unsigned_fixed_point_negation:
    +
    negation of an unsigned fixed-point value
    +
    +

    1364

    +
    register_name_on_nonregister:
    +
    register names can only be used for register variables
    +
    +

    1365

    +
    void_named_register:
    +
    named-register variables cannot have void type
    +
    +

    1367

    +
    parameter_with_link_scope_specifier:
    +
    parameters cannot have link scope specifiers
    +
    +

    1368

    +
    multiple_link_scope_specifiers:
    +
    multiple link scope specifiers
    +
    +

    1369

    +
    link_scope_requires_external_linkage:
    +
    link scope specifiers can only appear on functions and variables with +external linkage
    +
    +

    1370

    +
    link_scope_relaxation:
    +
    a redeclaration cannot weaken a link scope
    +
    +

    1371

    +
    invalid_link_scope:
    +
    link scope specifier not allowed on this declaration
    +
    +

    1372

    +
    nonstd_qualifier_in_global_scope_decl:
    +
    nonstandard qualified name in global scope declaration
    +
    +

    1373

    +
    impl_narrowing_64_bit_int:
    +
    implicit conversion of a 64-bit integral type to a smaller integral +type (potential portability problem)
    +
    +

    1374

    +
    expl_narrowing_64_bit_int:
    +
    explicit conversion of a 64-bit integral type to a smaller integral +type (potential portability problem)
    +
    +

    1375

    +
    pointer_conversion_to_same_size_int:
    +
    conversion from pointer to same-sized integral type (potential +portability problem)
    +
    +

    1377

    +
    friend_specifier_ignored:
    +
    friend specifier is not allowed in a class definition; friend +specifier is ignored
    +
    +

    1378

    +
    cannot_use_thread_local_storage:
    +
    only static and extern variables can use thread-local storage
    +
    +

    1379

    +
    multiple_thread_local_storage_specifiers:
    +
    multiple thread-local storage specifiers
    +
    +

    1380

    +
    virtual_function_never_defined:
    +
    virtual entity-kind “entity” was not defined (and cannot be +defined elsewhere because it is a member of an unnamed namespace)
    +
    +

    1381

    +
    stray_carriage_return:
    +
    carriage return character in source line outside of comment or +character/string literal
    +
    +

    1382

    +
    expr_not_fixed_point:
    +
    expression must have fixed-point type
    +
    +

    1383

    +
    invalid_access_specifier:
    +
    invalid use of access specifier is ignored
    +
    +

    1384

    +
    ptr_conv_to_bool:
    +
    pointer converted to bool
    +
    +

    1385

    +
    ptr_to_member_conv_to_bool:
    +
    pointer-to-member converted to bool
    +
    +

    1386

    +
    storage_specifier_ignored:
    +
    storage specifier ignored
    +
    +

    1387

    +
    dll_interface_ignored_on_class_template:
    +
    dllexport and dllimport are ignored on class templates
    +
    +

    1388

    +
    base_class_has_different_dll_interface:
    +
    base class dllexport/dllimport specification differs from that of the +derived class
    +
    +

    1389

    +
    redeclaration_adds_dll_interface:
    +
    redeclaration cannot add dllexport/dllimport to “entity”(declared at line xxxx)
    +
    +

    1390

    +
    dll_interface_conflict_dllexport_assumed:
    +
    dllexport/dllimport conflict with “entity” (declared at line +xxxx); dllexport assumed
    +
    +

    1391

    +
    dllimport_defined:
    +
    cannot define dllimport entity
    +
    +

    1392

    +
    dll_interface_requires_external_linkage:
    +
    dllexport/dllimport requires external linkage
    +
    +

    1393

    +
    class_and_member_have_dll_interface:
    +
    a member of a class declared with dllexport/dllimport cannot itself +be declared with such a specifier
    +
    +

    1394

    +
    field_without_dll_interface:
    +
    field of class type without a DLL interface used in a class with a +DLL interface
    +
    +

    1395

    +
    microsoft_parenthesized_member:
    +
    parenthesized member declaration is nonstandard
    +
    +

    1396

    +
    white_space_inside_splice:
    +
    white space between backslash and newline in line splice ignored
    +
    +

    1397

    +
    dll_interface_conflict_none_assumed:
    +
    dllexport/dllimport conflict with “entity” (declared at line +xxxx); dllimport/dllexport dropped
    +
    +

    1398

    +
    bad_nonstd_anonymous_union_field:
    +
    invalid member for anonymous member class – class “type” has a +disallowed member function
    +
    +

    1399

    +
    nonstd_reinterpret_cast:
    +
    nonstandard reinterpret_cast
    +
    +

    1400

    +
    positional_format_specifier_zero:
    +
    positional format specifier cannot be zero
    +
    +

    1401

    +
    nonlocal_vla_not_allowed:
    +
    a local class cannot reference a variable-length array type from an +enclosing function
    +
    +

    1402

    +
    class_and_inherited_member_instance_have_dll_interface:
    +
    member entity-kind “entity” (declared at line xxxx) already +has an explicit dllexport/dllimport specifier
    +
    +

    1403

    +
    vla_in_return_type:
    +
    a variable-length array is not allowed in a function return type
    +
    +

    1404

    +
    ptr_to_member_of_vla_type:
    +
    variable-length array type is not allowed in pointer to member of +type “type”
    +
    +

    1405

    +
    statement_expr_with_vla_type:
    +
    the result of a statement expression cannot have a type involving a +variable-length array
    +
    +

    1406

    +
    trigraph_ignored:
    +
    support for trigraphs is disabled
    +
    +

    1407

    +
    attribute_requires_external_linkage:
    +
    the “xxxx” attribute can only appear on functions and variables +with external linkage
    +
    +

    1408

    +
    cl_strict_mode_incompatible_with_ignore_std:
    +
    strict mode is incompatible with treating namespace std as an alias +for the global namespace
    +
    +

    1414

    +
    invalid_symbolic_asm_operand_name:
    +
    invalid symbolic operand name “xxxx”
    +
    +

    1415

    +
    match_limit_for_symbolic_asm_operand:
    +
    a symbolic match constraint must refer to one of the first ten +operands
    +
    +

    1416

    +
    if_exists_not_allowed:
    +
    use of __if_exists is not supported in this context
    +
    +

    1417

    +
    if_exists_not_closed:
    +
    __if_exists block not closed in the same scope in which it was opened
    +
    +

    1418

    +
    bad_init_for_thread_local:
    +
    thread-local variable cannot be dynamically initialized
    +
    +

    1419

    +
    unaligned_qualifier_dropped:
    +
    conversion drops “__unaligned” qualifier
    +
    +

    1420

    +
    insufficient_enum_range:
    +
    some enumerator values cannot be represented by the integral type +underlying the enum type
    +
    +

    1421

    +
    friend_class_template_default_arg_not_allowed:
    +
    default argument is not allowed on a friend class template declaration
    +
    +

    1422

    +
    multi_char_literal:
    +
    multicharacter character literal (potential portability problem)
    +
    +

    1423

    +
    exp_class_type:
    +
    expected a class, struct, or union type
    +
    +

    1424

    +
    offsetof_nonfield:
    +
    second operand of offsetof must be a field
    +
    +

    1425

    +
    offsetof_bit_field:
    +
    second operand of offsetof may not be a bit field
    +
    +

    1426

    +
    offsetof_virtual_base_member:
    +
    cannot apply offsetof to a member of a virtual base
    +
    +

    1427

    +
    offset_in_non_POD_nonstandard:
    +
    offsetof applied to a type other than a standard-layout class
    +
    +

    1428

    +
    default_arg_on_member_friend:
    +
    default arguments are not allowed on a friend declaration of a member +function
    +
    +

    1429

    +
    default_arg_requires_friend_to_be_definition:
    +
    default arguments are not allowed on friend declarations that are not +definitions
    +
    +

    1430

    +
    redeclaration_of_friend_with_default_args:
    +
    redeclaration of entity-kind “entity” (declared at line xxxx) +previously declared as a friend with default arguments is not allowed
    +
    +

    1431

    +
    bad_qualifier_for_nested_class_decl:
    +
    invalid qualifier for “type” (a derived class is not allowed here)
    +
    +

    1432

    +
    bad_qualifier_for_delayed_class_definition:
    +
    invalid qualifier for definition of class “type”
    +
    +

    1433

    +
    no_prior_push_macro:
    +
    no prior push_macro for “xxxx”
    +
    +

    1434

    +
    wide_string_not_allowed:
    +
    wide string literal not allowed
    +
    +

    1436

    +
    feature_requires_c:
    +
    “xxxx” is only allowed in C
    +
    +

    1437

    +
    microsoft_ptr_width_must_follow_star:
    +
    __ptr32 and __ptr64 must follow a “*”
    +
    +

    1438

    +
    microsoft_ptr_width_conflict:
    +
    __ptr32 and __ptr64 cannot both apply
    +
    +

    1439

    +
    name_must_be_prototype_instantiation:
    +
    template argument list of “xxxx” must match the parameter list
    +
    +

    1440

    +
    incomplete_class_type:
    +
    an incomplete class type is not allowed
    +
    +

    1441

    +
    complex_integral_type:
    +
    complex integral types are not supported
    +
    +

    1442

    +
    real_and_imag_require_complex_argument:
    +
    __real and __imag can only be applied to complex values
    +
    +

    1443

    +
    real_and_imag_applied_to_real_value:
    +
    __real/__imag applied to real value
    +
    +

    1444

    +
    deprecated_entity_with_custom_message:
    +
    entity-kind “entity” was declared deprecated (“xxxx”)
    +
    +

    1446

    +
    dll_interface_in_unnamed_namespace:
    +
    dllimport/dllexport applied to a member of an unnamed namespace
    +
    +

    1447

    +
    thiscall_requires_nonstatic_member:
    +
    __thiscall can only appear on nonstatic member function declarations
    +
    +

    1448

    +
    vararg_thiscall:
    +
    __thiscall not allowed on function with ellipsis parameter
    +
    +

    1449

    +
    specialization_of_referenced_entity_pos:
    +
    explicit specialization of entity-kind “entity” must precede its +first use (at line xxxx)
    +
    +

    1450

    +
    sealed_base_class:
    +
    a sealed class type cannot be used as a base class
    +
    +

    1451

    +
    duplicate_class_modifier:
    +
    duplicate class modifier
    +
    +

    1452

    +
    function_modifiers_abstract_and_sealed:
    +
    a member function cannot have both the “abstract” and “sealed” +modifiers
    +
    +

    1453

    +
    pure_specifier_on_sealed_member:
    +
    a sealed member cannot be pure virtual
    +
    +

    1454

    +
    function_modifier_requires_virtual_function:
    +
    nonvirtual function cannot be declared with “abstract” or “sealed” +modifier
    +
    +

    1455

    +
    override_member_does_not_override:
    +
    member function declared with “override” does not override a base +class member
    +
    +

    1456

    +
    override_of_sealed_function:
    +
    cannot override sealed entity-kind “entity” (declared at line +xxxx)
    +
    +

    1457

    +
    type_is_declared_abstract:
    +
    entity-kind “entity” (declared at line xxxx) was declared +with the class modifier “abstract”
    +
    +

    1534

    +
    duplicate_function_modifier:
    +
    duplicate function modifier
    +
    +

    1535

    +
    no_char16_t_representation:
    +
    invalid character for char16_t literal
    +
    +

    1537

    +
    cl_unrecognized_calling_convention:
    +
    unrecognized calling convention xxxx, must be one of:
    +
    +

    1541

    +
    enum_base_type_must_be_integral:
    +
    underlying type of enum type must be an integral type
    +
    +

    1542

    +
    enum_base_type_too_limited:
    +
    some enumerator constants cannot be represented by “type”
    +
    +

    1543

    +
    feature_not_allowed_in_current_mode:
    +
    “xxxx” not allowed in current mode
    +
    +

    1544

    +
    cl_type_traits_helpers_option_only_in_cplusplus:
    +
    type traits helpers option can be used only when compiling C++
    +
    +

    1545

    +
    gnu_sentinel_attribute_requires_ellipsis:
    +
    attribute “sentinel” requires an ellipsis parameter
    +
    +

    1546

    +
    invalid_gnu_sentinel_argument:
    +
    argument must be a constant null pointer value
    +
    +

    1547

    +
    no_gnu_sentinel_argument:
    +
    insufficient number of arguments for sentinel value
    +
    +

    1548

    +
    gnu_sentinel_must_be_ellipsis_argument:
    +
    sentinel argument must correspond to an ellipsis parameter
    +
    +

    1549

    +
    implementation_key_outside_mapping_region:
    +
    __declspec(implementation_key(…) can appear only between #pragma +start_map_region and #pragma stop_map_region
    +
    +

    1550

    +
    start_map_region_ignored:
    +
    #pragma start_map_region already active: pragma ignored
    +
    +

    1551

    +
    stop_map_region_ignored:
    +
    no #pragma start_map_region is currently active: pragma ignored
    +
    +

    1552

    +
    var_used_as_destructor:
    +
    entity-kind “entity” cannot be used to name a destructor (a type +name is required)
    +
    +

    1553

    +
    empty_wide_character:
    +
    nonstandard empty wide character literal treated as L’0’
    +
    +

    1554

    +
    invalid_typename_specifier:
    +
    “typename” may not be specified here
    +
    +

    1555

    +
    no_default_delete_in_virtual_dtor:
    +
    a non-placement operator delete must be visible in a class with a +virtual destructor
    +
    +

    1556

    +
    name_linkage_mismatch_for_variable:
    +
    name linkage conflicts with previous declaration of entity-kind +“entity” (declared at line xxxx)
    +
    +

    1557

    +
    alias_loop:
    +
    alias creates cycle of aliased entities
    +
    +

    1559

    +
    register_mapped_variable_cannot_have_initializer:
    +
    a variable with static storage duration allocated in a specific +register cannot be declared with an initializer
    +
    +

    1560

    +
    register_mapped_variable_must_be_POD:
    +
    a variable allocated in a specific register must be trivially copyable
    +
    +

    1561

    +
    predef_macro_redefined:
    +
    predefined meaning of “entity” discarded
    +
    +

    1563

    +
    designator_for_non_POD:
    +
    class type not suitable for use with designators
    +
    +

    1565

    +
    nonstandard_anonymous_union_qualifier:
    +
    anonymous union qualifier is nonstandard
    +
    +

    1566

    +
    anonymous_union_qualifier_ignored:
    +
    anonymous union qualifier is ignored
    +
    +

    1568

    +
    struct_declspec_ignored_in_C_mode:
    +
    __declspec(xxxx) ignored (it has no meaning for a C struct)
    +
    +

    1569

    +
    nonstandard_secondary_decl_specifiers:
    +
    specifiers after comma between declarations are nonstandard
    +
    +

    1570

    +
    secondary_specifier_ignored:
    +
    nonstandard specifier ignored
    +
    +

    1571

    +
    enum_attribute_ignored:
    +
    attributes are ignored on an enum declaration that is not also a +definition
    +
    +

    1572

    +
    reference_declared_mutable:
    +
    declaring a reference with “mutable” is nonstandard
    +
    +

    1573

    +
    array_condition_always_true:
    +
    a condition declaration for an array is always true
    +
    +

    1574

    +
    static_assert:
    +
    static assertion failed with “xxxx”
    +
    +

    1575

    +
    gnu_visibility_conflict:
    +
    visibility attribute ignored because it conflicts with a previous +declaration
    +
    +

    1576

    +
    pcc_field_ambiguity:
    +
    field name resolves to more than one offset – see “entity”(declared at line xxxx) and “entity” (declared at line +xxxx)
    +
    +

    1577

    +
    not_a_field_name:
    +
    “xxxx” is not a field name
    +
    +

    1578

    +
    case_label_conflict:
    +
    case label value has already appeared in this switch at line xxxx
    +
    +

    1579

    +
    member_cannot_have_internal_linkage:
    +
    a member function cannot have internal linkage
    +
    +

    1580

    +
    builtin_function_hidden:
    +
    declaration hides built-in entity-kind “entity”
    +
    +

    1581

    +
    builtin_function_overloaded:
    +
    declaration overloads built-in entity-kind “entity”
    +
    +

    1582

    +
    cl_list_macros_incompatible_with_multiple_trans_units:
    +
    the option to list macro definitions may not be specified when +compiling more than one translation unit
    +
    +

    1583

    +
    lparen_after_function:
    +
    unexpected parenthesis after declaration of entity-kind “entity”(malformed parameter list or invalid initializer?)
    +
    +

    1584

    +
    nonstandard_parenthesized_string_initializer:
    +
    parentheses around a string initializer are nonstandard
    +
    +

    1586

    +
    auto_variable_in_own_initializer:
    +
    a variable declared with an auto type specifier cannot appear in its +own initializer
    +
    +

    1587

    +
    cannot_deduce_auto_type:
    +
    cannot deduce “auto” type
    +
    +

    1588

    +
    auto_brace_initialization_not_allowed:
    +
    initialization with “{…}” is not allowed for “auto” type
    +
    +

    1589

    +
    auto_type_in_array_type:
    +
    “auto” type cannot appear in top-level array type
    +
    +

    1590

    +
    auto_type_in_function_type:
    +
    “auto” type cannot appear in top-level function type
    +
    +

    1591

    +
    invalid_member_constant_type:
    +
    a member of type “type” cannot have an in-class initializer
    +
    +

    1592

    +
    member_constant_not_const:
    +
    a member with an in-class initializer must be const
    +
    +

    1593

    +
    auto_type_requires_initializer:
    +
    cannot deduce “auto” type (initializer required)
    +
    +

    1594

    +
    inconsistent_deduction_of_auto:
    +
    “auto” type is “type” for this entity, but was previously implied +to be “type”
    +
    +

    1595

    +
    bad_constructor_decl:
    +
    invalid constructor declaration
    +
    +

    1596

    +
    bad_type_qualifier:
    +
    invalid use of a type qualifier
    +
    +

    1597

    +
    abstract_or_sealed_on_union:
    +
    a union cannot be abstract or sealed
    +
    +

    1598

    +
    auto_not_allowed_here:
    +
    “auto” is not allowed here
    +
    +

    1599

    +
    unfinished_base_class:
    +
    definition of base class type not completed yet
    +
    +

    1600

    +
    static_extern_template:
    +
    “extern template” cannot refer to a specialization of static +entity-kind “entity” (declared at line xxxx)
    +
    +

    1601

    +
    extern_template_follows_instantiation:
    +
    “extern template” cannot follow explicit instantiation of +entity-kind “entity”
    +
    +

    1602

    +
    bad_declspec_restrict_return:
    +
    __declspec(restrict) requires a function returning a pointer type
    +
    +

    1603

    +
    cl_report_gnu_extensions_requires_gnu_mode:
    +
    the “report_gnu_extensions” option is only valid in GNU C and GNU C++ +modes
    +
    +

    1604

    +
    vla_is_nonstandard:
    +
    variable-length array types are nonstandard
    +
    +

    1605

    +
    designator_is_nonstandard:
    +
    designators are nonstandard
    +
    +

    1606

    +
    extended_designator_is_gnu_extension:
    +
    this designator syntax is a GNU extension
    +
    +

    1607

    +
    compound_literal_is_nonstandard:
    +
    compound literals are nonstandard
    +
    +

    1608

    +
    statement_expression_is_gnu_extension:
    +
    statement expressions are a GNU extension
    +
    +

    1609

    +
    asm_name_after_definition:
    +
    asm name ignored for previously defined entity
    +
    +

    1610

    +
    attribute_is_gnu_extension:
    +
    attributes are a GNU extension
    +
    +

    1611

    +
    asm_operand_spec_is_gnu_extension:
    +
    extended asm syntax is a GNU feature
    +
    +

    1612

    +
    volatile_asm_is_gnu_extension:
    +
    volatile asm declarations are a GNU extension
    +
    +

    1613

    +
    asm_name_is_gnu_extension:
    +
    asm name specifiers are a GNU extension
    +
    +

    1614

    +
    gnu_restrict_is_nonstandard:
    +
    the “__restrict” qualifier is nonstandard
    +
    +

    1615

    +
    typeof_is_gnu_extension:
    +
    “typeof” is a GNU extension
    +
    +

    1616

    +
    typedef_modification_is_nonstandard:
    +
    modifying the size or signedness of a typedef is nonstandard
    +
    +

    1617

    +
    zero_length_array_is_gnu_extension:
    +
    zero-length arrays are a GNU extension
    +
    +

    1618

    +
    flexible_array_is_nonstandard:
    +
    flexible array members are nonstandard
    +
    +

    1619

    +
    nonnull_on_nonpointer:
    +
    attribute “nonnull” references nonpointer parameter
    +
    +

    1620

    +
    nonnull_parameter_number_too_large:
    +
    argument for attribute “nonnull” is larger than number of parameters
    +
    +

    1621

    +
    no_pointer_parameters:
    +
    no parameter has pointer type
    +
    +

    1622

    +
    null_argument_for_nonnull_parameter:
    +
    null argument provided for parameter marked with attribute “nonnull”
    +
    +

    1623

    +
    access_prevents_dtor_generation:
    +
    the destructor for “type” has been suppressed because the +destructor for “type” is inaccessible
    +
    +

    1624

    +
    suppressed_dtor_needed:
    +
    the suppressed destructor for “type” is needed
    +
    +

    1625

    +
    inline_gnu_noinline_conflict:
    +
    routine is both “inline” and “noinline”
    +
    +

    1626

    +
    invalid_cleanup_routine:
    +
    invalid cleanup routine
    +
    +

    1627

    +
    attribute_cleanup_requires_automatic_storage:
    +
    attribute “cleanup” requires automatic storage duration
    +
    +

    1628

    +
    attribute_cleanup_for_parameter:
    +
    attribute “cleanup” does not apply to parameters
    +
    +

    1629

    +
    bad_type_for_cleanup_routine:
    +
    cleanup routine has invalid type
    +
    +

    1630

    +
    nonstandard_conversion_for_cleanup:
    +
    call of cleanup routine requires suspect conversion
    +
    +

    1631

    +
    microsoft_ptr_signedness_must_follow_star:
    +
    __sptr and __uptr must follow a “*”
    +
    +

    1632

    +
    microsoft_ptr_signedness_conflict:
    +
    __sptr and __uptr cannot both be specified
    +
    +

    1633

    +
    microsoft_ptr_sign_extension:
    +
    widening pointer conversion from “type” to “type” extends +sign bit
    +
    +

    1634

    +
    microsoft_ptr_signedness_on_ptr_to_member:
    +
    __sptr and __uptr don’t apply to pointer-to-member types
    +
    +

    1635

    +
    const_mbr_suppresses_copy_asgn_decl:
    +
    the declaration of the copy assignment operator for “type” has +been suppressed because entity-kind “entity” is const
    +
    +

    1636

    +
    ref_mbr_suppresses_copy_asgn_decl:
    +
    the declaration of the copy assignment operator for “type” has +been suppressed because entity-kind “entity” has reference type
    +
    +

    1637

    +
    subobj_copy_asgn_decl_suppressed:
    +
    the declaration of the copy assignment operator for “type” has +been suppressed because that of “type” was suppressed
    +
    +

    1638

    +
    ambig_suppresses_copy_asgn_decl:
    +
    the declaration of the copy assignment operator for “type” has +been suppressed because that of “type” is ambiguous
    +
    +

    1639

    +
    access_suppresses_copy_asgn_decl:
    +
    the declaration of the copy assignment operator for “type” has +been suppressed because that of “type” is inaccessible
    +
    +

    1640

    +
    subobj_copy_ctor_decl_suppressed:
    +
    the declaration of the copy constructor for “type” has been +suppressed because that of “type” was suppressed
    +
    +

    1641

    +
    ambig_suppresses_copy_ctor_decl:
    +
    the declaration of the copy constructor for “type” has been +suppressed because that of “type” is ambiguous
    +
    +

    1642

    +
    access_suppresses_copy_ctor_decl:
    +
    the declaration of the copy constructor for “type” has been +suppressed because that of “type” is inaccessible
    +
    +

    1643

    +
    inaccessible_dtor_not_invoked:
    +
    the destructor for “type” will not be called because it is +inaccessible and the destructor for “type” was suppressed
    +
    +

    1644

    +
    file_ends_with_unterminated_type_definition:
    +
    definition at end of file not followed by a semicolon or a declarator
    +
    +

    1645

    +
    bad_type_for_gnu_sync_function:
    +
    first argument must be a pointer to integer or enum type
    +
    +

    1646

    +
    invalid_gnu_sync_size:
    +
    synchronized operations are valid only on objects of size 1, 2, 4, or +8
    +
    +

    1647

    +
    extra_arguments_ignored:
    +
    extra arguments ignored
    +
    +

    1648

    +
    equals_assumed_in_cmd_line_macro_def:
    +
    ‘=’ assumed following macro name “xxxx” in command-line definition
    +
    +

    1649

    +
    white_space_required_after_macro_name:
    +
    white space is required between the macro name “xxxx” and its +replacement text
    +
    +

    1650

    +
    call_result_should_be_used:
    +
    result of call is not used
    +
    +

    1651

    +
    warn_unused_result_with_void_return:
    +
    attribute “warn_unused_result” is ignored for void return type
    +
    +

    1653

    +
    dll_interface_ignored_on_qualified_declaration:
    +
    dllimport/dllexport is ignored on redeclaration using a qualified name
    +
    +

    1654

    +
    leading_character_ignored_in_char_literal:
    +
    too many characters in character literal – extra leading characters +ignored
    +
    +

    1655

    +
    first_inline_after_definition:
    +
    entity-kind “entity” cannot be declared inline after its +definition at line xxxx
    +
    +

    1658

    +
    type_with_no_linkage_in_template_arg:
    +
    a template argument may not reference a type with no name linkage
    +
    +

    1659

    +
    virtual_ignored:
    +
    “virtual” is ignored here
    +
    +

    1660

    +
    vla_type_in_template_arg:
    +
    a template argument may not reference a variable-length array type
    +
    +

    1661

    +
    UCN_names_surrogate_code_point:
    +
    a universal character name cannot designate a surrogate code point
    +
    +

    1662

    +
    include_next_in_primary_source_file:
    +
    #include_next cannot be used in the primary source file
    +
    +

    1663

    +
    bad_template_member_definition:
    +
    “entity” cannot be specified in a template member definition – +“entity” assumed instead
    +
    +

    1664

    +
    local_function_attribute_ignored:
    +
    attribute “xxxx” is ignored on local function declaration
    +
    +

    1665

    +
    concat_yields_invalid_token:
    +
    concatenation with “xxxx” in entity-kind “entity” does not +create a valid token
    +
    +

    1666

    +
    ambiguous_injected_template_name:
    +
    “entity” is ambiguous (entity-kind “entity” assumed)
    +
    +

    1667

    +
    function_qualifier_on_static_member:
    +
    a type qualifier is not allowed on a static member function
    +
    +

    1668

    +
    function_qualifier_on_ctor_or_dtor:
    +
    a type qualifier is not allowed on a constructor or destructor
    +
    +

    1669

    +
    function_qualifier_on_new_or_delete:
    +
    a type qualifier is not allowed on operator new or operator delete
    +
    +

    1670

    +
    function_qualifier_on_nonmember:
    +
    a type qualifier is not allowed on a nonmember function
    +
    +

    1671

    +
    assume_expression_discarded:
    +
    argument to xxxx has side-effects but is unevaluated
    +
    +

    1672

    +
    cl_unrecognized_unicode_source_kind:
    +
    unrecognized Unicode source kind (must be one of UTF-8, UTF-16, +UTF-16LE, UTF-16BE): xxxx
    +
    +

    1673

    +
    bad_unicode_char_in_pp_output:
    +
    Unicode character with hex value xxxx not representable in +preprocessing output
    +
    +

    1674

    +
    ctor_dtor_priority_reserved:
    +
    requested constructor/destructor priority is reserved for internal use
    +
    +

    1675

    +
    unrecognized_gcc_pragma:
    +
    unrecognized GCC pragma
    +
    +

    1676

    +
    unrecognized_gcc_visibility_pragma:
    +
    unrecognized GCC visibility pragma directive
    +
    +

    1677

    +
    unrecognized_visibility:
    +
    unrecognized visibility kind
    +
    +

    1678

    +
    ELF_visibility_pop_mismatch:
    +
    visibility pragma was still active
    +
    +

    1679

    +
    ELF_visibility_stack_empty:
    +
    no matching visibility push
    +
    +

    1680

    +
    typeid_of_incomplete_type:
    +
    typeid of incomplete type
    +
    +

    1682

    +
    array_size_one_assumed:
    +
    array entity-kind “entity” assumed to have one element
    +
    +

    1683

    +
    vector_size_attribute_requires_integral_floating_or_enum_type:
    +
    vector_size attribute requires an arithmetic or enum type
    +
    +

    1684

    +
    vector_size_too_large:
    +
    vector size is too large
    +
    +

    1685

    +
    vector_size_must_be_power_of_two:
    +
    the number of elements in a vector must be a power of two
    +
    +

    1686

    +
    vector_size_must_be_multiple_of_element_size:
    +
    vector size must be a multiple of the element size
    +
    +

    1687

    +
    mixed_vector_scalar_operation:
    +
    mixed vector-scalar operation not allowed
    +
    +

    1688

    +
    vectors_must_have_same_size:
    +
    operation requires two vectors of the same size
    +
    +

    1689

    +
    dependent_vector_size:
    +
    template-dependent vector size is not allowed
    +
    +

    1692

    +
    vector_size_attribute_on_complex_type:
    +
    vector_size attribute is not allowed with a complex element type
    +
    +

    1694

    +
    vector_element_type_mismatch:
    +
    vector operation requires identical element types
    +
    +

    1695

    +
    vector_operation_requires_integer_vector:
    +
    vector operation does not apply to vector with non-integral type
    +
    +

    1696

    +
    cannot_open_file:
    +
    cannot open xxxx file “xxxx”
    +
    +

    1697

    +
    cannot_open_file_reason:
    +
    cannot open xxxx file “xxxx”: xxxx
    +
    +

    1703

    +
    file_write_error_errno:
    +
    error while writing xxxx file: xxxx
    +
    +

    1712

    +
    il_output:
    +
    IL output
    +
    +

    1713

    +
    restrict_qualifier_dropped:
    +
    conversion drops “__restrict” qualifier
    +
    +

    1714

    +
    unable_to_get_mapped_memory_reason:
    +
    unable to obtain mapped memory for “xxxx”: xxxx
    +
    +

    1715

    +
    restrict_qualifier_ignored:
    +
    restrict qualifier is ignored
    +
    +

    1717

    +
    nonstandard_array_with_flexible_array_element:
    +
    array of elements containing a flexible array member is nonstandard
    +
    +

    1718

    +
    vector_template_parameter:
    +
    a template parameter may not have a vector type
    +
    +

    1719

    +
    out_of_order_ctor_init:
    +
    the initialization of entity-kind “entity” will be done before +that of entity-kind “entity”
    +
    +

    1721

    +
    inheritance_kind_ignored_on_enum:
    +
    inheritance kind is ignored on an enum specifier
    +
    +

    1723

    +
    extended_modifier_ignored_on_enum:
    +
    modifier is ignored on an enum specifier
    +
    +

    1724

    +
    non_unicode_char_in_ident:
    +
    identifier character cannot be represented in Unicode
    +
    +

    1725

    +
    non_unicode_char_in_header:
    +
    header name contains characters that cannot be represented in Unicode
    +
    +

    1726

    +
    invalid_locale:
    +
    “xxxx” is not a valid locale name
    +
    +

    1727

    +
    nonstd_template_void_param_list:
    +
    declaring a void parameter list with a template parameter is +nonstandard
    +
    +

    1728

    +
    cl_lambdas_option_only_in_cplusplus:
    +
    lambdas option can be used only when compiling C++
    +
    +

    1729

    +
    capture_mode_matches_default:
    +
    explicit capture matches default
    +
    +

    1730

    +
    not_a_variable:
    +
    entity-kind “entity” is not a variable
    +
    +

    1731

    +
    capture_of_static_duration_variable:
    +
    a variable with static storage duration cannot be captured in a lambda
    +
    +

    1732

    +
    cannot_capture_this_by_reference:
    +
    “this” cannot be captured by reference
    +
    +

    1733

    +
    this_in_lambda:
    +
    “this” cannot be used inside the body of this lambda
    +
    +

    1734

    +
    anon_union_ref_in_lambda:
    +
    a member of an outer-scope anonymous union cannot be referenced +inside the body of a lambda
    +
    +

    1735

    +
    not_captured_local_var_in_lambda:
    +
    an enclosing-function local variable cannot be referenced in a lambda +body unless it is in the capture list
    +
    +

    1736

    +
    bad_local_var_in_lambda:
    +
    invalid reference to an outer-scope local variable in a lambda body
    +
    +

    1737

    +
    captured_local_var_not_in_innermost_function:
    +
    a local variable outside the current function scope cannot be captured
    +
    +

    1738

    +
    not_captured_this_in_lambda:
    +
    the enclosing-function “this” cannot be referenced in a lambda body +unless it is in the capture list
    +
    +

    1740

    +
    captured_var_type_not_copyable:
    +
    lambda captured variable of type “type” cannot be copied to +closure class field of type “type”
    +
    +

    1741

    +
    cl_invalid_template_directory:
    +
    invalid template directory: xxxx
    +
    +

    1749

    +
    enum_value_out_of_underlying_range:
    +
    enumeration value is outside the range of its underlying type +(“type”)
    +
    +

    1750

    +
    not_a_line_splice:
    +
    “" followed by white space is not a line splice
    +
    +

    1751

    +
    dynamic_cast_without_rtti:
    +
    this dynamic_cast cannot be done without runtime type information, +which is disabled
    +
    +

    1752

    +
    ambiguous_cast_selects_direct_base:
    +
    conversion to “type” is ambiguous; direct base selected
    +
    +

    1753

    +
    requested_size_too_large:
    +
    an internal buffer would be too large
    +
    +

    1754

    +
    exception_handler_used:
    +
    C++ exception handler used, but exception handling semantics have not +been specified
    +
    +

    1755

    +
    type_qualifier_ignored_on_constructor:
    +
    type qualifier ignored on constructor
    +
    +

    1756

    +
    lambda_capture_involves_variable_length_array:
    +
    a variable captured by a lambda cannot have a type involving a +variable-length array
    +
    +

    1757

    +
    incompatible_vectors_conversion:
    +
    conversion between incompatible vector types
    +
    +

    1758

    +
    missing_lambda_body:
    +
    expected a “{” introducing a lambda body
    +
    +

    1759

    +
    cl_rvalue_references_option_only_in_cplusplus:
    +
    rvalue references option can be used only when compiling C++
    +
    +

    1760

    +
    type_qualifier_on_lambda:
    +
    a type qualifier is not allowed on a lambda
    +
    +

    1761

    +
    more_than_one_capture:
    +
    a name cannot appear more than once in a capture-list
    +
    +

    1762

    +
    explicit_template_args_ignored:
    +
    explicit template arguments ignored
    +
    +

    1763

    +
    bad_constant_lambda:
    +
    a lambda is not allowed in a constant expression
    +
    +

    1764

    +
    class_type_required:
    +
    “type” is not a class type
    +
    +

    1765

    +
    delete_of_array_type:
    +
    “delete” applied to a pointer-to-array type treated as delete[]
    +
    +

    1766

    +
    delete_of_array_type_nonstandard:
    +
    “delete” applied to a pointer-to-array type is nonstandard; treated +as delete[]
    +
    +

    1767

    +
    function_does_not_match_arguments:
    +
    entity-kind “entity” cannot be called with the given argument list
    +
    +

    1768

    +
    rvalue_reference_bound_to_lvalue:
    +
    an rvalue reference cannot be bound to an lvalue
    +
    +

    1769

    +
    rvalue_ref_template_parameter:
    +
    a nontype template parameter cannot have rvalue reference type
    +
    +

    1770

    +
    type_qualifiers_ignored_on_reference:
    +
    type qualifiers are ignored (underlying type is a reference)
    +
    +

    1771

    +
    decl_with_local_type_but_not_defined:
    +
    entity-kind “entity”, declared using a local type, must be +defined in this translation unit
    +
    +

    1772

    +
    decl_with_no_linkage_type_but_not_defined:
    +
    entity-kind “entity”, declared using a type with no linkage, must +be defined in this translation unit
    +
    +

    1773

    +
    bad_rvalue_ref_dynamic_cast_operand:
    +
    the operand of an rvalue reference dynamic_cast must have a complete +class type
    +
    +

    1774

    +
    invalid_function_to_be_defaulted:
    +
    “= default” can only appear on default constructors, copy/move +constructors, copy/move assignment operators, and destructors
    +
    +

    1775

    +
    deleted_function_definition_must_be_first_declaration:
    +
    “= delete” can only appear on the first declaration of a function
    +
    +

    1776

    +
    deleted_function:
    +
    entity-kind “entity” (declared at line xxxx) cannot be +referenced – it is a deleted function
    +
    +

    1777

    +
    bad_unevaluated_lambda:
    +
    a lambda is not allowed in an unevaluated expression
    +
    +

    1778

    +
    bad_function_for_gnu_va_arg_pack:
    +
    __builtin_va_arg_pack/__builtin_va_arg_pack_len can appear only in +an inline function with an ellipsis parameter
    +
    +

    1779

    +
    function_defaulted_in_friend_decl:
    +
    “= default” cannot be specified on a friend declaration
    +
    +

    1780

    +
    exp_cpp_keyword:
    +
    expected a C++ keyword
    +
    +

    1782

    +
    nonconstant_offsetof:
    +
    offset is not constant
    +
    +

    1783

    +
    unrecognized_microsoft_comment_pragma_type:
    +
    unrecognized #pragma comment type “xxxx”
    +
    +

    1784

    +
    cl_auto_type_option_only_in_cplusplus:
    +
    option to control whether “auto” is a type specifier can be used only +when compiling C++
    +
    +

    1785

    +
    cl_auto_storage_option_only_in_cplusplus:
    +
    option to control whether “auto” is a storage class can be used only +when compiling C++
    +
    +

    1786

    +
    cl_auto_cannot_be_disabled:
    +
    the type specifier and storage class specifier meanings of “auto” +cannot both be disabled
    +
    +

    1787

    +
    bad_pragma_comment_string:
    +
    invalid string in #pragma comment
    +
    +

    1788

    +
    deleted_function_overrides_nondeleted_function:
    +
    deleted function overrides nondeleted entity-kind “entity”
    +
    +

    1789

    +
    nondeleted_function_overrides_deleted_function:
    +
    nondeleted function overrides deleted entity-kind “entity”
    +
    +

    1790

    +
    deleted_default_constructor:
    +
    the default constructor of “type” cannot be referenced – it is a +deleted function
    +
    +

    1791

    +
    rvalue_reference_catch_type:
    +
    an rvalue reference is not allowed as a catch type
    +
    +

    1792

    +
    default_args_incompatible:
    +
    default arguments of entity-kind “entity” is incompatible with a +declaration in another translation unit
    +
    +

    1793

    +
    default_arg_differs_in_other_trans_unit:
    +
    default arguments of entity-kind “entity” were different during +compilation of “xxxx”
    +
    +

    1795

    +
    initializers_incompatible:
    +
    initializer for entity-kind “entity” is different in another +translation unit
    +
    +

    1796

    +
    initializer_differs_in_other_trans_unit:
    +
    initializer for entity-kind “entity” was different during +compilation of “xxxx”
    +
    +

    1797

    +
    designator_for_template_dependent_type:
    +
    a designator into a template-dependent type is not allowed
    +
    +

    1798

    +
    invalid_pragma_conform_kind:
    +
    unrecognized conformance kind
    +
    +

    1799

    +
    exp_on_or_off:
    +
    expected “on” or “off”
    +
    +

    1800

    +
    forScope_stack_empty:
    +
    #pragma conform(forScope) stack is empty
    +
    +

    1801

    +
    no_matching_forScope_stack_entry:
    +
    no previous #pragma conform(forScope) entry matches “xxxx”
    +
    +

    1802

    +
    show_pragma_conform_forScope_is_nonstandard:
    +
    forScope behavior is nonstandard
    +
    +

    1803

    +
    show_pragma_conform_forScope_is_standard:
    +
    forScope behavior is standard
    +
    +

    1804

    +
    deleted_main:
    +
    function “main” cannot be deleted
    +
    +

    1805

    +
    useless_type_qualifiers_in_type_name:
    +
    type qualifiers are meaningless here
    +
    +

    1806

    +
    invalid_assignment_operator_to_be_defaulted:
    +
    invalid type for defaulted assignment operator
    +
    +

    1807

    +
    function_template_cannot_be_defaulted:
    +
    function templates cannot be defaulted
    +
    +

    1808

    +
    invalid_constructor_to_be_defaulted:
    +
    invalid type for defaulted constructor
    +
    +

    1809

    +
    call_requires_one_argument:
    +
    function call requires one argument
    +
    +

    1810

    +
    call_requires_floating_point_argument:
    +
    function call requires a real floating-point argument
    +
    +

    1811

    +
    copy_ctor_with_default_arg_cannot_be_defaulted:
    +
    a copy constructor with a default argument cannot be defaulted
    +
    +

    1812

    +
    predeclared_function_cannot_be_deleted:
    +
    a predeclared function cannot be deleted
    +
    +

    1813

    +
    empty_then_statement:
    +
    empty dependent statement in if-statement
    +
    +

    1814

    +
    empty_else_statement:
    +
    empty dependent statement in “else” clause of if-statement
    +
    +

    1815

    +
    deleted_elided_cctor:
    +
    entity-kind “entity” (declared at line xxxx), required for +copy that was eliminated, cannot be referenced – it is a deleted +function
    +
    +

    1816

    +
    main_first_param_not_int:
    +
    nonstandard first parameter “type” of “main”, expected “int”
    +
    +

    1817

    +
    main_wrong_num_params:
    +
    nonstandard number of parameters for “main”, expected zero or two +parameters
    +
    +

    1818

    +
    main_second_param_wrong_type:
    +
    nonstandard second parameter “type” of “main”, expected “char +*[]” or “char **”
    +
    +

    1819

    +
    incl_dir_both_sys_and_nonsys:
    +
    “xxxx” was specified as both a system and non-system include +directory – the non-system entry will be ignored
    +
    +

    1820

    +
    cl_rvalue_ctor_is_copy_ctor_option_only_in_cplusplus:
    +
    option to control move constructors and move assignment operators can +be used only when compiling C++
    +
    +

    1823

    +
    trailing_return_type_requires_auto:
    +
    a trailing return type requires the “auto” type specifier
    +
    +

    1824

    +
    trailing_return_type_in_nested_declarator:
    +
    a trailing return type cannot appear in a nested declarator
    +
    +

    1825

    +
    trailing_return_type_function_without_simple_auto:
    +
    a function declarator with a trailing return type must be preceded by +a simple “auto” type specifier
    +
    +

    1826

    +
    missing_trailing_return_type:
    +
    “auto” function requires a trailing return type
    +
    +

    1827

    +
    pure_virtual_member_template:
    +
    a member template cannot have a pure specifier
    +
    +

    1828

    +
    excess_characters_in_literal_ignored:
    +
    string literal too long – excess characters ignored
    +
    +

    1830

    +
    nullptr_conv_to_bool:
    +
    std::nullptr_t converted to bool
    +
    +

    1833

    +
    invalid_empty_attribute_arg_list:
    +
    attribute “xxxx” does not allow an empty argument list
    +
    +

    1834

    +
    attr_twice_in_group:
    +
    attribute appears more than once
    +
    +

    1835

    +
    wrong_entity_for_attribute:
    +
    attribute “xxxx” does not apply here
    +
    +

    1836

    +
    attr_disallows_bit_field:
    +
    attribute “xxxx” does not apply to bit fields
    +
    +

    1837

    +
    attr_requires_bit_field:
    +
    attribute “xxxx” requires a bit field
    +
    +

    1838

    +
    attr_disallows_member_function:
    +
    attribute “xxxx” does not apply to member functions
    +
    +

    1839

    +
    attr_requires_member_function:
    +
    attribute “xxxx” requires a member function
    +
    +

    1840

    +
    attr_disallows_virtual_function:
    +
    attribute “xxxx” does not apply to virtual functions
    +
    +

    1841

    +
    attr_requires_virtual_function:
    +
    attribute “xxxx” requires a virtual function
    +
    +

    1842

    +
    attr_disallows_pure_virtual_function:
    +
    attribute “xxxx” does not apply to pure virtual functions
    +
    +

    1843

    +
    attr_requires_pure_virtual_function:
    +
    attribute “xxxx” requires a pure virtual function
    +
    +

    1844

    +
    attr_disallows_register_storage:
    +
    attribute “xxxx” does not apply to register variables
    +
    +

    1845

    +
    attr_requires_register_storage:
    +
    attribute “xxxx” requires a register variable
    +
    +

    1846

    +
    attr_must_also_appear_in_first_declaration:
    +
    attribute “xxxx” did not appear on original declaration
    +
    +

    1847

    +
    invalid_attribute_location:
    +
    attributes are not allowed here
    +
    +

    1848

    +
    attr_must_appear_in_class_definition:
    +
    attribute “xxxx” must appear in a class definition
    +
    +

    1849

    +
    pure_final_virtual:
    +
    “final” applied to a pure virtual function
    +
    +

    1850

    +
    override_of_final_function:
    +
    cannot override “final” entity-kind “entity” (declared at line +xxxx)
    +
    +

    1851

    +
    undefined_static_function_treated_as_extern:
    +
    static entity-kind “entity” treated as extern because it was +referenced but not defined
    +
    +

    1852

    +
    cl_gnu_c89_inlining_option_only_in_C:
    +
    option to enable GNU-C89-style inlining can be used only when +compiling C
    +
    +

    1853

    +
    first_decl_not_gnu_inline:
    +
    function was previously declared without the “gnu_inline” attribute
    +
    +

    1854

    +
    gnu_inline_requires_inline:
    +
    the “gnu_inline” attribute is ignored on non-inline functions
    +
    +

    1855

    +
    carries_dependency_not_on_first_decl:
    +
    entity-kind “entity” previously declared without the +carries_dependency attribute
    +
    +

    1856

    +
    bad_array_member_initialization:
    +
    invalid initializer for array entity-kind “entity”
    +
    +

    1857

    +
    cl_must_specify_cpp11_mode:
    +
    must specify C++11 or C++14 mode when building runtime library
    +
    +

    1858

    +
    attr_disallows_function_type:
    +
    attribute “xxxx” does not apply to function types
    +
    +

    1859

    +
    attr_requires_function_type:
    +
    attribute “xxxx” requires a function type
    +
    +

    1860

    +
    attribute_ignored_on_nonstatic_member_function:
    +
    attribute “xxxx” does not apply to nonstatic member functions
    +
    +

    1861

    +
    attr_disallows_automatic_storage:
    +
    attribute “xxxx” does not apply to automatic variables
    +
    +

    1862

    +
    attr_requires_automatic_storage:
    +
    attribute “xxxx” requires an automatic variable
    +
    +

    1863

    +
    attr_disallows_external_linkage:
    +
    attribute “xxxx” does not apply to a variable or function with +external linkage
    +
    +

    1864

    +
    attr_requires_local_variable:
    +
    attribute “xxxx” requires a local variable
    +
    +

    1865

    +
    attributes_ignored:
    +
    attributes ignored here
    +
    +

    1866

    +
    unattached_attribute:
    +
    attribute does not apply to any entity
    +
    +

    1867

    +
    bad_attribute_template_substitution:
    +
    bad attribute argument substitution
    +
    +

    1868

    +
    bad_tls_model_attr_arg:
    +
    the argument of the “tls_model” attribute must be “global-dynamic”, +“local-dynamic”, “initial-exec”, or “local-exec”
    +
    +

    1869

    +
    inconsistent_tls_model_attr_arg:
    +
    the declaration at line xxxx specified a different “tls_model” +argument
    +
    +

    1870

    +
    attr_disallows_inline:
    +
    attribute “xxxx” does not apply to inline functions
    +
    +

    1871

    +
    attr_requires_inline:
    +
    attribute “xxxx” requires a inline function
    +
    +

    1872

    +
    include_kind_mismatch:
    +
    both file names in an include_alias pragma must use the same +delimiter characters
    +
    +

    1873

    +
    signed_unsigned_comparison:
    +
    comparison between signed and unsigned operands
    +
    +

    1874

    +
    attribute_ignored_on_unnamed_type:
    +
    attribute “xxxx” ignored on unnamed type
    +
    +

    1875

    +
    attribute_ignored_on_nondefinition:
    +
    attribute “xxxx” ignored because no definition follows
    +
    +

    1876

    +
    incompatible_thread_locality:
    +
    thread locality is incompatible with a previous declaration of +entity-kind “entity” (declared at line xxxx)
    +
    +

    1877

    +
    no_implicit_capture_on_enclosing_lambda:
    +
    this enclosing-function local variable cannot be referenced in this +lambda body because an enclosing lambda does not allow implicit +captures
    +
    +

    1878

    +
    unbalanced_attribute_argument:
    +
    this attribute argument contains unmatched parentheses, brackets, or +braces
    +
    +

    1879

    +
    invalid_builtin_fpclassify_args:
    +
    a call to __builtin_fpclassify requires five integral arguments +followed by one floating-point argument
    +
    +

    1880

    +
    bad_final_builtin_fpclassify_arg:
    +
    the last argument in a call to __builtin_fpclassify must have a real +floating-point type
    +
    +

    1881

    +
    invalid_alignment_reducing_attr:
    +
    alignment cannot be set to less than the default alignment
    +
    +

    1882

    +
    attribute_on_explicit_instantiation:
    +
    attributes are not allowed on explicit instantiations
    +
    +

    1883

    +
    attr_disallows_definition:
    +
    attribute “xxxx” does not apply to a definition
    +
    +

    1884

    +
    attr_requires_definition:
    +
    attribute “xxxx” requires a definition
    +
    +

    1885

    +
    friend_attribute_requires_definition:
    +
    standard attributes cannot appear on friend declarations that are not +definitions
    +
    +

    1886

    +
    inconsistent_alignment:
    +
    specified alignment (xxxx) is different from alignment (xxxx) +specified on a previous declaration
    +
    +

    1887

    +
    variable_align_attr_not_on_definition:
    +
    alignment attribute must also appear on definition at line xxxx
    +
    +

    1888

    +
    alias_used_in_type:
    +
    entity-kind “entity” may not be used in the type-id of the +alias-declaration
    +
    +

    1890

    +
    transparent_union_cannot_have_floating_first_field:
    +
    “type” cannot be transparent because its first field has a +floating-point type
    +
    +

    1891

    +
    transparent_union_cannot_have_bit_field_first:
    +
    “type” cannot be transparent because its first field is a bit +field
    +
    +

    1892

    +
    missing_override_attr_in_base_check_class:
    +
    virtual function of a “base_check” class overrides a base class +member but lacks the “override” attribute
    +
    +

    1893

    +
    hiding_attr_on_nonhiding_member:
    +
    “hiding” attribute specified on a declaration that does not hide a +base class declaration
    +
    +

    1894

    +
    hiding_attr_on_unhidden_member:
    +
    “hiding” attribute specified on a declaration referred to by the +using-declaration at line xxxx
    +
    +

    1895

    +
    hiding_attr_required:
    +
    attribute “hiding” is required on a declaration (in a “base_check” +class) that hides entity-kind “entity” (declared at line xxxx)
    +
    +

    1896

    +
    undefined_decl_using_local_type:
    +
    entity-kind “entity” is not defined in this translation unit but +depends on a local type
    +
    +

    1897

    +
    undefined_decl_using_no_linkage_type:
    +
    entity-kind “entity” is not defined in this translation unit but +depends on a type with no linkage
    +
    +

    1898

    +
    missing_attribute_in_other_translation_unit:
    +
    attribute “xxxx” is missing in another translation unit
    +
    +

    1899

    +
    conflicting_attribute_in_other_translation_unit:
    +
    attribute “xxxx” conflicts with another translation unit
    +
    +

    1900

    +
    cl_nonstd_gnu_keywords_requires_gnu_mode:
    +
    the “nonstd_gnu_keywords” option is only valid in GNU C and GNU C++ +modes
    +
    +

    1901

    +
    const_var_in_C_const_expr:
    +
    use of a const variable in a constant expression is nonstandard in C
    +
    +

    1902

    +
    cannot_init_auto_flexible_array_member:
    +
    an initializer cannot be specified for a flexible array member with +automatic storage duration
    +
    +

    1904

    +
    final_base_class:
    +
    a “final” class type cannot be used as a base class
    +
    +

    1905

    +
    export_removed:
    +
    exported templates are no longer in the standard C++ language
    +
    +

    1906

    +
    template_dependent_designator:
    +
    a template-dependent designator is not allowed
    +
    +

    1907

    +
    offsetof_ref_field:
    +
    second operand of offsetof may not be a field with reference type
    +
    +

    1908

    +
    cl_long_lifetime_temps_incompat_with_newer_features:
    +
    long lifetime temporaries are incompatible with other requested newer +language features
    +
    +

    1909

    +
    wide_deprecation_string:
    +
    wide character string literal will not be quoted in diagnostics
    +
    +

    1910

    +
    missing_attribute_arguments:
    +
    missing arguments for attribute “xxxx”
    +
    +

    1911

    +
    sfinae_requires_newer_abi_version:
    +
    options “c++11” and “c++11_sfinae” require a different compiler +configuration
    +
    +

    1912

    +
    template_param_pack_not_at_end:
    +
    template parameter pack not at end of parameter list
    +
    +

    1913

    +
    parameter_pack_decl_not_allowed:
    +
    a parameter pack declaration is not allowed here
    +
    +

    1914

    +
    param_pack_cannot_have_default:
    +
    a parameter pack cannot have a default
    +
    +

    1915

    +
    cl_cppcli_only_in_microsoft_cplusplus:
    +
    C++/CLI can be enabled only in Microsoft C++ mode
    +
    +

    1916

    +
    reserved_enumerator_name:
    +
    “value__” cannot be used as the name of an enumerator constant (it +is a reserved name in this context)
    +
    +

    1917

    +
    cppcli_enumerator_requires_explicit_value:
    +
    an explicit enumerator value is required in an enum type with boolean +underlying type
    +
    +

    1919

    +
    pack_not_expanded:
    +
    parameter pack “xxxx” was referenced but not expanded
    +
    +

    1920

    +
    expansion_contains_no_packs:
    +
    pack expansion does not make use of any argument packs
    +
    +

    1921

    +
    pack_length_mismatch:
    +
    pack “xxxx” does not have the same number of elements as +“xxxx”
    +
    +

    1923

    +
    vector_size_attribute_on_enum_type:
    +
    vector_size attribute is not allowed with an enum type
    +
    +

    1924

    +
    virtual_static_property:
    +
    a property cannot be both static and virtual
    +
    +

    1925

    +
    trivial_indexed_property:
    +
    an indexed property cannot be trivial
    +
    +

    1926

    +
    invalid_property_accessor_decl:
    +
    this declaration cannot appear in a property definition
    +
    +

    1927

    +
    qualified_cli_accessor:
    +
    a qualified function type cannot be used to declare an accessor +function
    +
    +

    1928

    +
    ellipsis_cli_accessor:
    +
    an accessor function cannot have an ellipsis parameter
    +
    +

    1929

    +
    property_get_already_declared:
    +
    a “get” accessor was already declared for this property at line +xxxx
    +
    +

    1930

    +
    property_set_already_declared:
    +
    a “set” accessor was already declared for this property at line +xxxx
    +
    +

    1931

    +
    property_get_cannot_have_parameter:
    +
    a “get” accessor cannot have a parameter
    +
    +

    1932

    +
    bad_property_get_return:
    +
    return type of “get” accessor does not match property type
    +
    +

    1933

    +
    bad_property_set_return:
    +
    return type of “set” accessor must be void
    +
    +

    1934

    +
    empty_property_indices:
    +
    a property cannot declare an empty list of indices
    +
    +

    1935

    +
    void_property_index_type:
    +
    a property index cannot have type void
    +
    +

    1936

    +
    property_set_index_type_mismatch:
    +
    index type does not match the corresponding parameter in the “set” +accessor
    +
    +

    1937

    +
    property_get_index_type_mismatch:
    +
    index type does not match the corresponding parameter in the “get” +accessor
    +
    +

    1938

    +
    property_set_index_type_missing:
    +
    index type is missing in the “set” accessor
    +
    +

    1939

    +
    property_get_index_type_missing:
    +
    index type is missing in the “get” accessor
    +
    +

    1940

    +
    property_set_missing_value_parameter:
    +
    “set” accessor is missing its value parameter
    +
    +

    1941

    +
    extra_property_accessor_parameters:
    +
    accessor function has too many parameters
    +
    +

    1942

    +
    property_set_value_parameter_mismatch:
    +
    the last parameter of the “set” accessor does not match the property +type
    +
    +

    1943

    +
    cppcli_not_enabled:
    +
    “xxxx” requires C++/CLI mode
    +
    +

    1944

    +
    win32_api_error:
    +
    error in Win32 API “xxxx“: xxxx
    +
    +

    1945

    +
    using_not_at_file_scope:
    +
    #using may only be used at global scope
    +
    +

    1947

    +
    member_name_reserved_by_property:
    +
    member name “xxxx” is reserved by entity-kind “entity”(declared at line xxxx)
    +
    +

    1948

    +
    exp_lbracket:
    +
    expected a “[”
    +
    +

    1949

    +
    cl_microsoft_version_insufficient_for_cppcli:
    +
    C++/CLI mode requires microsoft_version >= 1600
    +
    +

    1950

    +
    static_default_indexed_property:
    +
    a default-indexed property cannot be static
    +
    +

    1951

    +
    virtual_static_property_accessor:
    +
    a property accessor cannot be both static and virtual
    +
    +

    1952

    +
    visibility_specifier_on_nested_type:
    +
    a top-level visibility specifier cannot appear on a nested type +declaration
    +
    +

    1953

    +
    visibility_specifier_requires_definition:
    +
    a top-level visibility specifier requires a type definition
    +
    +

    1954

    +
    trivial_reference_property:
    +
    a trivial property cannot have a reference type
    +
    +

    1955

    +
    trivial_const_or_volatile_property:
    +
    a trivial property cannot have a const or volatile type
    +
    +

    1956

    +
    incompatible_enum_kinds:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared as a different kind of enum type
    +
    +

    1957

    +
    lambda_captures_managed_class_type:
    +
    a variable captured by a lambda cannot have a managed class type
    +
    +

    1958

    +
    covariant_override_in_managed_class:
    +
    virtual function overriding with a covariant return type is not +allowed in a managed class
    +
    +

    1959

    +
    array_of_handle:
    +
    array of handles is not allowed
    +
    +

    1960

    +
    handle_to_array:
    +
    handle to array is not allowed
    +
    +

    1961

    +
    handle_to_function:
    +
    handle to function is not allowed
    +
    +

    1962

    +
    handle_to_void:
    +
    handle to void is not allowed
    +
    +

    1963

    +
    handle_to_address_type:
    +
    handle to handle, pointer, or reference is not allowed
    +
    +

    1964

    +
    tracking_reference_to_function:
    +
    tracking reference to function is not allowed
    +
    +

    1966

    +
    field_cannot_be_tracking_reference:
    +
    a field cannot be a tracking reference
    +
    +

    1967

    +
    invalid_ref_tracking_ref_combination:
    +
    a tracking reference cannot be combined with an ordinary reference in +this way
    +
    +

    1968

    +
    static_storage_variable_with_ref_class_type:
    +
    a variable with static storage duration cannot have a ref class type
    +
    +

    1969

    +
    unnamed_cli_managed_class_type:
    +
    a managed class cannot be unnamed
    +
    +

    1970

    +
    local_cli_managed_class_type:
    +
    a managed class cannot be local
    +
    +

    1971

    +
    conflicting_cli_class_type_kinds:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared as a different kind of class
    +
    +

    1972

    +
    conflicting_cli_class_template_kinds:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared as a different kind of class template
    +
    +

    1973

    +
    literal_requires_managed_class:
    +
    literal data members can only be members of managed classes
    +
    +

    1974

    +
    literal_without_initializer:
    +
    a literal data member must be initialized
    +
    +

    1975

    +
    invalid_literal_type:
    +
    a literal data member of type “type” is not allowed
    +
    +

    1976

    +
    literal_const_has_no_effect:
    +
    const has no effect on a literal data member
    +
    +

    1977

    +
    initonly_requires_managed_class:
    +
    initonly data members can only be members of managed classes
    +
    +

    1978

    +
    initonly_const_has_no_effect:
    +
    const has no effect on an initonly data member
    +
    +

    1979

    +
    cli_get_accessor_missing:
    +
    entity-kind “entity” (declared at line xxxx) has no “get” +accessor
    +
    +

    1980

    +
    cli_set_accessor_missing:
    +
    entity-kind “entity” (declared at line xxxx) has no “set” +accessor
    +
    +

    1981

    +
    static_constructor_with_params:
    +
    a static constructor cannot have parameters
    +
    +

    1982

    +
    static_constructor_member_template:
    +
    a static constructor cannot be a member template
    +
    +

    1983

    +
    compound_lvalue_as_asm_operand:
    +
    a compound lvalue is not allowed as an asm output operand
    +
    +

    1984

    +
    property_requires_managed_class:
    +
    properties can only be members of managed classes
    +
    +

    1985

    +
    qualifier_not_allowed_on_managed_member_function:
    +
    a type qualifier is not allowed on a member function of a managed +class
    +
    +

    1986

    +
    pointer_to_ref_or_interface_class:
    +
    an ordinary pointer to a C++/CLI ref class or interface class is not +allowed
    +
    +

    1987

    +
    reference_to_ref_or_interface_class:
    +
    an ordinary reference to a C++/CLI ref class or interface class is +not allowed
    +
    +

    1988

    +
    override_name_must_be_a_base_class_member_function:
    +
    override specifier does not name a base class member function
    +
    +

    1989

    +
    override_name_nonvirtual:
    +
    override specifier designates a nonvirtual member entity-kind +“entity” (declared at line xxxx)
    +
    +

    1990

    +
    multiple_overrides:
    +
    member function overrides entity-kind “entity” (declared at line +xxxx) which is already overridden by entity-kind “entity”(declared at line xxxx)
    +
    +

    1991

    +
    multiple_visibility_specifiers:
    +
    at most one visibility specifier is allowed
    +
    +

    1992

    +
    invalid_delegate_type:
    +
    type “type” used for delegate definition is not a function type
    +
    +

    1993

    +
    delegate_requires_managed_class:
    +
    delegate member types can only be members of managed classes
    +
    +

    1994

    +
    tracking_reference_to_delegate:
    +
    a tracking reference to a delegate type is not allowed
    +
    +

    1995

    +
    bad_use_of_delegate_type:
    +
    a delegate type is not allowed here
    +
    +

    1996

    +
    empty_pack_expansion:
    +
    this pack expansion produced an empty list of expressions, and an +expression is needed here
    +
    +

    1997

    +
    virtual_static_event:
    +
    an event cannot be both static and virtual
    +
    +

    1998

    +
    event_requires_managed_class:
    +
    events can only be members of managed classes
    +
    +

    1999

    +
    invalid_event_accessor_decl:
    +
    this declaration cannot appear in an event definition
    +
    +

    2000

    +
    invalid_event_type:
    +
    event type must be a handle-to-delegate type
    +
    +

    2001

    +
    event_add_already_declared:
    +
    an “add” accessor was already declared for this event at line xxxx
    +
    +

    2002

    +
    event_remove_already_declared:
    +
    a “remove” accessor was already declared for this event at line +xxxx
    +
    +

    2003

    +
    event_raise_already_declared:
    +
    a “raise” accessor was already declared for this event at line +xxxx
    +
    +

    2004

    +
    virtual_static_event_accessor:
    +
    an event accessor cannot be both static and virtual
    +
    +

    2005

    +
    bad_event_add_or_remove_return:
    +
    return type of “add” and “remove” accessors must be void
    +
    +

    2006

    +
    event_accessor_missing_value_parameter:
    +
    event accessor is missing its value parameter
    +
    +

    2007

    +
    extra_event_accessor_parameters:
    +
    accessor function has too many parameters
    +
    +

    2008

    +
    event_accessor_value_parameter_mismatch:
    +
    the type “type” of the parameter of the event accessor does not +match the event type (“type”)
    +
    +

    2009

    +
    event_raise_type_mismatch:
    +
    the type of the “raise” accessor does not match the event’s delegate +invocation type
    +
    +

    2010

    +
    missing_add_or_remove_accessor:
    +
    an event definition must include both “add” and “remove” accessors
    +
    +

    2011

    +
    static_conversion_function_must_have_one_parameter:
    +
    a static conversion function must accept exactly one argument
    +
    +

    2012

    +
    bad_parameter_type_for_static_member_operator:
    +
    static operator must have a parameter type T, T&, T%, or T^ with T = +“type”
    +
    +

    2013

    +
    sizeof_operand_not_parameter_pack:
    +
    the operand of sizeof… must be a parameter pack name
    +
    +

    2014

    +
    sizeof_pack_in_non_variadic_context:
    +
    the sizeof… operator can be used only in a variadic template
    +
    +

    2015

    +
    event_name_not_allowed:
    +
    event name cannot appear here
    +
    +

    2016

    +
    handle_to_standard_class_type:
    +
    a handle to a non-managed class is not allowed
    +
    +

    2017

    +
    handle_to_unscoped_enum_type:
    +
    a handle to an unscoped enum type is not allowed
    +
    +

    2018

    +
    property_attribute_in_managed_class:
    +
    “property” attribute not allowed in managed class
    +
    +

    2019

    +
    pure_virtual_definition:
    +
    a pure specifier (”= 0”) followed by a definition is nonstandard
    +
    +

    2020

    +
    managed_nullptr_not_allowed:
    +
    the managed nullptr type cannot be used here
    +
    +

    2021

    +
    addr_of_ref_class:
    +
    the “&” operator cannot be used to take the address of an object with +a ref class type
    +
    +

    2022

    +
    array_of_managed_class:
    +
    array of managed class is not allowed
    +
    +

    2023

    +
    static_storage_variable_with_handle_or_tracking_ref_type:
    +
    a variable with static storage duration cannot have a handle or +tracking reference type
    +
    +

    2024

    +
    lambda_captures_handle_or_tracking_ref:
    +
    a variable captured by a lambda cannot be a handle or tracking +reference
    +
    +

    2025

    +
    invalid_param_array_type:
    +
    a C++/CLI parameter array requires a handle to a one-dimensional +cli::array type
    +
    +

    2026

    +
    cannot_import_metadata:
    +
    could not import metadata from file “xxxx”
    +
    +

    2027

    +
    namespace_cli_cannot_be_extended:
    +
    the cli namespace cannot be extended
    +
    +

    2028

    +
    cli_array_invalid_element_type:
    +
    the element type of a cli::array must be a handle or value type
    +
    +

    2029

    +
    cli_array_invalid_number_of_dimensions:
    +
    invalid number of dimensions for cli::array type
    +
    +

    2030

    +
    invalid_type_pointed_to_for_interior_ptr_or_pin_ptr:
    +
    a cli::interior_ptr/cli::pin_ptr must point to a standard class, a +value class, an integer, a handle, or a standard pointer
    +
    +

    2031

    +
    type_cannot_be_class_member:
    +
    “type” cannot be a class member
    +
    +

    2032

    +
    pin_ptr_param_not_allowed:
    +
    a parameter of type cli::pin_ptr is not allowed
    +
    +

    2033

    +
    bad_finalizer_decl:
    +
    invalid finalizer declaration
    +
    +

    2034

    +
    too_many_params_for_finalizer:
    +
    a finalizer may not have parameters
    +
    +

    2035

    +
    function_qualifier_on_finalizer:
    +
    a type qualifier is not allowed on a finalizer
    +
    +

    2036

    +
    return_type_on_finalizer:
    +
    a return type may not be specified on a finalizer
    +
    +

    2037

    +
    no_finalizer_using_declaration:
    +
    a using-declaration may not name a finalizer
    +
    +

    2038

    +
    finalizer_name_must_be_qualified:
    +
    a finalizer name must be qualified
    +
    +

    2039

    +
    finalizer_qualifier_type_mismatch:
    +
    qualifier of finalizer name “type” does not match type “type”
    +
    +

    2040

    +
    var_used_as_finalizer:
    +
    entity-kind “entity” cannot be used to name a finalizer (a type +name is required)
    +
    +

    2041

    +
    invalid_finalizer_name:
    +
    invalid finalizer name for type “type”
    +
    +

    2042

    +
    ambiguous_finalizer:
    +
    finalizer reference is ambiguous – both entity-kind “entity” and +entity-kind “entity” could be used
    +
    +

    2043

    +
    finalizer_requires_reference_type:
    +
    a finalizer can only be a member of a ref class
    +
    +

    2045

    +
    finalizer_type_mismatch:
    +
    type used as finalizer name does not match type “type”
    +
    +

    2046

    +
    finalizer_does_not_exist:
    +
    a finalizer does not exist for this type
    +
    +

    2047

    +
    handle_of_non_managed:
    +
    the “%” operator can be used only on an object with a managed class +type
    +
    +

    2048

    +
    ptr_handle_or_ref_to_interior_ptr:
    +
    a pointer, handle, or reference to a cli::interior_ptr is not allowed
    +
    +

    2049

    +
    ptr_handle_or_ref_to_pin_ptr:
    +
    a pointer, handle, or reference to a cli::pin_ptr is not allowed
    +
    +

    2050

    +
    ptr_or_ref_to_cli_array:
    +
    a pointer or reference to a C++/CLI array is not allowed
    +
    +

    2051

    +
    bad_use_of_cli_array_type:
    +
    a C++/CLI array type is not allowed here
    +
    +

    2052

    +
    invalid_ref_class_base:
    +
    a C++/CLI ref class can only derive from another ref class or from +interface classes
    +
    +

    2053

    +
    invalid_value_class_base:
    +
    a C++/CLI value class can only derive from interface classes
    +
    +

    2054

    +
    invalid_interface_class_base:
    +
    a C++/CLI interface class can only derive from interface classes
    +
    +

    2055

    +
    ref_class_has_multiple_ref_bases:
    +
    a ref class can have at most one direct ref base class (“type” is +already such a base)
    +
    +

    2056

    +
    managed_base_for_standard_class:
    +
    a standard class cannot derive from a managed class
    +
    +

    2057

    +
    virtual_base_for_managed_class:
    +
    a managed class cannot have a virtual base
    +
    +

    2058

    +
    managed_class_type_cannot_have_private_or_protected_base:
    +
    a managed class cannot have a “private” or “protected” base
    +
    +

    2059

    +
    override_requires_virtual:
    +
    the “override” modifier requires a virtual function declaration with +an explicit “virtual” keyword
    +
    +

    2060

    +
    abstract_requires_virtual:
    +
    the “abstract” modifier requires a virtual function declaration with +an explicit “virtual” keyword
    +
    +

    2061

    +
    sealed_requires_virtual:
    +
    the “sealed” modifier requires a virtual function declaration with an +explicit “virtual” keyword
    +
    +

    2062

    +
    named_override_requires_virtual:
    +
    a named override specifier requires a virtual function declaration +with an explicit “virtual” keyword
    +
    +

    2063

    +
    pin_ptr_return_type_not_allowed:
    +
    a cli::pin_ptr return type is not allowed
    +
    +

    2064

    +
    cppcli_attribute_only:
    +
    attribute “xxxx” applies in C++/CLI mode only
    +
    +

    2065

    +
    normal_ref_bound_to_gc_lvalue:
    +
    a simple (non-tracking) reference cannot be bound to an entity on the +managed heap
    +
    +

    2067

    +
    cli_entity_not_loaded:
    +
    “xxxx“ not loaded from default assemblies
    +
    +

    2068

    +
    list_initializer_nonstandard_in_current_mode:
    +
    list initialization syntax is a C++11 feature
    +
    +

    2069

    +
    sizeof_ref_or_interface_class:
    +
    operand of sizeof may not be a ref class type or interface class type
    +
    +

    2070

    +
    cli_array_invalid_number_of_subscripts:
    +
    invalid number of subscripts for this cli::array type
    +
    +

    2071

    +
    ptr_to_member_of_managed_class:
    +
    a pointer-to-member is not valid for a managed class
    +
    +

    2072

    +
    private_virtual_member_function_not_sealed:
    +
    private virtual member function of managed class is not “sealed”
    +
    +

    2073

    +
    modifier_not_allowed_on_destructor:
    +
    modifier is not allowed on a destructor
    +
    +

    2074

    +
    modifier_not_allowed_on_finalizer:
    +
    modifier is not allowed on a finalizer
    +
    +

    2075

    +
    virtual_has_no_effect:
    +
    “virtual” has no effect on a destructor of a managed class
    +
    +

    2076

    +
    new_or_override_required:
    +
    “new” or “override” is required because this declaration matches +entity-kind “entity” (declared at line xxxx)
    +
    +

    2077

    +
    new_or_virtual_required:
    +
    “new” or “virtual” is required because this declaration matches +entity-kind “entity” (declared at line xxxx)
    +
    +

    2078

    +
    override_for_interface_member:
    +
    “new” or “override” are not valid here because the matching +entity-kind “entity” (declared at line xxxx) is a member of +an interface
    +
    +

    2079

    +
    new_requires_matching_base_member:
    +
    “new” modifier without a matching base ref class member
    +
    +

    2080

    +
    overriding_reduces_accessibility_in_managed_type:
    +
    entity-kind “entity” (declared at line xxxx) overridden with +reduced access
    +
    +

    2081

    +
    bad_tracking_ref_init:
    +
    a reference of type “type” cannot be initialized with a value of +type “type”
    +
    +

    2082

    +
    copy_constructor_in_value_class_type:
    +
    a copy constructor cannot be declared in a value class
    +
    +

    2083

    +
    default_constructor_in_value_class_type:
    +
    a default constructor cannot be declared in a value class
    +
    +

    2084

    +
    destructor_in_value_class_type:
    +
    a destructor cannot be declared in a value class
    +
    +

    2085

    +
    assignment_in_value_class_type:
    +
    an assignment operator cannot be declared in a value class
    +
    +

    2086

    +
    nonvalue_class_type_cannot_be_value_class_member:
    +
    non-value class “type” cannot be the type of a member of a value +class
    +
    +

    2087

    +
    cppcli_requires_newer_abi_version:
    +
    option “cppcli” requires a different compiler configuration
    +
    +

    2088

    +
    managed_member_exception_spec:
    +
    exception specifications are not allowed on member functions of +managed classes
    +
    +

    2089

    +
    managed_class_cannot_have_friend:
    +
    a managed class cannot declare a friend
    +
    +

    2092

    +
    local_class_in_managed_member_function:
    +
    a local class definition is not allowed in a member function of a +managed class
    +
    +

    2093

    +
    local_lambda_in_managed_member_function:
    +
    a local lambda is not allowed in a member function of a managed class
    +
    +

    2094

    +
    cli_interface_member_function_definition:
    +
    a member function of a C++/CLI interface class type cannot have a +definition
    +
    +

    2095

    +
    missing_get_and_set_accessors:
    +
    a property definition must include at least one accessor (“get” or +“set”)
    +
    +

    2096

    +
    subscript_mechanism_conflict:
    +
    default-indexed property conflicts with entity-kind “entity”(declared at line xxxx)
    +
    +

    2097

    +
    unusable_pack:
    +
    entity-kind “entity” cannot be used because it follows a +parameter pack and cannot be deduced from the parameters of +entity-kind “entity”
    +
    +

    2098

    +
    excess_pack_expansion:
    +
    this pack expansion produced more than one expression, and a single +expression is needed here
    +
    +

    2099

    +
    cli_enum_base_has_no_system_counterpart:
    +
    type must correspond to System::Boolean, System::Byte, System::SByte, +System::Int16, System::UInt16, System::Int32, System::UInt32, +System::Int64, or System::UInt64
    +
    +

    2100

    +
    bad_call_of_handle:
    +
    call of an object of a handle type without appropriate operator() or +conversion functions to pointer-to-function type
    +
    +

    2101

    +
    abstract_declarator_pack_is_nested:
    +
    an unnamed parameter pack declaration cannot be parenthesized
    +
    +

    2102

    +
    cl_variadic_templates_only_in_cplusplus:
    +
    variadic templates can be enabled only when compiling C++
    +
    +

    2103

    +
    conflicting_properties:
    +
    property definition conflicts with entity-kind “entity” (declared +at line xxxx)
    +
    +

    2106

    +
    generic_param_cannot_have_default:
    +
    a generic parameter cannot have a default
    +
    +

    2107

    +
    bad_param_kind_for_generic:
    +
    a generic can only have type parameters
    +
    +

    2108

    +
    for_each_missing_function:
    +
    to be used with “for each” statements, type “type” must provide +nonstatic member function “xxxx”
    +
    +

    2109

    +
    for_each_static_function:
    +
    “for each” cannot use member entity-kind “entity” because it is +static
    +
    +

    2110

    +
    for_each_no_matching_overload:
    +
    in this “for each” statement, no instance of “entity” is callable +with an empty argument list
    +
    +

    2111

    +
    for_each_invalid_return_type_for_move_next:
    +
    “for each” cannot use member function “MoveNext” because the return +type is invalid
    +
    +

    2112

    +
    for_each_incompatible_type:
    +
    a “for each” statement cannot operate on an expression of type +“type”
    +
    +

    2113

    +
    for_each_missing_field:
    +
    to be used with “for each” statements, type “type” must provide a +non-indexed property “xxxx”
    +
    +

    2115

    +
    for_each_getenumerator_return_type_invalid:
    +
    in this “for each” statement, “type” is not a valid enumerator +(returned by “GetEnumerator” of “type”)
    +
    +

    2116

    +
    exp_in:
    +
    expected “in”
    +
    +

    2117

    +
    no_suitable_synthesis_assignment_operator:
    +
    class “type” has no suitable assignment operator (after operator +synthesis)
    +
    +

    2118

    +
    not_a_generic_param:
    +
    “xxxx” is not a generic parameter
    +
    +

    2119

    +
    not_generic_param_of_curr_decl:
    +
    “xxxx” is not a generic parameter of the innermost generic +parameter list
    +
    +

    2120

    +
    invalid_constraint:
    +
    invalid generic constraint
    +
    +

    2121

    +
    invalid_event_use:
    +
    invalid use of event member (only subscription, unsubscription, and +invocation are allowed)
    +
    +

    2122

    +
    event_without_raise_invoked:
    +
    invoking an event with no “raise” accessor is invalid
    +
    +

    2123

    +
    bad_event_compound_assignment:
    +
    only “+=” and “-=” are valid for events
    +
    +

    2124

    +
    typeid_of_managed_type:
    +
    typeid of a managed type is not allowed
    +
    +

    2125

    +
    cli_typeid_of_managed_pointer:
    +
    typeid of a managed pointer type is not allowed
    +
    +

    2126

    +
    name_before_typeid_not_type:
    +
    name followed by “::typeid” must be a type name
    +
    +

    2127

    +
    reserved_dispose:
    +
    a member “xxxx” of this type is reserved within a managed class +– destructor intended?
    +
    +

    2128

    +
    reserved_finalize:
    +
    a member “xxxx” of this type is reserved within a managed class +– finalizer intended?
    +
    +

    2129

    +
    invalid_idisposable_dispose:
    +
    System::IDisposable::Dispose is missing or invalid
    +
    +

    2130

    +
    invalid_object_finalize:
    +
    System::Object::Finalize is missing or invalid
    +
    +

    2131

    +
    finalize_does_not_override_object_finalize:
    +
    entity-kind “entity” does not override System::Object::Finalize
    +
    +

    2132

    +
    bad_handle_dynamic_cast_operand:
    +
    the operand of a handle dynamic_cast must be a handle to a complete +class type
    +
    +

    2133

    +
    bad_tracking_ref_dynamic_cast_operand:
    +
    the operand of a tracking-reference dynamic_cast must be an lvalue of +a complete class type
    +
    +

    2134

    +
    bad_cli_dynamic_cast_type:
    +
    the type in a dynamic_cast to a handle or tracking reference type +must refer to a complete class
    +
    +

    2135

    +
    cast_interior_ptr_to_ptr:
    +
    an interior pointer cannot be cast to a native pointer
    +
    +

    2136

    +
    cppcli_explicit_conversion_only_in_ref_and_value_classes:
    +
    explicit conversion operators can only be declared in ref and value +class types
    +
    +

    2137

    +
    cppcli_explicit_conversion_is_virtual:
    +
    explicit conversion operator cannot be virtual
    +
    +

    2138

    +
    expr_not_arithmetic_or_unscoped_enum:
    +
    expression must have arithmetic or unscoped enum type
    +
    +

    2139

    +
    expr_not_arithmetic_or_unscoped_enum_or_pointer:
    +
    expression must have arithmetic, unscoped enum, or pointer type
    +
    +

    2140

    +
    expr_not_integral_or_unscoped_enum:
    +
    expression must have integral or unscoped enum type
    +
    +

    2141

    +
    expr_not_integral_or_unscoped_enum_or_fixed_point:
    +
    expression must have integral, unscoped enum, or fixed-point type
    +
    +

    2142

    +
    scoped_enum_operation_type_mismatch:
    +
    a built-in binary operator applied to a scoped enumeration requires +two operands of the same type
    +
    +

    2143

    +
    invalid_gcnew_type:
    +
    gcnew cannot allocate an entity of type “type”
    +
    +

    2144

    +
    gcnew_used_with_placement_syntax:
    +
    placement syntax cannot be used with gcnew
    +
    +

    2145

    +
    new_used_on_unsuitable_value_type:
    +
    new can only be used with simple value types
    +
    +

    2146

    +
    new_used_on_managed_class_type:
    +
    new cannot be used on a managed class (gcnew should be used instead)
    +
    +

    2147

    +
    new_used_on_handle_or_tracking_reference_type:
    +
    new cannot be used on a handle type
    +
    +

    2148

    +
    cli_array_must_have_new_or_array_init:
    +
    gcnew for a C++/CLI array must have a new initializer or an array +initializer
    +
    +

    2149

    +
    gcnew_bad_type_used_with_array_init:
    +
    an array initializer can only be used to initialize a C++/CLI array +type
    +
    +

    2150

    +
    gcnew_used_with_auto_syntax:
    +
    gcnew does not allow auto
    +
    +

    2151

    +
    too_many_array_bounds:
    +
    too many array bounds
    +
    +

    2152

    +
    too_few_array_bounds:
    +
    too few array bounds
    +
    +

    2153

    +
    too_few_generic_args:
    +
    too few arguments for entity-kind “entity”
    +
    +

    2154

    +
    too_many_generic_args:
    +
    too many arguments for entity-kind “entity”
    +
    +

    2156

    +
    no_matching_arity:
    +
    no declaration of entity-kind “entity” accepts the number of +generic arguments supplied
    +
    +

    2157

    +
    bad_function_for_delegate:
    +
    invalid delegate initializer – must be a function
    +
    +

    2158

    +
    ambiguous_function_for_delegate:
    +
    invalid delegate initializer – more than one function matches the +delegate type
    +
    +

    2159

    +
    mismatched_function_for_delegate:
    +
    invalid delegate initializer – function does not match the delegate +type
    +
    +

    2160

    +
    missing_delegate_object:
    +
    invalid delegate initializer – an object is needed in addition to a +function
    +
    +

    2161

    +
    nonmanaged_function_for_delegate:
    +
    invalid delegate initializer – function is not a member of a managed +class
    +
    +

    2162

    +
    superfluous_delegate_object:
    +
    invalid delegate initializer – object is not needed for the +specified function
    +
    +

    2163

    +
    incompatible_delegate_object:
    +
    invalid delegate initializer – object has type “type” but type +“type” is expected
    +
    +

    2164

    +
    address_of_managed_member_function:
    +
    taking the address of a member function of a managed class is not +allowed
    +
    +

    2165

    +
    bad_delegate_init_list:
    +
    invalid delegate initializer – expected either +“(<function-address>)” or “(<object-handle>, <member-address>)”
    +
    +

    2166

    +
    interface_not_implemented:
    +
    class fails to implement interface member entity-kind “entity”(declared at line xxxx)
    +
    +

    2167

    +
    gcnew_of_native_array:
    +
    gcnew cannot be used to allocate a native array
    +
    +

    2168

    +
    cli_interface_cannot_have_assignment:
    +
    a C++/CLI interface class cannot declare an assignment operator
    +
    +

    2169

    +
    sealed_cli_interface:
    +
    a C++/CLI interface class cannot be sealed
    +
    +

    2171

    +
    destructor_or_finalizer_with_named_override:
    +
    a destructor or finalizer declaration cannot include a named override +specifier
    +
    +

    2172

    +
    override_name_is_destructor_or_finalizer:
    +
    an override specifier cannot designate a destructor or finalizer
    +
    +

    2173

    +
    named_override_requires_managed_type:
    +
    a named override specifier is allowed only in a managed class
    +
    +

    2174

    +
    named_override_type_mismatch:
    +
    no member designated by the named override specifier matches the type +of this member
    +
    +

    2175

    +
    static_constructor_with_named_override:
    +
    a static constructor declaration cannot include a named override +specifier
    +
    +

    2176

    +
    unnamed_scoped_enum:
    +
    a scoped enum type must have a name
    +
    +

    2177

    +
    branch_into_finally:
    +
    transfer of control into a finally block is not allowed
    +
    +

    2178

    +
    return_from_finally:
    +
    return statement inside a finally block is not allowed
    +
    +

    2179

    +
    missing_finally:
    +
    try block requires at least one handler or finally clause
    +
    +

    2180

    +
    managed_object_not_thrown_by_handle:
    +
    a managed object must be thrown by handle
    +
    +

    2181

    +
    managed_object_not_caught_by_handle:
    +
    a managed object must be caught by handle
    +
    +

    2182

    +
    break_cannot_be_in_finally_block:
    +
    a break statement cannot be used in a finally block
    +
    +

    2183

    +
    continue_cannot_be_in_finally_block:
    +
    a continue statement cannot be used in a finally block
    +
    +

    2184

    +
    no_overloaded_subscript_with_offsetof:
    +
    builtin offsetof cannot be used when subscripting is overloaded
    +
    +

    2185

    +
    duplicate_constraint:
    +
    duplicate constraint
    +
    +

    2186

    +
    multiple_class_constraints:
    +
    more than one class constraint: “type” and “type”
    +
    +

    2187

    +
    multiple_constraint_clauses:
    +
    more than one constraint clause for entity-kind “entity”
    +
    +

    2188

    +
    initonly_static_data_member_not_initialized:
    +
    initonly static data members must have an initializer or be +initialized in a static constructor
    +
    +

    2189

    +
    gnu_attr_on_template_redecl:
    +
    GNU attributes on a template redeclaration have no effect
    +
    +

    2190

    +
    gnu_attr_on_template_redecl_but_original_kept:
    +
    GNU attributes on a template redeclaration have no effect (the +attributes of the original declaration at line xxxx apply instead)
    +
    +

    2191

    +
    cli_param_array_must_be_last_parameter:
    +
    a C++/CLI parameter array must be the last parameter
    +
    +

    2192

    +
    default_arg_used_in_param_array_function:
    +
    a function with a C++/CLI parameter array cannot have default +arguments
    +
    +

    2193

    +
    ellipsis_after_param_array:
    +
    a C++/CLI parameter array cannot be followed by an ellipsis parameter
    +
    +

    2194

    +
    parameter_array_on_operator_function:
    +
    a C++/CLI parameter array is not allowed in an operator function +parameter list
    +
    +

    2195

    +
    microsoft_inline_not_allowed_here:
    +
    __inline and __forceinline are not allowed here
    +
    +

    2196

    +
    data_member_with_interface_type:
    +
    a data member cannot have a C++/CLI interface class type
    +
    +

    2197

    +
    variable_with_interface_type:
    +
    a variable cannot have a C++/CLI interface class type
    +
    +

    2198

    +
    parameter_with_interface_type:
    +
    a parameter cannot have a C++/CLI interface class type
    +
    +

    2199

    +
    return_type_is_interface:
    +
    a function return type cannot be a C++/CLI interface class type
    +
    +

    2200

    +
    array_of_generic_param:
    +
    an array of generic parameter type is not allowed
    +
    +

    2201

    +
    ptr_handle_or_ref_to_generic_param:
    +
    a pointer, handle, or reference to a generic parameter type is not +allowed
    +
    +

    2202

    +
    ref_class_initonly_field:
    +
    an initonly field cannot have a ref class type
    +
    +

    2203

    +
    ref_bound_to_initonly_field:
    +
    a reference cannot be bound to an initonly field
    +
    +

    2204

    +
    address_of_initonly_field:
    +
    taking the address of an initonly field is not allowed
    +
    +

    2205

    +
    modification_of_initonly_field:
    +
    an initonly field can only be modified by the instance constructor of +its containing class
    +
    +

    2206

    +
    modification_of_static_initonly_field:
    +
    a static initonly field can only be modified by the static +constructor of its containing class
    +
    +

    2207

    +
    member_function_call_on_initonly_field:
    +
    member function will be invoked on a copy of the initonly field
    +
    +

    2208

    +
    expr_not_pointer_nor_handle:
    +
    expression must have pointer or handle type but it has type “type”
    +
    +

    2209

    +
    move_ctor_or_assign_copy_of_lvalue:
    +
    a move constructor or move assignment operator is used to copy an +lvalue here, which may destroy the source object
    +
    +

    2210

    +
    generic_selection_with_points_to:
    +
    member selection on a C++/CLI generic entity must use the “->” +syntax, not “.”
    +
    +

    2211

    +
    invalid_specific_ref_class_base:
    +
    a ref class type cannot derive from “type”
    +
    +

    2212

    +
    generic_class_must_be_managed:
    +
    a generic class must be managed (i.e., a ref class, a value class, or +an interface class)
    +
    +

    2213

    +
    sealed_constraint:
    +
    a sealed class cannot be used as a constraint
    +
    +

    2214

    +
    dynamic_cast_to_value_generic:
    +
    the type in a dynamic_cast cannot be a generic type that might be a +value type
    +
    +

    2215

    +
    UCN_names_invalid_code_point:
    +
    a universal character name must designate a valid code point
    +
    +

    2216

    +
    override_with_constraint_mismatch:
    +
    generic constraints do not match those of entity-kind “entity”(declared at line xxxx)
    +
    +

    2217

    +
    bad_argument_for_underlying_type:
    +
    __underlying_type only applies to enum types
    +
    +

    2218

    +
    too_many_cast_operands:
    +
    expected only one operand expression for this cast
    +
    +

    2219

    +
    bad_unicode_char_in_string:
    +
    Unicode character with hex value xxxx not representable in the +system default code page
    +
    +

    2220

    +
    conv_of_pm_to_func_ptr:
    +
    nonstandard conversion of bound pointer-to-member to a function +pointer
    +
    +

    2221

    +
    deprecated_access_specifier:
    +
    access specifier xxxx is deprecated – use xxxx instead
    +
    +

    2222

    +
    static_accessor_in_nonstatic_property_or_event:
    +
    a static accessor function is not permitted in a nonstatic property +or event definition
    +
    +

    2223

    +
    both_ref_and_value_constraints:
    +
    “type” has both a value class and ref class constraint
    +
    +

    2224

    +
    circular_constraints:
    +
    “type” and “type” involve circular naked type constraints
    +
    +

    2225

    +
    invalid_type_constraint:
    +
    “type” is not a valid type constraint
    +
    +

    2226

    +
    pch_file_incomplete:
    +
    precompiled header file “xxxx” not used (because it is incomplete)
    +
    +

    2227

    +
    invalid_generic_arg:
    +
    “type” is not a valid generic argument
    +
    +

    2228

    +
    bad_assembly_info_attribute:
    +
    assembly_info attribute applied to an invalid type
    +
    +

    2229

    +
    ref_class_not_satisfied:
    +
    “type” does not satisfy the ref class constraint of generic +parameter “type”
    +
    +

    2230

    +
    value_class_not_satisfied:
    +
    “type” does not satisfy the value class constraint of generic +parameter “type”
    +
    +

    2231

    +
    gcnew_and_abstract:
    +
    “type” does not satisfy the gcnew constraint of generic parameter +“type” because it is abstract
    +
    +

    2232

    +
    gcnew_and_no_ctor:
    +
    “type” does not satisfy the gcnew constraint of generic parameter +“type” because it does not have a public default constructor
    +
    +

    2233

    +
    gcnew_and_no_gcnew:
    +
    generic parameter “type” does not satisfy the gcnew constraint of +generic parameter “type” because it does not have the gcnew +constraint
    +
    +

    2234

    +
    type_not_satisfied:
    +
    “type” does not satisfy the “type” type constraint of generic +parameter “type”
    +
    +

    2235

    +
    constraint_mismatch:
    +
    constraint on generic parameter “type” differs from previous +declaration (at line xxxx)
    +
    +

    2236

    +
    standard_array_member_in_managed_class:
    +
    a member of a managed class cannot be a standard array
    +
    +

    2237

    +
    handle_member_in_standard_class:
    +
    a member of a non-managed class cannot be a handle
    +
    +

    2238

    +
    tracking_reference_member_in_standard_class:
    +
    a member of a non-managed class cannot be a tracking reference
    +
    +

    2239

    +
    reinterpret_cast_of_handle:
    +
    unsafe reinterpret_cast of handle
    +
    +

    2240

    +
    generic_type_in_template_arg:
    +
    a template argument may not reference a generic type parameter
    +
    +

    2241

    +
    comma_operator_in_cli_subscript:
    +
    an expression list is not allowed in this subscript operation (use +parentheses around a top-level comma operator)
    +
    +

    2242

    +
    expr_not_pointer_or_array_handle:
    +
    expression must have pointer-to-object or handle-to-C++/CLI-array +type but it has type “type”
    +
    +

    2243

    +
    unrecognized_ms_attr:
    +
    unrecognized attribute
    +
    +

    2244

    +
    standard_class_member_in_managed_class:
    +
    a member of a managed class cannot be of a non-managed class type
    +
    +

    2245

    +
    ref_or_interface_class_member_in_standard_class:
    +
    a member of a non-managed class cannot have a ref class type or +interface class type
    +
    +

    2247

    +
    template_delegate:
    +
    a delegate may not be declared as a template
    +
    +

    2248

    +
    invalid_generic_specialization:
    +
    a generic cannot be explicitly specialized
    +
    +

    2249

    +
    generic_in_template:
    +
    a generic cannot be declared in a class template
    +
    +

    2250

    +
    template_in_generic:
    +
    a template cannot be declared in a generic class
    +
    +

    2251

    +
    static_literal_field:
    +
    a literal field cannot be declared “static”
    +
    +

    2252

    +
    nonstandard_long_float:
    +
    “long float” is a nonstandard extension – use “double” instead
    +
    +

    2253

    +
    standard_class_nested_in_managed_class:
    +
    a standard class cannot be nested in a managed class
    +
    +

    2254

    +
    clrcall_requires_cppcli:
    +
    __clrcall is valid only in C++/CLI mode
    +
    +

    2255

    +
    vararg_clrcall:
    +
    __clrcall not allowed on function with ellipsis parameter
    +
    +

    2256

    +
    bad_use_of_function_modifier:
    +
    “xxxx” is not allowed here
    +
    +

    2257

    +
    override_with_trivial_property_or_event:
    +
    a trivial property or event cannot be used to override entity-kind +“entity” (declared at line xxxx)
    +
    +

    2258

    +
    exp_id_in_for_each_decl:
    +
    expected an iterator variable name
    +
    +

    2259

    +
    missing_notequal_on_for_each_type:
    +
    the iterator type in this “for each” statement is “type”, which +is not a pointer type or an iterator-like class type
    +
    +

    2260

    +
    missing_incr_on_for_each_type:
    +
    the iterator type in this “for each” statement is “type”, which +is not a pointer type or an iterator-like class type
    +
    +

    2261

    +
    missing_indirect_on_for_each_type:
    +
    the iterator type in this “for each” statement is “type”, which +is not a pointer type or an iterator-like class type
    +
    +

    2262

    +
    no_packing_of_non_POD_field:
    +
    packing attribute on the parent type is ignored for this field of +class type “type” that is not standard-layout
    +
    +

    2263

    +
    nonpublic_implicit_interface_match:
    +
    entity-kind “entity” (declared at line xxxx) not implemented +because this declaration is not public and has no named override +specifier
    +
    +

    2264

    +
    missing_gnu_inline_attr_on_redeclaration:
    +
    this declaration is missing the gnu_inline attribute specified in the +previous declaration at line xxxx
    +
    +

    2265

    +
    managed_member_function_cannot_have_ellipsis_parameter:
    +
    a member function of a managed class cannot have an ellipsis parameter
    +
    +

    2266

    +
    invalid_prev_decl_iterator:
    +
    previously-declared entity-kind “entity” invalid as iterator of +“for each” statement
    +
    +

    2267

    +
    generic_parameter_requires_clrcall:
    +
    calling convention ignored because the function type involves a +generic parameter; __clrcall used instead
    +
    +

    2268

    +
    generic_parameter_does_not_permit_varargs:
    +
    a function type involving a generic parameter cannot have an ellipsis +parameter
    +
    +

    2269

    +
    virtual_required_for_base_override:
    +
    “virtual” is required to override the matching entity-kind +“entity” (declared at line xxxx)
    +
    +

    2270

    +
    virtual_required_for_interface_implementation:
    +
    “virtual” is required to implement the matching entity-kind +“entity” (declared at line xxxx)
    +
    +

    2271

    +
    initonly_volatile_not_allowed:
    +
    an initonly data member cannot be volatile
    +
    +

    2272

    +
    member_name_reserved_by_cli_operator:
    +
    a member “xxxx” of this type is reserved within a managed class +– C++/CLI operators must be declared using the keyword “operator”
    +
    +

    2273

    +
    tracking_ref_to_constant:
    +
    a tracking reference to non-const cannot be bound to a constant
    +
    +

    2274

    +
    attributes_with_no_decl:
    +
    attributes ignored here because they do not apply to a declared entity
    +
    +

    2275

    +
    tracking_reference_to_system_string:
    +
    a tracking reference to System::String is not allowed
    +
    +

    2276

    +
    use_of_generic_class_with_pending_constraint:
    +
    invalid use of a generic class “type” with pending constraints +(probably caused by an invalid metadata file)
    +
    +

    2277

    +
    invalid_entity_for_pending_constraint:
    +
    a pending constraint clause is only allowed for generic class +declarations (but not generic class definitions)
    +
    +

    2278

    +
    invalid_empty_initializer_list:
    +
    empty initializer list not allowed here
    +
    +

    2279

    +
    template_in_managed_class:
    +
    a template cannot be declared in a managed class
    +
    +

    2280

    +
    bad_generic_declaration_scope:
    +
    a generic declaration is not allowed here
    +
    +

    2281

    +
    interface_cannot_have_member_generics:
    +
    interface types cannot have member generics
    +
    +

    2282

    +
    character_not_latin_1:
    +
    Unicode character not Latin-1, truncated to low-order byte
    +
    +

    2283

    +
    range_based_for_missing_function:
    +
    to be used with range-based “for” statements, type “type” must +provide function “xxxx”
    +
    +

    2284

    +
    missing_notequal_on_range_based_for_type:
    +
    the iterator type in this range-based “for” statement is “type”, +which is not a pointer type or an iterator-like class type
    +
    +

    2285

    +
    missing_incr_on_range_based_for_type:
    +
    the iterator type in this range-based “for” statement is “type”, +which is not a pointer type or an iterator-like class type
    +
    +

    2286

    +
    missing_indirect_on_range_based_for_type:
    +
    the iterator type in this range-based “for” statement is “type”, +which is not a pointer type or an iterator-like class type
    +
    +

    2287

    +
    range_based_for_incomplete_array_type:
    +
    a range-based “for” statement cannot operate on an array of unknown +size or incomplete type “type”
    +
    +

    2288

    +
    begin_end_type_mismatch_in_range_based_for:
    +
    return types for “begin” and “end” functions used in a range-based +“for” statement must be the same (“begin” return type is “type”, +“end” return type is “type”)
    +
    +

    2289

    +
    inaccessible_elided_dtor:
    +
    entity-kind “entity” (declared at line xxxx), required to +destroy temporary that was eliminated, is inaccessible
    +
    +

    2290

    +
    range_based_for_no_matching_overload:
    +
    in this range-based “for” statement, no instance of “entity”matches the argument list
    +
    +

    2291

    +
    range_based_for_undefined_identifier:
    +
    this range-based “for” statement requires a suitable “xxxx”function and none was found
    +
    +

    2292

    +
    for_each_undefined_identifier:
    +
    this “for each” statement requires a suitable “xxxx” function and +none was found
    +
    +

    2293

    +
    class_metadata_not_representable:
    +
    “type” has a metadata representation not representable using +C++/CLI
    +
    +

    2294

    +
    exp_ellipsis:
    +
    expected “…”
    +
    +

    2295

    +
    implements_requires_interface:
    +
    “type” in __implements list is not an interface
    +
    +

    2296

    +
    implements_must_precede_virtual_functions:
    +
    an __implements list must precede virtual function declarations
    +
    +

    2297

    +
    missing_implements_list:
    +
    “type” specified “__implements …” in its list of bases, but is +missing a matching __implements list
    +
    +

    2298

    +
    unused_dereference_of_ref_class:
    +
    the result of dereferencing a handle to a ref or interface class type +must be used
    +
    +

    2300

    +
    exp_rparen_and_pragma_ignored:
    +
    expected a “)”; pragma ignored
    +
    +

    2301

    +
    using_or_access_declaration_in_managed_class:
    +
    a using-declaration or access declaration cannot appear in a managed +class
    +
    +

    2302

    +
    skipped_inaccessible_function:
    +
    Note: entity-kind “entity” (declared at line xxxx) could have +been called but was not considered because it is inaccessible
    +
    +

    2303

    +
    cli_abstract_member_function_definition:
    +
    an abstract member function of a C++/CLI managed class cannot have a +definition
    +
    +

    2304

    +
    nonstatic_addressof_operator_in_managed_class:
    +
    declaring this unary “operator*” can change the meaning of +dereferencing a handle (use static member operators to explicitly +indicate applicable types)
    +
    +

    2319

    +
    interface_nonstatic_data_member:
    +
    an interface class cannot contain a nonstatic data member
    +
    +

    2320

    +
    pragma_gcc_system_header_in_primary_file:
    +
    #pragma GCC system_header cannot be used in the primary source file
    +
    +

    2321

    +
    too_large_to_inline:
    +
    entity-kind “entity” is too large to be inlined
    +
    +

    2323

    +
    cl_gen_move_operations_option_only_in_cplusplus:
    +
    option to control move operations can be used only when compiling C++
    +
    +

    2324

    +
    cl_gen_move_operations_and_rvalue_ctor_is_copy_ctor:
    +
    move operations cannot be generated when rvalue constructors are copy +constructors
    +
    +

    2325

    +
    cl_move_operations_require_rvalue_references:
    +
    option to control move operations cannot be used when rvalue +references are disabled
    +
    +

    2326

    +
    final_managed_class:
    +
    “final” cannot be used for managed classes (use “sealed” instead)
    +
    +

    2327

    +
    cast_to_cli_interface_class:
    +
    a cast to CLI interface class “type” is not allowed – cast to +handle intended?
    +
    +

    2328

    +
    new_of_cli_interface_class:
    +
    cannot create an object of a CLI interface class
    +
    +

    2329

    +
    enum_type_replacement:
    +
    this declaration hides the nonstandard declaration of entity-kind +“entity” (declared at line xxxx) because the underlying types +are incompatible
    +
    +

    2330

    +
    known_comparison_with_null:
    +
    pointer comparison result is constant, because operand can never be +null
    +
    +

    2331

    +
    value_init_of_incomplete:
    +
    an object of the incomplete type “type” cannot be +value-initialized
    +
    +

    2332

    +
    value_init_of_reference:
    +
    a reference cannot be value-initialized
    +
    +

    2333

    +
    exp_lparen_or_brace:
    +
    expected a “(” or a “{”
    +
    +

    2334

    +
    explicit_ctor_in_copy_list_init:
    +
    copy-list-initialization cannot use a constructor marked “explicit”
    +
    +

    2335

    +
    ptr_to_member_of_type_void:
    +
    pointer to member of type void is not allowed
    +
    +

    2336

    +
    ptr_to_member_of_reference_type:
    +
    pointer to member of reference type is not allowed
    +
    +

    2337

    +
    ptr_to_member_of_handle_type:
    +
    pointer to member of handle type is not allowed
    +
    +

    2338

    +
    braced_init_list_not_allowed:
    +
    a brace-enclosed list is not allowed here
    +
    +

    2339

    +
    arrow_star_operator_in_managed_class:
    +
    an operator->* member is not allowed in a managed class
    +
    +

    2340

    +
    bad_assembly_index:
    +
    assembly metadata refers to non-existent assembly
    +
    +

    2341

    +
    attribute_conflict:
    +
    attribute “xxxx” conflicts with earlier attribute “xxxx”
    +
    +

    2342

    +
    incompatible_enum_base_types:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared with a different base type
    +
    +

    2343

    +
    invalid_scoped_enum_elaboration:
    +
    “enum class” and “enum struct” cannot be used here (use plain “enum” +instead)
    +
    +

    2344

    +
    extra_braces_on_simple_init:
    +
    only one level of braces is allowed on an initializer for an object +of type “type”
    +
    +

    2345

    +
    not_an_enum_type_name:
    +
    entity-kind “entity” (declared at line xxxx) cannot be used +as an enum type name
    +
    +

    2347

    +
    auto_new_with_braced_init:
    +
    a braced-initializer cannot be used with “new auto”
    +
    +

    2348

    +
    missing_initializer_list_ctor:
    +
    the definition of std::initializer_list does not contain the expected +constructor
    +
    +

    2349

    +
    variable_hides_entity:
    +
    declaration hides entity-kind “entity” (declared at line xxxx)
    +
    +

    2350

    +
    invalid_std_initializer_list_parameter_list:
    +
    invalid template parameter list for std::initializer_list (it should +be one ordinary type parameter with no default)
    +
    +

    2351

    +
    braced_list_passed_to_ellipsis:
    +
    a brace-enclosed list cannot be passed for an ellipsis parameter
    +
    +

    2352

    +
    initializer_list_not_included:
    +
    an #include <initializer_list> is needed prior to a use of +std::initializer_list, including an implicit use
    +
    +

    2353

    +
    inline_on_alias:
    +
    the “inline” keyword cannot be used on a namespace alias declaration
    +
    +

    2354

    +
    prev_ns_not_inline:
    +
    the previous declaration of entity-kind “entity” was not declared +inline
    +
    +

    2355

    +
    prev_ns_inline:
    +
    entity-kind “entity” was previously declared inline
    +
    +

    2356

    +
    first_arg_must_be_integer_constant:
    +
    the first argument must be an integer constant
    +
    +

    2357

    +
    designator_requires_aggregate_type:
    +
    a designator cannot be used with a non-aggregate type “type”
    +
    +

    2358

    +
    indirect_anon_union_designator:
    +
    a designator for an anonymous union member can only appear within +braces corresponding to that anonymous union
    +
    +

    2359

    +
    cl_func_prototype_tags_option_only_in_C:
    +
    function prototype tags can only be enabled when compiling C
    +
    +

    2360

    +
    cannot_elide_braces:
    +
    braces cannot be omitted for this subobject initializer
    +
    +

    2361

    +
    narrowing_conversion:
    +
    invalid narrowing conversion from “type” to “type”
    +
    +

    2362

    +
    constant_narrowing_conversion:
    +
    invalid narrowing conversion from “type” to “type”: constant +value does not fit in destination type
    +
    +

    2363

    +
    cast_to_incomplete_array_type:
    +
    cast to incomplete array type “type” is not allowed
    +
    +

    2364

    +
    constant_narrowing_conversion_to_float:
    +
    invalid narrowing conversion from “type” to “type”: constant +value cannot be represented exactly in destination type
    +
    +

    2365

    +
    braced_init_in_paren_init:
    +
    a parenthesized initializer for a non-class entity must be an +expression, not a brace-enclosed list
    +
    +

    2366

    +
    braced_list_for_implicit_lambda_type:
    +
    a brace-enclosed list does not provide a return type for this lambda
    +
    +

    2367

    +
    invalid_explicit_exception_specification:
    +
    the declared exception specification is incompatible with the +generated one
    +
    +

    2368

    +
    scoped_enum_nonstandard_in_current_mode:
    +
    scoped enum types are a C++11 feature
    +
    +

    2369

    +
    value_init_of_function:
    +
    a function type cannot be value-initialized
    +
    +

    2370

    +
    list_init_of_incomplete:
    +
    list-initialization of an object type “type” is not allowed +because the type is incomplete
    +
    +

    2371

    +
    std_initializer_list_has_dtor:
    +
    std::initializer_list has a destructor, and is not supposed to – +library is misconfigured
    +
    +

    2372

    +
    explicit_enum_base_nonstandard_in_current_mode:
    +
    explicit enum base types are a C++11 feature
    +
    +

    2373

    +
    unconvertible_con_expr:
    +
    this constant expression has type “type” instead of the required +“type” type
    +
    +

    2374

    +
    new_of_initializer_list:
    +
    a “new” of an std::initializer_list object is unlikely to work as +expected because the underlying array will be destroyed at the end of +the full expression
    +
    +

    2377

    +
    defined_always_false:
    +
    “defined” is always false in a macro expansion in Microsoft mode
    +
    +

    2378

    +
    init_list_element_type_not_complete_object:
    +
    “type” cannot be the element type of an initializer list because +it is not a complete object type
    +
    +

    2379

    +
    invalid_default_arg:
    +
    mismatched delimiters in default argument expression
    +
    +

    2380

    +
    conv_of_unbound_pm_to_func_ptr:
    +
    nonstandard conversion of pointer-to-member to a function pointer
    +
    +

    2381

    +
    dynamic_exception_specifications_deprecated:
    +
    dynamic exception specifications are deprecated
    +
    +

    2382

    +
    bad_scope_for_partial_spec:
    +
    entity-kind “entity” cannot be partially specialized in the +current scope
    +
    +

    2383

    +
    previous_constexpr_decl_conflict:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared constexpr
    +
    +

    2384

    +
    previous_nonconstexpr_decl_conflict:
    +
    entity-kind “entity” (declared at line xxxx) was previously +not declared constexpr
    +
    +

    2385

    +
    constexpr_variable_decl_must_be_definition:
    +
    missing initializer for constexpr variable
    +
    +

    2386

    +
    invalid_constexpr:
    +
    “constexpr” is not valid here
    +
    +

    2387

    +
    invalid_constexpr_body:
    +
    a constexpr function must contain exactly one return statement
    +
    +

    2388

    +
    invalid_statement_in_constexpr_function:
    +
    statement may not appear in a constexpr function
    +
    +

    2389

    +
    invalid_statement_in_constexpr_constructor:
    +
    statement may not appear in a constexpr constructor
    +
    +

    2390

    +
    constexpr_virtual_combination:
    +
    a function cannot be both constexpr and virtual in this mode
    +
    +

    2391

    +
    nonliteral_return_type_in_constexpr_function:
    +
    a constexpr function cannot have a nonliteral return type “type”
    +
    +

    2392

    +
    nonliteral_param_type_in_constexpr_function:
    +
    a constexpr function cannot have a parameter of nonliteral type +“type”
    +
    +

    2393

    +
    unsequenced_use_of_variable:
    +
    unsequenced uses of entity-kind “entity” in expression may +produce undefined results
    +
    +

    2394

    +
    3rd_arg_of_assume_aligned_must_be_integral:
    +
    the optional third argument of a call to __builtin_assumed_aligned +must have integral type
    +
    +

    2395

    +
    constexpr_destructor:
    +
    a destructor cannot be constexpr
    +
    +

    2396

    +
    invalid_mmap_address:
    +
    address supplied for mmap must be aligned on a page boundary: xxxx
    +
    +

    2397

    +
    constexpr_constructor_with_function_try_block:
    +
    the body of a constexpr constructor cannot be a function try block
    +
    +

    2398

    +
    missing_initializer_on_fields_with_constexpr_ctor:
    +
    constexpr entity-kind “entity” provides no initializer for:
    +
    +

    2400

    +
    default_ctor_call_not_constant:
    +
    calling the default constructor for “type” does not produce a +constant value
    +
    +

    2401

    +
    default_ctor_not_constexpr:
    +
    the default constructor for “type” is not constexpr
    +
    +

    2402

    +
    constexpr_variable_must_have_literal_type:
    +
    a constexpr variable must have a literal type or a reference type
    +
    +

    2403

    +
    constexpr_ctor_with_virtual_base:
    +
    a constructor for a class with virtual bases cannot be constexpr
    +
    +

    2404

    +
    bad_cpp11_constant_function_call:
    +
    function call must have a constant value in a constant expression
    +
    +

    2405

    +
    constexpr_main:
    +
    function “main” may not be declared constexpr
    +
    +

    2407

    +
    tag_defined_in_constexpr_body:
    +
    a class or enum type definition cannot appear in a constexpr function +or constructor body
    +
    +

    2408

    +
    only_gnu_attributes_here:
    +
    only GNU-style attributes are permitted here
    +
    +

    2409

    +
    auto_used_two_ways:
    +
    nonstandard use of “auto” to both deduce the type from an initializer +and to announce a trailing return type
    +
    +

    2410

    +
    nonstd_qualified_void_param_list:
    +
    declaring a void parameter list with a qualified void type is +nonstandard
    +
    +

    2411

    +
    qualifier_ignored_on_local_declaration:
    +
    the qualifier on this local declaration is ignored
    +
    +

    2412

    +
    bad_conv_constant_expr_type:
    +
    this constant expression has type “type” instead of the required +xxxx type
    +
    +

    2413

    +
    bad_argument_for_bases:
    +
    an instantiation of __bases or __direct_bases requires a class type
    +
    +

    2414

    +
    bad_prototype_argument_for_bases:
    +
    the argument of __bases and __direct_bases must be a type template +parameter
    +
    +

    2415

    +
    bases_not_in_template:
    +
    xxxx can only be used in template contexts
    +
    +

    2416

    +
    constexpr_return_not_constant:
    +
    constexpr function return is non-constant
    +
    +

    2417

    +
    nonconstexpr_call_in_mem_initializer:
    +
    constexpr constructor calls non-constexpr entity-kind “entity”
    +
    +

    2418

    +
    nonconstant_field_initializer_in_mem_initializer:
    +
    constructor cannot be constexpr because the initializer of +entity-kind “entity” is not a constant expression
    +
    +

    2419

    +
    nonconstant_mem_init_for_constexpr_ctor:
    +
    non-constant initializer for constexpr constructor
    +
    +

    2420

    +
    generated_default_constructor_used_in_field_initializer:
    +
    the generated default constructor for “type” cannot be used in an +initializer for its own data member
    +
    +

    2421

    +
    recursive_initializer_instantiation:
    +
    instantiation of initializer of entity-kind “entity” depends on +its own value
    +
    +

    2422

    +
    defaulted_default_ctor_cannot_be_constexpr:
    +
    defaulted default constructor cannot be constexpr because the +corresponding implicitly declared default constructor would not be +constexpr
    +
    +

    2424

    +
    bad_binary_digit:
    +
    invalid binary number
    +
    +

    2425

    +
    multiple_union_field_initializers:
    +
    a union can have at most one field initializer – entity-kind +“entity” (declared at line xxxx) also has an initializer
    +
    +

    2427

    +
    union_constexpr_constructor_initializes_no_field:
    +
    constexpr constructor of a union must initialize one of its fields
    +
    +

    2428

    +
    constexpr_constructor_initializes_no_variant_field:
    +
    constexpr constructor fails to initialize an anonymous union (defined +at line xxxx)
    +
    +

    2429

    +
    constexpr_static_data_member_without_initializer:
    +
    a constexpr static data member declaration requires an in-class +initializer
    +
    +

    2430

    +
    cl_max_constexpr_option_only_in_cplusplus:
    +
    maximum constexpr depth/count options can be used only when compiling +C++
    +
    +

    2431

    +
    excessive_constexpr_complexity:
    +
    expression not folded to a constant due to excessive constexpr +function call complexity
    +
    +

    2432

    +
    cl_unrestricted_unions_option_only_in_cplusplus:
    +
    unrestricted union options can be used only when compiling C++
    +
    +

    2433

    +
    constexpr_ctor_does_not_initialize_base:
    +
    constexpr constructor must initialize direct base class “type”
    +
    +

    2434

    +
    field_initializer_list:
    +
    creation of an std::initializer_list object in a field initializer is +unlikely to work as expected because the underlying array will be +destroyed at the end of the full expression
    +
    +

    2435

    +
    this_not_constant:
    +
    “this” cannot be used in a constant expression
    +
    +

    2437

    +
    constexpr_explicit_instantiation:
    +
    “constexpr” is not allowed on an explicit instantiation directive
    +
    +

    2438

    +
    generated_default_ctor_exception_spec_circularity:
    +
    cannot determine the exception specification of the default +constructor due to a circular dependency
    +
    +

    2439

    +
    anon_union_at_decl_position:
    +
    anonymous union defined at line xxxx
    +
    +

    2440

    +
    unbounded_constexpr_ctor_init_recursion:
    +
    this constructor uses the initializer of entity-kind “entity”(declared at line xxxx), which would result in unbounded recursion
    +
    +

    2442

    +
    block_extern_initializer_not_allowed:
    +
    an initializer is not allowed on a local declaration of an extern +variable
    +
    +

    2443

    +
    local_named_register_initializer_not_allowed:
    +
    an initializer is not allowed on a local declaration of a named +register variable
    +
    +

    2445

    +
    cl_unrestricted_unions_in_microsoft_mode:
    +
    unrestricted unions cannot be enabled in Microsoft mode
    +
    +

    2446

    +
    delegation_loop:
    +
    constructor delegates directly or indirectly to itself
    +
    +

    2447

    +
    delegation_init_and_mem_init:
    +
    a delegating constructor cannot have other mem-initializers
    +
    +

    2448

    +
    ref_qualifier_not_allowed:
    +
    a ref-qualifier is not allowed here
    +
    +

    2449

    +
    same_param_types_with_and_without_ref_qualifiers:
    +
    overloading two member functions with the same parameter types +requires that they both have ref-qualifiers or both lack +ref-qualifiers
    +
    +

    2450

    +
    bad_raw_string_delim_char:
    +
    invalid character in raw string delimiter
    +
    +

    2451

    +
    missing_raw_string_delim_lparen:
    +
    parenthesis terminating raw string delimiter not found within 16 +characters – raw string indicator ignored
    +
    +

    2452

    +
    missing_raw_string_delimiter:
    +
    ending delimiter for raw string not found
    +
    +

    2453

    +
    pack_not_last_arg:
    +
    a parameter pack must be the final template argument in a partial +specialization
    +
    +

    2454

    +
    pm_call_obj_not_lvalue:
    +
    a pointer-to-member function with type “type” can only be used +with an lvalue object
    +
    +

    2455

    +
    pm_call_obj_not_rvalue:
    +
    a pointer-to-member function with type “type” can only be used +with an rvalue object
    +
    +

    2456

    +
    defaulted_copy_ctor_cannot_have_const_parameter:
    +
    the parameter of this defaulted copy-constructor cannot be const +because a base or member copy constructor parameter is non-const
    +
    +

    2457

    +
    defaulted_assignment_cannot_have_const_parameter:
    +
    the parameter of this defaulted assignment operator cannot be const +because a base or member copy assignment parameter is non-const
    +
    +

    2458

    +
    empty_anonymous_union:
    +
    an anonymous union must contain at least one nonstatic data member
    +
    +

    2459

    +
    delegating_constructor_requires_newer_abi_version:
    +
    option “delegating_constructors” requires a different compiler +configuration
    +
    +

    2460

    +
    alignment_reduction_unconditionally_ignored:
    +
    a reduction in alignment is ignored
    +
    +

    2461

    +
    bad_rvalue_ref_const_cast_operand:
    +
    the operand of a const_cast to an rvalue reference type cannot be a +non-class prvalue
    +
    +

    2462

    +
    expr_not_a_glvalue:
    +
    expression must be an lvalue or xvalue
    +
    +

    2463

    +
    lossy_conversion:
    +
    conversion may change the value
    +
    +

    2464

    +
    deprecated_string_conv:
    +
    conversion from a string literal to “char *” is deprecated
    +
    +

    2465

    +
    deprecated_string_conv_gen:
    +
    conversion from a string literal to pointer-to-character (non-const) +is deprecated
    +
    +

    2466

    +
    override_and_final_is_cpp11:
    +
    “override” and “final” are C++11 features
    +
    +

    2467

    +
    rvalue_reference_in_exception_specification:
    +
    rvalue references are not allowed as exception specification types
    +
    +

    2468

    +
    attr_disallows_handler_param:
    +
    attribute “xxxx” does not apply to handler parameters
    +
    +

    2469

    +
    attr_requires_handler_param:
    +
    attribute “xxxx” requires a handler parameter
    +
    +

    2470

    +
    wrong_entity_for_alignas:
    +
    alignas does not apply here
    +
    +

    2471

    +
    std_alignof_with_expr_arg:
    +
    the standard “alignof” operator does not accept an expression +argument (use a type instead)
    +
    +

    2472

    +
    bad_qualifier_for_member_enum_decl:
    +
    invalid qualifier for “type” (a derived class is not allowed here)
    +
    +

    2473

    +
    always_inline_requires_inline:
    +
    the “always_inline” attribute is ignored on non-inline functions
    +
    +

    2474

    +
    inheriting_ctor_not_from_direct_base:
    +
    inheriting constructors must be inherited from a direct base class
    +
    +

    2476

    +
    exp_asm_label:
    +
    expected a label
    +
    +

    2477

    +
    missing_label_operand_number:
    +
    expected an operand number after “%”
    +
    +

    2478

    +
    label_operand_number_out_of_range:
    +
    operand number for “%” does not refer to a valid label argument
    +
    +

    2479

    +
    wide_string_invalid_in_asm:
    +
    a wide string is invalid in an “asm” statement
    +
    +

    2480

    +
    attribute_is_nonstandard:
    +
    attribute is nonstandard
    +
    +

    2481

    +
    decltype_is_not_base_class:
    +
    not a base class of class “type”
    +
    +

    2482

    +
    bad_user_defined_suffix:
    +
    non-identifier character in user-defined literal suffix
    +
    +

    2483

    +
    multichar_ud_lit:
    +
    a multicharacter literal cannot be part of a user-defined literal
    +
    +

    2484

    +
    ud_string_suffix_mismatch:
    +
    user-defined literal suffix does not match the earlier “xxxx”
    +
    +

    2485

    +
    invalid_literal_operator_id:
    +
    invalid literal operator name
    +
    +

    2486

    +
    literal_operator_not_found:
    +
    user-defined literal operator not found
    +
    +

    2487

    +
    ambig_literal_operator:
    +
    ambiguous literal operators and/or literal operator template:
    +
    +

    2488

    +
    udl_cannot_be_class_member:
    +
    a literal operator cannot be a member of a class
    +
    +

    2489

    +
    extern_c_literal_operator:
    +
    a literal operator cannot have extern “C” name linkage
    +
    +

    2490

    +
    no_parameter_for_literal_operator:
    +
    at least one parameter expected for a literal operator
    +
    +

    2491

    +
    too_many_parameters_for_literal_operator:
    +
    too many parameters for this literal operator
    +
    +

    2492

    +
    invalid_parameter_type_for_literal_operator:
    +
    invalid parameter type “type” for literal operator
    +
    +

    2493

    +
    invalid_integer_parameter_for_literal_operator:
    +
    invalid integer parameter type (“type”) for literal operator; +expected a character type or unsigned long long
    +
    +

    2494

    +
    invalid_float_parameter_for_literal_operator:
    +
    invalid floating-point parameter type (“type”) for literal +operator; expected long double
    +
    +

    2495

    +
    pointer_to_nonconst_for_literal_operator:
    +
    invalid first parameter type (“type”) for literal operator; +pointer to non-const type is not allowed
    +
    +

    2496

    +
    invalid_second_parameter_type_for_literal_operator:
    +
    invalid second parameter type (“type”) for literal operator; must +be size_t
    +
    +

    2497

    +
    invalid_pointer_parameter_for_literal_operator:
    +
    invalid pointer parameter type (“type”) for literal operator; +expected a pointer to a character type
    +
    +

    2498

    +
    ellipsis_parameter_for_literal_operator:
    +
    a literal operator cannot have an ellipsis parameter
    +
    +

    2499

    +
    invalid_parameter_for_literal_operator_template:
    +
    a literal operator template cannot have any parameters
    +
    +

    2500

    +
    invalid_template_parameter_for_literal_operator_template:
    +
    a literal operator template must have a template parameter list +equivalent to “<char …>”
    +
    +

    2501

    +
    thread_local_not_allowed:
    +
    thread-local storage class is not valid here
    +
    +

    2502

    +
    thread_local_follows_non_thread_local:
    +
    thread-local declaration follows non-thread-local declaration +(declared at line xxxx)
    +
    +

    2503

    +
    non_thread_local_follows_thread_local:
    +
    non-thread-local declaration follows thread-local declaration +(declared at line xxxx)
    +
    +

    2504

    +
    default_arg_for_literal_operator:
    +
    a literal operator cannot have default arguments
    +
    +

    2505

    +
    attribute_ignored_for_thread_local:
    +
    attribute is ignored for thread-local variables
    +
    +

    2506

    +
    lit_suffix_no_underscore:
    +
    a user-provided literal suffix must begin with “_”
    +
    +

    2507

    +
    rvalue_references_is_cpp11:
    +
    rvalue references are a C++11 feature
    +
    +

    2508

    +
    lambdas_is_cpp11:
    +
    lambda expressions are a C++11 feature
    +
    +

    2509

    +
    std_attributes_is_cpp11:
    +
    standard attribute syntax is a C++11 feature
    +
    +

    2510

    +
    delegating_constructor_is_cpp11:
    +
    delegating constructors are a C++11 feature
    +
    +

    2511

    +
    inheriting_constructor_is_cpp11:
    +
    inheriting constructors are a C++11 feature
    +
    +

    2512

    +
    field_initializers_is_cpp11:
    +
    field initializers are a C++11 feature
    +
    +

    2513

    +
    deleted_functions_is_cpp11:
    +
    deleted functions are a C++11 feature
    +
    +

    2514

    +
    defaulted_functions_is_cpp11:
    +
    defaulted functions are a C++11 feature
    +
    +

    2515

    +
    storage_class_not_allowed_in_specialization:
    +
    a storage class is not allowed in an explicit specialization
    +
    +

    2517

    +
    specialization_of_unscoped_enum:
    +
    an unscoped enumeration must be opaque in order to be specialized
    +
    +

    2518

    +
    nonmember_enum_template:
    +
    an enumeration template declaration must refer to a previously +declared member of a class template
    +
    +

    2519

    +
    operand_must_be_vector:
    +
    expected a vector operand
    +
    +

    2520

    +
    incompatible_shuffle_source_operands:
    +
    shuffle source operands have incompatible types “type” and +“type”
    +
    +

    2521

    +
    nonintegral_shuffle_mask:
    +
    shuffle mask (type “type”) is not a vector of integers
    +
    +

    2522

    +
    incompatible_shuffle_mask:
    +
    shuffle mask (type “type”) has a length different from the source +operand (type “type”)
    +
    +

    2523

    +
    bad_size_for_static_address_init:
    +
    static initialization with an address value requires a destination of +the same size as the address
    +
    +

    2524

    +
    feature_test_macro_req_id:
    +
    the argument to a feature-test macro must be a simple identifier
    +
    +

    2525

    +
    has_include_next_in_primary_source_file:
    +
    __has_include_next cannot be used in the primary source file
    +
    +

    2526

    +
    absolute_file_name_in_has_include_next:
    +
    absolute file name used in __has_include_next
    +
    +

    2527

    +
    attr_not_applied_to_function_type:
    +
    attribute “xxxx” must be applied to a function type
    +
    +

    2529

    +
    bad_c11_noreturn:
    +
    _Noreturn is not allowed here
    +
    +

    2530

    +
    operand_must_be_real_floating_value:
    +
    expected an operand of real floating-point type (not “type”)
    +
    +

    2531

    +
    incompatible_builtin_complex_types:
    +
    __builtin_complex requires operands of compatible types (unlike +“type” and “type”)
    +
    +

    2532

    +
    default_association_appears_more_than_once:
    +
    a default association already appeared in this _Generic selection
    +
    +

    2533

    +
    variably_modified_type_not_allowed_here:
    +
    a type involving a variable length array is not allowed here
    +
    +

    2534

    +
    duplicate_type_in_c11_generic:
    +
    duplicate association type (“type”) in _Generic selection
    +
    +

    2535

    +
    no_match_in_c11_generic:
    +
    no association matches the selector type “type”
    +
    +

    2536

    +
    incompatible_ifunc_resolver_type:
    +
    the type of entity-kind “entity” (“type”) is incompatible +with an ifunc resolver type
    +
    +

    2537

    +
    ifunc_cant_be_alias:
    +
    a function cannot have both ifunc and alias attributes
    +
    +

    2538

    +
    ifunc_cant_be_weak:
    +
    a function cannot have both ifunc and weak attributes
    +
    +

    2539

    +
    call_requires_string_literal:
    +
    call requires a string literal operand
    +
    +

    2540

    +
    duplicate_inheriting_constructor:
    +
    duplicate inheriting constructor declaration (previous at line +xxxx)
    +
    +

    2541

    +
    modified_decltype_auto_type:
    +
    “decltype(auto)” must be a placeholder for the complete type of the +variable (not for a component of that type)
    +
    +

    2542

    +
    decltype_auto_not_allowed_here:
    +
    decltype(auto) is not allowed here
    +
    +

    2543

    +
    decltype_auto_type_requires_initializer:
    +
    cannot deduce “decltype(auto)” (initializer required)
    +
    +

    2544

    +
    cannot_deduce_decltype_auto_type:
    +
    cannot deduce “decltype(auto)” type
    +
    +

    2545

    +
    thread_local_must_include_static_or_extern:
    +
    a block-scope thread-local declaration must include static or extern
    +
    +

    2546

    +
    deduced_return_type_conflict:
    +
    deduced return type “type” conflicts with previously deduced type +“type”
    +
    +

    2547

    +
    use_of_undefined_function_with_deduced_return_type:
    +
    cannot deduce the return type of entity-kind “entity” (declared +at line xxxx); it has not been defined
    +
    +

    2548

    +
    virtual_function_cannot_have_deduced_return_type:
    +
    a virtual function cannot have a deduced return type
    +
    +

    2549

    +
    keyword_dropped:
    +
    entity-kind “entity” will be treated as a context-sensitive +keyword from this point
    +
    +

    2550

    +
    global_ns_has_no_actual_member:
    +
    the global namespace has no actual member “xxxx”
    +
    +

    2551

    +
    different_enum_comparison:
    +
    comparison between two different enum types (“type” and +“type”)
    +
    +

    2552

    +
    unrecognized_target_attribute:
    +
    target attribute not recognized
    +
    +

    2553

    +
    gnu_mv_default_missing:
    +
    missing “default” target function
    +
    +

    2554

    +
    gnu_mv_only_one_arch:
    +
    only one arch= target may be specified
    +
    +

    2555

    +
    generic_class_cannot_be_custom_attribute:
    +
    a generic class cannot be a custom attribute
    +
    +

    2556

    +
    invalid_ms_attribute_target:
    +
    invalid attribute target “xxxx”
    +
    +

    2557

    +
    ambiguous_ms_attribute:
    +
    ambiguous attribute – both “type” and “type” could be used
    +
    +

    2558

    +
    cli_attribute_inaccessible_field:
    +
    a named attribute argument can only reference a public nonstatic +read/write field or scalar property
    +
    +

    2559

    +
    cli_attribute_invalid_field:
    +
    a named attribute argument can only reference a nonstatic field or +scalar property of an attribute parameter type
    +
    +

    2560

    +
    cli_attribute_invalid_argument:
    +
    invalid attribute argument – expression must be a constant of an +attribute parameter type
    +
    +

    2561

    +
    cli_typeid_of_generic_param_in_attribute:
    +
    an attribute argument cannot use generic type parameters
    +
    +

    2562

    +
    invalid_use_of_standalone_custom_ms_attr:
    +
    “type” may only be used as a standalone attribute
    +
    +

    2563

    +
    field_target_on_nontrivial_property_or_event:
    +
    the ‘field’ attribute target cannot be used on a non-trivial +property/event
    +
    +

    2564

    +
    invalid_attribute_target_for_standalone_ms_attr:
    +
    invalid attribute target for a standalone attribute
    +
    +

    2565

    +
    invalid_attribute_target_for_ms_attr:
    +
    invalid attribute target for this context
    +
    +

    2566

    +
    invalid_use_of_custom_ms_attr:
    +
    “type” attribute cannot be used here
    +
    +

    2567

    +
    cli_param_array_attribute_deprecated:
    +
    “type” is deprecated; use ‘…’ to specify a parameter array
    +
    +

    2568

    +
    namespace_default_cannot_be_extended:
    +
    the default namespace cannot be extended
    +
    +

    2569

    +
    cppcx_box_invalid_type:
    +
    the boxed type must be a value class or enum
    +
    +

    2570

    +
    tracking_reference_to_value_class:
    +
    tracking reference to value class is not allowed
    +
    +

    2571

    +
    handle_to_value_class:
    +
    handle to value class is not allowed
    +
    +

    2572

    +
    tracking_reference_to_enum:
    +
    tracking reference to enum is not allowed
    +
    +

    2573

    +
    handle_to_enum:
    +
    handle to enum is not allowed
    +
    +

    2574

    +
    cppcx_public_native_type:
    +
    a public native type is not allowed
    +
    +

    2575

    +
    public_nested_type_in_cppcx_type:
    +
    a public nested type is not allowed
    +
    +

    2576

    +
    cppcx_generic_type_not_allowed:
    +
    generic types are not permitted in C++/CX
    +
    +

    2577

    +
    cppcx_generic_method_not_allowed:
    +
    generic methods are not permitted in C++/CX
    +
    +

    2578

    +
    cppcx_generic_constraints_not_allowed:
    +
    generic constraints are not allowed
    +
    +

    2579

    +
    nonpublic_data_member_in_public_cppcx_value_type:
    +
    non-public data members are not allowed in public C++/CX value types
    +
    +

    2580

    +
    public_nondata_member_in_public_cppcx_value_type:
    +
    public non-data members are not allowed in public C++/CX value types
    +
    +

    2581

    +
    cppcx_public_value_class_constructor:
    +
    constructors are not allowed in public C++/CX value types
    +
    +

    2582

    +
    bad_cppcx_event_add_return:
    +
    the return type of the “add” accessor must be +Windows::Foundation::EventRegistrationToken
    +
    +

    2583

    +
    bad_cppcx_event_remove_return:
    +
    the return type of the “remove” accessor must be void
    +
    +

    2584

    +
    bad_cppcx_event_remove_parameter:
    +
    the parameter type of the “remove” accessor must be +Windows::Foundation::EventRegistrationToken
    +
    +

    2585

    +
    cppcx_handle_or_ref_to_generic_param:
    +
    a handle or reference to a generic parameter type is not allowed
    +
    +

    2586

    +
    public_data_member_in_public_non_value_type:
    +
    public data members are not allowed in non-value types
    +
    +

    2587

    +
    cl_cppcx_only_in_microsoft_cplusplus:
    +
    C++/CX can be enabled only in Microsoft C++ mode
    +
    +

    2588

    +
    cl_cppcx_and_cppcli:
    +
    C++/CLI and C++/CX modes cannot be combined
    +
    +

    2589

    +
    cppcx_not_enabled:
    +
    “xxxx” requires C++/CX mode
    +
    +

    2590

    +
    cl_microsoft_version_insufficient_for_cppcx:
    +
    C++/CX mode requires microsoft_version >= 1600
    +
    +

    2591

    +
    literal_fields_disallowed_in_cppcx_mode:
    +
    Literal fields are not allowed in C++/CX
    +
    +

    2592

    +
    normal_ref_bound_to_cppcx_lvalue:
    +
    a standard reference cannot be bound to a C++/CX type
    +
    +

    2593

    +
    cppcx_enum_base_has_no_platform_counterpart:
    +
    type must correspond to Platform::Boolean, default::uint8, +default::int8, default::int16, default::uint16, default::int32, +default::uint32, default::int64, or default::uint64
    +
    +

    2594

    +
    event_in_cppcx_value_type:
    +
    a C++/CX value type cannot have events
    +
    +

    2595

    +
    bad_cppcx_dynamic_cast_type:
    +
    a dynamic_cast to a handle type must refer to a complete class type
    +
    +

    2596

    +
    cppcx_array_only_one_dimension_allowed:
    +
    Platform::Array can only be one-dimensional
    +
    +

    2597

    +
    cppcx_tracking_reference_on_standard_class_type:
    +
    tracking reference to standard class type is not allowed
    +
    +

    2598

    +
    cppcx_value_type_deriving_from_interface:
    +
    a C++/CX value type cannot inherit from an interface
    +
    +

    2599

    +
    cppcx_value_type_contains_virtual_function:
    +
    a C++/CX value type cannot contain virtual functions
    +
    +

    2600

    +
    partial_class_incorrect_type_or_location:
    +
    “partial” can only be applied to “ref class” or “ref struct” at +global scope or namespace scope
    +
    +

    2601

    +
    cppcx_invalid_array_property_set_value_parameter:
    +
    the parameter of the “set” accessor must be of type “const +Platform::Array<T>^”
    +
    +

    2602

    +
    cppcx_public_global_type:
    +
    the definition of a public C++/CX type is not allowed at global scope
    +
    +

    2603

    +
    cppcx_public_indexed_property:
    +
    an indexed property with a public “get” or “set” accessor is not +allowed
    +
    +

    2604

    +
    cppcx_public_nested_delegate:
    +
    a public nested delegate type is not allowed
    +
    +

    2605

    +
    cppcx_bad_delegate_init_list:
    +
    invalid delegate initializer – expected either “(<function-address +or functor-object> [, Platform::CallbackContext])” or “(<object +handle>, <member-address> [, Platform::CallbackContext [, bool]])”
    +
    +

    2606

    +
    cppcx_invalid_delegate_object:
    +
    invalid delegate initializer – object must be a handle to a managed +class
    +
    +

    2607

    +
    cppcx_non_const_array_parameter:
    +
    C++/CX does not support ‘in/out’ arrays – use “const +Platform::Array<T>^” for ‘in’ and “Platform::WriteOnlyArray<T>^” or +“Platform::Array<T>^*” for ‘out’ on public APIs
    +
    +

    2608

    +
    missing_target_attribute:
    +
    missing “target” attribute for entity-kind “entity” (declared at +line xxxx)
    +
    +

    2609

    +
    no_matching_target_attribute:
    +
    no declared member function matches “target” attributes for +entity-kind “entity”
    +
    +

    2610

    +
    invalid_base_for_ms_attributes:
    +
    Microsoft attributes in this location are only permitted for +interface types
    +
    +

    2611

    +
    resolver_routine_required:
    +
    GNU function multiversion resolver routine required
    +
    +

    2612

    +
    enum_in_managed_class_missing_definition:
    +
    an enum type declared in a managed class must include a definition
    +
    +

    2613

    +
    decltype_qualified_declared_name:
    +
    a decltype-qualified name is nonstandard in this declaration context
    +
    +

    2614

    +
    final_modifier_requires_virtual_function:
    +
    nonvirtual function cannot be declared with “final” modifier
    +
    +

    2615

    +
    target_on_special_function:
    +
    “target” attribute on special function is not supported
    +
    +

    2616

    +
    target_string_must_be_narrow:
    +
    must be a narrow string literal
    +
    +

    2617

    +
    target_unmatched_parens:
    +
    unmatched parentheses
    +
    +

    2618

    +
    gcc_pragma_nothing_to_pop:
    +
    no corresponding “push_options”
    +
    +

    2619

    +
    pragma_inside_function:
    +
    this pragma is not allowed inside a function
    +
    +

    2620

    +
    inline_new_or_delete_operator:
    +
    declaring a new or delete operator “inline” is nonstandard
    +
    +

    2621

    +
    pack_expansion_for_field_mem_init:
    +
    a mem-initializer for a data member cannot be a pack expansion
    +
    +

    2622

    +
    generic_lambda_cannot_capture:
    +
    generic lambda expressions cannot have capture defaults in this mode
    +
    +

    2623

    +
    friend_with_def_arg_must_be_definition:
    +
    a default template argument in a friend declaration may only be +specified in a definition
    +
    +

    2624

    +
    friend_with_def_arg_must_be_only_decl:
    +
    a friend template declaration with a default template argument must +be the only declaration (first declared at line xxxx)
    +
    +

    2625

    +
    non_autonomous_opaque_enum_decl:
    +
    an opaque enum declaration cannot be part of another declaration
    +
    +

    2626

    +
    nonstd_opaque_enum_decl_in_type_id:
    +
    an opaque enum declaration is nonstandard in this context
    +
    +

    2627

    +
    extended_friends_is_cpp11:
    +
    extended friend syntax is a C++11 feature
    +
    +

    2628

    +
    digit_separators_not_enabled:
    +
    digit separators not enabled, apostrophe begins a character literal
    +
    +

    2629

    +
    bad_digit_separator_pos:
    +
    digit separator cannot appear here
    +
    +

    2630

    +
    constexpr_ignored_on_microsoft_nonstatic_member:
    +
    “constexpr” is ignored here in Microsoft mode
    +
    +

    2631

    +
    bad_gnu_stmt_return:
    +
    invalid expression for statement expression result
    +
    +

    2632

    +
    macro_not_udl_suffix:
    +
    identifier is a macro and not a literal suffix
    +
    +

    2633

    +
    cannot_call_named_member_on_lvalue:
    +
    entity-kind “entity” (declared at line xxxx) cannot be called +on an lvalue
    +
    +

    2634

    +
    cannot_call_named_member_on_rvalue:
    +
    entity-kind “entity” (declared at line xxxx) cannot be called +on an rvalue
    +
    +

    2635

    +
    cannot_call_member_on_lvalue:
    +
    member function cannot be called on an lvalue
    +
    +

    2636

    +
    cannot_call_member_on_rvalue:
    +
    member function cannot be called on an rvalue
    +
    +

    2637

    +
    templ_param_list_too_long:
    +
    the template parameter list is too long
    +
    +

    2638

    +
    bad_alias_templ_redecl:
    +
    alias template type “type” is incompatible with the previous type +of “type” in the redeclaration of entity-kind “entity”(declared at line xxxx)
    +
    +

    2639

    +
    field_initializer_is_not_constant:
    +
    the field initializer for entity-kind “entity” (declared at line +xxxx) is not a constant expression
    +
    +

    2640

    +
    constraint_number_mismatch:
    +
    the number of operand constraints must be the same in each constraint +string
    +
    +

    2641

    +
    too_many_constraints:
    +
    the constraint string contains too many alternative constraints; not +all constraints were checked
    +
    +

    2643

    +
    decltype_auto_cannot_be_qualified:
    +
    decltype(auto) cannot have added type qualifiers
    +
    +

    2644

    +
    bad_init_capture_capture:
    +
    init-capture “entity” (declared at line xxxx) cannot be +captured here
    +
    +

    2645

    +
    invalid_nontype_template_argument:
    +
    invalid nontype template argument of type “type”
    +
    +

    2646

    +
    abi_tag_ignored_in_C_mode:
    +
    the abi_tag attribute is ignored (it has no meaning in C mode)
    +
    +

    2647

    +
    abi_tag_redefinition:
    +
    redeclaration adds abi_tag attribute “xxxx“
    +
    +

    2648

    +
    abi_tag_ignored:
    +
    abi_tag attribute is ignored (superseded by later abi_tag attribute)
    +
    +

    2649

    +
    no_abi_tag_on_declaration:
    +
    previous declaration of entity-kind “entity” (declared at line +xxxx) had no abi_tag attribute
    +
    +

    2651

    +
    abi_tag_ignored_on_specialization:
    +
    abi_tag attribute is ignored on specialization
    +
    +

    2652

    +
    decltype_auto_return_must_be_standalone:
    +
    decltype(auto) cannot appear under a pointer, reference, or +pointer-to-member construct
    +
    +

    2653

    +
    exp_class_or_typename:
    +
    expected “class” or “typename”
    +
    +

    2654

    +
    placement_new_refers_to_non_placement_delete:
    +
    placement “new” expression refers to non-placement entity-kind +“entity” (declared at line xxxx)
    +
    +

    2655

    +
    cl_must_specify_cpp14_mode:
    +
    must specify C++14 mode when building runtime library
    +
    +

    2659

    +
    constexpr_not_const:
    +
    constexpr non-static member function will not be implicitly ‘const’ +in C++14
    +
    +

    2660

    +
    nonliteral_var_in_constexpr_function:
    +
    variable type “type” in constexpr function is not a literal type
    +
    +

    2661

    +
    nonautomatic_var_in_constexpr_function:
    +
    variable in constexpr function does not have automatic storage +duration
    +
    +

    2662

    +
    uninitialized_var_in_constexpr_function:
    +
    variable in constexpr function is uninitialized
    +
    +

    2663

    +
    auto_direct_list_init_requires_singleton:
    +
    braced initialization of a variable declared with a placeholder type +but without “=” requires exactly one element inside the braces
    +
    +

    2664

    +
    cl_invalid_target:
    +
    no “xxxx“ –target configuration exists
    +
    +

    2665

    +
    attribute_not_supported_in_x86_64:
    +
    attribute is supported only in 32-bit x86 configurations
    +
    +

    2666

    +
    cl_missing_argument:
    +
    “xxxx“ requires an argument
    +
    +

    2667

    +
    special_member_coroutine:
    +
    a constructor or destructor cannot be a coroutine
    +
    +

    2668

    +
    main_coroutine:
    +
    entity-kind “entity” cannot be a coroutine
    +
    +

    2669

    +
    yield_in_catch:
    +
    co_yield expressions are not permitted in a catch clause
    +
    +

    2674

    +
    special_class_template_not_found:
    +
    class template “xxxx” not found
    +
    +

    2675

    +
    typename_needed:
    +
    use the “typename” keyword to treat entity-kind “entity” as a +type in a dependent context
    +
    +

    2676

    +
    shufflevector_index_out_of_range:
    +
    argument value must be less than the sum of the vector elements
    +
    +

    2677

    +
    not_a_type_member:
    +
    “type” has no member “xxxx”
    +
    +

    2678

    +
    braced_list_for_implicit_return_type:
    +
    a brace-enclosed list does not provide a return type
    +
    +

    2679

    +
    await_not_allowed_outside_function_scope:
    +
    a co_await expression must appear in a function scope
    +
    +

    2680

    +
    await_not_allowed_in_catch_clause:
    +
    a co_await expression is not allowed inside a catch clause
    +
    +

    2681

    +
    coroutine_with_ellipsis_parameter:
    +
    a coroutine cannot have an ellipsis parameter
    +
    +

    2682

    +
    cl_relaxed_constexpr_requires_bool:
    +
    enabling C++14-style constexpr requires support for “bool”
    +
    +

    2683

    +
    constexpr_function_undefined:
    +
    constexpr entity-kind “entity” (declared at line xxxx) is not +defined
    +
    +

    2684

    +
    constexpr_call_not_interpretable:
    +
    this call cannot be evaluated because the target function +entity-kind “entity” (declared at line xxxx) is not constexpr +or not completely defined yet
    +
    +

    2687

    +
    anon_union_alias_member_template:
    +
    invalid anonymous union – alias member template is not allowed
    +
    +

    2688

    +
    utf8_char_lit_too_long:
    +
    a UTF-8 character literal value cannot occupy more than one code unit
    +
    +

    2689

    +
    variable_not_constant_valued:
    +
    the value of entity-kind “entity” (declared at line xxxx) +cannot be used as a constant
    +
    +

    2690

    +
    variable_not_constant_addressed:
    +
    a pointer or reference to entity-kind “entity” (declared at line +xxxx) cannot be used as a constant
    +
    +

    2691

    +
    constexpr_non_array_subscript:
    +
    nonzero subscript for non-array object
    +
    +

    2692

    +
    constexpr_out_of_bounds_array_access:
    +
    cannot access position n in array of n elements
    +
    +

    2693

    +
    constexpr_called_from:
    +
    called from:
    +
    +

    2694

    +
    constexpr_union_field_inactive:
    +
    invalid access to inactive entity-kind “entity” of union +(entity-kind “entity” is active)
    +
    +

    2695

    +
    constexpr_goto:
    +
    ‘goto’ cannot be executed in constexpr contexts
    +
    +

    2696

    +
    constexpr_missing_return_value:
    +
    missing return value
    +
    +

    2697

    +
    constexpr_null_callee:
    +
    callee is null
    +
    +

    2698

    +
    constexpr_null_dereference:
    +
    attempt to dereference a null pointer
    +
    +

    2699

    +
    constexpr_access_one_past_array_end:
    +
    attempt to access storage one position past the end of an array of +n elements
    +
    +

    2700

    +
    constexpr_access_to_expired_storage:
    +
    attempt to access expired storage
    +
    +

    2701

    +
    constexpr_access_to_runtime_storage:
    +
    attempt to access run-time storage
    +
    +

    2703

    +
    constexpr_call_to_nonconstexpr_function:
    +
    cannot call non-constexpr entity-kind “entity” (declared at line +xxxx)
    +
    +

    2704

    +
    constexpr_vla:
    +
    cannot use variable-length array during constexpr evaluation
    +
    +

    2705

    +
    constexpr_negative_shift:
    +
    cannot perform a negative shift
    +
    +

    2706

    +
    constexpr_shift_excess:
    +
    shift amount (n) too large
    +
    +

    2707

    +
    constexpr_integer_overflow:
    +
    value exceeds range of “type”
    +
    +

    2708

    +
    constexpr_fp_error:
    +
    floating-point error
    +
    +

    2709

    +
    constexpr_null_ptr_to_member_data:
    +
    attempt to dereference a null pointer-to-member (data member)
    +
    +

    2710

    +
    comparison_of_pointers_to_void_and_function:
    +
    comparing a pointer to void and a pointer to a function is nonstandard
    +
    +

    2711

    +
    ms_metadata_init_failed:
    +
    metadata initialization failed
    +
    +

    2712

    +
    constexpr_bad_derived_class_cast:
    +
    invalid base-to-derived cast (actual derived class type is “type”)
    +
    +

    2713

    +
    constexpr_invalid_pm_access:
    +
    invalid access to entity-kind “entity” in object of complete type +“type”
    +
    +

    2714

    +
    bad_gnu_auto_type:
    +
    “xxxx” not allowed here
    +
    +

    2715

    +
    gnu_auto_type_with_secondary_declarator:
    +
    “xxxx” does not permit multiple declarators
    +
    +

    2716

    +
    auto_type_brace_initialization_not_allowed:
    +
    initialization with “{…}” is not allowed for “xxxx”
    +
    +

    2717

    +
    modified_auto_type:
    +
    “xxxx” must be a placeholder for the complete type of the +variable (not for a component of that type)
    +
    +

    2718

    +
    gnu_auto_type_without_initializer:
    +
    a variable declared with “xxxx” requires an initializer
    +
    +

    2719

    +
    constant_must_be_positive:
    +
    integer constant must be greater than or equal to zero
    +
    +

    2720

    +
    type_must_be_integral:
    +
    type must be an integral type
    +
    +

    2721

    +
    constexpr_expression_cannot_be_interpreted:
    +
    expression cannot be interpreted
    +
    +

    2722

    +
    constexpr_statement_cannot_be_interpreted:
    +
    statement cannot be interpreted
    +
    +

    2723

    +
    constexpr_interpreter_address:
    +
    invalid use of address of interpreter storage
    +
    +

    2724

    +
    constexpr_invalid_constant_kind:
    +
    invalid constant kind for constant-expression
    +
    +

    2725

    +
    constexpr_type_too_large:
    +
    type “type” too large for constant-expression evaluation
    +
    +

    2726

    +
    constexpr_type_invalid:
    +
    invalid type “type” for constant-expression evaluation
    +
    +

    2727

    +
    constexpr_invalid_type_conversion:
    +
    conversion from “type” to “type” is invalid in +constant-expression evaluation
    +
    +

    2728

    +
    constexpr_fp_conversion_failed:
    +
    floating-point conversion failed
    +
    +

    2730

    +
    deduced_return_types_is_cpp14:
    +
    deduced return types are a C++14 feature
    +
    +

    2731

    +
    constexpr_ctor_with_dtor:
    +
    cannot evaluate a constructor with an associated destructor
    +
    +

    2732

    +
    constexpr_missing_initializer_for_field:
    +
    entity-kind “entity” not initialized during constexpr evaluation
    +
    +

    2733

    +
    constexpr_invalid_pdiff:
    +
    invalid pointer difference in constexpr evaluation
    +
    +

    2734

    +
    constexpr_non_array_pointer_arithmetic:
    +
    invalid arithmetic on non-array pointer
    +
    +

    2735

    +
    constexpr_pointer_ahead_of_array:
    +
    cannot set pointer before the first array element
    +
    +

    2736

    +
    coroutine_with_deduced_return_type:
    +
    a coroutine with a deduced return type is invalid
    +
    +

    2737

    +
    await_in_unevaluated_operand:
    +
    expression not allowed in unevaluated context
    +
    +

    2740

    +
    return_in_coroutine:
    +
    “return” is not permitted in a coroutine (use “co_return” instead)
    +
    +

    2741

    +
    invalid_co_return:
    +
    “co_return” is only allowed in coroutines
    +
    +

    2742

    +
    constexpr_fp_values_not_comparable:
    +
    floating-point values cannot be compared
    +
    +

    2743

    +
    constexpr_pointers_not_comparable:
    +
    pointer values cannot be compared because they do not point into the +same complete object or they point to subobjects with different +accessibility
    +
    +

    2744

    +
    ignoring_attribute_on_non_inline_namespace:
    +
    ignoring abi_tag attribute on non-inline namespace
    +
    +

    2745

    +
    ignoring_attribute_on_anonymous_namespace:
    +
    ignoring abi_tag attribute on anonymous namespace
    +
    +

    2746

    +
    complex_template_parameter:
    +
    complex or imaginary template parameter type is nonstandard
    +
    +

    2747

    +
    yield_outside_of_function:
    +
    co_yield expression is not permitted outside a function scope
    +
    +

    2748

    +
    thread_local_ignored:
    +
    ignoring thread-local indication on anonymous union
    +
    +

    2751

    +
    object_not_initialized:
    +
    access to uninitialized object
    +
    +

    2752

    +
    constexpr_volatile_fetch:
    +
    attempt to read from volatile storage
    +
    +

    2753

    +
    constexpr_no_active_union_field:
    +
    invalid access to inactive entity-kind “entity” of union (no +field is active)
    +
    +

    2754

    +
    label_in_constexpr_function:
    +
    label definitions cannot appear in constexpr functions
    +
    +

    2755

    +
    constexpr_equality_past_the_end_address:
    +
    cannot compare a pointer past the end of an array with a pointer to +another complete object
    +
    +

    2756

    +
    variable_templ_function_type:
    +
    function type “type” is an invalid type for a variable template +instantiation
    +
    +

    2757

    +
    incomplete_var_type:
    +
    variable cannot have incomplete type “type”
    +
    +

    2758

    +
    field_subobject_not_initialized:
    +
    access to uninitialized subobject (entity-kind “entity”)
    +
    +

    2759

    +
    base_subobject_not_initialized:
    +
    access to uninitialized subobject (base class “type”)
    +
    +

    2760

    +
    constexpr_vacuous_dtor_call:
    +
    a pseudo-destructor call is not permitted in a constant-expression
    +
    +

    2761

    +
    constexpr_modifying_const_storage:
    +
    attempt to modify const storage
    +
    +

    2764

    +
    constexpr_access_past_object:
    +
    attempt to access storage one position past an object treated as an +array of one element
    +
    +

    2765

    +
    constexpr_reinterpret_cast:
    +
    cannot use reinterpret_cast in constant-expression evaluation
    +
    +

    2766

    +
    constexpr_invalid_null_ptr_operation:
    +
    operation not allowed on null pointer
    +
    +

    2767

    +
    star_this_not_constant_valued:
    +
    the value of *this cannot be used as a constant
    +
    +

    2768

    +
    inline_on_nested_namespace:
    +
    the “inline” keyword cannot be used on a nested namespace declaration
    +
    +

    2769

    +
    carries_dependency_ignored:
    +
    the “carries_dependency” attribute is ignored
    +
    +

    2770

    +
    event_interface_cannot_have_definition:
    +
    an “__event __interface” cannot have a definition here
    +
    +

    2771

    +
    invalid_event_handler_type:
    +
    an event handler must have a void or integral return type
    +
    +

    2772

    +
    event_interface_must_be_previously_defined:
    +
    an “__event __interface” must have been previously defined
    +
    +

    2773

    +
    too_many_template_arguments:
    +
    too many template arguments for entity-kind “entity”
    +
    +

    2774

    +
    enumerator_already_declared:
    +
    enumerator already declared (see entity-kind “entity” (declared +at line xxxx))
    +
    +

    2775

    +
    microsoft_version_doesnt_support_cpp14_mode:
    +
    the version of Microsoft being emulated must be at least 1903 to use +“–ms_c++14”
    +
    +

    2776

    +
    microsoft_version_doesnt_support_cpplatest_mode:
    +
    the version of Microsoft being emulated must be at least 1903 to use +“–ms_c++latest”
    +
    +

    2777

    +
    c11_atomic_array_or_function_type:
    +
    type “type” cannot be _Atomic because it is an array or function +type
    +
    +

    2778

    +
    c11_atomic_specifier_with_qualified_type:
    +
    the _Atomic(…) specifier cannot be applied to qualified type +“type”
    +
    +

    2779

    +
    access_to_member_of_c11_atomic_object:
    +
    access to member of _Atomic object
    +
    +

    2780

    +
    c11_atomic_bit_field:
    +
    a bit field cannot have an _Atomic type
    +
    +

    2782

    +
    nonconstexpr_mem_init_ctor_for_constexpr_ctor:
    +
    constexpr constructor calls non-constexpr constructor for subobject +initialization
    +
    +

    2783

    +
    terse_static_assert_not_enabled:
    +
    expected a comma (the one-argument version of static_assert is not +enabled in this mode)
    +
    +

    2784

    +
    terse_static_assert:
    +
    static assertion failed
    +
    +

    2785

    +
    conflicting_nullability:
    +
    at most one of the qualifiers _Nullable, _Nonnull, and +_Null_unspecified can modify a type
    +
    +

    2786

    +
    invalid_type_for_nullability:
    +
    nullability qualifiers are only permitted on pointer and +pointer-to-member types
    +
    +

    2787

    +
    vector_length_too_large:
    +
    vector length is too large
    +
    +

    2788

    +
    invalid_vector_element_type:
    +
    vector element type must be integral, enum, or real floating-point +type
    +
    +

    2789

    +
    builtin_needs_128_bit_integers:
    +
    builtin function is not available because 128-bit integers are not +supported
    +
    +

    2790

    +
    builtin_needs_vector_types:
    +
    builtin function is not available because vector types are not +supported
    +
    +

    2791

    +
    must_introduce_attribute:
    +
    two consecutive left square brackets always introduce an attribute +list but an attribute list cannot appear here
    +
    +

    2792

    +
    invalid_target_attribute:
    +
    unrecognized “target” attribute disqualifies this routine from being +used by resolver routine
    +
    +

    2793

    +
    vector_type_required:
    +
    “type” is not a vector type
    +
    +

    2794

    +
    vector_types_differ_in_length:
    +
    vector types “type” and “type” must have the same length
    +
    +

    2795

    +
    member_special_after_class_definition:
    +
    added default arguments cannot result in declaring a default or copy +constructor
    +
    +

    2796

    +
    template_arg_cannot_point_to_subobject:
    +
    a nontype template argument of reference type must bind to a function +or to a complete object
    +
    +

    2797

    +
    type_not_allowed_here:
    +
    “type” not allowed here
    +
    +

    2798

    +
    register_keyword_disallowed:
    +
    use of the “register” storage class specifier is not allowed
    +
    +

    2799

    +
    register_keyword_deprecated:
    +
    use of the “register” storage class specifier is deprecated
    +
    +

    2800

    +
    incr_of_bool_not_allowed:
    +
    incrementing a bool value is not allowed
    +
    +

    2801

    +
    redeclaration_of_range_iterator:
    +
    “xxxx”, declared as iterator of range-based “for” statement, may +not be redeclared in this scope
    +
    +

    2802

    +
    namespace_not_allowed:
    +
    an attribute namespace may not be used here (because a “using” prefix +was specified)
    +
    +

    2803

    +
    attribute_namespace_unrecognized:
    +
    attribute namespace “xxxx” is unrecognized
    +
    +

    2804

    +
    default_member_init_for_value_class:
    +
    a default member initializer is not permitted in a value class
    +
    +

    2805

    +
    cl_implicit_noexcept_requires_noexcept_support:
    +
    “–implicit_noexcept” requires a mode that enables noexcept
    +
    +

    2806

    +
    constexpr_virtual_base:
    +
    cannot fold operation involving virtual base class (“type”)
    +
    +

    2807

    +
    initializer_not_constant:
    +
    initialization is not constant
    +
    +

    2808

    +
    constexpr_incomplete_type:
    +
    cannot evaluate value of incomplete “type”
    +
    +

    2809

    +
    nodiscard_routine:
    +
    ignoring return value from routine declared with “nodiscard” attribute
    +
    +

    2810

    +
    nodiscard_return_type:
    +
    ignoring return value type with “nodiscard” attribute
    +
    +

    2811

    +
    nodiscard_doesnt_apply:
    +
    the “nodiscard” attribute does not apply to destructors or routines +with void return type
    +
    +

    2812

    +
    fallthrough_applies_to_null_statement:
    +
    the “fallthrough” attribute only applies to null statements
    +
    +

    2813

    +
    fallthrough_not_in_switch:
    +
    the “fallthrough” attribute may only appear in an enclosing switch +statement
    +
    +

    2814

    +
    fallthrough_must_precede_switch_case:
    +
    fallthrough statement must precede switch case label or default
    +
    +

    2815

    +
    constexpr_expiring_temporary:
    +
    reference or pointer to temporary with limited lifetime
    +
    +

    2816

    +
    address_of_nontrue_enable_if_function:
    +
    cannot take the address of a function with an “enable_if” attribute +whose condition is not unconditionally true
    +
    +

    2817

    +
    nonconstant_enable_if_attr:
    +
    “enable_if” attributes with conditions that are not constant values +are not currently supported
    +
    +

    2818

    +
    attribute_declared_here:
    +
    attribute was declared here
    +
    +

    2819

    +
    has_include_not_in_if:
    +
    __has_include cannot appear outside #if
    +
    +

    2820

    +
    coclass_base_requirements_not_met:
    +
    could not add CComCoClass base class
    +
    +

    2821

    +
    constexpr_string_not_null_terminated:
    +
    not a null-terminated string
    +
    +

    2822

    +
    non_scalar_vacuous_dtor_call:
    +
    non-scalar type “type” cannot be used in a pseudo-destructor call
    +
    +

    2823

    +
    constexpr_weak_address:
    +
    address of “weak” entity-kind “entity” is not constant
    +
    +

    2824

    +
    excessive_rescan_depth:
    +
    too many recursive substitutions of function template signatures
    +
    +

    2825

    +
    invalid_struct_binding_specifier:
    +
    invalid specifier for structured binding declaration
    +
    +

    2826

    +
    invalid_struct_binding_syntax:
    +
    invalid structured binding syntax
    +
    +

    2827

    +
    missing_initializer:
    +
    missing initializer
    +
    +

    2828

    +
    invalid_struct_binding_type:
    +
    type “type” has no components to bind to
    +
    +

    2829

    +
    too_many_struct_bindings:
    +
    too many identifiers
    +
    +

    2830

    +
    missing_bindings:
    +
    there are more elements than there are binding names
    +
    +

    2831

    +
    missing_std_tuple_element:
    +
    “std::tuple_element” not defined
    +
    +

    2832

    +
    missing_std_tuple_element_instance:
    +
    cannot instantiate “std::tuple_element” for <xxxx, “type”>
    +
    +

    2833

    +
    failed_tuple_container_member_get:
    +
    cannot call member function “get<xxxx>()” for type “type”
    +
    +

    2834

    +
    tuple_get_no_matching_overload:
    +
    no instance of “entity” matches the argument list
    +
    +

    2835

    +
    struct_binding_undefined_identifier:
    +
    this structured binding requires a suitable “xxxx” function and +none was found
    +
    +

    2836

    +
    struct_binding_inline:
    +
    a structured binding cannot be declared “inline”
    +
    +

    2837

    +
    struct_binding_constexpr:
    +
    a structured binding cannot be declared “constexpr”
    +
    +

    2838

    +
    struct_binding_storage_class:
    +
    a structured binding cannot declare an explicit storage class
    +
    +

    2839

    +
    invalid_tuple_size:
    +
    std::tuple_size<”type”>::value is not a valid integral +constant-expression
    +
    +

    2840

    +
    condition_does_not_declare_a_variable:
    +
    a condition declaration must declare a variable
    +
    +

    2841

    +
    condition_decl_must_have_initializer:
    +
    a condition declaration must include an initializer
    +
    +

    2842

    +
    parenthesized_init_not_allowed:
    +
    a parenthesized initializer is not permitted for a condition +declaration
    +
    +

    2843

    +
    condition_with_multiple_declarators:
    +
    a condition declaration can only declare one variable
    +
    +

    2844

    +
    struct_binding_lambda:
    +
    structured binding cannot bind to closure type
    +
    +

    2845

    +
    struct_binding_private_member:
    +
    cannot bind to non-public entity-kind “entity”
    +
    +

    2846

    +
    struct_binding_incomplete_type:
    +
    cannot bind to incomplete type “type”
    +
    +

    2847

    +
    invalid_init_statement:
    +
    this declaration is not valid here
    +
    +

    2848

    +
    constexpr_function_with_function_try_block:
    +
    the body of a constexpr function cannot be a function try block
    +
    +

    2849

    +
    branch_into_constexpr_if:
    +
    transfer of control into a constexpr if block is not allowed
    +
    +

    2850

    +
    lambda_capture_structured_binding:
    +
    structured binding cannot be captured
    +
    +

    2851

    +
    microsoft_version_doesnt_support_cpp17_mode:
    +
    the version of Microsoft being emulated must be at least 1911 to use +“–ms_c++17”
    +
    +

    2852

    +
    attempt_to_read_past_end_of_object:
    +
    attempt to read past the end of the object
    +
    +

    2853

    +
    constexpr_lambdas_not_enabled:
    +
    constexpr lambdas are not enabled in this mode
    +
    +

    2854

    +
    lambda_not_constant_expr:
    +
    a constant expression cannot contain a lambda expression
    +
    +

    2855

    +
    template_argument_index_out_of_bounds:
    +
    value exceeds number of template arguments
    +
    +

    2856

    +
    fold_expression_operator_mismatch:
    +
    second operator in binary fold expression does not match first
    +
    +

    2857

    +
    invalid_fold_expression_operator:
    +
    invalid fold expression operator
    +
    +

    2858

    +
    two_packs_in_fold_expression:
    +
    a binary fold expression cannot apply to two parameter packs
    +
    +

    2859

    +
    invalid_empty_fold_expression:
    +
    empty expansion not valid for this fold expression
    +
    +

    2860

    +
    inline_nonstatic_data_mem:
    +
    a nonstatic data member cannot be declared as inline
    +
    +

    2861

    +
    no_pack_in_fold_expression:
    +
    fold expression does not refer to a parameter pack
    +
    +

    2862

    +
    same_param_types_with_different_exception_specifications:
    +
    two functions with the same parameter types but different exception +specifications cannot be overloaded
    +
    +

    2863

    +
    dynamic_exc_spec_not_permitted:
    +
    dynamic exception specifications are not permitted in this mode
    +
    +

    2865

    +
    invalid_noexcept_specifier_operand:
    +
    invalid operand for noexcept specifier
    +
    +

    2866

    +
    lambda_in_noexcept_specifier:
    +
    lambda expression cannot appear in noexcept specifier of a template
    +
    +

    2867

    +
    inaccessible_rvalue_dtor:
    +
    entity-kind “entity” (declared at line xxxx) is inaccessible
    +
    +

    2868

    +
    bad_enum_template_decl:
    +
    invalid specifier in enum template declaration
    +
    +

    2869

    +
    no_float80:
    +
    80-bit floating-point types are not supported in this configuration
    +
    +

    2870

    +
    no_float128:
    +
    128-bit floating-point types are not supported in this configuration
    +
    +

    2871

    +
    invalid_enumerator_value:
    +
    invalid enumerator value
    +
    +

    2872

    +
    must_be_atomic_qualified_type:
    +
    must be an _Atomic qualified type
    +
    +

    2873

    +
    element_type_incomplete:
    +
    type of array element must be complete
    +
    +

    2874

    +
    always_inline_suppressed:
    +
    the always_inline attribute has been suppressed for this function
    +
    +

    2875

    +
    negative_value:
    +
    a negative value is not permitted here
    +
    +

    2876

    +
    integer_pack_element_for_type:
    +
    an integer pack element cannot match entity-kind “entity”
    +
    +

    2877

    +
    integer_pack_element_for_template:
    +
    an integer pack element cannot match entity-kind “entity”
    +
    +

    2878

    +
    unexpected_designator:
    +
    unexpected designator
    +
    +

    2879

    +
    cannot_evaluate_builtin_offsetof:
    +
    cannot evaluate __builtin_offsetof
    +
    +

    2880

    +
    deduction_guide_def:
    +
    deduction guide “type” cannot be defined
    +
    +

    2881

    +
    bad_deduction_guide_scope:
    +
    deduction guide must be declared in the same scope as entity-kind +“entity”
    +
    +

    2882

    +
    invalid_specifier_for_deduction_guide:
    +
    invalid specifier for deduction guide declaration (only “explicit” is +permitted)
    +
    +

    2883

    +
    constexpr_mutable_field_load:
    +
    mutable entity-kind “entity” of a constant cannot be accessed in +a constant expression
    +
    +

    2884

    +
    member_function_modifier_on_static_member:
    +
    function modifier does not apply to static member declaration
    +
    +

    2885

    +
    overloadable_attribute_requires_prototype:
    +
    the “overloadable” attribute requires a prototyped function +declaration
    +
    +

    2886

    +
    cannot_deduce_auto_templ_param:
    +
    cannot deduce “auto” template parameter type “type” from +“type”
    +
    +

    2887

    +
    modified_class_template_placeholder:
    +
    class template name must be a placeholder for the complete type being +initialized (not for a component of that type)
    +
    +

    2888

    +
    alias_declaration_is_cpp11:
    +
    alias declarations are a C++11 feature
    +
    +

    2889

    +
    alias_template_is_cpp11:
    +
    alias templates are a C++11 feature
    +
    +

    2890

    +
    bad_deduction_guide_return_type:
    +
    the return type must directly designate a specialization of the +associated class template
    +
    +

    2891

    +
    explicit_deduction_guide_in_copy_list_init:
    +
    copy-list-initialization cannot use “explicit” entity-kind +“entity”
    +
    +

    2893

    +
    invalid_udl_value:
    +
    Invalid value for user-defined literal operator
    +
    +

    2894

    +
    has_cpp_attrib_not_in_if:
    +
    xxxx cannot appear outside of preprocessor directives
    +
    +

    2895

    +
    bad_deduction_guide_access:
    +
    deduction guide must be declared with the same accessibility as +entity-kind “entity”
    +
    +

    2896

    +
    lambda_not_allowed_here:
    +
    a lambda is not permitted in this context
    +
    +

    2897

    +
    align_not_equivalent:
    +
    specified alignment is not equivalent to previous declaration
    +
    +

    2898

    +
    no_alignment_on_definition:
    +
    no alignment specified on definition; previous declaration had +specified an alignment
    +
    +

    2899

    +
    builtin_needs_128_bit_floats:
    +
    builtin function is not available because 128-bit floating-point +types are not supported
    +
    +

    2900

    +
    constexpr_shift_negative_value:
    +
    left-shifting a negative value has undefined behavior
    +
    +

    2901

    +
    no_array_designators_in_cpp_mode:
    +
    array designators are nonstandard in C++
    +
    +

    2902

    +
    no_chained_designators_in_cpp_mode:
    +
    chained designators are nonstandard in C++
    +
    +

    2903

    +
    no_mixed_init_in_cpp_mode:
    +
    mixing designated and non-designated initializers is nonstandard in +C++
    +
    +

    2904

    +
    no_out_of_order_init_in_cpp_mode:
    +
    out-of-order initializers are nonstandard in C++
    +
    +

    2905

    +
    invalid_string_literal_operator_template:
    +
    a string literal operator template must have a template parameter +list equivalent to “<typename T, T …>”
    +
    +

    2906

    +
    duplicate_designator:
    +
    duplicate designator is not allowed
    +
    +

    2907

    +
    likely_unlikely_conflict:
    +
    attribute conflicts with previous likely/unlikely attribute
    +
    +

    2908

    +
    implicit_copy_this_capture_deprecated:
    +
    the implicit by-copy capture of “this” is deprecated
    +
    +

    2909

    +
    empty_lambda_template_param_list:
    +
    an empty template parameter list is not allowed in a lambda expression
    +
    +

    2910

    +
    microsoft_version_doesnt_support_cpp20_mode:
    +
    the version of Microsoft being emulated must be at least 1920 to use +“–ms_c++20”
    +
    +

    2911

    +
    bad_stdc_pragma_arg_for_mode:
    +
    STDC pragma argument not accepted in this mode
    +
    +

    2912

    +
    if_constexpr_is_cpp17:
    +
    constexpr if statements are a C++17 feature
    +
    +

    2913

    +
    no_pack_expansion_in_designator:
    +
    pack expansion is not allowed in a designated initializer list
    +
    +

    2914

    +
    no_designator_value:
    +
    field designator has no value
    +
    +

    2915

    +
    multiple_union_field_initializers_empty:
    +
    a union can have at most one field initializer
    +
    +

    2916

    +
    bad_ordering_type:
    +
    no valid std::xxxx type found (<compare> must be included)
    +
    +

    2917

    +
    invalid_spaceship_types:
    +
    invalid types (“type” and “type”) for built-in operator<=>
    +
    +

    2918

    +
    fold_expressions_nonstandard:
    +
    fold expressions are nonstandard in this mode
    +
    +

    2919

    +
    selection_initializer_nonstandard:
    +
    C++17-style initializer is nonstandard in this mode
    +
    +

    2920

    +
    star_this_capture_nonstandard:
    +
    capturing *this is nonstandard in this mode
    +
    +

    2921

    +
    using_attribute_nonstandard:
    +
    C++17-style “using” attribute prefix is nonstandard in this mode
    +
    +

    2922

    +
    nested_namespace_nonstandard:
    +
    C++17-style nested namespaces are nonstandard in this mode
    +
    +

    2923

    +
    constexpr_and_consteval_specifiers:
    +
    only one of “constexpr”, “consteval”, and “constinit” can appear on a +declaration
    +
    +

    2924

    +
    consteval_virtual_combination:
    +
    a function cannot be both consteval and virtual in this mode
    +
    +

    2925

    +
    consteval_explicit_instantiation:
    +
    “consteval” is not allowed on an explicit instantiation directive
    +
    +

    2926

    +
    invalid_consteval:
    +
    “consteval” is not valid here
    +
    +

    2927

    +
    consteval_destructor:
    +
    a destructor cannot be consteval
    +
    +

    2928

    +
    consteval_ctor_with_virtual_base:
    +
    a constructor for a class with virtual bases cannot be consteval
    +
    +

    2929

    +
    consteval_variable:
    +
    “consteval” is not permitted on the declaration of a variable or +static data member
    +
    +

    2930

    +
    previous_consteval_decl_conflict:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared consteval
    +
    +

    2931

    +
    previous_nonconsteval_decl_conflict:
    +
    entity-kind “entity” (declared at line xxxx) was previously +not declared consteval
    +
    +

    2932

    +
    consteval_main:
    +
    function “main” may not be declared consteval
    +
    +

    2933

    +
    consteval_call_nonconstant:
    +
    call to consteval entity-kind “entity” did not produce a valid +constant expression
    +
    +

    2934

    +
    address_of_consteval_function:
    +
    address of consteval entity-kind “entity” in constant expression +result
    +
    +

    2935

    +
    consteval_overrides_nonconsteval:
    +
    consteval member cannot override non-consteval entity-kind +“entity”
    +
    +

    2936

    +
    nonconsteval_overrides_consteval:
    +
    non-consteval member cannot override consteval entity-kind +“entity”
    +
    +

    2938

    +
    constexpr_invalid_dynamic_cast:
    +
    dynamic_cast to subobject of type “type” is invalid (most-derived +type is “type”)
    +
    +

    2939

    +
    VA_OPT_not_allowed:
    +
    the identifier __VA_OPT__ can only appear in the replacement lists +of variadic macros
    +
    +

    2940

    +
    nested_VA_OPT:
    +
    __VA_OPT__ cannot appear in a __VA_OPT__ operand
    +
    +

    2941

    +
    unclosed_VA_OPT:
    +
    missing closing parenthesis for __VA_OPT__
    +
    +

    2942

    +
    missing_VA_OPT_paren:
    +
    __VA_OPT__ must be followed by “(”
    +
    +

    2943

    +
    paste_cannot_be_first_in_VA_OPT:
    +
    “##” may not be first in a __VA_OPT__ operand
    +
    +

    2944

    +
    paste_cannot_be_last_in_VA_OPT:
    +
    “##” may not be last in a __VA_OPT__ operand
    +
    +

    2945

    +
    nested_inline_namespace_nonstandard:
    +
    C++20-style nested inline namespaces are nonstandard in this mode
    +
    +

    2946

    +
    derived_class_too_far:
    +
    cannot convert pointer to base class “type” to pointer to derived +class “type” – attempt to point beyond the most-derived object
    +
    +

    2948

    +
    invalid_variable_main:
    +
    “main” cannot be used as a global variable name or given C language +linkage
    +
    +

    2949

    +
    linkage_main:
    +
    function “main” cannot be declared in a linkage-specification
    +
    +

    2950

    +
    struct_binding_in_condition:
    +
    structured binding is not allowed in a condition
    +
    +

    2951

    +
    missing_attr_namespace:
    +
    an attribute namespace identifier is required before “::”
    +
    +

    2952

    +
    multiple_attr_namespaces:
    +
    only one attribute namespace is allowed
    +
    +

    2953

    +
    bad_return:
    +
    “return” not allowed here
    +
    +

    2954

    +
    struct_binding_with_multiple_declarators:
    +
    a structured binding cannot be combined with other declarators
    +
    +

    2955

    +
    branch_out_of_constant:
    +
    cannot branch out of a constant-evaluation context
    +
    +

    2956

    +
    struct_binding_template:
    +
    structured binding templates are not permitted
    +
    +

    2957

    +
    braced_init_in_parens:
    +
    a parenthesized initializer must be an expression, not a +brace-enclosed list
    +
    +

    2958

    +
    cannot_deduce_class_template_arguments:
    +
    cannot deduce class template arguments
    +
    +

    2959

    +
    consteval_new_or_delete_operator:
    +
    a new or delete operator cannot be declared “consteval”
    +
    +

    2960

    +
    address_of_consteval_function_leaked:
    +
    the address of a consteval function cannot be used here
    +
    +

    2961

    +
    alignof_function_type:
    +
    the alignment of a function type (“type”) is nonstandard
    +
    +

    2962

    +
    alignof_incomplete_array:
    +
    the alignment of an array of unspecified bound is nonstandard in C
    +
    +

    2963

    +
    cannot_be_common_internal_linkage:
    +
    a variable cannot have both “common” and “internal_linkage” attributes
    +
    +

    2964

    +
    internal_linkage_not_on_prior_declaration:
    +
    the “internal_linkage” attribute did not appear on a prior declaration
    +
    +

    2965

    +
    no_class_template_guide:
    +
    no viable template argument deduction candidate found for +entity-kind “entity”
    +
    +

    2966

    +
    fully_qualified_constructor_call:
    +
    a fully qualified constructor call is not allowed
    +
    +

    2967

    +
    bad_scope_for_defaulted_comparison:
    +
    a defaulted comparison operator must be a member or a friend of the +class it applies to
    +
    +

    2968

    +
    bad_param_type_for_defaulted_comparison:
    +
    bad type “type” for parameter of defaulted comparison operator +(must be “reference to const X” where X is the enclosing class type)
    +
    +

    2969

    +
    return_type_of_default_comparison_must_be_bool:
    +
    return type of defaulted comparison operator must be “bool”
    +
    +

    2970

    +
    nonconst_defaulted_member_comparison:
    +
    a defaulted member comparison operator must be “const”
    +
    +

    2972

    +
    no_return_value_and_return_void:
    +
    a coroutine’s promise type “type” cannot have both “return_void” +and “return_value” set
    +
    +

    2973

    +
    return_value_at:
    +
    “return_value” declared at line xxxx
    +
    +

    2974

    +
    return_void_at:
    +
    “return_void” declared at line xxxx
    +
    +

    2975

    +
    implicit_co_return_with_no_return_void:
    +
    missing co_return statement while “type” has no “return_void” at +end of entity-kind “entity”
    +
    +

    2976

    +
    no_nothrow_global_new_for_coroutine:
    +
    no nothrow variant of the global “operator new” found for coroutine +state allocation
    +
    +

    2977

    +
    no_viable_delete_for_coroutine:
    +
    no viable “operator delete” found for coroutine state deallocation
    +
    +

    2978

    +
    no_constexpr_coroutine:
    +
    a constexpr function cannot be a coroutine
    +
    +

    2979

    +
    await_operand_not_a_class:
    +
    the operand to this xxxx expression resolves to non-class +“type”
    +
    +

    2980

    +
    await_not_allowed_in_static_initializer:
    +
    a co_await expression is not allowed in a static initializer
    +
    +

    2981

    +
    final_suspend_cannot_throw:
    +
    the co_await expression calling entity-kind “entity” must be +non-throwing
    +
    +

    2982

    +
    excessive_comparison_rewrites:
    +
    too many recursive comparison rewrite operations
    +
    +

    2983

    +
    invalid_placeholder_for_defaulted_spaceship_return:
    +
    a deducible return type for a default operator<=> must be “auto”
    +
    +

    2984

    +
    constexpr_implied_source_nonconstant:
    +
    implicit copy of non-constant source
    +
    +

    2985

    +
    struct_binding_restricted_storage_class:
    +
    a structured binding cannot declare an explicit storage class other +than static or thread_local
    +
    +

    2986

    +
    defaulted_comparison_for_property:
    +
    defaulted comparison operators are not supported for nontrivial +Microsoft property fields
    +
    +

    2987

    +
    invalid_std_comparison_type:
    +
    standard comparison type (“type”) must be a class type with a +single nonstatic data member of integral type
    +
    +

    2988

    +
    invalid_std_comparison_value:
    +
    no constexpr static data member “xxxx” found in “type”
    +
    +

    2989

    +
    constexpr_alloc_too_large:
    +
    number of elements (n) too large for dynamic allocation
    +
    +

    2990

    +
    constexpr_allocation_too_large:
    +
    constexpr dynamic allocation request too large
    +
    +

    2991

    +
    constexpr_bad_deallocation:
    +
    deallocation of storage that was not dynamically allocated
    +
    +

    2992

    +
    constexpr_bad_deallocation_size:
    +
    deallocation size (n) does not correspond to size allocated +(n)
    +
    +

    2993

    +
    constexpr_allocation_pos:
    +
    allocation occurred here
    +
    +

    2994

    +
    constexpr_bad_deallocation_type:
    +
    deallocation type (“type”) does not correspond to allocation type +(“type”)
    +
    +

    2995

    +
    constexpr_leftover_allocations:
    +
    some dynamic allocations (total number = n) were not deallocated
    +
    +

    2996

    +
    constexpr_invalid_intrinsic_signature:
    +
    intrinsic entity-kind “entity” declared with unexpected signature +(type “type”)
    +
    +

    2997

    +
    constexpr_begin_report:
    +
    >> output from std::__report_constexpr_value
    +
    +

    2998

    +
    constexpr_end_report:
    +
    >> end output from std::__report_constexpr_value
    +
    +

    2999

    +
    constexpr_dependent_array_size:
    +
    cannot use array with dependent array size in constexpr evaluation
    +
    +

    3000

    +
    nodiscard_routine_with_reason:
    +
    ignoring return value from routine declared with “nodiscard” +attribute (“xxxx”)
    +
    +

    3001

    +
    nodiscard_return_type_with_reason:
    +
    ignoring return value type with “nodiscard” attribute (“xxxx”)
    +
    +

    3002

    +
    nodiscard_constructor:
    +
    constructor used to create discarded object has “nodiscard” attribute
    +
    +

    3003

    +
    nodiscard_constructor_with_reason:
    +
    constructor used to create discarded object has “nodiscard” attribute +(“xxxx”)
    +
    +

    3004

    +
    nodiscard_object_type:
    +
    type of discarded object has “nodiscard” attribute
    +
    +

    3005

    +
    nodiscard_object_type_with_reason:
    +
    type of discarded object has “nodiscard” attribute (“xxxx”)
    +
    +

    3006

    +
    vacuous_destructor_not_called:
    +
    a pseudo-destructor reference can only be used for a +pseudo-destructor call
    +
    +

    3007

    +
    constexpr_explicit_dtor_call:
    +
    an explicit destructor call is not permitted in a constant-expression
    +
    +

    3008

    +
    comma_operator_in_array_subscript_deprecated:
    +
    an unparenthesized comma operator in an array subscript expression is +deprecated
    +
    +

    3009

    +
    constexpr_alloc_too_small:
    +
    number of dynamically-allocated elements (n) too small for +initializer
    +
    +

    3011

    +
    volatile_ass_deprecated:
    +
    use of the result of an assignment to a volatile scalar object is +deprecated
    +
    +

    3012

    +
    volatile_op_ass_deprecated:
    +
    a volatile destination type for a compound assignment expression is +deprecated
    +
    +

    3013

    +
    volatile_func_param_deprecated:
    +
    a volatile function parameter is deprecated
    +
    +

    3014

    +
    volatile_return_type_deprecated:
    +
    a volatile return type is deprecated
    +
    +

    3015

    +
    volatile_str_bind_deprecated:
    +
    use of a volatile qualifier on a structured binding is deprecated
    +
    +

    3016

    +
    ext_vector_type_invalid_size:
    +
    the “ext_vector_type” argument must be between 1 and 2047
    +
    +

    3017

    +
    ext_vector_type_not_in_typedef:
    +
    the “ext_vector_type” attribute may appear only in a typedef
    +
    +

    3018

    +
    ext_vector_type_requires_integral_floating_type:
    +
    the “ext_vector_type” attribute applies only to integer or +floating-point types
    +
    +

    3019

    +
    feature_test_macro_ignored:
    +
    this feature-test macro is ignored (and returns 0) in the current +compilation mode
    +
    +

    3020

    +
    constexpr_multiple_union_initializers:
    +
    cannot evaluate an aggregate initializer with multiple elements for a +union
    +
    +

    3021

    +
    cmp_operator_does_not_return_bool:
    +
    entity-kind “entity” (declared at line xxxx) selected for +operator rewrite does not return type bool
    +
    +

    3022

    +
    constexpr_class_specific_new:
    +
    a new-expression calling a class-specific allocation function cannot +be constant-evaluated
    +
    +

    3023

    +
    constexpr_placement_new:
    +
    a placement new-expression cannot be constant-evaluated
    +
    +

    3024

    +
    constexpr_nonvirtual_subobject_delete:
    +
    deleting through a subobject pointer requires a virtual destructor
    +
    +

    3026

    +
    invalid_intaddr_address:
    +
    operand of __INTADDR__ must be offset from null pointer
    +
    +

    3027

    +
    ambiguous_c11_generic:
    +
    _Generic construct matches multiple types
    +
    +

    3028

    +
    ambiguous_c11_generic_previous_match:
    +
    the other match is “type”
    +
    +

    3029

    +
    availability_attribute_ignored:
    +
    the “availability” attribute used here is ignored
    +
    +

    3030

    +
    init_stmt_in_range_for_nonstandard:
    +
    C++20-style initializer statement in a range-based “for” statement is +nonstandard in this mode
    +
    +

    3031

    +
    co_await_on_non_range_based_for:
    +
    co_await can only apply to a range-based “for” statement
    +
    +

    3032

    +
    cannot_deduce_type_in_range_based_for:
    +
    cannot deduce type of range in range-based “for” statement
    +
    +

    3033

    +
    inline_variables_nonstandard:
    +
    inline variables are a C++17 feature
    +
    +

    3034

    +
    destroying_delete_wrong_type:
    +
    destroying operator delete requires “type” as first parameter
    +
    +

    3035

    +
    destroying_delete_with_extra_params:
    +
    a destroying operator delete cannot have parameters other than +std::size_t and std::align_val_t
    +
    +

    3036

    +
    cl_relaxed_abstract_checking_only_in_cplusplus:
    +
    relaxed abstract class options can be used only when compiling C++
    +
    +

    3037

    +
    invalid_start_of_requires_clause_expr:
    +
    invalid start of expression in requires clause
    +
    +

    3038

    +
    cast_in_requires_clause:
    +
    a cast expression in a requires-clause must be parenthesized
    +
    +

    3039

    +
    invalid_operator_in_requires_clause:
    +
    this operator cannot appear at the top level (without parentheses) in +a requires-clause
    +
    +

    3040

    +
    nonbool_atomic_constraint:
    +
    atomic constraint must have type bool
    +
    +

    3041

    +
    atomic_constraint_substitution_failed:
    +
    atomic constraint failed substitution
    +
    +

    3042

    +
    atomic_constraint_evaluation_failed:
    +
    atomic constraint not constant
    +
    +

    3043

    +
    atomic_constraint_false:
    +
    atomic constraint evaluates to false
    +
    +

    3044

    +
    template_constraint_not_satisfied:
    +
    template constraint not satisfied
    +
    +

    3045

    +
    bad_scope_for_concept:
    +
    concept definition cannot appear in this scope
    +
    +

    3046

    +
    invalid_concept_redecl:
    +
    invalid redeclaration of entity-kind “entity” (declared at line +xxxx)
    +
    +

    3047

    +
    concept_arg_list_substitution_failed:
    +
    substitution of arguments “<templ-args>” for concept-id failed
    +
    +

    3048

    +
    concept_failed:
    +
    concept is false for arguments “<templ-args>”
    +
    +

    3049

    +
    trailing_requires_clause_not_on_template:
    +
    a requires-clause is not allowed here (not a templated function)
    +
    +

    3051

    +
    requires_incompatible_with_previous_decl:
    +
    requires-clause incompatible with entity-kind “entity” (declared +at line xxxx)
    +
    +

    3052

    +
    expected_an_attribute:
    +
    expected an attribute
    +
    +

    3054

    +
    exp_type_name:
    +
    expected a type name
    +
    +

    3055

    +
    requires_expr_ellipsis_param:
    +
    an ellipsis parameter is not permitted in a requires-expression
    +
    +

    3056

    +
    unnamed_require_expr_param:
    +
    unnamed parameter in requires-expression has no effect
    +
    +

    3057

    +
    exp_concept_name:
    +
    expected a concept name
    +
    +

    3058

    +
    is_constant_evaluated_in_constant_expression:
    +
    call to xxxx appearing in a constant expression always produces +“true”
    +
    +

    3059

    +
    is_constant_evaluated_in_consteval_context:
    +
    call to xxxx appearing in a consteval context always produces +“true”
    +
    +

    3060

    +
    is_constant_evaluated_in_nonconstexpr_context:
    +
    call to xxxx appearing in a non-constexpr function always +produces “false”
    +
    +

    3061

    +
    type_constraint_failed:
    +
    type constraint failed for “type”
    +
    +

    3062

    +
    cl_export_template_option_incompatible_with_modules:
    +
    option “export” cannot be used in modes where C++ modules are enabled
    +
    +

    3063

    +
    glb_mod_fgmt_decl_must_come_first:
    +
    a global module fragment declaration must precede any other +declaration
    +
    +

    3064

    +
    module_decl_only_after_glb_mod:
    +
    a module declaration can only be preceded by a global module fragment
    +
    +

    3065

    +
    pvt_mod_fgmt_only_after_module:
    +
    a private module fragment must be preceded by a module declaration
    +
    +

    3066

    +
    cannot_export_fgmt:
    +
    a xxxx module fragment cannot be exported
    +
    +

    3067

    +
    more_than_one_module_decl:
    +
    cannot declare more than one module
    +
    +

    3068

    +
    more_than_one_fgmt_decl:
    +
    cannot declare more than one xxxx module fragment
    +
    +

    3069

    +
    module_req_primary_name:
    +
    a module must be declared with a non-empty name
    +
    +

    3070

    +
    header_not_importable:
    +
    “xxxx” is not an importable header
    +
    +

    3071

    +
    cannot_import_module_with_no_name:
    +
    cannot import a module with no name
    +
    +

    3072

    +
    module_cannot_depend_on_itself:
    +
    a module cannot have an interface dependency on itself
    +
    +

    3073

    +
    module_already_imported:
    +
    module “module name” has already been imported
    +
    +

    3075

    +
    module_file_not_found:
    +
    could not find module file for module “xxxx”
    +
    +

    3076

    +
    cannot_import_module:
    +
    could not import module file “xxxx”
    +
    +

    3079

    +
    unknown_ifc_partition:
    +
    unknown partition name “xxxx”
    +
    +

    3085

    +
    types_must_have_same_size:
    +
    the type of the second operand “type” must have the same size as +“type”
    +
    +

    3086

    +
    type_must_be_trivially_copyable:
    +
    type must be trivially copyable
    +
    +

    3087

    +
    unsupported_type_for_bit_cast:
    +
    type “type” is currently not supported for constexpr evaluation +of __builtin_bit_cast
    +
    +

    3088

    +
    bitfields_not_allowed:
    +
    class types with bitfields “type” are not currently supported for +constexpr evaluation of __builtin_bit_cast
    +
    +

    3089

    +
    reference_type_not_allowed:
    +
    non-static data member of reference type “type” prevents +constexpr evaluation of __builtin_bit_cast
    +
    +

    3090

    +
    volatile_type_not_allowed:
    +
    a volatile type “type” prevents constexpr evaluation of +__builtin_bit_cast
    +
    +

    3091

    +
    invalid_bit_cast_type:
    +
    a union, pointer, or pointer-to-member type “type” prevents +constexpr evaluation of __builtin_bit_cast
    +
    +

    3093

    +
    deleted_inh_def_constructor:
    +
    the sub-object construction of “type” for inheriting constructors +cannot be performed – the associated constructor is deleted
    +
    +

    3094

    +
    promise_type_returns_return_void:
    +
    entity-kind “entity” must return void
    +
    +

    3095

    +
    invalid_start_of_member_declaration:
    +
    invalid start of member declaration
    +
    +

    3096

    +
    exp_auto:
    +
    expected “auto”
    +
    +

    3097

    +
    operator_not_allowed_after_new:
    +
    this operator is not allowed at this point; parenthesize the +preceding new-expression
    +
    +

    3098

    +
    invalid_use_of_concept:
    +
    invalid use of concept
    +
    +

    3099

    +
    rvalue_defaulted_member_comparison:
    +
    a defaulted member comparison operator cannot be “&&”-qualified
    +
    +

    3100

    +
    constexpr_comparison_calls_nonconstexpr_function:
    +
    default constexpr comparison function calls non-constexpr function +entity-kind “entity” (declared at line xxxx)
    +
    +

    3101

    +
    invalid_constexpr_memcmp:
    +
    constexpr memory comparison is only supported for integer or +array-of-integer objects
    +
    +

    3102

    +
    constraint_concept_template:
    +
    a concept template cannot have associated constraints
    +
    +

    3103

    +
    export_not_allowed:
    +
    “export” is not allowed
    +
    +

    3104

    +
    export_class_members:
    +
    exporting individual class members is not allowed
    +
    +

    3105

    +
    export_must_introduce_name:
    +
    an exported declaration must introduce a name
    +
    +

    3106

    +
    export_cannot_contain_export:
    +
    an export declaration cannot contain an export declaration (previous +declaration at line xxxx)
    +
    +

    3107

    +
    export_cannot_contain_import:
    +
    an export declaration cannot contain a module import declaration
    +
    +

    3108

    +
    export_only_in_modules:
    +
    an export declaration can only appear in a module interface unit
    +
    +

    3109

    +
    export_internal_linkage:
    +
    an export declaration cannot export a name with internal linkage
    +
    +

    3112

    +
    empty_requires_expression:
    +
    a requires-expression must specify at least one requirement
    +
    +

    3113

    +
    invalid_constinit:
    +
    “constinit” is not valid here
    +
    +

    3114

    +
    constinit_variable_storage:
    +
    “constinit” is only valid for declarations of variables with static +or thread storage duration
    +
    +

    3115

    +
    constinit_variable_has_dynamic_init:
    +
    constinit variable requires dynamic initialization
    +
    +

    3116

    +
    missing_constinit:
    +
    variable was previously declared with “constinit” at line xxxx
    +
    +

    3117

    +
    use_of_non_prototype_func_declarator:
    +
    use of non-prototype function declarator
    +
    +

    3118

    +
    cannot_be_const_qualified:
    +
    argument cannot have a const-qualified type
    +
    +

    3119

    +
    ptr_to_mem_of_incomplete_class:
    +
    a pointer-to-member of an incomplete type “type” is not allowed
    +
    +

    3120

    +
    pack_init_capture_not_enabled:
    +
    pack expansion in init-capture not enabled in this mode
    +
    +

    3121

    +
    pack_init_capture_is_cpp20:
    +
    pack expansion in init-capture is a C++20 feature
    +
    +

    3122

    +
    comparison_defaulted_in_class_must_be_first_decl:
    +
    a comparison operator defaulted in a class definition must be the +first declaration of that comparison operator (entity-kind +“entity” (declared at line xxxx))
    +
    +

    3123

    +
    pack_init_capture_in_non_variadic_context:
    +
    a pack expansion in an init-capture can be used only in a variadic +template
    +
    +

    3124

    +
    type_constraint_requires_type_concept:
    +
    type constraint uses entity-kind “entity” (declared at line +xxxx) that is not a type concept (i.e., a concept template whose +first parameter is a type parameter)
    +
    +

    3125

    +
    placeholder_type_failed_constraint:
    +
    the deduced placeholder type “type” failed the type constraint
    +
    +

    3126

    +
    ineligible_default_constructor:
    +
    default constructor for “type” is not eligible
    +
    +

    3127

    +
    ambiguous_destructor_constraints:
    +
    destructor for “type” is ambiguous because of unordered +constraints
    +
    +

    3128

    +
    failed_destructor_constraints:
    +
    destructor for “type” is ineligible because of failed constraints
    +
    +

    3129

    +
    destructor_position:
    +
    ambiguous destructor candidate
    +
    +

    3130

    +
    trailing_requires_on_virtual_func:
    +
    a virtual function cannot have a trailing requires clause
    +
    +

    3131

    +
    function_ineligible:
    +
    entity-kind “entity” (declared at line xxxx) does not satisfy +its constraints
    +
    +

    3132

    +
    bad_decltype_qualifier:
    +
    result of decltype qualifier “type” is not a class or enumeration
    +
    +

    3133

    +
    cpp20_reversed_comparison_ambiguity:
    +
    comparison is ambiguous in standard C++20 because the implied +comparison operator with reversed parameters is an equally good match +– this is usually caused by a missing “const” qualifier on the +comparison operator; see “entity” (declared at line xxxx)
    +
    +

    3134

    +
    invalid_concept_id:
    +
    invalid concept-id
    +
    +

    3135

    +
    requires_clause_arg_list_substitution_failed:
    +
    substitution of arguments “<templ-args>” for requires-clause +failed
    +
    +

    3136

    +
    ineligible_member_function:
    +
    constraints for entity-kind “entity” (declared at line xxxx) +are not satisfied
    +
    +

    3137

    +
    var_with_virtual_bases_in_constexpr_function:
    +
    variable type “type” in constexpr function has virtual base +classes
    +
    +

    3138

    +
    constexpr_object_with_virtual_base:
    +
    a constant expression cannot allocate a virtual base subobject (for +type “type”)
    +
    +

    3139

    +
    template_parameter_has_nonstructural_class_type:
    +
    a template parameter of class type must be of structural class type
    +
    +

    3140

    +
    utf8_lit_no_ulit:
    +
    support for UTF-8 literals requires u-literal support.
    +
    +

    3141

    +
    duplicate_module_map:
    +
    module file mapping for “xxxx“ specified more than once
    +
    +

    3142

    +
    duplicate_header_unit_map:
    +
    header unit mapping for “xxxx“ specified more than once
    +
    +

    3143

    +
    missing_header_unit_map:
    +
    no mapping specified for “xxxx“
    +
    +

    3145

    +
    cannot_find_header_for_import:
    +
    cannot find header “xxxx“ to import
    +
    +

    3146

    +
    multiple_module_matches:
    +
    more than one file in the module file list matches “xxxx“
    +
    +

    3147

    +
    module_file_mismatch:
    +
    module file found for “xxxx“ is for a different module
    +
    +

    3149

    +
    module_read_error:
    +
    unable to read module file
    +
    +

    3150

    +
    builtin_needs_char8_t:
    +
    builtin function is not available because the char8_t type is not +supported with the current options
    +
    +

    3152

    +
    nonstandard_use_of_explicit_default_constructor:
    +
    nonstandard use of explicit constructor “entity” (declared at +line xxxx) for default aggregate element initialization
    +
    +

    3153

    +
    constexpr_memcpy_operand_not_object:
    +
    source or destination of memcpy-like intrinsic does not point to an +object
    +
    +

    3154

    +
    constexpr_memcpy_distinct_types:
    +
    memcpy-like intrinsic attempts to copy representationally-distinct +types “type” and “type”
    +
    +

    3155

    +
    constexpr_memcpy_nontrivial_type:
    +
    memcpy-like intrinsic attempts to copy nontrivially-copyable type +“type”
    +
    +

    3156

    +
    constexpr_memcpy_partial_object:
    +
    memcpy-like intrinsic attempts to copy partial object
    +
    +

    3157

    +
    constexpr_memcpy_overflow:
    +
    memcpy-like intrinsic attempts to copy past array boundary
    +
    +

    3158

    +
    constexpr_memcpy_overlap:
    +
    memcpy-like intrinsic attempts to copy overlapping byte ranges (using +corresponding memmove operation instead)
    +
    +

    3159

    +
    nondefining_friend_requires_clause:
    +
    a friend declaration with a trailing-requires-clause must be a +definition
    +
    +

    3160

    +
    type_not_scalar:
    +
    expression must have arithmetic or pointer type but has type +“type”
    +
    +

    3161

    +
    type_not_arithmetic_or_enum_or_pointer:
    +
    expression must have arithmetic, enum, or pointer type but has type +“type”
    +
    +

    3162

    +
    type_not_arithmetic_or_unscoped_enum_or_pointer:
    +
    expression must have arithmetic, unscoped enum, or pointer type but +has type “type”
    +
    +

    3163

    +
    type_not_pointer:
    +
    expression must have pointer type but it has type “type”
    +
    +

    3164

    +
    member_access_requires_pointer:
    +
    operator -> or ->* applied to “type” instead of to a pointer type
    +
    +

    3166

    +
    cannot_interpret_target_bits:
    +
    cannot interpret bit layout for this compilation target
    +
    +

    3167

    +
    ifc_no_corresponding_operator:
    +
    no corresponding operator for IFC operator “xxxx”
    +
    +

    3168

    +
    ifc_no_corresponding_calling_conv:
    +
    no corresponding calling convention for IFC calling convention +“xxxx”
    +
    +

    3169

    +
    module_file_contains_unsupported_constructs:
    +
    module “module name” contains unsupported constructs
    +
    +

    3170

    +
    unhandled_ifc_construct:
    +
    unsupported IFC construct: “xxxx”
    +
    +

    3171

    +
    is_signed_no_longer_a_keyword:
    +
    __is_signed is no longer a keyword from this point
    +
    +

    3172

    +
    dim_not_const_unsigned_int:
    +
    an array dimension must have a constant unsigned integer value
    +
    +

    3174

    +
    modules_not_enabled:
    +
    modules are not enabled in this mode
    +
    +

    3175

    +
    import_name_not_allowed:
    +
    “import” is not allowed in a module name
    +
    +

    3176

    +
    module_name_not_allowed:
    +
    “module” is not allowed in a module name
    +
    +

    3179

    +
    not_an_enum_type:
    +
    entity-kind “entity” is not an enum type
    +
    +

    3180

    +
    using_enum_conflicts:
    +
    enumerator “entity” conflicts with entity-kind “entity”
    +
    +

    3181

    +
    using_enum_redecl:
    +
    enumerator “entity” has already been declared in this scope at +line xxxx
    +
    +

    3182

    +
    empty_throw_specification_not_cpp20:
    +
    the “throw()” specification is not part of C++20 and later
    +
    +

    3183

    +
    multiple_header_map_matches:
    +
    more than entry in the header unit map matches “xxxx“
    +
    +

    3184

    +
    exp_push_pop:
    +
    #pragma diagnostic must have either ‘push’ or ‘pop’ argument
    +
    +

    3185

    +
    no_corresponding_push:
    +
    no ‘#pragma diagnostic push’ was found to match this ‘diagnostic pop’
    +
    +

    3186

    +
    macro_in_pp_directive:
    +
    “xxxx” cannot be a macro when used in an import or module +directive
    +
    +

    3187

    +
    not_global_namespace:
    +
    this directive can only appear in the global namespace scope
    +
    +

    3188

    +
    export_not_at_namespace_scope:
    +
    an “export” declaration can appear only at global or namespace scope
    +
    +

    3189

    +
    identifier_not_keyword:
    +
    “xxxx” is parsed as an identifier rather than a keyword because +the tokens that follow it do not match those of a preprocessor +directive
    +
    +

    3190

    +
    apparent_module_pp_directive:
    +
    this appears to be the start of a preprocessor directive, but the +lack of a ‘;’ followed immediately by a newline prevents that
    +
    +

    3191

    +
    module_directive_in_macro:
    +
    this appears to be a modules preprocessing directive, but such +directives cannot appear within a macro expansion
    +
    +

    3192

    +
    module_directive_in_if:
    +
    a “module” directive cannot appear within the scope of conditional +inclusion (e.g., #if, #else, #elseif, etc.)
    +
    +

    3193

    +
    import_skipped:
    +
    the import of “xxxx” has been skipped
    +
    +

    3194

    +
    bad_gro_on_alloc_fail:
    +
    promise type “type” must declare +get_return_object_on_allocation_failure as a static member function +requiring no arguments
    +
    +

    3195

    +
    expl_spec_alias_template:
    +
    an alias template cannot be explicitly specialized
    +
    +

    3196

    +
    matching_lbrace:
    +
    to match this “{”
    +
    +

    3197

    +
    macro_invocation:
    +
    in this macro invocation
    +
    +

    3198

    +
    call_with_unusable_argument_conversion:
    +
    call requires an ambiguous argument conversion
    +
    +

    3199

    +
    named_module_source_conflict:
    +
    declaration owned by module xxxx conflicts with entity-kind +“entity” (declared at line xxxx)
    +
    +

    3200

    +
    global_module_source_conflict:
    +
    declaration owned by global module conflicts with entity-kind +“entity” (declared at line xxxx) owned by a named module
    +
    +

    3201

    +
    bad_malloc_attribute:
    +
    the first argument to a “malloc” attribute must be a function
    +
    +

    3202

    +
    cannot_capture_var:
    +
    cannot capture “entity” (declared at line xxxx)
    +
    +

    3203

    +
    cannot_capture_this:
    +
    cannot capture “this”
    +
    +

    3204

    +
    already_in_consteval_context:
    +
    already in consteval context
    +
    +

    3205

    +
    if_consteval_requires_braced_dependent_statement:
    +
    “if consteval” and “if not consteval” require braced dependent +statements
    +
    +

    3206

    +
    if_consteval_in_nonconstexpr_function:
    +
    “if consteval” and “if not consteval” are meaningless in a +non-constexpr function
    +
    +

    3207

    +
    branch_into_if_consteval:
    +
    transfer of control into an “if consteval” or “if not consteval” +statement is not allowed
    +
    +

    3208

    +
    constexpr_local_static:
    +
    constant-evaluation cannot go through the declaration of a variable +with static or thread storage duration
    +
    +

    3209

    +
    mutable_qualifier_on_explicit_this_lambda:
    +
    the mutable qualifier is not allowed on a lambda with an explicit +“this” parameter
    +
    +

    3210

    +
    static_with_explicit_this:
    +
    a member function declared with “static” cannot have an explicit +“this” parameter
    +
    +

    3211

    +
    explicit_this_param_must_be_first:
    +
    an explicit “this” parameter must be the first declared parameter
    +
    +

    3212

    +
    bad_this:
    +
    “this” is not allowed here
    +
    +

    3214

    +
    explicit_this_needs_this:
    +
    an explicit “this” function requires a selector operand
    +
    +

    3215

    +
    if_consteval_nonstandard:
    +
    “if consteval” and “if not consteval” are not standard in this mode
    +
    +

    3216

    +
    lambda_without_parameters_nonstandard:
    +
    omitting “()” in a lambda declarator is nonstandard in this mode
    +
    +

    3217

    +
    lambda_without_parameters_requires_clause:
    +
    a trailing-requires-clause is not permitted when the lambda parameter +list is omitted
    +
    +

    3218

    +
    invalid_ifc_partition:
    +
    module “module name” invalid partition requested
    +
    +

    3219

    +
    undefined_ifc_partition:
    +
    module “module name” undefined partition (believed to be +“xxxx”) requested
    +
    +

    3222

    +
    invalid_overflowing_ifc_position:
    +
    module “module name” file position n (relative position +n) requested for partition “xxxx” - which overflows the end +of its partition
    +
    +

    3223

    +
    invalid_misaligned_ifc_position:
    +
    module “module name” file position n (relative position +n) requested for partition “xxxx” - which is misaligned with +its partitions elements
    +
    +

    3224

    +
    invalid_ifc_position_backtrace_field:
    +
    from subfield “xxxx” (relative position to node n)
    +
    +

    3225

    +
    invalid_ifc_position_backtrace_pos:
    +
    from partition “xxxx” element n (file position n, +relative position n)
    +
    +

    3226

    +
    nonstandard_lambda_attributes:
    +
    attributes on lambdas are a C++23 feature
    +
    +

    3227

    +
    confusable_identifier:
    +
    identifier “xxxx” could be confused with a visually-similar one +appearing at line xxxx
    +
    +

    3228

    +
    suspicious_comment_formatting:
    +
    this comment contains suspicious Unicode formatting control characters
    +
    +

    3229

    +
    suspicious_string_formatting:
    +
    this string contains Unicode formatting control characters that could +result in unexpected runtime behavior
    +
    +

    3230

    +
    suppressed_module_warning_diag:
    +
    n suppressed warning was encountered while processing module +“module name”
    +
    +

    3231

    +
    suppressed_module_warnings_diag:
    +
    n suppressed warnings were encountered while processing module +“module name”
    +
    +

    3232

    +
    suppressed_module_error_diag:
    +
    n suppressed error was encountered while processing module +“module name”
    +
    +

    3233

    +
    suppressed_module_errors_diag:
    +
    n suppressed errors were encountered while processing module +“module name”
    +
    +

    3236

    +
    virtual_with_explicit_this:
    +
    a virtual member function cannot have an explicit “this” parameter
    +
    +

    3237

    +
    address_of_unqualified_explicit_this_function:
    +
    taking the address of an explicit “this” function requires a +qualified name
    +
    +

    3238

    +
    implicit_address_of_explicit_this_function:
    +
    forming the address of an explicit “this” function requires the “&” +operator
    +
    +

    3239

    +
    string_literal_cannot_initialize_flexible_array_member:
    +
    a string literal cannot be used to initialize a flexible array member
    +
    +

    3246

    +
    ifc_missing_function_definition:
    +
    the IFC representation of the definition of function “xxxx” is +missing
    +
    +

    3247

    +
    member_function_modifier_on_template:
    +
    function modifier does not apply to member template declaration
    +
    +

    3248

    +
    constexpr_too_many_nested_anonymous_types:
    +
    member selection involves too many nested anonymous types
    +
    +

    3249

    +
    no_common_type:
    +
    there is no common type between the operands
    +
    +

    3250

    +
    exp_pointer_to_member:
    +
    expected a pointer-to-member
    +
    +

    3251

    +
    lone_flexible_array_member:
    +
    a flexible array member cannot be declared in an otherwise-empty type
    +
    +

    3252

    +
    missing_gnu_srcloc_type:
    +
    expected “std::source_location::__impl” to be defined to a class +with only the data members “_M_function_name”, “_M_file_name”, +“_M_column”, “_M_line”
    +
    +

    3253

    +
    srcloc_column_bounds:
    +
    given column number is too large for “std::source_location” +implementation
    +
    +

    3254

    +
    srcloc_line_bounds:
    +
    given line number is too large for “std::source_location” +implementation
    +
    +

    3255

    +
    utf16_char_lit_too_long:
    +
    a UTF-16 character constant cannot occupy more than one code unit; +value truncated
    +
    +

    3256

    +
    both_arguments_must_have_same_type:
    +
    both arguments must have the same type
    +
    +

    3257

    +
    invalid_type_for_builtin:
    +
    type “type” is invalid as an argument for this builtin
    +
    +

    3258

    +
    constexpr_called_from_rout:
    +
    called from entity-kind “entity” (declared at line xxxx):
    +
    +

    3259

    +
    qualified_unnamed_bit_field_type:
    +
    a qualified type is nonstandard for anonymous bit fields
    +
    +

    3260

    +
    bad_vector_conditional_size:
    +
    the element type of the vector condition (“type”) must have the +same size as the element type of the result (“type”)
    +
    +

    3261

    +
    bad_vector_float_operand_size:
    +
    the floating-point vector operand type (“type”) has no matching +integer vector type
    +
    +

    3262

    +
    mangling_for_requires:
    +
    mangling for “requires” expressions is not yet implemented
    +
    +

    3263

    +
    unavailable_attr:
    +
    because of an “unavailable” attribute
    +
    +

    3264

    +
    duplicate_asm_qualifier:
    +
    duplicate ‘asm’ qualifier
    +
    +

    3265

    +
    incomplete_enum_bit_field_or_bad_opaque_enum:
    +
    either a bit field with an incomplete enum type or an opaque +enumeration with an invalid base type
    +
    +

    3266

    +
    ifc_partition_mismatch:
    +
    attempted to construct an element from IFC partition “xxxx” using +an index into IFC partition “xxxx”
    +
    +

    3267

    +
    ifc_partition_bad_entry_size:
    +
    the partition “xxxx” specified its entry size as n when nwas expected
    +
    +

    3268

    +
    ifc_requirement_failure:
    +
    an unexpected IFC requirement was encountered while processing +module “module name”
    +
    +

    3269

    +
    ifc_requirement_failure_fill_in:
    +
    condition failed at line n in xxxx: “xxxx”
    +
    +

    3270

    +
    circular_constraint:
    +
    atomic constraint depends on itself
    +
    +

    3271

    +
    noreturn_with_return_type:
    +
    “noreturn” function has non-void return type
    +
    +

    3272

    +
    ifc_bad_function_param_name:
    +
    a correction has been made by dropping the parameter “xxxx” (at +relative index n)
    +
    +

    3273

    +
    default_arg_on_member_template_def:
    +
    a default template argument cannot be specified on the definition of +a member template outside its class
    +
    +

    3274

    +
    ifc_bad_identifier:
    +
    invalid IFC identifier name “xxxx” encountered during entity +reconstruction
    +
    +

    3276

    +
    invalid_ifc_sort_value:
    +
    module “module name” invalid sort value
    +
    +

    3277

    +
    ifc_function_template_parse_failure:
    +
    a function template loaded from an IFC module was incorrectly parsed +as entity-kind “entity” (declared at line xxxx)
    +
    +

    3278

    +
    ifc_entity_ref_failure:
    +
    failed to load an IFC entity reference in module “module name”
    +
    +

    3279

    +
    ifc_entity_ref_failure_info:
    +
    from partition “xxxx” element n (file position n, +relative position n)
    +
    +

    3280

    +
    no_chained_designators_with_destructor:
    +
    chained designators are not permitted for a class type with a +nontrivial destructor
    +
    +

    3281

    +
    explicit_specialization_friend:
    +
    an explicit specialization declaration may not be a friend declaration
    +
    +

    3282

    +
    std_float128_not_supported:
    +
    the std::float128_t type is not supported; std::float64_t will be +used instead
    +
    +

    3284

    +
    alias_template_deduction_guide:
    +
    a deduction guide may not be declared for alias template “entity”
    +
    +

    3285

    +
    unavailable_entity:
    +
    entity-kind “entity” was declared declared unavailable
    +
    +

    3286

    +
    unavailable_entity_with_custom_message:
    +
    entity-kind “entity” was declared unavailable (“xxxx”)
    +
    +

    3287

    +
    deprecated_attr:
    +
    because of a “deprecated” attribute
    +
    +

    3288

    +
    explicit_lambda_template_parameters_is_cpp20:
    +
    explicit lambda template parameters are a C++20 feature
    +
    +

    3289

    +
    c23_noreturn_deprecated:
    +
    the use of “_Noreturn” has been obsoleted in C23; use “[[noreturn]]” +instead
    +
    +

    3290

    +
    c23_alignof_deprecated:
    +
    the use of “_Alignof” has been obsoleted in C23; use “alignof” instead
    +
    +

    3291

    +
    c23_alignas_deprecated:
    +
    the use of “_Alignas” has been obsoleted in C23; use “alignas” instead
    +
    +

    3292

    +
    c23_bool_deprecated:
    +
    the use of “_Bool” has been obsoleted in C23; use “bool” instead
    +
    +

    3293

    +
    c23_static_assert_deprecated:
    +
    the use of “_Static_assert” has been obsoleted in C23; use +“static_assert” instead
    +
    +

    3294

    +
    c23_thread_local_deprecated:
    +
    the use of “_Thread_local” has been obsoleted in C23; use +“thread_local” instead
    +
    +

    3295

    +
    ms_ifc_unavailable:
    +
    Microsoft mode must be enabled to use the module file “xxxx” (a +Microsoft Visual Studio IFC module)
    +
    +

    3296

    +
    file_for_module_not_found:
    +
    could not open module file “xxxx”
    +
    +

    3297

    +
    found_from_module_map:
    +
    found in the module map for module “xxxx”
    +
    +

    3298

    +
    found_from_header_unit_map:
    +
    found in the header unit map for “xxxx”
    +
    +

    3299

    +
    cl_invalid_output_mode:
    +
    unrecognized output mode (must be one of text, sarif): xxxx
    +
    +

    3300

    +
    cl_c23_typeof_option_only_in_C:
    +
    option “c23_typeof” can be used only when compiling C
    +
    +

    3301

    +
    cl_invalid_clang_version:
    +
    invalid clang version number: xxxx
    +
    +

    3305

    +
    constexpr_flexible_array_initializer:
    +
    cannot evaluate an initializer for a flexible array member
    +
    +

    3306

    +
    nonstandard_bit_field_initializer:
    +
    a default bit-field initializer is a C++20 feature
    +
    +

    3307

    +
    ifc_too_many_template_args:
    +
    too many arguments in template argument list in module “module +name”
    +
    +

    3308

    +
    ifc_too_many_template_args_info:
    +
    detected for the template argument represented by “xxxx” element +n (file position n, relative position n)
    +
    +

    3309

    +
    ifc_too_few_template_args:
    +
    too few arguments in template argument list in module “module +name”
    +
    +

    3310

    +
    ifc_too_few_template_args_info:
    +
    detected while processing the template argument list represented by +“xxxx” element n (file position n, relative position +n)
    +
    +

    3311

    +
    nonstandard_conversion_from_scoped_enum:
    +
    conversion from scoped enumeration type “type” is nonstandard
    +
    +

    3312

    +
    constexpr_allocation_mismatch:
    +
    deallocation does not match allocation kind (one is for an array and +the other not)
    +
    +

    3313

    +
    constexpr_address_unknown:
    +
    comparison involves unknown address (e.g., the address of a weak +variable)
    +
    +

    3314

    +
    bad_argument_to_make_signed:
    +
    __make_signed is only compatible with non-bool integer and enum types
    +
    +

    3315

    +
    bad_argument_to_make_unsigned:
    +
    __make_unsigned is only compatible with non-bool integer and enum +types
    +
    +

    3316

    +
    intrinsic_name_released:
    +
    the intrinsic name “xxxx” will be treated as an ordinary +identifier from here
    +
    +

    3317

    +
    array_subobject_not_initialized:
    +
    access to uninitialized subobject at index n
    +
    +

    3318

    +
    ifc_line_number_overflow:
    +
    IFC line number (n) overflows maximum allowed value (n) +module “module name”
    +
    +

    3319

    +
    invalid_unrepresentable_ifc_position:
    +
    module “module name” requested element n of partition +“xxxx”, this file position exceeds the maximum representable value
    +
    +

    3320

    +
    wrong_number_of_arguments:
    +
    wrong number of arguments
    +
    +

    3321

    +
    candidate_failed_constraint:
    +
    constraint on candidate entity-kind “entity” not satisfied
    +
    +

    3322

    +
    candidate_wrong_param_count:
    +
    number of parameters of entity-kind “entity” does not match the +call
    +
    +

    3323

    +
    candidate_expl_templ_arg_subst_failed:
    +
    substituting explicit template arguments “<templ-args>” for +entity-kind “entity” failed
    +
    +

    3324

    +
    impl_deleted_move_candidate_ignored:
    +
    entity-kind “entity” is an implicitly “= delete” move function +and thus ignored during overload resolution
    +
    +

    3325

    +
    arg_for_empty_param_pack:
    +
    entity-kind “entity” does not match because argument #*n* is +provided for an empty parameter pack
    +
    +

    3326

    +
    nonviable_because_arg_mismatch:
    +
    entity-kind “entity” does not match because argument #*n* does +not match parameter
    +
    +

    3327

    +
    deduction_failed:
    +
    candidate entity-kind “entity” failed deduction
    +
    +

    3328

    +
    builtin_operator_nonviable_because_arg_mismatch:
    +
    built-in operator*xxxx* does not match because argument #*n* does +not match parameter
    +
    +

    3329

    +
    integral_operand:
    +
    <integral>
    +
    +

    3330

    +
    promoted_integral_operand:
    +
    <promoted integral>
    +
    +

    3331

    +
    ptrdiff_t_operand:
    +
    <ptrdiff_t>
    +
    +

    3332

    +
    enum_operand:
    +
    <enum>
    +
    +

    3333

    +
    scoped_enum_operand:
    +
    <scoped enum>
    +
    +

    3334

    +
    arith_operand:
    +
    <arithmetic>
    +
    +

    3335

    +
    promoted_arith_operand:
    +
    <promoted arithmetic>
    +
    +

    3336

    +
    nonbool_arith_operand:
    +
    <non-bool arithmetic>
    +
    +

    3337

    +
    pointer_operand:
    +
    <pointer>
    +
    +

    3338

    +
    nullptr_operand:
    +
    <nullptr>
    +
    +

    3339

    +
    handle_operand:
    +
    <handle>
    +
    +

    3340

    +
    handle_to_cli_array_operand:
    +
    <handle to CLI array>
    +
    +

    3341

    +
    pointer_to_object_operand:
    +
    <pointer to object>
    +
    +

    3342

    +
    pointer_to_function_operand:
    +
    <pointer to function>
    +
    +

    3343

    +
    ptr_to_member_operand:
    +
    <pointer-to-member>
    +
    +

    3344

    +
    bool_operand:
    +
    <bool>
    +
    +

    3345

    +
    bool_equivalent_operand:
    +
    <bool-like>
    +
    +

    3346

    +
    class_operand:
    +
    <class>
    +
    +

    3347

    +
    auto_cast_is_cpp23:
    +
    auto(<expr>) and auto{<expr>} are a C++23 feature
    +
    +

    3348

    +
    anon_union_using_declaration:
    +
    invalid anonymous union – using declaration is not allowed
    +
    +

    3349

    +
    ifc_file_incompatibility:
    +
    IFC file “xxxx” cannot be processed
    +
    +

    3350

    +
    unsupported_ifc_file_version_info:
    +
    IFC version n.*n* is not supported
    +
    +

    3351

    +
    unsupported_ifc_file_arch_info:
    +
    IFC architecture “xxxx” is incompatible with the current target +architecture
    +
    +

    3352

    +
    unknown_ifc_partition_conversion:
    +
    module “module name” requests index n of an unsupported +partition corresponding to “xxxx”
    +
    +

    3353

    +
    param_cannot_be_completed:
    +
    parameter number n of entity-kind “entity” has type +“type” which cannot be completed
    +
    +

    3354

    +
    param_is_incomplete:
    +
    parameter number n of entity-kind “entity” has incomplete +type “type”
    +
    +

    3355

    +
    param_is_abstract:
    +
    parameter number n of entity-kind “entity” has abstract type +“type”
    +
    +

    3356

    +
    struct_bindings_is_cpp17:
    +
    structured bindings are a C++17 feature
    +
    +

    3357

    +
    capturing_struct_bindings_is_cpp20:
    +
    capturing structured bindings is a C++20 feature
    +
    +

    3358

    +
    bad_splicer_operand:
    +
    operand of splicer has type “type” instead of std::meta::info
    +
    +

    3359

    +
    not_a_type_reflection:
    +
    operand (reflection for reflection-description) is not the +reflection of a type
    +
    +

    3360

    +
    nonconstant_splicer_operand:
    +
    nonconstant operand of splicer
    +
    +

    3361

    +
    bad_std_string_view:
    +
    use of “type” instead of std::string_view (= +std::basic_string_view<char>)
    +
    +

    3362

    +
    inconsistent_std_string_view:
    +
    std::string_view used here is inconsistent with use in other +intrinsics
    +
    +

    3363

    +
    invalid_std_string_view_for_reflection:
    +
    definition of std::string_view does not match assumptions of +reflection (no base classes and data members for pointer and length)
    +
    +

    3364

    +
    constexpr_reflection_not_of_constant:
    +
    reflection is not that of a constant value
    +
    +

    3368

    +
    bad_reflection_kind_for_expression_splice:
    +
    bad reflection (reflection-description) for expression splice
    +
    +

    3369

    +
    already_defined_with_pos:
    +
    entity-kind “entity” has already been defined (previous +definition at line xxxx)
    +
    +

    3371

    +
    incompatible_std_meta_value_of_type:
    +
    extract of type “type” is not compatible with the given +reflection (entity with type “type”)
    +
    +

    3372

    +
    reflection_of_overloaded_set:
    +
    reflecting an overload set is not currently permitted
    +
    +

    3373

    +
    intrinsic_requires_template_instance:
    +
    this intrinsic requires a reflection for a template instance
    +
    +

    3374

    +
    invalid_reflection_equality:
    +
    incompatible types “type” and “type” for operator
    +
    +

    3375

    +
    invalid_reflection_for_intrinsic:
    +
    invalid reflection for intrinsic metafunction
    +
    +

    3376

    +
    nonmember_reflection_for_intrinsic:
    +
    intrinsic metafunction requires a reflection for a class member
    +
    +

    3377

    +
    union_base:
    +
    a class cannot not derive from a union
    +
    +

    3378

    +
    base_with_flexible_array:
    +
    cannot derive from a class with a flexible array member
    +
    +

    3379

    +
    null_reflection:
    +
    null reflection
    +
    +

    3380

    +
    namespace_alias:
    +
    namespace alias
    +
    +

    3381

    +
    unspecified_reflection:
    +
    reflection (details unavailable)
    +
    +

    3382

    +
    std_meta_substitute_bad_arg_reflection:
    +
    bad reflection (reflection-description) for template argument in +std::meta::substitute
    +
    +

    3383

    +
    std_meta_substitute_failed:
    +
    call to std::meta::substitute (for reflection-description) failed
    +
    +

    3384

    +
    expired_reflection_value:
    +
    reflection value refers to inactive entity
    +
    +

    3385

    +
    cannot_splice_general_expression:
    +
    an expression splice must splice a constant value, a variable, or a +function
    +
    +

    3386

    +
    cannot_splice_member_access:
    +
    a member access splice must splice a data member or a member function
    +
    +

    3387

    +
    splice_is_not_a_member_of_class:
    +
    member entity-kind “entity” (declared at line xxxx) is not a +direct or indirect member of “type”
    +
    +

    3388

    +
    unicode_name_not_found:
    +
    the name “xxxx” does not designate a known Unicode character
    +
    +

    3389

    +
    unterminated_unicode_name:
    +
    unterminated named Unicode character escape
    +
    +

    3390

    +
    invalid_char_in_unicode_name:
    +
    character cannot appear in a Unicode name
    +
    +

    3391

    +
    empty_unicode_name:
    +
    empty named Unicode character escape
    +
    +

    3392

    +
    exp_lsplice:
    +
    expected a “[:”
    +
    +

    3393

    +
    exp_rsplice:
    +
    expected a “:]”
    +
    +

    3394

    +
    lambda_mutable_and_static:
    +
    a lambda expression cannot be both “mutable” and “static”
    +
    +

    3395

    +
    static_lambda_nonstandard:
    +
    a “static” lambda expression is nonstandard
    +
    +

    3396

    +
    static_lambda_with_capture:
    +
    a “static” lambda expression must have an empty capture specification
    +
    +

    3399

    +
    ifc_creation_failure:
    +
    an IFC file could not be produced for the current translation unit
    +
    +

    3400

    +
    unsupported_il_to_ifc:
    +
    one or more entities cannot currently be written to an IFC file
    +
    +

    3401

    +
    nonstandard_explicit_bool:
    +
    ‘explicit(bool)’ is a C++20 feature
    +
    +

    3402

    +
    bad_type_for_atomic_fetch:
    +
    first argument must be a pointer to integer, enum, or supported +floating-point type
    +
    +

    3403

    +
    module_use_in_multi_tu_mode:
    +
    C++ modules cannot be used when compiling multiple translation units
    +
    +

    3404

    +
    module_use_with_export_template:
    +
    C++ modules cannot be used with the pre-C++11 “export” feature
    +
    +

    3405

    +
    ifc_unsupported_token:
    +
    the IFC token “xxxx” is not supported
    +
    +

    3406

    +
    pass_object_size_not_in_function_decl:
    +
    the “pass_object_size” attribute is only valid on parameters of +function declarations
    +
    +

    3407

    +
    attr_arg_out_of_small_integer_range:
    +
    the argument of the “xxxx” attribute n must be a value +between 0 and n
    +
    +

    3408

    +
    ref_qualifier_ignored:
    +
    a ref-qualifier here is ignored
    +
    +

    3409

    +
    invalid_neon_vector_element_type:
    +
    invalid NEON vector element type “type”
    +
    +

    3410

    +
    invalid_neon_polyvector_element_type:
    +
    invalid NEON polyvector element type “type”
    +
    +

    3411

    +
    invalid_scalable_vector_element_type:
    +
    invalid scalable vector element type “type”
    +
    +

    3412

    +
    invalid_scalable_vector_tuple_elements:
    +
    invalid number of tuple elements for scalable vector type
    +
    +

    3413

    +
    invalid_neon_vector_size:
    +
    a NEON vector or polyvector must be either 64 or 128 bits wide
    +
    +

    3414

    +
    sizeless_type_not_allowed:
    +
    sizeless type “type” is not allowed
    +
    +

    3415

    +
    value_init_of_sizeless_type:
    +
    an object of the sizeless type “type” cannot be value-initialized
    +
    +

    3416

    +
    ifc_unexpected_null_scope_member:
    +
    unexpected null declaration index found as part of scope n
    +
    +

    3417

    +
    cl_unnamed_module_map:
    +
    a module name must be specified for the module file map referencing +the file “xxxx”
    +
    +

    3418

    +
    ifc_partition_missing_element:
    +
    a null index value was received where a node in the IFC partition +“xxxx” was expected
    +
    +

    3419

    +
    void_template_variable:
    +
    entity-kind “entity” (declared at line xxxx) cannot have type +“type”
    +
    +

    3420

    +
    ref_qualifier_nonstandard:
    +
    a ref-qualifier is nonstandard in this mode
    +
    +

    3421

    +
    range_based_for_nonstandard:
    +
    a range-based “for” statement is nonstandard in this mode
    +
    +

    3422

    +
    auto_type_nonstandard:
    +
    “auto” as a type specifier is nonstandard in this mode
    +
    +

    3423

    +
    cannot_import_module_bad_checksum:
    +
    could not import module file “xxxx” due to file corruption
    +
    +

    3425

    +
    extraneous_injected_member_tokens:
    +
    extraneous tokens injected after member declaration
    +
    +

    3426

    +
    bad_injection_scope:
    +
    bad injection scope (reflection-description)
    +
    +

    3427

    +
    expected_string_view_value:
    +
    expected a value of type std::string_view but got “type”
    +
    +

    3428

    +
    extraneous_injected_statement_tokens:
    +
    extraneous tokens injected after statement
    +
    +

    3429

    +
    extraneous_injected_declaration_tokens:
    +
    extraneous tokens injected after declaration
    +
    +

    3430

    +
    tuple_index_overflow:
    +
    tuple index value (n) overflow
    +
    +

    3431

    +
    constexpr_begin_report_tokens:
    +
    >> output from std::meta::__report_tokens
    +
    +

    3432

    +
    constexpr_end_report_tokens:
    +
    >> end output from std::meta::__report_tokens
    +
    +

    3433

    +
    constexpr_no_current_parameters:
    +
    not in a context with parameter variables
    +
    +

    3434

    +
    empty_delimited_escape:
    +
    a delimited escape sequence must have at least one character
    +
    +

    3435

    +
    unterminated_delimited_escape:
    +
    unterminated delimited escape sequence
    +
    +

    3436

    +
    constant_addresses_local_variable:
    +
    constant contains address of a local variable
    +
    +

    3437

    +
    struct_binding_consteval:
    +
    a structured binding cannot be declared “consteval”
    +
    +

    3438

    +
    module_import_conflict:
    +
    “entity” conflicts with the imported declaration entity-kind +“entity” (declared at line xxxx)
    +
    +

    3439

    +
    char_too_wide_for_rep:
    +
    character cannot be represented in the specified character type
    +
    +

    3440

    +
    annotation_after_using:
    +
    an annotation cannot appear in the context of a “using” attribute +prefix
    +
    +

    3441

    +
    annotation_must_have_literal_type:
    +
    type “type” of annotation is not a literal type
    +
    +

    3442

    +
    ext_vector_type_requires_bool_integral_floating_type:
    +
    the “ext_vector_type” attribute applies only to bool, integer, or +floating-point types
    +
    +

    3443

    +
    multiple_union_designators:
    +
    multiple designators into the same union are not permitted
    +
    +

    3444

    +
    debug_show_location:
    +
    test message
    +
    +

    3445

    +
    microsoft_version_doesnt_support_cpp23_mode:
    +
    the version of Microsoft being emulated must be at least 1943 to use +“–ms_c++23”
    +
    +

    3446

    +
    cl_invalid_cwd:
    +
    invalid current working directory: xxxx
    +
    +

    3447

    +
    cleanup_attribute_in_constexpr_function:
    +
    “cleanup” attribute within a constexpr function is not currently +supported
    +
    +

    3448

    +
    assume_statement_applies_to_null_statements:
    +
    the “assume” attribute can only apply to a null statement
    +
    +

    3449

    +
    assumption_failed:
    +
    assumption failed
    +
    +

    3450

    +
    variable_templates_is_cpp14:
    +
    variable templates are a C++14 feature
    +
    +

    3451

    +
    address_of_function_with_pass_object_size_attr:
    +
    cannot take the address of a function with a parameter declared with +the “pass_object_size” attribute
    +
    +

    3452

    +
    all_arguments_must_have_same_type:
    +
    all arguments must have the same type
    +
    +

    3453

    +
    comparison_details:
    +
    the final comparison was xxxx xxxx xxxx
    +
    +

    3454

    +
    too_many_arguments_provided_for_attribute:
    +
    too many arguments for attribute “xxxx”
    +
    +

    3455

    +
    constexpr_bad_mantissa_string:
    +
    mantissa string does not contain a valid number
    +
    +

    3456

    +
    constexpr_float_error:
    +
    floating-point error during constant evaluation
    +
    +

    3457

    +
    inheriting_ctor_ignored_for_copy:
    +
    inheriting constructor entity-kind “entity” ignored for +copy/move-like operation
    +
    +

    3458

    +
    cannot_get_file_size:
    +
    cannot determine size of file xxxx
    +
    +

    3459

    +
    cannot_read_file:
    +
    cannot read xxxx
    +
    +

    3461

    +
    unrec_embed_param:
    +
    unrecognized parameter name
    +
    +

    3462

    +
    dupl_embed_param:
    +
    parameter specified more than once
    +
    +

    3463

    +
    has_embed_not_in_if:
    +
    __has_embed cannot appear outside #if
    +
    +

    3464

    +
    setlocale_lc_numeric_failed:
    +
    could not set LC_NUMERIC locale to C
    +
    +

    3465

    +
    elifdef_not_enabled:
    +
    elifdef and elifndef are not enabled in this mode and are ignored in +text being skipped
    +
    +

    3466

    +
    nonstandard_alias_declaration_context:
    +
    an alias declaration is nonstandard in this context
    +
    +

    3467

    +
    out_of_order_field_allocation_nonstandard:
    +
    the target ABI may allocate nonstatic members in an order not +matching their declaration order, which is nonstandard in C++23 and +later
    +
    +

    3470

    +
    module_unit_export_unexpected:
    +
    the module declaration cannot be exported from this translation unit +unless creating a module interface file
    +
    +

    3471

    +
    module_unit_export_expected:
    +
    the module declaration must be exported from this translation unit to +create a module interface file
    +
    +

    3472

    +
    cannot_write_module_none_declared:
    +
    module file generation was requested but no module was declared in +the translation unit
    +
    +

    3473

    +
    candidate_constraints_failed:
    +
    substituting “<templ-args>” for entity-kind “entity” failed +constraints
    +
    +

    3474

    +
    concept_not_satisfied:
    +
    entity-kind “entity” not satisfied for “<templ-args>”
    +
    +

    3475

    +
    bad_embed_initializer:
    +
    the #embed expansion is too long to initialize an entity of type +“type”
    +
    +

    3476

    +
    bad_defined_pp_op:
    +
    the “defined” operator is not permitted here
    +
    +

    3477

    +
    ptr_to_mem_to_non_member:
    +
    entity-kind “entity” is not a member of “type”
    +
    +

    3478

    +
    embed_narrowing:
    +
    narrowing conversion to signed character in #embed data
    +
    +

    3479

    +
    invalid_vector_of_bool_operator:
    +
    operator is not permitted for “vector of bool” types
    +
    +

    3480

    +
    constexpr_object_too_large:
    +
    object too large for constant-evaluation
    +
    +

    3481

    +
    self_referencing_temporary_object:
    +
    self-referencing temporary object
    +
    +

    3482

    +
    lambda_cannot_refer_to_local_entity_here:
    +
    a lambda cannot refer to a local variable or init-capture in this +context
    +
    +

    3483

    +
    parameter_capture_conflict:
    +
    a lambda parameter cannot hide an explicit capture
    +
    +

    3484

    +
    template_parameter_capture_conflict:
    +
    a lambda template parameter cannot hide an explicit capture
    +
    +

    3485

    +
    insufficient_address_space:
    +
    insufficient address space exists to process this translation unit
    +
    +

    3486

    +
    undetermined_type:
    +
    <undetermined type>
    +
    +

    3487

    +
    undetermined_constant:
    +
    <undetermined constant>
    +
    +

    3488

    +
    undetermined_template:
    +
    <undetermined template>
    +
    +

    3489

    +
    bad_flt_config:
    +
    the configured size of xxxx is too small for the specified number +of mantissa + exponent bits
    +
    +

    3490

    +
    expression:
    +
    expression
    +
    +

    3491

    +
    quoted_expression:
    +
    <expression>
    +
    +

    3492

    +
    unnamed:
    +
    unnamed
    +
    +

    3493

    +
    quoted_unnamed:
    +
    <unnamed>
    +
    +

    3494

    +
    error_type:
    +
    <error-type>
    +
    +

    3495

    +
    unknown_type:
    +
    <unknown-type>
    +
    +

    3496

    +
    something:
    +
    <something>
    +
    +

    3497

    +
    null_type:
    +
    <null-type>
    +
    +

    3498

    +
    no_init:
    +
    <no-init>
    +
    +

    3499

    +
    zero_init:
    +
    <zero-init>
    +
    +

    3500

    +
    bitwise_copy_of:
    +
    bitwise copy of:
    +
    +

    3501

    +
    bitwise_copy:
    +
    <bitwise-copy>
    +
    +

    3502

    +
    class_result_via_ctor:
    +
    class result via ctor:
    +
    +

    3503

    +
    constructor_call:
    +
    <constructor-call>
    +
    +

    3504

    +
    null_expression:
    +
    <NULL expression>
    +
    +

    3505

    +
    quoted_error:
    +
    <error>
    +
    +

    3506

    +
    null_routine:
    +
    <NULL routine>
    +
    +

    3507

    +
    quoted_default:
    +
    <default>
    +
    +

    3508

    +
    parameter_number:
    +
    parameter #
    +
    +

    3509

    +
    one_level_up:
    +
    (one level up)
    +
    +

    3510

    +
    levels_up:
    +
    levels up
    +
    +

    3511

    +
    dynamic_init:
    +
    dynamic-init:
    +
    +

    3512

    +
    error_constant:
    +
    <error-constant>
    +
    +

    3513

    +
    stack_offset_of:
    +
    stack-offset-of:
    +
    +

    3514

    +
    implicit_element:
    +
    <implicit element>
    +
    +

    3515

    +
    repetitions_of:
    +
    repetitions of
    +
    +

    3516

    +
    type_code_integer:
    +
    integer
    +
    +

    3517

    +
    type_code_enum:
    +
    enum
    +
    +

    3518

    +
    type_code_scoped_enum:
    +
    scoped enum
    +
    +

    3519

    +
    type_code_arithmetic:
    +
    arithmetic
    +
    +

    3520

    +
    type_code_non_bool_arithmetic:
    +
    non-bool arithmetic
    +
    +

    3521

    +
    type_code_pointer:
    +
    pointer
    +
    +

    3522

    +
    type_code_nullptr_type:
    +
    nullptr type
    +
    +

    3523

    +
    type_code_handle:
    +
    handle
    +
    +

    3524

    +
    type_code_handle_to_CLI_array:
    +
    handle-to-CLI-array
    +
    +

    3525

    +
    type_code_pointer_to_object:
    +
    pointer-to-object
    +
    +

    3526

    +
    type_code_pointer_to_function:
    +
    pointer-to-function
    +
    +

    3527

    +
    type_code_pointer_to_member:
    +
    pointer-to-member
    +
    +

    3528

    +
    type_code_bool:
    +
    bool
    +
    +

    3529

    +
    type_code_bool_equivalent:
    +
    bool-equivalent
    +
    +

    3530

    +
    type_code_class:
    +
    class
    +
    +

    3531

    +
    volatile_inc_deprecated:
    +
    a volatile operand to an increment expression is deprecated
    +
    +

    3532

    +
    volatile_dec_deprecated:
    +
    a volatile operand to a decrement expression is deprecated
    +
    +

    3533

    +
    indeterminate_not_on_first_decl:
    +
    entity-kind “entity” previously declared without the +“indeterminate” attribute
    +
    +

    3534

    +
    default_constructor_is_explicit:
    +
    the default constructor for “type” is explicit
    +
    +

    3535

    +
    ifc_definition_load_failure:
    +
    failed to load the definition of entity-kind “entity” in module +“module name”
    +
    +

    3536

    +
    ifc_initializer_load_failure:
    +
    failed to load the initializer for entity-kind “entity” in +module “module name”
    +
    +

    3537

    +
    base_class_of_class_type_with_typedef_name:
    +
    a class with a typedef name for linkage purposes cannot have a base +class
    +
    +

    3538

    +
    member_function_of_class_type_with_typedef_name:
    +
    a class with a typedef name for linkage purposes cannot have a member +function
    +
    +

    3539

    +
    member_type_of_class_type_with_typedef_name:
    +
    a class with a typedef name for linkage purposes cannot have a nested +type, other than an enumeration type or a non-closure class type
    +
    +

    3540

    +
    lambda_in_class_type_with_typedef_name:
    +
    a class with a typedef name for linkage purposes cannot contain a +lambda expression
    +
    +

    3541

    +
    field_init_in_class_type_with_typedef_name:
    +
    a class with a typedef name for linkage purposes cannot have a +nonstatic data member with a default member initializer
    +
    +

    3542

    +
    static_data_member_not_allowed_in_unnamed_class:
    +
    a static data member declaration is not allowed in an unnamed class
    +
    +

    3543

    +
    initializer_addresses_dllimport_variable:
    +
    initializer result addresses a dllimport variable
    +
    +

    3544

    +
    cannot_be_specialized:
    +
    template with “no_specializations” attribute cannot be specialized
    +
    +

    3545

    +
    static_dimension_nonstandard:
    +
    “static” is nonstandard here
    +
    +

    3546

    +
    enum_previously_declared_without_explicit_base:
    +
    entity-kind “entity” (declared at line xxxx) was previously +declared without an explicit enum base
    +
    +

    3547

    +
    missing_typename:
    +
    missing “typename” is nonstandard here
    +
    +

    3548

    +
    abbreviated_deduction_guide:
    +
    abbreviated function template syntax is nonstandard for deduction +guides
    +
    +

    3549

    +
    explicit_this_is_cpp23:
    +
    explicit “this” parameters are a C++23 feature
    +
    +

    3550

    +
    array_designator_for_deduced_context:
    +
    array designators are not supported in template deduction contexts
    +
    +

    3551

    +
    second_argument_wrong_shape:
    +
    the second argument must be an integer type with the same shape (a +scalar or vector type) as the first argument
    +
    +

    3552

    +
    vector_of_boolean_required:
    +
    argument must be a vector of boolean types
    +
    +

    3553

    +
    pointer_to_scalar_required:
    +
    argument must be a pointer to a scalar type
    +
    +

    3554

    +
    incorrect_masked_type:
    +
    incorrect argument type (should be “type”)
    +
    +

    3555

    +
    vector_type_with_size_is_required:
    +
    a vector type (with the same number of elements as the first +argument) is required
    +
    +

    3556

    +
    struct_binding_packs_is_cpp26:
    +
    structured binding packs are a C++26 feature
    +
    +

    3557

    +
    non_template_structured_binding_pack:
    +
    a structured binding pack can only be declared inside a template
    +
    +

    3558

    +
    multiple_structured_binding_packs:
    +
    cannot declare multiple packs in a structured binding declaration
    +
    +

    3559

    +
    cl_cpp26_requires_parse_nonclass_templates:
    +
    The “–no_parse_templates” option cannot be used in C++26 mode
    +
    +

    3560

    +
    type_pack_element_cannot_match:
    +
    a type pack element cannot match entity-kind “entity”
    +
    +

    3561

    +
    c23_old_style_param_id:
    +
    identifier-only parameters can only be used in old-style function +definitions, which are nonstandard since C23
    +
    +

    3562

    +
    cl_require_func_prototypes_option_only_in_C:
    +
    option “no_require_func_prototypes” can be used only when compiling C
    +
    +

    3563

    +
    address_of_overload_set_implicit_obj_member_selected:
    +
    overload resolution for an address-of-overload-set call may not +select implicit-object member entity-kind “entity” (declared at +line xxxx)
    +
    +

    3564

    +
    pack_indexing_is_cpp26:
    +
    pack indexing is a C++26 feature
    +
    +

    3565

    +
    pack_index_out_of_bounds:
    +
    pack index exceeds number of pack elements
    +
    +

    3566

    +
    alias_ctad_is_cpp20:
    +
    class template argument deduction for alias templates is a C++20 +feature
    +
    +

    3567

    +
    bitint_width_too_large:
    +
    _BitInt(n) is invalid; the maximum integer width is n
    +
    +

    3568

    +
    signed_bitint_width_too_small:
    +
    _BitInt(n) is invalid; the minimum signed _BitInt width is n
    +
    +

    3569

    +
    unsigned_bitint_width_too_small:
    +
    unsigned _BitInt(n) is invalid; the minimum unsigned _BitInt +width is n
    +
    +

    3570

    +
    bitint_enum_base_not_allowed:
    +
    _BitInt types cannot be the underlying type of an enumeration type
    +
    +

    3571

    +
    deduction_guide_redeclaration:
    +
    redeclaration of deduction guide “type” (previous declaration at +line xxxx)
    +
    +

    3572

    +
    create_pch_file_not_created:
    +
    precompiled header file “xxxx” was not created
    +
    +

    3576

    +
    non_c_like_typedef_for_linkage:
    +
    anonymous non-C-like type given name for linkage purposes by typedef +or alias declaration
    +
    +

    3577

    +
    non_c_like_because_of_base_class:
    +
    type is not C-like because of this base class
    +
    +

    3578

    +
    non_c_like_because_of_default_member_init:
    +
    type is not C-like because of this default member initializer
    +
    +

    3579

    +
    non_c_like_because_of_friend:
    +
    type is not C-like because of this friend declaration
    +
    +

    3580

    +
    non_c_like_because_of_member:
    +
    type is not C-like because of this member declaration
    +
    +

    3581

    +
    non_c_like_because_of_lambda:
    +
    type is not C-like because of this lambda expression
    +
    +

    3582

    +
    enum_qualifier_is_cpp11:
    +
    an enum-type name qualifier is a C++11 feature
    +
    +

    3583

    +
    unrestricted_unions_is_cpp11:
    +
    unrestricted unions are a C++11 feature
    +
    +

    3584

    +
    pack_expansion_for_non_pack_alias_param:
    +
    a pack expansion cannot be used as an argument for non-pack +entity-kind “entity” of entity-kind “entity”
    +
    +

    3585

    +
    uniterable_reflection_range:
    +
    the range passed to the metafunction cannot be iterated
    +
    +

    3587

    +
    interpreter_message_remark:
    +
    xxxx xxxx
    +
    +

    3588

    +
    interpreter_message_warning:
    +
    xxxx xxxx
    +
    +

    3589

    +
    interpreter_message_error:
    +
    xxxx xxxx
    +
    +

    3590

    +
    constexpr_diag_arg_count:
    +
    a call to “__builtin_constexpr_diag” requires three arguments
    +
    +

    3591

    +
    constexpr_diag_bad_level:
    +
    the first argument in a call to “__builtin_constexpr_diag” must be 0 +(remark), 1 (warning), 2 (error), 16 (remark at caller), 17 (warning +at caller), or 18 (error at caller)
    +
    +

    3592

    +
    constexpr_diag_bad_string:
    +
    a string literal or an object with the representation of +std::string_view is required for the tag and the message in a call to +“__builtin_constexpr_diag”
    +
    +

    3593

    +
    constexpr_diag_bad_tag:
    +
    the tag in a call to “__builtin_constexpr_diag” may contain only +letters, digits, and underscores
    +
    +

    3594

    +
    cl_invalid_constexpr_diag_tag:
    +
    invalid tag in constexpr diagnostic control option: xxxx
    +
    +

    3595

    +
    token_sequence_needs_double_caret:
    +
    a token sequence must be introduced by “^^”
    +
    +

    3596

    +
    exp_interpolator:
    +
    expected an interpolator (”[”, “[:”, “{”, “val”, or “str”)
    +
    +

    3597

    +
    interpolated_id_is_not_identifier:
    +
    “xxxx” does not spell an identifier
    +
    +

    3598

    +
    interpolated_operand_is_not_token_sequence:
    +
    the operand of a “{…}” interpolator is not a token sequence
    +
    +

    3599

    +
    tag_redefined_differently:
    +
    this declaration of entity-kind “entity” does not declare the +same type as the declaration at line xxxx
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/exceptions/index.html b/doc/exceptions/index.html new file mode 100644 index 0000000..6b57f43 --- /dev/null +++ b/doc/exceptions/index.html @@ -0,0 +1,802 @@ + + + + + 14. Exception Handling - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    14. Exception Handling#

    +

    The high-level representation of exception handling in the IL closely follows +the C++ language specification. The data structures involved are defined in +il_def.h, and the routines to manage declarations and other support are in +decls.c, statements.c, and expr.c.

    +

    A global variable, exceptions_enabled, controls whether exception +processing is done. An error is issued if the flag is FALSE and the source +program attempts to use a syntactic feature that pertains to exception +handling. The default value of the exceptions_enabled flag is configurable +(see DEFAULT_EXCEPTIONS_ENABLED in lang_feat.h). The value may be +toggled by a command-line option (-x), except that its value may be TRUE +only in C++ mode and only when cfront-compatibility mode has not been selected.

    +

    Any actual implementation of exception handling will require a tradeoff between +portability and efficiency. The high-level representation of exception +handling (that is, the representation of the “unlowered” IL) is not explicit +about a number of details that an actual implementation will have to deal with, +notably finding the right handler, copying the throw object to the right +handler parameter, and calling the right set of destructors at the right time. +Therefore, though a portable implementation of exception handling is provided +(see lower_eh.c and routines provided for run-time support), back ends may +choose to replace it with an implementation adapted to the specific support +available on the target platform. IL lowering can instead be configured to do +partial lowering or no lowering of exception handling features.

    +

    This chapter describes the high-level support for exceptions and then +summarizes the main features of the portable implementation.

    +
    +

    14.1. Exception Specifications#

    +

    An exception specification that appears on a function declaration is +represented by an entry of type an_exception_specification. The +function refers to it by means of the exception_specification field of +its routine type supplement. When the function is declared with no +exception specification (meaning that any exception might be thrown), the +exception_specification pointer will be NULL. A dynamic throw +specification entry itself has a pointer to a linked list of entries of +type a_throw_spec_type_entry, each of which indicates a type of +exception that will be thrown from the given routine; that pointer is NULL +to indicate that no exceptions will be thrown. A noexcept specifier +points to a constant representing its operand or NULL if there is no such +operand.

    +

    scan_exception_specification, which is called from function_declarator, +scans an exception specification and allocates a throw specification entry +and its associated list of types, if any. Subsequently (i.e., after the +routine entry has been identified) the exception specification is either added +to the routine type supplement or checked against a prior declaration (see +check_exception_specification).

    +

    The used_in_exception flag is set for any type that appears in an exception +specification (as well as for any type that is the type of a throw +expression or appears in the exception declaration of a handler). Some +implementations of exception handling may use this flag in generating special +code for run-time type identification. In addition, if such a type is (or +“contains”) a class or enumeration type, that class or enumeration type must be +externally linked. See set_used_in_exception_or_rtti_flag (in +types.c).

    +
    +
    +

    14.2. try Blocks#

    +

    A try block is represented in the IL by a statement of kind +stmk_try_block, which points to a compound statement block and a linked +list of handlers. The latter are entries of type a_handler; each points to +a (possibly unnamed) parameter (the local variable to which the throw +object will be copied when the handler is invoked) and to an stmk_block +statement, the body of the handler; for a default handler (i.e., the +catch(...) case) the parameter pointer in the handler entry is NULL.

    +

    A try block is scanned by try_block_statement (in statements.c). +First compound_statement is called to scan the part of the try block +that precedes the first handler declaration. Then handler_declaration (in +decls.c) is called for each catch clause.

    +

    handler_declaration scans the exception declaration (calling +decl_specifiers and, if a named parameter is present, declarator). +Except for the default handler case, it creates a variable entry to +represent the parameter, whether it is explicitly declared or not. It also +does various checks to assure that the parameter’s type is valid (e.g., that it +is not an incomplete type) and calls set_used_in_exception_or_rtti_flag; +then it calls type_masks_handler_param_type (in types.c), to assure +that it is not masked by a previous handler declaration in the same try +block.

    +

    Finally, compound_statement is called to scan the handler’s body. Special +checking is done to assure that no label defined within the handler is +referenced by a goto from outside the handler.

    +

    in C++/CLI mode, there may be a “finally” block at the end, either in +addition to or in place of the catch clauses. It provides code that is +always executed when the try block is exited, whether normally, via a +goto or return, or via a thrown exception.

    +
    +
    +

    14.3. throw Expressions#

    +

    A throw expression is scanned by scan_throw_operator (in expr.c). +An enk_throw expression node is produced, which points to a dynamic +initialization entry that describes the object to be thrown (or rather, how to +copy it to the space for the object allocated by the run-time). +set_used_in_exception_or_rtti_flag is called for the type. A “rethrow”, +where no throw object is specified (i.e., throw;), is represented by an +enk_throw expression with a NULL pointer.

    +
    +
    +

    14.4. Portable Implementation#

    +

    One exception handling implementation provided in this release is a portable +implementation that provides complete EH support while requiring few changes to +existing back ends. Because this is a portable implementation there is a +significant impact on the performance of the generated code when exception +handling is enabled.

    +
    +

    14.4.1. A walk-through of an EH example#

    +

    What follows is a rather contrived example that provides an overview of how the +compiled code and the run-time system cooperate in throwing and handling +exceptions. It is intended as an introduction, with a more detailed discussion +of some of its features in subsequent sections.

    +

    Here is the example (with the numbers to the right corresponding to the text +that follows):

    +
    #include <stdio.h>
    +struct A { ~A() { } };
    +struct B : public A { };
    +struct C { };
    +void f(int i) throw(A) {                       // 2, 3, 4
    +  A  a1;                                       // 5
    +  if (i==0) throw a1;                          // 6
    +  B  b1;
    +  if (i==1) throw b1;
    +  C  c1;
    +  if (i==2) throw c1;
    +}
    +int main() {
    +  for (int i = 0; i < 3; ++i) {
    +    printf("i=%0d\n", i);
    +    try {                                      // 1
    +      f(i);
    +    }
    +    catch (A a) { printf("Caught an A\n"); }   // 7, 8
    +    catch (...) { printf("Caught something else\n"); }
    +  }  /* for */                                 // 9
    +}
    +
    +
    +
      +
    1. Each time the for loop in main is executed and control enters +the try block, prologue code is executed, which includes pushing an +entry onto the “EH stack” to record that a try block has been +entered. (The EH stack is the principal data structure used to track the +dynamic context in which exception handling events occur.)

    2. +
    3. Each time f is called, prologue code for the function pushes another +entry onto the EH stack to record that a function with exception +specifications has been entered. This entry provides the run-time system +with a list of the types that may be thrown from f.

    4. +
    5. Moreover, since f contains objects (namely, automatic variables with +destructors) that may need to be cleaned up if an exception is thrown +during its execution, an additional entry is pushed onto the EH stack +for object cleanup. [1] The array it points to is updated each time +an object that is eligible for clean-up is constructed.

    6. +
    7. The first clean-up region of f is entered, and global variable +__eh_curr_region is updated accordingly. This routine has three such +regions – the region in which no objects require clean-up, the region in +which a1 requires clean-up, and the region in which both a1 and +b1 require clean-up. [2]

    8. +
    9. When a1 is constructed, the second clean-up region is entered. The +address of a1 is entered in the “object address table”.

    10. +
    11. The processing for the original source expression “throw a1” +involves three steps:

      +
        +
      • +
        __throw_setup is called to record information about a1 (most +importantly, its type) and to return a pointer to a piece of storage +into which it may be copied. [3]
        +
        +
      • +
      • +
        The compiled code makes a copy of a1 to pass to +__throw. Note that if class A had a copy constructor, the +generated code would include a call of __exception_started prior +to making the copy of a1.
        +
        +
      • +
      • +
        __throw is called. First it walks the EH stack to identify the +action that is required – in this case, it locates a handler that +can catch an A object. It then makes a second pass through the +EH stack to do the appropriate clean-up, which in this case involves +calling the destructor for a1 and popping a couple of entries +off the EH stack. The actions performed by __throw may entail a +good deal more complexity, as described in greater detail later.
        +
        +
      • +
      +
    12. +
    13. After the clean-up is complete, control transfers back to the try +block in main, and specifically to the first handler (since it is +the one that catches an A object), and then “Caught an A” is +printed out.

    14. +
    15. The epilogue code of the handler involves a call to +__free_thrown_object, to deallocate the storage into which a1 +was copied.

    16. +
    17. As the try block is exited, the EH stack entry for the current +try block is popped, restoring the state to what it was originally, +before the try block was entered.

    18. +
    +

    On the second iteration of the for loop in main, the same sequence of +events takes place, except for two things. First, in function fb1 is +also constructed, so that the third clean-up region is entered and the address +of b1 is recorded in the object address table (along with that of a1); +that means that two objects are eligible for clean-up when an exception occurs. +Second, __throw must take into account that A is an accessible base +class of B in locating the handler that can catch b1.

    +

    Finally, on the third iteration of the loop, __throw detects a violation of +the exception specification for function f – c1 is the thrown object +this time, but C is not on the list of types that the function is allowed +to throw. As a result, unexpected is called, which results in a call to +terminate.

    +
    +
    +

    14.4.2. Run-Time Support#

    +
    +

    14.4.2.1. The EH Stack#

    +

    A principal data structure used in coordinating the compiled code and the +run-time is the “EH stack”. It maintains information about the dynamic context +in which exception handling events occur. The EH stack is a linked list of +structures, and a new entry is pushed onto the stack each time a try block +is entered, each time a function with an exception specification is entered, +and each time a function is entered for which some kind of object clean-up must +be done if an exception is thrown.

    +
    +
    +

    14.4.2.2. Code generated for a try block#

    +

    When a try block is entered, a try block entry is pushed onto the EH +stack. The try block entry contains

    +
      +
    • +
      a setjmp buffer that will be used for transfer of control back to the +try block when an exception is thrown;
      +
      +
    • +
    • +
      a list of the catch clauses associated with the try block;
      +
      +
    • +
    • +
      other status information used to record the current state of the try +block.
      +
      +
    • +
    +

    The state information in the try block is initialized so that the run-time +knows that the try section of the block (as opposed to one of the handlers) +is currently being executed. When generating code for exception cleanup it is +sometimes necessary for the front end to generate try blocks that do not +appear in the original program. These are known as “internal” try blocks +and are distinguished from normal try blocks by the fact that the pointer +to the list of catch clauses is null.

    +
    +
    +

    14.4.2.3. Prologue code for a function with an exception specification#

    +

    When a function with an exception specification is entered, a throw +specification entry is pushed onto the EH stack. This entry provides a list of +the types that may be thrown (directly or indirectly) by the function. It is +removed from the EH stack when the function returns.

    +
    +
    +

    14.4.2.4. Prologue code for a function that may need clean-up if an exception is thrown#

    +

    When a function constructs objects that may need to be cleaned up in the event +of an exception, its prologue code pushes a function clean-up entry onto the EH +stack. Note that a given function may push both a throw specification +entry and a function clean-up entry.

    +

    A function clean-up entry will be pushed on the stack if the function creates +any automatic objects (including temporaries) of classes with destructors; one +is also generated when an object may be dynamically allocated using operator +new and the front end is configured to generate the operator new call +outside the constructor.

    +

    The function clean-up entry contains

    +
      +
    • +
      a pointer to an array of region entries that are used to describe the +clean-up regions within the function
      +
      +
    • +
    • +
      a pointer to an array table that provides additional information for +certain region entries
      +
      +
    • +
    • +
      a pointer to an object address table used to determine the address of +objects referenced by the region and array tables
      +
      +
    • +
    +

    A region is associated with a specific sequence of clean-up actions that would +be required should an exception occur. A new region is typically started +whenever a destructable object comes into or goes out of scope.

    +

    The global variable __eh_curr_region records the region number currently +being executed. It is saved each time a new function entry or try block is +pushed on the stack and restored when the entry is popped.

    +

    The region entries contain the information needed to identify the object to be +cleaned up and the kind of clean-up action required. The run-time must be able +to determine the address of each object for which some kind of clean-up must be +done. Ideally this would be done by putting stack offsets in the region +entries. This can’t be done in the portable implementation, and so instead the +region entries contain an index into the object address table. The object +address table is allocated on the stack because its contents vary with each +invocation of the function. As each region is entered, the appropriate entry +in the object address table is filled in with the address of the object to be +cleaned up. The address of the object address table is recorded in the +function entry on the EH stack.

    +

    The region entries have been designed to be as compact as possible. Some +unusual circumstances require additional information not normally available in +the region entry. The additional information is needed when the region entry +describes an array or when the region entry describes a new allocation of a +class object whose operator delete function is of the two-operand variety. +In these cases the region entry contains an index into an array supplement and +the array supplement pointer is stored in the function entry on the EH stack.

    +
    +
    +

    14.4.2.5. Throwing an exception (generated code)#

    +

    When an exception is thrown, the run-time routine __throw_setup is called +to provide information to the run-time system about the object being thrown and +to allocate space into which the thrown object may be copied. A pointer to +this space is returned to the caller (i.e., the compiled code), which is +responsible for actually making the copy of the object. If copying the object +requires calling a copy constructor, __exception_started is called after +the evaluation of the object to be thrown, but before the copy constructor is +called. Once the object has been copied the run-time routine __throw is +called to complete the throw processing. If the thrown object requires +destruction, __throw_setup_dtor is called instead of __throw_setup. If +the thrown object is a multi-level pointer, __throw_setup_ptr is called +instead of __throw_setup.

    +
    +
    +

    14.4.2.6. Throwing an exception (__throw_setup)#

    +

    When __throw_setup is called, an entry is pushed onto the throw stack +(which is distinct from the EH stack). The throw stack contains information +about each of the thrown objects and is needed because throws may be nested +(i.e., a throw may occur while in a handler reached as the result of an earlier +throw). __throw_setup records the information provided by the caller in +the throw stack entry. This includes information about the type of the thrown +object.

    +

    The run-time system requires information about the types of objects that are +thrown and caught and also for types used in exception specifications. The +term “typeinfo” is used to refer to this type description information. +[4] It is not necessarily possible to generate only one typeinfo record +for a given type. [5] Consequently it must be possible to determine that +two typeinfo records refer to the same type. This is done by having each +typeinfo point to a “unique ID object”. The unique ID objects are +generated as tentative definitions to avoid potential multiple definition +problems. Two typeinfo records refer to the same type if they point to the +same unique ID object. The typeinfo information includes a list of the +base classes of the type. The base class list includes all direct base classes +as well as all virtual base classes, whether direct or indirect.

    +

    When checking exception specifications and looking for a catch clause that +can catch the thrown object, it is necessary to determine whether a given type +is a base class (and an accessible one) of the thrown type. This is done by +traversing the typeinfo base class list. The base class list includes +information about accessibility and ambiguity, which allows the runtime to +ignore non-public and ambiguous base classes.

    +

    In front end versions preceding 2.29, the runtime routine __throw_alloc was +called instead of __throw_setup. It had a similar function and a similar +interface, with one additional parameter, which (when non-NULL) was a string +indicating the accessibility for each base class, computed by the front end at +the point of the throw. This changed because the C++ language changed: As of +March 1995, the rules for throw were changed to allow catching only public +base classes, which eliminates the need for determining any special +accessibility at the point of throw.

    +
    +
    +

    14.4.2.7. Marking the initiation of the exception (__exception_started)#

    +

    An exception is considered “uncaught” after the expression in the throw +statement has been evaluated. If a copy constructor must be called to copy the +thrown object into the temporary copy used by the EH runtime, the copy +constructor must be called while the exception is considered uncaught. In +other words, if an exception is thrown during the evaluation of the expression +in the throw, that exception is handled normally. If, however, an exception is +thrown from a copy constructor called to copy an object to the temporary used +by the EH runtime (and control is transferred out of the copy constructor +because of the exception) terminate() must be called instead.

    +

    __exception_started is called to mark the point at which an exception is +considered uncaught. When the copy of the thrown object can be made without +calling a copy constructor __exception_started is not called, and the +exception is considered uncaught at the point at which __throw is called.

    +
    +
    +

    14.4.2.8. Throwing an exception (__throw)#

    +

    After the compiled code copies the thrown object into the space designated by +__throw_setup, it issues a call to __throw to complete the processing.

    +

    __throw makes two passes through the try stack. The first pass +determines what should occur as a result of the throw – transferring to a +specific handler, calling unexpected because an exception specification was +violated, or calling terminate (for any of several reasons). Once the end +result of the throw has been determined, a second pass is made through the EH +stack entries to perform any clean-up actions that are required.

    +

    During the first pass through the EH stack +check_exception_type_specifications is called for each try block entry +and each throw specification entry. Only try blocks that are executing +the try portion of the block (as opposed to a handler) are eligible to be +the destination of a throw. try blocks that are currently in handlers +are simply ignored. The search is terminated when a matching catch clause +is found or a violated exception specification is detected. When it is a +matching catch clause that is found, a pointer to the thrown object is +passed to the routine so that it may be adjusted for any derived-to-base-class +conversions that may be needed. If the matching catch clause is associated +with an internal try block, the search of the EH stack continues to +determine if a normal try block can be found. The search for a normal +try block that with a matching handler is used to determine whether +terminate() should be called.

    +

    According to the standard it is implementation-defined whether the stack is +unwound before terminate() is called. The runtime can be configured to +select either of the possible behaviors by setting the +UNWIND_STACK_BEFORE_CALLING_TERMINATE configuration flag. If this flag is +not set, terminate() would be called now if no matching handler was found.

    +

    In the second pass only the function clean-up entries are processed. The +function cleanup is called for each such entry. cleanup processes the +region entries associated with the function starting with the region number +specified by the caller. Each region entry contains a “flags” field that +controls how the region information is interpreted.

    +
      +
    • +
      If the “conditional flag” bit is set, the region entry describes an object +that is conditionally constructed and must only be destroyed if a variable, +whose address is determined from the next element in the region array, +indicates the object was actually constructed.
      +
      +
    • +
    • +
      If the “new allocation” bit is set, the region entry describes an object +allocated by new that must be deleted during clean-up. In this case +the function pointer in the region entry that normally points to the +destructor instead points to the delete routine to be called.
      +
      +
    • +
    • +
      If the “VLA” bit is set, the region entry describes a variable length +array, whose size is determined from the next element in the region array.
      +
      +
    • +
    +

    One of the fields in the region entry is the region number of the next entry to +be processed. The end of the region list is designated by a reserved value in +the next entry field.

    +

    If an exception occurs while constructing or destructing an array, the clean-up +operation must destroy the remaining portion of the partially constructed (or +destructed) array. To accomplish this there is a special kind of EH stack +entry that is only used by vec_new and vec_delete. When this entry is +encountered during the clean-up pass, __cleanup_vec_new_or_delete is called +to the required clean-up.

    +

    After all of the function clean-up entries have been processed, __throw +determines whether there are any clean-up actions required by the try block +associated with the handler to which control is to be transferred. If so, +cleanup is called to do the required clean-up operations.

    +

    Only after all the clean-up operations have been completed is the action +performed that was determined by the first pass through the EH stack:

    +
      +
    • +
      If an exception specification was violated, unexpected is called.
      +
      +
    • +
    • +
      If no handler was found, terminate() is called (when the +UNWIND_STACK_BEFORE_CALLING_TERMINATE configuration flag is set).
      +
      +
    • +
    • +
      Otherwise, control is transferred to the handler. Global variable +__catch_clause_number is set to the sequence number of the catch +clause to which control is to be transferred, and another global variable, +__caught_object_address, is set to the address of the object to be used +to initialize the handler parameter. The state information in the try +block entry is updated to indicate that a handler is now being executed. +Finally, longjmp is used to branch back to the appropriate try +block.
      +
      +
    • +
    +
    +
    +

    14.4.2.9. In the handler#

    +

    The try block code uses __catch_clause_number to select the appropriate +handler, and then the handler parameter is initialized using +__caught_object_address: If the handler parameter is a reference, it is +initialized by setting a pointer to the global variable; otherwise, the object +pointed to by __caught_object_address is used to initialize the handler +parameter. __exception_caught is called after the handler parameter has +been initialized. This marks the end of the period during which an exception +is considered uncaught. __exception_caught is not called by the catch +clause associated with an internal try block. Instead, an internal try block +exits by calling __internal_rethrow, which calls __exception_caught +before performing the rethrow.

    +
    +
    +

    14.4.2.10. A rethrow from the handler#

    +

    A rethrow (a throw with no operand) may be executed anywhere within the +dynamic context of a handler. This has the effect of doing a nested throw of +the object on top of the throw stack. Note that it rethrows the thrown object +and not the caught object (the two can be different if a derived-to-base +conversion occurred or if the object was caught using ellipsis).

    +

    The handling of rethrow is almost identical to the handling of a normal throw. +The only difference is that the thrown object is not copied. The throw stack +entry for the rethrow points to the copy of the thrown object made when the +original throw was done.

    +
    +
    +

    14.4.2.11. At the end of a handler#

    +

    At the end of each handler __free_throw_object is called to pop entries off +of the throw stack, call the destructor for the thrown object, and to free the +space used for copies of the thrown objects associated with the throw stack +entries being cleared.

    +
    +
    +

    14.4.2.12. Run-Time storage management#

    +

    The exception handling run-time dynamically allocates information used for book +keeping (e.g., throw stack entries) and for making copies of thrown objects. +The memory is allocated and freed using a stack discipline. The run-time +includes a static buffer that is used for this dynamically allocated memory. +If the static buffer is exhausted, additional memory is allocated using +malloc. If the run-time is unable to allocate the memory needed to handle +an exception, terminate is called.

    +
    +
    +
    +
    +

    14.5. Non-Portable Implementation#

    +

    The non-portable implementation would be more properly described as “turning +off parts of the portable implementation so that a back end can do something +better.” EDG does not provide a complete non-portable implementation (in IL +lowering and the runtime), but our customers should be able to write one using +the information provided by the front end.

    +

    The portable implementation is also known as the full-lowering implementation, +because it lowers everything related to exception handling to C, leaving +nothing related to exception handling in the IL. It is enabled by setting +DO_FULL_PORTABLE_EH_LOWERING to TRUE.

    +

    The next step down from that is the partial-lowering implementation, which is +enabled by setting GENERATE_EH_TABLES to TRUE. In that mode, the data +tables of the portable scheme are still generated, but the executable code is +rendered as exception-handling operations, so that a back end can choose a +different approach (e.g., not using setjmp, not maintaining a separate EH +stack).

    +

    The final step down is the no-lowering implementation, which is enabled by +having both DO_FULL_PORTABLE_EH_LOWERING and GENERATE_EH_TABLES FALSE. +In that mode, the data tables are not generated either, but the object lifetime +information is preserved so that the back end can use it to generate its own +version of the cleanup tables.

    +

    See the IL Lowering chapter for details on the constructs +preserved and lowered under each alternative.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/expr/index.html b/doc/expr/index.html new file mode 100644 index 0000000..cb3cc33 --- /dev/null +++ b/doc/expr/index.html @@ -0,0 +1,3150 @@ + + + + + 9. Expression Scanning - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    9. Expression Scanning#

    +

    expr.c and expr.h contain the code and associated declarations to scan +expressions. exprutil.c and exprutil.h contain utilities related to +expression scanning, for processing other than the actual syntax analysis. +overload.c and overload.h contain code to do overload resolution and +conversions.

    +

    The expression routines function as an expression-scanning utility for the rest +of the front end. They provide a set of simple interface routines that are +called to scan various kinds of expressions:

    +
      +
    • +
      scan_integer_expression scans an integral expression, e.g., the +selector expression for a switch statement.
      +
      +
    • +
    • +
      scan_void_expression scans a “void” expression, one whose value is +thrown away, e.g., an expression statement or the incrementing expression +in a for statement.
      +
      +
    • +
    • +
      scan_default_arg_expr scans a default argument expression.
      +
      +
    • +
    • +
      scan_template_argument_constant_expression scans a nontype argument of +a template reference.
      +
      +
    • +
    • +
      scan_return_expression scans the expression in a return statement.
      +
      +
    • +
    • +
      scan_case_label_constant scans a constant expression for a switch case.
      +
      +
    • +
    • +
      scan_constant_dimension_expression scans a constant array bound.
      +
      +
    • +
    • +
      scan_pp_expression scans a preprocessing expression, e.g., an +expression in an #if.
      +
      +
    • +
    • +
      scan_integral_constant_expression scans an integral constant +expression.
      +
      +
    • +
    • +
      scan_constant_initializer_expression scans an initializer that is +required to be a constant.
      +
      +
    • +
    • +
      scan_member_constant_initializer_expression scans an initializer for a +member constant (integral or enum) in C++.
      +
      +
    • +
    • +
      scan_full_initializer_expr_as_componentscans an initializer that need +not be a constant.
      +
      +
    • +
    • +
      scan_class_initializer_expression scans an initializer for a class.
      +
      +
    • +
    • +
      scan_class_parenthesized_initializer scans a parenthesized initializer +for a class.
      +
      +
    • +
    • +
      scan_boolean_controlling_expression scans a scalar expression that +controls a conditional statement (if, while, do while, and +for).
      +
      +
    • +
    +

    Each of these routines has roughly the same structure. scan_expr_full is +called to do the actual expression scanning. This produces a result of type +an_operand, which is checked for kind, converted to a required type (if +there is one), and then converted to the form required on return from the +interface routine, usually an expression node or a constant.

    +

    Some other utility expression routines with a different type of interface:

    +
      +
    • +
      scan_ctor_arguments is called to scan a parenthesized list of +expressions that acts as the argument list for a constructor call, for +example
      +
      +
      struct A {
      +  A(int, int);
      +};
      +A aa(1, j+1);  // scan_ctor_arguments is called
      +
      +
      +
    • +
    • +
      try_to_convert_class_operand_to_builtin_type is called to convert an +expression of a class type to a builtin type, as when such an expression +appears as the conditional expression in an if statement or the like.
      +
      +
    • +
    • +
      scan_braced_init_list scans a complete braced-enclosed initializer as +in the C++11 “initializer lists” feature. convert_initializer is used +to convert initializers, in particular brace-enclosed initializers, to the +type of the entity being initialized.
      +
      +
    • +
    • +
      find_default_constructor finds a default constructor capable of +initializing an object of a given class type.
      +
      +
    • +
    • +
      find_copy_constructor finds a copy constructor capable of copying an +object of a given class type with a given cv-qualification.
      +
      +
    • +
    • +
      find_copy_assignment_operator is similar for an operator= function.
      +
      +
    • +
    +
    +

    9.1. scan_expr_full#

    +

    scan_expr_full actually handles all expression scanning. It is called with +a set of option flags that configure its processing for various types of +expressions. It scans through the tokens of an expression, builds an +expression tree for the expression scanned, and returns an argument of type +an_operand to describe the expression scanned.

    +

    Its arguments are as follows:

    +
    + + + + + + + + + + + + + + + +
    +
    result
    +
    +
    +
    The result (of type an_operand) of this level of expression +scanning.
    +
    +
    +
    prec_level
    +
    +
    +
    The operator precedence level at which to terminate the scanning. +Expression scanning continues while the next operator precedence is +higher than this (or equal, with right-associative operators).
    +
    +
    +
    expression_kind
    +
    +
    +
    The kind of expression that is expected: ek_pp for a preprocessing +expression, ek_integral_constant for an integral constant +expression, ek_init_constant for a constant initializer expression +(not used in C++, except for nontype template arguments and some C++11 +expressions), ek_normal for a normal expression, or ek_sizeof +for the operand of sizeof. For the three constant expression +cases, some operators are restricted, some operand types are +restricted, and values of variables (etc.) may not be loaded. (See +the section on constant expressions.)
    +
    +
    +
    local_options
    +
    +
    +
    A bit-set of option switches that apply to just this level of +expression scanning (i.e., they do not apply to subexpressions scanned +within this expression scan). The switches control whether the comma +operator is allowed, whether the expression is being scanned as the +immediate operand of a cast, etc.
    +
    +
    +
    +

    Note that typically scan_expr_full is called through the macro +scan_expr.

    +
    +
    +

    9.2. Parsing Technique#

    +

    scan_expr_full scans an expression using a modified version of recursive +descent. The technique is “modified” in that it includes an operator +precedence level (higher precedences, numerically, bind more tightly). This +modification avoids the many levels of subroutine calls inherent in the +traditional recursive descent method. In the modified method, there is +approximately one subroutine call per leaf operand. Basically, +scan_expr_full will scan an expression up to either something it does not +understand (presumably something that follows the end of the expression), or up +to an operator that has lower precedence than the level being scanned (or equal +precedence when left-associative).

    +

    The precedence check is done by the routine token_ends_expr. One special +case: when inside a template argument list, “>” is treated as the closing +bracket for the argument list rather than the “greater than” operator.

    +

    For example, the expression 1+2*3-4 is parsed as follows:

    +
      +
    1. scan_expr_full is called with level 0. It takes the 1, then +looks at the operator +. The current level (0) is less than the +level of + (12), so scan_expr_full takes the + and calls +itself with level 12.

    2. +
    3. scan_expr_full (called with level 12) takes the 2, then looks at +the operator *. The current level (12) is less than the level of +* (13), so scan_expr_full takes the * and calls itself +with level 13.

    4. +
    5. scan_expr_full (called with level 13) takes the 3, then looks at +the operator -. The current level (13) is greater than the level of +- (12), so scan_expr_full returns the constant expression for +3.

    6. +
    7. Back in scan_expr_full (level 12, step 2 above), 2*3 is +assembled (by computing the constant result). scan_expr_full then +looks at the operator -. The current level (12) is equal to the +level of -, and - is left-associative, so scan_expr_full +returns the constant expression for 2*3 (i.e., 6).

    8. +
    9. Back in scan_expr_full (level 0, step 1), 1+(2*3) is assembled +(by computing the constant result). scan_ \expr_full then looks at +the operator -. The current level (0) is less than the level of +- (12), so scan_expr_full takes the - and calls itself with +level 12.

    10. +
    11. scan_expr_full (called with level 12) takes the 4, then looks at +the next token of input, which is something unrecognized, and returns +the constant expression for 4.

    12. +
    13. Back in scan_expr_full (level 0, step 5), (1+(2*3))-4 is +assembled (by computing the constant result). scan_expr_full then +looks at the next token of input, which is something unrecognized, and +returns the constant expression for (1+(2*3))-4 (i.e., 3).

    14. +
    +
    +
    +

    9.3. scan_expr_full Processing#

    +

    The processing within scan_expr_full is only slightly more complicated than +the description above. There are two major sections: In the first, a leaf +operand (identifier or constant), a prefix operator followed by an expression, +or an expression in parentheses (or a cast) is scanned. In the second section, +there is a loop with the above-described precedence level test at the top. So +long as the next thing in the input (whether it is a postfix operator, +subscript, function argument list, or binary operator) has an appropriate +precedence, it will be taken and added to the current expression. The loop +stops on the first thing that is not recognized or has a lower precedence. A +loop is required for expressions containing equal-precedence left-associative +operators, like 1+2*3*4+5: the *3 and *4 would be accumulated on +successive iterations of the loop in one call of scan_expr_full.

    +
    +
    +

    9.4. Scanning Identifiers#

    +

    When scan_expr_full scans an identifier, it calls scan_identifier, +which builds an operand for identifiers for enumeration constants, variables, +functions, etc. Odd C++ “names” like operator+ are also handled by +scan_identifier. The appropriate routines are called to turn them into +pseudo-identifier tokens, and thereafter the handling is the same as for other +names.

    +

    In constant expressions, variables are only allowed if they can legitimately be +part of a constant expression.

    +

    For undefined identifiers in C mode, scan_identifier enters the identifier +as an undefined identifier; shortly, the identifier will turn out to be either +truly undefined (in which case an error is generated) or will turn out to be +the name of an implicitly-declared function (in which case +decl_default_function in decls.c will be called to declare it as such).

    +

    In C++, nonstatic data members and nonstatic member functions are processed as +if preceded by “this->” (see make_this_pointer_operand). If the +identifier is a type identifier and it is followed by a left parenthesis, +scan_functional_notation_type_conversion is called to scan a type cast.

    +

    Also in C++, special considerations are made for uses of identifiers in local +classes (which can only use entities from the enclosing function in very +limited ways) and in local lambdas (which have similarities to local classes, +with the added wrinkle that references to enclosing local variables must be +interpreted as uses of fields of the associated closure class, and these fields +may have to be created as a result of these references). See +bad_nested_function_variable_ref and +make_selection_for_captured_variable.

    +
    +
    +

    9.5. Scanning Constants#

    +

    When scan_expr_full scans a constant, it calls make_constant_operand to +build the appropriate operand. Floating constants are allowed in integral +constant expressions only as the immediate operand of a cast (see +local_options, above). For string literals, +make_string_constant_operand is called instead. It produces an lvalue for +the array of characters; except in unusual cases (e.g., when the string is used +to initialize a character array), this is changed to a pointer to the string +(by conv_array_operand_to_pointer_operand).

    +
    +
    +

    9.6. Scanning Operations#

    +

    Processing for operators is done by lower-level routines. The routines are +called when the operator token has been scanned, so for non-unary operators, +this means after the left operand expression has been scanned. Most of these +routines have a structure similar to the following, which describes a generic +binary operation routine:

    +
      +
    • +
      A check is made to see if the operator is allowed in the present type of +expression (some operators, for example, are disallowed in some kinds of +constant expressions).
      +
      +
    • +
    • +
      The right operand is scanned by calling scan_expr_full with appropriate +switches.
      +
      +
    • +
    • +
      In C++ mode if either of the operands has a class type, +check_for_operator_overloading is called to see if operator overloading +applies. If it does, an appropriate operator function call is generated. +If not, the remaining steps are done.
      +
      +
    • +
    • +
      The left operand (passed in) is converted from a glvalue to a prvalue. In +cases where the left operand is supposed to be an lvalue, that is checked, +and using_lvalue or modifying_lvalue (depending on how the lvalue +is used) is called.
      +
      +
    • +
    • +
      The type of the left operand is checked.
      +
      +
    • +
    • +
      The right operand is converted from a glvalue to a prvalue.
      +
      +
    • +
    • +
      The type of the right operand is checked.
      +
      +
    • +
    • +
      The types of the operands are checked to see if they are compatible with +one another and with the operation. This sometimes selects a subcase of +the operation (e.g., pointer addition instead of integer addition).
      +
      +
        +
      • +
        For arithmetic operations, determine_arithmetic_conversions is called +to determine the usual arithmetic conversions and +change_binary_operand_types is called to promote the operand types as +necessary.
        +
        +
      • +
      • +
        For pointer operands, check_compatibility_of_pointer_operands is +called to check the operand types and do implicit type changes.
        +
        +
      • +
      • +
        For pointers to members, +check_ptr_to_member_operands_for_compatibility is called to do a +similar check.
        +
        +
      • +
      +
    • +
    • +
      which_binary_operator is called to select the proper intermediate +language operator for the operation on this type of operands.
      +
      +
    • +
    • +
      do_binary_operation is called to produce the result operand, either by +folding an operation on constants (by calling binary_operation in +folding.c, but not when not-evaluated), or by building an expression +tree.
      +
      +
    • +
    • +
      The start position of the expression is recorded in the result operand.
      +
      +
    • +
    +

    The prefix ++ and -- operators are scanned by +scan_prefix_incr_decr.

    +

    The unary operator & is scanned by scan_ampersand_operator. It usually +calls take_address_of_lvalue to produce the prvalue address result. In +pcc mode, it issues a warning for taking the address of an array, and calls +conv_array_operand_to_pointer_operand to produce address-of-array-element +instead of the ANSI address-of-array. If the operand is the qualified name of +a class member, a pointer-to-member constant is created. In C++/CLI, & +applied to an lvalue that might be on the CLR heap (as determined by +is_gc_lvalue_expr) produces an interior_ptr result.

    +

    The C++/CLI unary operator % is scanned by +scan_handle_address_operator. It produces an eok_handle_to or +eok_box operator. The result is a handle.

    +

    The unary operator * is scanned by scan_indirection_operator, producing +an lvalue or function designator as a result.

    +

    scan_arith_prefix_operator is called to scan the prefix operators +, +-, ~, and !. The unary version of the code in +do_binary_operation (fold if constant by calling unary_operation in +folding.c, else build expression node) is included directly here, since +these are all of the normal unary operators.

    +

    The sizeof operator is scanned by scan_sizeof_operator, which calls +is_decl_not_expr to decide whether or not the argument is a type name. If +it is, type_name is called to scan the type. If the argument is not a +type, it is scanned as a not-evaluated expression. The size of the type is +taken from the type entry in either case.

    +

    scan_alignof_operator is used to scan the __ALIGNOF__ construct (an +extension; similar to sizeof, but returns the alignment for a type instead +of its size).

    +

    scan_intaddr_operator is used to scan the __INTADDR__ construct (used +in the offsetof macro to scan an address expression and cast it to integral +type).

    +

    scan_noexcept_operator scans the C++11 noexcept operator.

    +

    scan_typeid scans the typeid operator. It produces an expression node +of kind enk_typeid.

    +

    scan_dynamic_cast_operator scans the dynamic_cast operator. Cases that +require runtime type determination are rendered as eok_dynamic_cast +expression nodes (or eok_ref_dynamic_cast, for casts to reference types); +the other cases are turned into ordinary casts.

    +

    scan_static_cast_operator scans static_cast.

    +

    scan_safe_cast_operator scans the C++/CLI safe_cast. It’s essentially +the same as static_cast except that it allows additional runtime-checked +cases, which are found by process_runtime_checked_safe_cast.

    +

    scan_reinterpret_cast_operator scans reinterpret_cast.

    +

    scan_const_cast_operator scans const_cast.

    +

    scan_new_operator is used to scan the new operator. The new +operation is rendered as an enk_new_delete operator tagged as a “new”, +whose supplement describes the operator new function to call plus +(optionally) some kind of initialization of the space allocated (for example, a +constructor call). For the C++/CLI gcnew, an enk_gcnew is used, and +the supplement for that includes additional information, including an +initializer. For a gcnew of a C++/CLI array, the supplement contains both +information about the array bounds (either as explicitly provided, or deduced +from the number of elements in the initializer), and an aggregate initializer +for the array elements (the latter is scanned by scan_cli_array_init). For +delegate initializers, scan_delegate_initializer scans the initializer, +which requires hand-coded checking because the delegate class doesn’t have +constructors that accurately cover the allowed initializers.

    +

    scan_delete_operator is used to scan the delete operator. The +delete operation is rendered as an enk_new_delete operator tagged as a +“delete”, whose supplement describes the operator delete function to call +plus (optionally) a destructor to call on the space being deallocated.

    +

    A left parenthesis can indicate a cast, a nested expression, or a C++17 fold +expression. scan_cast_or_expr is called for all cases. It uses +is_decl_not_expr to decide whether or not the thing following the left +parenthesis is a type name. If it is, type_name is called to scan the +type, cast_type_pre_check to check the legality of the type, and +do_cast to check and process the cast. For casts to void, an explicit +cast-to-void expression node is placed on top of the expression, as a special +marker for simplify_void_operand, but no simplification is done at this +point. In pcc mode, certain casts of lvalues leave an lvalue as the result +(see still_an_lvalue). If what is inside the parentheses is not a type, +scan_expr_full is called to scan a nested expression or the first term of a +fold expression. If it turns out to be a fold expression (or the left +parenthesis was followed by an ellipsis, which also implies a fold expression), +scan_fold_expression is called to scan the fold expression in either +generic form (during the prototype instantiation of the enclosing template) or +expanded form (during real instantiations).

    +

    The postfix ++ and -- operators are scanned by +scan_postfix_incr_decr.

    +

    Subscripting is scanned by scan_subscript_operator. The subscript is +represented by an eok_subscript operator. Constant subscripts are checked +for legality by valid_node_if_subscript or by the constant-folding +routines. When the first operand is a C++/CLI array, the contents of the [ +… ] are scanned as an expression list (no top-level comma operator is +allowed), and an eok_cli_subscript operator is used. Default indexed +properties, indexed properties, and operator[] functions can all be used to +implement the subscripting operation. Property rewrites are considered both +for the entire subscripted operation and for the first operand if it can be +converted to something subscriptable.

    +

    Function calls are scanned by scan_function_call. The function name is +entered as a default function if it is undefined (in C89 mode). The argument +list is scanned, and each argument is cast or default-promoted (see +prep_argument_operand and arg_default_promote_operand) appropriately. +The arguments are checked against the applicable function prototype or, if the +called function has an old-style declaration with a body, against the declared +old-style parameters. If the called function was declared with the pragma +__printf_args or the pragma __scanf_args, and the format string is a +constant, check_printf_scanf_arg is called for each argument following the +format string. It checks that the type of the argument matches the type of the +corresponding formatting specifier, and issues a warning if not. +assemble_function_call and make_function_call are called to put +together the actual function call. If the function is a virtual function, a +different expression operator is used; the virtual call is suppressed if the +function was named with a qualified name or if the proper function to call can +be determined statically. If the function is an overloaded function, +scan_call_arguments just builds a list of entries of type +an_arg_list_elem that describe the arguments scanned. No checking can be +done on them until the specific function to be called is identified in overload +resolution.

    +

    The operators -> and . are scanned by +scan_field_selection_operator. After the right operand (a member name) is +scanned, the processing breaks apart into several cases:

    +
      +
    • +
      For nonstatic data members (C fields), do_field_selection_operation is +called; it in turn calls fold_field_selection to fold field selection +relative to a constant address to produce another constant address. The +expression operator generated is eok_dot_field or +eok_points_to_field.
      +
      +
    • +
    • +
      For nonstatic member functions, do_member_function_selection is called. +It produces an operand for a bound function, i.e., a function bound to a +selector object.
      +
      +
    • +
    • +
      For static data members and static member functions, +combine_unneeded_selector_with_operand is called, and it generates an +eok_dot_static or eok_points_to_static operation.
      +
      +
    • +
    +

    For nonstatic members, cast_pointer_for_field_selection is called to cast +the left operand pointer to a base class if necessary.

    +

    The operators ->* and .* are scanned by +scan_ptr_to_member_operator. For member function cases, the result is a +bound member function. For data member cases, an eok_pm_field or +eok_pm_points_to_field operation is generated.

    +

    The operators *, /, and % are scanned by scan_mult_operator.

    +

    The operators + and - are scanned by scan_add_operator.

    +

    The operators >> and << are scanned by scan_shift_operator.

    +

    The operators >, <, <=, and >= are scanned by +scan_rel_operator, and the operators == and != are scanned by +scan_eq_operator.

    +

    The operators &, ^, and | are scanned by scan_bit_operator.

    +

    The operators && and || are scanned by scan_logical_operator, and +the operator ? (and the associated :) is scanned by +scan_conditional_operator. When these operators have constant operands for +the boolean controlling expressions, some operands will be scanned as +not-evaluated expressions, and the result tree is (conditionally) simplified +accordingly.

    +

    The operator “,” is scanned by scan_comma_operator. Note that the +comma operator is not allowed at the top level in initializer expressions and +in argument lists, because it means something else in those contexts; see the +local_options parameter of scan_expr_full.

    +

    scan_simple_assignment_operator scans the operator =. It calls +prep_assignment_operand to check and convert the right operand in most +cases. Assignment to “this” is recognized as a special case and +allowed with a warning.

    +

    scan_compound_assignment_operator scans compound assignment operators +(+=, -=, et al.).

    +

    Lambda expressions are scanned by scan_lambda_expression. The actual +parsing is handed to scan_lambda in class_decl.c, and +scan_lambda_expression constructs the required temporary initialization +from the resulting a_lambda entry. (See also Scanning Identifiers for +special measures needed when parsing identifiers in a lambda body.)

    +
    +
    +

    9.7. Operand Data Structure#

    +

    Throughout the expression routines (and nowhere else), all the information +about an operand is maintained in an entry called an_operand. The operand +contains the type of the operand, its “kind” (indicating the way in which the +operand is represented, i.e., as a constant or an expression tree), its “state” +(none, glvalue, prvalue, or function designator), and its source position. +Variables of type an_operand are typically stack-based variables within the +expression routines. They are never allocated in the intermediate language +memory region.

    +

    An lvalue is an object in memory; an rvalue is a value, with no associated +memory location. The distinction between lvalues and rvalues is very important +in the C language. [1] Names of variables start out as lvalues, and if +their values are used, they are implicitly converted to rvalues. C++11 adds +xvalues, which are eXpiring values produced by certain rvalue reference +operations. They share an operand state with lvalues, since the two are very +similar (they have addresses, possibly cv-qualified types, dynamic type, object +identity). They can be distinguished with the is_an_lvalue() and +is_an_xvalue() tests. Lvalues and xvalues are collectively known as +glvalues. The things formerly known as rvalues in C and in pre-C++11 C++ are +now known in C++11 as prvalues, and prvalues and xvalues collectively are now +known as rvalues.

    +

    The expression scanning routines attempt to model the C++11 concept of “value +categories” exactly, and the an_operand entry plays a part in that. [2] +It is always clear from the operand whether an expression is currently an +lvalue, xvalue, or prvalue, and the transformation from glvalue to prvalue is +done deliberately and when appropriate (see conv_glvalue_to_prvalue).

    +

    For functions, the equivalent of an lvalue is a function designator, and +there is a representation for those in an_operand.

    +

    In the C++ language definition, the term “lvalue” includes C’s function +designator as well as C’s lvalue, but in this implementation and this +documentation we use the term with the narrower C meaning.

    +

    When the operand representation is an expression, the operand points to an +expression tree in an intermediate language memory region. When the operand +representation is a constant, however, the constant is contained directly in +the operand (it is not allocated). This allows the expression routines to scan +constant expressions and fold them to constant results without allocating and +throwing away useless intermediate constant entries.

    +

    When an operand represents a bound function, that is, a C++ member function +with an associated object, the operand has the bound_function flag set. A +second operand is used to describe the associated object. There’s no direct +link between the two; the expression routines must carry around two operand +entries.

    +

    When expressions appear in a comma-separated list, such as an argument list, +the operands on the list are often represented as entries of type +an_arg_list_elem. Such entries can represent either an expression (in +an_operand form), or a brace-enclosed list, the latter being needed for the +C++11 “initializer lists” feature.

    +

    The C++/CLI ECMA standard mentions the concept of a “gc-lvalue,” and defines +conversions between normal lvalues and gc-lvalues. It turns out those concepts +are not needed, at least not in the suggested way, and no added kind of lvalue +is needed in an_operand entries. The important principle is that the +language must never allow the address of something that might be on the CLR +heap to be placed in a normal pointer where the garbage collector cannot find +it. So, whenever the address of something that might be in the CLR heap is +taken, the address must be placed in an interior_ptr or a pin_ptr, both +which are visible to the garbage collector. The functions +is_gc_lvalue_expr and is_gc_lvalue_operand test for lvalues that might +be in the CLR heap; if they return TRUE, the address of such an entity is made +an interior_ptr.

    +
    +
    +

    9.8. Primitive Operations on Operands#

    +

    Many routines exist to do primitive operations on operands. Routines that +perform initialization are

    +
      +
    • +
      set_operand_kind and
      +
      +
    • +
    • +
      clear_operand.
      +
      +
    • +
    +

    Constructors for the various kinds of operands are

    +
      +
    • +
      make_constant_operand,
      +
      +
    • +
    • +
      make_string_constant_operand,
      +
      +
    • +
    • +
      make_integer_constant_operand,
      +
      +
    • +
    • +
      make_expression_operand,
      +
      +
    • +
    • +
      make_glvalue_expression_operand,
      +
      +
    • +
    • +
      make_indefinite_function_operand,
      +
      +
    • +
    • +
      make_sym_for_ptr_to_member_operand,
      +
      +
    • +
    • +
      make_lvalue_variable_operand,
      +
      +
    • +
    • +
      make_ptr_to_member_constant_operand,
      +
      +
    • +
    • +
      make_function_designator_operand, and
      +
      +
    • +
    • +
      make_field_operand.
      +
      +
    • +
    +

    Routines that create operands for one- and two-operand expressions are

    +
      +
    • +
      build_unary_result_operand and
      +
      +
    • +
    • +
      build_binary_result_operand.
      +
      +
    • +
    +

    Error operands are created for parts of expressions containing errors by

    +
      +
    • +
      make_error_operand,
      +
      +
    • +
    • +
      conv_to_error_operand,
      +
      +
    • +
    • +
      error_in_operand, and
      +
      +
    • +
    • +
      error_and_make_error_operand,
      +
      +
    • +
    +

    which differ in whether or not they issue errors, and where. +make_node_from_operand converts an operand to an equivalent expression +tree.

    +
    +
    +

    9.9. Checking Operands#

    +

    op_is_zero_constant tests for a zero operand. There is also a set of +check_... routines, which are called to verify that an operand has certain +attributes, and if not, issue an error and change the operand to an error +operand:

    +
      +
    • +
      check_modifiable_lvalue_operand,
      +
      +
    • +
    • +
      check_integral_operand,
      +
      +
    • +
    • +
      check_integral_or_enum_operand,
      +
      +
    • +
    • +
      check_integral_or_enum_or_fixed_point_operand,
      +
      +
    • +
    • +
      check_arithmetic_operand,
      +
      +
    • +
    • +
      check_pointer_operand,
      +
      +
    • +
    • +
      check_object_pointer_operand,
      +
      +
    • +
    • +
      check_function_pointer_operand,
      +
      +
    • +
    • +
      check_scalar_operand.
      +
      +
    • +
    +

    check_boolean_controlling_expression checks that an expression controlling +a conditional is a scalar expression, and in C++ modes that don’t disable the +bool keyword, it converts the expression to bool.

    +
    +
    +

    9.10. Transformations on Operands#

    +

    Several routines handle transformations on expressions defined by the standard:

    +
      +
    • +
      conv_glvalue_to_prvalue changes a glvalue to a prvalue. Several +special cases are handled. Type qualifiers on the glvalue type are removed +to make the prvalue type. Most of the work for expression cases is handled +by conv_glvalue_expr_to_prvalue. conv_glvalue_to_prvalue calls +using_lvalue to do the error check for using the element just past the +end of an array; it also generates an error if it is called to convert a +glvalue in a constant expression.
      +
      +
    • +
    • +
      conv_array_operand_to_pointer_operand changes an array to a pointer to +the first element of the array.
      +
      +
    • +
    • +
      conv_function_designator_to_ptr_to_function changes a function +designator to a pointer to the function.
      +
      +
    • +
    +

    do_operand_transformations is a convenient way to request the preceding +three transformations. It can do any or all of them.

    +

    Note that in C++ operand transformations often cannot be done until one knows +the way in which an expression will be used. In an expression like arr + +xx, for example, with arr an array, one cannot convert the array to a +pointer until one has ruled out the possibility that this operation is an +overloaded use of operator “+” with a function for which the first +parameter is a reference to an array. In C, the transformations can often be +done earlier, but for ease of handling they are delayed as in C++.

    +
      +
    • +
      promote_operand handles the integral promotions (C standard, 6.3.1.1); +these are done only where explicitly called for.
      +
      +
    • +
    • +
      determine_arithmetic_conversions handles the usual arithmetic +conversions (C standard, 6.3.1.8). In pcc mode, the promotions are +unsigned preserving (e.g., unsigned char is promoted to unsigned +int), and all float operations are forced to double. To +determine integral promotion types type_after_integral_promotions (in +types.c) is called; a special case involving bit-fields is handled by +type_after_bit_field_integral_promotion.
      +
      +
    • +
    • +
      arg_default_promote_operand does the default argument promotions on an +operand (C standard, 6.5.2.2).
      +
      +
    • +
    • +
      take_address_of_lvalue converts an lvalue to a prvalue pointer to the +object. This is the & operator for objects. It checks for taking the +address of a bit field or a register variable. +take_reference_to_operand does the similar operation for a reference +binding.
      +
      +
    • +
    +

    When fixed-point types (an Embedded C extension described in ISO/IEC TR 18037) +are enabled, transformations of fixed-point operands are also performed as +needed. For example, in arithmetic operations involving both a fixed-point and +a floating-point operand the fixed-point operand is converted to a +floating-point type. However, unlike most other mixed-type operations, +operations involving a mix of fixed-point and integer operands do not cause the +conversion of the operands to a common type.

    +
    +
    +

    9.11. The Expression Stack#

    +

    While expressions are being scanned, the expression routines maintain an +expression stack. This stack snakes through local stack frames (i.e., it is +not allocated via malloc). The expression stack contains information on +the kind of expression being scanned, whether or not the expression is being +evaluated (e.g., the operand of a sizeof is not evaluated), and some other +minor information.

    +

    There is a new stack entry for each major kind of expression scanned, but not +for each level in the expression. That is, if one started on a normal +expression, an entry would be placed on the stack; no new entries would be +added for parentheses or grouped operators in the expression; but if a sizeof +expression, or an integral constant expression in an array size in a type in a +cast, is reached, a new entry would be placed on the top of the stack.

    +

    See push_expr_stack and pop_expr_stack.

    +
    +
    +

    9.12. Expression Lists and Initializer Lists#

    +

    The C++ language, as of the C++11 revision, uses lists of expressions in two +contexts:

    +
      +
    • +
      argument lists of function calls (syntax term expression-list), for +example “f(x, 2)”, and
      +
      +
    • +
    • +
      initializer lists (syntax term initializer-list), for example +initializers of variables as in “A a{x, 2};”.
      +
      +
    • +
    +

    Those contexts at first glance might seem to have little in common other than +the fact that they involve lists of expressions. However, the standard ties +the use of variadic template pack expansions and the use of brace-enclosed +initializer lists to those expression-list contexts, and in some cases +initializer lists become argument lists for constructor calls. So, in the end, +it becomes appropriate and desirable to represent both kinds of expression +lists with the same data structure and to process them with many of the same +routines.

    +

    The data structure used is an_init_component, which can represent

    +
      +
    • +
      an expression, e.g., “x”, in an_operand form, or
      +
      +
    • +
    • +
      a braced-enclosed list, e.g., “{1, 2, 3}”, as a pointer to a list of +init-component entries, or
      +
      +
    • +
    • +
      a designator, e.g., an array element designation like “[1]=” in an +aggregate initializer, or
      +
      +
    • +
    • +
      a continuation state to resume parsing when parsing of an initializer list +was suspended (see below).
      +
      +
    • +
    +

    In initializer processing, e.g., in decl_inits.c and expression routines +that interface with that, the name an_init_component is used. In routines +that are more related to argument lists and overload resolution, on the other +hand, the name an_arg_list_elem is used instead. It’s a typedef to the +same type, but it reflects a slightly different view of what the structure +represents. In practice, the line between the two is a bit fuzzy, and +especially with some lower-level routines the naming has to choose one or the +other name and is therefore somewhat arbitrary. Probably the main thing to +remember is that both names are used for the same data structure, with the +expression routines using the an_arg_list_elem name somewhat more often, +and the initializer routines using an_init_component exclusively. About +the only real difference that can be pointed out is that an argument list +referred to via an_arg_list_elem will never have a designator on the list.

    +

    Init-component entries are linked together into lists and trees. Something +like “{1, {2, 3, 4}}”, for example, creates a braced-init-list component +pointing to a list of two entries, the second of which is a braced-init-list +component pointing to a list of three expression components.

    +

    The essence of the initializer lists feature in the language is that the same +notation can be used for initializations that are ultimately interpreted in +many different ways. Therefore, the handling of initializer lists inherently +involves a two-step process: first, parsing the source into a tree of +init-component entries, and then interpreting those entries by context as +describing calls and initializations of various kinds. At the simplest level, +the initializer processing calls scan_braced_init_list first to scan an +entire braced-init-list, and then convert_initializer to convert it to the +type of the entity being initialized. The real work in scanning +braced-init-lists is done by parse_braced_init_list_full and its +subroutines.

    +

    In some cases the front end will process a very long braced initializer list in +parts to avoid tying up too much memory in init-component entries (which are +transient front end structures). It does this by suspending and resuming the +parsing of the initializer (repeatedly if needed) and using placeholder +init-component entries (of kind ick_continued) that point to some state +information sufficient to resume parsing later on. This is fairly transparent +to the routines processing init-component entries, but requires that those +routines use macros like next_elem and is_last_elem rather than +directly access the next pointers of init-component entries. This is only +possible for traditional aggregate initializers, but it is a worthwhile +optimization because occasionally programs contain initializers with thousands +or even millions of elements.

    +

    So some expression routines deal with an init-component (or list or tree of +them) as the “source” for an initialization. And some routines will scan an +expression or braced-init-list in init-component form to do lookahead, and then +place the init-component entry in an initializer cache, later to be fetched +out of there as if it had been freshly scanned from source. That’s used, for +example, for declarations with “auto” type; an expression is scanned so its +type can be used for the auto type deduction, and the expression is then +put into the initializer cache so it will be picked up at the appropriate time +later.

    +

    Because expression components are scanned at one point and then revisited later +for processing, some of the context information for them must be saved along +with the init-component entries. In particular, because it’s not known at the +time of scan where the full-expression boundaries will fall, each expression is +scanned in its own invented lifetime, and is “bundled” with that lifetime in +the init-component. When the expression is removed from the list later for +additional processing, the lifetime is reactivated or subsumed into an existing +lifetime. Likewise, the cross reference entries associated with an expression +are detached from the current expression and saved in the init-component, and +then reactivated when the expression is processed further. This allows things +like tracking of whether a variable is ultimately used as an lvalue or rvalue. +(See scan_expr_as_init_component for the bundling code, and +extract_operand_from_expression_component and +unbundle_init_component_expressions for the unbundling.)

    +

    The processing when a braced-init-list meets a destination type is handled by +convert_initializer (callable from outside the expression routines) and +prep_list_initializer (callable only from within the expression routines). +The latter does the real work. It has some significant subroutines:

    +
      +
    • +
      make_initializer_list_object makes an object of type +std::initializer_list<T> from a braced-init-list, which involves a call +to a constructor of initializer_list passing an array containing the +element values.
      +
      +
    • +
    • +
      value_initialization handles value-initialization, which is usually the +result when the braced-init-list is an empty list, “{}”.
      +
      +
    • +
    • +
      check_narrowing_conversion checks for the “narrowing” conversions, +issuing appropriate diagnostics.
      +
      +
    • +
    +

    prep_list_initializer operates in one of three modes:

    +
      +
    1. Producing an_operand result. This is the usual mode for internal calls +in the expression routines.

    2. +
    3. Guided by an_init_state, producing either a dynamic init entry or a +constant as a result. This is the usual mode for calls that come from +initializer processing by way of convert_initializer. This mode can +be modified to produce no diagnostics or generate no IL, which is used +for SFINAE analysis.

    4. +
    5. Doing overload resolution analysis, producing a result in an entry of +type an_arg_match_summary. That is used when evaluating arguments in +overload resolution, and in that mode no errors are issued, no IL is +generated, and the source init-components are not modified (in other +words, it’s purely exploratory).

    6. +
    +

    All processing for aggregates, i.e., arrays and aggregate classes, is done by +code in decl_inits.c. prep_list_initializer calls +prep_aggr_initializer to handle aggregate initialization from a +braced-init-list, and the initializer processing routines will call back into +the expression routines as necessary. In certain cases, processing will hop +back and forth between the two areas repeatedly. In those cases, the +an_init_state structure is used to convey information across the +transitions, e.g., to record something that expression processing knows so that +as the transfer or control goes to the decl_inits.c routines and back into +expression processing that information is still known.

    +

    The expression routines have to be quite careful about whether they are dealing +with a single expression or (a member of) an expression list, and that is made +easier by using different structures to represent those, i.e., an_operand +for a single expression, and an_arg_list_elem for (a member of) an +expression list. There are some rare cases in the C++11 language where a +brace-enclosed list is allowed in a context where a single expression is +allowed, and in those cases an_operand of kind ok_braced_init_list is +constructed, which points to an init-component list. That allows a lot of the +existing routines to accept a braced-init-list in some limited cases. To give +one example, the assignment operators allow a braced-init-list as their second +operand, even though that’s not an expression list context. So, if a +braced-init-list is present, it is scanned as an operand (see +scan_braced_init_list_as_operand) and passed around in that form to the +usual routines. When it gets to the operator-overloading routine +check_for_operator_overloading, that routine is prepared to unpack that +operand and use the braced-init-list in overload resolution. There are also +some cases when rescanning expressions (see below) where a braced-init-list +operand is constructed so that a braced-init-list can be returned through an +interface that is designed for single operand expressions.

    +

    The an_arg_operand data structure, which in the past was used for operands +in argument lists, is now reserved for a few cases where a single +non-expression-list expression needs to be returned to a caller outside the +expression routines, specifically for nontype template arguments values.

    +

    In most cases, there is no direct IL representation for initializer lists, +because when a braced-init-list meets a destination type it is converted to +some expression form that is no longer a braced-init-list. (For example, it +might become a dynamic init for a constructor call, or a nonconstant aggregate +dynamic init.) However, in prototype instantiations of templates there may be +braced-init-lists that have not met a real destination type and therefore +cannot be interpreted yet, and those must remain in braced-init-list form. For +those, the enk_braced_init_list expression node kind is used. It points to +a list of expressions, some of which may themselves be enk_braced_init_list +nodes.

    +
    +
    +

    9.13. Constant Expressions#

    +

    Constant expression processing has two fairly different modes:

    +
      +
    1. In C mode, and in C++ mode prior to C++11, each constituent of an +expression is checked immediately to see whether it is allowed in a +constant expression. An error is issued if not. So, for example, the +appearance of a throw operator in a constant expression draws an +immediate error. Class-typed values are never allowed, and neither are +user-defined conversions. This mode is referred to as the “traditional +constant expression” mode (see, for example, +curr_expr_kind_is_traditional_const).

    2. +
    3. In C++11 (roughly, when constexpr_enabled is TRUE), what matters is +whether the expression overall folds to a constant, regardless of the +constituents of the expression. So, for example, “1 ? 2 : i” is a +valid C++11 constant expression: the reference to “i” is not +evaluated and does not rule out a constant expression. Class-typed +constant values (of “literal” type) are allowed, and so are user-defined +conversions using constexpr functions. This mode is referred to as +the constexpr mode. (A variation of that mode, known as “relaxed +constexpr mode”, is enabled in C++14 mode. See also +Folding and constexpr.)

    4. +
    +

    In both modes, references to constant-valued variables and operations on +constant operands are folded as soon as they can be, [3] and a constant +value is passed up to the next level, so the basic processing is very much the +same. The main differences are:

    +
      +
    • +
      In traditional constant expressions, many operator-scan routines check +immediately on entry whether the operator they handle is valid, and issue +an error if not. In C++11 constant expressions, the check is done by +calling operator_not_allowed_in_cpp11_constant_expr (or +construct_not_allowed_in_cpp11_constant_expr), which issues no error in +unevaluated parts of expressions.
      +
      +
    • +
    • +
      Various routines that handle looking for user-defined conversions (e.g., +check_user_defined_conversions_for_cast) allow user-defined conversions +when constexpr_enabled is TRUE.
      +
      +
    • +
    • +
      Calls, including constructor calls, can be folded to constants. This is +done by first building the normal IL for the call and then, if the function +or constructor involved is constexpr, seeing whether the call can be +folded to a constant. This is done by expr_fold_constexpr_call and +expr_fold_constexpr_ctor. Implicit calls, like conversion function +calls, can also be folded to constants. If backing expressions are being +recorded, the original IL for the call is recorded as the backing +expression for the result constant.
      +
      +
    • +
    • +
      Both modes require tracking, in non-constant expressions, of whether the +expression makes use of anything not allowed in a constant expression. +[4] In traditional constant expressions, the kinds of expressions ruled +out are tracked at the an_operand level (see the +ruled_out_expr_kinds set and the rule_out_expr_kinds routine), and +for specific kinds of constant expressions (e.g., integral constant +expressions). In C++11 constant expressions, a single boolean flag called +constant_expr_ruled_out is maintained in the expression stack, and +there’s effectively only one kind of constant expression. (Note, however, +that in C++11 mode some kinds of expressions are scanned as traditional +constant expressions, e.g., preprocessor expressions and nontype template +argument address expressions, because the C++11 language rules still impose +many restrictions on the kinds of operators that can be used in them.)
      +
      In certain contexts, the rules about what is ruled out are relaxed +slightly. Specifically, in contexts that will later be subject to +parameter substitution in constexpr call evaluation, a use of the value +of a parameter variable does not rule the expression out as a potential +constant expression (because in a real evaluation, the parameter might have +a constant value). Those contexts (the return expression of a +constexpr function, the mem-initializers of a constexpr +constructor, and the field initializers of a literal class) are identified +by in_potential_constant_constexpr_context.
      +
      When init-components are used, expression processing is often done in two +steps: first, the expression is scanned into an init-component, and then +the init-component is converted to the final required type. In those +cases, the constant_expr_ruled_out flag is copied from the expression +stack into the init-component, and then back from the init-component to the +expression stack when the conversion processing is started.
      +
      +
    • +
    • +
      In several contexts, the C++11 standard calls for a “converted constant +expression” of a given type (for example, an array bound is a converted +constant expression of type size_t). This is implemented by +process_converted_constant_expression. The required type can be a +specific type, like size_t, or a general category of types, like +integral types. In traditional constant expressions, that routine just +scans a constant expression and converts it as necessary, not allowing +user-defined conversions. In C++11 mode, it allows user-defined +conversions but imposes a restriction on the types of implicit conversions +allowed at the end (e.g., not “narrowing” conversions). The C++11 rules +are therefore broader overall but more restrictive in certain cases. The +set of allowed implicit conversions is defined by +impl_converted_constant_expr_conversion_possible.
      +
      +
    • +
    • +
      constexpr calls and constructions in constant expressions produce a +constant result directly, i.e., not a temporary initialized by a constant, +but other temporaries (e.g., a temporary needed to bind “const int &” +to an integer constant 2) are created as usual. Processing within +folding fetches the value out of the temporary if appropriate, or creates a +special compile-time temporary using a ck_address/abk_temporary +constant that holds the necessary constant value. Operations that cannot +be converted to those forms are left as initialization of a temporary, +which is considered non-constant.
      +
      +
    • +
    +
    +
    +

    9.14. Rescanning Expressions#

    +

    The C++11 standard introduced some new rules for template deduction (see +WG21 paper N2634). +When a function template is considered in overload resolution, part of the +process is “template deduction,” which is an attempt to find values for the +template parameters of that template that will specify a template instance +that is a viable function for the call. The deduction rules require that +any expressions that appear in the template type be valid after +substitution of the deduced template arguments for the template parameters. +Whereas in older versions of the standard “valid” was defined by a specific +list of requirements, and only relatively simple expressions were allowed, +the C++11 rules now allow arbitrarily complex expressions inside +unevaluated contexts (e.g., sizeof and decltype), and “valid” is +defined by the normal semantic rules of the language, except that access +checking is not done. So, for example:

    +
    template <class T> auto f(T p1, T p2) -> decltype(p1 + p2) {
    +  return p1 + p2;
    +};
    +struct A {
    +  const A & operator +(const A&);
    +};
    +A a1, a2;
    +int main() {
    +  f(a1, a2);
    +}
    +
    +
    +

    Here, the call is valid only if the expression “p1+p2” is valid, which is +true only if there is a valid meaning for the “+” operator, possibly found +by doing overload resolution as in this case. Any error detected during this +process should cause only a failure of deduction for that template, and not a +hard error. (This idea is summarized in the acronym that is often used to +refer to this non-error-producing deduction process, SFINAE, which stands for +Substitution Failure Is Not An Error.)

    +

    To implement this, the Front End is capable of “rescanning” expressions to redo +the semantic checking on them. An expression saved during the initial scan of +a template is copied, with substitution of template argument values for +template parameters, and is then passed through the normal +expression-processing routines in order to do everything that would have been +done to that expression after scanning it from source tokens. A key part of +the infrastructure for performing that is that almost all operator-scanning +routines have an rcblock parameter, which can be used to pass in a rescan +control block. When that parameter is non-NULL, it gives information about the +expression to be rescanned, the template arguments and template parameters, and +some options. The operator scan function tests rcblock each time it is +about to get something from source tokens, and when rcblock is non-null it +instead uses the previously-scanned IL expression to produce the same +information in the same form. That information then passes through the parts +of the operator routine that handle semantic checking, implicit conversions and +transformations, etc., undergoing exactly the processing it would have received +if scanned from source.

    +

    Because IL expressions don’t contain all the information that was available +when the expression was originally scanned, additional information (in the form +of an_expr_rescan_info_entry) is saved whenever an expression is scanned in +a context that might later be subject to a rescan (essentially, in function +template headers). That rescan information includes a copy of the +an_operand entry that represented the IL expression, and a bit of +additional information like the operator source position.

    +

    When deduction is being done, if expr_is_rescannable is true for an +expression, it is passed to rescan_expr_with_substitution_internal, which +determines the operator-scanning function that corresponds to the top operator +of the expression (see operator_token_for_expr_rescan) and then calls that +operator-scanning function. The scanning function will then do substitution +and rescanning on its operands (see make_rescan_operands), followed by the +semantic checking and processing it usually does, before returning an operand +back to its caller, which will continue through the rescan process. If an +error occurs, the error flag in the rescan control block is set, and once the +processing returns to the top level the deduction fails.

    +

    The expression rescanning code co-exists with the older code that handled +SFINAE processing for many years before this change, e.g., routines like +copy_template_param_expr. Those routines are still used when new-style +SFINAE is turned off (see cpp0x_sfinae_enabled), and also for parts of +expressions that aren’t rescannable.

    +

    For braced-init-lists, a copy of the original list in init-component form is +saved in the rescan info operand (see +save_rescan_info_for_braced_init_list). On the rescan, that list is +rescanned. As with all rescans, the source of the rescan is mined for +source-like information, and a lot of other information is ignored. That +means, for rescanned braced-init-lists, that the original list is not modified +or really “used” – it’s a guide for the rescan as opposed to a source of +expression operands to be used directly.

    +

    Making rescanning work requires some special coding conventions in +expression-processing routines:

    +
      +
    1. The error-reporting routines cannot be called directly. Instead the +corresponding routines beginning with “expr_” must called. So, for +example, instead of “pos_error” one must call +“expr_pos_error”. This allows the interception of error calls so +that they set a flag in the expression stack instead of issuing an +error.

    2. +
    3. Code that checks access must be conditional on +expr_access_checking_should_be_done(). Note that it’s usually +necessary to avoid the access checks altogether rather than doing them +and getting to the point where an error would be issued, in order that +complete and correct IL is generated.

    4. +
    5. Calls out to utility routines in other parts of the front end must not +generate errors (unless those errors come from handling something +outside of the expression; for example, it’s okay to issue an error out +of a template instantiation that is kicked off by the expression +processing). If those utility routines might generate errors, they must +have parameters that can be used to get an error return instead of +having an error issued. For an example, see binary_operation in +folding.c and its error_detected parameter.

    6. +
    7. Scanning routines for added operators must have an rcblock +parameter, to indicate the rescan. Within such routines, all processing +that deals with source tokens must have a rescan alternative that pick +up the information from the expression being rescanned. As a general +guideline, beware of using curr_token, pos_curr_token, +end_pos_curr_token, locator_for_curr_id, +const_for_curr_token, curr_construct_ end_position, +error_position, and the error-reporting routines that use an implied +position.

      +

      Near the end of the scanning routine, call +record_operator_position_in_rescan_info to record the operator +position in the rescan information for the expression.

      +

      The scanning routine should be added to +operator_token_for_expr_rescan and +rescan_expr_with_substitution_internal so it will be rescannable. If +an operator scanning routine is not added to those routines, it will not +be rescannable, and if it comes up in a deduction context the deduction +will simply fail. That may be acceptable for certain kinds of +operators.

      +
    8. +
    9. Note that none of these restrictions are necessary for features used +only in C mode, but may be desirable anyway to allow the option of using +that feature in C++ mode at some later date.

    10. +
    +
    +
    +

    9.15. Void Expressions#

    +

    When a void expression has been scanned, either by scan_void_expression or +as the first operand in scan_comma_operator, simplify_void_operand is +called to trim off any parts of the expression that have no effect. This +trimming is done very conservatively, however. Top-level casts to void are +removed. Other kinds of trimming could be done, but they are not in the +interest of preserving the source expression. simplify_void_operand issues +a warning for expressions that have no overall effect. (See +node_has_side_effects.)

    +

    Expressions that are explicitly cast to void are not processed as void +expressions at the time of the cast; a cast-to-void node is placed on top of +the expression, and the expression is handed up. If the node makes it up to +the top level, it is simplified and the cast-to-void node is removed. Casts to +void can remain in the final intermediate language, but only in rare cases +(such as

    +
    i>0 ? (void)f(1) : (void)g(2)
    +
    +
    +

    as a statement).

    +
    +
    +

    9.16. Type Conversions#

    +

    Type conversions happen implicitly (in assignments and initializations) and +explicitly (in casts). Either way, they are done under control of the +expression routines. And they must be: in C++, conversions involve not just +the type of an expression, but whether it is and stays an lvalue or an rvalue, +and whether or not other implicit transformations may be done. The data +structure that can express these concepts is an_operand, and it exists only +within expr.c, exprutil.c, and overload.c.

    +

    To scan and process an expression correctly, one needs to know what will +ultimately be done with it, specifically what type it will be converted to. +Therefore, in all cases involving conversion, all necessary information about +the destination is passed into the expression routines, and they take care of +the conversion. By the time the expression is returned to the caller, it has +the correct type.

    +

    The routines that control these conversions have names beginning with +“prep_”:

    +
      +
    • +
      prep_conversion_operand deals with the general assignment or +initialization case.
      +
      +
    • +
    • +
      prep_initializer_operand deals with initialization. Its interesting +special case is initialization of references.
      +
      +
    • +
    • +
      prep_elision_initializer_operand deals with initialization of entities +with class types that have constructors, where it may be possible to avoid +a copy constructor call.
      +
      +
    • +
    • +
      prep_argument_operand deals with initialization when it applies to +arguments. Its interesting special case is generating copy constructor +calls for class values passed by value.
      +
      +
    • +
    • +
      prep_return_by_cctor_operand deals with expressions in return +statements (also considered an initialization case), specifically in +routines that return class values by calling a copy constructor. A dynamic +initialization entry describing the initializing operation is built and +returned to the caller.
      +
      +
    • +
    • +
      prep_assignment_operand deals with the right-side expressions in +assignments.
      +
      +
    • +
    +

    In general, these routines do their work in two parts:

    +
      +
    • +
      They determine whether or not the source operand can be converted to the +destination type, and if so, how. This is done by calling +conversion_possible.
      +
      +
    • +
    • +
      If the conversion is valid, they do it, by calling convert_operand.
      +
      +
    • +
    +

    conversion_possible uses impl_conversion_possible (from types.c) to +see if a standard conversion if available to do the conversion); if not, it +calls user_defined_conversion_possible to see if a user-defined conversion +can be done.

    +

    user_defined_conversion_possible calls conversion_to_class_possible to +check for constructors and conversion_from_class_possible to check for +conversion functions that might be applicable.

    +

    convert_operand calls cast_operand for simple conversions, and +user_convert_operand for user-defined conversions.

    +

    cast_operand and cast_node are called to change the type of an +operand or expression node. (cast_operand is actually just a wrapper +on top of cast_operand_full, which does the real work.) The caller of +those routines must have already determined that the conversion is valid. +If the cast is implicit and if it does not change the type of an operand, +that operand is usually left alone. (An exception are casts on bit fields, +because a bit-field access that has no cast on it has slightly different +properties – especially with respect to promotion – from the same access +with a cast on top.)

    +

    If the operand is a constant, type_change_constant is called to fold the +conversion.

    +

    If the operand is an expression, add_cast_to_node is called to add a cast +to the expression tree. For casting a pointer-to-class to a +pointer-to-related-class it calls add_base_class_casts or +add_derived_class_casts, and for the similar cases involving pointers to +members, it calls add_pm_base_class_casts or +add_pm_derived_class_casts.

    +

    The routines that scan explicit casts use several lower-level routines:

    +
      +
    • +
      check_user_defined_conversions_for_cast looks to see if a cast performs +any user-defined conversions, and if so applies them.
      +
      +
    • +
    • +
      set_up_for_cast_to_reference does some checking and setup in the cases +where the cast is to a reference type.
      +
      +
    • +
    • +
      cast_operand_for_reference_cast is like cast_operand, but for cases +where the operand is being cast to a reference type (including an rvalue +reference type).
      +
      +
    • +
    • +
      generic_cast_operand performs a cast when either the source operand or +the destination type involves something template-dependent in a prototype +instantiation. In such cases, it’s not generally possible to know what the +cast does, and we just want to put a generic representation of it in the +IL.
      +
      +
    • +
    +

    In C++/CLI, string literals start out as standard C++ string constants, and are +converted to C++/CLI strings if the context requires it. So, for example, if a +standard string literal is passed as an argument to a function that takes a +parameter of type “System::String^”, the string will be converted to +a C++/CLI string. This is done by setting the constant type to “handle to +System::String” without setting the implicit_cast flag. There is no +conversion of the characters in the string to Unicode (or in any other way), in +spite of what the ECMA standard seems to require. Wide string literals can +also be converted to C++/CLI strings in this way, and in that case the string +contents are treated as Unicode (as they always are in Microsoft mode, and +therefore in C++/CLI mode; but still no conversion is done). Having C++/CLI +strings represented as constants is a little strange, since ultimately they +have to result in creation of a class object on the heap, and use of its – +non-constant – address. However, MSVC treats such strings as constants, so +representing them that way makes it easier to emulate MSVC’s behavior. See +literal_type_convertible_to_cli_string, +is_literal_convertible_to_cli_string, and +convert_operand_to_handle_to_cli_string.

    +

    C++/CLI also allows boxing and unboxing conversions, i.e., between a value of a +value type and (a handle to) a boxed value in the CLR heap. Boxing can be +either an implicit conversion or a cast; unboxing is always done explicitly by +a cast. Operands having fundamental types will be implicitly converted to a +boxed value in cases where a class is required, e.g., in an example like +“(3).toString()”, or when they are implicitly converted to an appropriate +handle type. Significant routines for boxing and unboxing are +is_boxable_type, add_box_to_expression, add_unbox_to_expression, +box_value_type_operand, and unbox_after_indirection_if_required.

    +
    +
    +

    9.17. Temporaries#

    +

    create_expr_temporary creates an enk_temp_init node that defines a +expression temporary. It hangs a dynamic initialization entry under that node +and, if the temporary will require a destructor call, puts the destructor +information in the dynamic initialization entry.

    +

    alloc_dtor_dynamic_init is the routine that actually allocates the dynamic +initialization entry for the temporary. If the temporary is within the +expression in a return statement in a routine that returns its value via a copy +constructor, the destructor routine is recorded in the dynamic initialization +entry, but the destructor routine is not marked as referenced. This is because +the topmost initialization in the return expression should not indicate a +destructor (the caller does the destruction), but one cannot know at the time +the dynamic initialization entry is created whether or not it will end up being +the topmost one. Therefore, all entries are given destructors, but the +destructor routines are not marked as referenced. Each such dynamic +initialization is placed on a fixup list. After the entire expression is +processed, the destructor indication is cleared in the topmost initialization, +and fix_up_dynamic_init_dtors is called to revisit the dynamic +initialization entries and mark the (remaining) destructors as referenced.

    +

    temp_init_from_operand creates a temporary variable and initializes it from +a given operand value.

    +

    convert_operand_into_temp creates a temporary variable and initializes it +from a given operand value where there might be type conversion involved.

    +

    Note that the temporary closure object resulting from a lambda expression is +not represented with an enk_temp_init node; the enk_lambda node itself +represents the temporary (it points to an associated dynamic initialization +entry).

    +
    +
    +

    9.18. Copy Constructor Elision#

    +

    In cases where a class entity is being initialized, it is often possible to +avoid calling a copy constructor:

    +
    struct A { A(int) {...}};
    +A xx = 1;         // A::A(int)
    +
    +
    +

    The constructor in that case can be used to directly initialize the variable +xx. It’s not necessary to initialize a temporary with that constructor and +then copy the temporary to xx using a copy constructor. The process of +avoiding the unnecessary copy constructor call is called copy constructor +elision.

    +

    determine_dynamic_init_for_class_init is the routine that checks for the +possibility of copy constructor elision. It attempts to find a constructor or +other routine that can do the initialization directly. Failing that, it +returns a copy constructor.

    +

    If a copy constructor call is elided, the copy constructor must still exist. +To confirm its existence and accessibility handle_elided_copy_constructor +is called.

    +
    +
    +

    9.19. Selector Operands#

    +

    A function call like

    +
    p->f(xx);
    +
    +
    +

    is processed by (1) scanning p->f and generating a pair of operands (one +for the object, one for the function) bound together, then (2) processing the +call. Between the first step and the second, the selector operand for the +object is carried around alongside of the (primary) operand for the function.

    +

    If the function being called is a nonstatic member function (which would be the +usual case), the selector must sometimes become a pointer to an object rather +than an lvalue or rvalue for the object. conv_operand_to_object_pointer +does that transformation.

    +

    conv_selector_to_object_pointer also does that transformation but has a +flag indicating whether or not the object has been turned into a pointer, so +that the transformation is not done more than once.

    +

    conv_object_pointer_to_lvalue does the transformation in the other +direction.

    +

    It is noteworthy that the addresses of class prvalues can be taken. The +language does not allow the addresses of other kinds of prvalues to be taken. +However, the addresses of class objects are needed in order to do copy +constructor calls, member function calls, and base/derived class casts. The +language hints that all class prvalues might really be temporary variables of +class type, and that therefore it is possible to take their addresses. +Accordingly, the front end generates temporaries for class prvalues, including +cases when functions return class values. The routine +conv_class_prvalue_operand_to_object_pointer can turn an expression for a +class prvalue back into a pointer to the class object, usually by finding the +enk_temp_init node that defines the temporary and flipping the +address/value flag in that node back to “address.”

    +
    +
    +

    9.20. Overloaded Function Calls#

    +

    Overloaded function calls can be explicit calls or they can be implicit in +contexts that involve user-defined conversions (constructors or conversion +functions). In either case, the process of overload resolution must be done. +It involves considering an argument list and a set of overloaded functions, +selecting the function that best matches the argument list, then adjusting the +types of the arguments so that they are appropriate arguments for the function +selected.

    +

    The argument list is represented as a list of entries of type +an_arg_list_elem, with each entry containing either an expression in +an_operand form or a brace-enclosed list.

    +

    Each function in the overload set is considered in turn to see how well it +matches the argument list. If all of the arguments can be made to match the +function parameters, the function is added to a candidate functions list (see +type a_candidate_function). Under that entry is a list of entries that +describes how well each argument matches the function’s corresponding formal +parameter.

    +

    After all the functions are considered, select_best_candidate_functions is +called to select the function(s) with the best argument matches. For each +argument, it forms the set of functions that match best on that argument; then +the intersection of those best-match sets is formed. If the intersection has +just one function, it is the best-matching function. However, it must still be +compared to all the other functions to verify that the chosen function is +better in some argument position than each of the other functions (though not +necessarily on the same argument position for each function). After the +candidate functions list has been trimmed to a list of best-matching functions,

    +
      +
    • +
      If there are no functions on the list, an error is issued: no function is +appropriate.
      +
      +
    • +
    • +
      If there is more than one function on the list, an error is issued: several +functions are appropriate, so the call is ambiguous.
      +
      +
    • +
    • +
      If there is exactly one function on the list, that is the function to call. +The arguments are converted to the proper parameter types and the call is +generated.
      +
      +
    • +
    +

    compare_arg_match_levels compares two argument match summaries and +determines which of the two is a better match. Often, this is just a matter of +comparing the match levels. However, one of the overload resolution rules says +that if one match is a subsequence of the other (for certain cases), the +shorter sequence is the better match; this is the routine that implements that +rule. When comparing two matches at the same level, it looks to see if either +one is a subsequence of the other, and if so, the shorter sequence is called a +better match. The functions compare_argument_tiebreakers and +compare_standard_conversions are called to do most of the work.

    +

    There are several tie-breakers that will select one function over another when +the argument matches are equally good for the two functions. See +compare_candidate_functions.

    +

    If function templates are involved in the overload resolution, the candidate +functions set is built more or less as described above. After an initial check +that the number of arguments matches the number of parameters, +function_template_call_argument_deduction is called to do template +parameter deduction for the call. If deduction is possible, it returns a list +of template argument values and a routine type with the template argument +values substituted for the corresponding template parameters. This routine +type (which is a normal routine type containing no template parameters) is then +used for the rest of the overload resolution process. If the function name was +accompanied by a set of explicit template arguments (e.g., f<int>(1)), the +explicit template argument list is passed to the deduction routines and those +template parameters are not deduced. +function_template_call_argument_deduction calls matches_template_type +to do the actual deduction. After the list of candidate functions has been +built, select_best_candidate_functions considers the template candidates +alongside the non-template functions. If a template function is chosen as the +best function, find_template_function is called to build the instance of +the function, and the template function routine is then used as the result of +the overload resolution.

    +

    When template-dependent name lookup is enabled, some special processing is +done. If, in a prototype instantiation, the argument list contains an +expression of template-dependent type, overload resolution cannot be done. A +special “unknown dependent function” indication is returned to the caller. If, +in a prototype instantiation, the argument list contains no dependent +expressions, the call is a “non-dependent call” according to the standard. +Overload resolution is done, and the function selected is recorded (in +association with the token sequence number of the position of the call or +overloaded operator) by calling record_nondependent_call. Then, in a real +instantiation of the template, get_nondependent_call_info is called to +retrieve the information, if any, recorded for a given call. If there is +information associated with the call, the call is non-dependent and the +function previously determined by overload resolution is used again (overload +resolution is not done).

    +

    There are several things that are done during the processing of a +non-overloaded call that cannot be done at that point during the processing of +an overloaded function call, because it’s not known which specific function +will be called. Once overload resolution has been done, those things are done +by overloaded_function_catch_up:

    +
      +
    • +
      Check access to the function if it is a class member.
      +
      +
    • +
    • +
      Record reference information for the function called.
      +
      +
    • +
    • +
      Check that the return type of the function is not incomplete.
      +
      +
    • +
    +

    The casting of the arguments to the proper types is also a “catch-up” function.

    +

    select_overloaded_function is the top-level routine for overload +resolution. To find the best match it calls try_overloaded_function_match, +which first calls determine_arg_match_level to see how well the arguments +match (for the selector object, it uses selector_match_with_this_param +instead) and then calls select_best_candidate_functions to pick the best +function from the list of viable functions.

    +

    set_up_overload_set_traversal, next_symbol_in_overload_set, +set_up_overload_symbol_list_traversal, and +next_symbol_in_overload_symbol_list are used to set up and traverse +overload sets (the first two for normal sets, and the second two for sets +introduced by symbol lists, e.g., argument-dependent lookup or conversion +functions).

    +

    determine_arg_match_level implements the argument matching rules of the +language. An argument can match at any of the following levels:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    aml_exact
    +
    +
    +
    Exact match or trivial conversions.
    +
    +
    +
    aml_promotion
    +
    +
    +
    Match with promotions.
    +
    +
    +
    aml_std_conversion
    +
    +
    +
    Match with standard conversions.
    +
    +
    +
    aml_boxing_conversion
    +
    +
    +
    Match with boxing conversion (C++/CLI only)
    +
    +
    +
    aml_user_conversion
    +
    +
    +
    Match with user-defined conversions.
    +
    +
    +
    aml_ellipsis
    +
    +
    +
    Match with ellipsis.
    +
    +
    +
    aml_error
    +
    +
    +
    Match with error type (not in ARM).
    +
    +
    +
    aml_none
    +
    +
    +
    No match.
    +
    +
    +
    +

    C++/CLI adds a few additional complexities:

    +
      +
    • +
      Parameter arrays, where zero of more arguments at the end of the argument +list can be bundled together into a CLI array of values passed to a final +parameter with a parameter array type. Such a match is worse than other +matches except for an ellipsis match. Parameter arrays are also handled +when template type deduction is done.
      +
      +
    • +
    • +
      Overload sets are formed using hide-by-sig lookup. +use_hide_by_sig_lookup is called on a function symbol to see whether +hide-by-sig lookup applies (it only applies to members of managed classes), +and to build a list, attached to the symbol, of the symbols that should be +in the overload set for that symbol. The overload set traversal routines +set_up_overload_set_traversal and next_symbol_in_overload_set +determine whether the symbol requires hide-by-sig lookup, and traverse the +hide-by-sig list if so, skipping any inaccessible functions. Since +hide-by-sig applies only to member functions, it never has to co-exist with +argument-dependent lookup.
      +
      +
    • +
    +
    +
    +

    9.21. User-defined Conversions#

    +

    conversion_to_class_possible looks for a constructor or conversion function +that will convert an expression to a particular class type, and +conversion_from_class_possible looks for a conversion function that will +convert an expression from a class type to a specific other type or to a +built-in type from a given set. These use try_overloaded_function_match +for the constructor cases, and try_conversion_function_match_full for the +conversion function cases.

    +

    Conversion functions that return reference types are a little tricky in that +their results are lvalues or xvalues, but that falls out more or less naturally +from the fact that operand transformations (like glvalue to prvalue) are put +off as long as possible. When the result of a conversion is to be bound to a +reference, the kind of reference (lvalue reference or rvalue reference) +constrains the choice of suitable conversion functions.

    +

    C++/CLI adds static conversion functions. Those can convert to a class in +addition to from a class, and can also convert to/from a handle to a class or +tracking reference to a class. Therefore, places that look for conversion +functions must also look in the destination class for conversion functions, and +in the base classes of the source type, and must also consider handles to be +class-like as both source and destination types of a conversion, because the +classes underlying those handle types may have static conversion functions. +See try_static_conversion_function_match and +cli_handle_user_defined_conversion_possible.

    +
    +
    +

    9.22. Operator Overloading#

    +

    check_for_operator_overloading looks for operator overloading +possibilities. It is called only when one or more of the operands of an +operator has a class or enum type [5]. It considers three ways of +processing the operands:

    +
      +
    1. As arguments of an operator member function.

    2. +
    3. As arguments of an operator function that is not a member function.

    4. +
    5. As operands of the built-in version of the operator, with the operands +converted from the class types to acceptable built-in types by use of +conversion functions. This is not tried for operators that have a +built-in meaning for classes (”,”, “->”, “=”, and unary +“&”).

    6. +
    +

    As with overload resolution for function calls, the overloaded operator +resolution process considers each of the alternatives (functions and built-in +operator) in turn and builds a list of candidate functions. After all the +alternatives have been examined, the best one is selected (or an error is +issued). The operands are then adjusted to match the function or built-in +operator that was selected.

    +

    try_overloaded_function_match is called (possibly several times) to +determine how well the operator functions match the operands. +opname_member_function_symbol is used to find the applicable member +functions (if any), and nonmember_operator_function_lookup is used to find +the applicable nonmember functions (if any); special processing is done for +those if the operand types come from namespaces.

    +

    try_conversions_for_builtin_operator is called to try to find conversions +that will allow use of the built-in version of the operator. Its subroutines +– operand_type_pattern_for_operator, try_builtin_operands_match, and +try_pointer_builtin_operands_match – do the necessary investigation.

    +

    C++/CLI adds some additional issues:

    +
      +
    • +
      When the first operand is a handle, it is overloadable much as if it had +the underlying class type. An expression like “h+x” can be treated as +“h->operator+(x)”.
      +
      +
    • +
    • +
      When either operand is a handle, it may be possible to use a static +conversion function to convert the operand to a fundamental type for which +there is a builtin version of the operator, much as is done for class +operands.
      +
      +
    • +
    • +
      Static operator functions can apply. They don’t have a “this” +parameter, so the first operand matches the first parameter, and the +second operand (if there is one) the second parameter. “a+b” could +become “X::operator+(a,b)”. These are also searched for in the +class of the second operand, if there is one and it has class type.
      +
      +
    • +
    • +
      Operator synthesis can be done. If a class does not have an +“operator+=”, for example, the combination of an “operator+” and an +“operator=” can be used.
      +
      +
    • +
    • +
      In certain cases, string literals can act as if they are handles to +System::String, which then makes them overloadable.
      +
      +
    • +
    +
    +
    +

    9.23. Address of Overloaded Function#

    +

    When an overloaded function appears in an expression, it is represented an as +indefinite function operand, which is basically just an operand that points to +the overloaded function symbol.

    +

    When such an operand is subjected to the function-to-pointer transformation, +the operand stays an indefinite function, but changes from a function +designator to a prvalue pointer.

    +

    When such an operand shows up in a conversion where the destination type is a +function pointer, find_addr_of_overloaded_function_match is called to find +out which (if any) of the specific functions matches the required function +pointer. The operand is then converted to the specific function pointer in +cast_operand_full; overloaded_function_catch_up is called to do +whatever would have been done had it been known all along which specific +function was intended.

    +

    If the overload set includes one or more template functions, the resolution +algorithm is as follows:

    +
      +
    1. If there is an exact match in the set of non-function-templates, it is +selected (if there is more than one, the pointer use is ambiguous); +otherwise,

    2. +
    3. If there is a template function from which a function can be generated +that will match exactly, it is selected (if there is more than one, the +pointer use is ambiguous); otherwise,

    4. +
    5. If there is a non-exact match in the set of non-function-templates, it is +selected (this can only happen with pointers to member functions, where +an implicit conversion from base to derived is allowed).

    6. +
    +

    matching_template_function is called to attempt to find a match under rule +(2).

    +
    +
    +

    9.24. Range-based for statement#

    +

    The C++11 range-based for statement is checked and assembled by +check_range_based_for_statement. It determines which of the three +“patterns” is applicable for the statement and calls +check_range_based_for_array_case, check_range_based_for_member_case, or +check_range_based_for_default_case as necessary to perform the necessary +semantic checks and generate the IL.

    +

    The range-based-for statement takes the form:

    +
    +
    +
    for ( for-range-declaration : expression ) statement
    +
    +
    +

    and is defined to be equivalent to:

    +
    +
    +
    {
    +
    +
    auto && __range = (expression);
    +
    for ( auto __begin = begin-expr,
    +
    +
    +
    +
    __end = end-expr;
    +
    +
    __begin != __end;
    +
    ++__begin ) {
    +
    +
    for-range-declaration = *__begin;
    +
    statement
    +
    +
    }
    +
    +
    }
    +
    +
    +

    Lower level routines for handling variable initializer expressions, member +lookup, overload resolution, etc. are shared (where applicable) with the +for-each statement handling described below (together the range-based for +and for-each statements are referred internally as “enhanced for” +statements).

    +
    +
    +

    9.25. For-each Statement#

    +

    The C++/CLI for-each statement is checked and assembled by +check_for_each_statement. There are four “patterns” for the for-each +statement (the STL pattern, the CLI collection pattern, the CLI array pattern, +and the native array pattern). check_for_each_statement determines the +pattern matched by a given loop, and calls the right one of four routines, each +charged with checking one of the patterns and building the IL.

    +

    The for-each statement is defined in terms of a rewrite for each of the +patterns. For example, a for-each loop that matches the native array pattern +is rewritten from

    +
    +
    +
    for each (T t in c) statement
    +
    +
    +

    to

    +
    +
    +
    { C &cref = c;
    +
    +
    I *cend = &cref[0]+c_num_elements;`
    +
    I *i = cref;
    +
    for (; i != cend; ++i) {
    +
    +
    T t = static_cast<T>(*i);
    +
    statement
    +
    +
    }
    +
    +
    }
    +
    +
    +

    The IL for this case contains variables and associated scopes for the iterator +variable and the added temporary variables, initializer expressions for each of +those, and additional expressions for the loop != and ++ expressions. +Those are relatively simple in this case, but in other cases and other patterns +the generated expressions can be complex, and developing them may involve +member lookup, overload resolution, operator overloading, or user-defined +conversions. The front end’s goal is to provide IL that completely describes +the actions needed to implement the loop, while at the same time retaining the +parts in a high-enough-level form that source-analysis programs can discern the +original loop variables and expressions.

    +
    +
    +

    9.26. Properties#

    +

    Microsoft mode has properties, which are data members of classes that are +implemented by accessor functions, e.g., one to get the current value of the +property, and one to set the current value of the property. Properties come in +two kinds:

    +
      +
    • +
      Old-style properties, indicated by the __declspec(property(… )) +attribute. The accessor functions are only loosely associated with the +property, by being named in the attribute.
      +
      +
    • +
    • +
      New-style properties in C++/CLI, which begin with the “property” +context-dependent keyword. The accessor functions are declared as part of +the property declaration, in a form that looks vaguely like a nested class.
      +
      +
    • +
    +

    In both cases, the IL has a description of the property declaration, in +something close to the source form (that information is held in +an_property_or_event_descr entry). However, also in both cases, references +to the properties are expanded by expression processing, so they are not +retained in source form. A bit of source code like “p+=1” +might be expanded into a series of calls something like “call the get accessor +for p, call operator+ on the fetched value and 1, and call the put +accessor to store the computed value.” The generated IL contains some tags on +various nodes in the expansion that help source-analysis code recover the +original meaning, though in a cumbersome way.

    +

    Property references cannot be rewritten immediately. They have to be carried +around for a short while in expression processing until it becomes clear from +the context how the property is being used, i.e., a “get” or a “set”. Before +they are rewritten, property references are carried around as an_operand +entries of kind ok_property_ref. The operand can include a list of +subscripts that is part of the property reference. Once the context is +established, the property reference is rewritten; that’s handled by +rewrite_property_reference. As hinted at above, some rewrites are more +complicated than a simple “get” or “set”, and might involve a “get”, some +operation on the fetched value, possibly surrounded by conversions, and finally +a “set”. That happens for compound assignment operators and for pre- and +post-increment and -decrement operators. In such cases, the operand is cloned +(see clone_operand), so that it will only be evaluated once, and +rewrite_property_reference is called twice, once for the “get” and once for +the “set”.

    +

    C++/CLI events are very similar to the new-style properties, in representation +and in the fact that references are expanded by the front end.

    +
    +
    +

    9.27. C++/CLI Generics#

    +

    Expression processing for C++/CLI generics, meaning handling of expressions +during the scanning of a generic definition, mostly falls out of normal +expression processing. During the generic definition, the parameters of the +generic (represented as template parameters) are given values that are +generated class types that reflect the constraints on the generic parameters. +So, for example, if a generic parameter is constrained to derive from an +interface I, the generated class type will be such that it will be possible to +look up members of I in the class and find them in a base class that is I. +That makes most operations work without special handling. Also, for many +cases, the template parameter’s value is a handle to the constraint class type, +so that operations like assignment work because they become handle assignments +instead of class assignments (where it might not be possible to know whether +the class will have an appropriate operator= at runtime). There are a few +special cases with casting, where a generic parameter might or might not be a +value class type, or might or might not effectively be a handle at runtime. +Casts are rejected if they might be invalid because they treat a value type as +a handle, or vice-versa. Also, casts are rejected if it can be shown at +compile time that the source value type can never satisfy the constraints of +the destination type.

    +
    +
    +

    9.28. Reference Information#

    +

    To track references to identifiers, ref_entry is called for each identifier +reference in an expression. The information provided is used to write +cross-reference information (when requested) and to set the referenced, used, +modified, and address-taken flags in variable and routine entries. For some +identifiers, the kind of reference is known immediately, so +record_symbol_reference is called to record the information. For others, +the kind of reference is dependent on the expression context, and therefore it +is not known immediately. For such cases, an entry called a_ref_entry is +allocated and placed on a list of such entries for the current expression. +When the reference kind becomes known, the kind in the entry is updated (see +change_ref_kinds). At the end of the expression, +flush_ref_entries_list is called. It scans the entries on the list, calls +record_symbol_reference to record the (now fully determined) reference, and +then frees the entries.

    +
    +
    +

    9.29. Diagnostic output#

    +

    Diagnostic output in the expression-processing routines must be handled +specially in order that it be possible to suppress diagnostics when rescanning +an expression during template deduction. For that reason, what would normally +be simply a call of a diagnostic-output routine must be slightly more +complicated in the expression-processing source files. For the simpler +diagnostics, there are direct expr_ equivalents:

    +
      +
    • +
      For pos_error, use expr_pos_error.
      +
      +
    • +
    • +
      For pos_warning, use expr_pos_warning.
      +
      +
    • +
    • +
      For pos_diagnostic, use expr_pos_diagnostic.
      +
      +
    • +
    • +
      For syntax_error, use expr_syntax_error.
      +
      +
    • +
    +

    Other diagnostic calls should be enclosed in a test of +expr_error_should_be_issued or expr_diagnostic_should_be_issued, as +appropriate.

    +

    Any access-checking code must be conditioned on +expr_access_checking_should_be_done. It’s not enough to simply surround +access-error diagnostic calls with a suppression test; when template deduction +is being done, it must be as if no access checking is even attempted, and the +flow of control must continue as if the error were not present.

    +
    +

    9.29.1. Folding of Constant Operations#

    +

    There are four main files involved in folding constant operations:

    +
      +
    • +
      const_ints.c contains the code for low-level integer operations, with +const_ints.h containing associated declarations.
      +
      +
    • +
    • +
      fixed_pt.c contains the code for low-level fixed-point operations, with +fixed_pt.h containing associated declarations.
      +
      +
    • +
    • +
      float_pt.c contains the code for low-level floating-point operations, +with float_pt.h containing associated declarations.
      +
      +
    • +
    • +
      folding.c contains the higher-level code that handles folding of +constant operations and of type conversions on constants. folding.h +contains associated declarations. Code for folding of constexpr calls +and operations is also here.
      +
      +
    • +
    +
    +
    +
    +

    9.30. Low-level Integer Routines#

    +

    const_ints.c contains the routines that manipulate low-level integers. Any +integer literal constant in the source program and any operation on constant +integers implied by the source program are ultimately handled by the routines +here. For the most part, the low-level integer form can be viewed as a +representation for target machine integers on the host machine, although it is +also used for some things (like array dimensions) that are only arguably target +machine constants.

    +

    The point of these routines is to collect all the code that operates on target +integers in one place, so that it can be modified if necessary, and so that the +rest of the front end does not need to deal with the subtleties of signed and +unsigned representations, overflow, etc.

    +

    There are two different possible representations for integer values (type +an_integer_value):

    +
      +
    • +
      If there is some host integer type that is big enough to hold any target +integer (the usual case), an integer value is simply represented as a host +integer. Operations on that representation are done using the host C +operators, with extra overflow checking. If the host C compiler supports +long long, that type can be used as the representation type.
      +
      +
    • +
    • +
      Otherwise (for example, in a cross-compiler for a 64-bit target running on +a 32-bit host), an integer value is represented as a struct containing +an array of small integers (of type an_int_value_part). Operations on +that representation are simulated in software.
      +
      +
    • +
    +

    (See configuration constant INTEGER_VALUE_REPR_IS_A_HOST_INTEGER.)

    +

    The an_integer_value representation may be used to represent signed or +unsigned quantities. It is not self-identifying in that regard, i.e., the +representation does not contain an indication of the signedness of the value. +Therefore, in cases where signedness is significant, (e.g., multiplication), +the caller must pass in a separate argument indicating the signedness to be +used for the integer value. For values that can be represented in both the +signed and unsigned forms, the representation in the two forms is the same. +That allows small constants to be used as either signed or unsigned quantities +as the need arises.

    +

    The const_ints.c routines deal with integer values as single-sized +entities, the size being large enough to hold any of the target integer types. +The routines check for overflow relative to that representation, but they know +nothing of different integer types and their sizes.

    +

    Most routines in const_ints.c operate on values in the an_integer_value +form. For convenience, some routines are provided that operate on the IL +a_constant form, but it’s a circumspect use of that form: as far as the +routines are concerned, a_constant is a structure that only contains +an_integer_value (in the variant integer_value field) and a type (in +the type field) that can be passed to int_constant_is_signed to +determine the signedness of the value. No other fields of the constant need be +defined.

    +

    The routines that are used to translate between a_host_large_integer (some +large built-in host integral type) and the an_integer_value form are

    +
      +
    • +
      set_integer_value,
      +
      +
    • +
    • +
      set_unsigned_integer_value,
      +
      +
    • +
    • +
      value_of_integer_constant, and
      +
      +
    • +
    • +
      unsigned_value_of_integer_constant.
      +
      +
    • +
    +

    Routines used to get attributes of integer values are

    +
      +
    • +
      get_integer_size_and_alignment and
      +
      +
    • +
    • +
      int_constant_is_signed.
      +
      +
    • +
    +

    Utility routines used to determine the magnitude of an integer value, create a +bit mask, and sign-extend a value are

    +
      +
    • +
      bits_required_to_represent_integer_constant,
      +
      +
    • +
    • +
      make_integer_value_mask, and
      +
      +
    • +
    • +
      sign_extend_integer_value.
      +
      +
    • +
    +

    Routines used to format integer values in decimal string form are

    +
      +
    • +
      str_for_integer_constant.
      +
      +
    • +
    +

    Routines used to compare integer values (including some comparisons against the +limits of integers of given kinds) are

    +
      +
    • +
      cmp_integer_values,
      +
      +
    • +
    • +
      cmp_integer_constants,
      +
      +
    • +
    • +
      cmplit_integer_value,
      +
      +
    • +
    • +
      cmpulit_integer_value,
      +
      +
    • +
    • +
      in_range_for_integer_kind,
      +
      +
    • +
    • +
      le_max_value_for_integer_kind, and
      +
      +
    • +
    • +
      is_max_value_for_integer_kind.
      +
      +
    • +
    +

    On these, the two values being compared may have independent signedness. The +lit routines do comparison against a_host_large_integer or +a_host_large_unsigned value, typically a small constant.

    +

    Routines used to perform arithmetic and logical operations are

    +
      +
    • +
      add_integer_values,
      +
      +
    • +
    • +
      subtract_integer_values,
      +
      +
    • +
    • +
      multiply_integer_values,
      +
      +
    • +
    • +
      divide_integer_values,
      +
      +
    • +
    • +
      remainder_integer_values,
      +
      +
    • +
    • +
      and_integer_values,
      +
      +
    • +
    • +
      or_integer_values,
      +
      +
    • +
    • +
      xor_integer_values,
      +
      +
    • +
    • +
      shift_left_integer_values,
      +
      +
    • +
    • +
      shift_right_integer_values, and
      +
      +
    • +
    • +
      complement_integer_values.
      +
      +
    • +
    +

    On these, the two operands must have the same signedness (except that there are +versions of the add and subtract routines for the independent-signedness +cases). The result of the operation overwrites the first operand.

    +

    For some kinds of values, it’s just too much of a nuisance to use the integer +value routines, so the front end converts such values to +a_host_large_integer or a_host_large_unsigned (which are typically +signed and unsigned long, or signed and unsigned long long) and +operates on them in that form. The values handled that way are:

    +
      +
    • +
      Sizes of objects, including arrays (conceptually of type size_t on the +target).
      +
      +
    • +
    • +
      Offsets relative to objects (conceptually of type ptrdiff_t on the +target).
      +
      +
    • +
    • +
      Single characters (but not a character constant containing one or more +characters).
      +
      +
    • +
    • +
      Single wchar_t values.
      +
      +
    • +
    +

    Note that the target size_t and ptrdiff_t are allowed to be bigger than +the host a_host_large_integer; the use of a_host_large_integer +representation just restricts the possible constant values of that type that +the front end can deal with. The conversions into the host types are done with +overflow checking, so the front end will issue errors for values larger than +those it can accommodate.

    +
    +
    +

    9.31. Low-level Fixed-point Routines#

    +

    The routines in fixed_pt.c manipulate the internal repreentation of +fixed-point constants on the host machine. As with the integer routines, they +are collected in one place so that they can be changed more easily and so that +the front end at large need know nothing about the fixed-point representation.

    +

    They implement very low-level operations on the internal form of fixed-point +constants. Some of the standard product versions of these routines (e.g., for +conversion of a decimal text form of a fixed-point constant to internal form) +are not always accurate to the last significant bit: They are best viewed as +prototype routines for testing purposes, to be replaced by real routines for +the production version.

    +

    The main routines (or macros) in fixed_pt.c are the following:

    +
      +
    • +
      cmp_fixed_point_constants
      +
      +
    • +
    • +
      fxp_init_value
      +
      +
    • +
    • +
      fxp_value_is_zero
      +
      +
    • +
    • +
      fxp_string_to_fixed_point
      +
      +
    • +
    • +
      fxp_hex_string_to_fixed_point
      +
      +
    • +
    • +
      conv_fixed_point_to_fixed_point
      +
      +
    • +
    • +
      conv_integer_to_fixed_point
      +
      +
    • +
    • +
      conv_fixed_point_to_integer
      +
      +
    • +
    • +
      conv_float_to_fixed_point
      +
      +
    • +
    • +
      conv_fixed_point_to_float
      +
      +
    • +
    • +
      fxp_to_string
      +
      +
    • +
    • +
      fxp_add
      +
      +
    • +
    • +
      fxp_subtract
      +
      +
    • +
    • +
      fxp_multiply
      +
      +
    • +
    • +
      fxp_divide
      +
      +
    • +
    • +
      fxp_compare
      +
      +
    • +
    • +
      fxp_hash
      +
      +
    • +
    +
    +
    +

    9.32. Low-level Floating-point Routines#

    +

    The routines in float_pt.c manipulate target floating-point constants on +the host machine. As with the integer routines, they are collected in one +place so that they can be changed more easily and so that the front end at +large need know nothing about the floating-point representation.

    +

    They implement very low-level operations on the internal form of floating-point +constants. When USE_HOST_FP_CONVERSION_ROUTINES is TRUE (the default), +binary to decimal conversions are performed using standard UNIX conversion +routines provided by the host. When USE_HOST_FP_CONVERSION_ROUTINES is +FALSE, internal routines (in floating.c) are used to perform these +conversions. Arithmetic operations are performed without range checking; +therefore, they are best viewed as prototype routines for testing purposes, to +be replaced by real routines for the production version.

    +

    In cases where the target configuration supports floating-point types that are +not supported by the host compiler (e.g., __float128 and __float80 on +Windows), the Berkeley SoftFloat library can be used to perform +arithmetic operations on the host. This configuration can be selected by +setting the USE_SOFTFLOAT configuration macro to TRUE. In such +configurations, the USE_HOST_FP_CONVERSION routines is automatically set to +FALSE to enable a software-only floating-point configuration. Note that +such configurations are inherently slower than those that use floating-point +hardware. See the SoftFloat web site for licensing information.

    +

    The main routines in float_pt.c are the following:

    +
      +
    • +
      fp_change_kind
      +
      +
    • +
    • +
      fp_string_to_float
      +
      +
    • +
    • +
      fp_hex_string_to_float
      +
      +
    • +
    • +
      fp_to_string
      +
      +
    • +
    • +
      fp_long_to_float
      +
      +
    • +
    • +
      fp_unsigned_long_to_float
      +
      +
    • +
    • +
      fp_to_host_large_integer
      +
      +
    • +
    • +
      fp_to_host_large_unsigned
      +
      +
    • +
    • +
      fp_is_zero_constant
      +
      +
    • +
    • +
      fp_add
      +
      +
    • +
    • +
      fp_subtract
      +
      +
    • +
    • +
      fp_multiply
      +
      +
    • +
    • +
      fp_divide
      +
      +
    • +
    • +
      fp_compare
      +
      +
    • +
    • +
      fp_hash
      +
      +
    • +
    +
    +
    +

    9.33. Constant Folding#

    +

    The routines in folding.c do folding of constant operations and type +conversions on constants.

    +

    This folding is done in target machine arithmetic. For integers, routines in +const_ints.c do the actual operations on the generic integer value, but the +routines here add a layer that understands specific integer types, and does +overflow checking, masking, and sign extension according to the size and +signedness of the integer type. For fixed-point and floating operations, +target-specific code in fixed_pt.c and float_pt.c does the actual +operations. For pointer operations, the constants are either address constants +(a base symbol plus a byte offset) or integer constants cast to a pointer type +(the most common of these is NULL/0). The routines get_pointer_offset +and set_pointer_offset are used to extract and set the offsets in both +those cases.

    +

    The folding routines detect errors and warnings and call the error routines to +report them. When they are called in nonconstant contexts (like executable +statements), errors are downgraded to warnings, and the operation is left +unfolded, to be tried at runtime.

    +

    If the folding routines are unable to fold an operation to a constant (because +of some attribute of the operands, not because of an error), they return a flag +did_not_fold set to TRUE, which tells the caller to leave the operation +unfolded. For example, the pointer difference of pointers to different static +objects is a constant, but one that is unknowable until link time. +did_not_fold would be returned TRUE for that case (and no error or warning +would be indicated). The folding routines also record the unfolded expression +in constants resulting from the folding.

    +

    unary_operation and binary_operation are the top-level routines for +operations on constants. They take as input an operator and one or two +constants, and produce a constant (or an error indication) as output. The +operations are done with all necessary checking for overflows, etc. The +routines called by unary_operation to do the actual folding are

    +
      +
    • +
      do_inegate,
      +
      +
    • +
    • +
      do_fxnegate,
      +
      +
    • +
    • +
      do_fnegate,
      +
      +
    • +
    • +
      do_xnegate,
      +
      +
    • +
    • +
      do_complement, and
      +
      +
    • +
    • +
      do_not,
      +
      +
    • +
    +

    and those called by binary_operation are:

    +
      +
    • +
      do_iadd,
      +
      +
    • +
    • +
      do_isubtract,
      +
      +
    • +
    • +
      do_imultiply,
      +
      +
    • +
    • +
      do_idivide,
      +
      +
    • +
    • +
      do_remainder,
      +
      +
    • +
    • +
      do_shiftr,
      +
      +
    • +
    • +
      do_shiftl,
      +
      +
    • +
    • +
      do_icompare,
      +
      +
    • +
    • +
      do_and,
      +
      +
    • +
    • +
      do_or, and
      +
      +
    • +
    • +
      do_xor
      +
      +
    • +
    +

    for integers;

    +
      +
    • +
      do_land and
      +
      +
    • +
    • +
      do_lor
      +
      +
    • +
    +

    for scalars;

    +
      +
    • +
      do_fxadd,
      +
      +
    • +
    • +
      do_fxsubtract,
      +
      +
    • +
    • +
      do_fxmultiply,
      +
      +
    • +
    • +
      do_fxdivide, and
      +
      +
    • +
    • +
      do_fxcompare
      +
      +
    • +
    +

    for fixed-point;

    +
      +
    • +
      do_fadd,
      +
      +
    • +
    • +
      do_fsubtract,
      +
      +
    • +
    • +
      do_fmultiply,
      +
      +
    • +
    • +
      do_fdivide, and
      +
      +
    • +
    • +
      do_fcompare
      +
      +
    • +
    +

    for floating-point;

    +
      +
    • +
      do_xadd,
      +
      +
    • +
    • +
      do_xsubtract,
      +
      +
    • +
    • +
      do_xmultiply,
      +
      +
    • +
    • +
      do_xdivide,
      +
      +
    • +
    • +
      do_jmultiply,
      +
      +
    • +
    • +
      do_jdivide, and
      +
      +
    • +
    • +
      do_xcompare
      +
      +
    • +
    +

    for complex and imaginary;

    +
      +
    • +
      do_padd,
      +
      +
    • +
    • +
      do_pdiff, and
      +
      +
    • +
    • +
      do_pcompare
      +
      +
    • +
    +

    for pointers; and

    +
      +
    • +
      do_pmcompare
      +
      +
    • +
    +

    for pointers to members.

    +

    Actual shifting is performed by do_shift, which calls check_shift_count +for error checking. The shifting is implemented with the integer size and +sign-extension appropriate for the target.

    +

    When pointer addition or subtraction is folded, the resulting constant, if an +address constant, is checked to see if the offset lies within the base object. +Offsets beyond the end of the object and negative offsets are flagged with a +warning (most often, this is due to a constant subscript out of bounds). This +is checked by valid_address_constant.

    +

    In ordinary constant folding, valid_address_constant will allow the +position just past the end of an object without a warning, since it does not +know whether the address of that position is required (which is allowed by ANSI +C) or the value (which is an error). The routine using_lvalue calls +valid_address_constant again to check for the error once it is known that +it is the value that is being accessed.

    +

    type_change_constant_full changes the type of a constant to something else. +It’s usually called through the simpler interface type_change_constant. It +has subroutines

    +
      +
    • +
      conv_integer_to_integer,
      +
      +
    • +
    • +
      conv_integer_to_float,
      +
      +
    • +
    • +
      conv_float_to_integer,
      +
      +
    • +
    • +
      conv_float_to_float,
      +
      +
    • +
    • +
      conv_pointer_to_whatever,
      +
      +
    • +
    • +
      conv_integer_to_pointer,
      +
      +
    • +
    • +
      conv_ptr_to_member_to_ptr_to_member, and
      +
      +
    • +
    • +
      conv_integer_to_ptr_to_member.
      +
      +
    • +
    +

    with the obvious functions. Warnings about truncation and hidden changes of +sign are issued (the latter are suppressed if the type change was the result of +an explicit cast or if the operand was a non-decimal constant).

    +

    Casts of pointers to classes to pointers to base or derived classes are handled +by

    +
      +
    • +
      fold_base_class_cast and
      +
      +
    • +
    • +
      fold_derived_class_cast.
      +
      +
    • +
    +

    The similar cases for pointers to members are handled by

    +
      +
    • +
      fold_pm_base_class_cast and
      +
      +
    • +
    • +
      fold_pm_derived_class_cast.
      +
      +
    • +
    +

    fold_field_selection is called to fold a field selection relative to a +constant address. Because of the unusual second operand (a field rather than a +constant), binary_operation could not be used for this case. If the field +is a bit field, fold_field_selection returns a did_not_fold flag.

    +

    constant_glvalue_address and its companion routine +constant_prvalue_pointer examine expression trees to determine if they +represent constant addresses, computing and returning the appropriate constant +value on the fly.

    +
    +
    +

    9.34. Folding and constexpr#

    +

    C++11 and C++14 permit calls to constexpr functions and constructors in +constant-expressions. To implement this, the front end includes an IL +interpreter implemented in the source file interpret.c. The start of that +file contains extensive comments describing the overall structure of the +interpreter. The global variable relaxed_constexpr_enabled is TRUE +when the C++14 version of the constexpr feature is enabled. This enables +the interpretation of expressions, like assignments, with side-effects (valid +in C++14, but not C++11). It also removes C++11 structural constraints for +constexpr functions and constructors (e.g., it allows multiple statements +in definitions).

    +

    To avoid burdening the IL or the rest of the front end, the interpreter does +not record state information in the IL or other front end structures. Instead, +it maintains its own data structures linked to the IL through efficient hash +tables. It does, however, use front end types to represent integral and +floating-point values. Other kinds of values (e.g., addresses) are represented +using interpreter-specific structures.

    +

    The interpreter can fold calls to constexpr functions and constructors, but +it can also more generally fold expressions and dynamic initializations.

    +

    The entry points into the interpreter are interpret_expr,interpret_dynamic_init,interpret_constexpr_call, and +interpret_constexpr_ctor. These functions return a boolean value +indicating whether interpretation succeeded (TRUE) or failed (FALSE). +Interpretation can fail because it encountered an operation not permitted +during constexpr evaluation (e.g., a virtual function call), including +operations with undefined behavior (e.g., attempting to fetch a value from +uninitialized storage). It can also fail when the cost of interpretation +becomes too high. The parameters limiting that cost can be set through the +command-line options --max_depth_constexpr_call and +--max_cost_constexpr_call. If interpretation fails, the interpreter also +returns a diagnostic description indicating the reason for the failure (that +description can be emitted as part of the diagnostic if a constant was +required).

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/ext_intf/index.html b/doc/ext_intf/index.html new file mode 100644 index 0000000..43476a4 --- /dev/null +++ b/doc/ext_intf/index.html @@ -0,0 +1,8972 @@ + + + + + 2. External Interface - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    2. External Interface#

    +

    Bear in mind that this information applies to the standard product. If any +local modifications are made, the documentation given to users must be adjusted +accordingly.

    +
    +

    2.1. Command Line#

    +

    The front end is invoked by a command of the form

    +
    +

    edgcpfe [options] ifile

    +
    +

    to compile the single input file ifile. If - (hyphen) is specified +for ifile, the front end reads from stdin. [1] No particular +file name suffix is required on input files.

    +

    Command line options may be specified using either single character option +codes (e.g., -o) or keyword options (e.g., --output). A single +character option specification consists of a hyphen followed by one or more +option characters (e.g., -Ab). If an option requires an argument, the +argument may immediately follow the option letter, or may be separated from the +option letter by white space. A keyword option specification consists of two +hyphens followed by the option keyword (e.g., --strict). Keyword options +may be abbreviated by specifying as many of the leading characters of the +option name as are needed to uniquely identify an option name (for example, the +--wchar_t_keyword option may be abbreviated as --wc). If an option +requires an argument, the argument may be separated from the keyword by white +space, or the keyword may be immediately followed by =argument. When +the second form is used there may not be any white space on either side of the +equals sign.

    +

    If the configuration flag COMPILE_MULTIPLE_SOURCE_FILES is defined as TRUE, +a list of files may appear for ifile. If a list of files is specified, +options that specify a compilation output file (--output, --list, and +--xref) may not be used, and the name of each source file is written to the +error output file as the compilation of that file begins.

    +

    When one of the preprocessing-only modes is specified (see below), the +--output option can be used to specify the preprocessing output file. If +--output is not specified, preprocessing output is written to stdout. +Preprocessing output has trigraphs and line splices processed (and thus they do +not appear in their original form).

    +

    When compilation (rather than just preprocessing) is done, the output (if any) +from the compilation is written to a file selected by the back end; see the +documentation of the back end for further information. For versions of the +front end that generate an intermediate language file, the --output option +can be used to specify the IL output file.

    +

    The options are described in the following subsections (organized by +category).

    +
    +

    2.1.1. Language Dialect Options#

    +

    The following options select among various C and C++ dialects.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --anachronisms
    +
    --no_anachronisms
    +
    +
    +
    Enable or disable anachronisms in C++ mode. The default for this +option is specified by DEFAULT_ALLOW_ANACHRONISMS. This option is +valid only in C++ mode.
    +
    +
    +
    --c
    +
    -m
    +
    +
    +
    Enable compilation of C rather than C++.
    +
    +
    +
    --c89
    +
    +
    +
    Enable the compilation of the C89 version of C.
    +
    +
    +
    --c99
    +
    --no_c99
    +
    +
    +
    Enable or disable compilation of the C99 version of C. In either +case, C rather than C++ is compiled.
    +
    +
    +
    --c11
    +
    +
    +
    Enable language features added in the C11 standard. This option +cannot be combined with options enabling or requiring a C++ mode.
    +
    +
    +
    --c18
    +
    --c17
    +
    +
    +
    Enable support for C18 (which is only a minor “bug fix” change from +C11). This option cannot be combined with options enabling or +requiring a C++ mode.
    +
    +
    +
    --c23
    +
    +
    +
    Enable language features added in drafts of the anticipated C23 +standard. This option cannot be combined with options enabling or +requiring a C++ mode.
    +
    +
    +
    --old_c
    +
    -K
    +
    +
    +
    Enable K&R/pcc mode, which approximates the behavior of the standard +UNIX pcc. ANSI/ISO C features that do not conflict with K&R/pcc +features are still supported in this mode.
    +
    +
    +
    --c++
    +
    -p
    +
    +
    +
    Enable compilation of C++. This is the default.
    +
    +
    +
    --c++03
    +
    +
    +
    Enable compilation of C++ as specified by the ISO/IEC 14882:2003 +standard by explicitly disabling all C++11 features, regardless of +their configured default values (but individual C++11 features can be +enabled on the command line). This option implicitly enables C++ mode +and can be combined with the options enabling strict ANSI/ISO +conformance, as well as other emulation modes (e.g., --microsoft, +--g++).
    +
    +
    +
    --c++11
    +
    --no_c++11
    +
    --c++0x
    +
    --no_c++0x
    +
    +
    +
    Enable or disable extensions added in the C++11 standard. This option +is only valid in C++ mode and can be combined with the options +enabling strict ANSI/ISO conformance.
    +
    +
    +
    --c++14
    +
    +
    +
    Enable language features added in the C++14 standard. This option +cannot be combined with options enabling or requiring a C mode.
    +
    +
    +
    --c++17
    +
    +
    +
    Enable language features added in the C++17 standard. This option +cannot be combined with options enabling or requiring a C mode.
    +
    +
    +
    --c++20
    +
    +
    +
    Enable language features added in the C++20 standard. This option +cannot be combined with options enabling or requiring a C mode.
    +
    +
    +
    --c++23
    +
    +
    +
    Enable language features added in the C++23 standard. This option +cannot be combined with options enabling or requiring a C mode.
    +
    +
    +
    --c++26
    +
    +
    +
    Enable language features added in drafts of the anticipated C++26 +standard. This option cannot be combined with options enabling or +requiring a C mode.
    +
    +
    +
    --cfront_2.1
    +
    -b
    +
    +
    +
    Enable compilation of C++ with compatibility with cfront version 2.1. +This causes the compiler to accept language constructs that, while not +part of the C++ language definition, are accepted by the AT&T C++ +Language System (cfront) release 2.1. This option also enables +acceptance of anachronisms.
    +
    +
    +
    --cfront_3.0
    +
    +
    +
    Enable compilation of C++ with compatibility with cfront version 3.0. +This causes the compiler to accept language constructs that, while not +part of the C++ language definition, are accepted by the AT&T C++ +Language System (cfront) release 3.0. This option also enables +acceptance of anachronisms.
    +
    +
    +
    --c++cli
    +
    --no_c++cli
    +
    --cppcli
    +
    --no_cppcli
    +
    --clr
    +
    +
    +
    Enable or disable compilation of C++/CLI source. This option implies +Microsoft C++ mode; it cannot be combined with options that are +contrary to such a mode (e.g., forcing strict mode) or with the option +--microsoft_version with a value less than 1600.
    +
    +
    +
    --c++cx
    +
    --no_c++cx
    +
    --cppcx
    +
    --no_cppcx
    +
    +
    +
    Enable or disable compilation of C++/CX source. This option implies +Microsoft C++ mode; it cannot be combined with options that are +contrary to such a mode (e.g., forcing strict mode) or with the option +--microsoft_version with a value less than 1600. Support for this +mode is preliminary and will be improved in future versions of the +front end.
    +
    +
    +
    --clang
    +
    --no_clang
    +
    +
    +
    Enable or disable clang C or C++ language compatibility features. +This option also enables the GNU C or C++ language compatibility +features. It is only recognized when GNU_EXTENSIONS_ALLOWED is +TRUE. As of this writing, the only effect of clang mode apart from +enabling GNU emulation is to enable the feature-test macros like +__has_feature.
    +
    +
    +
    --clang_version version-number
    +

    +
    +
    +
    The version of the clang compiler that should be emulated. Version +x.y.z of the clang compiler is encoded as x*10000+y*100+z (e.g., +version 3.4.1 is emulated with the option “--clang_version +30401”).
    +
    +
    +
    --embedded_c
    +
    --no_embedded_c
    +
    +
    +
    Enable or disable support for all Embedded C language extensions +(fixed-point types, named address space qualifiers, and named-register +storage class specifiers). These options are not available with C++ +modes.
    +
    +
    +
    --embedded_c++
    +
    +
    +
    Enable the diagnosis of noncompliance with the “Embedded C++” subset +(from which templates, exceptions, namespaces, new-style casts, RTTI, +multiple inheritance, virtual base classes, and mutable are +excluded).
    +
    +
    +
    --g++
    +
    --no_g++
    +
    +
    +
    Enable or disable GNU C++ language compatibility features. This +option also specifies that the source language being compiled is C++. +It is only recognized when GNU_EXTENSIONS_ALLOWED is TRUE.
    +
    +
    +
    --gcc
    +
    --no_gcc
    +
    +
    +
    Enable or disable GNU C language compatibility features. This option +also specifies that the source language being compiled is C. It is +only recognized when GNU_EXTENSIONS_ALLOWED is TRUE.
    +
    +
    +
    --gnu_version version-number
    +

    +
    +
    +
    The version of the GNU compiler that should be emulated in any of the +GNU (C or C++) modes. Version x.y.z of the GNU compiler is encoded as +x*10000+y*100+z (e.g., version 3.4.1 is emulated with the option +“--gnu_version 30401”).
    +
    +
    +
    --microsoft
    +
    --microsoft_16
    +
    --no_microsoft
    +
    +
    +
    Enable or disable Microsoft emulation mode. These options may only be +used if MICROSOFT_EXTENSIONS_ALLOWED is TRUE. --microsoft +enables 32-bit mode. --microsoft_16 enables 16-bit mode (i.e., +support for near and far; the option is accepted only if +NEAR_AND_FAR_ALLOWED is TRUE). The default values are supplied by +DEFAULT_MICROSOFT_MODE and DEFAULT_NEAR_AND_FAR_ENABLED. In +Microsoft emulation mode, language features that are not recognized by +the Microsoft compiler are disabled by default. In most cases these +features can then be enabled through use of other command line options +(for example, --bool). Microsoft bugs mode is also enabled when +DEFAULT_MICROSOFT_BUGS is TRUE.
    +
    +
    +
    --microsoft_version version-number
    +
    +
    +
    The version of the Microsoft compiler that should be emulated in +Microsoft mode. This enables or disables particular Microsoft mode +features when the acceptance of those features varies between versions +of the Microsoft compiler. The value specified is the value of the +predefined macro _MSC_VER supplied by the version of the Microsoft +compiler to be emulated. For example, 1100 is the value that +corresponds to Visual C++ version 5.0. This option also enables +Microsoft mode, but it does not imply either 16-bit or 32-bit mode +(i.e., it uses whatever value has already been specified, or the +default value if none has been explicitly specified).
    +
    +
    +
    --microsoft_build_number build-number
    +
    +
    +
    The “build number” of the Microsoft compiler that should be emulated +in Microsoft mode (this option also enables Microsoft mode). This +value is used to set the value of the predeclared macro +_MSC_FULL_VER (which is a concatenation of the microsoft version +number and the build number; e.g., with “--microsoft_version 1600 +--microsoft_build_number 30507” _MSC_FULL_VER is defined to +expand to 160030507). The default build number is 99999.
    +
    +
    +
    --microsoft_bugs
    +
    --no_microsoft_bugs
    +
    +
    +
    Enable or disable recognition of certain Microsoft bugs. These +options also enable Microsoft mode. Microsoft bugs mode is +automatically enabled when Microsoft mode is used and +DEFAULT_MICROSOFT_BUGS is TRUE.
    +
    +
    +
    --ms_await
    +
    +
    +
    Emulate the Microsoft Visual Studio /await command-line switch +that enables a pre-C++20 version of coroutines.
    +
    +
    +
    --ms_await_strict
    +
    +
    +
    Emulate the Microsoft Visual Studio /await:strict command-line +switch that enables a pre-C++20 version of coroutines.
    +
    +
    +
    --ms_c11
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c11 command-line switch +by enabling the same set of C11 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1927 for this +option to have an effect.
    +
    +
    +
    --ms_c17
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c17 command-line switch +by enabling the same set of C17 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1928 for this +option to have an effect.
    +
    +
    +
    --ms_c23
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c23 command-line switch +by enabling the same set of C23 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1935 for this +option to have an effect.
    +
    +
    +
    --ms_c++14
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c++14 command-line switch +by enabling the same set of C++14 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1903 to use this +option.
    +
    +
    +
    --ms_c++17
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c++17 command-line switch +by enabling the same set of C++17 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1911 to use this +option.
    +
    +
    +
    --ms_c++20
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c++20 command-line switch +by enabling the same set of C++20 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1920 to use this +option.
    +
    +
    +
    --ms_c++23
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c++23 command-line switch +by enabling the same set of C++23 options that are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro. +microsoft_version must have a value of at least 1943 to use this +option.
    +
    +
    +
    --ms_c++latest
    +
    +
    +
    Emulate the Microsoft Visual Studio /std:c++latest command-line +switch by enabling the same set of C++ options as are supported by the +Visual Studio version that corresponds to the value of +microsoft_version. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro.
    +
    +
    +
    --ms_compatibility
    +
    --no_ms_compatibility
    +
    +
    +
    Enable or disable certain Microsoft compatibility options (as defined +by the clang-fms-compatibility option). Unlike the +--microsoft option (i.e., Microsoft emulation mode), this +command-line option can be combined with other emulation modes (e.g., +--clang). Specifying --ms_compatibility implies +--ms_extensions. If not specified explicitly with the +--microsoft_version command-line option, microsoft_version is +set to the value of the DEFAULT_MICROSOFT_VERSION macro.
    +
    +
    +
    --ms_std_preprocessor
    +
    --no_ms_std_preprocessor
    +
    +
    +
    Enable or disable a mode in which the behavior of the preprocessor in +Microsoft emulation mode conforms with the C and C++ Standards; when +disabled, the preprocessor emulates the behavior of the traditional +Microsoft preprocessor.
    +
    +
    +
    --ms_stdc
    +
    --no_ms_stdc
    +
    +
    +
    Emulate the /Zc:__STDC__ option of Microsoft’s Visual Studio by +setting the value of the __STDC__ macro to the value 1 or +leaving the macro undefined respectively. Implicitly enables +Microsoft emulation mode.
    +
    +
    +
    --ms_cplusplus_std_value
    +
    --no_ms_cplusplus_std_value
    +

    +
    +
    +
    Emulate the /Zc:__cplusplus[-] option of Microsoft’s Visual Studio +by either setting the value of the __cplusplus macro to the value +implied by the C++ standard currently being implemented or leaving it +as the default value of 199711L used by Visual Studio. Implicitly +enables Microsoft emulation mode.
    +
    +
    +
    --ms_extensions
    +
    --no_ms_extensions
    +
    +
    +
    Enable or disable certain Microsoft extensions (as defined by the +clang-fms-extensions option). Unlike the --microsoft +option (i.e., Microsoft emulation mode), this command-line option can +be combined with other emulation modes (e.g., --clang). If not +specified explicitly with the --microsoft_version command-line +option, microsoft_version is set to the value of the +DEFAULT_MICROSOFT_VERSION macro.
    +
    +
    +
    --ms_permissive
    +
    --no_ms_permissive
    +
    +
    +
    Enable or disable “permissive” mode during Microsoft emulation. These +command-line options control emulation of the Visual Studio +/permissive[-] command-line options and can be used in C, C++, +C++/CLI, or C++/CX modes. The default value is controlled by the +DEFAULT_MS_PERMISSIVE configuration macro. Specifying one of +these command-line options also implicitly enables Microsoft emulation +mode.
    +
    +
    +
    --nonstd_gnu_keywords
    +
    --no_nonstd_gnu_keywords
    +

    +
    +
    +
    In GNU modes, --no_nonstd_gnu_keywords disables GNU-specific +keywords that do not start with underscores (notably: typeof); the +option has no effect in other modes. --nonstd_gnu_keywords is +only accepted in GNU modes and enables any keywords that were disabled +by a prior occurrence of --no_nonstd_gnu_keywords.
    +
    +
    +
    --no_strict_gnu
    +
    --strict_gnu
    +
    +
    +
    For every version of the C and C++ ISO standards, the GNU and Clang +compilers support both the language as defined by ISO (with +-std=c* command-line options) as well as the language with certain +incompatible compiler-specific extensions (with -std=gnu*). +Specifying --strict_gnu on the command-line causes the front end +to emulate the -std=c* behavior of the selected GNU/Clang +compiler, while specifying --no_strict_gnu emulates the +-std=gnu* behavior. When these options are not specified, the +front end implicitly emulates the -std=c* behavior whenever any +--c* or --c++* command-line options are specified (e.g., +--c++11 mimics -std=c++11); otherwise the -std=gnu* +behavior is emulated.
    +
    +
    +
    --strict_warnings or -a
    +
    --strict or -A
    +
    +
    +
    Enable strict ANSI/ISO mode, which provides diagnostic messages when +nonstandard features are used, and disables features that conflict +with ANSI/ISO C or C++. This is compatible with both C and C++ mode. +It is not compatible with pcc mode. ANSI/ISO violations can be issued +as either warnings or errors depending on which command line option is +used. The -A and --strict options cause errors to be issued +whereas the -a and --strict_warnings options produce warnings. +(Note that nonstandard types, functions, etc., that might be +predeclared by various compilers will not be declared by the front end +in this mode, so any references to these names will be diagnosed as +errors, regardless of which of these options is specified.) The error +threshold is set so that the requested diagnostics will be listed.
    +
    +
    +
    --stricter_template_checking
    +
    +
    +
    If a selected dialect weakens the type checking performed in a +template, adding this option makes it stricter again (although not +always as strict as what is done in strict ANSI/ISO mode).
    +
    +
    +
    --sun
    +
    --no_sun
    +
    +
    +
    Enable or disable Sun CC (version 5.x) language compatibility +features. This option can only be used in C++ mode, and cannot be +combined with options to enable strict ANSI mode, or compatibility +with cfront, Microsoft, or GNU. It is only recognized when +SUN_EXTENSIONS_ALLOWED is TRUE.
    +
    +
    +
    --svr4
    +
    --no_svr4
    +
    +
    +
    Enable or disable recognition of SVR4 C compatibility features. The +default value is supplied by DEFAULT_SVR4_C_MODE. This option +also specifies that the source language being compiled is ANSI C.
    +
    +
    +
    --upc
    +
    --no_upc
    +
    +
    +
    Enable or disable UPC (Unified Parallel C) extensions.
    +
    +
    +
    --upc_threads n
    +
    +
    +
    Specify a fixed number of UPC threads (this is the value of the +THREADS identifier).
    +
    +
    +
    --upc_strict
    +
    --upc_relaxed
    +
    +
    +
    Specify the default UPC access method for objects of shared types.
    +
    +
    +
    +
    +
    +

    2.1.2. Input/output Options#

    +

    The following options control the kind of input read or output produced or the +location of such input or output.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --unicode_source_kind kind
    +

    +
    +
    +
    Source input files that do not begin with a byte order mark indicating +the kind of Unicode encoding are assumed to use the Unicode encoding +indicated by kind. Possible values of kind are UTF-8, +UTF-16, UTF-16LE (little-endian), UTF-16BE (big-endian), +and none (to indicate that the source file is not Unicode).
    +
    +
    +
    --gen_c_file_name file-name
    +

    +
    +
    +
    When using the C-generating back end or the C++-generating back end, +this option specifies the file name to be used for the generated +output.
    +
    +
    +
    --dependencies
    +
    -M
    +
    +
    +
    Do preprocessing only. Instead of the normal preprocessing output, +generate on the preprocessing output file a list of dependency lines +suitable for input to the UNIX make program. Note that when +implicit inclusion of templates is enabled, the output may indicate +false (but safe) dependencies unless --no_preproc_only is also +used.
    +
    +
    +
    --error_output efile
    +
    +
    +
    Redirect the output that would normally go to the error output +file (i.e., diagnostic messages) to the file efile. This option +is useful on systems where output redirection of files is not well +supported. If used, this option should probably be specified +first in the command line, since otherwise any command-line errors +for options preceding the --error_output would be written to +stderr before redirection.
    +
    +
    +
    --list lfile
    +
    -Llfile
    +
    +
    +
    Generate raw listing information in the file lfile. This +information is likely to be used to generate a formatted listing. +The raw listing file contains raw source lines, information on +transitions into and out of include files, and diagnostics +generated by the front end. Each line of the listing file begins +with a key character that identifies the type of line, as follows:
    +
    +
    +
    N:

    a normal line of source; the rest of the line is the text of the +line.

    +
    +
    X:

    the expanded form of a normal line of source; the rest of the +line is the text of the line. This line appears following the N +line, and only if the line contains non-trivial modifications +(comments are considered trivial modifications; macro expansions, +line splices, and trigraphs are considered non-trivial +modifications). Comments are replaced by a single space in the +expanded-form line.

    +
    +
    S:

    a line of source skipped by an #if or the like; the rest of the +line is text. Note that the #else, #elif, or #endif that ends a +skip is marked with an N.

    +
    +
    L:

    an indication of a change in source position. The line has a +format similar to the # line-identifying directive output by cpp, +that is to say

    +
    +

    L line-number "file-name" key

    +
    +

    where key is 1 for entry into an include file, 2 for exit from an +include file, and omitted otherwise. The first line in the raw +listing file is always an L line identifying the primary input +file. L lines are also output for #line directives (key is +omitted). L lines indicate the source position of the following +source line in the raw listing file.

    +
    +
    R, W, E, or C:

    an indication of a diagnostic (R for remark, W for +warning, E for error, and C for catastrophic error). The +line has the form

    +
    +

    S "file-name" line-number column-number +message-text

    +
    +

    where S is R, W, E, or C, as explained +above. Errors at the end of file indicate the last line of the +primary source file and a column number of zero. Command-line +errors are catastrophes with an empty file name ("") and a +line and column number of zero. Internal errors are catastrophes +with position information as usual, and message-text beginning +with (internal error). When a diagnostic displays a list (e.g., +all the contending routines when there is ambiguity on an +overloaded call), the initial diagnostic line is followed by one +or more lines with the same overall format (code letter, file +name, line number, column number, and message text), but in which +the code letter is the lower case version of the code letter in +the initial line. The source position in such lines is the same +as that in the corresponding initial line.

    +
    +
    +
    +
    --list_macros
    +
    +
    +
    Do preprocessing only. Instead of the normal preprocessing output, +generate on the preprocessing output file a list of all the macros in +effect after processing the source file, including predefined and +command-line macros along with their definitions.
    +
    +
    +
    --no_line_commands
    +
    -P
    +
    +
    +
    Do preprocessing only. Write preprocessed text to the preprocessing +output file, with comments removed and without line control +information.
    +
    +
    +
    --old_line_commands
    +
    +
    +
    When generating source output (e.g., with the C-generating back end), +put out #line directives in the form used by the Reiser cpp, i.e., +“# nnn” instead of “#line nnn”.
    +
    +
    +
    --output ofile
    +
    -o ofile
    +
    +
    +
    Specify the output file of the compilation, i.e., the preprocessing or +intermediate language output file.
    +
    +
    +
    --xref xfile
    +
    -Xxfile
    +
    +
    +
    Generate cross-reference information in the file xfile. For each +reference to an identifier in the source program, a line of the form
    +
    +
    +

    symbol-id name ref-code file-name line-number column-number

    +
    +
    +
    is written, where ref-code is D for definition, d for +declaration (that is, a declaration that is not a definition), T +for a full template instantiation, t for a partial template +instantiation (i.e., an instantiation of the template declaration, but +not of its definition), M for modification, A for address +taken, U for used, C for changed (but actually meaning “used +and modified in a single operation,” such as an increment), R for +any other kind of reference, or E for an error in which the kind +of reference is indeterminate. symbol-id is a unique decimal number +for the symbol. The fields of the above line are separated by tab +characters.
    +
    +
    +
    --create_header_unit file
    +
    +
    +
    Write an EDG IFC header unit file +representing the current translation unit to file.
    +
    +
    +
    --create_module_interface file
    +

    +
    +
    +
    Write an EDG IFC module file for a module interface unit to file.
    +
    +
    +
    --create_module_internal_partition file
    +

    +
    +
    +
    Write an EDG IFC module file for a module implementation unit to +file.
    +
    +
    +
    --module_interface
    +
    +
    +
    Write an EDG IFC module file for a module interface unit in the +current working directory. The filename is derived from the parsed +module declaration.
    +
    +
    +
    --module_internal_partition
    +

    +
    +
    +
    Write an EDG IFC module file for a module implementation unit in the +current working directory. The filename is derived from the parsed +module declaration.
    +
    +
    +
    +
    +
    +

    2.1.3. Preprocessor Options#

    +

    The following options control the behavior of the preprocessor.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --comments
    +
    -C
    +
    +
    +
    Keep comments in the preprocessed output. This should be specified +after either --preprocess or --no_line_commands; it does not +of itself request preprocessing output.
    +
    +
    +
    --define_macro name [ ( parm-list ) ] [ = def ]
    +
    -D name [ ( parm-list ) ] [ = def ]
    +

    +
    +
    +
    Define macro name as def. If “= def “ is omitted, +define name as 1. Function-style macros can be defined by +appending a macro parameter list to name.
    +
    +
    +
    --embed_directory dir
    +
    +
    +
    Add dir to the list of directories searched for #embeds. The +process by which files named in #embed directives are found is similar +to that used for #include. See Finding Include Files.
    +
    +
    +
    --import_dir dir-name
    +
    +
    +
    Specify the directory in which the files to be included by #import +directives are to be found. These files must have been generated +previously by the Microsoft compiler. This option is valid only in +Microsoft mode.
    +
    +
    +
    --incl_suffixes str
    +
    +
    +
    Specifies the list of suffixes to be used when searching for an +include file whose name was specified without a suffix. The +argument is a colon-separated list of suffixes (e.g., +"h:hpp::"). If a null suffix is to be allowed, it must be +included in the suffix list. The default is specified by the +configuation flag DEFAULT_INCLUDE_FILE_SUFFIX_LIST.
    +
    +
    +
    --include_directory dir
    +
    --sys_include dir
    +
    -Idir
    +
    +
    +
    Add dir to the list of directories searched for #includes. +See Finding Include Files.
    +
    +
    +
    --modules_directory dir
    +

    +
    +
    +
    Add dir to the list of directories searched for module files when +processing an import directive. The current working directory is +automatically added to the start of this list. If the +EDG_MODULES_PATH environment variable is set, that path is added +to the end of the list. See Finding Module Files.
    +
    +
    +
    --ms_header_unit header_path=module_file
    +
    --header_unit header_path=module_file
    +

    +
    +
    +
    Add module_file to the header unit map, corresponding to +header_path. When importing a header unit, if the resolved path +to the header matches header_path, then module_file is used as +the match. See Finding Module Files.
    +
    +
    +
    --ms_header_unit_angle header_path=module_file
    +
    --ms_header_unit_quote header_path=module_file
    +

    +
    +
    +
    Add module_file, corresponding to header_path, to a header +unit map selected by the form in which header_path is written, +<...> and "...", respectively. Unlike –ms_header_unit, +header_path is not resolved immediately but will be resolved on +demand. (See Finding Include Files.) If the resolved path to +the header for the header unit matches the resolved header_path, +module_file is used as the match. See Finding Module Files.
    +
    +
    +
    --ms_mod_file_map [ module_name= ] file
    +

    +
    +
    +
    If module_name is omitted, file will be examined to determine +if the module it represents matches the module named in the +import directive. Otherwise, an import of module_name will +resolve to file without examining its contents. See +Finding Module Files.
    +
    +
    +
    --ms_translate_include
    +
    --no_ms_translate_include
    +

    +
    +
    +
    Enable or disable the automatic translation of #include +directives into import directives when a header has a mapping +to a module file in a header unit map (see --ms_header_unit, +--ms_header_unit_angle, and --ms_header_unit_quote +regarding how such mappings are specified.)
    +
    +
    +
    --old_style_preprocessing
    +

    +
    +
    +
    Forces pcc style preprocessing when compiling in ANSI C or C++ mode. +This may be used when compiling an ANSI C or C++ program on a system +in which the system header files require pcc style preprocessing.
    +
    +
    +
    --preinclude_macros filename
    +
    --preinclude filename
    +
    +
    +
    Include the source code of the indicated file at the beginning of the +compilation. This can be used to establish standard macro +definitions, etc. The file name is searched for in the directories on +the include search list. When the preinclude_macros variant is +used, only the preprocessing directives from the file are evaluated. +All of the actual code is discarded. The effect of this option is +that any macro definitions from the specified file will be in effect +when the primary source file is compiled. All of the macro-only files +are processed before any of the normal preincludes. Within each +group, the files are processed in the order in which they were +specified.
    +
    +
    +
    --preprocess
    +
    -E
    +
    +
    +
    Do preprocessing only. Write preprocessed text to the preprocessing +output file, with comments removed and with line control information.
    +
    +
    +
    --no_preproc_only
    +
    +
    +
    May be used in conjunction with the options that normally cause the +front end to do preprocessing only (e.g., --preprocess, etc.) to +specify that a full compilation should be done (not just +preprocessing). When used with the implicit inclusion option, this +makes it possible to generate a preprocessed output file that includes +any implicitly included files.
    +
    +
    +
    --stdc_zero_in_system_headers
    +
    --no_stdc_zero_in_system_headers
    +

    +
    +
    +
    Enable or disable special processing of the __STDC__ macro +when referenced from system headers. When this feature is +enabled, __STDC__ has the value zero in system header files +(files found in directories specified using the --sys_include +option) and one otherwise. This feature is provided to emulate +the behavior of gcc in certain configurations. The default is +specified by DEFAULT_STDC_ZERO_IN_SYSTEM_HEADERS. If the flag +is not TRUE by default, the GNU mode default is specified by the +DEFAULT_GNU_STDC_ZERO_IN_SYSTEM_HEADERS macro.
    +
    +
    +
    --trace_includes
    +
    -H
    +
    +
    +
    Output a list of the names of files #included to the error +output file. The source file is compiled normally (i.e., it is not +just preprocessed) unless another option that causes preprocessing +only is specified.
    +
    +
    +
    --undefine_macro name
    +
    -Uname
    +
    +
    +
    Remove any initial definition of the macro name. +--undefine_macro options are processed after all +--define_macro options in the command line have been +processed.
    +
    +
    +
    --check_concatenations
    +
    --no_check_concatenations
    +

    +
    +
    +
    Specifies whether or not the front end will issue a diagnostic if a +concatenation operator ## in a macro expansion fails to produce a +valid preprocessor token as required by the C and C++ Standards.
    +
    +
    +
    --no_token_separators_in_pp_output
    +

    +
    +
    +
    Used in connection with options that generate preprocessing output, +suppresses the extra spaces the front end inserts in the text of macro +expansions to ensure that tokens that should not be combined remain +separate tokens. This can be used to prevent the insertion of +extraneous spaces when the front end is used as a preprocessor for +text that is not C or C++.
    +
    +
    +
    +
    +
    +

    2.1.4. Diagnostic Options#

    +

    The following options control when or how diagnostics are emitted.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --add_match_notes
    +
    --no_add_match_notes
    +
    +
    +
    Enable or disable diagnostic notes that +provide further details for a failure to match candidates in an +overload set.
    +
    +
    +
    --brief_diagnostics
    +
    --no_brief_diagnostics
    +

    +
    +
    +
    Enable or disable a mode in which a shorter form of the diagnostic +output is used. When enabled, the original source line is not +displayed and the error message text is not wrapped when too long to +fit on a single line.
    +
    +
    +
    --colors
    +
    --no_colors
    +
    +
    +
    Enable or disable colorization of diagnostic messages. The default +behavior is controlled by the DEFAULT_ENABLE_COLORIZED_DIAGNOSTICS +configuration macro (which defaults to TRUE). Colorized +diagnostics are disabled when not writing to a terminal, and are also +disabled when the NOCOLOR environment variable is set, the +TERM environment variable is unset, or the EDG_COLORS +environment variable is set to an empty string.
    +
    +
    +
    --constexpr_diag_suppress tag, tag,…
    +
    --constexpr_diag_remark tag, tag,…
    +
    --constexpr_diag_warning tag, tag,…
    +
    --constexpr_diag_error tag, tag,…
    +
    +
    +
    Override the severity of the diagnostics that calls of +__builtin_constexpr_diag request with any of the specified tags. +A tag is shown in brackets at the end of the diagnostic it names, and +may contain only letters, digits, and underscores. When more than +one of these options names a given tag, the last one on the command +line takes effect.
    +
    +
    +
    --context_limit number
    +

    +
    +
    +
    Set the context limit to number. The context limit is the maximum +number of template instantiation context entries to be displayed as +part of a diagnostic message. The default is specified by the +DEFAULT_CONTEXT_LIMIT macro. If the number of context entries +exceeds the limit, the first and last N context entries are displayed, +where N is half of the context limit. A value of zero is used to +indicate that there is no limit.
    +
    +
    +
    --diag_suppress tag, tag,…
    +
    --diag_remark tag, tag,…
    +
    --diag_warning tag, tag,…
    +
    --diag_error tag, tag,…
    +
    +
    +
    Override the normal error severity of the specified diagnostic +messages. The message(s) may be specified using a mnemonic error tag +or using an error number. The error tag names and error numbers are +listed in the Error Messages appendix.
    +
    +
    +
    --diag_once tag, tag,…
    +
    +
    +
    Causes the specified diagnostic to be issued only once as a warning or +remark. The message(s) may be specified using a mnemonic error tag or +using an error number. The error tag names and error numbers are +listed in the Error Messages appendix.
    +
    +
    +
    --display_error_number
    +
    --no_display_error_number
    +

    +
    +
    +
    Enable or disable the display of an error message number in any +diagnostic messages that are generated. The option may be used to +determine the error number to be used when overriding the severity of +a diagnostic message. The configuration macro +DEFAULT_DISPLAY_ERROR_NUMBER specifies the default behavior.
    +
    +
    +
    --error_limit number
    +
    -e number
    +
    +
    +
    Set the error limit to number. The front end will abandon +compilation after this number of errors (remarks and warnings are +not counted toward the limit). By default, the limit is 100.
    +
    +
    +
    --for_init_diff_warning
    +
    --no_for_init_diff_warning
    +

    +
    +
    +
    Enable or disable a warning that is issued when programs compiled +under the new for-init scoping rules would have had different behavior +under the old rules. The diagnostic is only put out when the new +rules are used. DEFAULT_WARNING_ON_FOR_INIT_DIFFERENCE specifies +the default behavior. This option is valid only in C++ mode.
    +
    +
    +
    --lossy_conversion_warning
    +
    --no_lossy_conversion_warning
    +

    +
    +
    +
    Enable or disable a warning that is issued when conversion of an +arithmetic value to a different type might result in lost data because +the target type cannot represent all the values of the source type.
    +
    +
    +
    --macro_positions_in_diagnostics
    +
    --no_macro_positions_in_diagnostics
    +

    +
    +
    +
    Enable or disable display of extra information for diagnostics that +refer to text in macro expansions. These options may only be used if +FULLY_RESOLVED_MACRO_POSITIONS is TRUE. The additional +information includes the original source line from which the text +identified by the message was copied into the macro expansion (i.e., a +macro definition or an argument in the top-level macro invocation), as +well as the chain of macro invocations that led to the expanded text +designated by the diagnostic (if MACRO_INVOCATION_TREE_IN_IL is +TRUE). The default value is given by +DEFAULT_MACRO_POSITIONS_IN_DIAGNOSTICS.
    +
    +
    +
    --module_import_diagnostics
    +
    --no_module_import_diagnostics
    +

    +
    +
    +
    Enable or disable the issuing of diagnostics while importing entities +from module files.
    +
    +
    +
    --output_mode mode
    +
    +
    +
    Set the front end diagnostic output mode to mode. Valid modes +are text for traditional command line diagnostic output and +sarif for SARIF (Static Analysis Results Interchange Format) +output (see www.sarif.info).
    +
    +
    +
    --promote_warnings
    +
    -W
    +
    +
    +
    Issue all warnings as if they were discretionary errors.``
    +
    +
    +
    --remarks
    +
    -r
    +
    +
    +
    Issue remarks, which are diagnostic messages even milder than +warnings.
    +
    +
    +
    --report_gnu_extensions
    +

    +
    +
    +
    Warn about the use of certain GNU extensions outside system header +files. Only valid in GNU C or C++ mode.
    +
    +
    +
    --template_typedefs_in_diagnostics
    +
    --no_template_typedefs_in_diagnostics
    +

    +
    +
    +
    Disable or enable, respectively, the replacement of typedefs +declared in template classes with their underlying type. +Diagnostic messages are often more useful when such typedefs are +replaced. The default behavior is specified by the +DEFAULT_TEMPLATE_TYPEDEFS_IN_DIAGNOSTICS macro.
    +
    +
    +
    --timing
    +
    -#
    +
    +
    +
    Generate compilation timing information. This option causes the +compiler to display the amount of CPU time and elapsed time used by +each phase of the compilation and a total for the entire compilation.
    +
    +
    +
    --top_templates number
    +
    +
    +
    At the end of the compilation, write to the error output file a report +of the templates that were substituted the most. number specifies +how many templates to report; if it is zero, every template that has a +nonzero number of substitutions is reported.
    +
    +
    +
    --no_use_before_set_warnings
    +
    -j
    +
    +
    +
    Suppress warnings on local automatic variables that are used before +their values are set. The front end’s algorithm for detecting such +uses is conservative and is likely to miss some cases that an +optimizer with sophisticated flow analysis could detect; thus, an +implementation might choose to suppress the warnings from the front +end when optimization has been requested but to permit them when the +optimizer is not being run.
    +
    +
    +
    --no_warnings
    +
    -w
    +
    +
    +
    Suppress warnings. Errors are still issued.
    +
    +
    +
    --wrap_diagnostics
    +
    --no_wrap_diagnostics
    +
    +
    +
    Enable or disable a mode in which the error message text is not +wrapped when too long to fit on a single line.
    +
    +
    +
    +
    +
    +

    2.1.5. Individual Language Features#

    +

    The following options enable or disable specific language syntax. (Options +that affect the meaning of existing constructs are listed in +Alternative Language Behaviors.)

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --alternative_tokens
    +
    --no_alternative_tokens
    +

    +
    +
    +
    Enable or disable recognition of alternative tokens. This controls +recognition of the digraph tokens in C and C++, and controls +recognition of the operator keywords (e.g., and, bitand, etc.) +in C++. The default behavior is specified by the +DEFAULT_ALTERNATIVE_TOKENS_ALLOWED configuration constant.
    +
    +
    +
    --array_new_and_delete
    +
    --no_array_new_and_delete
    +

    +
    +
    +
    Enable or disable support for array new and delete. The default +behavior is specified by the configuration constant +DEFAULT_ARRAY_NEW_AND_DELETE_ENABLED. This option is valid only +in C++ mode. The front end can be configured to define a +preprocessing variable when array new and delete are enabled. This +preprocessing variable may then be used by the standard header files +to decide whether to include the declarations for the array new/delete +functions.
    +
    +
    +
    --auto_storage
    +
    --no_auto_storage
    +
    +
    +
    Enable or disable the traditional meaning of auto as a storage +class specifier (only valid in C++ mode). (If disabled, then auto +must be a type specifier.). The default behavior is specified by the +DEFAULT_AUTO_STORAGE_CLASS_SPECIFIER_ENABLED configuration +constant.
    +
    +
    +
    --auto_type
    +
    --no_auto_type
    +
    +
    +
    Enable or disable auto as a type specifier where the actual type +is deduced from an initializer (only valid in C++ mode). This is a +C++11 feature. If enabled, the traditional meaning of auto as a +storage class specifier is disabled (which matches C++11), unless the +option --auto_storage is also supplied. The default behavior is +specified by the DEFAULT_AUTO_TYPE_SPECIFIER_ENABLED configuration +constant.
    +
    +
    +
    --bit_precise_integers
    +
    --no_bit_precise_integers
    +
    +
    +
    Enable or disable support for C23-style _BitInt types.
    +
    +
    +
    --bool
    +
    --no_bool
    +
    +
    +
    Enable or disable recognition of bool. The default value is +supplied by DEFAULT_BOOL_IS_KEYWORD. This option is valid only in +C++ mode. The front end can be configured to define a preprocessing +variable when bool is recognized. This preprocessing variable may +then be used by header files to determine whether a typedef should be +supplied to define bool.
    +
    +
    +
    --c23_typeof
    +
    --no_c23_typeof
    +
    +
    +
    Enable or disable support for the C23 typeof and +typeof_unqual operators, regardless of the current C language +level. This option is valid only in C mode.
    +
    +
    +
    --c++11_sfinae
    +
    --no_c++11_sfinae
    +
    +
    +
    Enable or disable template deduction in the style dictated by the +C++11 standard, i.e., where general expressions are allowed in +deduction contexts and they undergo the full usual semantic +checking. This type of deduction is necessary to get the full +power of the decltype feature in return types. (“SFINAE” is +an acronym for “Substitution Failure Is Not An Error”, which is +the guiding principle for template deduction, and by extension a +name for the process of deduction.)
    +
    +
    +
    --c++11_sfinae_ignore_access
    +
    --no_c++11_sfinae_ignore_access
    +

    +
    +
    +
    When new-style SFINAE is enabled, these options control whether or not +access errors cause deduction failures. The positive option indicates +that access checking should not be done during template deduction, and +therefore that access errors cannot cause a deduction failure; this +was the status quo ante when the new-style SFINAE rules were proposed. +The “no” version of the option indicates that access checking +should be done during template deduction, and therefore that access +errors cause a deduction failure; this is the revised direction chosen +by the standards committee.
    +
    +
    +
    --char8_t
    +
    --no_char8_t
    +

    +
    +
    +
    Enable or disable support for the char8_t keyword and type (a +C++20 feature). Enabled by default in C++20 mode.
    +
    +
    +
    --compound_literals
    +
    --no_compound_literals
    +
    +
    +
    Enable or disable support for “compound literals” (a C99 feature).
    +
    +
    +
    --concepts
    +
    --no_concepts
    +

    +
    +
    +
    Enable or disable support for concepts (a C++20 feature).
    +
    +
    +
    --delegating_constructors
    +
    --no_delegating_constructors
    +

    +
    +
    +
    Enable or disable delegating constructors (a C++11 feature).
    +
    +
    +
    --deprecated_string_conv
    +
    --no_deprecated_string_conv
    +

    +
    +
    +
    Enable or disable the deprecated conversion from a string literal to +char *. Meaningful only when string literals are const.
    +
    +
    +
    --designators
    +
    --no_designators
    +
    +
    +
    Enable or disable support for designators (a C99 feature). These +options are not available in C++ mode.
    +
    +
    +
    --digit_separators
    +
    --no_digit_separators
    +
    +
    +
    Enable or disable support for digit separators (a C++14 feature). +When this feature is enabled, an apostrophe can appear between the +digits of a numeric literal and is ignored, e.g., 123'456'789.
    +
    +
    +
    --extended_designators
    +
    --no_extended_designators
    +

    +
    +
    +
    Enable or disable support for “extended designators,” an extension +accepted only in C mode to emulate the behavior of certain other C +compilers when it comes to designators in aggregate initializers.
    +
    +
    +
    --dollar
    +
    -$
    +
    +
    +
    Accept dollar signs in identifiers. The default value of this option +is specified in a configuration file.
    +
    +
    +
    --exceptions--no_exceptions
    +
    -x
    +
    +
    +
    Enable or disable support for exception handling. -x is +equivalent to --exceptions. The default behavior is specified by +the configuration constant DEFAULT_EXCEPTIONS_ENABLED. This +option is valid only in C++ mode.
    +
    +
    +
    --exc_spec_in_func_type
    +
    --no_exc_spec_in_func_type
    +
    +
    +
    Enable or disable exceptions being part of a function type (enabled by +default in C++17 modes and disabled by default otherwise).
    +
    +
    +
    --explicit
    +
    --no_explicit
    +
    +
    +
    Enable or disable support for the explicit specifier on +constructor declarations. The default behavior is specified by the +configuration constant DEFAULT_EXPLICIT_KEYWORD_ENABLED. This +option is valid only in C++ mode.
    +
    +
    +
    --export
    +
    --no_export
    +
    +
    +
    Enable or disable recognition of exported templates. The default +value is supplied by DEFAULT_EXPORT_TEMPLATE_ALLOWED. This option +is valid only in C++ mode. This option requires that dependent name +processing be done, and cannot be used with implicit inclusion of +template definitions.
    +
    +
    +
    --extern_inline
    +
    --no_extern_inline
    +
    +
    +
    Enable or disable support for inline functions with external +linkage in C++. When inline functions are allowed to have +external linkage (as required by the standard), then extern and +inline are compatible specifiers on a nonmember function +declaration; the default linkage when inline appears alone is +external (that is, inline means extern inline on nonmember +functions); and an inline member function takes on the linkage of +its class (which is usually external). However, when inline +functions have only internal linkage (as specified in the ARM), then +extern and inline are incompatible; the default linkage when +inline appears alone is internal (that is, inline means +static inline on nonmember functions); and inline member +functions have internal linkage no matter what the linkage of their +class.
    +
    +
    +
    --fixed_point
    +
    --no_fixed_point
    +
    +
    +
    Enable or disable support for Embedded C fixed-point types. (Not +available in C++ modes.)
    +
    +
    +
    --lambdas
    +
    --no_lambdas
    +
    +
    +
    Enable or disable support for C++11 lambdas. (Only available in C++ +modes.)
    +
    +
    +
    --long_long
    +
    +
    +
    Permit the use of long long in strict mode in dialects in which it +is non-standard.
    +
    +
    +
    --modules
    +
    --no_modules
    +
    +
    +
    Enable or disable support for modules. Modules are currently +experimental and will be enabled by default in future releases in the +applicable modes. The front end does not currently generate modules +files of its own and can only consume module files produced by +Microsoft Visual Studio version 16.8. This support is incomplete and +compatibility will change in future releases.
    +

    +
    +
    +
    --multibyte_chars
    +
    --no_multibyte_chars
    +
    +
    +
    Enable or disable processing for multibyte character sequences in +comments, string literals, and character constants. The default +behavior is specified by +DEFAULT_MULTIBYTE_CHARS_IN_SOURCE_ALLOWED. Multibyte encodings +are used for character sets like the Japanese SJIS.
    +
    +
    +
    --named_address_spaces
    +
    --no_named_address_spaces
    +

    +
    +
    +
    Enable or disable support for Embedded C named address space +qualifiers. (Not available in C++ modes.)
    +
    +
    +
    --named_registers
    +
    --no_named_registers
    +
    +
    +
    Enable or disable support for Embedded C named-register storage class +specifiers. (Not available in C++ modes.)
    +
    +
    +
    --namespaces
    +
    --no_namespaces
    +
    +
    +
    Enable or disable support for namespaces. The default behavior is +specified by the configuration constant +DEFAULT_NAMESPACES_ENABLED. This option is valid only in C++ +mode.
    +
    +
    +
    --nonstd_using_decl
    +
    --no_nonstd_using_decl
    +

    +
    +
    +
    In C++, controls whether a nonmember using-declaration that specifies +an unqualified name is allowed.
    +
    +
    +
    --nullptr
    +
    --no_nullptr
    +
    +
    +
    Enable or disable support for the C++11/C23 nullptr keyword.
    +
    +
    +
    --old_specializations
    +
    --no_old_specializations
    +

    +
    +
    +
    Enable or disable acceptance of old-style template specializations +(i.e., specializations that do not use the template<> syntax). +Default behavior is specified by +DEFAULT_OLD_SPECIALIZATIONS_ALLOWED. This option is valid only in +C++ mode.
    +
    +
    +
    --relaxed_abstract_checking
    +
    --no_relaxed_abstract_checking
    +

    +
    +
    +
    Enable or disable a mode in which checking for the use abstract class +types as function parameter or return types is performed only when the +function is defined or called. Traditionally this checking has been +performed on non-defining function declarations as well, and this +behavior can be preserved via the second option.
    +
    +
    +
    --restrict
    +
    --no_restrict
    +
    +
    +
    Enable or disable recognition of the restrict keyword.
    +
    +
    +
    --rtti
    +
    --no_rtti
    +
    +
    +
    Enable or disable support for RTTI (runtime type information) +features: dynamic_cast, typeid. The default behavior is +specified by the configuration constant DEFAULT_RTTI_ENABLED. +This option is valid only in C++ mode.
    +
    +
    +
    --rvalue_ctor_is_copy_ctor
    +
    --rvalue_ctor_is_not_copy_ctor
    +

    +
    +
    +
    Determines whether an rvalue (or “move”) constructor is treated as a +copy constructor (the default) or not. If rvalue constructors are +treated as copy constructors, a user-declared rvalue constructor will +inhibit the implicit generation of a traditional copy constructor.
    +
    +
    +
    --rvalue_refs
    +
    --no_rvalue_refs
    +
    +
    +
    Enable or disable support for rvalue references. (Only valid in C++ +mode.)
    +
    +
    +
    --sun_linker_scope
    +
    --no_sun_linker_scope
    +

    +
    +
    +
    Enable or disable support for Sun CC 5.5 link scope specifiers +(__global, __symbolic, and __hidden). The default setting +is supplied by DEFAULT_SUN_LINKER_SCOPE_ALLOWED.
    +
    +
    +
    --thread_local_storage
    +
    --no_thread_local_storage
    +

    +
    +
    +
    Enable or disable the C++11 thread_local specifier (and, if so +configured, the __thread specifier) to indicate that variables +should be stored in thread-local storage. By default, the +__thread specifier is enabled in Sun mode and in GNU mode when +gnu_version >= 30400.
    +
    +
    +
    --trigraphs
    +
    --no_trigraphs
    +

    +
    +
    +
    Enable or disable recognition of trigraphs. The default behavior is +specified by the DEFAULT_TRIGRAPHS_ALLOWED configuration constant.
    +
    +
    +
    --typename
    +
    --no_typename
    +
    +
    +
    Enable or disable recognition of typename. The default value is +supplied by DEFAULT_TYPENAME_ENABLED. This option is valid only +in C++ mode.
    +
    +
    +
    --type_traits_helpers
    +
    --no_type_traits_helpers
    +

    +
    +
    +
    Enable or disable support for type traits helpers (like __is_union +and __has_virtual_destructor; intended to ease the implementation +of ISO/IEC TR 19768). Only valid in C++. Type traits helpers are +enabled in all C++ modes by default, except in GNU and Sun C++ modes.
    +
    +
    +
    --uliterals
    +
    --no_uliterals
    +
    +
    +
    Enable or disable recognition of U-literals (string literals of the +forms U"..." and u"...", and character literals of the forms +U'...' and u'...'). In C++ mode, this also enables or +disables the C++11 char16_t and char32_t keywords.
    +
    +
    +
    --unrestricted_unions
    +
    --no_unrestricted_unions
    +

    +
    +
    +
    Enable or disable C++11-style “unrestricted unions” (i.e., unions with +data members that have nontrivial initialization and/or destruction +semantics). This option can currently not be enabled in Microsoft +mode.
    +
    +
    +
    --user_defined_literals
    +
    --no_user_defined_literals
    +

    +
    +
    +
    Enable or disable C++11-style “user-defined literals,” i.e., +literals with a suffix designating an operator function that is to +be called to produce the value of the literal, e.g., 12.34_km, +which calls operator ""_km(12.34).
    +
    +
    +
    --utf8_char_literals
    +
    --no_utf8_char_literals
    +

    +
    +
    +
    Enable or disable C++17-style UTF-8 character literals (e.g., +u8'a'). Enabled by default in C++17 mode as well as when +microsoft_version >= 1900.
    +
    +
    +
    --variadic_macros
    +
    --no_variadic_macros
    +
    +
    +
    Enable or disable support for variadic macros (a C99 feature that is +also available in C++ mode).
    +
    +
    +
    --extended_variadic_macros
    +
    --no_extended_variadic_macros
    +

    +
    +
    +
    Enable or disable support for “extended variadic macros,” an extension +that emulates the behavior of certain other C compilers when it comes +to variadic macros.
    +
    +
    +
    --variadic_templates
    +
    --no_variadic_templates
    +

    +
    +
    +
    Enable or disable support for “variadic templates,” a C++11 feature +that allows declaration of templates with a variable number of +arguments. The default value is dependent on the major language mode +and on DEFAULT_VARIADIC_TEMPLATES_ENABLED. This option is valid +only in C++ modes.
    +
    +
    +
    --vla
    +
    --no_vla
    +
    +
    +
    Enable or disable support for “variable length arrays,” a C99 feature +and an extension in some other modes that allows the declaration and +use of arrays of automatic storage duration with dimensions that are +fixed at run time. These options are available only if +VLA_ALLOWED is configured to TRUE.
    +
    +
    +
    --wchar_t_keyword
    +
    --no_wchar_t_keyword
    +
    +
    +
    Enable or disable recognition of wchar_t as a keyword. The +default value is supplied by DEFAULT_WCHAR_T_IS_KEYWORD. This +option is valid only in C++ mode. The front end can be configured to +define a preprocessing variable when wchar_t is recognized as a +keyword. This preprocessing variable may then be used by the standard +header files to determine whether a typedef should be supplied to +define wchar_t.
    +
    +
    +
    +
    +
    +

    2.1.6. Alternative Language Behaviors#

    +

    The following options affect the meaning of various language constructs.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --aligned_new
    +
    --no_aligned_new
    +

    +
    +
    +
    Enable or disable calling special allocation and deallocation +functions for types with more stringent alignment requirements than +the fundamental types (enabled by default in C++17 modes and disabled +otherwise).
    +
    +
    +
    --arg_dep_lookup
    +
    --no_arg_dep_lookup
    +

    +
    +
    +
    In C++, controls whether argument dependent lookup of unqualified +function names is performed
    +
    +
    +
    --base_assign_op_is_default
    +
    --no_base_assign_op_is_default
    +

    +
    +
    +
    Enable or disable the anachronism of accepting a copy assignment +operator that has an input parameter that is a reference to a base +class as a default copy assignment operator for the derived class. +This option is enabled by default in cfront compatibility mode.
    +
    +
    +
    --class_name_injection
    +
    --no_class_name_injection
    +

    +
    +
    +
    In C++, controls whether the name of a class is injected into the +scope of the class (as required by the standard) or is not injected +(as was true in earlier versions of the C++ language).
    +
    +
    +
    --const_string_literals
    +
    --no_const_string_literals
    +

    +
    +
    +
    Control whether C++ string literals and wide string literals are const +(as required by the standard) or non-const (as was true in earlier +versions of the C++ language).
    +
    +
    +
    --default_calling_convention calling-convention
    +

    +
    +
    +
    The calling convention that should be assumed for functions that are +declared without an explicit calling convention. This option may only +be used if MICROSOFT_EXTENSIONS_ALLOWED is TRUE. +calling-convention must be one of __cdecl, __fastcall, +__stdcall, and __thiscall.
    +
    +
    +
    --default_nocommon_tentative_definitions
    +
    --default_common_tentative_definitions
    +

    +
    +
    +
    Control whether tentative definitions are placed in “common” storage. +These options are only available in configurations with +GNU_EXTENSIONS_ALLOWED set to TRUE. The default can be overridden +for specific variables with the GNU attributes common and +nocommon.
    +
    +
    +
    --defer_parse_function_templates
    +
    --no_defer_parse_function_templates
    +

    +
    +
    +
    Enable or disable deferral of prototype instantiations until the +first actual instantiation of a function. This is used to permit +the compilation of programs that contain definitions of unusable +function templates. It is enabled by default in g++ mode when +gnu_version is >= 30400 (but not when using the C++-generating +back end).
    +
    +
    +
    --dep_name
    +
    --no_dep_name
    +
    +
    +
    Enable or disable dependent name processing; i.e., the special lookup +of names used in templates as required by the C++ standard. The +default value is supplied by DEFAULT_DEPENDENT_NAME_PROCESSING. +This option is valid only in C++ mode and --dep_name cannot be +combined with --no_parse_templates.
    +
    +
    +
    --distinct_template_signatures
    +
    --no_distinct_template_signatures
    +

    +
    +
    +
    Control whether the signatures for template functions can match those +for non-template functions when the functions appear in different +compilation units. (This option is available only on versions that do +name mangling on the names of external entities.) The default is +--distinct_template_signatures, under which a normal function +cannot be used to satisfy the need for a template instance; e.g., a +function “void f(int)” could not be used to satisfy the need for +an instantiation of a template “void f(T)” with T set to +int. --no_distinct_template_signatures provides the older +language behavior, under which a non-template function can match a +template function. Also controls whether function templates may have +template parameters that are not used in the function signature of the +function template.
    +
    +
    +
    --enum_overloading
    +
    --no_enum_overloading
    +
    +
    +
    Enable or disable support for using operator functions to overload +builtin operations on enum-typed operands.
    +
    +
    +
    --far_data_pointers
    +
    --near_data_pointers
    +
    --far_code_pointers
    +
    --near_code_pointers
    +
    +
    +
    Set the default size for pointers when support for near and +far is enabled (e.g., in Microsoft 16-bit mode). Ignored in other +modes.
    +
    +
    +
    --friend_injection
    +
    --no_friend_injection
    +

    +
    +
    +
    In C++, controls whether the name of a class or function that is +declared only in friend declarations is visible when using the normal +lookup mechanisms. When friend names are injected, they are visible +to such lookups. When friend names are not injected (as required by +the standard), function names are visible only when using +argument-dependent lookup, and class names are never visible.
    +
    +
    +
    --func_prototype_tags
    +
    --no_func_prototype_tags
    +
    +
    +
    in C, controls whether tag types first +declared in a function prototype belong to the function prototype +scope (standard C behavior) or to a surrounding scope (default +Microsoft C behavior).
    +
    +
    +
    --gcc89_inlining
    +
    +
    +
    Use the GNU C89 semantics of inline in C99 mode. (Not valid in +C++ modes.)
    +
    +
    +
    --gen_move_operations
    +
    --no_gen_move_operations
    +

    +
    +
    +
    Enable or disable the generation of move constructors and move +assignment operators according to standard C++11 rules.
    +
    +
    +
    --guiding_decls
    +
    --no_guiding_decls
    +
    +
    +
    Enable or disable recognition of “guiding declarations” of template +functions. A guiding declaration is a function declaration that +matches an instance of a function template but has no explicit +definition (since its definition derives from the function template). +For example:
    +
    +
    +
    template <class T> void f(T) { ... }
    +void f(int);
    +
    +
    +
    +
    +
    When regarded as a guiding declaration, f(int) is an instance of +the template; otherwise, it is an independent function for which a +definition must be supplied. If --no_guiding_decls is combined +with --old_specializations, a specialization of a non-member +template function is not recognized – it is treated as a definition +of an independent function. Default behavior is specified by +DEFAULT_GUIDING_DECLS_ALLOWED. This option is valid only in C++ +mode.
    +
    +
    +
    --ignore_std
    +
    +
    +
    Enable a g++ compatibility feature that makes the std +namespace a synonym for the global namespace.
    +
    +
    +
    --implicit_extern_c_type_conversion
    +
    --no_implicit_extern_c_type_conversion
    +

    +
    +
    +
    Enable or disable an extension to permit implicit type conversion in +C++ between a pointer to an extern "C" function and a pointer to +an extern "C++" function. This extension is allowed in +environments where C and C++ functions share the same calling +conventions: IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE +must be set for it to be available. (It is useful for cfront +compatibility when DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT +is TRUE – in standard C++ the linkage specification is part of the +function type, with the consequence that otherwise identical function +types, one declared extern "C" and the other declared extern +"C++", are viewed as distinct.)
    +
    +
    +
    --implicit_noexcept
    +
    --no_implicit_noexcept
    +

    +
    +
    +
    Enable or disable the implicit generation of exception specifications +for user-declared destructors and deallocation functions in C++11 +mode. (In strict C++11 mode, it is enabled by default, whereas in +other C++11 modes it is disabled by default.)
    +
    +
    +
    --implicit_typename
    +
    --no_implicit_typename
    +

    +
    +
    +
    Enable or disable implicit determination, from context, whether a +template parameter dependent name is a type or nontype. The default +value is supplied by DEFAULT_IMPLICIT_TYPENAME_ENABLED. This +option is valid only in C++ mode.
    +
    +
    +
    --late_tiebreaker
    +
    --early_tiebreaker
    +
    +
    +
    Select the way that tie-breakers (e.g., cv-qualifier differences) +apply in overload resolution. In “early” tie-breaker processing, the +tie-breakers are considered at the same time as other measures of the +goodness of the match of an argument value and the corresponding +parameter type (this is the standard approach). In “late” tiebreaker +processing, tie-breakers are ignored during the initial comparison, +and considered only if two functions are otherwise equally good on all +arguments; the tie-breakers can then be used to choose one function +over another.
    +
    +
    +
    --long_lifetime_temps
    +
    --short_lifetime_temps
    +

    +
    +
    +
    Select the lifetime for temporaries: “short” means to end of full +expression; “long” means to the earliest of end of scope, end of +switch clause, or the next label. “short” is standard C++, and “long” +is what cfront uses (the cfront compatibility modes select “long” by +default).
    +
    +
    +
    --long_preserving_rules
    +
    --no_long_preserving_rules
    +

    +
    +
    +
    Enable or disable the K&R usual arithmetic conversion rules with +respect to long. This means the rules of K&R I, Appendix A, 6.6, +not the rules used by the pcc compiler. The significant difference is +in the handling of “long op unsigned int” when int and +long are the same size. The ANSI/ISO/pcc rules say the result is +unsigned long, but K&R I says the result is long (unsigned +long did not exist in K&R I).
    +
    +
    +
    --max_depth_constexpr_call= n
    +
    --max_cost_constexpr_call= n
    +

    +
    +
    +
    Specify the maximum depth of recursion or the maximum “cost” for +folding a top-level constexpr call (function or constructor). In +C++11 modes, the “cost” is the number of calls expanded from a single +top-level call. In C++14 modes, the “cost” is a combination of the +number of calls interpreted and the number of loop iterations +performed during the interpretation of a top-level call.
    +
    +
    +
    --ms_rvalue_cast
    +
    --no_ms_rvalue_cast
    +

    +
    +
    +
    Explicitly disable or enable treating a cast of an lvalue to its own +type as that same lvalue. (--ms_rvalue_cast corresponds to +standard behavior, but Microsoft compilers traditionally behaved +otherwise.) Implies Microsoft mode.
    +
    +
    +
    --ms_strict_ternary
    +
    --no_ms_strict_ternary
    +

    +
    +
    +
    Enable or disable strict standard-conforming behavior of the +conditional ternary operator (?:) in Microsoft mode. It is disabled +by default in Microsoft mode, unless Microsoft permissive mode is +disabled (see --no_ms_permissive). Implies Microsoft mode.
    +
    +
    +
    --nonconst_ref_anachronism
    +
    --no_nonconst_ref_anachronism
    +

    +
    +
    +
    Enable or disable the anachronism of allowing a reference to nonconst +to bind to a class rvalue of the right type. This anachronism is also +enabled by the --anachronisms option and the cfront-compatibility +options.
    +
    +
    +
    --nonstd_anonymous_unions
    +
    --no_nonstd_anonymous_unions
    +

    +
    +
    +
    Enable or disable extensions to the C++ anonymous union feature +(including of anonymous “structs” or “classes”). This option can also +be used in C modes. Enabled by default in GNU and Microsoft modes, +and disabled by default in strict modes.
    +
    +
    +
    --nonstd_default_arg_deduction
    +
    --no_nonstd_default_arg_deduction
    +

    +
    +
    +
    Controls whether default arguments are retained as part of deduced +function types. The C++ standard requires that default arguments not +be part of deduced function types.
    +
    +
    +
    --nonstd_instantiation_lookup
    +
    --no_nonstd_instantiation_lookup
    +

    +
    +
    +
    Controls whether the lookup of names during template instantiation +should, instead of the normal lookup rules, use rules that were part +of the C++98 working paper for some time during the development of the +standard. In this mode, names are looked up in both the namespace of +the template definition and in the namespace in which a template +entity was first referenced in a way that would require an +instantiation.
    +
    +
    +
    --nonstd_qualifier_deduction
    +
    --no_nonstd_qualifier_deduction
    +

    +
    +
    +
    Controls whether nonstandard template argument deduction should be +performed in the qualifier portion of a qualified name. With this +feature enabled, a template argument for the template parameter T +can de deduced in contexts like A<T>::B or T::B. The standard +deduction mechanism treats these as nondeduced contexts that use the +values of template parameters that were either explicitly specified or +deduced elsewhere.
    +
    +
    +
    --old_id_chars
    +
    --no_old_id_chars
    +
    +
    +
    Controls whether the set of extended characters accepted in C++ +identifiers should be those specified by pre-C++23 C++ standards or by +Unicode Standard Annex #44. The latter is the default in all C++ +modes, because the C++ Standard Committee adopted the Unicode +specification of identifier characters both for C++23 and +retroactively for earlier standards.
    +
    +
    +
    --old_for_init
    +
    --new_for_init
    +
    +
    +
    Control the scope of a declaration in a for-init-statement. The +old (cfront-compatible) scoping rules mean the declaration is in the +scope to which the for statement itself belongs; the new +(standard-conforming) rules in effect wrap the entire for +statement in its own implicitly generated scope. The default behavior +is specified by configuration constant +DEFAULT_USE_NONSTANDARD_FOR_INIT_SCOPE. This option is valid only +in C++ mode.
    +
    +
    +
    --pack_alignment n
    +
    +
    +
    Set the default alignment for packing classes and structs to n, a +power-of-2 value within the range defined by +TARG_MINIMUM_PACK_ALIGNMENT and TARG_MAXIMUM_PACK_ALIGNMENT. +The argument n is the default maximum alignment for nonstatic data +members; it can be overridden by a #pragma pack directive. This +option is allowed only when USER_CONTROL_OF_STRUCT_PACKING is +TRUE.
    +
    +
    +
    --parse_templates
    +
    --no_parse_templates
    +

    +
    +
    +
    Enable or disable the parsing of nonclass templates in their generic +form (i.e., even if they are not really instantiated). It is done by +default if dependent name processing is enabled. This option is valid +only in C++ mode.
    +
    +
    +
    --preserve_lvalues_with_same_type_casts
    +
    --no_preserve_lvalues_with_same_type_casts
    +

    +
    +
    +
    Explicitly enable or disable treating a cast of an lvalue to its own +type as that same lvalue (whereas both C and C++ specify that such +casts result in rvalues). Enabled by default in Microsoft and Sun +modes.
    +
    +
    +
    --require_func_prototypes
    +
    --no_require_func_prototypes
    +
    +
    +
    In C, controls whether old-style non-prototype function declarators +are recognized. If not, something like “int f();” is equivalent +to “int f(void);”. The default is that non-prototype function +declarators are not recognized in C23 mode, while they are recognized +in earlier C modes.
    +
    +
    +
    --short_enums
    +
    --no_short_enums
    +
    +
    +
    Enable or disable a mode in which all enumeration types are “packed” +(meaning that the underlying type of the enumeration is chosen to be +the smallest integer that will accommodate the enumerator constants). +Only valid in GNU C compatibility mode.
    +
    +
    +
    --signed_bit_fields
    +

    +
    +
    +
    Make bit fields declared with a plain integer type (e.g., short or +int, but not signed short or unsigned int) signed.
    +
    +
    +
    --signed_chars
    +
    -s
    +
    +
    +
    Make plain char signed. The default signedness for char is +selected at the time of installation of the front end (information on +this appears in a later section of this document). When plain +char is signed, the macro __SIGNED_CHARS__ is defined by the +front end.
    +
    +
    +
    --special_subscript_cost
    +
    --no_special_subscript_cost
    +

    +
    +
    +
    Enable or disable a special nonstandard weighting of the conversion to +the integral operand of the [] operator in overload resolution. +This is a compatibility feature that may be useful with some existing +code. The special cost is enabled by default in cfront 3.0 mode. +With this feature enabled, the following code compiles without error:
    +
    +
    +
    struct A {
    +  A();
    +  operator int *();
    +  int operator[](unsigned);
    +};
    +void main() {
    +  A a;
    +  a[0]; // Ambiguous, but allowed with
    +        // this option operator[]
    +        // is chosen
    +}
    +
    +
    +
    +
    +
    As of July 1996, the above is again acceptable, if ptrdiff_t is +configured as long. Using a parameter of type ptrdiff_t +(instead of unsignedint) is recommended for portability.
    +
    +
    +
    --no_stdarg_builtin
    +
    +
    +
    Disable special treatment of the <stdarg.h> header. When enabled, +the <stdarg.h> header is treated as a built-in, and references to +its macros (va_start et al) are passed through as such in +generated C or C++ code. The default value is supplied by +DEFAULT_PASS_STDARG_REFERENCES_TO_GENERATED_CODE. This option +cannot be used when the feature is disabled by default.
    +
    +
    +
    --unsigned_bit_fields
    +

    +
    +
    +
    Make bit fields declared with a plain integer type (e.g., short or +int, but not signed short or unsigned int) unsigned.
    +
    +
    +
    --unsigned_chars
    +
    -u
    +
    +
    +
    Make plain char unsigned. The default signedness for char is +selected at the time of installation of the front end (information on +this appears in a later section of this document).
    +
    +
    +
    --using_std
    +
    --no_using_std
    +
    +
    +
    Enable or disable implicit use of the std namespace when standard +header files are included. The default behavior is specified by the +configuration constant DEFAULT_IMPLICIT_USING_STD. This option is +valid only in C++ mode. Note that this does not do the equivalent +of putting a “using namespace std;” in the program to allow old +programs to be compiled with new header files; it has a special and +localized meaning related to the EDG versions of certain header files, +and is unlikely to be of much use to end-users of the Front End.
    +
    +
    +
    +
    +
    +

    2.1.7. Template Instantiation Options#

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --auto_instantiation
    +
    --no_auto_instantiation
    +
    -T
    +
    +
    +
    Enable or disable automatic instantiation of templates. The +-T option is equivalent to --auto_instantiation. The +default behavior is specified by the configuration flag +DEFAULT_AUTOMATIC_INSTANTIATION_MODE. See +Template Instantiation. This option is valid only in C++ +mode.
    +
    +
    +
    --definition_list_file file_name
    +

    +
    +
    +
    This option specifies the name of the template definition list file +passed between the front end and the prelinker. This file is a +temporary file and does not remain after the compilation is complete. +This option is supplied for use by the driver program that invokes the +front end and is not intended to be used by end-users.
    +
    +
    +
    --exported_template_file file-name
    +

    +
    +
    +
    This option specifies the name to be used for the exported template +file used for processing of exported templates. This option is +supplied for use by the driver program that invokes the front end and +is not intended to be used by end-users.
    +
    +
    +
    --ii_file file-name
    +
    +
    +
    This option specifies the name to be used for the template +instantiation request file used in automatic instantiation mode. This +option is supplied for use by the driver program that invokes the +front end and is not intended to be used by end-users.
    +
    +
    +
    --implicit_include
    +
    --no_implicit_include
    +
    -B
    +
    +
    +
    Enable or disable implicit inclusion of source files as a method +of finding definitions of template entities to be instantiated. +-B is equivalent to --implicit_include. The default +behavior is specified by the configuration flag +DEFAULT_IMPLICIT_TEMPLATE_INCLUSION_MODE. See +Template Instantiation. This option is valid only in C++ +mode.
    +
    +
    +
    --instantiate mode
    +
    -tmode
    +
    +
    +
    Control instantiation of external template entities. External +template entities are external (i.e., noninline and nonstatic) +template functions, variables, and template static data members. The +instantiation mode determines the template entities for which code +should be generated based on the template definition):
    +
    +
    +
    none

    Instantiate no template entities. This is the default.

    +
    +
    used

    Instantiate only the template entities that are used in this +compilation.

    +
    +
    all

    Instantiate all template entities whether or not they are used.

    +
    +
    local

    Instantiate only the template entities that are used in this +compilation and force those entities to be local to this +compilation.

    +
    +
    +
    +
    See Template Instantiation. This option is valid only in +C++ mode.
    +
    +
    +
    --instantiation_dir dir-name
    +

    +
    +
    +
    When --one_instantiation_per_object is used, this option can be +used to specify a directory into which the generated object files (or +C files, if the C-generating back end if being used) should be put. +The eccp script always specifies this option when invoking the +front end, with the default of Template.dir if the option is not +specified by the user.
    +
    +
    +
    --one_instantiation_per_object
    +

    +
    +
    +
    Put out each template instantiation in this compilation (function, +variable, or static data member) in a separate object file. The +primary object file contains everything else in the compilation, i.e., +everything that isn’t an instantiation. Having each instantiation in +a separate object file is very useful when creating libraries, because +it allows the user of the library to pull in only the instantiations +that are needed. That can be essential if two different libraries +include some of the same instantiations. This option is valid only in +C++ mode, and only if the configuration constant +ONE_INSTANTIATION_PER_OBJECT is TRUE.
    +
    +
    +
    --pending_instantiations= n
    +

    +
    +
    +
    Specifies the maximum number of instantiations of a given template +that may be in process of being instantiated at a given time. This is +used to detect runaway recursive instantiations. If n is zero, +there is no limit. The default is specified by the configuration +parameter DEFAULT_MAX_PENDING_INSTANTIATIONS.
    +
    +
    +
    --suppress_instantiation_flags
    +

    +
    +
    +
    When automatic instantiation is being used, this option suppresses the +generation of the special symbols used by the prelinker to do +automatic instantiation processing. This option is for use by the +driver and prelinker and should not be used directly by users. This +option is used by to implement the driver option that removes the +instantiation flags from object files once the prelinking step has +completed.
    +
    +
    +
    --template_directory dir
    +

    +
    +
    +
    Specifies a directory name to be placed on the exported template +search path. The directories are used to find the definitions of +exported templates and are searched in the order in which they are +specified on the command-line. The current directory is always the +first entry on the search path.
    +
    +
    +
    --template_info_file file-name
    +

    +
    +
    +
    This option specifies the name to be used for the template +instantiation information file used in automatic instantiation mode. +This option is supplied for use by the driver program that invokes the +front end and is not intended to be used by end-users.
    +
    +
    +
    +
    +
    +

    2.1.8. Code Generation Options#

    +

    The following options control the IL produced, the C-generating back end, or +the C++-generating back end.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --no_code_gen
    +
    -n
    +
    +
    +
    Do syntax-checking only, i.e., do not run the back end.
    +
    +
    +
    --force_vtbl
    +
    +
    +
    Force definition of virtual function tables in cases where the +heuristic used by the front end to decide on definition of virtual +function tables provides no guidance. See --suppress_vtbl. This +option is valid only in C++ mode.
    +
    +
    +
    --no_il_lowering
    +
    -N
    +
    +
    +
    On versions that include IL lowering and that write an intermediate +language file, suppress both IL lowering and the back end, and write +an unlowered (i.e., C++ rather than C) IL file. Probably not of +interest to end users.
    +
    +
    +
    --inline_statement_limit size
    +

    +
    +
    +
    When inlining is enabled, sets the maximum size (in number of lowered +statements) for a routine to be inlinable. A value of zero allows an +inlined routine to be any size. Only available when +MINIMAL_INLINING is configured to be TRUE.
    +
    +
    +
    --inlining
    +
    --no_inlining
    +
    +
    +
    Enable or disable minimal inlining of function calls. These options +are available only when MINIMAL_INLINING is configured to be TRUE. +The default is to do inlining when the C-generating back end is used.
    +
    +
    +
    --keep_restrict_in_signatures
    +
    --no_keep_restrict_in_signatures
    +
    +
    +
    In most modern configurations, top-level parameter type qualifiers +are removed from function types. In such configurations, this +option overrides or preserves that behavior for the restrict +qualifier; i.e., when the option is enabled, the mangled name of a +function will reflect the presence of top-level restrict parameter +type qualifiers.
    +
    +
    +
    --module_init name1,name2,…
    +
    -iname1,name2,…
    +
    +
    +
    When generating C output for testing (see c_gen_be in an +Appendix), when compiling in C mode, and if the current compilation +contains a main program, force calling of the file-scope +initialization routines in the indicated compiled units. This is +needed only when there are file-scope union initializations in +translation units that do not contain a main program. A message will +be issued during compilation of such units, indicating the need for +the --module_init option. All necessary names must be specified +in one --module_init option; a second --module_init will +overwrite the original list, not add to it. This option is not needed +when object code is generated by a back end other than the +C-generating back end, nor is it needed when the C-generating back end +is configured to generate ANSI C. This option is not needed in C++ +mode, because C++ has a language mechanism for getting initialization +code executed at program start-up.
    +
    +
    +
    --gen_c_clang_version version-number
    +

    +
    +
    +
    When using the C- or C++-generating back end to produce code that +is to be compiled with the clang compiler, this specifies the +version of the compiler being used (e.g., 150000 for version +15.0). This option is supplied for use by the driver program that +invokes the front end and is not intended to be used by end-users.
    +
    +
    +
    --gen_c_gnu_version version-number
    +

    +
    +
    +
    When using the C- or C++-generating back end to produce code that +is to be compiled with the gcc compiler, this specifies the +version of the compiler being used (e.g., 140100 for version +14.1.0). This option is supplied for use by the driver program +that invokes the front end and is not intended to be used by +end-users.
    +
    +
    +
    --gen_c_msvc_version version-number
    +

    +
    +
    +
    When using the C- or C++-generating back end to produce code that +is to be compiled with the Microsoft compiler, this specifies the +version of the compiler being used (e.g., 1932 for Visual Studio +2022 Update 2). (This option is identical to the earlier +--msvc_target_version option, which continues to be accepted.) +This option is supplied for use by the driver program that invokes +the front end and is not intended to be used by end-users.
    +
    +
    +
    --remove_unneeded_entities
    +
    --no_remove_unneeded_entities
    +

    +
    +
    +
    Enable or disable an optimization to prune the IL tree of types, +variables, routines, and related IL entries that are not “really +needed.” (Something may be referenced but unneeded if it is referenced +only by something that is itself unneeded; certain entities, such as +global variables and routines defined in the translation unit, are +always considered to be needed.) The positive form of the option is +available only when MAINTAIN_NEEDED_FLAGS is TRUE.
    +
    +
    +
    --suppress_vtbl
    +
    -V
    +
    +
    +
    Suppress definition of virtual function tables in cases where the +heuristic used by the front end to decide on definition of virtual +function tables provides no guidance. The virtual function table for +a class is defined in a compilation if the compilation contains a +definition of the first non-inline non-pure virtual function of the +class. For classes that contain no such function, the default +behavior is to define the virtual function table (but to define it as +a local static entity). The option --suppress_vtbl suppresses the +definition of the virtual function tables for such classes, and +--force_vtbl forces the definition of the virtual function table +for such classes. --force_vtbl differs from the default behavior +in that it does not force the definition to be local. This option is +valid only in C++ mode.
    +
    +
    +
    --target target-config-name
    +

    +
    +
    +
    For configurations that support multiple targets, specifies that the +target configuration named target-config-name should be used for the +compilation. If no --target option is specified, the default +target configuration (which may or may not be the legacy +configuration) is used.
    +
    +
    +
    +
    +
    +

    2.1.9. Precompiled Header Options#

    +

    The following options control how precompiled header files are generated and +used.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --pch
    +
    +
    +
    Automatically use and/or create a precompiled header file – for +details, see Precompiled Headers. If +--use_pch or --create_pch (manual PCH mode) appears on the +command line following this option, its effect is erased.
    +
    +
    +
    --create_pch file-name
    +
    +
    +
    If other conditions are satisfied (see +Precompiled Headers), create a precompiled header file with +the specified name. If --pch (automatic PCH mode) or +--use_pch appears on the command line following this option, +its effect is erased.
    +
    +
    +
    --use_pch file-name
    +
    +
    +
    Use a precompiled header file of the specified name as part of the +current compilation. If --pch (automatic PCH mode) or +--create_pch appears on the command line following this option, +its effect is erased.
    +
    +
    +
    --pch_dir directory-name
    +
    +
    +
    The directory in which to search for and/or create a precompiled +header file. This option may be used with automatic PCH mode +(--pch) or with manual PCH mode (--create_pch or +--use_pch).
    +
    +
    +
    --pch_messages
    +
    --no_pch_messages
    +
    +
    +
    Enable or disable the display of a message indicating that a +precompiled header file was created or used in the current +compilation.
    +
    +
    +
    --pch_verbose
    +
    +
    +
    In automatic PCH mode, for each precompiled header file that cannot be +used for the current compilation, a message is displayed giving the +reason that the file cannot be used.
    +
    +
    +
    --pch_mem size
    +
    +
    +
    The number of 1024-byte units of preallocated memory in which to save +precompiled-header state (only if USE_MMAP_FOR_MEMORY_REGIONS is +FALSE).
    +
    +
    +
    +
    +
    +

    2.1.10. C++/CLI Options#

    +
    + + + + + + + + + + + + + + + + + + +
    +
    --mscorlib_file_name file-name
    +
    +
    +
    Use the given assembly metadata file instead of mscorlib.dll to +import system types.
    +
    +
    +
    --preusing file-name
    +
    +
    +
    Import the given assembly metadata file prior to processing the input +source (but after importing mscorlib.dll or the file specified +with the --mscorlib_file_name option).
    +
    +
    +
    --using_directory directory-name
    +

    +
    +
    +
    Add the given directory to the search path used when searching for +assembly metadata files.
    +
    +
    +
    --using_framework_directory
    +
    --no_using_framework_directory
    +

    +
    +
    +
    Do or do not implicitly include the installation directory of the +Microsoft .NET runtime in the search path used when searching for +assembly metadata files. The default is to include that directory.
    +
    +
    +
    --vcmeta_directory directory-name
    +

    +
    +
    +
    Search for the vcmeta.dll file in the specified directory. If +omitted, vcmeta.dll is searched for in the same directory as the +module that contains the front end.
    +
    +
    +
    +
    +
    +

    2.1.11. Front End Debugging Options#

    +
    + + + + + + + + + + + + + + + +
    +
    --dbn
    +
    --dbname=n
    +
    -dn
    +
    -dname=n
    +
    +
    +
    Set the debug output level in the front end, which controls the +output of flow-tracing and similar information to the debug output +file (stderr). --dbn sets the debug level to n (in +the range 1-5) for the entire execution of the compiler (higher +values generate more voluminous debugging output). One can +control the debug output more precisely by specifying a routine +name and the debug level desired upon entry to that routine, as in +--dbname=n. Regardless of the previous setting +of the debug level, it will be changed to the indicated value on +entry to the indicated routine; on exit, it will be restored to +its former value. One can also use += or -= in place of += in that option to increase or decrease the debug level +relative to its current value. The former value is also restored +on exit from the routine in those cases. Ordinarily, a message is +written to debug output whenever the debug level is changed (i.e., +both on entry and exit in the above cases). If that is not +desirable, a ! (implying “not”) can be appended to the level +number in the command-line option, to indicate that the +level-change messages should not be produced for that request. +Several routine names can be specified, and/or several requests +can be made, by separating them with commas, as in the following:
    +
    +
    +

    --db fe_init,fe_wrapup+=2,get_token=3

    +
    +
    +
    -d-name1,-name2,…
    +
    +
    +
    Enable the named “debug flags”, which will enable debug output +associated with the flag. For example, -d-dump_layout produces +output related to the class type layout process.
    +
    +
    +
    -d#name1,#name2,…
    +
    +
    +
    Disable the named “debug flags”.
    +
    +
    +
    --db_name=name
    +
    +
    +
    Enable debug output for source entities with the given name. Not all +debug output takes this option into account; i.e., even with this +option some debug output not associated with the given name may be +produced. When simultaneously compiling multiple translation units, +entities in all translation units are considered by default. The +given name can be restricted to entities in the primary translation +units by preceding it with [] or to entities in a secondary +translation unit by preceding it with [file] where +file is the name of the secondary source file. For example,
    +
    +
    +

    -d-trans_corresp --db_name=[x.cpp]A::f

    +
    +
    +
    will output debugging information about cross-translation-unit +correspondences for a member A::f declared in a secondary +translation unit defined by source file x.cpp.
    +
    +
    +
    +
    +
    +

    2.1.12. Miscellaneous Options#

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    --version
    +
    -v
    +
    +
    +
    Display the version number of the front end, and the Edison Design +Group copyright.
    +
    +
    +
    --building_runtime
    +
    +
    +
    Used to indicate that the EDG runtime library is being compiled. This +causes additional macros to be predefined that are used to pass target +configuration information from the front end to the runtime.
    +
    +
    +
    --edg_base_dir
    +
    +
    +
    The name of the directory in which to find files needed by the front +end at execution time. This option is supplied for use by the driver +program that invokes the front end and is not intended to be used by +end-users.
    +
    +
    +
    --dump_command_options
    +
    +
    +
    Display the complete set of --name +command-line options recognized by the front end in a format that is +compatible with, e.g., the bash shell’s complete command to allow the +shell’s completion facility to be used with front end options.
    +
    +
    +
    --dump_configuration
    +
    +
    +
    Display the complete set of configuration +macros with which the front end was built. The output (to the error +output file) can be captured and used as the contents of the +defines.h file to recreate that configuration. This option is +available only in executables built with DEBUG set to TRUE.
    +
    +
    +
    --dump_legacy_as_target target-config-name
    +
    +
    +
    Displays the legacy configuration in such a manner that the +configuration can be used to specify a new target configuration named +target-config-name. For customers who have multiple versions of the +front end (each configured for a specific target), this option can be +used to generate a separate target configuration for each of the +legacy configurations, and the output combined to form a single +configuration where the target can be specified at run-time (via the +--target option). This option is available only in executables +built with DEBUG set to TRUE. The output is directed to the error +output file.
    +
    +
    +
    --incognito
    +
    --no_incognito
    +
    +
    +
    Enable or disable the suppression of implicitly-defined +EDG-specific macros such as __EDG__ and __EDG_VERSION__. +Suppressing these macros facilitates compilation of code that +incorrectly configures itself via conditional compilation when it +detects that the compiler is based on the EDG front end. The +default behavior of the front end is determined by the value of +the configuration macro DEFAULT_INCOGNITO.
    +
    +
    +
    --il_display
    +
    +
    +
    Displays the IL in a human-readable form. This is +the same output that would be generated by writing the IL to a file +and displaying it with the edgcpdisp utility. The IL that is +displayed is lowered IL (if the configuration does lowering) unless +the --no_il_lowering command-line option is also specified.
    +
    +
    +
    --mmap_address address
    +
    +
    +
    Specify the fixed address to be used in calls to mmap. Valid +addresses are specific to the host operating system (and +architecture), and may change from invocation to invocation +(depending, say on which shared libraries are loaded). The address +chosen should be aligned to the page size of the host. The use of a +fixed address for mmap is useful in cases where pre-compiled +header files are used (to ensure that the same address space is +available from one invocation of the front end to another). This +option is available only in executables built with +USE_FIXED_ADDRESS_FOR_MMAP set to TRUE.
    +
    +
    +
    --check_unicode_security
    +
    --no_check_unicode_security
    +
    +
    +
    Enable or disable checking of comments, string literals, and +identifiers for Unicode patterns that could be used to disguise +malicious source code by making it appear innocuous; suspicious +patterns are reported as warnings. Checking is only applicable to +UTF-encoded Unicode source and header files. These options are +available only in executables built with +UNICODE_VULNERABILITY_CHECKING_SUPPORTED set to TRUE.
    +
    +
    +
    --module_import_diagnostics
    +
    --no_module_import_diagnostics
    +
    +
    +
    Enable or disable the issuing of diagnostic messages during the import +of entities from a module. The option can be used to reduce verbosity +and condense diagnostics that do not relate to the source file being +compiled. The default setting is specified by the +DEFAULT_MODULE_IMPORT_DIAG_ENABLED configuration macro.
    +
    +
    +
    --wdir directory-name
    +
    +
    +
    Specify the directory to use in expanding relative path names. All +relative paths are expanded after command-line processing is complete, +so that any --wdir options preceding the final one have no effect.
    +
    +
    +
    +
    +
    +
    +

    2.2. Environment Variables#

    +

    The environment variable USR_INCLUDE can be set to a directory to be used +instead of /usr/include on the standard include file search list. (Of +course, this has no effect if the front end has been configured to have an +empty “standard list” of include files.)

    +

    When the front end is built with the __MICROSOFT_OS__ flag set, the +environment variable TMP is used to specify the directory to be used for +temporary files. If TMP is not set, and when __MICROSOFT_OS__ is not +set, the environment variable TMPDIR is used to indicate a directory to be +used for temporary files. If TMPDIR is not set, a default temporary +directory (often, /usr/tmp) is used. (Note: at the present time, the front +end only uses temporary files when generating an intermediate language file for +immediate use by a back end called in the same program, and in the C-generating +back end.)

    +
    +
    +

    2.3. Diagnostic Messages#

    +

    Diagnostic messages have an associated severity, as follows:

    +
      +
    • +
      Catastrophic errors indicate problems of such severity that the compilation +cannot continue. For example: command-line errors, internal errors, and +missing include files. If multiple source files are being compiled, any +source files after the current one will not be compiled.
      +
      +
    • +
    • +
      Errors indicate violations of the syntax or semantic rules of the C or C++ +language. Compilation continues, but object code is not generated.
      +
      +
    • +
    • +
      Warnings indicate something valid but questionable. Compilation continues +and object code is generated (if no errors are detected).
      +
      +
    • +
    • +
      Remarks indicate something that is valid and probably intended, but which a +careful programmer may want to check. These diagnostics are not issued by +default. Compilation continues and object code is generated (if no errors +are detected).
      +
      +
    • +
    +

    Diagnostics are written to the error output file with a form like the +following:

    +
    "test.c", line 5: a break statement may only be used within a loop
    +          or switch
    +    break;
    +    ^
    +
    +
    +

    Diagnostics are normally written to stderr, but the front end can be +configured to use stdout by setting the DIRECT_ERROR_OUTPUT_TO_STDOUT +configuration macro. When this flag is set, messages are directed to +stdout, except when doing preprocessing only. Errors during command-line +processing are always directed to stderr.

    +

    Diagnostic messages can optionally be “colorized”. Colorization is enabled +when the colorize_diagnostics global variable is TRUE. To support +colorization of diagnostics, diagnostics are annotated when the +annotate_diagnostics global variable is TRUE. In that case, annotation +sequences are inserted into the diagnostic message itself to identify pieces of +the diagnostic that might later be highlighted in some fashion. These two +character annotations take the form of an “escape” character +(DIAG_ANNOTATION_INDICATOR) followed by an a_diagnostic_annotation_kind +enumerator. When colorization is enabled, format_output_line replaces the +annotations with Select Graphic Rendition (SGR) codes that, on most terminal +emulators, can be used to highlight text in various ways. The SGR codes used +for colorization default to a string specified by DEFAULT_EDG_COLORS which +can be overridden by the EDG_COLORS environment variable (if set). The +string consists of a colon-separated list of elements, where each element +specifies a string that maps to an a_diagnostic_annotation_kind value +followed by an “=” and the SGR string to use when highlighting text of that +kind. For example:

    +
    "error=01;31:warning=01;35:note=01;36:locus=01:quote=01:range1=32"
    +
    +
    +

    A customer can use the annotations in a diagnostic to display the annotated +pieces in any fashion they desire (e.g., when a GUI is available).

    +

    Note that the message identifies the file and line involved, and that the +source line itself (with position indicated by the ^) follows the message. +If there are several diagnostics in one source line, each diagnostic will have +the form above, with the result that the text of the source line will be +displayed several times, with an appropriate position each time.

    +

    Long messages are wrapped to additional lines when necessary.

    +

    A configuration flag controls whether or not the string “error:” appears, +i.e., the front end can be configured so that the severity string is omitted +when the severity is “error”.

    +

    A command line option may be used to request a shorter form of the diagnostic +output in which the original source line is not displayed and the error message +text is not wrapped when too long to fit on a single line.

    +

    A command line option may be used to request that the error number be included +in the diagnostic message. When displayed, the error number also indicates +whether the error may have its severity overridden on the command line. If the +severity may be overridden, the error number will include the suffix “-D” +(for “discretionary”); otherwise no suffix will be present.

    +
    "Test_name.c", line 7: error #64-D: declaration does not declare anything
    +  struct {};
    +  ^
    +"Test_name.c", line 9: error #77: this declaration has no storage class or
    +          type specifier
    +  xxxxx;
    +  ^
    +
    +
    +

    Because an error is determined to be discretionary based on the error severity +associated with a specific context, a given error may be discretionary in some +cases and not in others.

    +

    For some messages, a list of entities is useful; they are listed following the +initial error message:

    +
    "test.c", line 4: error: more than one instance of overloaded function "f"
    +          matches the argument list:
    +            function "f(int)"
    +            function "f(float)"
    +            argument types are: (double)
    +    f(1.5);
    +    ^
    +
    +
    +

    In some cases, some additional context information is provided; specifically, +such context information is useful when the front end issues a diagnostic while +doing a template instantiation or while generating a constructor, destructor, +or assignment operator function. For example:

    +
    "test.c", line 7: error: "A::A()" is inaccessible
    +  B x;
    +     ^
    +          detected during implicit generation of "B::B()" at line 7
    +
    +
    +

    Without the context information, it is very hard to figure out what the error +refers to.

    +

    If the front end is configured with FULLY_RESOLVED_MACRO_POSITIONS (and, +optionally, MACRO_INVOCATION_TREE_IN_IL) set to TRUE, messages referring to +text occurring inside a macro expansion may provide additional information. +This additional information gives the source location from which the text was +copied into the macro expansion (i.e., from a macro definition or one of the +arguments in the top-level macro invocation), as well as possibly the chain of +macro invocations leading to the expanded text to which the diagnostic refers. +If the front end is configured to permit the display of this information, it +can also be enabled or disabled by the command-line option +--[no_]macro_positions_in_diagnostics. The information is presented in a +form like the following:

    +
    "test.c", line 1: error: identifier "val" is undefined
    +   #define incr(x) (x)+=val
    +                        ^
    +  in expansion of macro "incr" at "test.c", line 2,
    +  in expansion of macro "next_val" at "test.c", line 4:
    +   return next_val(i);
    +          ^
    +
    +
    +
    +
    +

    2.4. Termination Messages#

    +

    When the front end is installed without the USING_DRIVER option (see +information on configuration later in this document), it writes sign-off +messages to the error output file. For example, one of the following forms of +message

    +
    n errors detected in the compilation of "ifile".
    +1 catastrophic error detected in the compilation of "ifile".
    +n errors and 1 catastrophic error detected in the compilation of "ifile".
    +
    +
    +

    is written to indicate the detection of errors in the compilation. No message +is written if no errors were detected. The following message

    +
    Error limit reached.
    +
    +
    +

    is written when the count of errors reaches the error limit (see the -e +option, above); compilation is then terminated. The message

    +
    Compilation terminated.
    +
    +
    +

    is written at the end of a compilation that was prematurely terminated because +of a catastrophic error. The message

    +
    Compilation aborted.
    +
    +
    +

    is written at the end of a compilation that was prematurely terminated because +of an internal error. Such an error indicates an internal problem in the +compiler and should be reported to those responsible for its maintenance.

    +
    +
    +

    2.5. Response to Signals#

    +

    Except in multi-threaded builds, the signals SIGINT (caused by a user +interrupt, like ^C) and SIGTERM (caused by a kill command) are +trapped by the front end and cause abnormal termination. When +MULTIPLE_THREAD_COMPILATION is TRUE, it’s expected that the customer +application will install handlers as appropriate and no signal handling is +performed by the front end.

    +
    +
    +

    2.6. Exit Status#

    +

    On completion, the front end returns with a code indicating the +highest-severity diagnostic detected: 4 if there was a catastrophic error, 2 if +there were any errors, or 0 if there were any warnings or remarks or if there +were no diagnostics of any kind.

    +

    If multiple source files are compiled, the exit status indicates the +highest-severity diagnostic detected in the entire compilation.

    +
    +
    +

    2.7. Finding Include Files#

    +

    A file name specified in a #include directive is searched for in a set of +directories specified by command-line options and environment variables. If +the file name specified does not include a suffix, a set of suffixes is used +when searching for the file.

    +

    Files whose names are not absolute pathnames and that are enclosed in "..." +will be searched for in the following directories, in the order listed:

    +
      +
    1. The directory containing the current input file (the primary source file +or the file containing the #include); [2]

    2. +
    3. any directories specified in --include_directory options (in the +order in which they were listed on the command line);

    4. +
    5. any directories on the standard list (this list is selected at the time +of installation of the front end; often, it is just the one directory +/usr/include or a similar system include directory for C++).

    6. +
    +

    For file names enclosed in <...>, only the directories that are specified +using the --include_directory option and those on the standard list are +searched. If the directory name is specified as “-”, e.g., “-I-”, the +option indicates the point in the list of --include_directory options at +which the search for file names enclosed in <...> should begin. That is, +the search for <...> names should only consider directories named in +--include_directory options following the -I-, and the directories of +item 3 above. -I- also removes the directory containing the current input +file (item 1 above) from the search path for file names enclosed in "...".

    +

    An include directory specified with the --sys_include option is considered +a “system” include directory. Warnings are suppressed when processing files +found in system include directories. If a default include directory has been +specified using the USR_INCLUDE configuration flag or environment variable, +it is considered a system include directory.

    +

    If the file name has no suffix it will be searched for by appending each of a +set of include file suffixes. When searching in a given directory all of the +suffixes are tried in that directory before moving on to the next search +directory. The default set of suffixes is specified by the +DEFAULT_INCLUDE_FILE_SUFFIX_LIST configuration parameter. The default can +be overridden using the --incl_suffixes command-line option. A null file +suffix cannot be used unless it is present in the suffix list (i.e., the front +end will always attempt to add a suffix from the suffix list when the file name +has no suffix).

    +
    +
    +

    2.8. Finding Module Files#

    +

    An import directive can specify either a module unit or a header unit, and +the process of finding these differ. A header unit import names the header +identically to the equivalent #include directive (a file name enclosed in +<...> or "..."), while a module unit is imported by its name and not +the name of the file containing the module unit.

    +

    An import directive that specifies a header unit first finds the named +header using the process for finding #include files. See +Finding Include Files. If the header is found, the corresponding module file +is found by the following search, in the listed order:

    +
      +
    1. Using the direct mappings provided by --ms_header_unit.

    2. +
    3. Using the unresolved mappings provided by --ms_header_unit_angle (if +the header file name is specified via <...>) or by +--ms_header_unit_quote (if the header file name is specified via +"..."). If a match is found here, that match is added to the map +for --ms_header_unit.

    4. +
    +

    An import directive that specifies a module unit will search for the module +file, in the order listed:

    +
      +
    1. Any direct mappings from that module name to a module file as specified +by --ms_mod_file_map

    2. +
    3. Any files listed without a direct map by --ms_mod_file_map, examining +those files to determine if the module each represents matches the module +being imported

    4. +
    5. Files in the directory containing the current input file (the primary +source file or the file containing the import)

    6. +
    7. Files in any directories specified by--modules_directory (in the +order in which they were listed on the command line)

    8. +
    9. Files in the directory specified by the EDG_MODULES_PATH environment +variable, if it’s set.

    10. +
    +
    +
    +

    2.9. C++ Dialect Accepted#

    +

    In strict C++ mode, the front end accepts the complete C++ language as defined +by the ISO/IEC 14882:2003 standard, including export templates (if the front +end’s configuration allows them). In nonstrict C++ mode (which is the default +in common configurations), a small set of features – particularly, export +templates – are not supported, but some minor extensions commonly available on +other compilers are accepted.

    +

    The front end accepts the complete C++17 language as defined by the ISO/IEC +14882:2017 standard (enabled through the command-line option --c++17). The +front end also fully supports the earlier C++14, C++11, and (as noted above) +C++98/03 versions of the language. The front end supports most of the features +of the C++20 language as defined by the 14882:2020 standard (enabled through +the command-line option --c++20). The C++20 features that are not accepted +yet are described below.

    +

    Extensive compatibility modes are also available for the Microsoft Visual C++ +compilers, the GNU C++ (“GCC”) compilers, and the clang C++ compiler. A more +basic Sun C++ compatibility mode is also implemented. Only one emulation mode +may be active at a time (but --ms_extensions or --ms_compatibility may +be enabled in non-Microsoft emulation modes).

    +

    The front end also has a cfront compatibility mode, which duplicates a number +of “features” and bugs of cfront 2.1 and 3.0.x. Complete compatibility is not +guaranteed or intended – the mode is there to allow programmers who have +unwittingly used cfront features to continue to compile their existing code. +In particular, if a program gets an error when compiled by cfront, the EDG +front end may produce a different error or no error at all.

    +

    Command-line options are available to enable and disable anachronisms, to +control strict standard-conformance checking, and to adjust the severity of +certain diagnostics.

    +
    +

    2.9.1. C++20 Implementation Status#

    +

    Most of the new features and changes in the C++20 standard are accepted by +the front end. Details about the specific changes (e.g., the first version +of the front end to support the feature, and the standard committee papers +that introduced the feature) can be found on the EDG website.

    +

    The following C++20 features are not yet supported (our web site has links with +further details):

    +
      +
    • +
      Concepts are supported, but some of the most recent changes to the feature +are not yet supported:
      +
      +
        +
      • +
        Partial ordering of rewritten operator candidates resulting from +constrained templates
        +
        +
      • +
      • +
        Clarify declaration matching and partial ordering requiring substitution +into constraints
        +
        +
      • +
      +
    • +
    • +
      When are constexpr member functions defined? (core issue 1581). This +is not yet implemented because of concerns about potential code breakage.
      +
      +
    • +
    • +
      Modules. (There is partial support for importing Microsoft modules. See +the release notes for more information.)
      +
      +
    • +
    +
    +
    +

    2.9.2. C++23 and C++26 Implementation Status#

    +

    Some of the new features and changes in the C++23 and draft C++26 standard are +accepted by the front end. Details about the specific changes (e.g., the first +version of the front end to support the feature, and the standard committee +papers that introduced the feature) can be found on the EDG website.

    +
    +
    +

    2.9.3. “Default” C++ Mode#

    +

    The following extensions are accepted default C++ mode. Most of these are also +accepted in any other C++ mode that does not diagnose strict ANSI violations as +errors (exceptions are explicitly noted).

    +
      +
    • +
      A friend declaration for a class may omit the class keyword:
      +
      +
      class B;
      +class A {
      +  friend B;  // Should be "friend class B"
      +};
      +
      +
      +
    • +
    • +
      Constants of scalar type may be defined within classes (this is an old +form; the modern form uses an initialized static data member):
      +
      +
      class A {
      +  const int size = 10;
      +  int a[size];
      +};
      +
      +
      +
    • +
    • +
      In the declaration of a class member, a qualified name may be used:
      +
      +
      struct A {
      +  int A::f();  // Should be int f();
      +};
      +
      +
      +
    • +
    • +
      If ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE, an extension is +supported to allow an anonymous union to be introduced into a containing +class by a typedef name – it needn’t be declared directly, as with a +true anonymous union. For example:
      +
      +
      typedef union {
      +  int i, j;
      +} U;           // U identifies a reusable anonymous union.
      +class A {
      +  U;           // Okay -- references to A::i and A::j are allowed.
      +};
      +
      +
      +
      +
      In addition, the extension also permits “anonymous classes” and “anonymous +structs,” as long as they have no C++ features (e.g., no static data +members or member functions and no nonpublic members) and have no nested +types other than other anonymous classes, structs, or unions. For +instance,
      +
      +
      struct A {
      +  struct {
      +    int i, j;
      +  };           // Okay -- references to A::i and A::j are allowed.
      +};
      +
      +
      +
    • +
    • +
      If recognition of the restrict keyword is enabled, the C99 restrict +feature is supported in a form extended for C++, which allows restrict +as a type qualifier for reference and pointer-to-member types and for +nonstatic member functions. The set of C++ extensions is described in +J16/92-0057.
      +
      +
    • +
    • +
      If IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE is TRUE, implicit +type conversion between a pointer to an extern "C" function and a +pointer to an extern "C++" function is permitted. Here’s an example:
      +
      +
      extern "C" void f();     // f's type has extern "C" linkage
      +void (*pf)()             // pf points to an extern "C++" function
      +             = &f;       // error unless implicit conversion is allowed
      +
      +
      +
      +
      This extension is allowed in environments where C and C++ functions share +the same calling conventions (though it is pointless unless +DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT is TRUE). When +DEFAULT_IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_ALLOWED is set, it is +enabled by default; it can also be enabled in cfront-compatibility mode or +with command-line option --implicit_extern_c_type_conversion.
      +
      +
    • +
    • +
      A “?” operator whose second and third operands are string literals or +wide string literals can be implicitly converted to “char *” or +“wchar_t *”. (Recall that in C++ string literals are const. There +is a deprecated implicit conversion that allows conversion of a string +literal to “char *”, dropping the const. That conversion, however, +applies only to simple string literals. Allowing it for the result of a +“?” operation is an extension.)
      +
      +
      char *p = x ? "abc" : "def";
      +
      +
      +
    • +
    • +
      Default arguments may be specified for function parameters other than those +of a top-level function declaration (e.g., they are accepted on typedef +declarations and on pointer-to-function and pointer-to-member-function +declarations).
      +
      +
    • +
    • +
      Nonstatic local variables of an enclosing function can be referenced in a +non-evaluated expression (e.g., a sizeof expression) inside a local +class. A warning is issued.
      +
      +
    • +
    • +
      In default C++ mode (but not other non-C++11 modes), the friend class +syntax is extended to allow nonclass types as well as class types expressed +through a typedef or without an elaborated type name. For example:
      +
      +
      typedef struct S ST;
      +class C {
      +  friend S;             // Okay (requires S to be in scope).
      +  friend ST;            // Okay (same as "friend S;").
      +  friend int;           // Okay (no effect).
      +  friend S const;       // Error: cv-qualifiers cannot appear directly.
      +};
      +
      +
      +
    • +
    • +
      In default C++ mode, mixed string literal concatenations are accepted. +(This is a feature carried over from C99 and also available in GNU modes. +It is not enabled in other non-C++11 modes.)
      +
      +
      wchar_t *str = "a" L"b";  // Okay, same as L"ab".
      +
      +
      +
    • +
    • +
      In default C++ mode, variadic macros are accepted. (This is a feature +carried over from C99 and also available in GNU modes. It is not by +default enabled in other non-C++11 modes.)
      +
      +
    • +
    • +
      In default C++ mode, empty macro arguments are accepted (a feature carried +over from C99).
      +
      +
    • +
    • +
      A trailing comma in the definition of an enumeration type is silently +accepted (a feature carried over from C99):
      +
      +
      enum E { e, };
      +
      +
      +
    • +
    +

    Except where noted, all of the extensions described in the C dialect section +are also allowed in C++ mode.

    +
    +
    +

    2.9.4. GNU C++ Mode#

    +

    The front end can be built to accept GNU extensions. In GNU C++ mode, a large +number of extensions and bugs are closely emulated. This feature enables the +front end to compile many large and complex projects that were developed using +the GNU tool chain; this includes major open-source projects.

    +

    Support for this emulation is ongoing: New GNU C++ features are added as +needed, with priority given to features used in system headers.

    +

    Because the GNU compiler frequently changes behavior between releases, the +front end provides an option (--gnu_version) to specify a specific version +of GCC to emulate. Generally speaking, features and bugs are emulated to +exactly match each known version of GCC, but occasionally the emulation is +approximate and in such cases the front end is often a little more permissive +than GCC on the principle that it is more important to accept source that GCC +accepts than to diagnose every case that GCC diagnoses. The front end does +not, however, attempt to emulate every GCC command-line option; in particular, +GCC options to be extra-permissive are not emulated (however, the severity of +specific error diagnostics can sometimes be decreased to accept constructs that +are not by-default allowed in GNU emulation mode).

    +

    Some GNU features are only emulated when specific configuration options are +enabled. For example, support for complex floating-point types is only +available when the front end is configured to support C99 extensions.

    +

    A few GCC extensions there are likely not going to be supported in the +foreseeable future:

    +
      +
    • +
      The forward declaration of function parameters (so they can participate in +variable-length array parameters).
      +
      +
    • +
    • +
      GNU-style complex integral types (complex floating-point types are +supported)
      +
      +
    • +
    • +
      Nested functions
      +
      +
    • +
    • +
      Local structs with variable-length array fields. Such fields are treated +(with a warning) as zero-length arrays in GNU C mode, which is a useful +approximation in some circumstances, but not generally equivalent to the +GNU feature.
      +
      +
    • +
    +
    +
    +

    2.9.5. Microsoft C++ Mode#

    +

    The front end also extensively emulates the Microsoft Visual C++ compilers. As +is the case with GNU modes, an option (--microsoft_version) is available to +select a specific version of Microsoft’s compiler to emulate.

    +

    Although Microsoft C++ and C modes generally emulate both extensions/features +and bugs, the emulation of a certain class of bugs (considered more severe) can +be controlled separately (using the --no_microsoft_bugs/--microsoft_bugs +options).

    +

    Microsoft C++ mode can be combined with certain other language options to +enable a larger superset of the language accepted by the Microsoft compiler.

    +

    In addition to full Microsoft emulation mode, two subsets of Microsoft +emulation are available: --ms_extensions, and --ms_compatibility, +corresponding to clang’s -fms-extensions and -fms-compatibility +command-line options, respectively. These command-line options allow a certain +degree of Microsoft emulation while the primary emulation mode is something +else (e.g., --clang).

    +

    Support for Microsoft C++ emulation is ongoing: New features are added as +needed, with priority given to features used in system headers.

    +
    +
    +

    2.9.6. Microsoft C++/CLI Mode#

    +

    The front end implements the language extensions known as “C++/CLI” that +simplifies writing C++-like programs for Microsoft’s “.NET” environment. These +extensions are formally described through the ECMA-372 standard, but where the +Microsoft compiler deviates from the standard, the front end follows the +Microsoft compiler rather than the standard.

    +

    Almost all C++/CLI features are implemented in the front end. This includes +various managed class kinds and the special members (e.g., properties) that +they can contain, delegates, handles and tracking references, gcnew, +generics, importing of assemblies, hide-by-sig lookup rules, string literal +rules, and so forth. A notable exception is Microsoft-style attributes +(delimited by square brackets): The front end can parse them, but does not +currently implement their semantics.

    +

    An earlier attempt at integrating C++ and .NET was known as “Managed C++”: The +front end does not support those earlier Microsoft compiler features (which +have since been deprecated by Microsoft).

    +
    +
    +

    2.9.7. Extensions Accepted in Sun Compatibility Mode#

    +

    The front end provides a “Sun Compatibility” mode. This mode automatically +selects a set of command-line options that provides the greatest compatibility +with the Sun CC 5.x compiler. It also enables certain extensions that are +accepted by the Sun compiler. Note that this mode is provided to enable the +front end to compile code such as commonly used Sun header files, and is not +intended to provide complete compatibility with the Sun compiler.

    +

    Sun compatibility mode currently corresponds to the following combination of +options:

    +
    --no_guiding_decls
    +--extern_inline
    +--nonstd_using_decl
    +
    +
    +

    These settings can explicitly be overridden using more command-line options.

    +

    The following extensions are accepted in Sun compatibility mode:

    +
      +
    • +
      The Sun-specific link scope specifiers __global, __symbolic, and +__hidden can be recognized. In modes that recognize these keywords, +the pragmas “#pragma disable_ldscope” and “#pragma enable_ldscope” +can be used to temporarily allow these keywords as normal identifiers. For +example:
      +
      +
      __global int i;       // Accepted in some Sun modes.
      +#pragma disable_ldscope
      +int __global;         // Okay: Keyword (temporarily) deactivated.
      +#pragma enable_ldscope
      +struct __global;      // Error: __global is a keyword.
      +
      +
      +
    • +
    • +
      The __thread specifier can be used to indicate that a variable should +be placed in thread-local storage.
      +
      +
    • +
    • +
      In Sun mode, a non-tag from one scope hides a tag from another scope when +both are visible as a result of a using-directive.
      +
      +
      template <class T> struct B { };
      +namespace N {
      +  typedef B<char> A;
      +}
      +using namespace N;
      +class A;typedef A C;   // Sun mode uses typedef N::A instead of ambiguity
      +
      +
      +
    • +
    • +
      A reference to an undeclared function template is accepted when the +reference appears in the definition of a class template.
      +
      +
      template <class T> struct A {
      +  friend void f<>(T&);  // Accepted in Sun mode
      +};
      +
      +
      +
    • +
    • +
      When a friend class is declared with an unqualified name, the lookup of +that name is not restricted to the nearest enclosing namespace scope.
      +
      +
      struct S;
      +namespace N {
      +  class C {
      +    friend struct S;  // ::S in Sun and Microsoft modes
      +  };
      +                      // (N::S otherwise)
      +}
      +
      +
      +
    • +
    • +
      The typename keyword is ignored in most contexts.
      +
      +
      // The Sun compiler does recognize typename in a template parameter list
      +template <typename T> class C {
      +  // Illegal uses of typename that are accepted by the Sun compiler
      +  typename T t;
      +  typename typename T typename typename x;
      +};
      +
      +
      +
    • +
    • +
      A default argument may be specified in the definition of a member function +of a class template declared outside of the class.
      +
      +
      template <class T> struct A {
      +  void f(int);
      +};
      +template <class T> void A<T>::f(int = 0) { }
      +
      +
      +
    • +
    • +
      A template argument list may appear following a constructor name in +constructor definition that appears outside of the class definition:
      +
      +
      template <class T> struct A {
      +  A();
      +};
      +template <class T> A<T>::A<T>(){}
      +
      +
      +
    • +
    • +
      Template parameters are (incorrectly) visible in class template +specializations and specializations of members of class templates.
      +
      +
      template <class T> struct A {
      +  void f();
      +};
      +template <> struct A<int> {
      +  T t;  // T should not be visible here
      +};
      +template <> void A<char>::f() {
      +  T t;  // T should not be visible here
      +}
      +
      +
      +
    • +
    • +
      The explicit instantiation of a class does not cause the instantiation of +its inline members.
      +
      +
      +
      template <class T> struct A {
      +  void f() {
      +    g();
      +  } // Not instantiated in Sun mode
      +};
      +template class A<int>;
      +
      +
      +
      +
    • +
    • +
      An extern inline function that is referenced but not defined is +permitted (with a warning).
      +
      +
    • +
    • +
      Default arguments are retained as part of deduced function types.
      +
      +
    • +
    • +
      When searching for a header file specified using the <...> syntax, the +front end searches for the specified header file name and also for a +version with the suffix .SUNWCCh appended (e.g., stddef.h.SUNWCCh).
      +
      +
    • +
    • +
      The std namespace is predeclared.
      +
      +
    • +
    • +
      A reference to a nonstatic data member may be written without an object +(not even an implicit this->) inside a sizeof:
      +
      +
      typedef struct _X {
      +  char A[512];
      +} X;
      +static unsigned int foo() {
      +  return sizeof(X::A);
      +}
      +
      +
      +
    • +
    • +
      A storage class may appear in a declaration that also has a “direct” +linkage specification – e.g.,
      +
      +
      extern "s" static void f();
      +
      +
      +
      +
      is treated as equivalent to
      +
      +
      extern "C" { static void f(); }
      +
      +
      +
    • +
    +
    +
    +

    2.9.8. Anachronisms Accepted#

    +

    The following anachronisms are accepted when anachronisms are enabled:

    +
      +
    • +
      overload is allowed in function declarations. It is accepted and +ignored.
      +
      +
    • +
    • +
      Definitions are not required for static data members that can be +initialized using default initialization. The anachronism does not apply +to static data members of template classes; they must always be defined.
      +
      +
    • +
    • +
      The number of elements in an array may be specified in an array delete +operation. The value is ignored.
      +
      +
    • +
    • +
      A single operator++() and operator--() function can be used to +overload both prefix and postfix operations.
      +
      +
    • +
    • +
      The base class name may be omitted in a base class initializer if there is +only one immediate base class.
      +
      +
    • +
    • +
      Assignment to this in constructors and destructors is allowed. This is +allowed only if anachronisms are enabled and the “assignment to this” +configuration parameter is enabled.
      +
      +
    • +
    • +
      A bound function pointer (a pointer to a member function for a given +object) can be cast to a pointer to a function.
      +
      +
    • +
    • +
      A nested class name may be used as a nonnested class name provided no other +class of that name has been declared. The anachronism is not applied to +template classes.
      +
      +
    • +
    • +
      A reference to a non-const type may be initialized from a value of a +different type. A temporary is created, it is initialized from the +(converted) initial value, and the reference is set to the temporary.
      +
      +
    • +
    • +
      A reference to a non-const class type may be initialized from an rvalue of +the class type or a derived class thereof. No (additional) temporary is +used.
      +
      +
    • +
    • +
      A function with old-style parameter declarations is allowed and may +participate in function overloading as though it were prototyped. Default +argument promotion is not applied to parameter types of such functions when +the check for compatibility is done, so that the following declares the +overloading of two functions named f:
      +
      +
      int f(int);
      +int f(x) char x; { return x; }
      +
      +
      +
      +
      It will be noted that in C this code is legal but has a different +meaning: a tentative declaration of f is followed by its definition.
      +
      +
    • +
    • +
      When --nonconst_ref_anachronism is enabled, a reference to a nonconst +class can be bound to a class rvalue of the same type or a derived type +thereof.
      +
      +
      struct A {
      +  A(int);
      +  A operator=(A&);
      +  A operator+(const A&);
      +};
      +main () {
      +  A b(1);
      +  b = A(1) + A(2);   // Allowed as anachronism
      +}
      +
      +
      +
    • +
    +
    +
    +

    2.9.9. Extensions Accepted in Cfront 2.1 Compatibility Mode#

    +

    The following extensions are accepted in cfront 2.1 compatibility mode in +addition to the extensions listed in the 2.1/3.0 section following (i.e., these +are things that were corrected in the 3.0 release of cfront):

    +
      +
    • +
      The dependent statement of an if, while, do-while, or +for is not considered to define a scope. The dependent statement may +not be a declaration. Any objects constructed within the dependent +statement are destroyed at exit from the dependent statement.
      +
      +
    • +
    • +
      Implicit conversion from integral types to enumeration types is allowed.
      +
      +
    • +
    • +
      A non-const member function may be called for a const object. A +warning is issued.
      +
      +
    • +
    • +
      A const void * value may be implicitly converted to a void * value, +e.g., when passed as an argument.
      +
      +
    • +
    • +
      When, in determining the level of argument match for overloading, a +reference parameter is initialized from an argument that requires a +non-class standard conversion, the conversion counts as a user-defined +conversion. (This is an outright bug, which unfortunately happens to be +exploited in the NIH class libraries.)
      +
      +
    • +
    • +
      When a builtin operator is considered alongside overloaded operators in +overload resolution, the match of an operand of a builtin type against the +builtin type required by the builtin operator is considered a standard +conversion in all cases (e.g., even when the type is exactly right without +conversion).
      +
      +
    • +
    • +
      A reference to a non-const type may be initialized from a value that is +a const-qualified version of the same type, but only if the value is +the result of selecting a member from a const class object or a pointer +to such an object.
      +
      +
    • +
    • +
      The cfront 2.1 “transitional model” for nested type support is simulated. +In the transitional model a nested type is promoted to the file scope +unless a type of the same name already exists at the file scope. It is an +error to have two nested classes of the same name that need to be promoted +to file scope or to define a type at file scope after the declaration of a +nested class of the same name. This “feature” actually restricts the +source language accepted by the compiler. This is necessary because of the +effect this feature has on the name mangling of functions that use nested +types in their signature. This feature does not apply to template classes +and is only enabled when the configuration switch +CFRONT_2_1_OBJECT_CODE_COMPATIBILITY is TRUE.
      +
      +
    • +
    • +
      A cast to an array type is allowed; it is treated like a cast to a pointer +to the array element type. A warning is issued.
      +
      +
    • +
    • +
      When an array is selected from a class, the type qualifiers on the class +object (if any) are not preserved in the selected array. (In the normal +mode, any type qualifiers on the object are preserved in the element type +of the resultant array.)
      +
      +
    • +
    • +
      An identifier in a function is allowed to have the same name as a parameter +of the function. A warning is issued.
      +
      +
    • +
    • +
      An expression of type void may be supplied on the return statement in a +function with a void return type. A warning is issued.
      +
      +
    • +
    • +
      Cfront has a bug that causes a global identifier to be found when a member +of a class or one of its base classes should actually be found. This bug +is emulated in cfront compatibility mode but can be disabled by setting the +parameter CFRONT_GLOBAL_VS_MEMBER_NAME_LOOKUP_BUG to FALSE. A +warning is issued when, because of this feature, a nonstandard lookup is +performed.
      +

      +
      The following conditions must be satisfied for the nonstandard lookup to be +performed:
      +
      +
        +
      • +
        A member in a base class must have the same name as an identifier at the +global scope. The member may be a function, static data member, or +nonstatic data member. Member type names don’t apply because a nested +type will be promoted to the global scope by cfront which disallows a +later declaration of a type with the same name at the global scope.
        +
        +
      • +
      • +
        The declaration of the global scope name must occur between the +declaration of the derived class and the declaration of an out-of-line +constructor or destructor. The global scope name must be a type name.
        +
        +
      • +
      • +
        No other member function definition – even one for an unrelated class +– may appear between the destructor and the offending reference. +This has the effect that the nonstandard lookup applies to only one +class at any given point in time. For example:
        +
        +
        struct B {
        +  void func(const char*);
        +};
        +struct D : public B {
        +public:
        +  D();
        +  void Init(const char* );
        +};
        +struct func {
        +  func( const char* msg);
        +};
        +D::D(){}
        +void D::Init(const char* t){
        +  // Should call B::func --  calls func::func instead.
        +  new func(t);
        +}
        +
        +
        +
      • +
      +
      +
      The global scope name must be present in a base class (B::func in this +example) for the nonstandard lookup to occur. Even if the derived class +were to have a member named func, it is still the presence of +B::func that determines how the lookup will be performed.
      +
      +
    • +
    • +
      A parameter of type “const void *” is allowed on operator delete; +it is treated as equivalent to “void *”.
      +
      +
    • +
    • +
      A period (”.”) may be used for qualification where “::” should be +used. Only “::” may be used as a global qualifier. Except for the +global qualifier, the two kinds of qualifier operators may not be mixed in +a given name (i.e., you may say A::B::C or A.B.C but not A::B.C +or A.B::C). A period may not be used in a vacuous destructor reference +nor in a qualifier that follows a template reference such as A<T>::B.
      +
      +
    • +
    • +
      Cfront 2.1 does not correctly look up names in friend functions that are +inside class definitions. In this example function f should refer to the +functions and variables (e.g., f1 and a1) from the class +declaration. Instead, the global definitions are used.
      +
      +
      int a1;
      +int e1;
      +void f1();
      +class A {
      +  int a1;
      +  void f1();
      +  friend void f()  {
      +    int i1 = a1;   // cfront uses global a1
      +    f1();          // cfront uses global f1
      +  }
      +};
      +
      +
      +
      +
      Only the innermost class scope is (incorrectly) skipped by cfront +as illustrated in the following example.
      +
      +
      int a1;
      +int b1;
      +struct A {
      +  static int a1;
      +  class B {
      +    static int b1;
      +    friend void f() {
      +      int i1 = a1;  // cfront uses A::a1
      +      int j1 = b1;  // cfront uses global b1
      +    }
      +  };
      +};
      +
      +
      +
    • +
    • +
      operator= may be declared as a nonmember function. (This is flagged as +an anachronism by cfront 2.1)
      +
      +
    • +
    • +
      A type qualifier is allowed (but ignored) on the declaration of a +constructor or destructor. For example:
      +
      +
      class A {
      +  A() const;   // No error in cfront 2.1 mode
      +};
      +
      +
      +
    • +
    • +
      The preprocessing symbol c_plusplus is defined in addition to the +standard __cplusplus.
      +
      +
    • +
    +
    +
    +

    2.9.10. Extensions Accepted in Cfront 2.1 and 3.0 Compatibility Mode#

    +

    The following extensions are accepted in both cfront 2.1 and cfront 3.0 +compatibility mode (i.e., these are features or problems that exist in both +cfront 2.1 and 3.0):

    +
      +
    • +
      Type qualifiers on the this parameter may be dropped in contexts +such as this example:
      +
      +
      struct A {
      +  void f() const;
      +};
      +void (A::*fp)() = &A::f;
      +
      +
      +
      +
      This is actually a safe operation. A pointer to a const function may +be put into a pointer to non-const, because a call using the pointer is +permitted to modify the object and the function pointed to will actually +not modify the object. The opposite assignment would not be safe.
      +
      +
    • +
    • +
      Conversion operators specifying conversion to void are allowed.
      +
      +
    • +
    • +
      A nonstandard friend declaration may introduce a new type. A friend +declaration that omits the elaborated type specifier is allowed in default +mode, but in cfront mode the declaration is also allowed to introduce a new +type name.
      +
      +
      struct A {
      +   friend B;
      +};
      +
      +
      +
    • +
    • +
      The third operand of the ? operator is a conditional expression instead +of an assignment expression as it is in the modern language.
      +
      +
    • +
    • +
      A reference to a pointer type may be initialized from a pointer value +without use of a temporary even when the reference pointer type has +additional type qualifiers above those present in the pointer value. For +example,
      +
      +
      int *p;
      +const int *&r = p;  // No temporary used
      +
      +
      +
    • +
    • +
      A reference may be initialized with a null.
      +
      +
    • +
    • +
      Because cfront does not check the accessibility of types, access errors for +types are issued as warnings instead of errors.
      +
      +
    • +
    • +
      When matching arguments of an overloaded function, a const variable +with value zero is not considered to be a null pointer constant. In +general, in overload resolution a null pointer constant must be spelled +“0” to be considered a null pointer constant (e.g., '\0' is not +considered a null pointer constant).
      +
      +
    • +
    • +
      Inside the definition of a class type, the qualifier in the declarator for +a member declaration is dropped if that qualifier names the class being +defined.
      +
      +
      struct S {
      +  void S::f(); // No warning in cfront mode
      +};
      +
      +
      +
    • +
    • +
      An alternate form of declaring pointer-to-member-function variables is +supported, namely:
      +
      +
      struct A {
      +  void f(int);
      +  static void sf(int);
      +  typedef void A::T3(int);  // nonstd typedef decl
      +  typedef void T2(int);     // std typedef
      +};
      +typedef void A::T(int);   // nonstd typedef decl
      +T* pmf = &A::f;           // nonstd ptr-to-member decl
      +A::T2* pf = A::sf;        // std ptr to static mem decl
      +A::T3* pmf2 = &A::f;      // nonstd ptr-to-member decl
      +
      +
      +
      +
      where T is construed to name a routine type for a nonstatic member +function of class A that takes an int argument and returns +void; the use of such types is restricted to nonstandard +pointer-to-member declarations. The declarations of T and pmf in +combination are equivalent to a single standard pointer-to-member +declaration:
      +
      +
      void (A::* pmf)(int) = &A::f;
      +
      +
      +
      +
      A nonstandard pointer-to-member declaration that appears outside of a class +declaration, such as the declaration of T, is normally invalid and +would cause an error to be issued. However, for declarations that appear +within a class declaration, such as A::T3, this feature changes the +meaning of a valid declaration. cfront version 2.1 accepts declarations, +such as T, even when A is an incomplete type; so this case is also +excepted.
      +
      +
    • +
    • +
      Protected member access checking is not done when the address of a +protected member is taken. For example:
      +
      +
      class B { protected: int i; };
      +class D : public B { void mf(); };
      +void D::mf() {
      +  int B::* pmi1 = &B::i;  // error, OK in cfront mode
      +  int D::* pmi2 = &D::i;  // OK
      +}
      +
      +
      +
      +
      Note that protected member access checking for other operations (i.e., +everything except taking a pointer-to-member address) is done in the normal +manner.
      +
      +
    • +
    • +
      The destructor of a derived class may implicitly call the private +destructor of a base class. In default mode this is an error but in cfront +mode it is reduced to a warning. For example:
      +
      +
      class A {
      +  ~A();
      +};
      +class B : public A {
      +  ~B();
      +};
      +B::~B(){}      // Error except in cfront mode
      +
      +
      +
    • +
    • +
      When disambiguation requires deciding whether something is a parameter +declaration or an argument expression, the pattern type-name-or-keyword(identifier… ) is treated as an argument. For example:
      +
      +
      class A {
      +  A();
      +};
      +double d;
      +A x(int(d));
      +A(x2);
      +
      +
      +
      +
      By default int(d) is interpreted as a parameter declaration (with +redundant parentheses), and so x is a function; but in +cfront-compatibility mode int(d) is an argument and x is a +variable.
      +
      The declaration A(x2); is also misinterpreted by cfront. It should be +interpreted as the declaration of an object named x2, but in cfront +mode is interpreted as a function style cast of x2 to the type A.
      +
      Similarly, the declaration
      +
      +
      int xyz(int());
      +
      +
      +
      +
      declares a function named xyz, that takes a parameter of type “function +taking no arguments and returning an int.” In cfront mode this is +interpreted as a declaration of an object that is initialized with the +value int() (which evaluates to zero).
      +
      +
    • +
    • +
      A named bit-field may have a size of zero. The declaration is treated as +though no name had been declared.
      +
      +
    • +
    • +
      Plain bit fields (i.e., bit fields declared with a type of int) are +always unsigned.
      +
      +
    • +
    • +
      The name given in an elaborated type specifier is permitted to be a +typedef name that is the synonym for a class name, e.g.,
      +
      +
      typedef class A T;
      +class T *pa;   // No error in cfront mode
      +
      +
      +
    • +
    • +
      No warning is issued on duplicate size and sign specifiers.
      +
      +
      short short int i;    // No warning in cfront mode
      +
      +
      +
    • +
    • +
      An extra comma is allowed after the last argument in an argument list, as +for example in
      +
      +
      f(1, 2, );
      +
      +
      +
    • +
    • +
      A constant pointer-to-member-function may be cast to a pointer-to-function. +A warning is issued.
      +
      +
      struct A {
      +  int f();
      +};
      +main () {
      +  int (*p)();
      +  p = (int (*)())A::f;  // Okay, with warning
      +}
      +
      +
      +
    • +
    • +
      Arguments of class types that allow bitwise copy construction but also have +destructors are passed by value (i.e., like C structures), and the +destructor is not called on the “copy.” In normal mode, the class object is +copied into a temporary, the address of the temporary is passed as the +argument, and the destructor is called on the temporary after the call +returns. Note that because the argument is passed differently (by value +instead of by address), code like this compiled in cfront mode is not +calling-sequence compatible with the same code compiled in normal mode. In +practice, this is not much of a problem, since classes that allow bitwise +copying usually do not have destructors.
      +
      +
    • +
    • +
      A union member may be declared to have the type of a class for which the +user has defined an assignment operator (as long as the class has no +constructor or destructor). A warning is issued.
      +
      +
    • +
    • +
      When an unnamed class appears in a typedef declaration, the typedef +name may appear as the class name in an elaborated type specifier.
      +
      +
      typedef struct {
      + int i, j;
      +} S;
      +struct S x;     // No error in cfront mode
      +
      +
      +
    • +
    • +
      Two member functions may be declared with the same parameter types when one +is static and the other is nonstatic with a function qualifier.
      +
      +
      class A {
      +  void f(int) const;
      +  static void f(int);     // No error in cfront mode
      +};
      +
      +
      +
    • +
    • +
      The scope of a variable declared in the for-init-statement is the scope +to which the for statement belongs.
      +
      +
      int f(int i) {
      +  for (int j = 0; j < i; ++j) { /* ... */ }
      +  return j;     // No error in cfront mode
      +}
      +
      +
      +
    • +
    • +
      Function types differing only in that one is declared extern "C" and +the other extern "C++" can be treated as identical:
      +
      +
      typedef void (*PF)();
      +extern "C" typedef void (*PCF)();
      +void f(PF);
      +void f(PCF);
      +
      +
      +
      +
      When DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT is FALSE, PF and +PCF are considered identical and void f(PCF) is treated as a +compatible redeclaration of f. (By contrast, in standard C++``PF`` and +PCF are different and incompatible types – PF is a pointer to an +extern "C++" function whereas PCF is a pointer to an extern "C" +function – and the two declarations of f create an overload set.)
      +

      +
      However, even if DEFAULT_C_AND_CPP_FUNCTION_TYPES_ARE_DISTINCT is TRUE, +it is possible to set +IMPL_CONV_BETWEEN_C_AND_CPP_FUNCTION_PTRS_POSSIBLE to TRUE as well, so +that in cfront-compatibility mode an implicit type conversion will always +be done between a pointer to an extern "C" function and a pointer to an +extern "C++``”`` function.
      +
      +
    • +
    • +
      Functions declared inline have internal linkage.
      +
      +
    • +
    • +
      enum types are regarded as integral types.
      +
      +
    • +
    • +
      An uninitialized const object of non-POD class type is allowed even if +its default constructor is implicitly declared:
      +
      +
      struct A { virtual void f(); int i; };
      +const A a;
      +
      +
      +
    • +
    • +
      A function parameter type is allowed to involve a pointer or reference to +array of unknown bounds.
      +
      +
    • +
    • +
      If the user declares an operator= function in a class, but not one that +can serve as the default operator=, and bitwise assignment could be +done on the class, a default operator= is not generated; only the +user-written operator= functions are considered for assignments (and +therefore bitwise assignment is not done).
      +
      +
    • +
    • +
      A member function declaration whose return type is omitted (and thus +implicitly int) and whose name is found to be that of a type is +accepted if it takes no parameters:
      +
      +
      typedef int I;
      +struct S {
      +  I();    // Accepted in cfront mode (declares "int S::I()")
      +  I(int); // Not accepted
      +};
      +
      +
      +
    • +
    • +
      Default arguments are retained as part of deduced function types.
      +
      +
    • +
    +
    +
    +
    +

    2.10. C Dialect Accepted#

    +

    The front end accepts the ANSI/ISO C language as defined by ANSI/ISO +9899:1990. In C99 mode, it accepts the ANSI/ISO C language defined by +ISO/IEC 9899:1999 as modified by Technical Corrigenda 1 through 3. In C11 +mode, it accepts the C language defined by ISO/IEC 9899:2011 and in C18 +mode the language defined by ISO/IEC 9899:2018 (which only differs from C11 +in minor ways). In C23 mode, many of the features of the latest standard +have been implemented. See the EDG web site for up-to-date information about +feature implementation.

    +

    When Embedded C extensions are enabled, the front end can accept the constructs +described in ISO/IEC TR 18037 (fixed-point types, named address space +qualifiers, and named-register storage class specifiers).

    +

    The front end extensively emulates the C modes of the Microsoft, GNU, and clang +compilers. See GNU C++ Mode. As with C++ mode, only one emulation mode may +be in effect for a given compilation. The --ms_extensions and +--ms_compatibility options can be used to emulate certain Microsoft +behaviors irrespective of the emulation mode.

    +

    There is no Sun C mode corresponding to Sun C++ mode, however.

    +

    The special comments recognized by the UNIX lint program – +/*ARGSUSED*/, /*VARARGS*/ (with or without a count of non-varying +arguments), and /*NOTREACHED*/ – are also recognized by the front end.

    +

    When Unified Parallel C (UPC) mode is enabled, it also accepts the core +language extensions described in version 1.0 of the UPC Language +Specifications).

    +
    +

    2.10.1. C99 Features Available in Other Modes#

    +

    Certain C language features were added in the C99 version of the ISO C standard +and are supported in C99 mode. For a full list of those features, see ISO/IEC +9899:1999. A few features are noteworthy, however, because they are +implementation-specific or because they can be enabled in older C modes or +(when indicated) in C++ mode:

    +
      +
    • +
      The options --variadic_macros, --no_variadic_macros, +--extended_variadic_macros and --no_extended_variadic_macros +control whether macros taking a variable number of arguments are +recognized. Configuration flags are available to select the default +setting of these options; these are also available in C++ mode.
      +
      Ordinary variadic macros (as included in C99) are illustrated by the +following example:
      +
      +
      #define OVM(x, ...) x(__VA_ARGS__)
      +void f() { OVM(printf, "%s %d\n", "Three args for ", 1); }
      +/* Expands to: printf("%s %d\n", "Three args for ", 1) */
      +
      +
      +
      +
      During expansion the special identifier __VA_ARGS__ will be replaced by +the trailing arguments of the macro invocation. If variadic macros are +enabled, this special identifier can appear only in the replacement list of +variadic macros.
      +
      Extended variadic macros (as implemented by certain pre-C99 compilers) use +a slightly different syntax and allow the name of the variadic parameter to +be chosen (instead of .../__VA_ARGS__):
      +
      +
      #define EVM(x, args...) x(args)
      +void f() { EVM(printf, "%s %d\n", "Three args for ", 1); }
      +/* Same expansion as previous example. */
      +
      +
      +
      +
      In addition, enabling extended variadic macros adds a special behavior to +the token pasting operator ## when it is followed by an empty or omitted +macro argument: A preceding comma (possibly followed by white space) is +erased. Hence,
      +
      +
      #define EVM2(fmt, args) printf(fmt , ## args)
      +EVM2("Hello World\n")
      +
      +
      +
      +
      expands to printf("Hello World\n") and the extraneous comma is erased.
      +
      +
    • +
    • +
      If the LONG_LONG_ALLOWED switch is TRUE,
      +
      +
        +
      • +
        the long long and unsigned long long types are accepted;
        +
        +
      • +
      • +
        integer constants suffixed by LL are given the type long long, +and those suffixed by ULL are given the type unsigned long long +(any of the suffix letters may be written in lower case);
        +
        +
      • +
      • +
        the specifier %lld is recognized in printf and scanf +formatting strings; and
        +
        +
      • +
      • +
        the long long types are accommodated in the usual arithmetic +conversions.
        +
        +
      • +
      +
    • +
    • +
      restrict may be used as a type qualifier for object pointer types and +function parameter arrays that decay to pointers. Its presence is recorded +in the IL so that back ends can perform optimizations that would otherwise +be prevented because of possible aliasing. The keyword is enabled by +--restrict; this is also available in C++.
      +
      +
    • +
    • +
      If VLA_ALLOWED is TRUE, variable length arrays (VLAs) are supported. +VLA types may appear only in the declaration of an identifier that belongs +to a block or function-prototype scope. For example:
      +
      +
      void addscalar(int n, int m, double a[n][m], double x) {
      +  int i, j;
      +  for (i=0; i<n; i++)
      +    for (j=0; j<m, j++)
      +      a[i][j] += x;
      +        /* a refers to a VLA with n*m elements. */
      +}
      +double A[4][8];
      +void f() {
      +  addscalar(4, 8, A, 3.14);
      +}
      +
      +
      +
      +
      See also command line options --vla and --no_vla.
      +
      +
    • +
    • +
      When DESIGNATED_INITIALIZER_ENABLING_POSSIBLE is TRUE, designators may +be accepted in initializers for aggregates. Designators are not allowed in +C++ mode, however. The global variables designators_allowed and +extended_designators_allowed are controlled by configuration flags and +command line options. In turn they control which variety (if any) of +designators is recognized. See also command line options +--designators, --no_designators, --extended_designators and +--no_extended_designators.
      +
      When designators_allowed is TRUE, designators of the forms .x and +[k] are accepted. They can be concatenated to reach nested aggregate +elements. For example:
      +
      +
      struct X { double a; int b[10] } x
      +                        = { .b = { 1, [5] = 2 }, .b[3] = 1, .a = 42.0 };
      +
      +
      +
      +
      In addition, when extended_designators_allowed is TRUE, designators of +the form x: and [m ...  n] are accepted and the assignment (=) +token becomes optional after array element designators. Field designators +of the form x: cannot immediately be followed by an assignment token +(=) or another designator. Examples:
      +
      +
      struct X { double a; int b[10] } x
      +                        = { b: { 1, [5 ... 9] = 2 }, .b[7] 1, a: 42.0 };
      +struct Y y = { b:[3] /* Error */ = 7, a: = /* Error */ 42.0 };
      +
      +
      +
      +
      Designators permit multiple initializations of the same subobject: only the +last value is retained, but side-effects of prior initializing expressions +do occur.
      +
      +
    • +
    • +
      Compound literals are supported in expressions. For example,
      +
      +
      int *p = (int []){1, 2, 3};
      +
      +
      +
      +
      creates an unnamed lvalue of type int[3] initialized as indicated. +p is initialized to point to that array. Compound literals are not +allowed in C++ mode.
      +
      +
    • +
    • +
      The __generic pseudo-macro is implemented. This is an EDG extension +used to support the type-generic math header <tgmath.h>. The form of +the macro reference is:
      +
      +
      __generic(x, y, z, func_d, func_f, func_l, func_cd, func_cf, func_cl)
      +
      +
      +
      +
      where x and the optional y and z are the arguments with which a +type-generic function is called, and the remaining 6 arguments are the +names of functions from which is selected the actual function to be called. +The suffixes with which the function names are supplied here correspond to +function parameter types of double, float, long double, +double _Complex, float _Complex, and long double _Complex, +respectively. The order is fixed. Function names may be omitted. For +example, <tgmath.h> may have the following macros defined:
      +
      +
      #define sin(x)  __generic(x,,,  sin, sinf, sinl, csin, csinf,csinl)(x)
      +#define fmax(x,y) __generic(x, y,,fmax, fmaxf, fmaxl,,,)(x, y)
      +#define conjg(x)  __generic(x,,,  ,,, conjg, conjgf, conjgl)(x)
      +
      +
      +
      +
      Note that sin and conjg take only one argument, that fmax has +no forms that accept complex arguments, and that conjg has no forms +that accept real arguments.
      +
      There is also a __genericfx pseudo-macro that provides a similar +capability for fixed-point types. The form of the macro reference is:
      +
      +
      __genericfx(x, fnc_hr, fnc_uhr, fnc_r, fnc_ur, fnc_lr, fnc_ulr,
      +              fnc_hk, fnc_uhk, fnc_k, fnc_uk, fnc_lk, fnc_ulk)
      +
      +
      +
      +
      where x is as above and the remaining 12 arguments are the names of +functions, with the suffixes corresponding to function parameter types of +short_Fract, unsignedshort_Fract, _Fract, +unsigned_Fract, long_Fract, unsignedlong_Fract, short_Accum, unsignedshort_Accum, +_Accum, unsigned _Accum, long_Accum, unsignedlong_Accum, respectively.
      +
      +
    • +
    • +
      The keywords __I__, __NAN__, and __INFINITY__ are defined as, +respectively, a float _Imaginary i, a float Not-a-Number, and a float +positive Infinity. These are intended to be used by library writers to +implement the C99 macros I, NAN, and INFINITY. __NAN__ and +__INFINITY__ are also available in all modes, not just C99 mode.
      +
      +
    • +
    • +
      A trailing array member of unspecified length in a struct type is called a +flexible array member. Such members are a standard feature in C99. In +default C99 mode (but not in strict C99 mode) trailing struct members can +also have a type containing a flexible array member. For example:
      +
      +
      struct F {
      +  int i;
      +  int f[];  // OK in default and strict C99 modes
      +};
      +struct X {
      +  F x;  // OK in default C99 mode (but not in strict mode)
      +};
      +
      +
      +
    • +
    +
    +
    +

    2.10.2. ANSI C Extensions#

    +

    The following extensions are accepted (these are flagged if the -A or +-a option is specified):

    +
      +
    • +
      A translation unit (input file) can contain no declarations.
      +
      +
    • +
    • +
      Comment text can appear at the ends of preprocessing directives.
      +
      +
    • +
    • +
      __ALIGNOF__ (or __alignof__) is similar to sizeof, but returns +the alignment requirement value for a type, or 1 if there is no +alignment requirement. It may be followed by a type or expression in +parentheses:
      +
      +
      +

      __ALIGNOF__(type)        __alignof__(type)

      +

      __ALIGNOF__(expression)  __alignof__(expression)

      +
      +
      +
      The expression in the second form is not evaluated.
      +
      +
    • +
    • +
      __INTADDR__(expression) scans the enclosed expression as a +constant expression, and converts it to an integer constant (it is used in +the offsetof macro).
      +
      +
    • +
    • +
      A number of “type traits pseudo-functions” (taking one or more type +names) are accepted: __has_nothrow_assign, +__has_nothrow_constructor, __has_nothrow_copy, +__has_nothrow_move_assign, __has_trivial_assign, +__has_trivial_constructor, __has_trivial_copy, +__has_trivial_destructor, __has_trivial_move_assign, +__has_trivial_move_constructor, __has_virtual_destructor, +__is_abstract, __is_base_of, __is_class, +__is_constructible, __is_convertible_to, __is_destructible, +__is_empty, __is_enum, __is_literal_type, +__is_nothrow_assignable, __is_nothrow_constructible, +__is_nothrow_destructible, __is_pod, __is_polymorphic, +__is_standard_layout, __is_trivial, +__is_trivially_assignable, __is_trivially_constructible, +__is_trivially_copyable, __is_trivially_destructible, and +__is_union.
      +
      +
      double x[__is_union(union U)];  // Okay.
      +
      +
      +
      +
      These are silently accepted even in strict modes. They ease the +implementation C++11 metaprogramming templates (many of which were first +introduced by ISO/IEC TR 19768).
      +
      +
    • +
    • +
      Bit fields may have base types that are enums or integral types +besides int and unsigned int. This matches A.6.5.8 in the ANSI +Common Extensions appendix.
      +
      +
    • +
    • +
      If the ADDR_OF_BIT_FIELD_ALLOWED flag is TRUE, the address of a bit +field may be taken if the bit field has the same size and alignment as one +of the integral types. A warning is issued.
      +
      +
    • +
    • +
      The last member of a struct may have an incomplete array type. It may +not be the only member of the struct (otherwise, the struct would have zero +size).
      +
      +
    • +
    • +
      A file-scope array may have an incomplete struct, union, or +enum type as its element type. The type must be completed before the +array is subscripted (if it is), and by the end of the compilation if the +array is not extern. In C++, an incomplete class is also allowed.
      +
      +
    • +
    • +
      Static functions may be declared in function and block scopes. Their +declarations are moved to the file scope.
      +
      +
    • +
    • +
      enum tags may be incomplete: one may define the tag name and resolve it +(by specifying the brace-enclosed list) later.
      +
      +
    • +
    • +
      The values of enumeration constants may be given by expressions that +evaluate to unsigned quantities that fit in the unsigned int range but +not in the int range. A warning is issued for suspicious cases.
      +
      +
      /* When ints are 32 bits: */
      +enum a {w = -2147483648};  /* No warning */
      +enum b {x = 0x80000000};   /* No warning */
      +enum c {y = 0x80000001};   /* No warning */
      +enum d {z = 2147483649};   /* Warning */
      +
      +
      +
    • +
    • +
      An extra comma is allowed at the end of an enum list. A remark is +issued except in pcc mode.
      +
      +
    • +
    • +
      The final semicolon preceding the closing } of a struct or union +specifier may be omitted. A warning is issued except in pcc mode.
      +
      +
    • +
    • +
      A label definition may be immediately followed by a right brace. +(Normally, a statement must follow a label definition.) A warning is +issued.
      +
      +
    • +
    • +
      An empty declaration (a semicolon with nothing before it) is allowed. A +remark is issued.
      +
      +
    • +
    • +
      An initializer expression that is a single value and is used to initialize +an entire static array, struct, or union need not be enclosed in braces. +ANSI C requires the braces.
      +
      +
    • +
    • +
      In an initializer, a pointer constant value may be cast to an integral type +if the integral type is big enough to contain it.
      +
      +
    • +
    • +
      The address of a variable with register storage class may be taken. A +warning is issued.
      +
      +
    • +
    • +
      In an integral constant expression, an integer constant may be cast to a +pointer type and then back to an integral type.
      +
      +
    • +
    • +
      long float is accepted as a synonym for double.
      +
      +
    • +
    • +
      If PTR_TO_INCOMP_ARRAY_ARITHMETIC_ALLOWED is TRUE, pointers to +incomplete arrays may be used in pointer addition, subtraction, and +subscripting:
      +
      +
      int (*p)[];
      +...
      +q = p[0];
      +
      +
      +
      +
      A warning is issued if the value added or subtracted is anything other than +a constant zero. Since the type pointed to by the pointer has zero size, +the value added to or subtracted from the pointer is multiplied by zero and +therefore has no effect on the result.
      +
      +
    • +
    • +
      Benign redeclarations of typedef names are allowed. That is, a typedef +name may be redeclared in the same scope as the same type. A warning is +issued.
      +
      +
    • +
    • +
      Dollar signs can be accepted in identifiers through use of a command line +option or by setting a configuration parameter. The default is to not +allow dollar signs in identifiers.
      +
      +
    • +
    • +
      Numbers are scanned according to the syntax for numbers rather than the +pp-number syntax. Thus, 0x123e+1 is scanned as three tokens +instead of one invalid token. (If the -A or -a option is +specified, of course, the pp-number syntax is used.)
      +
      +
    • +
    • +
      Assignment and pointer difference are allowed between pointers to types +that are interchangeable but not identical, for example, unsigned char +* and char *. This includes pointers to same-sized integral types +(e.g., typically, int * and long *). A warning is issued except in +pcc mode. Assignment of a string constant to a pointer to any kind of +character is allowed without a warning.
      +
      +
    • +
    • +
      Assignment of pointer types is allowed in cases where the destination type +has added type qualifiers that are not at the top level (e.g., int ** +to const int **). Comparisons and pointer difference of such pairs of +pointer types are also allowed. A warning is issued.
      +
      +
    • +
    • +
      In operations on pointers, a pointer to void is always implicitly +converted to another type if necessary, and a null pointer constant is +always implicitly converted to a null pointer of the right type if +necessary. In ANSI C, some operators allow such things, and others +(generally, where it does not make sense) do not allow them.
      +
      +
    • +
    • +
      Pointers to different function types may be assigned or compared for +equality (==) or inequality (!=) without an explicit type cast. A +warning is issued. This extension is not allowed in C++ mode.
      +
      +
    • +
    • +
      A pointer to void may be implicitly converted to or from a pointer to a +function type.
      +
      +
    • +
    • +
      If the ATT_PREPROCESSING_EXTENSIONS_ALLOWED switch is TRUE, the +#assert preprocessing extensions of AT&T System V release 4 are +allowed. These allow definition and testing of predicate names. Such +names are in a name space distinct from all other names, including macro +names. A predicate name is given a definition by a preprocessing directive +of the form
      +
      +
      +
      +
      #assert name
      +
      #assert name(token-sequence)
      +
      +
      +
      +
      which defines the predicate name. In the first form, the predicate +is not given a value. In the second form, it is given the value +token-sequence. Such a predicate can be tested in a #if +expression, as follows:
      +
      +
      +
      +
      #name(token-sequence)
      +
      +
      +
      +
      which has the value 1 if a #assert of that name with that +token-sequence has appeared, and 0 otherwise. A given predicate may be +given more than one value at a given time.
      +
      +
      +
      A predicate may be deleted by a preprocessing directive of the form
      +
      +
      +
      +
      #unassert name
      +
      #unassert name(token-sequence)
      +
      +
      +
      +
      The first form removes all definitions of the indicated predicate name; the +second form removes just the indicated definition, leaving any others there +may be.
      +
      +
    • +
    • +
      GNU line directive flags are accepted on #line directives. The system +header flag is recognized, and the associated code is treated as if found +in a system include directory.
      +
      +
    • +
    • +
      asm statements and declarations are accepted. This is disabled in +strict ANSI C mode (-A or -a and -m options) since it conflicts +with the ANSI C standard for something like
      +
      +
      asm("xyz");
      +
      +
      +
      +
      which ANSI C interprets as a call of an implicitly-defined function asm +and which by default the front end interprets as an asm statement.
      +
      +
    • +
    • +
      When ASM_FUNCTION_ALLOWED is TRUE, asm functions are accepted, and +__asm is recognized as a synonym for asm. An asm function body +is represented in the IL by an uninterpreted null-terminated string +containing the text that appears in the source (including the text of +source comments when INCLUDE_COMMENTS_IN_ASM_FUNC_BODY is TRUE). An +asm function must be declared with no storage class, with a prototyped +parameter list, and with no omitted parameters:
      +
      +
      asm void f(int,int) {
      +  ...
      +}
      +
      +
      +
      +
      If asm functions are recognized and the C-generating back end is used, +it is required that ANSI-C be generated, not K&R C, because the asm +function must be put out with a prototyped parameter list.
      +
      +
    • +
    • +
      If ALLOW_NONSTANDARD_ANONYMOUS_UNIONS is TRUE, an extension is +supported to allow constructs similar to C++ anonymous unions, including +the following:
      +
      +
        +
      • +
        not only anonymous unions but also anonymous structs are allowed – that +is, their members are promoted to the scope of the containing struct and +looked up like ordinary members;
        +
        +
      • +
      • +
        they can be introduced into the containing struct by a typedef name +– they needn’t be declared directly, as with true anonymous unions; and
        +
        +
      • +
      • +
        a tag may be declared (C mode only).
        +
        +
      • +
      +
      +
      Among the restrictions: the extension only applies to constructs within +structs.
      +
      +
    • +
    • +
      If DEFAULT_ADDRESS_OF_ELLIPSIS_ALLOWED is TRUE, the expression &... +is accepted in the body of a function in which an ellipsis appears in the +parameter list. It is needed to support some versions of macro +va_start in stdarg.h.
      +
      +
    • +
    • +
      If DEFAULT_ALLOW_ELLIPSIS_ONLY_PARAM_IN_C_MODE is TRUE, an ellipsis may +appear by itself in the parameter list of a function declaration – e.g., +f(...). A diagnostic is issued in strict ANSI C mode.
      +
      +
    • +
    • +
      External entities declared in other scopes are visible. A warning is +issued.
      +
      +
      void f1(void) { extern void f(); }
      +void f2() {
      +  f(); /* Using out of scope declaration */
      +}
      +
      +
      +
    • +
    • +
      A non-lvalue array expression is converted to a pointer to the first +element of the array when it is subscripted or similarly used.
      +
      +
    • +
    • +
      The nonstandard preprocessing directive #include_next is supported. +This is a variant of the #include directive. It searches for the named +file only in the directories on the search path that follow the directory +in which the current source file (the one containing the #include_next +directive) is found. (This is an extension found in the GNU C compiler.)
      +
      +
    • +
    • +
      The nonstandard preprocessing directive #warning is supported. It is +similar to the #error directive, but results in a warning instead of a +catastrophic error when processed. This directive is not recognized in +strict mode. (This is an extension found in GNU C compilers.)
      +
      +
    • +
    +

    In the following areas considered “undefined behavior” by the ANSI C standard, +the front end does the following:

    +
      +
    • +
      Adjacent wide and non-wide string literals are not concatenated unless +wchar_t and char are the same type. (In C++ mode, when wchar_t +is a keyword, adjacent wide and non-wide string literals are never +concatenated.)
      +
      +
    • +
    • +
      In character and string escapes, if the character following the \ has +no special meaning, the value of the escape is the character itself. Thus +"\s" == "s". A warning is issued.
      +
      +
    • +
    • +
      A struct that has no named fields but at least one unnamed field is +accepted by default, but a diagnostic (a warning or error) is issued in +strict ANSI C mode.
      +
      +
    • +
    +
    +
    +

    2.10.3. K&R/pcc Mode#

    +

    When pcc mode is specified, the front end accepts the traditional C +language defined by The C Programming Language, first edition, by +Kernighan and Ritchie (K&R), Prentice-Hall, 1978. In addition, it provides +almost complete compatibility with the Reiser cpp and Johnson pcc +widely used as part of UNIX systems; since there is no documentation of the +exact behavior of those programs, complete compatibility cannot be +guaranteed.

    +

    In general, when compiling in pcc mode, the front end attempts to interpret +a source program that is valid to pcc in the same way that pcc would. +However, ANSI features that do not conflict with this behavior are not +disabled.

    +

    In some cases where pcc allows a highly questionable construct, the front +end will accept it but give a warning, where pcc would be silent (for +example: 0x, a degenerate hexadecimal number, is accepted as zero).

    +

    The known cases where the front end is not compatible with pcc are the +following:

    +
      +
    • +
      Token pasting is not done outside of macro expansions (i.e., in the primary +source line) when two tokens are separated only by a comment. That is, +a/**/b is not considered to be ab. The pcc behavior in that +case can be gotten by preprocessing to a text file and then compiling that +file.
      +

      +
      The textual output from preprocessing is also equivalent but not identical: +the blank lines and white space will not be exactly the same.
      +
      +
    • +
    • +
      pcc will consider the result of a ?: operator to be an lvalue if +the first operand is constant and the second and third operands are +compatible lvalues. This front end will not.
      +
      +
    • +
    • +
      pcc mis-parses the third operand of a ?: operator in a way that +some programs exploit:
      +
      +
      i ? j : k += l
      +
      +
      +
      +
      is parsed by pcc as
      +
      +
      i ? j : (k += l)
      +
      +
      +
      +
      which is not correct, since the precedence of += is lower than the +precedence of ?:. This front end will generate an error for that case.
      +
      +
    • +
    • +
      lint recognizes the keywords for its special comments anywhere in a +comment, regardless of whether or not they are preceded by other text in +the comment. The front end only recognizes the keywords when they are the +first identifier following an optional initial series of blanks and/or +horizontal tabs. lint also recognizes only a single digit of the +VARARGS count; the front end will accumulate as many digits as appear.
      +
      +
    • +
    +

    The differences in pcc mode relative to the default ANSI mode are as +follows:

    +
      +
    • +
      The keywords signed, const, and volatile are disabled, to avoid +problems with items declared with those names in old-style code. Those +keywords were ANSI C inventions. The other non-K&R keywords (enum and +void) are judged to have existed already in code and are not disabled.
      +
      +
    • +
    • +
      Declarations of the form
      +
      +
      typedef some-type void;
      +
      +
      +
      +
      are ignored.
      +
      +
    • +
    • +
      Assignment is allowed between pointers and integers, and between +incompatible pointer types, without an explicit cast. A warning is issued.
      +
      +
    • +
    • +
      A field selection of the form p->field is allowed even if +p does not point to a struct or union that contains field. +p must be a pointer or an integer. Likewise, x.field is +allowed even if x is not a struct or union that contains +field. x must be an lvalue. For both cases, all definitions of +field as a field must have the same offset within their struct or +union.
      +
      +
    • +
    • +
      If the configuration flag TARG_NO_ERROR_ON_INTEGER_OVERFLOW is TRUE, +overflows detected while folding signed integer operations on constants +will cause warnings rather than errors. Usually this should be set to +match the desired target machine behavior on integer operations in C.
      +
      +
    • +
    • +
      If the configuration flag SAME_REPR_INTS_INTERCHANGEABLE_IN_IL is TRUE, +integral types with the same representation (size, signedness, and +alignment) will be considered identical and may be used interchangeably. +For example, this means that int and long will be interchangeable +if they have the same size.
      +
      +
    • +
    • +
      A warning will be issued for a & applied to an array. The type of such +an operation is “address of array element” rather than “address of array”.
      +
      +
    • +
    • +
      For the shift operators << and >>, the usual arithmetic conversions +are done, the right operand is converted to int, and the result type is +the type of the left operand. In ANSI C, the integral promotions are done +on the two operands, and the result type is the type of the left operand. +The effect of this difference is that, in pcc mode, a long shift +count will force the shift to be done as long.
      +
      +
    • +
    • +
      When preprocessing output is generated, the line-identifying directives +will have the pcc form instead of the ANSI form.
      +
      +
    • +
    • +
      String literals will not be shared. Identical string literals will cause +multiple copies of the string to be allocated.
      +
      +
    • +
    • +
      sizeof may be applied to bit fields; the size is that of the underlying +type (e.g., unsigned int).
      +
      +
    • +
    • +
      lvalues cast to a type of the same size remain lvalues, except when they +involve a floating-point conversion.
      +
      +
    • +
    • +
      When a function parameter list begins with a typedef identifier, the +parameter list is considered prototyped only if the typedef identifier +is followed by something other than a comma or right parenthesis:
      +
      +
      typedef int t;
      +int f(t) {}     /* Old-style list */
      +int g(t x) {}   /* Prototyped list, parameter x of type t */
      +
      +
      +
      +
      That is, function parameters are allowed to have the same names as +typedefs. In the normal ANSI mode, of course, any parameter list +that begins with a typedef identifier is considered prototyped, so the +first example above would give an error.
      +
      +
    • +
    • +
      The names of functions and of external variables are always entered at the +file scope.
      +
      +
    • +
    • +
      A function declared static, used, and never defined is treated as if +its storage class were extern.
      +
      +
    • +
    • +
      A file-scope array that has an unspecified storage class and remains +incomplete at the end of the compilation will be treated as if its storage +class is extern (in ANSI mode, the number of elements is changed to 1, +and the storage class remains unspecified).
      +
      +
    • +
    • +
      The empty declaration
      +
      +
      +
      +
      struct x;
      +
      +
      +
      +
      will not hide an outer-scope declaration of the same tag.
      +
      +
    • +
    • +
      In a declaration of a member of a struct or union, no diagnostic is +issued for omitting the declarator list; nevertheless, such a declaration +has no effect on the layout. For example,
      +
      +
      struct s {char a; int; char b[2];} v;    /* sizeof(v) is 3 */
      +
      +
      +
    • +
    • +
      enums are always given type int. In ANSI mode, and depending on +the configuration flag enum_types_can_be_smaller_than_int, smaller +integral types will be used if possible.
      +
      +
    • +
    • +
      No warning is generated for a storage specifier appearing in other than the +first position in a list of specifiers (as in int static).
      +
      +
    • +
    • +
      short, long, and unsigned are treated as “adjectives” in type +specifiers, and they may be used to modify a typedef type.
      +
      +
    • +
    • +
      A “plain” char is considered to be the same as either signed char +or unsigned char, depending on the installation default and +command-line options. In ANSI C, “plain” char is a third type distinct +from both signed char and unsigned char.
      +
      +
    • +
    • +
      Free-standing tag declarations are allowed in the parameter declaration +list for a function with old-style parameters.
      +
      +
    • +
    • +
      float function parameters are promoted to double function +parameters.
      +
      +
    • +
    • +
      float functions are promoted to double functions.
      +
      +
    • +
    • +
      Declaration specifiers are allowed to be completely omitted in declarations +(ANSI C allows this only for function declarations). Thus
      +
      +
      i;
      +
      +
      +
      +
      declares i as an int variable. A warning is issued.
      +
      +
    • +
    • +
      The = preceding an initializer may be omitted. A warning is issued. +See K&R first edition, Appendix A, section 17 (anachronisms). This is +accepted only if C_ANACHRONISMS_ALLOWED is TRUE.
      +
      +
    • +
    • +
      All float operations are done as double.
      +
      +
    • +
    • +
      __STDC__ is left undefined.
      +
      +
    • +
    • +
      Extra spaces to prevent pasting of adjacent confusable tokens are not +generated in textual preprocessing output.
      +
      +
    • +
    • +
      The first directory searched for include files is the directory containing +the file containing the #include instead of the directory containing +the primary source file.
      +
      +
    • +
    • +
      Trigraphs are not recognized.
      +
      +
    • +
    • +
      Comments are deleted entirely (instead of being replaced by one space) in +preprocessing output.
      +
      +
    • +
    • +
      0x is accepted as a hexadecimal 0, with a warning.
      +
      +
    • +
    • +
      1E+ is accepted as a floating-point constant with an exponent of 0, +with a warning.
      +
      +
    • +
    • +
      The compound assignment operators may be written as two tokens (e.g., ++= may be written + =).
      +
      +
    • +
    • +
      The compound assignment operators may be written in their old-fashioned +reversed forms (e.g., -= may be written =-). A warning is issued. +This is described in K&R first edition, Appendix A, section 17 +(anachronisms). This is accepted only if C_ANACHRONISMS_ALLOWED is +TRUE.
      +
      +
    • +
    • +
      The digits 8 and 9 are allowed in octal constants.
      +
      +
    • +
    • +
      A warning rather than an error is issued for integer constants that are +larger than can be accommodated in an unsigned long. The value is +truncated to an acceptable number of low-order bits.
      +
      +
    • +
    • +
      The types of large integer constants are determined according to the K&R +rules (they won’t be unsigned in some cases where ANSI C would define +them that way). Integer constants with apparent values larger than +LONG_MAX are typed as long and are also marked as “non-arithmetic”, +which suppresses some warnings when using them.
      +
      +
    • +
    • +
      The escape \a (alert) is not recognized in character and string +constants.
      +
      +
    • +
    • +
      Macro expansion is done differently. Arguments to macros are not +macro-expanded before being inserted into the expansion of the macro. Any +macro invocations in the argument text are expanded when the macro +expansion is rescanned. With this method, macro recursion is possible and +is checked for.
      +
      +
    • +
    • +
      Token pasting inside macro expansions is done differently. End-of-token +markers are not maintained, so tokens that abut after macro substitution +may be parsed as a single token.
      +
      +
    • +
    • +
      Macro parameter names inside character and string constants are recognized +and substituted for.
      +
      +
    • +
    • +
      Macro invocations having too many arguments are flagged with a warning +rather than an error. The extra arguments are ignored.
      +
      +
    • +
    • +
      Macro invocations having too few arguments are flagged with a warning +rather than an error. A null string is used as the value of the missing +parameters.
      +
      +
    • +
    • +
      Extra #elses (after the first has appeared in an #if block) are +ignored, with a warning.
      +
      +
    • +
    • +
      Expressions in a switch statement are cast to int; this differs +from the ANSI C definition in that a long expression is (possibly) +truncated.
      +
      +
    • +
    • +
      The promotion rules for integers are different: unsigned char and +unsigned short are promoted to unsigned int.
      +
      +
    • +
    • +
      An identifier in a function is allowed to have the same name as a parameter +of the function. A warning is issued.
      +
      +
    • +
    +
    +
    +

    2.10.4. Extensions Accepted in SVR4 Compatibility Mode#

    +

    The following extensions are accepted in SVR4 C compatibility mode:

    +
      +
    • +
      Macro invocations having too many arguments are flagged with a warning +rather than an error. The extra arguments are ignored.
      +
      +
    • +
    • +
      Macro invocations having too few arguments are flagged with a warning +rather than an error. A null string is used as the value of the missing +parameters.
      +
      +
    • +
    • +
      The sequence /**/ in a macro definition is treated as equivalent to the +token-pasting operator ##.
      +
      +
    • +
    • +
      lvalues cast to a type of the same size remain lvalues, except when they +involve a floating-point conversion.
      +
      +
    • +
    • +
      Assignment is allowed between pointers and integers, and between +incompatible pointer types, without an explicit cast. A warning is issued.
      +
      +
    • +
    • +
      A field selection of the form p->field is allowed even if +p does not point to a struct or union that contains field. +p must be a pointer. Likewise, x.field is allowed even +if x is not a struct or union that contains field. x +must be an lvalue. For both cases, all definitions of field as a +field must have the same offset within their struct or union.
      +
      +
    • +
    • +
      In an integral constant expression, an integer constant may be cast to a +pointer type and then back to an integral type.
      +
      +
    • +
    • +
      Incompatible external object declarations are allowed if the object types +share the same underlying representation.
      +
      +
    • +
    • +
      Certain incompatible function declarations are allowed. A warning is +issued.
      +
      +
      typedef unsigned int size_t;
      +extern size_t strlen(const char *);
      +extern int strlen();  /* Warning */
      +
      +
      +
    • +
    +
    +
    +
    +

    2.11. Namespace Support#

    +

    Namespaces are enabled by default (see DEFAULT_NAMESPACES_ENABLED) except +in the cfront modes. The command-line options --namespaces and +--no_namespaces can be used to enable or disable the features.

    +

    When doing name lookup in a template instantiation, some names must be found in +the context of the template definition while others may also be found in the +context of the template instantiation. The front end implements two different +instantiation lookup algorithms: the one mandated by the standard (referred to +as “dependent name lookup”), and the one that existed before dependent name +lookup was implemented.

    +

    Dependent name lookup is done in strict mode (unless explicitly disabled by +another command-line option) or when dependent name processing is enabled by +either a configuration flag or command-line option.

    +
    +

    2.11.1. Dependent Name Processing#

    +

    When doing dependent name lookup, the front end implements the instantiation +name lookup rules specified in the standard. This processing requires that +nonclass prototype instantiations be done. This in turn requires that the code +be written using the typename and template keywords as required by the +standard.

    +
    +
    +

    2.11.2. Lookup Using the Referencing Context#

    +

    When not using dependent name lookup, the front end uses a name lookup +algorithm that approximates the two-phase lookup rule of the standard, but does +so in such a way that is more compatible with existing code and existing +compilers.

    +

    When a name is looked up as part of a template instantiation but is not found +in the local context of the instantiation, it is looked up in a synthesized +instantiation context that includes both names from the context of the template +definition and names from the context of the instantiation. Here’s an example:

    +
    namespace N {
    +  int g(int);
    +  int x = 0;
    +  template <class T> struct A {
    +    T f(T t) { return g(t); }
    +    T f() { return x; }
    +  };
    +}
    +namespace M {
    +  int x = 99;
    +  double g(double);
    +  N::A<int> ai;
    +  int i = ai.f(0);      // N::A<int>::f(int) calls N::g(int)
    +  int i2 = ai.f();      // N::A<int>::f() returns 0 (= N::x)
    +  N::A<double> ad;
    +  double d = ad.f(0);   // N::A<double>::f(double) calls M::g(double)
    +  double d2 = ad.f();   // N::A<double>::f() also returns 0 (= N::x)
    +}
    +
    +
    +

    The lookup of names in template instantiations does not conform to the rules in +the standard in the following respects:

    +
      +
    • +
      Although only names from the template definition context are considered for +names that are not functions, the lookup is not limited to those names +visible at the point at which the template was defined.
      +
      +
    • +
    • +
      Functions from the context in which the template was referenced are +considered for all function calls in the template. Functions from the +referencing context should only be visible for “dependent” function calls.
      +
      +
    • +
    +

    For details of the algorithm implemented, see the Symbol Table +chapter (in particular the Instantiation Context Lookup section).

    +
    +
    +

    2.11.3. Argument Dependent Lookup#

    +

    When argument-dependent lookup is enabled, functions made visible using +argument-dependent lookup overload with those made visible by normal lookup. +The standard requires that this overloading occur even when the name found by +normal lookup is a block extern declaration. The front end does this +overloading, but in default mode, argument-dependent lookup is suppressed when +the normal lookup finds a block extern.

    +

    This means a program can have different behavior, depending on whether it is +compiled with or without argument-dependent lookup, even if the program makes +no use of namespaces. For example:

    +
    struct A { };
    +A operator+(A, double);
    +void f() {
    +  A a1;
    +  A operator+(A, int);
    +  a1 + 1.0;     // calls operator+(A, double) with arg-dependent
    +                // lookup enabled but otherwise calls
    +                // operator+(A, int);
    +}
    +
    +
    +
    +
    +

    2.11.4. Runtime Support#

    +

    The headers and runtime provided with the EDG front end support two different +versions (i.e., with and without namespaces) under control of +__EDG_RUNTIME_USES_NAMESPACES, a preprocessing option defined by the front +end.

    +
    +
    +
    +

    2.12. Template Instantiation#

    +

    The C++ language includes the concept of templates. A template is a +description of a class or function that is a model for a family of related +classes or functions. [3] For example, one can write a template for a +Stack class, and then use a stack of integers, a stack of floats, and a +stack of some user-defined type. In the source, these might be written +Stack<int>, Stack<float>, and Stack<X>. From a single source +description of the template for a stack, the compiler can create +instantiations of the template for each of the types required.

    +

    The instantiation of a class template is always done as soon as it is needed in +a compilation. However, the instantiations of template functions, template +variables, member functions of template classes, and static data members of +template classes (hereafter referred to as template entities) are not +necessarily done immediately, for several reasons:

    +
      +
    • +
      One would like to end up with only one copy of each instantiated entity +across all the object files that make up a program. (This of course +applies to entities with external linkage.)
      +
      +
    • +
    • +
      The language allows one to write a specialization of a template entity, +i.e., a specific version to be used in place of a version generated from +the template for a specific data type. (One could, for example, write a +version of Stack<int>, or of just Stack<int>::push, that replaces +the template-generated version; often, such a specialization provides a +more efficient representation for a particular data type.) Since the +compiler cannot know, when compiling a reference to a template entity, if a +specialization for that entity will be provided in another compilation, it +cannot do the instantiation automatically in any source file that +references it. (The modern C++ language requires that a specialization be +declared in every compilation in which it is used, but for compatibility +with existing code and older compilers the EDG front end does not require +that in some modes. See the command-line option +--no_distinct_template_signatures.)
      +
      +
    • +
    • +
      C++ templates can be exported (i.e., declared with the keyword +export). Such templates can be used in a translation unit that does +not contain the definition of the template to instantiate. The +instantiation of such a template must be delayed until the template +definition has been found.
      +
      +
    • +
    • +
      The language also dictates that template functions that are not referenced +should not be compiled, that, in fact, such functions might contain +semantic errors that would prevent them from being compiled. Therefore, a +reference to a template class should not automatically instantiate all the +member functions of that class.
      +
      +
    • +
    +

    (It should be noted that certain template entities are always instantiated when +used, e.g., inline functions.)

    +

    From these requirements, one can see that if the compiler is responsible for +doing all the instantiations automatically, it can only do so on a program-wide +basis. That is, the compiler cannot make decisions about instantiation of +template entities until it has seen all the source files that make up a +complete program.

    +

    The EDG C++ front end provides an instantiation mechanism that does automatic +instantiation at link time. For cases where the programmer wants more explicit +control over instantiation, the front end also provides instantiation modes and +instantiation pragmas, which can be used to exert fine-grained control over the +instantiation process.

    +
    +

    2.12.1. Automatic Instantiation#

    +

    The goal of an automatic instantiation mode is to provide painless +instantiation. The programmer should be able to compile source files to object +code, then link them and run the resulting program, and never have to worry +about how the necessary instantiations get done.

    +

    In practice, this is hard for a compiler to do, and different compilers use +different automatic instantiation schemes with different strengths and +weaknesses:

    +
      +
    • +
      AT&T/USL/Novell/SCO’s cfront product saves information about each file it +compiles in a special directory called ptrepository. It instantiates +nothing during normal compilations. At link time, it looks for entities +that are referenced but not defined, and whose mangled names indicate that +they are template entities. For each such entity, it consults the +ptrepository information to find the file containing the source for the +entity, and it does a compilation of the source to generate an object file +containing object code for that entity. This object code for instantiated +objects is then combined with the “normal” object code in the link step.
      +

      +
      The programmer using cfront must follow a particular coding +convention: all templates must be declared in “.h” files, and for +each such file there must be a corresponding “.C” file containing +the associated definitions. The compiler is never told about the +“.C” files explicitly; one does not, for example, compile them in +the normal way. The link step looks for them when and if it needs +them, and does so by taking the “.h” file name and replacing its +suffix. [4]
      +

      +
      This scheme has the disadvantage that it does a separate compilation for +each instantiated function (or, at best, one compilation for all the member +functions of one class). Even though the function itself is often quite +small, it must be compiled along with the declarations for the types on +which the instantiation is based, and those declarations can easily run +into many thousands of lines. For large systems, these compilations can +take a very long time. The link step tries to be smart about recompiling +instantiations only when necessary, but because it keeps no fine-grained +dependency information, it is often forced to “recompile the world” for a +minor change in a “.h” file. In addition, cfront has no way of +ensuring that preprocessing symbols are set correctly when it does these +instantiation compilations, if preprocessing symbols are set other than on +the command line.
      +
      +
    • +
    • +
      Borland’s C++ compiler instantiates everything referenced in a compilation, +then uses a special linker to remove duplicate definitions of instantiated +functions.
      +

      +
      The programmer using Borland’s compiler must make sure that every +compilation sees all the source code it needs to instantiate all the +template entities referenced in that compilation. That is, one cannot +refer to a template entity in a source file if a definition for that entity +is not included by that source file. In practice, this means that either +all the definition code is put directly in the “.h” files, or that each +“.h” file includes an associated “.C” (actually, “.CPP”) file.
      +

      +
      This scheme is straightforward, and works well for small programs. For +large systems, however, it tends to produce very large object files, +because each object file must contain object code (and symbolic debugging +information) for each template entity it references.
      +
      +
    • +
    +

    EDG’s approach is a little different. It requires that, for each instantiation +of a non-exported template, there is some (normal, top-level, +explicitly-compiled) source file that contains the definition of the template +entity, a reference that causes the instantiation, and the declarations of any +types required for the instantiation. [5] This requirement can be met in +various ways:

    +
      +
    • +
      The Borland convention: each “.h” file that declares a template entity +also contains either the definition of the entity or includes another file +containing the definition.
      +
      +
    • +
    • +
      Implicit inclusion: when the compiler sees a template declaration in a +“.h” file and discovers a need to instantiate that entity, it is +given permission to go off looking for an associated definition file +having the same base name and a different suffix, and it implicitly +includes that file at the end of the compilation. This method allows +most programs written using the cfront convention to be compiled with +EDG’s approach. See Implicit Inclusion.
      +
      +
    • +
    • +
      The ad hoc approach: the programmer makes sure that the files that define +template entities also have the definitions of all the available types, and +adds code or pragmas in those files to request instantiation of the +entities there.
      +
      +
    • +
    +

    Exported templates are also supported by the EDG automatic instantiation +method, but they require additional mechanisms explained further on.

    +

    The EDG automatic instantiation method works as follows for non-exported +templates: [6]

    +
      +
    1. +
      The first time the source files of a program are compiled, no template +entities are instantiated. However, template information files (with, by +default, a “.ti” suffix) are generated and contain information about +things that could have been instantiated in each compilation [7].
      +
      +
    2. +
    3. +
      When the object files are linked together, a program called the +prelinker is run. It examines the object files, looking for +references and definitions of template entities, and for the added +information about entities that could be instantiated.
      +
      +
    4. +
    5. +
      If the prelinker finds a reference to a template entity for which there +is no definition anywhere in the set of object files, it looks for a file +that indicates that it could instantiate that template entity. When it +finds such a file, it assigns the instantiation to it. The set of +instantiations assigned to a given file is recorded in an associated +instantiation request file (with, by default, a “.ii” suffix).
      +
      +
    6. +
    7. +
      The prelinker then executes the compiler again to recompile each file for +which the instantiation request file was changed. The original +compilation command-line options (saved in the template information file) +are used for the recompilation.
      +
      +
    8. +
    9. +
      When the compiler compiles a file, it reads the instantiation request +file for that file and obeys the requests therein. It produces a new +object file containing the requested template entities (and all the other +things that were already in the object file). The compiler also receives +a definition list file, which lists all the instantiations for which +definitions already exist in the set of object files. If during the +compilation the compiler has the opportunity to instantiate a referenced +entity that is not on that list, it goes ahead and does the instantiation. +It passes back to the prelinker (in the definition list file) a list of +the instantiations that it has “adopted” in this way, so the prelinker can +assign them to the file. This adoption process allows rapid instantiation +and assignment of instantiations referenced from new instantiations, and +reduces the need to recompile a given file more than once during the +prelinking process.
      +
      +
    10. +
    11. +
      The prelinker repeats steps 3-5 until there are no more instantiations to +be adjusted.
      +
      +
    12. +
    13. +
      The object files are linked together.
      +
      +
    14. +
    +

    Once the program has been linked correctly, the instantiation request files +contain a complete set of instantiation assignments. From then on, whenever +source files are recompiled, the compiler will consult the instantiation +request files and do the indicated instantiations as it does the normal +compilations. That means that, except in cases where the set of required +instantiations changes, the prelink step from then on will find that all the +necessary instantiations are present in the object files and no instantiation +assignment adjustments need be done. That’s true even if the entire program is +recompiled.

    +

    If the programmer provides a specialization of a template entity somewhere in +the program, the specialization will be seen as a definition by the prelinker. +Since that definition satisfies whatever references there might be to that +entity, the prelinker will see no need to request an instantiation of the +entity. If the programmer adds a specialization to a program that has +previously been compiled, the prelinker will notice that too and remove the +assignment of the instantiation from the proper instantiation request file.

    +

    The instantiation request files should not, in general, require any manual +intervention. One exception: if a definition is changed in such a way that +some instantiation no longer compiles (it gets errors), and at the same time a +specialization is added in another file, and the first file is being recompiled +before the specialization file and is getting errors, the instantiation request +file for the file getting the errors must be deleted manually to allow the +prelinker to regenerate it.

    +

    If the prelinker changes an instantiation assignment, it will issue a message +like

    +
    C++ prelinker: A<int>::f() assigned to file test.o
    +C++ prelinker: executing: /edg/bin/eccp -c test.c
    +
    +
    +

    The automatic instantiation scheme can coexist with partial explicit control of +instantiation by the programmer through the use of pragmas or command-line +specification of the instantiation mode. See the following sections.

    +

    Instantiations are normally generated as part of the object file of the +translation unit in which the instantiations are performed. But when “one +instantiation per object” mode is specified, each instantiation is placed in +its own object file. One-instantiation-per-object mode is useful when +generating libraries that need to include copies of the instances referenced +from the library. If each instance is not placed in its own object file, it +may be impossible to link the library with another library containing some of +the same instances. Without this feature it is necessary to create each +individual instantiation object file using the manual instantiation mechanism.

    +

    The automatic instantiation mode can be configured out altogether by setting +the configuration flag AUTOMATIC_TEMPLATE_INSTANTIATION to FALSE. It can +be turned on or off using the --auto_instantiation and +--no_auto_instantiation command-line options. If automatic instantiation +is turned off, the template information file is not generated.

    +
    +
    +

    2.12.2. Instantiation Modes#

    +

    Normally, when a file is compiled, no template entities are instantiated +(except those assigned to the file by automatic instantiation). The overall +instantiation mode can, however, be changed by a command line option:

    +
    + + + + + + + + + + + + + + + +
    +
    -tnone
    +
    +
    +
    Do not automatically create instantiations of any template entities. +This is the default. It is also the usually appropriate mode when +automatic instantiation is done.
    +
    +
    +
    -tused
    +
    +
    +
    Instantiate those template entities that were used in the compilation. +This will include all static data members for which there are template +definitions.
    +
    +
    +
    -tall
    +
    +
    +
    Instantiate all template entities declared or referenced in the +compilation unit. For each fully instantiated template class, all of +its member functions and static data members will be instantiated +whether or not they were used. Nonmember template functions will be +instantiated even if the only reference was a declaration.
    +
    +
    +
    -tlocal
    +
    +
    +
    Similar to -tused except that the functions are given internal +linkage. This is intended to provide a very simple mechanism for +those getting started with templates. The compiler will instantiate +the functions that are used in each compilation unit as local +functions, and the program will link and run correctly (barring +problems due to multiple copies of local static variables.) However, +one may end up with many copies of the instantiated functions, so this +is not suitable for production use. -tlocal can not be used in +conjunction with automatic template instantiation. If automatic +instantiation is enabled by default, it will be disabled by the +-tlocal option. If automatic instantiation is not enabled by +default, use of -tlocal and -T is an error.
    +
    +
    +
    +

    In the case where the eccp script is given a single file to compile and +link, e.g.,

    +
    eccp t.c
    +
    +
    +

    the compiler knows that all instantiations will have to be done in the single +source file. Therefore, it uses the -tused mode and suppresses automatic +instantiation.

    +
    +
    +

    2.12.3. Instantiation #pragma Directives#

    +

    Instantiation pragmas can be used to control the instantiation of specific +template entities or sets of template entities. There are three instantiation +pragmas:

    +
      +
    • +
      The instantiate pragma causes a specified entity to be instantiated.
      +
      +
    • +
    • +
      The do_not_instantiate pragma suppresses the instantiation of a +specified entity. It is typically used to suppress the instantiation of an +entity for which a specific definition will be supplied.
      +
      +
    • +
    • +
      The can_instantiate pragma indicates that a specified entity can be +instantiated in the current compilation, but need not be; it is used in +conjunction with automatic instantiation, to indicate potential sites for +instantiation if the template entity turns out to be required. [8]
      +
      +
    • +
    +

    The argument to the instantiation pragma may be:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    a template class name
    +
    +
    +
    A<int>
    +
    +
    +
    a template class declaration
    +
    +
    +
    class A<int>
    +
    +
    +
    a member function name
    +
    +
    +
    A<int>::f
    +
    +
    +
    a static data member name
    +
    +
    +
    A<int>::i
    +
    +
    +
    a static data member decl.
    +
    +
    +
    int A<int>::i
    +
    +
    +
    a member function declaration
    +
    +
    +
    void A<int>::f(int, char)
    +
    +
    +
    a template function declaration
    +
    +
    +
    char* f(int, float)
    +
    +
    +
    a template variable name
    +
    +
    +
    x<int>
    +
    +
    +
    +

    A pragma in which the argument is a template class name (e.g., A<int> or +class A<int>) is equivalent to repeating the pragma for each member +function and static data member declared in the class. When instantiating an +entire class a given member function or static data member may be excluded +using the do_not_instantiate pragma. For example,

    +
    #pragma instantiate A<int>
    +#pragma do_not_instantiate A<int>::f
    +
    +
    +

    The template definition of a template entity must be present in the compilation +for an instantiation to occur. If an instantiation is explicitly requested by +use of the instantiate pragma and no template definition is available or a +specific definition is provided, an error is issued.

    +
    template <class T> void f1(T);  // No body provided
    +template <class T> void g1(T);  // No body provided
    +void f1(int) {}  // Specific definition
    +void main(){
    +  int i;
    +  double  d;
    +  f1(i);
    +  f1(d);
    +  g1(i);
    +  g1(d);
    +}
    +#pragma instantiate void f1(int)  // error - specific definition
    +#pragma instantiate void g1(int)  // error - no body provided
    +
    +
    +

    f1(double) and g1(double) will not be instantiated (because no bodies +were supplied) but no errors will be produced during the compilation (if no +bodies are supplied at link time, a linker error will be produced).

    +

    A member function name (e.g., A<int>::f) can only be used as a pragma +argument if it refers to a single user defined member function (i.e., not an +overloaded function). Compiler-generated functions are not considered, so a +name may refer to a user defined constructor even if a compiler-generated copy +constructor of the same name exists. Overloaded member functions can be +instantiated by providing the complete member function declaration, as in

    +
    #pragma instantiate char* A<int>::f(int, char*)
    +
    +
    +

    The argument to an instantiation pragma may not be a compiler-generated +function, an inline function, or a pure virtual function.

    +
    +
    +

    2.12.4. Implicit Inclusion#

    +

    When implicit inclusion is enabled, the front end is given permission to assume +that if it needs a definition to instantiate a template entity declared in a +“.h” file it can implicitly include the corresponding “.C” file to get +the source code for the definition. For example, if a template entity +ABC::f is declared in file xyz.h, and an instantiation of ABC::f is +required in a compilation but no definition of ABC::f appears in the source +code processed by the compilation, the compiler will look to see if a file +xyz.C exists, and if so it will process it as if it were included at the +end of the main source file.

    +

    To find the template definition file for a given template entity the front end +needs to know the path name specified in the original include of the file in +which the template was declared and whether the file was included using the +system include syntax (e.g., #include <file.h>). This information is not +available for preprocessed source containing #line directives. +Consequently, the front end will not attempt implicit inclusion for source code +containing #line directives.

    +

    The file to be implicitly included is found by replacing the file suffix with +each of the suffixes specified in the instantiation file suffix list. The +normal include search path mechanism is then used to look for the file to be +implicitly included.

    +

    DEFAULT_INSTANTIATION_FILE_SUFFIX_LIST defines the set of definition-file +suffixes tried. By default, the list is “.c”, “.C”, “.cpp”, +“.CPP”, “.cxx”, “.CXX”, and “.cc”.

    +

    Implicit inclusion works well alongside automatic instantiation, but the two +are independent. They can be enabled or disabled independently, and implicit +inclusion is still useful when automatic instantiation is not done.

    +

    The implicit inclusion mode can be configured out altogether by setting the +configuration flag INSTANTIATION_BY_IMPLICIT_INCLUSION to FALSE. It can be +turned on or off using the --implicit_include and --no_implicit_include +command-line options.

    +

    Implicit inclusions are only performed during the normal compilation of a file, +(i.e., not when doing only preprocessing). A common means of investigating +certain kinds of problems is to produce a preprocessed source file that can be +inspected. When using implicit inclusion it is sometimes desirable for the +preprocessed source file to include any implicitly included files. This may be +done using the --no_preproc_only command line option. This causes the +preprocessed output to be generated as part of a normal compilation. When +implicit inclusion is being used, the implicitly included files will appear as +part of the preprocessed output in the precise location at which they were +included in the compilation.

    +
    +
    +

    2.12.5. Exported Templates#

    +

    Exported templates are templates declared with the keyword export. +Exporting a class template is equivalent to exporting each of its static data +members and each of its non-inline member functions. An exported template is +special because its definition does not need to be present in a translation +unit that uses that template. In other words, the definition of an exported +(non-class) template does not need to be explicitly or implicitly included in a +translation unit that instantiates that template. For example, the following +is a valid C++ program consisting of two separate translation units:

    +
    // File 1:
    +#include <stdio.h>
    +static void trace() { printf("File 1\n"); }
    +
    +export template<class T> T const& min(T const&, T const&);
    +int main() {
    +  trace();
    +  return min(2, 3);
    +}
    +
    +
    +
    // File 2:
    +#include <stdio.h>
    +static void trace() { printf("File 2\n"); }
    +
    +export template<class T> T const& min(T const &a, T const &b) {
    +  trace();
    +  return a<b? a: b;
    +}
    +
    +
    +

    Note that these two files are separate translation units: one is not included +in the other. That allows the two functions trace() to coexist (with +internal linkage).

    +

    Support for exported templates can be enabled using the --export +command-line option (it is enabled by default in strict ANSI mode; -A or +--strict). For example, the program above could be built as follows using +the eccp script:

    +
    eccp --export -c file_1.c
    +eccp --export -c file_2.c
    +eccp file_1.o file_2.o
    +
    +
    +
    +

    2.12.5.1. Finding the exported template definition#

    +

    The automatic instantiation of exported templates is somewhat similar (from a +user’s perspective) to that of regular (included) templates. However, an +instantiation of an exported template involves at least two translation units: +one which requires the instantiation, and one which contains the template +definition.

    +

    When a file containing definitions of exported templates is compiled, a file +with a “.et” suffix is created and some extra information is included in +the associated “.ti” file. The “.et” files are used later by the front +end to find the translation unit that defines a given exported template.

    +

    When a file that potentially makes use of exported templates is compiled, the +compiler must be told where to look for “.et” files for exported templates +used by a given translation unit. By default, the compiler looks in the +current directory. Other directories may be specified with the +--template_directory option. Strictly speaking, the “.et” files are +only really needed when it comes time to generate an instantiation. This means +that code using exported templates can be compiled without having the +definitions of those templates available. Those definitions must be available +by the time prelinking is done (or when explicit instantiation is done).

    +

    The “.et” files only inform the front end about the location of exported +template definitions; they do not actually contain those definitions. The +sources containing the exported template definitions must therefore be made +available at the time of instantiation (usually, when prelinking is done). In +particular, the export facility is not a mechanism for avoiding the +publication of template definitions in source form.

    +
    +
    +

    2.12.5.2. Secondary translation units#

    +

    An instantiation of an exported template can be triggered by the prelinker, by +an explicit instantiation directive, or by the -tused command-line option. +In each case, the translation unit that contains the initial point of +instantiation will be processed as the primary translation unit. Based on +information it finds in the “.et” files, the front end will then load and +parse the translation unit containing the definition of the template to +instantiate. This is a secondary translation unit. The simultaneous +processing of the primary and secondary translation units enables the front end +to create instantiations of the exported templates (which can include entities +from both translation units). This process may reveal the need for additional +instantiations of exported templates, which in turn can cause additional +secondary translation units to be loaded [9].

    +

    When secondary translation units are processed, the declarations they contain +are checked for consistency. This process may report errors that would +otherwise not be caught. Many these errors are so-called “ODR violations” (ODR +stands for “one-definition rule”). For example:

    +
    // File 1:
    +struct X {
    +  int x;
    +};
    +int main() {
    +  return min(2, 3);
    +}
    +
    +// File 2:
    +struct X {
    +  unsigned x;  // Error: X::x declared differently in File 1
    +};
    +export template<class T> T const& min(T const &a, T const &b) {
    +  return a<b? a: b;
    +}
    +
    +
    +

    If there are no errors, the instantiations are generated in the output +associated with the primary translation unit (or in separate associated files +in one-instantiation-per-object mode). This may also require that entities +with internal linkage in secondary translation units be “externalized” so they +can be accessed from the instantiations in the primary translation unit.

    +
    +
    +

    2.12.5.3. Libraries with exported templates#

    +

    Typically a (non-export) library consists of an include directory and a lib +directory. The include directory contains the header files required by users +of the library and the lib directory contains the object code libraries that +client programs must use when linking programs.

    +

    With exported templates, users of the library must also have access to the +source code of the exported templates and the information contained in the +associated “.et” files. This information should be placed in a directory +that is distributed along with the include and lib directories: This is the +export directory. It must be specified using the --template_directory +option when compiling client programs.

    +

    The recommended procedure to build the export directory is as follows:

    +
      +
    1. +
      For each “.et” file in the original source directory, copy the +associated source file to the export directory.
      +
      +
    2. +
    3. +
      Concatenate all of the “.et” files into a single “.et” file +(e.g., mylib.et) in the export directory. The individual “.et” +files could be copied to the export directory, but having all of the +“.et” information in one file will make use of the library more +efficient.
      +
      +
    4. +
    5. +
      Create an export_info file in the export directory. The +export_info file specifies the include search paths to be used when +recompiling files in the export directory. If no export_info file is +provided, the include search path used when compiling the client program +that uses the library will also be used to recompile the library exported +template files.
      +
      +
    6. +
    +

    The export_info file consists of a series of lines of the form

    +
    include=x
    +
    +
    +

    or

    +
    sys_include=x
    +
    +
    +

    where x is a path name to be placed on the include search path. The +directories are searched in the order in which they are encountered in the +export_info file. The file can also contain comments – which begin with a +“#” – and blank lines. Spaces are ignored but tabs are not currently +permitted. For example:

    +
    # The include directories to be used for the xyz library
    +include = /disk1/xyz/include
    +sys_include = /disk2/abc/include
    +include=/disk3/jkl/include
    +
    +
    +

    The include search path specified for a client program is ignored by the front +end when it processes the source in the export library, except when no +export_info file is provided. Command-line macro definitions specified for +a client program are also ignored by the front end when processing a source +file from the export libary; the command-line macros specified when the +corresponding “.et” file was produced do apply. All other compilation +options (other than the include search path and command-line macro definitions) +used when recompiling the exported templates will be used to compile the client +program.

    +

    When a library is installed on a new system, it is likely that the +export_info file will need to be adapted to reflect the location of the +required headers on that system.

    +
    +
    +
    +
    +

    2.13. Extern Inline Functions#

    +

    Depending on the way in which the front end is configured, out-of-line copies +of extern inline functions are either implemented using static functions, or +are instantiated using a mechanism like the template instantiation mechanism. +Note that out-of-line copies of inline functions are only required in cases +where the function cannot be inlined, or when the address of the function is +taken (whether explicitly by the user, by implicitly generated functions, or by +compiler-generated data structures such as virtual function tables or exception +handling tables).

    +

    When static functions are used, local static variables of the functions are +promoted to global variables with specially encoded names, so that even though +there may be multiple copies of the code, there is only one copy of such global +variables. This mechanism does not strictly conform to the standard because +the address of an extern inline function is not constant across translation +units.

    +

    When the instantiation mechanism is used, the address of an extern inline +function is constant across translation units, but at the cost of requiring the +use of one of the template instantiation mechanisms, even for programs that +don’t use templates. Definitions of extern inline functions can be provided +either through use of the automatic instantiation mechanism or by use of the +-tused or -tall instantiation modes. There is no mechanism to manually +control the definition of extern inline function bodies.

    +
    +
    +

    2.14. Predefined Macros#

    +

    The front end defines a number of preprocessing macros. Many of them are only +defined under certain circumstances. This section describes the macros that +are provided and the circumstances under which they are defined. In addition, +a table of predefined macro definitions may be processed when the compiler is +invoked. This may be used for any kind of predefined macro, but in particular +is used to define the macros that gcc and g++ define when using gcc and g++ +modes. The format of the file and other information is described in +Predefined Macro Definition File.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    __STDC__
    +
    +
    +
    Defined in ANSI C mode and in C++ mode. In C++ mode the value may be +redefined. Not defined in Microsoft compatibility mode.
    +
    +
    +
    __DATE__
    +
    +
    +
    Defined in all modes to the date of the compilation in the form “Mmm +dd yyyy”.
    +
    +
    +
    __TIME__
    +
    +
    +
    Defined in all modes to the time of the compilation in the form +“hh:mm:ss”.
    +
    +
    +
    __FILE__
    +
    +
    +
    Defined in all modes to the name of the current source file.
    +
    +
    +
    __LINE__
    +
    +
    +
    Defined in all modes to the current source line number within the +current source file.
    +
    +
    +
    __cplusplus
    +
    +
    +
    Defined in C++ modes. In general, the value is 201103L if C++11 +features are enabled and either 1 or 199711L otherwise, but +which of those three values is chosen depends on the emulation +(compiler and version).
    +
    +
    +
    c_plusplus
    +
    +
    +
    Defined in cfront mode.
    +
    +
    +
    __cplusplus_cli
    +
    +
    +
    Defined in C++/CLI mode with the value 200406l.
    +
    +
    +
    __STDC_VERSION__
    +
    +
    +
    Defined in ANSI C mode with the value 199409L. The name of this +macro, and its value, are specified in Normative Addendum 1 of the ISO +C90 Standard. In C99 mode, defined with the value 199901L.
    +
    +
    +
    __STDC_HOSTED__
    +
    +
    +
    Defined in C99 and C++11 modes with the value specified by the +STDC_HOSTED configuration macro.
    +
    +
    +
    __STDC_IEC_559__
    +
    +
    +
    Defined in C99 mode if the configuration macro STDC_IEC_559 is +TRUE.
    +
    +
    +
    __STDC_IEC_559_COMPLEX__
    +

    +
    +
    +
    Defined in C99 mode if the configuration macro
    +
    +
    STDC_IEC_559_COMPLEX is TRUE.
    +
    +
    +
    +
    __STDC_ISO_10646__
    +
    +
    +
    Defined in C99 mode if the configuration macro STDC_ISO_10646 is +TRUE. The value is specified by the STDC_ISO_10646_VALUE macro.
    +
    +
    +
    __STDC_MB_MIGHT_NEQ_WC__
    +
    +
    +
    Defined in C99 mode if the configuration macro +STDC_MB_MIGHT_NEQ_WC is TRUE.
    +
    +
    +
    __SIGNED_CHARS__
    +
    +
    +
    Defined when plain char is signed. This is used in the +<limits.h> header file to get the proper definitions of +CHAR_MAX and CHAR_MIN.
    +
    +
    +
    __FUNCTION__
    +
    +
    +
    Defined in all modes to the name of the current function. An error is +issued if it is used outside of a function. An EDG, GNU, and +Microsoft extension. (Depending on the current mode, this identifier +behaves as a variable or as a string literal; never as a preprocessor +macro.)
    +
    +
    +
    __func__
    +
    +
    +
    Same as __FUNCTION__ in C99, C++11, and GNU modes. (This +identifier behaves as a variable; not as a preprocessor macro.)
    +
    +
    +
    __PRETTY_FUNCTION__
    +
    +
    +
    Defined in all modes to the name of the current function. This +includes the return type and parameter types of the function. An +error is issued if it is used outside of a function. An EDG and GNU +extension. (Depending on the current mode, this identifier behaves as +a variable or as a string literal; never as a preprocessor macro.)
    +
    +
    +
    __FUNCSIG__
    +
    +
    +
    Same as __PRETTY_FUNCTION__ in Microsoft mode. (This identifier +behaves as a string literal; not as a preprocessor macro.)
    +
    +
    +
    __FUNCDNAME__
    +
    +
    +
    Defined to the “decorated” name of the current function (i.e., its +mangled name) in Microsoft mode. (This identifier behaves as a string +literal; not as a preprocessor macro.)
    +
    +
    +
    __BASE_FILE__
    +
    +
    +
    Defined in all modes. Similar to __FILE__ but indicates the +primary source file rather than the current one (i.e., when the +current file is an included file).
    +
    +
    +
    _WCHAR_T
    +
    +
    +
    Defined in C++ mode when wchar_t is a keyword. The name of this +macro and whether it is predefined are specified by configuration +options. _WCHAR_T is the default.
    +
    +
    +
    _WCHAR_T_DEFINED
    +
    +
    +
    Defined in Microsoft C++ mode when wchar_t is a keyword.
    +
    +
    +
    _NATIVE_WCHAR_T_DEFINED
    +

    +
    +
    +
    Defined in Microsoft C++ mode when wchar_t is a keyword (Microsoft +version 1300 and above).
    +
    +
    +
    _BOOL
    +
    +
    +
    Defined in C++ mode when bool is a keyword. The name of this +macro and whether it is predefined are specified by configuration +options. _BOOL is the default.
    +
    +
    +
    __BOOL_DEFINED
    +
    +
    +
    Defined in Microsoft C++ mode when bool is a keyword.
    +
    +
    +
    __ARRAY_OPERATORS
    +
    +
    +
    Defined in C++ mode when array new and delete are enabled. The name +of this macro and whether it is predefined are specified by +configuration options. __ARRAY_OPERATORS is the default.
    +
    +
    +
    __EXCEPTIONS
    +
    +
    +
    Defined in C++ mode when exception handling is enabled. The name of +this macro and whether it is predefined are specified by configuration +options. __EXCEPTIONS is the default.
    +
    +
    +
    __RTTI
    +
    +
    +
    Defined in C++ mode when RTTI is enabled. The name of this macro and +whether it is predefined are specified by configuration options. +__RTTI is the default.
    +
    +
    +
    __PLACEMENT_DELETE
    +
    +
    +
    Defined in C++ mode when placement delete is enabled. The name of +this macro and whether it is predefined are specified by configuration +options. __PLACEMENT_DELETE is the default. Placement delete is +enabled when ABI_CHANGES_FOR_PLACEMENT_DELETE is TRUE and +exception handling is enabled.
    +
    +
    +
    __NO_LONG_LONG
    +
    +
    +
    Defined in all modes when the long long type is not supported. +The name of this macro and whether it is predefined are specified by +configuration options. __NO_LONG_LONG is the default.
    +
    +
    +
    __EDG_RUNTIME_USES_NAMESPACES
    +

    +
    +
    +
    Defined in C++ mode when the configuration flag +RUNTIME_USES_NAMESPACES is TRUE. The name of this macro and +whether it is predefined are specified by configuration options. +__EDG_RUNTIME_USES_NAMESPACES is the default.
    +
    +
    +
    __EDG_IMPLICIT_USING_STD
    +

    +
    +
    +
    Defined in C++ mode when the configuration flag +RUNTIME_USES_NAMESPACES is TRUE and when implicit_using_std +has been set to TRUE, either by a command line option or by the +configuration flag DEFAULT_IMPLICIT_USING_STD, indicating that the +standard header files should implicitly do a using-directive on the +std namespace. The name of this macro and whether it is +predefined are specified by configuration options. +__EDG_IMPLICIT_USING_STD is the default.
    +
    +
    +
    __EDG_TYPE_TRAITS_ENABLED
    +

    +
    +
    +
    Defined in non-Microsoft modes when type traits pseudo-functions (to +ease the implementation of ISO/IEC TR 19768; e.g., “__is_union”) +are enabled. The name of this predefined macro is specified by a +configuration option. __EDG_TYPE_TRAITS_ENABLED is the default.
    +
    +
    +
    __EDG__
    +
    +
    +
    Always defined.
    +
    +
    +
    __EDG_VERSION__
    +
    +
    +
    Defined to an integral value that represents the version number of the +front end. For example. version 2.30 is represented as 230.
    +
    +
    +
    __EDG_IA64_ABI
    +
    +
    +
    Defined as 1 when using a front end configured to use the IA-64 ABI.
    +
    +
    +
    __embedded_cplusplus
    +
    +
    +
    Defined as 1 in Embedded C++ mode.
    +
    +
    +
    _CHAR_UNSIGNED
    +
    +
    +
    Defined in Microsoft mode when char is unsigned.
    +
    +
    +
    _MSC_VER
    +
    +
    +
    Defined in Microsoft mode to the version number of the Microsoft +compiler that is to be emulated. For example, 1100 is the value that +corresponds to Visual C++ version 5.0.
    +
    +
    +
    _MSC_BUILD
    +
    +
    +
    Defined in Microsoft mode to the value of microsoft_build_number.
    +
    +
    +
    _M_CEE
    +
    +
    +
    Defined in Microsoft mode when C++/CLI mode is in effect (e.g., when +--cppcli is specified).
    +
    +
    +
    _MSC_EXTENSIONS
    +
    +
    +
    Defined in Microsoft mode.
    +
    +
    +
    _WIN32
    +
    +
    +
    Defined (unconditionally) in Microsoft mode.
    +
    +
    +
    _WIN64
    +
    +
    +
    Defined in Microsoft mode when targ_supports_x86_64 is TRUE.
    +
    +
    +
    _INTEGRAL_MAX_BITS
    +
    +
    +
    Defined in Microsoft mode to the number of bits in the largest +integral type that is supported. The value depends on the way in +which the front end was configured.
    +
    +
    +
    _CPPRTTI
    +
    +
    +
    Defined in Microsoft mode C++ when RTTI is enabled.
    +
    +
    +
    __GNUC__
    +
    +
    +
    Defined in GNU mode to the value specified by the GCC_VERSION +configuration macro.
    +
    +
    +
    __GNUC_MINOR__
    +
    +
    +
    Defined in GNU mode to the value specified by the +GCC_MINOR_VERSION configuration macro.
    +
    +
    +
    __VERSION__
    +
    +
    +
    Defined in GNU mode to the value specified by the +GCC_VERSION_STRING configuration macro.
    +
    +
    +
    __PRAGMA_REDEFINE_EXTNAME
    +

    +
    +
    +
    Defined if all modes when the configuration flag +REDEFINE_EXTNAME_PRAGMA_ENABLED is TRUE.
    +
    +
    +
    __upc__
    +
    +
    +
    Defined when UPC extensions are enabled.
    +
    +
    +
    __COUNTER__
    +
    +
    +
    Defined in Microsoft mode. Returns an integer value, starting with +zero and incremented each time the macro is used.
    +
    +
    +
    __TIMESTAMP__
    +
    +
    +
    Defined in Microsoft mode. Returns a string literal containing the +modification date and time of the source file in which it is +specified.
    +
    +
    +
    __EDG_IA64_ABI
    +
    +
    +
    Defined in C++ mode when using the IA-64 ABI. The name of this +predefined macro is specified by a configuration option. +__EDG_IA64_ABI is the default.
    +
    +
    +
    __EDG_IA64_ABI_USE_INT_STATIC_INIT_GUARD
    +
    +
    +
    Defined in C++ mode when using the IA-64 ABI when guard variables are +int-sized (i.e., in the ARM EABI). The name of this predefined +macro is specified by a configuration option. +__EDG_IA64_ABI_USE_INT_STATIC_INIT_GUARD is the default.
    +
    +
    +
    __EDG_IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS
    +
    +
    +
    Defined in C++ mode when using the IA-64 ABI when constructors and +destructors return the this pointer (i.e., in the ARM EABI). The +name of this predefined macro is specified by a configuration option. +__EDG_IA64_ABI_VARIANT_CTORS_AND_DTORS_RETURN_THIS is the default.
    +
    +
    +
    __EDG_SIZE_TYPE__
    +
    +
    +
    Defined to be the type of size_t.
    +
    __EDG_PTRDIFF_TYPE__
    +
    +
    Defined to be the type of ptrdiff_t.
    +
    +
    +
    +
    __CHAR16_T_AND_CHAR32_T
    +

    +
    +
    +
    Defined in C++ mode when char16_t and char32_t are keywords. +The name of this macro and whether it is predefined are specified by +configuration options. __CHAR16_T_AND_CHAR32_T is the default.
    +
    +
    +
    __CHAR16_TYPE__
    +
    +
    +
    Defined in GNU mode as the underlying type for char16_t (GNU +version 40400 and above).
    +
    +
    +
    __CHAR32_TYPE__
    +
    +
    +
    Defined in GNU mode as the underlying type for char32_t (GNU +version 40400 and above).
    +
    +
    +
    __VARIADIC_TEMPLATES
    +

    +
    +
    +
    Defined in C++ mode when variadic templates are supported. The name +of this macro and whether it is predefined are specified by +configuration options. __VARIADIC_TEMPLATES is the default.
    +
    +
    +
    __STDCPP_THREADS__
    +
    +
    +
    Defined in C++ mode when the implementation supports multiple threads +(i.e., when IMPLEMENTATION_SUPPORTS_MULTIPLE_THREADS is TRUE +and the global variable std_thread_local_storage_specifier_enabled +is TRUE).
    +
    +
    +
    +
    +
    +

    2.15. Pragmas#

    +

    #pragma directives are used within the source program to request certain +kinds of special processing. The #pragma directive is part of the standard +C and C++ languages, but the meaning of any pragma is implementation-defined.

    +
    +

    2.15.1. Instantiation Pragmas#

    +

    The following are described in detail in the template instantiation section of +this chapter:

    +
    #pragma instantiate
    +#pragma do_not_instantiate
    +#pragma can_instantiate
    +
    +
    +
    +
    +

    2.15.2. Precompiled Header Pragmas#

    +

    The following are described in the section on precompiled header processing:

    +
    #pragma hdrstop
    +#pragma no_pch
    +
    +
    +
    +
    +

    2.15.3. Once Pragma#

    +

    The front end also recognizes #pragma once, which, when placed at the +beginning of a header file, indicates that the file is written in such a way +that including it several times has the same effect as including it once. +Thus, if the front end sees #pragma once at the start of a header file, it +will skip over it if the file is #included again.

    +

    A typical idiom is to place an #ifndef guard around the body of the file, +with a #define of the guard variable after the #ifndef:

    +
    +
    +
    #pragma once           // optional
    +
    #ifndef FILE_H
    +
    #define FILE_H
    +
    ... body of the header file ...
    +
    #endif
    +
    +
    +

    The #pragma once is marked as optional in this example, because the front +end recognizes the #ifndef idiom and does the optimization even in its +absence. #pragma once is accepted for compatibility with other compilers +and to allow the programmer to use other guard-code idioms.

    +
    +
    +

    2.15.4. Diagnostic Pragmas#

    +

    The following pragmas may be used to control the error severity used when a +given diagnostic message is issued.

    +
    #pragma diag_suppress
    +#pragma diag_remark
    +#pragma diag_warning
    +#pragma diag_error
    +#pragma diag_default
    +#pragma diag_once
    +
    +
    +

    These are similar in function to the equivalent command-line options. Uses of +these pragmas have the following form:

    +
    +
    +
    #pragma diag_xxx [=] error_number_or_tag, error_number_or_tag …
    +
    +
    +

    The diagnostic affected is specified using either an error number or an error +tag name. The “=” is optional. Any diagnostic may be overridden to be an +error, but only diagnostics with a severity of discretionary error or below may +have their severity reduced to a warning or below, or be suppressed. The +diag_default pragma is used to return the severity of a diagnostic to the +one that was in effect before any pragmas were issued (i.e., the normal +severity of the message as modified by any command-line options). The +following example suppresses the “pointless friend declaration” warning on the +declaration of class A:

    +
    #pragma diag_suppress 522
    +class A { friend class A; };
    +#pragma diag_default 522
    +class B { friend class B; };
    +
    +
    +

    The diag_once pragma causes the specified diagnostics to be issued only +once as a warning or remark.

    +
    +
    +

    2.15.5. Pack Pragma#

    +

    When USER_CONTROL_OF_STRUCT_PACKING is TRUE, #pragma pack is +recognized. It is used to specify the maximum alignment allowed for nonstatic +data members of structs and classes, even if that alignment is less than the +alignment dictated by the member’s type.

    +

    The basic syntax is:

    +
    +
    +
    #pragma pack(n)
    +
    #pragma pack()
    +
    +
    +

    where argument n, a power-of-2 value within the range defined by +TARG_MINIMUM_PACK_ALIGNMENT and TARG_MAXIMUM_PACK_ALIGNMENT, is the new +packing alignment that is to go into effect for subsequent declarations, until +another #pragma pack is seen. The second form cancels the effect of a +preceding #pragma pack(n) and either restores the default packing +alignment specified by the --pack_alignment command-line option or, if the +option was not used, disables the packing of structs and classes.

    +

    An enhanced syntax (intended to be compatible with the similar facility offered +by Microsoft C/C++ compilers) is also supported in which keywords push and +pop can be used to manage a stack of packing alignment values – for +instance:

    +
    #pragma pack (push, xxx, 16)
    +  /* Packing alignment set to 16. */
    +#include "xxx.h"
    +#pragma pack (pop, xxx)
    +  /* Packing alignment reset to what it was prior to the
    +     above #pragma pack directive, even if the included header
    +     left some unrelated pragma pack entries on the stack. */
    +
    +
    +

    which has the effect saving the current packing alignment value and +establishing a new one, processing the include file (which may leave the +packing alignment with an unknown setting), and restoring the original value. +Finally, the form

    +
    #pragma pack(show)
    +
    +
    +

    causes the front end to emit a warning describing the current setting of the +maximum member alignment (if any).

    +

    In C++ a #pragma pack directive has “local” effect when it appears inside a +function template, an instantiation of a class template, or the body of a +member function or friend function that is defined within a class definition. +When such a context is entered, the current pack alignment state is saved, so +that it can be restored when the context is exited. For example,

    +
    template <class T> class A {
    +  :
    +#pragma pack(1)
    +  :
    +};
    +#pragma pack(4)
    +main() {
    +  A<int> a;                     // #pragma pack(1) is local to A<int>
    +  struct S { char c; int i; };  // sizeof(S) == 8, not 5
    +}
    +
    +
    +

    Moreover, within an instantiation of a class or function template, the default +pack alignment is that which is in effect at the point of the template’s +definition, not at the point of its instantiation. Here is an example:

    +
    #pragma pack(1)
    +template <class T> int f(T) {
    +  struct S { char c; int i; };   // default pack alignment is 1 for each
    +  return sizeof(S);              //   instance of f<T>
    +}
    +#pragma pack(4)
    +main() {
    +  int i = f(0);                  // i = 5, not 8
    +}
    +
    +
    +

    These rules apply to inline-defined member functions, too, because their bodies +are also scanned “out of order” relative to the textual order of the source +program (i.e., not till all the class members have been declared).

    +
    #pragma pack(4)
    +struct A {
    +  int f() {
    +#pragma pack(1)                   // #pragma pack(1) is local to A::f
    +    struct S { char c; int i; };  // sizeof(S) is 5
    +  }
    +  int g() {
    +    struct S { char c; int i; };  // sizeof(S) is 8
    +  }
    +#pragma pack(1)
    +  int h() {
    +    struct S { char c; int i; };  // sizeof(S) is 5
    +  }
    +};
    +
    +
    +

    When IDENT_DIRECTIVE_AND_PRAGMA is TRUE, #pragma ident is recognized, +as is #ident:

    +
    #pragma ident "string"
    +#ident "string"
    +
    +
    +

    Both are implemented by recording the string in a pragma entry and passing it +to the back end.

    +

    When PRAGMA_WEAK_ALLOWED is TRUE, #pragma weak is recognized. Its form +is:

    +
    +
    +
    #pragma weak name1 [ = name2 ]
    +
    +
    +

    where name1 is the name to be given “weak binding” and is a synonym for +name2 if the latter is specified. The entire argument string is recorded +in the pragma entry and passed to the back end.

    +
    +
    +

    2.15.6. Microsoft Pragmas#

    +

    The following pragmas are accepted in Microsoft mode:

    +
    #pragma push_macro("identifier")
    +#pragma pop_macro("identifier")
    +#pragma include_alias("a_long_file_name.h", "short.h")
    +
    +
    +

    In addition, when NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE is TRUE, +the setlocale pragma is accepted:

    +
    #pragma setlocale("locale name")
    +
    +
    +

    The pack pragma is also accepted by the Microsoft compiler, but its +acceptance by the front end is controlled by a separate configuration flag, not +by whether or not Microsoft mode is being used.

    +
    +
    +

    2.15.7. IL Display Pragma#

    +

    As a debugging aid, in configurations where NEED_IL_DISPLAY is TRUE, +the il_display pragma can be used to display the underlying IL for the IL +entity that the pragma is attached to. The il_display pragma is a +pbk_next_construct pragma that attaches to the subsequent declaration or +statement and displays the IL associated with that entity. Note that the IL +displayed represents the IL at the current point in the compilation and may not +accurately reflect the eventual IL. This can be useful for displaying source +location information. For example:

    +
    struct A { int x, y; };
    +void f(int i) {
    +#pragma il_display
    +  A a = { 1, 2 };
    +#pragma il_display
    +  i++;
    +}
    +
    +
    +
    +
    +
    +

    2.16. Precompiled Headers#

    +

    It is often desirable to avoid recompiling a set of header files, +especially when they introduce many lines of code and the primary source +files that #include them are relatively small. The EDG front end +provides a mechanism for, in effect, taking a snapshot of the state of the +compilation at a particular point and writing it to a disk file before +completing the compilation; then, when recompiling the same source file or +compiling another file with the same set of header files, it can recognize +the “snapshot point,” verify that the corresponding precompiled header +(“PCH”) file is reusable, and read it back in. Under the right +circumstances, this can produce a dramatic improvement in compilation time; +the trade-off is that PCH files can take a lot of disk space. Because of +potential memory conflicts between threads, precompiled header processing +is disabled in multi-threaded configurations. In particular, a PCH file +cannot be created if MULTIPLE_THREAD_COMPILATION is TRUE and, because +the configurations must match, a PCH file by a single-threaded +configuration cannot be used.

    +
    +

    2.16.1. Automatic Precompiled Header Processing#

    +

    When --pch appears on the command line, automatic precompiled header +processing is enabled. This means the front end will automatically look for a +qualifying precompiled header file to read in and/or will create one for use on +a subsequent compilation.

    +

    The PCH file will contain a snapshot of all the code preceding the “header +stop” point. The header stop point is typically the first token in the primary +source file that does not belong to a preprocessing directive, but it can also +be specified directly by #pragma hdrstop (see below) if that comes first. +For example:

    +
    #include "xxx.h"
    +#include "yyy.h"
    +int i;
    +
    +
    +

    The header stop point is int (the first non-preprocessor token) and the PCH +file will contain a snapshot reflecting the inclusion of xxx.h and +yyy.h. If the first non-preprocessor token or the #pragma hdrstop +appears within a #if block, the header stop point is the outermost +enclosing #if. To illustrate, here’s a more complicated example:

    +
    #include "xxx.h"
    +#ifndef YYY_H
    +#define YYY_H 1
    +#include "yyy.h"
    +#endif
    +#if TEST
    +int i;
    +#endif
    +
    +
    +

    Here, the first token that does not belong to a preprocessing directive is +again int, but the header stop point is the start of the #if block +containing it. The PCH file will reflect the inclusion of xxx.h and +conditionally the definition of YYY_H and inclusion of yyy.h; it will +not contain the state produced by #if TEST.

    +

    A PCH file will be produced only if the header stop point and the code +preceding it (mainly, the header files themselves) meet certain requirements:

    +
      +
    • +
      The header stop point must appear at file scope – it may not be within an +unclosed scope established by a header file. For example, a PCH file will +not be created in this case:
      +
      +
      // xxx.h
      +class A {
      +
      +// xxx.C
      +#include "xxx.h"
      +int i; };
      +
      +
      +
    • +
    • +
      The header stop point may not be inside a declaration started within a +header file, nor (in C++) may it be part of a declaration list of a linkage +specification. For example, in the following case the header stop point is +int, but since it is not the start of a new declaration, no PCH file +will be created:
      +
      +
      // yyy.h
      +static
      +
      +// yyy.C
      +#include "yyy.h"
      +int i;
      +
      +
      +
    • +
    • +
      Similarly, the header stop point may not be inside a #if block or a +#define started within a header file.
      +
      +
    • +
    • +
      The processing preceding the header stop must not have produced any errors. +(Note: warnings and other diagnostics will not be reproduced when the PCH +file is reused.)
      +
      +
    • +
    • +
      No references to predefined macros __DATE__ or __TIME__ may have +appeared.
      +
      +
    • +
    • +
      No use of the #line preprocessing directive may have appeared.
      +
      +
    • +
    • +
      #pragma no_pch (see below) must not have appeared.
      +
      +
    • +
    • +
      The code preceding the header stop point must have introduced a sufficient +number of declarations to justify the overhead associated with precompiled +headers. This is configurable – see PCH_DECL_SEQ_THRESHOLD.
      +
      +
    • +
    +

    When the host system does not support memory mapping, so that everything to be +saved in the precompiled header file is assigned to preallocated memory (i.e., +when USE_MMAP_FOR_MEMORY_REGIONS is FALSE), two additional restrictions +apply:

    +
      +
    • +
      The total memory needed at the header stop point cannot exceed the size of +the block of preallocated memory.
      +
      +
    • +
    • +
      No single program entity saved can exceed HOST_ALLOCATION_INCREMENT, +the preallocation unit.
      +
      +
    • +
    +

    When a precompiled header file is produced, it contains, in addition to the +snapshot of the compiler state, some information that can be checked to +determine under what circumstances it can be reused. This includes:

    +
      +
    • +
      The compiler version, including the date and time the compiler was built.
      +
      +
    • +
    • +
      The current directory (i.e., the directory in which the compilation is +occurring).
      +
      +
    • +
    • +
      The command line options.
      +
      +
    • +
    • +
      The initial sequence of preprocessing directives from the primary source +file, including #include directives.
      +
      +
    • +
    • +
      The date and time of the header files specified in #include directives.
      +
      +
    • +
    +

    This information comprises the PCH “prefix.” The prefix information of a given +source file can be compared to the prefix information of a PCH file to +determine whether the latter is applicable to the current compilation.

    +

    As an illustration, consider two source files:

    +
    // a.C
    +#include "xxx.h"
    +...               // Start of code
    +
    +// b.C
    +#include "xxx.h"
    +...               // Start of code
    +
    +
    +

    When a.C is compiled with --pch, a precompiled header file named +a.pch is created. Then, when b.C is compiled (or when a.C is +recompiled), the prefix section of a.pch is read in for comparison with the +current source file. If the command line options are identical, if xxx.h +has not been modified, and so forth, then, instead of opening xxx.h and +processing it line by line, the front end reads in the rest of a.pch and +thereby establishes the state for the rest of the compilation.

    +

    It may be that more than one PCH file is applicable to a given compilation. If +so, the largest (i.e., the one representing the most preprocessing directives +from the primary source file) is used. For instance, consider a primary source +file that begins with:

    +
    #include "xxx.h"
    +#include "yyy.h"
    +#include "zzz.h"
    +
    +
    +

    If there is one PCH file for xxx.h and a second for xxx.h and +yyy.h, the latter will be selected (assuming both are applicable to the +current compilation). Moreover, after the PCH file for the first two headers +is read in and the third is compiled, a new PCH file for all three headers may +be created.

    +

    When a precompiled header file is created, it takes the name of the primary +source file, with the suffix replaced by an implementation-specified suffix +(see PCH_FILE_SUFFIX, which is set to pch by default). Unless +--pch_dir is specified (see below), it is created in the directory of the +primary source file.

    +

    When a precompiled header file is created or used, a message such as

    +
    "test.C": creating precompiled header file "test.pch"
    +
    +
    +

    is issued. The user may suppress the message by using the command-line option +--no_pch_messages.

    +

    When the --pch_verbose option is used the front end will display a message +for each precompiled header file that is considered that cannot be used giving +the reason that it cannot be used.

    +

    In automatic mode (i.e., when --pch is used) the front end will deem a +precompiled header file obsolete and delete it under the following +circumstances:

    +
      +
    • +
      if the precompiled header file is based on at least one out-of-date header +file but is otherwise applicable for the current compilation; or
      +
      +
    • +
    • +
      if the precompiled header file has the same base name as the source file +being compiled (e.g., xxx.pch and xxx.C) but is not applicable for +the current compilation (e.g., because of different command-line options).
      +
      +
    • +
    +

    This handles some common cases; other PCH file clean-up must be dealt with by +other means (e.g., by the user).

    +

    Support for precompiled header processing is not available when multiple source +files are specified in a single compilation: an error will be issued and the +compilation aborted if the command line includes a request for precompiled +header processing and specifies more than one primary source file.

    +
    +
    +

    2.16.2. Manual Precompiled Header Processing#

    +

    Command-line option --create_pch file-name specifies that a precompiled +header file of the specified name should be created.

    +

    Command-line option --use_pch file-name specifies that the indicated +precompiled header file should be used for this compilation; if it is invalid +(i.e., if its prefix does not match the prefix for the current primary source +file), a warning will be issued and the PCH file will not be used.

    +

    When either of these options is used in conjunction with --pch_dir, the +indicated file name (which may be a path name) is tacked on to the directory +name, unless the file name is an absolute path name.

    +

    The --create_pch, --use_pch, and --pch options may not be used +together. If more than one of these options is specified, only the last one +will apply. Nevertheless, most of the description of automatic PCH processing +applies to one or the other of these modes – header stop points are determined +the same way, PCH file applicability is determined the same way, and so forth.

    +
    +
    +

    2.16.3. Other Ways for Users to Control Precompiled Headers#

    +

    There are several ways in which the user can control and/or tune how +precompiled headers are created and used.

    +
      +
    • +
      #pragma hdrstop may be inserted in the primary source file at a point +prior to the first token that does not belong to a preprocessing directive. +It enables the user to specify where the set of header files subject to +precompilation ends. For example,
      +
      +
      #include "xxx.h"
      +#include "yyy.h"
      +#pragma hdrstop
      +#include "zzz.h"
      +
      +
      +
      +
      Here, the precompiled header file will include processing state for +xxx.h and yyy.h but not zzz.h. (This is useful if the user +decides that the information added by what follows the #pragma hdrstop +does not justify the creation of another PCH file.)
      +
      +
    • +
    • +
      #pragma no_pch may be used to suppress precompiled header processing +for a given source file.
      +
      +
    • +
    • +
      Command-line option --pch_dir directory-name is used to specify the +directory in which to search for and/or create a PCH file.
      +
      +
    • +
    +

    Moreover, when the host system does not support memory mapping and preallocated +memory is used instead (i.e., when USE_MMAP_FOR_MEMORY_REGIONS is FALSE) +then one of the command-line options --pch, --create_pch, or +--use_pch, if it appears at all, must be the first option on the command +line; and in addition:

    +
      +
    • +
      Command-line option --pch_mem size may be used to change the size +of the preallocated block of memory from its default value. The +argument size is the number of 1024-byte units. (--pch_mem must +also be among the first options on the command line.)
      +
      +
    • +
    +
    +
    +

    2.16.4. Performance Issues#

    +

    The relative overhead incurred in writing out and reading back in a precompiled +header file is quite small for reasonably large header files. (An +implementation can adjust PCH_DECL_SEQ_THRESHOLD to avoid creating +precompiled header files with too little information in them.)

    +

    In general, it doesn’t cost much to write a precompiled header file out even if +it does not end up being used, and if it is used it almost always produces a +significant speedup in compilation. The problem is that the precompiled header +files can be quite large (from a minimum of about 250K bytes to several +megabytes or more), and so one probably doesn’t want many of them sitting +around.

    +

    Thus, despite the faster recompilations, precompiled header processing is not +likely to be justified for an arbitrary set of files with nonuniform initial +sequences of preprocessing directives. Rather, the greatest benefit occurs +when a number of source files can share the same PCH file. The more sharing, +the less disk space is consumed. With sharing, the disadvantage of large +precompiled header files can be minimized, without giving up the advantage of a +significant speedup in compilation times.

    +

    Consequently, to take full advantage of header file precompilation, users +should expect to reorder the #include sections of their source files and/or +to group #include directives within a commonly used header file.

    +

    The EDG front end source provides an example of how this can be done. A common +idiom is this:

    +
    #include "fe_common.h"
    +#pragma hdrstop
    +#include ...
    +
    +
    +

    where fe_common.h pulls in, directly and indirectly, a few dozen header +files; the #pragma hdrstop is inserted to get better sharing with fewer PCH +files. The PCH file produced for fe_common.h is a bit over a megabyte in +size. Another idiom, used by the source files involved in declaration +processing, is this:

    +
    #include "fe_common.h"
    +#include "decl_hdrs.h"
    +#pragma hdrstop
    +#include ...
    +
    +
    +

    decl_hdrs.h pulls in another dozen header files, and a second, somewhat +larger, PCH file is created. In all, the fifty-odd source files of the EDG +front end share just six precompiled header files. If disk space were at a +premium, one could decide to make fe_common.h pull in all the header +files used – then, a single PCH file could be used in building the EDG +front end.

    +

    Different environments and different projects will have different needs, but in +general, users should be aware that making the best use of the precompiled +header support will require some experimentation and probably some minor +changes to source code.

    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/genindex/index.html b/doc/genindex/index.html new file mode 100644 index 0000000..08720e4 --- /dev/null +++ b/doc/genindex/index.html @@ -0,0 +1,88 @@ + + + + + Index - CPFE 7.0 documentation + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    +
    + + +

    Index

    + +
    + +
    + + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/il/index.html b/doc/il/index.html new file mode 100644 index 0000000..5f6bd8a --- /dev/null +++ b/doc/il/index.html @@ -0,0 +1,4283 @@ + + + + + 4. Intermediate Language - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    4. Intermediate Language#

    +

    The Intermediate Language is the output of the front end. It is a +representation of the source program that is passed to the back end, and +from which the back end can perform analyses, make transformations, and/or +generate object code.

    +

    The intermediate language is a “high-level” intermediate language, that is, a +representation that is close in spirit to the original source language, rather +than a “low-level” intermediate language that is close to any typical computer +architecture. That fits the EDG philosophy of the function of a front end, +i.e., that a front end should determine the meaning of a source program and +produce an intermediate language representation of the source program that:

    +
      +
    • +
      accurately represents the meaning of the program;
      +
      +
    • +
    • +
      does not destroy information;
      +
      +
    • +
    • +
      does not add constraints that are not present in the source program; and
      +
      +
    • +
    • +
      makes explicit any implicit or overloaded operations in the source program, +so that the back end does not have to have a deep understanding of the +source language and does not have to search or interpret the intermediate +language. It follows from this that the front end does not do +optimization, does not rewrite source constructs in “simpler” forms, and +does not use a machine-dependent representation. It also follows that +ambiguity and overloading resolution are completely handled by the front +end and a back end need do nothing to deal with them. The intermediate +language is a tree-structured in-memory data structure. Both declarative +and executable constructs are represented in tree form, and in fact all +declarative and executable information at all levels is tied together into +one tree. Having a pointer to the root of this tree gives one all the +information necessary to generate object code for the source program. (In +other words, the intermediate language data structure is the only +information that needs to be passed from the front end to the back end. +There is no additional hidden information.) The source code definitions of +the intermediate language tables are in the file il_def.h. However, +some introductory information is necessary before one dives into that file.
      +
      +
    • +
    +
    +

    4.1. Memory Management#

    +

    Memory management may seem like a strange place to begin an overview of the +intermediate language. However, an understanding of the memory management +structure is necessary to get a feeling for the overall shape of the +intermediate language tree.

    +
    +

    4.1.1. Memory Regions#

    +

    It was decided early in the design of the front end that the intermediate +language would be an in-memory data structure. That is, it exists in +directly-addressable memory and can be examined without recourse to special +access routines. This is beneficial from the point of view of compilation +speed and ease of programming. However, it could be problematic from the point +of view of memory use, especially when processing extremely large source files. +To deal with that problem, it was decided that the intermediate language should +be set up so that the parts of the tree associated with different top-level +functions are placed in separate blocks of memory that need not all be in +memory at the same time. A top-level function is any function that is not a +lambda defined in a function scope, or the instantiation of a generic lambda +defined in a function scope. Functions that are not top-level are placed in +the memory region of the enclosing function. During the processing of a single +function, the intermediate language for that function (and for other functions +in the same memory region) and for the global declarations visible to that +function must be in memory. The intermediate language for all other functions, +however, is not needed at that time, and can be written out to a file or +otherwise removed from the active address space. As a result, a large source +program looks more like a sequence of reasonably-sized functions and uses +memory accordingly.

    +

    These blocks of memory are called “memory regions”. There is a memory region +for the file scope intermediate language and one for the intermediate language +of each top-level function of the source program.

    +

    The memory region scheme is a two-level scheme: there is a file scope memory +region which is always in memory, and a set of function scope memory regions of +which only one is guaranteed to be in memory at a given time. C++ lambdas +defined in function scopes are handled by placing them in the same memory +region as the enclosing function. Member functions of local classes in C++, +while somewhat similar to lambdas, are treated (with some careful allocation of +entities) as top-level functions and have their own memory regions.

    +
    +
    +

    4.1.2. Memory Regions and Pointers#

    +

    The memory management structure has an effect on pointers in the intermediate +language. Clearly, a pointer to an entry in a function scope memory region is +valid only if the associated memory region is actually in memory. Rather than +requiring dynamic checking of pointer legality, we decided to make a rule about +how pointers may be used. Specifically, entries within a function scope memory +region may only be pointed to from within that memory region. Entries in the +file scope memory region may, of course, be pointed to from anywhere, since +they are always in memory.

    +

    This rule has some consequences. The most important one is that anything that +must be referenced from more than one memory region must be allocated in the +file scope memory region. Specifically, since functions may be called from +many other functions, they must have some representation in the file scope +memory region. Of course, since the whole point of the function scope memory +regions is to avoid having everything in memory at one time, it wouldn’t make +sense to put the entire routine into the file scope memory region. What’s done +instead is to put the description of the interface to the routine (i.e., what’s +needed to call it) in the file scope memory region, and the description of the +implementation of the routine (i.e., what’s needed to execute it) in the +function scope memory region. Similarly, local static variables of functions +must be allocated in the file scope memory region because they are potentially +referenced from member functions of classes local to the function.

    +

    A second consequence is that anything referenced from the file scope memory +region must also be allocated in the file scope memory region. [1] This +second consequence becomes significant when combined with another intermediate +language decision, that of placing all entities with external visibility at the +file scope. [2] Placing the declaration of an external entity at the file +scope means placing all of the entities it references in the file scope memory +region, and that means placing all the entities they reference in the file +scope memory region. The practical consequence of all that is that all types +must be allocated in the file scope memory region, since it is not possible to +know at the time they are allocated whether or not they will be used as part of +the type of some external entity. In C++, that means in particular that all +classes are allocated in the file scope memory region (except for the bodies of +member functions). Likewise, all namespaces are allocated in the file scope +memory region except for the bodies of namespace member functions.

    +

    It is important to bear in mind that the file scope memory region is not the +same thing as the file scope. They are similar but not identical. The file +scope is a language concept: it is the outermost scope in a C or C++ program. +The file scope memory region is a memory management concept referring to a +block of memory whose contents must always be accessible. All entities in the +file scope are allocated in the file scope memory region, but some entities +allocated in the file scope memory region are function-scope entities, some are +function-scope entities moved to the file scope because they are externally +visible, and some are class or namespace members allocated in the file scope +memory region because all classes and namespaces are allocated there.

    +
    +
    +
    +

    4.2. Intermediate Language Files#

    +

    The intermediate language and memory management scheme are set up to allow but +not require the use of files to save the intermediate language. The front +end’s connection to a back end can be configured in a number of ways:

    +
      +
    • +
      The entire intermediate language tree can be passed in memory to the back +end. This is fastest but uses the most memory.
      +
      +
    • +
    • +
      The intermediate language can be written to a file on a +per-top-level-function basis and read back in on a per-top-level-function +basis in the back end. (Only one file is used, but the intermediate +language for each function is written separately and the memory involved is +reclaimed immediately.) This is slowest but uses the least memory.
      +
      +
    • +
    • +
      The intermediate language can be processed on a per–top-level-function +basis in some other way, then thrown away. For example, the intermediate +language can be translated to another intermediate language used by the +back end, and the original intermediate language can be discarded.
      +
      +
    • +
    +
    +
    +

    4.3. C versus C++ Intermediate language#

    +

    The intermediate language generated for C++ is a superset of the intermediate +language generated for C.

    +

    For the sake of customers that have an existing C back end, EDG provides a +optional and separate “IL lowering” pass that translates the C++ intermediate +language into the C intermediate language. Note that although the process is +called “lowering,” the resulting C intermediate language is still “high-level”; +it’s just not as high-level as it was. Also note that the IL lowering process +does some implementation of C++ features (e.g., virtual function tables, name +mangling, pointers-to-members, constructor and destructor wrapper code) which +are just abstractions in the unlowered IL. Clearly, a back end has the most +latitude in generating code for C++ if it starts with the unlowered C++ IL, but +it also has quite a bit more work to do. On the other hand, an extra pass over +the intermediate language takes time, so a configuration that uses the IL +lowering pass will not be as fast as one that does not use it.

    +

    The IL lowering pass is useful because

    +
      +
    1. it allows customers to get a C++ compiler going in minimal time;

    2. +
    3. if the features implemented by IL lowering require some minor changes, +the changes can be made in IL lowering, which is relatively small, rather +than in the front end as a whole, which is quite large; and

    4. +
    5. if a customer wants to attach a back end to the unlowered IL (either +initially or for an improved release of a compiler), the IL lowering code +serves as a guide to the tasks that must be done.

    6. +
    +

    The description of the intermediate language in this chapter is for the +unlowered IL. All C++-specific features are rewritten or removed by the IL +lowering, which means that some of the description in this chapter is of no +interest to a back end that uses the lowered IL. If there is some question +about whether or not a feature would remain in the lowered IL, the description +will indicate what effect IL lowering has.

    +

    There is no way at present to compile the C++ front end so that the IL that it +generates includes only the C IL definitions. Even though IL lowering will +eliminate uses of non-C features, the C++-specific fields and enumeration +values are still present in the source code. Back ends should ignore those +fields (they are not necessarily cleared) and should expect to get IL that is +valid C when one considers (only) the fields that C uses.

    +

    One catch: Dynamic initialization of entities in the middle of blocks is left +in its original form. This is not “incorrect” C IL, but is something that does +not come up in C(89) programs. It was judged that back ends would be capable +of dealing with the stmk_init statements even if they appear after other +executable statements in a block, and the alternative was to make lowering of +initialization of aggregates to constants quite messy.

    +

    Similarly, the initialization statement attached to an stmk_for is always a +simple stmk_expr in C, but in C IL generated by IL lowering, it can be an +arbitrary statement.

    +
    +
    +

    4.4. C99 and the Intermediate Language#

    +

    The ANSI/ISO C standard was updated in 1999, and the resulting version of C +is referred to as C99. The C/C++ front end supports C99 (as well as later +versions). In some cases, the IL has been extended to support newly-added +features of C99.

    +

    The IL extensions for C99 and later revisions are enabled by the macro +C99_IL_EXTENSIONS_SUPPORTED. If that macro is set to FALSE, C99 and +later modes can still be enabled, but all features that require the IL +extensions are disabled. Note, in particular, that if your interest is +only in supporting C++, or only C89, turning off these features will make +it slightly easier to write a back end, because you will have to implement +fewer IL constructs.

    +

    There is a lowering phase for C99, which rewrites many of the extensions into +standard C89 IL. This lowering phase is enabled by the macro +DO_IL_LOWERING.

    +

    See C99 features for a detailed list of C99 IL constructs. That list +summarizes the lowering done for each construct; there is more detail in the IL +Lowering chapter of this document.

    +
    +
    +

    4.5. C++/CLI and the Intermediate Language#

    +

    The front end supports the Microsoft C++/CLI language, a set of extensions to +C++ to allow programmers to interface to Microsoft’s .NET, which is a +heap-based garbage-collected environment in the style of Java or C#. There is +an ECMA standard for the C++/CLI language (ECMA 372), but the real standard is +the MSVC compiler, as it diverges from the ECMA document in significant ways.

    +

    The C++/CLI extensions involve new types, new expression operators, new member +function kinds, new declarations, and new statements. Those are covered in +detail in the appropriate sections of this document. The data structures and +code for those features are included when MICROSOFT_EXTENSIONS_ALLOWED is +TRUE; there is no separate macro for C++/CLI to control their inclusion. The +features are enabled only when cppcli_enabled is TRUE, and there is a macro +CPPCLI_ENABLING_POSSIBLE that when FALSE (the default) prevents the C++/CLI +features from being enabled. So if you do not want to support C++/CLI, leave +CPPCLI_ENABLING_POSSIBLE set to FALSE and you will never see any of its +features in the IL.

    +

    Note that C++/CLI is supported only when the front end is hosted on Windows. +Also note that C++/CLI is Microsoft’s second version of a C++ interface for +.NET; there was a previous set of extensions called “Managed C++”. The front +end does not support those features (and Microsoft is moving away from +supporting them as well).

    +
    +
    +

    4.6. Memory Region Processing Order#

    +

    When a file is compiled, the processing order of memory regions will look like:

    +
      +
    • +
      Start file scope memory region (1).
      +
      +
        +
      • +
        Start function scope memory region (2).
        +
        +
      • +
      • +
        End function scope memory region (2).
        +
        +
      • +
      • +
        Start function scope memory region (3).
        +
        +
      • +
      • +
        End function scope memory region (3).
        +
        +
      • +
      • +
        Etc.
        +
        +
      • +
      +
    • +
    • +
      End file scope memory region (1).
      +
      +
    • +
    +

    When IL lowering is done, it is done as each memory region is ended. When IL +files are written, they are written as each memory region is ended (after IL +lowering, if any).

    +

    When the front end instantiates functions or generates routines (like +constructors), there can be brief periods when multiple function scope memory +regions are active. The function scope memory region for the instantiated or +generated routine is started and ended while the primary function scope memory +region is still active. If this process kicks off instantiation or generation +of other routines, there can be many active function scope memory regions.

    +
    +
    +

    4.7. General Information#

    +

    Each major type of entity in the C/C++ language has a corresponding +intermediate language entry. For example: a_constant, a_type, +a_variable, a_routine, a_label, a_statement, and +an_expr_node. Each entry kind has a fixed size except for the entries +representing strings (used for literal strings and names), which have a +variable length. The IL entries are not self-labeling; one must know the kind +of thing pointed to to make sense of a pointer.

    +

    The intermediate language is high-level, meaning that the entities in it +correspond fairly closely to C and C++ language constructs. For example, all +of the C and C++ expression operators are present in their original forms. +There is no remapping of complex operators (like “?”) to lower-level +operations. Statements are kept in their original structured form, and not +flattened to ifs and gotos.

    +

    Since the structure of the intermediate language corresponds so closely to the +original C or C++ form, it implies no ordering of evaluation that was not in +the original program. Timing of side effects for post-increment operations, +for example, which must be completed by the next sequence point, is not +specified explicitly. It is up to the back end to adhere to the C and C++ +language rules when generating object code for such constructs.

    +

    By convention, there can be multiple pointers to any given declarative entity +(for example, many places can point to the constant entry for 1), but only +a single pointer to any executable entity (each use of 1 in an expression +requires a distinct expression node pointing to the common constant entry for +1).

    +

    The intermediate language tables are designed to keep memory requirements +reasonably low. There are several cases where enum values are stored as +a_bytes (which means as chars of some kind), in order to ensure +that only one byte is used for those rather than whatever the host C compiler +might choose for an enum. An example of such a type is +a_constant_repr_kind. This has the unfortunate side effect that explicit +casts are often required when dealing with values of these types. There are +also several cases where, in a union that has one case that is larger than all +the others, the extra information for the unusual case is broken out as a +separate supplement that is pointed to from the union (e.g., +a_routine_type_supplement).

    +

    As mentioned, all of the intermediate language is tree-structured. The +expression i+1 is a tree with a + expression node pointing to two +expression nodes representing i and 1; the statement

    +
    if (i) i=1; else i=2;
    +
    +
    +

    is a tree with an if statement node pointing to two statement nodes for +i=1 and i=2; and the declaration

    +
    int *m[5];
    +
    +
    +

    is a variable node for m pointing to a tree defining the type “array of +pointer to int”. All the statements of a function are bundled into one +tree which is pointed to by the function definition, and all the type, +variable, and function definitions for a given scope are on a list pointed to +by the header for the scope. At the top of the entire tree for a compilation +there is a header that points to the entry for the outermost scope. Beginning +there, one can get to all of the functions and therefore all of the functions’ +scopes; one can also get to all of the classes and therefore all of the +classes’ scopes. In other words, beginning at the IL header one can reach the +entire IL tree for the compilation.

    +
    +
    +

    4.8. The IL Header#

    +

    The top of the intermediate language tree is il_header, which contains +several important pointers:

    +
      +
    • +
      A pointer to the scope entry defining the primary scope of the compilation. +This is the root of the IL tree proper.
      +
      +
    • +
    • +
      A pointer to the top of a tree of entries describing the source files from +which the source program came.
      +
      +
    • +
    • +
      A pointer to the scope_region_entry array, which gives pointers to the +scope entries that are the top of the IL tree in each of the function scope +memory regions.
      +
      +
    • +
    • +
      A pointer to the function_def_table array, which gives the pointers to +the scope entries and memory region numbers for a given function +definition.
      +
      +
    • +
    +
    +
    +

    4.9. Source File Information#

    +

    The source file information structure describes the primary source input file +and the include files of the compilation, and the relationship between them. +It is a structure distinct from the IL tree proper because the file structure +of a program need not have any relationship to its syntactic structure. An +include file, for example, could include half of a routine, or the end of one +routine and the start of another. (This is of course not typical, but it’s +possible.) Within the IL tree proper, a source line’s position is given by a +sequence number, which is the ordinal position of the source line in the +sequence of lines read by the front end, starting at the beginning of the +primary source file and switching into include files when directed to by +#include directives. The sequence number is compact and unambiguous for +internal use, and can be translated easily to a file name and line number for +external use by referring to the source line information structure. The +routine conv_seq_to_file_and_line in il.c does that translation.

    +
    +
    +

    4.10. Source Correspondence Information#

    +

    Constructs that declare constants, types, variables, routines, fields, labels, +namespaces, templates, template parameters, and macros have information on the +associated source name and the source location of the declaration. This +information is given by the source_corresp field, which is a struct of +type a_source_correspondence. A source location is specified by an entry +of type a_source_position, which consists of a sequence number and a column +number. The column number is the 1-origined column number in the original +source line (not the logical source line that results after processing +trigraphs and line splices). Tab characters count as one column, so the +“column number” may not match the apparent display position on a terminal or +printer. If multibyte characters appear, including characters that come from +files in formats such as UTF-16, they count as a single column. The node for +statements has a source location as well, but (to save space) it contains only +a sequence number and no column number (see, however, the configuration flag +FULL_SOURCE_POS_IN_IL_STATEMENT).

    +

    Aside from a pointer to the name string and the source position, the source +correspondence information contains an assoc_info pointer. This is +intended to be used by the front end and other components to store a pointer to +information maintained locally about the entity. However, the information does +not survive into the next pass. In the front end, the pointer points back to +an associated symbol entry. That pointer is no longer valid once the front end +is finished (since the space for symbol entries may have been released), but +the pointer can be set in the back end as desired.

    +

    Compiler-generated entities have no source correspondence information +(since they do not appear in the program source). Their source +correspondence name pointer is NULL.

    +

    The source correspondence information also contains the name_linkage field, +which indicates the kind of linkage the entity has (e.g., is it externally +visible? Should C++ name mangling be done on it?), an access field (which +indicates the access for class members in C++), a parent_scope pointer to +the containing scope, and a referenced field.

    +

    When IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS is TRUE, the name string +in the source correspondence entry can contain multibyte character +sequences (e.g., UTF-8 when UNICODE_SOURCE_SUPPORTED is TRUE). When it +is FALSE, multibyte characters will be represented as \mXXXX or +\MXXXXXXXX escape sequences. When a universal-character-name +(e.g., \u00d6) appears in a name, the name string will contain the`` +u``XXXX or \UXXXXXXXX escape sequence, except that when +UNICODE_SOURCE_SUPPORTED and +IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS are both TRUE the UCN value +will be represented directly. IL lowering can do some limited rewriting of +such escape sequences; see REWRITE_UCN_ESCAPE_CHAR_IN_LOWERING. Note +that these flags do not control whether or not multibyte characters are +allowed in identifiers, only how they are represented; see +MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED.

    +
    +

    4.10.1. referenced and needed Flags#

    +

    The referenced flag in a source correspondence entry indicates whether an +entity is referenced. All entities that have no source correspondence have +referenced set to TRUE. For named entities, referenced is TRUE if the +entity is referenced in the intermediate language. The reference can be +implicit: in a case like

    +
    struct s {int a;} v;
    +
    +
    +

    the struct type is referenced, but not through the name s.

    +

    The referenced flag is set correctly but simplistically. More precise +information is available in the needed flag (and, in classes and routines, +the definition_needed flag). These are optional and are selected by the +configuration switch MAINTAIN_NEEDED_FLAGS. When present, they indicate +whether or not an entity is “really” needed, and whether the definition of a +class is really needed, or merely its declaration. This is determined by +marking as needed all externally-defined functions and variables, and all the +things they reference, and all the things those things reference, etc.

    +

    Depending on the setting of DEFAULT_REMOVE_UNNEEDED_ENTITIES, possibly as +overridden by a command-line option, unneeded entities and unneeded class +definitions will be removed from the IL tree. This process, however, does not +remove all unneeded entities, because some end up being required for IL +consistency even though they are not “needed.” One example: if a class and its +definition are needed, all the members of the class must be kept in the IL even +though some of the members may not be “needed” (in the sense of being +referenced directly or indirectly from an externally defined routine or +variable). The IL after removal of unneeded entities will be self-consistent, +in that a back end that does not use the needed flags will find nothing +surprising. If a back end uses the needed flag, it should also pay +attention to the class definition_needed flag or it may find some apparent +inconsistencies in the IL tree.

    +

    The setting of the “needed” flags and the removal of unneeded IL entries work +both with and without IL lowering. When IL lowering is done, the setting is +done after lowering, so that the flags reflect the lowered code.

    +

    When ONE_INSTANTIATION_PER_OBJECT is TRUE, a more complicated set of +“needed” flags is maintained. In that mode, each instantiation is put out as a +separate object file. There is still only one IL tree, but it is marked so +that a back end can sweep through it several times and put out a different +“slice” each time, each slice containing one instantiated entity (function, +variable, or static data member) plus exactly the set of other entities needed +by that entity. This is done via a set of per-instantiation “needed” flags, +represented as a bit vector implemented as a linked list of entries of type +a_per_instantiation_needed_flags_entry attached to the +per_instantiation_needed_flags field of the source correspondence. Each +slice is assigned one bit in that bit vector, and if the bit is 1 the +associated entity is needed in the slice.

    +

    See the Needed Flags section.

    +
    +
    +

    4.10.2. Source positions#

    +

    Source position information is recorded in the IL in various ways. The +decl_position field in the source correspondence indicates the source +position of the primary declaration of an entity. When an entity has more than +one declaration, decl_position corresponds to the defining declaration or, +if there is no defining declaration, the first declaration. When +GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, source positions on declarations +other than the primary declaration are recorded in the source-sequence list – +see decl_position in a_src_seq_secondary_decl. As noted previously, +position information is also recorded in a_statement; in addition, source +position information is recorded in other IL entries that have no source +correspondence field, e.g., a_base_class, a_using_decl, +an_instantiation_directive, a_static_assertion, and a_pragma.

    +

    In applications for which additional source position information is needed, +EXTRA_SOURCE_POSITIONS_IN_IL can be configured to TRUE. Note, however, +that this information can take a lot of extra space, so the feature is disabled +by default.

    +

    When EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, source range information +(beginning and ending source positions of various syntactic constructs) is +supplied. Each source correspondence has a pointer to +a_decl_position_supplement, which includes the source range of the complete +identifier (including namespace and class qualifiers, if present), as well as +the source range of the declaration-specifiers and the declarator. For +instance, the source position information for this declaration of foo is +indicated:

    +
    inline void A::foo(A *pa) { /* ... */ }
    +               ^                    decl_position
    +            ^^^^^^                  identifier_range
    +^^^^^^^^^^^                         specifiers_range
    +            ^^^^^^^^^^^^^           declarator_range
    +
    +
    +

    Moreover, though the param-type entry for parameter pa has no source +correspondence entry, it does have a pointer to a_decl_position_supplement, +which records its source range information:

    +
    inline void A::foo(A *pa) { /* ... */ }
    +                      ^^            identifier_range
    +                   ^                specifiers_range
    +                     ^^^            declarator_range
    +
    +
    +

    Source range information is supplied for a_base_class and +a_constructor_init, as well as for the initializer construct of explicitly +initialized variables. Moreover, when GENERATE_SOURCE_SEQUENCE_LISTS is +TRUE, pointers to a_decl_position_supplement also appear in +a_src_seq_secondary_decl entries; this provides source range information on +declarations that are not the primary declaration of an entity (e.g., +friend declarations).

    +

    Source range information is also provided for expression nodes when +EXTRA_SOURCE_POSITIONS_IN_IL is TRUE. The source positions of the start +and end of the expression, along with the source position of the operator (if +present) are recorded.

    +
    +
    +

    4.10.3. Name Linkage#

    +

    The name_linkage field of the source correspondence structure indicates the +kind of linkage the name of an entity (routine, variable, class or enumeration +type, or class member) has:

    +
      +
    • +
      External linkage, used in C mode and for extern "C" entities in C++ +mode, indicates that the name is visible outside its compilation unit.
      +
      +
    • +
    • +
      C++ external linkage, for normal entities in C++ mode, indicates that the +name is visible outside its compilation unit. The name may be subjected to +some kind of name mangling.
      +
      +
    • +
    • +
      Internal linkage indicates that the entity name is visible throughout its +compilation unit (e.g., a file-scope static variable).
      +
      +
    • +
    • +
      No linkage indicates that the entity name has no connection to other +entities with the same name (e.g., a local variable).
      +
      +
    • +
    +

    From a C perspective, the name linkage information seems to be redundant, in +that it would seem that one could decide the name linkage on the basis of a +variable or routine’s storage class. In C++, however, class names (i.e., +types) have linkage, and in some compatibility modes if a class is used in the +type of an external entity, it acquires external linkage, and its static data +members and member functions also get external linkage. It gets to be very +complicated to try to encode the storage class (including whether or not it can +be changed on subsequent declarations) and the name linkage in just the storage +class field.

    +

    In addition, the routine_name_linkage field in the routine type supplement +is significant. The linkage specification in a routine type declaration can +correspond to the routine’s calling convention – for example, when extern +"C++" and extern "C" imply distinct calling conventions or an +implementation-defined linkage specification has its own calling convention. +Among other things, this means that in C++ otherwise identical functions are +distinguished for purposes of overloading based on the linkages associated with +their parameter types:

    +
    typedef void (*PF)();             // Pointer to an extern "C++" function
    +extern "C" typedef void (*PFC)()  // Pointer to an extern "C" function
    +void f(PF);
    +void f(PFC);                      // Overloads f
    +
    +
    +

    Note, moreover, that the linkage specification of a function’s name need not +be identical to the linkage specification of its type. The former might +affect how its external name is generated and the latter might affect its +calling convention.

    +
    +
    +
    +

    4.11. Access Control#

    +

    Access control information appears in several places:

    +
      +
    • +
      The access field of a_source_correspondence, which appears in most +declarative entities.
      +
      +
    • +
    • +
      using-declarations and access declarations in classes, which may adjust +the accessibility of inherited members.
      +
      +
    • +
    • +
      Base class entries, which indicate the kind of derivation from the base +class to the derived class.
      +
      +
    • +
    • +
      Lists of the friend classes and friend functions of a class. These are +also available in reversed form as befriending lists for classes and +functions, which indicate the classes which have named the befriended class +or function as a friend.
      +
      +
    • +
    +

    This information is useful to the back end only for generating symbolic +debugging information. The necessary access control checks will have been done +by the front end, and access control does not have an effect on code +generation.

    +

    Only class members are subject to access control. All other entities (and all +entities in C) will have access of as_public.

    +
    +
    +

    4.12. The Scope Entry#

    +

    Each scope in the source program is represented by a scope entry in the IL +(type a_scope). There are scope entries for:

    +
      +
    • +
      the file scope;
      +
      +
    • +
    • +
      each function definition scope;
      +
      +
    • +
    • +
      each block within a function;
      +
      +
    • +
    • +
      each “prototype” scope (for function prototypes in function declarations);
      +
      +
    • +
    • +
      each class, struct, and union type (when the type has a body);
      +
      +
    • +
    • +
      each namespace (in C++); and
      +
      +
    • +
    • +
      each condition (tested initialized variable in C++, e.g., in an “if” +statement).
      +
      +
    • +
    +

    The scope entry for the file scope is pointed to from il_header; it +contains lists of the file-scope entities in the compilation. In particular, +it points to a list of the functions in the compilation. Each function is +represented by an a_routine entry. A function without a body (i.e., an +extern function) has just a routine entry. For a function with a body, the +field assoc_scope in the routine entry gives the region number for the +memory region containing the function, which allows one to get a pointer to the +scope entry for the function scope. That scope entry points to the statements +for the function, and to lists of its parameter definitions and of local +constants, types, variables, labels, and block scopes.

    +

    One can see that the scope entry is the most important entry in terms of the +overall structure of the IL tree, in that it groups entities together into a +scope and also points down to the subscopes. Conversely, many IL entries point +back to their containing scope via the parent_scope field of their source +correspondence entry. (The scope entries themselves also contain a parent +pointer to their enclosing scope; this parent pointer is null for the file +scope.)

    +

    A scope entry points to lists of the entities that are defined in the scope: +constants, types, variables, routines, sub-scopes, etc. The lists may be used +or not depending on the type of scope:

    +
      +
    • +
      File scope (allocated in the file scope memory region):
      +
      +
        +
      • +
        types: used for tags (class, struct, union, and enum) and +typedefs. Top-level class definitions appear here.
        +
        +
      • +
      • +
        variables: used for static and external variables at the file scope.
        +
        +
      • +
      • +
        routines: used for functions both with and without definitions +(bodies).
        +
        +
      • +
      • +
        dynamic initializations: used for variables that have dynamic +initializations (eliminated by IL lowering).
        +
        +
      • +
      +
    • +
    • +
      Function or block scope (allocated in a function scope memory region):
      +
      +
        +
      • +
        types: used for tags (class, struct, union, and enum) and +typedefs that are local to the function or block. This pointer is +unusual in that it will point to a list of entries allocated in the file +scope memory region. Local classes appear here.
        +
        +
      • +
      • +
        variables: used for local static variables (one list; this pointer is +unusual in that it will point to a list of entries allocated in the file +scope memory region) and automatic/register variables (another list).
        +
        +
      • +
      • +
        scopes: for subscopes (blocks that have declarations). Note that every +{ } has an associated block statement, but a block statement only has +an associated scope if it contains local declarations.
        +
        +
      • +
      +
    • +
    • +
      Function prototype scope (allocated in the file scope memory region):
      +
      +
        +
      • +
        types: used for tags (class, struct, union, and enum) and +typedefs that are local to the prototype scope.
        +
        +
      • +
      +
      +
      Used only in C, not C++. Function prototype scopes are used to contain +types defined in prototyped parameter lists. When the function type is +part of a function declaration (i.e., there is no body), there’s nowhere +else to put the types. When the function type is part of a definition, the +prototype scope is effectively part of the function scope, but it must be +kept separate so that it can be available in the file scope memory region +as part of the information on the interface to the function.
      +
      +
    • +
    • +
      Class scope (allocated in the file scope memory region):
      +
      +
        +
      • +
        constants: used for class constants (an extension).
        +
        +
      • +
      • +
        types: used for tags (class, struct, union, and enum) and +typedefs. Nested types appear here.
        +
        +
      • +
      • +
        variables: used for static data members of the class.
        +
        +
      • +
      • +
        routines: used for member functions of the class. This includes all +member functions: static and non-static, virtual and non-virtual, inline +and non-inline, constructors, destructors, operator functions, and +conversion functions. Friend functions are not listed here (see the +friend and befriending lists under the class type and routine entries).
        +
        +
      • +
      +
    • +
    • +
      Namespace scope (allocated in the file scope memory region):
      +
      +
        +
      • +
        types: used for tags (class, struct, union, and enum) and +typedefs. Type members of the namespace appear here.
        +
        +
      • +
      • +
        variables: used for variable members of the namespace.
        +
        +
      • +
      • +
        routines: used for function members of the namespace.
        +
        +
      • +
      • +
        namespaces: used for nested namespaces.
        +
        +
      • +
      +
    • +
    +

    The entries appear on the lists in the order of declaration in the source +program, with the exception that tags and routines appear at the point where +the full definition occurs, not where the first forward reference appears. +Unreferenced entities do appear on the lists.

    +

    Not all intermediate language entities appear directly on the lists. An entity +appears on a list if:

    +
      +
    • +
      it is named in the source program; or
      +
      +
    • +
    • +
      it is a tag (class, struct, union, or enum); or
      +
      +
    • +
    • +
      it is a front-end-generated temporary variable or parameter.
      +
      +
    • +
    +

    Note that enumerated constants appear as part of the definition of the enum +tag and not ever on a constants list.

    +

    The type lists will also contain “placeholder typerefs,” which are +tk_typeref types with no name and no type qualifiers which provide +information about corresponding positions in different type lists. These are +useful to IL lowering in promoting types out of classes and namespaces. See +the section on placeholder typerefs in the IL lowering chapter of this +document.

    +

    For function scopes, the scope entry contains additional information:

    +
      +
    • +
      A pointer to the routine entry (in the file scope memory region).
      +
      +
    • +
    • +
      A list of parameter variables, and (for a nonstatic member function) a +“this” parameter variable.
      +
      +
    • +
    • +
      For constructors and destructors, a list of a_constructor_init entries +indicating initialization or destruction to be done.
      +
      +
    • +
    • +
      Labels within the function.
      +
      +
    • +
    • +
      A list of entries for computing the bounds of variable length array types.
      +
      +
    • +
    +
    +
    +

    4.13. Types#

    +

    a_type describes a type, which can be void, an integral or enumeration +type, a real, complex, or imaginary floating-point type, a fixed-point type, a +pointer, a reference, std::nullptr_t (the type of the nullptr keyword +in C++), an array, a GNU vector type, a class or struct, a union, a +function type, a pointer-to-member type, a typeref, or a fully generic +template-dependent type. Some of these type kinds – including fixed-point and +vector types – are optional (i.e., available only in specific configurations).

    +

    void, std::nullptr_t, the fixed-point types, and the floating types are +self-contained. Integer types and enumeration types point to a supplement +entry of type an_integer_type_supplement (conveniently accessed with the +macro integer_type_supp). Enumeration types are basically integer types, +with an additional pointer to either a list of a_constant entries that +define the members of the enumeration (for unscoped enumeration types), or a +scope entry (for scoped enumeration types; the scope entry then points to the +list of enumerator constants). The entries representing the enumerator +constants may, e.g., be of interest to a back end for generating symbol +debugging information.

    +

    The integral, fixed-point, and floating types are provided in a fixed set of +sizes, e.g., float, double, and long double for floating. The +sizes of the types can be configured easily, but they remain essentially +symbolic. That is, int remains int and not “integral type of size 4”.

    +

    A special type kind is used to represent “template parameters” in a broad +sense. This includes normal template parameters, but also otherwise unknown +template-dependent types like typename T::X where T is a template +parameter. This general concept “template parameter type” is also used to +represent the auto type specifier in modes that support it. The general +type kind for template-dependent types is tk_template_param.

    +

    The other kinds of types are derived types – they point to one or more other +types, and are used to build up type trees. For example, the type entry for +int can be pointed to by an array type entry to build an array of int. +A pointer type entry could be put on top of that to make a pointer to array of +int.

    +

    Derived types are built up from their constituent types in the obvious way:

    +
      +
    • +
      Array types point to the element type and indicate the number of elements.
      +
      +
    • +
    • +
      Function types point to the return type. Parameters of prototyped cases +(and of the types of defined unprototyped functions) are represented by a +list of a_param_type entries (pointed to indirectly by the type entry +via an entry of type a_routine_type_supplement).
      +
      +
    • +
    • +
      Pointer and reference types point to the underlying type. Pointers and +references are represented as variants of a common type kind.
      +
      +
    • +
    • +
      Pointer-to-member types point to the class type and the underlying type.
      +
      +
    • +
    • +
      class, struct, and union types point to a list of a_field +entries that define the members. There is a class type supplement that +provides a great deal of additional information, especially in C++. (See +below.)
      +
      +
    • +
    • +
      typedefs, type qualifiers (e.g., const and volatile), type operators such +as decltype, and various other types are represented by an entry called a +typeref, described in more detail in a subsection below.
      +
      +
    • +
    +

    Simple types are shared. For example, there would only be one type entry for +the type int, and it would be pointed to in all cases where it is needed. +There is also sharing of pointer types, reference types, pointer-to-member +types, and qualified types: the based types list pointer in a type entry points +to a list of types based on the type (e.g., pointer-to the type); when a based +type is created, it is placed on the list and can thereafter be found and +reused.

    +

    Types include information indicating their size and alignment (but beware of +typerefs, which normally have no size or alignment of their own [3], +and function types, which have no size or alignment). The sizes and alignments +are set by routines in types.c and class_decl.c and are taken on faith +in the rest of the front end. Incomplete types have size zero and have the +flag incomplete set to TRUE. Other types (including classes that contain +no nonstatic data members) normally have sizes greater than zero (some C and +C++ dialects treat some completely defined types as having size 0).

    +

    When support for near and far is enabled (e.g., in 16-bit Microsoft +mode), the near and far memory attributes are encoded as type +qualifiers. A qualifier appears only if it is not the default. For example, +if the source specifies far and the default in that context is far, no +qualifier is added. Back ends that need to know about memory attributes can +check the size of individual pointers (i.e., does the pointer have the size of +a far pointer) or use the function is_far_type (e.g., to determine the +calling method for function types). The memory attributes appear only when +il_header.near_and_far_enabled is TRUE; see also NEAR_AND_FAR_ALLOWED.

    +

    When support for named address spaces is enabled (a feature of Embedded C), +named address spaces are also encoded as type qualifiers. Unlike other +qualifiers, named address spaces are not encoded as a bit vector (e.g., a bit +per address space) but as a small integer indicating which address space is +selected (zero represents “no specific address space” which is sometimes +referred to as “the generic address space”). This small integer can be used as +an index in the array named_address_spaces; this array is defined in +targ_def.h and can be configured to describe the address spaces of a +particular target.

    +

    Variable length array types are a special case, because the number of elements +in the array is computed at run time, and so the dimension is represented as an +expression. However, the type itself cannot point to the dimension expression, +since the former belongs to the file-scope memory region and the latter to a +function-scope memory region. Instead, the flag has_assoc_vla_dimension is +set in the type entry, and the dimension expression is stored in an entry of +type a_vla_dimension, which appears on a linked list pointed to by the +routine’s IL scope entry (see find_vla_dimension in il.c). When the +bound of a VLA is unspecified (e.g., because it was declared with the [*] +syntax), is_vla will be TRUE but has_assoc_vla_dimension will be FALSE.

    +
    +

    4.13.1. Typerefs#

    +

    Typerefs are used to record additional information for existing types:

    +
      +
    • +
      typedefs giving a name for a type,
      +
      +
    • +
    • +
      type qualifiers such as const and volatile,
      +
      +
    • +
    • +
      typeof (a GNU extension) and decltype (a C++11 feature) constructs,
      +
      +
    • +
    • +
      specializations of alias templates,
      +
      +
    • +
    • +
      type splices (a C++26 feature),
      +
      +
    • +
    • +
      type-returning traits,
      +
      +
    • +
    • +
      type-transforming attributes,
      +
      +
    • +
    • +
      dependent type pack index specifiers, and
      +
      +
    • +
    • +
      (when configured with DEFAULT_RECORD_FORM_OF_NAME_REFERENCE set to TRUE) +lexical information such as nested name qualifiers and alternative template +arguments.
      +
      +
    • +
    +

    Typeref type entries point to a typeref type supplement containing additional +information such as template argument lists, nested name qualifiers, and +operands of type operators.

    +

    For qualified pointer types, the typeref indicating the qualifier is on the +type of the pointer type: for int *const q the type is a const typeref +pointing to a pointer type entry, which points to an entry for int. +(By comparison, const int *q produces a pointer type entry pointing to +a const typeref, which points to an entry for int.)

    +

    It is often necessary for code that deals with types to access the target of a +typeref or chain of typerefs. Various convenience functions are provided for +this purpose, including skip_typerefs, skip_typerefs_not_typedefs, +skip_lexical_typerefs, etc.

    +
    +
    +

    4.13.2. Class Types#

    +

    Class types are class, struct, and union types [4]. Their +associated type entry always points to a class type supplement (conveniently +accessed with the macro class_type_supp), which carries additional +information especially relevant to C++.

    +

    In C, a struct or union type is relatively simple, and is defined by a +list of a_field entries. Each entry defines one field (member) of the +struct or union. The offset of a field is given as the combination of +a byte offset (the offset field) and a bit offset (the +offset_bit_remainder field). The latter is nonzero only for bit fields +(i.e., when is_bit_field is TRUE); a bit field also has a nonzero +bit_size, and its type (an integral type) is significant only as an +indication of the base type specified in the source program. Enum types and +integral types smaller than int can appear as the base type for a bit +field. A separate flag bit_field_is_signed indicates whether or not the +bit field is signed. Unnamed fields in the source program, which affect the +offsets of the fields that follow them (i.e., they introduce gaps), also appear +in the list of fields for the struct.

    +

    An associated scope is defined for a struct or union in C even though +the C language doesn’t really associate a scope with those constructs. The +scope is used only to represent the parent of the type’s fields. The type does +have a class type supplement, but that’s mostly necessary so that the pointer +to the associated scope can be recorded; the rest of the class type supplement +is irrelevant in C.

    +

    In C++, the fields are the nonstatic data members of the class, and the class +type supplement gives additional information about the class:

    +
      +
    • +
      A list of the base classes of the class (both direct and indirect).
      +
      +
    • +
    • +
      A list of the using-declarations (and access adjustments, from access +declarations), of friend classes and functions, and of classes that have +befriended the class. These are of interest to a back end only for +generating symbolic debugging information. Note that the friendship +information is available in normal and reversed forms: the “befriending” +information is backwards from the source form – it appears on the class +that is befriended, not the one that granted the friendship with a +friend declaration.
      +
      +
    • +
    • +
      A scope entry for the class, which contains the definitions of the static +data members (as variables) and member functions (as routines) of the +class. The scope is present only if the class has been defined.
      +
      +
    • +
    +

    The nonstatic data members are listed in declaration order, which (with the +default class allocation scheme) is the same as allocation order. Members of +base classes are not listed in the derived classes, even though they are in +some sense present by inheritance.

    +
    +

    4.13.2.1. Base Class Entries#

    +

    A base class entry describes a specific base class of a specific derived class. +It’s more than just the type of a base class – it describes how that class +type relates to the derived class:

    +
      +
    • +
      Where the storage for the base class appears in the derived class.
      +
      +
    • +
    • +
      The derivation path from the derived class to the base class; for virtual +base classes there may be more than one such path.
      +
      +
    • +
    • +
      The type of derivation, e.g., is the base class a virtual base class?
      +
      +
    • +
    • +
      The list of virtual functions of the base class that are overridden in the +derived class. (This information is useful for generating virtual function +tables.)
      +
      +
    • +
    +

    Base class entries are used for indirect base classes (i.e., base classes of +base classes) as well as for direct base classes.

    +

    The base classes list for a given class lists all of the base classes of the +class all the way down, in depth-first left-to-right order (i.e., an indirect +base class precedes the direct base class derived from it; not coincidentally, +this is the order defined by the language as initialization order.) A +nonvirtual base class can appear more than once on the list – it is marked as +ambiguous – but a virtual base class will appear only once, though it may have +more than one derivation path.

    +

    Base class entries are used in the IL wherever it is necessary to provide an +unambiguous specification of a base class instance.

    +
    +
    +

    4.13.2.2. Class Scopes#

    +

    If a class is defined, its class type supplement will point to a scope entry +that defines the contents of the class (except the nonstatic data members, +which are provided by the field list of the class type). The class scope will +contain:

    +
      +
    • +
      Constants, for class constants (an extension).
      +
      +
    • +
    • +
      Types, for types defined within the class (including nested classes).
      +
      +
    • +
    • +
      Variables, for static data members and instances of variable templates.
      +
      +
    • +
    • +
      Routines, for member functions, including static and non-static, virtual +and non-virtual, inline and non-inline, constructors, destructors, operator +functions, and conversion functions, but not friend functions. The routine +entries indicate any special attributes of each function, but the routine +list is just a list in declaration order. It’s not broken into sections or +indexed in any way. The only way to find all virtual functions, for +example, is to go through the list and examine each routine to see if it is +virtual.
      +
      +
    • +
    +
    +
    +

    4.13.2.3. Class Member Declaration Lists#

    +

    The lists described above group the members of a class by category, and none of +them accounts for constructs like a static_assert declaration, which +declares nothing. When MAINTAIN_CLASS_MEMBER_LIST is configured to TRUE, +the class type supplement of every defined class also points to the +member_declarations list, which has one an_il_entity_list_entry per +declaration that appeared in the body of the class, in the order in which the +declarations appeared. For example, the list built for

    +
    struct S {
    +  static_assert(sizeof(int) == 4);
    +  int a, b;
    +  template <class T> void f(T);
    +  friend void g();
    +  enum E { e1, e2 };
    +};
    +
    +
    +

    identifies, in order, a static assertion, a field (a), a field (b), a +template, a routine, and a type.

    +

    Note that:

    +
      +
    • +
      A friend declaration that appears in the body is included even though the +entity it declares is not a member of the class.
      +
      +
    • +
    • +
      Entities that are not explicitly declared in the body are not included: +that is the case for members that the front end generates (e.g., an +implicitly-declared default constructor) and for template instantiations +that are triggered while the body is being processed. A member that is +explicitly defaulted or deleted is declared, and is therefore included.
      +
      +
    • +
    • +
      An anonymous union is represented by the entry for its type; no entry is +created for the unnamed field through which the members of the union are +accessed (that field can be reached through the +anonymous_union_field pointer of the class type supplement).
      +
      +
    • +
    • +
      The closure class of a lambda expression that appears in the body (e.g., +in a default member initializer) is not included; that class is reached +through the a_lambda entry for the expression.
      +
      +
    • +
    • +
      An enumerator is not included because the declaration of its enumeration +type is; the enumerators can be reached through that type.
      +
      +
    • +
    • +
      A member template is represented by the entry for its template, not by an +entry for the prototype instantiation of the templated entity (see +Templates).
      +
      +
    • +
    • +
      A using-declaration that names an overload set (or, with using +enum, an enumeration) produces several a_using_decl entries but only +one entry on the list.
      +
      +
    • +
    • +
      An entity that is declared more than once in the body is represented by one +entry per declaration. For example, a nested class that is first declared +and later defined in the same body appears twice.
      +
      +
    • +
    +

    The list of an instantiated class template specialization describes the +declarations of the instantiated body.

    +
    +
    +

    4.13.2.4. Class Layout#

    +

    Class layout is done by routines in layout.c, and the decisions made are +recorded in the IL in the form of offsets, sizes, and alignments. The class +layout can be configured in various ways, or can be replaced in its entirety. +Class layout decides on:

    +
      +
    • +
      Offsets of nonstatic data members (fields) within the class.
      +
      +
    • +
    • +
      Offsets of base classes within the class. For virtual base classes, +offsets of the information that allows access to the virtual base classes +(typically, a pointer to the virtual base class).
      +
      +
    • +
    • +
      Offsets of virtual function information (typically, a pointer to a virtual +function table).
      +
      +
    • +
    • +
      Ordering of base classes and members, and insertion of necessary alignment +between them.
      +
      +
    • +
    +

    Virtual function table pointers and virtual base class pointers can be shared +with base classes. That is, space for such pointers need not be allocated in a +derived class if they are present in a base class; the derived class can use +the pointer in the base class.

    +

    There are many configuration macros that control class layout. See +targ_def.h.

    +
    +
    +

    4.13.2.5. C++/CLI Types#

    +

    In addition to the standard types, C++/CLI has

    +
      +
    • +
      handle and tracking reference types, which are represented as +tk_pointer types, but aren’t considered to be standard pointers or +standard references;
      +
      +
    • +
    • +
      interior_ptr and pin_ptr types, which are variants of standard +pointer types with certain added attributes and restrictions (they only +appear as the types of local variables, parameters, or return types);
      +
      +
    • +
    • +
      managed class types (refstruct, refclass, valueclass, interfaceclass), which are represented like standard +class types, with a value in the cli_class_type_kind field that +indicates the kind of managed class;
      +
      +
    • +
    • +
      enumclass types, which are similar to C++11 scoped enum types and +similarly represented;
      +
      +
    • +
    • +
      CLI array types, which are represented as managed class types tagged with +the is_cli_array field; and
      +
      +
    • +
    • +
      delegate types, which are represented as managed class types tagged with +the is_delegate_class field.
      +
      +
    • +
    +

    Fundamental types usually have corresponding value class types (e.g., int +corresponds to the System::Int32 value class type). In general, types +written in the source in either form are converted to the fundamental type +version. In cases where a managed type is required, the fundamental type is +converted to the value class, so for example “int ^” becomes “handle to +System::Int32” as soon as it is created. Otherwise, conversions between +the two kinds of types are always indicated explicitly. In particular, in +expressions a conversion from one form to the other will be indicated +explicitly, e.g., with a box or unbox operator.

    +
    +
    +
    +
    +

    4.14. Namespaces#

    +

    Namespaces are represented by entries of type a_namespace. Such an entry +is used for a namespace definition, in which case it points to a scope entry +that describes the contents of the namespace, and also for a namespace alias, +in which case it points to another namespace entry.

    +

    Entries of type a_using_decl describe using-directives and +using-declarations that appear in the source program. This +information is not needed for code generation, but may be useful in the +generation of symbolic debug information or for source-to-source +translation.

    +
    +
    +

    4.15. Constants#

    +

    a_constant describes a target machine constant, which can be an integer, a +string, a fixed-point constant, a floating-point constant, a complex or +imaginary constant, an address, or a pointer-to-member. Nontype template +parameters and the UPC identifiers THREADS and MYTHREAD are also +represented using a_constant entries. The constants are kept in target +form, and should not be manipulated without using the target-specific routines +for that purpose. Fixed-point constants are stored as a_fixed_point_values. Floating-point constants are stored as an_internal_float_value. String +constants are stored as a string of bytes in the target character set with an +associated length (to avoid any question about extra or missing null characters +in the string). The text of string constants is always allocated in the file +scope memory region to avoid some memory region problems.

    +

    Integers are usually maintained in a host large integer +(a_host_large_integer/a_host_large_unsigned) regardless of the size +or signedness of their actual integral type. They are always properly +masked and sign extended. If a host large integer is insufficiently large, +the front end can be configured to use a more general (but computationally +less efficient) representation of integer values (see the configuration +macro INTEGER_VALUE_REPR_IS_A_HOST_INTEGER). In either case, +an_integer_value is the type to use internally to represent an integer +constant.

    +

    Constants are also used as initial values of variables. When those variables +are aggregates (arrays or classes), some special kinds of constant entries are +used to represent aggregates of constants and repetition of constants within +those aggregates. Such constants are acting more as a structuring entity than +as simple constants; it’s just convenient to use the a_constant entry for +that function as well. Getting even farther afield, there is even a constant +kind (ck_dynamic_init) that indicates an element in an aggregate constant +that is in fact not a constant at all, and must be computed at run time and +placed at that position in the aggregate. The structure of the aggregate +constant will match the structure of the variable being initialized. For +example, the initial value for a variable whose type is “array of 4 structures +containing 2 integer fields” will be an aggregate constant containing a list of +four constants, each of those an aggregate constant containing a list of two +integer constants. Aggregate constants need not fully initialize an aggregate +(i.e., there may be fewer constants than there are members of the aggregate); +any members not explicitly initialized are implicitly initialized to zero (even +when the variable being initialized is non-static).

    +

    Most constants, specifically those used in expressions, are shared and reused, +so that only one constant 0, for example, need be allocated. Constants +used as constant initial values, however, are (and must be) unshared. [5] +Since the aggregating kinds of constant entries are only used in initial +values, it follows that they are always unshared. In pcc mode, string +constants are considered writable and are not shared.

    +

    In some cases, a program may include a cast of a constant value to another +type, and the result (clearly constant) may be unrepresentable in any of the +normal forms. An example is an integer constant cast to a pointer type. For +these situations, the a_constant entry has the implicit_cast field. +When set, it indicates that the value of the overall constant is to be the +constant value cast to the type indicated by the type field. The back end +must determine the exact value to be used.

    +

    Address constants are used to refer to the addresses of variables, +functions, string literals, etc. The offset in address constants is +expressed in bytes and is not scaled by the size of the object pointed to +(unlike in the C and C++ languages). Address constants are only used for +addresses that are truly constant, not, for example, for the addresses of +auto variables. Note, however, that the constant value may not be +known until link time, i.e., it might not be a compile-time constant.

    +

    Pointer-to-member constants represent the location of a particular data member +or member function of a class within an arbitrary instance of that class, i.e., +what is written in source as something like &A::xx (with xx a nonstatic +member of A). They are defined in a high-level form rather than (for +example) as an offset within the class, to leave it to IL lowering or the back +end to choose an implementation for pointers to members.

    +

    Wide character constants are represented as integral constants. Wide string +literals are represented as string constants. There are routines in +literals.c that do the necessary packing.

    +

    When character or string literals contain a universal-character-name (e.g., +\u00d6), the UCN value is converted from Unicode to the appropriate +character value or multibyte character sequence and stored in the string.

    +

    In C++/CLI, string literals start out as standard C++ string constants, and are +converted to C++/CLI strings if the context requires it. So, for example, if a +standard string literal is passed as an argument to a function that takes a +parameter of type “System::String^”, the string will be converted to +a C++/CLI string. This is done by setting the constant type to “handle to +System::String” without setting the implicit_cast flag. There is no +conversion of the characters in the string to Unicode (or in any other way), in +spite of what the ECMA standard seems to require. Wide string literals can +also be converted to C++/CLI strings in this way, and in that case the string +contents are treated as Unicode (as they always are in Microsoft mode, and +therefore in C++/CLI mode; but still no conversion is done). Having C++/CLI +strings represented as constants is a little strange, since ultimately they +have to result in creation of a class object on the heap, and use of its – +non-constant – address; however, MSVC treats such strings as constants, so +emulating the Microsoft compiler is easier when they are represented as +constants. It is left to back ends to transform these constants into +executable code as needed.

    +

    The front end generally attempts to fold constant-expressions into a single +a_constant node. The expression that led to the constant is also recorded +in the expr field in the a_constant entry. If this field is nonnull, +it points to the expression tree which produced the constant when folded; the +resulting constant is not shareable.

    +
    +
    +

    4.16. Variables#

    +

    a_variable describes a variable, parameter, static data member, instance of +a variable template, temporary, or structured binding. It indicates the type +and storage class. The storage class can be sc_auto, sc_register, +sc_static, sc_extern (meaning a reference to an external variable +defined in another compilation), or sc_unspecified (meaning a definition of +a variable visible to other compilations). The storage class is standardized +during declaration processing. Parameter variables can only have storage +classes of sc_auto or sc_register. File-scope and namespace scope +variables, instances of variable templates, and static data members can only +have storage classes of sc_static, sc_extern, or sc_unspecified. +Function- and block-local variables can only have storage classes of +sc_auto, sc_register, or sc_static.

    +

    Variables declared with a named-register storage class (an Embedded C +extension) have storage class sc_unspecified (not sc_register) but also +have the flag has_named_register_storage_class set to TRUE. The register +is described using a small integer stored in the variant field +asm_name_or_reg.id, which can be used to index the array +named_register_storage_classes. This array is defined in targ_def.h +and can be customized to describe the named-register storage classes available +on a particular target.

    +

    If the variable has an initial value, the field init_kind indicates whether +the variable should be statically initialized to a constant value (simple or +aggregate) or dynamically initialized to a constant or non-constant value +(simple or aggregate). In the dynamic initialization case, the variable points +to a dynamic initialization entry that indicates the initialization to be done. +(More on this below.) Note that static initialization is never used for +non-static local variables, even ones initialized with a constant value: static +initialization initializes the entity once, at program startup time, whereas an +automatic local variable must be initialized each time the function is invoked +and the variable declaration is reached. Structured bindings (a C++17 feature) +that refer to array elements or to fields are represented as variables, but +they are really aliases for simple expressions referring to parts of the +associated (unnamed) container variable. These bindings have an +initk_binding initializer kind and point to the aliased expression via +initializer.binding. Structured bindings that bind to a +std::tuple-like container are ordinary reference variables with +initk_dynamic initializers.

    +

    An uninitialized static variable is considered to be implicitly initialized to +zero. There is also an initk_zero initialization kind, which can be used +to explicitly initialize a variable to zero, statically or dynamically. On an +external variable, such initialization has the added function of indicating +that the variable is a true definition rather than a tentative definition.

    +

    If the address of the variable has been taken anywhere (implicitly by +conversion of an array to a pointer or in binding of a reference, or explicitly +by use of the & operator), the flag address_taken will be set.

    +

    If a variable is a local static variable of a function, +referenced_non_locally is TRUE if the variable is referenced from a +different function, specifically from a member function of a local class. This +may have an effect on aliasing analysis.

    +

    Local static variables create a memory-region difficulty: the variable entry +must be allocated in the file scope memory region, because the variable can be +referenced from the bodies of member functions of local classes. Dynamic +initialization of the variable, however, can be based on an expression +referencing a local (nonstatic) variable of the function, and therefore the +dynamic initialization must be allocated in the function scope memory region. +The a_local_static_variable_init entry solves this problem. When a local +static variable has initialization that must be allocated in the function scope +memory region, the variable init_kind is set to initk_function_local. +This is an indication that the variable is initialized, but details of the +initialization are not available in the file scope. In the function or block +scope in which the variable is defined, there will be +a_local_static_variable_init entry on the local_static_variable_inits +list of the scope. That entry will point to the variable, and give the +initialization details. Conceptually, the initialization information in the +local initialization entry is part of the variable information (it provides the +true values for the init_kind and initializer fields of the variable); +it’s in a different place because of memory region issues. The routine +get_variable_initializer can be used to fetch the complete initializer +information for a variable. It will search for and retrieve the function-local +information when necessary. Local static variables with initial values that +are simple (non-aggregate) constants always use initk_static initialization +rather than the initk_function_local form. This is done so that the values +of integral constant variables can be retrieved as constants while compiling +local classes. initk_function_local is used for dynamic initialization and +for aggregate constant initialization.

    +

    Temporary variables are generated by IL lowering, for class temporaries and +when initializing references. Temporary variables are also generated for +anonymous unions; see Anonymous Unions for more information.

    +
    +
    +

    4.17. Dynamic Initialization#

    +

    A dynamic initialization entry (type a_dynamic_init) is used to represent +initializations that require the execution of code at runtime, i.e., that +cannot be done as static initializations to a constant.

    +

    The kind field of the entry indicates the kind of initialization to be +done:

    +
      +
    • +
      Initialization to a constant. Note that this is different than static +initialization to a constant, in that it gets done at a particular time and +possibly more than once. The constant here is unshared and may be an +aggregate (one that is completely constant).
      +
      +
    • +
    • +
      Initialization to an expression. An expression is evaluated and its value +is the initial value.
      +
      +
    • +
    • +
      Initialization by a constructor. A constructor routine is called to +initialize the entity.
      +
      +
    • +
    • +
      Initialization by a routine returning a class object. A routine is called +and the value it returns (by calling a copy constructor) initializes the +entity.
      +
      +
    • +
    +

    A dynamic initialization entry can also indicate a destructor that must be +called to destroy the entity initialized. [6] Such dynamic +initialization entries will be linked onto the destructions list of an +object lifetime entry. The destruction is to be done any time the region +of the object lifetime is exited, and IL lowering generates the appropriate +destructions. See Object Lifetimes.

    +

    A dynamic initialization entry indicates what the initialization is to +do, but it does not indicate where the initialization is to be done +(except if the entity being initialized is a complete variable), and it +does not indicate when the initialization is to be done. Dynamic +initialization entries are used in several cases, and the context in each +case provides the additional information needed:

    +
      +
    • +
      For initialization of file-scope variables, instances of variable +templates, or static data members, the variable points to the dynamic +initialization entry, and the dynamic_inits list from the scope entry +for the file scope indicates the order in which the initializations should +be performed. Variables from namespaces also appear on this same list, +since their initializations are intermixed with those of the file-scope +variables.
      +
      +
    • +
    • +
      For initialization of function and block variables, the variable points to +the dynamic initialization entry, and there is an stmk_init statement +in the executable code of the function that points to the same dynamic +initialization entry and indicates the point at which the initialization +should be done. An stmk_init statement can appear in the same block as +the variable declaration or in a nested block. If the variable is a local +static variable, the initialization is to be done only the first time the +stmk_init is reached, and corresponding end-of-program destruction must +be done only if the initialization was done. Note that if a local variable +uses dynamic initialization it must have an associated stmk_init +statement.
      +
      +
    • +
    • +
      For initialization of temporaries in the middle of expressions, an +enk_temp_init node points to a dynamic initialization entry that +indicates the initialization to be done.
      +
      +
    • +
    • +
      For initialization of storage allocated by new, an enk_new_delete +node points to a dynamic initialization entry that indicates the +initialization to be done. These dynamic initialization entries never +indicate destruction.
      +
      +
    • +
    • +
      For destruction of storage in a delete, an enk_new_delete node +points to a dynamic initialization entry that indicates the destruction to +be done. These dynamic initialization entries never indicate +initialization.
      +
      +
    • +
    • +
      For initialization of members in a constructor-initializer (either +user-written or front-end-generated), an entry of type +a_constructor_init indicates the member or base class to initialize and +points to a dynamic initialization entry to indicate what to do. The order +of the a_constructor_init entries gives the order in which the +initializations should be done. These dynamic initialization entries never +indicate destruction (except when exceptions are enabled, in which case the +destructions indicated are to be done if an exception is thrown before the +constructor completes).
      +
      +
    • +
    • +
      Similarly, for destruction of members in a destructor (which can only be +front-end-generated), an entry of type a_constructor_init indicates the +member or base class to destroy and points to a dynamic initialization +entry to indicate what to do. The order of the a_constructor_init +entries gives the order in which the destruction should be done (i.e., if +one looks at a constructor and destructor for a class, the entries on the +destructor will be in the reverse order of those on the constructor). +These dynamic initialization entries never indicate initialization.
      +
      +
    • +
    • +
      For non-static data member initializers (NSDMIs), more recently renamed +as default member initializers (DMIs), the field entry initializer +field points to a dynamic initialization entry giving the initializer. +If such an initialization is not overridden in a given constructor, the +a_constructor_init entry for the field will have +use_field_initializer TRUE to indicate that the initial value comes +from the field initializer.
      +
      +
    • +
    • +
      For dynamic initialization of entities within an aggregate, for example
      +
      +
      int i[3] = {1, 2, j+k};
      +
      +
      +
      +
      dynamic initialization entries at two levels are needed. The variable +i will point to a dynamic initialization entry that indicates the +overall initialization. Because the initialization is an aggregate +initialization containing a non-constant value, the dynamic initialization +will have the kind dik_nonconstant_aggregate and will point to a +ck_aggregate constant. That constant points to a list of the constants +in the aggregate, beginning with the constants 1 and 2. Following +that is another constant entry of kind ck_dynamic_init which indicates +“this position in the aggregate is not really a constant; here’s what needs +to be done to compute it” and points to another dynamic initialization +entry, this one of kind dik_expression and indicating that the value to +use for the initialization is the expression j+k.
      +

      +
      Within the aggregate constant list, ck_init_repeat constants are used +to repeat a particular ck_dynamic_init initialization a specified +number of times. This is needed to do constructor initialization of arrays +of classes.
      +

      +
      In this aggregate case, the top-level dynamic initialization entry serves +as more of an aggregating construct than as a specification of a dynamic +initialization. It shouldn’t come as much of a surprise, then, to learn +that to specify only destruction for an aggregate, one uses a top-level +dik_nonconstant_aggregate dynamic initialization entry as is done in +the initialization case, and the destruction is specified in the +lower-level dynamic initialization entry. The troublesome thing about this +form is that one cannot tell just by looking at the top-level dynamic +initialization whether the overall construct does initialization, +destruction, or both. One must find and examine the lower-level dynamic +initialization entry.
      +
      +
    • +
    • +
      For returns from routines that return a class by value, the stmk_return +statement points to a dynamic initialization that indicates the way to +create the class being passed back to the caller.
      +
      +
    • +
    • +
      For expressions that are operands of throw, the throw expression +node points to a dynamic initialization that indicates the way to copy the +value for use by the runtime.
      +
      +
    • +
    • +
      For parameters of catch clauses, the catch clause points to a dynamic +initialization that describes the way to initialize the parameter from the +runtime’s copy of the thrown object.
      +
      +
    • +
    +

    IL lowering rewrites all dynamic initializations that are not valid in C, and +therefore constructor and destructor calls and non-constant aggregates do not +appear in the lowered IL.

    +
    +
    +

    4.18. Object Lifetimes#

    +

    In C++, class types can have associated destructors, which are called to +destroy objects of the class type at the ends of their lifetimes. These calls +are implicit: the programmer does not write them, and the compiler generates +them in the appropriate places. For example, on a goto out of a block +containing a class variable, the destructor for the variable must be called. +If there are several possible ways to exit the block (e.g., flowing off the +end, gotos, exceptions), the destructor must be called in each case.

    +

    The IL does not make the needed destructor calls explicit (in fact, for +exception handling, the needed destructor calls would be done by the runtime, +so there’s no way to put them in the IL without dictating a particular +implementation of exception handling). Instead, it gives information about +needed destructions and the associated object lifetimes in such a way that a +back end can easily generate the required destructor calls. (IL lowering puts +in those calls, so a back end working from the lowered IL need not deal with +object lifetimes.)

    +

    The IL concept of an “object lifetime” is modeled on a source language concept, +the idea that an object’s lifetime (the time during which it has a meaningful +value) might be different than the lifetime of the storage for the object. +That is, the object is constructed, used, and destroyed, and then the storage +that contained the object might remain around for some time longer, but it no +longer contains meaningful information and is no longer an object.

    +

    It should be noted that from an IL point of view, the concept of object +lifetime is only applied to objects of class types having destructors. From a +strict language point of view, other kinds of objects do have object lifetimes, +but those object lifetimes are not very interesting because they always match +the lifetime of the object storage; more precisely, in the absence of a +destructor there is no way to tell the difference between an object whose +lifetime has ended and one that is still active, as long as the storage remains +allocated to the entity. Therefore there is no benefit in associating IL +object lifetimes with entities that do not need destruction, and there is a +benefit – space savings – in not doing so. Note that this means that IL for +C programs, which by definition involve no constructors, never includes object +lifetimes.

    +

    The IL entry an_object_lifetime represents and defines an object lifetime. +There are several kinds of object lifetimes, each associated with a certain +kind of entity in the IL: [7]

    +
      +
    • +
      A static object lifetime, which lasts until the termination of the program. +For packaging reasons, there is a global static object lifetime and +possibly several function static object lifetimes (one for each function +that contains destructible local static entities). Such lifetimes are +bound to the file scope and function scopes.
      +
      +
    • +
    • +
      A block object lifetime, which lasts until the termination of a function or +block scope. Such a lifetime is bound to a function or block scope. There +is also a variant of this kind of lifetime, referred to as a +block-after-label lifetime, that lasts from a label or (in +long-lifetime-temporaries mode) a switch case or default label to the end +of the scope. The block-after-label lifetime points to a statement that is +or contains a label or to a stmk_switch_case statement, respectively.
      +
      +
    • +
    • +
      A try-block object lifetime, which surrounds the execution of a try +statement and its associated catch clauses, and is bound to a +try-supplement.
      +
      +
    • +
    • +
      An expression temporary object lifetime, which lasts until the end of a +full expression, and is bound to an expression node of kind +enk_object_lifetime, or to a dynamic initialization entry.
      +
      +
    • +
    +

    Each dynamic initialization in the IL that requires end-of-lifetime destruction +is placed on the linked list of destructions attached to the proper object +lifetime entry. The destructions in a given lifetime are linked together by +the next_in_destruction_list pointer, in the order in which they should be +destroyed (that is, the reverse of the order of construction). The +destructions pointer in the object lifetime entry points to the first +initialization on the list (the last one constructed and the first one to be +destroyed).

    +

    Not all dynamic initializations are placed on a lifetime list. Initializations +of nonclass objects, or objects of class types that have no destructors, +clearly do not need to go on lifetime lists. Even initializations of objects +of class types with destructors are put on lifetime lists only if the +destruction of the object is automatic at the end of the lifetime, e.g., not +for new (the programmer controls the time of destruction) or return by +constructor (the destruction is done by the caller, not the subroutine).

    +

    Each object lifetime has a parent_lifetime pointer, and also a +parent_destruction_sublist pointer giving the position of the child +lifetime relative to the destructions in the parent. This makes a tree +structure that one can enter at some inner lifetime and follow upward. The +path upward from a given starting point is referred to as the “cleanup chain” +starting at that point. For example:

    +
    struct A { A(); ~A(); };
    +void () {        // Lifetime 1 associated with this block
    +  A x;
    +  A y;
    +  {              // Lifetime 2 associated with this block
    +    A xx;
    +    // Position R
    +    A yy;
    +  }
    +  A z;
    +}
    +
    +
    +

    Lifetime 1 has the destructions list (z, y, x) and lifetime 2 has the +destructions list (yy, xx). Lifetime 2’s parent_lifetime pointer +points to lifetime 1, and its parent_destruction_sublist pointer points to +the initialization entry for y.

    +

    One can see that if a return statement appeared at position R above, one +would want to destroy xx from the inner lifetime and y and x from +the outer lifetime. How would a back end figure that out? Well, as the back +end processes the IL, it would keep track of the latest +initialization-with-destruction encountered, i.e., the one for xx when at +position R. The pointer to that initialization defines the cleanup chain that +applies at position R. Starting with that initialization, the back end would +follow the next_in_destruction list to the end, generating destructions for +the entities on that list. Then, using the lifetime pointer in the last +dynamic initialization and the parent_lifetime pointer in the lifetime +pointed to, it would go to the parent lifetime, entering its destructions list +at the point indicated by parent_destruction_sublist. It would then +generate destructions for the entities on that list. The process would +continue upward through parent lifetimes until the lifetime for the function is +processed.

    +

    Generating destructions at a goto is almost as easy. The goto +statement has a common_lifetime field set by the front end. It indicates +the first object lifetime that the goto and the label have in common, that +is, the innermost object lifetime that appears on the cleanup chains for both +the goto and the label. The destructions for the goto are generated by +working upward through the cleanup chain, as for the return case, except +that processing stops when the common lifetime is reached (before generating +any destructions in that lifetime; if the goto is directly in the common +lifetime, then no destructions are generated).

    +

    When labels appear, and are followed by declarations for destructible objects, +a new block-after-label lifetime is begun at the label. This is necessary for +backwards gotos:

    +
    struct A { A(); ~A(); };
    +void () {     // Lifetime 1 begins
    +  A x;
    +L:;           // Lifetime 2 begins after label
    +  A y;
    +  if (i) goto L;
    +}
    +
    +
    +

    The destruction of x will be in lifetime 1, and the destruction of y +will be in lifetime 2. The goto is in lifetime 2, and the label is in +lifetime 1 (the parent of lifetime 2), so the common lifetime for the goto +is lifetime 1. The cleanup code at the goto therefore destroys y as it +exits lifetime 2, but it does not destroy x.

    +

    Switch case labels are treated like other labels and can begin new object +lifetimes if necessary. The labels generated for break and continue +statements do not ever begin new lifetimes.

    +

    Destructible temporaries are treated much the same way as destructible +variables, and their initializations are likewise placed on lifetime lists. In +its choice of which lifetime to use in each case, the front end represents its +decisions on the lifetimes of temporaries. For example, when a reference +variable is bound to a temporary, the C++ language dictates that the lifetime +of the temporary is extended to match the lifetime of the reference (e.g., for +a static reference the temporary lasts until the end of the program). The +front end would represent this in the IL by placing the temporary on the same +lifetime as the reference variable.

    +

    In the modern C++ language, normal temporaries last until the end of the full +expression within which they occur. In the front end, this is represented by +placing an expr-temporary lifetime around the full expression and placing the +destructions of any temporaries therein. In older dialects of C++, however, +including the dialect implemented by cfront, temporaries lasted until end of +scope. This mode is implemented by the EDG C++ front end in cfront +compatibility mode and when --long_lifetime_temps is specified. To be more +precise, in long-lifetime-temporaries mode temporaries survive until end of +scope or until a label, and they are limited to a single statement when the +statement is a conditional dependent statement, or to a full expression when +the expression is the tested expression in a conditional or loop statement, or +the initializer for a local static variable. Since long-lifetime temporaries +are destroyed at a label, when walking a cleanup chain and going from a +block-after-label lifetime to its parent one should ignore destructions for +temporaries until one reaches and exits from a block lifetime (all temporaries +in the block lifetime and any intervening block-after-label lifetimes were +destroyed at some label, and are no longer active). Because of the destruction +of temporaries at labels, in this mode block-after-label lifetimes are required +at some labels even when there are no destructible objects created after the +label.

    +

    In addition to its use in generating destructions on programmed exit from +lifetimes, the block object lifetime information is also intended to be useful +in generating the cleanup description information needed by the runtime support +for exception handling. With the default configuration, IL lowering will use +the object lifetime information to generate data structures that support EDG’s +implementation of exception handling. Those who wish to create a +higher-performance version of exception handling may find it useful to turn off +lowering of exception handling features and to use the object lifetime +information directly in the back end to generate the required cleanup +information. In either case, because the object lifetime information is used +to generate exception handling information, it includes some information beyond +what is required to generate cleanup on block exits:

    +
      +
    • +
      There is information about the mem-initializers (both user-written and +front-end-generated) in constructors, and about the similar +(front-end-generated) data structure in destructors.
      +
      +
    • +
    • +
      For each new that does allocation inline (rather than letting a +constructor do it), a dynamic initialization entry is generated to indicate +the freeing of the storage to be done if an exception is thrown before the +storage is fully initialized.
      +
      +
    • +
    • +
      For local static variables, a block object lifetime is placed around the +entire initialization and bound to the local static variable initialization +IL entry. Exiting this lifetime via an exception causes the runtime to +reset the state so that the local variable is marked as uninitialized. If +its declaration is encountered again on a subsequent call, the +initialization will be attempted anew.
      +
      +
    • +
    • +
      For aggregate classes or arrays initialized by a brace-enclosed list, +individual sub-initializations will indicate destructions to be done if an +exception is thrown before the complete aggregate is initialized. Once the +aggregate has been completely initialized, these destructions to undo +partial construction no longer apply.
      +
      +
    • +
    +

    One of the unfortunate consequences of using dynamic initialization entries to +represent destructions is that the contextual nature of dynamic initialization +entries (they don’t indicate the entity to be initialized; it’s implied by the +context) – which is an advantage when the entries are used to do +initializations – is somewhat of a disadvantage when the entries are used to +do destructions. Specifically, unless one saves some information in the +dynamic initialization entry at the time it is processed as an initialization, +it is very hard to know what to destroy when one processes it as a destruction. +However, it’s not hard to solve this problem from a practical point of view: +one just adds a field to the dynamic initialization entry to point to +back-end-specific information recorded at the time that the initialization is +processed, and that information is then available, and in just the right form, +when the destruction is processed. That’s the technique used by IL lowering.

    +
    +
    +

    4.19. Routines#

    +

    a_routine describes a function. It indicates the type and storage class. +The storage class can be sc_static, sc_extern (meaning a reference to a +function defined in another compilation), or sc_unspecified (meaning a +definition of a function visible to other compilations). The storage class is +standardized during declaration processing. A function with a body will have +storage class sc_unspecified or sc_static; a function without a body +will have storage class sc_extern.

    +

    The type of a function is always a function type, which describes the +external interface to the function: its return type, its parameter types, +etc. A nonstatic member function will also have an implicit “this” +parameter, with a type of const pointer-to (possibly qualified) class. +The parameter types might have associated default argument value +expressions, although that information is useful to a back end only for +generation of symbolic debugging information, since calls of the routine +will have the default argument values supplied.

    +

    The routine entry also indicates whether or not the routine is inline, virtual, +and/or front-end-generated. (The front end generates routines for constructors +and destructors, assignment operator functions, and, when IL lowering is done, +for global initialization and termination routines, runtime routines, and +wrappers for constructors with default arguments.) The special_kind field +indicates whether or not the function is a C++ special function such as a +constructor. If the special_kind indicates that the routine is an operator +function, opname_kind indicates the kind of operator function it is. The +special_kind is significant to a back end using the unlowered C++ +intermediate code in that wrapper code needs to be generated for constructors +and destructors. Other than that, special_kind and opname_kind are +mostly of interest for generating symbolic debugging information and mangled +names.

    +

    The routine entry points to a list of classes that have befriended the +function. Those classes will have the function on their friend lists.

    +

    If the function is a virtual function, the routine entry indicates a virtual +function number assigned to the routine. Typically, this will be used as the +function’s index into a virtual function table, but since the unlowered C++ IL +leaves virtual function access as an abstraction, it’s only a helpful +identifying number at that level.

    +

    If the function has a body, the routine entry indicates the function +definition number and the memory region that contains the function +definition. By indexing through il_header.function_def_table, one can +get to the scope entry for the function (in the proper function scope +memory region). That scope entry points to the statements and local +declarations of the function. It also points to variables for the +parameters of the function, including a “this” parameter variable if +necessary. The parameter and “this” variables will match the parameter +and “this” types in the function type. (In non-prototyped functions, the +function type parameters might be promoted versions of the parameter +variable types.) For parameters that are passed using a copy constructor +(indicated by a flag in the parameter type entry), a back end using the +unlowered C++ IL may have to expect to receive the address of the class +entity rather than its value, and to do implicit indirections on the +references to the parameter.

    +

    The address_taken flag in the routine entry will be set if the address of +the function has been taken. Merely calling the function does not cause the +address_taken flag to be set, even though the IL for a call refers to the +routine address.

    +

    An exception specification that appears on a function declaration is +represented by an entry of type an_exception_specification, referred to +by means of the exception_specification field of the routine type +supplement. When the function is declared with no exception specification +(meaning that any exception might be thrown) the +exception_specification pointer will be NULL. The exception +specification entry representing a dynamic exception specification has a +pointer to a linked list of entries of type +an_exception_specification_type, each of which indicates a type of +exception that will be thrown from the given routine; that pointer is NULL +to indicate that no exceptions will be thrown. An exception +specification representing a noexcept specification points to an entry +of type a_constant representing its operand (or NULL if no operand is +specified).

    +

    When ASM_FUNCTION_ALLOWED is TRUE, asm functions are recognized and +passed uninterpreted to the back end. They are represented in the IL like +ordinary functions, except that they have a storage class of sc_asm and the +function body (pointed to from the associated scope entry) is represented by an +stmk_asm statement. The asm entry to which the latter refers points is a +null-terminated string containing the text that appeared in the source; +comments are removed unless INCLUDE_COMMENTS_IN_ASM_FUNC_BODY is TRUE.

    +

    In order to save space in the a_routine structure, some (mostly +GNU-specific) fields with default values that are rarely changed are located in +the a_gnu_routine_supplement struct, which is pointed to by the +gnu_extra_info field. This supplement is only allocated when one of the +fields has a non-default value.

    +

    The GNU function multiversioning feature (available in GNU C++ modes where +gnu_version >= 40800), allows for declarations/definitions of multiple +routines with the same signature but with different target attributes. The +target attributes specify which CPU architecture is applicable for each of +the functions in the group. Internally, the entire group of functions is +represented by a “representative” function (whose is_representative field +is TRUE). All target-specific functions are have the +is_target_specific field set to TRUE and are queued on the +mv_info.representative.targeted_versions list. Although each of the +routines (both representative and target-specific) have associated symbols, +only the symbol for the representative routine is entered into the symbol +table. This feature is controlled by the GNU_FUNCTION_MULTIVERSIONING +configuration macro.

    +
    +
    +

    4.20. Constructors and Destructors#

    +

    Constructor and destructor routines must do additional processing beyond what +appears in the body of the routine. Since this processing surrounds the code +in the definition of the routine, it is called “wrapper” code.

    +

    Some of the wrapper code is implicit: there must be code that initializes +the information in the class used to access virtual base classes and +virtual functions (typically, virtual base class pointers and virtual +function table pointers). The wrapper code must also control whether or +not virtual base classes are initialized or destroyed (they should be for a +complete object, but not for a subobject). If a new or delete +operation can be folded into a constructor or destructor (a configuration +option, but always true if assignment to “this” is supported), the +wrapper code may have to provide for calling a new or delete +routine.

    +

    The wrapper code must also do any necessary initialization or destruction for +base classes and members. The required actions are described explicitly by a +list of a_constructor_init entries which indicate the initialization or +destruction to be done, in the correct order. If the source program contains +constructor-initializer clauses, they will appear on the list in the right +positions. For any base class or member that requires initialization and for +which the source does not provide an initializer, a default initializer is +generated. In a front-end-generated copy constructor, the default +“initialization” will in fact be a copy. In a destructor, there is no source +construct for indicating specific destruction for base classes and members, so +the list is always front-end-generated in its entirety. It is also in the +correct order, i.e., the reverse of the order in the corresponding constructor +list.

    +

    IL lowering modifies constructor and destructors to provide all the necessary +wrapper code.

    +

    Calls of “destructors” for classes that do not have them or for simple types, +as in

    +
    p->int::~int();
    +
    +
    +

    are rendered as eok_dot_vacuous_destructor_call or +eok_points_to_vacuous_destructor_call expression nodes in the IL. No +routine entry is created for the ersatz destructor. Such nodes are rewritten +as casts to void in IL lowering.

    +
    +
    +

    4.21. Labels#

    +

    a_label is a declarative entity that describes a label (user-written or +front-end-generated) in a function. It is pointed to by the goto and label +definition statements in the executable code of the function.

    +
    +
    +

    4.22. asm Statements#

    +

    An asm statement (or declaration, whichever way you care to look at them) +can appear in two contexts:

    +
      +
    • +
      Within the bodies of functions, where it is considered to be executable +code and is represented by an stmk_asm statement pointing to +an_asm_entry that gives the asm statement string.
      +
      +
    • +
    • +
      At file or namespace scope, where it is considered to be a declaration and +is represented as an_asm_entry on a list of such entries attached to +the file or namespace scope a_scope entry. If such asm +declarations are supposed to affect declarations that immediately follow +them, the back end must consider the source positions of variables, +routines, and asm entries and do a merge of those lists.
      +
      +
    • +
    +
    +
    +

    4.23. Statements#

    +

    a_statement describes a statement, which can be an expression, an if, a +while, a do-while, a for, a switch, a goto, a +break, a continue, a label definition, a return, a block (with or +without an associated scope), a try block, or a declaration statement.

    +

    The representation of switch statements (stmk_switch) matches the +language definition, but the case and default labels are represented +using a separate statement entry kind stmk_switch_case. Each +stmk_switch_case entry points to an entry of type a_switch_case_entry +(which describes the label’s value, among other things). An stmk_switch +statement points to a list of all switch case entries associated with that +statement (via an entry of type a_switch_stmt_descr). A list of switch +case entries in sorted order of label value is usually also available (this +list excludes the default case), but not if any of the cases is +template-dependent. break statements to transfer out of a switch +statement are stmk_goto statements pointing to a label entry whose +switch_break_label flag is TRUE.

    +

    The stmk_init statement indicates the point in a sequence of executable +statements where the dynamic initialization of a variable should be done. It +points to the same dynamic initialization entry that the variable does. This +is particularly useful in C++ where variables can be declared and initialized +in the middle of a block.

    +

    The stmk_block statement is used both for a simple compound statement and +for a block (i.e., a compound statement containing local declarations). The +a_block entry pointed to from the statement indicates whether or not the +block has an associated scope. In C++, a block statement is always generated +for the dependent statement of conditionals (e.g., if), even if no { } +are present. However, the block will not have an associated scope unless +something is actually declared inside the block.

    +

    The stmk_try_block statement is used to represent a try block. It +points to a compound statement block and a linked list of handlers. The latter +are entries of type a_handler; each points to a (possibly unnamed) +parameter (the local variable to which the thrown object will be copied when +the handler is invoked) and to an stmk_block statement, the body of the +handler; for a default handler (i.e., the catch(...) case) the parameter +pointer in the handler entry is NULL.

    +

    The stmk_decl statement is used to represent a declaration statement. This +could be the declaration of one or more variables and/or functions (using one +of more comma-separated declarators), one or more typedef types, a local class +or enum type, a using-declaration, etc.

    +

    The C++/CLI “for each” statement is represented by an stmk_for_each +statement. Its representation includes an indication of which “pattern” the +loop matches (the CLI collection pattern, the CLI array pattern, the STL +pattern, or the native array pattern), and for each of those patterns +expressions that give the worked-out expansion for the pieces of the loop, so +that a code-generating back end does not need to figure out the expansion.

    +

    When support for variable length arrays is enabled, two additional statements +may appear.

    +
      +
    • +
      An stmk_set_vla_size statement is associated with a VLA declaration and +indicates exactly where the dimension expression for a VLA should be +evaluated.
      +
      +
    • +
    • +
      An stmk_vla_decl statement will refer to a variable of variably +modified type or to a tk_typeref type to indicate the location of the +corresponding variable or typedef declaration. This is generally +important because a VLA type has run-time dependencies that need to be +honored. Moreover, when the variable referred by an stmk_vla_decl +statement has a VLA type (not just a type that “contains” a VLA type), the +stmk_vla_decl statement indicates the point at which the storage for +the variable should be allocated. Note that a single stmk_vla_decl +statement may be preceded by multiple stmk_set_vla_size statements if +the type associated with the stmk_vla_decl statement has multiple +variable-length dimensions. (See also Types and +Operation Expressions.) In C modes, expression statements with a single +node of kind enk_vla_dealloc (see also VLA Deallocation) may be +generated to indicate the point at which a variable of VLA type should be +deallocated (e.g., preceding a goto out of a scope containing a VLA +variable). Such deallocation constructs are generated only when +VLA_DEALLOCATIONS_IN_IL is TRUE.
      +
      +
    • +
    +

    Note that variable-length array types can also appear in sizeof +expressions. None of the above statement kinds are generated for those cases +since statements cannot in general appear within expressions. Instead, such +expressions result in enk_sizeof expression nodes. Back ends can find and +examine the a_vla_dimension entries associated with such nodes to evaluate +the result of the sizeof expression.

    +
    +
    +

    4.24. Source Sequence Lists#

    +

    When GENERATE_SOURCE_SEQUENCE_LISTS is TRUE, lists of +a_source_sequence_entry are generated, ordered strictly according to +the order in the source program. This is useful for applications that care +about the exact order of declarations, redeclarations, and definitions in +the source code, e.g., source analysis applications. Each list entry +represents a declaration, a statement, a macro, a pragma, a template, or a +template specialization that represents an instantiation (if either of the +deprecated configuration macros +CLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS or +NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE). +Those entities representing declarations and statements point to the +corresponding IL entry, and the latter have pointers back (fields +source_sequence_entry in a_source_correspondence and in +a_statement).

    +

    The lists appear in the IL via the source_sequence_list pointer in +a_scope entries for the file scope and for each function scope. (The +pointer will always be NULL for other scope kinds.) Source sequence entries +themselves have both forward and backward pointers to facilitate list traversal +and management.

    +

    Logically, there is a single source-sequence list in a translation unit. +Actually, however, a number of lists may be involved. The file-scope +source-sequence list is pointed to from the scope entry for the file scope, but +when a function definition appears, another list, pointed to from the scope +entry for the function, is produced. The logical successor of the +source-sequence entry for the function (which is in the file-scope list) is the +first entry on the function-scope list, and the logical successor of the last +entry on the function-scope list is the entry pointed to by the next +pointer of the function’s source-sequence entry.

    +

    The reason for representing the logically continuous source-sequence list by +many discontinuous lists is that source-sequence entries appear in different +memory regions, just as the IL entries they point to do. Thus, the entries on +the file-scope source-sequence list are allocated in the file-scope memory +region, but the entries on a function-scope source-sequence list are usually +allocated in the memory region of that particular function.

    +

    Some declarations within a function, however, create entities that are +allocated at file scope. This is the case for types, static variables, and +variables and functions declared extern. The source-sequence entries for +such entries must also be in the file-scope memory region, but that means they +cannot be on the same linked list with entries allocated in the function-scope +memory region. Therefore, additional side branches are used: entries of type +a_src_seq_sublist (“sublist headers”) establish such branches by pointing +to the head and tail of a list of file-scope source-sequence entries that are +logically within the source-sequence list of the function scope.

    +

    The sublist headers for a given function, as well as being pointed to by +entries (“sublist parents”) in the function-scope source-sequence list, are +also chained together; the head of the linked list is pointed to by +src_seq_sublist_list in the function’s scope entry, and its tail is pointed +to by last_src_seq_sublist in the corresponding scope stack entry.

    +

    Entries of type a_src_seq_end_of_construct are inserted into the +source-sequence list to mark the point at which certain constructs terminate +(the entries point back to the associated IL entry). This includes class and +enum definitions and statement blocks. Such entries are also used to mark the +end of a set of source sequence entries for constructs embedded in a variable +or function declaration. For example, in:

    +
    int x[sizeof(struct S { int i; })];
    +
    +
    +

    (which is accepted in some modes only), the source sequence list contains an +entry for the definition of variable x, followed by entries for the +definition of struct S, followed by an entry marking the end-of-construct +of variable x‘s definition. An end-of-construct marker is similarly used +to mark the appearance of the “while (...)” part of a do-while statement +(this is, e.g., significant to be able to record whether a pragma appeared +before the statement as a whole, or just before the while keyword).

    +

    When a declaration is not a definition (e.g., a function declaration with no +body or a variable declared extern), it is represented by an entity of type +a_src_seq_secondary_decl, which is pointed to by the source-sequence entry +and points in turn to the corresponding IL entry. Therefore, when an entity +has more than one declaration, multiple source-sequence entries are created, +but only the one that represents the definition points directly to the IL +entry; the others point to secondary declaration entries. If there is no +definition of the entity in the compilation, all of the source sequence entries +for that entity will be secondary declarations.

    +

    (Source sequence lists are not actually added to the IL tree until +pop_scope is called for a function scope or the file scope. During front +end processing, the source sequence lists as described above are assembled from +smaller lists that are managed on a per-scope basis; whenever a scope stack +entry is popped, its list is typically merged into the list of the immediately +enclosing scope. Moreover, the source sequence list describing a function +definition may temporarily be a simple linked list containing a mix of entries +from the memory regions of the function scope and the file scope; the +representation involving sublist headers, as described above, is produced by a +fixup pass when the function scope is popped.)

    +

    Many implementations will not need the kind of information provided by +source-sequence lists and will choose to avoid the processing overhead and +especially the memory overhead they introduce. By default, therefore, +GENERATE_SOURCE_SEQUENCE_LISTS (defined in host_envir.h) is set to +FALSE.

    +
    +
    +

    4.25. Expressions#

    +

    an_expr_node describes an expression node, which can be an operator node, a +reference to a constant, variable, or function, an initialization of a +temporary, or a few other things like new or delete.

    +

    Each expression node has a type, indicated by its type field.

    +

    The simplest expression nodes are leaf nodes. The most common leaf node kind +are:

    +
      +
    • +
      enk_variable refers to a variable.
      +
      +
    • +
    • +
      enk_routine refers to a function.
      +
      +
    • +
    • +
      enk_constant refers to a constant.
      +
      +
    • +
    • +
      enk_field refers to a field.
      +
      +
    • +
    +
    +

    4.25.1. Lvalues and Rvalues (Value Categories)#

    +

    Each expression node has an is_lvalue flag, which is TRUE if the node +represents an lvalue and FALSE if it represents an rvalue. (It is also TRUE +for what is called a function designator in C, which is simply called an lvalue +in C++.)

    +

    So, an enk_variable node with is_lvalue TRUE indicates an lvalue for +the variable, and the same node with is_lvalue FALSE indicates an rvalue +for the variable, i.e., the value of the variable. In the statement

    +
    i = j;
    +
    +
    +

    the left operand would have is_lvalue TRUE and the right operand would have +is_lvalue FALSE.

    +

    Similarly, an enk_routine with is_lvalue is TRUE indicates an lvalue +for the function (which has a function type), and one with is_lvalue FALSE +indicates an rvalue for the function (which is the address of the function, and +has pointer-to-function type).

    +

    enk_constant nodes are usually rvalues, representing the value of an +indicated constant. The one exception is that an enk_constant for a +string constant (ck_string) can be an lvalue for the string.

    +

    C++11 adds the concept of “xvalues,” which are eXpiring values produced by +certain rvalue reference operations. They are indicated by the is_xvalue +flag in the node being TRUE (is_lvalue and is_xvalue are never both +TRUE). Lvalues and xvalues are collectively called “glvalues.” The things that +were called “rvalues” in pre-C++11 C++ and in C are known in C++11 as +“prvalues,” and the term “rvalue” becomes a collective term for prvalues plus +xvalues. [8] In the IL, xvalues in general can be viewed as funny versions +of lvalues.

    +

    Glvalue nodes shouldn’t be considered to have values. They’re just a +description of an object in memory. Because they don’t have values, they also +can’t be considered to be constant or to have constant values, though some +lvalues will have constant addresses (see constant_glvalue_address).

    +

    When a glvalue with a cv-qualified type is converted to a prvalue, the type +qualifiers are dropped (except for class-typed prvalues in C++). In the IL, +this is reflected in the fact that the expression node for the prvalue will +have the unqualified type. When an lvalue with a function type is converted to +a prvalue, its type becomes pointer-to-function.

    +

    Clearing the is_lvalue flag in an expression node where initially the flag +would be expected to be TRUE indicates a fetch from memory. This is obvious on +the enk_variable node, but it also applies to many other nodes, such as +field selection and subscripting operators. Nodes that can be made to include +a fetch merely by clearing the is_lvalue flag (or, similarly, the +is_xvalue flag) are referred to as “rvalueable”. One can test for the +presence of an implicit fetch (also known as an lvalue-to-rvalue conversion) in +an expression node by calling node_includes_glvalue_to_prvalue_conv.

    +
    +
    +

    4.25.2. Operation Expressions#

    +

    Expression nodes of kind enk_operation are operations. They are the +non-leaf nodes of expression trees, the ones that apply an operator to a set of +operands, to do operations like i+j.

    +

    The operands of an operation are linked together as a list, and the operation +node points to the first expression on the list.

    +

    Most operations take a fixed number of operands. The various forms of calls +are exceptions and take a variable number of operands.

    +

    The operator kind (addition, assignment, call, etc.) is described by the +variant.operation.kind field, which is mostly independent of the type of +the operands. For example, an addition is described with kind eok_add +independently of the operand type. There are a few exceptions to this when the +semantics of the operation vary sufficiently from the generic case to warrant a +separate operator. For example, pointer arithmetic uses dedicated operators +eok_padd, eok_psubtract, and eok_pdiff instead of the generic +eok_add and eok_subtract. Where applicable, an additional field +variant.operation.type_kind describes the class of types an operation acts +on. For example, this will be tk_float for the multiplication of two +floating-point values, or tk_template_param for a multiplication involving +a template-dependent operand. For operations that don’t apply to a particular +type kind (e.g., eok_call), the type_kind field is set to +tk_unknown. The type_kind field is set automatically when calling +make_operator_node or set_node_operator (it is ultimately computed by +operation_type_kind).

    +

    In the case of scalar controlling expressions, the several different cases +(integer, float, and pointer) are reduced to a single case (integer) by +standardizing the expression. Specifically, for the expression of a +stmk_if, stmk_while, stmk_end_test_while, or stmk_for, and for +the controlling operands of the eok_not, eok_land, eok_lor, and +eok_question operators, the expression will always be either an integer +constant 0 or 1, or an expression whose top operator is defined to +yield a 0 or 1 result. Where necessary, a constant value will be +standardized (e.g., 5.3 will be changed to 1), or a != 0 operation +of the proper type (integer, float, or pointer) will be added to the top of the +expression.

    +

    The operands of an expression may be evaluated in any order consistent with +the C and C++ “as-if” rule. By default, parentheses are not directly +represented in the IL; their effect is simply reflected in the operands of +the operators in the expression tree or, in cases where they have semantic +implications, by flags in various IL entries (e.g., +an_expr_node::is_parenthesized). Applications that need to be aware of +source-level parentheses can set the PARENS_IN_IL configuration option; +see Parentheses.

    +

    In general, operator nodes that do not correspond directly to something that +appeared in the source, and were added by the front end, are marked by having +compiler_generated set to true.

    +
    +
    +

    4.25.3. Addressing operators#

    +

    There are several addressing operators (note that when we refer to eok_... +names we mean those under the enk_operation expression variant):

    +
      +
    • +
      eok_address_of is the “&” operator. Its operand is an lvalue, and +its result is a prvalue of pointer type that is the address of the lvalue.
      +
      +
    • +
    • +
      eok_indirect is the “*” operator. Its operand is a prvalue +pointer, and its result is an lvalue that is the object pointed to. It +is rvalueable.
      +
      +
    • +
    • +
      eok_array_to_pointer converts its operand, an array (lvalue, xvalue, or +prvalue), to a prvalue pointer to the first element of the array.
      +
      +
    • +
    +

    The “restrict” qualifier on pointers, originally introduced in C99, is a type +qualifier on pointer types that indicates that they can be considered to be +unaliased (nothing else in scope points at what they point at). The function +node_is_pointer_with_restrict_semantics can be used to test an expression +node that is a pointer (e.g., the operand of an eok_indirect operation) to +see whether it has the “restrict” semantics.

    +
    +
    +

    4.25.4. References#

    +

    References are not pointers, but they are treated as somewhat pointer-like in +the IL, with their own versions of the addressing operators:

    +
      +
    • +
      eok_reference_to is the reference version of “&”. Its operand is a +glvalue, and its result is a prvalue of reference type that is the +“address” of (reference to) the glvalue. Its operand can also be a class +prvalue, in which case its result is the “address” of the underlying class +object.
      +
      +
    • +
    • +
      eok_ref_indirect is the reference version of “*”. Its operand is a +prvalue with reference type, and its result is an lvalue that is the object +referenced. It is rvalueable.
      +
      +
    • +
    +

    These operators do not, of course, appear in the source code; they are added by +the front end where needed. No operations are allowed on references other than +the above, or storing a reference somewhere, or passing it as an argument.

    +

    An example: for something like

    +
    int i;
    +int &r = i;
    +r = r;
    +
    +
    +

    the left operand of the assignment is an eok_ref_indirect with +is_lvalue TRUE over an enk_variable for r with is_lvalue FALSE, +and the right operand is an eok_ref_indirect with is_lvalue FALSE over +an enk_variable for r with is_lvalue FALSE.

    +

    Note that reference type values are typically dealt with as prvalues, in the +same way that pointers are. In the example above, the enk_variable for +r is effectively fetching the pointer-like value stored in the reference +variable, so its is_lvalue flag is FALSE. An enk_variable node with +is_lvalue TRUE for a reference variable would mean an lvalue for the cell +containing the reference value, but there’s no real use for that in the C++ +language, since you can’t take the address of the cell nor can you change its +value after initialization.

    +

    Address constants with kind ck_address can have reference type when they +are used to initialize a reference-typed variable. They represent a constant +reference value.

    +

    Rvalue references (source form like “int&&r”) are similar to the +traditional “lvalue” references. eok_reference_to and eok_ref_indirect +can be used with them also, and ck_address constants can have rvalue +reference type. An rvalue reference is always bound to an rvalue (i.e., an +xvalue or prvalue). See Casts for information on casts to +rvalue reference types.

    +
    +
    +

    4.25.5. Field Selection#

    +

    There are several operators that implement field selection:

    +
      +
    • +
      eok_dot_field is the “.” operator. The left operand is a class +glvalue or prvalue, the right operand is an enk_field, and the result +is a glvalue or prvalue of the type of the selected field (with +cv-qualifier adjustment). When the left operand is an lvalue, the result +is an lvalue (rvalueable), and similarly for an xvalue. When the left +operand is a prvalue, the result is a prvalue.
      +
      +
    • +
    • +
      eok_points_to_field is the “->” operator. The left operand is a +prvalue pointer to class, the right operand is an enk_field, and the +result is an lvalue (rvalueable) of the type of the selected field (with +cv-qualifier adjustment).
      +
      +
    • +
    • +
      eok_pm_field is the “.*” operator. The left operand is a class +glvalue or prvalue, the right operand is a pointer to data member, and the +result is a glvalue or prvalue of the type of the pointed-to member (with +cv-qualifier adjustment). When the left operand is an lvalue, the result +is an lvalue (rvalueable), and similarly for an xvalue. When the left +operand is a prvalue, the result is a prvalue.
      +
      +
    • +
    • +
      eok_pm_points_to_field is the “->*” operator. The left operand is +a prvalue pointer to class, the right operand is a pointer to data member, +and the result is an lvalue (rvalueable) of the type of the pointed-to +member (with cv-qualifier adjustment).
      +
      +
    • +
    • +
      eok_dot_static is the “.” operator when the entity selected is +static. The first operand is a class glvalue or prvalue (and it is +evaluated) and the second operand is an enk_variable for a static data +member, an enk_routine for a static member function, or an +enk_constant identifying a member constant (e.g., an enumerator). The +result is the second operand.
      +
      +
    • +
    • +
      eok_points_to_static is the “->” operator when the entity selected +is static. The first operand is a prvalue pointer to class (and it is +evaluated) and the second operand is an enk_variable for a static data +member, an enk_routine for a static member function, or an +enk_constant identifying a member constant (e.g., an enumerator). The +result is the second operand.
      +
      +
    • +
    +

    Note that most of the selection operators are rvalueable in some cases, but the +static variants are not; for those, the lvalue-to-rvalue conversion, if there +is one, has to be indicated on the second operand, and not in the +eok_dot_static or eok_points_to_static operation itself.

    +

    Also note that there are no variants of the pointer-to-member selections for +pointer-to-member-function cases. Those can be used only in calls, and the two +operands of the selection are simply folded into the eok_pm_call. +Likewise, the “.” or “->” operation in a member function call is simply +folded into the call.

    +
    +
    +

    4.25.6. Subscripting#

    +

    eok_subscript is the array subscripting “[]” operator. One operand is +a prvalue pointer to the first element of the array, and the other is an +integral subscript value. The result is an lvalue (rvalueable) for the +specified element of the array. Usually, the pointer operand is first, but +that’s not actually a requirement of the language, and the operands can appear +in either order, as for the expression “1[a]”. See the +pointer_operand_is_second field, which indicates this unusual case, and the +macro subscript_or_padd_pointer_operand, which can be used to extract the +pointer operand. As you will note from the name of that macro, this is also an +issue for the pointer addition (eok_padd) operator.

    +
    +
    +

    4.25.7. Casts#

    +

    The eok_cast operator is used to indicate simple casts.

    +

    Casting a derived class pointer to a base class pointer is represented by an +eok_base_class_cast operator. Casting a base class pointer to a derived +class pointer uses an eok_derived_class_cast operator. These casts differ +from ordinary pointer casts in that they may add or subtract an offset to the +pointer, and they must preserve a NULL pointer. They can also be applied +directly to a class glvalue or prvalue, rather than a pointer to a class +object, or to a C++/CLI handle.

    +

    eok_pm_base_class_cast and eok_pm_derived_class_cast are the similar +casts for pointers-to-members. The same operators are used for +pointers-to-data-members and pointers-to-member-functions, even though the +implementations of those are likely to be different.

    +

    The anachronism of casting a bound pointer-to-member-function to a normal +pointer (which is similar to the processing done by an +eok_points_to_pm_call to determine the function to call) is rendered as an +eok_virtual_function_ptr operation.

    +

    In pcc mode and in some Microsoft and GNU C++ modes, certain casts to +like-sized types (like int to unsigned int) leave a result that is +still an lvalue. For these cases, the lvalue is cast to the appropriate type +using the eok_lvalue_cast operator. The result is still an lvalue.

    +

    The C++ dynamic_cast operator is rendered as an eok_dynamic_cast +(pointer or handle case) or eok_ref_dynamic_cast (reference case), but only +for cases that require runtime processing. The rest are rendered as ordinary +casts.

    +

    Casts to bool are rendered as an eok_bool_cast, which has the same +effect as a “!= 0” test.

    +

    The eok_lvalue_adjust operator adjusts the type of a glvalue. Its operand +is a glvalue, and its result is a glvalue for the same object but with a +different type.

    +

    The eok_class_rvalue_adjust operator adjusts the type of a class prvalue. +It is limited to adjusting the cv-qualifiers of the type. Its operand is a +class prvalue, and its result is the same value with a different type. When +LOWER_CLASS_RVALUE_ADJUST is TRUE, IL lowering will rewrite these +adjustments by taking the address of the class rvalue, casting the pointer to +the proper type, and indirecting to get back to a class object.

    +

    Casts to reference types are represented as glvalue-to-glvalue operations. The +simplest cases are represented by the eok_ref_cast operator. The node type +is the underlying type of the reference, e.g., the node for a cast (T &)x +has type T, not type T&. The operand is a glvalue, and the result is a +glvalue for the same object but with the type T. More complicated +reference casts that involve related-class adjustments are represented by +eok_base_class_cast and eok_derived_class_cast operators operating on +class glvalues. Nodes that represent a cast to a reference type are marked +with the is_reference_cast flag. If several nodes are required (e.g., +multiple casts to base classes) only the topmost node will be marked. Note +that eok_ref_cast nodes are rvalueable, and when the is_lvalue flag is +cleared to indicate the presence of an lvalue-to-rvalue conversion the node +type becomes the cv-unqualified type (for non-class lvalues) or pointer-to the +lvalue type (for function lvalues). That means, for a function type F, a +cast to F& with an included lvalue-to-rvalue conversion is represented by a +node with type F*.

    +

    Casts to rvalue reference types are similarly represented by eok_ref_cast, +eok_base_class_cast, and eok_derived_class_cast nodes. They are marked +with the is_rvalue_reference_cast flag in addition to the +is_reference_cast flag. Although in the C++ language such reference casts +take an rvalue as their operand, in the IL the operand is always converted to a +glvalue and then cast. The node or nodes that do the cast are then exactly the +same as those that would be used for an lvalue reference cast. The final +(topmost) cast node will always be an eok_ref_cast node, and it will have +is_lvalue FALSE to indicate the result is an rvalue (unless the result +needs to be converted back to an lvalue for some reason).

    +
    +
    +

    4.25.8. Assignments#

    +

    There are assignment operators for integral types, fixed-point types, floating +types, classes (bitwise copy, or C struct assignment), pointers, and +pointers-to-members.

    +

    There is also a block-copy assignment, eok_bassign, which is only generated +by IL lowering and inside front-end-generated assignment operator functions, +and is needed to do bitwise copies of arrays when copying classes. It is +unusual in that its second operand is in lvalue form and its result type is +void.

    +

    In C++, assignment operators can return lvalues instead of rvalues. Such cases +are indicated by the returns_lvalue_instead_of_usual_rvalue flag in the +expression node. The expression type matches the type of thing returned (i.e., +it matches the first operand’s type). The same flag is used for prefix ++ +and -- and the “?” and “,” operators when they return an lvalue. +When that flag is set, is_lvalue will also always be set as well (in other +words, they are not rvalueable).

    +
    +
    +

    4.25.9. Compound Assignments#

    +

    In cases where a compound assignment operator (e.g., +=) is applied to +operands of two different types, the right side operator will be cast as +necessary to the type of the operation (as it would be for other operators). +The left side operand (the destination, an lvalue), however, is left in its +original type, which is also the type of the entire expression. The back end +must provide a cast of the value of the left operand to the operation type +(generally the type of the right operand, but see below) before performing the +operation on the operands. For example: in i-=f (i an int, f a +float), the back end must provide the cast of i to float before +doing the subtraction; the operation type is float; the result type (and +the type of the expression node) is int.

    +

    As mentioned above, the operation type for the operation is generally the right +operand type. There are two exceptions in which the underlying type of the +left operand is the operation type: shift assignments (<<= and >>=) and +pointer += and -= (for those cases, the right operand is not cast to +the operation type). Fixed-point +=, -=, *=, and /= are yet +more complicated; the function compound_assignment_operation_type should be +called to determine the operation type for those (it also works for all the +simpler cases).

    +

    GNU vector cases are even weirder, as no attempt is made to bring the operands +to a common type.

    +
    +
    +

    4.25.10. Binary Conditional Operator#

    +

    In some configurations, the front end supports a GNU extension known as the +“binary conditional operator”. The operator has the form expr1?:expr2 (i.e., similar to the regular conditional operator, but with +an omitted middle operand). Such expressions result in the value of expr1 +if expr1 converted to a boolean is true, or the value of expr2 +otherwise. In the IL, this is represented by the usual eok_question +operator, but with the flag is_gnu_two_operand_question_mark set to TRUE. +The expression includes a synthesized second operand, which may use an +enk_reuse_value expression node to reuse the value of the first operand +without evaluating it a second time.

    +
    +
    +

    4.25.11. Calls#

    +

    The normal call is rendered as an eok_call operation. The first operand +gives the address of the routine to call, and the rest of the operands are the +arguments for the call.

    +

    For nonstatic member function calls, the operation is eok_dot_member_call +(for calls in the x.f() form) or eok_points_to_member_call (for calls +in the p->f() form). The first operand is the routine address (as a normal +pointer, not a pointer-to-member); the second operand is the selector object (a +class glvalue or prvalue for eok_dot_member_call, or a pointer to a class +object for eok_points_to_member_call). The remaining operands are the +arguments to the call. In either case, a call with virtual semantics is +indicated by the is_virtual_call flag in the expression node.

    +

    For pointer-to-member-function calls, the operation is eok_dot_pm_call (for +calls in the (x.*pmf)() form) or eok_points_to_pm_call (for calls in +the (p->*pmf)() form). The first operand is the pointer-to-member-function +(i.e., a value of pointer-to-member-function type, not a normal pointer type); +the second is the selector object (a class glvalue or prvalue for +eok_dot_pm_call, or a pointer to class for eok_points_to_pm_call); the +rest are the actual arguments, as above.

    +

    If a routine has default arguments, the front end will supply the default +expressions if no explicit arguments are provided. The back end need not do +any special handling.

    +

    If a parameter of class type must be passed by using a copy constructor, a call +of the copy constructor into a temporary will be generated on the calling side. +Somewhat arbitrarily, the enk_temp_init node for that is marked as an +lvalue.

    +

    For routines that return a class object via a copy constructor, the call will +always be immediately underneath a dik_call_returning_class_via_cctor +dynamic initialization entry. The entity being initialized by the dynamic +initialization entry should be taken as the destination for the copy +constructor call. (IL lowering makes this explicit.)

    +

    Note that uses of operator functions and conversion functions are rendered as +routine calls even through they use operator syntax or are implicit in the +source program. Constructor and destructor “calls” generally only show up in +dynamic initialization entries, and not as standard calls in expressions.

    +

    Inlining is considered to be a back end issue. The front end does not do +inlining of calls. IL lowering optionally offers a limited form of inlining, +but it’s intended only for those who have no better alternative.

    +
    +
    +

    4.25.12. Returns#

    +

    The stmk_return statement is used to represent all returns, whether +explicitly written by the programmer or generated by the front end. In +addition to the expected

    +
    return;
    +return expr;
    +
    +
    +

    (which are distinguished by a NULL or non-NULL expr pointer), there is also +a special form of return used for returns in routines that return a class value +by calling a copy constructor. For those, the stmk_return statement has a +pointer to a dynamic initialization entry, which indicates the initializing +operation to be done to return the class object. IL lowering implements this +by having the caller pass an extra argument that provides the address at which +the class object should be placed, and having the called routine call the copy +constructor using the implicit parameter as its destination address.

    +
    +
    +

    4.25.13. Pointers to Members#

    +

    Pointer-to-member types are represented as an abstraction in the unlowered C++ +intermediate language. It is up to IL lowering or a back end to translate them +into a particular implementation. Typically, pointers to data members are +implemented as a small integral offset (the offset of the member within the +class) and pointers to member functions are rendered as a structure (see the +ARM, 8.1.2.c).

    +

    Pointer-to-member types are represented by a tk_ptr_to_member type entry.

    +

    Pointer-to-member constants are represented by a constant entry of kind +ck_ptr_to_member. These represent source constructs like &A::x, +meaning some sort of representation of the location of x in a class object +of type A (not a pointer to that member in a specific object, but rather a +representation of how to find that member in an arbitrary entity of that +class).

    +

    Operands of pointer-to-member type can be assigned (eok_assign) and +compared (eok_eq and eok_ne). They can also be cast to base or derived +classes (eok_pm_base_class_cast and eok_pm_derived_class_cast).

    +
    +
    +

    4.25.14. Temporary Initialization#

    +

    The enk_temp_init node is used to introduce a temporary in the middle of an +expression. It points to a dynamic initialization entry and an expression. +The initialization indicated in the dynamic initialization entry is performed +on the temporary, and then the temporary is returned as the value of the +enk_temp_init node, as an lvalue, xvalue, or prvalue. Any destruction +indicated in the dynamic initialization entry must be done to the temporary at +the end of the object lifetime to which the dynamic initialization is bound.

    +
    +
    +

    4.25.15. Condition Declarations#

    +

    In if, while, for, and switch statements in C++, the expression +tested can be a condition declaration. For example:

    +
    if (float x = f()) { ... }
    +
    +
    +

    This is represented in the IL as an expression node of kind enk_condition. +The condition has its own associated scope, which contains just the one +variable, and which wraps around the statement. Note that the initializations +for conditions in loops are done each time around the loop; if destruction is +also required, it too must be done each time around the loop.

    +
    +
    +

    4.25.16. New and Delete#

    +

    A new operator allocates storage and optionally initializes it. It is +represented by an enk_new_delete expression node. The supplement to that +node provides information about the new routine to be called, the arguments +for that call, and optionally a dynamic initialization entry that describes any +initialization to be done. If the allocation fails (i.e., the new routine +returns NULL), the initialization is not done.

    +

    A delete operator deallocates storage after optionally calling a +destructor. It is represented by an enk_new_delete expression node. The +supplement to that node provides information about the delete routine to be +called, the pointer to the object to be deleted, and optionally a dynamic +initialization entry that describes destruction to be done.

    +

    In both the new and the delete cases, the routine indicated in the +new/delete supplement may be NULL to indicate that the allocation or +deallocation should be done by the constructor or destructor. The dynamic +initialization entry in those cases indicates the appropriate constructor +or destructor. This alternative is controlled by configuration options +NEW_CAN_BE_FOLDED_INTO_CTOR and DELETE_CAN_BE_FOLDED_INTO_DTOR, +which must be true if assignment to “this” (an anachronism) is +supported, because the constructor or destructor must have control of +allocation and deallocation in that case.

    +

    When a delete contains the count of array elements (an anachronism), the +expression between [] is scanned and thrown away; it does not appear in the +IL.

    +

    The C++/CLI gcnew operator is represented by an enk_gcnew expression +node. For CLI array cases, the supplment provides both the bound sizes +(whether explicitly specified or determined from the size of the initializer) +and an initializer aggregate for the element values.

    +
    +
    +

    4.25.17. Lambda Expression#

    +

    A lambda expression – which produces a temporary “closure object” of a +class type with an operator() member – is represented by an +enk_lambda expression node. Such a node points to a supplement entry +of type a_lambda and to an a_dynamic_init entry describing the +initialization and (if applicable) the destruction of the temporary +“closure object” resulting from the expression. The a_lambda entry +describes the static properties of the lambda expression, such as the local +variables it captures (and how they are captured), the closure type, +relevant source positions, etc.

    +
    +
    +

    4.25.18. Throw Expression#

    +

    A throw expression is represented by an enk_throw expression node. It +points to a supplement that points to a dynamic initialization entry that +describes the object to be thrown (or rather, how to make a copy of it, since a +copy is what’s actually thrown); the supplement pointer is NULL in the case of +a “rethrow”.

    +
    +
    +

    4.25.19. Sizeof#

    +

    When a sizeof operator cannot be evaluated at compile time (for instance, +when it is applied to a variable length array), an enk_sizeof expression +node is put out. Such nodes are also used to represent dependent sizeof +expressions in prototype instantiations.

    +
    +
    +

    4.25.20. typeid#

    +

    The typeid operator is represented by an enk_typeid expression node. +It points to the type whose type information is wanted. For cases that require +runtime type determination (e.g., typeid(*p) where p points to a +polymorphic class type), there is also a pointer to an expression whose dynamic +type is to be determined at runtime.

    +

    enk_typeid is also used for the C++/CLI X::typeid feature. That’s +indicated by the is_cli_typeid flag. The result value in that case is a +handle to a System::Type entry.

    +
    +
    +

    4.25.21. VLA Deallocation#

    +

    In C mode, the front end may generate enk_vla_dealloc nodes to indicate +where VLAs should be deallocated. Such nodes may also be created when lowering +C++ IL for VLAs (when DO_IL_LOWERING is TRUE). The nodes are eliminated +from the IL altogether (both in C and C++ modes) if +LOWER_VARIABLE_LENGTH_ARRAYS is TRUE; the nodes are translated to calls +into the run-time support library.

    +
    +
    +

    4.25.22. Parameters#

    +

    When an identifier in an expression refers to a parameter, the resulting IL is +an enk_variable node if the parameter is referenced in the body of a +function. However, it is possible to refer to parameters in expressions that +appear outside the function body. For example, in C++11, a function template +declaration might be as follows:

    +
    template<class T> auto f(T p)->decltype(*p);
    +
    +
    +

    Such uses always appear in unevaluated contexts and are represented with +enk_param_ref nodes, which, like enk_variable nodes, are rvalueable.

    +

    An enk_param_ref node doesn’t point directly to IL representing a +parameter (e.g., a_param_type entries) because such a pointer might +become invalid when, e.g., two function types are combined through +composite_routine_type. Instead, the parameter is represented by two +integers: The parameter position in its enclosing parameter list, and the +“level” of the parameter list relative to the point of reference (function +declarators may be nested and an inner declarator may refer to a parameter +of an enclosing declarator).

    +
    +
    +

    4.25.23. Fixed-point operations#

    +

    Operations on fixed-point values are represented using the usual expression +operators (eok_negate, eok_post_incr, eok_add, eok_divide, +eok_eq, eok_assign, etc.). For mixed-type arithmetic (i.e., operations +involving two different fixed-point types, or a fixed-point type and an integer +type), these operators are different from most of the other (more common) +operators in that their operands are not converted to a common type. For +example, when adding a short int to a long _Accum, the operator is +applied directly to the unconverted operands without “usual arithmetic +conversions.” A back end is then responsible for performing the operation with +maximum precision and converting the result to the result type indicated in the +operator expression node. This arrangement is necessary to meet the +requirements of the Embedded C extensions (ISO/IEC TR 18037).

    +

    Note that while mixed-type fixed-point arithmetic does not in general attempt +to convert the operands to a common type, a conversion from unsigned to signed +may be applied if one operand is signed and the other not. Furthermore, an +operation involving a fixed-point operand and a floating-point operand is a +floating-point operation: The fixed-point operand is converted to a +floating-point type.

    +
    +
    +

    4.25.24. Parentheses#

    +

    Parentheses are represented in the IL as expression operation nodes with an +operator of eok_parens. Those are not usually generated; PARENS_IN_IL +must be set to TRUE to request them. When that flag is TRUE, each pair of +parentheses in a source program expression is represented by an eok_parens +node in the IL for the expression. If EXTRA_SOURCE_POSITIONS_IN_IL is also +TRUE, those expression nodes will include position information on the opening +and closing parenthesis tokens.

    +

    eok_parens nodes are not used or allowed in versions that use IL lowering. +They are intended mostly for source-analysis applications. Note that enabling +PARENS_IN_IL should not be done without reason, because it complicates the +code that deals with expressions. Every bit of code that wants to check for a +specific operator in an expression may have to check for and strip parentheses +off the expression before doing the check. That can be done by calling +skip_parens, but it’s hard to always remember to do that. (This problem is +very similar to the skip_typerefs problem for types, and that is widely +known as a pain and a source of bugs.)

    +
    +
    +

    4.25.25. Fold Expressions#

    +

    A C++17 fold-expression like “(ps + ...  + 1)” where ps contains an +unexpanded parameter pack is represented in generic template contexts (i.e., +“prototype instantiations”) using an enk_fold node. The expansion of the +construct (in real template instantiations), however, uses the ordinary binary +operator representations. For example, if ps expands to a sequence of +integer parameter variables, the expanded representation will involve a tree of +enk_operation/eok_add nodes.

    +
    +
    +

    4.25.26. Boxing and Unboxing#

    +

    C++/CLI boxing and unboxing is implemented by several operators:

    +
      +
    • +
      eok_box takes an operand of a value type (e.g., int) and returns a +handle to a boxed version of the value on the CLR heap (e.g., handle to +System::Int32).
      +
      +
    • +
    • +
      eok_handle_to_box has the same runtime meaning as eok_box, but is +generated for source uses of the unary % operator applied to a value +class.
      +
      +
    • +
    • +
      eok_unbox takes an operand that is a handle to a boxed value class or +boxed enum and returns an lvalue (in place on the heap) or rvalue (copied) +for the contained value, depending on the is_lvalue flag.
      +
      +
    • +
    • +
      eok_unbox_lvalue is similar, but the operand is an lvalue for the value +class or boxed enum. It is always compiler-generated, e.g., on top of an +eok_indirect applied to a handle to a value class.
      +
      +
    • +
    +
    +
    +
    +

    4.26. Pragmas#

    +

    A #pragma directive may be represented in the IL by an entry of type +a_pragma, which appears on a linked list pointed to by the pragmas +field of an IL scope entry. It includes a pointer (see the entity field) +if it is specifically associated with a statement, routine, etc.; the entity +does not point back, but rather has its has_associated_pragma flag set, +since more than one pragma entry may be associated with a given IL entity. For +additional information, see Pragmas and Attributes.

    +
    +
    +

    4.27. Anonymous Unions#

    +

    Anonymous unions are unions that have no name, either for the union type or for +the singular instance of the union. The names of the members of the union are +promoted into the surrounding context. There are two kinds of anonymous +unions:

    +
      +
    • +
      Anonymous unions within classes, as in
      +
      +
      class A {
      +  union {
      +    int i;
      +    float j;
      +  };
      +} x;
      +
      +
      +
      +
      Here, the fields of the anonymous union are promoted into the surrounding +class, so one can refer to x.i.
      +
      +
    • +
    • +
      Anonymous unions as variables, as in
      +
      +
      union {
      +  int i;
      +  float j;
      +};
      +
      +
      +
      +
      Here, i can be used as if it were a variable. Such constructs can +appear at file and namespace scope and within function and block scopes.
      +
      +
    • +
    +

    For the first (field) case, the IL reflects the source form: class A will +contain an unnamed field whose type is an unnamed union, which in turn contains +the fields i and j. A reference like x.i appears as a selection of +i directly from x. By looking at the field for i, one can tell +that it is a member of an anonymous union, and infer the additional field +selection. (IL lowering adds the extra field selection.)

    +

    For the second (variable) case, there will be an unnamed variable whose type is +the unnamed union. A reference like i appears as a selection of i out +of the unnamed variable, so it is more explicit (and less like the source +program) than the field case.

    +
    +
    +

    4.28. Virtual Function Tables#

    +

    There are no “virtual function tables” per se in the unlowered IL. There is +only the information that is part of the definition of virtual functions in the +language:

    +
      +
    • +
      Functions are marked as being virtual, including when they are implicitly +virtual because they override a virtual function from a base class. +Virtual functions are assigned ordinal numbers within a class, which can be +used as their indexes into a virtual function table.
      +
      +
    • +
    • +
      Calls to virtual functions use a special operator, eok_virtual_call.
      +
      +
    • +
    • +
      Base class entries contain information on virtual function overrides, i.e., +on which virtual functions of a base class are overridden by virtual +functions in derived classes (either the one the base class entry is +attached to or some class on the derivation path between the base class and +that one).
      +
      +
    • +
    +

    One can generate a virtual function table for A in B by scanning the +member functions of A looking for virtual functions, along with the +override list for base class A of B. If a function in A does not +appear on the override list, the function from A goes into the virtual +function table. Otherwise, the function from the override list goes into the +virtual function table. More detail can be found in the code in IL lowering +that generates virtual function tables.

    +
    +
    +

    4.29. C99 features#

    +

    The C99 IL extensions over C89 are as follows:

    +
      +
    • +
      For variable-length arrays (VLAs), the front end generates two additional +statement kinds (stmk_set_vla_size and stmk_vla_decl) and +optionally one additional expression node kind (enk_vla_dealloc; see +VLA Deallocation). Types and variables are also marked as being VLAs +when appropriate. This feature can be enabled also in C89 and C++ modes +(by --vla), and is controlled by the macro VLA_ALLOWED (which is +set by default if C99_IL_EXTENSIONS_SUPPORTED is set). If +LOWER_VARIABLE_LENGTH_ARRAYS is TRUE, the VLA-specific constructs are +eliminated from the IL (this requires the run-time support library).
      +
      +
    • +
    • +
      For compound literals, an enk_temp_init node is generated. Such a node +generates a temporary, and is otherwise used only in C++ mode. This +feature can be enabled also in C89 mode (by --compound_literals), and +is controlled by the macro COMPOUND_LITERAL_ENABLING_POSSIBLE (which is +set by default if C99_IL_EXTENSIONS_SUPPORTED is set). C99 lowering +eliminates compound literals by rewriting them as initialized generated +variables.
      +
      +
    • +
    • +
      For designators in initializers, ck_designator constants are +generated in aggregate initializers. This feature can be enabled also +in C89 mode (by --designators), and is controlled by the macro +DESIGNATED_INITIALIZER_ENABLING_POSSIBLE (which is set by default +if C99_IL_EXTENSIONS_SUPPORTED is set). If +LOWER_DESIGNATED_INITIALIZERS is TRUE (which it is by default if +C99 lowering is done), designators are almost completely eliminated; +they remain only for initializations of members other than the first in +unions, which are not possible in C89.
      +
      +
    • +
    • +
      For _Bool, the type is represented as in C++ (the bool_type flag is +set in the integral type). C99 lowering eliminates _Bool by rewriting +the type as a typedef to the underlying integer type.
      +
      +
    • +
    • +
      For complex and imaginary types, there are new type kinds (tk_complex +and tk_imaginary), new constant kinds (ck_complex and +ck_imaginary), and some new operator kinds (e.g., eok_jfadd and +eok_jmultiply) and conversions. If LOWER_COMPLEX is TRUE, C99 +lowering rewrites complex types as structs and imaginary types as +floating-point types, rewrites the constants as aggregate or floating-point +constants, and rewrites the operators and conversions as runtime routine +calls.
      +
      +
    • +
    • +
      For flexible array members, the last member of a struct type may have an +array type with an unknown bound. No lowering is done.
      +
      +
    • +
    • +
      For non-constant expressions in aggregate initializers, the aggregate +constants contain ck_dynamic_init constants, as in C++. C99 lowering +rewrites those as executable code.
      +
      +
    • +
    • +
      For inline functions, the function is marked with the is_inline and +suppress_inline_body flags, as in C++. If MINIMAL_INLINING is +TRUE, C99 lowering replaces inline function calls with the expansions where +possible (as is done in C++).
      +
      +
    • +
    • +
      For longlong, there are two new integer kinds (ik_long_long +and ik_unsigned_long_long) and new constants of these kinds. This +feature can be enabled also in C89 mode and in C++ mode, and is controlled +by the macro LONG_LONG_ALLOWED (which is set by default if +C99_IL_EXTENSIONS_SUPPORTED is set). No lowering is done.
      +
      +
    • +
    • +
      For mixed statements and declarations, the statements and declarations +appear intermixed in the statement list of a compound statement, as in C++. +No lowering is done.
      +
      +
    • +
    +
    +
    +

    4.30. Entry Prefix#

    +

    Each IL entry is preceded by a prefix, which is not part of the IL entry proper +but contains information about the entry that is useful to tree walking +routines and the like:

    +
      +
    • +
      Is the entry allocated in the file-scope memory region?
      +
      +
    • +
    • +
      Has the entry been encountered yet on a tree walk of the IL?
      +
      +
    • +
    • +
      Has the entry been encountered yet by IL lowering?
      +
      +
    • +
    • +
      What entry number has been assigned to the entry (for the alternate IL file +format)?
      +
      +
    • +
    +

    This prefix is allocated in space preceding the beginning of the entry (that +is, one has to do special address arithmetic to get to the prefix; see the +macro il_entry_prefix_of). Some of the flags mentioned above are present +only when required by the front end configuration.

    +
    +
    +

    4.31. Orphans#

    +

    Type entries and static variables that are local to a function require some +special handling. All type entries and all static variables are allocated in +the file scope memory region. However, types and static variables that are +local to a function are placed on the types and static variables list of a +function or block scope. Those are unusual lists: the scope entry (in a +function scope memory region) points to a list that is entirely in the file +scope memory region. Yet, the entries pointed to are not really part of the +file scope. They might, in fact, not be referenced from anywhere except the +function scope memory region. Such entries are “orphaned” in the file scope: +their parents can be processed, written out, and removed from memory, but the +children remain in the file scope, unattached to the rest of the file scope IL +tree.

    +

    A similar problem occurs when an IL entry such as a type is allocated in the +file scope memory region because it might be shared. If the entity is +referenced only from function scope memory regions, it too will be an orphan.

    +

    Orphans are a problem if one wants to process the intermediate language on a +per-memory-region basis. One needs to be able to find all of the orphans when +processing the file scope memory region. There are two mechanisms that help +with this:

    +
      +
    • +
      il_header points to a list of entries of type +a_scope_orphaned_list_header. Each entry on this list holds a copy of +the local type and static variable list pointers for a function or block +scope that has such entries. The a_scope_orphaned_list_header entries +are allocated in the file scope memory region, so they can be used to find +all such lists if the function and block scopes are no longer in memory.
      +

      +
      See the routine add_scope_orphaned_il_lists.
      +
      +
    • +
    • +
      Each file-scope IL entry is preceded by space for a pointer. (This space +precedes the entry prefix.) The pointer is used to chain potential orphans +onto a list of entries of the same kind headed by an element of the global +array orphaned_file_scope_il_entries. Those lists can be traversed +after processing the file scope to find entries that might otherwise be +lost. Note that entries are placed on the list if they are potential +orphans, i.e., if they are allocated in the file scope memory region and +are referenced from a function scope memory region. Most of the entries on +the lists will not be orphans, but all orphans will appear on the list.
      +

      +
      See the routine add_orphaned_file_scope_il_entry.
      +
      +
    • +
    +

    All orphan processing is included only if needed. It is needed if IL lowering +is done or if an IL file is written.

    +
    +
    +

    4.32. Relationship of the IL and the Symbol Table#

    +

    The symbol table of the front end is not part of the intermediate language +structure and is not passed to the back end. It is really mostly a name lookup +mechanism, which one can use to look up a name to get to the associated +intermediate language entry. By the time a back end receives the IL, all +references to entries are simply pointers to the proper entries, and therefore +no name lookup mechanism is needed.

    +

    The symbol table also contains some information that is only needed in the +front end (for error checking or searching) and is not passed to the back end, +or information that has no IL representation (for example, symbol entries for +keywords).

    +

    The symbol table also always reflects the true C and C++ idea of name scoping, +which may not exactly match the IL representation. For example, if we have the +declaration extern int xx in two scopes, each declares a name xx whose +visibility is limited to the scope in which it is declared, but the object (an +integer variable) associated with the name exists over the entire program. +During the front end compilation process there would be two different symbol +entries for xx in two different scopes, but in the intermediate language +there would be only one variable entry for xx, and it would appear at the +file scope level. All references to either xx of the source program would +point to that one entity, and would not indicate which of the original xxs was referenced.

    +
    +
    +

    4.33. Templates#

    +

    The front end generates IL for instances of templates. For example, class +types are generated for instances of class templates and routines are +generated for instances of function templates. A back end can view a +template as a sort of powerful macro expanded by the front end, and can +deal with the generated IL for instances exactly as if the instances were +non-template classes and routines. A code generator need not, in general, +care that the source program contained templates.

    +

    Each template declaration or definition in the source program is +represented by an IL entry of type a_template. A list of those is +attached to the templates field of a_scope. A separate +a_template entry is included for each declaration or definition of a +given template (i.e., there can be more that one a_template entry +associated with a single template; if there is, the first such entry is the +canonical one, and is used when referring to the template itself as opposed +to a given declaration of the template). When the macro +ALL_TEMPLATE_INFO_IN_IL is set to TRUE, a_template entries are also +generated for member functions, static data members, and member classes +nested in class templates. If RECORD_TEMPLATE_STRINGS is TRUE, the +a_template entry contains a pointer to a null-terminated string that is +a textual representation of the template declaration or definition.

    +

    The generated IL for an instance generated from a template does preserve some +indications of the fact that the entity came from a template:

    +
      +
    • +
      The type entry variant for class/struct/union has an is_template_class +flag that is set for template classes. If the class is an instance of a +template, rather than a member of a class that is a template, the class +type supplement’s template_arg_list field gives the list of template +arguments for the template.
      +
      +
    • +
    • +
      The routine entry has an is_template_function flag that is set for +template functions. If the function is an instance of a template, rather +than a member of a class that is a template, the routine entry’s +template_arg_list field gives the list of template arguments for the +template.
      +
      +
    • +
    • +
      The variable entry has an is_variable_template flag that is set for +template variables and template static data members.
      +
      +
    • +
    • +
      The variable and routine entries have instantiation information flags.
      +
      +
    • +
    +

    Template argument lists are represented by a list of a_template_arg +entries. Each entry points to an argument value: an IL type for a type +template argument, an IL constant for a nontype template argument, or an +a_template entry for a template template argument.

    +

    More information about templates is available when the macro +ALL_TEMPLATE_INFO_IN_IL is set to TRUE. With that setting:

    +
      +
    • +
      The assoc_template field (in a class type supplement, routine, or +variable) points to the (canonical) a_template entry for the associated +template.
      +
      +
    • +
    • +
      A canonical_template field of a_template points the canonical +a_template entry for the associated template.
      +
      +
    • +
    • +
      A definition_template field of a_template is set in the canonical +entry to point to the a_template entry associated with the template +definition (if any). In other entries it is NULL.
      +
      +
    • +
    +

    When ALL_TEMPLATE_INFO_IN_IL is TRUE and, in addition, the variable +prototype_instantiations_in_il is TRUE, the IL tree includes IL for +templates themselves (as opposed to IL for instances of templates). This IL is +produced by doing a “prototype instantiation” of the template, which means +doing syntax and (partial) semantic analysis of the template definition without +the use of actual template argument values. Of necessity, such analysis is +incomplete; the meaning of certain constructs cannot be determined until the +actual template argument values are known. Therefore, the IL for prototype +instantiations can contain special generic operators and variants of other IL +constructs that do not appear in normal IL (e.g., eok_lvalue).

    +

    Prototype instantiations of classes are always done. Prototype instantiations +of functions are done when the variable nonclass_prototype_instantiations +is TRUE (see the command-line option --parse_templates). The variable +prototype_instantiations_in_il controls whether prototype instantiations +are preserved in the IL. If the flag is FALSE, the instantiations – if done +– are thrown away and not linked into the IL tree. If the flag is TRUE, the +prototype instantiations are done and preserved, and

    +
      +
    • +
      The a_template entry for each template poimts to IL for its prototype +instantiation: a class type for a class template, a routine for a function +template, or a variable for a variable template or static data member +template.
      +
      +
    • +
    • +
      The a_template entry points to an entry of type a_template_decl, +which provides information about the template header (source position, +parameter list). The information on parameters is given by a list of +entries of type a_template_parameter. (The pointer is NULL for +a_template entries for member functions, static data members and member +classes nested in class templates.)
      +
      +
    • +
    +

    Note that when prototype_instantiations_in_il is TRUE and +nonclass_prototype_instantiations is FALSE only class prototype +instantiations are included in the IL.

    +

    While the front end is processing templates, it is convenient for it to be able +to generate IL versions of entities (like class members) that are not “real,” +i.e., that exist only as part of some template abstraction that will never be +seen by the back end. For those cases, it is helpful to be able to represent +types and constants which are not known but which nevertheless have a certain +identity, e.g., they’re derived from template parameters of a current template. +The tk_template_param type and the ck_template_param constant are used +for those cases. Likewise, a special a_template entry is created to +represent the unknown value of a template template parameter inside a prototype +instantiation. These entities will appear in the IL tree only inside prototype +instantiations.

    +

    C++/CLI generics are represented as templates with an extra flag +(is_generic_definition in both class types and routines). They can also +have additional constraint information, provided by entries of type +a_generic_constraint and a_generic_constraint_clause.

    +
    +
    +

    4.34. Macros#

    +

    If RECORD_MACROS_IN_IL is set to TRUE, entries of type a_macro are +created and added to the macros list of the IL header. The entries +contain a textual version of the macro definition (e.g., a string like +“#define x(a) a+1”), except for predefined macros like __LINE__ and +__FILE__ whose replacement text varies from one invocation to the next. +The entries for these macros contain an empty (zero-length) text string +instead of a fixed definition. If a macro is redefined (to a different +string), there is another macro entry for the new definition. Macro +entries are also used to represent #undef directives.

    +

    The front end can also be configured to maintain detailed information regarding +macro invocations. For instance, it is possible to determine the original +source position of text that appears in the expansion of a macro invocation. +This extra position information can be used to produce more-detailed diagnostic +messages regarding such text, and source analysis tools can more accurately +identify the positions and ranges associated with declarations, expressions, +and statements. It is also possible to determine the chain of macro +invocations that led to a particular macro expansion or to obtain a macro +invocation tree (similar to a function call tree) for an entire translation +unit.

    +

    If FULLY_RESOLVED_MACRO_POSITIONS is TRUE, a_source_position has an +extra sequence/column pair, orig_seq and orig_column. For text +appearing directly in the source, both pairs will indicate the same position. +For text that occurs in a macro expansion, however, +orig_seq/orig_column will be the source position at which the text +originally appeared before being copied into the macro expansion – either in +the definition of some macro or in the argument list of the top-level macro +invocation. (Regardless of the value of FULLY_RESOLVED_MACRO_POSITIONS, +the seq/column pair for all positions in a macro expansion indicate the +initial position of the top-level macro invocation.)

    +

    If MACRO_INVOCATION_TREE_IN_IL is set to TRUE, a flattened macro +invocation tree is kept in the file scope memory region. Because +variably-sized data is awkward to represent in the IL, the list of macro +invocation records is broken into fixed-size blocks of type +a_macro_invocation_record_block, each containing +MACRO_INVOCATIONS_PER_BLOCK records, and these blocks are organized +into a binary tree to reduce the cost of accessing an arbitrary invocation +record.

    +

    There is one record in the tree (of type a_macro_invocation_record) for +each macro invocation that was performed. Each such record indicates the +parent invocation, the macro that was invoked, and the (original) source +position of the macro name that introduced the invocation. Furthermore, if +EXTRA_SOURCE_POSITIONS_IN_IL is TRUE, the record will contain the +(original) ending position of the macro invocation (the last character of the +name of an object-like macro or the closing parenthesis in the invocation of a +function-like macro).

    +

    In addition, when MACRO_INVOCATION_TREE_IN_IL is TRUE, +a_source_position contains the index of the macro invocation record in +whose expansion that position occurs (or NO_PARENT_MACRO_INVOCATION if the +position refers to text that appears directly in source code).

    +

    The macro_context field in a_source_position and +parent_macro_index in a_macro_invocation_record enable +reconstruction of the stack of macro invocations that resulted in the text +at that position. Each macro invocation record is uniquely identified by +an index value of type a_macro_invocation_index, so the macro +invocation stack can be traced simply by following the chain of +parent_macro_index values. (An invocation of macro C is considered +to be a child of an invocation of macro P if C’s invocation appears +in the argument list or the expansion of that invocation of P.)

    +

    For convenience in accessing macro invocation records by index, +il_def.h defines the macro set_macro_inv_record_ptr_to_index(root, index, mirp), which sets a pointer mirp of +type a_macro_invocation_record_ptr to the address of the record at the +specified index, given the tree root (which is found in +il_header.root_macro_invocation_record_block).

    +

    In addition to direct access into the tree by record index, it is possible to +scan the tree sequentially; the records are stored in the same order that the +invocations were performed during preprocessing. To facilitate reconstruction +of the invocation tree during such a traversal without the necessity of +maintaining a separate invocation stack, the array contains certain +“placeholder” records that do not denote macro invocations. Such records are +identified by a negative value (other than NO_PARENT_MACRO_INVOCATION) for +the parent invocation.

    +

    To understand the use of these placeholder records, consider two records +M and N reflecting successive macro invocations. If the parent +invocation of N is the same as that of M, the two invocations are +siblings and the transition from M to N implies no change to the +conceptual invocation stack. If the parent invocation of N is M +itself, then N is a child of M (i.e., invocation M is assumed to be +pushed onto the stack). Otherwise, a non-negative parent index in N is +assumed to be a single-level pop of the conceptual stack – that is, the +parent of N is the parent of M’s parent. In all these cases, the +invocation records for M and N will be at consecutive indices. If, on +the other hand, the parent of N is a more remote ancestor of M, a +placeholder record will be inserted between M and N with a negative +parent index whose absolute value is the number of invocations to pop from +the conceptual stack in order to restore that remote ancestor to the top of +the stack.

    +
    +
    +

    4.35. Attributes#

    +

    C++11 (“standard”), GNU, and Microsoft __declspec attributes are +represented in the IL by entries of type an_attribute. If such attributes +appear on a declaration, they are pointed to by the attributes field of the +corresponding entry’s source correspondence; otherwise, a dedicated attributes +field is used (e.g., in a_param_type). When +RECORD_UNRECOGNIZED_ATTRIBUTES is TRUE, unrecognized attributes are +recorded in the IL with kind ak_unrecognized (when the macro is FALSE, +unrecognized attributes are not recorded and a warning is issued). All +attributes specified in the same “group” point to an entry of type +an_attribute_group. Empty groups contain a pseudo-attribute of kind +ak_empty_attr (or more than one, for a GNU construct like +“__attribute((,,,))”).

    +

    If an attribute includes an argument list, the corresponding attribute entry +points to a list of an_attribute_arg entries. An empty argument list – as +in __attribute((nonnull())) – is represented with an argument entry of +kind aak_empty. Otherwise, the entries in the argument list represent a +constant (aak_constant), a type (aak_type) or an uninterpreted token +(aak_token or aak_raw_token). aak_token entries represent single +tokens that may be followed by other arguments separated by a comma. In +contrast, aak_raw_token entries represent one or more tokens including the +commas; a sequence of aak_raw_token entries is always followed by a +terminating aak_empty entry (used primarily to record the position of the +token that follows in the source – this is useful for diagnostic purposes). +If an unrecognized attribute is followed by a non-empty argument list, that +list consists of aak_raw_token entries (including entries for any commas in +the list). E.g., the unrecognized C++ attribute [[ unrecog(x, y) ]] has +three aak_raw_token argument entries for “x”, “,”, and “y” +(followed by a aak_empty entry).

    +

    Microsoft attributes (delimited by single brackets) are represented in the IL +by entries of type an_ms_attribute. Depending on the configuration of the +front end, a given Microsoft attribute may be either “recognized” or +“unrecognized”. All attributes include a string representation of the +attribute from the source. In addition, recognized attributes include an +argument list representing the arguments that were specified in the attribute +reference.

    +

    Microsoft attributes that apply to function parameters are pointed to by the +param type entry. All other attributes are pointed to by the ms_attributes +field of an IL scope entry. Attributes that apply to a particular entity +include a pointer (see the entity field) to that entity. The entity does +not point back, but rather has its has_associated_attribute flag in its +source correspondence set.

    +
    +
    +

    4.36. Properties#

    +

    Microsoft properties come in two kinds:

    +
      +
    • +
      Old-style properties indicated by the __declspec(property(… )) +attribute. The accessor functions are only loosely associated with the +property, by being named in the attribute.
      +
      +
    • +
    • +
      New-style properties in C++/CLI, which begin with the “property” +context-dependent keyword. The accessor functions are declared as part of +the property declaration, in a form that looks vaguely like a nested class.
      +
      +
    • +
    +

    In both cases, the IL has a description of the property declaration, so that is +retained in something close to the source form (that information is held in +a_property_or_event_descr entry). However, also in both cases, references +to the properties are expanded by the front end, so they are not retained in +source form. A bit of source code like “p+=1” might be +expanded into a series of calls something like “call the get accessor for +p, call operator+ on the fetched value and 1, and call the put accessor +to store the computed value.” The generated IL contains some tags on various +nodes in the expansion that help source-analysis code recover the original +meaning, though in a cumbersome way.

    +

    C++/CLI events are very similar to the new-style properties, in representation +and in the fact that references are expanded by the front end.

    +
    +
    +

    4.37. Microsoft __if_exists blocks#

    +

    Representing __if_exists (and __if_not_exists) blocks in the IL is +problematic because, although the Microsoft documentation describes the +contents of an __if_exists block as a statement, the Microsoft compiler +actually accepts any fragment of a statement or declaration in the block (as +does our front end in Microsoft mode).

    +

    The front end provides a mechanism that can represent __if_exists blocks +that appear in class definitions, and which surround complete declarations of +the class. When an __if_exists appears in a valid location in a class +definition, an IL entry (an_ms_if_exists) and source sequence entry are +created for the start and end of the block. __if_exists blocks in other +scopes are not represented in the IL (but are still included in the textual +representation of templates). If an __if_exists appears in an invalid +context in a class definition, an error is issued.

    +

    IL entries are only created for __if_exists blocks that appear in the +prototype instantiation of class templates and classes nested within class +templates. In non-template contexts, the __if_exists is simply evaluated +when it is encountered.

    +
    +
    +

    4.38. IL Use Within the Front End#

    +

    Some aspects of the IL are used only during the front end processing and are +not seen by back ends.

    +

    Most of the primary table types have a kind used to represent errors (e.g., an +error constant, an error expression). These are used to replace parts of the +IL tree that contain errors. Since the back end is not run if there are +errors, a back end will never see these kinds of entries.

    +

    There are also a few table kinds used for unknown entities (not known yet, but +not an error), for example the unknown type kind tk_unknown. These are +replaced by actual kinds by the time a back end sees the IL.

    +

    Constant expressions are generally folded to a single constant value and +the front end uses that folded value for its processing. In scanning +1+2, for example, the 1 and 2 will be folded into a constant +entry for 3, and that value will be used internally. The original +expression that was folded is generally preserved via the expr field of +a_constant.

    +
    +
    +

    4.39. How To Extend the IL#

    +

    Extending the intermediate language involves making a coordinated set of +changes in several files. Three kinds of changes are discussed below:

    +
      +
    • +
      adding a field to an existing IL entry (typically quite straightforward),
      +
      +
    • +
    • +
      adding a new operator kind (usually also straightforward), and
      +
      +
    • +
    • +
      adding a brand new IL entry (only a little more complicated).
      +
      +
    • +
    +

    Note, however, that what is covered is the typical case. There may be +additional complications. And, of course, nothing of a general nature can be +said about how a field or entity is set and used or how it interacts with other +parts of the IL.

    +
    +

    4.39.1. Adding a Field to an Existing IL Entry#

    +

    This is what you need to do to add a field f of type T to existing IL +entry E with an_il_entry_kind iek_e:

    +
    + + + + + + + + + + + + +
    +
    in il_def.h:
    +
    +
    +
    Add f to E.
    +
    +
    +
    in il_alloc.c:
    +
    +
    +
    Initialize field f in the routine that allocates E objects.
    +
    +
    +
    in il_display.c:
    +
    +
    +
    Add code to display the value of f. This will typically appear +in a function called disp_e, and the display will depend +on the type T. For example, disp_boolean will be called for +a flag, disp_ptr will be called if T is of type +pointer-to-IL-entry, and so forth.
    +
    +
    +
    +

    and in addition, if T is of type pointer-to-IL-entry:

    +
    + + + + + + +
    +
    in walk_entry.h:
    +
    +
    +
    In WALK_ENTRY_ROUTINE_NAME, there will be a case clause +for iek_e within the main switch statement. Here you +will usually need to add a call to walk_ptr or remap_ptr. +(The latter is typically used if f is a secondary reference to +the object it points to, but walk_ptr can be used in any +case.) There are some special cases to look out for, however. For +example, if f points to a linked list, instead of walk_ptr +call either walk_list (if *T uses a next pointer) +or walk_list_on_link_field.
    +
    +
    +
    +

    If f is an addition to the a_type entry, update traverse_type_tree +accordingly.

    +

    If f is an addition to the an_expr_node entry, update traverse_expr +accordingly.

    +

    If f is an addition to the a_statement entry, update +traverse_statement accordingly.

    +

    If f is an addition to the a_dynamic_init entry, update +traverse_dynamic_init accordingly.

    +

    If f is an addition to the a_constant entry in its function as the +description of an initializer, update traverse_constant accordingly.

    +
    +
    +

    4.39.2. Adding a New Operator#

    +

    Most expression nodes (an_expr_node) represent operations +(enk_operation) like additions, assignments, calls, casts, etc. Each of +these operation kinds is identified by an enumeration constant (eok_add, +eok_call, …). To add a new operation kind, it is not sufficient to add +another constant; the following updates are also required:

    +
    + + + + + + + + + + + + + + + +
    +
    in il_def.h:
    +
    +
    +
    Add a string constant to db_operator_names.
    +
    +
    +
    in il_display.c:
    +
    +
    +
    Add a case for the new operator in disp_expr_operator_name.
    +
    +
    +
    in cp_gen_be.c:
    +
    +
    +
    Update generated_precedence to cover the new operator.
    +
    +
    +
    in il.c:
    +
    +
    +
    Update lvalue_rvalue_test and operation_type_kind, and if the +operator has side effects, also operation_has_side_effects.
    +
    +
    +
    +

    Furthermore, if the operator may produce an lvalue (is_lvalue is TRUE) or +xvalue (is_xvalue is TRUE), additional functions must know about the new +operator kind:

    +
    + + + + + + + + + +
    +
    in il.c:
    +
    +
    +
    is_rvalueable_node, node_does_fetch, and +operator_takes_lvalue_operand.
    +
    +
    +
    in exprutil.c:
    +
    +
    +
    conv_prvalue_expr_to_glvalue, and (if is_rvalueable_node +indicates that the operator is not “rvalueable”) +conv_glvalue_expr_to_prvalue.
    +
    +
    +
    +

    Finally, if the operator is an addressing operator, a few other routines +require updating:

    +
    + + + + + + + + + +
    +
    in folding.c:
    +
    +
    +
    constant_glvalue_address and constant_prvalue_pointer.
    +
    +
    +
    in il_walk.c:
    +
    +
    +
    traverse_addressing_subtree.
    +
    +
    +
    +

    Adding a new expression node kind (new enk_...variant) is harder. That +requires looking at all code that handles expressions, in particular switch +statements that case out on the expression kind, and making appropriate +changes. If the new variant includes an embedded type, be sure to update +examine_expr_for_dependent_type.

    +
    +
    +

    4.39.3. Adding an IL Entry#

    +

    This is what you need to do to add an IL entry of struct type X, +where X is a name with the form a_xxx:

    +
    + + + + + + + + + + + + + + + + + + + + + +
    +
    in il_def.h:
    +
    +
    +
    Add the definition of X. Add iek_xxx to the enumeration +an_il_entry_kind. Update the initialization of +il_entry_kind_names and sizeof_il_entry.
    +
    +
    +
    in walk_entry.h:
    +
    +
    +
    Add a case clause for iek_xxx in +WALK_ENTRY_ROUTINE_NAME. Add calls to process orphans in +WALK_ORPHANED_ENTRY_ROUTINE_NAME.
    +
    +
    +
    in il_walk.c:
    +
    +
    +
    Add calls to process orphans in +remap_first_ptr_of_orphaned_file_scope_entry_array and in +remap_last_ptr_of_orphaned_file_scope_entry_array.
    +
    +
    +
    in il_alloc.c:
    +
    +
    +
    Add an alloc_xxx routine. If the entity should always be +allocated in the file scope memory region, call alloc_il; to use +the current memory region, call alloc_cil. (Do not use +alloc_fe for entities in the IL.) If the entity is a supplement to +some other entry (to keep down the size of the containing entry), the +space for the supplement should be allocated when the containing entry +kind is set to that variant. See examples in set_type_kind. In +such cases, you should also change the copy routine for the containing +entity so that it copies the supplement as well. See copy_type +and copy_node for examples. If you want to track the number of +entities of type X that are allocated and how much space they use, +define a static variable num_xxxes_allocated, initialize +it in il_alloc_init, register it in il_alloc_one_time_init in +case precompiled headers are used, increment it in alloc_xxx, +and display it by adding code to show_il_alloc_space_used.
    +
    +
    +
    in il_display.c:
    +
    +
    +
    Add a disp_xxx routine. Add a case clause for +iek_xxx in disp_entry. If the entity is a supplement, +add its kind to the list at the beginning of disp_entry (a +list of entity kinds for which the entity is displayed with the +containing entity), and put the call of disp_xxx in the +clause for the containing entity.
    +
    +
    +
    in il.c:
    +
    +
    +
    If the entry might be an orphan (allocated in the file-scope memory +region, pointed to from something in a function-scope memory region, +but not pointed to from anything in the file-scope memory region), add +the entry kind as a case in +f_possibly_add_orphaned_file_scope_il_entry.
    +
    +
    +
    +

    This is what is required in the general case, but there are potentially many +other issues to consider. For example, if X has a substructure of type +a_source_correspondence:

    +
    + + + + + + + + + +
    +
    in il_alloc.c:
    +
    +
    +
    Be sure alloc_xxx calls set_default_source_corresp. +Add a case clause for iek_xxx in +source_corresp_for_il_entry.
    +
    +
    +
    in il_display.c:
    +
    +
    +
    Add a case clause for iek_xxx in disp_ptr.
    +
    +
    +
    +

    If X is added to a_class_type_supplement, and the field is one that is +meaningful even if the class does not have a definition:

    +
    + + + + + + +
    +
    in il.c:
    +
    +
    +
    If you use “needed” flags (MAINTAIN_NEEDED_FLAGS is TRUE), modify +turn_class_definition_into_declaration to copy X when clearing +the class type supplement.
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/includes/index.html b/doc/includes/index.html new file mode 100644 index 0000000..f5b71ac --- /dev/null +++ b/doc/includes/index.html @@ -0,0 +1,307 @@ + + + + + 20. ANSI C and C++ Include Files - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    20. ANSI C and C++ Include Files#

    +
    +

    20.1. Standard C++ Include Files#

    +

    The following include files are supplied with the front end:

    +
      +
    • +
      compare.stdh
      +
      +
    • +
    • +
      coroutine.stdh
      +
      +
    • +
    • +
      cxxabi.h
      +
      +
    • +
    • +
      exception.h
      +
      +
    • +
    • +
      exception.stdh
      +
      +
    • +
    • +
      initializer_list.stdh
      +
      +
    • +
    • +
      new.h
      +
      +
    • +
    • +
      new.stdh
      +
      +
    • +
    • +
      source_location.stdh
      +
      +
    • +
    • +
      stdexcept.h
      +
      +
    • +
    • +
      stdexcept.stdh
      +
      +
    • +
    • +
      stdfloat.stdh
      +
      +
    • +
    • +
      typeinfo.h
      +
      +
    • +
    • +
      typeinfo.stdh
      +
      +
    • +
    +

    The “. stdh” files are basically the same as the definitions in the C++ +standard. The standard specifies header names without a suffix (e.g., +<new>). The front end, by default, adds the stdh suffix when searching +for the header file. The “.h” versions are supplied so that older code +that uses header names like <new.h> will continue to work.

    +

    Not all of the header files for the libraries required by the C++ standard are +provided. In general, header files are only supplied for components of the +library for which an implementation is supplied with the front end.

    +

    The typeinfo.h header file contains the definition of the type_info +data structure used by the front end and the runtime library. The +type_info structure must not be changed unless corresponding changes are +also made in the front end and runtime.

    +

    The cxxabi.h header includes declarations of routines and data structures +specified by the IA-64 ABI.

    +
    +

    20.1.1. Namespaces and the Standard Header Files#

    +

    When front end configuration flag RUNTIME_USES_NAMESPACES is TRUE the front +end defines the preprocessing macro __EDG_RUNTIME_USES_NAMESPACES. This +flag is tested by the C++ header files to determine whether the runtime +declarations should appear in the global scope or in the std namespace. +The C++ header files also test the __EDG_IMPLICIT_USING_STD flag, which is +defined by the front end when the front end is configured to use namespace in +the runtime and when the --using_std option is specified when the front end +is invoked. This flag causes the header files to do a using namespace std +in any header file that contains declarations for entities in the std +namespace.

    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..23cb09b --- /dev/null +++ b/doc/index.html @@ -0,0 +1,288 @@ + + + + + CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    C/C++ Front End Documentation#

    +
    +
    +
    +

    Introduction#

    +

    This document describes the function and internal structure of the Edison +Design Group C/C++ Front End. More precisely, it gives the general overview +necessary as an introduction to the study of the source code of the Front End. +The source code comments provide more detailed information, and that +information is not necessarily repeated here.

    +

    The front end accepts the C++ language as defined by the ISO/IEC 14882:2020 +standard, as well as a number of the features of the ISO/IEC 14882:2024 +standard. The front end can also be configured to accept earlier revisions of +the C++ standard (e.g., ISO/IEC 14882:2003). With the proper command-line +options, it alternatively accepts the C language of the ISO/IEC 9899:1990, +ISO/IEC 9899:1999, ISO/IEC 9899:2011, and ISO/IEC 9899:2018 standards, as well +as a number of features from the ISO/IEC 9899:2024 standard. Certain other +dialects of C++ and C are also accepted, including Microsoft, GNU and Clang +dialects. C++/CLI, the Microsoft extension to C++ in support of Microsoft’s +.NET environment (and formalized through the ECMA-372 standard), is also +implemented.

    +

    It is a single pass, including integrated preprocessing. (Preprocessing +alone – to a textual output file – can also be done, as in traditional +compilers with a separate preprocessor.) The syntax-analysis technique is +recursive descent, with a precedence modification to speed up the scanning +of expressions.

    +

    The front end does no optimization. Its goal is to produce a complete and +clean parsed form of the source program, and to diagnose errors. It does +complete error checking, produces clear error messages (including the position +of the error within the source line), and avoids cascading of errors. It also +tries to avoid seeming overly finicky to a knowledgeable C or C++ programmer.

    +

    The front end is written in a portable dialect of C++, using features from the +ISO/IEC 14882:2011 standard (i.e., it’s written using C++11 features). Host +and target computer characteristics (e.g., command-line interface, character +sets, integer sizes, floating-point representation) are carefully separated +from the main body of code so that they can be easily changed for rehosting or +retargeting. There is extensive debugging and assertion-checking code, which +can be included or excluded by conditional compilation options.

    +

    The output from the front end is a high-level tree-structured in-memory +intermediate language. This intermediate language contains full information on +declarations, statements, and expressions, all in tree form, and all with +source-correspondence information that simplifies the generation of symbolic +debugging information.

    +

    The intermediate language can, if desired, be written to a file, read back from +such a file, or displayed in human-readable form.

    +

    When it translates C programs to intermediate language, the front end uses only +the C subset of the intermediate language. When it translates C++ programs to +intermediate language, it uses the full intermediate language. However, an +optional IL lowering pass can be used translate the C++ intermediate language +constructs into C intermediate language constructs to reduce the work required +of back ends.

    +

    It is expected that the front end will be combined with an appropriate back end +that will generate object code from the intermediate language. A simple back +end is provided that generates C from the intermediate language, and another +that generates C++ from the intermediate language (the latter is intended for +source-to-source applications).

    +

    Also included: minimal runtime, a template prelinker, an IL display utility, a +name demangler, and prototype header files.

    +

    This document covers:

    +
      +
    • The external interface of the front end – the command-line options, +language dialect, intermediate language, and host/target configuration +issues. (Error messages are listed in an appendix.)

    • +
    • The design of the front end – its philosophy and an overview of the source +code.

    • +
    +

    Readers of this document should be familiar with the C++ language, with the C +language, and with the basics of compiler theory.

    +
    +
    +
    +

    Indices and tables#

    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/int_overview/index.html b/doc/int_overview/index.html new file mode 100644 index 0000000..9543cc5 --- /dev/null +++ b/doc/int_overview/index.html @@ -0,0 +1,2675 @@ + + + + + 3. Overview of Internal Structure - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    3. Overview of Internal Structure#

    +
    +

    3.1. Function of the Front End#

    +

    The front end reads source files written in C or C++, diagnoses any errors in +them, and produces an intermediate language tree that represents the source +program.

    +

    The source files are one primary source file (named on the command line) +and zero or more header files (specified by #include directives). If +COMPILE_MULTIPLE_SOURCE_FILES or COMPILE_MULTIPLE_TRANSLATION_UNITS +is TRUE, multiple source files may be specified on the command line.

    +

    The intermediate language tree is an in-memory representation of the source +program, from which a back end can generate object code. This intermediate +form is high-level (i.e., its constructs correspond closely to C or C++ +constructs). Implicit transformations in the source language are made explicit +in the intermediate language. Source-correspondence information is preserved +so that symbolic debugging information can be generated.

    +

    When it translates C programs to intermediate language, the front end uses only +the C subset of the intermediate language. When it translates C++ programs to +intermediate language, it uses the full intermediate language. However, an +optional IL lowering pass can be used translate the C++ intermediate language +constructs into C intermediate language constructs (this lowering is not +available for C++/CLI and C++/CX).

    +

    The front end does not do any optimizations. It does not transform the program +in other than trivial ways.

    +

    The front end would usually be run from a driver, which invokes the front end +and back end in order, and which validates and distributes the command-line +options. In such a case, the front end would write the intermediate language +information to a file, which would be read by the back end.

    +

    The front end incorporates the preprocessing function of the C and C++ +languages, and does them on the fly as it parses the source program. The front +end can also be run in a preprocessing-only mode, and will generate +preprocessing output as a separate preprocessor would. Comments can be kept or +removed in this process.

    +

    The front end can generate a file containing raw listing information to be used +to assemble a compilation listing. The raw listing file contains raw source +lines, information on transitions into and out of include files, and +diagnostics generated by the front end. A file containing cross-reference +information (information on each reference to an identifier in the source +program) can also be generated in a different file.

    +
    +
    +

    3.2. Guide to the Source Files#

    +

    Note that most source files have a .c file suffix, even though they contain +C++ code and must be compiled with a C++ compiler (with the C++11 dialect). +That naming convention is for historical reasons and for ease in delivering +patches against earlier versions of the front end. Symbolic links (e.g., with +a .cpp suffix) can be added if required by a build environment.

    +

    The source files are:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    attribute.h
    +
    +
    +
    Declarations related to attribute.c (scanning of attributes).
    +
    +
    +
    basics.h
    +
    +
    +
    Basic declarations for every compilation.
    +
    +
    +
    builtin_defs.h
    +
    +
    +
    Declarations related to GCC/clang/Microsoft builtin functions. This +header file is generated automatically by a tool that retrieves the +signatures of these builtin functions from various versions of GCC and +clang compilers (the Microsoft builtin function signatures are +manually input to this automated process).
    +
    +
    +
    builtin_kinds.h
    +
    +
    +
    Builtin function kinds (split from builtin_defs.h to improve +compilation times). This header file is generated automatically by a +tool that retrieves the signatures of these builtin functions from +various versions of GCC and clang compilers (the Microsoft builtin +function signatures are manually input to this automated process).
    +
    +
    +
    c_gen_be.h
    +
    +
    +
    Declarations related to c_gen_be.c (C-generating back end).
    +
    +
    +
    cfe_daemon_common.h
    +
    +
    +
    Declarations related to cfe_daemon.c exposed for utility programs.
    +
    +
    +
    checking.h
    +
    +
    +
    Fundamental declarations associated with assertion checking.
    +
    +
    +
    class_decl.h
    +
    +
    +
    Declarations related to class_decl.c (class declarations +scanning).
    +
    +
    +
    cmd_line.h
    +
    +
    +
    Declarations related to cmd_line.c (command-line parsing).
    +
    +
    +
    const_ints.h
    +
    +
    +
    Declarations related to the manipulation of the internal +representation of integer constants.
    +
    +
    +
    cp_gen_be.h
    +
    +
    +
    Declarations related to cp_gen_be.c (C++/C-generating back end).
    +
    +
    +
    debug.h
    +
    +
    +
    Declarations related to debug.c (debug output).
    +
    +
    +
    decl_inits.h
    +
    +
    +
    Declarations related to decl_inits.c (declaration initializers +scanning).
    +
    +
    +
    decl_spec.h
    +
    +
    +
    Declarations related to decl_spec.c (declaration specifiers +scanning).
    +
    +
    +
    declarator.h
    +
    +
    +
    Declarations related to declarator.c (declarator scanning).
    +
    +
    +
    decls.h
    +
    +
    +
    Declarations related to decls.c (declarations scanning).
    +
    +
    +
    def_arg.h
    +
    +
    +
    Declarations related to def_arg.c (default argument scanning).
    +
    +
    +
    defines.h
    +
    +
    +
    A place to put #defines to configure the front end; +defines.h is included at the beginning of every source file.
    +
    +
    +
    direct_allocator.h
    +
    +
    +
    Declaration and definition of the Direct_allocator template.
    +
    +
    +
    disambig.h
    +
    +
    +
    Declarations related to disambig.c (C++ expression-declaration +disambiguation).
    +
    +
    +
    error.h
    +
    +
    +
    Declarations related to error.c (error reporting).
    +
    +
    +
    err_codes.h
    +
    +
    +
    Definition of the enumeration of error codes. This file is generated +from the error_msg.txt file. See mk_errinfo.
    +
    +
    +
    err_data.h
    +
    +
    +
    Definition of the enumeration of error codes. This file is generated +from the error_msg.txt and error_tag.txt files. See +mk_errinfo.
    +
    +
    +
    expr.h
    +
    +
    +
    Declarations related to expr.c (expression scanning).
    +
    +
    +
    exprutil.h
    +
    +
    +
    Declarations related to exprutil.c (expression scanning +utilities). Also, the data structures used in expression scanning.
    +
    +
    +
    extasm.h
    +
    +
    +
    Declarations related to extasm.c (GNU C extended asm statement +scanning).
    +
    +
    +
    fe_init.h
    +
    +
    +
    Declarations related to fe_init.c (initialization).
    +
    +
    +
    fe_wrapup.h
    +
    +
    +
    Declarations related to fe_wrapup.c (termination).
    +
    +
    +
    fixed_pt.h
    +
    +
    +
    Declarations related to fixed_pt.c (manipulation of fixed-point +constants).
    +
    +
    +
    float_pt.h
    +
    +
    +
    Declarations related to float_pt.c (manipulation of floating-point +constants).
    +
    +
    +
    float_type.h
    +
    +
    +
    Definitions of floating-point conversion routines used when +USE_HOST_FP_CONVERSION_ROUTINES is FALSE. This header file is +included multiple times (once for each distinct floating-point type) +by floating.c.
    +
    +
    +
    floating.h
    +
    +
    +
    Declarations related to floating.c (software-based conversion of +floating-point values between binary and decimal).
    +
    +
    +
    folding.h
    +
    +
    +
    Declarations related to folding.c (folding of constant +operations).
    +
    +
    +
    func_def.h
    +
    +
    +
    Declarations related to func_def.c (processing for function +definitions).
    +
    +
    +
    header_util.h
    +
    +
    +
    General utility components (mostly templates) intended for use in both +headers and compilation units.
    +
    +
    +
    host_envir.h
    +
    +
    +
    Declarations related to host_envir.c (definition of the host +environment, including operating system dependencies). Also, many +host configuration switches.
    +
    +
    +
    host_util.h
    +
    +
    +
    Definitions of host environment functions that are used by both the +front end and utility programs such as the prelinker. When the front +end is compiled, these routines are included as part of +host_envir.c.
    +
    +
    +
    ifc_map.h
    +
    +
    +
    Automatically-generated type declarations and definitions for +interacting with the IFC modules format.
    +
    +
    +
    ifc_map_functions.h
    +
    +
    +
    Automatically-generated function declarations for interacting with the +IFC modules format.
    +
    +
    +
    ifc_modules_inst.h
    +
    +
    +
    Automatically-generated macro invocations to facilitate instantiations +in ifc_modules_templ.c.
    +
    +
    +
    ifc_modules_internal.h
    +
    +
    +
    Declarations related only to the internal +implementation files for IFC modules file support.
    +
    +
    +
    ifc_modules_spec.h
    +
    +
    +
    Automatically-generated macro invocations to facilitate explicit +specializations in ifc_modules_templ.c.
    +
    +
    +
    ifc_modules.h
    +
    +
    +
    Declarations related to IFC modules files.
    +
    +
    +
    il.h
    +
    +
    +
    Declarations related to il.c (intermediate language).
    +
    +
    +
    il_alloc.h
    +
    +
    +
    Declarations related to il_alloc.c (allocation of intermediate +language entities).
    +
    +
    +
    il_def.h
    +
    +
    +
    The definition of the intermediate language.
    +
    +
    +
    il_display.h
    +
    +
    +
    Declarations related to il_display.c (display of intermediate +language in human-readable form).
    +
    +
    +
    il_file.h
    +
    +
    +
    Declarations related to the structure of the intermediate language +file.
    +
    +
    +
    il_read.h
    +
    +
    +
    Declarations related to il_read.c (reading the intermediate +language file).
    +
    +
    +
    il_to_str.h
    +
    +
    +
    Declarations related to il_to_str.c (creating external string-form +representations for certain IL entries).
    +
    +
    +
    il_walk.h
    +
    +
    +
    Declarations related to il_walk.c (walking the intermediate +language tree).
    +
    +
    +
    il_write.h
    +
    +
    +
    Declarations related to il_write.c (writing the intermediate +language file).
    +
    +
    +
    inline.h
    +
    +
    +
    Declarations related to inline.c (minimal inlining for IL +lowering).
    +
    +
    +
    interpret.h
    +
    +
    +
    Declarations related to interpret.c (IL interpreter for +constexpr functions).
    +
    +
    +
    lang_feat.h
    +
    +
    +
    Declarations of configuration switches that affect the source language +accepted.
    +
    +
    +
    layout.h
    +
    +
    +
    Declarations related to layout.c (class object layout).
    +
    +
    +
    lexical.h
    +
    +
    +
    Declarations related to lexical.c (source input and lexical +scanning). Also, the definition of the data structures related to the +current input line.
    +
    +
    +
    lint.h
    +
    +
    +
    A place to put directives to silence the lint program.
    +
    +
    +
    literals.h
    +
    +
    +
    Declarations related to literals.c (conversion of literal +constants).
    +
    +
    +
    lookup.h
    +
    +
    +
    Declarations related to lookup.c (name lookup).
    +
    +
    +
    lower_c99.h
    +
    +
    +
    Declarations related to lower_c99.c (C99 IL lowering).
    +
    +
    +
    lower_eh.h
    +
    +
    +
    Declarations related to lower_eh.c (IL lowering of exceptions).
    +
    +
    +
    lower_il.h
    +
    +
    +
    Declarations related to lower_il.c (IL lowering).
    +
    +
    +
    lower_init.h
    +
    +
    +
    Declarations related to lower_init.c (IL lowering of +initializations).
    +
    +
    +
    lower_name.h
    +
    +
    +
    Declarations related to lower_name.c (name mangling for IL +lowering).
    +
    +
    +
    macro.h
    +
    +
    +
    Declarations related to macro.c (macro definition and invocation).
    +
    +
    +
    mem_manage.h
    +
    +
    +
    Declarations related to mem_manage.c (memory management).
    +
    +
    +
    mem_tables.h
    +
    +
    +
    Declarations related to the memory management data structure.
    +
    +
    +
    modules.h
    +
    +
    +
    Declarations related to the processing of module files.
    +
    +
    +
    ms_attrib.h
    +
    +
    +
    Declarations related to Microsoft attribute processing.
    +
    +
    +
    ms_metadata.h
    +
    +
    +
    Declarations related to ms_metadata.cpp (reading C++/CLI metadata +from assemblies).
    +
    +
    +
    overload.h
    +
    +
    +
    Declarations related to overload.c (overload resolution for +expression processing).
    +
    +
    +
    pch.h
    +
    +
    +
    Declarations related to pch.c (precompiled header processing).
    +
    +
    +
    pragma.h
    +
    +
    +
    Declarations related to pragma.c (processing of #pragma +directives).
    +
    +
    +
    preproc.h
    +
    +
    +
    Declarations related to preproc.c (preprocessing directives).
    +
    +
    +
    scope_stk.h
    +
    +
    +
    Declarations related to scope_stk.c (scope stack management).
    +
    +
    +
    src_seq.h
    +
    +
    +
    Declarations related to src_seq.c (source sequence list +management).
    +
    +
    +
    statements.h
    +
    +
    +
    Declarations related to statements.c (statement scanning). Also, +the definition of the statement stack.
    +
    +
    +
    symbol_ref.h
    +
    +
    +
    Declarations related to symbol_ref.c (symbol references).
    +
    +
    +
    symbol_tbl.h
    +
    +
    +
    Declarations related to symbol_tbl.c (symbol table). Also, the +definitions of the symbol table and the scope stack.
    +
    +
    +
    sys_predef.h
    +
    +
    +
    Declarations related to sys_predef.c (system-specific predefined +macros). Also declarations related to builtins (and the place to add +user-defined builtins).
    +
    +
    +
    targ_def.h
    +
    +
    +
    Declarations that define default target machine characteristics, and +target configuration switches.
    +
    +
    +
    target.h
    +
    +
    +
    Declarations of target configuration variables, initialized to default +values defined in targ_def.h.
    +
    +
    +
    target_cfg.h
    +
    +
    +
    Definitions of target-specific routines to set and dump target +configurations (included once for each target configuration).
    +
    +
    +
    target_map.h
    +
    +
    +
    Definition of various routines that map target-specific configuration +macros to global variables in some fashion (included multiple times).
    +
    +
    +
    templates.h
    +
    +
    +
    Declarations related to templates.c (class and function +templates).
    +
    +
    +
    trans_copy.h
    +
    +
    +
    Declarations related to trans_copy.c (copying of secondary +translation unit IL to primary IL).
    +
    +
    +
    trans_corresp.h
    +
    +
    +
    Declarations related to trans_corresp.c (establishment of +correspondences between translation units).
    +
    +
    +
    trans_unit.h
    +
    +
    +
    Declarations related to trans_unit.c (driver for translation-unit +processing).
    +
    +
    +
    types.h
    +
    +
    +
    Declarations related to types.c (utility routines dealing with +types).
    +
    +
    +
    util.h
    +
    +
    +
    General utility components. This contains a set of (mostly templated) +utilities that are used in place of those that would normally be found +in a C++ standard library. The declarations are conditionally +enclosed in the edg namespace (under control of the +USE_EDG_NAMESPACE configuration macro).
    +
    +
    +
    version.h
    +
    +
    +
    Definition of the current version number of the front end.
    +
    +
    +
    walk_entry.h
    +
    +
    +
    Routines used by il_walk.c to walk through IL entries.
    +
    +
    +
    attribute.c
    +
    +
    +
    Scanning of attributes.
    +
    +
    +
    c_gen_be.c
    +
    +
    +
    The C-generating back end (for use in place of a “real” back end; +generates C code which can be compiled by a native target compiler).
    +
    +
    +
    cp_gen_be.c
    +
    +
    +
    The C++/C-generating back end (for use in source-to-source +transformation).
    +
    +
    +
    cfe.c
    +
    +
    +
    The main program for the front end.
    +
    +
    +
    cfe_daemon.c
    +
    +
    +
    The main program for the front end when built as a daemon..
    +
    +
    +
    class_decl.c
    +
    +
    +
    Class declarations scanning.
    +
    +
    +
    cmd_line.c
    +
    +
    +
    Command-line processing.
    +
    +
    +
    const_ints.c
    +
    +
    +
    Manipulation of the internal representation of integer constants.
    +
    +
    +
    debug.c
    +
    +
    +
    Debug control routines.
    +
    +
    +
    decl_inits.c
    +
    +
    +
    Declaration initializers scanning.
    +
    +
    +
    decl_spec.c
    +
    +
    +
    Declaration specifiers scanning.
    +
    +
    +
    declarator.c
    +
    +
    +
    Declarator scanning.
    +
    +
    +
    decls.c
    +
    +
    +
    Declarations scanning.
    +
    +
    +
    def_arg.c
    +
    +
    +
    Default argument caching and rescanning.
    +
    +
    +
    disambig.c
    +
    +
    +
    C++ expression-declaration disambiguation.
    +
    +
    +
    error.c
    +
    +
    +
    Error reporting.
    +
    +
    +
    expr.c
    +
    +
    +
    Expression scanning.
    +
    +
    +
    exprutil.c
    +
    +
    +
    Utilities for expression scanning.
    +
    +
    +
    extasm.c
    +
    +
    +
    Scanning of GNU C extended asm statement.
    +
    +
    +
    fe_init.c
    +
    +
    +
    Overall initialization.
    +
    +
    +
    fe_wrapup.c
    +
    +
    +
    Overall termination.
    +
    +
    +
    fixed_pt.c
    +
    +
    +
    Manipulation of fixed-point constants: conversion to and from internal +form and conversions and operations on the internal form.
    +
    +
    +
    float_pt.c
    +
    +
    +
    Manipulation of floating-point constants: conversion to and from +internal form and conversions and operations on the internal form.
    +
    +
    +
    floating.c
    +
    +
    +
    Conversion of floating-point values between binary and decimal +formats. Used only when USE_HOST_FP_CONVERSION_ROUTINES is +FALSE.
    +
    +
    +
    folding.c
    +
    +
    +
    Folding of constant operations.
    +
    +
    +
    func_def.c
    +
    +
    +
    Processing for function definitions.
    +
    +
    +
    host_envir.c
    +
    +
    +
    Handling of host-environment dependencies (e.g., file name rules and +opening of files).
    +
    +
    +
    ifc_map_functions.c
    +
    +
    +
    Automatically-generated function definitions for interacting with the +IFC modules format (that do not fit into one of the more specific IFC +map functions files).
    +
    +
    +
    ifc_map_functions_acc.c
    +
    +
    +
    Automatically-generated accessor function definitions for interacting +with the IFC modules format.
    +
    +
    +
    ifc_map_functions_dbg.c
    +
    +
    +
    Automatically-generated debug functions for debugging objects of types +declared in ifc_map.h.
    +
    +
    +
    ifc_map_functions_mut.c
    +
    +
    +
    Automatically-generated mutator function definitions for interacting +with the IFC modules format.
    +
    +
    +
    ifc_map_functions_val.c
    +
    +
    +
    Automatically-generated validation function definitions for validating +objects of types declared in ifc_map.h.
    +
    +
    +
    ifc_modules.c
    +
    +
    +
    Handling of operations common to reading and writing IFC module files.
    +
    +
    +
    ifc_modules_read.c
    +
    +
    +
    Handling of reading IFC modules files.
    +
    +
    +
    ifc_modules_templ.c
    +
    +
    +
    Template definitions and explicit instantiations shared by +ifc_modules.c and the IFC map functions files.
    +
    +
    +
    ifc_modules_write.c
    +
    +
    +
    Handling of writing IFC modules files.
    +
    +
    +
    il.c
    +
    +
    +
    Low-level manipulation of intermediate language constructs.
    +
    +
    +
    il_alloc.c
    +
    +
    +
    Allocation and initialization of intermediate language constructs.
    +
    +
    +
    il_display.c
    +
    +
    +
    Display of the intermediate language in human-readable form.
    +
    +
    +
    il_read.c
    +
    +
    +
    Reading the intermediate language from a file.
    +
    +
    +
    il_to_str.c
    +
    +
    +
    Creating textual representations for certain IL entries +(e.g., constants, types).
    +
    +
    +
    il_walk.c
    +
    +
    +
    Walking the in-memory intermediate language tree.
    +
    +
    +
    il_write.c
    +
    +
    +
    Writing the intermediate language to a file.
    +
    +
    +
    inline.c
    +
    +
    +
    Minimal inlining of function calls for IL lowering.
    +
    +
    +
    interpret.c
    +
    +
    +
    IL interpreter for constexpr functions.
    +
    +
    +
    layout.c
    +
    +
    +
    Laying out class objects.
    +
    +
    +
    lexical.c
    +
    +
    +
    Source input and lexical scanning.
    +
    +
    +
    literals.c
    +
    +
    +
    Conversion of literal constants to internal form.
    +
    +
    +
    lookup.c
    +
    +
    +
    Name lookup.
    +
    +
    +
    lower_c99.c
    +
    +
    +
    IL lowering from C99 to C89.
    +
    +
    +
    lower_eh.c
    +
    +
    +
    IL lowering of exception handling constructs.
    +
    +
    +
    lower_il.c
    +
    +
    +
    Intermediate language lowering (C++ constructs are translated to C +constructs).
    +
    +
    +
    lower_init.c
    +
    +
    +
    IL lowering of initializations, new/delete, and +constructors/destructors.
    +
    +
    +
    lower_name.c
    +
    +
    +
    Name mangling for IL lowering.
    +
    +
    +
    macro.c
    +
    +
    +
    Definition of macros (#define directive) and invocation +(expansion) of macros.
    +
    +
    +
    mem_manage.c
    +
    +
    +
    Memory management (dynamic allocation of storage).
    +
    +
    +
    modules.c
    +
    +
    +
    Generic module file processing.
    +
    +
    +
    ms_attrib.c
    +
    +
    +
    Processing of Microsoft attributes.
    +
    +
    +
    ms_metadata.cpp
    +
    +
    +
    Processing of C++/CLI metadata from assemblies. Contains C++ source +code that can only be compiled on a Microsoft Windows platform.
    +
    +
    +
    overload.c
    +
    +
    +
    Overload resolution for expression processing.
    +
    +
    +
    pch.c
    +
    +
    +
    Precompiled header processing.
    +
    +
    +
    pragma.c
    +
    +
    +
    Processing of #pragma directives.
    +
    +
    +
    preproc.c
    +
    +
    +
    Preprocessing directives.
    +
    +
    +
    scope_stk.c
    +
    +
    +
    Management of the scope stack.
    +
    +
    +
    src_seq.c
    +
    +
    +
    Management of source sequence lists.
    +
    +
    +
    statements.c
    +
    +
    +
    Statements scanning.
    +
    +
    +
    symbol_ref.c
    +
    +
    +
    Processing for symbol references.
    +
    +
    +
    symbol_tbl.c
    +
    +
    +
    Symbol table entry and look up, maintenance of name scoping.
    +
    +
    +
    sys_predef.c
    +
    +
    +
    Definitions of system-specific predefined macros and assertions.
    +
    +
    +
    target.c
    +
    +
    +
    Target configuration support.
    +
    +
    +
    templates.c
    +
    +
    +
    Declaring and instantiating class and function templates.
    +
    +
    +
    trans_copy.c
    +
    +
    +
    Copying of secondary translation unit IL to the primary IL.
    +
    +
    +
    trans_corresp.c
    +
    +
    +
    Establishment of correspondences between externally-linked entities in +different translation units.
    +
    +
    +
    trans_unit.c
    +
    +
    +
    Driver for translation-unit processing.
    +
    +
    +
    types.c
    +
    +
    +
    Utility routines dealing with types.
    +
    +
    +
    unicode_name_fsm.c
    +
    +
    +
    Automatically-generated data file for a finite state machine that +recognizes Unicode character names.
    +
    +
    +
    error_msg.txt
    +
    +
    +
    Contains the definition of the error codes and error messages and is +used to generate err_codes.h and err_data.h. See +mk_errinfo.
    +
    +
    +
    error_tag.txt
    +
    +
    +
    May be used to provide additional error “tags” or aliases that may be +used to reference a given error message in certain command line +options. This is used to generate err_data.h. See +mk_errinfo.
    +
    +
    +
    +

    Note that in general the files are paired. A .h file containing +declarative information corresponds to a .c/.cpp file containing +executable code. The file name.h contains the declarations of the +data structures and externally-callable routines for the file name.c, and is, in effect, the definition of the external interface to that +source file.

    +

    There are also some .h files that contain configuration information and are +not paired with a .c file (e.g., targ_def.h).

    +

    In addition, there is a set of .h files that contain #includes of +other header files. Their purpose is to group header files – both to help +manage their often complicated interactions and to make better use of +compilation systems that perform header precompilation.

    +
    + + + + + + + + + + + + + + + + + + +
    +
    basic_hdrs.h
    +
    +
    +
    Header files devoted to configuration.
    +
    +
    +
    fe_common.h
    +
    +
    +
    Header files common to all .c files.
    +
    +
    +
    decl_hdrs.h
    +
    +
    +
    Header files used for declaration processing.
    +
    +
    +
    expr_hdrs.h
    +
    +
    +
    Header files used for expression processing.
    +
    +
    +
    lower_hdrs.h
    +
    +
    +
    Header files used for IL lowering.
    +
    +
    +
    +

    In rough numbers, the .h files together are about 320,000 lines, and the +.c files about 1,017,000 lines (including IL lowering, the IL display +utility, and the C- and C++-generating back ends). The utility programs are +another 15,000 lines, and the minimal runtime about 11,000 lines.

    +
    +
    +

    3.3. Coding Philosophy#

    +

    This section contains miscellaneous information on the coding style and +philosophy used in writing the front end, which may be useful to those who must +maintain it.

    +

    The configuration section of a previous chapter of this document contains some +important information of this type.

    +

    Code should conform to the C++11 standard and not have any dialect-specific +constructs [1]. The environment dialect switches __ANSIC__, +__SYSV__, and __BSD__ should used to control inclusion of header files +that are not available in all versions of C++. basics.h (which should be +included first in every compilation) takes care of the most common header files +and the most common library routines (it will remap them via macros if +necessary).

    +

    The size argument on calls of functions like memcpy should be wrapped in a +call of the function-like macro size_t_arg if the size is anything other +than a sizeof operator.

    +

    Code that is host-dependent should be written only in host_envir.c and +cmd_line.c.

    +

    Target-dependent code should not be written outside of const_ints.c, +fixed_pt.c and float_pt.c (which are heavily target-dependent) and +literals.c, folding.c, and layout.c (which have some +target-dependent aspects). In particular, be careful about doing anything with +integers without going through the routines in const_ints.c.

    +
    +

    3.3.1. External Names#

    +

    External routines should always be declared both where the body occurs and in +the corresponding .h file. The .h file should be included everywhere +the routine is referenced.

    +

    External variables should be declared in .h files with EXTERN as their +storage class. All .h files that contain external variables must be +included in fe_init.c; there, the macro EXTERN, which ordinarily is +mapped to extern, is mapped to a null string. This makes the same +declarations, when scanned in fe_init.c, external definitions instead of +external references. If an external variable should have an initial value, the +initialization should be included in the .h file, surrounded by #if +VAR_INITIALIZERS/#endif. In fe_init.c the initializer will be +included.

    +

    Of course, variables should be made static instead of external if it is +possible to localize them to a single source file.

    +

    All static variables (external, internal, and function-local) must be saved and +restored as necessary when precompiled headers are generated. The point at +which a precompiled header is written or read is outside of any declaration and +at the file scope (etc.); variables that never have interesting values at such +points need not be saved and restored. All others, however (and these cannot +be function-local), must be registered by calling +register_pch_saved_variables so that they will be written to the +precompiled header file and restored.

    +

    Likewise, variables that are translation-unit specific should be registered by +calling register_trans_unit_variable. See the Multiple Translation Units chapter.

    +
    +
    +

    3.3.2. Include Files#

    +

    Include files always include any other files on which they depend. They also +define a flag once they have been included, and will skip themselves if +included again. (For example, cmd_line.h defines CMD_LINE_H). +Therefore, one can include the files in any order and without regard for +whether or not they have been included by other include files. To improve +compilation speed, #includes can be surrounded by #ifndef +flag/#endif.

    +
    +
    +

    3.3.3. Debug Code#

    +

    Debug code is surrounded by #if DEBUG/#endif. In such code, one should +test the value of debug_level to control output of debug information. +debug_level is zero ordinarily, to indicate that no debug output should be +produced. Debug code should be set to come out at an appropriate level: 1 +is for output that comes out once per source line, 3 for output that comes +out once per token, and 5 for output one would hardly ever want to see. +2 and 4 lie in between those levels in the expected way. Choosing an +appropriate debug level is more of an art than a science. If in doubt, make a +guess at the best level, run the front end with that level of debug output, and +see if the new messages seem out of place in the overall debug output at that +level.

    +

    One can also use db_flag_is_set to determine whether specific output should +be generated. For example, calls of db_flag_is_set("vtbl") are used in IL +lowering to control debug output related to virtual function tables. By +specifying -d-vtbl on the command line, one can get that particular debug +output and nothing else. A particular “flag” is considered set if the string +of the db_flag_is_set call is specified in a command-line debug option, so +a new “flag” is added by adding a call of db_flag_is_set with some new +string; there is no central registry of debug “flags.”

    +

    A similar facility for tracing names is provided by the --db_name=xxxx +command-line option and the db_has_traced_name macro. This can be used to +control extra output about processing of entities with specific names. +db_trace provides a combination of the features of db_flag_is_set and +db_has_traced_name.

    +

    Debugging options that are specified with the -d command-line option can +also be specified using the db_opt pragma. The pragma can be used to +specify a certain debug level or to define a certain debug flag for a portion +of a source program that is being compiled. For example:

    +
    template <class T> void f() {
    +#pragma db_opt -nondep_call
    +  g();
    +#pragma db_opt #nondep_call
    +}
    +
    +
    +

    When a flag name is preceded by “#”, the flag is cleared if previously set.

    +

    Debugging options that are specified with the --db_name command-line option +can also be specified using the db_name pragma.

    +

    The variable db_active is TRUE if debug_level is non-zero or if there +is the potential for it becoming non-zero (i.e., if there is a list of debug +requests from the command line). This can be used to control processing that +may be needed when debug output is generated, but should not be done when no +debugging is requested.

    +

    Diagnostic messages should be written to f_error. This is normally set to +stderr, but in some modes is set to stdout, and can be redirected to a +file by use of a command-line option. Debug output should be written to +f_debug. This is set to f_error, but is a separate file variable to +allow it to be changed if desired.

    +

    Entries and exits of routines should have calls to db_enter and +db_exit. These provide flow tracing. The db_enter call looks like

    +
    +
    +
    db_enter(level, "routine-name");
    +
    +
    +

    The db_exit call has no arguments. These calls will cause an entry +message and an exit message when debug_level is equal to or greater +than the level specified. Note that the calls need not be surrounded by +#if DEBUG/#endif; db_enter and db_exit are actually macros, +and when DEBUG is 0, they are defined as null strings. When +DEBUG is non-zero, they expand to calls to debug_enter and +debug_exit. Those calls are surrounded by ifs testing +db_active so that the routine calls are only done when debug output is +actually being generated (or may be generated, when a list of +routine-related debug requests is specified on the command line).

    +

    It should be clear that for db_exit to work correctly one should have a +single exit point for each routine, and not have return statements in the +middle of routines.

    +

    Some routines do not have db_enter and db_exit calls for speed +reasons – even the overhead of two ifs would be visible. An example is +skip_white_space in lexical.c.

    +
    +
    +

    3.3.4. Checking Code#

    +

    Checking code performs dynamic consistency checking, e.g., verifying the entry +conditions for routines and the consistency of tables. Checking code is always +surrounded by #if CHECKING/#endif. When a problem is found, this code +calls

    +
    +
    +
    internal_error("routine-name: problem found");
    +
    +
    +

    which displays the argument string and causes abnormal termination of the front +end.

    +

    As a concrete example of checking code: all switch statements should +have a default clause; if the default clause does not correspond to any +legal possibility, it should be present as checking code, and should call +internal_error to indicate that a bad value appeared as the switch +selector. (See CHECK_SWITCH_DEFAULT_UNEXPECTED in basics.h and +default_is_unexpected in checking.h for macros that assist in +applying this rule.)

    +

    Several routines are provided as convenient ways to do consistency +checking. Calls of these routines need not be surrounded by #if +CHECKING/#endif; they are defined as macros that expand to nothing +when CHECKING is disabled. check_assertion can be used to check an +expression to make sure it is true. expect_error checks that +total_errors is nonzero at the point of invocation or that it becomes +nonzero before the end of the compilation. This is useful to ensure that +situations that are expected to lead to error diagnostics will indeed do so +(only the first invocation will be reported on failure). +check_assertion_or_expect_error combines the previous two routines: it +has no effect if either the given condition is TRUE, or if total_errors +is nonzero by the end of the compilation. unexpected_condition is used +when a piece of code is not expected to be reached (for example, the +default clause of a switch). Three versions of each of these routines are +provided: the version described above, a version with a _str suffix +that accepts a single string argument, and a version with a _str2 +suffix that accepts two strings. The string(s) are printed on error +termination to provide additional information about the cause of the error.

    +

    The consistency checks that are enabled by the CHECKING flag do not +significantly affect the performance of the front end. There are other +consistency checks whose execution does affect the performance of the front +end. These extra consistency checks are enabled by the EXPENSIVE_CHECKING +flag. These checks are not intended to be enabled when optimum performance is +required (e.g., in production versions of a product).

    +
    +
    +

    3.3.5. Conventions for Declarations#

    +

    The type a_boolean (defined by default as int) should be used for +true/false variables, along with the constants TRUE and FALSE. +These are defined in basics.h and thus are available everywhere. In +structs, a_byte_boolean is used for boolean fields when there is +just one of them. When there are several, bit fields of length one are +used, to save space. Obviously, these rules will not work on all host +machines, but they will work well enough on most.

    +

    Fields in structs are ordered to some extent to reduce the space wasted +in gaps for alignment. It’s assumed that pointers and large integers have +similar size and alignment requirements, and thus a sequence of them will leave +no gaps. When small fields appear, however, they are grouped together to avoid +the gaps one would expect from a series of short/long/short/long fields.

    +

    Bit fields are declared with the type a_bit_field. It is usually +unsigned int, but when compiling with a compiler that uses the Microsoft +bit-field layout algorithm it can be set to unsigned char to get better +packing of the bit fields.

    +

    The type a_byte should be used for small integer fields (i.e., fields +whose values lie in the range 0-127), rather than char or unsigned +char. enum types are often given a base type of a_byte so that +their size is explicitly controlled to save space in structs.

    +

    For each table type (whether or not it is part of the intermediate +language) there is an associated allocation routine and an associated +routine that will set the fields of the table to default values. (In some +cases, these two functions are provided by one routine.) When a table has a +variant section and an associated tag field, there is also a routine to set +the tag field and set the associated variant fields to default values. A +tag field should never be assigned directly; it should only be set by this +routine. Consistent use of the allocation, clear, and set-kind routines +ensures that no uninitialized fields will cause sporadic problems, and that +new fields can be easily added. In addition, it can be useful to add the +following snippet to defines.h :

    +
    #if UNION_AS_STRUCT
    +#define union struct
    +#endif
    +
    +
    +

    Setting UNION_AS_STRUCT in a testing build allocates each variant field +in its own storage. This often allows detection of cases where code +accesses an incorrect variant for a given IL entry.

    +

    The names of macros are written in upper case in the front end source when they +are object-like (e.g., manifest constants), but in lower case when they are +function-like. The names of types and enumerators are written in lower case.

    +

    The names of typedefed, class, and templated types always begin with +a_ or an_ (e.g., a_type, an_expr_node). Pointer type names +end in _ptr. The names of constants in enumerations always begin with +a prefix that hints at the enumeration type (e.g., enk_ for +an_expr_node_kind).

    +
    +
    +

    3.3.6. Storage Allocation#

    +

    Allocation of space is never done by calling malloc or the like directly. +For all table entries, as mentioned earlier, the associated allocation routine +should be called. It will allocate and clear the space, and will also make +sure that the space is allocated in the right area (e.g., intermediate language +constructs must be allocated in the right memory region). For any other +allocation cases, one of the routines in mem_manage.c should be called +instead. alloc_fe has an interface like malloc, and allocates storage +that need not survive the execution of the front end. alloc_general is +similar, and allocates storage that will survive into the back end if the back +end is called as part of the same program (this should not be used ordinarily).

    +

    One case to do carefully: all names that become part of the intermediate +language (file names, directory names, identifier names) should be allocated in +the file-scope intermediate language region, by calling alloc_il.

    +

    Space is never freed by calling free or related routines. Where tables are +reused, the front end maintains individual lists of available entries for each +type of table, and takes entries off those lists before allocating new ones. +Space can be released on a memory region basis, for example to free up all the +space used for a given function once the function has been processed. When the +front end is configured in such a way that it can be re-initialized (by setting +MAKE_FRONT_END_CALLABLE) the front end keeps a record of all memory +allocations and automatically frees the memory when the front end terminates.

    +

    In general, every reasonable attempt is made to not allocate tables unless they +are actually needed. The intermediate language, for example, will contain some +wasted space, but extremely little.

    +

    In order to avoid any fixed limits in the front end, the primary non-IL data +structures are designed so they can be dynamically allocated and expanded +(curr_source_line, scope_stack, etc.). An initial allocation is done +that should cover all expected uses; if more space is needed, the table is +reallocated with a larger size. That means that there is a danger inherent in +keeping around pointers into those data structures, because if the table moves, +all pointers to the table become obsolete. In the input line/macro area, such +pointers are necessary, and there is a pointer registration scheme that is used +to make sure that all pointers are updated if a reallocation occurs. In other +areas, pointers can be avoided relatively easily. A simple rule to remember is +that one should never make a local pointer into one of the primary stacks +(scope_stack, struct_stmt_stack); one should instead use an index value +into the stack, since an index is not invalidated by a reallocation of a table. +When memory is allocated that may later be resized, it must initially be +allocated using either alloc_resizable_buffer or realloc_buffer. It +may then be resized later by calling realloc_buffer.

    +

    One can get a summary of space use by having debug_level non-zero in +fe_wrapup. This can be requested by specifying -dfe_wrapup=1 on the +command line. A summary of symbol table and constant sharing efficiency is +also included.

    +
    +
    +

    3.3.7. Typerefs#

    +

    The description of a type in the intermediate language contains a type entry +kind tk_typeref, which is used to define typedefs, and also to add type +qualifiers to a type, e.g., const in const int. Such an entry is in +some ways not a full-fledged type. For example, it doesn’t indicate its size; +one must go to the underlying type to get that. The macro skip_typerefs +and the function f_skip_typerefs can be used to strip off typerefs and get +to the underlying type, which can then be processed in the normal way. A very +common cause of bugs in code our customers add is failure to put in +skip_typerefs calls where necessary. (For that matter, it’s a common cause +of bugs in our code, though we try hard to find all those bugs before we ship +the code.) The whole skip_typerefs issue is error-prone and requires +discipline, but you do get used to it, and after many years of working with it +we remain convinced that it’s the right way to handle typedefs and type +qualifiers. Just be careful.

    +
    +
    +

    3.3.8. Source Positions#

    +

    Source positions are represented as a structure of type a_source_position +(see basics.h). It contains a sequence number and a column number. The +sequence number is a unique number assigned in ascending order to each source +line as it is read. Unlike a file name and line number, the sequence number is +unambiguous. It’s also more compact, and can be converted to a file name and +line number for external use (this is done in error messages, for example).

    +

    The column number is a 1-origined character position in the original source +line. The character position is the logical character number in the line, not +simply a byte offset. This is significant if the source file contains +multibyte characters or is in a format such as UTF-16. Tab characters are +counted as a single column. The position of text within a macro expansion is +considered to be the first character of the macro name in the macro call in the +original source line that directly or indirectly generated the text.

    +

    If the front end is configured with FULLY_RESOLVED_MACRO_POSITIONS set to +TRUE, each source position contains an additional sequence/column number pair. +For text within a macro expansion, this additional position information gives +the location from which the associated text was copied into the macro +expansion, i.e., a macro definition or macro argument.

    +

    If MACRO_INVOCATION_TREE_IN_IL is configured to TRUE, each source position +referring to text within a macro expansion contains the index of the macro +invocation record that identifies the macro in whose expansion the text at that +position occurs. For text appearing directly in the source, this index will be +NO_PARENT_MACRO_INVOCATION.

    +

    A sequence number of zero is used to indicate an unknown position or a +“position” in initialization, in a predefined macro, or in the command-line. +The column number indicates which. See basics.h.

    +

    Importing assembly metadata in C++/CLI is a process that creates a string +containing C++ code that expresses that metadata and then parses the contents +of that string. Each import is associated with a particular sequence number, +and that number is assigned to the position of each token extracted from that +string (with a column number zero). For example, when compiling a C++/CLI +source file, sequence number one will usually correspond to mscorlib.dll.

    +
    +
    +

    3.3.9. Language Dialect#

    +

    The global variable C_dialect (in cmd_line.h) indicates the C +dialect to be accepted: the choices are C_dialect_cplusplus, +C_dialect_ANSI, and C_dialect_pcc. The macro C_mode() is +useful as a way of testing for C versus C++. cppNN_mode +(where NN is the year of the relevant C++ Standard, e.g., cpp03_mode, +cpp17_mode, etc.) is TRUE when the features of the corresponding +revision of the language should be accepted, and similarly cNN_mode for versions of the C language.

    +

    The global variable strict_ansi_mode is TRUE if use of features that +are not part of the selected C or C++ Standard should cause diagnostics. +strict_ansi_error_severity indicates the level of diagnostic (warning, +discretionary error, or error) that should be produced for such cases.

    +

    microsoft_mode indicates whether a Microsoft dialect (C, C++, C++/CLI, +or C++/CX) is in effect. In configurations that do not allow Microsoft +extensions (i.e., when MICROSOFT_EXTENSIONS_ALLOWED is FALSE), it is a +macro equivalent to FALSE. This allows many Microsoft-mode-specific bits +of code to be written without surrounding them with conditional compilation +directives testing MICROSOFT_EXTENSIONS_ALLOWED. cppcli_enabled +and cppcx_enabled similarly indicate that the Microsoft dialect is +C++/CLI or C++/CX, respectively (if TRUE, microsoft_mode is TRUE too, +and C_mode() is FALSE). Some C++/CLI- and C++/CX-specific code is +delimited by conditional compilation directives testing +MICROSOFT_EXTENSIONS_ALLOWED because it uses variables, data members, +or functions that are available only when that macro is TRUE. (The macro +CPPCLI_ENABLING_POSSIBLE is tested in a few places for code that deals +with the importing of assembly metadata, but it shouldn’t be used to +conditionalize other C++/CLI-specific code. In particular, the IL +extensions representing C++/CLI and C++/CX constructs are only conditioned +on MICROSOFT_EXTENSIONS_ALLOWED.)

    +

    gpp_mode and gcc_mode indicate that, respectively, GNU C++ or GNU C +emulation is in effect. In configurations where GNU_EXTENSIONS_ALLOWED is +FALSE, these are macros equivalent to FALSE.

    +

    clang_mode indicates that clang emulation is in effect. Because the +initial emulation of the clang C++ compiler in the front end was very close +to g++, clang_mode also implies that gpp_mode or gcc_mode will +be set. When it is necessary to distinguish between the GNU and clang +emulations, the macros gnu_version_is, gpp_version_is, +gcc_version_is, clang_version_is, clangcpp_version_is, and +clangc_version_is (see lang_feat.h) allow finer-grained +discrimination (including the compiler version to be emulated). (There are +also corresponding Microsoft-specific macros, ms_version_is, +mscpp_version_is, and msc_version_is.)

    +

    cfront_2_1_mode is TRUE if the cfront 2.1 dialect of C++ is to be compiled. +cfront_3_0_mode indicates the cfront 3.0 dialect. The macro +any_cfront_mode() tests for either of those being set to TRUE.

    +

    (There are other variables/macros that control dialect variations. The ones +mentioned here are among the more frequently used ones.)

    +
    +
    +

    3.3.10. Expression Processing#

    +

    See Rescanning Expressions for some additional coding rules that apply +only within the expression-processing routines.

    +
    +
    +
    +

    3.4. Recursive Descent Parsing#

    +

    “Recursive descent” is an ad-hoc syntax parsing technique. It works well for +languages (like C) where very little lookahead is required to resolve local +ambiguities, and where the language in which the compiler is written is +recursive (as is true for the front end).

    +

    The idea of recursive descent provides a framework and a discipline for parsing +a language, but it is implemented entirely by hand-crafted code. There is +nothing automatic about the parsing. Thus, there is more possibility for error +in developing a recursive-descent parser than there is in developing a +table-driven parser. However, if one writes carefully and tests thoroughly, +the end result is better with a recursive descent parser: faster parsing, +better error recovery, and a clearer compiler (because all of the logic related +to a particular construct appears in one place).

    +

    To implement recursive descent, one writes routines for each non-terminal +construct in the language syntax. For example, one writes a routine to scan an +expression, and one to scan a statement, and one to scan a declaration. The +internal structure of these routines looks a great deal like the syntax of the +constructs they implement. For example, if a declaration is defined as a list +of declaration specifiers followed by a declarator followed by a semicolon, the +routine that scans a declaration would call the routine to scan a list of +declaration specifiers, then the routine to scan a declarator, and then check +for and discard a semicolon. Where the language has recursive constructs, the +routines involved will call each other recursively.

    +

    The terminal tokens that are being parsed come from the lexical routines, +specifically from get_token. At any given moment, there is a current +token (curr_token). It is the next token of input, the one that +hasn’t yet been taken. If the token is an identifier or a literal +constant, there is additional information associated with it. See +lexical.h.

    +

    As the recursive descent routines parse the input tokens, they build up +information on what they have parsed, in the intermediate language trees and in +the symbol table. They also check for and recover from errors.

    +

    The scanning of expressions is one area where recursive descent is inefficient +for languages (like C) where the expression syntax has many levels. A naive +recursive descent implementation would provide a routine for each level of the +expression syntax, and thus scanning a simple expression would involve perhaps +a dozen subroutine calls. For this reason, the front end uses a modified +recursive descent technique to scan expressions. Internal calls to the +scan_expr routine (in expr.c) specify a precedence level, and the scan +routine can decide whether to call itself recursively or not based on the +relative precedences of adjacent operators. With this modification, the number +of calls is reduced to very nearly one per operator. See the description of +expr.c later in this document for more detail.

    +

    To reduce the possibilities for errors in writing the parsing routines, one +should not check for the start of constructs by checking directly for all the +possible first tokens in that construct. Such a list of tokens is inherently +error-prone. For constructs of this kind, there are functions that will +indicate whether or not the current token looks like the start of the construct +(see, for example, is_decl_start in decls.c). Such routines might +themselves call other is_xxx_start routines if the constructs can +themselves begin with other complex constructs.

    +

    Several utility routines in lexical.c are useful for recursive descent +parsing. required_token can be used to check for and discard a required +token, and to issue a specific error message if the token is not present. +loop_token is used to check (at the bottom of the loop implementing an +iterative syntactic construct) for the occurrence of a particular token. The +token is taken if found, but no error is given if the token is not found. +next_token is useful for doing a limited kind of lookahead: it will return +the kind of the token following the current token, without actually getting +that token (actually, it gets it and then puts it back). In many cases, that +one token is enough to allow a decision to be made at a fork in the syntax. +See, for example, the code that recognizes statement labels in statement in +statements.c.

    +

    Consult any of the popular books on compiler theory for a more detailed +overview of recursive descent.

    +
    +
    +

    3.5. Error Recovery#

    +

    When the front end discovers an error, it has several goals:

    +
      +
    • +
      To describe the error clearly and indicate its position (including the +position within the source line);
      +
      +
    • +
    • +
      to recover from the error without generating extra errors;
      +
      +
    • +
    • +
      to preserve as much information as possible about the valid parts of the +construct containing the error, so that detection of other errors is not +needlessly compromised.
      +
      +
    • +
    +

    (“Error” here of course refers to remarks and warnings as well.)

    +

    Describing an error clearly requires that one not only detect the error, but +detect it at an appropriate level, so that the front end can guess better at +what was intended. Sometimes this requires clever code at decision points in +recursive descent parsing, so that on invalid constructs one goes to the more +likely of two subcases. Within the { } for a struct, for example, we +have a series of member declarations separated by semicolons. If a semicolon +is missing, one should not fall out of the loop and leave the scanning of the +struct. In other situations, clearly invalid cases should be flagged at +the higher level, and none of the subcases should be entered. For example, at +the beginning of a statement or a declaration, if the first token is not a +valid start for that construct, an error message (“expected a statement” or +“expected a declaration”) is more informative than descending into any of the +subcases and letting them issue errors.

    +
    +

    3.5.1. Error Positions#

    +

    The position of an error is often just as important as the error text. The +front end tries to give useful error positions. This is aided by the fact that +column positions are maintained for each token. A global variable +error_position indicates the position of the beginning of the last language +construct scanned. It is set by get_token on scanning each token, and it +is also set by each medium-sized language construct (e.g., an expression, a +declarator). Most recursive descent routines save the position of the first +token of the construct they scan, and then set error_position to that +position on return. error_position is the default position for errors when +no explicit position is specified, and this protocol for setting it works well +in ensuring that the error positions are right. Some cases take extra work. +For example, in the expression routines, the position of the left operand and +right operand, and the position of the operator itself, are known for each +operation. If an error is due to a problem with one of the operands, the error +position used is the position of that operand. If the problem is with the +combination of those operands (as in adding a pointer and a float), the error +position used is the position of the operator.

    +

    The macro set_err_pos_to_curr_token is used when one is going forward in +scanning. It sets the error position to the position of the current token. +One would use it, for example, when looking for the = that indicates an +initializer in a declaration. The previous construct (a declarator) has been +scanned and checked, and its position is in error_position. Now, however, +we are going forward, and the = that may have ended the expression scan +should once again be the current construct. In practice, there are few cases +like this; they only come up for optional tokens in the middle of constructs. +required_token handles the change of error position in the more usual case +of a required token.

    +

    When an error refers back to something earlier in the source, it often makes +sense to give the position of the other location rather than the current +location. Variables declared but never used, for example (a warning), are +detected at the closing brace of functions. However, that position is much +less informative than the position of the declaration of the variable in +question, so that is used. Likewise, when a comment is unclosed at end of +file, it is more useful to indicate the position of the start of the comment +instead of the location of the end of file, where the error was detected.

    +
    +
    +

    3.5.2. Error Codes#

    +

    Error messages are mapped to values of the enumeration an_error_code (see +err_codes.h, along with err_data.h for the associated error message +text). For example, ec_exp_line_number represents the message “expected a +line number”. ec_no_error is first in the enumeration, and therefore has +the value zero. Thanks to it, one can return error codes of type +an_error_code, and test them in if statements (non-zero means an +error).

    +

    Errors with codes beginning ec_exp_ (and texts beginning “expected a …”) +are uniformly syntax errors – some expected token or construct was not found.

    +

    The severity of an error is determined by the error routine called (e.g., +error instead of warning) and not by the error code. In fact, there +are cases where the same error code is used as both a warning and an error. +The severity of certain diagnostic messages may be overridden using a command +line option. A diagnostic that is issued with a severity that is less than an +error (i.e., remark, warning, or discretionary error) may have its severity +changed, or may be suppressed completely.

    +

    Some error message texts have fill-ins, as in

    +
    +
    +
    could not open source file "name"
    +
    +
    +

    For these, variants of the error routines should be called. For the case +above, for example, str_error would be called. The fill-in string is +passed to the error routine as a null-terminated string, and replaces +%s where it appears in the error text string. See +Error Reporting for details on the kinds of fill-ins available.

    +
    +
    +

    3.5.3. Syntax Errors#

    +

    In terms of internal processing, one must distinguish syntax errors from +semantic errors. Syntax errors are discovered when the sequence of tokens +in the source program cannot be parsed according to the language syntax +(for example, i=j+;–there’s something missing between the + and +the ;). All other errors are semantic errors – things that can be +parsed but are still nonsensical (for example, use of an undefined +variable, or adding two structs). In error recovery, the important +distinction between the two is that for a syntax error one must decide how +to continue parsing, whereas for a semantic error everything is fine as far +as parsing and there’s no question about how to continue.

    +

    Syntax errors should always cause the calling of flush_tokens in +lexical.c, and semantic errors should never call it. The routine +syntax_error records the occurrence of an error, and then calls +flush_tokens, which is a convenient combination.

    +

    flush_tokens scans and throws again tokens until it finds one in the +stop tokens set, and then returns. Paired tokens are also considered: if +a ( is scanned while flushing tokens, for example, the corresponding +) will be sought before continuing the search for a stop token. There +are some other special cases; see the code in lexical.c.

    +

    The stop tokens set is an array indexed by token kind. Each element of the +array is non-zero if the corresponding token is currently in the stop tokens +set (and thus should halt a flush). As recursive descent routines scan +constructs, they add to the stop tokens set those terminal tokens they expect +to see in their constructs, and then remove those tokens once they are +encountered. The macros add_stop_token and remove_stop_token are +called to add and remove tokens from the set by incrementing and decrementing +the associated element of the array. Since syntactic constructs are nested +inside one another, having each recursive descent routine add the tokens it +recognizes produces a stop tokens set that will halt a flush at a token with +which one of the active routines feels it can continue.

    +

    At boundaries where the syntax changes dramatically, push_stop_token_stack +is called to establish a new set of stop token values. The old values are +restored later by calling pop_stop_token_stack. This is done, for example, +when entering the processing for preprocessing directives, whose syntax is +dramatically different than the context in which they are embedded.

    +

    Uses of add_stop_token and remove_stop_token must be very carefully +paired. A missing call of either would probably cause the associated token to +be handled incorrectly in error flushes for the rest of the compilation. +Skipping a remove_stop_token call is easy to do if one does a goto out +of an inner loop in a recursive descent routine (say, because there is an +error) and one skips over the point where the remove_stop_token is done. +The likelihood of such a problem is lessened by having debug_enter and +debug_exit verify (by means of a checksum) that the contents of +stop_token_array are the same on exit as they were on entry. This check is +only done when debugging is active, however, because it’s time-consuming. +Also, fe_wrapup verifies that all the counts have returned to zero by the +end of the compilation; that check is always done. In addition, when expensive +checking code is enabled, pop_stop_token_stack verifies that all of the +elements of the stop token set that is being discarded have been reset to zero.

    +

    If required_token does not find the token it expects, it adds that token to +the stop tokens set, and calls syntax_error. After flush_tokens +finishes, required_token checks again to see if the desired token has come +up, and if so, scans over it.

    +
    +
    +

    3.5.4. Error Entries#

    +

    For both syntax and semantic errors, another part of error recovery is +producing something sensible, in spite of the error, in the data structure that +represents the program. This task is eased by having special “error” entries +for all of the major table types. There are, for example, error constants, +error types, and error expression nodes. They are used to take the place of +any part of the program tree that cannot be built because of an error. In +general, the code tries to build as much of the complete tree as possible. An +error in one part of an expression, for example, need not mean that the entire +expression tree will be replaced by an error expression node. Throughout the +front end, code must be capable of dealing with error entries. The basic +philosophy is that an error entry is considered to be compatible with anything +else. No additional errors should be issued on encountering an error entry, +since it is assumed that some error was issued when the entry was created.

    +

    When syntax errors involve missing identifiers, special error symbols are +created. A different error symbol is created for each error case. All error +symbols point to the same special associated symbol header (see the +documentation of symbol_tbl.c).

    +

    When errors involve duplicate declarations of the same symbol, the second +symbol is entered anyway. Both symbols are in the symbol table, but because of +the symbol table structure, the later declaration will the one that is visible, +and it therefore effectively replaces the earlier declaration.

    +

    In general, scanning routines do not need to return indications of success or +failure, since they always return a tree representing the construct scanned. +Some routines must deal with unusual cases where there is no possible +representation for the thing scanned, and so they return an error parameter. +The caller must check it.

    +
    +
    +

    3.5.5. Intelligent Error Diagnosis#

    +

    The front end attempts to diagnose as many errors and warnings as possible. If +one uses header files with function prototypes for all external functions and +variables, it should be possible when writing in ANSI C or in C++ to do away +with lint, or at least to relegate it to use in unusual cases. That is the +goal of the front end: diagnose not only errors but also questionable +constructs such as those flagged by lint. However, since lint is run +on request and the front end must be run on each compilation, one must take +care that the errors are not overly pedantic. The front end tries to do this +by being selective about errors. It’s a good idea, for example, to warn about +value-less return statements in functions that should return a value. +However, in old-style C, before the keyword void existed, it was standard +practice to omit the type specifier altogether on a function that returned +nothing. The C language says such a function has type int, but the C +programmer usually thinks of such a function as having type void. So, in +the front end, a warning is issued for a value-less return in a function with +an explicit type, but not for one in a function with an implicit int type. +In pcc mode, a warning is never issued.

    +

    A similar issue comes up in expressions. An expression like 1/0 looks like +an error (division by zero), but should not necessarily cause a compilation +error. If it occurs in a context where it is not evaluated (such as +0&&1/0), it never causes an error; if it occurs in a context where it must +be evaluated at compile time (as in the size of an array), it causes an error; +and if it occurs elsewhere (i.e., in executable code), it causes a warning and +is left as-is to cause a fault (or not) at execution time.

    +

    Likewise, when a constant seems to be part of a bit-oriented operation (it is a +non-decimal constant, or it results from a bit-wise operator applied to +constant operands), the normal warnings about implicit sign changes when the +constant is changed from signed to unsigned or vice-versa are suppressed.

    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/lex_pp/index.html b/doc/lex_pp/index.html new file mode 100644 index 0000000..e670d57 --- /dev/null +++ b/doc/lex_pp/index.html @@ -0,0 +1,2212 @@ + + + + + 7. Lexical Analysis and Preprocessing - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    7. Lexical Analysis and Preprocessing#

    +
    +

    7.1. Source Line Data Structure#

    +

    Before describing the routines involved in lexical analysis and preprocessing, +it is necessary to discuss the data structure that represents the current +source line. This data structure is used throughout the lexical routines, and +its form is dictated by the types of processing that must be done in the +lexical and macro routines. The routines and data structures described in this +section are defined in lexical.c and lexical.h.

    +
    +

    7.1.1. The Current Source Line#

    +

    A logical source line, in the ANSI C standard (2.1.2.2), is what results after +trigraphs have been replaced by the corresponding characters (e.g., ??= by +#) and line splices have been done (i.e., each line ending with a backslash +is spliced with the following line). The routine read_logical_source_line +does this processing, and the global array curr_source_line contains the +result. That is, in curr_source_line trigraphs have already been replaced, +and several physical source lines may have been spliced into one logical source +line. If any such transformations were made to produce the current source +line, the global variable orig_line_modif_list points at a list of entries +that describe all the transformations made, in a form such that

    +
      +
    • +
      the original source lines can be reconstructed from curr_source_line, +if that is necessary (e.g., for error-reporting purposes); and
      +
      +
    • +
    • +
      from a location within curr_source_line, one can determine the file +name, line number, and column from which that text came, for +error-reporting purposes.
      +
      +
    • +
    +
    +
    +

    7.1.2. Modifications to the Current Source Line#

    +

    When changes to the current logical source line are made because of +preprocessing, they are handled in a different way: curr_source_line is not +changed (much); instead, the global variable source_line_modif_list points +to a list of entries that indicate changes that have been made logically to +curr_source_line. Each of these changes is a deletion of some number of +characters at a given location, and an insertion of some number of characters +(possibly none) at that location. These entries represent changes due to +deletion of comments and replacement of macro invocations by the expansions of +those macros. (Comments need not be deleted, even logically, if preprocessing +output is not being produced. In pcc mode, comments are deleted entirely, +but in other modes they are replaced by one blank.)

    +

    The two sets of changes are handled differently, and one might ask why the +trigraphs and line splices are actually rendered in curr_source_line (with +instructions on undoing them), while the macro changes are not rendered (and +the instructions are for doing them rather than undoing them). The reason is +that the first set of changes is applicable at the character or intra-token +level, and the second set only applies at the inter-token level. It is a basic +goal of the lexical routines that the current position must be representable as +a single pointer, and that one be able to move forward efficiently in the input +by just incrementing that pointer. Trigraphs and line splices can occur within +tokens, and therefore if they were not rendered in curr_source_line one +would have to check for them in every case where one wants to move forward in +the input. The other modifications, on the other hand, can only occur between +tokens, and therefore they need not be expanded in the source line. They occur +between tokens, and special marker characters in the input stream are used to +indicate their presence. The marker characters cause the termination of +scanning of the previous token, followed (on the next call of get_token) by +interpretation of the marker character to decide where the input goes next. +This makes macro expansion efficient (the source line need not actually be +subjected to insertions and deletions) while preserving the ability to advance +through the input using just one pointer. It also preserves information that +allows one to construct either the original source line or the macro-expanded +line, and to know the origin of any particular part of the resultant line.

    +

    The modification entries can apply to the inserted text of other modifications, +so one can have modifications of modifications. Wherever a modification is +made, the original character (in curr_source_line or inserted text) is +replaced by a marker character (ATTENTION_MARKER) so that if that spot is +reached by sequential scanning from preceding text, one is cued to look at the +modification list to find the text that follows.

    +

    In extreme cases the data structure can get quite complex, with modifications +on modifications. In cases involving real-world macros, however, it remains +fairly simple.

    +

    ATTENTION_MARKER is a one-character lexical escape sequence. It has to be, +because a macro invocation can be as short as a single character, and the +ATTENTION_MARKER overwrites the beginning of the macro invocation. There +are also two-character lexical escape sequences, which begin with the +LE_ESCAPE character (which is zero). The second character of the escape +sequence is one of the following:

    +
      +
    • +
      LE_END_OF_LINE, which marks the end of the primary source line.
      +
      +
    • +
    • +
      LE_NEWLINE, which represents the newline character at the end of the +primary source line.
      +
      +
    • +
    • +
      LE_END_OF_INSERTION, which marks the end of the text inserted by a +source line modification.
      +
      +
    • +
    • +
      LE_END_OF_TOKEN, which separates tokens in macro text (see below).
      +
      +
    • +
    • +
      LE_INERT_MACRO, which indicates a macro name that should not be +expanded (see below).
      +
      +
    • +
    • +
      LE_NULL, which indicates a null (zero) character in the source line.
      +
      +
    • +
    +

    To ensure that the ATTENTION_MARKER and LE_ESCAPE characters are always +lexical escapes, rather than characters accidentally introduced into the +lexical data structure because of special characters in the input file, the +front end does two rewrites on input:

    +
      +
    • +
      The newline character at the ends of input lines is transformed into a +lexical escape sequence. This frees up the newline character to be used as +ATTENTION_MARKER.
      +
      +
    • +
    • +
      A null (zero) character in an input line is flagged with an error and +replaced by a space. In modes that allow null characters in the source +(e.g., gcc mode), the character is replaced by an LE_NULL escape +sequence (and an original line modification is created, so that column +numbers can be determined correctly).
      +
      +
    • +
    +

    The characters newline and null were selected for use as these reserved +characters because they are already special in the C language and in character +sets in general. No other pair of characters can be guaranteed not to occur in +source files, especially when international character encodings such as SJIS +are considered.

    +

    Note that because LE_ESCAPE is a zero character, the source line and +inserted text cannot be considered to be simple null-terminated strings. Also +note that the ATTENTION_MARKER and LE_ESCAPE characters will naturally +terminate the accumulation of the characters of a token.

    +

    The modification entries of both kinds are dynamically allocated, used, and +then freed when the next logical source line is about to be read. For each +kind, there is an available list (freed entries that are available for reuse), +an allocation routine, and a free routine. See

    +
      +
    • +
      add_orig_line_modif,
      +
      +
    • +
    • +
      free_orig_line_modif,
      +
      +
    • +
    • +
      add_source_line_modif,
      +
      +
    • +
    • +
      free_source_line_modif, and
      +
      +
    • +
    • +
      rem_source_line_modif.
      +
      +
    • +
    +

    The majority (75%?) of source lines have no modifications of any kind (not +counting comments), so the code in the lexical routines is optimized to deal +efficiently with that case.

    +

    Routines assoc_source_line_modif and nested_source_line_modif, along +with the associated macros go_into_insertion and leave_insertion, +handle the low-level tasks of determining where to go next in the input stream +based on the source modifications.

    +

    The current position in the input stream in given by curr_char_loc. +Ordinarily, it points to somewhere within curr_source_line, but when macros +are expanded it can point to somewhere in macro_buffer or to a +dynamically-allocated argument.

    +

    In the text of macro arguments and the replacement text for macros, the +individual characters have already been tokenized once. To ensure that the +tokenization is done the same way if and when it is done again, the text of +each token in source line modifications is followed by an LE_END_OF_TOKEN +lexical escape sequence. That escape sequence terminates the accumulation of +characters to make up a token, and is then ignored as part of the white-space +skip at the start of the next call of get_token. End-of-token sequences +are usually removed by gen_pp_output_for_curr_line, but an individual +end-of-token will be output as a blank if there is the possibility that two +adjacent tokens might be misparsed without one. See the discussion in +macro.c for further information.

    +

    In some obscure cases involving thwarted macro expansion, it is necessary to do +a true insertion into the source line, rather than the usual replacement of +some characters by some others. Fortunately, this only needs to be done at the +beginning of the line, so a simple mechanism suffices: a source line +modification with a NULL location is taken to be an insertion before the first +character of the line. Only one such insertion is allowed per line, and if one +exists, line_start_source_line_modif points to it.

    +

    curr_source_line and macro_buffer are actually dynamically-allocated +arrays, and can be expanded (by reallocation) as necessary. Therefore, there +is no limit to the length of source lines or of macros except that imposed by +available memory.

    +
    +
    +
    +

    7.2. Lexical Analysis#

    +

    “Lexical analysis” includes the reading of source lines and the breaking of +them into lexical tokens. It is also closely tied to preprocessor directives +and to macro processing, since they are invoked at the lexical level, and are +defined in terms of tokens. The source code for lexical processing is in +lexical.c, and associated declarations are in lexical.h.

    +
    +

    7.2.1. Getting Tokens#

    +

    The primary interface to the lexical routines is the routine get_token, +which fetches and returns the next token of input. When compiling C, these +tokens are the input for syntax analysis. When preprocessing only, the tokens +are fetched (by a loop in cpp_driver in preproc.c), and then discarded; +calling get_token repeatedly forces the reading of input lines and the +necessary preprocessing on each line, and each modified line is then written +out just before the next line is read. do_preprocessing_only and +generate_pp_output will be TRUE in that case. get_token is used in +both cases; in fact, it is used for all fetching of tokens in all contexts.

    +

    When get_token is called, it scans the next token of input and returns its +kind. The kind of token is also saved in curr_token. See the enumeration +a_token_kind, in lexical.h, for the list of token kinds (e.g., +tok_identifier, tok_lparen).

    +

    Much of the rest of the processing is dependent on several global switches, as +described in the following paragraphs. Most of these switches are defined in +preproc.h.

    +

    If fetch_pp_tokens is TRUE when get_token is called, a preprocessing +token (pp-token) is fetched instead of a regular token. Constants are not +converted (and numeric ones are returned as pp-numbers); adjacent string +literals are not concatenated; keywords are not recognized; and errors are not +issued for malformed tokens. Also, start_of_curr_token and +end_of_curr_token are set to point to the beginning and end of the current +token, and len_of_curr_token is set to its length.

    +

    If expand_macros is TRUE, preprocessing macros are expanded as they are +scanned. The caller sees only the tokens after expansion. If a macro name is +preceded by an LE_INERT_MACRO escape sequence, the macro is not expanded +and the identifier is returned to the caller with curr_token_is_inert_macro +set to TRUE.

    +

    When fetch_pp_tokens is FALSE, do_string_literal_concatenation controls +whether adjacent string literals are concatenated.

    +

    If in_preprocessing_directive is TRUE, the definition of white space is +changed to that for within preprocessing directives; i.e., keywords are not +recognized, and newline, #, and ## are recognized and returned as +tokens. However, if caching_pragma_tokens is TRUE, a pragma is being +recoded as a token cache, and this requires disabling some of the processing +that is normally done when in_preprocessing_directive is TRUE – +identifiers will be looked up and # and ## are not returned as tokens. +And if recognize_keywords_in_pragma is also set, keywords are looked up and +returned as keyword tokens rather than as identifier tokens. (This is required +for dealing with #pragma directives involving C or C++ constructs that must +be scanned by the compiler’s normal scanning routines; for instance, it is used +for processing the pragmas that control template instantiation.)

    +

    If in_pp_if_expression is TRUE (indicating that we are inside a +preprocessing #if expression), integer constants will get an implicit L +suffix, and undefined identifiers will be returned as the integer constant +0L.

    +

    If exp_header_name is TRUE, then "..." will be scanned as a header name +for an #include (tok_header_name). Other tokens will be processed +normally. exp_system_header_name is similar, for header names of the form +<...>.

    +

    If exp_digit_sequence is TRUE (indicating a string of decimal digits) then +the digits will be scanned as a tok_digit_sequence (used in the #line +directive). Other tokens will be processed normally.

    +

    For tokens that are literal constants, the struct const_for_curr_token is +set to the value of the constant (if fetch_pp_tokens is FALSE). This +global variable is also set for the literal portion of user-defined literals +(when user_defined_literals_enabled is TRUE), along with +ud_lit_op_sym_for_cur_token, which designates the symbol for the literal +operator or literal operator template chosen to produce the value of the +user-defined literal. When ud_lit_op_sym_for_curr_token designates a raw +literal operator or a literal operator template, const_for_curr_token is a +ck_string constant whose value is the actual spelling of the literal part of +the toke; otherwise, it is the value of that literal part.

    +

    For tokens that are identifiers, the corresponding symbol header is looked up +in the symbol table and locator_for_curr_id is set accordingly. For +user-defined literal tokens, locator_for_curr_id is set to designate the +literal-operator-id of the literal operator or literal operator template +denoted by the literal’s ud-suffix. It can be used later to refer to the +current definition of the identifier or operator (if there is one) or to enter +a new definition for the identifier or operator.

    +

    The routine get_token is basically one large switch statement that fans +out based on the current character of input. The various cases are:

    +
      +
    • +
      For operators and similar special-character tokens, get_token looks at +the next character or two and selects the appropriate token.
      +
      +
    • +
    • +
      For the lexical escape sequences (the ATTENTION_MARKER character or the +two-character LE_ESCAPE sequences), skip_white_space is called. These +characters are not all actually white space, but it simplifies processing +to let that routine handle them. All reads of new source lines are +requested by skip_white_space.
      +
      +
    • +
    • +
      For numbers, scan_number is called (it handles decimal, octal, and +hexadecimal integer literals, as well as decimal and hexadecimal +fixed-point and float literals). scan_number will determine the kind +of number, accumulate its characters, and, if appropriate, call the proper +conversion routine in literals.c to convert the literal constant string +to internal form in const_for_curr_token. It also handles recognition +of numeric user-defined literals and, when one is recognized, setting +ud_lit_op_sym_for_curr_token.
      +
      +
    • +
    • +
      For identifiers, the characters are accumulated and find_symbol is +called. This yields a list of symbols with the given name. The list is +then searched for a definition that is a macro or keyword. If the +identifier is a macro and if macro expansion is required, +macro_invocation (in macro.c) is called. Note that because this +look-up finds both macros and other uses of identifiers, a symbol only has +to be looked up once; it does not have to be looked up once to see whether +or not it is a macro, and then again later to see if it is something else.
      +
      +
    • +
    • +
      For quoted tokens (character constants and string literals, and the wide +versions thereof), an appropriate scanning routine is called, which in turn +calls accum_quoted_string. The latter accumulates the characters of +the string, checking for escapes and the like. When a string literal or +wide string literal is scanned outside of preprocessing mode, get_token +will call concat_adjacent_string_literals, which will check if the next +token is another string literal. If so, the adjacent strings will be +concatenated into a single string literal token. scan_char_constant +recognizes user-defined character literals and sets +ud_lit_op_sym_for_curr_token, as appropriate. In order to handle merging +of suffixes across concatenated string literals, the similar task for +user-defined string literals is handled by concat_adjacent_string_literals, +except when fetch_pp_tokens is TRUE; in that case, get_token performs the +requisite processing, as string literals are not concatenated in that mode.
      +
      +
    • +
    • +
      When a # appears as the first non-white-space character on a line, a +call to pp_directive (in preproc.c) is made to process a +preprocessing directive.
      +
      +
    • +
    +

    One very important requirement is that get_token be fast. About 30 percent +of total time time in the front end is likely to be spent in get_token and +its subordinate routines. Every effort has been made to make those routines +fast, and in particular, to avoid unnecessary subroutine calls. As an example, +simple white space (blanks and horizontal tabs) is skipped in get_token +itself, rather than incurring the overhead of calling skip_white_space.

    +

    The handling for pp-tokens and normal tokens differs in a number of ways, but +the most fundamental of those is the information returned to the caller. The +kind of token is returned in both cases. However, for identifiers and literal +constants, where additional information must be returned to precisely specify +the token, the returned value in the pp-token case is the actual characters of +the token, and in the normal token case it is something one step removed from +that: a symbol locator for identifiers, or a constant entry for constants. +This is useful, but it’s also necessary – when scanning normal tokens, and in +particular identifiers and literal constants, there are some cases where it is +necessary to skip forward to the next token to see if it has some effect on the +current one. For example, after scanning a string literal, one must look ahead +to see if the next token is another string literal, and if so, one concatenates +the two. Since the next token may be on another line, it’s clear that the +original string for the token in the current source line may be gone by the +time the next token is reached. Therefore, the locator or constant entry form +is necessary even inside of get_token.

    +
    +
    +

    7.2.2. Token Lookahead and Caching#

    +

    Sometimes syntactic analysis requires lookahead – it requires the fetching +of one or more tokens past the current position to discriminate between two +possible parses.

    +

    This comes up even in C, although the lookahead there is limited to a single +token. For example, when a statement begins with an identifier, one must look +past the identifier to see whether or not the next token is a “:” – if so, +the identifier is a label. (The routine next_token provides this +capability.)

    +

    In C++, lookahead is needed in many more contexts, and is not limited to +one-token lookahead. In addition, there are some language constructs that must +be saved in some lexical form when they appear, and then parsed later on the +basis of the saved information. The most obvious example is the bodies of +member functions declared inside a class: their name binding cannot be done +until the entire class declaration has been scanned, so the easiest +implementation is to save the member function bodies and then parse them when +the closing brace of the class is reached.

    +

    A construct called a token cache supports all these needs for lookahead, as +well as recording the tokens of template definitions and other syntactic +elements for delayed use. a_token_cache is a data structure that represents a +sequence of tokens. The tokens in a cache are represented by a list of shared +tokens (a_shared_token), each one describing an immutable token state (this +includes not just the token kind, but also any additional information required +to fully specify the token, e.g., a symbol locator for an identifier or a +constant entry for a literal constant). A similar data structure, +a_reusable_token_cache, is used for the tokens of a template definition or +delayed construct.

    +

    To build a nonreusable token cache, one declares a variable of type +a_token_cache. Then one reads through tokens in the usual way, calling +get_token to fetch each token, and then calls cache_curr_token before advancing +to the next. When enough lookahead or caching has been done, one can put all +the tokens in the token cache back on the front of the input stream by calling +rescan_cached_tokens.

    +

    get_token does not read directly from nonreusable token caches (although it +does do so with reusable token caches; see below). Instead, +rescan_cached_tokens adds the current token to the end of the cache and then +pushes the cached tokens in LIFO order onto the global +cached_token_rescan_stack (implemented as a stack instead of a list for +efficiency reasons), and finally calls get_token to fetch what was the first +token of the cache from the cached token rescan stack as the current token. As +long as the global rescan stack is non-empty, get_token will fetch a token from +the rescan stack (by calling get_token_from_cached_token_rescan_stack) instead +of scanning a new token from the current source line.

    +

    next_token is a simple user of the token caching facility; it caches the +current token, fetches the next and remembers its kind, then pushes the cache +back on the input stream to restore the original token (and also the next one, +behind it).

    +

    unget_token puts the current token back on the front of the input stream, +so that in effect afterwards there is no current token (although it doesn’t +actually go so far as to change curr_token). It is used in some unusual +error situations that want to fabricate and insert an identifier token where +one was missing in the source.

    +

    Two routines are available to cache sequences of tokens delimited by given +tokens:

    +
      +
    • cache_token_stream_until_matching_token

    • +
    • cache_token_stream_with_coalesce_flag

    • +
    +

    cache_token_stream_with_coalesce_flag is not intended to be called +directly. Instead, it is called by one of two interface routines:

    +
      +
    • cache_token_stream

    • +
    • cache_token_stream_coalesce_identifiers

    • +
    +

    cache_token_stream is used to cache tokens until one of a specified set of +stop tokens is found. This is used, for example, when caching the body of a +class or function template when all tokens up to a closing brace should be +cached. In such situations, the only special processing that is needed is to +keep track of paired delimiter tokens (e.g., {}, [], ()) so that, +for example, the closing brace of an inner block is not incorrectly taken as +the end of the template body.

    +

    When the stop token could appear within a template argument list, additional +processing must be done to determine whether a “<” that is encountered is +the start of a template argument list or simply a less than sign. In order to +determine this, the identifiers found while the tokens are cached must be +coalesced (the identifier coalescing process is described later in this +chapter). This special kind of token stream caching is done by calling +cache_token_stream_coalesce_identifiers. The process of coalescing an +identifier involves fetching some number of tokens. Because these tokens are +not fetched directly by cache_token_stream_coalesce_identifiers, a +mechanism is needed to get access to those tokens. +begin_caching_of_fetched_tokens is called to request that a cache of +fetched tokens be automatically constructed. Each new token returned by +get_token is added to a special cache. The token stream is then cached by +recording the starting token sequence number, getting each token, and +coalescing each identifier that is encountered until the stop token is found. +Once the starting and ending token sequence numbers are known, the tokens in +that range are extracted from the special cache. +end_caching_of_fetched_tokens is then used to indicate that the automatic +caching of tokens is no longer needed.

    +

    As noted above, token caches are also used to represent template definitions +and other syntactic constructs that require delayed processing. The tokens +that comprise the syntactic element are cached when it is scanned and are +rescanned later when needed. While other token caches are rescanned once and +discarded, reusable token caches may be rescanned over and over again. +Reusable token caches should be constructed by calling the factory function +shared_obj<a_token_cache> with reusable set to TRUE (this acts as a sanity +check to ensure the token cache is used in the intended way, but they are +otherwise built in exactly the same manner as other token caches). The +reusable token cache object (of type a_reusable_token_cache) is then +constructed from the result.

    +

    Various scenarios can cause multiple reusable token caches to be pending rescan +at a given time; calling rescan_reusable_cache pushes a reusable token cache +onto the global reusable_cache_stack. get_token first rescans tokens from the +(nonreusable) cached token rescan stack, as described above. When this stack +is exhausted it rescans tokens from the reusable cache at the top of the +reusable cache stack by calling get_token_from_reusable_cache_stack. When all +of the entries in a reusable cache have been scanned the cached token rescan +stack is restored and the entry is popped off of the reusable cache stack. +Token scanning then resumes with the next token on the cached token rescan +stack.

    +

    Reusable and nonreusable token caches may be freely intermixed; template +instantiations may occur while scanning tokens from a cache and a template +instantiation will usually create new caches, as needed, when doing +look-aheads, as described earlier.

    +
    +
    +

    7.2.3. Source Positions#

    +

    Each time a token is fetched, the global variable pos_curr_token is set to +the source position of the first character of the token. A source position +means a sequence number (which can be converted to a file name and line number) +and a column number from the original source line. The position is determined +by the macro macro_line_loc_to_source_pos. In the simplest and most common +case, a pointer to the starting character of the current token can be converted +easily to a source position by using the current sequence number and +determining the column number by taking the difference between the pointer and +the start of curr_source_line and applying an offset to convert the byte +offset into a logical column number using the macro logical_column_offset +(which can in some cases result in a call of f_logical_column_offset). In +more complicated cases, conv_line_loc_to_source_pos is called, and it uses +the information in both orig_line_modif_list and source_line_modif_list +to determine the source position. The source position of something in a +preprocessing modification is taken to be the position of the first character +of the original source line that contains the macro invocation that leads to +the given modification.

    +
    +
    +

    7.2.4. The Input Stack#

    +

    open_file_and_push_input_stack is called to enter both the primary source +file and #include files – by fe_init (in fe_init.c) and by +proc_include (in preproc.c), respectively – and it in turn calls +open_file_for_input and push_input_stack to do the work; when end of +file is reached, pop_input_stack is called.

    +

    open_file_for_input loops to try each possible include file directory when +attempting to open an include file; it also contains code for the (optional) +implicit inclusion feature of automatic template instantiation, permitting a +series of suffixes to be tried in each directory.

    +

    Together, the push/pop routines manage the input_stack, which contains +information about the current nesting of input files. To limit the number of +open files, they will reuse files once a few files have been opened (see +MAX_INCLUDE_FILES_OPEN_AT_ONCE). The storage for input_stack is +dynamically allocated and is reallocated larger as needed.

    +

    If the options requesting makefile information or a list of header files +were specified on the command line, do_preprocessing_only will be TRUE but +generate_pp_output will be FALSE. Either list_makefile_dependencies or +list_included_files will be TRUE. push_input_stack writes out the +appropriate information to the preprocessing output file.

    +

    The front end recognizes certain idioms used to allow an include file to be +included more than once with all of the includes after the first having no +effect. When one of these idioms is recognized the front end will ignore +subsequent attempts to include the file again. The front end recognizes two +commonly used mechanisms used to allow a file to be included multiple time: +placing the entire contents of a file inside a #ifndef or #ifdef, and +use of the #pragma once directive. A simple state machine is used to +determine whether subsequent includes of a given file may be suppressed. The +state information is maintained in the input stack entry. +suppress_subsequent_include_of_file is called for each file to be included. +If it returns TRUE then the call of push_input_stack is skipped and the +include is suppressed. See the comments that precede find_include_history +for additional information.

    +
    +
    +

    7.2.5. Skipping White Space#

    +

    skip_white_space is called to skip over any white space and get to the +start of the next token (some simple cases of white space are skipped in +get_token, for efficiency). Besides the usual white-space characters, it +also handles the skipping of comments, calling read_logical_source_line to +fetch the next line of input, and going into and leaving source modifications +upon encountering lexical escape sequences (e.g., ATTENTION_MARKER to go +into a modification, LE_ESCAPE/LE_END_OF_INSERTION to leave a +modification).

    +

    skip_white_space tracks the kind of white space it has skipped over +(comment/other) and sets global variable kind_of_white_space_skipped. This +information is useful in the macro processing routines, where white space can +be significant. Note that kind_of_white_space_skipped is not necessarily +set correctly if one calls get_token, since get_token does some +white-space skipping on its own.

    +

    When skip_white_space recognizes one of the lint comments

    +
    +
    +
    /*ARGSUSED*/,
    +
    /*NOTREACHED*/,
    +
    /*VARARGS*/, or
    +
    /*VARARGS n*/
    +
    +
    +

    add_curr_token_pseudo_pragma is called. It adds a pending pragma entry to +the current token pragma list. Later, the pending pragma entry is removed via +a call to extract_specific_pragmas, and processed (by setting global state +information or flags in IL entries). For ARGSUSED and VARARGS, that’s done in +record_lint_argsused_and_varargs_state. For NOTREACHED, it’s done in +check_lint_notreached_state.

    +
    +
    +

    7.2.6. Hanging Delete#

    +

    If global variable delete_source_from_loc is non-NULL, the text that +extends from that location in the current line to the position immediately +preceding curr_char_loc is to be deleted. This is referred to as a +“hanging delete”, and is used in deleting macro invocations. This flag is +necessary because the complete text of a macro invocation must be deleted (to +be replaced by the expansion of the macro), but the macro invocation may span +several lines, and the macro routines are not in control when ends of lines are +passed in skip_white_space. By setting this flag, the macro routines can +request that the text of a macro invocation be correctly deleted even if it +spills over onto additional lines. When the deletion is handled at line end, +delete_source_from_loc is updated to point to the start of the new source +line so that the hanging delete remains in effect.

    +
    +
    +

    7.2.7. Whitespace keywords#

    +

    C++/CLI has “whitespace keywords,” which are keywords made up of two words +separated by whitespace but considered a single keyword, for example “refclass”. These are scanned by scan_whitespace_keyword. One interesting +detail is that the characters that make up the token (which can be spread over +multiple lines because of the embedded whitespace) are replaced by a canonical +spelling of the keyword containing a single embedded space, the same way that a +macro is replaced in the input line by its expansion. That allows processing +that deals with tokens on the pp-token level to handle those whitespace keyword +tokens like any others, as a contiguous sequence of characters.

    +
    +
    +

    7.2.8. Textual Preprocessing Output#

    +

    When compiling C to intermediate language, there is no need to assemble the +actual logical source line that results after preprocessing. All that is +required is that the tokens of that line can be extracted. But when +preprocessing only is being done, the preprocessed line is output from +curr_source_line and the information in source_line_modif_list. [1] +gen_pp_output_for_curr_line assembles and puts out the effective line, +calling gen_pp_line_info to generate line-identification directives when +the file/line of the current line does not immediately follow that of the line +previously output. gen_pp_output_for_curr_line is called by +read_logical_source_line right before a new line is read; it is also called +when the input stack is pushed and popped for the starts and ends of input +files.

    +

    There are some special problems in producing the preprocessing output line when +preprocessing directives are passed to output. This must be done for certain +directives (like #pragma) that the preprocessor cannot process. If a +directive of that type contains a multi-line comment, the parts of the +directive preceding and following the comment must be written out on the same +line. In this case, the part preceding the comment will be written without a +terminating newline, and the part following the comment will be written later +on the end of that line.

    +
    +
    +

    7.2.9. Reading Logical Source Lines#

    +

    Aside from its primary function of reading the next logical source line and +processing trigraphs and line splices, read_logical_source_line also calls +gen_pp_output_for_curr_line to output the previous line (if needed), clears +the modification lists, and handles ends of files. It can be told to stay at +the end of a file (rather than popping out to the enclosing file) on end of +file, if that is desirable (as it is when scanning a comment that is unclosed +at end of file). On the ultimate end of file, it returns a special end-of-file +line (containing just an LE_END_OF_LINE lexical escape sequence) in +curr_source_line, and sets after_end_of_all_source.

    +

    If curr_source_line is too small, expand_curr_source_line is called to +reallocate it, and adjust_curr_source_line_structure_after_realloc (in +macro.c) is then called to walk through the data structure associated with +curr_source_line and change any pointers to curr_source_line to point +to the proper addresses within the new allocation for curr_source_line.

    +
    +
    +

    7.2.10. Multibyte characters in source code#

    +

    When MULTIBYTE_CHARS_IN_SOURCE_SUPPORTED is TRUE, multibyte character +sequences are accepted in comments, string literals, character constants, +identifiers, and header names. Multibyte character sequences are not wide +characters (e.g., Unicode); they are sequences of one or more characters, +appearing in a string of characters of the usual char size, and +representing single logical characters. For example, in the Japanese SJIS +encoding, the sequence 82A9 (in hexadecimal) represents a single Kanji +character: the first character (82) is in a range that indicates it is the +first character of a two-character sequence. Typically, the characters in the +ASCII code set will be accepted as themselves in multibyte character encodings, +i.e., they will be sequences of length one. Since each character sequence in a +multibyte character string need not have the same length (and some encodings +have explicit shift-state-change characters), a multibyte character string can +be understood only by scanning it from beginning to end, advancing over one +logical character at a time.

    +

    Moreover, since characters after the first in a multibyte sequence can look +like simple ASCII characters, it is not generally okay to look for an ASCII +character by doing a simple strchr-type search. The lexical routines count +on being able to do this for only two characters: the zero/null character (this +is guaranteed by the C standard; characters after the first in a multibyte +character sequence are not allowed to be zero) and the newline character (this +is effectively guaranteed by the fact that one must be able to read files +containing multibyte character sequences and discern the ends of lines without +tracking the multibyte character state as each character is read). [2]

    +

    To advance over logical characters, one needs a routine that will determine the +length of the multibyte character sequence at a given location. This is done +by the macro mbc_length and routine f_mbc_length. In the usual +configuration, that routine is implemented by calling the standard C library +routine mblen. mbc_length and related routines are used to do special +processing in the following places:

    +
      +
    • +
      In read_logical_source_line, the line splice (”\”) and trigraph +(”?”) characters are ignored if they appear in the middle of a +multibyte character sequence.
      +
      +
    • +
    • +
      In skip_white_space, the closing character for a C-style comment +(”*”) is ignored if it appears in the middle of a multibyte character +sequence. (”//” end-of-line comments require no special handling, +because the end-of-line marker is rendered as a lexical escape +sequence,which cannot appear within a multibyte character sequence.)
      +
      +
    • +
    • +
      In accum_quoted_string, scan_char_literal, scan_string_literal, +conv_single_char, and conv_single_wide_char, the characters inside +quoted strings are scanned as multibyte characters as necessary. The +routine mbc_to_wide_char is used to convert a multibyte character +sequence in a wide string literal or wide character constant to the +appropriate wchar_t character. In the usual configuration, +mbc_to_wide_char is implemented by calling the C library routine +mbtowc.
      +
      +
    • +
    • +
      In get_token, the scanning for identifiers uses is_identifier_char +to recognize identifier characters beyond the basic character set. +make_canonical_identifier handles encoding the multibyte characters +appropriately in the name string for the identifier.
      +
      +
    • +
    +

    Note that not all source code is scanned as multibyte characters, because that +would take too much time. The special scanning is done only in the contexts +listed above. For the line-splice and trigraph cases, when the line-read +routine sees those characters it goes to the beginning of the line and steps +through the characters of the line to find out where the character falls in the +multibyte character sequences, but that processing is done only if a potential +line splice or trigraph appears. Note also that there are configuration +options to turn off the special processing for several of the special +characters, for cases where the encoding guarantees no confusion on the +particular character.

    +

    If the encoding has locking state-change characters (e.g., JIS), each C-style +comment and string is assumed to begin in the initial shift state. This +follows a requirement stated in 5.2.1.2 of the ANSI/ISO C standard

    +

    If UNICODE_SOURCE_SUPPORTED is TRUE, the multibyte encoding selected is the +UTF-8 encoding of Unicode. UTF-16 is also supported, in the little-endian or +big-endian format, and is converted immediately to UTF-8 on input. The type of +source code in a file can be specified by a byte order mark (BOM) at the start +of the file, or by way of the --unicode_source_kind command-line option. +There is also a macro DEFAULT_UNICODE_SOURCE_KIND that can be used to +establish the default for files without a byte order mark.

    +

    When UNICODE_SOURCE_SUPPORTED is set to TRUE, identifiers and file name +strings in the front end are represented in UTF-8. For file names, there is +the expectation that the standard system fopen will be able to deal with UTF-8 +file names. If that isn’t the case, some host-specific code may have to be +added to fopen_interface. (For Windows-hosted configurations, specific +code is provided which calls the _wfopen function.)

    +

    If UTF-8 identifier name strings are somehow undesirable (e.g., a back end or +linker can’t handle them), the macro +IDENTIFIER_STRINGS_ALLOW_MULTIBYTE_CHARS can be set to FALSE, in which case +characters in identifiers outside of the basic character set will be rendered +in the \uxxxx or \Uxxxxxxxx form also used for UCNs. Note, +however, that the encoded form will come out in diagnostic messages that name +an entity in the source.

    +

    If DEFAULT_UNICODE_SOURCE_KIND is usk_none, source files without a byte +order mark are assumed to be encoded in ISO-8859-1 (otherwise known as +Latin-1), which matches the first 256 code points in Unicode. +(LOCALE_TO_SET_WHEN_MULTIBYTE_CHARS_ENABLED should be set to a locale that +matches ISO-8859-1.) Such a mode (which is the default for Windows-hosted +versions) is a hybrid mode in which some files are Unicode and some are not, +and in which therefore a character like a u-umlaut would be encoded differently +depending on the kind of source file it appears in. Such characters in +non-Unicode files are converted to UTF-8 (or the identifier encoding \uxxxx) when they appear in identifiers and file names. In hybrid +configurations, characters in textual preprocessing output are always converted +to UTF-8 if DEFAULT_UNICODE_SOURCE_KIND is not usk_none, and to +ISO-8859-1 otherwise. Characters that cannot be represented in ISO-8859-1 in +the latter case are converted to “?”.

    +

    When UNICODE_SOURCE_SUPPORTED is TRUE, +NATIVE_MULTIBYTE_CHARS_SUPPORTED_WITH_UNICODE may be set to TRUE to +indicate that non-Unicode files are encoded in some character set other than +ISO-8859-1.This feature requires the ability to translate other character sets +to and from Unicode. Such a facility is provided in newer versions of the +Windows API (Microsoft version 1400 and above) so this feature is enabled when +the front end is built with EDG_WIN32 set to TRUE. In identifiers and file +names, native characters are translated to their UTF-8 equivalent. In wide +strings, native characters are translated to their Unicode equivalent. In +narrow strings, they are left in their original form.

    +

    When Microsoft extensions are enabled and EDG_WIN32 is TRUE, this feature +enables support for the Microsoft setlocale pragma, which specifies the +character encoding to be used for the translation to and from Unicode.

    +
    +
    +

    7.2.11. Raw Listing Output#

    +

    gen_raw_listing_output_for_curr_line is called to write source lines to +f_raw_listing when raw listing information is requested; it calls +gen_expanded_raw_listing_output_for_curr_line to write out the +macro-expanded form of the source line if the source line has some +modifications.

    +

    gen_rlisting_line_info writes information about transitions into and out of +include files; it is called by push_input_stack at beginnings of files and +by pop_input_stack at ends of files.

    +
    +
    +

    7.2.12. Inserting Text into the Token Stream#

    +

    insert_string_into_token_stream may be called to cause a string to be +scanned as tokens that are processed as part of the input stream either before +or after processing the current token. When scanning tokens from the string, +macros are optionally expanded and adjacent string literals are concatenated. +The string cannot contain preprocessing directives, and trigraphs are not +recognized.

    +

    This mechanism is used is used to internalize C++ code generated by the C++ +metadata reader (see Declarations from C++/CLI Assembly Metadata) in the functions +scan_top_level_metadata_declarations and get_definition_of_class.

    +
    +
    +

    7.2.13. Utility Routines#

    +

    There are several routines in lexical.c that are utility routines for +syntax analysis, and are not directly related to get_token:

    +
      +
    • +
      flush_tokens is called on the occurrence of a syntax error, and throws +away tokens (by calling get_token) until a token is found that seems an +appropriate place to restart. The current stop token set pointed to by +curr_stop_token_stack_entry contains the set of tokens on which to stop +the flush (it is maintained by the macros add_stop_token, +remove_stop_token, and the routines push_stop_token_stack and +pop_stop_token_stack). Recursive-descent routines place the tokens +they expect in the set of stop tokens; then, if an error occurs, the flush +will stop at a point that one of the recursive descent routines will +recognize. flush_tokens should not in general be called directly; +syntax_error should be called to report a syntax error, and it will +call flush_tokens.
      +
      +
    • +
    • +
      flush_until_matching_token is called by flush_tokens (and can be +called from elsewhere) to flush from an opening token such as a left +parenthesis to the matching closing token.
      +
      +
    • +
    • +
      loop_token is a utility routine that can be called at the bottom of a +loop for a repeated syntactic construct (e.g., a comma-separated list). It +tests for a particular token and takes it if it is found.
      +
      +
    • +
    • +
      required_token is a utility routine that should be called when a +particular token is required to appear next. It checks for that token, and +issues an error if the token is not found.
      +
      +
    • +
    • +
      next_token returns the next token after the current one, without +disturbing the current token. This is used in recursive descent parsing +routines to look ahead at the next token to decide between two paths +through the syntax.
      +
      +
    • +
    • +
      next_two_tokens is similar to next_token except that if the next +token matches a value supplied by the caller the token after the next token +is fetched and returned to the caller. This is used when scanning vacuous +destructor references in C++ where it is necessary to look for a tilde +following a :: to recognize a nonclass vacuous destructor reference +[3].
      +
      +
    • +
    • +
      push_lexical_state_stack and pop_lexical_state_stack are used to +enter and exit a new lexical context. These are used, for example, when +instantiating a template and when switching from fetching normal tokens to +scanning a preprocessing directive.
      +
      +
    • +
    +
    +
    +
    +

    7.3. Scanning Names in C++#

    +

    Unlike C, in which all names are simple identifiers, in C++ the names of +entities are often more complicated. Names may be preceded by one or more +qualifiers such as namespace and class qualifiers (e.g., A::B::i) and +global scope qualifiers (e.g., ::i); class qualifiers may include template +references (e.g., A<int>::i); and the name that follows these qualifiers +may be more complicated than a simple identifier: it may also be an operator +name (e.g., operator+), a conversion function name (e.g., operator +int), a (C++11) literal operator name (e.g., operator ""_km), or a +destructor name (e.g., ~A). An arbitrarily complex name is referred to as +a “generalized identifier”. The process of collecting the tokens of a +generalized identifier and replacing them with a single tok_identifier +pseudo-token is referred to as “coalescing” the generalized identifier. A +hierarchy of routines is provided that scan generalized identifiers:

    +
      +
    • +
      is_generalized_identifier_start determines whether the current token +begins a generalized identifier and, if so, scans the tokens that comprise +the generalized identifier and records its description in +locator_for_curr_id.
      +
      +
    • +
    • +
      coalesce_and_lookup_qualified_name calls +is_generalized_identifier_start and, if the generalized identifier +includes a qualifier, the name after the qualifier is looked up in the +scope specified by the qualifier. Names without qualifiers are not looked +up. [4]
      +
      +
    • +
    • +
      coalesce_and_lookup_generalized_identifier is used to scan and look up +a generalized identifier. It calls coalesce_and_lookup_qualified_name +and looks up the name if it does not include a qualifier. Names that +include qualifiers will have already been looked up by +coalesce_and_lookup_qualified_name.
      +
      +
    • +
    +

    The arguments to these routines include options used to specify the kinds of +names that may be accepted and, for the coalesce-and-look-up routines, a lookup +mode that specifies the type of name lookup to be performed. The options +parameter specifies a set of “generalized identifier” (GID) flags. The GID +flags specify several different types of information:

    +
      +
    • +
      The kinds of identifiers that should be recognized. For example, ~A +may be recognized as a destructor, or the tilde may be an operator.
      +
      +
    • +
    • +
      The kinds of identifiers that are allowed. For example, are qualified +names allowed in this context? Are operator names allowed? The difference +between constructs that are “recognized” and those that are “allowed” is +that constructs that are not recognized (i.e., ~D) are not considered +identifiers by is_generalized_identifier_start while constructs that +are not allowed are considered identifiers but cause errors to be issued +indicating that the particular type of identifier is not permitted in the +current context.
      +
      +
    • +
    +
    +

    7.3.1. Recognizing Generalized Identifiers#

    +

    is_generalized_identifier_start is the lowest-level generalized identifier +routine and does most of the work. As the name suggests, +is_generalized_identifier_start is used to determine whether the current +token is the beginning of a generalized identifier.

    +

    is_generalized_identifier_start is actually a macro that first checks +whether the current identifier has already been coalesced. If it has, the +macro immediately returns TRUE; otherwise it calls +f_is_generalized_identifier_start, which performs the rest of the +processing described here.

    +

    For these examples is_generalized_identifier_start returns TRUE and sets +the current token to tok_identifier:

    +
    +
    +
    i::iX::i
    +
    ::X::i
    +
    ::A::B::i
    +
    A<int>::i
    +
    A::operator =
    +
    A::operator int
    +
    A::operator ""_km // When user-defined literals are recognized
    +
    A::~A
    +
    NS::i
    +
    NS::A::i
    +
    operator =
    +
    operator int
    +
    operator ""_km    // When user-defined literals are recognized
    +
    ~A                // When destructors are recognized
    +
    A<int>
    +
    NS::A<int>
    +
    ~int              // When nonclass vacuous destructors are recognized
    +
    int::~int         // When nonclass vacuous destructors are recognized
    +
    A::anything else except *   // Error
    +
    +
    +

    For these examples FALSE is returned and current token is set to +tok_ptr_to_member:

    +
    +
    +
    X::*
    +
    A<int>::*   // Template reference will be coalesced
    +
    +
    +

    For these examples FALSE is returned and the current token is not changed:

    +
    +
    +
    ::new
    +
    ::delete
    +
    ~A          // When destructors are not recognized
    +
    anything else
    +
    +
    +

    Determining whether or not the current token is the start of an identifier may +involve scanning all of the tokens that comprise the identifier. Consequently, +all of the tokens that make up an identifier are scanned the first time that +is_generalized_identifer_start is called for a given identifier. The +information needed to describe the generalized identifier is recorded in the +symbol locator, and on subsequent calls the information from the locator is +used to return the appropriate value to the caller. When a sequence of tokens +is coalesced the original tokens are replaced with a single tok_identifier +or tok_ptr_to_member. The resulting token and related state information in +the locator is referred to as a “pseudo-token”. When +is_generalized_identifier_start determines that the thing being scanned is +an identifier, the current token is set to tok_identifier, the locator is +updated with a description of the identifier, and the return value of the +function is TRUE. The fields in the locator that are set are

    +
      +
    • +
      is_qualified_name
      +
      +
    • +
    • +
      is_global_qualified_name
      +
      +
    • +
    • +
      is_file_scope_qualified_name
      +
      +
    • +
    • +
      is_operator_name
      +
      +
    • +
    • +
      is_destructor_name
      +
      +
    • +
    • +
      is_udl_operator_name
      +
      +
    • +
    • +
      is_class_member
      +
      +
    • +
    • +
      parent
      +
      +
    • +
    • +
      has_been_coalesced
      +
      +
    • +
    • +
      is_vacuous_destructor_reference
      +
      +
    • +
    • +
      is_nonclass_destructor
      +
      +
    • +
    +

    When coalescing a qualified name such as A::xxx the result is a locator +whose symbol header points to the name xxx, and whose parent points to +the A. If A is a class, is_class_member is TRUE and +parent.class_type points to the type of A. If A is a namespace, +is_class_member is FALSE and parent.namespace_ptr points to the +namespace entry for A. The final identifier (xxx) is not looked up. +Instead, the information is preserved in the locator so that, if necessary, +xxx can be looked up by coalesce_and_lookup_qualified_name.

    +

    is_generalized_identifier_start coalesces template class references of the +form A::i, [5] A<T>, and A<T>::i (but not simply A) by +calling coalesce_template_id. These references must be coalesced to +determine whether the template reference is the beginning of a qualified name +(e.g., A<int, float>::i cannot be determined to be a qualified name until +the :: is seen.) The result of a template class reference is an incomplete +instantiation. A complete instantiation is only generated when it is required +for a name to be looked up. A complete instantiation will be generated for +references like A<T>::X::Y, because X must be looked up in A<T>. A +complete instantiation will not be generated (at least not here) for references +like A<T>::X. The complete instantiation is delayed until X needs to +be looked up (typically in coalesce_and_lookup_qualified_name.) A template +argument list may also follow a function template name or an overloaded +function name in which one of the members of the overload set is a function +template. This is known as “explicit specification of function template +arguments”. Unlike template class references, a template function reference +cannot be resolved to a given template instance when the template argument list +is scanned (because function templates can be overloaded). As a result, when a +function template argument list is scanned, a pointer to the list is retained +in the symbol locator, but the reference is not otherwise resolved at this +point.

    +

    The pointer operator used when declaring a pointer-to-member looks a lot like a +qualified name; the only difference is that the final identifier is replaced +with an asterisk (*). For example, a pointer-to-member operator may look +like A<int>::B::C::*. Because of this similarity pointer-to-member +operators are also coalesced by is_generalized_identifier_start even though +they are not considered identifiers. When a pointer-to-member operator is +coalesced the current token is set to tok_ptr_to_member, the +parent.class_type field of the locator points to the type specified in the +operator (e.g., A<int>::A::B::C in the previous example), and the return +value of the function is FALSE.

    +

    The operators ::new and ::delete look like qualified names but are +actually operators. When called for these operators, +is_generalized_identifier_start leaves the current token unchanged and +returns FALSE.

    +

    C++ allows a destructor to be called for classes that have no destructor and +for nonclass types. We refer to this kind of destructor call as a “vacuous +destructor” reference. A GID option is used to indicate whether a vacuous +destructor should be recognized and, if so, whether it must be a nonclass +destructor. Vacuous destructor references, which are only allowed in field +selection operations, differ from other generalized identifiers in several +important ways:

    +
      +
    • +
      the qualifier, if present, and the identifier that follows the tilde may be +a nonclass type.
      +
      +
    • +
    • +
      the nonclass type found may be a keyword that names a basic type (e.g., +int::~int).
      +
      +
    • +
    +

    When a vacuous destructor reference is coalesced, the parent.class_type +points to the type specified by the name after the ::~ because it must be +possible to record the type of the vacuous destructor reference for cases that +do not include a qualifier.

    +
    +
    +

    7.3.2. Coalesce-and-Look-Up Routines#

    +

    The coalesce-and-look-up routines are:

    +
      +
    • coalesce_and_lookup_qualified_name

    • +
    • coalesce_and_lookup_generalized_identifier

    • +
    +

    After is_generalized_identifier_start has determined that the current token +does in fact begin an identifier the coalesce-and-look-up routines are used to +do the appropriate kind of name lookup. The difference between the two +routines is that coalesce_and_lookup_qualified_name will only perform a +lookup of the final identifier of a qualified name while both qualified names +and names without qualifiers will be handled by +coalesce_and_lookup_generalized_identifier.

    +

    One of the arguments passed to these routines is an “identifier lookup mode”, +an enumeration that specifies the kind of lookup to be performed. The lookup +mode is translated into a set of “identifier lookup” (IDL) flags that are +passed to the symbol table lookup routines. An error is issued by +coalesce_and_lookup_qualified_name if the name lookup fails, except in +ilm_tentative_type mode. [6] In all other respects the various +identifier lookup modes are identical as far as the coalesce and lookup +routines are concerned. coalesce_and_lookup_generalized_identifier does +not issue an error if the lookup of an unqualified name fails.

    +
    +
    +

    7.3.3. Generalized Identifier Errors#

    +

    check_for_generalized_identifier_errors is called by the +coalesce-and-look-up routines and also by is_generalized_identifier_start +to ensure that the identifier that has been scanned meets the constraints +specified by the GID “allowed” flags. The error tests are done by comparing +the current GID options with the information in the locator. When one +generalized identifier routine calls another, it masks off the error flags so +that the errors are diagnosed only once by the highest-level routine.

    +

    check_for_template_declarator_errors is called by the coalesce-and-look-up +routines to verify that the declarator in a template declaration does actually +refer to a template entity that is permitted in a template declaration. These +checks are done to provide diagnostics that are more helpful than those that +would result if the identifier were simply returned to declarator.

    +
    +
    +

    7.3.4. Template References#

    +

    coalesce_template_id coalesces references to class and function templates. +The kind of reference to be coalesced is determined based on a symbol that is +provided. If the symbol refers to a function template or an overload set +containing one or more function templates, +coalesce_template_function_reference is called, otherwise +coalesce_template_class_reference is called to handle class template +references or to diagnose the improper use of a template argument list.

    +
    +

    7.3.4.1. Template Class References#

    +

    coalesce_template_class_reference coalesces template class references, such +as A<int, 1>, into identifiers for which the specific_symbol field of +the locator points to a specific instance of the template. A class template +name is usually, but not always, followed by a template argument list. The +argument list may be omitted in declarations of the class template,

    +
    template <class T> class A;
    +template <class T> class A { /* ... */ };
    +
    +
    +

    in which case the name refers to the class template (not to one of its +instances), and may also be omitted inside the definition of a class template +or in the definition of a member function or static data member of the class +template,

    +
    template <class T> class A {
    +  A*       a;    // Equivalent to A<T>*   a
    +  int A::* pma;  // Equivalent to A<T>::* pma
    +};
    +
    +
    +

    in which case the name refers to the current instance of the class template +(e.g., A<T>).

    +

    There are several contexts in which template class references must be +coalesced. Most calls of coalesce_template_class_reference are from +is_generalized_identifier_start and include a template argument list or are +part of a qualified name. coalesce_template_class_reference is also called +by coalesce_and_lookup_generalized_identifier, which scans simple class +template names such as A, and by scan_tag_name, which scans specific +definitions of a template classes such as class A<int> {}. Like the +generalized identifier routines, coalesce_template_class_reference accepts +a set of generalized identifier options as one of its arguments. The only +value actually used is GID_TEMPLATE_ARGS_OPTIONAL which specifies that the +template argument list may be omitted for a reference that is not within the +class template definition. As described above, the argument list may always be +omitted within the class template definition.

    +

    The template argument list, if present, is scanned by calling either +scan_template_argument_list or scan_unknown_template_arg_list:

    +
      +
    • +
      scan_unknown_template_arg_list is used when scanning the template +argument list associated with a “nonreal” template – a class template that +is a member of a proxy or nonreal class. A nonreal template is created in +contexts in which a member class template of a template parameter dependent +class is used. For example:
      +
      +
      template <class T> struct A {
      +  typename T::X<int> tx;
      +};
      +
      +
      +
      +
      In such cases, it is assumed that T::X is a template because there are +no cases in which a less than sign could immediately follow a type name, so +the “<” must indicate the beginning of a template argument list. When +scanning a nonreal template argument list there is no information available +about the number of template parameters, their types, etc. All of this +must be inferred by scanning the actual arguments. Consequently, no +attempt is made to determine whether the number of arguments, the types, +etc. are correct. The disambiguation routines are used to determine +whether a given argument is a type or nontype (see below for the use of +this function in scanning function template references.)
      +
      +
    • +
    • +
      scan_template_argument_list is used when scanning the template +arguments of “real” templates. Default values are provided for any omitted +arguments. If the type of a nontype parameter depends on another template +parameter, the type of the parameter is generated by rescanning a token +cache constructed when the template was defined. Similarly, if the type of +the default value, or the default value itself, involves a template +parameter, the default value is also generated by rescanning a token cache +constructed when the template was defined.
      +
      +
    • +
    +

    Both routines call scan_template_argument_constant_expression for nontype +arguments and type_name for type arguments. find_template_class is +called, once a complete template argument list has been created, to find the +type that corresponds to the particular set of arguments. If no such type +exists, find_template_class creates one. In either case the symbol +associated with the type is returned.

    +
    +
    +

    7.3.4.2. Function Template References#

    +

    coalesce_function_template_reference coalesces references to functions that +employ an explicit template argument list. Unlike class templates, function +templates may be overloaded; therefore an explicit template argument list does +not necessarily identify a specific template instance. The function type of +the instance is also needed to determine the actual instance that is being +referenced, but is not available when the template argument list is scanned, so +the argument list must be retained until some later point when the function +type is also available.

    +

    scan_unknown_template_arg_list is used to scan explicit template argument +lists because, in general, there is no template parameter list that can be used +to determine the kind of argument expected (type vs. nontype), or the type of +the argument (for nontype arguments). As with nonreal template argument lists, +the disambiguation routines are used to determine whether a given argument is a +type or nontype. type_name is used to scan arguments that are types. +scan_nontype_template_argument is used to scan nontype arguments. Function +template argument lists differ from those of class templates in that, for +function templates, the corresponding template parameter list is not available +when the template argument list is scanned. The presence of the template +parameter list for a class template makes it possible to convert nontype +arguments to the type of the corresponding template parameter (or to a special +nonreal type in the case of a nonreal argument list). For function templates, +such conversions cannot be done until the specific function template to be used +has been identified. Consequently, when a nontype argument is scanned it must +be retained in a form that permits the conversion to be done later. +scan_nontype_template_argument returns a pointer to an_arg_operand, a +data structure used by the expression scanning routines to represent an +expression. The constant_is_an_arg_operand field in the template argument +is set to indicate that the nontype argument is represented in this form.

    +
    +
    +

    7.3.4.3. Variable Template References#

    +

    coalesce_variable_template_reference coalesces references to variable +templates. scan_template_argument_list is used to scan the template +arguments. find_template_variable is used to produce a variable symbol for +the instantiation of the given variable template using the specified template +arguments.

    +
    +
    +
    +
    +

    7.4. Conversion of Literal Constants#

    +

    The source file literals.c contains the code to handle conversion of +literal constants to internal form. The external form is a string of +characters, a token, as accumulated by get_token and its subroutines; the +internal form is a structure of type a_constant, representing an integer, +fixed-point, float, character, or string constant.

    +

    conv_integer_literal converts decimal, octal, and hexadecimal integer +constants. Aside from computing the value of the constant, it also recognizes +the trailing L and U suffixes, and determines the type of the overall +constant (on the basis of its value and the suffixes). For pcc mode, the +rules for determining the type of a constant are modified slightly.

    +

    conv_fixed_point_literal converts fixed-point constants (an Embedded C +feature), calling fxp_string_to_fixed_point or +fxp_hex_string_to_fixed_point in fixed_pt.c to actually do the +conversion. It also recognizes the various suffixes (k, r, …), and +sets the type of the result accordingly.

    +

    conv_float_literal converts float constants, calling fp_string_to_float +or fp_hex_string_to_float_point in float_pt.c to actually do the +conversion. It also recognizes the L and F suffixes, and sets the type +of the result accordingly.

    +

    conv_char_literal converts character constants to an integer value. It +uses conv_single_char to fetch and convert each character. If there is +more than one character, they are assembled into one integer (with ordering +controlled by TARG_CHAR_CONSTANT_FIRST_CHAR_MOST_SIGNIFICANT).

    +

    conv_string_literal converts string literals. It receives a count of +effective characters in the string from its caller (as computed by +accum_quoted_string), so it can dynamically allocate the space for the +string before scanning it. It also uses conv_single_char to convert each +character of the string.

    +

    conv_single_char converts one character to an integer value. This includes +simple characters, escapes like \n, and octal and hexadecimal escapes. At +the moment, this routine assumes that the host and target character sets are +the same.

    +

    concat_string_literals concatenates several string literals (in constant +form in a token cache) into one string. This is used for the concatenation of +adjacent string literals.

    +
    +
    +

    7.5. Preprocessing Directives#

    +

    The source file preproc.c contains the code to handle preprocessing +directives (except for #define, which is handled in macro.c). +Associated declarations are in preproc.h.

    +

    The routine cpp_driver is the top-level routine when the front end is being +run as a C preprocessor, typically to produce a preprocessed output file. It +calls get_token repeatedly until end of source, with +do_preprocessing_only set to TRUE to indicate that preprocessing only – +and not compilation – is being done.

    +

    Normally, when preprocessing output is required, generate_pp_output is TRUE +as well. But cpp_driver is also called when preprocessing is being done to +generate a list of #include files or a list of makefile dependencies. +In those cases, generate_pp_output is FALSE, and either +list_included_files or list_makefile_dependencies is TRUE.

    +

    pp_directive is called (by get_token) when a # is encountered at +the beginning of a source line. It sets in_preprocessing_directive, +fetches the directive identifier and identifies it by calling +identify_dir_keyword (which uses a simple linear search), calls the +appropriate routine to process the directive (which may call +ignore_harmless_trailing_comment to ignore extra text at the end of the +directive), calls end_of_directive_processing (to check for any extra text +that is not harmless), and then resets in_preprocessing_directive. If a +syntax error is detected in a directive, some_error_in_curr_directive is +set; this suppresses the check for extra text at the end of the directive.

    +

    When the text of a preprocessing directive is not to be written to the +preprocessing output, do_not_put_curr_line_in_pp_output is set – initially +in pp_directive and on each subsequent line, because of multi-line +comments, in read_logical_source_line; the flag is checked by the output +routine, gen_pp_output_for_curr_line. In the rare case that the text of a +preprocessing directive should be passed to output (because some C compiler +should see the directive to handle it), pass_pp_directive_to_output is set +to TRUE while the directive is scanned.

    +

    Each preprocessing directive has an associated processing routine (for example, +proc_if handles the #if directive).

    +

    proc_pragma processes the #pragma directive. This is an area that +would be configured for specific versions. Unrecognized pragmas must be +ignored (no error should be generated). When preprocessing only, #pragma +directives are passed to output (see pass_directive_to_output).

    +

    proc_ident processes the #ident directive, although the “processing” it +does is to ignore it. When preprocessing only, #ident directives are +passed to output (see pass_directive_to_output).

    +

    proc_error passes the rest of the directive to an error reporting routine, +as a catastrophic error, which terminates the compilation.

    +

    proc_line scans a line number, treating it as a digit-sequence rather than +an integer constant; optionally, it also scans a file name, calling +copy_header_name to extract the file name from the header name token. It +puts this information into the input stack and calls routines in il.c to +remember the proper correspondence between source sequence numbers and file +name/line number pairs.

    +

    proc_include scans the file name (as a header name in one of two forms) and +then calls push_input_stack to request reading from that include file. It +calls copy_header_name to extract the file name from the header name token.

    +

    proc_undef scans an identifier, looks it up, and removes any macro +definition under that name. It will not remove predefined macros. (A +predefined macro has a source position with a sequence number of zero, and a +column number of SP_COL_PREDEFINED_MACRO.)

    +

    #if and related directives depend on the pp_if_stack, which is a stack +of entries describing active #if constructs. The current depth of the +stack is indicated by pp_if_stack_depth. Each #if that has not yet +been closed by a corresponding #endif appears on the stack. The stack +entry indicates whether or not the #else for the #if has already +appeared, and has the source position of the #if for use as the error +position if the corresponding #endif never appears. In ANSI C or C++ mode, +each #if is required to be ended in the file in which it was begun: to +implement this, the variable base_pp_if_stack_depth contains the value of +pp_if_stack_depth as of the beginning of the current source file. The part +of the stack between base_pp_if_stack_depth and pp_if_stack_depth is +considered the only active part of the stack at any given moment. #endifs encountered must be associated with #ifs in the active part of the +stack, and all of the #ifs in the active part of the stack must be closed +by the end of the source file (this is checked by +verify_that_all_pp_ifs_were_closed, which is called from +pop_input_stack). In pcc mode, the #ifs do not have to match up +within each file; they only have to come out right at the end of the +compilation.

    +

    The various if-directives are handled by proc_if, proc_ifdef (which +also handles #ifndef), proc_else, proc_elif, and proc_endif. +proc_if and proc_elif call scan_if_expr, which calls +scan_pp_expression (in expr.c) to scan the if-expression (there are +restrictions on what can appear in such an expression). All of the +if-processors call perform_if once they know whether or not the #if +should be executed; perform_if returns if the condition is TRUE, and calls +skip_to_endif if the condition is FALSE. The latter reads lines looking +for preprocessing directives, counts nesting of #ifs, and looks for an +#else or #endif that matches the current if.

    +

    A new preprocessing directive can be added by:

    +
      +
    • +
      Adding an enumeration constant to a_pp_directive_kind;
      +
      +
    • +
    • +
      adding a test for the directive keyword in identify_dir_keyword;
      +
      +
    • +
    • +
      adding a switch clause for the directive in pp_directive; and
      +
      +
    • +
    • +
      adding a routine proc_directive to process the directive. Note +that the routine must take all the tokens in the directive (up to the +tok_newline) before returning.
      +
      +
    • +
    +
    +

    7.5.1. AT&T Preprocessing Extensions#

    +

    When ATT_PREPROCESSING_EXTENSIONS_ALLOWED is defined some of the AT&T +System V release 4 extensions to the preprocessor are supported. In that case, +the #assert and #unassert directives are handled by proc_assert and +proc_unassert. The data structure built for assert predicates is a simple +one: assert_predicates points to a list of an_assert_predicate entries, +each of which gives a predicate name and a list of an_assert_value entries +giving the value or values for the predicate. Entry and lookup are done with a +simple linear search. The token sequences involved are processed into +character strings (containing the token characters with a blank after each +token, and ended with a null character). Such character strings then represent +the token sequences, and can be saved and compared. +scan_assert_predicate_reference is called from get_token on detection +of a # inside of an #if expression; it scans the reference and returns +1 or 0 depending on whether or not the predicate is defined with the indicated +token sequence. enter_assert_predicate can be called from fe_init.c to +enter predefined predicate names.

    +
    +
    +

    7.5.2. C++/CLI Assembly Import#

    +

    The front supports the C++/CLI #using directive to import the metadata of +an assembly. This is done in function proc_using. In C++/CLI mode, a +“core library assembly” (usually, mscorlib.dll) is imported before input +source is processed, as well as any assemblies specified with the +--preusing command-line option: Function process_preusings handles that +part (see also Declarations from C++/CLI Assembly Metadata and C++/CLI Initialization).

    +
    +
    +
    +

    7.6. Macro Processing#

    +

    macro.c contains the code to handle the #define preprocessing directive +and invocations of macros. macro.h contains associated declarations.

    +
    +

    7.6.1. Macro Definition Data Structure#

    +

    When a macro is defined, the symbol created for it points to an entry of type +a_macro_def (defined in symbol_tbl.h). The macro’s parameter list is +represented by a linked list of entries of type a_macro_param; these give +the names of the parameters (needed only to verify that, on a benign +redefinition of the macro, the parameter names are the same). The replacement +text of the macro is a sequence of sections, each of which indicates text that +should be placed in the macro expansion at that point. Each section begins +with a byte that identifies the kind of section, as follows:

    +
    + + + + + + + + + + + + + + + + + + +
    +
    rt_null (0)
    +
    +
    +
    marks the end of the replacement text.
    +
    +
    +
    rt_text
    +
    +
    +
    indicates raw text that is part of the macro replacement text. The +next three bytes contain the count of characters following.
    +
    +
    +
    rt_raw_argument
    +
    rt_right_raw_argument
    +
    +
    +
    indicate that the raw (non-macro-expanded) text of an argument is to +be inserted at this point. This results from use of the ## +operator, or from parameters scanned in pcc mode. The next three +bytes contain a number indicating the argument to be used (1 is the +first argument, 2 the second, etc.). rt_raw_argument is used for +a parameter to the left of ## and for all parameters in pcc mode, +and rt_right_raw_argument is used for a parameter to the right of +##.
    +
    +
    +
    rt_stringized_raw_argument
    +

    +
    +
    +
    indicates that the “stringized” text of an argument is to be inserted +at this point (this results from use of the # operator). The next +three bytes contain a number indicating the argument to be used.
    +
    +
    +
    rt_argument
    +
    +
    +
    indicates that the macro-expanded text of an argument is to be +inserted at this point. The next three bytes contain a number +indicating the argument to be used.
    +
    +
    +
    +

    The ## (paste) operator has no direct representation in the replacement +text; it just results in the two entities being placed next to each other. For +example,

    +
    #define x(a,b) a ## b
    +
    +
    +

    results in rt_raw_argument(1) followed by rt_right_raw_argument(2).

    +

    White space in the replacement text is standardized. Any white space preceding +or following the replacement text is removed, as is any white space preceding +or following a ##, and any white space following a #. All other white +space is replaced by a single space.

    +

    Each token in the raw text (except the last, and any token preceding a ##) +is followed by an LE_END_OF_TOKEN lexical escape sequence. The raw text +immediately following insertions of arguments (except immediately following a +##) also starts with an end-of-token marker, to terminate the last token of +the inserted argument text. The end-of-token markers ensure that the tokens +will be tokenized the same way each time. For example, one problem comes up in

    +
    #define z(a) ..##a
    +
    +
    +

    The value of z(.) should be three “.” tokens, not the one token +“...”. End-of-token markers are not used when in pcc mode, since cpp +does not operate on a token level.

    +

    Similar standardization of white space and insertion of end-of-token markers is +done when the raw form of macro arguments is accumulated. This standardization +(of replacement text and macro argument text) makes it easier to check for +benign redefinitions and to generate the stringized form of arguments.

    +
    +
    +

    7.6.2. The Macro Buffer#

    +

    The global variable macro_buffer points to a large character array used as +a work area during macro processing. During macro definition, it holds the +replacement text. During macro invocation, it holds the expansions of all +macro invocations in the current line. It is dynamically allocated, and can be +expanded as necessary by calling expand_macro_buffer. +expand_macro_buffer will, in turn, call +adjust_curr_source_line_structure_after_realloc to walk through the data +structure associated with curr_source_line and change pointers to +macro_buffer to reference addresses within the new allocation for +macro_buffer. adjust_curr_source_line_structure_after_realloc +automatically finds such pointers in global variables and the public data +structure, but it has no way of knowing about local pointer variables. +Therefore, routines that have such variables register them by calling +register_pointer_variable, so that they will be found and adjusted if +reallocation is done.

    +

    In order to reduce memory consumption when processing very complex and lengthy +macro expansions, the reallocation process for macro_buffer differs from +that of the other extensible buffers. While the other buffers are simply +reallocated, relying on the C runtime to copy the complete old contents to the +new allocation, expand_macro_buffer compacts the contents of +macro_buffer by explicitly allocating a new buffer, copying data to the new +allocation only if it might still be in use, and then freeing the old buffer. +First, each existing source line modification (see +Modifications to the Current Source Line) is processed to copy its inserted text. +Within that text, only the ATTENTION_MARKER is copied from each portion +that is marked for deletion by another source line modification. (The +ATTENTION_MARKERs must be copied in order to allow scanning for inert +macro names, as described in Macro Invocations.) As a result, the +original text of already-expanded macro invocations and the expanded text of +macro arguments will not occupy space in the new macro_buffer allocation.

    +

    Second, text that is in the process of being constructed at the end of the +macro_buffer is copied to the end of the data in the new allocation. Any +routines that build data structures incrementally, so that reallocation can +occur before the structure is complete (e.g., macro replacement text in +proc_define), must identify the beginning of such data using +begin_macro_buffer_region and its completion with +release_macro_buffer_region.

    +
    +
    +

    7.6.3. Macro Definitions#

    +

    Macro definitions (#define directive) are handled by proc_define. It +scans the macro identifier, and looks it up in the symbol table (predefined +macros may not be redefined, and normal macros may be redefined only if the new +parameters and text match the existing parameters and text – a “benign” +redefinition). If a “(” follows immediately (with no intervening white +space), the macro is function-like; its parameter names are accumulated as a +list. Otherwise, the macro is object-like. proc_define then scans the +replacement text and builds the replacement text string in macro_buffer. +It calls mdefn_get_token to fetch tokens of the body and remember whether +or not any white space preceded each. White space is standardized, +end-of-token markers are inserted (if in ANSI C or C++ mode), parameter names +are recognized, and # and ## are handled as described above.

    +

    If in pcc mode, the opening and closing quoting characters of character +constants and string literals are scanned as single-character tokens, and the +insides of the quoted strings are tokenized. This results in recognition (and +later replacement) of parameter names within strings, as cpp does it. +Invalid tokens are passed textually to the replacement text (this is necessary +always, not just for this case), and skipped white space is kept in its +original form, so the contents of the string will be accurately rendered in the +final expansion of the macro.

    +

    After the replacement text is accumulated, it is copied to +dynamically-allocated storage, and the macro definition is completed and +attached to the symbol. For a redefinition, the new parameter list and +replacement text are first compared textually against the old. If they match, +the new definition is thrown away.

    +
    +
    +

    7.6.4. Macro Invocations#

    +

    macro_invocation handles the scanning and replacement of macro invocations. +It is called by get_token when an identifier that is a macro name is +scanned.

    +

    The first thing that macro_invocation checks is whether or not the macro +name is “inert”. The standard says that when a macro’s name is generated in +its own expansion (directly or indirectly), it is forever after protected +against further expansion (it is inert). This is implemented by the +assoc_macro field in the a_source_line_modif entry. A macro invocation +is replaced by the macro’s expansion by creating a modification entry that +indicates the textual changes to be made to the source line or to a previous +modification. The assoc_macro field records the origin of any given +change, by pointing to the definition of the macro that generated the change. +Given a pointer to the name of a macro at the beginning of a possible macro +invocation, one can therefore determine whether it is in the main source line +or in a modification (or nested in several), and from that one can see whether +the macro name appears as part of its own expansion. If so, the macro name is +inert, and is left as an identifier. (Actually, it is replaced by an +LE_INERT_MACRO lexical escape followed by the macro name. Once a macro +name is preceded by an inert-macro escape, it is considered inert every time it +is scanned, regardless of the context.) In pcc mode, macros are not considered +to be inert, and recursion is checked for by counting the number of nested +invocations of a given macro.

    +

    If the macro name is not inert, processing for expansion continues. +delete_source_from_loc is set to point to the beginning of the macro +identifier. This begins a “hanging delete” which will be closed when the end +of the macro invocation is found. At that point, the text of the hanging +delete will be replaced by the macro expansion, this replacement being +indicated by a source line modification entry.

    +

    If the macro is object-like, no parameters need be scanned. However, there are +several special cases in object-like macros: For __FILE__ and __LINE__, +the proper expansion string is developed from the current position information +in the input stack; for defined, which is an operator allowed in #if +expressions but handled as a pseudo-macro, the routine +scan_defined_operator is called. It scans both forms of the defined +operator, and returns 0 or 1. Alternatively, if the identifier +defined is not followed by appropriate tokens, it is left as an identifier +(see the discussion of check_for_following_parenthesis below).

    +

    If the macro is function-like, check_for_following_parenthesis is called to +scan forward looking for a parenthesis that begins the argument list. If the +next token is not a parenthesis, then the macro name is left as an identifier. +However, this is complicated, because in skipping white space while looking for +a left parenthesis, we may have gone onto a new source line. We have to delete +the identifier before leaving the old source line, on the assumption that we +are scanning a macro invocation. If it turns out that the identifier is not +the start of a macro invocation, the identifier must be reinserted into the new +source line.

    +

    Note the field sequence_id in a_source_line_modif; it is an integer +sequence number indicating the sequence in which source line modifications were +added. This is useful in cases where modifications must be undone (as in +identifier un-deletion when a macro identifier is followed by something other +than a left parenthesis on the same line); one can find all entries with +sequence numbers greater than a certain number, and remove them.

    +

    If a left parenthesis is found, the argument list is scanned, and this +requires a new data structure. An entry of type a_macro_arg contains +the text of a single argument value. That text exists in two forms – as +“raw” text (not macro-expanded), and as “expanded” text. The +a_macro_arg entries are dynamically allocated, and freed when no longer +needed (see alloc_macro_arg, free_macro_arg, and the variable +avail_macro_args). The text of macro arguments is not kept in +macro_buffer.

    +

    Each macro argument is initially scanned in raw form. arg_get_token is +called, with macro expansion turned off, and the characters of each token, with +standardized white space and end-of-token markers, are placed in the array +pointed to by raw_text in the a_macro_arg entry (a +dynamically-allocated array, which can be reallocated as needed to expand it). +The scan stops when a comma or right parenthesis is found. A variable is used +to count the nesting of parentheses, so that non-zero-level commas and right +parentheses will not stop the scan.

    +

    After the raw form of the argument has been accumulated, the raw text is +temporarily re-inserted in the source line and is re-scanned with macro +expansion on. The standard says that this must be done as if this text forms +the rest of the source file (i.e., the macro expansion is done in isolation +from the text following the raw argument value). This is implemented by having +the source modification entry that re-inserts the raw text have the field +is_isolated_text TRUE. This will cause get_token and +skip_white_space, upon reaching the LE_END_OF_INSERTION lexical escape +sequence at the end of the raw text, to return tok_end_of_source instead of +continuing into the surrounding text. macro_invocation scans the entire +raw argument again, saving the text of the tokens scanned in the +expanded_text array in the macro argument entry, and stopping when it gets +tok_end_of_source. If any modifications of the raw text were done because +of macro expansions (this can be determined by sequence id), they are removed. +This restores the raw text to its original state. In pcc mode, and when the +definition of the macro does not use the parameter in a context that requires +expansion,only the raw form of each argument is needed, so the rescan is not +done.

    +

    In cases where the macro argument is the result of a previous macro expansion, +the rescan begins in the text inserted by the macro expansion modifications +rather than in the raw_text buffer. That ensures that the inertness test +can be done properly on macro names encountered in the rescanned source. Once +the rescan reaches the end of the insertions and would continue into the +primary source line, the input stream is switched to the tail of the +raw_text buffer. (raw_text is used instead of the primary source line +because macro arguments can be continued to subsequent source lines, and once +the next line is read the only copy of the raw argument text is in the +raw_text array; the previous source line is gone.)

    +

    This process is repeated for each argument. After all arguments are scanned +(or immediately for object-like macros), expansion is done. The length of the +expansion is first determined, and then the textual change is made, by building +up text in macro_buffer and placing a source line modification to delete +the characters of the macro invocation and insert the characters of the +expansion.

    +

    For the special cases of predefined macros, the replacement text is already +available as a simple null-terminated string. For these cases, determining the +length and building the replacement string are easily done.

    +

    For the other, more normal, cases, the length is determined and the expansion +string is built up by interpreting the sections of the replacement text in +order. For unexpanded uses of parameters, the raw_text is copied. For +macro-expanded uses of parameters, the expanded_text is copied. For +stringized parameters, stringized_arg is called; it copies the +raw_text, inserting the surrounding quotes and the additional backslashes +to protect quotes and backslashes in the string.

    +

    The source line modification is then inserted to perform the macro expansion.

    +

    When, in pcc mode, the expansion is for a top-level macro, +expand_top_level_pcc_macro is called to expand any macro calls within the +body of the macro. A complete string for the expanded version is constructed +in an auxiliary buffer (aux_buffer_for_pcc_macros) and then copied back +into macro_buffer, replacing the original expansion and any source line +modifications associated with it. Getting a fully-expanded string is necessary +to get pcc-like token pasting behavior across internal macro expansion +boundaries. A variant of this processing is also done in Microsoft mode.

    +

    macro_invocation then returns. It indicates to get_token whether or +not the inserted text should be rescanned. If macro_invocation already +knows what the next token should be, it returns it directly (*rescan = +FALSE), thus saving get_token the time and trouble of scanning the token +text again.

    +

    A utility debug routine print_markered_text is available for use in +printing out text strings that contain end-of-token markers and/or transitions +into or out of source modifications.

    +
    +
    +

    7.6.5. Macro Position Tracking#

    +

    When FULLY_RESOLVED_MACRO_POSITIONS is TRUE, the front end keeps track of +the original location of text that is copied into macro expansions – i.e., +either in a #define line or in an argument to a top-level macro invocation. +This “original position” information is reflected in the orig_seq and +orig_column fields of a_source_position.

    +

    The principal data structure used in tracking original position information +through the various manipulations performed during macro definition and +invocation is a_macro_text_map, which defines an extensible array of +a_macro_text_map_entry elements (both defined in lexical.h). Each of +the repositories of text associated with macro definition and invocation – +macro definitions, the raw and expanded forms of macro arguments, and source +line modifications – has an associated macro text map.

    +

    A macro text map provides an ordered sequence of correspondences between +offsets in the associated text buffer and the original source locations from +which that text was copied. Each map entry defines a region of the associated +text buffer, beginning at offset start_of_region and extending up to but +not including the start_of_region of the next entry. The text at offset +start_of_region originally came from the location given by +corresponding_source_pos, with a one-to-one correspondence of increasing +offsets and source column positions throughout the entry’s buffer region. +Because the entries are ordered by buffer offset, the original source position +for a given offset can be efficiently found using a binary search (the +requisite bsearch predicate is +compare_macro_text_map_entry_with_offset, defined in lexical.c).

    +

    It will be helpful to trace the overall flow of information through the +definition and invocation of a macro before covering the details of how it is +accomplished. When a #define is processed, proc_define builds a text +map by incrementally recording the source position and offset in the +replacement text for each token of the definition that will be copied to the +macro expansion. A similar process occurs as each macro argument is copied to +the corresponding raw and expanded text buffers. During the interpretation of +the replacement text by macro_invocation, as each section of text is copied +from the replacement text or macro argument, the corresponding entries from the +associated macro text map are copied, adjusting the offsets to reflect the +location of the text in the macro expansion (but leaving the original source +positions). Finally, when conv_line_loc_to_source_pos is called to compute +a source position for a given character location in the expanded text, the +macro text map in the source line modification is used to determine the +corresponding original source position.

    +

    There are two principal patterns for adding entries to a text map. The simpler +pattern is when a sequence of map entries is copied from one map to another, +adjusting the offsets from being relative to the start of the source buffer to +being relative to the start of the target buffer. This technique is used to +create the text map for the source line modification containing the macro +expansion by copying portions of the text maps for the macro definition +replacement text and macro arguments. The function that performs this +operation is clone_macro_text_map_entries, defined in macro.c.

    +

    The other pattern occurs when a text buffer is built incrementally by fetching +one token at a time and adding its text to a buffer. In this case, the map +entries are built to reflect either the source position of the token, if the +token is in source text, or a copy of the corresponding text map entry, if the +token comes from a source line modification (e.g., a macro argument in a macro +invocation appearing in the expansion of another macro invocation). This +technique is used to create the replacement text in a macro definition and for +both the raw and expanded text of macro arguments. It is also used when +processing a top-level macro invocation in pcc and Microsoft modes.

    +

    Facilitating this process are the struct a_text_map_position_tracker and +the functions init_text_map_position_tracker, +add_token_to_macro_text_map, and terminate_macro_text_map (all defined +in macro.c). As each token is added to the text buffer, +add_token_to_macro_text_map is called to determine whether a new entry is +required in the map for the new token: if the token is from the same source +line or source line modification as the preceding token and its offset within +the current buffer region is the same as the column offset from the region’s +corresponding source position, then no new map entry is needed. If a new map +entry is required, either the appropriate map entries from the previous token’s +source line modification are copied, using clone_macro_text_map_entries, or +(for tokens from the current source line) a new entry is added covering the +appropriate region of the current source line for the preceding token(s).

    +

    One complication in this processing occurs when macro_buffer is +reallocated, as described earlier. Because a_text_map_position_tracker +objects in use at the time macro_buffer is reallocated might contain the +offset of text in a source line modification’s inserted text that occurs after +a portion of deleted text, and because that deleted text might be compacted as +part of the reallocation process, it is necessary to keep track of all active +position tracker objects so their current offset values can be adjusted if +necessary.

    +

    This is done using the variable active_text_map_position_trackers (in +macro.c), which is the top of a stack of all trackers currently in use, and +the field num_active_position_trackers in a_source_line_modif. +Whenever a token scan under control of a text map position tracker enters the +inserted text of a source line modification, its +num_active_position_trackers is incremented, and it is decremented when the +scan leaves that source line modification.

    +

    Whenever macro_buffer is reallocated, all the entries in each source line +modification’s text map are examined and each offset adjusted, if necessary, to +compensate for the removal of deleted text. Furthermore, if the modification’s +num_active_position_trackers field is greater than zero, all the trackers +in the active_text_map_position_trackers stack are checked for references +to that source line modification and their offsets adjusted as needed.

    +

    The text maps for macro definitions and the raw and expanded text of macro +arguments are completely self-contained: each has its own array of text map +entries and is associated with the containing data structure for the duration +of the compilation. (The array of entries for a macro definition is of fixed +size and is allocated in front-end memory, so that it will be stored in a +precompiled header, while the arrays for macro arguments are extensible.) A +different scheme is used for the text maps in source line modifications, +however. The reason for this decision is that the text map for a source line +modification may well be very large, with thousands or tens of thousands of +entries, while source line modifications themselves are ephemeral, generally no +longer needed once processing of the current logical source line has been +completed. The same reasoning led to the use of macro_buffer for the +inserted text of source line modification, so the memory management for source +line modification text maps is patterned after that of macro_buffer. Just +as each modification’s inserted text is simply a subrange of the text in +macro_buffer, the entries created during macro expansion are built in a +single map, called macro_text_map and defined in macro.c, and each +modification’s text map simply refers to a subrange of them. Initialization +and truncation of macro_text_map is done in parallel with the corresponding +operations on macro_buffer.

    +
    +
    +

    7.6.6. Macro Invocation Tree#

    +

    Maintaining the macro invocation tree is selected by setting +MACRO_INVOCATION_TREE_IN_IL to TRUE. Each macro invocation is recorded in +an object of type a_macro_invocation_record (defined in il_def.h), +giving the parent invocation, if any; the macro invoked; and its starting +position (as well as its ending position, if EXTRA_SOURCE_POSITIONS_IN_IL +is set to TRUE). (The “parent invocation” refers to the macro invocation in +whose argument list or expansion this macro invocation occurred. For macro +invocations occurring in program text and not in a macro argument list, +parent_macro_index will have the value NO_PARENT_MACRO_INVOCATION.)

    +

    Each time macro_invocation is called to expand a macro, it calls +register_macro_invocation to add an entry to the list and obtain the index +of the newly-added entry. This index and the macro invocation stack depth at +that point are stored into the source line modification created to hold the +macro’s expanded text. These values are used by recursive calls of +macro_invocation (to expand macro arguments) and by calls resulting from +rescanning expanded text to maintain the chain of parent invocations when the +macro name comes from a source line modification rather than directly from +source text.

    +

    Because variable-length data is awkward to represent in the IL (and extensible +arrays are not possible in memory regions), the macro invocation records are +grouped into fixed-size blocks (a_macro_invocation_record_block, defined in +il_def.h). In the IL, these blocks are organized into a binary tree to +facilitate relatively-efficient random access by index. During front-end +processing, however, they are kept in a doubly-linked list: apart from +diagnostic output, which need not be terribly efficient, there is no need for +random access to the invocation records (and even diagnostic output will most +often refer to records near the end of the list, so long linear searches are +uncommon). It is more efficient to create the binary tree form once, after the +total number of records is known, than to balance the tree repeatedly while it +is being created.

    +

    The macro_invocation_record_blocks are reorganized into a binary tree and +the relevant fields of il_header are set at the end of the translation unit +by a call to copy_macro_invocation_tree_to_il (defined in macro.c).

    +

    An additional effect of setting MACRO_INVOCATION_TREE_IN_IL is that +a_source_position is extended to include the macro_context field. This +field reflects the macro invocation in whose expansion the source position +resides, i.e., it is logically simply a copy of the invocation_record field +of the containing source line modification. However, the special treatment +given to top-level macros in pcc and Microsoft mode, in which the expansion of +the macro is rescanned for expansion and the result is copied back into the +source line modification corresponding to the top-level macro invocation, means +that the subsidiary source line modifications are no longer available at the +time source positions are being computed.

    +

    To avoid this problem, the macro invocation index that will be stored by +macro_invocation into source line modifications is also kept in the +macro_context field of each text map entry created for that invocation. +This information is preserved when the text maps for the subsidiary source line +modifications are cloned into the top-level modification by +expand_top_level_pcc_macro. This additional information allows the +macro_context field in source positions to be set in the same way as the +original position information, by looking up the offset in the text map of the +top-level modification. (This is the reason that it is not permitted to set +MACRO_INVOCATION_TREE_IN_IL to TRUE without also setting +FULLY_RESOLVED_MACRO_POSITIONS to TRUE.)

    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/lower_il/index.html b/doc/lower_il/index.html new file mode 100644 index 0000000..8c4d7cf --- /dev/null +++ b/doc/lower_il/index.html @@ -0,0 +1,4530 @@ + + + + + 5. IL Lowering - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    5. IL Lowering#

    +

    When we started developing the C++ front end, one of the first design decisions +we had to make was what intermediate language it would generate.

    +

    We already had a C front end (supporting the C89 version of the language) and a +Fortran front end. The C front end generated an intermediate language that +looked a lot like C, and the Fortran front end generated an intermediate +language that looked a lot like Fortran. The two intermediate languages were +compatible in the sense that they had the same structure and could be combined +into an intermediate language that is the union of the two.

    +

    It seemed clear that the C++ intermediate language ought to be compatible with +the other two languages in that same sense, and that in fact it should be a +superset of the C intermediate language, since C++ is (almost) a superset of +C89. (When we talk about the C intermediate language or “C IL”, we generally +refer to the IL to represent C89 constructs, not to the extensions supporting +the current C99 standard and other dialects like GNU C.)

    +

    But how much of a superset? Since our IL philosophy for Fortran and C had been +to make “high-level” ILs that were very close to the source language, our +initial inclination was to make an intermediate language with lots of new C++ +features that would be the same sort of thing for C++. It seemed like the +obvious approach. When we analyzed that idea, and discussed it with customers, +however, we realized a few things:

    +
      +
    • +
      There’s a big semantic jump from C to C++. Some of the C++ features are +much more complicated than C or Fortran features. Implementing them in a +back end would add a lot of work, and requires a lot of knowledge of the +C++ language.
      +
      Since our corporate mission is to deliver front ends that take care of +all of the language issues and the attendant grief so that back ends +can just worry about code generation (and its attendant grief), it +didn’t seem that we would be doing our full job by generating the +high-level C++ IL.
      +
      +
    • +
    • +
      We had customers that had existing C back ends and were interested in +adding C++ with minimum development cost.
      +
      +
    • +
    +

    Okay then, what about generating an IL that’s very close to the C IL? After +all, because of USL’s cfront, people view C++ as a language that can be +translated into C, maybe even as a macro language on top of C. Well, there are +problems with that, too:

    +
      +
    • +
      It hides information that is useful in generating symbolic debugging +information. (This has historically been a weakness of cfront-based +compilers, forcing programmers to debug using the generated C code.)
      +
      +
    • +
    • +
      It makes it harder for a back end to use unconventional or aggressive code +generation techniques for C++ constructs.
      +
      +
    • +
    • +
      It makes the front end less suitable for use in source-analysis tools (they +want to analyze the C++ source, not some version of it translated into C).
      +
      +
    • +
    +

    We considered various levels of intermediate language between the full C++ and +full C extremes, and all were unsatisfactory in some way. Then David Callahan +of Tera Computer suggested that we do it both ways, that we generate a full C++ +IL and also supply a piece of software that translates that IL into the +existing C IL.

    +

    Thus was born IL lowering. The front end proper generates a true C++ IL, and +IL lowering translates that IL into C IL, which can then be fed into a C back +end or the C-generating back end we use for testing. It should be noted that +although “lowering” is what’s done, the output is still “high-level” – it’s +not as high-level as it was, but it’s still at the level of the intermediate +language for C89.

    +

    The IL lowering pass is optional. It need not be used if it’s not wanted. The +IL utilities work with both versions of the IL.

    +

    Since many C++ features go into IL lowering as abstractions and come out as C +code, IL lowering is actually choosing implementations of those features. The +implementations are at the same level as those in cfront. That is, they are +relatively “standard” implementations. As one would expect, the generated C +has some of the same complex unreadable quality that cfront output has, and the +same ridiculously complex expressions. The front end can even be configured to +produce constructs that are object-code compatible with cfront’s. +Alternatively, the front end can generate code compatible with the IA-64 +(Itanium) ABI.

    +

    IL lowering can also do inlining, though we firmly believe that that is +something that only a back end can really do properly. [1]

    +

    The IL lowering pass seems to solve the problems raised:

    +
      +
    • +
      Both the C++ and C forms are available for those who prefer one form or the +other. In fact, one can use both forms, e.g., one could generate symbolic +debugging information from the C++ form and object code from the C form.
      +
      +
    • +
    • +
      It allows customers to get a C++ compiler going in minimal time.
      +
      +
    • +
    • +
      If the features implemented by IL lowering require some minor changes, the +changes can be made in IL lowering, which is relatively small, rather than +in the front end as a whole, which is quite large.
      +
      +
    • +
    • +
      If a customer wants to attach a back end to the unlowered IL (either +initially or for an improved release of a compiler), the IL lowering code +serves as a guide to the tasks that must be done.
      +
      +
    • +
    +

    Even though IL lowering will rewrite uses of non-C89 features, the C++-specific +fields of the IL are still present in the IL entries. Back ends should not +count on those fields being cleared; rather, they should ignore them and +consider only the fields that C uses. Viewed that way, the lowered IL should +contain nothing that would not show up in a C intermediate language tree.

    +

    One catch: Dynamic initialization of entities in the middle of blocks is left +in its original form. This is not “incorrect” C IL, but is something that does +not come up in C89 programs. It was judged that back ends would be capable of +dealing with the stmk_init statements even if they appear after other +executable statements in a block, and the alternative was to make lowering of +initialization of aggregates to constants quite messy.

    +

    The code for IL lowering is in lower_il.c, and the associated declarations +are in lower_il.h. Name mangling code is in lower_name.c and +lower_name.h. Code for lowering initializations, new/delete, and +constructors/destructors is in lower_init.c and lower_init.h. Code for +lowering exception handling features is in lower_eh.c and lower_eh.h.

    +

    Certain higher-level constructs – like variable-length arrays and complex +floating-point types – from more recent C dialects (primarily C99, but also +GNU C) can also be lowered to C89-level IL. The code for this is done +primarily in lower_c99.c. See Lowering C Dialects for an overview +of the constructs in this category that can be lowered.

    +

    Finally, IL lowering can also ensure that boolean controlling expressions +(e.g., the expression controlling which way an if-statement goes) always +produce an integer value 0 or 1 (as opposed to “zero or nonzero” or “null or +nonnull”). This normalization – enabled by setting +LOWERING_NORMALIZES_BOOLEAN_CONTROLLING_EXPRESSIONS to TRUE – can occur in +all modes (C++, C89, etc.) and usually involves adding a “!= 0” comparison +to the controlling expression.

    +
    +

    5.1. ABI support#

    +

    The front end and IL lowering support two ABIs (Application Binary Interfaces). +An ABI is a set of conventions for the runtime environment, which prescribes +class layout, access to virtual functions, name mangling, etc. Code generated +by two compilers that are compatible with a given ABI should, in theory, be +able to interact properly, and with libraries that are compatible with that +ABI.

    +

    Up through version 3.0, the front end supported a single ABI and some minor +variants thereof. This ABI, referred to as the “cfront-like ABI,” is an +extended version of the original ABI used by cfront. The extensions were +invented by EDG, and therefore the ABI does not conform to any industry +standard, other than in its general compatibility with what was once a de +facto standard. The variants of the cfront-like ABI are:

    +
      +
    • +
      cfront 3.0.1 compatibility, selected by setting +CFRONT_3_0_OBJECT_CODE_COMPATIBILITY to TRUE.
      +
      +
    • +
    • +
      cfront 2.1 compatibility, selected by setting +CFRONT_2_1_OBJECT_CODE_COMPATIBILITY to TRUE.
      +
      +
    • +
    • +
      If neither of those variants is selected, the default ABI is cfront-like +with some minor quirks eliminated, principally with respect to allocation +of space for virtual base classes. This variant was originally intended as +the default and best ABI, but in practice it hasn’t been used very much, +and the IA-64 ABI (see below) is a better choice.
      +
      +
    • +
    +

    As of version 3.1, the front end also supports the IA-64 ABI, described by +www.codesourcery.com/cxx-abi/abi.html. This is a modern ABI originally +designed for the Intel IA-64 (“Itanium”) architecture, but now an industry +standard widely used on other architectures as well. In particular, the GNU +g++ compiler uses the IA-64 ABI on many platforms. This ABI is selected by +setting IA64_ABI to TRUE. Note that the fully-lowered implementation of +exception handling provided by EDG works with the IA-64 ABI, but does not +conform to the spec, and that versions using the C-generating back end do not +fully conform because of some layout cases not easily represented in C.

    +

    Note that the IA-64 ABI requires linker support in the form of a feature (often +called COMDAT) that allows different object files to contain (identical) +definitions of certain functions and variables. The linker discards the +duplicates, ending up with a single definition.

    +

    The ABI support in the front end changes from time to time as features are +added and bugs are fixed. The macro ABI_COMPATIBILITY_VERSION can be set +to a version number of the front end to keep the ABI frozen as it was at that +version. Source language features that require ABI changes made after that +version are disabled.

    +
    +
    +

    5.2. What Does C++ IL Lowering Do?#

    +

    IL lowering is called at the end of processing of each “top-level” scope (i.e., +once at the end of each top-level function, and once at the end of the file +scope). It rewrites any C++ IL constructs in the scope as semantically +equivalent C IL constructs. (A similar process occurs for C99 IL; see +Lowering C Dialects for details.)

    +

    IL Lowering is suppressed if there are errors in the source program, if the +dialect of C language being compiled doesn’t require it, if preprocessing only +is being done, or if syntax-checking only is being done.

    +
    +

    5.2.1. Name Mangling#

    +

    (Code for name mangling is in lower_name.c and lower_name.h.)

    +

    “Name mangling” means transforming the names of C++ entities so that the names +include information on aspects of the entity’s type and fully qualified name. +This is made necessary by the fact that the object code and C environments into +which a C++ program is translated typically contain fewer and simpler name +spaces than there are in the C++ language. Specifically:

    +
      +
    • +
      Overloaded function names are not allowed in C, and probably not in object +code.
      +
      +
    • +
    • +
      Classes have their own scopes in C++, but not in the generated C form. An +entity x from inside a class must not conflict with an entity x +from the file scope, for example.
      +
      +
    • +
    • +
      External names in C and (probably) in the object code form a completely +flat name space. The names of C++ entities with external linkage must be +projected onto that name space so that they do not conflict with one +another. A function f from a class A, for example, must not have +the same external name as a function f from class B.
      +
      +
    • +
    • +
      Some C++ “names” are not names in the conventional sense of the word +(they’re not strings of alphanumeric characters), e.g., operator=.
      +
      +
    • +
    +

    We can see that there are three problems here:

    +
      +
    • +
      Generating C code names that will not clash for non-external entities. +This is only a problem when generating C code.
      +
      +
    • +
    • +
      Generating external names that will not clash. This is a problem whether +the output is C or object code.
      +
      +
    • +
    • +
      Generating alphanumeric names for entities with strange “names” in C++. +This is a problem whether the output is C or object code, at least for +external names.
      +
      +
    • +
    +

    As it happens, the name mangling process solves all three problems. It also +solves the problem of generating hidden names for some behind-the-scenes +language support in such a way that they will match up across separate +compilations (e.g., virtual function table names).

    +

    Once name mangling has been done, the name linkage of C++ external entities is +changed to C external.

    +
    +

    5.2.1.1. Cfront-like ABI name mangling#

    +

    The cfront-like ABI name mangling algorithm is the same as the one used by +cfront, and also matches the description in 7.2.1c of the ARM (except for some +minor details). The reader is referred there for a complete description. +Here, we just hit the highlights and the things that differ from or are +extensions to that description.

    +

    Each type has a corresponding mangled encoding. For example, a class type +is represented as the class name preceded by the number of characters in +the class name, as in 5abcde for abcde. Simple types are encoded +as lower-case letters, as in i for int or f for float. +long long, wchar_t, and bool, which do not appear in the ARM, +are encoded as “L”, “w”, and “b”, respectively. The C++11 +types char16_t and char32_t are encoded as “g” and “k”, +respectively. A std::nullptr_t type is encoded as “n”, while the +C++/CLI __nullptr is encoded as “j”. (In some Microsoft modes, +there are distinct integral types named __int8, __int16, +__int32 and __int64. They are encoded as “m1”, “m2”, +“m4”, and “m8”, respectively.) 128-bit integers (in GNU +compatibility mode) are mangled with “m16” and “Um16” (signed and +unsigned, respectively). Type modifiers and declarators are encoded as +upper-case letters preceding the types they modify, as in U for +unsigned or P for pointer. In GNU C++ mode, complex types are encoded +with an “x” preceding the code for the corresponding real +floating-point type (e.g., “xf” for “_Complex float”). The long +double type is indicated by an “r” encoding. In addition to the type +declarators mentioned in the ARM (i.e., “P” for pointer, “R” for +reference, “A” for array, “F” for function, and “M” for +member), an “E” encoding has been added to indicate an rvalue +reference. For ref-qualified member function types, an optional “_R” +(for an lvalue req-qualifier) or “_E” (for an rvalue ref-qualifier) can +follow the “F” that indicates a function type. When C++/CLI is +enabled, the “Ht” encoding is used for tracking references, “Hh” is +used for handles, “Hi” is used for interior_ptr, and “Hp” is +used for pin_ptr. __underlying_type (enabled when type trait +helpers are enabled) is mangled as “o”. See +mangled_encoding_for_type.

    +

    Types specified using the C++11 keyword decltype are encoded in one of +three ways. When a decltype expression is either type-dependent or +value-dependent (i.e., it has some component that could be affected by the +C++11 SFINAE rules), it is said to be instantiation-dependent and it is +encoded using the character “y” or “Y” followed by a mangled +encoding of the expression (”y” is used when the expression is an +unparenthesized id-expression or a class member access; “Y” is used +otherwise). decltype expressions that are not instantiation-dependent +are encoded using the known underlying type or value (e.g., +decltype(sizeof(int)) is mangled using the mangled encoding for the +size_t type, i.e., “Ui” in a front end that is configured to use +unsigned int to represent size_t). In a manner similar to +decltype, typeof(type) is mangled using the encoding “t” +and typeof(expression) is mangled using the encoding “p”. The +“u” mangled encoding is also introduced in C++11 to represent the use +of auto as a type specifier when it appears in a new-expression that +is mangled because it appears in the context of an instantiation-dependent +expression (e.g., decltype(new auto(p1))). The letter “n” is used +to encode the type for nullptr (i.e., std::nullptr_t). The “q” +mangled encoding is used for the decltype(auto) notation.

    +

    When a function parameter is a C++11 function parameter pack, its type is +represented by the encoding “Dp” followed by the function parameter type.

    +

    Nested class types are encoded as a “Q” followed by a digit indicating the +depth of nesting, followed by a “_”, followed by the mangled-form names of +the class types in the fully-qualified name of the class, from outermost to +innermost:

    +
    class A {
    +  class B {  // Q2_1A1B
    +  };
    +};
    +
    +
    +

    The name of the nested class itself is mangled to the form described above with +a prefix __, which serves to make the class name distinct from all user +names. The same mangling technique is used for namespaces. In cases where the +mangled entity is specified in the source code as being in the global scope +(e.g., p->::X::y), and the entity is a selection or call operand, the +global scope indication is specified using the letter “G” as the first +qualifier in a qualified name; for example:

    +
    int g(int);
    +template <class T> auto f(T p1) -> decltype(::g(p1));
    +                                   // f__tm__2_i__FZ1Z_YOcl_2_4g__GI1IO
    +
    +
    +

    Local class names and scoped enumerators are encoded by following the name by +“__L” followed by a number (which has no special meaning; it uniquely +identifies the type within the function scope). This example (which requires +–c++11) shows a local class and its mangling within a function template:

    +
    template <typename T> void f(T) {}
    +void x() {
    +  struct A {} a;  // __12A__L1__x__Fv
    +  f(a);           // f__tm__15_12A__L1__x__Fv__FZ1Z_v
    +}
    +
    +
    +

    This form is used when encoding the local class name as a type. It’s not +actually necessary to mangle the name of the local class itself unless it’s +also a nested class. See mangled_type_name_full. This is not in the ARM, +and cfront does it slightly differently.

    +

    The “__L” indicator is also used in the names of entities promoted out of +functions. There, the “__L” appears between the name of the entity and the +mangled name of the function:

    +
    void *f() {
    +  struct A {};           // __12A__L1__f__Fv
    +  static struct A a;     // a__L0__f__Fv
    +  return &a;
    +}
    +
    +
    +

    The instance number (after the “__L”) serves to ensure that the mangled +name is unique (and is chosen so as to make it repeatable across translation +units in cases where the ODR requires it). Note that in configurations where +local types cannot be used in template arguments (i.e., other than –c++11 or +when microsoft_mode >= 1400) and therefore can’t appear in external names, the +mangled names may differ slightly from those listed above.

    +

    Unnamed namespace names are mangled as __N followed by a unique string. +The unique string is the “module id” generated by IL lowering from the source +file name and some other information, but from the perspective of name mangling +it is simply ignored. Such names appear only in contexts where their length is +given, so it’s easy to know how much to ignore.

    +

    Template classes have mangled names that encode the arguments of the template:

    +
    template<class T1, class T2> class abc {};
    +abc<int, int> x;
    +abc__tm__3_ii
    +           ^^--- Two template arguments of type int.
    +         ^------ Total length of template argument list string, including
    +                   the underscore.
    +     ^^--------- Fixed string, indicates "template".
    +^^^------------- The name of the class template.
    +
    +
    +

    When distinct mangling for templates is disabled, “tm” is replaced by +“pt” (which is what cfront uses).

    +

    The encoding for nontype template arguments encodes both the parameter type and +the actual argument value:

    +
    template<int I> class def {};
    +def<5> x;
    +def__tm__7_XCiL15
    +                ^-- Literal constant representation.
    +               ^--- Length of literal constant.
    +              ^---- "L" indicates literal constant, "c" indicates address
    +                       of variable, etc.
    +            ^^----- Type of template argument, with "const" added.
    +           ^------- "X" indicates beginning of constant argument.
    +
    +
    +

    Template argument packs are introduced by “__pk__”:

    +
    +
    template <class T, class ...U> int f();
    +int x = f<short, int, double>();
    +f__tm__12_s__pk__3_id__Fv_i <-- encoding for "f<short, int, double>()"
    +                          ^---- Return type (int).
    +                        ^------ Argument list (void).
    +                       ^------- Function.
    +                    ^---------- Second argument of the pack (double).
    +                   ^----------- First argument of the pack (int).
    +                 ^------------- Total length of template argument pack.
    +             ^^---------------- Beginning of a template argument pack.
    +          ^-------------------- First template argument type (short).
    +       ^^---------------------- Total length of template argument list.
    +   ^^-------------------------- Introduces template arguments.
    +^------------------------------ The name of the function template.
    +
    +
    +
    +

    Constants are encoded with the letter “C” followed by the type of the +constant and the encoding of the constant value (e.g., “CiL_2_59” +represents the integer constant 59). There are several different encodings +for different kinds of constants:

    +
      +
    • +
      Integer:
      +
      +
      L3n12  <-- encoding for "-12"
      +   ^^----- Literal value.
      +  ^------- "n" indicates negative.
      + ^-------- Length of the literal.
      +^--------- "L" indicates a number.
      +
      +
      +
      +
      This is compatible with cfront 3.0.1.
      +

      +
      The length of the literal uses an encoding compatible with cfront, i.e., +it’s either a single digit or two digits followed by an underscore (e.g., +“L10_1234567890”). This encoding has some ambiguity problems when the +template argument is followed by an underscore. Such cases did not come up +in the cfront world, but they do come up when template arguments are +applied to template functions (see paragraphs on distinct mangling for +templates, below). To deal with this, a new unambiguous mangling for +literal lengths has been introduced as of version 2.32. It has the length +enclosed in underscores in all cases (single- or multi-digit), e.g., +“L_1_2”. This form is used in the new contexts that didn’t come up for +cfront, and the old form continues to be used in the cfront contexts.
      +
      +
    • +
    • +
      Float:
      +
      +
      L4n1p5 <-- encoding for "-1.5"
      +   ^^^---- Literal value ("p" for decimal point).
      +  ^------- "n" indicates negative.
      + ^-------- Length of the literal.
      +^--------- "L" indicates a number.
      +
      +
      +
      +
      cfront 3.0.1 does not implement this, so we made it up. In actuality, the +literal form of the floating constant depends on the fp_to_string +routine, so the encoding is likely to be longer (for example, it’s likely +to include an exponent).
      +
      +
    • +
    • +
      Complex floating point literals are mangled like floating point literals +above except that both real and imaginary components are included:
      +
      +
      L_3_0d0_3_1d1 <-- encoding for "0.0+1.0i"
      +          ^^^---- Imaginary portion of complex number.
      +       ^^^------- Length of the imaginary portion of the number.
      +    ^^^---------- Real portion of complex number.
      + ^^^------------- Length of the real portion of the complex number.
      +^---------------- "L" indicates a number.
      +
      +
      +
    • +
    • +
      Address of variable or routine:
      +
      +
      4abcd <-- encoding for address of "abcd"
      + ^^^^---- Name of entity.
      +^-------- Length of the name.
      +
      +
      +
      +
      This is compatible with cfront 3.0.1.
      +
      +
    • +
    • +
      For pointers to data members, the offset value encoded as an integer:
      +
      +
      L212  <--- encoding for an offset of "12"
      +  ^^------ Literal value.
      + ^-------- Length of the literal.
      +^--------- "L" indicates a number.
      +
      +
      +
      +
      This is compatible with cfront 3.0.1.
      +
      +
    • +
    • +
      For pointers to member functions, the __mptr triplet of values (delta, +index, function or offset), encoded as follows:
      +
      +
      LM0_L2n1_1j
      +         ^^- Function name, or alternatively "0" if the pointer
      +               to member uses an offset (e.g., LM0_L11_0).
      +    ^^^^---- Index value, encoded as an integer.
      +  ^--------- Delta value.
      +^^---------- "LM" indicates a pointer to member function.
      +
      +
      +
      +
      This is compatible with cfront 3.0.1. Note that “0” is always used +for the offset, not the actual offset value. This follows cfront. The +idea seems to be that “0” is really a way of saying “there is no +function;” the offset value itself would not be of interest to a name +demangler.
      +
      +
    • +
    • +
      For strings, the type of the string is encoded. The character “S” +is used to indicate a string literal. The string L"xyz" is encoded +as “CA4_CwLS” (i.e., a string literal of type const wchar_t[4]).
      +
      +
    • +
    • +
      nullptr is encoded using the encoding for integers given above; the +type is always “n” (for std::nullptr_t), and the value is +always zero, so the entire mangled encoding for nullptr is always +“CnL_1_0”.
      +
      +
    • +
    +

    The fact that there are rules for mangling type names seems to suggest that +names of types are mangled. Strictly speaking, except for nested class names, +they are not. It is really only the names of variables and routines that need +to be mangled. The mangled form of type names does have a use, however: it is +used when building the mangled names of variables and routines, to represent +the types referenced by the entity (e.g., parameter types).

    +

    Unnamed (class/struct/union, enums, lambda closure) types are given a generated +name during mangling; that name is then used as described above (e.g., in +mangled names of variables and routines). The names generated for these +unnamed types are constructed so as to ensure that types subject to ODR +constraints across translation units are given the same name; other types are +given names guaranteed not to collide with similar constructs in other +translation units.

    +

    Unnamed class/struct/union and enums are given the name “__Ut” followed by +an instance number (within the namespace/class/function scope) which makes the +generated name unique within that scope. A mangled encoding of the type will +include its parent’s encoding as well.

    +

    Lambda closure types are a special kind of unnamed class type, and they are +mangled with a similar “__Ul” encoding that additionally gives information +about the lambda’s parameter types:

    +
    +
    __Ul1_Fif <-- [](int, float)->float {return 0.0;}(i, f);
    +      ^^^---- Lambda operator() function type (int, float).
    +    ^-------- Instance (within parent scope).
    +^^^^--------- "__Ul" indicates lambda.
    +
    +
    +
    +

    Lambdas defined in certain contexts, specifically some default arguments and +member initializers, are subject to ODR constraints and therefore must get +names that can be generated identically in different compilations. That’s +accomplished by making the default argument or member initializer a +“pseudo-parent scope” and encoding the closure type as a member of that +pseudo-scope.

    +

    Lambdas defined in default arguments (and subject to ODR constraints) are given +a name based on this encoding:

    +
    +
    __Ud1_2_Fv__L0__f__FiT1 <-- void f(int i=[]{return 0;}(),int k=0)
    +          ^^^^^^^^^^^^^---- Local to function f(int,int).
    +        ^^----------------- Lambda operator() function type.
    +      ^-------------------- Declared in trailing parameter 2.
    +    ^---------------------- Instance 1 (within parameter).
    +^^^^----------------------- "__Ud" indicates lambda in default arg.
    +
    +
    +
    +

    Lambdas in member initializers are given a name that is prefixed with +“__Um”:

    +
    +
    __Q3_10S__tm__2_i1x8__Um1_Fv < template <class T> int S<T>::x =
    +                                                       []{return 1;}();
    +                          ^^-- Lambda operator() function type.
    +                        ^----- Instance (within member initializer).
    +                    ^^^^------ "__Um" indicates lambda in initializer.
    +                   ^---------- Length of type name that follows.
    +^^^^^^^^^^^^^^^^^^^----------- Nested encoding for S<int>::x::.
    +
    +
    +
    +

    The following kinds of entity names (only) are mangled:

    +
      +
    • +
      Function names. Even non-member function names are mangled, to deal with +overloading. Names of functions with extern "C" linkage are not +mangled. See mangle_function_name.
      +
      Mangled function names have the function name followed by “__” followed +by “F” followed by the mangled description of the types of the +parameters of the function. If the function is a member function, the +mangled form of the class name precedes the “F”. If the member +function is static, an “S” also precedes the “F”. In cases where +the function has extern "C" linkage on the function type, a “K” +modifier immediately follows the “F” indication.
      +
      +
      int f(float);                   // f__Ff
      +class A {
      +  int f(float);                 // f__1AFf
      +  static int g(float);          // g__1ASFf
      +};
      +
      +
      +
      +
      Members of namespaces are mangled like member functions.
      +
      For the Microsoft extension that allows explicit specification of a virtual +function to be overridden, name mangling adds the class of the overridden +virtual function as O followed by the class type encoding, after the +class name. So, for example, a member D::f that explicitly overrides +B::f would be encoded as f__1DO1BFv.
      +
      +
    • +
    • +
      Special and operator function names, like constructors and operator=(). +The encoding is similar to that for normal functions, but a coded name is +used instead of the routine name:
      +
      +
      class A {
      +  int operator+(float);         // __pl__1AFf
      +  A(float);                     // __ct__1AFf
      +};
      +int operator+(A, float);        // __pl__F1Af
      +
      +
      +
      +
      The ARM contains a full list of the name encodings. Static constructors, +used in C++/CLI, are encoded with “__st__”; finalizers are encoded with +“__df__”. See mangled_operator_name.
      +
      +
    • +
    • +
      Static data member names. The mangled form is the member name followed by +“__” followed by the mangled form of the class name:
      +
      +
      class A {
      +  static int i;                 // i__1A
      +};
      +
      +
      +
      +
      This type of mangling is also used for variables that are members of +namespaces. Generally speaking, the names of variables at the file scope +don’t need to be mangled, but that’s not true for variable templates, or +for variables that may have implicit or explicit abi_tags. See +mangle_variable_name.
      +
      +
    • +
    • +
      Functions that are instances or specializations of templates. These +are mangled to include the template signature. This is controlled by +the variable distinct_template_signatures. Template parameters +(both type and nontype) are mangled as “ZnZ” or “Zn_mZ”, where n is the template parameter position +number (first is 1) and m is the template parameter depth (top level +is 1, which is assumed in the case where it is not specified). The +return type of the function is also included in the mangled name. +“__S” can appear either directly after the template name, to +indicate that the template is specialized, or after the template +argument list, to indicate that the instance is specialized.
      +
      +
      template <class T> struct A {
      +  template <class T2> void f(T2);
      +};
      +template <> template <class T2> void A<char>::f(T2) {}
      +template <> template<> void A<float>::f(int) {}
      +A<int> ai;
      +A<char> ac;
      +A<float> af;
      +int main(){
      +  ai.f(1); // f__tm__2_i__10A__tm__2_iFZ1_2Z_v
      +  ac.f(1); // f__S__tm__2_i__10A__tm__2_cFZ1_2Z_v
      +  af.f(1); // f__tm__2_i__S__10A__tm__2_fFZ1_2Z_v
      +}
      +
      +
      +
      +

      +
      The specialization indications are also placed in the names of parent +classes of functions and static data members generated from templates. A +“__S” following directly after the class itself indicates that the +class is specialized (and similarly for a class template), and a “__S” +after the template argument list of a class template indicates that the +instance is specialized.
      +
      +
      template <class T> struct A {
      +  void f();
      +  struct B {
      +    void bf(T);
      +  };
      +};
      +template <> struct A<short> {
      +  void f();
      +};
      +template <> struct A<int>::B {
      +  void bf(int);
      +};
      +A<short> as;
      +A<int>::B aib;
      +main () {
      +  as.f();         // f__13A__tm__2_s__SFv
      +  aib.bf(1);      // bf__Q2_10A__tm__2_i4B__SFi
      +}
      +
      +
      +
      +
      When a partial specialization of a class template appears, the mangled name +has two template argument lists. The first (which begins with +“__ps__”) gives the template arguments that appear on the declaration +of the partial specialization, and the second gives the arguments according +to the template parameters of the partial specialization.
      +
      +
      template <class T, class U> struct A {};
      +template <class T> struct A<T *, int> {
      +  void f();  // f__23A__ps__6_PZ1Zi__tm__2_iFv_v
      +             //      A  <T *, int>   <int>
      +};
      +
      +
      +
      +
      Where expressions appear in template signatures, they are mangled as in the +following example:
      +
      +
      Opl_2_Z1ZZ2ZO <-- "Z1 + Z2", Z1/Z2 indicating nontype template
      +                  parameters.
      +            ^---- "O" to end the operation encoding.
      +         ^^^----- Second operand.
      +      ^^^-------- First operand.
      +   ^^^----------- Count of operands (with bracketing underscores).
      + ^^-------------- Operation, using same encoding as for operator
      +                  function names.
      +^---------------- "O" for operation.
      +
      +
      +
      +
      The two or three letter operation encodings (e.g., “pl” in the example +above) are the same as the operator function encodings specified in the ARM +(without the leading double underscores).
      +
      The operands can be template parameters, constants (using the encoding +described for nontype template arguments, not including the initial +“X”), subexpressions (using the expression operation encoding described +above), mangled names (e.g., of variables or routines), or (in decltype +expressions) function parameter references.
      +

      +
      In addition to those operations specified in the ARM, the following +operation encodings have been added as EDG extensions:
      +
      +
      "ds" = .*
      +"dt" = .
      +"ps" = unary plus
      +"ng" = unary minus
      +"de" = * (indirection)
      +"ao" = & (address of)
      +"ppe" = prefix increment (pp indicates postfix increment)
      +"mme" = prefix decrement (mm indicates postfix decrement)
      +"tw" = throw
      +"rl" = __real
      +"im" = __imag
      +"mn" = GNU min operator (<?)
      +"mx" = GNU max operator (>?)
      +"sp" = ... (pack expansion)
      +"ht" = % (C++/CLI unary "%" operator which returns a handle)
      +"sb" = [] (C++/CLI array subscript -- has variable number of operands)
      +"gc" = gcnew (C++/CLI gcnew -- optional list of dimension expressions
      +       precedes a type operand)
      +"cp" = () (call operation with ADL suppressed -- has variable number of
      +       operands)
      +"il" = {} (brace-enclosed initializer list -- has variable number of
      +       initializers)
      +"tl" = T{} (cast of a brace-enclosed initializer list -- has a type
      +       followed by a variable number of initializers)
      +"nx" = noexcept
      +"li" = literal operator (for user-defined literals -- has zero or one
      +       operand and is followed immediately by a count and the ud-suffix
      +       for the literal operator, e.g., operator "" _miles would be
      +       "li6_miles")
      +
      +
      +
      +
      The following added operations differ from the standard operation encoding +in that they include an initial type before a single operand. The “cs” +encoding is used to encode both the old-style cast (where there is one +non-type operand) as well as the functional-notation cast (where there can +be zero or more non-type operands). The case where a functional-notation +cast is used with one argument is indistinguishable from the old-style cast +case:
      +
      +
      "sc" = static_cast
      +"dc" = dynamic_cast
      +"rc" = reinterpret_cast
      +"cc" = const_cast
      +"cs" = old-style (one argument) or functional-notation cast
      +"sf" = C++/CLI safe_cast
      +
      +
      +
      +
      The following operation differs in that it takes a single type argument:
      +
      +
      "ct" = C++/CLI ::typeid
      +
      +
      +
      +
      The following operations differ in that their source can specify either a +type or an expression:
      +
      +
      "sz" = sizeof
      +"af" = __ALIGNOF__
      +"uu" = __uuidof
      +"ty" = typeid
      +"sk" = sizeof...
      +
      +
      +
      +
      The mangled encodings for these cases are:
      +
      +
      OszZ1Z0O <-- "sizeof(Z1)", Z1 indicating a template parameter.
      +       ^---- "O" to end the operation encoding.
      +      ^----- Count of operands, 0 for type and "e" cases, 1 for "X".
      +   ^^^------ Encoding for type or "e" or "X" (for expression cases).
      + ^^--------- Operation ("sz" for sizeof, "af" for __ALIGNOF__,
      +             "uu" for __uuidof, or "ty" for typeid)
      +^----------- "O" for operation.
      +
      +
      +
      +
      There are three cases. When the operation takes a type, then the type +is encoded after the operation encoding and there are no operands. +Prior to version 4.2, an expression was indicated with an “e” in +place of the type (but no expression was contained in the mangled name +and the operand count was still zero). In version 4.2 and later, the +mangled expression is included (operand count is 1), and the type is +replaced with an “X” to indicate that an expression follows. | | The +new and delete operations (as well as new[] and +delete[]) are encoded thusly:
      +
      +
         v--------------vvvvvvvvvv----- These are optional.
      +Onwg_1_CiL_2_10Z1Z_1_CiL_1_0O <-- encoding for "::new (10) T (0)"
      +                            ^---- "O" to end the encoding.
      +                     ^^^^^^^----- Initializers (if any).  An optional
      +                                  "bi" indicates the use of a
      +                                  brace-enclosed initializer list.
      +                  ^^^------------ Optional initializer count (zero
      +                                  or more).  Omitted (along with
      +                                  initializers) if none were
      +                                  specified.
      +               ^^^--------------- Type of new operation.
      +       ^^^^^^^^------------------ Placement arguments (if any).
      +    ^^^-------------------------- Placement argument count (zero
      +                                  or more).
      +   ^----------------------------- "g" indicates global new.
      + ^^------------------------------ new operation (nw, nwa).
      +^-------------------------------- "O" for operation.
      +
      +   v----------- This is optional.
      +Odlg_1_I1IO <-- encoding for "::delete p1"
      +          ^---- "O" to end the operation encoding.
      +       ^^^----- Argument to delete.
      +    ^^^-------- Argument count (always one for delete).
      +   ^----------- "g" indicates global delete.
      + ^^------------ delete operation (dl, dla).
      +^-------------- "O" for operation.
      +
      +
      +
      +
      Builtin operations (i.e., vendor-specific extensions like Microsoft +__is_base_of) use the operation “bi”, and any operands that are +types are prefixed by “T”. The encoding “__dn” was added to +represent a destructor name (and is followed by a single type name). +See mangled_encoding_for_expression for details on the mangling of +expressions. | | Where arrays with sizes based on template parameters +appear, they are mangled as “A_mangled-expression_element-type” (the underscore following the “A” differentiates +this case from the usual known-size array case). | | A template +template parameter that is followed by a template argument list, e.g., +ttparam<x,y,x> in source code, is represented by the Z...Z +encoding, with the template argument list encoding inserted before the +closing Z, as in Z1__tm__4_Z2ZZ. | | References to function +parameters in decltype expressions (e.g., p in template +<class T> auto f(T p) -> decltype(p)) are mangled as such:
      +
      +
       v-vv----- These are optional.
      +IC1_2I <-- "const param#1 two levels up"
      +     ^---- Terminating non-digit character so parameter number won't run
      +           into an entity with an initial length.
      +   ^^----- Number of "levels up" for this parameter (0-based).  Omitted
      +           if zero.
      +  ^------- Parameter number (1-based) or 0 for "this".
      + ^-------- Optional cv-qualifiers.
      +^--------- "I" indicates parameter reference.
      +
      +
      +
    • +
    • +
      The implicit or explicit use of this in a mangled name is also +represented with the function parameter mangling given above (where the +parameter number is set to zero).
      +
      +
    • +
    • +
      Names of variables generated for virtual function tables. These have names +like
      +
      +
      +

      __vtbl__mangled-class-name

      +
      +
      +
      or
      +
      +
      +

      __vtbl__mangled-base-class-name__mangled-class-name

      +
      +
      +
      In the case of a virtual function table used during construction or +destruction of a subobject, there can be an additional mangled class name +on the end. See make_var_for_virtual_function_table.
      +
      +
    • +
    • +
      Names of variables generated to contain runtime type information. These +have names like
      +
      +
      +

      __T_type-encoding

      +
      +
      +
      and
      +
      +
      +

      __TID_type-encoding

      +
      +
      +
      See mangled_typeinfo_name and mangled_id_object_name.
      +
      +
    • +
    • +
      Names of wrapper routines generated to deal with covariant virtual function +return types. These are pointed to from virtual function tables and have +names of the form
      +
      +
      +

      __VFE__overridden-class__overriding-function

      +
      +
      +
      See mangle_wrapper_name.
      +
      +
    • +
    • +
      Names of static variables and functions made external, e.g., because they +are referenced from an instantiation and each instantiation is placed in a +separate object file. The form of the mangled names is
      +
      +
      +
      +
      __STV__variable-name__module-id
      +
      __STF__mangled-function-name__module-id
      +
      +
      +
      +
      where module-id is a unique name generated for the current compilation.
      +
      +
    • +
    • +
      The GNU ifunc attribute, when lowered, creates a variable through which +calls to the function are dispatched. The variable uses the __IFV__ +prefix:
      +
      +
      +

      __IFV__variable-name

      +
      +
    • +
    • +
      When GNU function multiversioning is used, a set of routines with the same +unmangled name are given unique mangled names based on their use. The +following prefixes are used to create these names:
      +
      +
      +
      + + + + + + + + + + + + +
      +
      __RES__mangled-function_name
      +
      +
      +
      resolver function
      +
      +
      +
      __IFC__mangled-function-name
      +
      +
      +
      ifunc function
      +
      +
      +
      __TGT__targets__identifier
      +
      +
      +
      target-specific function
      +
      +
      +
      +
      +
    • +
    • +
      For classes and function names with the GNU abi_tag attribute, the +“__ab” prefix is used (once for each string literal that is specified +in the abi_tag attribute list):
      +
      +
      +

      __ab<count><tag>

      +
      +
      +
      where <count> represents the number of characters in the <tag> string +literal.
      +
      +
    • +
    • +
      Structured binding container variables (at namespace scope) are given +mangled names based on the binding variable(s) they refer to. The +“__SBC__” prefix is used to identify this mangling. Each of the +binding variables, in order, are included in the container’s mangled name, +separated by “__”. A final “__” indicates the end of the +structured binding container mangled name. For example, +__SBC__x__y______1N indicates a structured binding container for +[x,y] in namespace N.
      +
      +
    • +
    +

    Once a mangled name has been generated, a compression step examines it to see +whether it can be shortened by compression. The compression approach is +simple-minded: the sequence “JnnnJ” means “repeat the sequence +beginning at offset nnn in the mangled name.” The offset is 0-origined. Only +sequences that begin with a length (e.g., 7ABCDEFG) are eligible to be +repeated in this way. Each “J” in the original mangled name is replaced by +“JJ” to avoid ambiguities. If compression is done, the mangled name is +given a prefix of “__CPRnnnn__”, where nnnn is the length of +the uncompressed form of the name.

    +
    +
    +

    5.2.1.2. IA-64 ABI name mangling#

    +

    In the IA-64 ABI, name mangling is done according to the ABI spec +(www.codesourcery.com/cxx-abi/abi.html). We will not repeat that description +here.

    +

    There is no compression per se in the IA-64 ABI name mangling scheme. +Instead, entities that have appeared earlier in a mangled name can be +referenced again by way of a “substitution,” which is essentially the encoding +“S” followed by a number (base 36) indicating which of the preceding +entities is repeated. Entities of certain kinds (types, qualified name +prefixes, templates) are assigned numbers in their order of appearance in the +mangled name, and a later substitution can refer to such an entity by number. +Certain types and templates in the standard iostream header are assigned +predefined substitution codes so that they can be referenced cheaply. For the +implementation of substitutions, see add_substitution_if_available and +alloc_substitution. Note that one consequence of substitutions is that it +is impossible to reuse mangled names for entities as part of a larger mangled +name including that entity, because the substitution numbering in the reused +piece would be wrong for the overall mangled name.

    +

    Mangled names for entities local to a function are distinguished by a trailing +“discriminator,” a number that serves to distinguish like-named entities within +one function. Such entities are assigned discriminator numbers in the front +end, in strict order of appearance in the function. For example, the first +variable “i” in a function is assigned discriminator number zero, the next +one, etc. regardless of block scope nesting. These discriminator values are +recorded in the symbol table (rather than the IL) and IL lowering retrieves +them and includes them in mangled names.

    +

    Similarly, string literals within (certain) functions are numbered so that +mangled names can be generated for them. The C++ standard requires that if an +extern inline function is implemented by multiple copies, a string literal +that appears in the function has the same address in all copies. This is +implemented by assigning a sequence number to each string in functions that +might exist in multiple copies. Name mangling then uses that number to +generate a mangled name for the variable created to hold the string value.

    +

    For entities “externalized,” i.e., static variables or functions made external +because they must be referenced from multiple compilations (e.g., for exported +templates, or in one-instantiation-per-object mode), name mangling uses an +extension to the ABI spec. This is an encoding of the form

    +
    +

    B length module_id

    +
    +

    where module_id is a generated string describing the current compilation, +formed from the source file name and some other bits that help make it unique. +This encoding is used as a prefix on the <name> syntax term and is used to make +a local name unique when it is externalized.

    +

    For the Microsoft extension that allows explicit specification of a virtual +function to be overridden, name mangling adds the name of the overridden +virtual function as the encoding Q<nested-name> following the nested +name for the function, i.e., an <encoding> has an alternative of <function +name>Q<nested-name> <bare-function-type>. So, for example, a member +D::f that explicitly overrides B::f would be encoded as +_ZN1D1fEQN1B1fEv. This is an extension to the ABI spec.

    +

    Builtin operations in expressions (i.e., vendor-specific extensions like the +Microsoft __is_base_of) are encoded as a vendor-specific operator builtinXX, where XX is the number of the builtin operation. Any type operands are +encode as “TO” followed by the encoding for the type.

    +

    When C++/CLI is enabled, tracking references, interior_ptrs, pin_ptrs, and handles are mangled using the vendor extended type qualifier:

    +
    +

    <type> ::= U<source-name><type> # vendor extended type qualifier

    +
    +

    Tracking references use the encoding “8__trkref” for <source-name>, +interior_ptrs are encoded as “14__interior_ptr”, pin_ptrs +as “9__pin_ptr”, and handles are encoded as “8__handle”. C++/CLI +static constructors are encoded as “C8” and finalizers are “D7”. +__nullptr is encoded as “DN”; __underlying_type is encoded as +“Du”.

    +

    C++/CLI operators are generally mangled using the IA-64 ABI vendor extended +operator syntax:

    +
    +
    +
    <operator-name> ::= v<digit><source-name> # vendor extended +operator
    +
    +
    +

    The unary “%” operation (which produces a handle to its operand) uses the +“9clihandle” <source-name>; the array subscript operation (which has a +variable number of operands) is encoded with a <source-name> of +“12clisubscript”. Due to the limitation of a single digit in this +encoding, only 8 subscripts can be represented in the mangled name. The +::typeid operation is mangled as “9clitypeid”; safe_cast is +“12clisafe_cast”.

    +

    The vendor extended operator syntax isn’t flexible enough to support gcnew, +so an EDG-specific mangling (patterned after the mangling for new) is used:

    +
    +
    + + + + + + + + + + + + + + + +
    +
    ::= gc_<type>E
    +
    +
    +
    # gcnew <type>
    +
    +
    +
    ::= gc_<type><initializer>
    +
    +
    +
    # gcnew <typ>e {init}
    +
    +
    +
    ::= gc<expression>*_<type> E
    +
    +
    +
    # gcnew array<type>(dims)
    +
    +
    +
    ::= gc<expression>*_<type><initializer>
    +
    +
    +
    # gcnew array<type>(dims) {init}
    +
    +
    +
    +
    +

    The IA-64 ABI specification doesn’t specify how to mangle function names that +use the GNU multiversion feature. For these functions, the front end produces +mangled names similar to the names that GNU produces. More specifically, for +the resolver function and for target-specific functions, a suffix is appended +to the name (”.resolver” for resolver functions and a string that contains +a sorted list of the canonicalized target attributes for target-specific +functions). The mangling for an ifunc function is somewhat different: the +original name is mangled, then “.ifunc” is appended, then the name is +mangled again (with the signature of the lowered routine type). Note that +these GNU manglings contain periods which can cause problems in certain back +ends (e.g., C-generating back ends), so a configuration macro, +REPLACE_SPECIAL_CHARACTERS_IN_MANGLED_NAMES, is available to change the +periods into underscores. Note also that due to their non-standard nature, +these names cannot be demangled (either with or without the periods).

    +
    +
    +
    +

    5.2.2. Dynamic Initialization#

    +

    The a_dynamic_init entry, which describes a dynamic initialization, is used +both in C and C++. IL lowering rewrites cases that are not valid in C and +leaves the others. See lower_dynamic_init. Cases that must be rewritten +are:

    +
      +
    • +
      Initialization of a file-scope variable to a nonconstant value.
      +

      +
      See lower_file_scope_dynamic_inits.
      +

      +
      The initialization is rewritten as executable code in a file-scope +initialization routine (called __sti__module-id, or __tls_init +for initialization of objects with thread_local storage).
      +

      +
      The existence of the initialization routine is communicated to the +environment through creation of a file-scope static variable called +__link:
      +
      +
      void __sti__module_id() {...}
      +struct __linkl {
      +  struct __linkl *next;
      +  void           (*ctor)();
      +  void           (*dtor)();
      +};
      +static struct __linkl __link = {NULL, __sti__module_id, NULL};
      +
      +
      +
      +
      This is compatible with the cfront patch step. That tool or something +similar to it can find the __link variable and place it on a list of +entries to be consulted at program startup and termination. It is also +compatible with the alternative cfront munch tool, which looks for +routines with names beginning with __sti__ and __std__. Note that +the cfront approach allows the specification of a termination routine, but +that facility is not used by this front end (end-of-program destructions +are requested individually by calling a runtime routine, e.g., +__record_needed_destruction for the cfront-like ABI). This __link +variable is included in the program even if initialization is handled by +some fancier mechanism (see, for example, +USE_INIT_SECTION_IN_GENERATED_C for the C-generating back end), and +even in the IA-64 ABI, even though it may not be used in those cases.
      +

      +
      See make_code_to_invoke_file_scope_init_routine.
      +

      +
      When ONE_INSTANTIATION_PER_OBJECT is TRUE, each instantiation in a +compilation is put out as a separate object file. There is still only one +IL tree, but it is marked so that a back end can sweep through it several +times and put out a different “slice” each time, each slice containing one +instantiated entity (function, variable, or static data member) plus +exactly the set of other entities needed by that entity. This is done via +a set of per-instantiation “needed” flags. For slices that contain +variable template or static data member instantiations, the slice may +require file-scope initialization code. In these cases, multiple +file-scope initialization routines and multiple __link variables are +generated, each one marked to be included in the proper slice. Each +file-scope initialization is placed in the initialization routine for the +appropriate slice and any initialization for objects with thread_local +storage are put out in a __tls_init_N routine where the N indicates +the number of the slice).
      +
      +
    • +
    • +
      Initialization of a local static variable to a nonconstant value. The +initialization is rewritten as executable code, then surrounded by a +first-time test so that the initialization is done only once:
      +
      +
      void f() {
      +  static int i = j+k;
      +}
      +
      +
      +
      +
      is translated to (cfront-like ABI):
      +
      +
      static int temp;  // Implicitly initialized to zero
      +void f() {
      +  static int i;
      +  if (temp == 0) {
      +    temp = 1;
      +    i = j+k;
      +  }
      +}
      +
      +
      +
      +
      In the IA-64 ABI, the guard variable is set after the initialization. If +IA64_ABI_USE_GUARD_ACQUIRE_RELEASE is TRUE, the routines given in the +ABI spec are called, making the full (and potentially thread-safe) sequence
      +
      +
      static long long temp;  // Implicitly initialized to zero
      +void f() {
      +  static int i;
      +  if (temp == 0) {
      +    if (__cxa_guard_acquire(&temp)) {
      +      i = j+k;
      +      __cxa_guard_release(&temp);
      +    }
      +  }
      +}
      +
      +
      +
      +
      See add_first_time_test.
      +
      +
    • +
    • +
      Initialization by calling a routine that returns a class object via a copy +constructor. The initialization is rewritten as a call of the routine.
      +
      +
    • +
    • +
      Initialization using a constructor. The initialization is rewritten as a +call of the constructor.
      +

      +
      See add_constructor_call.
      +
      +
    • +
    • +
      Initialization to a nonconstant aggregate. The initialization is rewritten +as initialization to a constant aggregate combined with executable code to +initialize the nonconstant positions.
      +
      +
      void f() {
      +  int a[3] = {1, i+1, 3};
      +}
      +
      +
      +
      +
      is rewritten as
      +
      +
      void f() {
      +  int a[3] = {1, 0, 3};
      +  a[1] = i+1;
      +}
      +
      +
      +
      +
      See
      +
      +
        +
      • +
        lower_ck_dynamic_init
        +
        +
      • +
      • +
        lower_dynamic_init_aggregate_constant
        +
        +
      • +
      • +
        add_destructor_call
        +
        +
      • +
      +
    • +
    • +
      Any dynamic initialization requiring a destructor. The required destructor +call will be on a list of destructions to be done at the end of an object +lifetime. See Object Lifetimes.
      +

      +
      If the dynamic initialization is a valid C initialization except for the +requirement to call a destructor, it is left as-is; otherwise, it is +rewritten as described above.
      +

      +
      When a global or local static variable is constructed, and the variable +requires later destruction, this is recorded at runtime by calling the +routine __record_needed_destruction [2] (cfront-like ABI) or +__cxa_atexit (IA-64 ABI) The calls of that routine build a list of +entities to be destroyed at the time of program termination. If a +destruction requires only a destructor call, the data structure passed to +the runtime routine gives the address of the object and the address of the +destructor. Otherwise (for more complex cases, e.g., arrays), a routine is +generated containing the necessary destruction code, and the address of +that routine is passed in the data structure, along with a NULL object +pointer indicating the complex case.
      +

      +
      See record_needed_destruction.
      +
      +
    • +
    +

    In routines that return a class value by calling a copy constructor, the +stmk_return statement is unusual in that it points to a dynamic +initialization entry that describes the initializing operation to be done to +return a value. The destination of the initialization is taken to be the +address given by the implicit return value parameter added to the routine. The +caller passes in the address of a class object, and the code generated for the +return statement initializes that object before returning.

    +
    +
    +

    5.2.3. Main Program#

    +

    A call of the runtime routine _main is inserted at the start of the main +program. That routine invokes initialization code for file-scope variables, +and arranges things so that the corresponding termination code will be called +when the program terminates. See lower_scope, and the section on dynamic +initialization in this chapter.

    +
    +
    +

    5.2.4. Class Types#

    +

    The following processing is done on class types:

    +
      +
    • +
      If the class has virtual base classes, a copy of the class type is made +without the virtual base classes. This copy is given the name of the +original class prefixed with “__SO__”. This type is attached to the +original type through the type_as_subobject pointer. If the class has +no virtual base classes, the type-as-subobject is the same as the original +class type. See make_subobject_class_type.
      +
      +
    • +
    • +
      The field list of the class is augmented by adding generated fields for the +base classes of the class (using the type-as-subobject of the base classes +for the field types) and pointer to a virtual function table and (for the +cfront-like ABI) any required pointers to virtual base classes . This does +not change the size of the class – these entities were already part of the +class; they are just made explicit so they can be referenced as fields. +See prelower_class_type.
      +
      +
    • +
    • +
      If the class has virtual functions, a variable will be created for a +virtual function table for the class and for each base class of the class +as a subobject of the class. The declaration is created as an extern +declaration, and is turned into a definition (either external or static) +that is initialized if the virtual function table definition should be put +out. (See next section and make_vars_for_virtual_function_tables).
      +
      +
    • +
    • +
      If the class has virtual base classes, in the IA-64 ABI, information needed +to access virtual base classes and to call virtual functions in such bases +is determined and recorded. See +compute_vbase_and_vcall_offset_indices.
      +
      +
    • +
    • +
      The members of the class (local constants, local types including nested +classes, static data members, and member functions) are promoted out of the +class into the surrounding context. See promote_class_members and +do_scope_class_member_promotion.
      +
      +
    • +
    • +
      To support the anachronism that allows a static data member to be declared +but never defined, the storage class of static data members that are +externally visible and have no initial value is changed to sc_extern. +See lower_scope.
      +
      +
    • +
    +
    +
    +

    5.2.5. Virtual Function Tables#

    +

    Each class containing virtual functions has associated with it a virtual +function table. If it has base classes that also contain virtual functions, it +will also have associated with it an instance of each base class’s virtual +function table adjusted for use when that base class is a subobject within a +complete object of the derived class. So, associated with a class C we +might have a virtual function table for C as a complete object, one for +B as a subobject of a complete object of type C, and one for A as a +subobject of a complete object of type C.

    +

    In the cfront-like ABI, each of these virtual function tables is embodied in a +variable whose type is an array of entries of type

    +
    typedef void (*__vptp)();
    +struct __mptr {
    +  short d;
    +  short i;
    +  __vptp f;
    +};
    +
    +
    +

    d is the “delta” value to be added to the “this” pointer to adjust +it to point to the class in which the virtual function is defined; f +points to the virtual function. For a pure virtual function, the function +pointer points to the runtime routine __pure_virtual_called. In the +case of a deleted virtual function, a pointer to the runtime routine +__deleted_virtual_called is used for the function pointer.

    +

    Note that field i in the above is not used; it’s there for cfront +compatibility. cfront uses the same data structure for pointers to member +functions and virtual function table entries, even though a simpler structure +could have been used for virtual function tables.

    +

    In the IA-64 ABI, each of these virtual function tables is embodied in a +variable whose type is an array of entries of type ptrdiff_t, which is +used to encode function pointers, offsets, etc. There is no “delta” value. +Entries that require such an adjustment point to a thunk routine, which +adjusts the “this” pointer and then calls the proper routine. For a +pure virtual function, the function pointer points to the runtime routine +__cxa_pure_virtual; a deleted virtual function has its function pointer +initialized to the __cxa_deleted_virtual runtime routine.

    +

    Each entry defines one virtual function of the class. The routine entry for +the virtual function gives the virtual function number for the function, which +serves as the index into the virtual function table. In the cfront-like ABI, +the code generated uses entry [0] of the virtual function table to point to +the typeinfo for the class, and the first function is at entry [1]. In the +IA-64 ABI, the first function is at entry [0], but there are also negative +entries: [-1] points to the typeinfo for the class, [-2] gives the offset to +the beginning of the complete object , and [-3], [-4], etc., if needed, give +offsets to virtual base classes and offsets to be added to the “this” value +when calling virtual functions.

    +

    When an entity of a class type having virtual functions is initialized (by a +constructor), the virtual function table pointer in the class entity is set to +point to the virtual function table that is appropriate for that object (i.e., +the one that properly reflects whether the class entity is a complete object or +a subobject of some other class). Note that it’s the virtual function pointer +that is changed; the virtual function tables themselves are constant and are +not changed. They are not built up, on a per-routine basis or otherwise, for a +given entity. Rather, the proper complete table is chosen and a pointer to it +is put into the class entity. Many class entities can point to the same +virtual function table.

    +

    The variables for virtual function tables are externally visible (except for +classes with internal or no linkage), and they are shared between compilation +units to save space. For the sharing scheme to work correctly, exactly one +compilation unit must define the contents of each virtual function table. The +rest of the compilation units must put out the variable as an extern +declaration. What IL lowering does is to build every variable as an extern +declaration first, then change it to a definition (external or static) if the +virtual function table should be defined in the present compilation. The +heuristic used to decide whether or not a virtual function table definition +should be put out is the one described in ARM 10.8.1c: The virtual function +table for a class is put out if the compilation contains a definition for the +first non-inline virtual member function of the class. If the class contains +no non-inline virtual function, the virtual function table is defined as a +local static variable unless the --suppress_vtbl or --force_vtbl option +is specified on the command line. This same heuristic is used for the IA-64 +ABI [3], with the modification that virtual function tables that would be +put out as static are put out as COMDATs, so that the multiple copies can be +joined together by the linker.

    +

    To define a virtual function table, the variable is given a static initial +value that’s specified by a ck_aggregate constant. Each entry in the table +is defined appropriately. For a complete-object virtual function table, the +functions that go into the table are simply the virtual functions of the class +in the order of their virtual function numbers. For a virtual function table +for a subobject of class A in a complete object of class B, the member +functions of A are scanned looking for virtual functions, while at the same +time the override list for base class A of B is scanned. If a function +in A does not appear on the override list, the function from A goes +into the virtual function table. Otherwise, the function from the override +list goes into the virtual function table.

    +

    During the execution of constructors and destructors for base class subobjects, +virtual functions should act as if the complete object has the type of the +constructor or destructor class. That is, functions in classes further out +than the subobject class do not override during the subobject construction or +destruction. When virtual base classes are involved, this means that some +virtual function table instances need to be built to reflect three classes: a +class A (whose virtual function table this is) that is a subobject of a class B +(whose constructor is executing, and which therefore dictates overriding) that +is a subobject of a class C (which is the complete object type, and which +therefore dictates layout). This is necessary when there are virtual base +classes, and not otherwise, because the “delta” field in the virtual function +table is based on the offset between the objects for the classes of the +overridden and overriding functions, and that offset varies depending on the +type of the complete object.

    +

    In the IA-64 ABI, the normal (non-construction) virtual function table variable +for a class contains the primary virtual function table plus the virtual +function tables for the base classes of an object of that type, all +concatenated end-to-end in the single array. This is as required by the ABI +specification. For construction vtables, however, where the spec makes no such +requirement, each vtable is in a separate variable. In the cfront-like ABI, +every vtable is in a separate variable.

    +

    See

    +
      +
    • +
      make_vars_for_virtual_function_tables
      +
      +
    • +
    • +
      make_var_for_virtual_function_table
      +
      +
    • +
    • +
      define_one_virtual_function_table
      +
      +
    • +
    • +
      define_virtual_function_tables
      +
      +
    • +
    • +
      define_scope_virtual_function_tables
      +
      +
    • +
    • +
      add_vtbl_entry_init
      +
      +
    • +
    • +
      virtual_function_table_should_be_defined_here
      +
      +
    • +
    • +
      make_construction_vtbls
      +
      +
    • +
    +
    +
    +

    5.2.6. Covariant return types on virtual functions#

    +

    An overriding virtual function can return a pointer or reference to a +derived class where the overridden function returns a pointer or reference +to a base class. Such an overriding function is said to be covariant +with the overridden function. This requires special handling in IL +lowering because a call that appears (statically) to be to the overridden +function may in fact (dynamically) be a call to the overriding function, +and the value returned from the overriding function must undergo a +derived-to-base adjustment before it is returned to the caller. This is +implemented by adding wrapper functions: for each combination of an +overriding function and an overridden function, a wrapper is generated that +calls the overriding function, casts the returned value to the proper type, +and returns it. The virtual function table points to the wrapper function +from slots that need to call the overriding function but need the interface +of the overridden function.

    +

    This mechanism is also used more generally in the IA-64 ABI, for thunks +required for virtual function calls where a “this” adjustment is needed.

    +

    The IL representation for a wrapper function is a routine with

    +
      +
    • +
      overriding_function_for_wrapper and
      +
      +
    • +
    • +
      overridden_function_for_wrapper
      +
      +
    • +
    +

    set appropriately. In the case where a wrapper is being used for a covariant +return type adjustment, the wrapper body is simply a return of an +enk_result_of_overriding_function node cast to the proper +pointer-to-base-class. The enk_result_of_overriding_function node +represents the value returned from calling the overriding function with the +arguments passed to the wrapper.

    +

    This is controlled by the macro +ABI_CHANGES_FOR_COVARIANT_VIRTUAL_FUNC_RETURN.

    +

    While the IL representation is a wrapper function, the underlying +implementation need not be. In fact, for functions with variable-length +argument lists, a wrapper approach may not be feasible. Instead, a back end +can turn the wrapper routines into entry points of the overriding function, or +duplicate the body of the overriding function within each wrapper routine.

    +
    +
    +

    5.2.7. Namespaces#

    +

    The processing for namespaces is simply the promotion of the namespace members +out of the namespaces, with appropriate name mangling. See +do_namespace_member_promotion.

    +
    +
    +

    5.2.8. Routines#

    +

    The lowering for routines consists of making two kinds of implicit parameters +explicit:

    +
      +
    • +
      The implicit “this” parameter. This is present on nonstatic member +functions.
      +
      +
    • +
    • +
      The implicit parameter that provides the address into which a class value +should be returned, for functions returning a class by value. This +mechanism is not used for simple C-style structures, but is needed for more +complicated classes, because for those it must be possible to take the +address of a class value even if it is an rvalue, e.g., to cast to a base +class or call a member function. In this more complicated calling scheme, +the caller passes in the address of a temporary and the called routine +places the class value there on return.
      +
      +
    • +
    +

    Both the param_type_list in the routine type and the parameter variable +entries in the routine scope are updated to make the implicit parameters +explicit.

    +

    Parameters that are classes passed by value and requiring a copy constructor +require additional processing: Since classes that require a copy constructor +cannot be copied arbitrarily and cannot be moved, the caller actually does the +copy constructor call into a temporary and passes the address of the temporary +as the argument. The parameters on the receiving end must be changed to be +pointers to the class object, and all the references to the parameters must be +changed to add the extra indirection.

    +

    See lower_type and lower_scope.

    +
    +
    +

    5.2.9. Promotion of Local Entities to File Scope#

    +

    If the flag PROMOTE_LOCAL_ENTITIES_TO_FILE_SCOPE is TRUE, local static +variables and local types of functions will be promoted out of those functions +into the file scope under some conditions. Such promotion is enabled when the +IL will be fed into the C-generating back end, and may be desirable in other +cases where the output is textual and block-structured in some way.

    +

    The problem addressed by this transformation is shown by the following example:

    +
    void f() {
    +  static int i;
    +  class A {
    +    void g() {
    +      i = 1;       // Reference to variable local to function f
    +    }
    +  };
    +}
    +
    +
    +

    The body of A::g will become a free-standing function at file scope and yet +will have to reference the variable i of f. Therefore i must be +promoted out of f into the file scope so that it will be put out in the +file scope in the generated C code.

    +

    This is not a problem for an ordinary back end, as the reference to i will +be made in object code form or within the flat name space of an +assembly-language program.

    +

    See

    +
      +
    • +
      local_entities_should_be_promoted
      +
      +
    • +
    • +
      promote_local_entities_to_file_scope
      +
      +
    • +
    +
    +
    +

    5.2.10. Constructor Wrapper Code#

    +

    Constructors are modified to add the “wrapper” code that is required.

    +

    The constructor-initializer list indicates all the initializations that must be +done for base classes and members. It is in the language-defined order for +initialization: virtual base classes, then non-virtual base classes, then +members. Each base class or member that requires initialization will appear on +the list, with a front-end-generated default initialization if there is no +user-written one in the source.

    +

    The modifications made are:

    +
      +
    • +
      In the cfront-like ABI, if the class has virtual base classes, a parameter +is added for each such class. These parameters are used to pass in the +addresses of the virtual base classes when the constructor is called (from +another constructor) to initialize a subobject; when the constructor is +called to initialize a complete object, the parameters are passed as NULL. +In the IA-64 ABI, a single parameter is always added, for the VTT (virtual +table table) pointer passed in. Again, NULL is passed in to indicate a +complete object.
      +
      +
    • +
    • +
      In the cfront-like ABI, code is added to set any virtual base class +pointers in the class. The virtual base class pointers in the base classes +are set by the constructor calls for the base classes and therefore need +not be set by code at this level.
      +
      +
    • +
    • +
      Code is added to call a constructor for each virtual base class that +appears on the constructor-initializer list if a complete object is being +initialized.
      +
      +
    • +
    • +
      Code is added to call a constructor for each non-virtual base class that +appears on the constructor-initializer list.
      +
      +
    • +
    • +
      Code is added to initialize each member that appears on the +constructor-initializer list.
      +
      +
    • +
    • +
      If the class has any virtual functions, code is added to set the virtual +function table pointers in the current class and all of its base classes +that have virtual functions.
      +
      +
    • +
    • +
      If allocation can be folded into the constructor (a configuration +option, but always true if assignment to “this” is supported), the +entire routine is surrounded by code that tests the incoming “this” +parameter, and if it is NULL calls an appropriate new routine to +allocate space, which is then initialized. If the constructor actually +contains an assignment to “this”, the new code is not inserted and +the wrapper code above is inserted after each assignment to “this” +instead of at the beginning of the routine.
      +
      +
    • +
    +

    If the class has any virtual functions that are overridden in such a way that +there is a virtual base class step between the class of the overridden function +and the class of the overriding function, special virtual function instances +are required during construction of the class as a subobject. A constructor +for such a class, when called for a subobject, expects to receive an array of +virtual function table pointers from its caller (the constructor for the +derived class). It uses these virtual function table instances when setting +virtual function table pointers, and it passes parts of the array to its own +subobject constructors. In the cfront-like ABI, the pointer to the array is +passed (and received, in the subobject constructor) by setting the so-called +“transfer pointer” (a virtual function table or virtual base class pointer in +the class object that is unset at that point and can be borrowed for this +purpose). In the IA-64 ABI, the pointer to the array is passed in via the +added VTT pointer parameter.

    +

    In the IA-64 ABI, constructors have multiple entry points. The entry for a +complete object has a “C1” encoding in its mangled name, and has no added +parameters. The entry for a subobject has “C2”, and has an added VTT +pointer parameter if the class has virtual bases. The IL lowering +implementation puts the real code for the constructor in one function, which is +the subobject constructor if the class has virtual bases and the complete +object constructor otherwise. The other constructor is referred to as the +alternate entry point. When the class has virtual bases and +HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS is TRUE, the construction of +virtual bases is performed in the complete constructor before invoking the +subobject constructor; otherwise the alternate entry is simply an entry point +that calls the primary routine. Calls from an entry point to the primary +routine can be inlined if appropriate, or a back end can implement the entry +point functions as actual entry points to a single routine. See +alternate_entry_point.

    +

    See

    +
      +
    • +
      lower_constructor_code
      +
      +
    • +
    • +
      add_constructor_params
      +
      +
    • +
    • +
      add_constructor_wrapper_code
      +
      +
    • +
    • +
      lower_ctor_init
      +
      +
    • +
    +
    +
    +

    5.2.11. Destructor Wrapper Code#

    +

    Destructors are modified to add the “wrapper” code that is required.

    +

    The constructor-initializer list indicates all the destructions that must be +done for base classes and members. It is in the language-defined order for +destruction, i.e., the reverse of the initialization order. Each base class or +member that requires destruction will appear on the list, with a +front-end-generated destruction (there is no way to explicitly write one in the +source program).

    +

    The modifications made are:

    +
      +
    • +
      A parameter of type int is added. This parameter is used by the caller +as a bit mask: the 0x2 bit of the parameter set to 1 indicates a +complete object, and the 0x1 bit set to 1 indicates that the +storage for the object should be freed.
      +
      +
    • +
    • +
      If the class has any virtual functions, code is added to set the virtual +function table pointer in the class and in all of its base classes, so that +virtual function calls executed during the destruction will not call +functions in further-derived classes.
      +
      +
    • +
    +

    The above code is added at the beginning of the routine. The rest of the +wrapper code is added at the end of the routine. To make sure the code at the +end is reached, all returns in the routine body are rewritten as +gotos to the epilogue code.

    +
      +
    • +
      Code is added to destroy each member that appears on the +constructor-initializer list.
      +
      +
    • +
    • +
      Code is added to destroy each non-virtual base class that appears on the +constructor-initializer list.
      +
      +
    • +
    • +
      Code is added to destroy each virtual base class that appears on the +constructor-initializer list if a complete object is being destroyed.
      +
      +
    • +
    • +
      A delete routine is called to free the storage if the proper bit in +the implicit parameter is set. The entire routine is also enclosed in +an if statement so it will do nothing if the “this” parameter +passed in is NULL. If an assignment to “this” was actually done in the +routine, this delete is protected by a test to see if the “this” +parameter is (still) non-NULL.
      +
      +
    • +
    +

    See Constructor Wrapper Code regarding special virtual function tables used +during subobject construction. Similar processing is also needed in +destructor wrappers for subobject destruction.

    +

    In the IA-64 ABI, destructors have multiple entry points. The entry for a +complete object has a “D1” encoding in its mangled name, and has no added +parameters. The entry for a subobject has “D2”, and has an added VTT +pointer parameter if the class has virtual bases. The entry to destroy and +free storage for a complete object has “D0” and no added parameters. The +IL lowering implementation puts the real code for the destructor in one +function, which is the subobject destructor if the class has virtual bases and +the complete object destructor otherwise. The other destructors are known as +alternate entry points. When the class has virtual bases and +HANDLE_VIRTUAL_BASES_IN_COMPLETE_CTOR_DTORS is TRUE, the destruction of +virtual bases is performed in the complete destructor after invoking the +subobject destructor; otherwise alternate entry points simply call the primary +routine (for the deleting destructor, the entry point also contains the +deallocation code). Calls from an entry point to the primary routine can be +inlined if appropriate, or a back end can implement the entry point functions +as actual entry points to a single routine. See alternate_entry_point.

    +

    See

    +
      +
    • +
      lower_destructor_code
      +
      +
    • +
    • +
      add_destructor_params
      +
      +
    • +
    • +
      lower_dtor_init
      +
      +
    • +
    • +
      lower_destructor_dynamic_init
      +
      +
    • +
    +
    +
    +

    5.2.12. Calls#

    +

    See lower_call.

    +

    Calls of constructors and destructors are altered to add the implicit +parameters described in the previous sections. Except for constructor and +destructor calls in wrapper code, constructor and destructor calls are for +complete objects.

    +

    See make_ctor_implied_arg_list and make_dtor_implied_arg_list.

    +

    Calls of “vacuous” destructors, as in

    +
    p->int::~int();
    +
    +
    +

    are changed from eok_vacuous_destructor_call or +eok_points_to_vacuous_destructor_call operations to a cast to void.

    +

    Virtual function calls are rewritten from

    +
    object->func(args ...)
    +
    +
    +

    to (cfront-like ABI)

    +
    ((vtbl_temp = (object->__vptr)+index),
    +  (object+vtbl_temp->d)->(vtbl_temp->f)(args ...))
    +
    +
    +

    (Omitting some casting for clarity.) In other words, vtbl_temp is +assigned the address of the proper virtual function table entry, the +“this” pointer is adjusted by the “delta” value in the entry, and the +function indicated in the entry is called. If object is not a reusable +expression, the first occurrence of object above is replaced by +(object_temp = object), and the second by object_temp.

    +

    For the IA-64 ABI, the code is

    +
    (object->__vptr[index])(object, additional_args ...)
    +
    +
    +

    (recall that any required “this” adjustment is handled by thunk +routines and therefore is not needed at the call site).

    +

    See lower_virtual_function_call.

    +

    A related case (though not a call) is lowering of eok_virtual_function_ptr, +the operator that implements the anachronism of casting a bound member function +pointer to a normal function pointer. It rewrites

    +
    (func-type *)(object->func)
    +
    +
    +

    to (cfront-like ABI)

    +
    (func-type *)((object->__vptr)+index)->f)
    +
    +
    +

    or (IA-64 ABI)

    +
    (func-type *)*(object->__vptr)+index
    +
    +
    +

    See lower_virtual_function_ptr.

    +
    +
    +

    5.2.13. Return Value Optimization#

    +

    Return value optimization applies to functions that return a value via a copy +constructor. It can be done when all return statements in the function +return the same nonstatic local variable. The optimization is to rewrite all +references to the local variable to refer instead to the return-value address +passed in by the caller, thus avoiding a copy constructor call on exit. For +example:

    +
    struct A {
    +  A(int);
    +  A(const A&);
    +};
    +A f() {
    +  A a(1);       // Constructed into temp passed by caller
    +  return a;     // No copy needed
    +}
    +
    +
    +

    The front end proper detects the possibility of doing the optimization, but the +transformation is done by IL lowering. There are several parts to the +optimization:

    +
      +
    • +
      References to the address of the local variable are rewritten as references +to the (pointer) value of the return-value address parameter.
      +
      +
    • +
    • +
      The local variable is marked as unreferenced, and any initialization on it +is turned into initialization of the object pointed to by the return-value +address parameter.
      +
      +
    • +
    • +
      Return statements are transformed into simple returns doing no copy +constructor call and returning no value.
      +
      +
    • +
    +
    +
    +

    5.2.14. Expression Temporaries#

    +

    enk_temp_init nodes are used to introduce class temporaries in the middle +of expressions. They indicate the initialization to be done on the temporary +and any destruction to be done once the temporary is no longer needed. The +temporary is implicit in the high-level IL; IL lowering allocates a variable +for the temporary and uses it in place of references to the enk_temp_init +node.

    +

    The initialization and destruction are indicated by a dynamic initialization +entry, which is rewritten in the usual way. See lower_expr_full.

    +

    One special problem: When class temporaries created under a conditional +operator (”?”, “&&”, or “||”) require destruction, the destruction +must be done only if the initialization was done. For each case like this, it +is necessary to create a temporary, initialize it to zero at the start of the +block containing the expression, set it to one if the initialization is done, +and test it on exit from the block to determine whether or not to do the +destruction. See add_dyn_init_cleanup, init_conditional_flag_var, +set_conditional_flag_var, add_conditional_flag_test.

    +
    +
    +

    5.2.15. New and Delete#

    +

    new and delete are represented as an enk_new_delete expression +node.

    +

    There are three main new cases (see lower_new):

    +
      +
    • +
      A simple new is translated to a call of the appropriate new +routine. If the allocated object must be initialized, the pointer returned +from the allocation is tested to ensure that it is non-NULL, and then the +initialization is done.
      +
      +
    • +
    • +
      A simple class new is often translated to a constructor call, passing a +NULL pointer as an indication that the constructor should do the +allocation. (This is enabled by NEW_CAN_BE_FOLDED_INTO_CTOR. When +that is FALSE, the new routine is called, and if the allocation succeeds +the constructor is called.)
      +
      +
    • +
    • +
      An array new is translated into a call of a runtime routine; see below.
      +
      +
    • +
    +

    There are three main delete cases (see lower_delete):

    +
      +
    • +
      A simple delete is translated into a call of the appropriate delete +routine. If the allocated object must be destroyed, the destructor is +called before the deallocation routine.
      +
      +
    • +
    • +
      A simple class delete is usually translated into a destructor call, +passing a flag indicating that the destructor should do the deallocation.
      +
      +
    • +
    • +
      An array delete is translated into a call of a runtime routine; see +below.
      +
      +
    • +
    +

    Calls of new and delete that allocate or free arrays of classes that +have constructors or destructors are specially handled. They are converted to +calls of:

    +
    +
    +
    cfront-like ABI:
    +
    +
    +
    +
    __vec_new(array, num_elems, elem_size, ctor_routine)
    +
    __vec_delete(array, num_elems, elem_size, dtor_routine, +free, 0)
    +
    +
    +
    +
    IA-64 ABI:
    +
    +
    +
    +
    __cxa_vec_new(num_elems, elem_size, padding, +ctor_routine, dtor_routine)
    +
    __cxa_vec_delete(array, elem_size, padding, +dtor_routine)
    +
    +
    +
    +

    where

    +
    + + + + + + + + + + + + + + + + + + + + + +
    +
    array
    +
    +
    +
    is the address of the first element of the array. For +__vec_new, it may be NULL to indicate that the space for the +array should be allocated. For __vec_delete, it may be NULL +to indicate that the routine should do nothing.
    +
    +
    +
    num_elems
    +
    +
    +
    is the number of elements in the array. For +__vec_delete, it may be -1 to indicate that the number of +elements given in the corresponding __vec_new should be used.
    +
    +
    +
    elem_size
    +
    +
    +
    is the size in bytes of each array element.
    +
    +
    +
    ctor_routine or dtor_routine
    +
    +
    +
    is the address of the constructor or destructor routine to call, or +NULL if no routine should be called.
    +
    +
    +
    free
    +
    +
    +
    is non-zero to indicate that the storage for the array should +be freed.
    +
    +
    +
    padding
    +
    +
    +
    is the size of the array prefix in which the number of elements is +recorded by the runtime.
    +
    +
    +
    +

    The final argument of the __vec_delete call is not used; it is present for +compatibility with cfront.

    +

    These routines are necessary in order to save the number of elements in the +array from the time of the new (where it is known) to the time of the +delete (where it is not available), and also to call the constructors and +destructors for all the array elements.

    +

    For the cfront-like ABI, when exception handling is enabled, and only for +classes that have destructors, __vec_new_eh is called instead of +__vec_new. It has an additional final parameter that is a pointer to the +destructor. This is used to destroy any constructed elements if an exception +is thrown while __vec_new_eh is initializing the array elements.

    +

    For the cfront-like ABI, when value-initialization is to be done for a class +that has a generated constructor, __vec_new_eh_zero is called. It has the +same parameter list as __vec_new_eh, but it zeroes the storage before +calling the constructor.

    +

    With array new and delete, it is possible to define class-specific

    +
      +
    • +
      operator new[] and
      +
      +
    • +
    • +
      operator delete[]
      +
      +
    • +
    +

    functions. When those are specified, different runtime routines are called:

    +
    +
    +
    cfront-like ABI:
    +
    +
    +
    +
    __array_new(num_elems, elem_size, ctor_routine,
    +
                +dtor_routine, new_routine, delete_routine, is_two_arg)
    +
    __array_delete(entity_node, num_elems, elem_size, dtor_routine,
    +
                  +delete_routine, is_two_arg)
    +
    +
    +
    +
    IA-64 ABI:
    +
    +
    +
    +
    __cxa_vec_new2(num_elems, elem_size, padding, ctor_routine,
    +
                  +dtor_routine, new_routine, delete_routine)
    +
    __cxa_vec_new3(num_elems, elem_size, padding, ctor_routine,
    +
                  +dtor_routine, new_routine, delete_routine)
    +
    __cxa_vec_delete(array, elem_size, padding, dtor_routine)
    +
    +
    +
    +

    Most of the parameters are as described above. The others are:

    +
    + + + + + + + + + + + + +
    +
    new_routine
    +
    +
    +
    is the address of the special operator new[] +routine, or NULL if the default routine should be used.
    +
    +
    +
    delete_routine
    +
    +
    +
    is the address of the special operator delete[] +routine, or NULL if the default routine should be used. Also NULL on +__array_new if exceptions are disabled.
    +
    +
    +
    is_two_arg
    +
    +
    +
    is 1 to indicate that the delete_routine takes +two arguments, 0 otherwise.
    +
    +
    +
    +

    These routines are used only if ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE is +TRUE. For the cfront-like ABI, if value-initialization is to be done, +__array_new_zero is called in place of __array_new. The IA-64 ABI +“new3” routine is used for the two-argument delete case.

    +

    For the cfront-like ABI, when ABI_CHANGES_FOR_PLACEMENT_DELETE is TRUE, it +is possible to do a placement new of an array type and later deallocate the +storage via the delete operator. For that case, a special runtime routine +is called to ensure that the array size is recorded:

    +
    +
    +
    __placement_array_new(entity_node, num_elems, size_elem, +ctor_routine, dtor_routine)
    +
    +
    +

    and the value of the global runtime variable __array_new_prefix_size is +added to the size of the allocation requested in the placement new to allocate +extra space to contain the array prefix. See +make_placement_array_new_call. If value-initialization is to be done, +__placement_array_new_zero is called in place of __placement_array_new.

    +

    See lower_array_new and lower_array_delete.

    +
    +
    +

    5.2.16. Constructors and Destructors for Arrays#

    +

    Construction or destruction of an entire (static or automatic) array is done by +calling runtime routines. For the cfront-like ABI, __vec_new or +__vec_delete are used (see previous section). The address of the array is +passed into __vec_new, thus suppressing allocation, and 0 for the flag +free is passed into __vec_delete, thus suppressing freeing of the +storage. For the IA-64 ABI, there are specific runtime routines for these +functions:

    +
    +
    +
    __cxa_vec_ctor(array, num_elems, elem_size, ctor_routine, +dtor_routine)
    +
    __cxa_vec_dtor(array, num_elems, elem_size, dtor_routine)
    +
    +
    +

    Copying of an entire array using a copy constructor is done in the cfront-like +ABI by calling __vec_cctor, passing the array address, the number of +elements, the element size, the address of the routine to call, and the source +array address. [4] In the IA-64 ABI, the runtime routine is +__cxa_vec_cctor.

    +

    If the constructor involved has default arguments, a wrapper routine is created +that requires no arguments other than the “this” parameter and calls the +constructor with the proper default arguments. The wrapper routine is then +passed to the runtime routine, which can call it like a normal constructor.

    +

    See

    +
      +
    • +
      add_array_constructor_call
      +
      +
    • +
    • +
      add_destructor_call
      +
      +
    • +
    • +
      default_version_of_routine
      +
      +
    • +
    • +
      make_vec_delete_call
      +
      +
    • +
    +
    +
    +

    5.2.17. Pointers to Members#

    +

    Pointer-to-member types (tk_ptr_to_member) are transformed as follows:

    +
      +
    • +
      Pointers to data members are converted to values of an integral type. The +integer contains a byte offset to the data member in the class. In the +cfront-like ABI, one is added to leave the zero value free to indicate a +NULL pointer to data member. In the IA-64 ABI, nothing is added, and -1 is +used for a NULL pointer to data member.
      +
      +
      struct A { int i; int j;};
      +int A::*pdm = &A::j;       // unsigned int pdm = 5(cfront) 4(IA-64)
      +int A::*pdmn = 0;          // unsigned int pdmn = 0(cfront) -1(IA-64)
      +
      +
      +
    • +
    • +
      Pointers to member functions are represented by structures with the form
      +
      +
        +
      • +
        cfront-like ABI:
        +
        +
      • +
      +
      typedef void (*__vptp)();
      +struct __mptr { short d; short i; __vptp f; };
      +
      +
      +
      +
      This is essentially the structure described in 8.1.2.c of the ARM. +d is the offset to be added to the “this” pointer; i is the +index into the virtual function table (or -1 for a nonvirtual function, +or 0 for a NULL pointer); f is the nonvirtual function pointer when +i is -1 or the offset to the virtual function table pointer +(appropriately cast) when i is greater than zero.
      +
      +
      struct A {int f(); virtual int g();};
      +int (A::*pmf)() = &A::f;       // struct __mptr pmf = {0, -1, &f__1AFv};
      +int (A::*pmg)() = &A::g;       // struct __mptr pmg = {0,  1, 0};
      +
      +
      +
        +
      • +
        IA-64 ABI:
        +
        +
      • +
      +
      typedef void (*__vptp)();
      +struct __mptr { __vptp f; ptrdiff_t d; };
      +
      +
      +
      +
      f is zero for a NULL pointer, is a pointer to a function for the +non-virtual case, and is the vtable offset in bytes plus one for the +virtual function case. d is the offset to be added to the “this” +pointer. When IA64_ABI_USE_VARIANT_PTR_TO_MEMBER_FUNCTION_REPR is +TRUE, an alternate representation is used that works on architectures where +the low-order bit of a function address can be non-zero. In that +representation, f is zero for a NULL pointer (but you also have to +check that the low-order bit of d is zero), is a pointer to a function +for the non-virtual case, and is the vtable offset in bytes for the virtual +function case. d is the offset to be added to the “this” pointer, +shifted left one bit, and its low-order bit is one for the virtual function +case.
      +
      +
    • +
    +

    See lower_type.

    +

    Pointer-to-member constants (ck_ptr_to_member) are transformed to the above +forms. See lower_ptr_to_member_constant. The function case generates a +ck_aggregate constant. Such constants can only be used when the constant +appears as an initializer value; for other kinds of references (e.g., in an +assignment statement), the reference to the constant is changed to a reference +to a temporary variable that is initialized with the aggregate constant.

    +

    Assignment and comparison of pointers to data members are changed to integer +assignment and comparison operators. Assignment of pointers to member +functions is changed to structure assignment. Comparison of pointers to member +functions is changed to

    +
    +
    +
    cfront-like ABI:
    +
    +
    +
    (op1.i == op2.i) && (op1.i == 0 || (op1.d == op2.d && op1.f == op2.f))
    +
    +
    +
    +

    IA-64 ABI:

    +
    +
    (op1.f == op2.f) && (op1.f == 0 || op1.d == op2.d)
    +
    +
    +
    +

    IA-64 ABI alternate representation:

    +
    +
    (op1.f == op2.f) && ((op1.f == 0 && (((op1.d | op2.d) & 1) == 0))
    +                   || op1.d == op2.d)
    +
    +
    +
    +
    +

    (That is the code for ==; the code for != is similar.) If one of the +operands is a constant, the comparisons are done directly against the constant +values of the components of the constant, and unnecessary parts of the +expression above are omitted. A comparison against a null pointer to member +constant, for example, becomes simply

    +
    (op1.i == 0)
    +
    +
    +

    for the cfront-like ABI.

    +

    Casting a pointer to a data member to a base or derived class is changed to

    +
    +
    +
    cfront-like ABI:
    +
    +
    (pdm != 0) ? (pdm + offset) : 0
    +
    +
    +

    IA-64 ABI:

    +
    (pdm != -1) ? (pdm + offset) : -1
    +
    +
    +
    +

    Casting a pointer to a member function to a base or derived class is changed to

    +
    +
    +
    cfront-like ABI:
    +
    +
    (temp = pmf, (temp.i != 0) ? (temp.d += offset) : 0, temp)
    +
    +
    +

    IA-64 ABI:

    +
    (temp = pmf, (temp.f != 0) ? (temp.d += offset) : 0, temp)
    +
    +
    +

    IA-64 ABI alternate representation:

    +
    (temp = pmf, (temp.f != 0 || temp.d != 0)
    +                           ? (temp.d += offset) : 0, temp)
    +
    +
    +
    +

    The tricky issue in both cases is preserving a NULL pointer to member.

    +

    See lower_pm_related_class_cast.

    +

    Casts from one pointer-to-member-function type to another (not related) are +removed since both types will now have the same representation and since the +cast, left in, would be a cast to a structure type. Similar casts between +pointers to data members are casts from an integral type to the same integral +type and are left alone.

    +

    The eok_pm_points_to_field andeok_pm_field operators, which implement +the ->* and .* operators for pointers to data members, are rewritten:

    +
    p->*pdm
    +
    +
    +

    is lowered to

    +
    (member-type *)(((char *)p)+(pdm-1))
    +
    +
    +

    The IA-64 ABI version does not need the -1.

    +

    See lower_pm_field.

    +

    The eok_pm_call operator, which implements calls of functions identified by +a pointer to member, is rewritten:

    +
    object->pmf(args ...)
    +
    +
    +

    is lowered to (cfront-like ABI)

    +
    ((this_temp = (object_type *)((char *)object + pmf.d)),
    +                        // Adjust "this" pointer by delta from
    +                        //   pointer-to-member.
    + (func_temp = (function_type *)
    +                        // The computed function address gets cast to the
    +                        //   proper function type.
    +    ((pmf.i < 0) ?      // Check virtual/non-virtual pointer-to-member.
    +      pmf.f :           // Function address for non-virtual case.
    +                        // Virtual function case:
    +      ((vtbl_temp =     // Virtual function table entry address is address
    +                        //   of virtual function table + offset in table.
    +         *(__vtbl_entry **)((char *)this_temp +
    +                            (short)(pmf.f)) +
    +                        // Pointer to virtual function table is at offset
    +                        //   pmf.f in the object.
    +         pmf.i),        // + offset into table
    +       this_temp = (object_type *)
    +                     ((char *)this_temp + vtbl_temp->d),
    +                        // Adjust "this" pointer to get pointer to subobject
    +                        //   expected by the virtual function.
    +       vtbl_temp->f))), // Address of virtual function.
    + func_temp(             // Call using the function pointer computed.
    +                        // Arguments for the call:
    +   this_temp,           //   "this" pointer.
    +   args ...))           //   Additional arguments, if any.
    +
    +
    +

    If pmf is not a reusable expression, the first occurrence of pmf above +is replaced by (pmf_temp = pmf), and the rest by pmf_temp.

    +

    If the class and its base classes have no virtual functions, and the variable +pointer_to_member_call_optimization_allowed is TRUE (which does not conform +to the C++ standard), the following simpler version is used:

    +
    ((this_temp = (object_type *)((char *)object + pmf.d)),
    + eok_call((function_type *)pmf.f,
    +           this_temp,
    +           additional_args ...))
    +
    +
    +

    This seems slightly more complicated than is needed, but it makes sure that if +a reusable copy of pmf is needed, the temp for it is initialized before the +call is begun.

    +

    For the IA-64 ABI, the code is:

    +
    ((this_temp = (object_type *)((char *)object + pmf.d)),
    +                        // Adjust "this" pointer by delta
    +                        //   from pointer-to-member.
    + (func_temp = (function_type *)
    +                        // The computed function address gets cast to the
    +                        //   proper function type.
    +   ((pmf.f & 1) == 0) ? // Check virtual/non-virtual pointer-to-member.
    +      pmf.f :           // Function address for non-virtual case.
    +                        // Virtual function case:
    +      ((vtbl_temp =     // Virtual function table entry address is address
    +                        //   of virtual function table + offset in table.
    +         *(__vtbl_entry **)
    +           ((char *)this_temp +
    +                        // Pointer to virtual function table is at offset
    +                        //   zero in the object
    +            ((ptrdiff_t)pmf.f - 1)),
    +                        // + offset into table, dropping low-order bit.
    +       *vtbl_temp))),   // Address of virtual function.
    + func_temp(             // Call using the function pointer computed.
    +                        // Arguments for the call:
    +   this_temp,
    +           //   "this" pointer.
    +   additional_args ...)) //   Additional arguments, if any.
    +
    +
    +

    See lower_pm_call.

    +
    +
    +

    5.2.18. Operations Returning Lvalues#

    +

    Operations that return lvalues in C++ but not in C, i.e., assignment operators, +prefix ++ and --, and “?” and “,” operators, are rewritten in C +form. Often this involves duplication of expressions. This rewriting +operation is enabled or disabled by LOWER_LVALUE_RETURNING_OPERATIONS.

    +

    Lvalue-returning assignments are rewritten from

    +
    (c1 = c2)
    +
    +
    +

    to

    +
    ((c1 = c2), rcc2)
    +
    +
    +

    where rcc2 is a reusable copy of c2 (see +make_lvalue_reusable_copy). The comma operator is an lvalue-returning +operator, which is then further rewritten (see following).

    +

    Lvalue-returning “?” operators are rewritten from

    +
    ((g1 ? g2 : g3) = c2)
    +
    +
    +

    to

    +
    (g1 ? (g2 = c2) : (g3 = c2))
    +
    +
    +

    Lvalue-returning “,” operators are rewritten from

    +
    ((g1 , g2) = c2)
    +
    +
    +

    to

    +
    (g1 , (g2 = c2))
    +
    +
    +

    For both the “?” and the “,” cases, the operations in the rewritten +form are lvalue operations iff the “=” operation in the original is an +lvalue operation. The operation indicated as “=” can in fact be any +operation (e.g., simple or complex assignment, prefix ++ or --, field +selection). c2 isn’t present for unary operations.

    +
    + +
    +

    5.2.20. bool#

    +

    In modern C++, there is a bool type, and operations like “!=” return +bool instead of int. (C99 has a _Bool type, but the boolean +operation – like “!=” and “>” – produce int values.) The IL +representation of a boolean type is identical to an ordinary small integer +type, except that the variant field variant.integer.bool_type is TRUE. +That representation is therefore not lowered: A back end can just ignore the +bool_type field and treat a boolean type as the underlying integer type.

    +

    Several bool operations are rewritten by IL lowering:

    +
      +
    • +
      eok_bool_cast, which represents a cast to bool (or _Bool), is +rewritten as a “!= 0” test of the appropriate type. See +lower_bool_cast.
      +
      +
    • +
    • +
      An increment of a bool lvalue is rewritten to set the lvalue to 1 +(true). In the postincrement case, this involves saving the original +value, setting the lvalue to 1, and then returning the saved original +value. See lower_bool_increment.
      +
      +
    • +
    • +
      The return types of operations that yield a bool in C++ but an int +in C, e.g., “!=” and “&&”, are rewritten to yield an int. In +contexts where the result is tested directly, the type is simply changed; +where something else is done with the result (e.g., storing it in a +variable), a cast to the proper type is inserted. See +adjust_bool_operation_types.
      +
      +
    • +
    • +
      Compound assignment operators whose left-hand operand has type bool (or +_Bool) are rewritten to ensure that the result value is restricted to +0/1. See rewrite_compound_assignment.
      +
      +
    • +
    +
    +
    +

    5.2.21. Condition Declarations#

    +

    In if, while, for, and switch statements, the expression tested +can be a condition declaration. For example:

    +
    if (float x = f()) { ... }
    +
    +
    +

    This is represented in the IL as an expression node of kind enk_condition.

    +

    Loops and non-loops are handled somewhat differently by IL lowering. Non-loops +(if, switch) are rewritten as follows:

    +
    if (A x = y) { ... }
    +
    +
    +

    is transformed into

    +
    {  A x = y;  if (x) { ... }}
    +
    +
    +

    The test in the if actually uses the expression from the expr field of +the condition, which is the value of the declared variable converted to a +testable type if necessary.

    +

    Loops (while, for) are rewritten as follows:

    +
    for (w; A x = y; z) { ... }
    +
    +
    +

    or

    +
    while (A x = y) { ... }
    +
    +
    +

    is transformed into

    +
    {                                    {
    +   for (w;;) {                          while (1) {
    +     A x = y;                             A x = y;
    +     if (!x) {                            if (!x) {
    +       destroy x if necessary;              destroy x if necessary;
    +       goto break_label;                    goto break_label;
    +     }                                    }
    +     { ... } // Original statement        { ... } // Original statement
    +     z;      // Increment code
    +     destroy x if necessary;              destroy x if necessary;
    +  }                                    }
    +  break_label:;                        break_label:;
    +}                                   }
    +
    +
    +

    Again, the x in !x is the value of the declared variable converted to a +testable type if necessary. If the break_label exists already, it and the +block around the for/while are not added.

    +

    See lower_condition.

    +
    +
    +

    5.2.22. Anonymous Unions#

    +

    In the unlowered IL, field selections of fields of anonymous unions that are +embedded in classes elide the field selection(s) for the anonymous union(s). +For example:

    +
    class A {
    +  union {
    +    int i;
    +    float j;
    +  };
    +} x;
    +
    +
    +

    x.i appears as a selection of i directly out of x. IL lowering +adds the implied field selection through the unnamed union.

    +

    See adjust_field_selection_for_anonymous_union_references.

    +
    +
    +

    5.2.23. Automatic Template Instantiation#

    +

    When automatic template instantiation is enabled and +instantiation_flags_in_template_info_file is FALSE (an old mode not longer +much used), IL lowering helps the cause by getting certain information about +instantiations passed into the object file. The instantiation information is +recorded in the flags

    +
      +
    • +
      can_be_instantiated,
      +
      +
    • +
    • +
      do_not_instantiate, and
      +
      +
    • +
    • +
      instance_required
      +
      +
    • +
    +

    that appear in variable and routine entries.

    +

    IL lowering passes the values of these flags into the object code by generating +tentative definitions of global-scope variables that have names formed by +combining a prefix with the mangled name for the entity for which the flag is +being generated. The prefixes are

    +
      +
    • +
      __CBI__ for the can_be_instantiated flag,
      +
      +
    • +
    • +
      __DNI__ for the do_not_instantiate flag, and
      +
      +
    • +
    • +
      __TIR__ for the instance_required flag.
      +
      +
    • +
    +

    The routine make_instantiation_info_var is used to create these variables.

    +

    For template classes with virtual functions, where the decision on whether or +not to output a definition of the virtual function table is based on the +presence of a definition for the first non-inline virtual function of the +class, a reference to the virtual function table causes a __TIR__ for the +first virtual function to be generated (that requests a definition of the +function, and therefore of the virtual function table, somewhere in the +program). When a virtual function definition is generated, it references all +the virtual functions of the class, so __TIR__ variables are generated for +them (except for the first virtual function, to avoid the chicken-and-egg +problem of the first virtual function and the virtual function table each +forcing the other to be instantiated, with neither actually referenced from +anywhere).

    +

    The prelinker phase notices these names in the object files, and from them can +recover the associated instantiation information.

    +
    +
    +

    5.2.24. Guard Code on Variable Template and Template Static Data Member Initializations#

    +

    When TEMPLATE_STATIC_DATA_MEMBER_INIT_GUARD_CODE (in targ_def.h) is +TRUE, “guard” code is placed around initializations of instances of variable +templates and static data members of templates. Such guard code is necessary +if template instantiation resolution is done by instantiating everything and +then having the (specially-modified) linker discard duplicate copies of +instantiated routines. Dynamically-initialized template variables and static +data members of templates are a particular problem: because the initialization +code is generated in startup routines, and is undifferentiated from other code +in those routines, a flag is needed to indicate that initialization has already +been done. After any one instance of the code does initialization, all other +instances will do nothing.

    +

    The initialization guard code looks like (cfront-like ABI):

    +
    int guard_var;  // Implicitly initialized to 0
    +{
    +  if (guard_var == 0) {
    +    guard_var = 1;       // Initialization of static data member
    +  }
    +}
    +
    +
    +

    For the IA-64 ABI, the code sequence is the one generated by +add_first_time_test, which has either calls of __cxa_guard_acquire et +al. or is like the above but with the setting of the guard variable after the +initialization.

    +

    If the template variable or static data member is a specialization, its +initialization should take precedence over any other (non-specialization) +initializations. For that case, the guard variable is put out as a definition +with an initial value of -1. That disables the construction guard code for +all other instances.

    +

    Destruction is not a problem, since all destructions of static entities are put +on a list to be done at the end of program execution. The entry is only put on +the list exactly once when and if the initialization is done.

    +
    +
    +

    5.2.25. Runtime Type Information#

    +

    Runtime type information is needed for exception processing and for the RTTI +features of the C++ language. IL lowering generates special typeinfo +variables for each type that requires such information.

    +

    In the cfront-like ABI, note that the runtime typeinfo is not the same type +as the programmer-visible type_info; the runtime typeinfo contains a +type_info structure as a member, and has other information besides. The +typeinfo variables have mangled names of the form

    +
    +
    +
    __T_mangled-type-encoding
    +
    +
    +

    (except static typeinfo variables for non-class types, which are unnamed).

    +

    The variables are typeinfo structures (this is still for the cfront-like +ABI):

    +
    struct typeinfo {
    +  type_info       tinfo;      // User-visible type_info structure
    +  const char      *name;      // Null-terminated string for name
    +  char            *id;        // Id object pointer
    +  base_class_spec *bc;        // Array of base class information
    +};
    +
    +
    +

    Each pointer field is NULL if it is not applicable. In versions preceding +2.38, there was an additional field after id which contained a destructor +pointer. It was eliminated when the__throw_setup_dtor runtime routine +was added. In versions preceding 2.41, the name field was not const (it +was made const when const string literals were implemented).

    +

    In the IA-64 ABI, the type_info type visible to the user is the same as the +implementation type, and it has a number of derived classes that provide +additional information for pointer types, class types, etc. as described in +the ABI spec. typeinfo variables have mangled names beginning with +“_ZTI”.

    +

    If the type represented by a typeinfo variable is a polymorphic class, the +typeinfo variable is external if and only if the virtual function table +variable for the class is external, and the typeinfo variable is defined +(i.e., initialized) if and only if the virtual function table is defined. For +other cases (non-polymorphic classes and non-classes), the typeinfo +variable is always static and always defined.

    +

    In the IA-64 ABI, the typeinfo variable is made a COMDAT so that there will be +only one copy in the linked program even when the virtual function table +heuristic does not place the definition in a single file. Likewise, the name +string for a typeinfo variable is placed in a separate variable with a +predictable mangled name (beginning with “_ZTS”), which is made a COMDAT so +that all instances of the name are shared.

    +

    In the cfront-like ABI, when the typeinfo variable is static, and the +type is not an internally-linked class, it is possible that the same type +is represented by several typeinfo variables. [5] In those cases, +the object id pointer is used to indicate that those typeinfo entries +all correspond to the same type: the object id pointer is non-NULL and +points to an id object variable of type char whose name has the form

    +
    +

    __TID_mangled-type-encoding

    +
    +

    This variable is put out as a tentative definition and therefore there will be +only one copy of a given id object variable in the executable program. Two +typeinfo variables are considered to represent the same type if their id +object pointers are non-NULL and equal to one another.

    +

    In the cfront-like ABI, for classes that have base classes, the base class +array field points to a (static) variable initialized to an array of entries +with the following structure:

    +
    struct base_class_spec {
    +  typeinfo         *tinfo;  // typeinfo for base class
    +  short            offset;  // Offset of base class in derived class
    +  unsigned char flags;      // Flags
    +};
    +
    +
    +

    Only direct, virtual, and ambiguous base classes of the derived class +appear in the base class list. The flags byte contains a bit set: +0x01 indicates a virtual base class, 0x02 is set to mark the +last entry in the array, 0x04 indicates a public base class, 0x08 +indicates an ambiguous base class, and 0x10 indicates a direct base +class.

    +

    When ABI_CHANGES_FOR_RTTI is FALSE, an older form of the typeinfo entry +is generated, which is adequate for exception handling but not for RTTI. The +differences are as follows:

    +
      +
    • +
      The type_info and name fields are not present.
      +
      +
    • +
    • +
      typeinfo variables for nonclass types are put out as tentative +definitions and rely on default initialization to zero. Because of the +name mangling and the fact that the variable is external, there will be +only one copy of the typeinfo variable for any given nonclass type in +the executable program. No id object variable is needed.
      +
      +
    • +
    • +
      The public base class and ambiguous bits in the base class specification +are not set.
      +
      +
    • +
    +
    +

    5.2.25.1. The typeid operator#

    +

    The C++ typeid operator is represented by an expression node with kind +enk_typeid.

    +

    If the typeid node has a null expression pointer, the type is known +statically. IL lowering generates a typeinfo entry for the static type, +and replaces the typeid node with a field selection that computes the +address of the tinfo member of the typeinfo variable.

    +

    If the typeid node has a non-null expression pointer, the type (a +polymorphic class) must be determined at runtime.

    +

    In the cfront-like ABI, IL lowering replaces the typeid node with a runtime +routine call

    +
    __get_typeid((typeid_expr != NULL) ? vptr : NULL)
    +
    +
    +

    where typeid_expr is the typeid expression (or more precisely the +address indicated by that expression) and vptr is an expression for the +value of the virtual function table pointer for the class object pointed to. +If typeid_expr is not reusable, it will be assigned to a temporary and the +temporary will be used in the vptr expression. Note that when +typeid_expr is null, a null pointer is passed to __get_typeid; the +latter then throws bad_typeid.

    +

    In the IA-64 ABI, the code sequence is entirely inline:

    +
    (typeid_expr != NULL) ? (typeinfo*)(vptr[-1]) :
    +                        (__cxa_bad_typeid(), NULL)
    +
    +
    +
    +
    +

    5.2.25.2. The dynamic_cast operator#

    +

    A dynamic_cast is represented by an expression node with operator +eok_dynamic_cast. IL lowering rewrites that into

    +
    +

    cfront-like ABI:

    +
    +
    (src != NULL) ? __dynamic_cast    (src, vptr, desired_type, orig_src,
    +                                    static_type) :
    +                NULL
    +
    +
    +

    or

    +
    (src != NULL) ? __dynamic_cast_ref(src, vptr, desired_type, orig_src,
    +                                   static_type) :
    +                NULL
    +
    +
    +
    +

    IA-64 ABI:

    +
    +
    (src != NULL) ? __dynamic_cast    (src, static_type, desired_type, hint) :
    +                NULL
    +
    +
    +

    or

    +
    (temp =         __dynamic_cast     (src, static_type, desired_type, hint))
    +                     ? temp : __cxa_bad_cast()
    +
    +
    +
    +
    +

    The second form in each ABI is for a cast to a reference type. src is the +expression being cast (or its address, in the reference case); vptr is the +virtual function pointer for the class (note that it’s protected by the +null-pointer check); desired_type is a pointer to the typeinfo for the +desired class, or NULL for a dynamic cast to “void *”; orig_src is the +original source pointer in the dynamic cast (the value passed as the first +parameter may have been cast to a base class if the original class has no +virtual function pointer); and static_type points to the typeinfo for +the underlying class of the source pointer’s static type.

    +

    In the IA-64 ABI, a dynamic_cast to void * is done as inline code, by +extracting the offset-to-base from the [-2] entry in the virtual function table +and adding that to the object address.

    +

    Note that dynamic_casts that do not require runtime processing are +translated by the front end into simple casts or base class casts.

    +
    +
    +
    +

    5.2.26. Exceptions#

    +

    The lowering of exception handling (EH) features can be configured three +different ways:

    +
      +
    1. Full lowering: all exception handling features are reduced to C, and +no support for EH features is required in the back end. This solution +is easy to use and highly portable, but entails a fairly significant +overhead in execution cost (15-20%). This mode is required for the +C-generating back end, and is supported by the minimal runtime +provided by EDG. It is enabled by the configuration switch +DO_FULL_PORTABLE_EH_LOWERING.

    2. +
    3. Partial lowering: the data tables of the portable scheme are generated, +but they use stack offsets for variables (in the portable scheme, all +addresses are computed at runtime and stored in an object address table). +try, catch, and throw are preserved in the IL. Much of the +minimal runtime provided by EDG would still be applicable, but some +parts would require changes. This mode is enabled by the configuration +switch GENERATE_EH_TABLES.

    4. +
    5. No lowering: No data tables are generated; the object lifetime +information is preserved for use in generating tables in a back end. +try, catch, and throw are preserved in the IL. The back +end makes all decisions about the way in which EH features are +implemented. This mode is enabled by having both GENERATE_EH_TABLES +and DO_FULL_PORTABLE_EH_LOWERING set to FALSE.

    6. +
    +

    It should be noted that in all three schemes the statements and expressions +attached under EH constructs are lowered. Even in the partial/no lowering +schemes, lowering generates the code needed for things like copying thrown and +caught objects. Special expression nodes that represent (partially) lowered +exception handling constructs, of kind enk_lowered_eh_construct, are used +to represent the parts of those operations that remain for the back end to +define.

    +

    The portable implementation is the one that involves the most transformations +in IL lowering, and the other two schemes are essentially scaled-back versions +of the full-lowering scheme. Therefore, the description that follows covers +the processing for the full-lowering scheme and indicates differences in the +other schemes.

    +

    Exception handling imposes a nontrivial overhead in time and/or space on +programs, including those that do not make use of exceptions. Accordingly, +exception handling can be enabled or disabled by a command-line option, and +when it is disabled IL lowering will not generate the code or data structures +to support it.

    +

    The fully- and partially-lowered implementations do work with the IA-64 ABI, +but they are not compatible with the ABI spec. For a fully-comforming IA-64 +ABI implementation, it is necessary to do the EH implementation in the back +end.

    +
    +

    5.2.26.1. Maintaining Context#

    +

    When an exception is thrown, the stack is unwound to the catch point, and +destructible objects created in the stack frames removed from the stack must be +destroyed by the runtime. In order to be able to do that, the runtime must +have access to information about the stack frames and the destructible objects +therein. This information is provided by entries linked into an exception +handling stack. There are three kinds of stack entries:

    +
      +
    • +
      Entries representing a function. These are pushed on entry to a function +and popped on exit from that function, and they point to information about +the destructible objects in the function. No stack frame is needed for any +function that has no destructible objects and no try blocks.
      +
      +
    • +
    • +
      Entries for exception specifications of a function. These are pushed at +the beginning of each function having an exception-specification (i.e., a +list of the exception types that the function is permitted to throw), and +popped at the end of each such function. The stack frame points to an +array that describes the types that may be thrown.
      +
      +
    • +
    • +
      Entries for try blocks. These are pushed at the beginning of each +try block and popped on exit from each such block. The stack frame +provides space for a setjmp buffer, and a pointer to an array that +describes the types caught at each associated catch handler clause.
      +
      +
    • +
    +

    The code to push and pop stack frames is generated by

    +
      +
    • +
      push_eh_stack_frame and
      +
      +
    • +
    • +
      pop_eh_stack_frame.
      +
      +
    • +
    +

    The function and exception-specification stack frames are requested by +add_eh_function_prologue (which also handles epilogue code).

    +

    The function stack frame points to several data structures that describe the +destructible objects:

    +
      +
    • +
      The region table, which has entries that describe objects and the cleanup +to be done for them. See make_region_table_entry. The table is an +array, and an index into that array is called a cleanup region number. +Each entry contains a cleanup region number for a “next” entry in the +table, which makes it possible to link entries into lists of cleanup +actions. At any given point in a function, one can describe the sequence +of cleanup actions required on termination of that routine by indicating a +cleanup region number, i.e., the index number of the first entry of a +linked list of region table entries that enumerates the destructions and +deallocations to be done, in the order they are to be done. IL lowering +generates code to maintain the global variable __eh_curr_region +appropriately to indicate the set of cleanup actions necessary at each +point in each function. See assign_to_eh_curr_region.
      +
      +
    • +
    • +
      The array table, which provides additional information about destructible +objects that are arrays (for example, the array element size). See +make_array_table_entry.
      +
      +
    • +
    • +
      The object address table, which provides the addresses of destructible +objects. The region table identifies objects by indicating their index +numbers in the object address table. This extra level of indirection is +necessary to separate the static parts of the region table, which can be +used for all activations of a function, from the changeable part, which is +different for each activation. (When a function calls itself recursively, +for example, the exception stack entries for the various activations will +point to distinct copies of the object address table but to a common static +copy of the region table.) See object_addr_table_index.
      +
      +
    • +
    +

    The exception-specification stack frame indicates the types that may be thrown +by pointing to an array whose elements are exception type specifications. An +exception type specification is a structure defined as follows:

    +
    struct exception_type_specification {
    +  typeinfo      *tinfo;
    +  unsigned char flags;
    +  unsigned char *ptr_flags;
    +};
    +
    +
    +

    The tinfo pointer points to a typeinfo variable for a type. The +flags value is a bit set that indicates modifications of that type, e.g., +pointer-to the type. One of the bits is used to indicate the last entry in the +array. The ptr_flags field (added in version 2.41) is non-null for +multi-level pointer types. It points to an array of flags values, each one +describing the cv-qualifiers at one level of a multi-level pointer type. +Again, one of the bits is used to indicate the last entry in the array.

    +

    The try-block stack frame contains space for a setjmp buffer, and a pointer +to an array in which each entry represents a catch handler. The entries in the +array are exception type specification structures, each one describing the type +to be caught by the associated handler.

    +

    Note that local and global static variables are never handled in normal +exception cleanup. The required destructions for all static entities that have +been constructed are placed on a runtime list, and therefore the cleanup for +those entities need not and should not be described in the region tables.

    +

    In the partial-lowering scheme, the region table and array table are generated, +but the object address table is not used. Instead, the addresses of variables +in the region table and array table are given as stack offsets using +ck_stack_offset constants. Since there is no object address table, the +code that computes addresses and places them in the object address table is +unnecessary. No exception stack is maintained; instead, expression nodes with +subkinds leck_function_prologue and leck_function_epilogue are inserted +at the appropriate places to indicate to the back end that appropriate +maintenance should be done at those points, and to identify the variables for +the region table and array table. It is assumed that the back end will also +deal with the exception-specification, if any, for the function. In place of +assignments to __eh_curr_region, expression nodes with subkind +leck_cleanup_state are used to communicate the new region table entry +number to the back end at each place that changes it. typeinfo information +is still put out for all types involved in exception handling operations, but +there will be no references to those entries in the lowered code. They are +pointed to from the type entries, available for use by a back end.

    +

    In the no-lowering scheme, none of the tables are generated (including the +typeinfo entries). As in the partial-lowering scheme,

    +
      +
    • +
      leck_function_prologue,
      +
      +
    • +
    • +
      leck_function_epilogue, and
      +
      +
    • +
    • +
      leck_cleanup_state
      +
      +
    • +
    +

    nodes will be inserted. The latter have a pointer to a dynamic initialization +entry, rather than a region number, as the indication of the cleanup state to +be established at that point.

    +

    When INDICATE_CLEANUP_STATE_IN_UNREACHABLE_CODE is TRUE, cleanup state +instructions will be emitted even at the unreachable ends of blocks. This may +be desirable if the back end is using the cleanup state information to build a +table of cleanup address ranges rather than leaving them as some kind of +executable code. The instructions generated will have the special kind +leck_unreachable_cleanup_state.

    +
    +
    +

    5.2.26.2. Throwing an Exception#

    +

    The enk_throw expression node is rewritten either as

    +
    __rethrow();
    +
    +
    +

    for the rethrow case (throw with no operand), or as

    +
    ((temp = __throw_setup(&typeinfo, size, flags)),
    +         (initialization, __throw()))
    +
    +
    +

    for the normal case. typeinfo is the runtime type information variable for +the base type being thrown, size is the size in bytes of the object being +thrown, and flags is a bit set that indicates the relationship of the type +thrown to the typeinfo type – for example, that the type being thrown is a +pointer to the type indicated by the typeinfo variable. The +__throw_setup call allocates space for a copy of the thrown object; the +initialization code makes a copy of the thrown object in that allocated space; +and the __throw call actually does the throw (and does not return). If the +thrown object requires destruction, __throw_setup_dtor is called instead of +__throw_setup (this routine was added in version 2.38). +__throw_setup_dtor has an additional final parameter, which is the +destructor pointer. If the thrown object is a multi-level pointer, +__throw_setup_ptr is called instead of __throw_setup (this routine was +added in version 2.41). __throw_setup_ptr has a parameter in place of the +flags parameter, which is a pointer to an array of flag bytes that indicate the +cv-qualifiers at each level of the multi-level pointer type. In cases where +the thrown object is copied to the allocated space using a copy constructor, +and the copy is implicit, __exception_started is called before the copy +constructor call to tell the runtime to consider the copy constructor call as +“inside” the throw.

    +

    In front end versions preceding 2.29, and when ABI_CHANGES_FOR_RTTI is +FALSE, a runtime routine __throw_alloc is called instead of +__throw_setup. It has one additional argument: if the typeinfo +type is a class with base classes, the argument is a character string +containing the letter “Y” or “N” for each base class to indicate +whether the base class is accessible. Otherwise, it is a NULL pointer.

    +

    In the partial-lowering and no-lowering schemes, the enk_throw node is +preserved. The dynamic initialization that copies the thrown object is +lowered, using a node with subkind

    +
      +
    • +
      leck_thrown_object_address
      +
      +
    • +
    +

    to indicate the address in the runtime to which the thrown object should be +copied. A node with subkind leck_exception_started is used to mark the +point before a copy constructor call.

    +

    See lower_throw.

    +
    +
    +

    5.2.26.3. Catching an Exception#

    +

    The routine lower_try_block lowers the stmk_try_block statement to +generate code for a try and its associated catch clauses. The code +does roughly the following:

    +
      +
    • +
      Push a try-block entry on the exception stack. This entry points to an +array whose elements describe the types to be caught by each catch +handler. The index of an entry in the array is the number assigned to +identify the associated catch handler.
      +
      +
    • +
    • +
      Do a setjmp in an “if” surrounding the dependent statement of the +try. This records the address to be jumped back to in the event that +one of the catch handlers is to be executed. When the call to setjmp +returns (the first time), the try block is executed.
      +
      +
    • +
    • +
      For each catch handler, test the global variable +__catch_clause_number (which is set by the runtime before the transfer +back to this code) to see if it matches the number of the catch clause. If +so, copy the value of the caught object (whose address the runtime provides +in __caught_object_address) to the handler parameter (see +begin_catch_clause). Call __exception_caught to indicate to the +runtime that the exception is fully caught. Execute the dependent +statement of the catch, and, on exit, call __free_thrown_object +(see cleanup_on_exit_from_catch).
      +
      +
    • +
    • +
      At the end of the try block, whether reached from the try or from a +catch handler, pop the try-block entry off the exception stack.
      +
      +
    • +
    +

    Note three aspects of using setjmp to implement try:

    +
      +
    1. The size of the setjmp buffer must be configured to match the target +environment. See

      +
        +
      • +
        TARG_JMP_BUF_NUM_ELEMENTS,
        +
        +
      • +
      • +
        TARG_J _BUF_ELEMENT_INT_KIND.
        +
        +
      • +
      • +
        TARG_JMP_BUF_ELEMENTS_ARE_FLOAT, and
        +
        +
      • +
      • +
        TARG_JMP_BUF_ELEMENT_FLOAT_KIND
        +
        +
      • +
      +

      in targ_def.h.

      +
    2. +
    3. The setjmp is represented as a runtime routine call. This may +necessitate some sleight of hand from a back end if setjmp is not really +a runtime routine.

    4. +
    5. Some optimization may have to be suppressed for the region of the try +block. In C, on return from a setjmp only volatile variables are +guaranteed to be set correctly. The code generated by IL lowering, however, +assumes that all variables are set correctly, which means that variables +cannot be kept in registers over calls in any code in which exceptions might +be thrown. The contains_try_block flag in the routine entry is a +partial solution. See also the modified_within_try_block flag.

    6. +
    +

    In the partial-lowering and no-lowering schemes, the stmk_try_block +statement is preserved, with things under it lowered. The initializations of +catch parameters are lowered, with a node with subkind +leck_caught_object_address used to represent the address in the runtime +from which the caught object should be copied. (Note that the implicit +indirection inserted for reference parameters in the full-lowering approach is +not inserted in these modes; a back end can check the handler parameter type +and generate such an indirection if one is necessary.) A node of subkind +leck_exception_caught is used to indicate the point (after the +initialization, if any) where the exception is considered fully caught. On +exit from a try or catch (by flowing off the end or by goto or +return), a node of subkind leck_try_epilogue or leck_catch_epilogue +is inserted.

    +
    +
    +

    5.2.26.4. Unordered Evaluation#

    +

    The C and C++ language rules do not fully define the order of evaluation of +parts of expressions. For example, in “A(1) + A(2)” the evaluation of +A(1) could occur before or after the evaluation of A(2). When +destructible temporaries appear in such contexts, the order of construction and +destruction of the temporaries cannot be predicted from the language rules +alone, e.g., the temporary for A(1) could be constructed before or after +the temporary for A(2). Such temporaries are called “unordered” +temporaries, and the dynamic initialization entries for them are marked as +such. These temporaries cause a problem for a portable implementation, because +is it necessary when indicating the cleanup to be done at the point of +construction of A(1) or A(2) to indicate that the other temporary might +or might not already have been constructed. This is done by adding a +conditional flag for each temporary, which indicates whether or not the +construction has been done, and having the cleanup position in the cleanup +region table include destructions for both temporaries. The runtime then tests +the conditional flags to indicate whether the destructions should actually be +done. This method, of course, involves a time and space overhead, so the flag +DO_UNORDERED_EH_PROCESSING can be set to FALSE to switch it off. It can be +switched off if the back end will do the constructions in the canonical order +indicated by the IL, or if the next_in_destruction_list linkage of the +initializations is changed before IL lowering to match the order that will +actually be used by the back end, or if the back end will use some different +technique to accomplish the same result. Note that when using the C-generating +back end, the order in which temporaries are constructed depends on the C +compiler that will be used, so if one has detailed information about the order +in which it will evaluate expressions, one may be able to switch off this +processing. The unordered processing is turned off in the no-lowering scheme.

    +
    +
    +

    5.2.26.5. Placement Delete#

    +

    When a placement new is done, and there exists a corresponding +operatordelete function (one with the same parameter types as the +operatornew, ignoring the first parameter), if an exception is thrown +before the initialization associated with the new completes, the +operatordelete is called to deallocate the storage. This is +implemented by wrapping the code that performs the initialization inside an +internal try block. If an exception is thrown while executing the try +expression, the associated catch expression, a call of the delete routine, +is executed. In the fully-lowered scheme, this internal try block is +expanded into the same code sequence used for a statement-level try (but as +part of an expression). In the partial-lowering and no-lowering schemes, the +internal try is indicated by an expression node with subkind +leck_internal_try. See make_internal_try_expr.

    +
    +
    +
    +

    5.2.27. Lowering extern inline#

    +

    When LOWER_EXTERN_INLINE is TRUE, extern inline functions are processed +specially. In the cfront-like ABI, they are lowered to normal static inline +functions; this mainly involves just a change of the storage class in the +routine entry. In the IA-64 ABI, they are left external but put into a COMDAT +so that multiple copies are folded into one by the linker.

    +

    The code generated in LOWER_EXTERN_INLINE mode in the cfront-like ABI does +not quite conform to the standard, because it does not ensure that when the +address of an extern inline function is taken the address is the same +across different compilation units. Setting INSTANTIATE_EXTERN_INLINE to +TRUE (instead of setting LOWER_EXTERN_INLINE) provides standard-conforming +behavior: extern inline functions are treated like template instances, and +the template prelinker assigns the “instantiation” of the function to a single +file, thus ensuring that if its address is taken it is the same everywhere.

    +

    Two transformations that apply to all extern inline functions, whether +LOWER_EXTERN_INLINE is specified or not:

    +
      +
    • +
      For functions that have local static variables, the static variables are +promoted out of the function and made external (and given mangled names), +so that all copies of the function will refer to a common set of static +variables. If the static variables are initialized, the initialization +guard variables are also made external, with mangled names that begin with +__LSG__ (cfront-like ABI) or _ZGV (IA-64 ABI).
      +
      +
    • +
    • +
      If ASSIGN_STRING_LITERAL_SEQUENCE_NUMBERS is TRUE, similar processing +is done for string literals: they are moved into external variables with +mangled names so that every copy of the extern inline function gets the +same address for the same string literal. This is off by default in the +cfront-like ABI, even though it should be TRUE for full conformance to the +C++ standard, because it’s expensive way out of proportion to its benefit. +Not being able to count on a COMDAT-like mechanism, the cfront-like ABI +must put out the variables for the string literals as tentative definitions +(therefore uninitialized), and initialize them at each point of use. It’s +not at all pretty, especially in small inline functions, and it’s a feature +that hardly anyone ever counts on.
      +
      +
    • +
    +
    +
    +

    5.2.28. Inlining#

    +

    As an option, IL lowering can do inlining of function calls. That is, when it +encounters a call of a function declared inline, it can replace the call +with IL corresponding to the body of the function with the parameters replaced +by the corresponding arguments. When a function call occurs as a statement, +the statements of the function body are inserted in place of the call. When +the function call occurs within an expression, the body of the function is +rewritten as one large expression and that expression is inserted in the proper +place in the containing expression. It is not always possible to do this sort +of inlining: there are certain constructs (e.g., loops) that cannot be rendered +in expression form. Even when the inlining is done at the statement level, +there are certain constructs that are not practical to inline. Calls that +cannot be inlined are left in their original call form, and an out-of-line copy +of the function is used. A remark is issued.

    +

    Inlining of this style has some serious limitations. Aside from the +impossibility of inlining certain function bodies, there is also the problem +that inlining at this level is done without knowledge of the target +architecture, and therefore without the ability to know whether the inlined +version of a call is preferable to the original version. The inlined version +might be ridiculously large, or might be worse in some other way. Inlined +calls produce extremely convoluted expressions, which stress back ends and C +compilers.

    +

    In short, if you want inlining (and you do, for C++), you probably want to do +it some other way. The version EDG supplies is provided as a convenience for +those who use the C-generating back end and whose C compilers do not handle +inlining. It’s intended to give roughly the same functionality as cfront, and +EDG does not plan to enhance it in any substantial way.

    +

    The code to perform inlining is contained in inline.c, with the associated +declarations in inline.h. Inlining of function calls is enabled by the +configuration switch MINIMAL_INLINING. The default is to inline only when +using the C-generating back end.

    +

    Inlining is done on code that has already been lowered, which is to say on C +code. When the end of the lowering of a function’s body is reached, +set_up_routine_for_inlining is called to determine whether the routine can +be inlined. If so, the inlinable flag in the routine entry is set. Note +that this means that a routine call cannot be inlined until the full definition +of the function has been seen and lowered. Also note that lowering is not done +if any errors are detected, so inlining is always done using correct code. A +function is disqualified for inlining immediately if any of the following are +true:

    +
      +
    • +
      The function has local static variables.
      +
      +
    • +
    • +
      The function has local constants.
      +
      +
    • +
    • +
      The function has local types.
      +
      +
    • +
    • +
      The function has block scopes.
      +
      +
    • +
    • +
      The function includes pragmas.
      +
      +
    • +
    • +
      The function has an ellipsis in its parameter list.
      +
      +
    • +
    +

    A function that passes these tests is eligible to be inlined. When a call is +seen, do_inlining_of_call is invoked to do the expansion. The expansion is +done in three steps:

    +
      +
    1. set_up_variable_remapping_for_inlining makes temporary variables +for the parameters and local variables of the function, and generates +assignment code to initialize each parameter temporary with the +corresponding argument expression. If the argument is constant-valued +and the parameter is not modified in the function, no temporary is +needed; the constant will be used directly.

    2. +
    3. expand_statement_inline does the expansion of the function body. +It makes a copy of the statements and expressions of the function, +replacing references to the parameters and local variables with the +appropriate temporaries or constants. If the function call being +inlined appears at the statement level, the copy is made in statement +form. Otherwise, the function body is translated into expression +form as the copy is made. Expression statements are copied as +expressions; a sequence of statements is formed via comma operations; +and if statements are rendered as “?” operations. Loops cannot +be translated to expression form, and therefore can be inlined only in +the statement mode. gotos and labels generally preclude inlining +in both modes, but the special case of a goto to a label +immediately following it is allowed and eliminated. returns +are allowed only at the end of the function at the top level (or as +the last statement in a block that is the last statement in a block +… that is the last statement of the top-level block of the function). +Dynamic initialization of local variables is translated to +assignments, but aggregate initialization precludes inlining.

    4. +
    5. finish_variable_remapping_for_inlining adds the created temporaries +to the calling context scope, and then the statement sequence or +expression tree is inserted into the IL tree, replacing the original +call.

    6. +
    +

    Since the inlining operation is an attempt to inline the function, one that may +fail, the statement sequence or expression tree for the inlined call is built +off to the side, and attached to the IL tree only once the inlining operation +is completed successfully. Likewise, the temporaries created for parameters +and local variables are not entered into the scope of the call until the end of +the operation. If an inlining operation fails, the original call is left in +place and the routine is marked as requiring an out-of-line copy. (An +out-of-line copy is also required if the address of the routine was taken.) If +inlining of a call fails because of something that precludes all inlining of +the function, the inlinable flag of the routine is cleared so no further +attempts will be made. If the inlining operation failed only because of the +context (e.g., the function includes a loop and the call is inside an +expression), the inlinable flag is left TRUE.

    +

    As the function body is copied with substitution for the parameters and local +variables, new constant expressions may be created. That is, when a constant +argument is passed for an unmodified parameter, the references to the parameter +in the function body are replaced by the proper constant value. That may +produce operations whose operands are constant (e.g., p + 1 becomes 1 + +1, which can be simplified to 2).

    +

    This substitution and folding is done by +adjust_copied_expression_for_inlining, which is called from +copy_expr_tree as each node in the tree is copied. The list of remappings +to be done is built by set_up_variable_remapping_for_inlining and pointed +to by the static variable variable_remappings_for_inlining. +get_var_remapping_for_inlining consults the list to find the applicable +remapping for a variable.

    +

    More dramatic simplification is possible for short-circuiting operators like +“?” and for if statements (whether they are rewritten in expression +form or not). If the tested expression is constant, parts of the expression +tree or statement tree are discarded accordingly. For example, when parameter +p is replaced by 1,

    +
    p ? i : (j + 1)
    +
    +
    +

    becomes simply i, and

    +
    if (p > 0) i = 1; else i = 2;
    +
    +
    +

    becomes simply i = 1. This is handled by +copy_and_simplify_short_circuited_operation for the operator cases, and in +expand_statement_inline for the if statement.

    +

    Arguments can be considered to be constant even if they are not literally +constants. For example, the address of a local variable is not a compile-time +constant, but it is constant over the duration of a call, and therefore can be +considered constant-valued for purposes of parameter remapping.

    +

    The this parameter of constructors is given special treatment so that the +allocation sequence at the beginning of constructors will be eliminated when +the constructor is operating on a known variable. According to the normal +parameter rules, this in a constructor is modified within the function and +therefore a temporary must be used. However, we know how constructors work, +and if there is no assignment to this in the constructor we know the only +modification is one that will be eliminated when the constructor is called with +a non-null argument for this. In such cases, the this parameter is +remapped directly to a constant, and the allocation sequence is eliminated by +the normal short-circuit optimization.

    +
    +
    +

    5.2.29. Lowering thread_local#

    +

    The thread_local keyword was added in C++11 and the dynamic initialization +and destruction of objects with thread_local storage requires lowering +support.

    +

    If the back end has the capability to execute code at thread creation time, +then it is most efficient to set the configuration macro +USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES to FALSE in which +case lowering creates one or more initialization routines (depending on the +setting of SEPARATE_ROUTINES_FOR_FILE_SCOPE_DYNAMIC_INITS) for each +dynamically-initialized variable with thread_local storage in the +translation unit and sets il_header.thread_local_dynamic_init_routines to +point to the list (in the proper order). It is the responsibility of the back +end to ensure that this list of routines is invoked at thread creation time.

    +

    In most cases, however, the compiler won’t have the capability to execute code +at thread creation time, in which case +USE_LAZY_INITIALIZATION_FOR_THREAD_LOCAL_VARIABLES should be set to +TRUE. In such configurations, each use of an object with thread_local +storage duration that may be dynamically initialized is re-written to invoke +the “wrapper” routine for the object (see lower_thread_local_variable). +Lowering creates a “wrapper” routine (see +thread_local_wrapper_for_variable) that invokes an “initialization” routine +(if one exists) and then returns a pointer to the thread_local object. +This ensures that each thread_local object is properly initialized (though +at considerable run-time cost). Mangled names for wrapper routines contain the +mangled name of the thread_local object along with a prefix ( _ZTW in +the IA-64 ABI and __TWR__ in the Cfront ABI).

    +

    Note that although “wrapper” routines are only required for dynamically +initialized thread_local variables, the lack of “wrapper” routines for +thread_local variables with external linkage that are not dynamically +initialized results in a non-compliant implementation (i.e., the standard +requires that all thread_local variables be initialized before the first +odr-use of any thread_local variable, but the use of a statically +initialized thread_local circumvented the initialization process). As a +result, the all_thread_locals_have_wrappers global variable was introduced +in 4.10, and when set to TRUE, results in standard compliant behavior. The +previous behavior matches g++’s behavior and is achieved by setting +all_thread_locals_have_wrappers to FALSE.

    +

    The “initialization” routines that wrappers call perform the actual +initialization for the thread_local objects (and incorporate a +thread_local guard variable to ensure the initialization is performed only +once per thread). When the back end supports weak references, +LAZY_INITIALIZATION_USES_WEAK_REFERENCES should be set to TRUE, in +which case each “initialization” routine is aliased to the __tls_init +routine that initializes that particular thread_local object. In cases +where a thread_local object is used in one translation unit and defined in +another, a reference to an initialization routine is created in the first +translation unit but there may or may not be a definition for the +initialization routine in the second routine (it will be aliased to the +__tls_init routine in that translation unit only if the thread_local +object is dynamically initialized). When weak references are used wrapper +routines need to allow for the case where an initialization routine is +NULL. For back ends that do not support weak references, a do-nothing +initialization routine is created for this case (see +make_null_thread_local_init_routine_for_variable). Mangled names for +initialization routines contain the mangled name of the thread_local object +along with a prefix (_ZTH in the IA-64 ABI and __THI__ in the Cfront +ABI).

    +

    The __tls_init routines themselves (or __tls_init_N in +one-instantiation-per-object mode) are created during the lowering of +file-scope dynamic initializations (see Dynamic Initialization).

    +

    In a manner similar to the handling of destructions of static entities, +destructions of file-scope objects with thread_local duration are +registered with the run-time library through calls to __cxa_thread_atexit +(for the IA-64 ABI) or __record_needed_thread_destruction (for the Cfront +ABI). The run-time library is then responsible for invoking these destructors +when the thread terminates (see record_needed_destruction).

    +
    +
    +

    5.2.30. Lowering ifunc#

    +

    The GNU ifunc attribute maps to the STT_GNU_IFUNC symbol type in the +ELF standard and is not available on many architectures. The STT_GNU_IFUNC +symbol type allows a routine’s symbol to be determined dynamically at load +time. At load time, the routine specified as the resolver (in the ifunc +attribute) is invoked (once) and returns a pointer to the routine that will be +used to resolve all instances of that symbol for that execution of the +executable. This provides a very low overhead mechanism to select one of a +family of functions (typically based on the underlying CPU architecture). +Here’s an example (with --gcc --gnu_version 40600):

    +
    int printf(const char *,...);
    +void target() {
    +  printf("Here\n");
    +}
    +static void (*resolver(void))(void) {
    +  return (void(*)(void))&target;
    +}
    +void source() __attribute__ ((ifunc ("resolver")));
    +int main() {
    +  source();   // Prints "Here"
    +}
    +
    +
    +

    For back ends that don’t support the STT_GNU_IFUNC symbol, an approximation +of the run-time behavior can be achieved by setting LOWER_IFUNC to +TRUE. In that case, lowering will convert the routine with the ifunc +attribute into a “wrapper” routine as such:

    +
    decltype(source) resolver_result = source;
    +source(args...) {
    +  if (resolver_result == source) {
    +    resolver_result = (decltype(source))resolver();
    +  }
    +  return *resolver_result(args...);
    +}
    +
    +
    +

    This has the effect of invoking the resolver only once (though at run time +rather than at load time). Invocations of source incur an extra function +call and indirection, but lowering re-writes references to source so they +are dispatched through the resolver variable whenever possible (in which case +the only overhead is an extra indirection).

    +

    Note that there are a few caveats:

    +
      +
    • +
      The re-writing of calls to avoid the wrapper routine only occurs once the +declaration with the ifunc attribute has been seen; any reference prior +to that point will be unlowered (and will hence invoke the wrapper). That +can be an issue if, for example, the declaration with the ifunc +attribute is only in a library’s implementation (and not in the shared +header file). In that case, code that is compiled with the shared header +file will contain references to the wrapper routine.
      +
      +
    • +
    • +
      Constants (i.e., ck_address/abk_routine) that refer to the +ifunc are not re-written in lowering, so they’ll always point to the +wrapper routine.
      +
      +
    • +
    +

    See lower_ifunc_routine and lower_ifunc_expr for more information.

    +
    +
    +

    5.2.31. Lowering GNU function multiversioning#

    +

    GNU supports function multiversioning in version 4.8.0 and later via the +target attribute in C++ mode. Detailed documentation is available here: +http://gcc.gnu.org/wiki/FunctionMultiVersioning. The target attribute +allows multiple versions of a function definition to be supplied, and the +choice of which version to call is determined at load time based on +characteristics of the machine where the program is running. The choice is +made by a compiler-generated (when lowering is enabled) “resolver” routine that +selects the best routine from the target-specific versions. The resolver +routine is executed once at load time (because it is associated with an +ifunc routine) to determine which target-specific routine to use for the +particular CPU. For back ends that don’t support ifunc, see +LOWER_IFUNC.

    +

    For example (assuming USE_X86_FUNCTION_MULTIVERSIONING is TRUE, with--gnu_version 40800):

    +
    __attribute__ ((target("default")))     int foo () { return 222; }
    +__attribute__ ((target("arch=corei7"))) int foo () { return 777; }
    +__attribute__ ((target("avx")))         int foo () { return 333; }
    +int main () {
    +  int (*fp)() = foo;
    +  return fp() != foo();
    +}
    +
    +
    +

    Would generate lowered pseudo-code like this:

    +
    int foo_default () { return 222; }  // "default" foo
    +int foo_corei7 () { return 777; }   // "corei7" foo
    +int foo_avx () { return 333; }      // "avx" foo
    +// Resolver function returns address of specific function
    +static (int *foo.resolver()) { // lowering-generated resolver function
    +  resolved_foo = // one of foo_default, foo_corei7, foo_avx
    +  return resolved_foo;
    +}
    +int foo.ifunc() __attribute__((ifunc("foo.resolver"));
    +int main () {
    +  int (*fp)() = foo.ifunc;    // &foo lowered to &foo.ifunc
    +                              // Dynamic loader invokes foo.resolver
    +                              // to select which specific foo.
    +                              // foo.ifunc is invoked once during
    +                              // startup.
    +  return fp() != foo.ifunc(); // call of foo is lowered to foo.ifunc
    +}
    +
    +
    +

    Note that at present, lowering is only performed when +USE_X86_FUNCTION_MULTIVERSIONING is TRUE (the rules that are used to determine +at run-time which of a set of target-specific functions are machine-specific +and only the x86 case is implemented).

    +

    See lower_mv_routine, lowered_mv_routine, and create_mv_resolver.

    +
    +
    +
    +

    5.3. How is IL Lowering Done?#

    +
    +

    5.3.1. Sequencing#

    +

    All the individual transformations done by IL lowering are relatively +straightforward. What makes the job of IL lowering so difficult is the fact +that it must operate under some very difficult sequencing constraints.

    +

    They come about because IL lowering must be done on a per-function basis, so +that individual memory regions can be lowered and then written to a file. That +means that when function scope memory regions are lowered, the file scope +entities that they reference are not yet lowered. And they cannot be: since +the file-scope entities are still active entities in the compilation, if they +were modified by IL lowering it would disturb the rest of the compilation.

    +

    To pick an example: to lower a virtual function call in a function scope, one +needs to be able to reference the virtual function pointer field in the class +entity. That field is added by IL lowering. But the class type is in the file +scope memory region, and therefore has not yet been lowered at the time the +virtual function call is lowered.

    +

    Another example: IL lowering changes reference types into pointer types. +However, mangled names of functions must be based on the original types, +including reference types. Therefore, mangled names must be generated before +reference types are changed to pointer types.

    +

    Another example: the variable that contains a virtual function table must be +available when constructors and destructors for classes are lowered. However, +it is not possible to know at that point in the compilation whether or not the +definition of the virtual function table should be put out. In fact, it’s not +possible to tell whether it should be internal or external. Therefore, virtual +function table variable definitions cannot be done at the time the variable +declarations are done.

    +

    In short, lots of processing that would be fairly straightforward if the entire +IL tree could be lowered at once becomes convoluted because some parts of the +tree have already been lowered, some haven’t, some cannot be yet, etc.

    +

    One technique that helps is the concept of “prelowering” classes. This is +processing that’s done as soon as possible on completed class definitions. It +does not modify the class, but it adds information that is needed to use the +class in lowering code:

    +
      +
    • +
      The type-as-subobject (a copy of the type with any virtual base classes +removed).
      +
      +
    • +
    • +
      The fields that make the base classes, virtual base class pointers, and +virtual function table pointer of the class explicit. (Note that this +change affects the field list of the type, which would seem to be a +modification; however, since the fields are not in the symbol table, they +cannot be found by the front end. It does mean that front end code should +not traverse the field list to visit all the fields. It should use the +symbol list instead.)
      +
      +
    • +
    • +
      Variables for virtual function tables. These are all created as extern +declarations, and they are changed to definitions or to static variables +later if that is appropriate.
      +
      +
    • +
    +

    See prelower_class_type.

    +

    Another technique is to not clear C++-specific fields when they are +lowered, where that’s possible. One example: the implicit “this” +parameter type in a routine type entry becomes an explicit first parameter +type when lowered. However, the pointer to the implicit type is not +cleared. That allows code that wants to see whether or not a function is a +nonstatic member function to fetch the “this” parameter type without having +to know whether or not the type has already been lowered. One consequence +of this technique is that back ends cannot count on having the C++-specific +fields cleared, and should therefore not look at them.

    +
    +
    +

    5.3.2. The IL Lowering Flag#

    +

    The IL lowering flag is a two-state flag that appears in the prefix that +precedes each IL entry. It is flipped from 0 to 1 when the associated entry is +visited during IL lowering. This allows IL lowering to know that it has +already processed a given entry and thereby avoid looping when there are cycles +in the IL graph.

    +

    This flag is similar to the il_walk_flag used by the IL walk routines, but +is kept separate so that IL lowering is not forced to visit all of the IL tree +even if it knows that certain parts cannot contain entries that will be +modified by lowering. It should be noted that even though every entry has a +flag, not all entries’ flags are maintained by IL lowering. For example, IL +lowering does not maintain the flag on expression nodes, because it knows that +it will visit each expression node exactly once.

    +

    Why not use the standard IL walk routines to do the traversal? The problem is +that the IL walk routines cannot co-exist with processing that changes the +structure of the IL tree. Since IL lowering can eliminate entries, move them +around, add entries, and swap entries, the IL walk routines could get into +loops, get lost, or process entries more than once. Therefore they are not +suitable, and IL lowering has its own IL traversal code.

    +
    +
    +

    5.3.3. Orphaned Entries#

    +

    Type entries and static variables that are local to a function require some +special handling. All type entries and all static variables are allocated in +the file scope memory region. However, types and static variables that are +local to a function are placed on the types and static variables list of a +function or block scope. Those are unusual lists: the function scope entries +(in a function scope memory region) point to lists that are entirely in the +file scope memory region. Yet, the entries pointed to are not really part of +the file scope. They might, in fact, not be referenced from anywhere except +the function scope memory region. Such entries are “orphaned” in the file +scope: their parents are processed, written out, and removed from memory, but +the children remain in the file scope, unattached to the rest of the file scope +IL tree.

    +

    There is special processing in the IL write, read, and walk routines to deal +with such orphans, but special handling is also required in IL lowering.

    +

    Such entries clearly must be lowered at some point. Do we lower them when the +function scope is lowered, or do we lower them when the file scope is lowered? +Well, lowering them with the function scope is impractical, since it’s hard to +tell which of the file-scope references are orphans and which are not. Even if +we know that a static variable, say, is an orphan, how much of its subtree do +we process? Is its type an orphan, or just a normal file-scope type?

    +

    So it’s easier not to do lowering on orphans. The processing then lowers +entries in the function scope, and leaves all those in the file scope alone. +Whenever a pointer hops into the file scope memory region, IL lowering leaves +that entry alone, regardless of whether or not it might be an orphan.

    +

    This solves one problem but creates another. If there truly are orphaned +entries, how will the IL lowering for the file scope find them to lower them? +The answer is that orphans or potential orphans are recorded on a special list, +using support routines and data structures provided by the IL support +components. When a pointer hops into the file scope memory region, the entry +pointed to is recorded as a potential orphan, and at the end of the lowering +for the file scope all the orphans are visited. If they turn out not to be +orphans, the IL lowering flag will indicate that they have already been visited +and they will not be processed again.

    +

    See lower_orphaned_entries.

    +
    +
    +

    5.3.4. Maintained Context#

    +

    While IL lowering works through a top-level scope, it maintains a stack that +shows the nesting of scopes for the present position (the spot for which +lowering is being done). This makes it easy to find the innermost enclosing +scope or the innermost enclosing function at any given moment, for example to +create a temporary in the innermost scope. The global variable +curr_context points to the top of the context stack.

    +
    +
    +

    5.3.5. Object Lifetimes#

    +

    The object lifetime entries in the IL provide information about regions of the +program on exit from which automatic destructions of class objects are done. +The destructions to be done appear in a list attached to the object lifetime +entry (in the form of dynamic initialization entries). IL lowering uses this +information to insert destructor calls on exit from those regions (whether by +flowing off the end of the region or branching out of it via a goto or the +like), and to build region table information for exception handling.

    +

    As IL lowering works through the IL, it keeps track of the current position in +cleanup terms, which is to say the latest initialization encountered that +requires automatic destruction. This is maintained in the +latest_initialization field of the current context. Given the pointer to +the latest initialization, gen_cleanup_actions and its subroutines can walk +up the cleanup chain, generating the appropriate destructions. In the case of +a return, the walk up the chain continues until the lifetime for the +function scope is reached. In the case of a goto, the cleanup continues +until the lifetime indicated in the goto statement is reached (that +lifetime is determined by the front end, and is the innermost lifetime that the +goto and the label have in common).

    +

    At the beginning of lowering of a block, the object lifetime for the block and +for any expression-temporary lifetimes immediately within it are processed. +This processing (which is performed by begin_object_lifetime) involves +allocating an entry of type a_destructible_entity_descr and attaching it to +each dynamic initialization on the lifetime destructions lists. These entries +are used to record information that will be needed when generating the +initialization and the later destruction. In particular, the position of the +entity (in initialization position form; see below) is determined and recorded +in the entry at the time of initialization. That position is then used when +generating the destruction code. The beginning-of-lifetime processing also +includes deciding whether the entity will require a conditional flag to +indicate that the construction has been done. If one is required, the variable +for it is created and code to initialize it to zero is inserted.

    +

    At the beginning of block-after-label lifetimes, similar processing is done, +but it takes a bit of effort to get it done at the right time, because there is +no explicit indication of a new lifetime on a statement that ushers in a +block-after-label lifetime. One must note, at the beginning of the previous +block or block-after-label lifetime, the next block-after-label lifetime in +sequence, and watch for the appearance of the associated statement during the +normal processing of statements. Also at labels (including switch case +labels), long lifetime temporaries must be destroyed (and when exceptions are +enabled, the region table is adjusted accordingly). (For this reason, +block-after-label lifetimes can begin at stmk_switch_case statements in +long-lifetime-temporaries mode.)

    +
    +
    +

    5.3.6. Initialization Positions#

    +

    an_init_pos_descr is used to contain a description of a position within an +initialization. As an aggregate initialization is processed, such a +description is maintained for the current position. The description can then +be turned into an expression that addresses the indicated position, which is +necessary when generating code to initialize pieces of aggregates:

    +
    int j;
    +void f() {
    +  struct {int i; int j;} k[2] = {{1, 1}, {j+1, 2}};
    +}
    +
    +
    +

    becomes

    +
    int j;
    +void f() {
    +  struct {int i; int j;} k[2] = {{1, 1}, {0, 2}};
    +  k[1].i = j+1;
    +}
    +
    +
    +
    +
    +

    5.3.7. Insert Locations#

    +

    Many transformations work by inserting new pieces of code into expressions or +statement lists. The insert location for such insertions is described by a +structure of type an_insert_location. It can describe an insert location +either within an expression or within a sequence of statements. The code +inserted is typically in units of “statements”, even when the insertion is +within expressions. That is, a lowering routine would assemble something like +temp = 1 and that construct would be inserted, either as a free-standing +expression statement, or as a clause in a comma operation added within an +expression. For the expression insertion case, for example,

    +
    i ? (void)A(i) : (void)0
    +
    +
    +

    might be modified by insertion of an assignment:

    +
    i ? (temp = 1, (void)A(i)) : (void)0
    +
    +
    +

    Since the insertion is done in statement units, the callers of the insert +routines need not in general be concerned about whether or not the insert +location is in an expression or a statement. The low-level routines do the +necessary adjustment, including rendering conditional tests as if +statements or “?” operators.

    +

    See

    +
      +
    • +
      insert_expr
      +
      +
    • +
    • +
      insert_statement
      +
      +
    • +
    • +
      insert_if_statement
      +
      +
    • +
    +
    +
    +

    5.3.8. Reusable Copies#

    +

    There are a few cases where an expression that is used once in the original IL +tree is used more than once in the lowered IL tree. Without special handling, +such cases might cause problems if the expression involved has side effects. +The routine make_reusable_copy solves the problem: given an expression +tree, it returns a distinct expression tree that produces the same value. If +the original tree has no side effects, it is simply copied. If it has side +effects, the original expression is modified to assign the expression value to +a temporary, and the new copy is simply a reference to the temporary.

    +

    Note that the new copy does not replace the original expression. The original +expression continues to be used in its original location, and the copy is used +for the second reference. Further copies can be made from either of the +expressions.

    +

    make_lvalue_reusable_copy does a similar operation for expressions that are +lvalues. It handles bit-field lvalues specially.

    +
    +
    +
    +

    5.4. Lowering C Dialects#

    +

    In some newer C modes like C99 or GNU C mode, some features create IL +constructs that are not used in IL for C89. In order to make things easier for +back ends, the front end includes a C lowering phase, which can rewrite many +(but not all) of these newer C constructs. Many (but not all) of the +additional IL features are enabled by C99_IL_EXTENSIONS_SUPPORTED. Most of +the code for this lowering is in lower_c99.c, with related declarations in +lower_c99.h.

    +
      +
    • +
      For compound literals, the generated enk_temp_init node is rewritten as +an initialized generated variable. See lower_c99_temp_init.
      +
      +
    • +
    • +
      Designated initializers are processed to produce a C89-style aggregate +initializer. This is done outside of the primary C99 lowering phase, and +is enabled by LOWER_DESIGNATED_INITIALIZERS. ck_designator +constants remain in the IL after this lowering for initializations of +members other than the first in unions, which are not expressible in C89 +IL. See lower_designated_initializers. Note that there are some +advantages to not doing this lowering and instead handling the designators +in a back end, notably that that can avoid some very large IL structures +for big sparsely-initialized arrays.
      +
      +
    • +
    • +
      The _Bool type is unchanged, but a C89 view of the IL does not consider +the bool_type flag and therefore sees the underlying integer. Compound +assignment operators whose left-hand operand has type _Bool are +rewritten to ensure that the result value is restricted to 0/1, via the +same routines that do this processing in C++ lowering; see +rewrite_compound_assignment. Boolean casts are also handled as in C++; +see bool.
      +
      +
    • +
    • +
      Complex types are rewritten as structs, imaginary types are rewritten as +floating-point types, complex constants are rewritten as aggregate +initializers, imaginary constants are rewritten as floating-point +constants, and operators and conversions on complex and imaginary types are +rewritten as runtime routine calls. This is controlled by +LOWER_COMPLEX. See lower_c99_nonreal_float_types, +lower_c99_complex_cast, and lower_c99_operator. Also see the file +c99_complex.c in the runtime library for descriptions and sample +implementations of the complex runtime routines. Note that a back end +could treat the runtime routines as intrinsics and generate machine +instructions directly for the calls. (Again, the C99-centric names are +historical: These routines also handle complex types appearing in GNU C +source.)
      +

      +
      For compound assignment operators, the operation is rewritten in terms +of the underlying operation, and the result is then converted and +stored in the destination variable (e.g., x += y is rewritten as +x = x + y). If the left side is an expression with side effects, +its address is evaluated and stored in a temporary, and the two +references to the left hand side (to fetch its value as as input to the +operation, and to store the result) are done by way of indirection +through the temporary. See rewrite_compound_assignment.
      +
      +
    • +
    • +
      If LOWER_FIXED_POINT is TRUE, fixed-point operations, types, and +constants are rewritten into standard C. Fixed-point types are lowered to +typedefs for appropriately-size integral types (see +lower_c99_fixed_point_types). Fixed-point constants are lowered to +integral constants (see lower_c99_fixed_point_constant). Fixed-point +operations and conversions are lowered to calls to runtime routines (see +lower_c99_fixed_point_operation, lower_c99_fixed_point_cast, +lower_c99_fixed_point_incr_decr, and rewrite_compound_assignment). +The runtime routines are not provided by EDG; they are available from +Dinkumware, Ltd. There is a long comment beginning with “Fixed-point +lowering:” in lower_c99.c that gives more details on the runtime +interface.
      +
      +
    • +
    • +
      When LOWER_VARIABLE_LENGTH_ARRAYS is TRUE variable-length arrays (VLAs) +are rewritten as pointers to storage allocated by the run-time library. +Storage for a VLA is allocated by a call to __vla_alloc, which is +produced by the lowering of certain stmk_vla_decl statements. The +storage is freed by calls to __vla_dealloc, which are the result of +lowering enk_vla_dealloc expression nodes (which may be produced +directly by the front end in C modes, or as the result of IL lowering in +C++ modes).
      +

      +
      A VLA type can be defined recursively to be either an array type with a +nonconstant bound, or a normal (constant-bound) array whose element is +a VLA type. The lowering process eventually replaces all VLA types and +pointer to VLA types by pointer types pointing to the underlying +(non-array) element type of the VLA type. For example, the type int +[3][n][4] is replaced by int* and the type +double*(*)[3][n][4] is replaced by double**. To avoid certain +subtle ordering problems, this type replacement is done in two stages. +First, all VLA types are collected on a linked list (see +record_vla_component_types_for_lowering) during the main C99 IL +lowering traversal (this is necessary because these types may only be +pointed to from an expression node, unlike, e.g., class types which are +listed on a scope’s type list). After the main tree traversal, the +actual replacement is done by a call to the function +lower_vla_types.
      +

      +
      The length of VLA types must in general be computed at run time. This +is achieved by evaluating the array bound expression and storing the +result in temporary helper variables. To further simplify the VLA size +computations in expressions, these variables are updated to hold a +total count of the number of (non-array) elements for a particular VLA +type component. For example, the type char[n][m] would produce two +variables, one holding the value m and the other holding the value +n*m. Once created, the IL entries for these variables can be +accessed through the a_vla_dimension entries of the associated VLA +type components. For VLA types appearing in explicit declarations +(variable declarations and typedef declarations), the front end adds +adds explicit stmk_set_vla_size statement indicating when the value +of these variables ought to be computed. However, in expression +contexts that introduce new VLA types (sizeof and cast expressions, +as well as compound literals) there are no such statements. Either +way, the bulk of the work to produce and compute these variables is +done in lower_vla_dimensions, which creates all the necessary +variables for an arbitrarily complex VLA type and returns an expression +that sets all the variables to their required values.
      +

      +
      With those variables available, the lowering of various array-related +operations (subscripting, pointer arithmetic, and run-time sizeof +expressions) is relatively straightforward. There is a long comment +near the beginning of lower_c99.c (conditioned on +LOWER_VARIABLE_LENGTH_ARRAYS) that gives more details on the + lowering of VLAs.
      +
      +
    • +
    • +
      Extended identifiers containing universal character names (\uxxxx), +whose name strings contain the \u etc., are rewritten as standard +identifiers if REWRITE_UCN_ESCAPE_CHAR_IN_LOWERING is TRUE. The +“\” character is changed to “_”. This is the same processing that +is done in C++ lowering.
      +
      +
    • +
    • +
      Non-constant expressions in aggregate initializers, i.e., those indicated +by ck_dynamic_init constants, are rewritten as executable code. This +is done via the same routines that do this processing in C++ lowering. See +lower_c99_stmk_init.
      +
      +
    • +
    • +
      Inline function calls are replaced by their expansions if +MINIMAL_INLINING is TRUE. This is done via the same routines that do +this processing in C++ lowering.
      +
      +
    • +
    • +
      Boolean controlling expressions are optionally normalized to always yield +an integer value of 0 or 1. This transformation occurs even in C89 mode +(and the same processing is done in C++ mode).
      +
      +
    • +
    +

    Some features are not lowered but use IL constructs that exist in IL produced +by lowering C++, which a back end is likely already to accept:

    +
      +
    • +
      For mixed statements and declarations, the statements and declarations +appear intermixed in the statement list of a compound statement.
      +
      +
    • +
    • +
      For longlong, there are two new integer kinds (ik_long_long +and ik_unsigned_long_long) and new constants of these kinds.
      +
      +
    • +
    +

    One feature is not lowered at all:

    +
      +
    • +
      For flexible array members, the last member of a struct type may have an +array type with an unknown bound. This probably does not require special +processing in a back end.
      +
      +
    • +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/modules/index.html b/doc/modules/index.html new file mode 100644 index 0000000..692a7cb --- /dev/null +++ b/doc/modules/index.html @@ -0,0 +1,2085 @@ + + + + + 16. Modules - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    16. Modules#

    +

    The EDG modules implementation is based upon the Microsoft IFC specification.

    +

    The EDG front end has experimental support for both the IFC variant produced by +Microsoft’s Visual Studio compiler and an EDG variant produced by the EDG front +end.

    +
    +

    16.1. Roles#

    +

    To make the system work, every IFC type is understood in terms of a “role”. The +type’s role in effect defines what semantics it will be generated with.

    +

    The roles are as follows:

    +
      +
    • Simple Sort - Any kind of enumeration of named values +unrelated to an index.

    • +
    • Index Sort - A “sort” that encodes a simple sort and an +associated index (e.g., DeclIndex is the “Index Sort”, with a “Simple +Sort” DeclSort).

    • +
    • Bitfield - Any IFC type that encodes things using bit flags.

    • +
    • Raw Numeric - Any IFC type that is an integer with no +associated implicit interpretation (from a format perspective, it’s just a +“dumb” number).

    • +
    • Raw Bytes - Similar to Raw Numeric, anything that’s just a +raw byte array.

    • +
    • +
      Nodes
        +
      • Partition Node - An IFC Node that can be directly read +from a partition, for instance a DeclFunction.

      • +
      • Basic Node - An IFC Node that only appears as a +sub-node (doesn’t have a partition of its own), for instance, a +ModuleReference.

      • +
      • Header Node - Basically what it says, an IFC Node that’s +part of the header (FileHeader and Partition).

      • +
      +
      +
      +
    • +
    • Foreign Index - A special role for IFC types that represent +an Index in another module file.

    • +
    • Value Category - A role representing several levels of +discriminated values (conceptually similar to an IFC std::variant)

    • +
    +
    +

    16.1.1. Simple Sort#

    +

    Simple sorts are represented as an enum (sorted in alphabetical order):

    +
    enum an_ifc_access_sort {
    +  ifc_as_none,
    +  ifc_as_private,
    +  ifc_as_protected,
    +  ifc_as_public
    +};  /* an_ifc_access_sort */
    +
    +
    +

    Simple sorts can also be converted to a c-string of their respective EDG name +via a call to the respective str_for function. This can be useful for +debugging and diagnostic purposes.

    +
    +
    +

    16.1.2. Index Sort#

    +

    Index sorts are represented as an index type (a struct with a module binding, +an associated Simple Sort value, and the associated index +value):

    +
    enum an_ifc_decl_sort {
    +  ifc_ds_decl_alias,
    +  ifc_ds_decl_barren,
    +  ifc_ds_decl_bitfield,
    +  ifc_ds_decl_concept,
    +  ifc_ds_decl_constructor,
    +  ifc_ds_decl_deduction_guide,
    +  ifc_ds_decl_destructor,
    +  ifc_ds_decl_enumeration,
    +  ifc_ds_decl_enumerator,
    +  ifc_ds_decl_expansion,
    +  ifc_ds_decl_explicit_instantiation,
    +  ifc_ds_decl_explicit_specialization,
    +  ifc_ds_decl_field,
    +  /* snip */
    +};  /* an_ifc_decl_sort */
    +
    +/*
    +The universal representation for an IFC DeclIndex.
    +*/
    +struct an_ifc_decl_index {
    +  an_ifc_module*
    +                mod;
    +                        /* The associated module. */
    +  an_ifc_decl_sort
    +                sort;
    +                        /* The associated DeclSort value for this index. */
    +  uint32_t      value;
    +                        /* The index value into the associated partition of
    +                           "sort" for this index.  Represented as the
    +                            largest common underlying type. */
    +};  /* an_ifc_decl_index */
    +
    +
    +
    +
    +

    16.1.3. Bitfield#

    +

    Bitfields are represented as a bitfield type (a struct with a module binding +and the raw value pulled from the module file):

    +
    /*
    +The universal representation for an IFC FunctionTraitsBitfield.
    +*/
    +struct an_ifc_function_traits_bitfield {
    +  an_ifc_module*
    +                mod;
    +                        /* The associated module. */
    +  an_ifc_function_traits_bitfield_storage
    +                value;
    +                        /* The raw bit value obtained from the module.
    +                           Represented as the largest common underlying
    +                           type. */
    +};  /* an_ifc_function_traits_bitfield */
    +
    +
    +

    This is then paired with a (alphabetically sorted) set of bit queries.

    +
    enum an_ifc_function_traits_bitfield_query : uint32_t {
    +  ifc_ftb_constexpr     = 1 << 0,
    +  ifc_ftb_constrained   = 1 << 1,
    +  ifc_ftb_defaulted     = 1 << 2,
    +  ifc_ftb_deleted       = 1 << 3,
    +  ifc_ftb_explicit      = 1 << 4,
    +  ifc_ftb_hidden_friend = 1 << 5,
    +  ifc_ftb_immediate     = 1 << 6,
    +  ifc_ftb_inline        = 1 << 7,
    +  ifc_ftb_no_return     = 1 << 8,
    +  ifc_ftb_none          = 1 << 9,
    +  ifc_ftb_pure_virtual  = 1 << 10,
    +  ifc_ftb_virtual       = 1 << 11
    +};  /* an_ifc_function_traits_bitfield_query */
    +
    +
    +

    A bitmask can then before formed and tested on a bitfield like so:

    +
    an_ifc_function_traits_bitfield bitfield = ...;
    +
    +if (test_bitmask<ifc_ftb_immediate | ifc_ftb_explicit>(bitfield)) {
    +  /* matched bitfield & (ifc_ftb_immediate | ifc_ftb_explicit) */
    +} else {
    +  /* didn't match */
    +}  /* if */
    +
    +
    +
    +
    +

    16.1.4. Raw Numeric#

    +

    Raw numerics are represented as a raw numeric type (a struct with a module +binding and the raw value pulled from the module file, along with a convenience +conversion operator):

    +
    /*
    +The universal representation for an IFC Index.
    +*/
    +struct an_ifc_index {
    +  an_ifc_module*
    +                mod;
    +                        /* The associated module. */
    +  an_ifc_index_storage
    +                value;
    +                        /* The raw bit value obtained from the module.
    +                           Represented as the largest common underlying
    +                           type. */
    +
    +  inline operator an_ifc_index_storage() const
    +    { return this->value; }
    +};  /* an_ifc_index */
    +
    +
    +

    Thus, the value itself can be passed around safely without concern of changes +in the underlying type, and with access to the module, while being trivial to +work with as an unsigned number:

    +
    an_ifc_index power_idx = ...;
    +
    +if (power_idx > 9000) {
    +  /* panic */
    +}  /* if */
    +
    +
    +
    +
    +

    16.1.5. Raw Bytes#

    +

    Types generated from the raw bytes role are derived from +Byte Buffers.

    +
    /*
    +The universal representation of an IFC SHA256 node.
    +
    +The representation is declared as a derived struct of an_ifc_Byte_buffer
    +rather than simply an alias of the instantiation to improve the debugger
    +experience.
    +*/
    +struct an_ifc_sha256 : an_ifc_Byte_buffer<an_ifc_sha256_storage> {
    +  using storage_type = an_ifc_sha256_storage;
    +  using base_type = an_ifc_Byte_buffer<storage_type>;
    +  using base_type::an_ifc_Byte_buffer;
    +};  /* an_ifc_sha256 */
    +
    +
    +

    These types also include an additional table documenting the number of bytes +available (starting from a specific version). For example, if a type has +32 bytes starting with version 0.33, and that doubles to 64 bytes in 0.41 +the following table will be written:

    +
    |----------------|
    +| Version | Size |
    +|---------|------|
    +| 0.33    | 32   |
    +| 0.41    | 64   |
    +|---------|------|
    +
    +
    +
    +
    +

    16.1.6. Nodes#

    +

    The node roles (Partition Node, Basic Node, and +Header Node) are all very similar, differing only in their +construction.

    +

    The node types are – similarly to Raw Bytes types – derived +from Byte Buffers.

    +
    /*
    +The universal representation of an IFC DeclFunction node.
    +
    +The representation is declared as a derived struct of an_ifc_Byte_buffer
    +rather than simply an alias of the instantiation to improve the debugger
    +experience.
    +*/
    +struct an_ifc_decl_function :
    +                          an_ifc_Byte_buffer<an_ifc_decl_function_storage> {
    +  using storage_type = an_ifc_decl_function_storage;
    +  using base_type = an_ifc_Byte_buffer<storage_type>;
    +  using base_type::an_ifc_Byte_buffer;
    +};  /* an_ifc_decl_function */
    +
    +
    +

    Additionally, – again similarly to Raw Bytes types – node +types include a descriptive table to aid in development:

    +
    |------------------------------------------------------------|
    +|               DeclFunction - 0.33 (32 bytes)               |
    +|-------------|-----------------------------|---------|------|
    +| Name        | Type                        | Version | Size |
    +|-------------|-----------------------------|---------|------|
    +| name        | NameIndex                   | 0.33    | 4    |
    +| locus       | SourceLocation              | 0.33    | 8    |
    +| type        | TypeIndex                   | 0.33    | 4    |
    +| home_scope  | DeclIndex                   | 0.33    | 4    |
    +| chart       | ChartIndex                  | 0.33    | 4    |
    +| traits      | FunctionTraitsBitfield      | 0.33    | 2    |
    +| specifiers  | BasicSpecifiersBitfield     | 0.33    | 1    |
    +| access      | AccessSort                  | 0.33    | 1    |
    +| properties  | ReachablePropertiesBitfield | 0.33    | 1    |
    +| __padding__ | uint8_t[3]                  |         | 3    |
    +|-------------|-----------------------------|---------|------|
    +
    +|------------------------------------------------------------|
    +|               DeclFunction - 0.41 (32 bytes)               |
    +|-------------|-----------------------------|---------|------|
    +| Name        | Type                        | Version | Size |
    +|-------------|-----------------------------|---------|------|
    +| name        | NameIndex                   | 0.33    | 4    |
    +| locus       | SourceLocation              | 0.33    | 8    |
    +| type        | TypeIndex                   | 0.33    | 4    |
    +| home_scope  | DeclIndex                   | 0.41    | 4    |
    +| chart       | ChartIndex                  | 0.33    | 4    |
    +| traits      | FunctionTraitsBitfield      | 0.33    | 2    |
    +| specifiers  | BasicSpecifiersBitfield     | 0.33    | 1    |
    +| access      | AccessSort                  | 0.33    | 1    |
    +| properties  | ReachablePropertiesBitfield | 0.33    | 1    |
    +| __padding__ | uint8_t[3]                  |         | 3    |
    +|-------------|-----------------------------|---------|------|
    +| home_scope  | DeclIndex                   | 0.41    | TF   |
    +|-------------|-----------------------------|---------|------|
    +
    +
    +

    Here, the first table describes DeclFunction from IFC version 0.33 up until +0.41 (non-inclusive) as a 32 byte structure. Each of the structure’s fields are +listed with their name, return type, the interpretation version of the return +type, and the size of the field. Additionally, a __padding__ field is +listed specifying there are 3 bytes of unused (or unknown) data padding the end +of the structure (which would otherwise be 29 bytes).

    +

    The second table describes DeclFunction for IFC version 0.41+ +(inclusive). This table is very similar to the structure describing the +earlier version of DeclFunction. However, this table specifies that the +home_scope’s DeclIndex has an updated value interpretation, and in the +bottom row of the table sized “TF” that a tacit field is being used to +define (in this case redefine) home_scope (see Tacit Field for +more information on tacit fields).

    +

    The values of these fields can be retrieved via calling the get_ifc_X +function where X is the name of the field (for information on the inner +workings of these functions, see Nodes). For instance, to +retrieve the home_scope (independent of the IFC version and underlying +semantics) the following function can be used:

    +
    an_ifc_decl_function func_decl = /* ... */;
    +an_ifc_decl_index    home_scope = get_ifc_home_scope(func_decl);
    +
    +
    +

    The returned home_scope is pre-validated during the node’s +construction, and ready for usage (for more information, see +Validation).

    +
    +

    16.1.6.1. Partition Node#

    +

    To get a partition node, in effectively all front end code, construct_node +should be used (for information on exceptional cases, see +Skipping Validation). This looks something like:

    +
    Opt<an_ifc_decl_function> opt_idf;
    +
    +construct_node(&opt_idf, index);
    +
    +
    +

    This will load the appropriate value found at the given index, run validation +(if necessary), and (if validation is successful) store the node in the Opt +variable.

    +
    +
    +

    16.1.6.2. Basic Node#

    +

    Basic nodes are only obtainable from a get_ifc_X operation, and used to +represent nodes which are nested in other nodes. For instance, you might have:

    +
    an_ifc_decl_reference decl_ref = ...;
    +
    +an_ifc_module_reference module_reference = get_ifc_unit(decl_ref);
    +
    +
    +

    Here the returned an_ifc_module_reference is a basic node. Note that this +is not wrapped in an optional, as the an_ifc_module_reference being a +sub-node of an_ifc_decl_reference was validated when +an_ifc_decl_reference was constructed.

    +
    +
    +

    16.1.6.3. Header Node#

    +

    Header nodes rarely need new code written for them, there are only two at the +time of writing (and for the foreseeable future):

    +
      +
    • an_ifc_file_header

    • +
    • an_ifc_partition

    • +
    +

    To get a header node, the low level construct_node_from_module is used +directly. Similarly, since header nodes are lower level, validate functions +need called explicitly.

    +

    The flow for interaction with these nodes is typically something like the +following (if not in practice, conceptually):

    +
    Opt<an_ifc_file_header> get_module_header(an_ifc_module *mod)
    +{
    +  Opt<an_ifc_file_header> result;
    +  an_ifc_file_header      raw_result;
    +
    +  init_byte_buffer(4, mod->f_size - 4);
    +  raw_result = construct_node_from_module<an_ifc_file_header>(mod);
    +  if (validate(raw_result, /*parent=*/NULL)) {
    +    result = raw_result;
    +  }  /* if */
    +  return result;
    +}  /* get_module_header */
    +
    +
    +

    This is conceptually very similar to what construct_node is doing behind +the scenes.

    +
    +
    +
    +

    16.1.7. Foreign Index#

    +

    Currently in the IFC spec there’s a DeclSort::Reference structure:

    +
    + + + + + + + + + + + + + + +

    Field

    Type

    unit

    ModuleReference

    local_index

    DeclIndex

    +
    +

    The problem is that the local_index field uses a DeclIndex, but +that DeclIndex is valid in a completely different module. This has +caused issues for the front end in the past where the index is accidentally +being used in the current module’s code.

    +

    The “Foreign Index” role is used to replace the DeclIndex type with a +new DeclForeignIndex type. This new type is more akin to a +Raw Numeric than a Index Sort.

    +

    The front end thus represents this as the following node structure:

    +
    + + + + + + + + + + + + + + +

    Field

    Type

    unit

    ModuleReference

    local_index

    DeclForeignIndex

    +
    +

    The DeclForeignIndex type in C++ code looks as follows:

    +
    /*
    +The universal representation for an IFC DeclForeignIndex.
    +*/
    +struct an_ifc_decl_foreign_index {
    +  an_ifc_module*
    +                mod;
    +                        /* The associated module. */
    +  an_ifc_decl_foreign_index_storage
    +                value;
    +                        /* The raw bit value obtained from the module.
    +                           Represented as the largest common underlying
    +                           type. */
    +};  /* an_ifc_decl_foreign_index */
    +
    +
    +

    This allows the index value to be imported into the current module in a +type safe way that can’t be accidentally treated as a DeclIndex. Thus, +interacting with the DeclReference you get something like:

    +
    an_ifc_decl_reference decl_ref = ...;
    +
    +an_ifc_decl_foreign_index local_index = get_ifc_local_index(decl_ref);
    +process_ifc_decl(local_index); /* type error */
    +
    +
    +

    In terms of correct usage, foreign indexes are typically deserialized via an +associated Tacit Field which reconstructs them as the appropriate +Index Sort in the context of their respective module.

    +

    As an example consider the DeclReference type:

    +
    |-------------------------------------------------|
    +|         DeclReference - 0.33 (12 bytes)         |
    +|-------------|------------------|---------|------|
    +| Name        | Type             | Version | Size |
    +|-------------|------------------|---------|------|
    +| unit        | ModuleReference  | 0.33    | 8    |
    +| local_index | DeclForeignIndex | 0.33    | 4    |
    +|-------------|------------------|---------|------|
    +| index       | DeclIndex        | ANY     | TF   |
    +|-------------|------------------|---------|------|
    +
    +
    +

    Using the tacit field index, local_index can be retrieved in the +context of the associated unit (i.e., IFC module) transparently:

    +
    an_ifc_decl_reference ref = ...;
    +an_ifc_decl_index     idx = get_ifc_index(ref);
    +
    +
    +
    +
    +

    16.1.8. Value Category#

    +

    Value categories are roughly equivalent to a variant type. The categories have +a Simple Sort which describes which variant is valid. The +actual variants can be any role.

    +

    This allows for handling of nested hierarchies like IFC Operators where an +OperatorSort selects the interpretation of the variant value which may +be one of several different Simple Sorts.

    +
    +
    +
    +

    16.2. Versioning#

    +
    +

    16.2.1. Simple Sort#

    +

    The Simple Sort versioning system works by converting from a +“versioned sort” (i.e., enumeration) to a “universal sort” (i.e., enumeration). +Each IFC version gets its own unique, and appropriately sized enumeration, like +so:

    +
    enum an_ifc_decl_sort_0_33 : uint32_t {
    +  ifc_0_33_ds_decl_vendor_extension        = 0,
    +  ifc_0_33_ds_decl_enumerator              = 1,
    +  ifc_0_33_ds_decl_variable                = 2,
    +  ifc_0_33_ds_decl_parameter               = 3,
    +  ifc_0_33_ds_decl_field                   = 4,
    +  ifc_0_33_ds_decl_bitfield                = 5,
    +  ifc_0_33_ds_decl_scope                   = 6,
    +  ifc_0_33_ds_decl_enumeration             = 7,
    +  /* snip */
    +};  /* an_ifc_decl_sort_0_33 */
    +
    +enum an_ifc_decl_sort_0_41 : uint32_t {
    +  ifc_0_41_ds_decl_vendor_extension       = 0,
    +  ifc_0_41_ds_decl_enumerator             = 1,
    +  ifc_0_41_ds_decl_variable               = 2,
    +  ifc_0_41_ds_decl_parameter              = 3,
    +  ifc_0_41_ds_decl_field                  = 4,
    +  ifc_0_41_ds_decl_bitfield               = 5,
    +  ifc_0_41_ds_decl_scope                  = 6,
    +  ifc_0_41_ds_decl_enumeration            = 7,
    +  /* snip */
    +};  /* an_ifc_decl_sort_0_41 */
    +
    +
    +

    Note that these versioned enumerators do not follow the typical naming +convention. This is done to reduce the amount of possible completions editor +auto complete has for ifc_ds_ (and similar).

    +

    The universal sort representation by contrast takes all of the unique names, +from all the versioned sorts, and puts them in one enumeration:

    +
    enum an_ifc_decl_sort : uint32_t {
    +  ifc_ds_decl_alias,
    +  ifc_ds_decl_barren,
    +  ifc_ds_decl_bitfield,
    +  ifc_ds_decl_concept,
    +  ifc_ds_decl_constructor,
    +  ifc_ds_decl_deduction_guide,
    +  ifc_ds_decl_destructor,
    +  ifc_ds_decl_enumeration,
    +  ifc_ds_decl_enumerator,
    +  ifc_ds_decl_expansion,
    +  ifc_ds_decl_explicit_instantiation,
    +  ifc_ds_decl_explicit_specialization,
    +  ifc_ds_decl_field,
    +  /* snip */
    +};  /* an_ifc_decl_sort */
    +
    +
    +

    This enumeration is sorted alphabetically to make things easier to find and to +prevent the list from being “shuffled” when new IFC versions are adopted.

    +

    Functions are then added to convert between the versioned sort (read from the +module file) to the universal sort, they look something like this:

    +
    inline an_ifc_decl_sort to_universal_sort(an_ifc_decl_sort_0_33 versioned)
    +/*
    +Given the versioned representation of DeclSort, return the corresponding
    +universal representation.
    +*/
    +{
    +  an_ifc_decl_sort result;
    +
    +  switch (versioned) {
    +    case ifc_0_33_ds_decl_vendor_extension:
    +      result = ifc_ds_decl_vendor_extension;
    +      break;
    +    case ifc_0_33_ds_decl_enumerator:
    +      result = ifc_ds_decl_enumerator;
    +      break;
    +    case ifc_0_33_ds_decl_variable:
    +      result = ifc_ds_decl_variable;
    +      break;
    +  /* snip */
    +
    +
    +

    This allows for stability in all of our logic despite a number of possible +changes to the sort for a particular version (e.g., numbering changes, removal, +and addition). Effectively, sorts become unique on name rather than unique on +value.

    +
    +
    +

    16.2.2. Index Sort#

    +

    As an Index Sort is composed of a Simple Sort +and an index value, its versioning relies upon the versioning of the associated +Simple Sort (see Simple Sort).

    +
    +
    +

    16.2.3. Bitfield#

    +

    Bitfield versioning works very similarly to +Simple Sort.

    +

    There’s similarly a versioned bitfield enum for each version, of appropriate +size, using the values that are correct for that version:

    +
    enum an_ifc_basic_specifiers_bitfield_0_33 : uint8_t {
    +  ifc_0_33_bsb_cxx                        = 0,
    +  ifc_0_33_bsb_c                          = 1 << 0,
    +  ifc_0_33_bsb_internal                   = 1 << 1,
    +  ifc_0_33_bsb_vague                      = 1 << 2,
    +  ifc_0_33_bsb_external                   = 1 << 3,
    +  ifc_0_33_bsb_deprecated                 = 1 << 4,
    +  ifc_0_33_bsb_initialized_in_class       = 1 << 5,
    +  ifc_0_33_bsb_non_exported               = 1 << 6,
    +  ifc_0_33_bsb_is_member_of_global_module = 1 << 7
    +};  /* an_ifc_basic_specifiers_bitfield_0_33 */
    +
    +
    +

    Unlike sorts, it’s not super practical to try and normalize the representation +itself, so instead the value is captured with a module reference.

    +
    /*
    +The universal representation for an IFC BasicSpecifiersBitfield.
    +*/
    +struct an_ifc_basic_specifiers_bitfield {
    +        an_ifc_module*
    +                mod;
    +                        /* The associated module. */
    +        an_ifc_basic_specifiers_bitfield_storage
    +                value;
    +                        /* The raw bit value obtained from the module.
    +                           Represented as the largest common underlying
    +                           type. */
    +};  /* an_ifc_basic_specifiers_bitfield */
    +
    +
    +

    This is then paired with a universal query enum (similar to the universal sort) +that gives a unique bit value to each possible bitfield and a test_bitmask +function.

    +
    enum an_ifc_basic_specifiers_bitfield_query : uint32_t {
    +  ifc_bsb_c                          = 1 << 0,
    +  ifc_bsb_cxx                        = 1 << 1,
    +  ifc_bsb_deprecated                 = 1 << 2,
    +  ifc_bsb_external                   = 1 << 3,
    +  ifc_bsb_initialized_in_class       = 1 << 4,
    +  ifc_bsb_internal                   = 1 << 5,
    +  ifc_bsb_is_member_of_global_module = 1 << 6,
    +  ifc_bsb_non_exported               = 1 << 7,
    +  ifc_bsb_vague                      = 1 << 8
    +};  /* an_ifc_basic_specifiers_bitfield_query */
    +
    +
    +template<an_ifc_basic_specifiers_bitfield_query a_Query>
    +inline a_boolean test_bitmask(
    +                         const an_ifc_basic_specifiers_bitfield &universal)
    +/*
    +Given the universal representation of BasicSpecifiersBitfield, return TRUE
    +if the universal bitmask specified by a_Query matches; otherwise, return
    +FALSE.
    +*/
    +{
    +  a_boolean result;
    +
    +  uint8_t mask = to_bitmask_0_33(a_Query);
    +  uint8_t test_value = universal.value & mask;
    +
    +  result = test_value == mask;
    +  return result;
    +}  /* test_bitmask */
    +
    +
    +

    At a high level, these functions generate per-version branches. Each of these +branches calls a function that converts the universal query, into a version +specific query (i.e., bitmask) for respective version (in this case there’s +only one version of the bitfield, so there are no branches, just a call to +to_bitmask_0_33). These bitmask conversion functions look something like +the following:

    +
    uint8_t to_bitmask_0_33(an_ifc_basic_specifiers_bitfield_query query)
    +/*
    +Given the universal representation of a BasicSpecifiersBitfield bitmask,
    +return the corresponding IFC version 0.33 representation of the bitmask.
    +*/
    +{
    +  uint8_t result = 0;
    +
    +  if (query & ifc_bsb_cxx) {
    +    result |= ifc_bsb_0_33_cxx;
    +  }  /* if */
    +  if (query & ifc_bsb_c) {
    +    result |= ifc_bsb_0_33_c;
    +  }  /* if */
    +  /* snip */
    +
    +
    +

    The versioned specific bitmask is then tested against the version specific +value, returning the result.

    +

    This approach allows the front end to test “the same” bitmasks in a version +agnostic way, with a very small runtime performance overhead.

    +
    +

    16.2.3.1. Bitwidth Limitations#

    +

    As bitfield versioning relies upon native integer types, there are limitations +imposed, namely there are a limited number of expressible bitfield queries +across all versions of the IFC.

    +

    If this becomes a problem in the future, two approaches are noted as promising.

    +

    The first (and simplest) being, the removal of the ability to create a bitmask +by joining two queries (bit-or) in favor of two (effectively bit-and) +tests. This would allow a much larger number of bitfield queries to be +represented as the bitfield query would no longer require its own bit position.

    +

    The second option being, the usage of a “big integer” type with overloaded +operators in place of a native integer type. As the translation process is +realistically performed at compile time (either via language level guarantees +if the front end moves to C++14 and these functions are made constexpr, or via +the optimizer), while this approach may on the surface seem more expensive, at +runtime it would likely be more efficient than the former.

    +

    If this problem is encountered, existing usage will guide the resolution (the +formation and usage of bit-or joined queries has thus far been limited, and may +not be useful long term).

    +
    +
    +
    +

    16.2.4. Raw Values#

    +

    Raw Numeric and Raw Bytes values effectively +aren’t versioned. As raw values have no semantic meaning at the format level, +there’s “nothing to be done.”

    +
    +
    +

    16.2.5. Nodes#

    +

    Node versioning relies upon a number of “field +accessors” (i.e., get_ifc_X) that read from the underlying byte +representation (abstracted by Byte Buffers). These accessors +additionally, abstract away the exact location and representation of various +field values within the node, allowing for complex changes to the node +representation to be “normalized.”

    +

    These accessor functions look something like the following:

    +
    template<>
    +an_ifc_decl_index get_ifc_decl(
    +                              const an_ifc_parameterized_entity &universal)
    +/*
    +Given the universal representation of ParameterizedEntity, return the
    +universal representation of the field "decl".
    +*/
    +{
    +  an_ifc_decl_index result;
    +
    +  /* Ensure the decl field exists in the current module version. */
    +  check_assertion(has_ifc_decl(universal));
    +  if (is_at_least(universal.get_module(), 0, 41)) {
    +    /* version specific logic */
    +  } else {
    +    /* version specific logic */
    +  }  /* if */
    +  return result;
    +}  /* get_ifc_decl */
    +
    +
    +

    For every version where the retrieval logic is different, we end up with a +separate branch gated on the lower bound of the version range. Newer values are +always checked first, as it’s presumed newer IFC versions will be the common +case.

    +
    +

    16.2.5.1. Stages#

    +

    The exact logic in a given branch used to read a field value, is represented in +the generator as a sequence of “stages.” These stages are setup via a “stage +builder” for the specific IFC node version. The stage builder allocates a +result variable for every stage (and can also allocate some additional +variables with extra name information if necessary).

    +

    In most cases the stages and the associated logic are fairly trivial. As an +example, consider:

    +
    an_ifc_decl_index_0_41 stage_0;
    +an_ifc_decl_index      stage_1;
    +
    +/* Copy the field (ParameterizedEntity::decl - DeclIndex) into
    +   version-specific storage. */
    +static_assert(sizeof(stage_0) == 4,
    +              "stage_0 is not properly sized storage!");
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/0);
    +stage_1 = to_universal_index(universal.get_module(), stage_0);
    +result = stage_1;
    +
    +
    +

    Here the raw value is copied (via copy_ifc_field) from an offset into a +version specific variable (stage 0). Then, said version specific variable is +converted (via to_universal_index) into a universal representation (stage +1). Finally, the resulting value is assigned to the result return +variable.

    +

    This is a trivial case of data retrieval where the data is directly stored as +part of the node, and only needs converted to a universal representation. For +more information about this process, and additional similar cases, see +Field Deserialization.

    +

    Additionally, it’s important to note that in some cases, more complicated +processing is similarly implemented via stages (for a variety of reasons). For +more information on this process, and advanced uses of the stage builder, see +Tacit Field.

    +
    +
    +

    16.2.5.2. Field Presence Checking#

    +

    The presence of an accessor sometimes depends on the IFC version. In +contexts where this is not obvious has_ifc_X functions can be used to +check to see if the associated get_ifc_X is valid. These are fairly +simple calls that return TRUE when field X is relevant to the node for +the corresponding IFC version, and FALSE otherwise.

    +
    +
    +
    +

    16.2.6. Foreign Index#

    +

    Foreign Indexes, despite conceptually being an +Index Sort are versioned more like Raw +Numerics. This is done as foreign indexes have an +associated module which contains its own revision information. Thus, using the +current (referencing) module’s version information to convert the raw value to +a universal understanding would be unreliable at best.

    +
    +
    +

    16.2.7. Value Category#

    +

    Value Categories rely upon the fact that the +types they’re composed of are themselves versioned. Thus, while value +categories are versioned, they do not have any versioning rules specific to +them.

    +
    +
    +
    +

    16.3. Deserialization#

    +

    IFC deserialization is notable for intricacies introduced by supporting +optional memory mapped IFC reading and support for big-endian and little-endian +byte orders.

    +
    +

    16.3.1. Byte Buffers#

    +

    The an_ifc_Byte_buffer class template is the class that’s fundamentally +responsible for abstracting away the location of the in memory representation +of a given byte sequences taken from the IFC file.

    +

    The most notable use the byte buffer abstraction being for the representation +of Nodes but some other IFC roles, such as +Raw Bytes, also make use of byte buffers.

    +

    The byte buffer fulfills its duty of abstracting away the memory location for a +given byte sequence via a union. Said union contains either the bytes required +for storage, or a storage_ptr; this determination is made during construction +of the respective byte buffer.

    +
    +
    +

    16.3.2. Endianness Agnostic Reading#

    +

    Endianness agnostic reading requires considerations for cases that are +and aren’t memory mapped.

    +
    +
    +

    16.3.3. Without Memory Mapping#

    +

    When memory mapping isn’t enabled, the front end resorts to calls to +get_bytes for each field in each node.

    +

    Each call copies the appropriate number of bytes for the field into a +Byte Buffer, reversing the byte order for the bytes +stored in the field if the host and IFC endianness do not match.

    +

    For nodes that contain nested (i.e., Basic Node) node +structures, the internal node’s fields are copied individually rather than +copying the entire internal node as “one field.”

    +
    +
    +

    16.3.4. With Memory Mapping#

    +

    When memory mapping is enabled, if there is an endianness mismatch, the +non-memory mapped approach described above is used.

    +

    Otherwise, the front end will use only a pointer to the start of the node +(within the broader memory mapped memory region). This pointer is then stored +and dereferenced when retrieving data in place of copying bytes into the +Byte Buffer.

    +

    There is also support for a-typical cases where the front end, even when +operating with memory mapping and matching endianness, explicitly requests an +explicit copy of the data. In practice, this isn’t currently used by the front +end and may be removed in the future.

    +
    +
    +

    16.3.5. Field Deserialization#

    +

    Fields are deserialized from the associated Byte +Buffer for the corresponding node. This process makes use +of one of two copy_ifc_field field functions, and in some cases an adjusted +Byte Buffer pointer instead of a copy.

    +
    +
    +

    16.3.6. Implicit Bounds Copying#

    +

    Copying with implicit bounds occurs when the destination object type is exactly +equivalent size. These copies additionally include a static assert as a +functional “sanity check” to ensure the code generation tool is right about the +size of the destination object (not just in theory, but in practice).

    +
    an_ifc_keyword_sort_0_33 stage_0;
    +an_ifc_keyword_sort      stage_1;
    +
    +/* Copy the field (KeywordSyntax::value - KeywordSort) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_0) == 4,
    +              "stage_0 is not properly sized storage!");
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/8);
    +
    +
    +
    +
    +

    16.3.7. Explicit Bounds Copying#

    +

    Copying with explicit bounds occurs when the destination object type is a +buffer of at least equivalent size.

    +
    enum an_ifc_source_location_part : uint8_t {};
    +using an_ifc_source_location_storage = an_ifc_source_location_part[8];
    +#if USE_MMAP_FOR_MODULES
    +using an_ifc_source_location_bytes = const an_ifc_source_location_storage*;
    +#else /* !USE_MMAP_FOR_MODULES */
    +using an_ifc_source_location_bytes = an_ifc_source_location_storage;
    +#endif /* USE_MMAP_FOR_MODULES */
    +
    +an_ifc_source_location_bytes stage_0;
    +
    +/* Copy the field (KeywordSyntax::locus - SourceLocation) into universal
    +   storage. */
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/0,
    +               /*size=*/8);
    +
    +
    +
    +
    +

    16.3.8. Byte Buffer Adjustment#

    +

    Byte Buffers are adjusted in place of a copy when the front end is +operating in memory mapped mode, and the resulting value is a byte buffer based +type. This process allows the front end to avoid unnecessary copies in memory +mapped modes when working with subobjects.

    +
    enum an_ifc_source_location_part : uint8_t {};
    +using an_ifc_source_location_storage = an_ifc_source_location_part[8];
    +using an_ifc_source_location_bytes = const an_ifc_source_location_storage*;
    +
    +an_ifc_source_location_bytes stage_0;
    +
    +/* Update the universal storage pointer to the start of the field
    +   (KeywordSyntax::locus - SourceLocation). */
    +stage_0 = (an_ifc_source_location_bytes)((*universal.get_storage()) + 0);
    +
    +
    +

    This optimization is only performed when memory mapped mode is available as +otherwise it creates an unsafe implicit dependence. In said case, the value +retrieved from a node via a field accessor depends on the lifetime of the +owning node’s storage. In other words, without memory mapping, it’s possible +for the memory that owns the subobject to go out of scope.

    +
    +
    +

    16.3.9. Field Copying#

    +

    The respective implementation of both overloads of copy_ifc_field perform a +memcpy operation; this is an intentional choice over casting and +dereferencing the pointer.

    +

    This decision is also closely related to the usage of Byte Buffers +over dedicated structs representing each version (which have debugging benefits +over the chosen approach).

    +

    In the case of both decisions, the driving force behind this choice is +alignment. In the former case attempting to dereference an misaligned pointer +is undefined behavior. Thus, attempting to “avoiding the copy” via a +reinterpret_cast paired with a deference could lead to severe portability +issues, and – ironically – degraded performance. However, the memcpy +operation can be safely optimized and used, even for unaligned inputs. Thus, +the approach of usage a memcpy to copy data into known fixed size types +gives maximum performance without the associated portability concerns.

    +

    In the case of the latter decision specifically, the individual data members +within a struct will be padded differently on different host compilers, +operating systems, and different architectures (to comply with alignment +requirements). Thus, attempting to “overlay” a struct onto the underlying IFC +byte representation, results in similar severe portability issues.

    +
    +
    +

    16.3.10. Tacit Field#

    +

    A “tacit field” is a field that isn’t actually part of the official field list +for a node. Tacit fields are regularly used to expose information that’s +(indirectly) always present. For instance, a node might have no “home_scope” +field but the home scope can always be resolved via a different field.

    +

    As an example, consider the following made up node “FooDef” (which for +the sake of the hypothetical, pairs a declaration with a syntactic +definition):

    +
    + + + + + + + + + + + + + + +

    Field

    Type

    declaration

    DeclIndex

    definition

    SyntaxIndex

    +
    +

    Continuing with the hypothetical, in practice for “FooDef” nodes the +DeclIndex for declaration, when valid, always points to a node that has a +home_scope field. A tacit field exposes this invariant explicitly. From +the front end’s perspective, adding a tacit field for home_scope is +“as-if” the binary representation defined “FooDef” to be:

    +
    + + + + + + + + + + + + + + + + + +

    Field

    Type

    declaration

    DeclIndex

    definition

    SyntaxIndex

    home_scope

    DeclIndex

    +
    +

    This also exposes this invariant to the validator, which will then make sure +declaration points to a node with a home_scope field containing a valid +DeclIndex.

    +

    Not all tacit fields perform this sort of “proxy retrieval” operation, +effectively any invariant can be exposed and validated in this way.

    +
    +

    16.3.10.1. Impact on Versioning#

    +

    This conceptual breadth of functionality allows tacit fields play a large +role in supporting different IFC versions as well. Consider a later +revision of “FooDef” changes declaration so that the DeclIndex +sometimes points to a new intermediary node “FooProxyDecl”, which then +itself always points to a third node that has a home_scope.

    +

    Tacit fields allow this change to be “invisible” to existing logic. The +existing home_scope tacit field can be updated to follow the new rules +and properly retrieve the home_scope as one might expect. However, +tacit fields can also “replace” (or “override”) a field that’s explicitly +part of the binary node representation (i.e., “explicitly declared”) if +they share the same name.

    +

    In the context of this example, existing code might break – badly – when +it encounters the new intermediary “FooProxyDecl” node after a call to +the field accessor get_ifc_declaration(const an_ifc_foo_decl&). A new +declaration tacit field can be added that automatically “sees through” +the wrapper, “as-if” it was never added. The existing logic then goes back +to functioning as it did before, as from its perspective nothing changed.

    +

    Code that then needs to observe the new “FooProxyDecl” can then be +accounted for by adding additional tacit fields that either expose the +“true” value of declaration or information from “FooProxyDecl.”

    +

    The exact approach taken is situational, however, tacit fields are a powerful +tool for resolving versioning issues.

    +
    +
    +

    16.3.10.2. Tacit Field Implementation#

    +

    As noted in Nodes, field accessors work via “stages” +constructed from a “stage builder” in the code generation tool.

    +

    These can get exceptionally complicated in terms of implemented +code. Consider the following real example, taken verbatim from the front end:

    +
    template<>
    +an_ifc_decl_index get_ifc_home_scope(
    +                                   const an_ifc_decl_enumerator &universal)
    +/*
    +Given the universal representation of DeclEnumerator, return the universal
    +representation of the field "home_scope".
    +*/
    +{
    +  an_ifc_decl_index result;
    +
    +  /* Ensure the home_scope field exists in the current module version. */
    +  check_assertion(has_ifc_home_scope(universal));
    +  if (is_at_least(universal.get_module(), 0, 41)) {
    +    an_ifc_type_index_0_33 stage_0;
    +    an_ifc_type_index      stage_1;
    +    an_ifc_type_designated stage_2;
    +    an_ifc_decl_index_0_41 stage_3;
    +    an_ifc_decl_index      stage_4;
    +    a_boolean              stage_5;
    +    an_ifc_decl_index      stage_6;
    +
    +    /* Copy the field (DeclEnumerator::type - TypeIndex) into
    +       version-specific storage. */
    +    static_assert(sizeof(stage_0) == 4,
    +                  "stage_0 is not properly sized storage!");
    +    copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12);
    +    stage_1 = to_universal_index(universal.get_module(), stage_0);
    +    /* Use the obtained index to retrieve the appropriate instance of
    +       TypeDesignated (the type tag should have been prechecked by
    +       validation).  Then, retrieve and return the desired value held by
    +       the field decl. */
    +    construct_node_unchecked(&stage_2, stage_1);
    +    /* Copy the field (TypeDesignated::decl - DeclIndex) into
    +       version-specific storage. */
    +    static_assert(sizeof(stage_3) == 4,
    +                  "stage_3 is not properly sized storage!");
    +    copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0);
    +    stage_4 = to_universal_index(stage_2.get_module(), stage_3);
    +    if (stage_4.sort == ifc_ds_decl_specialization) {
    +      stage_5 = TRUE;
    +    } else {
    +      stage_5 = FALSE;
    +    }  /* if */
    +    if (stage_5) {
    +      an_ifc_decl_index          stage_6_0;
    +      an_ifc_decl_specialization stage_6_1;
    +      an_ifc_decl_index_0_41     stage_6_2;
    +      an_ifc_decl_index          stage_6_3;
    +
    +      stage_6_0 = stage_4;
    +      /* Use the obtained index to retrieve the appropriate instance of
    +         DeclSpecialization (the type tag should have been prechecked by
    +         validation).  Then, retrieve and return the desired value held by
    +         the field decl. */
    +      construct_node_unchecked(&stage_6_1, stage_6_0);
    +      /* Copy the field (DeclSpecialization::decl - DeclIndex) into
    +         version-specific storage. */
    +      static_assert(sizeof(stage_6_2) == 4,
    +                    "stage_6_2 is not properly sized storage!");
    +      copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4);
    +      stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2);
    +      stage_6 = stage_6_3;
    +    } else {
    +      an_ifc_decl_index stage_6_0;
    +
    +      stage_6_0 = stage_4;
    +      stage_6 = stage_6_0;
    +    }  /* if */
    +    result = stage_6;
    +  } else {
    +    an_ifc_type_index_0_33 stage_0;
    +    an_ifc_type_index      stage_1;
    +    an_ifc_type_designated stage_2;
    +    an_ifc_decl_index_0_33 stage_3;
    +    an_ifc_decl_index      stage_4;
    +
    +    /* Copy the field (DeclEnumerator::type - TypeIndex) into
    +       version-specific storage. */
    +    static_assert(sizeof(stage_0) == 4,
    +                  "stage_0 is not properly sized storage!");
    +    copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12);
    +    stage_1 = to_universal_index(universal.get_module(), stage_0);
    +    /* Use the obtained index to retrieve the appropriate instance of
    +       TypeDesignated (the type tag should have been prechecked by
    +       validation).  Then, retrieve and return the desired value held by
    +       the field decl. */
    +    construct_node_unchecked(&stage_2, stage_1);
    +    /* Copy the field (TypeDesignated::decl - DeclIndex) into
    +       version-specific storage. */
    +    static_assert(sizeof(stage_3) == 4,
    +                  "stage_3 is not properly sized storage!");
    +    copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0);
    +    stage_4 = to_universal_index(stage_2.get_module(), stage_3);
    +    result = stage_4;
    +  }  /* if */
    +  return result;
    +}  /* get_ifc_home_scope */
    +
    +
    +
    +
    16.3.10.2.1. Stage Breakdown#
    +

    This is an intimidating amount of logic, however it’s composed of bite sized +pieces of principled logic coming together. At a high level, there are two +cases here, one for IFC version 0.41+ and one for earlier supported versions of +the IFC.

    +

    Consider the “ earlier “ code (i.e., the code for supporting IFC versions +prior to 0.41, which will be known from this point as the 0.33+ code):

    +
    an_ifc_type_index_0_33 stage_0;
    +an_ifc_type_index      stage_1;
    +an_ifc_type_designated stage_2;
    +an_ifc_decl_index_0_33 stage_3;
    +an_ifc_decl_index      stage_4;
    +
    +/* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_0) == 4,
    +              "stage_0 is not properly sized storage!");
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12);
    +stage_1 = to_universal_index(universal.get_module(), stage_0);
    +/* Use the obtained index to retrieve the appropriate instance of
    +   TypeDesignated (the type tag should have been prechecked by validation).
    +   Then, retrieve and return the desired value held by the field decl. */
    +construct_node_unchecked(&stage_2, stage_1);
    +/* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_3) == 4,
    +              "stage_3 is not properly sized storage!");
    +copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0);
    +stage_4 = to_universal_index(stage_2.get_module(), stage_3);
    +result = stage_4;
    +
    +
    +

    The code generation tool represents this as in effect, a directly constructed +expression AST, simplifying a bit:

    +
    IFCRemoteDelegate(
    +  IFCDirectDelegate('type'),
    +  'Type',
    +  'TypeDesignated',
    +  'decl'
    +)
    +
    +
    +

    This is conceptually an “expression” representing the retrieval of the +value. The innermost operation IFCDirectDelegate is thus the first to be +evaluated.

    +

    While fully documenting the tacit field system within the code generation tool +is out of scope, for purposes of understanding, an IFCDirectDelegate simply +means “read the type field” from the node.

    +

    Similarly, IFCRemoteDelegate simply means “take the input value (the +type field value), it’s a Type(Index) that must point to a +TypeDesignated node, read said node’s decl field.”

    +

    The “stage builder” takes this expression and transforms it into a series of +“stages.”

    +
    +
    16.3.10.2.1.1. Stage 0#
    +

    Read the versioned value of the type field:

    +
    an_ifc_type_index_0_33 stage_0;
    +
    +/* snip */
    +/* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_0) == 4,
    +              "stage_0 is not properly sized storage!");
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12);
    +
    +
    +
    +
    +
    16.3.10.2.1.2. Stage 1#
    +

    Turn the versioned type field value into a universal value:

    +
    an_ifc_type_index_0_33 stage_0;
    +an_ifc_type_index      stage_1;
    +
    +/* snip */
    +stage_1 = to_universal_index(universal.get_module(), stage_0);
    +
    +
    +
    +
    +
    16.3.10.2.1.3. Stage 2#
    +

    Load the TypeDesignated node:

    +
    an_ifc_type_index      stage_1;
    +an_ifc_type_designated stage_2;
    +
    +/* Use the obtained index to retrieve the appropriate instance of
    +   TypeDesignated (the type tag should have been prechecked by validation).
    +   Then, retrieve and return the desired value held by the field decl. */
    +construct_node_unchecked(&stage_2, stage_1);
    +
    +
    +
    +
    +
    16.3.10.2.1.4. Stage 3#
    +

    Read the versioned value of the decl field from the TypeDesignated +node:

    +
    an_ifc_type_designated stage_2;
    +an_ifc_decl_index_0_33 stage_3;
    +
    +/* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_3) == 4,
    +              "stage_3 is not properly sized storage!");
    +copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0);
    +
    +
    +
    +
    +
    16.3.10.2.1.5. Stage 4#
    +

    Turn the versioned decl field value into a universal value:

    +
    an_ifc_decl_index_0_33 stage_3;
    +an_ifc_decl_index      stage_4;
    +
    +stage_4 = to_universal_index(stage_2.get_module(), stage_3);
    +result = stage_4;
    +
    +
    +
    +
    +
    16.3.10.2.1.6. Stage 5 (Wrap-up)#
    +

    Assign the result:

    +
    an_ifc_decl_index      stage_4;
    +
    +result = stage_4;
    +
    +
    +

    The stage builder facilitates the creation of these stages from the expression, +creating a metaphorical “data retrieval pipeline.” The usage of expression +nodes and this system of generating C++ stages from these nodes, allows tacit +fields to be quickly written via reusable building blocks.

    +

    Examination of the validation logic will reveal it’s very similar to the logic +generated for field data retrieval, however rather than returning a result, it +performs a number of checks to make sure the would-be result and everything +required in-between is validated as necessary.

    +
    +
    +
    +
    16.3.10.2.2. Advanced Stage Breakdown#
    +

    After establishing an understanding of the flow of the 0.33+ code, consider the +0.41+ code:

    +
    an_ifc_type_index_0_33 stage_0;
    +an_ifc_type_index      stage_1;
    +an_ifc_type_designated stage_2;
    +an_ifc_decl_index_0_41 stage_3;
    +an_ifc_decl_index      stage_4;
    +a_boolean              stage_5;
    +an_ifc_decl_index      stage_6;
    +
    +/* Copy the field (DeclEnumerator::type - TypeIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_0) == 4,
    +              "stage_0 is not properly sized storage!");
    +copy_ifc_field(&stage_0, universal.get_storage(), /*offset=*/12);
    +stage_1 = to_universal_index(universal.get_module(), stage_0);
    +/* Use the obtained index to retrieve the appropriate instance of
    +   TypeDesignated (the type tag should have been prechecked by validation).
    +   Then, retrieve and return the desired value held by the field decl. */
    +construct_node_unchecked(&stage_2, stage_1);
    +/* Copy the field (TypeDesignated::decl - DeclIndex) into version-specific
    +   storage. */
    +static_assert(sizeof(stage_3) == 4,
    +              "stage_3 is not properly sized storage!");
    +copy_ifc_field(&stage_3, stage_2.get_storage(), /*offset=*/0);
    +stage_4 = to_universal_index(stage_2.get_module(), stage_3);
    +if (stage_4.sort == ifc_ds_decl_specialization) {
    +  stage_5 = TRUE;
    +} else {
    +  stage_5 = FALSE;
    +}  /* if */
    +if (stage_5) {
    +  an_ifc_decl_index          stage_6_0;
    +  an_ifc_decl_specialization stage_6_1;
    +  an_ifc_decl_index_0_41     stage_6_2;
    +  an_ifc_decl_index          stage_6_3;
    +
    +  stage_6_0 = stage_4;
    +  /* Use the obtained index to retrieve the appropriate instance of
    +     DeclSpecialization (the type tag should have been prechecked by
    +     validation).  Then, retrieve and return the desired value held by the
    +     field decl. */
    +  construct_node_unchecked(&stage_6_1, stage_6_0);
    +  /* Copy the field (DeclSpecialization::decl - DeclIndex) into
    +     version-specific storage. */
    +  static_assert(sizeof(stage_6_2) == 4,
    +                "stage_6_2 is not properly sized storage!");
    +  copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4);
    +  stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2);
    +  stage_6 = stage_6_3;
    +} else {
    +  an_ifc_decl_index stage_6_0;
    +
    +  stage_6_0 = stage_4;
    +  stage_6 = stage_6_0;
    +}  /* if */
    +result = stage_6;
    +
    +
    +

    Here stages 0 through 4 are identical to the 0.33+ code, however additional +stages have been added (i.e., the “pipeline” has been extended). Stage 6 is +particularly interesting as it works with substages.

    +

    To understand what’s going on here, consider the following simplified code from +the code generation tool:

    +
    existing_logic = IFCRemoteDelegate(
    +  IFCDirectDelegate('type'),
    +  'Type',
    +  'TypeDesignated',
    +  'decl'
    +)
    +source_value = IFCReusableResult(existing_logic)
    +
    +IFCConditionalDelegate(
    +  IFCTestSortMatch(
    +    source_value,
    +    'Decl',
    +    {'DeclSpecialization'}
    +  ),
    +  'DeclIndex',
    +  IFCRemoteDelegate(
    +    source_value,
    +    'Decl',
    +    'DeclSpecialization',
    +    'decl'
    +  ),
    +  source_value
    +)
    +
    +
    +

    The existing_logic, the associated IFCRemoteDelegate, and +IFCDirectDelegate were already covered, so those won’t be +revisited. However, IFCReusableResult, IFCTestSortMatch, and +IFCConditionalDelegate are new.

    +

    IFCReusableResult can be thought of like a lazily-evaluated, “memoization +instruction.” This allows reuse of the same value without reevaluation.

    +

    IFCTestSortMatch means “take the input value (the possibly memoized +TypeDesignated decl field value), evaluate true if its Decl(Sort) +value is DeclSpecialization; otherwise, evaluate false.”

    +

    IFCConditionalDelegate means “compute a DeclIndex value one of two +ways, if the input value (the test sort match) evaluates as true use the +first sub-expression, otherwise use the second.”

    +

    IFCConditionalDelegates are particularly notable as they allow logic +to have branched evaluation. When these branches are translated to C++ +code, these are implemented via substages (effectively stage builders that +inherent a prefix and their input from a parent stage builder’s stage).

    +

    Note how this all composes to allow the existing logic to be sanely extended. +Looking at what’s new, stage 5 is where things diverge.

    +
    +
    16.3.10.2.2.1. Stage 5#
    +

    The resulting DeclIndex is check to see if its sort is a +DeclSpecialization, storing the result as a boolean value:

    +
    an_ifc_decl_index      stage_4;
    +a_boolean              stage_5;
    +
    +if (stage_4.sort == ifc_ds_decl_specialization) {
    +  stage_5 = TRUE;
    +} else {
    +  stage_5 = FALSE;
    +}  /* if */
    +
    +
    +
    +
    +
    16.3.10.2.2.2. Stage 6 (Wrap-up)#
    +

    The previous result of the DeclSpecialization sort test is used, forking to +evaluate one of two sub-expressions before the result is assigned:

    +
    if (stage_5) {
    +  /* substage content */
    +} else {
    +  /* substage content */
    +}  /* if */
    +result = stage_6;
    +
    +
    +

    The first sub-expression (when a DeclSpecialization is used) unwraps +the decl field value from the DeclSpecialization node, storing the +result in stage 6:

    +
    an_ifc_decl_index          stage_6_0;
    +an_ifc_decl_specialization stage_6_1;
    +an_ifc_decl_index_0_41     stage_6_2;
    +an_ifc_decl_index          stage_6_3;
    +
    +stage_6_0 = stage_4;
    +/* Use the obtained index to retrieve the appropriate instance of
    +   DeclSpecialization (the type tag should have been prechecked by
    +   validation).  Then, retrieve and return the desired value held by the
    +   field decl. */
    +construct_node_unchecked(&stage_6_1, stage_6_0);
    +/* Copy the field (DeclSpecialization::decl - DeclIndex) into
    +   version-specific storage. */
    +static_assert(sizeof(stage_6_2) == 4,
    +              "stage_6_2 is not properly sized storage!");
    +copy_ifc_field(&stage_6_2, stage_6_1.get_storage(), /*offset=*/4);
    +stage_6_3 = to_universal_index(stage_6_1.get_module(), stage_6_2);
    +stage_6 = stage_6_3;
    +
    +
    +

    The second sub-expression (when a DeclSpecializtion is not used) passes +through the value as a no-op:

    +
    an_ifc_decl_index stage_6_0;
    +
    +stage_6_0 = stage_4;
    +stage_6 = stage_6_0;
    +
    +
    +

    Note that even though the second sub-expression ends up being generated as an +effective no-op case with no special processing of its own, a substage +(stage_6_0) is initialized. There is no special meaning to this, it’s merely an +implementation detail that falls out from the semantics of the code generation +tool. This may be improved in future revisions, but it’s largely a visual +defect that gets cleaned up during optimization.

    +
    +
    +
    +
    +
    +

    16.3.11. Validation#

    +

    The IFC validation system is designed to check all data read from the IFC file +while being “out of the way”, performant, and extendable.

    +
    +

    16.3.11.1. Point of Validation#

    +

    Data is validated upon construction of a node, namely within the +construct_node function (via a call to the validate function +corresponding to the node). This validation covers all get_ifc_X return +values (and in the case of Tacit Field, any intermediate data).

    +

    The validation system leverages the stage builder (for more information +about stages in general, see Stages) system used to create +the get_ifc_X functions themselves. The stage builder knows how to +create not only the typical “data retrieval pipeline”, but one which +validates the intermediate steps, and the returned data.

    +

    The extent of the validation depends on the role associated with the type +being validated.

    +
    +
    16.3.11.1.1. Simple Sort#
    +

    Simple Sort validation ensures that the input value corresponds +to a valid simple sort value for the current IFC version and simple sort type.

    +
    +
    +
    16.3.11.1.2. Index Sort#
    +

    Index Sort validation first checks the associated +Simple Sort for validation issues, then ensures that the +requested element exists in the associated partition. This latter step can be +thought of as a sort of pointer validation, it doesn’t ensure the validity of +the data being pointed to, but it does ensure the pointer itself is valid.

    +
    +
    +
    16.3.11.1.3. Nodes#
    +

    Nodes sometimes appear within other nodes (for more +information, see Basic Node). In these cases, the validator +recurses into the sub-node and also ensures the validity of its fields. This +reduces the number of calls required to work with sub-nodes, and improves +diagnostics (by providing extra context to work with).

    +
    +
    +
    16.3.11.1.4. Value Categories#
    +

    Value Category validation similar to Index Sort +validation first checks the associated Simple Sort for +validation issues. The respective variant is then validated as necessary.

    +
    +
    +
    +

    16.3.11.2. Validation Cache#

    +

    The validation system is made more efficient by a bit-based caching mechanism.

    +

    Each partition position in the IFC has its validation status represented as two +bits that are part of a 32-bit integer. The higher 16 bits are used to +represent an “invalid” flag while the lower 16 bits are used to represent a +“validated” flag. The choice to represent “invalid” status instead of “valid” +status is deliberate to minimize the number of writes to the validation cache +for a valid IFC file.

    +

    These 32-bit integers are themselves part of an array that’s allocated +per-partition representing all elements in the partition. The cache thus has +both high locality and high space efficiency.

    +

    When a node is constructed via construct_node the validation cache is +checked, and if the node has already been validated, the cached validation +status will be reused rather than rerunning the validate function for the +node.

    +

    The caching process also provides – as an adverse affect – a guarantee that +validation diagnostics are only emitted once.

    +
    +
    +

    16.3.11.3. Skipping Validation#

    +

    In general, data validation should not be skipped. However, in some cases it’s +desirable to skip validation.

    +
    +
    16.3.11.3.1. Pre-checked Data#
    +

    construct_node_prechecked can be useful as an optimization in places where +it’s known – with certainty – that the node being constructed has previously +been validated.

    +

    Note that when CHECKING is enabled this function will check the validation +cache to ensure that the node being constructed truly was previously validated.

    +
    +
    +
    16.3.11.3.2. Unchecked Data#
    +

    construct_node_unchecked can be used as part of low level implementation +details that can safely ignored validation status (or code that takes special +care to ensure safe usage). It’s important to emphasize, this function truly +bypasses all checks, and thus can introduce unsafe data or crashes if used +improperly.

    +

    An example of a time this function is useful is the find_trait +function. Traits are found via a binary search, attempting to validate the data +during the search would significantly degrade performance, and might lead to a +large number of unnecessary diagnostics about data that’s never used. The usage +is made safe as after the search completes the final result (if any) is +validated.

    +
    +
    +
    +
    +

    16.3.12. Visitors#

    +

    The visitor system is designed to allow the use of get_ifc_X +functions on a given Index Sort value. As an example, +consider the following:

    +
    an_ifc_decl_index decl_idx = ...;
    +an_ifc_decl_index home_scope_idx = get_ifc_home_scope(decl_idx);
    +
    +
    +

    This is not a field accessor as described in the Nodes section. +Instead, this function will load the appropriate node for the index, and then +delegate to that node’s field accessor of the same name. It’s thus in essence, +equivalent to writing:

    +
    switch (decl_idx.sort) {
    +  case ifc_ds_decl_function:
    +    { an_ifc_decl_function universal;
    +
    +      construct_node_prechecked(&universal, decl_idx);
    +      home_scope_idx = get_ifc_home_scope(universal);
    +    }
    +    break;
    +}  /* switch */
    +
    +
    +

    Note that this has some limitations, namely, the sort has to point to a node +that has the given field name for the current IFC version, and the node has to +have been previously validated.

    +

    To accommodate these limitations additional visitors are exposed for the +corresponding has_ifc_X function (for more information, see: +Field Presence Checking) and for node validation.

    +

    Thus, in most cases the correct usage looks something like the following:

    +
    an_ifc_decl_index decl_idx = ...;
    +an_ifc_decl_index home_scope_idx;
    +
    +/* Check if a valid version of the node pointed to by this decl_idx would
    +   ever have a valid home_scope */
    +if (has_ifc_home_scope(decl_idx)) {
    +  /* Make sure we're working with a valid node */
    +  if (validate(decl_idx)) {
    +    /* Guaranteed retrieval of a valid home scope index. */
    +    home_scope_idx = get_ifc_home_scope(decl_idx);
    +  }  /* if */
    +}  /* if */
    +
    +
    +

    This is often just simplified to:

    +
    an_ifc_decl_index decl_idx = ...;
    +an_ifc_decl_index home_scope_idx;
    +
    +if (has_ifc_home_scope(decl_idx) && validate(decl_idx)) {
    +  home_scope_idx = get_ifc_home_scope(decl_idx);
    +}  /* if */
    +
    +
    +
    +

    16.3.12.1. Passthrough#

    +

    In the case of certain nodes, a reasonable answer can be obtained, but is not +implicitly present. For these cases, an “implicit dereference” is added to the +code generation tool. These allow visitors to recurse using the “dereferenced” +value.

    +

    As an example, consider the following:

    +
    # Implicit dereferencing on the DeclIndex.
    +'Decl': {
    +  # Implicitly dereference DeclReference via the get_ifc_index function.
    +  'DeclReference': 'get_ifc_index'
    +}
    +
    +
    +

    This is an implicit dereference on the Decl Index Sort, that +applies the requested traversal to the result of a DeclReference’s +get_ifc_index field accessor.

    +

    In generated code, this looks something like the following:

    +
    case ifc_ds_decl_reference:
    +  { an_ifc_decl_reference universal;
    +
    +    construct_node_prechecked(&universal, idx);
    +
    +    an_ifc_decl_index remote_idx = get_ifc_index(universal);
    +    result = get_ifc_home_scope(remote_idx);
    +  }
    +  break;
    +
    +
    +

    This notably also applies to the has_ifc_X function:

    +
    case ifc_ds_decl_reference:
    +  { Opt<an_ifc_decl_reference> opt_universal;
    +
    +    construct_node(&opt_universal, idx);
    +    if (opt_universal.has_value()) {
    +      an_ifc_decl_index remote_idx = get_ifc_index(*opt_universal);
    +
    +      if (has_ifc_home_scope(remote_idx)) {
    +        result = TRUE;
    +      }  /* if */
    +    }  /* if */
    +  }
    +  break;
    +
    +
    +

    Thus, in contrast to an Tacit Field, a visitor is much more lenient +form of data retrieval, often used both in instances of “may-have” as opposed +to instances of “must-have.”

    +
    +
    +

    16.3.12.2. Implicit Conversion#

    +

    Some visitors are additionally configured with implicit conversions. These +conversions allow the visitor to return one return type while the underlying +get_ifc_X field accessors return different types.

    +

    As an example, the IFC’s TextOffset can be represented as a +NameIndex. Thus, to allow for one get_ifc_name visitor, a conversion is +added.

    +
    +
    +

    16.3.12.3. Limited Scope#

    +

    As most fields don’t need exposed by visitors, generating every possible +visitor could get quite expensive (both for the code generation tool and for +build times). Thus, instead, the code generation tool requires desired visitors +to be explicitly listed.

    +

    For instance, to define a simple visitor to expose the home_scope DeclIndex:

    +
    # Add a visitor over the Decl index for get_ifc_home_scope returning
    +# an_ifc_decl_index with no conversions.
    +(
    +  'Decl',
    +  'home_scope',
    +  'an_ifc_decl_index',
    +  {}
    +)
    +
    +
    +

    In more advanced cases like the +aforementioned get_ifc_name visitor, +conversions are specified like so:

    +
    # Add a visitor over the Decl index for get_ifc_name returning
    +# an_ifc_name_index with a potential conversion from a an_ifc_text_offset
    +# to an_ifc_name_index.
    +(
    +  'Decl',
    +  'name',
    +  'an_ifc_name_index',
    +  {
    +    'conversions': {
    +      'an_ifc_text_offset': IFCTextOffsetToNameIndex()
    +    }
    +  }
    +)
    +
    +
    +
    +
    +
    +
    +

    16.4. Partition Kinds#

    +

    The generation tool manages a list of partition kinds known to said tool (and +thus the front end).

    +

    These partition kinds are exposed via the an_ifc_partition_kind enum with +an additional ifc_pk_none value written to represent invalid states.

    +

    The total number of IFC partition kinds known to the front end (not including +ifc_pk_none) can be retrieved via the IFC_PARTITION_COUNT macro.

    +

    A alphabetically sorted mapping of IFC partition kind names to +an_ifc_partition_kind values (not including ifc_pk_none) named +ifc_partition_map is also maintained to enable binary search based mapping +between a given IFC partition kind name and the corresponding front end value +used for its representation.

    +

    As this mapping is extensive (with the exception of ifc_pk_none) +ifc_partition_mapping[partition_kind - 1].name can be used to retrieve the +name of any an_ifc_partition_kind value in constant time.

    +

    Additionally, the associated relationships between partition kinds and other +roles is also captured by several utility functions.

    +
    +

    16.4.1. get_ifc_partition_kind#

    +

    Some operations require knowing the partition kind associated with a given node +type. The get_ifc_partition_kind<T> explicit template specializations +expose this information via template instantiation.

    +
    +
    +

    16.4.2. get_ifc_partition_element_size#

    +

    Some operations require knowing the expected element size for a given partition +at a given IFC version. The get_ifc_partition_element_size function +provides this functionality taking a module and partition kind and returning +the expected size.

    +
    +
    +

    16.4.3. has_partition_kind#

    +

    Some operations require knowing whether or not a given +Simple Sort value has an associated partition kind. The +has_partition_kind functions take a simple sort and return TRUE if the +sort has an associated partition kind, otherwise they return FALSE.

    +
    +
    +

    16.4.4. to/from_partition_kind#

    +

    Some operations require a transition from an Index +Sort’s Simple Sort to a partition sort or +vice versa.

    +

    The to_partition_kind functions take a Simple Sort and +convert the sort to an_ifc_partition_kind.

    +

    Conversely, the to_X sort functions take an_ifc_partition_kind and +convert it to the desired Simple Sort.

    +

    Note that in both cases, any conversion failures will result in a crash.

    +
    +
    +
    +

    16.5. Debugging#

    +
    +

    16.5.1. Nodes#

    +

    As noted in the Field Copying subsection, to provide a portable +implementation of IFC Deserialization, sacrifices +were made that negatively impact the debugger experience of working with IFC +Nodes.

    +

    To mitigate this issue, DEBUG builds of the front end include db_node +functions which can be invoked to get a pretty-printed summary of the node’s +contents from within the debugger.

    +

    Consider the following:

    +
    an_ifc_decl_alias foo = ...;
    +/* break point */
    +
    +
    +

    When debugging this code, the db_node(const an_ifc_decl_alias &universal) +function (in most cases invoked simply as db_node(foo)) can be used to +print the node contents.

    +

    This results in output similar to the following:

    +
    =============================== DeclAlias ================================
    +access: AccessSort::None
    +aliasee:
    +  sort: TypeSort::TypePointer
    +  value: 0
    +home_scope: NULL
    +locus:
    +  column: 22
    +  line: 2
    +name: 189
    +specifiers:
    +  - C
    +  - Cxx
    +  - IsMemberOfGlobalModule
    +type:
    +  sort: TypeSort::TypeFundamental
    +  value: 0
    +
    +
    +
    +
    +
    +

    16.6. Code Organization#

    +

    This system generates a lot of code, as a result, to keep the front end build +times down code has been carefully organized and separated to prevent any one +translation unit from having an excessive impact on the build time.

    +

    The code generated files currently include:

    +
      +
    • ifc_map.h - A forward declaration of all types so they can be used in +ifc_module.h without polluting ifc_module.h with a large number of +functions.

    • +
    • ifc_map_functions.h - The forward declarations of functions imported in +files that need access to low level IFC reading operations.

    • +
    • ifc_map_functions.c - The implementation of functions declared in +ifc_map_functions.h that do not have a more specific implementation file.

    • +
    • ifc_map_functions_acc.c - The implementation of all IFC field accessor +functions.

    • +
    • ifc_map_functions_dbg.c - The implementation of all IFC debug functions.

    • +
    • ifc_map_functions_val.c - The implementation of all IFC validation +functions.

    • +
    • ifc_modules_inst.h - A list of macros imported in ifc_modules_templ.c +to manage explicit template instantiations.

    • +
    • ifc_modules_spec.h - A list of macros imported in ifc_modules_templ.c +to manage explicit template specializations.

    • +
    +

    Note that Visitor implementations are currently +found in ifc_map_functions.c.

    +

    The portion of the front end that handles deserialization is primarily found in +ifc_modules_read.c. The portion of the front end that handles +serialization is primarily found in ifc_modules_write.c. Code that is +common between the two is found in ifc_modules_internal.h and +ifc_modules.c.

    +

    All supporting template definitions and instantiations (that used by a mix of +ifc_modules.c, ifc_modules_read.c, ifc_modules_write.c`, and the +ifc_map_functions*.c files) are isolated to ifc_modules_templ.c, +preventing multiple translation units from instantiating the same template.

    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/objects.inv b/doc/objects.inv new file mode 100644 index 0000000..fe381f2 Binary files /dev/null and b/doc/objects.inv differ diff --git a/doc/pragma/index.html b/doc/pragma/index.html new file mode 100644 index 0000000..f71a23d --- /dev/null +++ b/doc/pragma/index.html @@ -0,0 +1,1147 @@ + + + + + 15. Pragmas and Attributes - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    15. Pragmas and Attributes#

    +

    Support for the processing of #pragma directives appears in several files +(including preproc.c, lexical.c, and il.c), but the principal +routines are in pragma.c. pragma.h and il_def.h contain +definitions of the data structures that are used.

    +

    Standard attributes, GNU attributes, and Microsoft __declspec attributes +are like pragmas in their semantic scope (i.e., a generic mechanism for small +language extensions), but unlike pragmas they fit in ordinary grammar-based +based front end processing. The principal routines for attribute processing +are in attribute.c (and attribute.h); the main data structures are in +il_def.h.

    +
    +

    15.1. Introduction to Pragma Processing#

    +

    Pragma processing differs from other front end processing in several ways. +Pragmas are scanned as part of the inter-token processing of the lexical +routines, yet the actual interpretation of the pragmas must be performed at a +suitable point in the syntactic and semantic processing of the front end. In +fact tokens may need to be scanned far in advance of when they are actually +used, and so pragmas may be encountered at the lexical level when it is +impossible for them to be fully processed. This occurs in scanning the bodies +of template definitions, in doing the lookahead to disambiguate declarations +and expressions, and so forth.

    +

    Moreover, it is clear that the “suitable point in syntactic and semantic +processing” where the pragma is interpreted will be different for different +pragmas. And some pragmas simply carry information for use by the back end and +do not affect front-end processing at all. Each pragma has special +requirements.

    +

    Pragmas are also unusual because, by definition, they are specific to a given +implementation. The mechanism that the EDG front end provides is intended to +make it relatively easy for customers to add pragmas and to customize how they +are processed, from how they are tokenized to how IL pragma entries are +generated. The handful of pragmas that are supplied by default with the EDG +front end can serve as prototypes for such customization.

    +

    A pivotal role in pragma processing is played by an entry of type +a_pending_pragma, a front-end-only repository of information about a +specific #pragma directive in the source. It is “pending” in that it is +awaiting interpretation, after which it is disposed of. Interpreting a pragma +may mean setting a flag in a symbol, causing a diagnostic to be suppressed, +creating an IL pragma entry to pass information on to the back end, and so +forth.

    +

    Pragma processing can be summarized as consisting of three steps:

    +
      +
    1. The #pragma directive that appears in the source code is identified and +recorded in a pending pragma entry. Although most pragmas are simply +recorded for later interpretation, “preprocessing immediate” pragmas are +dispatched immediately upon being recognized by the preprocessing +routines.

    2. +
    3. The pending pragma entry is “dispatched” – i.e., made available for +additional processing by being placed on a list where it can be found +later.

    4. +
    5. The pending pragma entry is interpreted, with its message transferred to +another form (e.g., a flag is set somewhere), and then it is disposed +of.

    6. +
    +

    Pragmas must be recognized to be processed, and once they have been recognized +much of the processing is table-driven. The key pieces of information about +every pragma are:

    +
      +
    • +
      The pragma kind – an element of the enumeration a_pragma_kind (defined +in il_def.h). Every pragma that is recognized corresponds to one +pragma kind.
      +
      +
    • +
    • +
      The pragma-id – the identifier string that follows the #pragma keyword +and that may be looked up in the array pragma_ids (defined in +il_def.h) to determine the pragma kind.
      +
      +
    • +
    • +
      The pragma kind description – a data structure of type +a_pragma_kind_description (defined in pragma.h and available to the +front end only) that summarizes the attributes and processing requirements +of a given pragma.
      +
      +
    • +
    +

    When the pragma has been recognized, much of the processing is governed by the +corresponding pragma kind description, which contains information such as how +(and whether) the pragma binds to an IL construct, whether the pragma is +intended to be processed by the front end or back end, and how tokens that +comprise the pragma should be passed from the point at which the pragma is +initially scanned to the point at which the pragma is semantically processed. +The pragma kind description also contains an optional processing function +pointer, which, if present, points to a function to be called to process this +kind of pragma.

    +

    pragma_description_for_pragma_kind is an array of pointers to pragma kind +descriptions that may be indexed by pragma kind. It is initialized in +pragma_init by a series of calls to add_pragma_kind_description.

    +
    +
    +

    15.2. Phase One: Recording Pragmas#

    +

    Pragma directives are initially scanned by the routine proc_pragma, which +is one of the preprocessing routines in preproc.c. As mentioned earlier, +the initial scanning of the pragma may occur far too early for the pragma to be +processed in any meaningful way. The most extreme example of this is a +template definition containing a pragma that must be reevaluated for each +instantiation generated from the template.

    +

    To accommodate this kind of use, the initial scanning of a pragma typically +consists simply of identifying the kind of pragma being scanned, and recording +the body of the pragma in a form in which it may easily be processed later. +Preprocessing immediate pragmas are the exception to this rule, and are +dispatched immediately upon being identified by the preprocessing routines.

    +

    Pragmas are expected to have the form

    +
    +

    #pragma identifier token1 token2 token3 …

    +
    +

    The pragma kind is determined by comparing the identifier with each the +elements of the array pragma_ids. Once the pragma kind has been +determined, the associated pragma kind description determines how the body of +the pragma is to be recorded. The body may be recorded as either a token cache +or a character string. Most pragmas will be recorded as token caches since +this is usually the easiest representation for the front end to use later. +Pragmas that are to be reemitted by the C or C++ generating back end must be +recorded as character strings.

    +

    When a pragma is recorded as a token cache, the pragma kind description +specifies how the lexical routines should tokenize the pragma body. +Specifically, it specifies whether macros should be expanded and whether the +recognition of certain preprocessing tokens (e.g., # and ##) should be +disabled. Typically both of these flags would be FALSE, but when scanning a +pragma containing what looks like a source language construct (as is the case +with the instantiation pragmas) these fields would be TRUE.

    +

    If the configuration parameter INCLUDE_UNRECOGNIZED_PRAGMAS_IN_IL is TRUE, +any pragma identifier that is not recognized is processed using the pragma kind +description associated with the pk_unrecognized pragma kind.

    +

    To record the pragma a pending pragma entry is allocated (see +alloc_pending_pragma in pragma.c), and the pragma representation (token +cache or text) is attached to it. A pragma is associated with a token that +immediately follows it in the source, so the newly created pending pragma entry +is appended to curr_token_pragmas, a list of pending pragma entries that +are associated with the current token (see add_to_curr_token_pragma_list).

    +

    Since the current token may be cached, the list of pending pragma entries +associated with it is cacheable, too (see add_pragma_entry_to_cache in +lexical.c). When a token is cached, the pragmas associated with it are +recorded in the cache as well, and when the token is retrieved from the cache +the associated pragmas are restored as the current_token_pragmas list. If +the cache from which the token was retrieved is a reusable cache, a copy of the +pragma list is made (instead of using the original list).

    +

    Pending pragma entries are also created to represent “pseudo pragmas”, +constructs that are processed by the front end like pragmas even though they +are not actually represented in the source code by a pragma directive. Thus, +lint comments are implemented as pseudo pragmas; e.g., when a /*ARGSUSED*/ +comment is encountered, the front end generates a pk_lint_argsused pragma +entry, and all subsequent processing is handled just like a pragma specified +using a #pragma directive.

    +
    +
    +

    15.3. Phase Two: Dispatching Pragmas#

    +

    The result of the initial scanning process is curr_token_pragmas, a list of +pending pragma entries that represent the pragmas immediately preceding the +current token. However, the pragma is not subject to further processing simply +as a consequence of being associated with the current token. For example, with

    +
    #pragma xyz
    +int a;
    +
    +
    +

    the xyz pragma is on the current token pragma list for int but is not +made available for additional processing until processing begins on the +construct that int introduces or else until the next token, a, is about +to fetched. This convention is followed to avoid processing the pending pragma +entry prematurely – we wouldn’t want to process pragma xyz if there is a +chance token int will end up in a token cache.

    +

    The pending pragma entries on the curr_token_pragmas list are dispatched +for additional processing either by select_curr_construct_pragmas or by +process_curr_token_pragmas. These routines do most of the middle phase +processing of pending pragma entries. How they differ and how they interact +can be explained in terms of pragma binding kinds.

    +

    Each pragma kind specifies one of three pragma binding kinds [1]; each +binding kind represents a different processing pathway; and each form of +processing implies a different form of dispatching.

    +
      +
    • +
      Pending pragma entries with a binding kind of pbk_immediate and +pbk_next_token are processed immediately at the point the current token +is consumed. Such pragmas may appear anywhere in the program, and though +they may be recorded in the IL, they are not bound to any particular IL +entity (the difference between pbk_immediate and pbk_next_token is +described below).
      +
      +
    • +
    • +
      Pending pragma entries with a binding kind of pbk_next_construct are +subject to processing during the processing of the given statement or +declaration. They must appear immediately before the first token of the +construct to which they will be bound. If they appear in the IL, they will +be bound to a particular IL entity.
      +
      +
    • +
    • +
      Pending pragma entries with a binding kind of pbk_other are not subject +to processing at any particular time – that is up to the implementation. +They may appear anywhere in the source program. They are dispatched onto a +list to wait for a processing function to check for them; if they are not +explicitly handled and removed, they simply remain there until the scope +they belong to is terminated.
      +
      +
    • +
    +
    +

    15.3.1. Bound Pragmas#

    +

    select_curr_construct_pragmas is called at the start of each new +declaration or statement. It is always called before advancing past the first +token of the construct; this is to ensure that it is called before +process_curr_token_pragmas is called. Its principal job is go through the +curr_token_pragmas list, removing each pbk_next_construct entry and +dispatching it to a list specifically reserved for pragmas bound to the current +construct, the curr_construct_pragmas list in the current scope stack +entry. The pragmas wait on the list to be processed sometime during the +processing of the current construct.

    +

    The pending pragma entries associated with the current construct will remain on +the list to which they are dispatched only for the life of the declaration or +statement. If the current construct cannot be bound to (this is the case, for +example, with the declaration of an unnamed enumeration or a break +statement), cannot_bind_to_curr_construct is called to issue diagnostics, +if appropriate, and clear the list. If, usually as a result of an error, the +processing of the pending pragma entries cannot be completed, +discard_curr_construct_pragmas is called to clear the list.

    +

    Normally, therefore, when select_curr_construct_pragmas is called, the list +it updates will have been cleared, since entries on the list for the previous +construct will already have been disposed of by the time the current construct +is dealt with. An exception is when a pragma precedes a label: such a pragma +is construed as applying not to the label but to the construct following, so it +must be preserved on the curr_construct_pragmas list as processing advances +past the label. In such situations pending pragma entries may accumulate, +e.g., for this case

    +
    #pragma some_pragma
    +l:
    +#pragma another_pragma
    +f();
    +
    +
    +

    both pragmas can end up bound to the call of function f.

    +

    Another job of select_curr_construct_pragmas, when source sequence entries +are being generated, is to add a source sequence entry for each pending pragma +entry on the curr_token_pragmas list. If an IL entry is subsequently +created for the pragma, it uses the source sequence entry; otherwise, the +source sequence entry is returned to an available list.

    +
    +
    +

    15.3.2. Unbound Pragmas#

    +

    process_curr_token_pragmas is called each time the current token is about +to be consumed and a new token is about to become the current token. Its job +is to handle pending pragma entries that remain on the curr_token_pragmas +list and then to clear that list before the next token is taken.

    +

    If it finds a pbk_immediate or pbk_next_token pragma on the list, it +initiates the completion of its processing. There is no dispatching of these +pragmas. They are processed immediately and automatically. In non-cached +contexts, pbk_immediate pragmas will have already been procesed when +process_curr_token_pragmas is called and will be ignored.

    +

    pbk_other pragmas are dispatched to a list of the pragmas that are +currently available for further processing in a given scope – see +pending_pragmas in a_scope_stack_entry. The pending pragma entry is +placed on the list of the current scope and is discarded when the current scope +terminates. Such a pragma simply waits on the list until some event removes it +to complete its processing; there is no default mechanism to trigger such +processing automatically.

    +

    Since select_curr_construct_pragmas will already have been called, there +should not be any pbk_next_construct entries remaining on the +curr_token_pragmas list. If there are, they must have appeared in the +source somewhere other than immediately before a declaration or statement. +process_curr_token_pragmas removes them from the list, optionally issuing a +diagnostic of the severity specified in the corresponding pragma kind +description.

    +

    If source sequence entries are being generated, process_curr_token_pragmas +will also add source sequence entries for each pending pragma entry that needs +one. If an IL entry is subsequently created for the pragma, it uses that +source sequence entry; otherwise, the source sequence entry is returned to an +available list.

    +
    +
    +
    +

    15.4. Phase Three: Interpreting Pragmas#

    +

    The pragma representations that result from the scanning of pragmas are called +“pending pragmas” because, having been created as repositories of uninterpreted +information about a specific pragma directive, they wait around for the right +moment for their processing to be completed. The completion can be described +as the “interpretation” of the pragma – its translation into another form so +that it will have the intended effect on subsequent compilation.

    +

    The different pragma binding kinds indicate, as noted above, different +processing pathways:

    +
      +
    • +
      Pending pragma entries with a binding kind of pbk_next_token are +processed automatically by process_curr_token_pragmas, at the point the +current token is consumed.
      +
      +
    • +
    • +
      Pending pragma entries with a binding kind of pbk_immediate are +processed immediately after they have been scanned. In cached contexts +they are also processed by process_curr_token_pragmas (in the same way +as pbk_next_token pragmas) each time the cache is rescanned.
      +
      +
    • +
    • +
      Pending pragma entries with a binding kind of pbk_next_construct are +subject to processing during the processing of the given statement or +declaration. Either they are processed as the result of an explicit action +involving a call to extract_specific_pragmas, or else the processing is +initiated automatically when (at an appropriate point, depending on the +construct they are associated with) process_curr_construct_pragmas is +called.
      +
      +
    • +
    • +
      Pending pragma entries with a binding kind of pbk_other are subject to +processing only as the result of an explicit action involving a call to +extract_specific_pragmas; otherwise they simply remain on the +pending_pragmas list of the current scope stack entry and their +processing is never completed.
      +
      +
    • +
    +

    process_curr_construct_pragmas is the routine that initiates automatic +processing for the pbk_next_construct pragmas associated with a given +declaration or statement. It traverses the list of them on the current scope +stack entry, making sure that each pragma binds to the sort of construct +(statement or declaration) that is currently being processed; it (optionally) +issues a diagnostic otherwise. If automatically_include_in_il (in the +corresponding pragma kind description) is TRUE, it calls +create_il_entry_for_pragma. If next_construct_processing_function is +non-NULL, it calls it do any additional processing that is required. It also +returns all the pending pragma entries to the available list.

    +

    If a pragma should be included in the IL, create_il_entry_for_pragma is +called; it calls add_pragma_to_il, which in turn calls alloc_pragma to +create the entry of type a_pragma and add_to_pragmas_list to add it to +the end of the pragmas list of the proper scope.

    +

    create_il_entry_for_pragma is called automatically – by +process_curr_token_pragmas for pbk_immediate pragmas and by +process_curr_construct_pragmas for pbk_next_construct pragmas – when +the automatically_include_in_il flag is set. It is also called +automatically by extract_specific_pragmas when that flag is set. It can be +called directly from pragma-processing code when automatic creation of IL +entries is undesirable.

    +

    The scope to which the IL pragma entry is attached is determined based on +several considerations. If a pbk_next_construct pragma is bound to a class +member, it belongs to the scope of the class; otherwise, if it is bound to an +IL entry allocated in the file-scope memory region, it belongs to the file +scope; otherwise, it belongs to the current (block or function) scope. A +pbk_immediate, pbk_next_token, or pbk_other pragma belongs to the +file scope if the global flag in the corresponding pragma kind description +is TRUE; otherwise it belongs to the current scope.

    +

    pbk_next_construct pragmas that are added to the IL have a pointer to the +IL entry with which they are associated (a statement, a variable, etc.), but +the latter has no pointer back to the pragma. Instead, the +has_associated_pragma flag (in a_source_correspondence and in +a_statement) is set, indicating that one or more pragmas is bound to it. +find_assoc_pragma may be called to locate the pragma entry (or entries) +associated with a given IL entry.

    +

    The automatic processing of pending pragma entries may also involve calling a +routine to do whatever special processing is required for the particular pragma +kind. The address of this routine, which must be declared with the appropriate +type (see a_next_construct_pragma_function, +an_immediate_pragma_function, and an_other_pragma_function) is recorded +in the pragma kind description. Here are some examples from pragmas supplied +by default by the EDG front end:

    +
      +
    • +
      instantiate_pragma is specified as the processing function for the +pbk_next_token pragma of kind pk_instantiate; it is called by +process_curr_token_pragmas when such pending pragma entries are +encountered; no IL entry is required.
      +
      +
    • +
    • +
      record_arg_pragma is the processing function for pragmas of kind +pk_printf_args and pk_scanf_args; it is called from +process_curr_construct_pragmas. Note that a symbol pointer is included +in the interface of the processing functions for pbk_next_construct +pragmas, and so record_arg_pragma is able to record the event for the +current routine.
      +
      +
    • +
    +

    The timing of the call to process_curr_construct_pragmas and therefore to +the corresponding processing function may be critical. The rules, in general, +are:

    +
      +
    • +
      for declarations, process_curr_construct_pragma is called at the point +the symbol is bound to its corresponding IL entry;
      +
      +
    • +
    • +
      for statements, it is called immediately after the statement entry is +created (but before other processing is done).
      +
      +
    • +
    +

    For reasons of timing and other considerations it is sometimes inappropriate to +use the automatic mechanisms that are provided. An alternative is to call +extract_specific_pragmas, which returns a pending pragma entry of a given +pragma kind, [2] and to do the required processing directly. For an example +of this style of pragma use see record_lint_argsused_and_varargs_state, +which is called only when a function is being defined: if +extract_specific_pragmas returns a pending pragma entry of the specified +kind, it sets a flag in the routine type supplement and, since the entry will +have been removed from the current construct pragma list, calls +free_pending_pragma_list to dispose of it.

    +

    extract_specific_pragmas is also called for pbk_other pragmas. In +fact, it is essential for completing the processing of such pragmas and should +be included in custom code to implement a specific pragma. Once this routine +has been called for a given pragma kind, the pending pragma entry returned is +no longer on the pending_pragmas list, so it cannot be found a second time. +Note also that the calling routine is responsible for freeing the pending +pragma entry.

    +
    +
    +

    15.5. How to Add A New Pragma#

    +

    The mechanisms provided to support #pragma directives have been designed +with extensibility in mind. This section is intended to provide some +additional guidance in adding new pragma kinds. In general, this is what you +will need to do to:

    +
      +
    • +
      Add a new entry to the enumeration a_pragma_kind in il_def.h, and +add an identifier string to the array pragma_ids.
      +
      +
    • +
    • +
      Decide on the binding kind for the pragma.
      +
      +
        +
      • +
        pbk_immediate is appropriate when the pragma’s effect is quite +independent of the context in which it appears in the source. It is +processed unconditionally immediately after the pragma is scanned. If +the pragma appears in a cached context, the pragma is also processed each +time the cache is rescanned.
        +
        +
      • +
      • +
        pbk_next_token is similar to pbk_immediate except that the pragma +is not processed until the next regular (non-preprocessing) token is +fetched and if the pragma appears in a cached context it is not processed +when it is first encountered but only each time the cache is rescanned.
        +
        +
      • +
      • +
        pbk_next_construct is appropriate when the pragma is meant to affect +the construct that immediately follows it in the source. Set one or both +of may_bind_to_decl or may_bind_to_statement depending on what +sort of construct it applies to. These pragmas are discarded (optionally +with a diagnostic) if they appear in front of the wrong kind of +construct.
        +
        +
      • +
      • +
        pbk_other is appropriate for maximum flexibility, though it requires +additional intervention by you, since the automated mechanisms are not +available.
        +
        +
      • +
      • +
        pbk_preproc_immediate is appropriate when the pragma must be +processed when encountered by the preprocessing routines and cannot be +deferred until the next nonpreprocessing token of the program is scanned. +No pending pragma entry is created for these pragmas and they cannot be +entered into the IL.
        +
        +
      • +
      +
    • +
    • +
      Create the pragma kind description by adding a call to +add_pragma_kind_description in pragma_init; the call should be made +using the interface function that is specific to the binding kind.
      +
      +
    • +
    • +
      If you want to store information – say, the value of a pragma argument +that will be used when the pragma is processed – you can add one or more +variant fields to a_pending_pragma. The switch statement in +alloc_pending_pragma (where the variant field, if any, is initialized) +should be updated to recognize the new pragma kind.
      +
      +
    • +
    • +
      If the pragma is to be entered in the IL and additional information is +needed in the IL entry, you should add variant fields to a_pragma +(defined in il_def.h) and initialize them in alloc_pragma (in +il_alloc.c).
      +
      +
    • +
    • +
      If the pragma is to be entered in the IL automatically, set +automatically_include_in_il when creating the pragma kind description +entry.
      +
      +
    • +
    • +
      If the pragma binding kind is pbk_immediate, pbk_next_token, or +pbk_next_construct, decide whether you want a processing function to be +called automatically. If so, be sure to include a pointer to it when +creating the pragma kind description entry.
      +

      +
      Even if you have specified a processing function, be sure that +automatically_include_in_il is FALSE if you want control over whether +the IL pragma entry should be created; if you do this, you can call +create_il_entry_for_pragma. If automatically_include_in_il is +TRUE, the IL pragma entry will already have been created before your +routine is called, but you will still be able to set any variant fields +that are specific to this pragma kind.
      +
      +
    • +
    • +
      If the pragma binding kind is pbk_other – or if it is +pbk_next_construct but you don’t want to use the automatic facility of +process_curr_construct_pragma – you will have to write code to call +extract_specific_pragmas and to do the required processing. Note that, +if automatically_include_in_il is set to TRUE, +extract_specific_pragmas will cause an IL pragma entry to be created; +if you want more control, be sure the flag is FALSE when you create the +pragma kind description entry.
      +
      +
    • +
    • +
      If your code uses extract_specific_pragmas, be sure to call +free_pending_pragma_list to dispose of the pending pragma entry (or +entries) returned to you.
      +
      +
    • +
    • +
      If your pragma processing function needs to deal with more than the pragma +identifier, decide whether your code requires the pragma to be represented +as a text string or as a token cache. If the former, set +record_pragma_text to TRUE when you create the pragma kind description +entry. However, if you choose to deal with tokens, the following +convention should be observed:
      +
      +
        +
      1. Call begin_rescan_of_pragma_tokens to find the appropriate token +cache for rescanning the tokens that comprise the pragma body; it also +pushes a sck_pragma scope. The first token you will see is the one +following the pragma identifier.

      2. +
      3. When you have finished scanning the tokens, call +wrapup_rescan_of_pragma_tokens to pop the sck_pragma scope and +check that all of the tokens were scanned from the cache; if the current +token is not the tok_end_of_source at the end of the pragma +directive, an “extra text in preprocessing directive” error will be +issued.

      4. +
      +
    • +
    • +
      You should set expand_macros to FALSE if you want to suppress macro +expansion while the pragma tokens are scanned. Furthermore, setting +processing_C_code when generating a token cache means keywords will be +recognized and adjacent string literals will be concatenated together.
      +
      +
    • +
    • +
      If you are simply passing the pragma on to the back end without processing +it in the front end, be sure that make_text_not_tokens is TRUE when you +create the pragma kind description entry – a pragma cannot be passed to +the back end in the form of a token cache.
      +
      +
    • +
    • +
      If you want a diagnostic issued when a pbk_next_construct pragma +appears in the wrong place in the source program or an unprocessed +pbk_other pragma is encountered when a scope is popped, set the +error_severity appropriately when you create the pragma kind +description entry; use es_none to suppress the diagnostic.
      +
      +
    • +
    +
    +
    +

    15.6. Introduction to Attributes#

    +

    Unlike pragmas, attributes are parsed like other ordinary language features. +This parsing is usually achieved with a call to scan_attributes, which +returns a list of attributes (an_attribute entries) in the order that they +were encountered. Each attribute entry represent a standard attribute, a GNU +attribute, or a Microsoft __declspec attribute [3]: The specific variant +is recorded in the family field (which can be af_std, af_gnu, or +af_ms_declspec). Whether a specific attribute family syntax is accepted is +determined by the global variables std_attributes_enabled, +gnu_attributes_enabled, and ms_declspec_attributes_enabled. The +parsing process also classifies attributes according to their kind +(ak_align, ak_nothrow, etc.) and their syntactic location +(al_prefix, al_declarator_id, etc.). As with pragmas, the front end +accepts attributes that it doesn’t recognize (these are assigned attribute kind +ak_unrecognized).

    +

    Attributes appear in “groups”. For example:

    +
    __attribute((align(4))) __attribute((pure,nothrow)) void f();
    +
    +
    +

    The an_attribute entry corresponding to the align attribute will point +to a first entry of type an_attribute_group, whereas the an_attribute +entries for pure and nothrow will both point to a second +an_attribute_group entry. Attribute groups can be empty (typically as the +result of macro expansion). To represent empty groups, an ak_empty +attribute is created (which then points to an ordinary entry of type +an_attribute_group). Attribute group entries do not carry information of +their own other than the position of delimiting tokens: Their principal +function is to indicate how attributes were grouped in the source code. The +“upside-down” arrangement of attributes vs. groups keeps all the attributes +associated with a given entity on a “flat” list, which simplifies traversing +them (the alternative would consist in having to traverse groups and within +each group traversing a list of attributes).

    +

    After attributes have been parsed, they are “attached” and “applied” to an +appropriate IL entity. This is usually done by calling attach_attributes.

    +

    Attaching an attribute means recording its entry in the IL by placing it on a +list pointed to by the IL entry of the entity to which the attribute applies. +Usually, the list is pointed to by the attributes field in +a_source_correspondence. Unrecognized attributes are recorded in the IL +only when the global variable record_unrecognized_attributes (initialized +with the configuration macro RECORD_UNRECOGNIZED_ATTRIBUTES) is TRUE. If +unrecognized attributes are not recorded in the IL, they elicit a warning.

    +

    Applying an attribute means that the validity of the attribute for its target +entity is checked (e.g., it is an error for a standard [[nothrow]] +attribute to be applied to a variable) and, possibly, that the IL entry for the +target entity is updated (e.g., the noreturn attribute causes the +does_not_return flag in the corresponding routine type supplement to be set +to TRUE). Applying an unrecognized or an empty attribute has no effect.

    +

    When simultaneously compiling multiple translation units, the attributes +attached to corresponding declarations are checked. By default, attributes +must match exactly, but alternative policies are possible for specific +attributes and contexts.

    +

    The parsing/classification of attributes, their application to IL entities, and +the checking of corresponding attributes across translation units (when +applicable) is at least in part table-driven.

    +
    +
    +

    15.7. Parsing Attributes#

    +

    As mentioned above, attributes are usually parsed by calling +scan_attributes. However, if only GNU attributes should be considered, +scan_gnu_attribute_groups is called instead. Both functions take an +argument of type an_attribute_location, which specifies the syntactic +context in which the call is made. For example, in the declaration

    +
    [[nothrow]] int __attribute((pure))
    +            f [[final]] () __attribute((deprecated));
    +
    +
    +

    the nothrow attribute is parsed as al_prefix, the pure attribute is +parsed as al_specifier, the final attribute is parsed as +al_declarator_id, and the deprecated attribute is parsed as +al_post_func. (I.e., the front end contains calls to scan_attributes +or scan_gnu_attribute_groups in various places, each call passing an +argument reflecting the current parsing context.)

    +

    In the case of standard attributes, strict appertaining rules allow the +syntactic context to unambiguously determine what entity the attribute applies +to. For example, standard al_prefix attributes apply to the variables, +functions, or typedefs being declared, while standard al_specifier +attributes apply to the type specified by the declaration specifiers.

    +

    In contrast, the syntactic location of GNU attributes does not unambiguously +determine the entity they apply to; instead, the affected entity depends on the +attribute kind. For example, in

    +
    __attribute((align(16))) int f1();
    +__attribute((vector_size(16))) int f2();
    +
    +
    +

    the align attribute modifies function f1, but the vector_size +attribute modifies type int. To deal with this, the front end reclassifies +some GNU attributes after they are parsed based on whether the attribute +transforms a type or not. This ensures that the attribute is applied to the +correct entity. For example, the vector_size attribute in the example +above is parsed as al_prefix, but then reclassified as al_specifier +(this is done in attach_specifier_attributes). A related example is

    +
    void f3() __attribute((warn_unused_result));
    +void f4() __attribute((pure));
    +
    +
    +

    These attributes are originally parsed with context al_post_func +(indicating they appear after a function declarator), which for a C++11 +attribute would imply that the attribute applies to the associated function +type. However, GNU attributes in this syntactic context can apply to the +function type (e.g., warn_unused_result) or to the function itself (e.g., +pure). In cases like these, the attributes are reclassified to +al_postfix (in scan_declarator_attributes) and the attribute +application function modifies the function or its type depending on the +attribute (and the same process applies to attributes after array declarators).

    +

    Microsoft __declspec attributes also lack strict appertaining rules, but +their treatment is simpler because there are no type-transforming +__declspec attributes and __declspec attributes can appear in fewer +syntactic locations (only al_prefix, al_specifier, and al_tag_name +contexts are valid, and the former two are usually equivalent). There are some +special cases, however. For example, the align attribute in

    +
    __declspec(align(16)) struct S { ... } x;
    +
    +
    +

    is equivalent to

    +
    struct __declspec(align(16)) S { ... } x;
    +
    +
    +

    and the front end handles this by recording the align attribute as an +al_tag_name attribute in such cases.

    +
    +

    15.7.1. Unscanning Attributes#

    +

    Sometimes, it is not clear at the time of parsing the attribute which context +the attributes will end up in. E.g., GNU attributes can appear after the left +parenthesis introducing function parameters and after the left parenthesis +introducing a nested declarator (see r_declarator in declarator.c). In +such circumstances, the attributes can be scanned (by calling +scan_attributes) with an assumed context, then “unscanned” (with +unscan_attributes), and then “rescanned” by calling scan_attributes +with the correct syntactic location. Note that the call to +unscan_attributes does not restore the tokens that made up the attributes; +it just stores the given attribute entries to be returned by the next call to +scan_attributes.

    +
    +
    +
    +

    15.8. Recognizing Attributes#

    +

    For an attribute to be recognized in the front end, it must have a description +in the array known_attr_table defined in attribute.c. The description +(type an_attr_descr) contains four fields:

    +
      +
    • +
      A string with the source form of the attribute name (e.g., “section”). +The optional leading and trailing underscores in the case of GNU attributes +should not be included in this string.
      +
      +
    • +
    • +
      A string encoding what kind of arguments (if any) the attribute takes. +This the “signature” of the attribute. The details of this encoding are +described in the definition of an_attr_descr in attribute.c. For +example, the code "(sn+)" would indicate that an argument list is +required and that it should contain one or more (narrow) string literals.
      +
      +
    • +
    • +
      A string encoding the general conditions (primarily, the mode) in which an +attribute should be accepted, and, in the case of standard attributes, the +attribute namespace for the attribute. This encoding too is described in +the definition of an_attr_descr in attribute.c. For example, +"g+(-39999)" indicates that the attribute should be accepted as a GNU +attribute in GNU C++ modes with gnu_version less than 40000, while +"c+[EDG]" specifies that the attribute should be accepted with standard +syntax and namespace-prefix EDG:: in modes that accept standard C++11 +attribute syntax.
      +
      +
    • +
    • +
      The attribute kind (e.g., ak_section) that should be assigned to the +attribute.
      +
      +
    • +
    +

    Note that there can be multiple entries for the same attribute kind. For +example, the nothrow attribute is accepted as a GNU attribute, as a +Microsoft __declspec attribute, and as a standard attribute, and therefore +(at the time of this writing) it has three description entries as follows:

    +
    ...
    +{ "nothrow", "", "1c+", ak_nothrow },
    +...
    +{ "nothrow", "", "gx", ak_nothrow },
    +...
    +{ "nothrow", "", "m+", ak_nothrow },
    +...
    +
    +
    +

    (the prefix “1” in "1c+" indicates that the attribute cannot be +repeated in an attribute group).

    +

    If an attribute name is recognized, but it does not meet other constraints, a +diagnostic is issued and the attribute is reclassified as ak_unrecognized +(by calling the macro make_attr_unrecognized). This recovery technique is +used throughout attribute processing: Rather than dropping an attribute +altogether, it is generally just reclassified by calling +make_attr_unrecognized.

    +
    +
    +

    15.9. Applying Attributes#

    +

    The application of attributes is highly dependent on the specific attribute +being applied, but some of the processing is also table-driven. Specifically, +the array known_attr_appl_table contains an entry of type +an_attr_appl_descr for every attribute kind. Each entry contains the +following fields:

    +
      +
    • +
      The attribute kind, included only for readability and consistency checking +(the array contents must match the enumeration an_attribute_kind).
      +
      +
    • +
    • +
      A string encoding which entity kinds an attribute applies to, and, +optionally, simple constraints for matching entities. The details of the +encoding are described in the definition of an_attr_appl_descr in +attribute.c. For example, "r|v" means the attribute applies to +routines and variables only, while "r|v:-a" means the same thing, but +requires the variable not to have automatic storage duration. (A failure +to meet these constraints causes the attribute to be reclassified as +ak_unrecognized.)
      +
      +
    • +
    • +
      A pointer to a callback function (of type an_attr_application_fn). If +this pointer is non-NULL and if the constraints in the previous field are +fullfilled, the indicated function is called with the attribute and the IL +entry it applies to (the “target entity”) passed in as arguments. The +callback function can check additional constraints on the target entity and +update the entry (and any other structures) as appropriate.
      +
      +
    • +
    +

    A few Microsoft __declspec attributes require special handling in the front +end. For example, the presence of a property(...) attribute is detected +soon after being scanned because it affects certain semantic checks performed +by the front end before the complete declaration has been parsed (and, +therefore, before the application callback function can be called).

    +
    +

    15.9.1. Type-Transforming Attributes#

    +

    Most attributes only modify relatively minor properties of the entities to +which they apply, and this modification is to the entity itself. For example, +the standard attribute [[final]] when applied to a class type X +prevents other classes from deriving from X; it does not create a new IL +entry. Some GNU attributes, however, can transform a type into a new type +requiring a distinct IL entry [4]. For example, the GNU attribute in:

    +
    float __attribute((vector_size(16))) vec;
    +
    +
    +

    transforms type float to a type “vector of float”. Such +type-transforming attributes are applied (and attached) using function +attach_type_attributes. It uses the array known_attr_appl_table much +like attach_attributes, but instead of making the resulting type entry +point directly to the attributes list, it adds a tk_typeref entry on top of +the resulting type for that purpose.

    +

    Because of the possibility of entity transformation, the callback functions +recorded in known_attr_appl_table must return an IL entry pointer that +represents the entity resulting from the application of the attribute to a +given entity. Except for type-transforming attributes, the returned IL entry +is the same entry as the one passed to the callback function.

    +
    +
    +
    +

    15.10. Attributes in Back Ends#

    +

    Most known attributes have an effect on IL fields that provides sufficient +information to a traditional code-generating back end. For example, the +nothrow attribute causes the never_throws flag in a_routine to be +set to TRUE. However, since attribute entries are also pointed to by affected +entities, it is not strictly necessary to add separate fields to IL entries. A +specific attribute can be found using the function find_attribute. For +example, the standard attribute carries_dependency is currently only +represented by its an_attribute entry.

    +

    The C-generating back end ignores most an_attribute entries. Instead, it +usually renders GNU attributes (when the target compiler is known to be a +version of GCC) based on other fields in the IL. However, for some attributes +that are only represented in the IL through their an_attribute entry, the +C-generating back end may emit a GNU attribute construct based on the presence +of the corresponding entry.

    +

    The C++-generating back end, on the other hand, renders attributes based only +on applicable an_attribute entries. To ensure that the rendered code is +close to the original form, attributes specified on a secondary declaration are +recorded twice in the IL (i.e., the entries are duplicated): Once on the list +pointed to by the source correspondence of the target entity, and once on a +list pointed by the associated a_src_seq_secondary_decl. Attributes on +primary declarations are recorded only once, but are marked as having appeared +on the primary declaration (flag on_primary_declaration in +an_attribute).

    +
    +
    +

    15.11. How to Add a New Attribute#

    +

    The framework described above make the addition of many common kinds of +attributes relatively simple:

    +
      +
    • +
      Add an ak_… attribute kind in il_def.h.
      +
      +
    • +
    • +
      Add one or more entries to the known_attr_table in attribute.c.
      +
      +
    • +
    • +
      Add an entry in the known_attr_appl_table in attribute.c.
      +
      +
    • +
    • +
      Write the callback function specified in the new known_attr_appl_table +entry (if such a callback is needed at all).
      +
      +
    • +
    • +
      If the attribute is not required to match exactly across translation units, +add one or more entries describing the correspondence handling to the +attr_corresp_table defined in attribute.c. (In some cases this may +involve adding additional functions or updating the code in +trans_corresp.c.)
      +
      +
    • +
    +

    (The attribute may require new IL entry fields or even new IL entry kinds. If +so, see How To Extend the IL.)

    +

    If attributes must be recognized in contexts that do not currently allow them, +additional calls to scan_attributes and attach_attributes must be added +to the front end (and, most likely, additional enumeration constants for +an_attribute_location). If the C++-generating back end is used, it will +also require a matching call to gen_attributes.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/runtime/index.html b/doc/runtime/index.html new file mode 100644 index 0000000..2295a1e --- /dev/null +++ b/doc/runtime/index.html @@ -0,0 +1,477 @@ + + + + + 21. Runtime Library - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    21. Runtime Library#

    +

    The runtime library routines provide basic runtime support. The source for +these routines is in the lib_src directory of the release structure.

    +

    “Basic” runtime support means support for operations built in to the C++ +language, like new and delete, and for operations for which code is +generated by IL lowering, e.g., array initialization. (This includes code +generated by the lowering of C99 constructs.) It does not mean support for all +libraries required by the C++ standard, e.g., iostreams.

    +

    The front end supports two different runtime models. A configuration macro is +used to select the runtime model to be used. The models supported are the +IA-64 ABI and one that is an extension of the one used with cfront.

    +

    The IA-64 model is a complete implementation of the IA-64 ABI, except that the +exception handling implementation does not conform to the ABI (because +producing a conforming implementation of exception handling requires back end +support).

    +

    The cfront runtime model is generally compatible with the one used by +cfront version 3.0.2, and in fact the code generated by the front end in +cfront object code compatibility mode will work with the libraries +supplied with cfront (with one exception that is described below). +Another way of saying the same thing: The runtime library is an independent +implementation of the runtime interface defined by cfront.

    +

    One incompatibility between our runtime support library and the one provided +with cfront is the handling of static destructors. The cfront static +destruction mechanism does not conform to the C++ standard, which requires all +static objects, including local static objects, to be destroyed in the reverse +order of construction. The EDG static destruction mechanism relies on a new +data structure called the needed destructions list. If a cfront runtime +library is to be used, the dtor_list.o file from the EDG library must be +included when a program is linked. This may be done by explicitly including +dtor_list.o in the link command generated by the driver, or by adding +dtor_list.o to the library file containing the cfront libraries.

    +

    In the area of exception handling, there is no standard cfront runtime +model (because no version of cfront that supports exception handling was +released by USL), so the model is invented by EDG, drawing on some +published aspects of the implementation done by Hewlett-Packard.

    +

    The runtime routines should be considered to be a sample implementation of a +runtime library. They are believed to be complete and to work correctly, but +they might require adaptation to make them work correctly in a given +environment, or to make them compatible with other runtime libraries or +conventions on the target system. In particular, if runtime compatibility with +cfront is not required, there are probably better ways of doing some of these +things. Also, the target system may provide efficient support for things that +can only be done in a clumsy way in a portable runtime library, e.g., getting +start-up initialization code run automatically at the beginning of execution.

    +
    +

    21.1. The --building_runtime option#

    +

    Like the front end, the runtime contains a number of configuration flags. In +many cases, it is essential that the same values be used by both the front end +and the runtime with which the generated code will be linked. To help make +sure the runtime is configured properly the --building_runtime option +should be specified when compiling the runtime. This causes additional +preprocessing macros to be defined that pass the value of certain configuration +flags from the front end to the runtime. The following preprocessing macros +are defined when the --building_runtime option is used:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    __EDG_JMP_BUF_ELEMENT_TYPE
    +

    +
    +
    +
    The name of the integer or floating point type that is used as the +element type of the jmp_buf array used by setjmp.
    +
    +
    +
    __EDG_JMP_BUF_NUM_ELEMENTS
    +

    +
    +
    +
    The number of elements in the jmp_buf array used by setjmp.
    +
    +
    +
    __EDG_DELTA_TYPE
    +
    +
    +
    The name of the integer type that is used to represent the offset in a +virtual function table entry.
    +
    +
    +
    __EDG_VIRTUAL_FUNCTION_INDEX_TYPE
    +

    +
    +
    +
    The name of the integer type that is used to represent the index field +in a virtual function table entry.
    +
    +
    +
    __EDG_VAR_HANDLE_TYPE
    +

    +
    +
    +
    The name of the integer type that is used to represent a “handle” in +exception handling tables. Defined only when GENERATE_EH_TABLES +is TRUE.
    +
    +
    +
    __EDG_REGION_NUMBER_TYPE
    +

    +
    +
    +
    The type of a region number field in the exception handling tables. +Defined only when GENERATE_EH_TABLES is TRUE.
    +
    +
    +
    __EDG_ETS_FLAG_TYPE
    +

    +
    +
    +
    The type used to pass exception types flags to the runtime library. +Defined only when GENERATE_EH_TABLES is TRUE.
    +
    +
    +
    __EDG_NULL_EH_REGION_NUMBER
    +

    +
    +
    +
    The value used as the null region number value in the exception +handling tables. Defined only when GENERATE_EH_TABLES is TRUE.
    +
    +
    +
    __EDG_LOWER_VARIABLE_LENGTH_ARRAYS
    +

    +
    +
    +
    Indicates whether or not the front end is configured to lower +variable-length arrays. Set to the value of (VLA_ALLOWED && +LOWER_VARIABLE_LENGTH_ARRAYS) in the front end.
    +
    +
    +
    __EDG_IA64_ABI_USE_VARIANT_ARRAY_COOKIES
    +

    +
    +
    +
    Non-zero when the variant representation of array cookies is used in +the IA-64 ABI. Defined only when IA64_ABI is TRUE.
    +
    +
    +
    __EDG_ELEM_COUNT_PARAM_TYPE
    +

    +
    +
    +
    The type used to represent the number_of_elements argument in the +Cfront-like ABI. Defined only when IA64_ABI is FALSE.
    +
    +
    +
    __EDG_ABI_COMPATIBILITY_VERSION
    +

    +
    +
    +
    The value of ABI_COMPATIBILITY_VERSION used when the front end was +built.
    +
    +
    +
    __EDG_ABI_CHANGES_FOR_RTTI
    +

    +
    +
    +
    The value of ABI_CHANGES_FOR_RTTI used when the front end was +built.
    +
    +
    +
    __EDG_ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE
    +

    +
    +
    +
    The value of ABI_CHANGES_FOR_ARRAY_NEW_AND_DELETE used when the +front end was built.
    +
    +
    +
    __EDG_ABI_CHANGES_FOR_PLACEMENT_DELETE
    +

    +
    +
    +
    The value of ABI_CHANGES_FOR_PLACEMENT_DELETE used when the front +end was built.
    +
    +
    +
    __EDG_BSD
    +
    +
    +
    The value of the __BSD__ macro when the front end was built.
    +
    +
    +
    __EDG_SYSV
    +
    +
    +
    The value of the __SYSV__ macro when the front end was built.
    +
    +
    +
    __EDG_ANSIC
    +
    +
    +
    The value of the__ANSIC__ macro when the front end was built.
    +
    +
    +
    __EDG_CPP11_IL_EXTENSIONS_SUPPORTED
    +
    +
    +
    The value of CPP11_IL_EXTENSIONS_SUPPORTED when the front end was +built.
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/search/index.html b/doc/search/index.html new file mode 100644 index 0000000..3a2fe33 --- /dev/null +++ b/doc/search/index.html @@ -0,0 +1,112 @@ + + + + + Search - CPFE 7.0 documentation + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    +
    + +

    Search

    + + + + +

    + Searching for multiple words only shows matches that contain + all words. +

    + + +
    + + +
    +

    + + +
    + + +
    + +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + + + + \ No newline at end of file diff --git a/doc/searchindex.js b/doc/searchindex.js new file mode 100644 index 0000000..8351c01 --- /dev/null +++ b/doc/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"alltitles":{"#elif":[[4,"elif"]],"#else":[[4,"else"]],"#if and #endif":[[4,"if-and-endif"]],"#pragma Directives":[[23,"pragma-directives"]],"A rethrow from the handler":[[8,"a-rethrow-from-the-handler"]],"A walk-through of an EH example":[[8,"a-walk-through-of-an-eh-example"]],"ABI support":[[16,"abi-support"]],"ANSI C Extensions":[[10,"ansi-c-extensions"]],"ANSI C and C++ Include Files":[[12,null]],"AT&T Preprocessing Extensions":[[15,"at-t-preprocessing-extensions"]],"Access Control":[[11,"access-control"],[21,"access-control"]],"Active, Inactive, and \u201cOther\u201d Symbols":[[21,"active-inactive-and-other-symbols"]],"Adding a Field to an Existing IL Entry":[[11,"adding-a-field-to-an-existing-il-entry"]],"Adding a New Operator":[[11,"adding-a-new-operator"]],"Adding an IL Entry":[[11,"adding-an-il-entry"]],"Address of Overloaded Function":[[9,"address-of-overloaded-function"]],"Addressing operators":[[11,"addressing-operators"]],"Administrative Functions":[[0,null]],"Advanced Concepts":[[24,"advanced-concepts"]],"Advanced Stage Breakdown":[[17,"advanced-stage-breakdown"]],"Aggregate Initializers":[[6,"aggregate-initializers"]],"Alias Templates":[[23,"alias-templates"],[23,"id13"]],"Alias templates":[[23,"id4"]],"Alternative Language Behaviors":[[10,"alternative-language-behaviors"]],"Anachronisms Accepted":[[10,"anachronisms-accepted"]],"Annotating Function Arguments":[[4,"annotating-function-arguments"]],"Anonymous Unions":[[11,"anonymous-unions"],[16,"anonymous-unions"]],"Applying Attributes":[[18,"applying-attributes"]],"Argument Dependent Lookup":[[10,"argument-dependent-lookup"]],"Argument-Dependent Lookup":[[21,"argument-dependent-lookup"]],"Asking Questions About Types":[[22,"asking-questions-about-types"]],"Assignments":[[11,"assignments"]],"At the end of a handler":[[8,"at-the-end-of-a-handler"]],"Attributes":[[11,"attributes"]],"Attributes in Back Ends":[[18,"attributes-in-back-ends"]],"Auto type deduction":[[6,"auto-type-deduction"]],"Automatic Instantiation":[[10,"automatic-instantiation"],[23,"automatic-instantiation"]],"Automatic Precompiled Header Processing":[[10,"automatic-precompiled-header-processing"]],"Automatic Template Instantiation":[[16,"automatic-template-instantiation"]],"Automatically Generated Definitions":[[23,"automatically-generated-definitions"]],"Base Class Entries":[[11,"base-class-entries"]],"Base Class List":[[3,"base-class-list"]],"Base Classes":[[3,"base-classes"]],"Basic Node":[[17,"basic-node"]],"Basic Organization":[[21,"basic-organization"]],"Binary Conditional Operator":[[11,"binary-conditional-operator"]],"Bitfield":[[17,"bitfield"],[17,"ifc-bitfield-versioning"]],"Bitwidth Limitations":[[17,"bitwidth-limitations"]],"Bound Pragmas":[[18,"bound-pragmas"]],"Boxing and Unboxing":[[11,"boxing-and-unboxing"]],"Building Support for C++/CLI and C++/CX Modes":[[1,"building-support-for-c-cli-and-c-cx-modes"]],"Building and Using the IL Display Program":[[1,"building-and-using-the-il-display-program"]],"Building the Front End":[[1,"building-the-front-end"]],"Building the Front End Only":[[1,"building-the-front-end-only"]],"Byte Buffer Adjustment":[[17,"byte-buffer-adjustment"]],"Byte Buffers":[[17,"byte-buffers"]],"C Dialect Accepted":[[10,"id3"]],"C mode out-of-scope declarations":[[21,"c-mode-out-of-scope-declarations"]],"C versus C++ Intermediate language":[[11,"c-versus-c-intermediate-language"]],"C++ Dialect Accepted":[[10,"c-dialect-accepted"]],"C++-Generating Back End":[[5,null]],"C++/CLI Accessor Names":[[3,"c-cli-accessor-names"]],"C++/CLI Assembly Import":[[15,"c-cli-assembly-import"]],"C++/CLI Derivations":[[3,"c-cli-derivations"]],"C++/CLI Generics":[[9,"c-cli-generics"],[23,"c-cli-generics"]],"C++/CLI Initialization":[[0,"c-cli-initialization"]],"C++/CLI Managed Class Definitions":[[3,"c-cli-managed-class-definitions"]],"C++/CLI Member Functions":[[3,"c-cli-member-functions"]],"C++/CLI Options":[[10,"c-cli-options"]],"C++/CLI Static Data Members":[[3,"c-cli-static-data-members"]],"C++/CLI Type Constructs":[[6,"c-cli-type-constructs"]],"C++/CLI Types":[[11,"c-cli-types"]],"C++/CLI and the Intermediate Language":[[11,"c-cli-and-the-intermediate-language"]],"C++20 Implementation Status":[[10,"c-20-implementation-status"]],"C++23 and C++26 Implementation Status":[[10,"c-23-and-c-26-implementation-status"]],"C-Generating Back End":[[2,null]],"C-style":[[4,"c-style"]],"C/C++ Front End Documentation":[[13,null]],"C99 Features Available in Other Modes":[[10,"c99-features-available-in-other-modes"]],"C99 and the Intermediate Language":[[11,"c99-and-the-intermediate-language"]],"C99 features":[[11,"c99-features"]],"Calls":[[11,"calls"],[16,"calls"]],"Canonical Entries":[[25,"canonical-entries"]],"Casts":[[11,"casts"]],"Catching an Exception":[[16,"catching-an-exception"]],"Cfront-like ABI name mangling":[[16,"cfront-like-abi-name-mangling"]],"Checking Code":[[14,"checking-code"]],"Checking Operands":[[9,"checking-operands"]],"Class Declarations":[[3,null],[3,"id1"]],"Class Definitions":[[3,"class-definitions"]],"Class Layout":[[11,"class-layout"]],"Class Linkage":[[3,"class-linkage"]],"Class Member Declaration Lists":[[11,"class-member-declaration-lists"]],"Class Member Projection Symbols":[[21,"class-member-projection-symbols"]],"Class Object Layout":[[3,"class-object-layout"]],"Class Scopes":[[11,"class-scopes"]],"Class Symbol Supplement":[[21,"class-symbol-supplement"]],"Class Templates":[[23,"class-templates"],[23,"id3"],[23,"id6"],[23,"id10"],[23,"id12"]],"Class Types":[[11,"class-types"],[16,"class-types"]],"Classes":[[21,"classes"]],"Classifying the Template Declaration":[[23,"classifying-the-template-declaration"]],"Coalesce-and-Look-Up Routines":[[15,"coalesce-and-look-up-routines"]],"Code Generation Options":[[10,"code-generation-options"]],"Code Organization":[[17,"code-organization"]],"Code generated for a try block":[[8,"code-generated-for-a-try-block"]],"Coding Philosophy":[[14,"coding-philosophy"]],"Coding Style Guide":[[4,null]],"Command Line":[[10,"command-line"]],"Command-line Parsing":[[0,"command-line-parsing"]],"Commonly-used Configuration Macros":[[1,"commonly-used-configuration-macros"]],"Compiler-Generated Functions":[[3,"compiler-generated-functions"]],"Completing the Declaration":[[6,"completing-the-declaration"]],"Completing the Function Template":[[23,"completing-the-function-template"]],"Compound Assignments":[[11,"compound-assignments"]],"Concepts":[[23,"concepts"]],"Condition Declarations":[[11,"condition-declarations"],[16,"condition-declarations"]],"Configuration":[[2,"configuration"]],"Configuring and Building the C++ Front End":[[1,null]],"Configuring and Building the Run-Time Support Library":[[1,"configuring-and-building-the-run-time-support-library"]],"Configuring the Front End":[[1,"configuring-the-front-end"]],"Connection With IL Scope Entries":[[21,"connection-with-il-scope-entries"]],"Constant Entries":[[22,"constant-entries"]],"Constant Expressions":[[9,"constant-expressions"]],"Constant Folding":[[9,"constant-folding"]],"Constants":[[5,"constants"],[11,"constants"]],"Constrained Templates":[[23,"constrained-templates"]],"Constructor Initializers":[[6,"constructor-initializers"]],"Constructor Wrapper Code":[[16,"constructor-wrapper-code"]],"Constructors and Destructors":[[11,"constructors-and-destructors"],[21,"constructors-and-destructors"]],"Constructors and Destructors for Arrays":[[16,"constructors-and-destructors-for-arrays"]],"Conventions for Declarations":[[14,"conventions-for-declarations"]],"Conversion of Literal Constants":[[15,"conversion-of-literal-constants"]],"Copy Constructor Elision":[[9,"copy-constructor-elision"]],"Copying Tested Binaries":[[24,"copying-tested-binaries"]],"Copying from Secondary Translation Units":[[25,"copying-from-secondary-translation-units"]],"Correspondence Checking":[[25,"correspondence-checking"]],"Covariant return types on virtual functions":[[16,"covariant-return-types-on-virtual-functions"]],"Creating a PCH File":[[0,"creating-a-pch-file"]],"Data Members":[[4,"data-members"]],"Data Structures":[[23,"data-structures"]],"Debug Code":[[14,"debug-code"]],"Debug Print Routines":[[22,"debug-print-routines"]],"Debug Routines":[[0,"debug-routines"]],"Debugging":[[17,"debugging"]],"Debugging Facilities":[[25,"debugging-facilities"]],"Declaration Parse State":[[6,"declaration-parse-state"]],"Declaration Scanning":[[6,"declaration-scanning"]],"Declaration Specifiers":[[6,"declaration-specifiers"]],"Declarations":[[3,"declarations"],[5,"declarations"],[6,null]],"Declarations from C++/CLI Assembly Metadata":[[6,"declarations-from-c-cli-assembly-metadata"]],"Declarations vs. Expressions":[[6,"declarations-vs-expressions"]],"Declarators":[[6,"declarators"]],"Default Arguments":[[3,"default-arguments"]],"Default Initialization":[[6,"default-initialization"]],"Deferred Class Fixup":[[3,"deferred-class-fixup"]],"Delegates (C++/CLI mode)":[[3,"delegates-c-cli-mode"]],"Dependent Name Processing":[[10,"dependent-name-processing"]],"Derivation Path":[[3,"derivation-path"]],"Deserialization":[[17,"deserialization"]],"Destructor Wrapper Code":[[16,"destructor-wrapper-code"]],"Destructor-initializers":[[6,"destructor-initializers"]],"Development Aids":[[1,"development-aids"]],"Diagnostic Messages":[[10,"diagnostic-messages"]],"Diagnostic Options":[[10,"diagnostic-options"]],"Diagnostic Pragmas":[[10,"diagnostic-pragmas"]],"Diagnostic output":[[9,"diagnostic-output"]],"Directories and Files in a Release":[[1,"directories-and-files-in-a-release"]],"Documentation":[[4,"documentation"]],"Driving the Front End":[[1,"driving-the-front-end"]],"Dynamic Initialization":[[11,"dynamic-initialization"],[16,"dynamic-initialization"]],"EDG Testing Framework":[[24,null]],"Empty Loop Bodies":[[4,"empty-loop-bodies"]],"Endianness Agnostic Reading":[[17,"endianness-agnostic-reading"]],"Entry Prefix":[[11,"entry-prefix"]],"Environment Variables":[[10,"environment-variables"]],"Error Codes":[[14,"error-codes"]],"Error Entries":[[14,"error-entries"]],"Error Messages":[[7,null]],"Error Positions":[[14,"error-positions"]],"Error Recovery":[[14,"error-recovery"]],"Error Reporting":[[0,"error-reporting"]],"Exception Handling":[[8,null]],"Exception Specifications":[[8,"exception-specifications"]],"Exceptions":[[16,"exceptions"]],"Executable Code":[[5,"executable-code"]],"Exit Status":[[10,"exit-status"]],"Explicit Bounds Copying":[[17,"explicit-bounds-copying"]],"Explicit Instantiation Directives":[[23,"explicit-instantiation-directives"]],"Explicit Specializations":[[23,"explicit-specializations"]],"Explicit and Implicit Captures":[[3,"explicit-and-implicit-captures"]],"Exported Templates":[[10,"exported-templates"],[23,"exported-templates"]],"Expression Lists and Initializer Lists":[[9,"expression-lists-and-initializer-lists"]],"Expression Processing":[[14,"expression-processing"]],"Expression Scanning":[[9,null]],"Expression Temporaries":[[16,"expression-temporaries"]],"Expressions":[[11,"expressions"],[22,"expressions"]],"Extensions Accepted in Cfront 2.1 Compatibility Mode":[[10,"extensions-accepted-in-cfront-2-1-compatibility-mode"]],"Extensions Accepted in Cfront 2.1 and 3.0 Compatibility Mode":[[10,"extensions-accepted-in-cfront-2-1-and-3-0-compatibility-mode"]],"Extensions Accepted in SVR4 Compatibility Mode":[[10,"extensions-accepted-in-svr4-compatibility-mode"]],"Extensions Accepted in Sun Compatibility Mode":[[10,"extensions-accepted-in-sun-compatibility-mode"]],"Extern Inline Functions":[[10,"extern-inline-functions"]],"External Interface":[[10,null]],"External Names":[[14,"external-names"]],"Externalization of statics":[[25,"externalization-of-statics"]],"Failure Debug Mode":[[24,"failure-debug-mode"]],"Failure Limiting":[[24,"failure-limiting"]],"Field Copying":[[17,"field-copying"]],"Field Deserialization":[[17,"field-deserialization"]],"Field Initializers":[[3,"field-initializers"]],"Field Presence Checking":[[17,"field-presence-checking"]],"Field Selection":[[11,"field-selection"]],"Fields":[[3,"fields"]],"File Variables":[[0,"file-variables"]],"File-Loaded Filters":[[24,"file-loaded-filters"]],"Filter Reduction":[[24,"filter-reduction"]],"Filtering":[[24,"filtering"]],"Finding Corresponding Pairs":[[25,"finding-corresponding-pairs"]],"Finding Include Files":[[10,"finding-include-files"]],"Finding Module Files":[[10,"finding-module-files"]],"Finding the exported template definition":[[10,"finding-the-exported-template-definition"]],"Fixed-point operations":[[11,"fixed-point-operations"]],"Fold Expressions":[[11,"fold-expressions"]],"Folding and constexpr":[[9,"folding-and-constexpr"]],"Folding of Constant Operations":[[9,"folding-of-constant-operations"]],"For-each Statement":[[9,"for-each-statement"]],"Foreign Index":[[17,"foreign-index"],[17,"id5"]],"Friend Declarations":[[3,"friend-declarations"]],"Front End Behaviors":[[1,"front-end-behaviors"]],"Front End Debugging Options":[[10,"front-end-debugging-options"]],"Full Instantiation":[[23,"full-instantiation"]],"Function":[[2,"function"]],"Function Overloading":[[21,"function-overloading"]],"Function Template References":[[15,"function-template-references"]],"Function Templates":[[23,"function-templates"],[23,"id5"],[23,"id7"],[23,"id14"]],"Function Templates and Member Functions of Class Templates":[[23,"function-templates-and-member-functions-of-class-templates"]],"Function of the Front End":[[14,"function-of-the-front-end"]],"GNU C++ Mode":[[10,"gnu-c-mode"]],"General Condition Rules":[[4,"general-condition-rules"]],"General Information":[[11,"general-information"]],"General Layout Steps":[[3,"general-layout-steps"]],"General Line Breaks":[[4,"general-line-breaks"]],"General Line Wrapping":[[4,"general-line-wrapping"]],"General Statement Rules":[[4,"general-statement-rules"]],"General Whitespace Rules":[[4,"general-whitespace-rules"]],"Generalized Identifier Errors":[[15,"generalized-identifier-errors"]],"Generated C Code":[[2,"generated-c-code"]],"Generating Strings from IL Types and Constants":[[0,"generating-strings-from-il-types-and-constants"]],"Generating the Template Class":[[23,"generating-the-template-class"]],"Getting Information About Base Classes":[[22,"getting-information-about-base-classes"]],"Getting Tokens":[[15,"getting-tokens"]],"Guard Code on Variable Template and Template Static Data Member Initializations":[[16,"guard-code-on-variable-template-and-template-static-data-member-initializations"]],"Guide to the Source Files":[[14,"guide-to-the-source-files"]],"Hanging Delete":[[15,"hanging-delete"]],"Header Node":[[17,"header-node"]],"Hide-by-sig lookup":[[21,"hide-by-sig-lookup"]],"Host-dependent Routines":[[0,"host-dependent-routines"]],"How To Extend the IL":[[11,"how-to-extend-the-il"]],"How is IL Lowering Done?":[[16,"how-is-il-lowering-done"]],"How to Add A New Pragma":[[18,"how-to-add-a-new-pragma"]],"How to Add a New Attribute":[[18,"how-to-add-a-new-attribute"]],"IA-64 ABI name mangling":[[16,"ia-64-abi-name-mangling"]],"IL Display Pragma":[[10,"il-display-pragma"]],"IL Features":[[1,"il-features"]],"IL Lowering":[[16,null]],"IL Representation":[[6,"il-representation"]],"IL Use Within the Front End":[[11,"il-use-within-the-front-end"]],"Identifiers and Symbol Headers":[[21,"identifiers-and-symbol-headers"]],"Impact on Versioning":[[17,"impact-on-versioning"]],"Implementing Alternative Automatic Instantiation Mechanisms":[[23,"implementing-alternative-automatic-instantiation-mechanisms"]],"Implicit Bounds Copying":[[17,"implicit-bounds-copying"]],"Implicit Conversion":[[17,"implicit-conversion"]],"Implicit Inclusion":[[10,"implicit-inclusion"],[23,"implicit-inclusion"]],"Important Constrained-Template Functions":[[23,"important-constrained-template-functions"]],"In the handler":[[8,"in-the-handler"]],"Include Files":[[14,"include-files"]],"Index Sort":[[17,"index-sort"],[17,"ifc-index-sort-versioning"],[17,"id10"]],"Indices and tables":[[13,"indices-and-tables"]],"Individual Language Features":[[10,"individual-language-features"]],"Init Components and Init States":[[6,"init-components-and-init-states"]],"Initial Compilation":[[23,"initial-compilation"]],"Initialization":[[6,"initialization"]],"Initialization Positions":[[16,"initialization-positions"]],"Initialization and Wrapup":[[0,"initialization-and-wrapup"]],"Initialization, Termination, and Keeping Translation Units Separate":[[25,"initialization-termination-and-keeping-translation-units-separate"]],"Inline Definitions":[[3,"inline-definitions"]],"Inlining":[[16,"inlining"]],"Input/output Options":[[10,"input-output-options"]],"Insert Locations":[[16,"insert-locations"]],"Inserting Text into the Token Stream":[[15,"inserting-text-into-the-token-stream"]],"Instantiating Non-Template Inline Functions":[[23,"instantiating-non-template-inline-functions"]],"Instantiation #pragma Directives":[[10,"instantiation-pragma-directives"]],"Instantiation Context Lookup":[[21,"instantiation-context-lookup"]],"Instantiation Modes":[[10,"instantiation-modes"],[23,"instantiation-modes"]],"Instantiation Pragmas":[[10,"instantiation-pragmas"]],"Intelligent Error Diagnosis":[[14,"intelligent-error-diagnosis"]],"Intermediate Language":[[11,null]],"Intermediate Language Display":[[0,"intermediate-language-display"]],"Intermediate Language Files":[[11,"intermediate-language-files"]],"Intermediate Language Traversal":[[0,"intermediate-language-traversal"]],"Introduction":[[13,"introduction"]],"Introduction to Attributes":[[18,"introduction-to-attributes"]],"Introduction to Pragma Processing":[[18,"introduction-to-pragma-processing"]],"Iteration and Termination":[[23,"iteration-and-termination"]],"K&R/pcc Mode":[[10,"k-r-pcc-mode"]],"Labels":[[11,"labels"]],"Lambda Expression":[[11,"lambda-expression"]],"Lambdas":[[3,"lambdas"]],"Language Dialect":[[14,"language-dialect"]],"Language Dialect Options":[[10,"language-dialect-options"]],"Lexical Analysis":[[15,"lexical-analysis"]],"Lexical Analysis and Preprocessing":[[15,null]],"Libraries with exported templates":[[10,"libraries-with-exported-templates"]],"Limited Scope":[[17,"limited-scope"]],"Linkage Specifications":[[6,"linkage-specifications"]],"Lists of Entries":[[22,"lists-of-entries"]],"Live Feedback":[[24,"live-feedback"]],"Looking Up Class Members":[[21,"looking-up-class-members"]],"Looking Up Names in the Current Scope":[[21,"looking-up-names-in-the-current-scope"]],"Looking Up Names in the File Scope":[[21,"looking-up-names-in-the-file-scope"]],"Looking Up Namespace Members":[[21,"looking-up-namespace-members"]],"Looking for Class Member Projection Symbols":[[21,"looking-for-class-member-projection-symbols"]],"Lookup Options":[[21,"lookup-options"]],"Lookup Using the Referencing Context":[[10,"lookup-using-the-referencing-context"]],"Lookup of Entities Imported from C++/CLI Metadata":[[21,"lookup-of-entities-imported-from-c-cli-metadata"]],"Low-level Fixed-point Routines":[[9,"low-level-fixed-point-routines"]],"Low-level Floating-point Routines":[[9,"low-level-floating-point-routines"]],"Low-level Integer Routines":[[9,"low-level-integer-routines"]],"Lowering C Dialects":[[16,"lowering-c-dialects"]],"Lowering GNU function multiversioning":[[16,"lowering-gnu-function-multiversioning"]],"Lowering extern inline":[[16,"lowering-extern-inline"]],"Lowering ifunc":[[16,"lowering-ifunc"]],"Lowering thread_local":[[16,"lowering-thread-local"]],"Lvalues and Rvalues (Value Categories)":[[11,"lvalues-and-rvalues-value-categories"]],"Macro Definition Data Structure":[[15,"macro-definition-data-structure"]],"Macro Definitions":[[15,"macro-definitions"]],"Macro Invocation Tree":[[15,"macro-invocation-tree"]],"Macro Invocations":[[15,"macro-invocations"]],"Macro Position Tracking":[[15,"macro-position-tracking"]],"Macro Processing":[[15,"macro-processing"]],"Macros":[[11,"macros"]],"Main Program":[[16,"main-program"]],"Maintained Context":[[16,"maintained-context"]],"Maintaining Context":[[16,"maintaining-context"]],"Managing Instantiation of Functions, Variables, and Static Data Members":[[23,"managing-instantiation-of-functions-variables-and-static-data-members"]],"Manual Precompiled Header Processing":[[10,"manual-precompiled-header-processing"]],"Marking the initiation of the exception (__exception_started)":[[8,"marking-the-initiation-of-the-exception-exception-started"]],"Member Constant Extension":[[3,"member-constant-extension"]],"Member Function Templates":[[3,"member-function-templates"]],"Member Function of Class Templates":[[23,"member-function-of-class-templates"]],"Member Functions":[[3,"member-functions"],[4,"member-functions"]],"Member Initializer":[[4,"member-initializer"]],"Memory Management":[[0,"memory-management"],[11,"memory-management"]],"Memory Management Issues":[[0,"memory-management-issues"]],"Memory Region Processing Order":[[11,"memory-region-processing-order"]],"Memory Regions":[[11,"memory-regions"]],"Memory Regions and Intermediate Language":[[25,"memory-regions-and-intermediate-language"]],"Memory Regions and Pointers":[[11,"memory-regions-and-pointers"]],"Microsoft Attributes":[[6,"microsoft-attributes"]],"Microsoft C++ Mode":[[10,"microsoft-c-mode"]],"Microsoft C++/CLI Mode":[[10,"microsoft-c-cli-mode"]],"Microsoft Pragmas":[[10,"microsoft-pragmas"]],"Microsoft __if_exists blocks":[[11,"microsoft-if-exists-blocks"]],"Miscellaneous Options":[[10,"miscellaneous-options"]],"Modifications to the Current Source Line":[[15,"modifications-to-the-current-source-line"]],"Modifying Type Trees":[[22,"modifying-type-trees"]],"Modules":[[17,null]],"Multi-Configuration Support":[[24,"multi-configuration-support"]],"Multi-file Testing":[[24,"multi-file-testing"]],"Multibyte characters in source code":[[15,"multibyte-characters-in-source-code"]],"Multiple Translation Units":[[25,null]],"Name Linkage":[[11,"name-linkage"]],"Name Mangling":[[16,"name-mangling"]],"Name Scope":[[3,"name-scope"]],"Name Scopes":[[21,"name-scopes"]],"Names":[[3,"names"],[5,"names"]],"Namespace Declarations":[[6,"namespace-declarations"]],"Namespace Projection Symbols":[[21,"namespace-projection-symbols"]],"Namespace Support":[[10,"namespace-support"]],"Namespace Symbols":[[21,"namespace-symbols"]],"Namespaces":[[6,"namespaces"],[11,"namespaces"],[16,"namespaces"]],"Namespaces and the Standard Header Files":[[12,"namespaces-and-the-standard-header-files"]],"Naming Convention":[[4,"naming-convention"]],"Needed Flags":[[0,"needed-flags"]],"Negative Filters":[[24,"negative-filters"]],"Nested Class Anachronism Lookup":[[21,"nested-class-anachronism-lookup"]],"New and Delete":[[11,"new-and-delete"],[16,"new-and-delete"]],"No Expectations Mode":[[24,"no-expectations-mode"]],"No Flakey Tests Mode":[[24,"no-flakey-tests-mode"]],"Nodes":[[17,"nodes"],[17,"ifc-node-versioning"],[17,"id11"],[17,"id13"]],"Non-Portable Implementation":[[8,"non-portable-implementation"]],"Nonreal and Proxy Class Lookup":[[21,"nonreal-and-proxy-class-lookup"]],"Nonreal and Proxy Class Members":[[21,"nonreal-and-proxy-class-members"]],"Object Layout Models":[[3,"object-layout-models"]],"Object Lifetimes":[[11,"object-lifetimes"],[16,"object-lifetimes"],[22,"object-lifetimes"]],"Offset and Alignment":[[3,"offset-and-alignment"]],"Once Pragma":[[10,"once-pragma"]],"One-instantiation-per-object mode":[[25,"one-instantiation-per-object-mode"]],"Operand Data Structure":[[9,"operand-data-structure"]],"Operation":[[2,"operation"]],"Operation Expressions":[[11,"operation-expressions"]],"Operations Returning Lvalues":[[16,"operations-returning-lvalues"]],"Operator Overloading":[[9,"operator-overloading"]],"Optional Components":[[1,"optional-components"]],"Ordering Dependencies":[[25,"ordering-dependencies"]],"Orphaned Entries":[[16,"orphaned-entries"],[22,"orphaned-entries"]],"Orphans":[[11,"orphans"]],"Other Declarative Entries":[[22,"other-declarative-entries"]],"Other Ways for Users to Control Precompiled Headers":[[10,"other-ways-for-users-to-control-precompiled-headers"]],"Overloaded Function Calls":[[9,"overloaded-function-calls"]],"Overloaded Operators":[[21,"overloaded-operators"]],"Overloading":[[3,"overloading"]],"Overview":[[3,"overview"],[6,"overview"],[23,"overview"],[23,"id2"]],"Overview of Internal Structure":[[14,null]],"Pack Pragma":[[10,"pack-pragma"]],"Parameter Alignment":[[4,"parameter-alignment"]],"Parameters":[[11,"parameters"]],"Parentheses":[[11,"parentheses"]],"Parsing Attributes":[[18,"parsing-attributes"]],"Parsing Technique":[[9,"parsing-technique"]],"Partial Instantiation":[[23,"partial-instantiation"]],"Partial Specializations":[[23,"partial-specializations"]],"Partition Kinds":[[17,"partition-kinds"]],"Partition Node":[[17,"partition-node"]],"Passthrough":[[17,"passthrough"]],"Performance Issues":[[10,"performance-issues"]],"Phase One: Recording Pragmas":[[18,"phase-one-recording-pragmas"]],"Phase Three: Interpreting Pragmas":[[18,"phase-three-interpreting-pragmas"]],"Phase Two: Dispatching Pragmas":[[18,"phase-two-dispatching-pragmas"]],"Placement Delete":[[16,"placement-delete"]],"Point of Validation":[[17,"point-of-validation"]],"Pointer & Reference Types":[[4,"pointer-reference-types"]],"Pointers to Members":[[11,"pointers-to-members"],[16,"pointers-to-members"]],"Portable Implementation":[[8,"portable-implementation"]],"Post-condition":[[4,"post-condition"]],"Pragmas":[[10,"pragmas"],[11,"pragmas"]],"Pragmas and Attributes":[[18,null]],"Pre-checked Data":[[17,"pre-checked-data"]],"Pre-condition":[[4,"pre-condition"]],"Precompiled Header Options":[[10,"precompiled-header-options"]],"Precompiled Header Pragmas":[[10,"precompiled-header-pragmas"]],"Precompiled Headers":[[0,"precompiled-headers"],[10,"precompiled-headers"]],"Predefined Macro Definition File":[[0,"predefined-macro-definition-file"]],"Predefined Macros":[[10,"predefined-macros"]],"Prefix and Header Stop Point":[[0,"prefix-and-header-stop-point"]],"Prelinker":[[23,"prelinker"]],"Preprocessing Directives":[[15,"preprocessing-directives"]],"Preprocessor Directives":[[4,"preprocessor-directives"]],"Preprocessor Options":[[10,"preprocessor-options"]],"Primitive Operations on Operands":[[9,"primitive-operations-on-operands"]],"Problem Reporting":[[24,"problem-reporting"]],"Prologue code for a function that may need clean-up if an exception is thrown":[[8,"prologue-code-for-a-function-that-may-need-clean-up-if-an-exception-is-thrown"]],"Prologue code for a function with an exception specification":[[8,"prologue-code-for-a-function-with-an-exception-specification"]],"Promotion of Local Entities to File Scope":[[16,"promotion-of-local-entities-to-file-scope"]],"Properties":[[9,"properties"],[11,"properties"]],"Properties and Events (Microsoft and C++/CLI modes)":[[3,"properties-and-events-microsoft-and-c-cli-modes"]],"Prototype Scopes":[[5,"prototype-scopes"]],"Range-based":[[4,"range-based"]],"Range-based for statement":[[9,"range-based-for-statement"]],"Raw Bytes":[[17,"raw-bytes"]],"Raw Listing Output":[[15,"raw-listing-output"]],"Raw Numeric":[[17,"raw-numeric"]],"Raw Values":[[17,"raw-values"]],"Re-record Mode":[[24,"re-record-mode"]],"Reading Logical Source Lines":[[15,"reading-logical-source-lines"]],"Reading the Intermediate Language from a File":[[0,"reading-the-intermediate-language-from-a-file"]],"Recognizing Attributes":[[18,"recognizing-attributes"]],"Recognizing Generalized Identifiers":[[15,"recognizing-generalized-identifiers"]],"Recompilation":[[23,"recompilation"]],"Recursive Descent Parsing":[[14,"recursive-descent-parsing"]],"Reference Information":[[9,"reference-information"]],"References":[[5,"references"],[11,"references"]],"Regress Mode":[[24,"regress-mode"]],"Related Class Casts":[[16,"related-class-casts"]],"Relationship of the IL and the Symbol Table":[[11,"relationship-of-the-il-and-the-symbol-table"]],"Replaceable Code":[[1,"replaceable-code"]],"Replay mode":[[24,"replay-mode"]],"Replaying Failed Test":[[24,"replaying-failed-test"]],"Replaying Mismatched":[[24,"replaying-mismatched"]],"Replaying Regressions":[[24,"replaying-regressions"]],"Replaying Subset of Failed Test":[[24,"replaying-subset-of-failed-test"]],"Replaying Unexpected":[[24,"replaying-unexpected"]],"Representation of constraints":[[23,"representation-of-constraints"]],"Rescanning Expressions":[[9,"rescanning-expressions"]],"Response to Signals":[[10,"response-to-signals"]],"Return Value":[[4,"return-value"]],"Return Value Optimization":[[16,"return-value-optimization"]],"Returns":[[11,"returns"]],"Reusable Copies":[[16,"reusable-copies"]],"Rewritten Property References":[[5,"rewritten-property-references"]],"Roles":[[17,"roles"]],"Routines":[[11,"routines"],[16,"routines"]],"Routines that Implement Language Concepts":[[22,"routines-that-implement-language-concepts"]],"Run-Time Support":[[8,"run-time-support"]],"Run-Time storage management":[[8,"run-time-storage-management"]],"Runtime Library":[[19,null]],"Runtime Support":[[10,"runtime-support"]],"Runtime Type Information":[[16,"runtime-type-information"]],"Scanning Constants":[[9,"scanning-constants"]],"Scanning Identifiers":[[9,"scanning-identifiers"]],"Scanning Names in C++":[[15,"scanning-names-in-c"]],"Scanning Operations":[[9,"scanning-operations"]],"Scanning the Lambda Body":[[3,"scanning-the-lambda-body"]],"Scope List":[[21,"scope-list"]],"Secondary translation units":[[10,"secondary-translation-units"]],"Selector Operands":[[9,"selector-operands"]],"Sequencing":[[16,"sequencing"]],"Setting Sizes and Alignments of Types":[[22,"setting-sizes-and-alignments-of-types"]],"Setup Requirements":[[24,"setup-requirements"]],"Simple Sort":[[17,"simple-sort"],[17,"ifc-simple-sort-versioning"],[17,"id9"]],"Single-file Testing":[[24,"single-file-testing"]],"Sizeof":[[11,"sizeof"]],"Skipping Validation":[[17,"skipping-validation"]],"Skipping White Space":[[15,"skipping-white-space"]],"Slow Lookup Processing (scope_stack_lookup)":[[21,"slow-lookup-processing-scope-stack-lookup"]],"Slow Test Reporting":[[24,"slow-test-reporting"]],"Source Correspondence Information":[[11,"source-correspondence-information"]],"Source File Information":[[11,"source-file-information"],[22,"source-file-information"]],"Source Line Data Structure":[[15,"source-line-data-structure"]],"Source Output":[[5,"source-output"]],"Source Positions":[[14,"source-positions"],[15,"source-positions"]],"Source Sequence Entries":[[22,"source-sequence-entries"]],"Source Sequence Lists":[[5,"source-sequence-lists"],[11,"source-sequence-lists"]],"Source positions":[[11,"source-positions"]],"Special Cases":[[4,"special-cases"],[21,"special-cases"]],"Special Filters":[[24,"special-filters"]],"Stage 0":[[17,"stage-0"]],"Stage 1":[[17,"stage-1"]],"Stage 2":[[17,"stage-2"]],"Stage 3":[[17,"stage-3"]],"Stage 4":[[17,"stage-4"]],"Stage 5":[[17,"stage-5"]],"Stage 5 (Wrap-up)":[[17,"stage-5-wrap-up"]],"Stage 6 (Wrap-up)":[[17,"stage-6-wrap-up"]],"Stage Breakdown":[[17,"stage-breakdown"]],"Stages":[[17,"stages"]],"Standard Attributes, GNU Attributes, and __declspec Attributes":[[6,"standard-attributes-gnu-attributes-and-declspec-attributes"]],"Standard C++ Include Files":[[12,"standard-c-include-files"]],"Statement Scanning":[[20,null]],"Statements":[[4,"statements"],[11,"statements"],[22,"statements"]],"Static Data Members":[[3,"static-data-members"]],"Static Data Members of Class Templates":[[23,"static-data-members-of-class-templates"]],"Static vs. Nonstatic":[[3,"static-vs-nonstatic"]],"Storage Allocation":[[14,"storage-allocation"],[22,"storage-allocation"]],"Subscripting":[[11,"subscripting"]],"Support for Source Language Dialects":[[1,"support-for-source-language-dialects"]],"Symbol Locator":[[21,"symbol-locator"]],"Symbol Lookup":[[21,"symbol-lookup"]],"Symbol Management":[[21,"symbol-management"]],"Symbol Table":[[21,null]],"Symbols and IL Entries":[[21,"symbols-and-il-entries"]],"Symbols and Symbol Headers":[[21,"symbols-and-symbol-headers"]],"Syntax Errors":[[14,"syntax-errors"]],"Synthesized Namespace Projection Symbols":[[21,"synthesized-namespace-projection-symbols"]],"Table Management":[[22,null]],"Tacit Field":[[17,"tacit-field"]],"Tacit Field Implementation":[[17,"tacit-field-implementation"]],"Tagless Classes":[[3,"tagless-classes"]],"Taking Apart Types":[[22,"taking-apart-types"]],"Target Platform Options":[[1,"target-platform-options"]],"Target-Specific Configuration":[[1,"target-specific-configuration"]],"Template Class References":[[15,"template-class-references"]],"Template Conversion Operators":[[21,"template-conversion-operators"]],"Template Declaration Information":[[23,"template-declaration-information"]],"Template Declarations":[[23,"template-declarations"]],"Template Instantiation":[[10,"template-instantiation"]],"Template Instantiation Options":[[10,"template-instantiation-options"]],"Template Parameter Clauses":[[23,"template-parameter-clauses"]],"Template Parameters":[[4,"template-parameters"]],"Template References":[[15,"template-references"]],"Template Symbols":[[21,"template-symbols"]],"Templates":[[4,"templates"],[11,"templates"],[23,null]],"Templates and Macros":[[5,"templates-and-macros"]],"Templates in the IL":[[23,"templates-in-the-il"]],"Temporaries":[[9,"temporaries"]],"Temporary Initialization":[[11,"temporary-initialization"]],"Termination Messages":[[10,"termination-messages"]],"Test Run Cleanup":[[24,"test-run-cleanup"]],"Test Run Status":[[24,"test-run-status"]],"Test Termination":[[24,"test-termination"]],"Testing Tools":[[24,"testing-tools"]],"Textual Preprocessing Output":[[15,"textual-preprocessing-output"]],"The --building_runtime option":[[19,"the-building-runtime-option"]],"The Active Symbol List":[[21,"the-active-symbol-list"]],"The Copy Address Pointer":[[25,"the-copy-address-pointer"]],"The Current Source Line":[[15,"the-current-source-line"]],"The EH Stack":[[8,"the-eh-stack"]],"The Empty Base Class Layout Optimization":[[3,"the-empty-base-class-layout-optimization"]],"The Expression Stack":[[9,"the-expression-stack"]],"The IL Header":[[11,"the-il-header"]],"The IL Lowering Flag":[[16,"the-il-lowering-flag"]],"The Inactive Symbol Lists":[[21,"the-inactive-symbol-lists"]],"The Input Stack":[[15,"the-input-stack"]],"The Macro Buffer":[[15,"the-macro-buffer"]],"The Scope Entry":[[11,"the-scope-entry"]],"The Template Information and Instantiation Request Files":[[23,"the-template-information-and-instantiation-request-files"]],"The defines.h File":[[1,"the-defines-h-file"]],"The dettarg Utility":[[1,"the-dettarg-utility"]],"The dynamic_cast operator":[[16,"the-dynamic-cast-operator"]],"The eccp script":[[1,"the-eccp-script"]],"The edgcc Driver for Windows":[[1,"the-edgcc-driver-for-windows"]],"The typeid operator":[[16,"the-typeid-operator"]],"The \u201cLambda Declarator\u201d":[[3,"the-lambda-declarator"]],"The \u201cOther\u201d Symbol List":[[21,"the-other-symbol-list"]],"Throw Expression":[[11,"throw-expression"]],"Throwing an Exception":[[16,"throwing-an-exception"]],"Throwing an exception (__throw)":[[8,"throwing-an-exception-throw"]],"Throwing an exception (__throw_setup)":[[8,"throwing-an-exception-throw-setup"]],"Throwing an exception (generated code)":[[8,"throwing-an-exception-generated-code"]],"Token Lookahead and Caching":[[15,"token-lookahead-and-caching"]],"Transformations":[[2,"transformations"]],"Transformations on Operands":[[9,"transformations-on-operands"]],"Translation Unit Correspondences":[[25,"translation-unit-correspondences"]],"Troublesome Cases":[[5,"troublesome-cases"]],"Type Conversions":[[9,"type-conversions"]],"Type Entries":[[22,"type-entries"]],"Type Names in Expressions":[[6,"type-names-in-expressions"]],"Type, Scope, and Symbol":[[3,"type-scope-and-symbol"]],"Type-Transforming Attributes":[[18,"type-transforming-attributes"]],"Typerefs":[[11,"typerefs"],[14,"typerefs"],[22,"typerefs"]],"Types":[[11,"types"],[22,"types"]],"Unbound Pragmas":[[18,"unbound-pragmas"]],"Unchecked Data":[[17,"unchecked-data"]],"Unordered Evaluation":[[16,"unordered-evaluation"]],"Unscanning Attributes":[[18,"unscanning-attributes"]],"User-Defined Conversions":[[3,"user-defined-conversions"],[21,"user-defined-conversions"]],"User-defined Conversions":[[9,"user-defined-conversions"]],"Using Declarations and Access Declarations":[[3,"using-declarations-and-access-declarations"]],"Using a PCH file":[[0,"using-a-pch-file"]],"Using the Top-Level Makefile":[[1,"using-the-top-level-makefile"]],"Using-Declarations":[[6,"using-declarations"]],"Using-Directives":[[6,"using-directives"]],"Utility Programs":[[26,null]],"Utility Routines":[[15,"utility-routines"]],"VLA Deallocation":[[11,"vla-deallocation"]],"Validation":[[17,"validation"]],"Validation Cache":[[17,"validation-cache"]],"Value Categories":[[17,"value-categories"]],"Value Category":[[17,"value-category"],[17,"id6"]],"Variable Grouping":[[4,"variable-grouping"]],"Variable Initializers":[[6,"variable-initializers"]],"Variable Template References":[[15,"variable-template-references"]],"Variable Templates":[[23,"variable-templates"],[23,"id8"],[23,"id11"]],"Variable Templates and Static Data Member Templates":[[23,"variable-templates-and-static-data-member-templates"]],"Variable Templates and Static Data Members of Class Templates":[[23,"variable-templates-and-static-data-members-of-class-templates"]],"Variables":[[11,"variables"]],"Variadic Templates":[[23,"variadic-templates"]],"Verbose Mode":[[24,"verbose-mode"]],"Versioning":[[17,"versioning"]],"Virtual Base Class":[[3,"virtual-base-class"]],"Virtual Function Tables":[[11,"virtual-function-tables"],[16,"virtual-function-tables"]],"Virtual Functions":[[3,"virtual-functions"],[3,"id13"]],"Visitors":[[17,"visitors"]],"Void Expressions":[[9,"void-expressions"]],"What Does C++ IL Lowering Do?":[[16,"what-does-c-il-lowering-do"]],"Whitespace keywords":[[15,"whitespace-keywords"]],"With Memory Mapping":[[17,"with-memory-mapping"]],"Without Memory Mapping":[[17,"without-memory-mapping"]],"Wrapping Function Calls":[[4,"wrapping-function-calls"]],"Wrapping Function Declarations":[[4,"wrapping-function-declarations"]],"Writing a Class":[[4,"writing-a-class"]],"Writing a Function":[[4,"writing-a-function"]],"Writing a Lambda":[[4,"writing-a-lambda"]],"Writing a Test File":[[24,"writing-a-test-file"]],"Writing a Variable":[[4,"writing-a-variable"]],"Writing the Intermediate Language to a File":[[0,"writing-the-intermediate-language-to-a-file"]],"asm Declarations":[[6,"asm-declarations"]],"asm Statements":[[11,"asm-statements"]],"basics.h and Build Environment Configuration":[[1,"basics-h-and-build-environment-configuration"]],"bool":[[16,"bool"]],"edg-run-test":[[24,"edg-run-test"]],"edg_decode":[[26,"edg-decode"]],"edg_munch":[[26,"edg-munch"]],"edg_prelink":[[26,"edg-prelink"]],"edgy":[[24,"edgy"]],"for Statements":[[4,"for-statements"]],"get_ifc_partition_element_size":[[17,"get-ifc-partition-element-size"]],"get_ifc_partition_kind":[[17,"get-ifc-partition-kind"]],"has_partition_kind":[[17,"has-partition-kind"]],"if Statements":[[4,"if-statements"]],"lang_feat.h, host_envir.h, targ_def.h, and target.h":[[1,"lang-feat-h-host-envir-h-targ-def-h-and-target-h"]],"mk_errinfo":[[26,"mk-errinfo"]],"normal_id_lookup":[[21,"normal-id-lookup"]],"push_scope and pop_scope":[[21,"push-scope-and-pop-scope"]],"referenced and needed Flags":[[11,"referenced-and-needed-flags"]],"scan_expr_full":[[9,"scan-expr-full"]],"scan_expr_full Processing":[[9,"scan-expr-full-processing"]],"switch Statements":[[4,"switch-statements"]],"throw Expressions":[[8,"throw-expressions"]],"to/from_partition_kind":[[17,"to-from-partition-kind"]],"try Blocks":[[8,"try-blocks"]],"typeid":[[11,"typeid"]],"using-Directive Processing":[[21,"using-directive-processing"]],"while Statements":[[4,"while-statements"]],"\u201cDefault\u201d C++ Mode":[[10,"default-c-mode"]],"\u201cExtern\u201d Symbols":[[21,"extern-symbols"]]},"docnames":["admin","build","c_gen_be","class_decl","code_style","cp_gen_be","decls","err_msgs","exceptions","expr","ext_intf","il","includes","index","int_overview","lex_pp","lower_il","modules","pragma","runtime","statements","symbol_tbl","tables","templates","testing","trans_unit","utilities"],"envversion":{"sphinx":66,"sphinx.domains.c":3,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":9,"sphinx.domains.index":1,"sphinx.domains.javascript":3,"sphinx.domains.math":2,"sphinx.domains.python":4,"sphinx.domains.rst":2,"sphinx.domains.std":2},"filenames":["admin.rst","build.rst","c_gen_be.rst","class_decl.rst","code_style.rst","cp_gen_be.rst","decls.rst","err_msgs.rst","exceptions.rst","expr.rst","ext_intf.rst","il.rst","includes.rst","index.rst","int_overview.rst","lex_pp.rst","lower_il.rst","modules.rst","pragma.rst","runtime.rst","statements.rst","symbol_tbl.rst","tables.rst","templates.rst","testing.rst","trans_unit.rst","utilities.rst"],"indexentries":{},"objects":{},"objnames":{},"objtypes":{},"terms":{"0d":8,"0f":23,"0i":16,"0l":15,"0x":10,"0x01":16,"0x02":16,"0x04":16,"0x08":16,"0x1":16,"0x10":16,"0x123e":10,"0x2":16,"0x80000000":10,"0x80000001":10,"10k":0,"11_sfina":[7,10],"11_sfinae_ignore_access":10,"12clisafe_cast":16,"12clisubscript":16,"14__interior_ptr":16,"16be":[7,10],"16le":[7,10],"199409l":10,"199711l":10,"199901l":10,"1c":[16,18],"1e":10,"1st":4,"200406l":10,"201103l":10,"250k":10,"2nd":4,"34_km":10,"3rd":4,"3rd_arg_of_assume_aligned_must_be_integr":7,"4abcd":16,"5abcd":16,"64k":0,"7abcdefg":16,"82a9":15,"8__handl":16,"8__trkref":16,"9__pin_ptr":16,"9clihandl":16,"9clitypeid":16,"A":[0,1,2,3,4,5,6,9,10,11,13,14,15,16,17,19,20,21,22,23,24,25,26],"AT":10,"About":[9,15],"After":[0,1,3,6,8,9,14,15,16,17,18,21,23,25],"Again":[0,16,23],"All":[0,1,3,5,9,10,11,14,15,16,17,21,24,25],"An":[0,1,3,6,8,9,10,11,14,15,16,17,18,20,21,22,23,24,26],"And":[3,9,11,15,16,18,21,22,23],"Are":15,"As":[0,1,3,5,6,8,9,10,11,14,15,16,17,18,20,21,23,24],"At":[0,3,5,9,10,11,14,15,16,17,20,21,23],"Be":11,"Being":21,"Between":[0,9],"Both":[3,5,6,9,10,11,14,15,16,18,21,23,24],"But":[0,3,6,10,15,16,21,23],"By":[0,1,3,9,10,11,14,15,18,23,24,25,26],"Could":25,"Do":[10,11,23,26],"Doing":9,"Each":[0,1,2,3,6,8,9,10,11,14,15,16,17,18,20,21,22,23,25,26],"For":[0,1,2,3,4,5,6,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"From":[10,11,17],"Further":16,"Has":11,"Having":[1,9,10,11,22,23],"Here":[3,6,8,9,10,11,16,17,18,21,23,24],"How":25,"I":[0,1,6,9,10,16,18,23],"If":[0,1,2,3,4,6,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"In":[0,1,2,3,4,5,6,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,25,26],"Is":[9,10,11,16],"It":[0,1,2,3,5,6,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"Its":[0,3,6,9,10,11,13,18,20,26],"More":[5,11,13,16,21],"Most":[0,3,5,6,9,10,11,14,15,16,18,21,23,25,26],"No":[0,3,9,10,11,14,15,16,18,21,23,25],"Not":[0,1,3,9,10,11,12,16,17,25],"OFF":7,"ON":7,"Of":[10,11,14,24],"On":[0,2,3,8,9,10,11,15,16,21,23],"Or":[0,23],"Other":[0,6,9,11,15,23,25],"Same":[3,10],"Should":[10,11,24],"So":[0,3,9,11,14,16,21,23,25],"Some":[0,1,3,5,6,8,9,10,11,14,16,17,18,20,21,25,26],"Such":[0,2,3,6,9,10,11,14,15,16,18,20,21,22,23,25],"TO":16,"That":[0,2,3,5,6,9,10,11,14,15,16,20,21,23,25],"The":[0,2,4,5,6,7,10,12,13,14,17,18,20,22,24,26],"Their":[3,10,11,14,18,23],"Then":[0,2,3,6,8,9,10,11,15,16,17,21,23],"There":[0,2,3,6,9,10,11,13,14,15,16,17,18,20,21,22,23,24,25,26],"These":[0,1,2,3,5,6,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"They":[0,2,3,4,6,9,10,11,14,15,16,18,19,21,22,23,25],"This":[0,1,2,3,4,5,6,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"Those":[0,1,9,10,11,14,16,22],"To":[0,1,3,5,6,8,9,10,14,15,16,17,18,19,21,22,23,24,25,26],"Under":[9,10],"Up":16,"We":[0,15,16,21,23],"What":[3,6,8,11,21],"When":[0,1,2,3,4,5,6,8,9,10,11,12,13,14,15,16,17,18,20,21,22,23,24,25,26],"Where":[3,11,14,16,21],"Which":[15,21],"While":[0,3,6,9,11,15,16,17,21,23,25],"With":[0,6,10,11,13,14,16,23],"Would":16,"You":[0,2,18,24],"_":[7,16,24],"__":[2,16],"__12a__l1__f__fv":16,"__12a__l1__x__fv":16,"__28_7_i":2,"__ab":16,"__alignof__":[9,10,16],"__ansic__":[1,14,19],"__array_delet":16,"__array_new":16,"__array_new_prefix_s":16,"__array_new_zero":16,"__array_oper":10,"__asm":10,"__attribut":[1,6,11,18],"__attribute__":16,"__base":7,"__base_file__":10,"__begin":9,"__bool_defin":10,"__bsd__":[1,2,14,19],"__builtin_assumed_align":7,"__builtin_bit_cast":7,"__builtin_complex":7,"__builtin_constexpr_diag":[7,10],"__builtin_fpclassifi":7,"__builtin_offsetof":7,"__builtin_va_arg_pack":7,"__builtin_va_arg_pack_len":7,"__catch_clause_numb":[8,16],"__caught_object_address":[8,16],"__cbi__":[10,16,23],"__cbi__f__fi__tir__f__fi__dni__f__fi":23,"__cdecl":10,"__cgi__":2,"__char16_t_and_char32_t":10,"__char16_type__":10,"__char32_type__":10,"__char_bit__":0,"__cleanup_vec_new_or_delet":8,"__clrcall":7,"__counter__":10,"__cplusplus":10,"__cplusplus_c":10,"__cpr":16,"__ct__1aff":16,"__cxa_atexit":16,"__cxa_bad_cast":16,"__cxa_bad_typeid":16,"__cxa_deleted_virtu":16,"__cxa_guard_acquir":16,"__cxa_guard_releas":16,"__cxa_pure_virtu":16,"__cxa_thread_atexit":16,"__cxa_vec_cctor":16,"__cxa_vec_ctor":16,"__cxa_vec_delet":16,"__cxa_vec_dtor":16,"__cxa_vec_new":16,"__cxa_vec_new2":16,"__cxa_vec_new3":16,"__date__":[0,10],"__declspec":[1,3,7,9,11,18],"__deleted_virtual_cal":16,"__df__":16,"__direct_bas":7,"__dn":16,"__dni__":[16,23],"__dynamic_cast":16,"__dynamic_cast_ref":16,"__edg__":10,"__edg_abi_changes_for_array_new_and_delet":19,"__edg_abi_changes_for_placement_delet":19,"__edg_abi_changes_for_rtti":19,"__edg_abi_compatibility_vers":19,"__edg_ans":19,"__edg_bsd":19,"__edg_cpp11_il_extensions_support":19,"__edg_delta_typ":19,"__edg_elem_count_param_typ":19,"__edg_ets_flag_typ":19,"__edg_ia64_abi":10,"__edg_ia64_abi_use_int_static_init_guard":10,"__edg_ia64_abi_use_variant_array_cooki":19,"__edg_ia64_abi_variant_ctors_and_dtors_return_thi":10,"__edg_implicit_using_std":[10,12],"__edg_jmp_buf_element_typ":19,"__edg_jmp_buf_num_el":19,"__edg_lower_variable_length_array":19,"__edg_null_eh_region_numb":19,"__edg_ptrdiff_type__":10,"__edg_region_number_typ":19,"__edg_runtime_uses_namespac":[10,12],"__edg_size_type__":10,"__edg_sysv":19,"__edg_type_traits_en":10,"__edg_var_handle_typ":19,"__edg_version__":10,"__edg_virtual_function_index_typ":19,"__eh_curr_region":[8,16],"__embedded_cplusplus":10,"__end":9,"__event":7,"__except":[7,10],"__exception_caught":[8,16],"__exception_start":16,"__fastcal":10,"__file__":[10,11,15],"__final":7,"__float128":9,"__float80":9,"__forceinlin":7,"__free_throw_object":8,"__free_thrown_object":[8,16],"__func__":10,"__funcdname__":10,"__funcsig__":10,"__function__":10,"__gener":10,"__genericfx":10,"__get_typeid":16,"__global":10,"__gnuc__":10,"__gnuc_minor__":10,"__gnuc_patchlevel__":0,"__has_emb":7,"__has_featur":10,"__has_includ":7,"__has_include_next":7,"__has_nothrow_assign":10,"__has_nothrow_constructor":10,"__has_nothrow_copi":10,"__has_nothrow_move_assign":10,"__has_trivial_assign":10,"__has_trivial_constructor":10,"__has_trivial_copi":10,"__has_trivial_destructor":10,"__has_trivial_move_assign":10,"__has_trivial_move_constructor":10,"__has_virtual_destructor":10,"__have_builtin_setjmp__":0,"__hidden":10,"__i__":10,"__if_exist":7,"__if_not_exist":11,"__ifc__":16,"__ifv__":16,"__imag":[7,16],"__impl":7,"__implement":7,"__infinity__":10,"__inlin":7,"__int16":16,"__int32":16,"__int64":16,"__int8":16,"__intaddr__":[7,9,10],"__interfac":[3,7,11],"__internal_rethrow":8,"__is_abstract":10,"__is_base_of":[10,16],"__is_class":10,"__is_construct":10,"__is_convertible_to":10,"__is_destruct":10,"__is_empti":10,"__is_enum":10,"__is_gnu_or_microsoft_mod":0,"__is_literal_typ":10,"__is_nothrow_assign":10,"__is_nothrow_construct":10,"__is_nothrow_destruct":10,"__is_pod":10,"__is_polymorph":10,"__is_sign":7,"__is_standard_layout":10,"__is_trivi":10,"__is_trivially_assign":10,"__is_trivially_construct":10,"__is_trivially_copy":10,"__is_trivially_destruct":10,"__is_union":10,"__l":16,"__l_":2,"__leav":7,"__line__":[10,11,15],"__link":16,"__linkl":16,"__lsg__":16,"__make_sign":7,"__make_unsign":7,"__microsoft_os__":10,"__mptr":16,"__n":16,"__nan__":10,"__no_long_long":10,"__nullptr":16,"__padding__":17,"__pk__":16,"__pl__1aff":16,"__pl__f1af":16,"__placement_array_new":16,"__placement_array_new_zero":16,"__placement_delet":10,"__pragma":7,"__pragma_redefine_extnam":10,"__pretty_function__":10,"__printf_arg":9,"__ps__":16,"__ptr32":7,"__ptr64":7,"__pure_virtual_cal":16,"__q3_10s__tm__2_i1x8__um1_fv":16,"__rang":9,"__real":[7,16],"__record_needed_destruct":16,"__record_needed_thread_destruct":16,"__report_constexpr_valu":7,"__report_token":7,"__res__":16,"__restrict":7,"__rethrow":16,"__rtti":10,"__s":16,"__sbc__":16,"__sbc__x__y______1n":16,"__scanf_arg":9,"__signed_chars__":10,"__so__":16,"__sptr":7,"__st__":16,"__std__":[16,26],"__stdc__":10,"__stdc_hosted__":10,"__stdc_iec_559__":10,"__stdc_iec_559_complex__":10,"__stdc_iso_10646__":10,"__stdc_mb_might_neq_wc__":10,"__stdc_version__":10,"__stdcall":10,"__stdcpp_threads__":10,"__stf__":16,"__sti__":[2,16,26],"__sti__module_id":16,"__stv__":16,"__super":7,"__symbol":10,"__sysv__":[1,14,19],"__t":2,"__t_":16,"__tgt__":16,"__thi__":16,"__thiscal":[7,10],"__thread":10,"__throw":16,"__throw_alloc":[8,16],"__throw_setup":16,"__throw_setup_dtor":[8,16],"__throw_setup_ptr":[8,16],"__tid_":16,"__time__":[0,10],"__timestamp__":10,"__tir__":[16,23],"__tls_init":16,"__tls_init_":16,"__tls_init_n":16,"__tri":7,"__twr__":16,"__ud":16,"__ud1_2_fv__l0__f__fit1":16,"__ul":16,"__ul1_fif":16,"__um":16,"__unalign":7,"__underlying_typ":[7,16],"__upc__":10,"__uptr":7,"__ut":16,"__uuidof":[7,16],"__va_args__":[7,10],"__va_opt__":7,"__variadic_templ":10,"__vec_cctor":16,"__vec_delet":16,"__vec_new":16,"__vec_new_eh":16,"__vec_new_eh_zero":16,"__version__":10,"__vfe__":16,"__vla_alloc":16,"__vla_dealloc":16,"__vms__":1,"__vptp":16,"__vptr":16,"__vtbl__":16,"__vtbl_entri":16,"__w64":7,"__wint_type__":0,"__x":2,"_accum":[10,11],"_aligna":7,"_alignof":7,"_allow":1,"_atom":7,"_bitint":[7,10],"_bool":[7,10,11,16],"_buf_element_int_kind":16,"_char_unsign":10,"_closur":3,"_complex":[7,10,16],"_cpprtti":10,"_e":16,"_entry_of":25,"_f__fif":26,"_fract":10,"_gener":7,"_imaginari":[7,10],"_incl_path":1,"_init":25,"_integral_max_bit":10,"_km":[10,15],"_m_cee":10,"_m_column":7,"_m_file_nam":7,"_m_function_nam":7,"_m_ix86":1,"_m_line":7,"_m_x64":1,"_main":[16,26],"_mile":16,"_mode":14,"_msc_build":10,"_msc_extens":10,"_msc_full_ver":10,"_msc_ver":10,"_native_wchar_t_defin":10,"_nonnul":7,"_noreturn":7,"_null_unspecifi":7,"_nullabl":7,"_one_time_init":25,"_pragma":7,"_ptr":14,"_r":16,"_simpl":23,"_start":14,"_static_assert":7,"_str":14,"_str2":14,"_t":3,"_thread_loc":7,"_tok_":5,"_trans_unit_init":25,"_type":22,"_wchar_t":10,"_wchar_t_defin":10,"_wfopen":15,"_win32":10,"_win64":10,"_x":10,"_z":26,"_zgv":16,"_zn1d1feqn1b1fev":16,"_zth":16,"_zti":16,"_zts":16,"_ztw":16,"a1":[6,8,9,10,23],"a2":[6,9,23],"a3":23,"a4":23,"a5":23,"a_":[4,11,14,16],"a__l0__f__fv":16,"a_base_class":[3,11,25],"a_base_class_deriv":3,"a_bit_field":14,"a_block":11,"a_boolean":[4,14,17,23],"a_byt":[11,14],"a_byte_boolean":14,"a_candidate_funct":9,"a_class_def_st":3,"a_class_symbol_suppl":[3,21],"a_class_type_suppl":[3,11],"a_const":[3,6,9,11,15,20,22],"a_constant_repr_kind":11,"a_constructor_init":[6,11],"a_control_flow_descr":20,"a_conversion_head":21,"a_conversion_list_entri":[3,21],"a_ctor_init_block":6,"a_decl_parse_st":[3,6],"a_decl_position_suppl":11,"a_def_arg_expr_fixup":3,"a_derivation_step":3,"a_destructible_entity_descr":16,"a_diagnostic_annotation_kind":10,"a_dynamic_init":[6,11,16],"a_field":[3,6,11],"a_fixed_point_valu":11,"a_foo":4,"a_for_loop":22,"a_func_info_block":[3,23],"a_generic_constraint":[11,23],"a_generic_constraint_claus":[11,23],"a_gnu_routine_suppl":11,"a_handl":[8,11],"a_hide_by_sig_list_entri":21,"a_host_large_integ":[9,11],"a_host_large_unsign":[9,11],"a_label":11,"a_lambda":[3,9,11],"a_local_static_variable_init":11,"a_long_file_nam":10,"a_long_typ":4,"a_long_type_nam":4,"a_macro":11,"a_macro_arg":15,"a_macro_def":[15,21],"a_macro_invocation_index":11,"a_macro_invocation_record":[11,15],"a_macro_invocation_record_block":[11,15],"a_macro_invocation_record_ptr":11,"a_macro_param":15,"a_macro_text_map":15,"a_macro_text_map_entri":15,"a_member_decl_info":3,"a_name_space_kind":21,"a_namespac":[6,11],"a_namespace_symbol_suppl":21,"a_next_construct_pragma_funct":18,"a_nother_variable_typ":4,"a_pack_expansion_descr_ptr":23,"a_pack_expansion_stack_entry_ptr":23,"a_param_id":6,"a_param_typ":[6,11,23],"a_pending_pragma":18,"a_per_instantiation_needed_flags_entri":[0,11],"a_pp_directive_kind":15,"a_pragma":[11,18],"a_pragma_kind":18,"a_pragma_kind_descript":18,"a_projection_descr":21,"a_property_or_event_descr":[3,11],"a_property_set_symbol_suppl":3,"a_queri":17,"a_ref_entri":9,"a_requires_claus":23,"a_reusable_token_cach":15,"a_routin":[3,11,18,23],"a_routine_fixup":3,"a_routine_type_suppl":11,"a_scop":[11,22],"a_scope_orphaned_list_head":[0,11,22],"a_scope_pointers_block":21,"a_scope_stack_entri":[18,21,22],"a_shared_token":15,"a_source_correspond":[1,11,18],"a_source_line_modif":15,"a_source_posit":[0,11,14,15],"a_source_sequence_entri":11,"a_src_seq_end_of_construct":11,"a_src_seq_secondary_decl":[11,18,22],"a_src_seq_sublist":11,"a_stat":[11,18],"a_state_catch":4,"a_static_assert":11,"a_switch_case_entri":[11,20],"a_switch_stmt_descr":[11,22],"a_symbol":21,"a_symbol_head":21,"a_symbol_list_entri":21,"a_symbol_loc":21,"a_symbol_reference_kind":21,"a_templ":[3,11,23],"a_template_arg":11,"a_template_cach":23,"a_template_decl":[11,23],"a_template_decl_info":23,"a_template_inst":23,"a_template_param":23,"a_template_param_type_suppl":23,"a_template_paramet":11,"a_template_symbol_suppl":[21,23,25],"a_text_map_position_track":15,"a_th":4,"a_thingi":4,"a_throw_spec_type_entri":8,"a_token_cach":15,"a_token_kind":[15,21],"a_trans_unit_corresp":25,"a_translation_unit":25,"a_typ":[11,14,22],"a_type_a":4,"a_type_b":4,"a_type_qualifier_set":[6,22],"a_type_tree_traversal_flag_set":22,"a_using_decl":[3,6,11],"a_vari":[3,6,11,21],"a_variable_typ":4,"a_variable_type_nam":4,"a_vla_dimens":[6,11,16],"aa":9,"aak_const":11,"aak_empti":11,"aak_raw_token":11,"aak_token":11,"aak_typ":11,"ab":10,"abandon":10,"abbrevi":[4,7,10,23],"abbreviated_deduction_guid":7,"abc":[0,10,16],"abc__tm__3_ii":16,"abcd":[2,16],"abi":[1,2,3,7,10,12,19,26],"abi_changes_for_array_new_and_delet":[16,19],"abi_changes_for_covariant_virtual_func_return":16,"abi_changes_for_placement_delet":[10,16,19],"abi_changes_for_rtti":[16,19,22],"abi_compatibility_vers":[16,19],"abi_tag":[7,16],"abi_tag_ignor":7,"abi_tag_ignored_in_c_mod":7,"abi_tag_ignored_on_speci":7,"abi_tag_redefinit":7,"abil":[0,15,16,17],"abk_routin":16,"abk_temporari":9,"abl":[5,6,8,10,11,15,16,18,21,23,24],"abnorm":[0,10,14],"abort":[0,10,24],"abov":[0,1,3,5,6,9,10,11,14,15,16,17,18,21,23,24,25],"absenc":[2,3,6,10,11,23],"absens":23,"absolut":[7,10,11],"absolute_file_name_in_has_include_next":7,"abstract":[1,3,6,7,10,11,16,17,22,23],"abstract_class_catch_typ":7,"abstract_class_object_not_allow":7,"abstract_class_param_typ":7,"abstract_declarator_pack_is_nest":7,"abstract_or_sealed_on_union":7,"abstract_requires_virtu":7,"abstractor":6,"abut":10,"ac":16,"accept":[0,1,3,4,5,6,7,9,11,13,14,15,16,18,21,22,23,24],"access":[2,5,6,7,8,9,10,14,15,16,17,22,23,24,25],"access_already_specifi":7,"access_control_error_report":21,"access_for_symbol":21,"access_prevents_dtor_gener":7,"access_suppresses_copy_asgn_decl":7,"access_suppresses_copy_ctor_decl":7,"access_to_end_of_path":[3,21],"access_to_member_of_c11_atomic_object":7,"accessor":[5,7,9,11,14,17,21],"accesssort":17,"accident":[15,17],"accommod":[0,1,2,3,5,9,10,17,18,22],"accompani":[4,6,9],"accomplish":[0,1,3,8,15,16,21,22,23],"accord":[3,6,8,9,10,11,14,15,16,18,20,21,25],"account":[3,8,10,11,17,21,24],"accum_quoted_str":15,"accumul":[0,3,6,9,10,15,18,24],"accur":[9,10,11,15,23],"achiev":[0,3,6,16,18],"acquir":[3,11,21],"acronym":[9,10],"across":[0,1,4,6,9,10,15,16,17,18,21,24,25],"act":[9,11,15,16,23],"action":[4,6,8,9,11,16,18,21,23,24],"activ":[3,6,7,10,11,14,15,16,20,23,25],"active_scope_lookup":21,"active_text_map_position_track":15,"actual":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"ad":[10,14],"adapt":[8,10,19,23,26],"add":[0,1,2,3,4,5,6,7,8,9,10,12,14,15,16,17,19,20,21,22,23,24,25,26],"add_active_using_direct":[6,21],"add_active_using_directive_to_scop":21,"add_active_using_directives_for_namespac":21,"add_address_of_to_nod":22,"add_array_constructor_cal":16,"add_base_class_cast":9,"add_based_type_list_memb":22,"add_box_to_express":9,"add_cast_to_nod":9,"add_cli_system_base_class":3,"add_conditional_flag_test":16,"add_constructor_cal":16,"add_constructor_param":16,"add_constructor_wrapper_cod":16,"add_curr_token_pseudo_pragma":15,"add_default_include_search_path":0,"add_derived_class_cast":9,"add_destructor_cal":16,"add_destructor_param":16,"add_diag_info":0,"add_dyn_init_cleanup":16,"add_eh_function_prologu":16,"add_empty_source_sequence_entri":22,"add_end_of_construct_source_sequence_entri":22,"add_end_of_parse_act":6,"add_first_time_test":16,"add_implicit_cli_bas":3,"add_indirect_base_class":3,"add_indirection_to_nod":22,"add_instanti":25,"add_integer_valu":9,"add_lambda_captur":3,"add_match_not":10,"add_member_to_proxy_or_nonreal_class":21,"add_orig_line_modif":15,"add_orphaned_file_scope_il_entri":[11,22],"add_pm_base_class_cast":9,"add_pm_derived_class_cast":9,"add_pragma_entry_to_cach":18,"add_pragma_kind_descript":18,"add_pragma_to_il":18,"add_ref_indirection_to_nod":22,"add_reference_to_to_nod":22,"add_scope_orphaned_il_list":[11,22],"add_source_line_modif":15,"add_source_sequence_entry_for_partial_instanti":22,"add_source_sequence_entry_to_list":22,"add_statement_at_stmt_po":20,"add_statement_list":20,"add_stmt_at_stmt_po":20,"add_stop_token":[0,14,15],"add_substitution_if_avail":16,"add_switch_claus":20,"add_symbol_to_lookup_set":21,"add_symbol_to_scope_list":21,"add_to_asm_entries_list":22,"add_to_constants_list":22,"add_to_control_flow_descr_list":20,"add_to_curr_token_pragma_list":18,"add_to_derived_type_list":6,"add_to_destructions_list":22,"add_to_dynamic_inits_list":22,"add_to_exported_templates_list":23,"add_to_front_of_include_search_path":0,"add_to_include_search_path":0,"add_to_inline_function_list":23,"add_to_instantiations_required_list":23,"add_to_labels_list":22,"add_to_macros_list":22,"add_to_namespaces_list":22,"add_to_parameters_list":22,"add_to_partial_order_candidates_list":23,"add_to_pragma_list":22,"add_to_pragmas_list":18,"add_to_request_fil":23,"add_to_routines_list":22,"add_to_scopes_list":22,"add_to_source_sequence_list":22,"add_to_templates_list":22,"add_to_types_list":22,"add_to_using_decls_list":22,"add_to_variables_list":22,"add_token_to_macro_text_map":15,"add_type_qualifi":6,"add_unbox_to_express":9,"add_vtbl_entry_init":16,"addendum":10,"addit":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"additional_arg":16,"addr_of_bit_field_allow":10,"addr_of_constructor_or_destructor":7,"addr_of_ref_class":7,"address":[0,2,3,5,6,7,8,10,15,16,18,22,23],"address_of_bit_field":7,"address_of_consteval_funct":7,"address_of_consteval_function_leak":7,"address_of_function_with_pass_object_size_attr":7,"address_of_initonly_field":7,"address_of_managed_member_funct":7,"address_of_nontrue_enable_if_funct":7,"address_of_overload_set_implicit_obj_member_select":7,"address_of_register_vari":7,"address_of_unqualified_explicit_this_funct":7,"address_taken":[11,22],"addscalar":10,"adequ":16,"adher":11,"adjac":[7,10,14,15,18],"adject":10,"adjust":[0,2,7,8,9,10,11,15,16,22],"adjust_bool_operation_typ":16,"adjust_copied_expression_for_inlin":16,"adjust_curr_source_line_structure_after_realloc":15,"adjust_field_selection_for_anonymous_union_refer":16,"adjust_output_posit":5,"adl":16,"adopt":[10,17,23],"adv_to_signif_source_sequence_entri":5,"advanc":[15,18,23,25],"advance_to_next_pack_el":23,"advance_to_next_template_arg":23,"advantag":[0,1,10,11,16,23,24],"advers":17,"af":16,"af_gnu":18,"af_ms_declspec":18,"af_std":18,"affect":[0,1,3,5,6,7,10,11,14,16,17,18,21,23,24],"affin":7,"afford":3,"afield":11,"aforement":[3,6,17],"after_end_of_all_sourc":15,"afterward":[15,25],"aggr_init_array":6,"aggr_init_array_design":6,"aggr_init_array_remainder_if_need":6,"aggr_init_class":6,"aggr_init_class_remainder_if_need":6,"aggr_init_cli_array":6,"aggr_init_cli_array_level":6,"aggr_init_cli_array_with_alloc":6,"aggr_init_el":6,"aggr_init_field_design":6,"aggr_init_generic_el":6,"aggr_init_simple_el":6,"aggreg":[2,5,7,9,10,11,16,23],"aggress":16,"agre":23,"ahead":[3,6,10,15],"ai":[10,16,23],"aib":16,"aid":[2,10,14,17,24],"aim":24,"ak_":18,"ak_align":18,"ak_empti":18,"ak_empty_attr":11,"ak_nothrow":18,"ak_sect":18,"ak_unrecogn":[11,18],"akin":[6,17,24],"al":[5,9,10,16],"al_declarator_id":18,"al_post_func":18,"al_postfix":18,"al_prefix":18,"al_specifi":18,"al_tag_nam":18,"alert":[2,10],"algorithm":[3,6,8,9,10,14,16,21,23],"alia":[4,6,7,11,17,22,26],"alias":[6,7,10,11,14,16,23,26],"alias_cannot_have_definit":7,"alias_ctad_is_cpp20":7,"alias_declar":6,"alias_declaration_is_cpp11":7,"alias_loop":7,"alias_prototype_instanti":23,"alias_template_declar":23,"alias_template_deduction_guid":7,"alias_template_is_cpp11":7,"alias_used_in_typ":7,"aliase":17,"aliased_name_bad_kind":7,"aliased_name_undeclar":7,"aliased_variable_cannot_have_register_storage_class":7,"align":[0,1,2,7,9,10,11,14,17,18],"align_not_equival":7,"align_val_t":7,"aligna":7,"aligned_new":10,"alignment_of_typ":11,"alignment_reduction_ignor":7,"alignment_reduction_unconditionally_ignor":7,"alignment_without_virtual_base_class":3,"alignof":7,"alignof_function_typ":7,"alignof_incomplete_array":7,"alignof_incomplete_typ":7,"all_arguments_must_have_same_typ":7,"all_instanti":25,"all_proto_params_must_be_nam":7,"all_template_info_in_il":11,"all_thread_locals_have_wrapp":16,"alloc":[0,3,6,7,8,9,10,11,15,16,17,18,20,21,23,25],"alloc_":11,"alloc_accessible_base_class":22,"alloc_asm_entri":22,"alloc_asm_function_bodi":22,"alloc_base_class":22,"alloc_base_class_deriv":22,"alloc_cil":[11,22],"alloc_class_type_suppl":22,"alloc_const":22,"alloc_control_flow_descr":20,"alloc_conversion_head":21,"alloc_conversion_list_entri":21,"alloc_ctor_init":22,"alloc_derivation_step":22,"alloc_dtor_dynamic_init":9,"alloc_dynamic_init":22,"alloc_exception_specif":22,"alloc_expr_nod":22,"alloc_f":[0,11,14],"alloc_field":22,"alloc_gener":[0,14],"alloc_hidden_nam":22,"alloc_hidden_name_fixup":5,"alloc_il":[11,14,22],"alloc_in_region":0,"alloc_label":22,"alloc_list_entry_for_class":22,"alloc_list_entry_for_routin":22,"alloc_local_static_variable_init":22,"alloc_lowered_eh_construct_nod":22,"alloc_macro":22,"alloc_macro_arg":15,"alloc_namespac":22,"alloc_node_for_const":22,"alloc_object_lifetim":22,"alloc_overriding_virtual_funct":22,"alloc_param_typ":22,"alloc_pending_pragma":18,"alloc_pragma":[18,22],"alloc_primary_file_scope_il":25,"alloc_resizable_buff":[0,14],"alloc_routin":22,"alloc_scop":22,"alloc_shareable_const":22,"alloc_source_sequence_entri":22,"alloc_src_seq_end_of_construct":22,"alloc_src_seq_secondary_decl":22,"alloc_src_seq_sublist":22,"alloc_stat":22,"alloc_substitut":16,"alloc_switch_case_entri":22,"alloc_symbol":21,"alloc_symbol_head":21,"alloc_templ":22,"alloc_template_arg":22,"alloc_template_param_type_descr":22,"alloc_temporary_vari":22,"alloc_thingi":4,"alloc_typ":22,"alloc_unshared_const":22,"alloc_using_decl":22,"alloc_vari":22,"allocation_operator_in_namespac":7,"allow":[0,1,2,3,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25,26],"allow_nonstandard_anonymous_union":10,"almost":[8,9,10,11,16,21,23,25],"alon":[1,7,9,10,13,16],"along":[0,1,2,3,4,8,9,10,11,14,15,16,17,21,23,26],"alongsid":[5,9,10,24],"alphabet":[17,24],"alphanumer":16,"alreadi":[0,1,3,5,7,9,10,15,16,17,18,21,22,23,24,25],"already_defin":7,"already_defined_with_po":7,"already_in_consteval_context":7,"already_in_lookup_set":21,"already_initi":7,"also":[0,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],"alter":[0,2,7,16,21],"altern":[0,1,2,5,7,8,9,11,13,15,16,18,22,24,26],"alternate_entry_point":16,"alternate_il_file_format":0,"alternative_token":10,"although":[0,1,2,3,5,6,9,10,11,15,16,18,21,22,23,25],"altogeth":[9,10,11,14,16,18],"alway":[0,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"always_inlin":7,"always_inline_requires_inlin":7,"always_inline_suppress":7,"ambig_literal_oper":7,"ambig_suppresses_copy_asgn_decl":7,"ambig_suppresses_copy_ctor_decl":7,"ambigu":[0,3,5,6,7,8,9,10,11,14,16,21,23],"ambiguous_assignment_oper":7,"ambiguous_base_class":7,"ambiguous_block_size_spec":7,"ambiguous_c11_gener":7,"ambiguous_c11_generic_previous_match":7,"ambiguous_cast_selects_direct_bas":7,"ambiguous_class_cal":7,"ambiguous_constructor":7,"ambiguous_constructor_for_convers":7,"ambiguous_conversion_funct":7,"ambiguous_conversion_to_builtin":7,"ambiguous_copy_constructor":7,"ambiguous_default_constructor":7,"ambiguous_derived_class":7,"ambiguous_destructor":7,"ambiguous_destructor_constraint":7,"ambiguous_fin":7,"ambiguous_function_for_deleg":7,"ambiguous_guiding_decl":7,"ambiguous_injected_template_nam":7,"ambiguous_ms_attribut":7,"ambiguous_nam":7,"ambiguous_operator_funct":7,"ambiguous_overloaded_funct":7,"ambiguous_partial_spec":7,"ambiguous_ptr_to_overloaded_funct":7,"ambiguous_question_oper":7,"ambiguous_user_defined_convers":7,"ambiguous_virtual_function_overrid":7,"aml_boxing_convers":9,"aml_ellipsi":9,"aml_error":9,"aml_exact":9,"aml_non":9,"aml_promot":9,"aml_std_convers":9,"aml_user_convers":9,"among":[0,2,3,6,10,11,14,21,22,23],"amount":[0,3,6,7,10,17,23],"an_":[4,14],"an_arg_list_elem":9,"an_arg_match_summari":9,"an_arg_operand":[9,15],"an_asm_entri":[6,11],"an_assert_pred":15,"an_assert_valu":15,"an_attr_appl_descr":18,"an_attr_application_fn":18,"an_attr_descr":18,"an_attribut":[11,18],"an_attribute_arg":11,"an_attribute_group":[11,18],"an_attribute_kind":18,"an_attribute_loc":18,"an_elem":4,"an_error_cod":[0,14],"an_exception_specif":[8,11],"an_exception_specification_typ":11,"an_expr_nod":[11,14,23],"an_expr_node_kind":14,"an_expr_rescan_info_entri":9,"an_ifc_access_sort":17,"an_ifc_basic_specifiers_bitfield":17,"an_ifc_basic_specifiers_bitfield_0_33":17,"an_ifc_basic_specifiers_bitfield_queri":17,"an_ifc_basic_specifiers_bitfield_storag":17,"an_ifc_byte_buff":17,"an_ifc_decl_alia":17,"an_ifc_decl_enumer":17,"an_ifc_decl_foreign_index":17,"an_ifc_decl_foreign_index_storag":17,"an_ifc_decl_funct":17,"an_ifc_decl_function_storag":17,"an_ifc_decl_index":17,"an_ifc_decl_index_0_33":17,"an_ifc_decl_index_0_41":17,"an_ifc_decl_refer":17,"an_ifc_decl_sort":17,"an_ifc_decl_sort_0_33":17,"an_ifc_decl_sort_0_41":17,"an_ifc_decl_speci":17,"an_ifc_file_head":17,"an_ifc_foo_decl":17,"an_ifc_function_traits_bitfield":17,"an_ifc_function_traits_bitfield_queri":17,"an_ifc_function_traits_bitfield_storag":17,"an_ifc_index":17,"an_ifc_index_storag":17,"an_ifc_keyword_sort":17,"an_ifc_keyword_sort_0_33":17,"an_ifc_modul":17,"an_ifc_module_refer":17,"an_ifc_name_index":17,"an_ifc_parameterized_ent":17,"an_ifc_partit":17,"an_ifc_partition_kind":17,"an_ifc_sha256":17,"an_ifc_sha256_storag":17,"an_ifc_source_location_byt":17,"an_ifc_source_location_part":17,"an_ifc_source_location_storag":17,"an_ifc_text_offset":17,"an_ifc_type_design":17,"an_ifc_type_index":17,"an_ifc_type_index_0_33":17,"an_il_entity_list_entri":11,"an_il_entry_kind":11,"an_il_entry_prefix":0,"an_il_to_str_output_control_block":0,"an_immediate_pragma_funct":18,"an_init_compon":[6,9],"an_init_pos_descr":16,"an_init_st":[6,9],"an_initi":6,"an_insert_loc":16,"an_instantiation_direct":11,"an_int_value_part":9,"an_integer_type_suppl":11,"an_integer_valu":[9,11],"an_internal_float_valu":11,"an_ms_attribut":[6,11],"an_ms_if_exist":11,"an_object_lifetim":[11,20],"an_operand":[6,9],"an_opname_kind":21,"an_other_pragma_funct":18,"an_other_variable_typ":4,"an_overriding_virtual_funct":3,"an_property_or_event_descr":9,"anachron":[0,7,11,16],"anachronism_error_sever":0,"anachronist":0,"analys":11,"analysi":[1,9,10,11,13,16,20,23],"analyz":[16,23],"ancestor":11,"and_integer_valu":9,"anew":11,"angl":6,"ani":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,20,21,22,23,24,25,26],"annex":10,"annot":[2,7,10],"annotate_diagnost":10,"annotation_after_us":7,"annotation_must_have_literal_typ":7,"announc":7,"anon_union_alias_member_templ":7,"anon_union_at_decl_posit":7,"anon_union_class_member_templ":7,"anon_union_member_access":7,"anon_union_member_funct":7,"anon_union_ref_in_lambda":7,"anon_union_storage_class":7,"anon_union_using_declar":7,"anonym":[3,7,10],"anonymous_union_field":11,"anonymous_union_qualifier_ignor":7,"anoth":[0,1,2,3,5,6,7,8,9,10,11,13,14,15,16,17,18,19,21,22,23,25,26],"another_long_vari":4,"another_pragma":18,"ansi":[0,1,2,3,5,7,9,11,14,15],"answer":[3,16,17,21,22],"ant":10,"anticip":[3,6,10],"any_cfront_mod":14,"any_mor":23,"any_ref_memb":[3,21],"anyon":16,"anyth":[0,7,9,10,11,14,15,17,20,23,24],"anyway":[9,14,21],"anywher":[1,8,10,11,16,18,23],"ao":16,"apart":[0,9,10,15],"api":[7,15],"apostroph":[7,10],"appar":[0,7,10,11],"apparent_module_pp_direct":7,"appear":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,20,21,22,23,24,25,26],"append":[0,1,3,10,16,18,21,22,23,24],"appendix":[10,13,26],"appertain":[6,18],"appli":[0,3,4,6,7,9,10,11,14,15,16,17,21,22,23,24,26],"applic":[0,1,3,5,6,7,9,10,11,13,15,16,18,21,23],"apply_microsoft_attribut":6,"approach":[0,3,8,10,16,17,20,23,26],"appropri":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,20,21,22,23,24,25,26],"approxim":[9,10,16,24],"arbitrari":[0,9,10,11,22,23],"arbitrarili":[3,9,11,15,16],"arcan":21,"arch":[7,16],"architectur":[1,3,7,10,11,16,17],"area":[0,3,4,5,9,10,14,15,19],"aren":[2,6,9,11,17,24],"arg":[6,7,10,16,23,24],"arg_default_promote_operand":9,"arg_dep_lookup":[7,10],"arg_for_empty_param_pack":7,"arg_get_token":15,"argsus":[10,15,18],"arguabl":[6,9],"argument":[0,2,6,7,9,11,14,15,16,18,19,22,23,24],"argument_dependent_lookup":21,"argument_templ":23,"arguments_provided_for_attribut":7,"aris":[9,25],"arith_operand":7,"arithmet":[7,9,10,11,16],"ariti":23,"arm":[1,9,10,11,16,20,21],"around":[0,2,3,4,5,7,9,10,11,14,16,17,18,21,23,24],"arr":9,"arrang":[3,11,16,18,23],"array":[0,1,2,3,5,6,7,8,9,10,11,14,15,17,18,19,21,22,23,25],"array_condition_always_tru":7,"array_declar":6,"array_designator_for_deduced_context":7,"array_element_typ":22,"array_member_initi":7,"array_new_and_delet":10,"array_of_abstract_class":7,"array_of_funct":7,"array_of_generic_param":7,"array_of_handl":7,"array_of_incomplete_typ":7,"array_of_managed_class":7,"array_of_refer":7,"array_of_void":7,"array_size_must_be_posit":7,"array_size_one_assum":7,"array_size_too_larg":7,"array_subobject_not_initi":7,"array_type_not_allow":7,"arrow_star_operator_in_managed_class":7,"art":14,"as_publ":[11,21],"ascend":[2,14],"ascii":15,"asid":[0,3,6,11,15,16,21],"ask":[2,15,21],"asm":[7,10,14,20,22],"asm_decl_not_allow":7,"asm_declar":[6,20],"asm_func_must_be_prototyp":7,"asm_function_allow":[10,11,22],"asm_input_must_not_have_output_mod":7,"asm_name_after_definit":7,"asm_name_conflict":7,"asm_name_in_rout_defn":7,"asm_name_in_typedef":7,"asm_name_is_gnu_extens":7,"asm_name_on_auto_vari":7,"asm_name_or_reg":11,"asm_not_allow":7,"asm_operand_spec_is_gnu_extens":7,"asm_output_must_have_output_mod":7,"asm_stat":20,"aspect":[0,1,6,10,11,14,16,19,21,23],"assembl":[0,1,7,9,10,11,14,16],"assemble_function_cal":9,"assembly_info":7,"assert":[7,10,11,13,14,15,17],"assert_pred":15,"assign":[0,2,3,4,6,7,9,10,14,16,17,18,20,21,23,25,26],"assign_string_literal_sequence_numb":16,"assign_to_eh_curr_region":16,"assign_where_compare_m":7,"assigned_goto_requires_void_ptr":7,"assignment_in_value_class_typ":7,"assignment_oper":21,"assignment_to_thi":7,"assist":[6,14,20],"assoc_block":6,"assoc_info":[3,6,11],"assoc_macro":15,"assoc_pointers_block":21,"assoc_pointers_block_of":21,"assoc_scop":[3,11],"assoc_source_line_modif":15,"assoc_templ":11,"assoc_typ":[3,21],"associ":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"associated_th":4,"assort":0,"asssoci":10,"assum":[1,2,6,7,10,11,14,15,16,18,21,23,24],"assume_expression_discard":7,"assume_statement_applies_to_null_stat":7,"assumpt":[6,7,15],"assumption_fail":7,"assur":[8,21,22,23],"ast":17,"asterisk":15,"atlmfc":1,"atom":7,"atomic_constraint_evaluation_fail":7,"atomic_constraint_fals":7,"atomic_constraint_substitution_fail":7,"att_preprocessing_extensions_allow":[10,15],"attach":[0,2,3,6,9,10,11,15,16,18,20,21,22,23,25],"attach_attribut":18,"attach_specifier_attribut":18,"attach_type_attribut":18,"attempt":[0,3,5,6,7,8,9,10,11,14,15,16,17,20,23,24,25],"attempt_to_read_past_end_of_object":7,"attend":[2,16],"attent":[5,11],"attention_mark":15,"attr_arg_out_of_small_integer_rang":7,"attr_corresp_t":18,"attr_disallows_automatic_storag":7,"attr_disallows_bit_field":7,"attr_disallows_definit":7,"attr_disallows_external_linkag":7,"attr_disallows_function_typ":7,"attr_disallows_handler_param":7,"attr_disallows_inlin":7,"attr_disallows_member_funct":7,"attr_disallows_pure_virtual_funct":7,"attr_disallows_register_storag":7,"attr_disallows_virtual_funct":7,"attr_must_also_appear_in_first_declar":7,"attr_must_appear_in_class_definit":7,"attr_not_applied_to_function_typ":7,"attr_requires_automatic_storag":7,"attr_requires_bit_field":7,"attr_requires_definit":7,"attr_requires_func_typ":7,"attr_requires_function_typ":7,"attr_requires_handler_param":7,"attr_requires_inlin":7,"attr_requires_local_vari":7,"attr_requires_member_funct":7,"attr_requires_pure_virtual_funct":7,"attr_requires_register_storag":7,"attr_requires_virtual_funct":7,"attr_twice_in_group":7,"attribut":[2,3,7,9,10,14,16,21,23,25],"attribute_after_parenthesized_initi":7,"attribute_cleanup_for_paramet":7,"attribute_cleanup_requires_automatic_storag":7,"attribute_conflict":7,"attribute_declared_her":7,"attribute_does_not_apply_to_local_vari":7,"attribute_does_not_apply_to_typ":7,"attribute_ignored_for_thread_loc":7,"attribute_ignored_on_incomplete_class_decl":7,"attribute_ignored_on_nondefinit":7,"attribute_ignored_on_nonstatic_member_funct":7,"attribute_ignored_on_unnamed_typ":7,"attribute_is_gnu_extens":7,"attribute_is_nonstandard":7,"attribute_nam":6,"attribute_namespace_unrecogn":7,"attribute_not_allow":7,"attribute_not_supported_in_x86_64":7,"attribute_on_explicit_instanti":7,"attribute_requires_external_linkag":7,"attributes_ignor":7,"attributes_in_rout_defn":7,"attributes_with_no_decl":7,"augment":[3,16,23],"author":24,"auto":[3,4,7,9,10,11,16,17,23],"auto_brace_initialization_not_allow":7,"auto_cast_is_cpp23":7,"auto_direct_list_init_requires_singleton":7,"auto_ignor":7,"auto_instanti":10,"auto_new_with_braced_init":7,"auto_not_allowed_her":7,"auto_storag":10,"auto_typ":10,"auto_type_brace_initialization_not_allow":7,"auto_type_in_array_typ":7,"auto_type_in_function_typ":7,"auto_type_nonstandard":7,"auto_type_requires_initi":7,"auto_used_two_way":7,"auto_variable_in_own_initi":7,"autom":[14,18],"automat":[0,1,2,6,7,8,9,11,14,15,17,18,19,20,21,26],"automatic_template_instanti":10,"automatically_include_in_il":18,"automatically_instanti":23,"autonom":5,"aux_buffer_for_pcc_macro":15,"auxiliari":[0,2,15],"avail":[0,1,3,5,6,7,8,9,11,14,15,16,17,18,20,21,22,23,25,26],"avail_macro_arg":15,"availability_attribute_ignor":7,"averag":0,"avoid":[0,1,2,3,5,8,9,10,11,13,14,15,16,17,18,22,23,24,25,26],"avx":16,"await":[10,18],"await_in_unevaluated_operand":7,"await_not_allowed_in_catch_claus":7,"await_not_allowed_in_static_initi":7,"await_not_allowed_outside_function_scop":7,"await_operand_not_a_class":7,"awar":[3,6,10,11],"away":[3,7,9,11,14,15,17,21],"awkward":[11,15],"b":[0,2,3,4,6,8,9,10,11,15,16,21,23,24,25,26],"b1":[6,8,10],"b2":6,"ba":3,"back":[0,1,3,6,7,8,9,10,11,13,14,15,16,17,19,20,21,22,23,24,25,26],"back_end":[0,1,2],"back_end_is_c_gen_b":1,"back_end_is_cp_gen_b":1,"back_end_should_be_cal":1,"backslash":[7,15],"backtrack":3,"backward":[11,20],"bad":[0,7,14,17],"bad_address_of_ellipsi":7,"bad_affin":7,"bad_alias_templ_redecl":7,"bad_arg_type_for_operator_new":7,"bad_argument_for_bas":7,"bad_argument_for_underlying_typ":7,"bad_argument_to_make_sign":7,"bad_argument_to_make_unsign":7,"bad_array_element_typ":7,"bad_array_member_initi":7,"bad_asm_constraint_lett":7,"bad_asm_constraint_modifi":7,"bad_asm_func_ellipsi":7,"bad_asm_function_def":7,"bad_assembly_index":7,"bad_assembly_info_attribut":7,"bad_attribute_align":7,"bad_attribute_template_substitut":7,"bad_base_class":7,"bad_binary_digit":7,"bad_bit_field_s":7,"bad_bit_field_typ":7,"bad_c11_noreturn":7,"bad_call_of_class_object":7,"bad_call_of_handl":7,"bad_cast":7,"bad_character_valu":7,"bad_class_template_decl":7,"bad_cli_dynamic_cast_typ":7,"bad_cmd_line_macro":7,"bad_combination_of_dll_attribut":7,"bad_combination_of_type_specifi":7,"bad_complex_operation_result":7,"bad_compound_literal_typ":7,"bad_const_cast":7,"bad_const_cast_typ":7,"bad_const_volatile_ref_init":7,"bad_constant_function_cal":7,"bad_constant_lambda":7,"bad_constant_oper":7,"bad_constructor_decl":7,"bad_constructor_param":7,"bad_constructor_typ":7,"bad_conv_constant_expr_typ":7,"bad_conversion_function_decl":7,"bad_cpp11_constant_function_cal":7,"bad_cppcx_dynamic_cast_typ":7,"bad_cppcx_event_add_return":7,"bad_cppcx_event_remove_paramet":7,"bad_cppcx_event_remove_return":7,"bad_data_member_initi":7,"bad_decl_for_export":7,"bad_declspec_properti":7,"bad_declspec_restrict_return":7,"bad_decltype_qualifi":7,"bad_deduction_guide_access":7,"bad_deduction_guide_return_typ":7,"bad_deduction_guide_scop":7,"bad_default_arg_typ":7,"bad_default_assign":7,"bad_defined_pp_op":7,"bad_delegate_init_list":7,"bad_destructor_decl":7,"bad_digit_separator_po":7,"bad_dynamic_cast_typ":7,"bad_embed_initi":7,"bad_enum_template_decl":7,"bad_event_add_or_remove_return":7,"bad_event_compound_assign":7,"bad_exception_specification_for_speci":7,"bad_export_info_fil":7,"bad_extra_arg_for_postfix_oper":7,"bad_file_scope_storage_class":7,"bad_final_builtin_fpclassify_arg":7,"bad_finalizer_decl":7,"bad_first_arg_type_for_operator_delet":7,"bad_fixed_operation_result":7,"bad_fixed_point_valu":7,"bad_float_const":7,"bad_float_operation_result":7,"bad_float_or_fixed_suffix":7,"bad_float_valu":7,"bad_flt_config":7,"bad_friend_decl":7,"bad_function_for_deleg":7,"bad_function_for_gnu_va_arg_pack":7,"bad_function_return_typ":7,"bad_function_storage_class":7,"bad_generic_declaration_scop":7,"bad_gnu_auto_typ":7,"bad_gnu_stmt_return":7,"bad_gro_on_alloc_fail":7,"bad_handle_dynamic_cast_operand":7,"bad_hex_digit":7,"bad_ident_str":7,"bad_il_fil":7,"bad_indirection_operand":7,"bad_init_capture_captur":7,"bad_init_for_thread_loc":7,"bad_initializer_for_array_with_unspecified_bound":7,"bad_initializer_typ":7,"bad_injection_scop":7,"bad_integral_compound_liter":7,"bad_integral_oper":7,"bad_line_numb":7,"bad_linkage_for_decl":7,"bad_linkage_for_redefine_extnam":7,"bad_linkage_of_ref_within_inline_funct":7,"bad_linkage_specifi":7,"bad_local_var_in_lambda":7,"bad_macro_mode_nam":7,"bad_macro_redef":7,"bad_malloc_attribut":7,"bad_member_storage_class":7,"bad_member_template_decl":7,"bad_member_template_sym":7,"bad_member_type_in_ptr_to_memb":7,"bad_multibyte_char":7,"bad_multibyte_char_local":7,"bad_nested_function_variable_ref":9,"bad_nonconst_ref_init":7,"bad_nonstd_anonymous_union_field":7,"bad_nontype_template_arg":7,"bad_octal_digit":7,"bad_ordering_typ":7,"bad_pack_align":7,"bad_param_kind_for_gener":7,"bad_param_specifi":7,"bad_param_storage_class":7,"bad_param_type_for_defaulted_comparison":7,"bad_parameter_type_for_static_member_oper":7,"bad_partial_speci":7,"bad_pch_fil":7,"bad_pp_directive_keyword":7,"bad_pp_oper":7,"bad_pragma_comment_str":7,"bad_predef_macro_lin":7,"bad_predef_macro_redef":7,"bad_printf_format_str":7,"bad_property_get_return":7,"bad_property_set_return":7,"bad_prototype_argument_for_bas":7,"bad_ptr_dynamic_cast_operand":7,"bad_pure_specifi":7,"bad_qualified_function_typ":7,"bad_qualified_function_type_paramet":7,"bad_qualifier_for_delayed_class_definit":7,"bad_qualifier_for_member_enum_decl":7,"bad_qualifier_for_nested_class_decl":7,"bad_raw_string_delim_char":7,"bad_ref_dynamic_cast_operand":7,"bad_reflection_kind_for_expression_splic":7,"bad_reg_nam":7,"bad_return":7,"bad_return_type_for_op_delet":7,"bad_return_type_for_op_new":7,"bad_return_type_on_main":7,"bad_return_type_on_virtual_function_overrid":7,"bad_return_value_typ":7,"bad_rvalue_array":7,"bad_rvalue_ref_const_cast_operand":7,"bad_rvalue_ref_dynamic_cast_operand":7,"bad_scope_for_concept":7,"bad_scope_for_defaulted_comparison":7,"bad_scope_for_definit":7,"bad_scope_for_explicit_instanti":7,"bad_scope_for_partial_spec":7,"bad_scope_for_redeclar":7,"bad_scope_for_speci":7,"bad_shared_storage_class":7,"bad_size_for_static_address_init":7,"bad_specifier_outside_class_decl":7,"bad_splicer_operand":7,"bad_statement_in_statement_expr":7,"bad_std_string_view":7,"bad_stdc_fx_overflow_pragma_arg":7,"bad_stdc_pragma_arg":7,"bad_stdc_pragma_arg_for_mod":7,"bad_storage_class_for_named_address_space_vari":7,"bad_storage_class_on_template_decl":7,"bad_storage_class_with_inlin":7,"bad_strong_using_scop":7,"bad_suffix":7,"bad_templ_arg_expr_oper":7,"bad_template_declar":7,"bad_template_declaration_scop":7,"bad_template_member_definit":7,"bad_template_nam":7,"bad_thi":7,"bad_tls_model_attr_arg":7,"bad_token":7,"bad_tracking_ref_dynamic_cast_operand":7,"bad_tracking_ref_init":7,"bad_type_for_atomic_fetch":7,"bad_type_for_cleanup_routin":7,"bad_type_for_gnu_sync_funct":7,"bad_type_from_instanti":7,"bad_type_name_redeclar":7,"bad_type_qualifi":7,"bad_typeid":16,"bad_unevaluated_lambda":7,"bad_unicode_char_in_pp_output":7,"bad_unicode_char_in_str":7,"bad_union_field":7,"bad_upc_shared_array_layout_qualifi":7,"bad_upc_shared_pointer_layout_qualifi":7,"bad_upc_shared_void_pointer_layout_qualifi":7,"bad_use_of_cli_array_typ":7,"bad_use_of_delegate_typ":7,"bad_use_of_function_modifi":7,"bad_use_of_main":7,"bad_use_of_member_function_typedef":7,"bad_use_of_sharp":7,"bad_user_defined_suffix":7,"bad_uuid_str":7,"bad_va_arg":7,"bad_va_copi":7,"bad_va_end":7,"bad_va_start":7,"bad_variable_for_init_prior":7,"bad_vector_conditional_s":7,"bad_vector_float_operand_s":7,"badc":24,"balanc":15,"bar":[4,10,24],"bare":[0,16],"base":[0,2,5,6,7,8,10,14,15,16,17,18,20,21,23,24,25,26],"base_assign_op_is_default":10,"base_check":7,"base_class":3,"base_class_already_initi":7,"base_class_has_different_dll_interfac":7,"base_class_init_anachron":7,"base_class_not_allowed_for_union":7,"base_class_of_class_type_with_typedef_nam":7,"base_class_offset_too_larg":7,"base_class_spec":16,"base_class_with_nonvirtual_dtor":7,"base_pp_if_stack_depth":15,"base_subobject_conflict":3,"base_subobject_not_initi":7,"base_typ":17,"base_uses_tail_pad":7,"base_with_flexible_array":7,"based_not_allowed_her":7,"based_not_followed_by_star":7,"based_requires_variable_nam":7,"based_var_cannot_be_loc":7,"based_var_must_be_ptr":7,"bases_not_in_templ":7,"bash":10,"basi":[0,1,3,10,11,14,15,16,21,23,24,25],"basic":[0,2,6,7,9,10,11,12,13,14,15,19,22,23],"basic_hdr":14,"basic_string_view":7,"basicspecifiersbitfield":17,"baz":24,"bc":16,"bcopi":1,"bear":[10,11],"becam":[1,9,11],"becaus":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,18,19,20,21,22,23,25,26],"becom":[3,9,10,11,14,16,17,18,20,21,23,25],"befor":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25],"befriend":[3,11,21],"befriending_class":3,"begin":[0,1,2,3,5,6,7,9,10,11,14,15,16,18,19,20,21,22,23,26],"begin_caching_of_fetched_token":15,"begin_catch_claus":16,"begin_deferral_of_access_check":21,"begin_end_type_mismatch_in_range_based_for":7,"begin_macro_buffer_region":15,"begin_object_lifetim":16,"begin_potential_pack_expansion_context":23,"begin_rescan_of_pragma_token":18,"begin_template_arg_list_travers":23,"begun":[11,15,16,20,23],"behav":10,"behavior":[3,5,7,8,9,15,16,17,22,23],"behind":[15,16,17],"believ":[0,7,16,19],"belong":[1,3,6,10,11,18,20,21,22,23],"benefici":11,"benefit":[0,5,10,11,16,17,23],"benign":[10,15],"berkeley":[1,9],"besid":[1,10,15,16,22],"best":[0,9,10,14,16,17,21,23],"better":[0,8,9,10,11,14,16,19,23,25],"bewar":[9,11],"beyond":[0,6,7,9,11,15,22,23],"bf":16,"bf__q2_10a__tm__2_i4b__sfi":16,"bi":16,"big":[9,10,15,16,17,25],"bigger":9,"bin":[1,10],"binari":[1,7,9,14,15,16,17],"binary_oper":9,"bind":[6,7,9,10,11,15,16,17,18,22,23],"bind_object_lifetim":22,"bit":[0,1,2,3,6,7,8,9,10,11,14,16,17,20,22],"bit_field_is_sign":11,"bit_precise_integ":10,"bit_siz":11,"bitand":10,"bite":17,"bitfield":7,"bitfields_not_allow":7,"bitint_enum_base_not_allow":7,"bitint_width_too_larg":7,"bitmask":17,"bits_required_to_represent_integer_const":9,"bitwis":[7,10,11],"bitwise_copi":7,"bitwise_copy_of":7,"blank":[10,15,26],"block":[0,1,2,4,6,7,9,10,15,16,17,18,20,21,22,23],"block_extern_initializer_not_allow":7,"block_scope_function_must_be_extern":7,"bodi":[0,2,6,7,8,9,10,11,13,14,15,16,18,20,21,22,23,25],"bom":15,"book":[8,14],"bool":[7,9,10,11,23],"bool_equivalent_operand":7,"bool_operand":7,"bool_typ":[11,16],"bool_type_not_allow":7,"boolean":[0,6,7,9,11,14,16,17,23],"boolean_controlling_expr_is_const":7,"borland":[1,10],"born":16,"borrow":16,"both_arguments_must_have_same_typ":7,"both_ref_and_value_constraint":7,"bottom":[3,14,15,17],"bound":[2,5,6,7,9,10,11,16,20,23],"bound_funct":9,"bound_function_cast_anachron":7,"bound_function_must_be_cal":7,"boundari":[3,7,9,14,15],"bourn":1,"box":[3,6,7,9,22],"box_value_type_operand":9,"boxed_type_for":6,"boxing_conversion_poss":22,"brace":[3,4,6,7,9,10,11,14,15,16,20,23],"brace_init_vari":6,"brace_initialization_not_allow":7,"braced_init_in_paren":7,"braced_init_in_paren_init":7,"braced_init_list_not_allow":7,"braced_initi":6,"braced_list_for_implicit_lambda_typ":7,"braced_list_for_implicit_return_typ":7,"braced_list_passed_to_ellipsi":7,"bracket":[6,7,9,10,11,16,18,21],"branch":[7,8,11,16,17,20],"branch_into_constexpr_if":7,"branch_into_fin":7,"branch_into_handl":7,"branch_into_if_constev":7,"branch_into_statement_expr":7,"branch_into_try_block":7,"branch_out_of_const":7,"branch_past_initi":7,"brand":[3,6,11],"breadth":17,"break":[0,5,7,9,10,11,15,17,18,20],"break_cannot_be_in_finally_block":7,"break_label":16,"break_must_be_in_loop_or_switch":7,"break_stat":20,"breakag":10,"breaker":[9,10],"breakpoint":[0,25],"brief":[0,11],"brief_diagnost":10,"briefli":21,"bring":[0,1,11,25,26],"broad":[4,6,11],"broader":[3,9,17],"broken":[2,4,11,21,25],"brought":[3,25],"brush":3,"bsd":2,"bsearch":15,"bucket":[21,22],"buffer":[0,7,8,16,21],"bug":[2,5,7,10,11,14,16,24,26],"build":[0,6,7,9,10,11,14,15,16,17,21,22,23],"build_bin":24,"build_binary_result_operand":9,"build_prefix_inform":0,"build_runtim":1,"build_unary_result_operand":9,"builder":17,"building_pch_prefix":0,"building_runtim":10,"built":[0,1,7,9,10,11,14,15,16,19,21,22,23,25],"builtin":[7,9,10,14,16],"builtin_def":14,"builtin_function_hidden":7,"builtin_function_overload":7,"builtin_kind":14,"builtin_needs_128_bit_float":7,"builtin_needs_128_bit_integ":7,"builtin_needs_char8_t":7,"builtin_needs_vector_typ":7,"builtin_operator_nonviable_because_arg_mismatch":7,"bulk":16,"bullet":6,"bundl":[9,11],"burden":[1,9],"bypass":[3,7,17,20,23],"byte":[0,3,7,9,10,11,14,15,16],"c":[7,8,14,17,18,19,20,22,24,25,26],"c1":[6,8,16],"c11":10,"c11_atomic_array_or_function_typ":7,"c11_atomic_bit_field":7,"c11_atomic_specifier_with_qualified_typ":7,"c17":10,"c18":10,"c2":[6,16],"c23":[7,10],"c23_alignas_deprec":7,"c23_alignof_deprec":7,"c23_bool_deprec":7,"c23_noreturn_deprec":7,"c23_old_style_param_id":7,"c23_static_assert_deprec":7,"c23_thread_local_deprec":7,"c23_typeof":[7,10],"c8":16,"c89":[1,7,9,10,11,14,16],"c90":10,"c99":[6,14,16,19],"c99_complex":16,"c99_constant_in_unsigned_long_long_rang":7,"c99_il_extensions_support":[11,16],"c_anachronisms_allow":10,"c_dialect":14,"c_dialect_ansi":14,"c_dialect_cplusplus":14,"c_dialect_pcc":14,"c_gen_b":[2,10,14],"c_gen_be_generates_ansi_c":2,"c_mode":14,"c_num_el":9,"c_plusplus":10,"ca":3,"ca4_cwl":16,"cach":[3,6,9,14,18,21,23],"cache_curr_token":15,"cache_template_declar":23,"cache_token_stream":15,"cache_token_stream_coalesce_identifi":15,"cache_token_stream_until_matching_token":15,"cache_token_stream_with_coalesce_flag":15,"cacheabl":18,"cached_token_rescan_stack":15,"caching_pragma_token":15,"calcul":3,"call":[0,1,2,3,5,6,7,8,10,14,15,17,18,19,20,21,22,23,25,26],"call_of_pure_virtu":7,"call_of_zero":7,"call_requires_floating_point_argu":7,"call_requires_one_argu":7,"call_requires_string_liter":7,"call_result_should_be_us":7,"call_with_unusable_argument_convers":7,"callabl":[0,3,7,9,14,26],"callahan":16,"callback":[0,6,18],"callbackcontext":7,"calle":7,"called_function_redeclared_inlin":7,"caller":[0,3,6,7,8,9,11,14,15,16,21,22],"calling_convention_ignor":7,"calling_convention_ignored_for_typ":7,"calling_convention_may_not_precede_nested_declar":7,"calling_convention_not_allow":7,"came":[5,11,15,21,23],"can":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"can_be_instanti":[16,23],"can_boolean_controlling_express":20,"can_instanti":[10,23],"cancel":[0,10],"cancel_il_fil":0,"candid":[7,9,10,21,23],"candidate_constraints_fail":7,"candidate_expl_templ_arg_subst_fail":7,"candidate_failed_constraint":7,"candidate_wrong_param_count":7,"cannot_assign_to_ms_attr":7,"cannot_be_common_internal_linkag":7,"cannot_be_const_qualifi":7,"cannot_be_declared_in_scop":7,"cannot_be_speci":7,"cannot_bind_to_curr_construct":18,"cannot_build_temp_file_nam":7,"cannot_call_member_on_lvalu":7,"cannot_call_member_on_rvalu":7,"cannot_call_named_member_on_lvalu":7,"cannot_call_named_member_on_rvalu":7,"cannot_capture_thi":7,"cannot_capture_this_by_refer":7,"cannot_capture_var":7,"cannot_cast_away_const":7,"cannot_change_access":7,"cannot_chdir":7,"cannot_create_instantiation_request_fil":7,"cannot_create_pch_fil":0,"cannot_deduce_auto_templ_param":7,"cannot_deduce_auto_typ":7,"cannot_deduce_class_template_argu":7,"cannot_deduce_decltype_auto_typ":7,"cannot_deduce_type_in_range_based_for":7,"cannot_define_dllimport_funct":7,"cannot_elide_brac":7,"cannot_evaluate_builtin_offsetof":7,"cannot_export_fgmt":7,"cannot_find_header_for_import":7,"cannot_get_file_s":7,"cannot_import_metadata":7,"cannot_import_modul":7,"cannot_import_module_bad_checksum":7,"cannot_import_module_with_no_nam":7,"cannot_init_auto_flexible_array_memb":7,"cannot_initi":7,"cannot_initialize_destructible_flexible_array":7,"cannot_initialize_field":7,"cannot_initialize_flexible_array_memb":7,"cannot_initialize_indirect_flexible_array":7,"cannot_inlin":7,"cannot_inline_cal":7,"cannot_interpret_target_bit":7,"cannot_open_fil":7,"cannot_open_file_reason":7,"cannot_open_pch_input_file_reason":7,"cannot_open_temp_file_reason":7,"cannot_read_fil":7,"cannot_redef_predef_macro":7,"cannot_redefin":0,"cannot_splice_general_express":7,"cannot_splice_member_access":7,"cannot_undef_predef_macro":7,"cannot_use_thread_local_storag":7,"cannot_write_module_none_declar":7,"canon":[11,15,16,23],"canonic":16,"canonical_":25,"canonical_il_entry_of":25,"canonical_templ":11,"capabl":[1,9,10,11,14,15,16,23],"capit":4,"captur":[0,7,10,11,17,23,24],"capture_mode_matches_default":7,"capture_of_static_duration_vari":7,"captured_local_var_not_in_innermost_funct":7,"captured_var_type_not_copy":7,"capturing_struct_bindings_is_cpp20":7,"care":[0,1,2,5,9,10,11,13,14,16,17,21,23,25],"caret":0,"carri":[3,9,10,11,18],"carriag":7,"carries_depend":[7,18],"carries_dependency_ignor":7,"carries_dependency_not_on_first_decl":7,"carv":0,"cascad":13,"case":[0,1,2,3,6,7,8,9,10,11,14,15,16,17,18,19,20,22,23,24,25,26],"case_label":20,"case_label_conflict":7,"case_label_must_be_in_switch":7,"cast":[0,2,3,4,5,6,7,9,10,17,21,22],"cast_in_requires_claus":7,"cast_interior_ptr_to_ptr":7,"cast_nod":9,"cast_not_arithmetic_or_enum_or_point":7,"cast_not_integr":7,"cast_not_integral_or_enum":7,"cast_not_scalar":7,"cast_operand":9,"cast_operand_for_reference_cast":9,"cast_operand_ful":9,"cast_pointer_for_field_select":9,"cast_to_abstract_class":7,"cast_to_bad_typ":7,"cast_to_cli_interface_class":7,"cast_to_incomplete_array_typ":7,"cast_to_qualified_typ":7,"cast_type_pre_check":9,"casual":0,"cat":24,"catastroph":[0,10,15,24],"catch":[0,1,7,8,9,11,23],"categori":[3,9,10,16,22,25],"caught":[7,8,10,16],"caus":[0,1,2,3,4,5,7,9,10,11,12,14,15,16,17,18,19,20,21,23,25,26],"caveat":[1,16],"cc":[1,7,10,16,24],"cc_clobber_ignor":7,"ccomcoclass":7,"cd":[1,24],"cdisp":24,"cell":11,"cend":9,"central":[6,14,23],"centric":16,"certain":[0,1,3,5,6,8,9,10,11,13,14,15,16,17,18,19,21,22,23,25,26],"certainti":17,"cfc_":3,"cfe":[0,14],"cfe_daemon":14,"cfe_daemon_common":14,"cfront":[1,3,6,7,8,11,14,19,20,23,26],"cfront_2":10,"cfront_2_1_mod":14,"cfront_2_1_object_code_compat":[10,16],"cfront_3":10,"cfront_3_0_mod":14,"cfront_3_0_object_code_compat":16,"cfront_global_defined_after_nested_typ":7,"cfront_global_vs_member_name_lookup_bug":10,"cfront_multiple_nested_typ":7,"cfront_name_lookup_bug":7,"cfront_object_code_compat":3,"chain":[7,10,11,15,16,22],"challeng":6,"chanc":[5,18],"chang":[0,1,2,3,4,6,7,8,9,10,11,12,13,14,15,16,17,21,22,23,24,25,26],"change_binary_operand_typ":9,"change_class_locator_into_constructor_loc":21,"change_primary_include_search_dir":0,"change_ref_kind":9,"changeabl":16,"chapter":[1,3,6,8,10,11,14,15,16,20,21],"char":[0,2,3,4,6,7,9,10,11,14,15,16,21,23],"char16_t":[7,10,16],"char32_t":[10,16],"char8_t":[7,10],"char_bit":1,"char_max":[1,10],"char_min":[1,10],"char_too_wide_for_rep":7,"charact":[0,1,2,4,6,7,9,10,11,13,14,16,18,21,24,26],"character_not_latin_1":7,"characterist":[1,13,14,16,21,24],"charg":9,"chart":17,"chartindex":17,"cheapli":16,"check":[0,1,3,6,7,8,10,11,13,15,16,18,20,21,22,23,24,26],"check_":9,"check_abstract_class":3,"check_ambiguity_and_verify_access":21,"check_anonymous_union_symbol":3,"check_arithmetic_operand":9,"check_assert":[0,14,17],"check_assertion_or_expect_error":14,"check_assertion_str":0,"check_boolean_controlling_express":9,"check_class_linkag":3,"check_compatibility_of_pointer_operand":9,"check_concaten":10,"check_exception_specif":8,"check_exception_type_specif":8,"check_for_branch_into_handl":20,"check_for_cli_delegate_definit":3,"check_for_cli_modifi":3,"check_for_done_with_memory_region":[0,21],"check_for_each_stat":[9,20],"check_for_following_parenthesi":15,"check_for_generalized_identifier_error":15,"check_for_jump_over_initi":20,"check_for_operator_overload":9,"check_for_prior_use_of_partial_spec":23,"check_for_template_declarator_error":15,"check_for_virtual_overrid":3,"check_function_pointer_operand":9,"check_goto_and_label":20,"check_if_entity_should_be_automatically_instanti":23,"check_if_present_in_request_fil":23,"check_implicit_lambda_return_typ":3,"check_integral_operand":9,"check_integral_or_enum_operand":9,"check_integral_or_enum_or_fixed_point_operand":9,"check_invalid_use_of_special_cli_class_typ":6,"check_lint_notreached_st":15,"check_modifiable_lvalue_operand":9,"check_narrowing_convers":9,"check_object_pointer_operand":9,"check_operator_function_param":3,"check_partial_spec_nontype_param_usag":23,"check_partial_speci":23,"check_pointer_operand":9,"check_printf_scanf_arg":9,"check_protected_member_access":21,"check_ptr_to_member_operands_for_compat":9,"check_range_based_for_array_cas":9,"check_range_based_for_default_cas":9,"check_range_based_for_member_cas":9,"check_range_based_for_stat":[9,20],"check_scalar_operand":9,"check_shift_count":9,"check_special_declaration_form":6,"check_special_member_funct":3,"check_switch_default_unexpect":14,"check_template_constraint":23,"check_unicode_secur":10,"check_user_defined_conversions_for_cast":9,"check_validity_on":6,"check_void_return_okay":20,"checked_trans_unit_copy_address_of":25,"checksum":[0,14],"chicken":16,"child":11,"children":[11,16],"choic":[0,5,9,11,14,16,17,23,25],"choos":[0,2,8,9,10,11,14,16,18,21,23],"chose":23,"chosen":[0,9,10,15,16,17,25],"chunk":0,"cil":1,"cil_2_59":16,"circuit":16,"circular":[3,7],"circular_constraint":7,"circumspect":9,"circumst":[8,10,18,21,24,25],"circumv":16,"ck_address":[9,11,16],"ck_aggreg":[6,11,16],"ck_complex":11,"ck_design":[11,16],"ck_dynamic_init":[5,6,11,16],"ck_imaginari":11,"ck_init_repeat":11,"ck_ptr_to_memb":[11,16],"ck_stack_offset":16,"ck_string":[11,15],"ck_template_param":[11,23],"cl":1,"cl_ambiguous_opt":7,"cl_anachronism_option_only_in_cplusplus":7,"cl_arg_dependent_lookup_option_only_in_cplusplus":7,"cl_array_new_and_delete_option_only_in_cplusplus":7,"cl_auto_cannot_be_dis":7,"cl_auto_instantiation_option_only_in_cplusplus":7,"cl_auto_storage_option_only_in_cplusplus":7,"cl_auto_type_option_only_in_cplusplus":7,"cl_back_end_requires_il_fil":7,"cl_bool_option_only_in_cplusplus":7,"cl_c23_typeof_option_only_in_c":7,"cl_cfront_incompatible_with_microsoft":7,"cl_class_name_injection_option_only_in_cplusplus":7,"cl_compound_literals_option_only_in_c":7,"cl_could_not_open_il_fil":7,"cl_cpp26_requires_parse_nonclass_templ":7,"cl_cppcli_only_in_microsoft_cplusplus":7,"cl_cppcx_and_cppc":7,"cl_cppcx_only_in_microsoft_cplusplus":7,"cl_dep_name_option_only_in_cplusplus":7,"cl_dep_name_requires_parse_nonclass_templ":7,"cl_duplicate_file_nam":7,"cl_embedded_c_option_only_in_c":7,"cl_embedded_cplusplus_option_only_in_cplusplus":7,"cl_enum_overloading_option_only_in_cplusplus":7,"cl_error_in_debug_option_argu":7,"cl_exceptions_option_only_in_cplusplus":7,"cl_explicit_option_only_in_cplusplus":7,"cl_export_template_option_incompatible_with_modul":7,"cl_export_template_option_only_in_cplusplus":7,"cl_export_template_requires_dep_nam":7,"cl_export_template_requires_distinct_templ_sig":7,"cl_export_template_requires_no_implicit_includ":7,"cl_extended_designators_option_only_in_c":7,"cl_extern_inline_option_only_in_cplusplus":7,"cl_fixed_point_option_only_in_c":7,"cl_for_init_diff_warning_option_only_in_cplusplus":7,"cl_friend_injection_option_only_in_cplusplus":7,"cl_func_prototype_tags_option_only_in_c":7,"cl_gen_move_operations_and_rvalue_ctor_is_copy_ctor":7,"cl_gen_move_operations_option_only_in_cplusplus":7,"cl_gnu_c89_inlining_option_only_in_c":7,"cl_guiding_decls_option_only_in_cplusplus":7,"cl_ignore_std_option_only_in_cplusplus":7,"cl_ii_file_name_incompatible_with_multiple_input":7,"cl_il_display_requires_il_file_nam":7,"cl_il_file_must_be_specifi":7,"cl_impl_extern_c_conv_option_only_in_cplusplus":7,"cl_implicit_include_incompatible_with_multiple_trans_unit":7,"cl_implicit_inclusion_option_only_in_cplusplus":7,"cl_implicit_noexcept_requires_noexcept_support":7,"cl_implicit_typename_option_only_in_cplusplus":7,"cl_import_only_in_microsoft":7,"cl_incompatible_language_mod":7,"cl_incorrect_host_id":7,"cl_instantiation_option_only_in_cplusplus":7,"cl_invalid_clang_vers":7,"cl_invalid_constexpr_diag_tag":7,"cl_invalid_cwd":7,"cl_invalid_edg_base_directori":7,"cl_invalid_error_limit":7,"cl_invalid_error_numb":7,"cl_invalid_error_tag":7,"cl_invalid_flag_nam":7,"cl_invalid_gnu_vers":7,"cl_invalid_import_directori":7,"cl_invalid_instantiation_directori":7,"cl_invalid_instantiation_mod":7,"cl_invalid_macro_definit":7,"cl_invalid_macro_undefinit":7,"cl_invalid_microsoft_vers":7,"cl_invalid_numb":7,"cl_invalid_opt":7,"cl_invalid_output_mod":7,"cl_invalid_pch_directori":7,"cl_invalid_pch_s":7,"cl_invalid_target":7,"cl_invalid_template_directori":7,"cl_lambdas_option_only_in_cplusplus":7,"cl_late_tiebreaker_option_only_in_cplusplus":7,"cl_list_macros_incompatible_with_multiple_trans_unit":7,"cl_list_make_dependencies_incompatible_with_multiple_trans_unit":7,"cl_long_lifetime_temps_incompat_with_newer_featur":7,"cl_max_constexpr_option_only_in_cplusplus":7,"cl_microsoft_version_insufficient_for_cppc":7,"cl_microsoft_version_insufficient_for_cppcx":7,"cl_missing_argu":7,"cl_missing_source_file_nam":7,"cl_move_operations_require_rvalue_refer":7,"cl_must_specify_cpp11_mod":7,"cl_must_specify_cpp14_mod":7,"cl_named_address_spaces_option_only_in_c":7,"cl_named_registers_option_only_in_c":7,"cl_namespaces_option_only_in_cplusplus":7,"cl_no_output_file_need":7,"cl_nonstandard_qualifier_deduction_option_only_in_cplusplus":7,"cl_nonstd_gnu_keywords_requires_gnu_mod":7,"cl_nonstd_using_decl_option_only_in_cplusplus":7,"cl_old_for_init_option_only_in_cplusplus":7,"cl_old_specializations_option_only_in_cplusplus":7,"cl_one_instantiation_per_object_incompatible_with_multiple_input":7,"cl_one_instantiation_per_object_option_only_in_cplusplus":7,"cl_output_file_incompatible_with_multiple_input":7,"cl_parse_nonclass_templates_option_only_in_cplusplus":7,"cl_pch_incompatible_with_multiple_input":7,"cl_pch_must_be_first":7,"cl_pending_instantiations_option_only_in_cplusplus":7,"cl_pp_output_incompatible_with_multiple_trans_unit":7,"cl_relaxed_abstract_checking_only_in_cplusplus":7,"cl_relaxed_constexpr_requires_bool":7,"cl_report_gnu_extensions_requires_gnu_mod":7,"cl_require_func_prototypes_option_only_in_c":7,"cl_rtti_option_only_in_cplusplus":7,"cl_rvalue_ctor_is_copy_ctor_option_only_in_cplusplus":7,"cl_rvalue_references_option_only_in_cplusplus":7,"cl_short_enums_requires_gcc_mod":7,"cl_special_subscript_cost_option_only_in_cplusplus":7,"cl_strict_mode_incompatible_with_anachron":7,"cl_strict_mode_incompatible_with_cfront":7,"cl_strict_mode_incompatible_with_ignore_std":7,"cl_strict_mode_incompatible_with_long_preserv":7,"cl_strict_mode_incompatible_with_microsoft":7,"cl_strict_mode_incompatible_with_pcc":7,"cl_strict_mode_incompatible_with_sun":7,"cl_strict_mode_incompatible_with_svr4":7,"cl_sun_incompatible_with_cfront":7,"cl_sun_mode_only_in_cplusplus":7,"cl_svr4_c_option_only_in_ansi_c":7,"cl_tim_local_conflicts_with_auto_instanti":7,"cl_too_many_argu":7,"cl_type_traits_helpers_option_only_in_cplusplus":7,"cl_typename_option_only_in_cplusplus":7,"cl_unnamed_module_map":7,"cl_unrecognized_calling_convent":7,"cl_unrecognized_unicode_source_kind":7,"cl_unrestricted_unions_in_microsoft_mod":7,"cl_unrestricted_unions_option_only_in_cplusplus":7,"cl_upc_requires_ansi_c_dialect":7,"cl_variadic_templates_only_in_cplusplus":7,"cl_vla_option_only_in_c":7,"cl_vtbl_option_only_in_cplusplus":7,"cl_wchar_t_option_only_in_cplusplus":7,"clang":[0,1,7,10,13,14],"clang_mod":14,"clang_vers":10,"clang_version_i":14,"clangc_version_i":14,"clangcpp_version_i":14,"clarifi":10,"clariti":[4,16],"clash":16,"class":[0,2,5,6,7,8,9,10,14,17,18,24,25],"class_and_inherited_member_instance_have_dll_interfac":7,"class_and_member_function_name_conflict":7,"class_and_member_have_dll_interfac":7,"class_and_member_name_conflict":7,"class_decl":[3,6,9,11,14,23],"class_def_in_statement_expr":7,"class_definition_needed_flag_is_set":0,"class_member_declar":3,"class_member_template_declar":[3,23],"class_metadata_not_represent":7,"class_name_inject":[7,10],"class_operand":7,"class_qualified_id_lookup":21,"class_qualified_name_not_allow":7,"class_qualified_name_requir":7,"class_result_via_ctor":7,"class_specifi":[3,6,23],"class_templ":23,"class_template_declar":23,"class_template_instantiations_in_source_sequence_list":11,"class_template_same_name_as_templ_param":7,"class_too_larg":7,"class_typ":[15,21],"class_type_requir":7,"class_type_supp":11,"class_with_op_delete_but_no_op_new":7,"class_with_op_new_but_no_op_delet":7,"classic":3,"classif":[7,18],"classifi":18,"claus":[0,4,6,7,8,10,11,14,15,16,20],"clean":[10,13,17],"cleanup":[0,6,7,8,11,16],"cleanup_attribute_in_constexpr_funct":7,"cleanup_on_exit_from_catch":16,"clear":[0,8,9,11,13,14,15,16,18,20,21,22,23,25],"clear_body_for_routin":25,"clear_const":22,"clear_expr_nod":22,"clear_il_to_str_output_control_block":0,"clear_loc":21,"clear_operand":9,"clear_symbol":21,"clear_variable_definit":25,"clearer":[3,14],"clever":14,"cli":[7,8,13,14,16,20,22],"cli_abstract_member_function_definit":7,"cli_array_element_typ":22,"cli_array_invalid_element_typ":7,"cli_array_invalid_number_of_dimens":7,"cli_array_invalid_number_of_subscript":7,"cli_array_must_have_new_or_array_init":7,"cli_array_rank":22,"cli_array_rank_const":22,"cli_attribute_inaccessible_field":7,"cli_attribute_invalid_argu":7,"cli_attribute_invalid_field":7,"cli_class_type_kind":11,"cli_entity_not_load":7,"cli_enum_base_has_no_system_counterpart":7,"cli_get_accessor_miss":7,"cli_handle_user_defined_conversion_poss":9,"cli_interface_cannot_have_assign":7,"cli_interface_member_function_definit":7,"cli_param_array_attribute_deprec":7,"cli_param_array_must_be_last_paramet":7,"cli_set_accessor_miss":7,"cli_typeid_of_generic_param_in_attribut":7,"cli_typeid_of_managed_point":7,"client":10,"clix":26,"clobber":7,"clone":[9,15,22,24],"clone_macro_text_map_entri":15,"clone_operand":9,"close":[0,1,3,4,6,7,8,9,10,11,14,15,16,17,18,20,21,23],"close_file_if_open":0,"close_or_remove_template_info":23,"close_temp_fil":0,"closer":24,"closur":[3,7,9,11,16],"clr":[9,10,11],"clrcall_requires_cppc":7,"clumsi":19,"cluster":21,"cmd":[23,24],"cmd_line":[0,14],"cmd_line_early_init":0,"cmd_line_h":14,"cmp_fixed_point_const":9,"cmp_integer_const":9,"cmp_integer_valu":9,"cmp_operator_does_not_return_bool":7,"cmplit_integer_valu":9,"cmpulit_integer_valu":9,"cn":24,"cnl_1_0":16,"co":[9,16,21],"co_await":7,"co_await_on_non_range_based_for":7,"co_return":7,"co_yield":7,"coalesc":21,"coalesce_and_lookup_generalized_identifi":15,"coalesce_and_lookup_qualified_nam":15,"coalesce_function_template_refer":15,"coalesce_template_class_refer":[15,23],"coalesce_template_function_refer":15,"coalesce_template_id":15,"coalesce_variable_template_refer":15,"coclass_base_requirements_not_met":7,"code":[0,3,6,7,9,11,12,13,18,19,20,21,22,23,24,25,26],"code_is_unreach":7,"code_reach":20,"codesourceri":[1,3,16],"coexist":[3,10,21],"coincident":11,"collaps":4,"collect":[3,9,11,15,16,20,23],"collect_type_qualifi":6,"collector":9,"collid":16,"colon":[3,4,10,24],"color":10,"colorize_diagnost":10,"column":[0,2,4,5,7,10,11,14,15,17,21,25],"com":[1,3,6,16],"combin":[0,3,6,7,9,10,11,13,14,16,21,22,23,24],"combine_dir_and_file_nam":0,"combine_type_specifi":6,"combine_unneeded_selector_with_operand":9,"comdat":16,"come":[0,1,3,6,7,8,9,10,11,14,15,16,17,20,21,23],"comform":16,"comma":[3,6,7,9,10,11,15,16,23,24],"comma_operator_in_array_subscript_deprec":7,"comma_operator_in_cli_subscript":7,"command":[1,2,6,7,8,9,11,13,14,15,16,19,23,24,25,26],"command_line_error":0,"comment":[0,1,2,4,5,7,9,10,11,13,14,15,16,18,20,23,26],"comment_unclosed_at_eof":7,"commentari":24,"committe":10,"common":[0,3,6,7,9,10,11,14,15,16,17,18,21,22,23,24,26],"common_lifetim":11,"common_object_lifetim":20,"communic":[3,16],"compact":[4,8,11,14,15],"companion":9,"compar":[0,3,7,9,10,11,12,15,18,22,23,25],"compare_arg_match_level":9,"compare_argument_tiebreak":9,"compare_candidate_funct":9,"compare_constraint":23,"compare_function_templ":23,"compare_macro_text_map_entry_with_offset":15,"compare_standard_convers":9,"comparison":[7,9,10,11,16,22,23,26],"comparison_defaulted_in_class_must_be_first_decl":7,"comparison_detail":7,"comparison_of_pointers_to_void_and_funct":7,"compat":[1,3,6,7,8,9,11,14,16,19,20,21,22,23,24,25],"compel":11,"compens":15,"compet":21,"compil":[0,1,2,5,6,7,8,9,10,11,13,14,15,16,17,18,19,21,22,24,25,26],"compile_multiple_source_fil":[0,1,10,14,25],"compile_multiple_translation_unit":[0,14,25],"compiler_gener":11,"compiler_generated_function_cannot_be_instanti":7,"complement":1,"complement_integer_valu":9,"complet":[0,1,2,3,5,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,24,25,26],"complete_class_definit":3,"complete_class_type_is_need":[21,23],"complete_function_template_decl":23,"complex":[0,1,3,7,8,9,10,11,14,15,16,17,20,23],"complex_bar":4,"complex_integral_typ":7,"complex_template_paramet":7,"complex_type_not_allow":7,"compli":17,"compliant":16,"complic":[0,2,3,4,5,6,7,9,10,11,14,15,16,17,20,23],"compon":[3,7,9,11,12,14,16,21,22,23,24,25],"compos":[4,6,17],"composit":[6,22],"composite_routine_typ":11,"composite_typ":22,"compound":[4,6,7,8,9,10,16,20],"compound_assignment_operation_typ":11,"compound_liter":[7,10,11],"compound_literal_enabling_poss":11,"compound_literal_is_nonstandard":7,"compound_lvalue_as_asm_operand":7,"compound_stat":[6,8,20,23],"compress":16,"compris":[3,10,15,18,21,23,25],"compromis":14,"comput":[0,3,7,8,9,11,13,15,16,17,20,21],"compute_area_of_point":4,"compute_vbase_and_vcall_offset_indic":16,"concat_adjacent_string_liter":15,"concat_string_liter":15,"concat_yields_invalid_token":7,"concaten":[0,2,7,10,15,16,18,23],"concept":[2,3,7,9,10,11,16],"concept_arg_list_substitution_fail":7,"concept_fail":7,"concept_not_satisfi":7,"conceptu":[0,5,9,11,17,25],"concern":[1,3,6,9,10,15,16,17,24],"conclud":23,"concret":14,"concurr":24,"cond":23,"condens":10,"condit":[0,1,6,7,8,9,10,13,14,15,18,23,24],"condition":14,"condition_decl_must_have_initi":7,"condition_does_not_declare_a_vari":7,"condition_with_multiple_declar":7,"confer":[3,21],"config":[1,10,24],"configu":10,"configur":[0,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25,26],"confirm":[6,9],"conflict":[2,3,7,10,16,25],"conflicting_attribute_in_other_translation_unit":7,"conflicting_calling_convent":7,"conflicting_cli_class_template_kind":7,"conflicting_cli_class_type_kind":7,"conflicting_nul":7,"conflicting_properti":7,"conflicts_with_predeclared_type_info":7,"conflicts_with_previous_function_decl":6,"conflicts_with_using_decl":7,"conform":[7,10,14,16,19],"confus":[3,5,7,10,15,23],"confusable_identifi":7,"congruent_path":3,"conjg":10,"conjgf":10,"conjgl":10,"conjunct":[1,10,21,24],"connect":[10,11],"consecut":[7,11],"consequ":[0,3,5,6,8,10,11,15,16,18,20,21,23,25,26],"conserv":[9,10],"consid":[0,1,2,3,4,5,7,8,9,10,11,14,15,16,17,18,19,21,23,24],"consider":[3,9,10,16,17,18,24],"consist":[0,1,3,6,10,11,14,16,18,21,23,25],"const":[0,2,3,4,6,7,9,10,11,14,16,17,21,22],"const_cast":[7,9,16],"const_for_curr_token":[9,15],"const_function_anachron":7,"const_ignor":7,"const_int":[1,9,14],"const_mbr_suppresses_copy_asgn_decl":7,"const_string_liter":10,"const_var_in_c_const_expr":7,"const_volatile_ref_init_anachron":7,"const_volatile_ref_init_from_rvalu":7,"constant":[1,2,6,7,8,10,14,16,17,18,20,21,23,25],"constant_addresses_local_vari":7,"constant_expr_ruled_out":9,"constant_glvalue_address":[9,11],"constant_is_an_arg_operand":15,"constant_must_be_posit":7,"constant_narrowing_convers":7,"constant_narrowing_conversion_to_float":7,"constant_prvalue_point":[9,11],"constant_value_not_known":7,"constev":7,"consteval_call_nonconst":7,"consteval_ctor_with_virtual_bas":7,"consteval_destructor":7,"consteval_explicit_instanti":7,"consteval_main":7,"consteval_new_or_delete_oper":7,"consteval_overrides_nonconstev":7,"consteval_vari":7,"consteval_virtual_combin":7,"constexpr":[3,7,10,14,17,21],"constexpr_access_one_past_array_end":7,"constexpr_access_past_object":7,"constexpr_access_to_expired_storag":7,"constexpr_access_to_runtime_storag":7,"constexpr_address_unknown":7,"constexpr_alloc_too_larg":7,"constexpr_alloc_too_smal":7,"constexpr_allocation_mismatch":7,"constexpr_allocation_po":7,"constexpr_allocation_too_larg":7,"constexpr_and_consteval_specifi":7,"constexpr_bad_dealloc":7,"constexpr_bad_deallocation_s":7,"constexpr_bad_deallocation_typ":7,"constexpr_bad_derived_class_cast":7,"constexpr_bad_mantissa_str":7,"constexpr_begin_report":7,"constexpr_begin_report_token":7,"constexpr_call_not_interpret":7,"constexpr_call_to_nonconstexpr_funct":7,"constexpr_called_from":7,"constexpr_called_from_rout":7,"constexpr_class_specific_new":7,"constexpr_comparison_calls_nonconstexpr_funct":7,"constexpr_constructor_initializes_no_variant_field":7,"constexpr_constructor_with_function_try_block":7,"constexpr_ctor_does_not_initialize_bas":7,"constexpr_ctor_with_dtor":7,"constexpr_ctor_with_virtual_bas":7,"constexpr_dependent_array_s":7,"constexpr_destructor":7,"constexpr_diag_arg_count":7,"constexpr_diag_bad_level":7,"constexpr_diag_bad_str":7,"constexpr_diag_bad_tag":7,"constexpr_diag_error":10,"constexpr_diag_remark":10,"constexpr_diag_suppress":10,"constexpr_diag_warn":10,"constexpr_en":9,"constexpr_end_report":7,"constexpr_end_report_token":7,"constexpr_equality_past_the_end_address":7,"constexpr_expiring_temporari":7,"constexpr_explicit_dtor_cal":7,"constexpr_explicit_instanti":7,"constexpr_expression_cannot_be_interpret":7,"constexpr_flexible_array_initi":7,"constexpr_float_error":7,"constexpr_fp_conversion_fail":7,"constexpr_fp_error":7,"constexpr_fp_values_not_compar":7,"constexpr_function_undefin":7,"constexpr_function_with_function_try_block":7,"constexpr_goto":7,"constexpr_ignored_on_microsoft_nonstatic_memb":7,"constexpr_implied_source_nonconst":7,"constexpr_incomplete_typ":7,"constexpr_integer_overflow":7,"constexpr_interpreter_address":7,"constexpr_invalid_constant_kind":7,"constexpr_invalid_dynamic_cast":7,"constexpr_invalid_intrinsic_signatur":7,"constexpr_invalid_null_ptr_oper":7,"constexpr_invalid_pdiff":7,"constexpr_invalid_pm_access":7,"constexpr_invalid_type_convers":7,"constexpr_lambdas_not_en":7,"constexpr_leftover_alloc":7,"constexpr_local_stat":7,"constexpr_main":7,"constexpr_memcpy_distinct_typ":7,"constexpr_memcpy_nontrivial_typ":7,"constexpr_memcpy_operand_not_object":7,"constexpr_memcpy_overflow":7,"constexpr_memcpy_overlap":7,"constexpr_memcpy_partial_object":7,"constexpr_missing_initializer_for_field":7,"constexpr_missing_return_valu":7,"constexpr_modifying_const_storag":7,"constexpr_multiple_union_initi":7,"constexpr_mutable_field_load":7,"constexpr_negative_shift":7,"constexpr_no_active_union_field":7,"constexpr_no_current_paramet":7,"constexpr_non_array_pointer_arithmet":7,"constexpr_non_array_subscript":7,"constexpr_nonvirtual_subobject_delet":7,"constexpr_not_const":7,"constexpr_null_calle":7,"constexpr_null_derefer":7,"constexpr_null_ptr_to_member_data":7,"constexpr_object_too_larg":7,"constexpr_object_with_virtual_bas":7,"constexpr_out_of_bounds_array_access":7,"constexpr_placement_new":7,"constexpr_pointer_ahead_of_array":7,"constexpr_pointers_not_compar":7,"constexpr_reflection_not_of_const":7,"constexpr_reinterpret_cast":7,"constexpr_return_not_const":7,"constexpr_shift_excess":7,"constexpr_shift_negative_valu":7,"constexpr_statement_cannot_be_interpret":7,"constexpr_static_data_member_without_initi":7,"constexpr_string_not_null_termin":7,"constexpr_too_many_nested_anonymous_typ":7,"constexpr_type_invalid":7,"constexpr_type_too_larg":7,"constexpr_union_field_inact":7,"constexpr_vacuous_dtor_cal":7,"constexpr_variable_decl_must_be_definit":7,"constexpr_variable_must_have_literal_typ":7,"constexpr_virtual_bas":7,"constexpr_virtual_combin":7,"constexpr_vla":7,"constexpr_volatile_fetch":7,"constexpr_weak_address":7,"constinit":7,"constinit_variable_has_dynamic_init":7,"constinit_variable_storag":7,"constitu":[9,11],"constitut":[1,6,21,23],"constrain":[9,10],"constraint":[3,6,7,9,10,11,15,16,18,21],"constraint_concept_templ":7,"constraint_mismatch":7,"constraint_number_mismatch":7,"constru":[10,18],"construct":[0,1,2,3,5,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23],"construct_messag":0,"construct_nod":17,"construct_node_from_modul":17,"construct_node_precheck":17,"construct_node_uncheck":17,"construct_not_allowed_in_cpp11_constant_expr":9,"constructor":[0,2,3,4,7,8,10,14,22,23],"constructor_cal":7,"constructor_type_mismatch":7,"consult":[10,14,16,20,23,26],"consum":[0,1,3,10,14,18,23],"consumpt":15,"contain":[0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"contains_try_block":16,"contend":10,"content":[0,1,4,5,8,9,10,11,14,15,16,17,18,23,24],"context":[0,3,5,6,7,8,9,11,14,15,17,18,23,25,26],"context_limit":10,"contextu":[11,24],"contigu":15,"continu":[0,3,4,6,7,8,9,10,11,12,14,15,16,17,20,23],"continue_cannot_be_in_finally_block":7,"continue_must_be_in_loop":7,"continue_stat":20,"contrari":[3,10],"contrast":[3,10,11,17,18],"contriv":8,"control":[0,1,2,3,5,6,7,8,9,14,15,16,18,20,23],"control_flow_descr_list":20,"conv_array_operand_to_pointer_operand":9,"conv_char_liter":15,"conv_class_prvalue_operand_to_object_point":9,"conv_fixed_point_liter":15,"conv_fixed_point_to_fixed_point":9,"conv_fixed_point_to_float":9,"conv_fixed_point_to_integ":9,"conv_float_liter":15,"conv_float_to_fixed_point":9,"conv_float_to_float":9,"conv_float_to_integ":9,"conv_from_inaccessible_base_class":7,"conv_function_designator_to_ptr_to_funct":9,"conv_glvalue_expr_to_prvalu":[9,11],"conv_glvalue_to_prvalu":[9,11],"conv_integer_liter":15,"conv_integer_to_fixed_point":9,"conv_integer_to_float":9,"conv_integer_to_integ":9,"conv_integer_to_point":9,"conv_integer_to_ptr_to_memb":9,"conv_line_loc_to_source_po":15,"conv_lvalue_to_rvalu":[9,11],"conv_object_pointer_to_lvalu":9,"conv_of_pm_to_func_ptr":7,"conv_of_unbound_pm_to_func_ptr":7,"conv_operand_to_object_point":9,"conv_pointer_to_whatev":9,"conv_prvalue_expr_to_glvalu":11,"conv_ptr_to_member_to_ptr_to_memb":9,"conv_selector_to_object_point":9,"conv_seq_to_file_and_lin":[11,22],"conv_single_char":15,"conv_single_wide_char":15,"conv_string_liter":15,"conv_to_error_operand":9,"conveni":[0,1,3,6,9,11,14,16,17,21,22,23],"convent":[7,9,10,11,16,17,18,19,24],"convers":[0,2,5,6,7,8,10,11,14,16,22,23],"conversion_from_class_poss":9,"conversion_function_not_us":7,"conversion_header_list":21,"conversion_list":[3,21],"conversion_poss":9,"conversion_result_typ":21,"conversion_to_class_poss":9,"conversion_to_pointer_loses_bit":7,"convert":[0,3,7,9,10,11,14,15,16,17,21,22,23],"convert_initi":[6,9],"convert_operand":9,"convert_operand_into_temp":9,"convert_operand_to_handle_to_cli_str":9,"converting_to_incomplete_class":7,"convey":9,"convinc":14,"convolut":16,"cooki":19,"cooper":8,"coordin":[8,11,23],"copi":[0,1,2,3,6,7,8,10,11,14,15,18,21,22,23],"copy_and_extend_path":3,"copy_and_simplify_short_circuited_oper":16,"copy_constructor_in_value_class_typ":7,"copy_ctor_with_default_arg_cannot_be_default":7,"copy_expr_tre":[16,22],"copy_from_secondary_to_primary_il":25,"copy_function_bodies_to_primary_il":25,"copy_header_nam":15,"copy_ifc_field":17,"copy_macro_invocation_tree_to_il":15,"copy_nod":11,"copy_secondary_trans_unit_il_to_primari":25,"copy_template_param_expr":9,"copy_typ":11,"copy_type_with_substitut":23,"copy_virtual_function_override_list":3,"copyabl":7,"copyright":10,"core":[0,6,10,15],"corei7":16,"coroutin":[7,10,12],"coroutine_with_deduced_return_typ":7,"coroutine_with_ellipsis_paramet":7,"corpor":16,"correct":[0,1,6,7,9,10,11,14,15,16,17,18,19,23,24,26],"corresp_decl_at":7,"corresp_decl_incompat":7,"corresp_intercept":25,"corresp_member_template_is_different_kind":7,"corresp_prototype_sym":23,"correspond":[0,1,2,3,5,6,7,8,9,10,12,13,14,15,16,17,18,21,22,23,24],"correspondence_checking_don":25,"correspondence_checking_underway":25,"corresponding_base_class":22,"corresponding_source_po":15,"corrigenda":10,"corrupt":7,"corrupted_export_template_fil":7,"cost":[9,10,11,16],"count":[0,7,10,11,14,15,16,24,25],"count_charact":4,"counter":23,"counterpart":[3,25],"coupl":[8,24],"cours":[0,1,3,10,11,14,16,21],"covari":[2,7],"covariant_override_in_managed_class":7,"cover":[9,11,13,14,15,16,17,26],"cp":[1,16,24],"cp_gen_b":[5,11,14],"cp_gen_be_target_matches_source_dialect":1,"cpfe":24,"cpfe_cp":24,"cpfe_custom":24,"cpp":[1,6,10,14,15,24],"cpp03_mode":14,"cpp0x_sfinae_en":9,"cpp11_il_extensions_support":19,"cpp17_mode":14,"cpp20_reversed_comparison_ambigu":7,"cpp_driver":[0,15],"cppbe":24,"cppcli":[1,7,10],"cppcli_attribute_on":7,"cppcli_en":[11,14],"cppcli_enabling_poss":[1,11,14],"cppcli_enumerator_requires_explicit_valu":7,"cppcli_explicit_conversion_is_virtu":7,"cppcli_explicit_conversion_only_in_ref_and_value_class":7,"cppcli_not_en":7,"cppcli_requires_newer_abi_vers":7,"cppcx":10,"cppcx_array_only_one_dimension_allow":7,"cppcx_bad_delegate_init_list":7,"cppcx_box_invalid_typ":7,"cppcx_enabl":14,"cppcx_enabling_poss":1,"cppcx_enum_base_has_no_platform_counterpart":7,"cppcx_generic_constraints_not_allow":7,"cppcx_generic_method_not_allow":7,"cppcx_generic_type_not_allow":7,"cppcx_handle_or_ref_to_generic_param":7,"cppcx_invalid_array_property_set_value_paramet":7,"cppcx_invalid_delegate_object":7,"cppcx_non_const_array_paramet":7,"cppcx_not_en":7,"cppcx_public_global_typ":7,"cppcx_public_indexed_properti":7,"cppcx_public_native_typ":7,"cppcx_public_nested_deleg":7,"cppcx_public_value_class_constructor":7,"cppcx_tracking_reference_on_standard_class_typ":7,"cppcx_value_type_contains_virtual_funct":7,"cppcx_value_type_deriving_from_interfac":7,"cpu":[7,10,11,16],"craft":14,"crash":[17,24],"creat":[3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"create_block_scop":22,"create_cli_delegate_definit":3,"create_expr_temporari":9,"create_external_symbol_for_linked_ent":6,"create_header_unit":[10,24],"create_il_entry_for_pragma":18,"create_initial_template_arg_list":23,"create_module_interfac":10,"create_module_internal_partit":10,"create_mv_resolv":16,"create_or_remove_instantiation_information_fil":23,"create_pch":[0,10],"create_pch_file_not_cr":7,"create_prototype_typ":23,"create_proxy_or_nonreal_class_memb":21,"creating_pch":7,"creation":[3,7,9,10,11,16,17,18,21,23],"cref":9,"criteria":21,"critic":18,"cross":[0,6,9,10,14,21],"cs":16,"csin":10,"csinf":10,"csinl":10,"ct":16,"ctor":[6,7,16,23],"ctor_dtor_priority_reserv":7,"ctor_initi":[3,6,23],"ctor_inti":6,"ctor_routin":16,"ctrl":24,"cu":15,"cumbersom":[9,11],"cur":4,"curr_char_loc":15,"curr_construct_":9,"curr_construct_pragma":18,"curr_context":16,"curr_expr_kind_is_traditional_const":9,"curr_object_lifetim":22,"curr_scope_id_lookup":21,"curr_source_lin":[14,15],"curr_stop_token_stack_entri":15,"curr_token":[9,14,15],"curr_token_is_inert_macro":15,"curr_token_pragma":18,"curr_translation_unit":25,"curr_type_symbol":6,"current":[0,1,2,3,5,6,7,8,9,10,11,14,16,17,18,20,22,23,24,25,26],"current_token_pragma":18,"custom":[1,7,8,10,11,14,16,18,26],"cv":[3,9,10,11,16],"cv_qualified_function_typ":7,"cx":[7,10,14],"cxx":[1,3,10,16,17],"cxxabi":12,"cycl":[0,7,16,23],"cygwin":1,"d":[0,2,3,4,6,10,14,15,16,21,24,25,26],"d0":[2,16],"d1":[6,16],"d2":[6,10,16],"d7":16,"d__unix__":1,"daemon":14,"danger":14,"data":[0,1,2,5,6,7,8,10,11,12,14,18,19,20,21,22,25,26],"data_member_with_interface_typ":7,"databas":23,"date":[0,2,9,10,20],"david":16,"db":10,"db_abbreviated_typ":22,"db_access_control":22,"db_activ":[0,14],"db_constant":22,"db_corresp":25,"db_dynamic_initi":22,"db_enter":14,"db_exit":14,"db_express":22,"db_field":22,"db_flag_is_set":14,"db_has_traced_nam":14,"db_initi":22,"db_member_funct":22,"db_name":[10,14,22],"db_name_linkag":22,"db_node":17,"db_object_lifetim":22,"db_object_lifetime_stack":22,"db_operator_nam":11,"db_opt":14,"db_scope":22,"db_source_sequence_entri":22,"db_statement":22,"db_statement_list":22,"db_static_data_memb":22,"db_trace":14,"db_type":22,"db_type_nam":22,"db_variabl":22,"db_virtual_function_info":22,"dc":16,"dd":10,"de":[0,10,16],"deactiv":10,"deal":[0,1,2,3,5,6,8,9,11,14,15,16,18,21,22,23,25],"dealloc":[7,8,9,10,16],"deallocation_operator_in_namespac":7,"dealt":[10,11,18,21],"debug":[1,2,3,5,7,11,13,15,16,26],"debug_ent":[0,14],"debug_exit":[0,14],"debug_level":[0,14],"debug_show_loc":7,"debugg":[1,3,5,17,24,25],"decay":10,"decid":[0,1,3,6,9,10,11,14,15,16,18,20,21,23,24],"decim":[9,10,14,15,16,24],"decis":[0,10,11,14,15,16,17,23],"decl":[0,3,6,8,9,10,14,17,23],"decl_call_operator_for_lambda":3,"decl_default_funct":9,"decl_friend_class":3,"decl_friend_funct":3,"decl_function_templ":23,"decl_hdr":[10,14],"decl_hides_catch_paramet":7,"decl_hides_function_paramet":7,"decl_hides_template_paramet":7,"decl_idx":17,"decl_in_prototype_scop":7,"decl_incompatible_with_previous_us":7,"decl_info":23,"decl_init":[3,6,9,14],"decl_lambda_capture_field":3,"decl_literal_field":3,"decl_member_funct":[3,21,23],"decl_member_function_templ":3,"decl_modifiers_ignor":7,"decl_modifiers_incompatible_with_previous_decl":7,"decl_modifiers_invalid_for_this_decl":7,"decl_nonstatic_data_memb":3,"decl_nonstd_member_const":3,"decl_of_void_ignor":7,"decl_paramet":[6,23],"decl_posit":11,"decl_property_or_event_memb":3,"decl_ref":17,"decl_routin":[3,6,23],"decl_scop":21,"decl_scope_level":[3,21],"decl_seq":23,"decl_should_be_of_param":7,"decl_spec":[3,6,14],"decl_specifi":[3,6,8,23],"decl_stat":3,"decl_statement_ful":20,"decl_static_data_memb":[3,6,23],"decl_token_cach":23,"decl_typedef":[3,6],"decl_vari":6,"decl_with_local_type_but_not_defin":7,"decl_with_no_linkage_type_but_not_defin":7,"declalia":17,"declar":[0,2,7,8,9,10,12,13,15,17,18,20,25,26],"declaration_after_stat":7,"declaration_hides_for_init":7,"declaration_scop":23,"declarator_rang":11,"declared_but_not_referenc":7,"declares_someth":3,"declenumer":17,"declforeignindex":17,"declfunct":17,"declindex":17,"declrefer":17,"declsort":17,"declspec_align_reduction_ignor":7,"declspec_property_not_allow":7,"declspeci":17,"declspecializt":17,"decltyp":[7,9,10,11,16,22],"decltype_auto_cannot_be_qualifi":7,"decltype_auto_not_allowed_her":7,"decltype_auto_return_must_be_standalon":7,"decltype_auto_type_requires_initi":7,"decltype_is_not_base_class":7,"decltype_qualified_declared_nam":7,"decod":[1,26],"decode_identifi":26,"decor":10,"decreas":10,"decrement":[7,9,14,15,16,23],"decrib":6,"dedic":[6,11,17],"deduc":[0,3,6,7,9,10,23],"deduced_return_type_conflict":7,"deduced_return_types_is_cpp14":7,"deduct":[7,9,10,23],"deduction_fail":7,"deduction_guide_def":7,"deduction_guide_redeclar":7,"deem":10,"deep":11,"def":[0,10,16,23],"def__tm__7_xcil15":16,"def_arg":14,"def_arg_expr_list":23,"def_external_linkag":6,"def_initi":[6,23],"default":[0,1,2,4,7,8,9,11,12,14,15,16,18,20,21,22,23,24,26],"default_":1,"default_address_of_ellipsis_allow":10,"default_allow_anachron":10,"default_allow_ellipsis_only_param_in_c_mod":10,"default_alternative_tokens_allow":10,"default_arg_already_defin":7,"default_arg_differs_in_other_trans_unit":7,"default_arg_expr_not_allow":7,"default_arg_for_literal_oper":7,"default_arg_not_at_end":7,"default_arg_on_function_template_not_allow":7,"default_arg_on_member_decl":7,"default_arg_on_member_friend":7,"default_arg_on_member_template_def":7,"default_arg_prototype_instanti":23,"default_arg_requires_friend_to_be_definit":7,"default_arg_used_in_param_array_funct":7,"default_args_incompat":7,"default_argument_promot":22,"default_array_new_and_delete_en":10,"default_association_appears_more_than_onc":7,"default_auto_storage_class_specifier_en":10,"default_auto_type_specifier_en":10,"default_automatic_instantiation_mod":10,"default_bool_is_keyword":10,"default_c_and_cpp_function_types_are_distinct":10,"default_calling_convent":10,"default_common_tentative_definit":10,"default_constructor_in_value_class_typ":7,"default_constructor_is_explicit":7,"default_context_limit":10,"default_cppcli_en":1,"default_ctor_call_not_const":7,"default_ctor_not_constexpr":7,"default_dependent_name_process":10,"default_display_error_numb":10,"default_edg_bas":0,"default_edg_color":10,"default_emulate_gnu_abi_bug":[1,3,26],"default_enable_colorized_diagnost":10,"default_exceptions_en":[8,10],"default_explicit_keyword_en":10,"default_export_template_allow":10,"default_gnu_abi_vers":1,"default_gnu_compat":1,"default_gnu_stdc_zero_in_system_head":10,"default_guiding_decls_allow":10,"default_impl_conv_between_c_and_cpp_function_ptrs_allow":10,"default_implicit_template_inclusion_mod":10,"default_implicit_typename_en":10,"default_implicit_using_std":10,"default_include_file_suffix_list":10,"default_incognito":10,"default_init_of_refer":7,"default_instantiation_file_suffix_list":10,"default_is_unexpect":[4,14],"default_label":20,"default_label_appears_more_than_onc":7,"default_label_must_be_in_switch":7,"default_macro_positions_in_diagnost":10,"default_max_pending_instanti":10,"default_member_init_for_value_class":7,"default_microsoft_bug":10,"default_microsoft_compat":1,"default_microsoft_mod":10,"default_microsoft_vers":10,"default_module_import_diag_en":10,"default_ms_permiss":10,"default_multibyte_chars_in_source_allow":10,"default_namespaces_en":10,"default_near_and_far_en":10,"default_nocommon_tentative_definit":10,"default_not_allowed_on_partial_spec":7,"default_old_specializations_allow":10,"default_pass_stdarg_references_to_generated_cod":10,"default_record_form_of_name_refer":11,"default_remove_unneeded_ent":[0,11],"default_rtti_en":10,"default_stdc_zero_in_system_head":10,"default_sun_compat":1,"default_sun_linker_scope_allow":10,"default_svr4_c_mod":10,"default_target_configuration_nam":1,"default_template_arg_not_allow":7,"default_template_typedefs_in_diagnost":10,"default_trigraphs_allow":10,"default_typename_en":10,"default_unicode_source_kind":15,"default_use_nonstandard_for_init_scop":10,"default_use_predefined_macro_fil":0,"default_variadic_templates_en":10,"default_version_of_routin":16,"default_warning_on_for_init_differ":10,"default_wchar_t_is_keyword":10,"defaulted_assignment_cannot_have_const_paramet":7,"defaulted_comparison_for_properti":7,"defaulted_copy_ctor_cannot_have_const_paramet":7,"defaulted_default_ctor_cannot_be_constexpr":7,"defaulted_functions_is_cpp11":7,"defect":17,"defer":[0,6,17,18,21],"defer_parse_function_templ":10,"deferr":10,"defin":[0,2,5,6,7,8,10,11,12,13,14,15,16,17,18,19,20,22,23,24,25,26],"define_label":20,"define_macro":10,"define_member_funct":6,"define_one_virtual_function_t":16,"define_scope_virtual_function_t":16,"define_special_member_funct":3,"define_static_data_memb":[3,6],"define_virtual_function_t":16,"defined_always_fals":7,"defines_someth":3,"definit":[1,2,4,5,6,7,8,9,11,12,14,16,17,18,20,21,22,25,26],"definition_list_fil":10,"definition_need":[0,11],"definition_of_implicitly_declared_funct":7,"definition_templ":11,"defintit":23,"degener":10,"degrad":17,"degre":[10,24],"delay":[0,3,6,9,10,15,21,23],"delayed_scan_fixup_for_class":[3,23],"delayed_scan_for_function_template_default_arg":[3,23],"delayed_scan_of_default_arg_expr":3,"deleg":[6,7,9,10,11,17],"delegate_requires_managed_class":7,"delegating_constructor":[7,10],"delegating_constructor_is_cpp11":7,"delegating_constructor_requires_newer_abi_vers":7,"delegation_init_and_mem_init":7,"delegation_loop":7,"delet":[0,7,8,9,10,14,19,21,23,24],"delete_can_be_folded_into_dtor":11,"delete_count_anachron":7,"delete_fil":0,"delete_of_array_typ":7,"delete_of_array_type_nonstandard":7,"delete_of_function_point":7,"delete_of_incomplete_class":7,"delete_routin":16,"delete_source_from_loc":15,"deleted_default_constructor":7,"deleted_elided_cctor":7,"deleted_funct":7,"deleted_function_definition_must_be_first_declar":7,"deleted_function_overrides_nondeleted_funct":7,"deleted_functions_is_cpp11":7,"deleted_inh_def_constructor":7,"deleted_main":7,"deliber":[9,17,25],"delimit":[2,6,7,10,11,14,15,18],"deliv":[10,14,16],"delta":16,"demand":[3,10,23],"demangl":[1,13,16,26],"demonstr":1,"denomin":26,"denot":[4,6,11,15,23,25],"dep":23,"dep_nam":[7,10],"depend":[1,2,3,6,7,9,11,14,15,16,17,18,20,22,23,24,26],"dependent_stat":20,"dependent_stmt_is_declar":7,"dependent_vector_s":7,"deprec":[7,10,11,18],"deprecated_access_specifi":7,"deprecated_attr":7,"deprecated_ent":7,"deprecated_entity_with_custom_messag":7,"deprecated_string_conv":[7,10],"deprecated_string_conv_gen":7,"depth":[3,7,10,11,15,16,21,23],"depth_innermost_function_scop":21,"depth_innermost_instantiation_scop":[21,23],"depth_innermost_namespace_scop":21,"depth_of_initial_lookup_scop":21,"depth_of_innermost_scope_that_affects_access_control":21,"depth_scope_stack":21,"derefer":[7,9,17],"dereferenc":[7,17],"deriv":[0,1,2,6,7,8,9,10,11,16,17,18,21,22,23],"derived_class_from_virtual_bas":7,"derived_class_too_far":7,"derived_nam":0,"descend":[0,14],"descent":[0,9,13,15],"descib":23,"describ":[0,1,3,4,6,8,9,10,11,13,14,15,16,17,18,19,21,22,23,24,25,26],"descript":[0,1,3,4,6,7,8,9,10,11,14,15,16,17,18,20,22,23,24,26],"descriptor":20,"design":[0,1,3,5,6,7,8,9,10,11,13,14,15,16,17,18,21,23,24],"designated_initializer_enabling_poss":[10,11],"designator_for_non_pod":7,"designator_for_template_dependent_typ":7,"designator_is_nonstandard":7,"designator_requires_aggregate_typ":7,"designators_allow":10,"desir":[0,1,4,5,9,10,11,13,14,15,16,17,22],"desired_typ":16,"despit":[3,10,17],"destin":[6,7,8,9,10,11,16,17],"destroy":[7,8,10,11,16,19],"destroying_delete_with_extra_param":7,"destroying_delete_wrong_typ":7,"destruct":[6,8,9,10,11,16,19,22],"destructor":[3,4,7,8,9,10,14,15,19,20,22,23],"destructor_in_value_class_typ":7,"destructor_name_must_be_qualifi":7,"destructor_or_finalizer_with_named_overrid":7,"destructor_posit":7,"destructor_qualifier_type_mismatch":7,"destructor_type_mismatch":7,"detach":9,"detail":[0,1,3,6,7,8,10,11,13,14,15,16,17,18,20,21,22,23,24,25],"detect":[0,3,7,8,9,10,14,15,16,18,20,21,23],"determin":[0,1,3,5,6,7,8,9,10,11,12,14,15,16,17,18,20,21,22,23,24,25],"determine_arg_match_level":9,"determine_arithmetic_convers":9,"determine_assoc_namespaces_and_class":21,"determine_correspond":25,"determine_dynamic_init_for_class_init":9,"develop":[4,5,9,10,14,15,16,17,22],"deviat":10,"devic":6,"devot":14,"dfe_wrapup":14,"diag_":10,"diag_annotation_ind":10,"diag_default":[0,10],"diag_error":[0,10],"diag_messag":0,"diag_onc":10,"diag_remark":10,"diag_suppress":10,"diag_warn":10,"diagnos":[3,10,13,14,15,23],"diagnosi":10,"diagnost":[0,1,3,6,7,11,14,15,17,18,21,23,24,25,26],"dialect":[3,11,13,24],"dictat":[5,10,11,15,16,22],"did_not_fold":9,"didn":[16,17],"difer":23,"diff":24,"differ":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25],"different_enum_comparison":7,"different_return_type_on_virtual_function_overrid":7,"differenti":[2,16],"difficult":[0,6,16],"difficulti":[0,11,23],"digit":[7,10,15,16,24],"digit_separ":10,"digit_separators_not_en":7,"digraph":10,"diirect":21,"dik_call_returning_class_via_cctor":11,"dik_express":11,"dik_non":11,"dik_nonconstant_aggreg":11,"dilemma":0,"dim":16,"dim_not_const_unsigned_int":7,"dimens":[6,7,9,10,11,16,22],"dimension":[6,7],"dinkumwar":16,"dir":[10,23,24],"direct":[0,1,2,3,5,7,8,9,11,14,16,17,18,22,24,25],"direct_alloc":14,"direct_error_output_to_stdout":10,"directori":[0,7,10,14,15,19,23,24,26],"directory_of":0,"disabl":[0,1,7,9,10,11,14,15,16,18,23,24,26],"disable_ldscop":10,"disadvantag":[10,11,23],"disallow":[0,7,9,10],"disambig":[6,14],"disambigu":[5,6,7,10,14,15,18,23],"disappear":21,"discard":[0,7,10,11,14,15,16,18,20,21,23,25],"discard_curr_construct_pragma":18,"discern":[9,15,22],"disciplin":[8,14],"discontinu":11,"discov":[10,14,24],"discret":0,"discretionari":[0,10,14],"discrimin":[14,15,16,17,21],"discuss":[3,6,8,11,15,16,20,21,23],"disguis":10,"disk":10,"disk1":10,"disk2":10,"disk3":10,"disp":[1,24],"disp_":11,"disp_boolean":11,"disp_entri":[0,11],"disp_expr_operator_nam":11,"disp_ptr":11,"dispatch":[3,6,16,23],"display":[4,7,11,13,14,22,23,24,26],"display_error_numb":10,"dispos":[0,3,7,18],"dispose_of_unapplied_attribut":6,"disprov":6,"disqualifi":[7,16,23],"disregard":21,"distinct":[0,2,3,6,7,8,9,10,11,14,16,18,21,23],"distinct_template_signatur":[10,16],"distinguish":[0,3,5,6,7,8,9,11,14,16,21,22,23],"distribut":[4,10,14,26],"disturb":[15,16],"dive":[11,24],"diverg":[11,17],"divid":3,"divide_by_zero":7,"divide_integer_valu":9,"divis":[7,14,23],"dl":16,"dla":16,"dll":[0,1,6,7,10,14,15],"dll_interface_conflict_dllexport_assum":7,"dll_interface_conflict_none_assum":7,"dll_interface_ignored_on_class_templ":7,"dll_interface_ignored_on_qualified_declar":7,"dll_interface_in_unnamed_namespac":7,"dll_interface_requires_external_linkag":7,"dll_thread_conflict":7,"dllexport":7,"dllimport":7,"dllimport_defin":7,"dmi":3,"dmis":11,"dn":16,"do_and":9,"do_any_needed_instanti":23,"do_binary_oper":9,"do_cast":9,"do_class_layout":3,"do_compl":9,"do_fadd":9,"do_fcompar":9,"do_fdivid":9,"do_field_selection_oper":9,"do_fmultipli":9,"do_fneg":9,"do_fsubtract":9,"do_full_portable_eh_low":[8,16,22],"do_fxadd":9,"do_fxcompar":9,"do_fxdivid":9,"do_fxmultipli":9,"do_fxneg":9,"do_fxsubtract":9,"do_iadd":9,"do_icompar":9,"do_idivid":9,"do_il_low":[1,11],"do_imultipli":9,"do_ineg":9,"do_inlining_of_cal":16,"do_isubtract":9,"do_jdivid":9,"do_jmultipli":9,"do_land":9,"do_lor":9,"do_member_function_select":9,"do_namespace_member_promot":16,"do_not":9,"do_not_clear_specific_symbol":21,"do_not_instanti":[10,16,23],"do_not_put_curr_line_in_pp_output":15,"do_not_reus":21,"do_operand_transform":9,"do_or":9,"do_padd":9,"do_pcompar":9,"do_pdiff":9,"do_pmcompar":9,"do_preprocessing_on":15,"do_remaind":9,"do_scope_class_member_promot":16,"do_shift":9,"do_shiftl":9,"do_shiftr":9,"do_stat":20,"do_string_literal_concaten":15,"do_unordered_eh_process":16,"do_using_directive_lookup":21,"do_xadd":9,"do_xcompar":9,"do_xdivid":9,"do_xmultipli":9,"do_xneg":9,"do_xor":9,"do_xsubtract":9,"doc":1,"document":[1,6,9,10,11,14,16,17,26],"doe":[0,1,2,3,4,6,7,8,9,10,11,13,14,15,17,18,19,20,21,22,23,24,25,26],"does_not_return":18,"doesn":[0,1,2,6,9,10,11,14,15,16,17,18,20,21,23,26],"dollar":10,"don":[0,3,6,7,9,10,11,16,17,18,21,22,23,24,26],"done":[0,1,2,3,5,6,7,8,9,10,11,13,14,15,17,18,19,21,22,23,25,26],"dos":[0,1],"doubl":[0,2,3,6,7,9,10,11,16,17,21,23,26],"double_for_long_doubl":7,"doubli":[15,20],"doubt":14,"downgrad":9,"download":1,"dozen":[0,1,10,14,22],"dp":16,"dps":6,"draft":[3,10],"dramat":[10,14,16],"draw":[9,19],"drive":17,"driven":[1,14,18,20,25],"driver":[10,14,19,23,24,25,26],"driver_debug":24,"drop":[7,10,11,16,18],"ds":16,"dstandalone_il_display":1,"dt":16,"dtest_numb":24,"dtor":16,"dtor_initi":[6,23],"dtor_list":19,"dtor_routin":16,"du":16,"dual_lookup_ambiguous_nam":7,"dualiti":23,"dub":1,"due":[0,3,7,9,10,14,15,16,24],"dumb":17,"dummi":[2,6,23],"dump":[0,1,2,14,24],"dump_ampersand":2,"dump_command_opt":10,"dump_configur":[1,10,24],"dump_const":2,"dump_enum_definit":2,"dump_expr":2,"dump_func_definition_typ":2,"dump_general_declaration_using_typ":2,"dump_header_cod":2,"dump_initi":2,"dump_layout":10,"dump_legacy_as_target":[1,10],"dump_routine_decl":2,"dump_routine_definit":2,"dump_scope_const":2,"dump_scope_routin":2,"dump_scope_typ":2,"dump_scope_vari":2,"dump_source_file_correspondence_info":2,"dump_stat":2,"dump_struct_union_definit":2,"dump_typ":2,"dump_type_decl":2,"dump_typedef_decl":2,"dump_variable_decl":2,"dump_variable_nam":2,"dupl_base_class_nam":7,"dupl_calling_convent":7,"dupl_decl_specifi":7,"dupl_embed_param":7,"dupl_get_or_put":7,"dupl_mem_attrib":7,"dupl_param_nam":7,"dupl_type_qualifi":7,"duplic":[0,7,10,14,16,18,25],"duplicate_asm_qualifi":7,"duplicate_class_modifi":7,"duplicate_constraint":7,"duplicate_design":7,"duplicate_friend_decl":7,"duplicate_function_modifi":7,"duplicate_header_unit_map":7,"duplicate_inheriting_constructor":7,"duplicate_macro_param_nam":7,"duplicate_module_map":7,"duplicate_ms_attr_arg":7,"duplicate_threads_dim":7,"duplicate_type_in_c11_gener":7,"duplicate_typedef":7,"duplicate_typedef_in_class":7,"duplicate_using_decl":7,"durat":[6,7,10,15,16,18],"dure":[0,1,3,6,7,8,9,10,11,15,16,17,18,21,22,23,24,25,26],"duti":17,"dyn_array":4,"dyn_local_static_in_statement_expr":7,"dynam":[0,2,3,5,6,7,8,9,14,15,20,21,22,26],"dynamic_cast":[1,7,9,10,11],"dynamic_cast_operand_must_be_polymorph":7,"dynamic_cast_to_value_gener":7,"dynamic_cast_without_rtti":7,"dynamic_exc_spec_not_permit":7,"dynamic_exception_specifications_deprec":7,"dynamic_init":[7,11],"e":[0,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],"e1":[3,5,10,11],"e2":[3,11],"e3":3,"eabi":[1,10],"earli":[0,3,7,10,11,18,24],"earlier":[0,7,8,9,10,13,14,15,16,17,18,20,21,23,24],"earliest":10,"early_tiebreak":10,"eas":[0,9,10,11,14,22,23],"easi":[0,5,11,14,16,18,23],"easier":[1,3,9,11,15,16,17,24],"easiest":[15,18],"easili":[1,9,10,11,13,14,15,16,18,21,24,25],"ec_":[0,26],"ec_exp_":14,"ec_exp_line_numb":14,"ec_no_error":[0,14],"ec_unclosed_str":0,"eccp":[10,23,24],"eccp_command":24,"eclips":[3,21],"ecma":[1,9,10,11,13],"ed":14,"edg":[0,1,3,4,8,10,11,14,16,17,18,19,23,26],"edg_auxiliary_info_dir_nam":0,"edg_bas":[0,1,7],"edg_base_dir":[0,10],"edg_c_to_obj_compil":1,"edg_color":10,"edg_decod":1,"edg_default_defin":1,"edg_eccp_config":1,"edg_header_pack":24,"edg_main":[0,1],"edg_modules_path":10,"edg_munch":1,"edg_prelink":[1,23],"edg_test_hom":24,"edg_test_no_copy_":24,"edg_test_runs_kept":24,"edg_win32":[1,15],"edg_x86_64":24,"edg_x86_64_cp":24,"edgcpdisp":[1,10],"edgcpf":[1,10],"edgtest":24,"edgy_my_test":24,"edison":[10,13],"edit":[1,10],"editor":[4,17],"educ":1,"effect":[0,2,3,5,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,26],"effective_decl_level":3,"effici":[0,1,8,9,10,11,14,15,16,17,19,21,25,26],"effort":[15,16],"efil":10,"egg":16,"eh":16,"ehsc":1,"either":[0,1,2,3,4,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25],"ek_init_const":9,"ek_integral_const":9,"ek_norm":9,"ek_pp":9,"ek_sizeof":9,"elabor":[3,5,7,10,21,23,24],"elaps":[10,24],"elem_s":16,"element":[0,6,7,8,9,10,11,14,15,16,17,18,19,21,22,23,25,26],"element_type_incomplet":7,"elf":16,"elf_visibility_pop_mismatch":7,"elf_visibility_stack_empti":7,"elicit":[18,23],"elid":[3,9,16],"elif":10,"elifdef":7,"elifdef_not_en":7,"elifndef":7,"elig":[7,8,16],"elimin":[0,2,3,5,7,8,11,16,20,22,25,26],"eliminate_bodies_of_unneeded_funct":0,"eliminate_unneeded_il_entri":0,"ellipsi":[7,8,9,10,16],"ellipsis_after_param_array":7,"ellipsis_cli_accessor":7,"ellipsis_not_allow":7,"ellipsis_on_operator_funct":7,"ellipsis_parameter_for_literal_oper":7,"elog":24,"els":[0,3,7,8,9,10,11,14,15,16,17,18,21,23,26],"elseif":7,"elsewher":[2,7,10,14,15,21,23,25],"emb":[6,7,10],"embed":[4,6,7,9,10,11,14,15,16],"embed_directori":10,"embed_narrow":7,"embedded_c":[7,10],"embedded_c_option_incompatible_with_individual_feature_opt":7,"embodi":16,"emiss":6,"emit":[1,2,9,10,16,17,18,23],"emphas":[4,17],"employ":[15,21],"empti":[0,2,7,9,10,11,15,18,21,23],"empty_anonymous_union":7,"empty_clobbers_list":7,"empty_delimited_escap":7,"empty_else_stat":7,"empty_include_search_path":7,"empty_lambda_template_param_list":7,"empty_macro_argu":7,"empty_pack_alignment_stack":7,"empty_pack_expans":7,"empty_property_indic":7,"empty_requires_express":7,"empty_template_param_list":7,"empty_then_stat":7,"empty_throw_specification_not_cpp20":7,"empty_translation_unit":7,"empty_unicode_nam":7,"empty_wide_charact":7,"emul":[1,7,9,10,11,14,20,24,26],"enabl":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,20,21,22,23,24,25,26],"enable_if":7,"enable_ldscop":10,"encapsul":[0,3,6],"enclos":[3,6,7,9,10,11,14,15,16,20,21,22,23,25],"enclosing_scop":23,"enclosing_template_decl":23,"encod":[0,1,10,11,15,16,17,18,23],"encount":[0,2,3,5,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25],"end":[0,3,4,6,7,9,12,15,16,17,19,20,21,22,23,24,25,26],"end_caching_of_fetched_token":15,"end_deferral_of_access_check":21,"end_error":0,"end_of_curr_token":15,"end_of_directive_process":15,"end_of_file_scope_needed_flags_phas":0,"end_of_flush":7,"end_of_scope_symbol_check":21,"end_of_source_sequence_list":21,"end_pos_curr_token":9,"end_posit":9,"end_potential_pack_expansion_context":23,"endian":[1,10,15],"endif":[0,2,7,10,14,15,17,24],"endpoint":21,"english":0,"enhanc":[9,10,16],"enk_":[11,14],"enk_braced_init_list":9,"enk_compound_req":23,"enk_concept_id":23,"enk_condit":[11,16],"enk_const":11,"enk_field":11,"enk_fold":11,"enk_gcnew":[9,11],"enk_lambda":[9,11],"enk_lowered_eh_construct":16,"enk_nested_req":23,"enk_new_delet":[9,11,16],"enk_object_lifetim":11,"enk_oper":11,"enk_param_ref":11,"enk_requir":23,"enk_result_of_overriding_funct":[2,16],"enk_reuse_valu":11,"enk_routin":11,"enk_sizeof":11,"enk_temp_init":[9,11,16],"enk_throw":[8,11,16],"enk_type_operand":23,"enk_typeid":[9,11,16],"enk_vari":11,"enk_vla_dealloc":[11,16],"enlarg":0,"enough":[0,1,3,9,10,14,15,16,20],"ensur":[2,10,11,14,15,16,17,18,20,23,25],"ensure_il_scope_exist":20,"ensure_inclass_static_member_constant_initializer_is_scan":3,"entail":[6,8,16,23],"enter":[0,3,6,8,9,10,11,14,15,16,18,20,21,22,23,26],"enter_assert_pred":15,"enter_keyword":21,"enter_namespace_projection_symbol":21,"enter_overloaded_symbol":21,"enter_predef_macro":[0,21],"enter_symbol":21,"enter_synthesized_namespace_projection_symbol":21,"entir":[1,3,6,7,9,10,11,14,15,16,17,20,21,22,23,25],"entireti":11,"entiti":[0,1,2,3,5,6,7,9,10,11,12,14,15,18,20,22,23,25,26],"entity_cannot_be_speci":7,"entity_defined_in_other_trans_unit":7,"entity_defined_twic":7,"entity_differs_in_other_trans_unit":7,"entity_nod":16,"entri":[0,1,2,3,5,6,7,8,9,10,15,18,19,20,23,24],"enum":[0,2,3,5,6,7,9,10,11,14,16,17,22,23],"enum_attribute_ignor":7,"enum_base_type_must_be_integr":7,"enum_base_type_too_limit":7,"enum_bit_field_too_smal":7,"enum_const_cast":7,"enum_in_managed_class_missing_definit":7,"enum_not_allow":7,"enum_operand":7,"enum_overload":[7,10],"enum_previously_declared_without_explicit_bas":7,"enum_qualifier_is_cpp11":7,"enum_specifi":6,"enum_type_not_allow":7,"enum_type_replac":7,"enum_types_can_be_smaller_than_int":[6,10],"enum_value_out_of_int_rang":7,"enum_value_out_of_underlying_rang":7,"enumer":[0,2,6,7,8,9,10,11,14,15,16,17,18,21,24,25,26],"enumerator_already_declar":7,"environ":[0,3,6,7,11,13,14,16,19,24,25,26],"environment":[0,10],"eok_":11,"eok_add":11,"eok_address_of":11,"eok_array_to_point":11,"eok_assign":11,"eok_base_class_cast":11,"eok_bassign":[2,11],"eok_bool_cast":[11,16],"eok_box":[9,11],"eok_cal":[11,16],"eok_cast":11,"eok_class_rvalue_adjust":11,"eok_cli_subscript":9,"eok_derived_class_cast":11,"eok_divid":11,"eok_dot_field":[9,11],"eok_dot_member_cal":11,"eok_dot_pm_cal":11,"eok_dot_stat":[9,11],"eok_dot_vacuous_destructor_cal":11,"eok_dynamic_cast":[9,11,16],"eok_eq":11,"eok_handle_to":9,"eok_handle_to_box":11,"eok_indirect":11,"eok_jfadd":11,"eok_jmultipli":11,"eok_land":11,"eok_lor":11,"eok_lvalu":11,"eok_lvalue_adjust":11,"eok_lvalue_cast":11,"eok_n":11,"eok_neg":11,"eok_not":11,"eok_padd":11,"eok_paren":11,"eok_pdiff":11,"eok_pm_base_class_cast":11,"eok_pm_cal":[11,16],"eok_pm_derived_class_cast":11,"eok_pm_field":[9,11,16],"eok_pm_points_to_field":[9,11,16],"eok_points_to_field":[9,11],"eok_points_to_member_cal":11,"eok_points_to_pm_cal":11,"eok_points_to_stat":[9,11],"eok_points_to_vacuous_destructor_cal":[11,16],"eok_post_incr":11,"eok_psubtract":11,"eok_quest":11,"eok_ref_cast":11,"eok_ref_dynamic_cast":[9,11],"eok_ref_indirect":[5,11],"eok_reference_to":[5,11],"eok_subscript":[9,11],"eok_subtract":11,"eok_unbox":11,"eok_unbox_lvalu":11,"eok_vacuous_destructor_cal":16,"eok_virtual_cal":11,"eok_virtual_function_ptr":[11,16],"ephemer":15,"epilogu":[8,16],"eq_const":22,"equal":[3,7,9,10,14,16],"equals_assumed_in_cmd_line_macro_def":7,"equiv_template_arg_list":23,"equival":[0,3,4,6,7,9,10,14,15,16,17,18,22,23,24,26],"eras":[0,2,10],"err_cod":[0,1,14,26],"err_data":[0,1,14,26],"error":[1,3,6,8,9,10,11,13,16,17,18,20,21,22,23,24,25,26],"error_and_make_error_operand":9,"error_cod":[0,26],"error_const":7,"error_detect":9,"error_direct":7,"error_in_operand":9,"error_limit":10,"error_msg":[0,1,14,26],"error_nod":22,"error_number_or_tag":10,"error_output":10,"error_posit":[0,9,14],"error_sever":18,"error_symbol_head":21,"error_tag":[0,1,14,26],"error_typ":[7,22],"ersatz":11,"es_alloc":11,"es_discretionary_error":0,"es_error":0,"es_non":18,"es_warn":0,"escap":[7,10,11,15,24,26],"especi":[1,9,10,11,15,16,21],"essenc":[9,17],"essenti":[0,1,3,9,10,11,16,18,19,23],"establish":[0,1,2,3,9,10,11,14,15,16,17,21,23,25],"establish_":25,"establish_block_extern_function_correspond":25,"establish_block_extern_variable_correspond":25,"establish_class_instantiation_corresp":25,"establish_friend_type_correspond":25,"establish_function_instantiation_corresp":25,"establish_trans_unit_correspondences_for_class":25,"establish_variable_instantiation_corresp":25,"estim":24,"et":[5,9,10,16,23],"etc":[0,1,2,3,4,5,6,7,9,10,11,14,15,16,18,20,21,22,23,25,26],"evalu":[0,2,3,7,8,9,10,11,14,17,21,23,24],"even":[0,1,2,3,5,6,9,10,11,14,15,16,17,18,20,21,22,23,25],"event":[0,1,5,7,8,9,11,16,18,20,21],"event_accessor_missing_value_paramet":7,"event_accessor_value_parameter_mismatch":7,"event_add_already_declar":7,"event_in_cppcx_value_typ":7,"event_interface_cannot_have_definit":7,"event_interface_must_be_previously_defin":7,"event_name_not_allow":7,"event_raise_already_declar":7,"event_raise_type_mismatch":7,"event_remove_already_declar":7,"event_requires_managed_class":7,"event_without_raise_invok":7,"eventregistrationtoken":7,"eventu":[0,6,10,16,25],"ever":[11,14,16,17],"everi":[0,1,3,6,10,11,14,15,16,17,18,21,23,24,25],"everyth":[0,2,8,9,10,11,14,16,17,26],"everywher":[14,16],"evid":5,"evm":10,"evm2":10,"exact":[0,2,3,4,5,7,9,10,11,15,16,17,18,20,22,23,24,25],"examin":[1,3,5,9,10,11,15,16,17,20,21,22,23,25,26],"examine_expr_for_dependent_typ":11,"exampl":[0,1,2,3,5,6,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"exc_spec_in_func_typ":10,"exceed":[4,7,10],"except":[1,3,4,6,7,9,10,11,12,14,15,17,18,19,20,21,22,23,24,25],"exception_handler_us":7,"exception_spec_override_incompat":7,"exception_specif":[8,11],"exception_specification_ignor":7,"exception_specification_not_allow":7,"exception_type_specif":16,"exceptions_en":8,"exceptions_in_embedded_cplusplus":7,"excess":[7,17,23],"excess_characters_in_literal_ignor":7,"excess_initializers_ignor":7,"excess_pack_expans":7,"excessive_comparison_rewrit":7,"excessive_constexpr_complex":7,"excessive_rescan_depth":7,"exchang":23,"exclud":[2,10,11,13,23],"exclude_from_context_output":21,"exclus":[0,9],"exe":1,"exec":7,"execut":[0,1,2,6,7,8,9,10,11,14,15,16,19,22,23,24,26],"execution_arg":24,"executor":24,"exert":10,"exhaust":[0,1,8,15,21,24],"exist":[0,1,2,3,4,6,7,8,9,10,14,15,16,17,21,22,23,25],"existing_log":17,"exit":[0,3,6,8,11,14,15,16,23,24],"exit_compil":0,"exit_foral":7,"exp_asm_clobb":7,"exp_asm_label":7,"exp_asm_operand":7,"exp_asm_str":7,"exp_assign":7,"exp_attribute_nam":7,"exp_auto":7,"exp_class":7,"exp_class_or_typenam":7,"exp_class_typ":7,"exp_colon":7,"exp_comma":7,"exp_comma_or_gt":7,"exp_comma_or_rbracket":7,"exp_concept_nam":7,"exp_cpp_keyword":7,"exp_declar":7,"exp_definition_of_tag":7,"exp_digit_sequ":15,"exp_ellipsi":7,"exp_error_argu":7,"exp_except_or_fin":7,"exp_field_nam":7,"exp_file_nam":7,"exp_gt":7,"exp_gt_not_shift_right":7,"exp_header_nam":15,"exp_id_in_for_each_decl":7,"exp_identifi":7,"exp_in":7,"exp_int_const":7,"exp_interpol":7,"exp_lbrac":7,"exp_lbracket":7,"exp_line_numb":7,"exp_lparen":7,"exp_lparen_or_brac":7,"exp_lsplic":7,"exp_lt":7,"exp_macro_param":7,"exp_member_nam":7,"exp_ms_attr_arg_list":7,"exp_ms_attr_bool_valu":7,"exp_ms_attr_enum_valu":7,"exp_on_or_off":7,"exp_oper":7,"exp_pointer_to_memb":7,"exp_primary_expr":7,"exp_push_pop":7,"exp_rbrac":7,"exp_rbracket":7,"exp_rparen":7,"exp_rparen_and_pragma_ignor":7,"exp_rsplic":7,"exp_semicolon":7,"exp_stat":7,"exp_string_liter":7,"exp_system_header_nam":15,"exp_templ":7,"exp_type_nam":7,"exp_type_specifi":7,"exp_whil":7,"expand":[0,2,5,7,9,10,11,14,15,16,18,23],"expand_curr_source_lin":15,"expand_macro":[15,18],"expand_macro_buff":15,"expand_statement_inlin":16,"expand_top_level_pcc_macro":15,"expanded_text":15,"expans":[1,5,7,9,10,11,14,15,16,18,23],"expansion_contains_no_pack":7,"expect":[0,1,2,5,6,7,9,10,11,13,14,15,16,17,18,23],"expect_error":14,"expected_an_attribut":7,"expected_string_view_valu":7,"expected_template_arg":7,"expedi":1,"expens":[1,14,16,17,21,23,24,25],"expensive_check":[1,14],"experi":17,"experiment":[10,17],"expir":[7,9,11],"expired_reflection_valu":7,"expl_conversion_poss":22,"expl_narrowing_64_bit_int":7,"expl_spec_alias_templ":7,"explain":[1,3,10,18],"explan":3,"explicit":[0,1,2,5,6,7,8,9,10,11,14,15,16,18,19,20,21,22,26],"explicit_ctor_in_copy_list_init":7,"explicit_deduction_guide_in_copy_list_init":7,"explicit_enum_base_nonstandard_in_current_mod":7,"explicit_instanti":23,"explicit_instantiation_not_in_namespace_scop":7,"explicit_lambda_template_parameters_is_cpp20":7,"explicit_not_allow":7,"explicit_specialization_friend":7,"explicit_specialization_not_in_namespace_scop":7,"explicit_template_args_ignor":7,"explicit_template_args_not_allow":7,"explicit_this_is_cpp23":7,"explicit_this_needs_thi":7,"explicit_this_param_must_be_first":7,"explod":2,"exploit":[0,1,3,10],"exploratori":9,"expon":[7,10,16],"export":[0,1,7,16,21,24,25],"export_after_definit":7,"export_cannot_contain_export":7,"export_cannot_contain_import":7,"export_class_memb":7,"export_info":[10,23],"export_internal_linkag":7,"export_must_introduce_nam":7,"export_not_allow":7,"export_not_at_namespace_scop":7,"export_on_instanti":7,"export_only_in_modul":7,"export_remov":7,"exported_in_unnamed_namespac":7,"exported_instantiation_and_speci":7,"exported_template_fil":10,"expos":[14,17,21],"exposit":24,"expr":[6,7,8,9,11,14,15,16,23],"expr1":11,"expr2":11,"expr_":9,"expr_access_checking_should_be_don":9,"expr_diagnostic_should_be_issu":9,"expr_direct_init_object":6,"expr_error_should_be_issu":9,"expr_fold_constexpr_cal":9,"expr_fold_constexpr_ctor":9,"expr_ful":9,"expr_has_no_effect":7,"expr_hdr":14,"expr_init_aggr_vari":6,"expr_init_scalar_vari":6,"expr_is_rescann":9,"expr_not_a_glvalu":7,"expr_not_a_modifiable_lvalu":7,"expr_not_an_lvalu":7,"expr_not_an_lvalue_or_function_design":7,"expr_not_arithmet":7,"expr_not_arithmetic_or_enum":7,"expr_not_arithmetic_or_enum_or_point":7,"expr_not_arithmetic_or_unscoped_enum":7,"expr_not_arithmetic_or_unscoped_enum_or_point":7,"expr_not_bool":7,"expr_not_class":7,"expr_not_const":7,"expr_not_fixed_point":7,"expr_not_integr":7,"expr_not_integral_const":7,"expr_not_integral_or_enum":7,"expr_not_integral_or_enum_or_fixed_point":7,"expr_not_integral_or_fixed_point":7,"expr_not_integral_or_unscoped_enum":7,"expr_not_integral_or_unscoped_enum_or_fixed_point":7,"expr_not_object_point":7,"expr_not_point":7,"expr_not_pointer_nor_handl":7,"expr_not_pointer_or_array_handl":7,"expr_not_pointer_to_object":7,"expr_not_ptr_to_class":7,"expr_not_ptr_to_funct":7,"expr_not_ptr_to_memb":7,"expr_not_ptr_to_struct_or_union":7,"expr_not_scalar":7,"expr_not_struct_or_union":7,"expr_pos_diagnost":9,"expr_pos_error":9,"expr_pos_warn":9,"expr_range_modifiers_in_il":1,"expr_syntax_error":9,"expresison":23,"express":[0,1,2,3,4,5,7,10,13,15,17,18,20,21,23,24,25],"expression_kind":9,"exprutil":[9,11,14,22,23],"ext_vector_typ":7,"ext_vector_type_invalid_s":7,"ext_vector_type_not_in_typedef":7,"ext_vector_type_requires_bool_integral_floating_typ":7,"ext_vector_type_requires_integral_floating_typ":7,"extasm":14,"extend":[1,2,6,7,9,10,14,15,16,17,18,21,23,26],"extended_design":[7,10],"extended_designator_is_gnu_extens":7,"extended_designators_allow":10,"extended_friends_is_cpp11":7,"extended_modifier_ignored_on_enum":7,"extended_variadic_macro":10,"extens":[1,2,6,7,9,11,13,14,16,17,18,19,20,21,22],"extent":[14,17],"extern":[0,2,3,5,6,7,8,11,13,15,22,23,26],"extern_c_literal_oper":7,"extern_inlin":[7,10],"extern_inline_never_defin":7,"extern_template_follows_instanti":7,"external_name_clash":7,"externalize_statics_for_exported_templ":25,"extra":[0,1,3,6,7,9,10,11,14,15,16,17,18,21,23,24,25],"extra_arguments_ignor":7,"extra_bits_ignor":7,"extra_braces_on_simple_init":7,"extra_chars_on_numb":7,"extra_event_accessor_paramet":7,"extra_property_accessor_paramet":7,"extra_semicolon":[0,7],"extra_source_positions_in_il":[1,11,15],"extra_text_in_pp_direct":7,"extract":[7,9,11,14,15,16,21,22,26],"extract_operand_from_expression_compon":9,"extract_specific_pragma":[15,18],"extran":[7,10],"extraneous_injected_declaration_token":7,"extraneous_injected_member_token":7,"extraneous_injected_statement_token":7,"extrem":[0,6,11,14,15,16,18],"f":[0,2,3,4,5,6,8,9,10,11,14,15,16,18,21,23,24,25,26],"f1":[10,18],"f2":[10,18],"f2__tm__4_z1z__fz1z_v":23,"f3":18,"f4":18,"f__13a__tm__2_s__sfv":16,"f__1aff":16,"f__1afv":16,"f__1do1bfv":16,"f__23a__ps__6_pz1zi__tm__2_ifv_v":16,"f__ff":16,"f__s__tm__2_i__10a__tm__2_cfz1_2z_v":16,"f__tm__12_s__pk__3_id__fv_i":16,"f__tm__15_12a__l1__x__fv__fz1z_v":16,"f__tm__2_i__10a__tm__2_ifz1_2z_v":16,"f__tm__2_i__fz1z_yocl_2_4g__gi1io":16,"f__tm__2_i__s__10a__tm__2_ffz1_2z_v":16,"f__tm__4_z1z__fz1z_v":23,"f_check_cli_type_pointed_to":6,"f_check_protected_member_access":21,"f_debug":14,"f_error":14,"f_get_opnam":21,"f_get_type_qualifi":22,"f_identical_typ":22,"f_impl":3,"f_instantiate_template_class":[3,21],"f_is_generalized_identifier_start":15,"f_logical_column_offset":15,"f_mbc_length":15,"f_possibly_add_orphaned_file_scope_il_entri":11,"f_raw_list":[0,15],"f_size":17,"f_skip_typeref":14,"f_types_are_compat":[22,25],"f_update_source_sequence_list":22,"f_xref_info":21,"fabric":15,"facil":[0,1,10,14,15,16,18,23],"facilit":[3,6,10,11,14,15,17,21,24],"fact":[0,2,3,5,6,8,9,10,11,14,15,16,17,18,19,20,21,22,23,25],"facto":16,"factori":15,"fail":[0,7,9,10,11,15,16,21,23],"failed_destructor_constraint":7,"failed_tuple_container_member_get":7,"failur":[0,9,10,14,17,18],"fair":[0,2,3,4,6,9,11,15,16,17,24,25],"faith":11,"fake":2,"fall":[6,9,14,15,17,20,23],"fallthrough":7,"fallthrough_applies_to_null_stat":7,"fallthrough_must_precede_switch_cas":7,"fallthrough_not_in_switch":7,"fals":[0,1,4,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24],"famili":[10,16,18,21],"familiar":13,"fan":15,"fancier":16,"far":[0,3,9,10,11,14,15,17,18,20,21,23],"far_code_point":10,"far_data_point":10,"farther":[3,11],"fashion":[7,10,14,24],"fast":[0,11,15,21],"faster":[10,14,24],"fastest":11,"fault":14,"favor":17,"fc":24,"fe_cleanup":0,"fe_common":[10,14],"fe_init":[0,1,10,14,15,21,25],"fe_wrapup":[0,10,14,23,25],"fe_wrapup_part_2":0,"feasibl":16,"featur":[0,2,3,6,7,8,9,13,14,15,16,18,21,23,24],"feature_not_allowed_in_current_mod":7,"feature_requires_c":7,"feature_test_macro_ignor":7,"feature_test_macro_req_id":7,"fed":[2,16,24],"feedback":23,"feedgcpdisp":1,"feedgcpf":1,"feel":[11,14],"fetch":[0,3,7,9,11,15,16,18,21,23,25],"fetch_pp_token":15,"fewer":[10,11,16,18],"fghi":0,"fictiti":0,"field":[0,1,2,5,6,7,8,9,10,14,15,16,18,19,21,22,23,25],"field_cannot_be_tracking_refer":7,"field_cannot_involve_vla_typ":7,"field_init_in_class_type_with_typedef_nam":7,"field_initi":3,"field_initializer_is_not_const":7,"field_initializer_list":7,"field_initializers_is_cpp11":7,"field_lvalue_selection_expr":22,"field_name_conflicts_with_class":7,"field_rvalue_selection_expr":22,"field_subobject_not_initi":7,"field_target_on_nontrivial_property_or_ev":7,"field_type_cannot_be_qualified_with_named_address_spac":7,"field_uses_tail_pad":7,"field_with_asm_name_not_allow":7,"field_without_dll_interfac":7,"fifti":10,"figur":[10,11],"file":[2,3,4,5,6,7,9,13,15,17,18,19,25,26],"file_1":10,"file_2":10,"file_delete_error_reason":7,"file_ends_with_unterminated_type_definit":7,"file_for_module_not_found":7,"file_h":10,"file_nam":10,"file_scope_id_lookup":21,"file_scope_pointers_block":25,"file_scope_region_numb":25,"file_write_error":7,"file_write_error_errno":7,"filehead":17,"filenam":[1,10],"fill":[0,8,14,21,22,26],"filter":[1,21,26],"final":[0,1,3,6,7,8,9,10,11,15,16,17,18,20,21,22,25],"final_base_class":7,"final_managed_class":7,"final_modifier_requires_virtual_funct":7,"final_suspend_cannot_throw":7,"finalize_does_not_override_object_fin":7,"finalizer_does_not_exist":7,"finalizer_name_must_be_qualifi":7,"finalizer_qualifier_type_mismatch":7,"finalizer_requires_reference_typ":7,"finalizer_type_mismatch":7,"find":[0,1,3,6,7,8,9,11,14,15,16,17,18,20,21,22,23,24,26],"find_":25,"find_addr_of_overloaded_function_match":9,"find_assoc_pragma":18,"find_attribut":18,"find_base_class_of":22,"find_class_template_instanti":25,"find_class_template_memb":23,"find_copy_assignment_oper":9,"find_copy_constructor":9,"find_corresp_prototype_tag_sym":23,"find_corresponding_inst":23,"find_default_constructor":9,"find_direct_base_class_of":22,"find_direct_or_virtual_base_class_of":22,"find_enclosing_struct_stmt":20,"find_external_symbol":21,"find_function_template_instanti":25,"find_function_template_memb":23,"find_include_histori":15,"find_instantiation_insert_scop":22,"find_linked_symbol":[6,23],"find_matching_template_inst":23,"find_member_function_templ":23,"find_nested_class_symbol":21,"find_out_of_scope_declar":21,"find_progenitor_symbol":21,"find_projected_symbol":21,"find_symbol":[15,21],"find_synthesized_projection_symbol":21,"find_template_class":[15,23],"find_template_funct":[9,23],"find_template_vari":15,"find_trait":17,"find_type_correspond":25,"find_variable_member_templ":23,"find_vla_dimens":11,"fine":[10,14,23,24],"finer":14,"finicki":13,"finish":[0,3,6,11,14,18,21,23,25],"finish_for_init_block":20,"finish_function_body_process":[21,25],"finish_function_processing_for_memory_region":3,"finish_il_fil":0,"finish_moved_entity_process":25,"finish_processing_for_function_bodi":25,"finish_trans_unit_copi":25,"finish_variable_remapping_for_inlin":16,"finit":14,"firm":16,"first":[0,2,3,4,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25],"first_arg_must_be_integer_const":7,"first_decl_not_gnu_inlin":7,"first_inline_after_definit":7,"fit":[4,7,10,11,14,18,23],"five":[7,24,25],"fix":[0,1,3,4,6,7,10,14,15,16,17,24,25],"fix_type_list_ordering_problem":25,"fix_up_dynamic_init_dtor":9,"fixed_point":[7,10],"fixed_point_typ":22,"fixed_pt":[1,9,14,15],"fixed_register_clobb":7,"fixed_register_us":7,"fixed_sign_chang":7,"fixed_template_paramet":7,"fixed_to_fixed_convers":7,"fixed_to_float_convers":7,"fixed_to_integer_convers":7,"fixup":[6,9,11],"fixup_curr_block_labels_and_goto":20,"fixup_function_scope_source_sequence_list":22,"fixup_instantiation_scop":21,"fixup_virtual_base_class":3,"flag":[1,2,3,4,5,6,7,8,9,10,12,14,15,17,18,19,20,21,22,23,24,25,26],"flat":[5,16,18],"flatten":11,"flavor":23,"fledg":14,"flexibl":[7,10,11,16,18],"flexible_array_is_nonstandard":7,"flexible_array_member_not_allow":7,"flg":23,"fli":[9,14,23],"flip":[9,16,23],"floa":10,"float":[0,1,2,3,7,10,11,13,14,15,16,18,19,23,25,26],"float128_t":7,"float64_t":7,"float_pt":[1,9,14,15],"float_template_paramet":7,"float_to_fixed_convers":7,"float_to_float_convers":7,"float_to_integer_convers":7,"float_typ":[14,22],"flow":[0,1,4,9,10,11,14,15,16,17,20],"flush":[14,15],"flush_ref_entries_list":9,"flush_token":[0,14,15],"flush_until_matching_token":15,"fmax":10,"fmaxf":10,"fmaxl":10,"fms":10,"fmt":[10,26],"fmt_arg_does_not_exist":7,"fmt_arg_is_not_str":7,"fn":24,"fnc_hk":10,"fnc_hr":10,"fnc_k":10,"fnc_lk":10,"fnc_lr":10,"fnc_r":10,"fnc_uhk":10,"fnc_uhr":10,"fnc_uk":10,"fnc_ulk":10,"fnc_ulr":10,"fnc_ur":10,"fnm":23,"focus":24,"fold":[7,10,14,16],"fold_base_class_cast":9,"fold_derived_class_cast":9,"fold_expression_operator_mismatch":7,"fold_expressions_nonstandard":7,"fold_field_select":9,"fold_pm_base_class_cast":9,"fold_pm_derived_class_cast":9,"follow":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,26],"foo":[4,10,11,16,17,24],"foo_avx":16,"foo_corei7":16,"foo_default":16,"foodef":17,"fooproxydecl":17,"fopen":15,"fopen_interfac":15,"for_each_getenumerator_return_type_invalid":7,"for_each_incompatible_typ":7,"for_each_invalid_return_type_for_move_next":7,"for_each_iterator_declar":20,"for_each_missing_field":7,"for_each_missing_funct":7,"for_each_no_matching_overload":7,"for_each_stat":20,"for_each_static_funct":7,"for_each_undefined_identifi":7,"for_init_diff_warn":10,"for_init_hidden_declar":7,"for_init_hides_declar":7,"for_init_stat":20,"for_stat":20,"forbid":26,"forc":[0,9,10,15,16,17,23,24],"force_vtbl":[10,16],"forese":[10,17],"forev":15,"fork":[14,17],"form":[0,1,2,3,5,6,7,9,10,11,13,14,15,16,17,18,21,22,23,24,25,26],"form_address_const":0,"form_array_declar":0,"form_char":0,"form_class_or_namespace_qualifi":0,"form_const":[0,5],"form_float_kind_nam":0,"form_function_declar":0,"form_int_kind_nam":0,"form_integer_const":0,"form_nam":0,"form_pm_const":0,"form_template_arg":0,"form_typ":0,"form_type_first_part":0,"form_type_second_part":0,"form_type_specifi":0,"formal":[1,7,9,10,13,23],"format":[0,1,4,7,9,10,11,14,15,17,22,23,26],"format_output_lin":[0,10],"format_rout_not_vararg":7,"former":[0,3,6,9,10,11,17,18,22,23,25],"forscop":7,"forscope_stack_empti":7,"forth":[0,1,6,9,10,11,18,22,23],"fortran":16,"fortun":[15,23],"forward":[2,3,7,10,11,14,15,17,20],"found":[0,3,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25,26],"found_from_header_unit_map":7,"found_from_module_map":7,"foundat":7,"four":[0,1,6,9,11,18,21,23,25],"fourth":[6,18,21],"fp":[10,16,24],"fp_add":9,"fp_change_kind":9,"fp_compar":9,"fp_divid":9,"fp_hash":9,"fp_hex_string_to_float":9,"fp_hex_string_to_float_point":15,"fp_is_zero_const":9,"fp_long_to_float":9,"fp_multipli":9,"fp_string_to_float":[9,15],"fp_subtract":9,"fp_to_host_large_integ":9,"fp_to_host_large_unsign":9,"fp_to_str":[9,16],"fp_unsigned_long_to_float":9,"fragment":[0,5,7,11,24],"frame":[9,16],"framemak":26,"framework":[3,14,18],"fread":0,"free":[0,1,8,9,10,11,14,15,16,18,21],"free_init_component_list":6,"free_list_of_symbol_list_entri":21,"free_macro_arg":15,"free_memory_region":0,"free_object_lifetim":22,"free_orig_line_modif":15,"free_pending_pragma_list":18,"free_source_line_modif":15,"freed":[0,8,14,15,16,20,21],"freeli":15,"frequent":[6,10,14,21],"fresh":[1,9],"friend":[0,5,6,7,10,11,21,22,23,24],"friend_attribute_requires_definit":7,"friend_cannot_add_default_argu":7,"friend_class":3,"friend_class_template_default_arg_not_allow":7,"friend_inject":[7,10],"friend_is_nonreal_templ":7,"friend_partial_speci":7,"friend_qualification_ignor":7,"friend_routin":3,"friend_specifier_ignor":7,"friend_template_in_local_class":7,"friend_with_def_arg_must_be_definit":7,"friend_with_def_arg_must_be_only_decl":7,"friendship":[3,11],"front":[0,2,3,5,6,8,9,12,15,16,17,18,19,21,22,23,24,25,26],"frozen":16,"fs_constant":22,"fulfil":[17,21],"full":[0,2,5,7,8,9,10,11,13,14,16,26],"full_enter_symbol":21,"full_source_pos_in_il_stat":11,"full_speci":23,"fullfil":18,"fulli":[1,3,7,9,10,11,15,16,17,18,23,24],"fully_qualified_constructor_cal":7,"fully_resolved_macro_posit":[1,10,11,14,15],"func":[10,16],"func_cd":10,"func_cf":10,"func_cl":10,"func_d":10,"func_decl":17,"func_def":[3,6,14],"func_f":10,"func_info":[6,23],"func_l":10,"func_name1":3,"func_name2":3,"func_prototype_tag":10,"func_temp":16,"function":[1,5,6,7,13,17,18,19,20,22,24,25],"function_addr_expr":22,"function_declar":[3,6,8],"function_def_t":11,"function_defaulted_in_friend_decl":7,"function_definit":[3,6],"function_does_not_match_argu":7,"function_inelig":7,"function_lvalue_expr":22,"function_modifier_requires_virtual_funct":7,"function_modifiers_abstract_and_s":7,"function_nam":16,"function_prototype_instanti":[3,23],"function_qualifier_on_ctor_or_dtor":7,"function_qualifier_on_fin":7,"function_qualifier_on_new_or_delet":7,"function_qualifier_on_nonmemb":7,"function_qualifier_on_static_memb":7,"function_returning_abstract_class":7,"function_returning_array":7,"function_returning_funct":7,"function_returning_named_address_spac":7,"function_returning_shar":7,"function_rvalue_nod":22,"function_template_call_argument_deduct":9,"function_template_cannot_be_default":7,"function_template_declar":23,"function_template_named_main":7,"function_typ":16,"function_type_must_come_from_declar":7,"function_type_not_allow":7,"function_type_requir":7,"functionmultivers":16,"functiontraitsbitfield":17,"functor":7,"fundament":[1,3,6,9,10,11,14,15,17,21,22,23,24],"fundamental_type_from_system_typ":[6,22],"funni":11,"furthermor":[3,6,11,15,18,21,23],"futur":[7,10,17],"fuzzi":9,"fwrite":0,"fxp_add":9,"fxp_compar":9,"fxp_divid":9,"fxp_hash":9,"fxp_hex_string_to_fixed_point":[9,15],"fxp_init_valu":9,"fxp_multipli":9,"fxp_string_to_fixed_point":[9,15],"fxp_subtract":9,"fxp_to_str":9,"fxp_value_is_zero":9,"g":[0,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],"g1":[10,16,21],"g2":[16,21],"g3":16,"g__1asff":16,"gain":0,"gap":[3,11,14],"garbag":[9,11],"gate":17,"gather":3,"gc":[9,16],"gc_":16,"gcc":[0,1,2,7,10,14,15,16,18,24],"gcc89_inlin":10,"gcc_is_generated_code_target":1,"gcc_lvalue_cast_ignor":7,"gcc_minor_vers":10,"gcc_mode":14,"gcc_pragma_nothing_to_pop":7,"gcc_use_of_cast_as_lvalu":7,"gcc_version":10,"gcc_version_i":14,"gcc_version_str":10,"gcnew":[7,9,10,11,16],"gcnew_and_abstract":7,"gcnew_and_no_ctor":7,"gcnew_and_no_gcnew":7,"gcnew_bad_type_used_with_array_init":7,"gcnew_of_native_array":7,"gcnew_used_with_auto_syntax":7,"gcnew_used_with_placement_syntax":7,"gdb":24,"gear":1,"gen_attribut":18,"gen_block_stat":5,"gen_bound_funct":5,"gen_c_clang_vers":10,"gen_c_file_nam":10,"gen_c_gnu_vers":10,"gen_c_msvc_vers":10,"gen_class_definit":5,"gen_class_qualifi":5,"gen_cleanup_act":16,"gen_const":5,"gen_decl_nam":5,"gen_declar":5,"gen_declaration_using_typ":5,"gen_dynamic_init":5,"gen_enum_definit":5,"gen_expanded_raw_listing_output_for_curr_lin":15,"gen_expr":5,"gen_field_decl":5,"gen_for_stat":5,"gen_initi":5,"gen_initializer_const":5,"gen_instantiation_direct":5,"gen_macro":5,"gen_member_constant_decl":5,"gen_move_oper":10,"gen_nam":5,"gen_namespac":5,"gen_namespace_qualifi":5,"gen_new_delet":5,"gen_pp_line_info":15,"gen_pp_output_for_curr_lin":15,"gen_prop_event_or_op_synth_cal":5,"gen_raw_listing_output_for_curr_lin":15,"gen_rlisting_line_info":15,"gen_routine_decl":5,"gen_secondary_decl":5,"gen_simple_field_select":5,"gen_stat":5,"gen_switch_stat":5,"gen_temp_init":5,"gen_templ":5,"gen_try_block_stat":5,"gen_typ":5,"gen_type_decl":5,"gen_typedef_decl":5,"gen_unqualified_nam":5,"gen_using_declar":5,"gen_using_directive_or_declar":5,"gen_variable_decl":5,"general":[0,1,2,5,6,9,10,12,13,14,16,17,18,19,20,21,22,23,24,25,26],"generat":[1,6,7,9,11,13,14,15,16,17,18,19,20,21,22,24,25,26],"generate_eh_t":[8,16,19],"generate_portable_assembl":1,"generate_pp_output":15,"generate_precompiled_head":0,"generate_source_sequence_list":[5,11,21],"generate_source_source_sequence_list":22,"generate_special_funct":3,"generate_top_level_metadata_cod":6,"generate_trivial_accessor":3,"generated_default_constructor_used_in_field_initi":7,"generated_default_ctor_exception_spec_circular":7,"generated_exception_spec_override_incompat":7,"generated_preced":11,"generic":[0,1,3,6,7,10,11,14,18,21,22,24],"generic_cast_operand":9,"generic_class_cannot_be_custom_attribut":7,"generic_class_must_be_manag":7,"generic_in_templ":7,"generic_lambda_cannot_captur":7,"generic_param_cannot_have_default":7,"generic_param_if_generic_definition_argu":23,"generic_parameter_does_not_permit_vararg":7,"generic_parameter_requires_clrcal":7,"generic_selection_with_points_to":7,"generic_type_in_template_arg":7,"get":[0,1,3,5,7,9,10,11,14,16,17,19,21,23,24,25,26],"get_based_typ":22,"get_byt":17,"get_current_lambda":3,"get_definition_of_class":[6,15,21],"get_ifc_":17,"get_ifc_decl":17,"get_ifc_declar":17,"get_ifc_home_scop":17,"get_ifc_index":17,"get_ifc_local_index":17,"get_ifc_nam":17,"get_ifc_unit":17,"get_integer_size_and_align":9,"get_mangled_function_nam":23,"get_mangled_variable_nam":23,"get_modul":17,"get_module_head":17,"get_next_source_fil":0,"get_nondependent_call_info":9,"get_opnam":21,"get_pointer_offset":9,"get_property_function_miss":7,"get_property_or_event_accessor_symbol_head":[3,21],"get_return_object_on_allocation_failur":7,"get_storag":17,"get_token":[0,10,14,15,21],"get_token_from_cached_token_rescan_stack":15,"get_token_from_reusable_cache_stack":15,"get_top_level_type_qualifi":22,"get_type_qualifi":22,"get_var_remapping_for_inlin":16,"get_variable_initi":11,"getenumer":7,"gid":15,"gid_template_args_opt":15,"give":[0,1,3,4,5,9,10,11,13,14,15,16,17,21,24,25],"given":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"glanc":9,"glb_mod_fgmt_decl_must_come_first":7,"global":[0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,18,21,22,23,25,26],"global_module_source_conflict":7,"global_ns_has_no_actual_memb":7,"global_operator_new_or_delete_symbol":21,"global_qualifier_not_allow":7,"glvalu":[9,11],"gnu":[0,1,3,7,11,13,14,18,20,21,26],"gnu_":3,"gnu_attr_on_template_redecl":7,"gnu_attr_on_template_redecl_but_original_kept":7,"gnu_attributes_en":18,"gnu_auto_type_with_secondary_declar":7,"gnu_auto_type_without_initi":7,"gnu_extensions_allow":[1,10,14],"gnu_extra_info":11,"gnu_function_multivers":11,"gnu_inlin":7,"gnu_inline_requires_inlin":7,"gnu_may_use_bit_pad":7,"gnu_mv_default_miss":7,"gnu_mv_only_one_arch":7,"gnu_restrict_is_nonstandard":7,"gnu_sentinel_attribute_requires_ellipsi":7,"gnu_sentinel_must_be_ellipsis_argu":7,"gnu_target_version_numb":1,"gnu_vers":[10,11,16,18,24],"gnu_version_i":14,"gnu_virtual_base_gap":7,"gnu_visibility_conflict":7,"go":[0,1,3,7,10,11,14,15,16,17,18,20,23,25],"go_into_insert":15,"goal":[0,9,10,13,14,15],"goe":[0,2,3,6,8,9,10,11,14,15,16,17,21,23],"gone":[6,15],"good":[1,3,7,8,9,10,14,24],"got":7,"goto":[7,8,11,14,16,20],"goto_stat":20,"gotten":10,"govern":[18,22],"gpp":0,"gpp_mode":14,"gpp_version_i":14,"grain":[10,14,24],"grammar":18,"grammat":3,"grant":11,"graph":[0,3,16],"graphic":10,"great":[11,14,21,23,24],"greater":[3,7,8,9,11,14,15,16,21],"greatest":[3,10,21],"grief":16,"gross":21,"group":[2,3,6,9,10,11,13,14,15,18,23,24],"grow":20,"gs_directory_of":0,"guarante":[2,10,11,15,16,17],"guard":[10,22],"guard_var":16,"guess":[0,14],"gui":10,"guid":[7,9,10,11,16,17,23],"guidanc":[10,18],"guidelin":9,"guiding_decl":[7,10],"guilti":4,"gx":18,"h":[0,2,3,4,5,6,8,9,10,11,12,14,15,16,17,18,20,21,22,23,24,25,26],"half":[10,11,22],"hall":10,"halt":[14,23],"hand":[0,3,7,9,11,14,15,16,18,21,23,25],"handl":[0,1,2,3,4,5,6,7,9,10,11,14,15,16,17,18,19,20,21,22,23,25],"handle_elided_copy_constructor":9,"handle_lvalue_constant_nod":5,"handle_member_in_standard_class":7,"handle_of_non_manag":7,"handle_operand":7,"handle_to_address_typ":7,"handle_to_array":7,"handle_to_cli_array_operand":7,"handle_to_enum":7,"handle_to_funct":7,"handle_to_standard_class_typ":7,"handle_to_unscoped_enum_typ":7,"handle_to_value_class":7,"handle_to_void":7,"handle_virtual_bases_in_complete_ctor_dtor":16,"handler":[1,7,10,11,16,20,21,22],"handler_declar":8,"handler_redeclares_paramet":7,"hang":[3,9],"happen":[0,3,6,9,10,16,21,23,24,25],"hard":[9,10,11,14,16],"harder":[11,16,21],"hardwar":9,"harmless":15,"has_assoc_vla_dimens":11,"has_associated_attribut":11,"has_associated_pragma":[11,18],"has_been_coalesc":15,"has_cpp_attrib_not_in_if":7,"has_embed_not_in_if":7,"has_ifc_":17,"has_ifc_decl":17,"has_ifc_home_scop":17,"has_include_next_in_primary_source_fil":7,"has_include_not_in_if":7,"has_matching_template_funct":23,"has_named_register_storage_class":11,"has_valu":17,"hash":[9,21,22,23],"hash_const":22,"hasn":[3,14,16],"have_access_across_path":21,"have_access_to_symbol":[3,21],"have_member_access_privileg":21,"have_proj_access_to_symbol":3,"have_protected_member_access_privileg":21,"haven":16,"hazi":2,"hdrstop":[0,10],"head":[0,11,21,22],"headach":5,"header":[1,2,3,4,6,7,9,13,14,15,16,20,22,23,24,25,26],"header_not_import":7,"header_path":10,"header_unit":[10,24],"header_unit_fil":24,"header_util":14,"heap":[7,9,11],"heavili":[14,23],"held":[0,9,11,17],"hello":10,"help":[0,2,6,9,11,14,15,16,19,22,23,24,25,26],"helper":[0,1,3,7,10,16],"henc":[3,10,16,23,25],"hereaft":[10,23],"heurist":[3,10,16],"hewlett":19,"hex":7,"hex_fp_const":7,"hexadecim":[7,10,15],"hh":[10,16],"hi":16,"hidden":[0,5,7,9,11,16,21,22,24],"hidden_anonymous_union_field":7,"hidden_by_old_for_init":7,"hide":[7,9,10,16],"hide_by_sig_lookup_result":21,"hiding_attr_on_nonhiding_memb":7,"hiding_attr_on_unhidden_memb":7,"hiding_attr_requir":7,"hierarchi":[15,17,21],"high":[1,8,9,10,11,13,14,16,17,18],"higher":[9,10,11,14,16,17,23],"highest":[10,15],"highlight":[0,10,16,24],"hint":[9,14,16,23],"histor":[14,16],"histori":[0,1],"hit":[16,23],"hoc":[10,14],"hold":[0,1,4,9,11,15,16,23],"holder":22,"home":17,"home_scop":17,"home_scope_idx":17,"honor":11,"hop":[9,16],"horizont":[10,15],"host":[1,7,9,10,11,13,14,15,17],"host_allocation_incr":10,"host_envir":[0,11,14,23],"host_util":14,"hour":1,"howev":[0,1,2,3,4,5,6,8,9,10,11,13,14,15,16,17,18,21,22,23,24,25,26],"hp":16,"hpp":10,"hpux":26,"ht":16,"html":16,"http":16,"human":[0,1,2,10,13,14],"hundr":2,"hybrid":15,"hyphen":10,"hypothet":17,"i1":10,"i2":10,"i__1a":16,"ia":[1,3,10,12,19,26],"ia64":2,"ia64_abi":[1,16,19],"ia64_abi_use_guard_acquire_releas":16,"ia64_abi_use_variant_ptr_to_member_function_repr":16,"ic1_2i":16,"ick_continu":9,"id":[6,7,8,10,11,15,16,18,21,23],"id_already_declar":7,"id_can_only_appear_in_funct":7,"id_linkag":[6,23],"id_must_be_class_or_namespace_nam":7,"id_must_be_class_or_type_nam":7,"idea":[9,11,14,16],"ideal":[3,8],"ident":[0,1,3,5,7,8,9,10,11,15,16,17,22,23],"ident_directive_and_pragma":10,"identical_typ":22,"identif":[8,15],"identifi":[0,1,2,3,5,6,7,8,10,11,14,16,18,20,23,24,25,26],"identifier_not_keyword":7,"identifier_rang":11,"identifier_strings_allow_multibyte_char":[11,15],"identify_dir_keyword":15,"identify_source_fil":0,"idiom":[10,15,20],"idispos":[3,7],"idl":15,"idl_instantiation_context":21,"idl_is_static_decl":3,"idl_linkage_lookup":21,"idl_projection_symbol_allow":21,"idl_skip_class_scop":21,"idl_skip_curr_function_scop":21,"idl_tentative_type_lookup":21,"idn":23,"idx":17,"iec":[1,9,10,11,13],"iek_":11,"if_consteval_in_nonconstexpr_funct":7,"if_consteval_nonstandard":7,"if_consteval_requires_braced_dependent_stat":7,"if_constexpr_is_cpp17":7,"if_exists_not_allow":7,"if_exists_not_clos":7,"if_stat":20,"ifc":[7,10,14,17,24],"ifc_0_33_bsb_c":17,"ifc_0_33_bsb_cxx":17,"ifc_0_33_bsb_deprec":17,"ifc_0_33_bsb_extern":17,"ifc_0_33_bsb_initialized_in_class":17,"ifc_0_33_bsb_intern":17,"ifc_0_33_bsb_is_member_of_global_modul":17,"ifc_0_33_bsb_non_export":17,"ifc_0_33_bsb_vagu":17,"ifc_0_33_ds_decl_bitfield":17,"ifc_0_33_ds_decl_enumer":17,"ifc_0_33_ds_decl_field":17,"ifc_0_33_ds_decl_paramet":17,"ifc_0_33_ds_decl_scop":17,"ifc_0_33_ds_decl_vari":17,"ifc_0_33_ds_decl_vendor_extens":17,"ifc_0_41_ds_decl_bitfield":17,"ifc_0_41_ds_decl_enumer":17,"ifc_0_41_ds_decl_field":17,"ifc_0_41_ds_decl_paramet":17,"ifc_0_41_ds_decl_scop":17,"ifc_0_41_ds_decl_vari":17,"ifc_0_41_ds_decl_vendor_extens":17,"ifc_as_non":17,"ifc_as_priv":17,"ifc_as_protect":17,"ifc_as_publ":17,"ifc_bad_function_param_nam":7,"ifc_bad_identifi":7,"ifc_bsb_0_33_c":17,"ifc_bsb_0_33_cxx":17,"ifc_bsb_c":17,"ifc_bsb_cxx":17,"ifc_bsb_deprec":17,"ifc_bsb_extern":17,"ifc_bsb_initialized_in_class":17,"ifc_bsb_intern":17,"ifc_bsb_is_member_of_global_modul":17,"ifc_bsb_non_export":17,"ifc_bsb_vagu":17,"ifc_creation_failur":7,"ifc_definition_load_failur":7,"ifc_ds_":17,"ifc_ds_decl_alia":17,"ifc_ds_decl_barren":17,"ifc_ds_decl_bitfield":17,"ifc_ds_decl_concept":17,"ifc_ds_decl_constructor":17,"ifc_ds_decl_deduction_guid":17,"ifc_ds_decl_destructor":17,"ifc_ds_decl_enumer":17,"ifc_ds_decl_expans":17,"ifc_ds_decl_explicit_instanti":17,"ifc_ds_decl_explicit_speci":17,"ifc_ds_decl_field":17,"ifc_ds_decl_funct":17,"ifc_ds_decl_refer":17,"ifc_ds_decl_speci":17,"ifc_ds_decl_vari":17,"ifc_ds_decl_vendor_extens":17,"ifc_entity_ref_failur":7,"ifc_entity_ref_failure_info":7,"ifc_file_incompat":7,"ifc_ftb_constexpr":17,"ifc_ftb_constrain":17,"ifc_ftb_default":17,"ifc_ftb_delet":17,"ifc_ftb_explicit":17,"ifc_ftb_hidden_friend":17,"ifc_ftb_immedi":17,"ifc_ftb_inlin":17,"ifc_ftb_no_return":17,"ifc_ftb_non":17,"ifc_ftb_pure_virtu":17,"ifc_ftb_virtu":17,"ifc_function_template_parse_failur":7,"ifc_initializer_load_failur":7,"ifc_line_number_overflow":7,"ifc_map":[14,17],"ifc_map_funct":[14,17],"ifc_map_functions_acc":[14,17],"ifc_map_functions_dbg":[14,17],"ifc_map_functions_mut":14,"ifc_map_functions_v":[14,17],"ifc_missing_function_definit":7,"ifc_modul":[14,17],"ifc_modules_inst":[14,17],"ifc_modules_intern":[14,17],"ifc_modules_read":[14,17],"ifc_modules_spec":[14,17],"ifc_modules_templ":[14,17],"ifc_modules_writ":[14,17],"ifc_no_corresponding_calling_conv":7,"ifc_no_corresponding_oper":7,"ifc_partition_bad_entry_s":7,"ifc_partition_count":17,"ifc_partition_map":17,"ifc_partition_mismatch":7,"ifc_partition_missing_el":7,"ifc_pk_non":17,"ifc_requirement_failur":7,"ifc_requirement_failure_fill_in":7,"ifc_too_few_template_arg":7,"ifc_too_few_template_args_info":7,"ifc_too_many_template_arg":7,"ifc_too_many_template_args_info":7,"ifc_unexpected_null_scope_memb":7,"ifc_unsupported_token":7,"ifcconditionaldeleg":17,"ifcdirectdeleg":17,"ifcremotedeleg":17,"ifcreusableresult":17,"ifctestsortmatch":17,"ifctextoffsettonameindex":17,"ifdef":[4,15],"iff":16,"ifil":10,"ifn":23,"ifndef":[10,14,15],"ifunc":7,"ifunc_cant_be_alia":7,"ifunc_cant_be_weak":7,"ignor":[3,5,7,8,9,10,11,15,16,17,18,21,22,23,26],"ignore_harmless_trailing_com":15,"ignore_std":[7,10],"ignoring_attribute_on_anonymous_namespac":7,"ignoring_attribute_on_non_inline_namespac":7,"ii":[10,23],"ii_fil":10,"ik_long_long":[11,16],"ik_unsigned_long_long":[11,16],"il":[2,3,5,7,8,9,13,14,15,18,19,20,22,24,25],"il_alloc":[11,14,18,22],"il_alloc_init":11,"il_alloc_one_time_init":11,"il_def":[0,3,8,11,14,15,18,22,23],"il_display":[0,1,10,11,14],"il_entry_kind_nam":11,"il_entry_prefix_of":11,"il_fil":[0,14],"il_head":[0,2,11,15,16,22],"il_identical_typ":22,"il_low":25,"il_output":7,"il_read":[0,1,14],"il_scop":21,"il_should_be_written_to_fil":1,"il_to_str":[0,1,2,5,14],"il_walk":[0,1,11,14],"il_walk_flag":[0,16],"il_writ":[0,14],"ill":[3,26],"illeg":[3,10],"illustr":[0,3,10,24],"ilm_tentative_typ":15,"ilp64_will_narrow":7,"im":16,"imag":0,"imagin":0,"imaginari":[7,9,11,16],"imaginary_times_assign":7,"immedi":[0,1,3,4,5,6,7,9,10,11,15,16,18,21,23,24],"immut":15,"impact":[8,24],"imper":1,"impl_conv_between_c_and_cpp_function_ptrs_poss":10,"impl_conversion_poss":[9,22],"impl_converted_constant_expr_conversion_poss":9,"impl_deleted_move_candidate_ignor":7,"impl_handle_convers":22,"impl_narrowing_64_bit_int":7,"impl_pointer_convers":22,"impl_ptr_to_member_convers":22,"implement":[0,1,2,3,5,6,7,9,11,12,13,14,15,16,18,19,21,24,25,26],"implement_dispose_pattern_if_need":3,"implementation_key":7,"implementation_key_outside_mapping_region":7,"implementation_supports_multiple_thread":10,"implementor":26,"implements_must_precede_virtual_funct":7,"implements_requires_interfac":7,"impli":[3,7,9,10,11,14,16,18,22,23,24],"implic":11,"implicit":[0,2,5,6,7,9,11,14,15,16,20,21,22],"implicit_address_of_explicit_this_funct":7,"implicit_call_of_ambiguous_nam":7,"implicit_cast":[9,11],"implicit_co_return_with_no_return_void":7,"implicit_copy_this_capture_deprec":7,"implicit_el":7,"implicit_extern_c_type_convers":[7,10],"implicit_fixed_point_to_floating_point_convers":7,"implicit_func_decl":7,"implicit_includ":[7,10],"implicit_int_on_main":7,"implicit_noexcept":[7,10],"implicit_return_from_non_void_funct":7,"implicit_this_param_typ":3,"implicit_typenam":10,"implicit_using_std":10,"import":[0,1,3,5,6,7,8,9,10,11,14,17,20,24,25],"import_dir":10,"import_metadata":6,"import_metadata_fil":6,"import_name_not_allow":7,"import_skip":7,"impos":[3,9,15,16,17],"imposs":[10,16,18,21,23],"impract":16,"improp":[7,15,17],"improperly_terminated_macro_cal":7,"improv":[0,2,3,10,11,14,16,17,24,26],"in_potential_constant_constexpr_context":9,"in_pp_if_express":15,"in_preprocessing_direct":15,"in_range_for_integer_kind":9,"inaccess":[0,3,7,9,10,21],"inaccessible_base_class":7,"inaccessible_dtor_not_invok":7,"inaccessible_elided_cctor":7,"inaccessible_elided_dtor":7,"inaccessible_rvalue_dtor":7,"inaccessible_special_funct":7,"inacess":21,"inact":[6,7,25],"inactive_scope_lookup":21,"inadvis":1,"inappropri":18,"incident":23,"incl_dir_both_sys_and_nonsi":7,"incl_suffix":10,"inclass_initializer_fixup":3,"inclass_initializer_fixup_for_class":3,"inclin":16,"includ":[0,1,2,3,4,5,6,7,8,9,11,13,15,16,17,18,19,20,21,22,23,24,25,26],"include_alia":[7,10],"include_c":24,"include_c99":24,"include_comments_in_asm_func_bodi":[10,11],"include_directori":10,"include_in_context_output":0,"include_kind_mismatch":7,"include_next":[7,10],"include_next_in_primary_source_fil":7,"include_recurs":7,"include_unrecognized_pragmas_in_il":18,"include_whitespac":4,"inclus":[0,1,4,7,11,14,15,17],"incognito":10,"incom":16,"incompat":[0,2,7,10,19,25],"incompatible_assignment_operand":7,"incompatible_builtin_complex_typ":7,"incompatible_delegate_object":7,"incompatible_enum_base_typ":7,"incompatible_enum_kind":7,"incompatible_exception_spec":7,"incompatible_exception_specif":7,"incompatible_ifunc_resolver_typ":7,"incompatible_inline_specifier_on_specific_decl":7,"incompatible_linkage_specifi":7,"incompatible_operand":7,"incompatible_param":7,"incompatible_ptr_to_member_selection_operand":7,"incompatible_shuffle_mask":7,"incompatible_shuffle_source_operand":7,"incompatible_std_meta_value_of_typ":7,"incompatible_thread_loc":7,"incompatible_vectors_convers":7,"incomplet":[2,3,7,8,9,10,11,15,21,23],"incomplete_class_return_typ":7,"incomplete_class_typ":7,"incomplete_enum_bit_field_or_bad_opaque_enum":7,"incomplete_function_return_typ":7,"incomplete_return_typ":7,"incomplete_type_not_allow":7,"incomplete_var_typ":7,"incongru":23,"inconsist":[3,7,11,23],"inconsistent_align":7,"inconsistent_deduction_of_auto":7,"inconsistent_std_string_view":7,"inconsistent_tls_model_attr_arg":7,"incorpor":[1,6,14,16,21,23,24],"incorrect":[7,10,11,14,15,16],"incorrect_masked_typ":7,"incr":10,"incr_of_bool_deprec":7,"incr_of_bool_not_allow":7,"increas":[1,3,10,15],"increment":[6,7,9,10,11,14,15,16,20,23],"increment_field_offset":3,"incur":[10,15,16],"inde":[0,14],"indefinit":9,"indent":[2,4,5],"independ":[3,6,9,10,11,17,18,19,21,23],"indetermin":[7,10],"indeterminate_not_on_first_decl":7,"indeterminate_overloaded_funct":7,"index":[0,3,6,7,8,9,11,13,14,15,16,18,19,21],"indic":[0,1,2,3,6,7,8,9,10,11,14,15,16,18,19,20,21,22,23,24,25,26],"indicate_cleanup_state_in_unreachable_cod":16,"indirect":[3,5,6,7,8,10,11,14,15,16,17,21,22,23],"indirect_anon_union_design":7,"indirect_nonvirtual_base_class_not_allow":7,"indistinguish":16,"individu":[0,7,11,14,15,16,17,20,21,23,24],"industri":16,"ineffici":14,"inelig":7,"ineligible_default_constructor":7,"ineligible_member_funct":7,"inequ":10,"inert":15,"inexact_fixed_convers":7,"inexact_fp_convers":7,"inexact_fxp_convers":7,"inexpens":1,"infer":[11,15],"infin":10,"infinit":[23,24,25],"influenc":23,"info":[6,7,9,10,23],"infom":23,"inform":[0,1,2,3,5,6,7,8,10,13,14,15,17,18,20,21,24,25,26],"infrastructur":9,"infrequ":0,"ing":24,"inher":[9,14,17],"inherit":[3,7,10,11,16,21],"inheritance_kind_already_set":7,"inheritance_kind_ignored_on_enum":7,"inherited_member_not_allow":7,"inheriting_constructor_is_cpp11":7,"inheriting_ctor_ignored_for_copi":7,"inheriting_ctor_not_from_direct_bas":7,"inhibit":[6,10],"init":[3,7,9,10,16,20,22],"init_auto_instantiation_inform":23,"init_byte_buff":17,"init_cli_symbol":0,"init_conditional_flag_var":16,"init_decl_parse_st":6,"init_kind":11,"init_list_element_type_not_complete_object":7,"init_memory_region":0,"init_needing_temp_not_allow":7,"init_prior":7,"init_priority_reserv":7,"init_stmt_in_range_for_nonstandard":7,"init_text_map_position_track":15,"init_v":3,"initi":[1,2,5,7,10,14,15,17,18,19,20,21,22,24,26],"initialization_not_reach":7,"initializer_addresses_dllimport_vari":7,"initializer_differs_in_other_trans_unit":7,"initializer_in_param":7,"initializer_list":[7,9,12],"initializer_list_not_includ":7,"initializer_not_allowed_on_array_new":7,"initializer_not_const":7,"initializers_incompat":7,"initk_bind":[6,11],"initk_dynam":11,"initk_function_loc":11,"initk_stat":11,"initk_zero":[2,11],"initon":[3,7],"initonly_const_has_no_effect":7,"initonly_requires_managed_class":7,"initonly_static_data_member_not_initi":7,"initonly_volatile_not_allow":7,"inject":[3,7,10,21],"inlin":[0,1,2,4,6,7,11,14,17,21,25],"inline_and_nonfunct":7,"inline_function_cannot_be_instanti":7,"inline_function_wrapup":23,"inline_gnu_noinline_conflict":7,"inline_main":7,"inline_never_defin":7,"inline_new_or_delete_oper":7,"inline_nonstatic_data_mem":7,"inline_not_allow":7,"inline_on_alia":7,"inline_on_nested_namespac":7,"inline_qualifier_ignor":7,"inline_statement_limit":10,"inline_variables_nonstandard":7,"inner":[3,11,14,15,17,20,21,23],"innermost":[0,3,6,7,10,11,16,17,20,21,22],"innocu":10,"input":[1,3,5,6,7,9,11,14,16,17,23,25,26],"input_stack":[0,15],"ins":[0,14,26],"insert":[0,2,6,10,11,21,22,23,26],"insert_expr":16,"insert_if_stat":16,"insert_in_virtual_function_override_list":3,"insert_instantiation_src_seq_list":[21,22],"insert_src_seq_list":22,"insert_stat":16,"insert_string_into_token_stream":15,"insid":[0,2,3,6,7,9,10,11,14,15,16,20,21,22,23],"inspect":10,"instal":[1,10],"instanc":[1,3,4,6,7,9,10,11,15,16,17,20,21,22,23,24,25],"instance_requir":[16,23],"instance_sym":23,"instanti":[0,1,2,3,5,6,7,9,11,14,15,17,18,22,26],"instantiat":[23,25],"instantiate_class_templ":[3,23],"instantiate_ent":23,"instantiate_extern_inlin":[16,23],"instantiate_field_initializer_if_need":3,"instantiate_pragma":18,"instantiate_template_alia":23,"instantiate_template_class":23,"instantiate_template_funct":23,"instantiate_template_vari":23,"instantiation_by_implicit_inclus":10,"instantiation_context_lookup":21,"instantiation_dir":10,"instantiation_flags_in_template_info_fil":[16,23],"instantiation_mod":23,"instantiation_needed_bit_numb":[0,2],"instantiation_requested_and_speci":7,"instantiation_requested_no_definition_suppli":7,"instantiation_requir":23,"instantiation_wrapup":23,"instantiations_requir":23,"instantiations_to_process":25,"instead":[0,1,2,3,4,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"instruct":[15,16,17],"insuffici":[3,4,7,11],"insufficient_address_spac":7,"insufficient_enum_rang":7,"int":[0,2,3,4,5,6,7,8,9,10,11,14,15,16,18,21,22,23,24,26],"int16":7,"int32":[6,7,11,22],"int64":7,"int8":7,"int_constant_is_sign":9,"int_kind_is_sign":22,"int_max":1,"integ":[0,1,3,6,7,10,11,13,14,15,16,17,19,22,24],"integer_may_not_fit_in_fixed_point_result":7,"integer_overflow":7,"integer_overflow_class_intern":7,"integer_overflow_intern":7,"integer_pack_element_for_templ":7,"integer_pack_element_for_typ":7,"integer_sign_chang":7,"integer_to_fixed_convers":7,"integer_to_float_convers":7,"integer_too_larg":7,"integer_trunc":7,"integer_typ":22,"integer_type_supp":11,"integer_valu":9,"integer_value_repr_is_a_host_integ":[9,11],"integr":[1,2,3,7,9,10,11,13,16,22],"integral_operand":7,"intel":[3,16],"intend":[0,1,2,5,7,8,9,10,11,13,14,15,16,18,23,24,26],"intens":24,"intent":17,"inter":[15,18],"interact":[11,14,16,17,18],"intercept":[9,25],"interchang":[6,10,22],"interchangeable_typ":22,"interconnect":25,"interest":[3,4,9,10,11,14,15,16,17,20,21,22,24],"interfac":[0,1,3,6,7,8,9,11,13,14,15,16,18,19,21,22,24,26],"interface_cannot_be_loc":7,"interface_cannot_be_nested_class":7,"interface_cannot_have_ctor_or_dtor":7,"interface_cannot_have_data_memb":7,"interface_cannot_have_friend":7,"interface_cannot_have_member_gener":7,"interface_cannot_have_member_templ":7,"interface_cannot_have_oper":7,"interface_cannot_have_private_or_protect":7,"interface_cannot_have_static_memb":7,"interface_cannot_have_typedef":7,"interface_cannot_have_virtual_bas":7,"interface_must_derive_from_interfac":7,"interface_nonstatic_data_memb":7,"interface_not_impl":7,"interior":[6,7],"interior_ptr":[0,6,7,9,11,16],"intermedi":[1,2,3,5,6,7,9,10,13,14,15,16,17,20,21,22],"intermediari":[17,21],"intermingl":3,"intermix":[11,15,16,26],"internal":[0,1,3,6,7,8,9,10,11,13,15,16,17,23,24,25,26],"internal_error":[0,14],"internal_linkag":7,"internal_linkage_not_on_prior_declar":7,"internat":15,"interpol":7,"interpolated_id_is_not_identifi":7,"interpolated_operand_is_not_token_sequ":7,"interpret":[3,7,8,9,10,11,14,15,17],"interpret_constexpr_cal":9,"interpret_constexpr_ctor":9,"interpret_dynamic_init":9,"interpret_expr":9,"interpreter_message_error":7,"interpreter_message_remark":7,"interpreter_message_warn":7,"interrupt":10,"intersect":9,"interven":[11,15,21],"intervent":[10,18],"intimid":17,"intra":15,"intricaci":17,"intrins":[7,16],"intrinsic_name_releas":7,"intrinsic_requires_template_inst":7,"introduc":[3,4,6,7,9,10,11,15,16,17,18,23,25,26],"introduct":[1,3,8],"introductori":11,"invalid":[6,7,9,10,11,14,15,17,23,26],"invalid_access_specifi":7,"invalid_alignment_reducing_attr":7,"invalid_argument_to_attribut":7,"invalid_asm_qualifi":7,"invalid_assignment_operator_to_be_default":7,"invalid_attribute_loc":7,"invalid_attribute_target_for_ms_attr":7,"invalid_attribute_target_for_standalone_ms_attr":7,"invalid_base_for_ms_attribut":7,"invalid_bit_cast_typ":7,"invalid_builtin_fpclassify_arg":7,"invalid_case_rang":7,"invalid_char":7,"invalid_char_in_unicode_nam":7,"invalid_cleanup_routin":7,"invalid_co_return":7,"invalid_concept_id":7,"invalid_concept_redecl":7,"invalid_constev":7,"invalid_constexpr":7,"invalid_constexpr_bodi":7,"invalid_constexpr_memcmp":7,"invalid_constinit":7,"invalid_constraint":7,"invalid_constructor_to_be_default":7,"invalid_declar":7,"invalid_default_arg":7,"invalid_delegate_typ":7,"invalid_designator_kind":7,"invalid_destructor_nam":7,"invalid_empty_attribute_arg_list":7,"invalid_empty_fold_express":7,"invalid_empty_initializer_list":7,"invalid_entity_for_pending_constraint":7,"invalid_enumerator_valu":7,"invalid_error_numb":7,"invalid_error_tag":7,"invalid_event_accessor_decl":7,"invalid_event_handler_typ":7,"invalid_event_typ":7,"invalid_event_us":7,"invalid_explicit_exception_specif":7,"invalid_finalizer_nam":7,"invalid_float_parameter_for_literal_oper":7,"invalid_fold_expression_oper":7,"invalid_function_to_be_default":7,"invalid_gcnew_typ":7,"invalid_generic_arg":7,"invalid_generic_speci":7,"invalid_gnu_sentinel_argu":7,"invalid_gnu_sync_s":7,"invalid_identifier_start_ucn":7,"invalid_identifier_ucn":7,"invalid_idisposable_dispos":7,"invalid_ifc_partit":7,"invalid_ifc_position_backtrace_field":7,"invalid_ifc_position_backtrace_po":7,"invalid_ifc_sort_valu":7,"invalid_inheritance_kind_for_class":7,"invalid_init_stat":7,"invalid_instantiation_argu":7,"invalid_intaddr_address":7,"invalid_integer_parameter_for_literal_oper":7,"invalid_interface_class_bas":7,"invalid_link_scop":7,"invalid_literal_operator_id":7,"invalid_literal_typ":7,"invalid_local":7,"invalid_member_constant_typ":7,"invalid_microsoft_pragma_oper":7,"invalid_misaligned_ifc_posit":7,"invalid_mmap_address":7,"invalid_ms_attr_enum_valu":7,"invalid_ms_attr_nam":7,"invalid_ms_attr_uuid_valu":7,"invalid_ms_attribute_target":7,"invalid_name_after_templ":7,"invalid_neon_polyvector_element_typ":7,"invalid_neon_vector_element_typ":7,"invalid_neon_vector_s":7,"invalid_nested_class_redecl":7,"invalid_noexcept_specifier_operand":7,"invalid_nontype_template_argu":7,"invalid_object_fin":7,"invalid_operator_in_requires_claus":7,"invalid_overflowing_ifc_posit":7,"invalid_param_array_typ":7,"invalid_parameter_for_literal_operator_templ":7,"invalid_parameter_type_for_literal_oper":7,"invalid_pch_fil":7,"invalid_placeholder_for_defaulted_spaceship_return":7,"invalid_pointer_parameter_for_literal_oper":7,"invalid_pragma_conform_kind":7,"invalid_pragma_oper":7,"invalid_prev_decl_iter":7,"invalid_property_accessor_decl":7,"invalid_ref_class_bas":7,"invalid_ref_tracking_ref_combin":7,"invalid_reflection_equ":7,"invalid_reflection_for_intrins":7,"invalid_scalable_vector_element_typ":7,"invalid_scalable_vector_tuple_el":7,"invalid_scoped_enum_elabor":7,"invalid_second_parameter_type_for_literal_oper":7,"invalid_selective_overrider_declar":7,"invalid_spaceship_typ":7,"invalid_specific_ref_class_bas":7,"invalid_specifier_for_deduction_guid":7,"invalid_start_of_member_declar":7,"invalid_start_of_requires_clause_expr":7,"invalid_statement_in_constexpr_constructor":7,"invalid_statement_in_constexpr_funct":7,"invalid_std_comparison_typ":7,"invalid_std_comparison_valu":7,"invalid_std_initializer_list_parameter_list":7,"invalid_std_string_view_for_reflect":7,"invalid_storage_class_in_for_init":7,"invalid_string_literal_operator_templ":7,"invalid_struct_binding_specifi":7,"invalid_struct_binding_syntax":7,"invalid_struct_binding_typ":7,"invalid_symbolic_asm_operand_nam":7,"invalid_target_attribut":7,"invalid_template_parameter_for_literal_operator_templ":7,"invalid_token_after_templ":7,"invalid_tuple_s":7,"invalid_type_constraint":7,"invalid_type_for_builtin":7,"invalid_type_for_nul":7,"invalid_type_for_w64":7,"invalid_type_pointed_to_for_interior_ptr_or_pin_ptr":7,"invalid_typename_specifi":7,"invalid_ucn":7,"invalid_udl_valu":7,"invalid_unrepresentable_ifc_posit":7,"invalid_use_of_concept":7,"invalid_use_of_custom_ms_attr":7,"invalid_use_of_ms_attr":7,"invalid_use_of_standalone_custom_ms_attr":7,"invalid_use_of_standalone_ms_attr":7,"invalid_value_class_bas":7,"invalid_variable_main":7,"invalid_vector_element_typ":7,"invalid_vector_of_bool_oper":7,"invari":17,"invent":[9,10,16,19,23],"investig":[9,10],"invis":[5,17],"invoc":[0,1,2,3,6,7,8,10,11,14,16,21,23,24,25,26],"invocation_record":15,"invok":[0,1,3,6,7,8,10,11,12,14,15,16,17,21,23,24,26],"involv":[0,2,3,6,7,8,9,10,11,14,15,16,18,20,21,22,23,25],"iostream":[16,19],"ip":3,"iron":17,"irregular":21,"irrelev":[11,20],"irrespect":10,"is_":14,"is_accessible_base_class":21,"is_accessible_imm_base_class":21,"is_aggregate_or_union_typ":22,"is_alias_templ":23,"is_an_lvalu":9,"is_an_xvalu":9,"is_any_ptr_or_ref_typ":22,"is_any_reference_typ":22,"is_arithmetic_or_enum_typ":22,"is_array_typ":22,"is_at_least":17,"is_auto_param":23,"is_bit_field":11,"is_boxable_typ":[9,22],"is_char_array_typ":22,"is_character_typ":22,"is_class_memb":[15,21],"is_class_struct_union_typ":22,"is_class_symbol":21,"is_class_template_decl":23,"is_cli_array":[6,11],"is_cli_array_typ":[6,22],"is_cli_generic_constraint_typ":22,"is_cli_generic_param_typ":22,"is_cli_interface_typ":22,"is_cli_param_array":6,"is_cli_system_object_typ":22,"is_cli_system_string_typ":22,"is_cli_typeid":11,"is_complete_class_struct_union_typ":22,"is_const_qualified_typ":22,"is_constant_evaluated_in_constant_express":7,"is_constant_evaluated_in_consteval_context":7,"is_constant_evaluated_in_nonconstexpr_context":7,"is_constructor_decl":6,"is_constructor_symbol":21,"is_conversion_nam":21,"is_copy_constructor_symbol":21,"is_decl_not_expr":[6,9,20],"is_decl_start":14,"is_declar":23,"is_delegate_class":11,"is_delegate_typ":22,"is_destructor_nam":[15,21],"is_destructor_symbol":21,"is_enum_typeis_integral_or_enum_typ":22,"is_error":21,"is_error_typ":22,"is_far_typ":11,"is_file_scope_qualified_nam":[15,21],"is_fixed_point_typ":22,"is_floating_typ":22,"is_foo_bar":4,"is_for_init_block":20,"is_function_symbol":21,"is_function_typ":22,"is_gc_lvalue_expr":9,"is_gc_lvalue_operand":9,"is_generalized_identifer_start":15,"is_generalized_identifier_start":15,"is_generic_definit":[11,23],"is_global_qualified_nam":[15,21],"is_gnu_two_operand_question_mark":11,"is_guiding_decl":23,"is_handle_or_tracking_ref_typ":22,"is_handle_to_cli_array_typ":22,"is_handle_typ":22,"is_identifier_char":15,"is_illegal_abstract_class_typ":22,"is_immediate_class_typ":22,"is_immediate_error_typ":22,"is_implicitly_cast_integral_const":5,"is_incomplete_typ":22,"is_inlin":[11,23],"is_integr":22,"is_integral_typ":22,"is_interior_ptr_typ":22,"is_isolated_text":15,"is_last_elem":9,"is_literal_convertible_to_cli_str":9,"is_literal_typ":3,"is_lvalu":11,"is_lvalue_reference_typ":22,"is_managed_class_typ":22,"is_managed_nullptr_typ":22,"is_match_for_function_templ":23,"is_max_value_for_integer_kind":9,"is_member_const":3,"is_member_function_symbol":21,"is_more_speci":23,"is_namespace_alia":6,"is_nonclass_destructor":[15,21],"is_nonr":23,"is_nonreal_class":23,"is_nullptr_typ":22,"is_object_typ":22,"is_on_any_derivation_of":22,"is_operator_nam":[15,21],"is_or_contains_local_typ":22,"is_or_contains_specific_template_param":22,"is_or_contains_template_param":22,"is_or_contains_unnamed_or_local_typ":22,"is_pack_el":23,"is_parenthes":11,"is_pin_ptr_typ":22,"is_pointer_or_handle_typ":22,"is_pointer_typ":22,"is_polymorphic_class_typ":22,"is_prototype_instanti":23,"is_ptr_or_ref_typ":22,"is_ptr_to_member_typ":22,"is_qualified_nam":[15,21],"is_qualified_typ":22,"is_ref_class_typ":22,"is_reference_cast":11,"is_reference_typ":22,"is_repres":11,"is_restrict_qualified_typ":22,"is_rvalue_reference_cast":11,"is_rvalue_reference_typ":22,"is_rvalueable_nod":11,"is_scalar_typ":22,"is_secondary_trans_unit":25,"is_semivisible_nested_class":21,"is_signed_integral_typ":22,"is_signed_no_longer_a_keyword":7,"is_speci":23,"is_standard_class_typ":22,"is_super_qualifi":21,"is_tag_symbol":21,"is_target_specif":11,"is_template_alia":23,"is_template_class":[11,23],"is_template_class_typ":22,"is_template_funct":11,"is_template_id":21,"is_template_param_typ":22,"is_top_level_":22,"is_top_level_const_qualified_typ":22,"is_top_level_qualified_typ":22,"is_top_level_restrict_qualified_typ":22,"is_top_level_volatile_qualified_typ":22,"is_tracking_reference_typ":22,"is_two_arg":16,"is_type_constraint":23,"is_type_symbol":21,"is_udl_operator_nam":15,"is_union_typ":22,"is_useless_object_lifetim":[20,22],"is_using_decl":[3,21],"is_vacuous_destructor_refer":[15,21],"is_valid_generic_argumen":23,"is_value_class_typ":22,"is_variable_templ":11,"is_virtu":3,"is_virtual_cal":11,"is_vla":11,"is_void_typ":22,"is_volatile_qualified_typ":22,"is_xvalu":11,"ismemberofglobalmodul":17,"isn":[0,6,10,15,16,17,23],"iso":[1,5,9,10,11,13,15],"isol":[15,17,22],"issu":[1,2,3,6,8,9,11,13,14,15,16,17,18,20,21,22,23,24,25,26],"itanium":[1,3,16],"item":[0,3,10,23],"iter":[7,8,9,10,14,20,24,26],"ix":15,"ixx":24,"j":[2,5,6,9,10,11,14,16,23,24],"j1":10,"j16":10,"japanes":[1,10,15],"java":11,"jis":15,"jj":16,"jkl":10,"jmp_buf":19,"job":[16,18,20,24],"job_count":24,"johnson":10,"join":[6,16,17],"json":24,"judg":[10,11,16,21],"juli":10,"jump":[2,16],"just":[0,1,2,3,5,6,9,10,11,14,15,16,17,18,20,21,22,23,24],"justif":20,"justifi":[4,10],"k":[2,5,7,9,11,15,16],"kanji":15,"keep":[0,4,6,8,10,11,14,15,16,17,18,20,22,23,24],"keep_definition_in_il":0,"keep_in_il":0,"keep_restrict_in_signatur":10,"kept":[0,3,11,14,15,16,21,23,24,25],"kernighan":10,"key":[5,9,10,18,21,25],"keyword":[0,3,6,7,9,10,11,14,16,18,20,21,23],"keyword_drop":7,"keywordsort":17,"keywordsyntax":17,"kick":[3,9,11,23,25],"kill":[10,24],"kind":[0,2,3,5,6,7,8,9,10,11,14,15,16,18,20,21,22,23,25,26],"kind_of_white_space_skip":15,"know":[0,6,8,9,10,11,15,16,17,21,23,24,25],"knowledg":[13,16],"known":[0,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"known_attr_appl_t":18,"known_attr_t":18,"known_comparison_with_nul":7,"known_not_to_be_a_literal_typ":3,"known_to_be_a_literal_typ":3,"l":[1,2,7,10,11,15,16,18,26],"l10_1234567890":16,"l212":16,"l3n12":16,"l4n1p5":16,"l_1_2":16,"l_3_0d0_3_1d1":16,"label":[0,2,4,7,8,10,14,15,16,18,20,21,22,23],"label_fill_in":0,"label_in_constexpr_funct":7,"label_operand_number_out_of_rang":7,"labeled_declar":7,"lack":[7,16,18],"laid":3,"lambda":[0,7,9,10,16,21],"lambda_cannot_refer_to_local_entity_her":7,"lambda_capture_for_vari":3,"lambda_capture_involves_variable_length_array":7,"lambda_capture_structured_bind":7,"lambda_captures_handle_or_tracking_ref":7,"lambda_captures_managed_class_typ":7,"lambda_in_class_type_with_typedef_nam":7,"lambda_in_noexcept_specifi":7,"lambda_mutable_and_stat":7,"lambda_not_allowed_her":7,"lambda_not_constant_expr":7,"lambda_without_parameters_nonstandard":7,"lambda_without_parameters_requires_claus":7,"lambdas_is_cpp11":7,"lang_feat":[8,14,23],"languag":[2,3,5,6,7,8,9,13,15,16,17,18,19,20,21,23,24,26],"larg":[0,1,3,5,6,7,9,10,11,14,15,16,17,20,24,25],"larger":[0,7,9,10,11,14,15,16,17],"largest":[10,17],"last":[0,3,7,9,10,11,14,15,16,21,22,23,24],"last_line_backslash":7,"last_line_incomplet":7,"last_matching_source_sequence_entri":22,"last_src_seq_sublist":11,"late":[7,10],"late_tiebreak":10,"later":[0,1,3,5,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25],"latest":[7,10,11,16],"latest_initi":16,"latex":26,"latin":[7,15],"latitud":11,"latter":[0,1,3,5,6,7,8,9,10,11,13,15,16,17,18,20,21,22,23,25],"lay":[3,14],"layer":9,"layout":[1,7,10,14,16,22],"lazi":21,"lazili":17,"lazy_initialization_uses_weak_refer":16,"lc_all":24,"lc_numer":7,"ld":26,"le_end_of_insert":15,"le_end_of_lin":15,"le_end_of_token":15,"le_escap":15,"le_inert_macro":15,"le_max_value_for_integer_kind":9,"le_newlin":15,"le_nul":15,"lead":[7,10,14,15,16,17,18,21,25,26],"leading_character_ignored_in_char_liter":7,"leaf":[6,9,11],"lean":23,"learn":11,"least":[0,3,5,6,7,8,9,10,11,14,15,16,17,18,21,23],"leav":[2,8,9,10,11,14,15,16,21],"leave_insert":15,"leave_must_be_in_tri":7,"leck_catch_epilogu":16,"leck_caught_object_address":16,"leck_cleanup_st":16,"leck_exception_caught":16,"leck_exception_start":16,"leck_function_epilogu":16,"leck_function_prologu":16,"leck_internal_tri":16,"leck_thrown_object_address":16,"leck_try_epilogu":16,"leck_unreachable_cleanup_st":16,"led":[10,11,15],"left":[0,1,3,4,6,7,9,10,11,14,15,16,18,23],"legaci":[1,10],"legacy_target_configuation_nam":1,"legal":[3,9,10,11,14,21],"legitim":9,"len_of_curr_token":15,"length":[0,1,2,4,6,7,8,10,11,14,15,16,19,21,23],"lengthi":15,"lenient":17,"less":[0,3,6,7,9,10,11,14,15,16,18,20,21,23,24,25],"lessen":14,"let":[11,14,15],"letter":[0,4,7,10,16],"level":[0,2,3,5,6,7,8,10,11,13,14,15,16,17,18,20,21,23,25,26],"levels_up":7,"leverag":17,"lexic":[0,3,11,14,18,21,22,23],"lexical_init":0,"lexical_one_time_init":0,"lexical_trans_unit_init":0,"lfile":10,"li":16,"li6_mil":16,"lib":[0,1,10],"lib_":1,"lib_src":[1,19],"libari":10,"libc":1,"librari":[0,2,6,7,9,11,12,14,15,16,23,24,26],"licens":9,"lie":[9,14],"life":18,"lifetim":[7,8,9,10,17,20],"lifo":15,"like":[0,1,2,3,4,5,6,7,9,10,11,12,14,15,17,18,19,20,21,22,23,24,25,26],"likelihood":14,"likely_unlikely_conflict":7,"likewis":[0,3,6,9,10,11,14,16,20,23,25],"limit":[0,1,2,3,6,7,9,10,11,14,15,16,18,20,21,23,26],"line":[1,2,5,6,7,8,9,11,13,14,16,17,21,22,23,24,25,26],"line_start_source_line_modif":15,"linear":15,"link":[0,1,2,3,6,7,8,9,10,11,14,15,16,19,20,21,22,23,24,25,26],"link_scope_relax":7,"link_scope_requires_external_linkag":7,"link_symbol_into_symbol_t":21,"linkag":[2,7,10,16,21,22,23,25,26],"linkage_conflict":7,"linkage_main":7,"linkage_specif":6,"linkage_specifier_not_allow":7,"linker":[1,10,15,16,21,23,26],"linker_opt":24,"lint":[10,14,15,18],"lint_notreached_flag":20,"linux":1,"list":[0,1,2,4,6,7,8,10,13,14,16,17,18,19,20,23,24,25,26],"list_included_fil":15,"list_init_of_incomplet":7,"list_initializer_nonstandard_in_current_mod":7,"list_macro":10,"list_makefile_depend":15,"lit":9,"lit_suffix_no_underscor":7,"liter":[0,1,2,3,6,7,9,10,11,14,16,18,22],"literal_const_has_no_effect":7,"literal_fields_disallowed_in_cppcx_mod":7,"literal_operator_not_found":7,"literal_requires_managed_class":7,"literal_type_convertible_to_cli_str":9,"literal_without_initi":7,"littl":[0,3,5,9,10,11,14,15,17,21,23],"ll":[10,16],"lld":10,"lm":16,"lm0_l11_0":16,"lm0_l2n1_1j":16,"ln":24,"load":[0,6,7,9,10,16,17,21,23],"loader":16,"local":[0,1,2,3,5,6,7,8,9,10,11,14,15,17,19,20,21,22,23,26],"local_class_friend_requires_prior_decl":7,"local_class_function_def_miss":7,"local_class_in_managed_member_funct":7,"local_cli_managed_class_typ":7,"local_entities_should_be_promot":16,"local_function_attribute_ignor":7,"local_index":17,"local_lambda_in_managed_member_funct":7,"local_named_register_initializer_not_allow":7,"local_opt":9,"local_pragma_pack":7,"local_static_variable_init":11,"local_type_in_funct":7,"local_type_in_nonlocal_var":7,"local_type_in_template_arg":7,"local_type_used_in_except":7,"local_variable_hidden":7,"locale_to_set_when_multibyte_chars_en":[1,15],"locat":[1,3,6,7,8,9,10,11,14,15,17,18,20,22,23,24,26],"locator_for_curr_id":[9,15,21],"lock":15,"locus":[10,17],"log":24,"logic":[1,4,9,11,14,17,21,23,24],"logical_column_offset":15,"lone_flexible_array_memb":7,"long":[0,2,4,5,7,9,10,11,14,15,16,17,20,22,23],"long_lifetime_temp":[10,11],"long_long":10,"long_long_allow":[10,11],"long_max":[0,1,10],"long_min":1,"long_preserving_rul":10,"long_vari":4,"longer":[0,7,9,10,11,15,16,17,18,20,21,22,23,26],"longest":4,"longjmp":8,"look":[0,1,3,6,8,9,10,11,14,16,17,18,20,23,24,25,26],"look_up_conversion_template_inst":21,"lookahead":[3,9,14,18],"lookup":[3,6,9,11,14,15,23,25],"lookup_in_namespac":21,"loop":[0,3,6,7,8,9,10,11,14,15,16,20,21,23,24],"loop_not_reach":7,"loop_token":[14,15],"loos":[6,9,11],"lose":0,"lossy_convers":7,"lossy_conversion_warn":10,"lost":[10,11,16],"lot":[0,4,6,9,10,11,15,16,17,21,23,24],"low":[0,5,7,10,11,14,15,16,17,21],"lower":[0,1,2,3,4,5,8,9,10,11,13,14,17,19,21,22,23,24,25],"lower_array_delet":16,"lower_array_new":16,"lower_bool_cast":16,"lower_bool_incr":16,"lower_c99":[14,16],"lower_c99_complex_cast":16,"lower_c99_fixed_point_cast":16,"lower_c99_fixed_point_const":16,"lower_c99_fixed_point_incr_decr":16,"lower_c99_fixed_point_oper":16,"lower_c99_fixed_point_typ":16,"lower_c99_nonreal_float_typ":16,"lower_c99_oper":16,"lower_c99_stmk_init":16,"lower_c99_temp_init":16,"lower_cal":16,"lower_ck_dynamic_init":16,"lower_class_rvalue_adjust":11,"lower_complex":[11,16],"lower_condit":16,"lower_constructor_cod":16,"lower_ctor_init":16,"lower_delet":16,"lower_designated_initi":[11,16],"lower_destructor_cod":16,"lower_destructor_dynamic_init":16,"lower_dtor_init":16,"lower_dynamic_init":16,"lower_dynamic_init_aggregate_const":16,"lower_eh":[8,14,16],"lower_expr_ful":16,"lower_extern_inlin":16,"lower_file_scope_dynamic_init":16,"lower_fixed_point":16,"lower_hdr":14,"lower_ifunc":16,"lower_ifunc_expr":16,"lower_ifunc_routin":16,"lower_il":[14,16,23],"lower_init":[14,16],"lower_lvalue_returning_oper":16,"lower_mv_routin":16,"lower_nam":[14,16],"lower_new":16,"lower_orphaned_entri":16,"lower_pm_cal":16,"lower_pm_field":16,"lower_pm_related_class_cast":16,"lower_ptr_to_member_const":16,"lower_related_class_cast":16,"lower_scop":16,"lower_thread_local_vari":16,"lower_throw":16,"lower_try_block":16,"lower_typ":16,"lower_variable_length_array":[11,16,19],"lower_virtual_function_cal":16,"lower_virtual_function_ptr":16,"lower_vla_dimens":16,"lower_vla_typ":16,"lowered_mv_routin":16,"lowering_normalizes_boolean_controlling_express":16,"lowest":[15,26],"lp":24,"lparen":4,"lparen_after_funct":7,"lstd":26,"ltd":16,"lvalu":[2,5,7,9,10,22],"lvalue_rvalue_test":11,"m":[2,3,10,11,16,18,24,26],"m1":16,"m16":16,"m2":16,"m4":16,"m8":16,"m_":[2,5],"m_write_ch":[2,5],"m_write_spac":5,"m_write_str":2,"m_write_tok_ch":[2,5],"m_write_tok_str":[2,5],"machin":[0,9,10,11,14,15,16,26],"machineri":6,"maco":1,"macosx":[1,26],"macosx64":26,"macro":[2,3,6,7,9,12,14,16,17,18,19,20,21,22,23,25],"macro_buff":15,"macro_context":[11,15],"macro_in_pp_direct":7,"macro_invoc":[7,15],"macro_invocation_record_block":15,"macro_invocation_tree_in_il":[1,10,11,14,15],"macro_invocations_per_block":11,"macro_is_en":4,"macro_line_loc_to_source_po":15,"macro_nam":0,"macro_not_udl_suffix":7,"macro_positions_in_diagnost":10,"macro_recurs":7,"macro_text_map":15,"macro_valu":0,"made":[0,1,2,3,5,6,7,8,9,10,11,12,14,15,16,17,18,20,21,23,24],"magnitud":[9,25],"main":[0,1,2,3,5,6,7,8,9,10,11,13,14,15,18,21,22,23,25,26],"main_coroutin":7,"main_first_param_not_int":7,"main_second_param_wrong_typ":7,"main_wrong_num_param":7,"maintain":[0,1,2,5,6,8,9,10,11,14,15,17,20,21,22,23,25],"maintain_class_member_list":11,"maintain_needed_flag":[0,10,11],"mainten":[10,14,16,24],"major":[9,10,11,14,15,22,23],"make":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"make_array_table_entri":16,"make_attr_unrecogn":18,"make_boxed_enum_typ":6,"make_canonical_identifi":15,"make_cli_metadata_fil":6,"make_closure_class":3,"make_code_to_invoke_file_scope_init_routin":16,"make_constant_operand":9,"make_construction_vtbl":16,"make_ctor_implied_arg_list":16,"make_default_assignment_bodi":3,"make_default_constructor_bodi":3,"make_default_destructor_bodi":3,"make_dtor_implied_arg_list":16,"make_error_operand":9,"make_expression_operand":9,"make_field_operand":9,"make_front_end_cal":[0,1,14],"make_function_cal":9,"make_function_designator_operand":9,"make_g":1,"make_glvalue_expression_operand":9,"make_il_template_entri":23,"make_indefinite_function_operand":9,"make_initializer_list_object":9,"make_instantiation_info_var":16,"make_integer_constant_operand":9,"make_integer_value_mask":9,"make_internal_try_expr":16,"make_locator_for_symbol":21,"make_lvalue_reusable_copi":16,"make_lvalue_variable_operand":9,"make_namespace_projection_symbol":21,"make_node_from_operand":9,"make_null_thread_local_init_routine_for_vari":16,"make_operator_nod":[11,22],"make_opname_loc":21,"make_placement_array_new_cal":16,"make_pointer_typ":[6,22],"make_predef_macro_t":1,"make_predefined_macro_fil":0,"make_projection_symbol":21,"make_ptr_to_member_constant_operand":9,"make_qualified_typ":22,"make_reference_typ":[6,22],"make_region_table_entri":16,"make_rescan_operand":9,"make_reusable_copi":16,"make_rvalue_reference_typ":[6,22],"make_selection_for_captured_vari":9,"make_source_sequence_secondary_decl":22,"make_string_constant_operand":9,"make_subobject_class_typ":16,"make_sym_for_ptr_to_member_operand":9,"make_symbol_for_cli_array":6,"make_symbol_for_cli_interior_ptr":6,"make_symbol_for_cli_pin_ptr":6,"make_symbol_for_namespace_c":0,"make_template_class_sym":23,"make_template_class_symbol":21,"make_template_funct":23,"make_template_str":23,"make_text_not_token":18,"make_this_pointer_operand":9,"make_type_conversion_loc":21,"make_unnamed_tag_symbol":[3,21],"make_unqualified_typ":22,"make_using_decl":[3,6],"make_using_direct":6,"make_var_for_virtual_function_t":16,"make_vars_for_virtual_function_t":16,"make_vec_delete_cal":16,"make_win_predef_macro_t":1,"make_zero_of_proper_typ":22,"makefil":[7,15],"maker":26,"malform":[7,15],"malformed_universal_charact":7,"malici":10,"malloc":[0,7,8,9,14,22],"manag":[6,7,9,10,14,15,17,20,25,26],"managed_base_for_standard_class":7,"managed_class_cannot_have_friend":7,"managed_class_type_cannot_have_private_or_protected_bas":7,"managed_member_exception_spec":7,"managed_member_function_cannot_have_ellipsis_paramet":7,"managed_nullptr_not_allow":7,"managed_object_not_caught_by_handl":7,"managed_object_not_thrown_by_handl":7,"mandat":[3,10,21,23],"mangl":[2,7,10,11,14,23,25,26],"mangle_function_nam":16,"mangle_variable_nam":16,"mangle_wrapper_nam":16,"mangled_encoding_for_express":16,"mangled_encoding_for_typ":16,"mangled_id_object_nam":16,"mangled_name_too_long":7,"mangled_operator_nam":16,"mangled_type_name_ful":16,"mangled_typeinfo_nam":16,"mangling_for_requir":7,"mani":[0,1,3,4,6,7,9,10,11,14,15,16,18,19,21,22,23,24,25],"manifest":14,"manipul":[9,11,14,15,22,25],"manner":[1,3,10,15,16,26],"mantissa":7,"manual":[1,14,23,24,26],"map":[0,3,6,7,10,14,15,16,21,22,23,24,25],"mappabl":0,"march":8,"margin":[0,2,4],"mark":[0,2,3,5,7,9,10,11,15,16,18,21,22,23,24,25,26],"mark_as_need":0,"mark_declar":21,"mark_defin":21,"mark_secondary_trans_unit_il_entities_used_from_primary_as_need":25,"mark_to_keep_in_il":0,"mark_variable_value_set":21,"marker":[0,9,10,11,15,25,26],"markup":26,"mask":[7,8,9,11,15,16,17],"masked_by_default_handl":7,"masked_by_handl":7,"master":23,"match":[0,1,2,3,5,6,7,8,9,10,11,15,16,17,18,21,22,23,24,25],"match_limit_for_symbolic_asm_operand":7,"match_regex":24,"matches_partial_speci":23,"matches_template_typ":[9,23],"matching_lbrac":7,"matching_template_funct":[6,9,23],"math":10,"matter":[0,1,3,9,10,14,23,24],"max":[3,16,24],"max_cost_constexpr_cal":[9,10],"max_depth_constexpr_cal":[9,10],"max_fail_count":24,"max_include_files_open_at_onc":15,"max_output_line_s":2,"max_pending_instanti":23,"maxim":4,"maximum":[0,2,3,4,7,10,11,17,18,24],"may":[0,1,2,3,4,5,6,7,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"may_bind_to_decl":18,"may_bind_to_stat":18,"mayb":[16,23],"mbc_length":15,"mbc_to_wide_char":15,"mblen":[1,15],"mbtowc":15,"mdefn_get_token":15,"mean":[0,2,3,5,6,7,8,9,10,11,14,15,16,17,18,19,20,21,23,24,25],"meaning":[0,10,11,18],"meaningless":[7,23],"meant":[1,6,18,26],"measur":[9,10],"mechan":[0,1,3,5,6,10,11,15,16,17,18,19,21,22,25,26],"medium":14,"meet":[9,10,11,15,18,21],"megabyt":10,"mem":[7,9,10,11,23],"mem_attrib_ignor":7,"mem_attrib_incompat":7,"mem_attrib_may_not_precede_nested_declar":7,"mem_manag":[0,1,14],"mem_tabl":14,"member":[0,2,5,6,7,9,10,14,15,17,18,22,25],"member_access_requires_point":7,"member_already_initi":7,"member_cannot_have_internal_linkag":7,"member_check_ambiguity_and_verify_access":21,"member_constant_not_const":7,"member_declar":11,"member_function_call_on_initonly_field":7,"member_function_modifier_on_static_memb":7,"member_function_modifier_on_templ":7,"member_function_of_class_type_with_typedef_nam":7,"member_function_redecl_outside_class":7,"member_function_redecl_sym":[3,23],"member_function_redeclar":7,"member_name_reserved_by_cli_oper":7,"member_name_reserved_by_properti":7,"member_partial_spec_not_in_namespac":7,"member_ref_requires_object":7,"member_special_after_class_definit":7,"member_type_of_class_type_with_typedef_nam":7,"member_using_declar":[3,6],"member_using_must_be_visible_in_direct_bas":7,"memberwis":3,"memcpi":[1,2,7,14,17],"memmov":7,"memoiz":17,"memori":[1,3,5,6,7,8,9,10,13,14,15,16,18,21,22],"memory_mismatch":7,"memset":2,"mention":[0,1,3,9,11,14,15,16,18,21,23],"mere":[0,5,11,17],"merg":[0,3,5,11,15,21,25],"merge_function_into_lookup_set":21,"merit":0,"messag":[0,1,2,11,13,14,15,18,23,24,26],"messi":[11,16],"met":[9,10],"meta":7,"metadata":[0,1,7,10,14,15,23],"metafunct":7,"metaphor":17,"metaprogram":10,"method":[7,9,10,11,16,21,23,26],"meticul":24,"mf":10,"mft":24,"microsoft":[0,1,2,5,7,9,13,14,15,16,17,18,20],"microsoft_16":10,"microsoft_bug":10,"microsoft_build_numb":10,"microsoft_extensions_allow":[1,10,11,14,22],"microsoft_inline_not_allowed_her":7,"microsoft_mod":[14,16],"microsoft_parenthesized_memb":7,"microsoft_ptr_sign_extens":7,"microsoft_ptr_signedness_conflict":7,"microsoft_ptr_signedness_must_follow_star":7,"microsoft_ptr_signedness_on_ptr_to_memb":7,"microsoft_ptr_width_conflict":7,"microsoft_ptr_width_must_follow_star":7,"microsoft_vers":[7,10,20],"microsoft_version_doesnt_support_cpp14_mod":7,"microsoft_version_doesnt_support_cpp17_mod":7,"microsoft_version_doesnt_support_cpp20_mod":7,"microsoft_version_doesnt_support_cpp23_mod":7,"microsoft_version_doesnt_support_cpplatest_mod":7,"mid":[2,23],"middl":[6,11,14,15,16,18,26],"midst":[6,23],"might":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,17,19,21,22,23,24,25,26],"milder":10,"million":9,"mimic":10,"min":[10,16],"mind":[1,10,11,16,18],"mine":[9,24],"mingw":1,"minim":[1,10,11,13,14,16,17],"minimal_inlin":[1,10,11,16],"minimum":[7,10,16],"minor":[0,1,2,9,10,11,16,18,25],"minus":[16,23],"minut":1,"mirp":11,"mis":10,"misalign":[7,17],"misc":1,"miscellan":14,"misconfigur":7,"misdiagnos":24,"misinterpret":10,"mismatch":[0,7,17,23],"mismatched_function_for_deleg":7,"mismatched_shared_block_s":7,"misnom":3,"mispars":15,"miss":[0,1,2,7,10,11,14,15,24],"missing_access_specifi":7,"missing_add_or_remove_accessor":7,"missing_attr_namespac":7,"missing_attribute_argu":7,"missing_attribute_in_other_translation_unit":7,"missing_base_class_or_member_nam":7,"missing_bind":7,"missing_class_definit":7,"missing_const_assignment_oper":7,"missing_const_copy_constructor":7,"missing_constinit":7,"missing_constraint_lett":7,"missing_decl_specifi":7,"missing_default_constructor_on_const":7,"missing_default_constructor_on_unnamed_const":7,"missing_delegate_object":7,"missing_endif":7,"missing_exception_declar":7,"missing_fin":7,"missing_floating_point_typ":7,"missing_get_and_set_accessor":7,"missing_gnu_inline_attr_on_redeclar":7,"missing_gnu_srcloc_typ":7,"missing_handl":7,"missing_header_unit_map":7,"missing_implements_list":7,"missing_incr_on_for_each_typ":7,"missing_incr_on_range_based_for_typ":7,"missing_indirect_on_for_each_typ":7,"missing_indirect_on_range_based_for_typ":7,"missing_initi":7,"missing_initializer_list":7,"missing_initializer_list_ctor":7,"missing_initializer_on_const":7,"missing_initializer_on_field":7,"missing_initializer_on_fields_with_constexpr_ctor":7,"missing_initializer_on_refer":7,"missing_initializer_on_unnamed_const":7,"missing_label_operand_numb":7,"missing_lambda_bodi":7,"missing_named_register_storage_class":7,"missing_namespace_nam":7,"missing_notequal_on_for_each_typ":7,"missing_notequal_on_range_based_for_typ":7,"missing_override_attr_in_base_check_class":7,"missing_pp_if":7,"missing_raw_string_delim_lparen":7,"missing_raw_string_delimit":7,"missing_std_tuple_el":7,"missing_std_tuple_element_inst":7,"missing_target_attribut":7,"missing_template_arg_list":7,"missing_template_param":7,"missing_template_param_list":7,"missing_trailing_return_typ":7,"missing_type_specifi":7,"missing_typedef_nam":7,"missing_typenam":7,"missing_va_opt_paren":7,"mission":16,"mitig":17,"mix":[4,6,7,9,10,11,16,17,21,24,25],"mixed_enum_typ":7,"mixed_enum_type_anachron":7,"mixed_string_concaten":7,"mixed_vector_scalar_oper":7,"mk_errinfo":[0,1,14],"mm":[10,16],"mmap":[7,10],"mmap_address":10,"mme":16,"mml":26,"mmm":10,"mn":16,"mnemon":10,"mod":17,"mod_by_zero":7,"mode":[0,2,6,7,8,9,11,14,15,16,17,18,19,20,26],"mode_incompatible_with_typ":7,"model":[9,10,11,19,23],"modern":[1,3,10,11,16],"modest":2,"modif":[0,1,5,9,10,13,14,16,18,24,25],"modifi":[0,1,2,3,5,6,7,9,10,11,14,15,16,18,21,23,25,26],"modification_of_initonly_field":7,"modification_of_static_initonly_field":7,"modified_auto_typ":7,"modified_class_template_placehold":7,"modified_decltype_auto_typ":7,"modified_within_try_block":16,"modifier_not_allowed_on_destructor":7,"modifier_not_allowed_on_fin":7,"modifying_lvalu":9,"modul":[2,7,14,16,21,23,24],"module_already_import":7,"module_cannot_depend_on_itself":7,"module_decl_only_after_glb_mod":7,"module_directive_in_if":7,"module_directive_in_macro":7,"module_fil":[10,24],"module_file_contains_unsupported_construct":7,"module_file_mismatch":7,"module_file_not_found":7,"module_id":16,"module_id_ptr":25,"module_import_conflict":7,"module_import_diagnost":10,"module_init":10,"module_interfac":[10,24],"module_internal_partit":[10,24],"module_nam":10,"module_name_not_allow":7,"module_read_error":7,"module_refer":17,"module_req_primary_nam":7,"module_unit_export_expect":7,"module_unit_export_unexpect":7,"module_use_in_multi_tu_mod":7,"module_use_with_export_templ":7,"modulerefer":17,"modules_directori":10,"modules_not_en":7,"modulo":24,"moment":[10,14,15,16,18,23],"monoton":2,"moot":3,"more_than_one_captur":7,"more_than_one_fgmt_decl":7,"more_than_one_module_decl":7,"moreov":[3,8,10,11,15,18,21],"mostly":[0,1,3,6,9,11,14,20,23,25],"move":[1,3,4,6,7,10,11,14,15,16,17,21,22,23,24,25],"move_ctor_or_assign_copy_of_lvalu":7,"move_to_end_of_types_list":3,"movenext":7,"ms":[0,1],"ms_attr_not_allow":7,"ms_attrib":14,"ms_attribut":11,"ms_await":10,"ms_await_strict":10,"ms_c":[7,10],"ms_c11":10,"ms_c17":10,"ms_c23":10,"ms_compat":10,"ms_cplusplus_std_valu":10,"ms_declspec_attributes_en":18,"ms_extens":10,"ms_header_unit":10,"ms_header_unit_angl":10,"ms_header_unit_quot":10,"ms_ifc_unavail":7,"ms_metadata":[1,6,14],"ms_metadata_init_fail":7,"ms_mod_file_map":10,"ms_permiss":10,"ms_rvalue_cast":10,"ms_std_preprocessor":10,"ms_stdc":10,"ms_strict_ternari":10,"ms_translate_includ":10,"ms_version_i":14,"msc_version_i":14,"mscore":1,"mscorlib":[0,1,6,10,14,15,21],"mscorlib_file_nam":10,"mscpp_version_i":14,"msg":10,"msinfo":1,"msvc":[9,11,24],"msvc_is_generated_code_target":1,"msvc_target_vers":10,"msvc_target_version_numb":1,"much":[1,3,6,9,10,11,14,15,16,17,18,20,21,23,24,25],"mult_storage_class":7,"multi":[8,10,15,16,23],"multi_char_liter":7,"multibyt":[1,7,10,11,14],"multibyte_char":10,"multibyte_chars_in_source_support":[1,11,15],"multicastdeleg":3,"multichar_ud_lit":7,"multicharact":7,"multidimension":[3,7,22],"multipl":[0,1,4,6,7,8,9,10,11,14,15,16,17,18,21,23,24],"multiple_attr_namespac":7,"multiple_block_s":7,"multiple_class_constraint":7,"multiple_constraint_claus":7,"multiple_declspec_align":7,"multiple_explicit_instanti":7,"multiple_header_map_match":7,"multiple_inheritance_in_embedded_cplusplus":7,"multiple_link_scope_specifi":7,"multiple_module_match":7,"multiple_named_address_spac":7,"multiple_overrid":7,"multiple_structured_binding_pack":7,"multiple_template_decls_not_allow":7,"multiple_thread_compil":10,"multiple_thread_local_storage_specifi":7,"multiple_union_design":7,"multiple_union_field_initi":7,"multiple_union_field_initializers_empti":7,"multiple_visibility_specifi":7,"multipli":[10,21],"multiply_integer_valu":9,"multivers":[7,11],"munch":[1,16,26],"munch_nm":1,"must":[0,1,2,3,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,25,26],"must_be_atomic_qualified_typ":7,"must_be_class_or_namespace_lookup":21,"must_be_prototype_instanti":7,"must_be_tag_lookup":21,"must_introduce_attribut":7,"mutabl":[3,7,10],"mutable_in_embedded_cplusplus":7,"mutable_not_allow":7,"mutable_qualifier_on_explicit_this_lambda":7,"mutat":14,"mv_info":11,"mx":16,"my_filt":24,"my_templ":4,"my_var_a":4,"my_var_c":4,"my_vari":4,"my_very_long_funct":4,"mylib":10,"mythread":[7,11],"mythread_constant_not_allow":7,"n":[0,1,3,4,7,8,10,11,15,16,21,24,25,26],"n2634":9,"na":0,"naiv":14,"nake":7,"name":[0,1,2,7,8,9,12,13,17,18,19,22,23,24,25,26],"name1":[7,10],"name2":[7,10],"name_before_typeid_not_typ":7,"name_linkag":[3,11],"name_linkage_mismatch_for_vari":7,"name_must_be_prototype_instanti":7,"name_not_class_in_file_scop":7,"name_not_found_in_file_scop":7,"name_not_member_of_class_or_base_class":7,"name_not_tag_in_file_scop":7,"name_space_for_symbol_kind":21,"named_address_spac":[7,10,11],"named_address_space_for_paramet":7,"named_address_space_not_allow":7,"named_address_space_on_function_typ":7,"named_module_source_conflict":7,"named_override_requires_managed_typ":7,"named_override_requires_virtu":7,"named_override_type_mismatch":7,"named_regist":[7,10],"named_register_not_allow":7,"named_register_storage_class":11,"nameindex":17,"namespac":[0,3,4,5,7,9,14,15,18,22,23,25],"namespace_alia":7,"namespace_alias_def_not_allow":7,"namespace_cli_cannot_be_extend":7,"namespace_declar":6,"namespace_def_not_allow":7,"namespace_default_cannot_be_extend":7,"namespace_name_not_allow":7,"namespace_not_allow":7,"namespace_ptr":15,"namespace_qualified_id_lookup":21,"namespace_qualified_name_requir":7,"namespaces_in_embedded_cplusplus":7,"nan":10,"narrow":[7,9,15,18,24],"narrowing_convers":7,"nativ":[1,7,9,11,14,15,17],"native_multibyte_chars_supported_with_unicod":[10,15],"natur":[0,1,3,9,11,15,16,23],"near":[3,9,10,11,14,15,16,21,23],"near_and_far_allow":[10,11],"near_and_far_en":11,"near_code_point":10,"near_data_point":10,"nearest":[10,20,21],"neat":4,"necess":11,"necessari":[0,1,2,3,5,6,8,9,10,11,13,14,15,16,17,18,20,21,22,23,24,25,26],"necessarili":[6,8,9,10,11,13,14,15,22,23],"necessit":[2,16],"need":[1,2,3,4,5,6,7,9,10,14,15,16,17,18,19,20,21,22,23,24,25,26],"need_il_display":10,"needed_flag_bit_numb":[0,2],"needed_flag_is_set":0,"needless":14,"needn":[3,10],"needs_more_squirrel":4,"negat":[0,4,7,9,11,16,17],"negative_shift_count":7,"negative_valu":7,"neither":[0,9,16,23],"neon":7,"ness":5,"nest":[3,6,7,8,9,10,11,14,15,16,17,18,22,23],"nested_class_anachron":7,"nested_com":7,"nested_inline_namespace_nonstandard":7,"nested_namespace_nonstandard":7,"nested_source_line_modif":15,"nested_upc_foral":7,"nested_va_opt":7,"net":[0,1,10,11,13],"never":[0,2,3,6,7,9,10,11,14,15,16,17,18,21,23,25,26],"never_defin":7,"never_throw":18,"nevertheless":[0,5,10,11],"new":[0,1,3,4,6,7,8,9,10,12,14,15,17,19,20,21,22,23,24,25,26],"new3":16,"new_array_size_must_be_nonneg":7,"new_can_be_folded_into_ctor":[11,16],"new_cast_in_embedded_cplusplus":7,"new_for_init":10,"new_il_region":22,"new_memory_region":0,"new_of_cli_interface_class":7,"new_of_initializer_list":7,"new_or_override_requir":7,"new_or_virtual_requir":7,"new_requires_matching_base_memb":7,"new_routin":16,"new_struct_stmt_stack":[6,23],"new_type_nam":6,"new_used_on_handle_or_tracking_reference_typ":7,"new_used_on_managed_class_typ":7,"new_used_on_unsuitable_value_typ":7,"newer":[4,7,15,16,17],"newli":[11,15,18,21,23],"newlin":[4,7,15],"next":[0,1,3,4,6,8,9,10,11,14,15,16,18,20,21,23,25],"next_construct_processing_funct":18,"next_elem":[6,9],"next_in_destruct":11,"next_in_destruction_list":[11,16],"next_in_scop":21,"next_scope_that_affects_access_control":21,"next_symbol_in_overload_set":9,"next_symbol_in_overload_symbol_list":9,"next_token":[14,15],"next_token_is_top_level_decl_start":0,"next_two_token":15,"next_val":10,"nf":0,"ng":16,"nih":10,"nit":16,"nm":[23,26],"nn":[2,14],"nnn":[10,16,24],"nnnn":16,"nnnnnn":2,"no_":10,"no_abi_tag_on_declar":7,"no_access_or_using_decl_in_union":7,"no_access_to_nam":7,"no_access_to_type_cfront_mod":7,"no_add_match_not":10,"no_aligned_new":10,"no_alignment_on_definit":7,"no_alternative_token":10,"no_anachron":10,"no_appropriate_delet":7,"no_arg_dep_lookup":10,"no_array_designators_in_cpp_mod":7,"no_array_new_and_delet":10,"no_array_new_and_delete_support":7,"no_auto_instanti":10,"no_auto_storag":10,"no_auto_typ":10,"no_base_assign_op_is_default":10,"no_bit_precise_integ":10,"no_bool":10,"no_brief_diagnost":10,"no_c":10,"no_c23_typeof":10,"no_c99":10,"no_chained_designators_in_cpp_mod":7,"no_chained_designators_with_destructor":7,"no_char16_t_represent":7,"no_char8_t":10,"no_check_concaten":10,"no_check_unicode_secur":10,"no_clang":10,"no_class_name_inject":10,"no_class_template_guid":7,"no_classification_for_fixed_point_typ":7,"no_code_gen":10,"no_color":10,"no_common_typ":7,"no_compound_liter":10,"no_concept":10,"no_const_string_liter":10,"no_constexpr_coroutin":7,"no_constructor_for_convers":7,"no_conversion_funct":7,"no_corresponding_delet":7,"no_corresponding_member_delet":7,"no_corresponding_push":7,"no_cppc":10,"no_cppcx":10,"no_ctor_but_const_or_ref_memb":7,"no_ctor_or_dtor_using_declar":7,"no_default_constructor":7,"no_default_delete_in_virtual_dtor":7,"no_defer_parse_function_templ":10,"no_delegating_constructor":10,"no_dep_nam":[7,10],"no_deprecated_string_conv":10,"no_design":10,"no_designator_valu":7,"no_diagnost":6,"no_digit_separ":10,"no_display_error_numb":10,"no_distinct_template_signatur":10,"no_embedded_c":10,"no_enum_overload":10,"no_exc_spec_in_func_typ":10,"no_except":10,"no_exception_support":7,"no_explicit":10,"no_export":10,"no_export_support":7,"no_extended_design":10,"no_extended_variadic_macro":10,"no_extern_inlin":10,"no_finalizer_using_declar":7,"no_fixed_point":10,"no_float128":7,"no_float80":7,"no_for_init_diff_warn":10,"no_friend_inject":10,"no_func_prototype_tag":10,"no_g":10,"no_gcc":10,"no_gen_move_oper":10,"no_get_properti":7,"no_gnu_sentinel_argu":7,"no_gnu_virtual_base_gap":7,"no_guiding_decl":10,"no_il_low":[1,10],"no_implicit_capture_on_enclosing_lambda":7,"no_implicit_extern_c_type_convers":10,"no_implicit_includ":10,"no_implicit_noexcept":10,"no_implicit_typenam":10,"no_incognito":10,"no_init":7,"no_inlin":10,"no_internal_linkage_for_new_or_delet":7,"no_keep_restrict_in_signatur":10,"no_lambda":10,"no_line_command":10,"no_long_preserving_rul":10,"no_lossy_conversion_warn":10,"no_macro_positions_in_diagnost":10,"no_match_for_addr_of_overloaded_funct":7,"no_match_for_type_of_overloaded_funct":7,"no_match_in_c11_gener":7,"no_matching_ar":7,"no_matching_constructor":7,"no_matching_forscope_stack_entri":7,"no_matching_funct":7,"no_matching_function_due_to_selector":7,"no_matching_new_funct":7,"no_matching_operator_funct":7,"no_matching_target_attribut":7,"no_microsoft":10,"no_microsoft_bug":10,"no_mixed_init_in_cpp_mod":7,"no_modul":10,"no_module_import_diagnost":10,"no_ms_compat":10,"no_ms_cplusplus_std_valu":10,"no_ms_extens":10,"no_ms_permiss":10,"no_ms_rvalue_cast":10,"no_ms_std_preprocessor":10,"no_ms_stdc":10,"no_ms_strict_ternari":10,"no_ms_translate_includ":10,"no_multibyte_char":10,"no_mutable_allowed_on_anonymous_union":7,"no_named_address_spac":10,"no_named_field":7,"no_named_regist":10,"no_named_register_for_array":7,"no_namespac":10,"no_negative_designator_rang":7,"no_nonconst_ref_anachron":10,"no_nonstd_anonymous_union":10,"no_nonstd_default_arg_deduct":10,"no_nonstd_gnu_keyword":10,"no_nonstd_instantiation_lookup":10,"no_nonstd_qualifier_deduct":10,"no_nonstd_using_decl":10,"no_nothrow_global_new_for_coroutin":7,"no_nullptr":10,"no_old_id_char":10,"no_old_speci":10,"no_ordinary_and_extended_design":7,"no_out_of_order_init_in_cpp_mod":7,"no_overloaded_subscript_with_offsetof":7,"no_overrider_for_pure_virtual_funct":7,"no_pack_expansion_in_design":7,"no_pack_in_fold_express":7,"no_packing_of_non_pod_field":7,"no_parameter_for_literal_oper":7,"no_params_with_class_or_enum_typ":7,"no_params_with_class_typ":7,"no_parent_macro_invoc":[11,14,15],"no_parse_templ":[7,10],"no_pch":[0,10],"no_pch_messag":10,"no_pointer_paramet":7,"no_preproc_on":10,"no_preserve_lvalues_with_same_type_cast":10,"no_prior_declar":7,"no_prior_push_macro":7,"no_put_properti":7,"no_qualified_friend_definit":7,"no_range_designator_with_dynamic_init":7,"no_relaxed_abstract_check":10,"no_remove_unneeded_ent":10,"no_require_func_prototyp":[7,10],"no_restrict":10,"no_return_value_and_return_void":7,"no_rtti":10,"no_rvalue_ref":10,"no_scope_depth":21,"no_short_enum":10,"no_speci":7,"no_special_subscript_cost":10,"no_stdarg_builtin":10,"no_stdc_zero_in_system_head":10,"no_strict_gnu":10,"no_suitable_assignment_oper":7,"no_suitable_copy_constructor":7,"no_suitable_synthesis_assignment_oper":7,"no_sun":10,"no_sun_linker_scop":10,"no_svr4":10,"no_template_typedefs_in_diagnost":10,"no_thread_local_storag":10,"no_token_separators_in_pp_output":10,"no_trigraph":10,"no_type_of_specified_width":7,"no_type_traits_help":10,"no_typenam":10,"no_typename_in_friend_class_decl":7,"no_uliter":10,"no_unrestricted_union":10,"no_upc":10,"no_use_before_set_warn":10,"no_user_defined_convers":7,"no_user_defined_liter":10,"no_using_framework_directori":10,"no_using_std":10,"no_utf8_char_liter":10,"no_value_returned_in_non_void_funct":7,"no_variadic_macro":10,"no_variadic_templ":10,"no_viable_delete_for_coroutin":7,"no_vla":10,"no_warn":10,"no_wchar_t_keyword":10,"no_wrap_diagnost":10,"nocolor":10,"nocommon":10,"node":[0,1,2,5,7,8,9,11,14,16,22,23,25],"node_does_fetch":11,"node_for_integer_const":22,"node_has_side_effect":9,"node_includes_glvalue_to_prvalue_conv":11,"node_is_pointer_with_restrict_semant":11,"nodiscard":7,"nodiscard_constructor":7,"nodiscard_constructor_with_reason":7,"nodiscard_doesnt_appli":7,"nodiscard_object_typ":7,"nodiscard_object_type_with_reason":7,"nodiscard_return_typ":7,"nodiscard_return_type_with_reason":7,"nodiscard_routin":7,"nodiscard_routine_with_reason":7,"noexcept":[7,8,9,11,16],"noinlin":7,"noisi":24,"nomin":21,"non":[0,1,2,3,5,6,7,9,10,11,14,15,16,17,18,19,21,22,24,25],"non_arith_operation_in_templ_arg":7,"non_autonomous_opaque_enum_decl":7,"non_c_like_because_of_base_class":7,"non_c_like_because_of_default_member_init":7,"non_c_like_because_of_friend":7,"non_c_like_because_of_lambda":7,"non_c_like_because_of_memb":7,"non_c_like_typedef_for_linkag":7,"non_integral_operation_in_templ_arg":7,"non_pod_passed_to_ellipsi":7,"non_pod_va_arg":7,"non_scalar_vacuous_dtor_cal":7,"non_template_structured_binding_pack":7,"non_thread_local_follows_thread_loc":7,"non_unicode_char_in_head":7,"non_unicode_char_in_id":7,"non_zero_int_conv_to_point":7,"nonautomatic_var_in_constexpr_funct":7,"nonbool_arith_operand":7,"nonbool_atomic_constraint":7,"nonclass":[3,6,10,11,15,16,21,23],"nonclass_prototype_instanti":11,"nonclass_template_instantiations_in_source_sequence_list":[11,21,22],"noncompli":10,"nonconst":[6,7,9,10,16],"nonconst_defaulted_member_comparison":7,"nonconst_ref_anachron":10,"nonconst_ref_init_anachron":7,"nonconst_ref_init_from_rvalu":7,"nonconstant_enable_if_attr":7,"nonconstant_field_initializer_in_mem_initi":7,"nonconstant_mem_init_for_constexpr_ctor":7,"nonconstant_offsetof":7,"nonconstant_splicer_operand":7,"nonconsteval_overrides_constev":7,"nonconstexpr_call_in_mem_initi":7,"nonconstexpr_mem_init_ctor_for_constexpr_ctor":7,"nondeclar":21,"nondeduc":10,"nondefin":23,"nondefining_friend_requires_claus":7,"nondelet":7,"nondeleted_function_overrides_deleted_funct":7,"nondep_cal":14,"nondepend":23,"nondependent_cal":23,"nondiscretionari":0,"none":[1,3,7,9,10,11,14,15,16,17,21,22,23],"nonempti":[3,23],"nonetheless":6,"nonexist":9,"nonexplicit":23,"nonexternal_entity_in_template_arg":7,"nongener":6,"noninlin":[8,10,23],"nonintegral_shuffle_mask":7,"nonliter":7,"nonliteral_param_type_in_constexpr_funct":7,"nonliteral_return_type_in_constexpr_funct":7,"nonliteral_var_in_constexpr_funct":7,"nonloc":[3,7,26],"nonlocal_label_refer":7,"nonlocal_vla_not_allow":7,"nonmanaged_function_for_deleg":7,"nonmemb":[3,7,9,10,21,22,23],"nonmember_enum_templ":7,"nonmember_operator_function_lookup":[9,21],"nonmember_operator_not_allow":7,"nonmember_reflection_for_intrins":7,"nonmember_using_declar":6,"nonnest":[10,21],"nonnul":[7,11,16],"nonnull_on_nonpoint":7,"nonnull_parameter_number_too_larg":7,"nonobject_pointer_arithmet":7,"nonoverrid":3,"nonpoint":7,"nonpreprocess":18,"nonpubl":[7,10],"nonpublic_data_member_in_public_cppcx_value_typ":7,"nonpublic_implicit_interface_match":7,"nonreal":[15,23],"nonreal_member_symbol_kind":21,"nonreus":15,"nonsens":14,"nonshared_blocksizeof":7,"nonshared_strict_relax":7,"nonstandard":[0,6,7,10],"nonstandard_alias_declaration_context":7,"nonstandard_anonymous_union_qualifi":7,"nonstandard_array_with_flexible_array_el":7,"nonstandard_bit_field_initi":7,"nonstandard_conversion_for_cleanup":7,"nonstandard_conversion_from_scoped_enum":7,"nonstandard_explicit_bool":7,"nonstandard_lambda_attribut":7,"nonstandard_long_float":7,"nonstandard_parenthesized_string_initi":7,"nonstandard_ptr_minus_ptr":7,"nonstandard_secondary_decl_specifi":7,"nonstandard_use_of_explicit_default_constructor":7,"nonstat":[5,6,7,9,10,11,16,21],"nonstatic_addressof_operator_in_managed_class":7,"nonstatic_member_def_not_allow":7,"nonstd":10,"nonstd_address_of_ellipsi":7,"nonstd_address_of_label":7,"nonstd_anonymous_union":10,"nonstd_array_cast":7,"nonstd_asm_funct":7,"nonstd_assigned_goto":7,"nonstd_bit_field_typ":7,"nonstd_brac":7,"nonstd_character_at_start_of_macro_def":7,"nonstd_const_memb":7,"nonstd_const_member_decl_not_allow":7,"nonstd_default_arg":7,"nonstd_default_arg_deduct":10,"nonstd_default_arg_on_function_template_redecl":7,"nonstd_ellipsis_only_param":7,"nonstd_extra_comma":7,"nonstd_fixed_point_suffix":7,"nonstd_forward_decl_enum":7,"nonstd_friend_decl":7,"nonstd_gnu_keyword":[7,10],"nonstd_ignored_array_cast":7,"nonstd_implicit_int":7,"nonstd_instantiation_lookup":10,"nonstd_long_long":7,"nonstd_member_function_address":7,"nonstd_old_speci":7,"nonstd_opaque_enum_decl_in_type_id":7,"nonstd_pp_direct":7,"nonstd_qualified_void_param_list":7,"nonstd_qualifier_deduct":[7,10],"nonstd_qualifier_in_global_scope_decl":7,"nonstd_qualifier_in_namespace_member_decl":7,"nonstd_reinterpret_cast":7,"nonstd_template_void_param_list":7,"nonstd_unnamed_field":7,"nonstd_unnamed_memb":7,"nonstd_using_decl":[7,10],"nonstd_void_param_list":7,"nonstrict":10,"nontempl":[3,23],"nontrivi":[3,6,7,10,16],"nontyp":[7,9,10,11,15,16,21,23],"nonuniform":10,"nonunion":7,"nonvalue_class_type_cannot_be_value_class_memb":7,"nonviable_because_arg_mismatch":7,"nonvirtu":[3,7,11,16],"nonzero":[3,7,10,11,14,16,24,26],"noreturn":[6,7,18],"noreturn_function_does_return":7,"noreturn_with_return_typ":7,"normal":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24],"normal_ref_bound_to_cppcx_lvalu":7,"normal_ref_bound_to_gc_lvalu":7,"normal_termin":0,"normat":10,"not_a_base_class_memb":7,"not_a_class_or_struct_nam":7,"not_a_class_templ":7,"not_a_field":7,"not_a_field_nam":7,"not_a_field_or_base_class":7,"not_a_generic_param":7,"not_a_line_splic":7,"not_a_memb":7,"not_a_member_class":7,"not_a_tag_memb":7,"not_a_templ":7,"not_a_template_nam":7,"not_a_type_memb":7,"not_a_type_nam":7,"not_a_type_reflect":7,"not_a_vari":7,"not_an_actual_memb":7,"not_an_enum_typ":7,"not_an_enum_type_nam":7,"not_captured_local_var_in_lambda":7,"not_captured_this_in_lambda":7,"not_class_memb":7,"not_compatible_with_previous_decl":7,"not_compatible_with_templ_templ_param":7,"not_enough_preallocated_memori":7,"not_found_on_pack_alignment_stack":7,"not_generic_param_of_curr_decl":7,"not_global_namespac":7,"not_instantiatable_ent":7,"not_used_in_partial_spec_arg_list":7,"not_used_in_template_function_param":7,"notabl":[6,8,10,16,17,21],"notat":[3,9,16],"note":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25,26],"noteworthi":[9,10],"noth":[0,8,9,10,11,14,16,17,20,22],"nothrow":[6,7,18],"notic":[10,16,23],"notifi":25,"notion":[3,6,23,24],"notreach":[10,15],"novel":10,"now":[2,3,8,9,14,16,20,21,23],"nowher":[9,11],"np":0,"ns":15,"nsdmi":3,"nsdmis":11,"nsk_label":21,"nsk_macro":21,"nsk_other":21,"nt":0,"nt_util":1,"nuisanc":9,"null":[0,2,3,4,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,25],"null_argument_for_nonnull_paramet":7,"null_char_ignor":7,"null_char_in_header_nam":7,"null_char_in_str":7,"null_express":7,"null_refer":7,"null_reflect":7,"null_routin":7,"null_typ":7,"nullabl":7,"nullptr":[7,10,11,16],"nullptr_conv_to_bool":7,"nullptr_operand":7,"nullptr_t":[7,11,16],"num_":11,"num_active_position_track":15,"num_classes_on_scope_stack":21,"num_elem":16,"num_l_paren":4,"num_r_paren":4,"num_slow_tests_report":24,"number":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,19,21,22,23,24,25,26],"number_of_el":19,"numer":[0,9,10,15],"nw":16,"nwa":16,"nx":16,"o":[0,1,10,16,19,24,26],"obey":10,"obj":24,"object":[0,1,2,5,6,7,8,9,10,13,14,15,17,19,20,21,23,26],"object_addr_table_index":16,"object_not_initi":7,"object_temp":16,"object_typ":16,"obscur":15,"observ":[3,17,18,21],"obsolet":[7,10,14],"obtain":[1,7,11,15,17,21,23],"obvious":[0,2,3,9,11,14,15,16,17,23],"occasion":[1,9,10,24],"occupi":[3,7,15],"occur":[0,3,5,6,7,8,9,10,11,14,15,16,17,18,21,23,24,25],"occurr":[3,5,10,14,15,16,22],"octal":[7,10,15],"odd":[9,10],"odlg_1_i1io":16,"odr":[10,16],"offend":10,"offer":[3,10,11],"offici":[0,3,17],"offset":[0,7,8,9,10,11,14,15,16,17,19],"offset_bit_remaind":[3,11],"offset_in_non_pod_nonstandard":7,"offsetof":[7,9,10],"offsetof_bit_field":7,"offsetof_nonfield":7,"offsetof_ref_field":7,"offsetof_virtual_base_memb":7,"ofil":10,"often":[0,1,3,6,9,10,11,14,15,16,17,21,22,23,24,25],"ok":[10,24],"ok_braced_init_list":9,"ok_property_ref":9,"okay":[0,2,9,10,15,16,20,22],"okay_as_output_fil":0,"old":[2,3,6,7,9,10,11,14,15,16,22,23],"old_c":10,"old_fashioned_assignment_oper":7,"old_fashioned_field_select":7,"old_fashioned_initi":7,"old_fashioned_ptr_field_select":7,"old_for_init":10,"old_id_char":10,"old_line_command":10,"old_speci":[7,10],"old_specialization_not_allow":7,"old_style_incompatible_param":7,"old_style_parameter_list":7,"old_style_preprocess":10,"older":[4,6,9,10,11,12,16],"oleaut32":1,"omiss":7,"omit":[3,7,10,11,14,15,16,20,24],"omitted_exception_specif":7,"omitted_exception_specification_on_speci":7,"on_primary_declar":18,"onc":[0,1,2,3,5,6,7,8,9,11,14,15,16,17,18,20,21,22,23,24,25],"one":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,19,20,21,22,23,24,26],"one_instantiation_per_object":[0,2,7,10,11,16],"one_level_up":7,"one_th":4,"ongo":10,"onli":[0,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"only_applies_to_float_typ":7,"only_gnu_attributes_her":7,"onto":[0,3,6,8,11,15,16,17,18,20,21,22,23,25],"onwg_1_cil_2_10z1z_1_cil_1_0o":16,"op":[4,10,17],"op1":16,"op2":16,"op_arrow_loop":7,"op_is_zero_const":9,"opaqu":7,"open":[0,4,6,7,10,11,14,15,21,23],"open_file_and_push_input_stack":15,"open_file_for_input":15,"open_output_fil":0,"open_source_fil":0,"open_temp_fil":0,"oper":[0,1,3,4,5,6,7,8,10,14,15,17,19,22,23,24,25,26],"operand":[2,6,7,8,10,11,14,16,21],"operand_must_be_real_floating_valu":7,"operand_must_be_vector":7,"operand_type_pattern_for_oper":9,"operation_has_side_effect":11,"operation_may_not_fit_in_fixed_point_result":7,"operation_type_kind":11,"operator_lookup_namespac":21,"operator_name_not_allow":7,"operator_not_allowed_after_new":7,"operator_not_allowed_in_cpp11_constant_expr":9,"operator_takes_lvalue_operand":11,"operator_token_for_expr_rescan":9,"operatorsort":17,"opinion":0,"opl_2_z1zz2zo":16,"opnam":21,"opname_function_symbol":21,"opname_kind":11,"opname_kind_for_token":21,"opname_member_function_symbol":9,"opname_symbol_head":21,"opname_symbol_t":21,"opportun":10,"oppos":[0,8,9,11,16,17],"opposit":[10,26],"opt":17,"opt_declaration_list":20,"opt_idf":17,"opt_univers":17,"optim":[0,9,10,11,13,14,15,17,21],"optimized_expr_for_select":5,"optimum":14,"option":[0,2,3,5,6,7,8,9,11,12,13,14,15,16,17,18,20,22,23,24,25,26],"options_al":24,"options_sep":24,"or_integer_valu":9,"order":[0,1,2,3,5,6,7,9,10,14,15,16,17,18,19,20,21,23,24,26],"ordin":11,"ordinari":[0,3,5,6,7,9,10,11,16,18,21,23],"ordinarili":[0,2,3,6,10,14,15],"org":16,"organiz":[6,10,11,15,24],"orient":14,"orig_column":[11,15],"orig_line_modif_list":15,"orig_seq":[11,15],"orig_src":16,"origin":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,18,21,22,23,24,25],"orphan":0,"orphaned_file_scope_il_entri":[0,11,22],"oszz1z0o":16,"other_argu":4,"other_func":4,"other_macro":4,"other_macro_is_en":4,"other_other_macro_is_en":4,"other_th":4,"others":[0,1,2,3,5,6,9,10,11,14,15,16,21,22],"otherwis":[1,2,3,4,5,6,7,8,9,10,11,15,16,17,18,20,21,23,24,26],"out_of_class_initializer_ignor":7,"out_of_memori":7,"out_of_memory_during_pch_alloc":7,"out_of_order_ctor_init":7,"out_of_order_field_allocation_nonstandard":7,"outer":[3,7,10,11,20,21],"outermost":[0,3,10,11,16,21],"outlin":6,"output":[0,1,2,4,6,7,11,13,14,16,17,21,23,24,25,26],"output_dir":24,"output_mod":10,"outright":10,"outsid":[2,3,5,6,7,8,9,10,11,14,15,16,20,21,23,24],"outward":21,"overal":[0,1,3,6,9,10,11,14,15,16],"overflow":[3,7,9,10],"overhead":[10,11,14,15,16,17,23],"overlap":[3,7,21],"overlay":17,"overload":[0,6,7,10,11,14,15,16,17,22,23],"overload_anachron":7,"overload_check_ambiguity_and_verify_access":21,"overload_distinguish":22,"overloadable_attribute_requires_prototyp":7,"overloaded_function_catch_up":9,"overloaded_function_linkag":7,"overly":[2,5,13,14],"overrid":[0,2,3,7,10,11,16,17,24,26],"overridden":[0,1,2,3,7,10,11,14,16],"overridden_function_for_wrapp":16,"override_and_final_is_cpp11":7,"override_for_interface_memb":7,"override_member_does_not_overrid":7,"override_name_is_destructor_or_fin":7,"override_name_must_be_a_base_class_member_funct":7,"override_name_nonvirtu":7,"override_of_final_funct":7,"override_of_sealed_funct":7,"override_requires_virtu":7,"override_with_constraint_mismatch":7,"override_with_trivial_property_or_ev":7,"overriding_function_for_wrapp":16,"overriding_reduces_accessibility_in_managed_typ":7,"overriding_virtual_funct":3,"overview":[8,11,13,16],"overwrit":[9,10,15,24,25],"overwritten":0,"ovm":10,"owned":7,"owning":17,"owns":17,"p":[0,2,3,5,6,9,10,11,16,23,25],"p1":[9,16],"p2":9,"pa":[10,11],"pack":[7,9,11,14,16,23,24],"pack_align":10,"pack_expansion_for_field_mem_init":7,"pack_expansion_for_non_pack_alias_param":7,"pack_index_out_of_bound":7,"pack_indexing_is_cpp26":7,"pack_init_capture_in_non_variadic_context":7,"pack_init_capture_is_cpp20":7,"pack_init_capture_not_en":7,"pack_length_mismatch":7,"pack_not_expand":7,"pack_not_last_arg":7,"packag":[11,26],"packard":19,"pad":[7,16,17],"page":[7,10,13],"pain":11,"painless":10,"paint":3,"pair":[9,10,11,14,15,17,21,22,23,26],"pal":23,"panic":17,"paper":[9,10],"paragraph":[15,16],"parallel":[3,10,15],"param":[11,16,22,23],"param_cannot_be_complet":7,"param_id":23,"param_id_list_needs_function_def":7,"param_is_abstract":7,"param_is_incomplet":7,"param_not_allow":7,"param_pack_cannot_have_default":7,"param_type_list":16,"param_value_has_been_chang":21,"paramet":[0,2,3,6,7,8,9,10,14,15,16,18,21,22,25],"parameter":10,"parameter_array_on_operator_funct":7,"parameter_capture_conflict":7,"parameter_numb":7,"parameter_pack_decl_not_allow":7,"parameter_with_interface_typ":7,"parameter_with_link_scope_specifi":7,"parameteriz":10,"parameterizedent":17,"parametersm":23,"parcel":0,"paren":[4,24],"parens_in_il":11,"parent":[0,3,7,11,15,16,17,21,22],"parent_destruction_sublist":11,"parent_lifetim":11,"parent_macro_index":[11,15],"parent_scop":11,"parenthes":[0,2,5,6,7,9,10,15,20],"parenthesi":[6,7,9,10,11,15,18],"parenthesized_init_not_allow":7,"parm":10,"parmet":23,"pars":[1,3,7,10,13,15,23,25],"parse_braced_init_list_ful":9,"parse_templ":[7,10,11],"parser":[14,23],"part":[0,1,2,3,5,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25,26],"partial":[0,1,2,7,8,10,11,16,21,22],"partial_class_incorrect_type_or_loc":7,"partial_overrid":7,"partial_spec_after_instanti":7,"partial_spec_after_instantiation_ambigu":7,"partial_spec_arg_depends_on_templ_param":7,"partial_spec_is_primary_templ":7,"partial_spec_template_arg_list":23,"partial_speci":23,"partial_specialization_not_allow":7,"particip":[10,23],"particular":[0,1,2,3,4,5,6,9,10,11,14,15,16,17,18,19,21,22,23,24,25],"partit":7,"partition_kind":17,"pass":[0,1,2,3,4,6,7,8,9,10,11,13,14,15,16,17,18,19,21,22,23,24,25,26],"pass_directive_to_output":15,"pass_object_s":7,"pass_object_size_not_in_function_decl":7,"pass_pp_directive_to_output":15,"past":[6,7,9,15,17,18],"paste":[7,10,15],"paste_cannot_be_first":7,"paste_cannot_be_first_in_va_opt":7,"paste_cannot_be_last":7,"paste_cannot_be_last_in_va_opt":7,"patch":[1,14,16,24,26],"path":[10,11,15,23,24],"pathnam":10,"pathway":18,"pattern":[3,9,10,11,15,16,20,23,24],"pay":[0,11],"pbk_immedi":18,"pbk_next_construct":[10,18],"pbk_next_token":18,"pbk_other":18,"pbk_preproc_immedi":18,"pc":3,"pcc":[2,3,6,9,11,14,15],"pcc_address_of_array":7,"pcc_field_ambigu":7,"pcf":10,"pch":[7,10,14],"pch_cmd_line_option_mismatch":7,"pch_curr_directory_chang":7,"pch_decl_seq_threshold":10,"pch_dir":[0,10],"pch_file_incomplet":7,"pch_file_prefix_mismatch":7,"pch_file_suffix":10,"pch_header_files_have_chang":7,"pch_mem":[0,10],"pch_messag":10,"pch_verbos":10,"pdf":1,"pdm":16,"pdmn":16,"pe":3,"pe_info":3,"peculiar":25,"pedant":14,"pedep":23,"pend":[3,7,15,18,23],"pending_class_definit":3,"pending_instanti":[10,23],"pending_pragma":18,"peopl":16,"per":[0,1,2,9,10,11,14,15,16,17,23,24,26],"per_instantiation_needed_flag":[0,11],"percent":15,"percentag":[0,24],"perfect":[0,24],"perform":[1,3,4,6,7,8,9,11,14,15,16,17,18,21,23,24,25],"perform_deferred_access_check":21,"perform_deferred_access_checks_for_funct":21,"perform_if":15,"perhap":[0,1,14],"period":[8,10,11,16],"period_used_as_qualifi":7,"perman":[21,23],"permiss":[5,10],"permit":[3,6,7,9,10,15,16,21,23],"perobject":26,"persist":[22,23],"perspect":[10,11,16,17,22],"pertain":8,"pesep":23,"pf":[10,11],"pfc":11,"phase":[2,3,6,10,11,16,21,23,25],"philosophi":[11,13,16],"physic":15,"pick":[9,16,23,24],"pick_count":24,"piec":[0,3,8,10,11,14,16,17,18,21,22],"piggi":21,"pin":6,"pin_ptr":[0,6,7,9,11,16],"pin_ptr_param_not_allow":7,"pin_ptr_return_type_not_allow":7,"pipe":24,"pipelin":17,"pivot":18,"pk_instanti":18,"pk_lint_argsus":18,"pk_printf_arg":18,"pk_scanf_arg":18,"pk_unrecogn":18,"pl":16,"pl_default_use_definition_list_fil":26,"pl_nm":1,"place":[0,1,2,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"placehold":[6,7,9,11,22],"placeholder_type_failed_constraint":7,"placement":[6,7,10],"placement_new_refers_to_non_placement_delet":7,"plain":[1,7,10,23],"plan":16,"platform":[7,8,14,16,24],"play":[9,17,18,23],"plm":1,"plus":[0,2,9,11,16],"pm_call_obj_not_lvalu":7,"pm_call_obj_not_rvalu":7,"pm_class_typ":22,"pm_derived_class_from_virtual_bas":7,"pm_member_typ":22,"pm_virtual_base_from_derived_class":7,"pma":15,"pmf":[10,11,16],"pmf2":10,"pmf_temp":16,"pmg":16,"pmi1":10,"pmi2":10,"pod":[3,6,10],"poimt":11,"point":[1,2,3,5,6,7,8,10,13,14,15,16,18,19,20,21,22,23,25],"pointer":[0,2,3,5,6,7,8,9,10,14,15,17,18,20,21,22,23,26],"pointer_conversion_loses_bit":7,"pointer_conversion_to_same_size_int":7,"pointer_declar":6,"pointer_offset":3,"pointer_operand":7,"pointer_operand_is_second":11,"pointer_outside_base_object":7,"pointer_to_function_operand":7,"pointer_to_member_call_optimization_allow":16,"pointer_to_member_typ":6,"pointer_to_nonconst_for_literal_oper":7,"pointer_to_object_operand":7,"pointer_to_ref_or_interface_class":7,"pointer_to_refer":7,"pointer_to_scalar_requir":7,"pointless":[7,10],"polici":18,"pollut":17,"polymorph":[3,7,11,16],"polyvector":7,"pool":0,"pop":[0,3,6,7,8,10,11,15,16,18,20,21,22,23],"pop_class_reactivation_scop":21,"pop_eh_stack_fram":16,"pop_expr_stack":9,"pop_input_stack":[15,22],"pop_lexical_state_stack":15,"pop_macro":10,"pop_name_context":5,"pop_namespace_extension_scop":21,"pop_namespace_reactivation_scop":21,"pop_object_lifetim":[20,22],"pop_primary_include_search_dir":0,"pop_scop":[0,11,22,23,25],"pop_stmt_stack":20,"pop_stop_token_stack":[14,15],"pop_template_instantiation_scop":23,"popular":[1,14],"portabl":[1,2,7,10,13,16,17,19],"portion":[1,8,10,14,15,16,17,21,24],"pos":0,"pos_curr_token":[9,15],"pos_diagnost":9,"pos_error":9,"pos_ty2_warn":0,"pos_warn":9,"pose":21,"posit":[0,1,2,3,4,5,6,7,9,10,13,17,18,20,21,22,23,24,25],"positional_after_nam":7,"positional_format_specifier_zero":7,"possibl":[0,1,2,3,5,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"post":[0,9,11,20],"postfix":[7,9,10,16],"postincr":16,"potenti":[0,3,7,8,9,10,11,14,15,16,17,21,22,23],"power":[7,10,11,17],"power_idx":17,"pp":[10,15,16],"pp_direct":15,"pp_else_already_appear":7,"pp_if_stack":15,"pp_if_stack_depth":15,"ppe":16,"practic":[9,10,11,14,16,17,21],"pragma":[0,2,6,7,9,14,15,16,22],"pragma_description_for_pragma_kind":18,"pragma_gcc_system_header_in_primary_fil":7,"pragma_id":18,"pragma_init":18,"pragma_inside_funct":7,"pragma_may_not_be_used_her":7,"pragma_must_precede_decl_or_stmt":7,"pragma_must_precede_declar":7,"pragma_must_precede_stat":7,"pragma_pack_show_args_ignor":7,"pragma_weak_allow":10,"pre":[2,7,9,10,11,25],"prealloc":[0,7,10],"prec_level":9,"preced":[0,1,4,5,6,7,8,9,10,11,13,14,15,16,18,20,21,22,23],"precheck":17,"precis":[0,3,10,11,13,15,16,20,21,23],"preclud":[0,16],"precompil":[7,11,14,15],"predeclar":[1,7,10],"predeclared_function_cannot_be_delet":7,"predef_macro_redefin":7,"predefin":[1,6,7,11,14,15,16,21],"predefined_macro":[0,1],"predefined_macro_file_nam":0,"predic":[10,15,22,23],"predict":[0,16],"prefer":[3,7,16,20,21,23,24],"prefix":[2,3,4,5,6,7,9,10,14,16,17,18,23,24,25,26],"preinclud":10,"preinclude_macro":10,"preliminari":[10,21],"prelink":[1,10,13,14,16,26],"preload":0,"prelow":16,"prelower_class_typ":16,"prematur":[10,18],"premium":10,"prentic":10,"prep_":9,"prep_aggr_initi":[6,9],"prep_argument_operand":9,"prep_assignment_operand":9,"prep_conversion_operand":9,"prep_elision_initializer_operand":9,"prep_initializer_operand":9,"prep_list_initi":9,"prep_return_by_cctor_operand":9,"prepar":[6,9,20],"prepare_for_trans_unit_copi":25,"prepend":21,"preproc":[0,6,14,15,18,22],"preproc_init":0,"preprocess":[0,5,7,9,10,11,12,13,14,16,18,19,23],"preprocessor":[1,7,9,13,14,15,24,25],"prerequisit":0,"prescan":[3,6,23],"prescan_decl_specifi":6,"prescan_declar":6,"prescan_default_arg_expr":[3,23],"prescan_function_declar":6,"prescan_function_definit":3,"prescan_initializer_for_auto_type_deduct":6,"prescrib":16,"presenc":[1,2,3,6,10,11,15,16,18,21,23],"present":[0,1,3,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25],"preserv":[0,2,3,6,7,8,9,10,11,14,15,16,18,21,23,25,26],"preserve_lvalues_with_same_type_cast":10,"pressur":24,"presum":[9,17,24],"pretti":[2,16,17],"preus":[0,6,10,15],"prev_ns_inlin":7,"prev_ns_not_inlin":7,"prevent":[0,7,10,11,17,18,21,23,24,26],"previous":[0,1,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,26],"previous_consteval_decl_conflict":7,"previous_constexpr_decl_conflict":7,"previous_nonconsteval_decl_conflict":7,"previous_nonconstexpr_decl_conflict":7,"previous_scop":21,"price":0,"primari":[0,3,5,7,9,10,11,14,15,16,18,21,22,23,24,25],"primarili":[1,6,11,16,17,18,20,21,23,24],"primary_base_class":3,"primary_cpf":24,"princip":[3,6,8,15,16,18,21,23,25],"principl":[3,9,10,17,25],"print":[0,8,14,15,16,17,24],"print_markered_text":15,"printer":11,"printf":[0,4,8,10,16],"printf_arg_mismatch":7,"prior":[1,3,7,8,9,10,16,17,23,24],"priorit":4,"prioriti":[7,10],"privat":[3,4,6,7,10],"private_virtual_member_function_not_s":7,"privileg":21,"probabl":[0,1,2,7,9,10,14,16,19,26],"probable_guiding_friend":7,"probable_inadvertent_lbracket_digraph":7,"probable_inadvertent_sharp_digraph":7,"problem":[0,1,2,3,6,7,8,10,11,14,15,16,17,20,21,22,23,25,26],"problemat":[11,24],"proc_":15,"proc_assert":15,"proc_command_lin":0,"proc_defin":15,"proc_elif":15,"proc_els":15,"proc_endif":15,"proc_error":15,"proc_id":15,"proc_if":15,"proc_ifdef":15,"proc_includ":15,"proc_lin":[15,22],"proc_pragma":[15,18],"proc_unassert":15,"proc_undef":15,"proc_us":15,"procedur":10,"proceed":[0,3,21,23],"proces":18,"process":[0,1,2,3,5,6,7,8,16,17,20,22,23,24,25,26],"process_converted_constant_express":9,"process_curr_construct_pragma":18,"process_curr_token_pragma":18,"process_deferred_class_fixup":3,"process_deferred_class_fixups_and_instanti":3,"process_deferred_instantiation_request":3,"process_generic_lambda_param_typ":3,"process_ifc_decl":17,"process_pending_instanti":25,"process_preus":[0,15],"process_runtime_checked_safe_cast":9,"process_translation_unit":[23,25],"process_verification_list":25,"processing_c_cod":18,"processor":[5,15],"produc":[0,1,2,3,6,7,8,9,10,11,13,14,15,16,17,19,21,22,23,25],"product":[1,9,10,14,26],"profil":5,"program":[0,2,3,5,7,8,9,10,11,13,14,15,18,19,21,23,24],"program_entity_too_large_for_pch":7,"program_too_larg":7,"programm":[0,8,10,11,13,14,16],"progress":[21,24,25],"prohibit":23,"project":[3,4,6,10,16],"project_base_class_conversion_funct":[3,21],"promis":[7,17],"promise_type_returns_return_void":7,"promot":[2,3,7,9,10,11,20,22],"promote_class_memb":16,"promote_label_and_goto_lifetim":20,"promote_local_entities_to_file_scop":16,"promote_operand":9,"promote_warn":10,"promoted_arith_operand":7,"promoted_integral_operand":7,"prone":14,"propag":3,"proper":[0,1,2,3,6,8,9,10,11,13,15,16,17,18,19,22,23,26],"properti":[7,10,17,18,21,23],"property_attribute_in_managed_class":7,"property_get_already_declar":7,"property_get_cannot_have_paramet":7,"property_get_index_type_mismatch":7,"property_get_index_type_miss":7,"property_name_not_allow":7,"property_requires_managed_class":7,"property_set_already_declar":7,"property_set_index_type_mismatch":7,"property_set_index_type_miss":7,"property_set_missing_value_paramet":7,"property_set_value_parameter_mismatch":7,"proport":16,"propos":[3,10],"protect":[3,5,7,10,15,16,21],"protected_access_problem":7,"proto":1,"protocol":14,"prototyp":[1,2,3,6,7,9,10,11,13,14,18,21,22,23],"prototype_instanti":23,"prototype_instantiations_in_il":[1,11,23],"prototype_lost":7,"prototype_templ":23,"prove":20,"provid":[0,1,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"provis":[21,23],"provision":3,"proxi":[3,15,17],"proxy_class_for_template_param":21,"prune":[10,20],"prvalu":[7,9,11],"ps":[11,16],"pseudo":[3,6,7,9,10,11,15,16,18,21],"pt":16,"ptr":10,"ptr_conv_to_bool":7,"ptr_flag":16,"ptr_func_ptr_data_conv":7,"ptr_handle_or_ref_to_generic_param":7,"ptr_handle_or_ref_to_interior_ptr":7,"ptr_handle_or_ref_to_pin_ptr":7,"ptr_incomplete_throw":7,"ptr_or_ref_to_cli_array":7,"ptr_or_ref_to_incomplete_typ":7,"ptr_or_ref_to_qualified_function_typ":7,"ptr_to_incomp_array_arithmetic_allow":10,"ptr_to_mem_of_incomplete_class":7,"ptr_to_mem_to_non_memb":7,"ptr_to_member_cast_to_ptr_to_funct":7,"ptr_to_member_conv_to_bool":7,"ptr_to_member_of_handle_typ":7,"ptr_to_member_of_managed_class":7,"ptr_to_member_of_reference_typ":7,"ptr_to_member_of_type_void":7,"ptr_to_member_of_vla_typ":7,"ptr_to_member_operand":7,"ptr_to_member_typ":22,"ptr_to_member_typedef":7,"ptrdiff_t":[7,9,10,16],"ptrdiff_t_operand":7,"ptrepositori":10,"public":[3,6,7,8,10,15,16,21],"public_data_member_in_public_non_value_typ":7,"public_nested_type_in_cppcx_typ":7,"public_nondata_member_in_public_cppcx_value_typ":7,"publish":19,"pull":[6,10,17],"pure":[3,6,7,9,10,16,18],"pure_final_virtu":7,"pure_specifier_on_nonvirtual_funct":7,"pure_specifier_on_sealed_memb":7,"pure_virtual_definit":7,"pure_virtual_funct":7,"pure_virtual_member_templ":7,"purpos":[0,1,3,4,6,7,9,11,14,15,16,17,18,20,21,22,23,24],"push":[3,6,7,8,10,11,15,16,18,20,21,22,23],"push_class_reactivation_scop":21,"push_eh_stack_fram":16,"push_expr_stack":9,"push_input_stack":[15,22],"push_instantiation_context":21,"push_lexical_state_stack":15,"push_macro":[7,10],"push_name_context":5,"push_namespace_extension_scop":21,"push_namespace_reactivation_scop":21,"push_object_lifetim":[20,22],"push_opt":7,"push_primary_include_search_dir":0,"push_scop":[20,23],"push_scope_ful":21,"push_stmt_stack":20,"push_stop_token_stack":[14,15],"push_template_instantiation_scop":[21,23],"put":[0,2,3,5,6,7,8,9,10,11,14,15,16,17,21,23,24,25,26],"put_property_function_miss":7,"pvt_mod_fgmt_only_after_modul":7,"pwd":1,"python":24,"q":[3,10,11,16,22,24,25,26],"q2_1a1b":16,"qual":25,"qualif":[3,9,10],"qualifi":[0,2,3,4,5,6,7,9,10,11,14,15,16,21,22,23],"qualified_cli_accessor":7,"qualified_lookup":21,"qualified_name_not_allow":7,"qualified_name_redecl_sym":6,"qualified_name_requir":7,"qualified_reference_typ":7,"qualified_unnamed_bit_field_typ":7,"qualified_using_directive_lookup":21,"qualified_void_return_typ":7,"qualifier_dropped_in_ref_init":7,"qualifier_ignored_on_local_declar":7,"qualifier_in_member_declar":7,"qualifier_in_namespace_member_decl":7,"qualifier_must_be_base_class":7,"qualifier_not_allowed_on_managed_member_funct":7,"qualiti":16,"quantiti":[9,10],"quasi":23,"queri":[17,23],"question":[3,10,11,14,21],"queu":11,"quick":[17,21,24,25],"quirk":16,"quit":[0,1,3,9,10,11,15,16,17,18,21],"quo":10,"quot":[0,7,10,15,26],"quoted_default":7,"quoted_error":7,"quoted_express":7,"quoted_unnam":7,"r":[2,5,7,9,11,15,16,18,24,25,26],"r_declar":[6,18],"ra":24,"race":1,"rais":[3,7,16],"ran":24,"random":[0,15,24],"rang":[1,7,10,11,14,15,16,17,20,21],"range1":10,"range_based_for_incomplete_array_typ":7,"range_based_for_missing_funct":7,"range_based_for_no_matching_overload":7,"range_based_for_nonstandard":7,"range_based_for_undefined_identifi":7,"rank":[6,22,24],"rapid":[10,24],"rare":[9,11,15,17,25],"rather":[0,1,2,3,5,7,8,9,10,11,14,15,16,17,18,21,22,23,25],"raw":[0,7,10,14],"raw_result":17,"raw_text":15,"rc":[3,16],"rcblock":9,"rcc2":16,"re":[0,1,2,3,11,14,15,16,17,20,22,23],"reach":[0,6,8,9,10,11,14,15,16,20,21,23,25],"reachabl":[7,20],"reachablepropertiesbitfield":17,"reactiv":[3,6,9,21,23,25],"reactivate_class_and_instantiation_scop":21,"read":[1,2,3,5,7,10,11,13,14,16,23,25,26],"read_auto_instantiation_inform":23,"read_logical_source_lin":15,"read_memory_region":0,"readabl":[0,1,2,10,13,14,18],"reader":[6,13,15,16],"readi":17,"readili":[23,26],"readm":1,"real":[0,2,6,7,9,10,11,14,15,16,17,21,23],"real_and_imag_applied_to_real_valu":7,"real_and_imag_require_complex_argu":7,"real_imaginary_convers":7,"realist":[17,24],"realiz":16,"realli":[0,3,5,6,9,10,11,16,22,23,25],"realloc":[14,15,21],"realloc_buff":[0,14],"reascend":0,"reason":[0,3,4,6,8,9,10,11,14,15,16,17,18,21,23,24,25],"reassign":25,"recach":23,"recal":[10,16,23],"receiv":[3,6,7,9,10,11,15,16,24],"recent":[1,10,11,16],"recheck":21,"reclaim":[0,11,21],"reclassifi":18,"recod":15,"recogn":[3,6,7,9,10,11,14,20,22,23],"recognit":[10,15,18],"recognize_keywords_in_pragma":15,"recognize_microsoft_attribut":6,"recombin":0,"recommend":[1,10,24],"recompil":[0,10,26],"recomput":[0,21],"reconstitut":5,"reconstruct":[0,7,11,15,17],"record":[0,1,3,6,8,9,10,11,14,15,16,20,21,22,23,25],"record_arg_pragma":18,"record_builtin_typ":25,"record_end_of_lifetime_destruct":22,"record_end_of_source_fil":22,"record_hidden_names_in_il":22,"record_inclass_initializer_fixup":3,"record_instanti":25,"record_lint_argsused_and_varargs_st":[15,18],"record_macros_in_il":[1,11,22],"record_needed_destruct":16,"record_nondependent_cal":9,"record_operator_position_in_rescan_info":9,"record_partial_aggregate_cleanup_destruct":6,"record_pragma_text":18,"record_predeclared_template_funct":23,"record_start_of_source_fil":22,"record_struct_binding_expr_for_array_el":6,"record_struct_binding_expr_for_field":6,"record_switch_case_entri":20,"record_symbol_declar":21,"record_symbol_refer":[9,21],"record_template_str":[11,23],"record_unrecognized_attribut":[11,18],"record_virtual_function_overrid":3,"record_vla_component_types_for_low":16,"recours":11,"recov":[5,9,11,14,16],"recoveri":18,"recreat":10,"recurs":[0,3,6,7,9,10,13,15,16,17,21,23,25,26],"recursive_def_arg_instanti":7,"recursive_initializer_instanti":7,"recursive_inst_of_templ_default_arg":7,"recycl":6,"redecl_changes_access":7,"redeclar":[0,7,10,11,21,23],"redeclaration_adds_dll_interfac":7,"redeclaration_of_condition_decl_nam":7,"redeclaration_of_for_init_decl_nam":7,"redeclaration_of_friend_with_default_arg":7,"redeclaration_of_range_iter":7,"redeclaration_of_template_param_nam":7,"redefin":[0,10,11,15,17],"redefine_extname_pragma_en":10,"redefinit":[3,7,15],"redirect":[10,14],"redo":9,"redon":25,"reduc":[0,1,7,10,11,13,14,15,16,17,21,23,24,25],"reduct":[0,7],"redund":[7,10,11,21],"redundant_exception_specification_typ":7,"reemit":18,"reenter":21,"reenter_symbol":21,"reevalu":[17,18],"ref":[0,3,4,6,7,10,11,15,16,17,23],"ref_bound_to_initonly_field":7,"ref_class_has_multiple_ref_bas":7,"ref_class_initonly_field":7,"ref_class_not_satisfi":7,"ref_entri":9,"ref_mbr_suppresses_copy_asgn_decl":7,"ref_not_allowed_in_union":7,"ref_or_interface_class_member_in_standard_class":7,"ref_qualifier_ignor":7,"ref_qualifier_nonstandard":7,"ref_qualifier_not_allow":7,"ref_to_nested_function_var":7,"refer":[0,2,3,6,7,8,10,14,16,17,20,21,22,23,25,26],"referenc":[0,3,7,8,9,14,15,16,17,21,22,23,25,26],"reference_declared_mut":7,"reference_to_implicitly_invoked_funct":3,"reference_to_ref_or_interface_class":7,"reference_to_refer":7,"reference_to_trivial_default_constructor":[3,6],"reference_to_void":7,"reference_type_not_allow":7,"referenced_non_loc":11,"referencing_namespac":23,"reflect":[3,7,9,10,11,15,16,18,21,23],"reflection_of_overloaded_set":7,"regard":[5,9,10,11,14,15,16,21],"regardless":[0,9,10,11,15,16,24],"regener":[10,23],"regex":24,"region":[0,3,5,6,8,9,14,15,16,17,18,19,21,22],"region_scope_entri":0,"regist":[0,6,7,9,10,11,14,15,16,25],"register_clobbered_twic":7,"register_in_address_spac":7,"register_in_us":7,"register_keyword_deprec":7,"register_keyword_disallow":7,"register_macro_invoc":15,"register_mapped_variable_cannot_have_initi":7,"register_mapped_variable_must_be_pod":7,"register_name_on_nonregist":7,"register_pch_saved_vari":[0,14],"register_pointer_vari":15,"register_storage_class_conflict":7,"register_too_smal":7,"register_trans_unit_vari":[14,25],"register_trans_unit_variable_with_field":25,"register_used_and_clobb":7,"register_used_twic":7,"registr":14,"registri":14,"regular":[0,3,10,11,15,17,18,23,24],"rehost":13,"reiniti":[0,1],"reinsert":15,"reinstat":21,"reinterpret_cast":[7,9,16,17],"reinterpret_cast_conversion_poss":22,"reinterpret_cast_of_handl":7,"reiser":10,"reject":9,"relat":[0,1,2,3,4,7,8,9,10,11,14,15,17,18,21,23,25,26],"related_class_point":22,"relationship":[3,16,17,23],"relax":[7,9],"relaxed_abstract_check":10,"relaxed_constexpr_en":9,"releas":[0,8,10,11,14,15,16,19,26],"release_macro_buffer_region":15,"releg":14,"relev":[11,14,15,17,23,25],"reli":[1,3,6,15,16,17,19,21,22,23,24,25],"relink_unnamed_tag_symbol":[3,21],"reload":23,"rem_source_line_modif":15,"remain":[0,3,6,8,9,10,11,14,15,16,18,20,21,23,24,25],"remaind":[1,6,23],"remainder_integer_valu":9,"remap":[0,1,11,14,16,25],"remap_first_ptr_of_orphaned_file_scope_entry_array":11,"remap_il_header_point":0,"remap_last_ptr_of_orphaned_file_scope_entry_array":11,"remap_pointers_in_il_entri":0,"remap_ptr":11,"remark":[0,3,7,10,14,16,24],"remark_as_need":0,"rememb":[0,9,11,14,15,21],"remind":[9,11],"remot":11,"remote_idx":17,"remov":[0,3,7,8,9,10,11,14,15,16,17,18,20,21,22,23,25,26],"remove_control_flow_descr":20,"remove_from_destructions_list":22,"remove_from_routines_list":22,"remove_from_source_sequence_list":22,"remove_list_of_flow_control_descr":20,"remove_stop_token":[0,14,15],"remove_symbol":21,"remove_symbol_from_scope_list":21,"remove_unneeded_ent":10,"renam":[2,9,11],"render":[1,2,8,9,11,15,16,18],"rendit":10,"reopen":[0,6],"reopen_error_output_fil":0,"reopen_source_fil":0,"reorder":[0,10],"reorgan":15,"repeat":[1,3,6,9,10,11,13,15,16,18,21,23],"repetit":[0,7,11],"repetitions_of":7,"replac":[0,2,3,6,7,8,9,10,11,14,15,16,17,21,23,24,25],"replace_file_name_suffix":0,"replace_special_characters_in_mangled_nam":16,"report":[3,6,9,10,14,15,20,21,23,26],"report_gnu_extens":[7,10],"report_goto_past_init":20,"report_switch_past_init":20,"report_virtual_function_ambigu":3,"reposit":0,"repositori":[3,15,18,21],"repreent":9,"repres":[0,3,6,7,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26],"represent":[0,3,5,7,8,9,10,11,13,14,15,16,17,18,19],"reproduc":[0,10,21,23,24,25],"req":16,"request":[0,2,7,9,10,11,14,15,16,17,21,25],"requested_size_too_larg":7,"requir":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25,26],"require_func_prototyp":10,"required_token":[14,15],"requires_clause_arg_list_substitution_fail":7,"requires_clause_satisfi":23,"requires_expr_ellipsis_param":7,"requires_incompatible_with_previous_decl":7,"requisit":15,"requit":1,"rerecord":24,"rerun":[17,24,25],"rescan":[3,6,10,14,15,18,23],"rescan_cached_token":15,"rescan_expr_with_substitution_intern":9,"rescan_reusable_cach":15,"rescann":9,"reserv":[0,2,3,4,7,8,9,15,18,21,22,26],"reserved_dispos":7,"reserved_enumerator_nam":7,"reserved_fin":7,"reset":[0,10,11,14,15,21,23],"reset_curr_block_object_lifetim":20,"resid":[3,15,21],"resiz":[0,14],"resolut":[6,7,9,10,11,14,16,17,21,23],"resolv":[3,7,10,14,15,16,17,21,23,24,25],"resolved_foo":16,"resolver_result":16,"resolver_routine_requir":7,"resort":17,"resourc":24,"respect":[0,1,3,4,6,9,10,11,14,15,16,17,21,22,23,24,26],"respons":[6,8,11,16,17,18,21,23],"rest":[0,3,9,10,11,14,15,16,22,23],"restart":[7,15],"restor":[0,6,8,10,11,14,15,18,21,23,25],"restore_struct_stmt_stack":23,"restrict":[3,5,7,9,10,11,15,16,21,22,23],"restrict_not_allow":7,"restrict_pointer_to_funct":7,"restrict_qualifier_drop":7,"restrict_qualifier_ignor":7,"restructuredtext":26,"result":[0,1,3,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24],"resum":[6,9,15],"retain":[0,9,10,11,15,20,21,23,25,26],"retarget":13,"rethrow":[11,16],"retri":[3,21],"retriev":[3,6,9,11,14,16,17,18],"retroact":[3,10,23],"return":[0,2,3,5,6,7,8,9,10,14,15,17,18,20,21,22,23,24,25],"return_from_ctor_function_try_block_handl":7,"return_from_fin":7,"return_in_coroutin":7,"return_ref_init_requires_temp":7,"return_stat":20,"return_type_cannot_distinguish_funct":7,"return_type_is_interfac":7,"return_type_of_default_comparison_must_be_bool":7,"return_type_on_constructor":7,"return_type_on_conversion_funct":7,"return_type_on_destructor":7,"return_type_on_fin":7,"return_valu":7,"return_value_at":7,"return_void":7,"return_void_at":7,"returning_ptr_to_local_temp":7,"returning_ptr_to_local_vari":7,"returning_ref_to_local_vari":7,"returns_lvalue_instead_of_usual_rvalu":11,"reus":[0,3,6,10,11,14,15,16,17,20,21,22,23],"reusabl":[10,15,17,18,21],"reusable_cache_stack":15,"reveal":[3,10,17,20,24],"revers":[6,7,10,11,16,17,19,23],"review":24,"revis":[9,10,11,13,14,17],"revisit":[3,9,17],"rewrit":[1,2,3,7,9,11,15,16,25],"rewrite_compound_assign":16,"rewrite_property_refer":9,"rewrite_secondary_trans_unit_il_entity_pointers_used_in_primari":25,"rewrite_ucn_escape_char_in_low":[11,16],"rewritten":[2,9,10,11,16,23,25],"rewritten_property_reference_kind":5,"rid":0,"ridicul":16,"right":[0,2,3,4,6,7,8,9,10,11,14,15,16,17,18,20,21,23],"ritchi":10,"rl":16,"rn":24,"role":[18,23],"root":[0,6,11,21],"root_macro_invocation_record_block":11,"rough":[6,9,14,16,17],"round":0,"roundabout":23,"routin":[1,2,3,5,6,7,8,10,12,14,18,19,20,21,23,25,26],"routine_definition_needed_flag_is_set":0,"routine_fixup_list":21,"routine_name_linkag":11,"routine_type_is_nonstatic_member_funct":3,"row":17,"rp":24,"rparen":4,"rs":3,"rst":26,"rt":24,"rt_argument":15,"rt_null":15,"rt_raw_argu":15,"rt_right_raw_argu":15,"rt_stringized_raw_argu":15,"rt_text":15,"rtti":[1,7,10,16],"rtti_in_embedded_cplusplus":7,"rule":[3,6,7,8,9,10,11,14,15,16,17,18,20,21,23],"rule_out_expr_kind":9,"ruled_out_expr_kind":9,"run":[0,5,6,7,9,10,11,14,15,16,17,19,20,25,26],"run_config":24,"run_end_of_parse_act":6,"run_test":24,"run_test_default_config":24,"run_test_flag":24,"runaway":[10,23],"runaway_recursive_instanti":7,"runner":24,"runtim":[0,1,7,8,9,11,12,13,14,15,17,23,24,26],"runtime_uses_namespac":[10,12],"rvalu":[2,7,9,10,16,22],"rvalue_ctor_is_copy_ctor":10,"rvalue_ctor_is_not_copy_ctor":10,"rvalue_defaulted_member_comparison":7,"rvalue_expr_for_lvalu":22,"rvalue_ref":10,"rvalue_ref_template_paramet":7,"rvalue_reference_bound_to_lvalu":7,"rvalue_reference_catch_typ":7,"rvalue_reference_in_exception_specif":7,"rvalue_references_is_cpp11":7,"rvalueabl":11,"s":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"sacrific":17,"safe":[6,10,16,17,21,24],"safe_cast":[9,16],"said":[11,16,17,24],"sake":[11,17],"same_param_types_with_and_without_ref_qualifi":7,"same_param_types_with_different_exception_specif":7,"same_repr_ints_interchangeable_in_il":10,"sampl":[1,10,16,19,23,24],"sample_edg_eccp_config":1,"sane":17,"saniti":[15,17,24],"sarif":[7,10],"sat":7,"satisfi":[0,7,9,10,21,23],"save":[0,3,6,8,9,10,11,14,15,16,21,23,25],"save_rescan_info_for_braced_init_list":9,"saw":24,"say":[0,3,9,10,14,15,16,17,18,19,23],"sb":16,"sbyte":7,"sc":16,"sc_asm":11,"sc_auto":11,"sc_extern":[3,11,16],"sc_regist":11,"sc_static":11,"sc_unspecifi":[3,11],"scalabl":7,"scalar":[3,6,7,9,10,11],"scale":[11,16,20,24],"scan":[0,2,8,10,11,13,14,16,18,21,23,25],"scan_":9,"scan_add_oper":9,"scan_alignof_oper":9,"scan_ampersand_oper":9,"scan_and_record_cli_delegate_definit":[3,6],"scan_arith_prefix_oper":9,"scan_assert_predicate_refer":15,"scan_attribut":18,"scan_base_specifier_list":3,"scan_bit_oper":9,"scan_boolean_controlling_express":9,"scan_braced_init_list":[6,9],"scan_braced_init_list_as_operand":9,"scan_call_argu":9,"scan_case_label_const":9,"scan_cast_or_expr":9,"scan_char_const":15,"scan_char_liter":15,"scan_class_definit":[3,6,23],"scan_class_initializer_express":9,"scan_class_parenthesized_initi":[6,9],"scan_cli_array_init":9,"scan_cli_delegate_definition_from_assembly_import":6,"scan_cli_generic_class_definition_from_assembly_import":6,"scan_cli_property_or_event_head":3,"scan_comma_oper":9,"scan_compound_assignment_oper":9,"scan_concept_express":23,"scan_conditional_oper":9,"scan_const_cast_oper":9,"scan_constant_dimension_express":9,"scan_constant_initializer_express":9,"scan_conversion_oper":21,"scan_ctor_argu":9,"scan_declarator_attribut":18,"scan_default_arg_expr":9,"scan_defined_oper":15,"scan_delegate_initi":9,"scan_delete_oper":9,"scan_dependent_type_parenthesized_initi":6,"scan_dynamic_cast_oper":9,"scan_eq_oper":9,"scan_exception_specif":8,"scan_expr":[9,14],"scan_expr_as_init_compon":9,"scan_field_selection_oper":9,"scan_fold_express":9,"scan_for_each_express":20,"scan_fs_constant_express":3,"scan_full_initializer_expr_as_compon":[6,9],"scan_function_bodi":[3,6],"scan_function_cal":9,"scan_functional_notation_type_convers":9,"scan_generic_argument_list":23,"scan_gnu_attribute_group":18,"scan_handle_address_oper":9,"scan_identifi":[3,9],"scan_if_expr":15,"scan_indirection_oper":9,"scan_init_captur":3,"scan_intaddr_oper":9,"scan_integer_express":9,"scan_integral_constant_express":[6,9],"scan_label":20,"scan_lambda":[3,9],"scan_lambda_capture_list":3,"scan_lambda_declar":3,"scan_lambda_express":9,"scan_logical_oper":9,"scan_mem_initi":6,"scan_member_constant_initializer_express":[3,9],"scan_member_declar":23,"scan_microsoft_attribut":6,"scan_microsoft_function_modifi":3,"scan_mult_oper":9,"scan_new_oper":[6,9],"scan_noexcept_oper":9,"scan_nonmember_declar":6,"scan_nonstatic_data_memb":3,"scan_nontype_template_argu":15,"scan_numb":15,"scan_parenthesized_mem_init_arg":6,"scan_postfix_incr_decr":9,"scan_pp_express":[9,15],"scan_prefix_incr_decr":9,"scan_previously_decl_iterator_nam":20,"scan_ptr_to_member_oper":9,"scan_pure_specifi":3,"scan_range_based_for_express":20,"scan_real_declarator_id":6,"scan_reinterpret_cast_oper":9,"scan_rel_oper":9,"scan_requires_claus":23,"scan_requires_expr":23,"scan_return_express":[3,9],"scan_safe_cast_oper":9,"scan_shift_oper":9,"scan_simple_assignment_oper":9,"scan_sizeof_oper":9,"scan_static_cast_oper":9,"scan_string_liter":15,"scan_subscript_oper":9,"scan_tag_nam":[3,6,15,23],"scan_template_argument_constant_express":[9,15],"scan_template_argument_list":15,"scan_template_declar":23,"scan_template_param_list":23,"scan_throw_oper":8,"scan_top_level_metadata_declar":[0,6,15],"scan_typeid":9,"scan_unknown_template_arg_list":15,"scan_void_express":[9,20],"scan_whitespace_keyword":15,"scanf":10,"scanning_generated_code_from_metadata":6,"scenario":[15,24],"scene":[16,17],"scheme":[0,8,10,11,14,15,16,26],"scienc":14,"sck_block":20,"sck_class_reactiv":21,"sck_class_struct_union":21,"sck_function":22,"sck_namespac":6,"sck_namespace_extens":6,"sck_pragma":18,"sck_routin":21,"sck_template_declar":23,"sck_template_instanti":[21,23],"sco":10,"scope":[0,2,4,6,7,8,9,10,12,14,15,18,20,22,23,25],"scope_orphaned_list_head":0,"scope_region_entri":11,"scope_stack":[14,21],"scope_stk":[0,6,14,21],"scoped_enum_nonstandard_in_current_mod":7,"scoped_enum_operand":7,"scoped_enum_operation_type_mismatch":7,"script":[0,10,23,24,26],"script_fil":24,"se":[11,16],"seach":21,"seal":[3,7],"sealed_base_class":7,"sealed_cli_interfac":7,"sealed_constraint":7,"sealed_requires_virtu":7,"search":[0,3,7,8,9,10,11,12,13,14,15,17,21,22,23,24,25,26],"sec":24,"second":[0,2,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"second_argument_wrong_shap":7,"secondari":[0,5,6,11,14,18,22,23],"secondary_specifier_ignor":7,"secondary_st":4,"section":[0,1,3,6,8,9,10,11,14,15,16,17,18,21,22,23,24],"see":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"seek":0,"seem":[9,11,13,14,15,16,17,22,23,25],"seen":[0,3,6,10,11,15,16,20,21,22,25],"segment":0,"seldom":18,"select":[0,1,2,3,5,7,8,9,10,14,15,16,17,19,21,22,23,24,26],"select_best_candidate_funct":9,"select_best_partial_order_candid":23,"select_copy_constructor":21,"select_curr_construct_pragma":18,"select_default_constructor":21,"select_destructor":21,"select_overloaded_funct":9,"selection_initializer_nonstandard":7,"selector":[7,11,14,20],"selector_match_with_this_param":9,"self":[0,7,9,11,15],"self_friendship":7,"self_referencing_temporary_object":7,"semant":[6,7,9,10,11,14,16,17,18,20,23],"semicolon":[0,3,4,7,10,14],"sens":[5,6,10,11,14,16,21,23],"sensibl":14,"sensit":[3,7,21],"sentinel":7,"separ":[0,1,2,3,4,6,7,8,9,10,11,13,14,15,16,17,18,20,21,23,24],"separate_routines_for_file_scope_dynamic_init":16,"seq":11,"sequenc":[0,1,2,3,6,7,8,9,10,14,15,17,18,21,23,24,25,26],"sequence_id":15,"sequenti":[0,3,11,15,21],"seri":[6,9,10,11,14,15,17,18,23,24],"serial":17,"serious":16,"serv":[0,3,10,11,16,18,21,23,24],"servic":22,"set":[0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,23,24,25,26],"set_active_using_list_scope_depth":21,"set_array_type_s":22,"set_but_not_us":7,"set_class_definition_need":0,"set_class_definition_needed_flag":0,"set_class_keep_definition_in_il":0,"set_conditional_flag_var":16,"set_constant_kind":22,"set_decl_sequence_numb":21,"set_default_source_corresp":11,"set_err_pos_to_curr_token":14,"set_error_const":22,"set_expr_node_kind":22,"set_field_size_and_offset":3,"set_flag":1,"set_force_external_linkage_flag":22,"set_instantiation_required_for_template_class_memb":23,"set_integer_valu":9,"set_literal_type_flag":3,"set_macro_inv_record_ptr_to_index":11,"set_needed_flag":0,"set_needed_flags_at_end_of_file_scop":0,"set_nested_template_class_symbol_info":23,"set_node_oper":[11,22],"set_offset_for_virtual_function_info":3,"set_offsets_for_empty_nonvirtual_base_class":3,"set_offsets_for_field":3,"set_offsets_for_indirect_base_class":3,"set_offsets_for_nonvirtual_base_class":3,"set_offsets_for_virtual_base_class":3,"set_operand_kind":9,"set_output_posit":[2,5],"set_pointer_offset":9,"set_preferred_base_class_deriv":3,"set_routine_definition_need":0,"set_routine_definition_needed_flag":0,"set_routine_keep_definition_in_il":0,"set_severity_for_error_numb":0,"set_severity_for_error_tag":0,"set_signal_handl":0,"set_source_corresp":21,"set_src_seq_secondary_decl_field":22,"set_symbol_kind":21,"set_to_error_loc":21,"set_to_named_error_loc":21,"set_trans_unit_correspond":25,"set_type_kind":11,"set_type_s":[6,22],"set_unsigned_integer_valu":9,"set_up_for_cast_to_refer":9,"set_up_generic_lambda_declarator_scan":3,"set_up_overload_set_travers":9,"set_up_overload_symbol_list_travers":9,"set_up_routine_for_inlin":16,"set_up_variable_remapping_for_inlin":16,"set_used_in_exception_or_rtti_flag":[8,22],"set_virtual_function_numb":3,"setenv":1,"setjmp":[8,16,19],"setlocal":[1,10,15],"setlocale_lc_numeric_fail":7,"setup":[9,17],"sever":[0,2,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"sf":[10,16],"sfb_no_class_reactiv":3,"sfina":[9,10,16],"sfinae_requires_newer_abi_vers":7,"sfk_none":3,"sft":24,"sgi":26,"sgr":10,"sha256":17,"shape":[7,11],"share":[1,3,6,7,9,10,11,14,15,16,17,20,21,22,23,25],"shareabl":11,"shareable_constants_t":22,"shared_affinity_typ":7,"shared_block_size_must_be_posit":7,"shared_block_size_too_larg":7,"shared_inside_struct":7,"shared_nonthreads_dim":7,"shared_obj":15,"shared_paramet":7,"shell":[1,10,24],"shift":[7,9,10,11,15,16],"shift_count_too_larg":7,"shift_left_integer_valu":9,"shift_right_integer_valu":9,"shine":24,"ship":14,"short":[0,5,9,10,11,14,15,16,23],"short_enum":[7,10],"short_lifetime_temp":10,"shortcom":[2,26],"shortcut":3,"shorten":16,"shorter":[9,10],"should_be_instanti":23,"should_delay_finishing_of_function_bodi":21,"should_delay_lowering_on_funct":21,"shouldn":[4,11,14,25],"show":[0,5,7,9,10,11,16,22,23,24],"show_il_alloc_space_us":11,"show_pragma_conform_forscope_is_nonstandard":7,"show_pragma_conform_forscope_is_standard":7,"shown":[1,9,10,16,21,24],"shrt_max":1,"shuffl":[7,17],"shufflevector_index_out_of_rang":7,"sibl":11,"side":[0,6,7,9,10,11,16,21],"sig":[9,10],"sigint":[10,24],"sign":[0,2,3,7,9,10,11,14,15,16,22],"sign_extend_integer_valu":9,"signal":[0,1,23],"signatur":[3,7,10,11,14,16,18,21,23],"signed":[7,9,10,11,22],"signed_bit_field":10,"signed_bitint_width_too_smal":7,"signed_char":10,"signed_one_bit_field":7,"signed_unsigned_comparison":7,"signific":[0,2,3,8,9,10,11,14,15,16,17,18,21,23],"sigterm":[10,24],"silenc":[14,24],"silent":[10,24],"similar":[0,1,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,21,22,23,24,25,26],"similar_typedef":7,"simpl":[0,1,3,6,7,9,10,11,13,14,15,16,18,20,21,23,24,25],"simple_incompatible_param":7,"simpler":[9,11,15,16,18,24],"simplest":[9,11,15,17,21],"simpli":[0,1,2,3,4,5,6,8,9,11,14,15,16,17,18,21,23,24,25,26],"simplic":[9,24],"simplif":[9,16],"simplifi":[0,1,3,6,9,10,13,15,16,17,18,21],"simplify_curr_class_qualified_nam":6,"simplify_void_operand":9,"simplist":11,"simul":[2,6,9,10,23],"simultan":[10,18,23,24],"sin":10,"sinc":[0,1,2,3,6,7,8,9,10,11,14,15,16,17,18,20,21,22,23],"sinf":10,"singl":[0,1,2,3,4,5,6,7,9,10,11,13,14,15,16,18,20,21,22,23,25,26],"single_arg_postfix_incr_decr_anachron":7,"singular":11,"sinl":10,"sit":10,"site":[1,9,10,16,21,23],"situat":[0,1,3,11,14,15,17,18,21,25],"six":10,"size":[0,1,2,3,6,7,8,9,10,11,13,14,15,16,17,21],"size_affected_by_tail_pad":7,"size_elem":16,"size_t":[1,7,9,10,16,21],"size_t_arg":14,"size_without_virtual_base_class":3,"sizeless":7,"sizeless_type_not_allow":7,"sizeof":[6,7,9,10,14,16,17,23],"sizeof_bit_field":7,"sizeof_funct":7,"sizeof_il_entri":11,"sizeof_operand_not_parameter_pack":7,"sizeof_pack_in_non_variadic_context":7,"sizeof_ref_or_interface_class":7,"sizeof_t":1,"sjis":[1,10,15],"sk":16,"sk_class_or_struct":3,"sk_class_or_struct_tag":23,"sk_class_templ":[3,21,23],"sk_concept_templ":23,"sk_constant":[3,23],"sk_extern_funct":21,"sk_extern_vari":21,"sk_field":3,"sk_function_templ":[3,21,23],"sk_keyword":21,"sk_macro":21,"sk_member_funciont":23,"sk_member_funct":[3,21,23],"sk_namespac":[6,21],"sk_namespace_project":[6,21],"sk_overloaded_funct":[3,21,23],"sk_paramet":21,"sk_project":[3,21],"sk_property_set":3,"sk_property_symbol":3,"sk_routin":[6,21,23],"sk_static_data_memb":[3,21,23],"sk_type":[6,23],"sk_union":3,"sk_union_tag":23,"sk_variabl":[21,23],"sk_variable_templ":23,"skip":[0,3,5,7,9,10,14,24],"skip_lexical_typeref":[11,22],"skip_paren":11,"skip_to_endif":15,"skip_typeref":[11,14,22],"skip_typerefs_not_typedef":[11,22],"skip_white_spac":[14,15],"skipped_inaccessible_funct":7,"slant":3,"sleight":16,"slice":[0,2,11,16,25],"slight":[0,2,3,9,10,11,15,16,20,21,22],"slot":16,"slow":0,"slower":[9,21],"slowest":[11,24],"slowli":24,"small":[0,1,3,7,9,10,11,14,15,16,17,18],"smaller":[7,10,11],"smallest":10,"smallhash":23,"smart":10,"sn":18,"snake":[4,5,9],"snapshot":[0,10],"snip":17,"snippet":14,"softfloat":9,"softwar":[9,14,16],"solari":[1,26],"solut":16,"solv":[0,11,16],"some_contain":4,"some_error_in_curr_direct":15,"some_func":4,"some_pragma":18,"somehow":15,"someth":[0,2,4,5,6,7,8,9,10,11,14,15,16,17,23,24],"something_els":4,"sometim":[1,3,5,6,8,9,10,11,14,15,17,18,20,21,23,25],"somewhat":[2,3,5,6,9,10,11,16,20,21,23,25],"somewher":[10,11,15,16,18,21,23],"soon":[9,10,11,16,18,23,25],"sooner":23,"sophist":[0,10],"sort":[0,3,5,6,7,11,16,18,23],"sought":[3,10,14,21,25],"sourc":[0,2,3,6,7,8,9,10,13,16,18,19,20,21,23,24,25,26],"source_corresp":[3,11,21,25],"source_corresp_for_il_entri":11,"source_line_modif_list":15,"source_loc":[7,12],"source_posit":21,"source_sequence_entri":11,"source_sequence_list":[11,21,22],"source_valu":17,"sourceloc":17,"sp":16,"sp_col_predefined_macro":15,"space":[0,2,3,4,7,8,9,10,11,14,16,17,21,22,23,25],"span":15,"spars":16,"spawn":24,"speak":[10,16,21,23],"spec":[16,17],"special":[0,3,5,6,7,8,9,10,11,14,15,16,17,18,22,25,26],"special_class_template_not_found":7,"special_function_kind":3,"special_kind":[3,11],"special_member_coroutin":7,"special_subscript_cost":[7,10],"specialization_follows_param_list":7,"specialization_of_called_inline_template_funct":7,"specialization_of_referenced_ent":7,"specialization_of_referenced_entity_po":7,"specialization_of_referenced_templ":7,"specialization_of_unscoped_enum":7,"specialization_out_of_namespac":7,"specialized_with_old_syntax":23,"specif":[0,2,3,5,7,9,10,11,14,15,16,17,18,20,21,22,23,24,25],"specifi":[0,1,3,4,5,7,8,9,10,11,12,14,15,16,17,18,19,21,22,23,24,25,26],"specific_decl":23,"specific_def":23,"specific_symbol":[15,21],"specifiers_rang":11,"speed":[0,2,5,11,13,14,24],"speedup":10,"spell":[4,7,10,15,24],"spent":15,"sphinx":26,"spill":15,"spirit":11,"spite":[0,9,11,14],"splice":[7,10,11,15],"splice_is_not_a_member_of_class":7,"splicer":7,"split":[14,23],"split_token_cach":23,"sporad":14,"spot":[0,15,16,23],"spread":15,"sq":0,"squar":[6,7,10],"src":[1,16],"src_seq":14,"src_seq_sublist_list":11,"srcloc_column_bound":7,"srcloc_line_bound":7,"ss":10,"st":[0,10],"stabil":17,"stabl":[0,24],"stack":[0,3,5,6,7,10,11,14,16,18,20,21,22,23,25],"stack_offset_of":7,"stack_referenced_include_directori":10,"stage":[16,21,25],"stage_0":17,"stage_1":17,"stage_2":17,"stage_3":17,"stage_4":17,"stage_5":17,"stage_6":17,"stage_6_0":17,"stage_6_1":17,"stage_6_2":17,"stage_6_3":17,"stand":[1,5,6,9,10,16,21,22],"standalon":[0,7],"standalone_il_display":1,"standalone_utility_program":22,"standard":[0,1,2,3,7,8,9,10,11,13,14,15,16,18,19,20,21,22,23,26],"standard_array_member_in_managed_class":7,"standard_class_member_in_managed_class":7,"standard_class_nested_in_managed_class":7,"star_this_capture_nonstandard":7,"star_this_not_constant_valu":7,"start":[0,1,2,3,4,6,7,8,9,10,11,14,15,16,17,18,19,20,21,23,24,25],"start_block_stat":20,"start_error":0,"start_for_init_block":20,"start_il_fil":0,"start_map_region":7,"start_map_region_ignor":7,"start_of_curr_token":15,"start_of_region":15,"start_secondary_declar":6,"start_stmt_claus":20,"startup":[11,16,26],"state":[0,1,7,8,9,10,11,14,15,16,17,21,23,25],"state_catcher_us":4,"statement":[0,2,3,5,6,7,8,10,13,14,15,16,18,21,23,25],"statement_expr_in_default_arg":7,"statement_expr_with_vla_typ":7,"statement_expression_in_function_on":7,"statement_expression_is_gnu_extens":7,"static":[0,2,4,6,7,8,9,10,11,14,15,17,19,20,21,22,26],"static_accessor_in_nonstatic_property_or_ev":7,"static_assert":[7,11,17],"static_cast":[9,16],"static_cast_conversion_poss":22,"static_constructor_member_templ":7,"static_constructor_with_named_overrid":7,"static_constructor_with_param":7,"static_conversion_function_must_have_one_paramet":7,"static_data_member_not_allow":7,"static_data_member_not_allowed_in_unnamed_class":7,"static_default_indexed_properti":7,"static_dimension_nonstandard":7,"static_extern_templ":7,"static_lambda_nonstandard":7,"static_lambda_with_captur":7,"static_literal_field":7,"static_member_next":3,"static_member_operator_not_allow":7,"static_nonstatic_with_same_param_typ":7,"static_not_allow":7,"static_storage_variable_with_handle_or_tracking_ref_typ":7,"static_storage_variable_with_ref_class_typ":7,"static_typ":16,"static_used_by_instanti":0,"static_variable_in_inline_funct":7,"static_with_explicit_thi":7,"statist":0,"statment":6,"status":[0,8,17,21],"stay":[9,15,25],"std":[1,7,9,10,11,12,16,17],"std_alignof_with_expr_arg":7,"std_attributes_en":18,"std_attributes_is_cpp11":7,"std_float128_not_support":7,"std_initializer_list_has_dtor":7,"std_meta_substitute_bad_arg_reflect":7,"std_meta_substitute_fail":7,"std_thread_local_storage_specifier_en":10,"stdarg":10,"stdc":7,"stdc_host":10,"stdc_iec_559":10,"stdc_iec_559_complex":10,"stdc_iso_10646":10,"stdc_iso_10646_valu":10,"stdc_mb_might_neq_wc":10,"stdc_pragma_not_allowed_her":7,"stdc_zero_in_system_head":10,"stddef":10,"stderr":[10,14],"stdexcept":12,"stdfloat":12,"stdh":12,"stdin":[0,10,26],"stdio":[0,8,10],"stdlib":24,"stdout":[0,10,14,24,26],"step":[0,1,5,8,9,10,15,16,17,18,21,23,25],"still":[0,1,2,3,4,5,7,8,9,10,11,14,15,16,18,21,23,26],"still_an_lvalu":9,"stl":[9,11],"stmk_asm":11,"stmk_block":[8,11],"stmk_decl":11,"stmk_end_test_whil":11,"stmk_expr":11,"stmk_for":[11,20],"stmk_for_each":11,"stmk_goto":11,"stmk_if":11,"stmk_init":[11,16],"stmk_range_based_for":20,"stmk_return":[11,16],"stmk_set_vla_s":[6,11,16],"stmk_switch":11,"stmk_switch_cas":[11,16],"stmk_try_block":[8,11,16],"stmk_vla_decl":[11,16],"stmk_while":11,"stmt_update_source_sequence_list":22,"stop":[4,6,9,10,11,14,15,21,24,25,26],"stop_map_region":7,"stop_map_region_ignor":7,"stop_token_array":14,"storag":[0,3,6,7,9,10,11,15,16,17,18,23],"storage_class_in_friend_decl":7,"storage_class_not_allow":7,"storage_class_not_allowed_in_speci":7,"storage_class_not_first":7,"storage_class_requires_function_or_vari":7,"storage_ptr":17,"storage_specifier_ignor":7,"storage_typ":17,"store":[0,2,3,5,7,8,9,10,11,15,16,17,18,21,22,23,24,25],"str":[0,4,6,7,10],"str_command_line_error":0,"str_error":14,"str_for":17,"str_for_integer_const":9,"straightforward":[0,1,2,3,5,10,11,16,21],"strang":[5,9,11,16],"strategi":20,"stray_carriage_return":7,"strchr":15,"stream":[3,23],"strength":10,"stress":[2,16],"strict":[0,6,7,10,11,16,18,21],"strict_ansi_discretionary_sever":0,"strict_ansi_error_sever":[0,14],"strict_ansi_mod":14,"strict_gnu":10,"strict_warn":10,"stricter":[10,23],"stricter_template_check":10,"stride":2,"string":[1,2,5,6,7,8,9,10,11,14,15,16,17,18,21,23,24,26],"string_literal_cannot_initialize_flexible_array_memb":7,"string_typ":22,"string_view":7,"stringent":10,"stringiz":15,"stringized_arg":15,"strip":[11,14],"strip_local_typedef":22,"strive":0,"strlen":10,"strong":[7,21],"struct":[0,2,3,4,5,6,7,8,9,10,11,14,15,16,17,18,21,22,23,25],"struct_binding_constev":7,"struct_binding_constexpr":7,"struct_binding_in_condit":7,"struct_binding_incomplete_typ":7,"struct_binding_inlin":7,"struct_binding_lambda":7,"struct_binding_packs_is_cpp26":7,"struct_binding_private_memb":7,"struct_binding_restricted_storage_class":7,"struct_binding_storage_class":7,"struct_binding_templ":7,"struct_binding_undefined_identifi":7,"struct_binding_with_multiple_declar":7,"struct_bindings_is_cpp17":7,"struct_declspec_ignored_in_c_mod":7,"struct_not_allow":7,"struct_stmt_stack":[14,20],"struct_too_larg":7,"structur":[0,1,3,5,6,7,8,10,11,12,13,16,17,18,19,20,21,22,24,25,26],"stt_gnu_ifunc":16,"stu":23,"stuck":24,"stuctur":6,"studi":13,"studio":[1,7,10,17],"style":[0,2,3,6,7,9,10,11,14,15,16,18,22,23],"sub":[7,11,17,24],"subaggreg":6,"subblock":20,"subcas":[9,14,22],"subdirectori":[1,24],"subexpress":[9,16],"subfield":7,"subject":[0,1,3,6,9,10,11,15,16,18,21,23],"subkind":16,"sublist":[11,22],"subobj_copy_asgn_decl_suppress":7,"subobj_copy_ctor_decl_suppress":7,"subobject":[3,7,10,11,16,17],"subordin":15,"subordinate_templ":23,"subrang":15,"subroutin":[0,2,3,9,11,14,15,16,20,21,22],"subscop":[11,25],"subscript":[3,7,9,10,16],"subscript_mechanism_conflict":7,"subscript_or_padd_pointer_operand":11,"subscript_out_of_rang":7,"subsect":[1,10,11,17],"subsequ":[0,3,6,7,8,9,10,11,15,18,20,21,23],"subset":[1,3,10,13,14,21],"subsidiari":15,"subst_arg_is_not_vari":7,"substag":17,"substanti":[0,1,16],"substitut":[0,1,7,9,10,16,23,26],"substitute_template_argu":23,"substructur":11,"subsum":9,"subt":21,"subtl":[3,5,16,23],"subtleti":9,"subtract":[7,9,10,11,16],"subtract_integer_valu":9,"subtre":[0,16,22],"succeed":[9,16,23],"success":[0,6,9,11,14,16,17,21,23],"successor":11,"suffic":15,"suffici":[1,6,9,10,11,18,21,22],"suffix":[0,1,2,7,10,12,14,15,16,23,25],"suggest":[0,9,15,16],"suit":24,"suitabl":[1,2,7,9,10,16,18,21,22,26],"sum":7,"summar":[1,3,8,9,11,18,21],"summari":[0,9,14,17],"sun":[1,2,7],"sun_extensions_allow":[1,10],"sun_is_generated_code_target":1,"sun_linker_scop":10,"sun_target_version_numb":1,"sunwcch":10,"super":17,"super_after_scop":7,"super_not_in_class":7,"superflu":20,"superfluous_delegate_object":7,"supersed":7,"superset":[10,11,16],"supplement":[3,6,8,9,11,18,22,23,25],"supplementari":[21,26],"suppli":[0,1,6,7,10,11,12,15,16,18,19,21,23,26],"supplment":11,"support":[0,3,6,7,9,11,13,14,15,17,18,19,20,22,23,25,26],"suppos":[3,7,9,10,11,25],"suppress":[0,1,2,5,6,7,9,10,14,15,16,18,21,23,26],"suppress_inline_bodi":[11,23],"suppress_instantiation_flag":[10,26],"suppress_microsoft_attribute_process":6,"suppress_subsequent_include_of_fil":15,"suppress_vtbl":[10,16],"suppressed_dtor_need":7,"suppressed_module_error_diag":7,"suppressed_module_errors_diag":7,"suppressed_module_warning_diag":7,"suppressed_module_warnings_diag":7,"sure":[0,2,10,11,14,16,17,18,19,21,23,24,25],"surfac":17,"surpris":11,"surrog":7,"surround":[0,1,2,7,9,10,11,14,15,16,23],"surviv":[0,11,14],"suspect":7,"suspend":[6,9,23],"suspici":[7,10],"suspicious_comment_format":7,"suspicious_string_format":7,"svr4":[7,26],"svr4_token_pasting_com":7,"swallow":23,"swap":16,"sweep":[0,2,11,16,25],"swept":0,"switch":[0,1,7,9,10,11,14,15,16,17,18,20,22,23,25],"switch_break_label":11,"switch_il_region":22,"switch_selector_expr_is_const":7,"switch_stat":20,"switch_translation_unit":25,"sy":0,"sym":[0,6],"sym_add_diag_info":0,"sym_not_a_class_templ":7,"sym_not_a_templ":7,"sym_not_a_type_nam":7,"sym_tbl_init":0,"sym_update_source_sequence_list":[21,22],"symbol":[0,1,5,6,7,9,10,13,14,15,16,18,22,23,25,26],"symbol_for_member_funct":3,"symbol_projected_from_base_class":21,"symbol_ref":[3,6,14,21,22],"symbol_supplement_for_class":21,"symbol_t":21,"symbol_tbl":[3,14,15,21,23],"sync":[6,10],"synchron":7,"synonym":10,"syntact":[3,6,7,8,11,14,15,17,18,23],"syntax":[0,3,6,7,9,10,11,13,15,16,18,23],"syntax_error":[0,9,14,15],"syntaxindex":17,"synth_namespace_projection_symbol":21,"synthes":[3,10,11],"synthesi":[7,9],"synthesized_namespace_project":21,"synthet":3,"sys_includ":[10,24],"sys_predef":[1,14],"system":[0,1,2,3,6,7,8,9,10,11,14,15,17,19,22,23,24,26],"system_head":7,"system_type_from_fundamental_typ":[6,22],"sz":16,"t":[0,1,2,3,4,5,6,7,8,9,10,11,14,16,17,18,20,21,22,23,24,25,26],"t1":[0,16,23],"t2":[0,10,16,23,24],"t3":[10,23],"t_c_ee131b0b":23,"tab":[4,10,11,14,15],"tabl":[0,3,5,6,7,8,9,10,14,15,17,18,19,23,24,25,26],"tack":10,"tag":[0,2,3,6,7,9,10,11,14,16,17,21,23,26],"tag_defined_in_constexpr_bodi":7,"tag_kind_incompatible_with_declar":7,"tag_kind_incompatible_with_template_paramet":7,"tag_redefined_differ":7,"tagless":[6,21],"tail":[7,11,15,21],"tak_start_of_pack_expans":23,"take":[0,1,2,3,4,6,7,8,9,10,11,14,15,16,17,18,21,23,24,26],"take_address_of_lvalu":9,"take_reference_to_operand":9,"taken":[0,1,3,7,9,10,11,14,15,16,17,18,23,24,25],"taking_address_of_temporari":7,"talk":16,"tall":10,"tandem":5,"tantamount":3,"targ_":1,"targ_char_constant_first_char_most_signific":15,"targ_def":[2,11,14,16,23],"targ_external_names_get_underscore_ad":26,"targ_field_alloc_sequence_equals_decl_sequ":3,"targ_ia64_vtable_entry_int_kind":1,"targ_j":16,"targ_jmp_buf_element_float_kind":16,"targ_jmp_buf_elements_are_float":16,"targ_jmp_buf_num_el":16,"targ_little_endian":1,"targ_little_endian_win32":1,"targ_maximum_pack_align":10,"targ_minimum_pack_align":10,"targ_no_error_on_integer_overflow":10,"targ_optimize_empty_base_class_layout":3,"targ_ptrdiff_t_int_kind":1,"targ_supports_x86_64":10,"target":[2,3,6,7,8,9,10,11,13,14,15,16,18,19,22],"target_cfg":14,"target_configuration_":1,"target_map":14,"target_on_special_funct":7,"target_string_must_be_narrow":7,"target_unmatched_paren":7,"targeted_vers":11,"task":[3,6,11,14,15,16,22],"tcf_seek_corresp":25,"tear":0,"technic":[4,6,10],"techniqu":[0,2,3,4,6,11,13,14,15,16,18,21,23],"tell":[0,6,9,11,16,26],"temp":16,"temp_init_from_operand":9,"temp_stat":4,"temp_used_for_ref_init":7,"templ":7,"templ_param_list_not_allow":7,"templ_param_list_too_long":7,"templat":[0,1,6,7,9,13,14,17,18,22,24,25,26],"template_and_inline_function_wrapup":[23,25],"template_and_instance_linkage_conflict":7,"template_arg_cannot_point_to_subobject":7,"template_arg_list":[11,21,23],"template_argument_index_out_of_bound":7,"template_constraint_not_satisfi":7,"template_declar":23,"template_declaration_or_direct":3,"template_deleg":7,"template_dependent_design":7,"template_depth_mismatch":7,"template_directive_or_declar":[6,23],"template_directori":[10,23],"template_friend_definition_not_allow":7,"template_id_not_allow":7,"template_in_gener":7,"template_in_managed_class":7,"template_info":23,"template_info_fil":10,"template_instance_already_us":7,"template_missing_closing_brac":7,"template_not_allow":7,"template_not_in_templ":7,"template_operator_delet":7,"template_operator_new":7,"template_or_specialization_declar":23,"template_param_in_elab_typ":7,"template_param_pack_not_at_end":7,"template_parameter_capture_conflict":7,"template_parameter_has_class_typ":7,"template_parameter_has_nonstructural_class_typ":7,"template_speci":23,"template_static_data_member_init_guard_cod":16,"template_sym":23,"template_template_param":23,"template_template_param_same_name_as_templ_param":7,"template_typedefs_in_diagnost":10,"templates_cleanup":0,"templates_in_embedded_cplusplus":7,"templk_concept":23,"temporari":[0,2,3,6,7,8,10,20,22],"temporarili":[3,10,11,15],"tempt":0,"ten":[7,15],"tend":[0,2,10],"tentat":[0,2,6,8,10,11,16,23],"tentative_type_lookup":21,"tera":16,"term":[0,3,4,8,9,10,11,14,15,16,17,18,23],"term_compil":0,"term_stmt_claus":20,"termin":[0,1,4,7,8,9,11,14,15,16,18,20,21,26],"terminate_curr_block_object_lifetim":20,"terminate_macro_text_map":15,"terminolog":23,"ternari":10,"terribl":[15,22],"terse_static_assert":7,"terse_static_assert_not_en":7,"test":[0,1,2,3,7,9,10,11,12,14,15,16,17,20,22,23],"test_":24,"test_bitmask":17,"test_fil":24,"test_nam":[10,24],"test_numb":24,"test_root":24,"test_run_timestamp":24,"test_runs_directori":24,"test_valu":17,"testabl":16,"tex":26,"text":[0,1,5,6,7,8,9,10,11,14,18,23,26],"textoffset":17,"textual":[5,10,11,13,14,16,23],"tf":17,"tgmath":10,"thank":14,"themselv":[0,9,10,11,14,15,16,17,23,24],"theori":[13,14,16,17],"thereaft":[0,9,11,25],"therebi":[3,10,16,21],"therefor":[0,1,2,3,6,8,9,10,11,14,15,16,18,22,23,25],"therein":[10,11,16],"thereof":[10,15,16,23],"thing":[0,1,2,3,4,5,6,8,9,10,11,14,15,16,17,18,19,21,22,23,25,26],"thingi":4,"thingy_help":4,"think":[5,14,23],"third":[2,6,7,8,10,17,20,23,25],"this_in_lambda":7,"this_not_const":7,"this_temp":16,"this_used_incorrect":7,"thiscall_requires_nonstatic_memb":7,"thorough":14,"though":[0,2,3,5,6,8,9,10,11,14,15,16,17,18,20,21,23,25],"thought":[3,17,21,23],"thousand":[0,9,10,15],"thread":[7,10,11,16],"thread_loc":[7,10],"thread_local_dynamic_init_routin":16,"thread_local_follows_non_thread_loc":7,"thread_local_ignor":7,"thread_local_must_include_static_or_extern":7,"thread_local_not_allow":7,"thread_local_storag":10,"thread_local_wrapper_for_vari":16,"threads_constant_not_allow":7,"threads_dimension_requires_definite_block_s":7,"three":[0,1,3,5,6,7,8,9,10,11,14,15,16,21,22,23,25],"threshold":[0,10],"throughout":[0,9,11,14,15,18],"throw":[1,7,9,14,15,22],"thrown":[7,9,11,15,16,21],"thunk":16,"thus":[0,3,5,6,7,10,11,14,15,16,17,18,21,23,24],"thusli":16,"thwart":15,"ti":[10,23],"tie":[0,1,9,10,11,15,21],"tiebreak":[7,10],"tight":9,"tild":15,"tildize_loc":21,"till":[6,10,20,21],"tim_al":23,"tim_loc":23,"tim_non":23,"tim_us":23,"time":[0,2,3,6,7,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"timeout":24,"timeout_second":24,"timestamp":[0,24],"tinfo":16,"tk_class":[3,21],"tk_complex":11,"tk_float":11,"tk_imaginari":11,"tk_pointer":[6,11],"tk_ptr_to_memb":[11,16],"tk_routin":22,"tk_struct":[3,21],"tk_template_param":[11,23],"tk_typeref":[6,11,14,18],"tk_union":[3,21],"tk_unknown":[3,11],"tl":16,"tlocal":10,"tls_model":7,"tm":16,"tmp":[10,24],"tmpdir":10,"tnm":23,"tnnnn":2,"tnone":10,"to_bitmask_0_33":17,"to_partition_kind":17,"to_to_":22,"to_universal_index":17,"to_universal_sort":17,"to_x":17,"togeth":[0,3,4,6,9,10,11,14,15,16,17,18,23,24,26],"toggl":8,"tok_":2,"tok_digit_sequ":15,"tok_end_of_sourc":[15,18,23],"tok_header_nam":15,"tok_identifi":[15,21],"tok_lparen":15,"tok_newlin":15,"tok_ptr_to_memb":15,"toke":15,"token":[0,2,3,5,6,7,9,10,11,14,18,20,21,23],"token1":18,"token2":18,"token3":18,"token_ends_expr":9,"token_sequence_needs_double_caret":7,"told":[0,10,15,21],"too_few_args_for_oper":7,"too_few_argu":7,"too_few_array_bound":7,"too_few_generic_arg":7,"too_few_macro_arg":7,"too_few_printf_arg":7,"too_few_template_arg":7,"too_few_template_param":7,"too_large_to_inlin":7,"too_many_args_for_convers":7,"too_many_args_for_oper":7,"too_many_argu":7,"too_many_arguments_provided_for_attribut":7,"too_many_array_bound":7,"too_many_cast_operand":7,"too_many_charact":7,"too_many_constraint":7,"too_many_generic_arg":7,"too_many_initializer_valu":7,"too_many_macro_arg":7,"too_many_ms_attr_arg":7,"too_many_parameters_for_literal_oper":7,"too_many_params_for_destructor":7,"too_many_params_for_fin":7,"too_many_printf_arg":7,"too_many_struct_bind":7,"too_many_template_arg":7,"too_many_template_argu":7,"too_many_template_param":7,"too_many_unused_instanti":7,"too_many_virtual_funct":7,"took":24,"tool":[1,10,11,14,16,17,26],"toolset":1,"top":[0,3,5,6,7,8,9,10,11,15,16,18,20,22,23,24,25],"top_dir":24,"top_templ":10,"topic":6,"topmost":[9,11],"toption":6,"tostr":9,"total":[0,7,10,15,16,17,24],"total_error":14,"toward":[1,10],"tp":1,"tr":[9,10,11],"trace":[0,1,10,11,14,15],"trace_corresp_ptr":25,"trace_includ":10,"track":[1,3,5,6,7,8,9,10,11,16,21,22,23,25],"tracker":15,"tracking_ref_to_const":7,"tracking_reference_member_in_standard_class":7,"tracking_reference_to_deleg":7,"tracking_reference_to_enum":7,"tracking_reference_to_funct":7,"tracking_reference_to_system_str":7,"tracking_reference_to_value_class":7,"trade":10,"tradeoff":8,"tradit":[0,1,3,6,9,10,11,13,18],"trail":[2,4,6,7,10,15,16,18,23],"trailing_requires_clause_not_on_templ":7,"trailing_requires_on_virtual_func":7,"trailing_return_type_function_without_simple_auto":7,"trailing_return_type_in_nested_declar":7,"trailing_return_type_requires_auto":7,"trait":[7,10,11,16,17],"tran":[0,25],"trans_copi":[14,25],"trans_corresp":[10,14,18,25],"trans_unit":[14,25],"trans_unit_copy_address_of":25,"trans_unit_corresp":25,"trans_unit_for_scop":25,"transfer":[6,7,8,9,11,16,18,20,21],"transform":[1,5,6,11,14,15,16,17,22],"transient":9,"transit":[0,9,10,11,14,15,17,20,21],"translat":[0,1,2,3,6,7,9,11,13,14,15,16,17,18,20,21,23,26],"translation_unit":[0,6],"translation_unit_wrapup":25,"transpar":[6,7,9,17],"transparent_attribute_ignor":7,"transparent_type_is_not_union":7,"transparent_union":7,"transparent_union_cannot_have_bit_field_first":7,"transparent_union_cannot_have_floating_first_field":7,"trap":10,"travers":[2,3,5,6,8,9,11,16,17,18,21,22,23,25],"traverse_addressing_subtre":11,"traverse_and_modify_type_tre":22,"traverse_const":11,"traverse_dynamic_init":11,"traverse_expr":[0,11],"traverse_stat":[0,11],"traverse_type_tre":[11,22],"treat":[0,3,6,7,9,10,11,15,16,17,21,23,25,26],"treatment":[3,10,15,16,18,21,23],"tree":[0,1,2,3,5,6,9,10,11,13,14,16,20,23,24,25],"tri":[0,3,7,9,10,11,13,14,15,16,17,20,23,25,26],"trick":[0,23],"tricki":[9,16,20],"trigger":[3,10,11,18,23,25],"trigraph":[7,10,11,15],"trigraph_ignor":7,"trim":[0,9],"triplet":16,"trivial":[3,4,6,7,9,10,14,17],"trivial_const_or_volatile_properti":7,"trivial_default_constructor":3,"trivial_indexed_properti":7,"trivial_reference_properti":7,"trk_is_template_alia":23,"troubl":15,"troublesom":11,"true":[0,1,3,4,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,25,26],"truli":[0,3,9,11,16,17],"truncat":[2,7,9,10,15],"try_block_stat":[8,20],"try_builtin_operands_match":9,"try_conversion_function_match_ful":9,"try_conversions_for_builtin_oper":9,"try_op":4,"try_overloaded_function_match":9,"try_pointer_builtin_operands_match":9,"try_static_conversion_function_match":9,"try_string_literal_init":6,"try_to_convert_class_operand_to_builtin_typ":9,"tsr":0,"ttparam":16,"tune":10,"tupl":[7,11],"tuple_el":7,"tuple_get_no_matching_overload":7,"tuple_index_overflow":7,"tuple_s":7,"turn":[0,2,3,5,6,8,9,10,11,15,16,17,18,20,21,22,23,24,25,26],"turn_class_definition_into_declar":[0,11],"tuse":10,"tw":16,"twice":[2,3,9,11,18],"twist":6,"two":[0,1,2,3,4,6,7,8,9,10,11,14,15,16,17,19,20,21,22,23,24,25],"two_packs_in_fold_express":7,"tx":15,"txt":[0,1,14,24,26],"ty":[0,16],"ty2":0,"typ":16,"type":[1,2,5,7,8,10,14,15,17,19,20,21,23,24,25,26],"type_after_bit_field_integral_promot":[9,22],"type_after_integral_promot":[9,22],"type_as_subobject":16,"type_cannot_be_class_memb":7,"type_cannot_be_param_nam":7,"type_change_const":9,"type_change_constant_ful":9,"type_code_arithmet":7,"type_code_bool":7,"type_code_bool_equival":7,"type_code_class":7,"type_code_enum":7,"type_code_handl":7,"type_code_handle_to_cli_array":7,"type_code_integ":7,"type_code_non_bool_arithmet":7,"type_code_nullptr_typ":7,"type_code_point":7,"type_code_pointer_to_funct":7,"type_code_pointer_to_memb":7,"type_code_pointer_to_object":7,"type_code_scoped_enum":7,"type_constraint_fail":7,"type_constraint_requires_type_concept":7,"type_decl_in_anon_union":7,"type_def_not_allowed_in_func_type_decl":7,"type_definition_not_allow":7,"type_generic_function_mismatch":7,"type_identifier_not_allow":7,"type_info":[1,8,12,16],"type_is_declared_abstract":7,"type_is_interfac":7,"type_kind":11,"type_masks_handler_param_typ":8,"type_must_be_integr":7,"type_must_be_object_typ":7,"type_must_be_trivially_copy":7,"type_nam":[6,9,15],"type_name_ful":6,"type_not_allowed_her":7,"type_not_arithmetic_or_enum_or_point":7,"type_not_arithmetic_or_unscoped_enum_or_point":7,"type_not_point":7,"type_not_satisfi":7,"type_not_scalar":7,"type_pack_element_cannot_match":7,"type_pointed_to":22,"type_ptr":3,"type_qualifier_ignor":7,"type_qualifier_ignored_on_constructor":7,"type_qualifier_not_allow":7,"type_qualifier_on_lambda":7,"type_qualifier_on_void_return_typ":7,"type_qualifiers_ignored_on_refer":7,"type_specifier_not_allow":7,"type_start_error":0,"type_symbol_typ":21,"type_traits_help":10,"type_with_named_address_space_not_allow":7,"type_with_no_linkage_in_funct":7,"type_with_no_linkage_in_template_arg":7,"type_with_no_linkage_in_var_with_linkag":7,"typedef":[0,2,3,5,6,7,9,10,11,14,16,18,21,22,23],"typedef_cannot_be_param_nam":7,"typedef_in_elab_typ":7,"typedef_modification_is_nonstandard":7,"typedef_not_allow":7,"typedesign":17,"typefundament":17,"typeid":[7,8,9,10,22],"typeid_expr":16,"typeid_needs_typeinfo":7,"typeid_of_incomplete_typ":7,"typeid_of_managed_typ":7,"typeindex":17,"typeinfo":[1,7,8,12,16],"typenam":[3,4,7,10,11,15,16,21,23],"typename_need":7,"typename_not_in_templ":7,"typeof":[7,10,11,16],"typeof_is_gnu_extens":7,"typeof_unqu":10,"typepoint":17,"typeref":23,"types_are_both_pointers_or_both_handl":22,"types_are_compat":22,"types_must_have_same_s":7,"typesort":17,"typic":[0,1,3,6,8,9,10,11,15,16,17,18,20,21,23,24,26],"typo":22,"u":[0,2,7,10,11,15,16,23,26],"u00d6":11,"u1":23,"u2":23,"u8":10,"uchar_max":1,"ucn":[11,15],"ucn_names_basic_char":7,"ucn_names_invalid_code_point":7,"ucn_names_surrogate_code_point":7,"ud":[15,16],"ud_lit_op_sym_for_cur_token":15,"ud_lit_op_sym_for_curr_token":15,"ud_string_suffix_mismatch":7,"udl_cannot_be_class_memb":7,"ugli":[9,11],"ui":16,"uint16":7,"uint32":7,"uint32_t":17,"uint64":7,"uint8":7,"uint8_t":17,"ulimit":24,"uliter":10,"ull":10,"ulong_max":1,"ultim":[3,6,9,11,15,23],"um16":16,"umlaut":15,"un":[3,15,23],"unabl":[7,8,9],"unable_to_get_mapped_memori":7,"unable_to_get_mapped_memory_reason":7,"unalias":11,"unalign":17,"unaligned_qualifier_drop":7,"unalt":[0,16,26],"unambigu":[11,14,16,18,21],"unari":[7,9,11,16],"unary_oper":9,"unassert":[10,15],"unattach":[11,16],"unattached_attribut":7,"unavail":7,"unavailable_attr":7,"unavailable_ent":7,"unavailable_entity_with_custom_messag":7,"unbalanced_attribute_argu":7,"unbind_object_lifetim":22,"unbound":[7,22],"unbounded_constexpr_ctor_init_recurs":7,"unbox":[9,22],"unbox_after_indirection_if_requir":9,"unboxing_conversion_poss":22,"unbundl":9,"unbundle_init_component_express":9,"uncallable_elided_cctor":7,"uncaught":8,"unchang":[0,15,16,26],"unclos":[7,10,14,15],"unclosed_str":7,"unclosed_va_opt":7,"uncommon":15,"uncompress":16,"uncondit":[7,10,18],"unconstrain":23,"unconvent":16,"unconvert":11,"unconvertible_con_expr":7,"und":23,"undeclar":10,"undeclared_paramet":7,"undef":[5,7,11,21],"undefin":[7,9,10,14,15,17,22,23,26],"undefine_macro":10,"undefined_decl_using_local_typ":7,"undefined_decl_using_no_linkage_typ":7,"undefined_identifi":7,"undefined_ifc_partit":7,"undefined_preproc_id":7,"undefined_static_function_treated_as_extern":7,"undefinit":[7,23],"undergo":[9,10,16,23],"underlying":[0,2,6,7,9,10,11,14,16,17,20,22,23,24],"underlying_array_element_typ":22,"underlying_type_of_derived_typ":22,"underneath":11,"underscor":[1,4,7,10,16,18,26],"understand":[1,9,11,17],"understood":[15,17],"undesir":[15,18],"undetermin":7,"undetermined_const":7,"undetermined_templ":7,"undetermined_typ":7,"undifferenti":16,"undo":[11,15],"undon":15,"unduli":2,"unevalu":[7,9,11],"unexpand":[11,15],"unexpect":[7,8],"unexpected_condit":[0,14],"unexpected_condition_str":0,"unexpected_design":7,"unexpected_end_of_default_arg":7,"unexpected_template_arg_list":7,"unexpected_type_for_size_t":7,"unfinished_base_class":7,"unfold":9,"unfortun":[0,3,10,11,26],"unget_token":15,"unhandled_ifc_construct":7,"unicod":[1,7,9,10,11,14,15,24],"unicode_name_fsm":14,"unicode_name_not_found":7,"unicode_source_kind":[10,15],"unicode_source_support":[1,11,15],"unicode_vulnerability_checking_support":10,"unifi":10,"uniform":14,"unimplemented_keyword":7,"uniniti":[6,7,9,10,11,14,16],"uninitialized_base_class_with_const_memb":7,"uninitialized_field_with_const_memb":7,"uninitialized_var_in_constexpr_funct":7,"uninstanti":23,"unintend":[7,24],"uninterpret":[0,10,11,18],"union":[0,2,3,5,6,7,10,14,17,21,22],"union_already_initi":7,"union_as_struct":14,"union_bas":7,"union_cannot_be_transpar":7,"union_cannot_be_transparent_sym":7,"union_constexpr_constructor_initializes_no_field":7,"union_nonunion_mismatch":7,"uniqu":[1,3,8,10,11,14,16,17,21,22,23,25],"unit":[0,1,2,3,5,6,7,11,14,15,16,17,18,21,23,24],"uniterable_reflection_rang":7,"universal":[7,11,16,17],"unix":[0,1,2,9,10,23,26],"unknow":9,"unknown":[3,6,7,9,10,11,14,16,17,20,21,22,23],"unknown_ifc_partit":7,"unknown_ifc_partition_convers":7,"unknown_typ":[7,22],"unless":[0,3,4,6,7,9,10,11,12,14,16,20,21,22,23],"unlik":[0,1,3,4,6,7,9,10,11,14,15,16,17,18,21,23],"unlink_src_seq_entri":22,"unlink_symbol_from_symbol_t":21,"unlow":[1,8,10,11,16,21],"unmangl":16,"unmatch":7,"unmodifi":16,"unnam":[0,1,2,3,5,6,7,8,10,11,16,18,21,22,23,25],"unnamed_class_virtual_function_def_miss":7,"unnamed_cli_managed_class_typ":7,"unnamed_field_symbol":3,"unnamed_object_with_uninitialized_field":7,"unnamed_require_expr_param":7,"unnamed_scoped_enum":7,"unnamed_tag_symbol_head":21,"unnamed_type_in_template_arg":7,"unnecessari":[9,15,16,17,21],"unneed":[0,10,11,25],"unord":[7,23],"unpack":[1,9],"unparenthes":[7,16],"unpars":23,"unprint":0,"unprocess":[2,18],"unprototyp":[2,7,11],"unqual_function_with_qual_object":7,"unqual_named_function_with_qual_object":7,"unqualifi":[3,10,11,15,21],"unqualified_sup":7,"unreach":[7,16,20],"unread":16,"unrec_embed_param":7,"unrecog":11,"unrecogn":[6,7,9,11,15,18],"unrecognized_attribut":7,"unrecognized_char_escap":7,"unrecognized_format_function_typ":7,"unrecognized_gcc_pragma":7,"unrecognized_gcc_visibility_pragma":7,"unrecognized_microsoft_comment_pragma_typ":7,"unrecognized_ms_attr":7,"unrecognized_pragma":7,"unrecognized_stdc_pragma":7,"unrecognized_target_attribut":7,"unrecognized_upc_pragma":7,"unrecognized_vis":7,"unreferenc":[2,7,11,16,23],"unreferenced_function_param":7,"unrel":[10,17,23],"unreli":17,"unrepres":3,"unrepresent":11,"unresolv":[3,10,23],"unrestrict":[7,10],"unrestricted_union":10,"unrestricted_unions_is_cpp11":7,"unsaf":[7,17],"unsatisfactori":16,"unsatisfi":24,"unscan_attribut":18,"unscop":[7,11],"unsequenc":7,"unsequenced_use_of_vari":7,"unset":[10,16],"unshar":11,"unsign":[0,7,9,10,11,14,16,17],"unsigned_bit_field":10,"unsigned_bitint_width_too_smal":7,"unsigned_char":10,"unsigned_compare_with_neg":7,"unsigned_compare_with_zero":7,"unsigned_enum_bit_field_with_signed_enumer":7,"unsigned_fixed_point_neg":7,"unsigned_value_of_integer_const":9,"unspeci":25,"unspecifi":[6,7,10,11],"unspecified_reflect":7,"unsubscript":7,"unsupport":7,"unsupported_ifc_file_arch_info":7,"unsupported_ifc_file_version_info":7,"unsupported_il_to_ifc":7,"unsupported_type_for_bit_cast":7,"untermin":7,"unterminated_delimited_escap":7,"unterminated_unicode_nam":7,"unus":[0,10,17,21,22],"unusable_pack":7,"unused_dereference_of_ref_class":7,"unusu":[0,3,8,9,11,14,15,16,18,20,21,24],"unwind":20,"unwind_stack_before_calling_termin":8,"unwit":10,"unwound":[8,16],"unwrap":17,"upc":[7,10,11,20],"upc_blocksizeof":7,"upc_foral":[7,20],"upc_relax":10,"upc_shared_void_comparison":7,"upc_strict":10,"upc_thread":10,"updat":[0,1,3,8,9,10,11,14,15,16,17,18,21,22,23,24,25,26],"update_inline_function_flag":23,"update_instantiation_required_flag":23,"update_source_sequence_list":22,"update_template_param_symbol":23,"upon":[10,15,17,18,20,23],"upper":[14,16],"uppercas":4,"upsid":18,"upward":11,"usabl":[3,9,16,24],"usag":[7,17,24],"use":[2,4,5,7,8,9,12,13,14,15,16,17,18,19,20,22,23,24,25,26],"use_edg_namespac":14,"use_field_initi":[6,11],"use_fixed_address_for_mmap":[0,10],"use_hide_by_sig_lookup":[9,21],"use_host_fp_convers":9,"use_host_fp_conversion_routin":[9,14],"use_init_section_in_generated_c":16,"use_lazy_initialization_for_thread_local_vari":16,"use_mmap_for_memory_region":10,"use_mmap_for_modul":17,"use_of_generic_class_with_pending_constraint":7,"use_of_non_prototype_func_declar":7,"use_of_undefined_function_with_deduced_return_typ":7,"use_own_sjis_multibyte_char_process":1,"use_pch":[0,10],"use_softfloat":9,"use_system_includ":24,"use_x86_function_multivers":16,"used_before_set":7,"used_in_except":8,"used_in_exception_or_rtti":22,"useless":[9,20],"useless_decl":7,"useless_placement_delet":7,"useless_type_qualifi":7,"useless_type_qualifier_on_return_typ":7,"useless_type_qualifiers_in_type_nam":7,"useless_using_declar":7,"user":[0,1,2,6,7,11,14,15,16,23,24,26],"user_control_of_struct_pack":10,"user_convert_operand":9,"user_defined_conversion_poss":9,"user_defined_liter":10,"user_defined_literals_en":15,"usher":16,"using_attribute_nonstandard":7,"using_decl":6,"using_decl_conflicts_with_prev_decl":7,"using_decl_in_embedded_cplusplus":7,"using_direct":6,"using_directives_appli":21,"using_directori":10,"using_driv":[1,10],"using_enum_conflict":7,"using_enum_redecl":7,"using_framework_directori":10,"using_lvalu":9,"using_not_at_file_scop":7,"using_or_access_declaration_in_managed_class":7,"using_out_of_scope_declar":7,"using_pch":7,"using_std":[10,12],"usk_non":15,"usl":[10,16,19,26],"usr":10,"usr_includ":10,"usual":[0,1,3,5,6,7,9,10,11,14,15,16,18,20,21,22,23,25,26],"utf":[1,7,10,11,14,15],"utf16_char_lit_too_long":7,"utf8_char_lit_too_long":7,"utf8_char_liter":10,"utf8_lit_no_ulit":7,"util":[0,2,6,9,10,13,14,16,17,22,23],"uu":16,"uuid":7,"uuidof_requires_uuid_class_typ":7,"v":[1,2,3,10,11,15,16,18,26],"v1":23,"va_arg":7,"va_arg_would_have_been_promot":7,"va_args_not_allow":7,"va_copi":7,"va_end":7,"va_opt_not_allow":7,"va_start":[7,10],"va_start_requires_ellipsis_funct":7,"vacuous":[3,10,15,16,21],"vacuous_destructor_not_cal":7,"vagu":[9,11],"val":[7,10],"valid":[0,3,5,6,7,8,9,10,11,14,16,18,21,22,23,24,26],"valid_address_const":9,"valid_node_if_subscript":9,"valu":[0,1,3,5,6,7,8,9,10,14,15,18,19,20,21,22,23,24,25,26],"value__":7,"value_class_not_satisfi":7,"value_has_been_set":21,"value_init_of_funct":7,"value_init_of_incomplet":7,"value_init_of_refer":7,"value_init_of_sizeless_typ":7,"value_initi":9,"value_of_integer_const":9,"value_of_pragma_pack_show":7,"value_returned_in_constructor":7,"value_returned_in_void_funct":7,"valuetyp":3,"var":3,"var_addr_expr":22,"var_initi":[0,14],"var_lvalue_expr":22,"var_retained_incomp_typ":7,"var_rvalue_expr":22,"var_used_as_destructor":7,"var_used_as_fin":7,"var_with_uninitialized_field":7,"var_with_uninitialized_memb":7,"var_with_virtual_bases_in_constexpr_funct":7,"vararg":[6,10,15],"vararg_clrcal":7,"vararg_thiscal":7,"vari":[8,10,11,16,22,24],"variabl":[1,2,3,5,7,8,9,14,17,18,19,20,21,22,24,25],"variable_align_attr_not_on_definit":7,"variable_hides_ent":7,"variable_not_constant_address":7,"variable_not_constant_valu":7,"variable_remappings_for_inlin":16,"variable_templ_function_typ":7,"variable_template_prototype_instanti":23,"variable_templates_is_cpp14":7,"variable_with_interface_typ":7,"variably_modified_type_not_allow":7,"variably_modified_type_not_allowed_her":7,"variad":[6,7,9,10],"variadic_macro":10,"variadic_templ":10,"variant":[0,1,3,7,9,10,11,14,15,16,17,18,19,23],"variat":[0,1,3,6,9,14,23],"varieti":[1,6,8,10,17],"various":[0,1,3,5,6,8,9,10,11,14,15,16,17,18,20,21,22,23,24,25,26],"vax":1,"vcmeta":10,"vcmeta_directori":10,"ve":[0,24],"vec":18,"vec_delet":8,"vec_new":8,"vector":[0,2,6,7,11,18],"vector_element_type_mismatch":7,"vector_length_too_larg":7,"vector_of_boolean_requir":7,"vector_operation_requires_integer_vector":7,"vector_s":[7,18],"vector_size_attribute_on_complex_typ":7,"vector_size_attribute_on_enum_typ":7,"vector_size_attribute_requires_integral_floating_or_enum_typ":7,"vector_size_must_be_multiple_of_element_s":7,"vector_size_must_be_power_of_two":7,"vector_size_too_larg":7,"vector_template_paramet":7,"vector_type_requir":7,"vector_type_with_size_is_requir":7,"vector_types_differ_in_length":7,"vectors_must_have_same_s":7,"vendor":[3,16],"verbatim":[5,17,24],"verbos":[10,26],"veri":[0,1,2,3,4,5,6,7,9,10,11,14,15,16,17,23,24],"verif":25,"verifi":[0,1,6,9,10,14,15,23,25],"verify_":25,"verify_generic_arg_list_satisfies_constraint":23,"verify_standalone_attribut":6,"verify_template_nontype_arg":23,"verify_that_all_pp_ifs_were_clos":15,"versa":[3,7,9,14,17,24],"version":[0,1,2,4,7,8,9,10,11,12,14,15,16,18,19,21,22,23,25,26],"versus":14,"very_fals":4,"very_long_long_long_long_foo":4,"very_long_long_long_long_long_foo":4,"via":[0,1,3,4,6,7,8,9,10,11,14,15,16,17,21,22,23,24,25],"viabl":[7,9],"vice":[3,7,9,14,17,24],"view":[1,9,10,11,16,20,23,25],"violat":[0,8,9,10],"virtual":[2,5,6,7,8,9,10,14,19,21,23],"virtual_base_for_managed_class":7,"virtual_function_cannot_have_deduced_return_typ":7,"virtual_function_decl_hidden":7,"virtual_function_info_offset":3,"virtual_function_never_defin":7,"virtual_function_table_should_be_defined_her":16,"virtual_function_templ":7,"virtual_has_no_effect":7,"virtual_ignor":7,"virtual_inline_never_defin":7,"virtual_not_allow":7,"virtual_required_for_base_overrid":7,"virtual_required_for_interface_implement":7,"virtual_static_ev":7,"virtual_static_event_accessor":7,"virtual_static_not_allow":7,"virtual_static_properti":7,"virtual_static_property_accessor":7,"virtual_with_explicit_thi":7,"visibility_specifier_on_nested_typ":7,"visibility_specifier_requires_definit":7,"visibl":[3,7,8,9,10,11,14,16,21,23],"visit":[0,16,21,22],"visual":[1,4,7,10,17,24],"vla":[6,7,8,10,16],"vla_allow":[10,11,19],"vla_deallocations_in_il":11,"vla_in_return_typ":7,"vla_in_statement_expr":7,"vla_is_nonstandard":7,"vla_is_not_auto":7,"vla_not_allow":7,"vla_size_ignor":7,"vla_type_in_template_arg":7,"vla_with_unspecified_bound_not_allow":7,"vlas":[10,11,16],"vms":1,"void":[0,2,3,4,5,6,7,8,10,11,14,16,18,20,21,22,23],"void_named_regist":7,"void_param_not_allow":7,"void_property_index_typ":7,"void_template_paramet":7,"void_template_vari":7,"void_throw":7,"void_typ":22,"volatil":[2,3,7,10,11,16,21,22,24],"volatile_asm_is_gnu_extens":7,"volatile_ass_deprec":7,"volatile_dec_deprec":7,"volatile_func_param_deprec":7,"volatile_inc_deprec":7,"volatile_op_ass_deprec":7,"volatile_return_type_deprec":7,"volatile_str_bind_deprec":7,"volatile_type_not_allow":7,"volumin":10,"vptr":16,"vs":[15,18,24],"vt":23,"vtabl":16,"vtbl":14,"vtbl_temp":16,"vtt":16,"vv":16,"vvvvvvvvvv":16,"w":[10,16,24],"wait":[3,18,24],"walk":[0,2,11,14,15,16,22,25],"walk_declarative_entities_in_scop":0,"walk_entri":[0,11,14],"walk_entry_and_subtre":0,"walk_entry_routine_nam":11,"walk_file_scope_il":0,"walk_list":11,"walk_list_on_link_field":11,"walk_orphaned_entry_routine_nam":11,"walk_ptr":11,"walk_routine_scope_il":0,"walk_string_entri":0,"want":[0,2,9,10,11,14,15,16,18,23,24],"warn":[0,6,7,9,10,11,14,18,20,21],"warn_unused_result":[7,18],"warn_unused_result_with_void_return":7,"warning_direct":7,"warrant":[3,11],"wasn":[10,24,26],"wast":[14,21],"watch":16,"way":[0,1,2,3,4,5,6,7,9,11,14,15,16,17,18,19,21,22,23,24,25,26],"wc":10,"wchar_t":[7,9,10,15,16],"wchar_t_keyword":10,"wdir":10,"weak":[7,10,16,23],"weaken":[7,10],"web":[9,10],"websit":10,"weight":10,"weirder":11,"well":[0,1,2,3,5,6,8,9,10,11,13,14,15,16,17,18,20,21,23,24,25],"went":6,"wg21":9,"whatev":[3,9,10,11,18,23],"whenev":[0,8,9,10,11,15,16,21,23],"wherea":[1,3,6,9,10,11,14,18,21,23],"wherebi":[3,21,23],"wherev":[11,15,23],"whether":[0,1,3,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,25,26],"whi":[11,15,16],"which_binary_oper":9,"whichev":[11,23],"while_stat":20,"white":[7,10],"white_space_inside_splic":7,"white_space_required_after_macro_nam":7,"whitespac":0,"whole":[1,3,5,11,14,16,21],"whose":[0,1,3,6,7,8,9,10,11,14,15,16,21,23,24,25],"wide":[2,7,9,10,11,15,16],"wide_deprecation_str":7,"wide_string_invalid_in_asm":7,"wide_string_not_allow":7,"widen":7,"width":[3,4,7],"wiki":16,"will":[0,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],"win32":[1,7],"win32_api_error":7,"window":[0,7,9,11,14,15],"winrt":1,"wise":14,"wish":11,"within":[0,3,4,5,6,7,8,9,10,13,14,15,16,17,18,20,21,22,23,24,25,26],"without":[0,1,2,3,5,6,7,8,9,10,11,12,14,15,16,18,20,21,23,24,25,26],"won":[5,10,16,17],"word":[2,6,8,9,10,11,15,16,17,20,21,23,24],"work":[0,1,2,3,6,7,9,10,11,12,13,14,15,16,17,19,21,22,23,24,25,26],"world":[10,15,16],"worri":[10,16,23],"wors":[0,9,16,24],"worth":[0,23],"worthwhil":9,"wouldn":[2,11,18],"wrap":[0,2,10,11,14,16,24],"wrap_diagnost":10,"wrap_up_file_scop":25,"wrapper":[2,9,11,17],"wrapup":23,"wrapup_auto_instantiation_inform":23,"wrapup_base_class":3,"wrapup_control_flow_process":20,"wrapup_function_template_argument_deduct":23,"wrapup_namespace_scop":21,"wrapup_rescan_of_pragma_token":18,"wrapup_scop":21,"wrinkl":9,"writabl":11,"write":[1,2,3,5,7,8,9,10,11,14,15,16,17,18,21,26],"write_ch":[2,5],"write_cppcli_portable_assembl":1,"write_error_source_lin":0,"write_line_direct":2,"write_memory_region":0,"write_num":[2,5],"write_orig_source_lin":0,"write_signoff":0,"write_source_lin":0,"write_spac":5,"write_str":2,"write_tok_ch":[2,5],"write_tok_str":[2,5],"write_unsigned_num":[2,5],"write_xref_entri":21,"writeonlyarray":7,"writer":10,"written":[0,1,2,3,4,6,7,10,11,13,14,15,16,17,22,23,24,25,26],"wrong":[7,16,18,23],"wrong_entity_for_aligna":7,"wrong_entity_for_attribut":7,"wrong_number_of_argu":7,"www":[1,3,10,16],"x":[0,1,2,3,4,5,6,7,8,9,10,11,15,16,17,18,21,23,24],"x1":[4,23],"x2":[4,10],"x86":[7,16],"x_val":4,"xf":16,"xfile":10,"xor_integer_valu":9,"xref":10,"xvalu":[7,9,11],"xx":[9,11,16,24],"xxx":[0,10,11,14,15,22,23,24,26],"xxxx":[7,11,14,15,16],"xxxxx":10,"xxxxxxxx":[11,15],"xyz":[0,10,16,18,24],"y":[4,6,10,11,15,16,21,23],"y1":4,"y2":4,"y_val":4,"year":[9,14],"yes":0,"yet":[0,3,6,7,9,10,11,14,15,16,18,21,22,23,25],"yield":[3,7,11,15,16],"yield_in_catch":7,"yield_outside_of_funct":7,"yy":11,"yyy":[10,23],"yyy_h":10,"yyyi":10,"z":[4,10,11,15,16,21,23],"z1":[4,16],"z1__tm__4_z2zz":16,"z2":[4,16],"z_val":4,"zc":10,"zero":[0,2,3,6,7,9,10,11,14,15,16,19,22,23,24,25,26],"zero_init":7,"zero_length_array_is_gnu_extens":7,"zero_length_bit_field_must_be_unnam":7,"zero_length_str":7,"zip":1,"zzz":10},"titles":["Administrative Functions","Configuring and Building the C++ Front End","C-Generating Back End","Class Declarations","Coding Style Guide","C++-Generating Back End","Declarations","Error Messages","Exception Handling","Expression Scanning","External Interface","Intermediate Language","ANSI C and C++ Include Files","C/C++ Front End Documentation","Overview of Internal Structure","Lexical Analysis and Preprocessing","IL Lowering","Modules","Pragmas and Attributes","Runtime Library","Statement Scanning","Symbol Table","Table Management","Templates","EDG Testing Framework","Multiple Translation Units","Utility Programs"],"titleterms":{"A":[8,18],"AT":15,"About":22,"At":8,"Do":16,"For":9,"How":[11,16,18],"In":8,"No":24,"Other":[10,21,22],"The":[1,3,8,9,11,15,16,19,21,23,25],"To":11,"Up":[15,21],"What":16,"With":[17,21],"__declspec":6,"__exception_start":8,"__if_exist":11,"__throw":8,"__throw_setup":8,"abi":16,"accept":10,"access":[3,11,21],"accessor":3,"activ":21,"add":[11,18],"address":[9,11,25],"adjust":17,"administr":0,"advanc":[17,24],"aggreg":6,"agnost":17,"aid":1,"alia":23,"align":[3,4,22],"alloc":[14,22],"altern":[10,23],"anachron":[10,21],"analysi":15,"annot":4,"anonym":[11,16],"ansi":[10,12],"apart":22,"appli":18,"argument":[3,4,10,21],"array":16,"ask":22,"asm":[6,11],"assembl":[6,15],"assign":11,"attribut":[6,11,18],"auto":6,"automat":[10,16,23],"avail":10,"back":[2,5,18],"base":[3,4,9,11,22],"basic":[1,17,21],"behavior":[1,10],"binari":[11,24],"bitfield":17,"bitwidth":17,"block":[8,11],"bodi":[3,4],"bool":16,"bound":[17,18],"box":11,"break":4,"breakdown":17,"buffer":[15,17],"build":1,"building_runtim":19,"byte":17,"c":[0,1,2,3,4,5,6,9,10,11,12,13,15,16,21,23],"c99":[10,11],"cach":[15,17],"call":[4,9,11,16],"canon":25,"captur":3,"case":[4,5,21],"cast":[11,16],"catch":16,"categori":[11,17],"cfront":[10,16],"charact":15,"check":[9,14,17,25],"class":[3,4,11,15,16,21,22,23],"classifi":23,"claus":23,"clean":8,"cleanup":24,"cli":[0,1,3,6,9,10,11,15,21,23],"coalesc":15,"code":[1,2,4,5,8,10,14,15,16,17],"command":[0,10],"common":1,"compat":10,"compil":[3,23],"complet":[6,23],"compon":[1,6],"compound":11,"concept":[22,23,24],"condit":[4,11,16],"configur":[1,2,24],"connect":21,"constant":[0,3,5,9,11,15,22],"constexpr":9,"constrain":23,"constraint":23,"construct":6,"constructor":[6,9,11,16,21],"context":[10,16,21],"control":[10,11,21],"convent":[4,14],"convers":[3,9,15,17,21],"copi":[9,16,17,24,25],"correspond":[11,25],"covari":16,"creat":0,"current":[15,21],"cx":1,"data":[3,4,9,15,16,17,23],"dealloc":11,"debug":[0,10,14,17,22,24,25],"declar":[3,4,5,6,11,14,16,21,22,23],"deduct":6,"default":[3,6,10],"defer":3,"defin":[1,3,9,21],"definit":[0,3,10,15,23],"deleg":3,"delet":[11,15,16],"depend":[0,10,21,25],"deriv":3,"descent":14,"deseri":17,"destructor":[6,11,16,21],"dettarg":1,"develop":1,"diagnosi":14,"diagnost":[9,10],"dialect":[1,10,14,16],"direct":[4,6,10,15,21,23],"directori":1,"dispatch":18,"display":[0,1,10],"document":[4,13],"doe":16,"done":16,"drive":1,"driver":1,"dynam":[11,16],"dynamic_cast":16,"eccp":1,"edg":24,"edg_decod":26,"edg_munch":26,"edg_prelink":26,"edgcc":1,"edgi":24,"eh":8,"elif":4,"elis":9,"els":4,"empti":[3,4],"end":[1,2,5,8,10,11,13,14,18],"endian":17,"endif":4,"entiti":[16,21],"entri":[11,14,16,21,22,25],"environ":[1,10],"error":[0,7,14,15],"evalu":16,"event":3,"exampl":8,"except":[8,16],"execut":5,"exist":11,"exit":10,"expect":24,"explicit":[3,17,23],"export":[10,23],"express":[6,8,9,11,14,16,22],"extend":11,"extens":[3,10,15],"extern":[10,14,16,21,25],"facil":25,"fail":24,"failur":24,"featur":[1,10,11],"feedback":24,"field":[3,11,17],"file":[0,1,10,11,12,14,16,21,22,23,24],"filter":24,"find":[10,25],"fix":[9,11],"fixup":3,"flag":[0,11,16],"flakey":24,"float":9,"fold":[9,11],"foreign":17,"framework":24,"friend":3,"from_partition_kind":17,"front":[1,10,11,13,14],"full":23,"function":[0,2,3,4,8,9,10,11,14,15,16,21,23],"general":[3,4,11,15],"generat":[0,2,3,5,8,10,23],"generic":[9,23],"get":[15,22],"get_ifc_partition_element_s":17,"get_ifc_partition_kind":17,"gnu":[6,10,16],"group":4,"guard":16,"guid":[4,14],"h":1,"handl":8,"handler":8,"hang":15,"has_partition_kind":17,"header":[0,10,11,12,17,21],"hide":21,"host":0,"host_envir":1,"ia":16,"identifi":[9,15,21],"ifunc":16,"il":[0,1,6,10,11,16,21,23],"impact":17,"implement":[8,10,17,22,23],"implicit":[3,10,17,23],"import":[15,21,23],"inact":21,"includ":[10,12,14],"inclus":[10,23],"index":17,"indic":13,"individu":10,"inform":[9,11,16,22,23],"init":6,"initi":[0,3,4,6,8,9,11,16,23,25],"inlin":[3,10,16,23],"input":[10,15],"insert":[15,16],"instanti":[10,16,21,23,25],"integ":9,"intellig":14,"interfac":10,"intermedi":[0,11,25],"internal":14,"interpret":18,"introduct":[13,18],"invoc":15,"issu":[0,10],"iter":23,"k":10,"keep":25,"keyword":15,"kind":17,"label":11,"lambda":[3,4,11],"lang_feat":1,"languag":[0,1,10,11,14,22,25],"layout":[3,11],"level":[1,9],"lexic":15,"librari":[1,10,19],"lifetim":[11,16,22],"like":16,"limit":[17,24],"line":[0,4,10,15],"linkag":[3,6,11],"list":[3,5,9,11,15,21,22],"liter":15,"live":24,"load":24,"local":16,"locat":[16,21],"logic":15,"look":[15,21],"lookahead":15,"lookup":[10,21],"loop":4,"low":9,"lower":16,"lvalu":[11,16],"macro":[0,1,5,10,11,15],"main":16,"maintain":16,"makefil":1,"manag":[0,3,8,11,21,22,23],"mangl":16,"manual":10,"map":17,"mark":8,"may":8,"mechan":23,"member":[3,4,11,16,21,23],"memori":[0,11,17,25],"messag":[7,10],"metadata":[6,21],"microsoft":[3,6,10,11],"miscellan":10,"mismatch":24,"mk_errinfo":26,"mode":[1,3,10,21,23,24,25],"model":3,"modif":15,"modifi":22,"modul":[10,17],"multi":24,"multibyt":15,"multipl":25,"multivers":16,"name":[3,4,5,6,10,11,14,15,16,21],"namespac":[6,10,11,12,16,21],"need":[0,8,11],"negat":24,"nest":21,"new":[11,16,18],"node":17,"non":[8,23],"nonreal":21,"nonstat":3,"normal_id_lookup":21,"numer":17,"object":[3,11,16,22,25],"offset":3,"onc":10,"one":[18,25],"onli":1,"oper":[2,9,11,16,21],"operand":9,"optim":[3,16],"option":[1,10,19,21],"order":[11,25],"organiz":[17,21],"orphan":[11,16,22],"output":[5,9,10,15],"overload":[3,9,21],"overview":[3,6,14,23],"pack":10,"pair":25,"paramet":[4,11,23],"parenthes":11,"pars":[0,6,9,14,18],"partial":23,"partit":17,"passthrough":17,"path":3,"pcc":10,"pch":0,"per":25,"perform":10,"phase":18,"philosophi":14,"placement":16,"platform":1,"point":[0,9,11,17],"pointer":[4,11,16,25],"pop_scop":21,"portabl":8,"posit":[11,14,15,16],"post":4,"pragma":[10,11,18,23],"pre":[4,17],"precompil":[0,10],"predefin":[0,10],"prefix":[0,11],"prelink":23,"preprocess":15,"preprocessor":[4,10],"presenc":17,"primit":9,"print":22,"problem":24,"process":[9,10,11,14,15,18,21],"program":[1,16,26],"project":21,"prologu":8,"promot":16,"properti":[3,5,9,11],"prototyp":5,"proxi":21,"push_scop":21,"question":22,"r":10,"rang":[4,9],"raw":[15,17],"re":24,"read":[0,15,17],"recogn":[15,18],"recompil":23,"record":[18,24],"recoveri":14,"recurs":14,"reduct":24,"refer":[4,5,9,11,15],"referenc":[10,11],"region":[11,25],"regress":24,"relat":16,"relationship":11,"releas":1,"replac":1,"replay":24,"report":[0,24],"represent":[6,23],"request":23,"requir":24,"rescan":9,"respons":10,"rethrow":8,"return":[4,11,16],"reusabl":16,"rewritten":5,"role":17,"routin":[0,9,11,15,16,22],"rule":4,"run":[1,8,24],"runtim":[10,16,19],"rvalu":11,"scan":[3,6,9,15,20],"scan_expr_ful":9,"scope":[3,5,11,16,17,21],"scope_stack_lookup":21,"script":1,"secondari":[10,25],"select":11,"selector":9,"separ":25,"sequenc":[5,11,16,22],"set":22,"setup":24,"sig":21,"signal":10,"simpl":17,"singl":24,"size":22,"sizeof":11,"skip":[15,17],"slow":[21,24],"sort":17,"sourc":[1,5,11,14,15,22],"space":15,"special":[4,21,23,24],"specif":[1,6,8],"specifi":6,"stack":[8,9,15],"stage":17,"standard":[6,12],"state":6,"statement":[4,9,11,20,22],"static":[3,16,23,25],"status":[10,24],"step":3,"stop":0,"storag":[8,14,22],"stream":15,"string":0,"structur":[9,14,15,23],"style":4,"subscript":11,"subset":24,"sun":10,"supplement":21,"support":[1,8,10,16,24],"svr4":10,"switch":4,"symbol":[3,11,21],"syntax":14,"synthes":21,"t":15,"tabl":[11,13,16,21,22],"tacit":17,"tagless":3,"take":22,"targ_def":1,"target":1,"techniqu":9,"templat":[3,4,5,10,11,15,16,21,23],"temporari":[9,11,16],"termin":[10,23,24,25],"test":24,"text":15,"textual":15,"thread_loc":16,"three":18,"throw":[8,11,16],"thrown":8,"time":[1,8],"token":15,"tool":24,"top":1,"track":15,"transform":[2,9,18],"translat":[10,25],"travers":0,"tree":[15,22],"tri":8,"troublesom":5,"two":18,"type":[0,3,4,6,9,11,16,18,22],"typeid":[11,16],"typeref":[11,14,22],"unbound":18,"unbox":11,"uncheck":17,"unexpect":24,"union":[11,16],"unit":[10,25],"unord":16,"unscan":18,"use":[0,1,3,6,10,11,21],"user":[3,9,10,21],"util":[1,15,26],"valid":17,"valu":[4,11,16,17],"variabl":[0,4,6,10,11,15,16,23],"variad":23,"verbos":24,"version":17,"versus":11,"virtual":[3,11,16],"visitor":17,"vla":11,"void":9,"vs":[3,6],"walk":8,"way":10,"white":15,"whitespac":[4,15],"window":1,"within":11,"without":17,"wrap":[4,17],"wrapper":16,"wrapup":0,"write":[0,4,24]}}) \ No newline at end of file diff --git a/doc/statements/index.html b/doc/statements/index.html new file mode 100644 index 0000000..731aed7 --- /dev/null +++ b/doc/statements/index.html @@ -0,0 +1,454 @@ + + + + + 12. Statement Scanning - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    12. Statement Scanning#

    +

    statements.c contains the code to scan statements, and statements.h +contains the associated declarations.

    +

    The top-level routine here is compound_statement, which scans a +brace-enclosed list of statements. This is used for the bodies of functions +and for blocks (with and without local declarations) that appear within +functions. In C mode, it first calls opt_declaration_list to scan the +optional list of declarations; then, in C or C++ mode, it calls statement +(in a loop) to scan the statements.

    +

    statement scans one statement, with an optional preceding label or labels. +Its job is mostly to call the appropriate statement-scanning routine based on +the first token of the statement. For most statements, the first token is a +keyword that identifies the statement. Otherwise, the statement is an +expression statement (in C or C++) or a declaration (in C++ only; +is_decl_not_expr is called to decide whether the construct is an expression +or a declaration).

    +

    A stack of active statements is maintained in struct_stmt_stack. For each +active statement, it contains the kind of statement and some information about +what has been scanned so far in the statement. push_stmt_stack and +pop_stmt_stack manage the stack. find_enclosing_struct_stmt can be +used to find the nearest enclosing structured statement of a given type; this +is used in finding the construct associated with a break or continue.

    +

    One important function of the statement stack is that it points to the +intermediate language for the associated statement. The top-most entry +contains enough information to enable one to find the “current” location in the +intermediate language being generated, the point at which one would like to add +a statement. This is, in fact, exactly what add_statement_list does: it +links the given list of statements (possibly just a single statement) into the +growing tree of statements for the function. Usually, this is called throughadd_statement_at_stmt_pos , which allocates a statement of a given kind and +also maintains the code_reachable flag, indicating whether or not the +current location in the code is reachable. This flag is used to check for +unreachable code and issue appropriate warnings. Code is attached to the +statement tree even if it is unreachable. As statements are pushed onto and +popped off the stack, the code_reachable flag is maintained accordingly, +based on whether or not the beginning of the statement can be reached, whether +the end can be reached from the beginning, and whether the end can be reached +from the inside. The lint_notreached_flag is also consulted. For +statements that have several clauses (if and switch) +start_stmt_clause and term_stmt_clause are called at the appropriate +locations in processing to keep the code_reachable flag up to date.

    +

    The statement stack contains pointers to break and continue labels for +the statement. These are initialized to NULL, and later made to point to a +label if a goto is actually generated for a break or continue. At +pop_stmt_stack time, the definition for the break label is generated if +one is needed. The statement scanning routine must handle the continue +label is there is one.

    +

    If a statement is labeled with a simple label, statement calls +scan_label to look up or enter the label, then define_label to add a +label definition statement to the intermediate language.

    +

    Nothing tricky is involved in statement processing routines if_statement, +while_statement, do_statement, goto_statement, break_statement, +and continue_statement. asm_statement is called for asm statements; it +in turn calls asm_declaration.

    +

    dependent_statement is called to scan statements that are dependent +statements of if, switch, while, do while, and for +statements. In C mode, it just scans a statement. In C++ mode, it creates a +block statement and places the dependent statement under it, unless the +dependent statement is a block statement. That ensures that if anything is +declared in the dependent statement, its scope will be limited to the dependent +statement (this is a post-ARM C++ language rule).

    +

    for_statement scans a for or range-based for statement (or, in UPC +mode, a upc_forall statement). Since it is unknown at the beginning of +scanning whether a for or range-based for statement is being scanned, +two block scopes (used to contain the range-based for temporary variables) +are pushed in preparation for the range-based for case (they’re discarded +if scanning reveals a for statement). The first entity inside the +parentheses (initialization) is scanned by calling for_init_statement, +which allows an expression (in C or C++), a declaration (in C++ only), or a +for-range-declaration (in C++11). for_init_statement also determines +(through a call to decl_statement_full) which type of statement is being +scanned. If the for-init is a declaration (and a for statement is +being scanned), start_for_init_block is called to push an sck_block +scope (with is_for_init_block set to TRUE) onto the scope stack, where +it remains till after the dependent statement of the loop is scanned (see +finish_for_init_block). If the second expression (test) is present, it is +scanned by calling can_boolean_controlling_expression. The third +expression (increment) is scanned by calling scan_void_expression. For any +of those expressions/statements that is omitted, a NULL pointer is used in +the stmk_for statement. In the range-based for case, the statement +kind is set to stmk_range_based_for (this is somewhat unusual since the +statement kind is typically known earlier) and +scan_range_based_for_expression is called to scan the range expression. +Semantic checks, determination of the type of range-based for (see header +comments), and IL generation are handled by +check_range_based_for_statement.

    +

    The Microsoft for-each statement (available in C++/CLI emulation mode, as well +as when microsoft_version >= 1400) is scanned by for_each_statement. +If the for-each statement contains a previously declared iterator variable, it +is scanned by scan_previously_decl_iterator_name, otherwise the iterator +declaration is scanned by for_each_iterator_declaration. Two block scopes +are pushed (an outer block scope for the loop temporary variables, and an inner +scope for the iterator variable). The collection expression is scanned by +scan_for_each_expression and semantic checks (and IL generated) by +check_for_each_statement. check_for_each_statement handles the various +types of for-each statements (see the header comment for details). Much of the +underlying code is shared with the range-based for statement.

    +

    return_statement scans the return statement. It examines the type of +the current function. A void function should have returns that +return no value; other functions should return a value. +check_void_return_okay checks whether or not a value-less return is +okay in the current function. It is also used at the final closing brace of +the function if that position is reachable (since there is an implicit +return there).

    +

    switch statements cause the most problems. switch_statement itself is +not too complicated: it just pushes an entry on the statement stack, scans the +selector expression, and scans the dependent statement. The complex processing +comes with case_label (which also handles the GNU extension of case ranges; +e.g., “case 1 ...  3:”) and default_label, or more precisely, with the +subroutine those two cases call, add_switch_clause. That routine +determines whether or not the label can be added to the list of labels for the +currently-active clause, or whether instead a new clause must be begun. It +also determines where the case value (or the default) belongs in the list of +constants for the clause. The configuration macro +RECORD_SWITCH_CASE_ENTRIES determines how individual case labels are +represented. When TRUE (the default), all the labels (including the default +case and any GNU case ranges) are represented using type +a_switch_case_entry. When FALSE (an option maintained primarily for +backward compatibility purposes), the labels within a clause are usually +represented as a list of a_constant entries, but in a clause labeled with +default, any specific values from case labels are superfluous and are +removed. In the latter approach, GNU case ranges are represented as a list +containing all the constants in the range (which doesn’t scale well for large +ranges). Because the intermediate language idiom for switch statements is +slightly different from the C language idiom, a bit of translation from one +idiom to the other is necessary:

    +
      +
    • +
      A break in a switch usually just ends the current clause and makes +the code following it unreachable. Since the intermediate language +switch clauses end with a break by default, no goto to a +break label is usually needed.
      +
      +
    • +
    • +
      Fall-through from one clause into the next is translated as a goto to a +generated label at the start of the next clause.
      +
      +
    • +
    • +
      When case or default labels are not at the top level in the +switch body (i.e., they are defined within structured statements inside +the switch), the switch clause is just a goto to a generated +label at the right location, and the unusual statement(s) inside the +switch body go into the body statement attached to the intermediate +language switch.
      +
      +
    • +
    • +
      Likewise, when there are local declarations in the compound statement that +is the body of the switch, those declarations go into the body +statement.
      +
      +
    • +
    +

    There is also processing to detect and report cases in which a declaration that +involves implicit or explicit initialization is bypassed by a transfer of +control (by means of a goto or switch). A separate data structure is +maintained to assist in this checking: variable control_flow_descr_list +identifies a doubly linked list of entries of type a_control_flow_descr +that represents a view of the static control flow pattern of a given function. +Blocks, gotos, labels, case labels, and initializing declarations are +all represented by entries on the list. Some of these entries point to IL +entries, but the IL does not point back.

    +

    The list is dynamically pruned – it has only enough information on it for the +checking that is required. For instance, once a forward goto has been checked, +it is no longer interesting and is removed, and entire blocks may be removed +once they become irrelevant to subsequent analysis. (See +remove_control_flow_descr and remove_list_of_flow_control_descrs, which +place entries onto an available list, and alloc_control_flow_descr, which +reuses freed entries in preference to allocating new ones.)

    +

    add_to_control_flow_descr_list is called (from add_stmt_at_stmt_pos for +initializations, from push_stmt_stack for blocks, etc.) to add a new entry +to the end of the list, though in some cases the entry will not be +added – because it is not required after all – and sometimes it will even +cause other entries to be removed – for instance, if a completed block turns +out to have no labels or gotos, the entire block can be eliminated.

    +

    At the end of a block within a switch statement, +add_to_control_flow_descr_list may call report_switch_past_init, which +examines the entries on the list for initializing declarations that may be +bypassed by a transfer of control to a case label. An error is issued in +C++ mode, a warning otherwise.

    +

    check_for_jump_over_initialization is called from goto_statement and +from statement when a label definition is seen. For a forwards goto it +calls add_to_control_flow_descr_list to record information that will be +used for checking when the label is processed. For a label it calls +check_goto_and_label to report any previously recorded gotos that may +now be recognized to involve bypassing an initializing declaration (see +report_goto_past_init, which issues an error in C++ and a warning +otherwise); and an entry representing the label is added to the list. For a +backwards goto it again calls check_goto_and_label, which in turn calls +report_goto_past_init, if appropriate.

    +

    The control flow descriptor list is also used by +check_for_branch_into_handler, which reports attempts to branch into an +exception handler from code outside the handler.

    +

    An important part of statement processing is the management of object +lifetimes. For example, each time a compound statement starts, a new object +lifetime begins; and it ends when the compound statement terminates. In other +words, objects (e.g., automatic variables and long-lifetime expression +temporaries) created inside the compound statement have lifetimes that +terminate when it does. The destructor (if any) for such an object must be +called in the event of the normal termination of the scope, a branch out of it, +or unwinding through it as the result of an exception. The information +enabling back ends to support these implicit destructor calls, in the right +place and in the right order, is provided by entries of type +an_object_lifetime, discussed in detail in the chapter on the intermediate +language.

    +

    Each time a new function or block scope is created, a new object lifetime is +pushed on the object lifetime stack – push_object_lifetime is called in +push_scope, and the object lifetime is bound to the scope entry for block +scopes in ensure_il_scope_exists (in il.c). In addition, an object +lifetime is pushed for try blocks in try_block_statement and for cfront +dependent statements in start_block_statement; in the latter case, since +there is no scope, the lifetime entry is bound to the block entry associated +with the block statement.

    +

    When a label is defined, a block-after-label object lifetime is pushed. Such +lifetimes are effectively subblocks of the current lifetime that run from the +label to the end of the block in which the label appears. When a label is +defined inside an inner block, a block-after-label lifetime is also pushed in +the containing block when the inner block terminates. (See +terminate_curr_block_object_lifetime and +reset_curr_block_object_lifetime.) Block-after-label lifetimes are also +pushed for case labels.

    +

    The object lifetime that is current at the point of the label’s definition is +recorded in the label statement. A goto statement that references that +label will point to the innermost object lifetime shared by the label and the +goto; this is computed by common_object_lifetime.

    +

    The general strategy is always to create an object lifetime at standard +transitions in the source code (e.g., upon entering a block or when a label is +seen) and then, when the construct it belongs to terminates, to decide whether +there is justification for retaining that lifetime entry in the IL. If not (as +determined by is_useless_object_lifetime), it is removed from the IL tree.

    +

    Consequently, a label or goto statement may be assigned an object lifetime +that subsequently proves “useless”. In that case the object lifetime pointers +of the statement entries are promoted (see +fixup_curr_block_labels_and_gotos, which calls +promote_label_and_goto_lifetimes; this is also where +pop_object_lifetime is called for block-after-label lifetimes). This +processing is driven by management of the control flow description list (see +add_to_control_flow_descr_list).

    +

    If all the labels and gotos in a function end up pointing to the function +scope lifetime but the function scope lifetime itself turns out to be useless, +then the lifetime pointers in the label and goto statements are cleared +(see wrapup_control_flow_processing).

    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/symbol_tbl/index.html b/doc/symbol_tbl/index.html new file mode 100644 index 0000000..00a6539 --- /dev/null +++ b/doc/symbol_tbl/index.html @@ -0,0 +1,2519 @@ + + + + + 6. Symbol Table - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    6. Symbol Table#

    +

    The primary function of the symbol table is to provide a mechanism for +associating names and entities: a name can be entered into the symbol table in +association with a particular definition and then later looked up to get back +to the same definition. Name visibility is controlled by an implementation of +nested name scopes and class member inheritance. Provision is also made for +overloaded operators and user-defined conversion functions, which are not +looked up by name. In addition, the symbol table serves as a repository of +information that is needed for front-end processing but is of no use to back +ends. symbol_tbl.c contains the code to manage the symbol table, +lookup.c contains the code that looks up identifiers, scope_stk.c +contains the code that manages the scope stack, and symbol_ref.c contains +the code that manages the recording of references to symbols. +symbol_tbl.h, lookup.h, scope_stk.h, and symbol_ref.h contain +the associated declarations.

    +
    +

    6.1. Basic Organization#

    +
    +

    6.1.1. Symbols and Symbol Headers#

    +

    The key components of the symbol table are entries of type a_symbol and +a_symbol_header. Typically, symbols represent specific uses of a name +(e.g., the same name may be declared in different name scopes or belong to +different name spaces), but all symbols for a particular name share the same +symbol header. Each symbol entry points to a header which identifies the name +associated with it; the symbol header points in turn to symbols that share its +name. Symbols with the same name from different translation units (see +Multiple Translation Units) share the same symbol header.

    +

    For certain special cases (overloaded operators and user-defined conversions) +the symbol header has no actual name but can be thought of as representing a +family of virtual names to be constructed for the associated symbols: a single +symbol header is shared by all symbols that overload a given operator or, for +user-defined conversions, a given return type. (The names generated by the +compiler to assure type-safe linkage are not produced by the front end and so +do not appear in the symbol table.)

    +

    At the gross level the symbol table has three distinct pieces, each of which +has its own “root”, a global variable that is accessed in the lookup process:

    +
      +
    • +
      For named symbols symbol_table is a hash table where each bucket points +to a linked list of symbol headers. The name is reduced to a hash value +that is used to index the array.
      +
      +
    • +
    • +
      For overloaded operator symbols opname_symbol_table is an array of +symbol header pointers that is indexed by members of the enumeration +an_opname_kind. There will be one symbol header for each overloaded +operator.
      +
      +
    • +
    • +
      For user-defined conversion symbols conversion_header_list points to a +linked list of entities of type a_conversion_header, one for each +result type for which the user has declared a conversion routine. Each +conversion header points to a single symbol header.
      +
      +
    • +
    +
    +
    +

    6.1.2. Active, Inactive, and “Other” Symbols#

    +

    Each symbol header contains pointers to three lists of symbols of the same name +(or that otherwise share the symbol header): the active symbol list, the +inactive symbol list, and the other symbol list.

    +
    +

    6.1.2.1. The Active Symbol List#

    +

    The list of active symbols includes all symbols that are still in scope. The +order of the symbols on the list is significant since certain of the lookup +mechanisms take the first symbol found. When symbols are entered into the +symbol table, their entries are always placed at the beginning of the list, so +that declarations in inner scopes will eclipse outer-scope declarations of the +same names. An exception is made when a tag and a nontype with the same name +exist in the same scope in C++. In such cases the tag is always placed on the +list following the nontype so that it will be hidden except when accessed using +an elaborated type specifier. When the inner scope ends, its symbol entries +are removed, which exposes the outer declarations.

    +

    Note, however, that symbols from the same scope can coexist on the active list, +since different kinds of symbols can belong to different name spaces. For +instance, a variable, a macro, and (in ordinary C) a tag can all share the same +name. The array name_space_for_symbol_kind maps a symbol kind into +a_name_space_kind (e.g., nsk_label, nsk_macro, nsk_other). The +lookup mechanism must check for name-space compatibility: in most cases, it +takes the first in the active list whose kind maps into the appropriate name +space. The name space kind nsk_other is the normal name space for types, +variables, enumeration constants, and functions.

    +
    +
    +

    6.1.2.2. The Inactive Symbol Lists#

    +

    When a scope terminates, the symbol for each name declared in that scope is +removed from the active list of the associated symbol header. In most cases, +this means the symbol is removed from the symbol table (i.e., that it can no +longer be found by any lookup mechanism). But for some symbols (e.g., class +and namespace members) it must remain possible to look up a name even after it +passes out of scope, and so its symbol is moved from the symbol header’s active +list to its inactive list. The order of symbols on the inactive list is not +significant.

    +

    Thus, the inactive symbol list will comprise symbols for class members that are +no longer in scope but are still indirectly accessible, whenever the class is +accessed.

    +

    Similarly, when the template declaration scope terminates, its symbols +representing the template parameters are also added to the inactive list. This +enables them to be accessible during instantiation of the template.

    +

    Namespace scopes are not terminated when the namespace is closed because the +namespace may be extended later in the compilation. Namespaces may be extended +either explicitly by opening a namespace extension scope, or implicitly as a +side-effect of a namespace member definition in the file scope or as a +side-effect of the instantiation of a template entity defined in a namespace +scope. When the original namespace definition scope is closed, the namespace +members are moved from the active list to the inactive list. If the namespace +scope is later extended, new symbols for the namespace are entered directly on +to the inactive list.

    +

    The file scope is popped when the scanning of a translation unit is completed +so that its symbols are not on the active list if any other translation units +must be processed. As with namespaces, the symbols are moved to the inactive +list to permit the file scope to be reactivated later, if additional processing +of the original translation unit is required (e.g., to generate template +instantiations).

    +
    +
    +

    6.1.2.3. The “Other” Symbol List#

    +

    The “other” symbols list is used for symbols that are never found using the +normal lookup routines. Specifically, the “other” symbols list includes +“extern” symbols and synthesized namespace projection symbols, both of which +are described below.

    +
    +
    +
    +

    6.1.3. Scope List#

    +

    When symbols are entered into the symbol table, they are also entered onto a +list of the symbols declared in the current name scope (discussed in detail +below). [1] This list preserves the names in declaration order and is +referenced in removing symbols from the active list (and usually from the +symbol table) when the name scope is terminated.

    +

    Typically, this list lasts no longer than the scope stack entry that points to +it – when the entry is popped off the scope stack, the associated list is +discarded. In some cases, however, the list must be kept around for later use.

    +
      +
    • +
      For class scopes it is stored in the class symbol supplement for the class +for use in cases in which the declaration order must be observed (e.g., in +doing member initialization).
      +
      +
    • +
    • +
      For function prototype scopes it is used to reenter parameter symbols in +the function scope.
      +
      +
    • +
    • +
      For namespace scopes it is preserved in the pointers block for the +namespace.
      +
      +
    • +
    • +
      For file scopes it is preserved in the translation unit entry (there can be +more than one file scope when processing multiple translation units).
      +
      +
    • +
    +
    +
    +

    6.1.4. Special Cases#

    +

    There are several classes of symbol for which special treatment is required.

    +

    Symbol entries for constructors, though they have names, are not entered +directly into the symbol table. That is, they do not appear on the active or +inactive list of the symbol header for the name. Rather, they are accessed +from the constructor field of the class’s supplement entry. Thus the +symbol lookup for constructor X::X is always by way of the symbol +supplement for class X.

    +

    A tagless class, struct, or union presents an interesting case because it has +no name but must have a symbol to serve as a repository of information for the +front end’s processing. Such symbols all share a single symbol header (see +static variable unnamed_tag_symbol_header in symbol_tbl.c) but are not +entered on any list.

    +

    C++/CLI property accessor functions are members of a property which is itself a +member of a class, but the property is not a nested class; it’s a data member. +For the accessors, special symbol headers are generated that are a combination +of the symbol header for the property and the symbol header for the access +name. See get_property_or_event_accessor_symbol_header. Event accessors +are handled similarly.

    +

    Error symbols are created in various cases when errors are detected. They have +no name associated with them, and, like unnamed class symbols, they all share +the same symbol header (see static variable error_symbol_header in +symbol_tbl.c).

    +
    +
    +

    6.1.5. Symbols and IL Entries#

    +

    For the most part symbol entries are little more than an indication of the kind +of symbol and a pointer to an IL entry that provides more information. Thus, +sk_variable and sk_static_data_member symbols point to an entry of type +a_variable; constants, types, tags, fields, functions, and labels are +similar. The principal function of most symbol entries is simply to indicate a +mapping between names and the intermediate language constructs to which those +names correspond.

    +

    But symbol entries also serve as repositories of information that the front end +requires for its processing but that back ends do not care about. For +instance, sk_keyword symbols contain the keyword token value and for +sk_macro symbols there is a pointer to a_macro_def. Most notably, +symbols representing classes, structs, and unions point not only to the +corresponding IL entry but also to an entry of type +a_class_symbol_supplement, which contains a number of flags and pointers +(including a pointer to the constructor symbol, as described above).

    +

    Some symbols just point to other symbols: sk_projection symbols, which +represent names in a derived class that are inherited from a base class, +contain a pointer to the original symbol, and sk_overloaded_function +symbols point to a linked list of routine symbols that represent instances of +the overloaded name.

    +

    sk_parameter symbols are created during parameter processing. They are +needed because parameter names hide names from containing scopes (e.g., in +default argument expressions). However, they do not refer to any IL entity; +rather, when a function definition is present, they are reentered into the +function scope and turned into sk_variable symbols which do point to +variable entries.

    +
    +
    +

    6.1.6. Function Overloading#

    +

    Each instance of an overloaded function is represented by a symbol – of kind +sk_member_function for member functions and sk_routine otherwise. +However, these symbols are not directly present in the symbol table. Rather, +the whole family of functions that share the common name or operator in a given +scope is represented by an sk_overloaded_function symbol, and that is what +actually appears in the symbol table (i.e., is on the active or inactive list +of a symbol header). Consequently, name lookup finds only the overloaded +function symbol, not the symbol for the particular function required. [2]

    +

    The actual function symbols appear on a linked list pointed to from the +overloaded function symbol. The order of symbols on the list is not +significant, since the argument matching algorithm requires visiting every +instance anyway. The list may contain function symbols, function template +symbols, projection or namespace projection symbols that point to functions or +function templates, or a combination of any or all of these.

    +
    +
    +
    +

    6.2. Name Scopes#

    +
    +

    6.2.1. push_scope and pop_scope#

    +

    Aside from the structure described above, the symbol table also has a name +scope structure. Each time a new name scope is entered (for the file scope, a +class, struct, or union, a function, a block, function prototype, namespace, +template declaration, or template instantiation), push_scope is called to +push a new entry onto the scope stack. (See scope_stack, a global variable +that points to an array of elements of type a_scope_stack_entry. Since the +scope stack is implemented as a dynamically allocated array that can be +extended by reallocation when necessary, elements should always be accessed by +indexing into the array rather than by reusing a pointer.)

    +

    There are actually a number of different routines used to push different kinds +of scopes (e.g., push_template_instantiation_scope). The various routines +all call push_scope_full, which does most of the processing. +push_scope is used for pushing “normal” scopes that don’t require that +extra arguments be supplied when called. This section uses the name +push_scope to refer to the set of functions that add scopes to the scope +stack. Most of the actions described here are performed by +push_scope_full.

    +

    push_scope assigns a unique number to each scope, and when an identifier is +entered into the symbol table, the scope number is recorded in its symbol +(field decl_scope); this number may be referenced during symbol lookup, and +it is used to detect multiple declaration errors during symbol entry. When the +name scope ends, pop_scope is called to remove its symbols from the symbol +table (class member symbols are an exception, as described above) and to pop +the scope stack entry off the stack. pop_scope calls wrapup_scope, +which removes the symbol entries for the scope from the active list and +reenters them on the inactive list when appropriate (for class, namespace, and +template declaration scopes). wrapup_scope also calls +end_of_scope_symbol_check, which issues diagnostics on incomplete types and +on entities that were declared and never referenced or set and never used. +When the file scope is popped at the end of the translation unit, pop_scope +calls wrapup_namespace_scopes, which in turn calls wrapup_scope for all +of the namespace scopes in the translation unit.

    +

    The previous_scope field of the scope stack entry is used to determine the +order in which scopes on the scope stack are to be considered for name lookup +purposes. For most scopes, this field is set by push_scope_full.

    +

    push_scope and pop_scope maintain a number of state variables, some +global and some local to symbol_tbl.c:

    +
      +
    • +
      depth_scope_stack gives the depth of the current name scope in the +scope stack. [3]
      +
      +
    • +
    • +
      decl_scope_level gives the scope depth of the scope entry with which +declarations should be associated. [4]
      +
      +
    • +
    • +
      depth_innermost_function_scope is the depth of a sck_routine scope +stack entry that is or contains the current scope; if there is none or if a +class scope intervenes its value is NO_SCOPE_DEPTH.
      +
      +
    • +
    • +
      num_classes_on_scope_stack is the number of class entries currently on +the scope stack (including sck_class_reactivation as well as +sck_class_struct_union scopes).
      +
      +
    • +
    • +
      depth_of_innermost_scope_that_affects_access_control is used in +determining whether a piece of code has member access privileges to a given +class (e.g., in a friend function).
      +
      +
    • +
    • +
      depth_innermost_namespace_scope is the depth of the innermost namespace +scope that is visible on the scope stack, or the depth of the file scope if +no namespace scopes are visible.
      +
      +
    • +
    • +
      depth_innermost_instantiation_scope is the depth of the current +template instantiation scope or NO_SCOPE_DEPTH if no instantiations are +active.
      +
      +
    • +
    +

    push_scope also causes new memory regions to be created for the file scope +and for function scopes. When the scope is popped, the following processing is +done:

    +
      +
    • +
      If IL lowering is being performed, should_delay_lowering_on_function is +called to determine whether the function should be lowered at this point. +A number of circumstances can cause lowering to be delayed, such as the +need to preserve unlowered IL for constexpr evaluations, the need for a +module-id that has not yet been determined, etc.
      +
      +
    • +
    • +
      should_delay_finishing_of_function_body is called to determine whether +a function body should be “finished” at this point. If so, +finish_function_body_processing is called. This will lower the +function, if it has not already been lowered, do needed flag processing (if +necessary), and any other operations that may be needed before the memory +is potentially freed.
      +
      +
    • +
    • +
      check_for_done_with_memory_region is called either to write out the +entries in the memory region to a file and reclaim the entire region for +reuse or, if the interface to the back end is in memory, to reclaim only +the unused portion of it. In some cases the memory must be kept and IL +file generation deferred. This is done, for example, when a function body +is kept for potential inlining, or if the function contains a generic +lambda that may be instantiated later.
      +
      +
    • +
    +

    The name scope for a class whose definition is completed must be reinstated to +process the definition of a member function of that class or the initializer of +static data member of that class. This is accomplished by calling +push_class_reactivation_scope, which has the effect of making the symbols +on a symbol header’s inactive list visible (that is, those inactive list +symbols whose decl_scope value matches the scope number of the reactivated +scope become visible). When the class to be reactivated is a nested class, +push_class_reactivation_scope reactivates its enclosing class first to +create the required name visibility and hiding. If the class being reactivated +is from a namespace, the namespace will also be reactivated (see below). A +matching call to pop_class_reactivation_scope is required once processing +for the member function definition or static member initializer is finished.

    +

    The assoc_type field in sck_class_struct_union and +sck_class_reactivation scope stack entries points to the type entry for the +corresponding class, struct, or union.

    +

    Namespace scopes, like class scopes, are reactivated when processing the +declarations of namespace members outside of their namespace. As mentioned +earlier, namespace scopes are unique in that they are not actually closed +when the end of a namespace definition is reached. The namespace can be +extended later either by a namespace extension declaration or by a name +that is injected while processing the definition of a member of a namespace +outside of the namespace (including the instantiation of templates defined +in the namespace). Namespaces are reactivated by calling +push_namespace_reactivation_scope. +pop_namespace_reactivation_scope is called when the reactivated +namespace is no longer required. Reactivating a namespace causes any +namespaces that enclose the reactivated namespace also to be reactivated. +Namespaces are extended by calling push_namespace_extension_scope. +When the namespace extension scope is no longer required, +pop_namespace_extension_scope must be called. Extending a namespace +causes any namespaces that enclose the extended namespace also to be +extended. A namespace is reactivated in contexts in which the names from +the namespace must be visible but new names cannot be added to the +namespace. A namespace is extended in contexts in which names from the +namespace must be visible and new names can be added.

    +

    The scope stack contains a set of pointers that are used to track the symbols +for the scope and the “last” pointers that point to the end of the each of the +lists of IL entries associated with the scope. For most scope kinds, this +information is no longer needed when the scope stack entry is popped off of the +stack. Because namespace scopes can be extended, this information must be +preserved for those scopes. Furthermore, a given namespace can appear on the +scope stack more than once when templates are being instantiated. When more +than one scope stack entry exists for a given namespace, they must share the +same set of symbol and IL entry pointers. The pointers that must be preserved +between extensions of the namespace and shared between scope stack entries for +the namespace are in a structure called a_scope_pointers_block. Each scope +stack entry contains a pointers block structure and field named +assoc_pointers_block that points to a pointers block structure. For all +scopes except namespace and namespace extension scopes, the +assoc_pointers_block pointer is NULL, indicating that the pointers block +within the scope stack entry should be used. For namespace and namespace +extension scopes, the assoc_pointers_block pointer points to a pointers +block in the namespace symbol supplement for the namespace. The macro +assoc_pointers_block_of should be used to obtain a pointer to the +appropriate pointers block for a given scope stack entry.

    +

    push_template_instantiation_scope is called when the appropriate context in +which a given template can be instantiated needs to be established. When a +template instantiation scope is pushed, the sequence of scopes used for name +lookup purposes is changed. In fact, there are four distinct sets of scopes +used for name lookup when a template instantiation in progress:

    +
      +
    • +
      the scopes associated with the local context of the template: These include +the template instantiation scope (with which the template parameters are +associated), the scope associated with the class or function being +instantiated, and any scopes nested within the class or function being +instantiated.
      +
      +
    • +
    • +
      the template definition context scopes: The scopes that are only part of +the context in which the template was defined.
      +
      +
    • +
    • +
      the referencing context scopes: The scopes that are only part of the +context in which the template reference that caused the instantiation +occurred, beginning with the innermost namespace scope.
      +
      +
    • +
    • +
      the common scopes: The scopes that enclose both the definition context and +the referencing context. This always contains at least the file scope.
      +
      +
    • +
    +

    push_instantiation_context determines which of the required namespace +scopes are already present on the scope stack and pushes those entries that are +not already present. It then calls +reactivate_class_and_instantiation_scopes to reactivate any classes that +may enclose the template that is being instantiated. If an enclosing class is +itself a template class, an instantiation scope for that class is also pushed +so that its template parameters will be visible to the entity being +instantiated.

    +

    fixup_instantiation_scopes is called after all of the scopes have been +pushed. It performs the following functions:

    +
      +
    • +
      All of the instantiation scopes that were pushed, except for the outermost +one, are flagged as nested instantiations. Only nonnested instantiation +scopes are considered for special instantiation context lookups, as +described later.
      +
      +
    • +
    • +
      The context and common scope depths are recorded in the nonnested +instantiation scope.
      +
      +
    • +
    • +
      The previous scope pointers of the outermost definition context scope and +the referencing context scope are set to point to the common scope.
      +
      +
    • +
    • +
      The next_scope_that_affects_access_control field is updated to make +sure that it does not point at a scope that is not part of the current +context.
      +
      +
    • +
    • +
      In the set of instantiation scopes pushed by a call to +push_template_instantiation_scope, all except the innermost one have +their exclude_from_context_output flag set. This prevents unnecessary +context information from being generated during diagnostic output.
      +
      +
    • +
    +

    The previous_scope field is also updated when a namespace reactivation +scope is pushed within a template declaration scope. In such cases, the names +from the namespace extension scope must not be considered until after the +template parameters. For example, in the following case the T in the +function parameter list must refer to the template parameter and not N::T.

    +
    namespace N { typedef int T;}
    +template <class T> void N::f(T);
    +
    +
    +

    If GENERATE_SOURCE_SEQUENCE_LISTS is configured to TRUE, source sequence +lists for active scopes are recorded in the scope stack entry (see +source_sequence_list and end_of_source_sequence_list in +a_scope_stack_entry). When pop_scope is called for the file scope or a +function scope, the list is moved to the corresponding IL scope. Otherwise, +the list is merged into the list of a containing scope, which usually means +that the list is simply appended to the list of the immediately containing +scope; for sck_template_instantiation scopes, however (when a +compiler-generated specialization represents an automatic instantiation – that +is, when either CLASS- or +NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is configured to +TRUE), insert_instantiation_src_seq_list is called to move the list to an +appropriate location in the list of an enclosing scope.

    +
    +
    +

    6.2.2. Connection With IL Scope Entries#

    +

    While not all scope stack entries correspond to an intermediate language scope +entry, all intermediate language scope entries have a corresponding scope stack +entry. Every scope stack entry has a (possibly NULL) pointer to an +intermediate language scope entry; every intermediate language scope entry +refers back to the corresponding scope stack entry by means of a scope number.

    +

    For example, a new scope stack entry is pushed for a statement block whether or +not it contains any declarations, but the intermediate language scope is not +created until it is needed, and not till then is the IL_scope pointer in +the scope stack entry updated.

    +

    The scope stack entries for the file scope, namespaces, classes, routines, and +blocks are closely tied to a corresponding intermediate language scope entry: +the latter has pointers to the lists of types, variables, etc. for that scope, +and the pointers block has the pointers to the ends of those lists. The +pointers block in the scope stack entry is used for all scopes except for +namespace and namespace extension scopes, for which the pointers block is +located in the namespace symbol supplement. These tail pointers are only +needed while the scope is active, to add entries at the end of the list, and +having them in the pointers block reduces the size of the intermediate language +scope entry.

    +
    +
    +
    +

    6.3. Classes#

    +

    Classes (in the generic sense, including structs and unions) require the +management of quite a lot of information. Some of this must reside in the +intermediate language. For instance, the entities that represent members of a +class are kept on lists pointed to from the intermediate language scope entry +associated with the class; and the base classes from which the class is derived +are associated with the class’s type entry. In these and other cases +information associated with a class is stored in intermediate language +declarative constructs, and appropriately so, since the information is of use +to back ends.

    +

    However, there is a great deal of information that the front end needs but back +ends do not care about, and it would be wasteful to store it in the +intermediate language. Instead, it is kept in the symbol table so that it can +be thrown away when front-end processing is complete.

    +
    +

    6.3.1. Class Symbol Supplement#

    +

    Entities of type a_class_symbol_supplement, pointed to from all class, +struct, and union tag symbols, constitute the main repository for +front-end-only information about classes.

    +

    Among the fields in class symbol supplements are:

    +
      +
    • +
      symbols, the symbol list pointed to from the scope stack entry for the +class, retained even after the scope stack entry disappears. The symbols +are in declaration order, which is the order in which initialization is to +be performed.
      +
      +
    • +
    • +
      constructor, a pointer to the sk_member_function or +sk_overloaded_function symbol that represents the constructor(s) for +the class. As noted above, the constructor symbol cannot be accessed +directly by normal name lookup, but only via this pointer.
      +
      +
    • +
    • +
      destructor and assignment_operator, pointers to the symbols +representing the destructor and operator=() functions for the class. +Both could also be accessed by normal name lookup, but having the pointers +directly available makes some processing, especially implicit invocations +of these functions, more efficient and facilitates deciding whether the +compiler needs to generate one.
      +
      +
    • +
    • +
      conversion_list, a linked list of entries that provide quick access to +the symbols for the user-defined conversion functions for the class (i.e., +that define a conversion from the class to some other type). The list +includes symbols for inherited conversion functions.
      +
      +
    • +
    • +
      routine_fixup_list, a pointer to entities that store cached tokens to +allow for delayed scanning of default arguments and the bodies of member +functions that are defined inline.
      +

      +
      operator_lookup_namespaces, a pointer to a list of namespaces that are +the parent namespaces of the class or one of its base classes. The global +scope is explicitly represented on this list by an entry with a NULL +namespace pointer. This list is used to specify the namespaces to be +searched for operator functions when an overloaded operator function is +called with an operand of the class.
      +
      +
    • +
    • +
      A number of flags to summarize attributes of the class. Most of these +flags are redundant – the attributes could also be computed by examining +other data. For instance, any_ref_member is checked when putting out +warnings on variables that should be initialized; its value could also be +determined by looking at all the nonstatic data members to see if any have +reference types.
      +
      +
    • +
    +
    +
    +

    6.3.2. Class Member Projection Symbols#

    +

    Symbols of kind sk_projection provide a mechanism to represent names that +are visible in a derived class having been declared in a base class. Each +projection symbol has a supplementary entity of type a_projection_descr +which identifies the fundamental base class member by pointing to the base +class entry and to a symbol from that base class. [5]

    +

    Projection symbols are created as needed (in the course of looking up a name) +and are added to the scope of the derived class. Once entered in a class +scope, they permanently associate the name in the derived class with a +declaration in a base class. The next time the name is looked up in the +lexical context of the class, the projection symbol will be found directly, +without the more expensive search of the base classes.

    +

    A projection symbol records a name’s accessibility in the current scope (e.g., +it may have been declared public originally but be less accessible in the +context of the derived class). It also notes whether a name is ambiguous. +These attributes of name inheritance are computed on the initial lookup, when +the projection symbol is created, and thus need not be recomputed on subsequent +references to the name.

    +

    Projection symbols are also used to represent base class member names that are +explicitly incorporated into the derived class by means of a +using-declaration; for these cases the flag is_using_decl is set to +TRUE.

    +

    When a using-declaration in a derived class specifies an overloaded member +function from a base class, each member of the original overload set will be +projected into the base class independently and recorded in an overload set +created in the derived class. The latter may contain a mix of +sk_member_function symbols from the derived class and sk_projection +symbols referring to member functions in one or more base classes. For +example:

    +
    struct A {
    +  void f(int);
    +  void f();
    +};
    +struct B {
    +  void f(double);
    +};
    +struct C : public A, public B {
    +  using A::f;
    +  using B::f;
    +  void f(char);
    +};
    +
    +
    +

    Here, the overload set for C::f will include C::f(char) along with +projections into C of A::f(int), A::f(), and B::f(double).

    +

    On the other hand, when is_using_decl is FALSE in an sk_projection +symbol, the projection may refer to an entire overload set and not to any +particular instance of the name. In such cases the access value will +represent the greatest access available; a particular function may turn out to +have less accessibility.

    +
    +
    +

    6.3.3. Namespace Projection Symbols#

    +

    Symbols of kind sk_namespace_projection are used to represent names made +visible by using-declarations that refer to namespace members +(using-declarations that refer to class members are described above). As +with class member using-declarations, when a using-declaration +specifies a overloaded function from another namespace, each member of the +overload set is projected into the current scope separately. The resulting +overload set may contain a mix of function, function template and namespace +projection symbols.

    +
    +
    +
    +

    6.4. Template Symbols#

    +

    Symbols of kind sk_class_template and sk_function_template have an +associated entry of kind a_template_symbol_supplement. Template processing +is discussed in detail in another chapter.

    +
    +
    +

    6.5. Namespace Symbols#

    +

    Symbols of kind sk_namespace have an associated entry of kind +a_namespace_symbol_supplement. As described above, the namespace symbol +supplement contains the pointers block used by scope stack entries that refer +to the namespace. It is possible for more than one scope stack entry for a +namespace or namespace extension scope to refer to a single namespace. In such +cases the scope stack entries all refer to the one pointers block structure in +the namespace symbol supplement. The namespace symbol supplement also contains +information used by the name lookup routines when doing lookups in the presence +of using-directives.

    +
    +
    +

    6.6. Symbol Lookup#

    +
    +

    6.6.1. Symbol Locator#

    +

    Symbol lookup is the process whereby a name, a qualified name, an operator +token, or a conversion result type is used to search for a symbol in the symbol +table and, if it exists, return it to the caller. A key intermediary construct +in this process is the entity of type a_symbol_locator. It consists of

    +
      +
    • +
      A pointer to a symbol header. (Sometimes error locators have a NULL symbol +header pointer; in all other cases a locator will point to a valid symbol +header.)
      +
      +
    • +
    • +
      A source position, the line and column in the source program at which the +reference starts.
      +
      +
    • +
    • +
      specific_symbol, a pointer to a symbol. This is usually NULL, but if +preliminary processing happens to turn up a symbol (e.g., in validating a +qualified name), it is saved here so that the lookup need not be done +again.
      +
      +
    • +
    • +
      The is_qualified_name, is_global_qualified_name, +is_file_scope_qualified_name, and is_super_qualified flags, which +specify the kind of qualifier, if any, that preceded the name.
      +
      +
    • +
    • +
      is_class_member, a flag that is TRUE for qualified names for which the +qualifier names a class. Note that the qualifier may also contain a +namespace specifier, but the last qualifier specifies a class name.
      +
      +
    • +
    • +
      parent, a union that, for qualified names, contains a pointer to either +the class or namespace specified by the qualifier. The is_class_member +field is used to specify whether the qualifier is a class or a namespace. +This field is also used to specify the class type associated with a vacuous +destructor reference.
      +
      +
    • +
    • +
      The is_template_id flag is TRUE if the name was followed by a template +argument list that has been coalesced. If the name is a class template +name, the specific_symbol will point to the template class designated +by the template argument list. The do_not_clear_specific_symbol flag +is set to TRUE when a class template argument list is coalesced because the +template argument list is not retained in the locator, and it would be +impossible to recompute the specific_symbol value if it were cleared.
      +
      +
    • +
    • +
      template_arg_list is used when an explicit function template argument +list is specified, and points to the template argument list that was +scanned. The is_template_id flag is also set. An empty template +argument list may be specified (e.g., “<>”), so the is_template_id +flag should be used to check for the presence of an explicit function +template argument list, not the template_arg_list field.
      +
      +
    • +
    • +
      The is_operator_name flag and the operator name kind. This flag is +TRUE and the associated field is defined only when it is an operator name +that is being looked up.
      +
      +
    • +
    • +
      The is_conversion_name flag and the conversion result type. This flag +is TRUE and the associated field is defined only when it is a user-defined +conversion that is being looked up.
      +
      +
    • +
    • +
      The is_destructor_name flag is TRUE when the name is a destructor name.
      +
      +
    • +
    • +
      The is_vacuous_destructor_reference and is_nonclass_destructor +flags, which are used to identify explicit destructor references for +classes without destructors or for nonclass types.
      +
      +
    • +
    • +
      The is_semivisible_nested_class flag is TRUE when the name is not +visible by standard scoping rules but only by a special search that +implements the “nested class anachronism” (ARM 18.3.5).
      +
      +
    • +
    • +
      The access_control_error_reported flag is TRUE if an accessibility +error has already been issued on the symbol.
      +
      +
    • +
    • +
      The is_error flag is TRUE when the locator represents an error.
      +
      +
    • +
    • +
      The do_not_clear_specific_symbol flag is TRUE if the +specific_symbol points to a value that should be retained because it +cannot or should not be reproduced by a repeated lookup. This is primarily +used for coalesced class template references, as described above, but is +also used for specific symbol error locators (error locators that refer to +a specially created error symbol).
      +
      +
    • +
    +

    Symbol locators are necessary because symbol lookup sometimes occurs in several +stages at separate points of processing. They provide a way to save and use +the intermediate results. For instance, when an identifier is scanned by +get_token, the locator is stored in locator_for_curr_id. Often a local +copy is made so that the information can be preserved as additional tokens are +scanned. Then when it comes time to actually enter the symbol in the symbol +table, all the information needed is right there in the locator.

    +
    +
    +

    6.6.2. Identifiers and Symbol Headers#

    +

    Each name in the source program is looked up as it is scanned. This is +necessary in part so that get_token processing can distinguish identifiers +from keywords.

    +

    find_symbol is called to look up the names in the hash table pointed to by +global variable symbol_table. The interface to find_symbol uses a name +string with a length rather than a null-terminated string because the string in +question is usually part of the source line buffer.

    +

    After the bucket number is computed, it searches the list of symbol headers +pointed to by the bucket till it finds a matching name. If it finds a match, +it moves the symbol header to the front of its bucket list so that +frequently-used entries will cluster near the beginning. If no match is found, +a new symbol header is created and entered. A pointer to the symbol header +(whether newly created or not) is returned in the symbol locator, and a pointer +to the list of active symbols associated with the symbol header is also +returned.

    +
    +
    +

    6.6.3. normal_id_lookup#

    +

    find_symbol locates a symbol header but does not actually find the symbol +itself. For simple names (e.g., not qualified names) that is done by +normal_id_lookup, which searches the symbol header’s active list – and, if +appropriate, its inactive list – to find a symbol in the appropriate name +space and lexical scope.

    +

    normal_id_lookup uses one of two search algorithms. The fast search (which +is the only one used in ordinary C mode) simply searches the active list: the +first symbol found which meets the search requirements is returned; in C++ mode +this search may only be used when there are no scopes on the scope stack that +alter the sequence in which scopes are considered for name lookup, and when the +lookup is not one of a number of special lookups that disregard certain kinds +of symbols.

    +

    The second and slower algorithm is required when

    +
      +
    • +
      A class or class reactivation scope is present, in which case one must look +for inactive symbols for the class members and for member names that are +inherited from base classes.
      +
      +
    • +
    • +
      A namespace, namespace extension, or namespace reactivation scope is +present, in which case one must look for inactive symbols for the namespace +members.
      +
      +
    • +
    • +
      A template instantiation scope is present, in which case inactive symbols +for the template parameters must be considered, and the scopes must be +searched in an irregular order (as described earlier).
      +
      +
    • +
    • +
      A using-directive is in effect, in which case one must look for symbols +for the namespaces referenced directly or indirectly by the +using-directive.
      +
      +
    • +
    • +
      A special lookup option has been specified for a given lookup. For +example, the lookup may optionally ignore class scopes, etc.
      +
      +
    • +
    +

    In such cases each scope must be considered individually, since there is no +single list that summarizes the visibility of names.

    +

    This comes up, for instance, in the non-inline definition of a member function: +the class definition has been completed and its names have been removed from +the active list, so those names must be searched for on the inactive list. For +example,

    +
    int i;
    +struct S { int i; int f(); };
    +int S::f() { return i; }
    +
    +
    +

    Here, when the body of S::f() is being scanned, the symbol for ::i will +be on the active list of the symbol header for i, whereas the symbol for +S::i will no longer be in scope, having been moved over to the inactive +list when the definition of S was completed. However, since the scope for +S is reactivated before the member function body is scanned, and since the +reactivated scope is examined before the file scope, it is S::i rather than +::i that will be found.

    +

    Similarly, when a namespace member is defined outside of its namespace a +namespace extension scope is pushed onto the scope stack at the point at which +names from the namespace should be visible.

    +
    int i;
    +namespace N { int i; int f(); }
    +void N::f() { return i; }
    +
    +
    +

    Here, as with the class member example shown above, the namespace member +N::i is found, hiding ::i.

    +
    +

    6.6.3.1. Slow Lookup Processing (scope_stack_lookup)#

    +

    scope_stack_lookup and the routines it calls are used to implement the slow +lookup. It is passed a range of scope depths to be included in the lookup. +Each scope is examined separately. The lookup begins with the scope stack +entry indicated by the global variable depth_of_initial_lookup_scope and +proceeds by following the previous_scope link in the scope stack entry +until a scope entry with no previous scope is found. active_scope_lookup +is called for scopes whose symbols are still on the active list and +inactive_scope_lookup is called for scopes whose symbols have been +transferred to the inactive list. When a class or class reactivation scope is +processed, a flag is returned that specifies whether scope_stack_lookup +should look for a projection symbol for the class as described below.

    +

    When a template instantiation scope has been processed, and a symbol has not +yet been found, names from both the context in which the template was defined +and from the context in which the template was used must be considered. This +is done by calling instantiation_context_lookup, which is described below.

    +

    A using-directive can cause names from other namespaces to be visible in a +namespace scope (including the global scope) that is currently on the scope +stack. The using_directives_apply flag in the scope stack entry is used to +indicate that such processing is required. When this flag is set for a +namespace scope or the global scope, do_using_directive_lookup is called to +search for applicable symbols from namespaces named in using-directives.

    +

    The presence of using-directives can result in more than one symbol +being found that satisfies the lookup. In such cases +do_using_directive_lookup creates a synthesized namespace projection +symbol that represents the set of symbols found (See using-Directive Processing and +Synthesized Namespace Projection Symbols). The lookup could determine that the name is +ambiguous in the current context, in which case a synthesized namespace +projection symbol that is flagged as ambiguous is returned.

    +
    +
    +

    6.6.3.2. Looking for Class Member Projection Symbols#

    +

    When a name is not found in a class, the classes from which it is derived must +be searched before the containing scope is examined. This is done by +find_projected_symbol, which looks for the name among the base classes (see +find_progenitor_symbol and symbol_projected_from_base_class) and if +successful creates an sk_projection symbol in the derived class and adds it +to either the active or the inactive list of the symbol header for the name. A +pointer to the projection symbol, which (as described previously) represents +the inheritance, is returned to normal_id_lookup, where it is placed in the +locator (field specific_symbol); a pointer to the symbol of which it is the +projection is returned from normal_id_lookup as the function return value. +Consider this example:

    +
    int i;
    +struct S { int i; };
    +struct T : public S { int f(); };
    +int T::f() { return i; }
    +
    +
    +

    In this case the scope for T is reactivated when the body of T::f() is +scanned. No T::i is found in the scope of T, but before the containing +scope (namely the file scope) is searched, the base class must be examined, and +so normal_id_lookup calls find_projected_symbol. This search turns up +S::i, so again ::i is eclipsed. In addition, a projection symbol for +i is created in class T (it points to S::i since it represents the +“projection” of i from S into T). Thus, on subsequent searches for +i in the scope of T a T::i will be found, namely the projection +symbol referring to S::i, and so the base class search will not have to be +repeated.

    +

    find_projected_symbol and its subroutines also compute the accessibility of +the inherited name and determine whether it is ambiguous. No errors are put +out at this point, since the name lookup routines are interested in name +visibility only; instead, the status is recorded in the projection symbol and +diagnostics can be issued later if appropriate.

    +
    +
    +

    6.6.3.3. Instantiation Context Lookup#

    +

    When a name is looked up as part of a template instantiation, and the name is +not found in the local context of the instantiation (the template parameters +and the scope(s) associated with the class or function being instantiated) it +must be looked up in the instantiation context. The front end implements two +different instantiation context lookup algorithms: the one mandated by the +standard (referred to as “dependent name lookup”), and the one that existed +before dependent name lookup was implemented that more closely reflects +existing practice and is more compatible with other compilers.

    +

    As described earlier, push_template_instantiation_scope configures the +scope stack so that three distinct contexts exist outside of the local context +of the instantiation: the template definition scopes, the referencing context +scopes, and the scopes common to both.

    +

    When doing dependent name lookup, the following steps are used to produce the +final result of the lookup:

    +
      +
    • +
      The name is looked up in the context of the template definition and only +names visible at the point of the template definition are considered.
      +
      +
    • +
    • +
      Only those base classes that do not depend on template parameters are +considered.
      +
      +
    • +
    +

    When not doing dependent name lookup, the following steps are used to produce +the final result of the lookup:

    +
      +
    • +
      The name is looked up in both the template definition context and the +referencing context by calling scope_stack_lookup with the appropriate +starting and ending scope depths. The lookup in the referencing context is +suppressed if the lookup in the definition context finds a class member.
      +
      +
    • +
    • +
      If none or only one of the lookups produces a symbol, and if the lookup in +the definition context did not find a class member, scope_stack_lookup +is called again to look in the common scopes.
      +
      +
    • +
    • +
      If no symbols were found by the two context lookups, the result of the +common scope lookup is used.
      +
      +
    • +
    • +
      If only one of the two context lookups produced a symbol, the result of the +common scope lookup is used as the value of the context lookup that did not +produce a symbol, and the next rule is followed.
      +
      +
    • +
    • +
      If the symbol from the referencing context is not a function or function +template, it is discarded.
      +
      +
    • +
    • +
      If there is still only one symbol from the two context lookups, that symbol +is used.
      +
      +
    • +
    • +
      If there are two symbols, a synthesized namespace projection symbol is +created that represents the result of the lookup.
      +
      +
    • +
    +

    Note that in both cases, these algorithms describe the result of the “normal” +lookup of the name. In addition to the entities made visible by the normal +lookup, additional functions and/or function templates may be made visible by +argument-dependent lookup.

    +
    +
    +

    6.6.3.4. Nested Class Anachronism Lookup#

    +

    If the processing described thus far in normal_id_lookup fails to find a +qualifying symbol, an additional search implementing the “nested class +anachronism” (ARM 18.3.5) is performed by calling find_nested_class_symbol, +which finds names of nested classes which, strictly speaking, should not be +visible. For example,

    +
    struct S {
    +  struct T {
    +    int a;
    +  };
    +  int b;
    +};
    +struct T x;
    +
    +
    +

    After the normal search for T is exhausted without turning up a symbol, an +additional search is made through the inactive list of the corresponding symbol +header for a symbol of a nested class whose innermost non-class containing +scope (in this case, the file scope) is still an active scope (in this case, it +is). When such a symbol is found, and it is the only symbol that qualifies, it +is returned to normal_id_lookup and a warning is issued. [6]

    +
    +
    +

    6.6.3.5. Nonreal and Proxy Class Lookup#

    +

    If the processing described thus far in normal_id_lookup fails to find a +qualifying symbol, and one or more of the classes included in the lookup has a +“nonreal” base class, a nonreal class member is created by calling +add_member_to_proxy_or_nonreal_class, and the symbol for the newly created +class member is returned.

    +
    typedef int Y;
    +template <class T> struct A : T {
    +  X x;   // assumed to be T::X
    +  Y y;   // ::Y
    +};
    +
    +
    +

    The nonreal lookup is only done when the normal lookup fails to find a symbol. +In the example above, ::Y is found, so no nonreal member is created. The +lookup of X fails to find a symbol, so a nonreal member is created.

    +
    +
    +

    6.6.3.6. Hide-by-sig lookup#

    +

    C++/CLI has a special kind of lookup used for members of managed classes, +called “hide-by-sig” lookup. In normal C++ name lookup, a name in a derived +class hides all instances of the same name in a base class; this is called +“hide-by-name” lookup. In hide-by-sig lookup, on the other hand, a member +function in a derived class hides a member in a base class only if their +signatures match. A function “voidf(int)” in a derived class, for +example, would not hide a function “voidf(char)” in a base class; +both would appear in an overload set and might compete with each other. In +addition, hide-by-sig lookup considers access – inaccessible members of base +classes are not seen by the lookup. And there are special rules regarding +interfaces, which are too arcane to describe here. Hide-by-sig lookup only +applies to functions.

    +

    Hide-by-sig lookup is implemented by building a list of +a_hide_by_sig_list_entrys that enumerates all the symbols that co-exist +with a given symbol in an overload set. The list is built by +use_hide_by_sig_lookup and saved in the symbol’s +hide_by_sig_lookup_result field so it only needs to be constructed the +first time a hide-by-sig lookup is done on the symbol. Overload resolution +traverses that list to build up the set of functions in an overload resolution +set. Access is checked while the overload set is built up, and inacessible +functions are discarded at that point (different places in the program may have +differing access to the base class members; this allows a single general +hide-by-sig list to be built and then used with different access contexts).

    +
    +
    +

    6.6.3.7. Lookup of Entities Imported from C++/CLI Metadata#

    +

    When C++/CLI metadata files are imported by way of a #using directive or +implicitly for the entities in mscorlib, only the namespace-scope-level +names in the file are added to the symbol table. For a class, for example, the +class name is entered as an incomplete type, and its definition and members are +not immediately entered. Later, if a lookup is done in the class scope, the +members of the class are fetched from metadata and added to the symbol table. +This “lazy” lookup makes the use of metadata files much more efficient, since +things are not loaded until they are actually needed. This is implemented by +piggy-backing on the mechanism that instantiates templates when a member of the +template is required: f_instantiate_template_class (often invoked from the +macro complete_class_type_is_needed)will call get_definition_of_class +to fill in the definition of an entity imported from metadata. This is done +automatically whenever a class-scope lookup is done in a class that came from +metadata. The definition is loaded, the lookup is then done, and the result is +returned to the caller, who has no need to know that the class definition had +to be loaded to be able to perform the name lookup.

    +
    +
    +

    6.6.3.8. C mode out-of-scope declarations#

    +

    When compiling C code, if the processing described thus far in +normal_id_lookup fails to find a qualifying symbol, +find_out_of_scope_declaration is called to look for an external variable or +function that was declared in a scope that is no longer visible. If such a +symbol is found, it is reentered in the current scope and returned as the +result of the lookup.

    +
    void g1(void) {
    +  extern void f(int);
    +  f(1);
    +}
    +void g2(void) {
    +  f(2);
    +}
    +
    +
    +

    A symbol for void f(int) is reentered in g2, even though f is no +longer visible. This lookup is not performed in strict mode.

    +
    +
    +

    6.6.3.9. Lookup Options#

    +

    Options flags may be supplied to normal_id_lookup that affect the kinds of +symbols that are visible and other aspects of the name lookup process. In +certain contexts a name lookup is required to determine whether a given name is +a type. In this context a projection symbol should not be created unless the +name is a type. The flag IDL_TENTATIVE_TYPE_LOOKUP is used to suppress the +creation of a projection symbol in this instance.

    +

    A special lookup is also required when scanning a constructor initializer list +that may include member names and base class names but may not reference the +names of parameters of the constructor. The IDL_SKIP_CURR_FUNCTION_SCOPE +flag is used to request this kind of lookup.

    +

    IDL_LINKAGE_LOOKUP indicates that the lookup is being used to find a +previous declaration of a name and that certain special lookup features should +be suppressed and that the lookup should terminate at the nearest enclosing +namespace scope. This option suppresses nested class anachronism, nonreal +member lookup, and out-of-scope declaration processing.

    +

    IDL_SKIP_CLASS_SCOPES causes class and class reactivation scopes to be +ignored. This is used when looking up nonmember operator functions.

    +

    IDL_INSTANTIATION_CONTEXT is used to indicate that a lookup operation is +part of a special instantiation lookup that looks in both the template +definition and reference contexts.

    +
    +
    +
    +

    6.6.4. Looking Up Names in the Current Scope#

    +

    curr_scope_id_lookup looks up a name in the current scope and returns the +symbol found or NULL if no symbol is found. The symbol must be a name declared +in the scope. using-directives are not considered and projection symbols +to base class members are not considered unless the +IDL_PROJECTION_SYMBOL_ALLOWED option is specified.

    +
    +
    +

    6.6.5. Looking Up Class Members#

    +

    class_qualified_id_lookup is used to look up a name in the scope of a class +and its base classes. As with normal_id_lookup, the caller provides a +symbol locator that contains a pointer to the symbol header for the identifier +being looked up. The search begins by looking through the inactive list for a +symbol from the scope associated with the class type passed by the caller. If +the symbol is not found on the inactive list, the active list is also checked. +The active list check is needed when a class-qualified lookup is done while the +class is being defined. For example,

    +
    struct A {
    +  struct B {};
    +  A::B f();  // the A:: is not necessary, but is allowed
    +};
    +
    +
    +

    If the symbol has still not been found, and the lookup is being done in a +nonreal class, a symbol for a nonreal class member is created by calling +add_member_to_proxy_or_nonreal_class, and the newly created symbol is +returned (see Nonreal and Proxy Class Members for more information).

    +

    If the symbol has still not been found, the name is checked to see if it is a +constructor or destructor for the class. If so, the symbol for the constructor +or destructor from the class symbol supplement is returned.

    +

    Finally, if the symbol has still not been found, find_projected_symbol is +called to search the base classes for a member that may be projected into the +class.

    +
    +

    6.6.5.1. Nonreal and Proxy Class Members#

    +

    A nonreal class is a template class that has one or more template arguments +that depend on template parameters. A proxy class is a class that stands in +for a template parameter when that template parameter is used in a context that +requires a class type. For example:

    +
    template <class T> struct A {
    +  typename T::A      a;
    +  typename A<T*>::X  b;
    +  typename T::Z<int> c;
    +  int n[T::B];
    +};
    +
    +
    +

    In this example a proxy class is created for T so that A and B may +be looked up in T. A nonreal class for A<T*> is created, a nonreal +template named T::Z is created, and the nonreal instance T::Z<int> is +created.

    +

    proxy_class_for_template_param creates a proxy class associated with a +given template parameter. The proxy class is created the first time that it is +needed

    +

    create_proxy_or_nonreal_class_member creates a member of a nonreal or proxy +class. It is called by add_member_to_proxy_or_nonreal_class which also +adds the newly created symbol to the inactive list so that it may be found by +subsequent lookups. The kind of entity that is created (type, constant, or +template) depends on the kind of lookup that is done, and on whether the +“implicit typename” option is enabled. nonreal_member_symbol_kind is used +to determine the kind of symbol to be created for a given set of lookup +options.

    +
    +
    +
    +

    6.6.6. Looking Up Namespace Members#

    +

    namespace_qualified_id_lookup is used to look up a name in the scope of a +namespace. If the name is not found in the namespace, the name is also sought +in any namespaces referenced by using-directives in the specified +namespace. lookup_in_namespace is called to look for the name in the +specified namespace. If a symbol is found, it is returned; otherwise +lookup_in_namespace calls qualified_using_directive_lookup, which loops +though the using-directives found in the original namespace and calls +lookup_in_namespace recursively to look for the name in those namespaces. +qualified_using_directive_lookup always considers all namespaces named in +using-directives within a given namespace (i.e., it does not stop searching +when a symbol is found in a given namespace). For example, the hierarchy below +would be created by the following example:

    +
    //   D       E
    +//    \     /
    +//     B   C
    +//      \ /
    +//       A
    +namespace E { }
    +namespace D { }
    +namespace C { using namespace E; }
    +namespace B { using namespace D; }
    +namespace A { using namespace B; using namespace C;}
    +
    +
    +

    In such a hierarchy, when looking up a name in namespace A

    +
      +
    • +
      If the name is found in A, the lookup will not look in any other +namespace.
      +
      +
    • +
    • +
      If the name is not found in A, the lookup will always look in both +B and C.
      +
      +
    • +
    • +
      If the name is not found in B, the lookup will look in D.
      +
      +
    • +
    • +
      If the name is not found in C, the lookup will look in E.
      +
      +
    • +
    +

    The presence of using-directives can result in more than one symbol +being found that satisfies the lookup. In such cases +qualified_using_directive_lookup creates a synthesized namespace +projection symbol that represents the set of symbols found (see +using-Directive Processing and Synthesized Namespace Projection Symbols). The lookup could determine +that the name is ambiguous in the current context, in which case a +synthesized namespace projection symbol that is flagged as ambiguous is +returned.

    +

    When a namespace contains an inline namespace (a C++11 feature), or a namespace +named in a GNU strong using-diirective, namespace lookup is done slightly +differently. Normally, if a name is found in a namespace, other namespaces +made visible in that namespace by using-directives are not searched, but a +namespace was made visible as an inline namespace (or strong using-directive) +is searched even when a symbol was found in the original namespace.

    +
    +
    +

    6.6.7. Looking Up Names in the File Scope#

    +

    The file scope is also known as the global scope, and, with the addition of +namespaces, as the “global namespace”. The same qualified name lookup rules +apply to both namespace qualified lookups and file scope qualified lookups. +file_scope_id_lookup looks on the active list for a name declared at the +file scope. If the name is not found on the active list, the inactive list is +seached. If the name is not found in the file scope, +qualified_using_directive_lookup is called to look in scopes named by +using-directives in the file scope.

    +

    In the presence of multiple translation units there can be more than one file +scope. The scope pointer for the file scope to be used is passed to +file_scope_id_lookup.

    +
    +
    +

    6.6.8. Argument-Dependent Lookup#

    +

    When an unqualified name is used as the function name in a function call, the +name is looked up using both the normal lookup mechanism and also using what is +known as “argument-dependent lookup”. Argument-dependent lookup uses the types +of the function arguments to produce a set of “associated classes” and +“associated namespaces” to be searched for candidate functions.

    +

    argument_dependent_lookup is called to perform an argument-dependent +lookup. It calls determine_assoc_namespaces_and_classes to determine the +associated namespaces and classes to be used for the lookup. Normally, only +names from the current translation unit are considered by the +argument-dependent lookup process, but when instantiating exported templates +(and non-exported templates whose instantiation results from the instantiation +of an exported template) argument-dependent lookup is done in each of the +translation units on the translation unit stack and the results of the lookups +are combined.

    +

    Argument-dependent lookup returns a list of symbols representing the candidate +functions being found. The symbol list may contain functions, function +templates, and overload sets. Argument-dependent lookup is normally done in +conjunction with a normal lookup. The symbol representing the normal lookup +result is passed to argument_dependent_lookup and is returned as an element +of the resulting symbol list. The resulting symbol list may directly or +indirectly (as part of an overload set) include multiple instances of a given +function or function template. This occurs for several reasons:

    +
      +
    • +
      The symbol list includes the result of both the normal and +argument-dependent lookups, which may produce overlapping results.
      +
      +
    • +
    • +
      The symbol list includes overload sets which may, as a result of +using-directives, include the same functions or function templates.
      +
      +
    • +
    • +
      The argument-dependent lookup may be done in multiple translation units +when exported templates are used. The same functions or templates may be +found in more than one of the translation units.
      +
      +
    • +
    +
    +
    +

    6.6.9. using-Directive Processing#

    +

    using-directives are used to make names from a namespace visible at a +certain point in the unqualified lookup process (i.e., the lookup performed by +normal_id_lookup). using-directives that appear in namespace scopes +can also affect qualified lookups in the namespace in which they appear. +Qualified using-directive lookups simply make use of the +using-directives list found in the scope entry. Unqualified +using-directive lookups, on the other hand, rely on additional data +structures that are maintained to optimize the process of finding names made +visible by using-directives during the normal_id_lookup process.

    +

    A using-directive can appear in a namespace scope (including the files +scope), or in a block scope. The scope that contains the using-directive +is often not the scope at which the using-directive “applies”, however. A +using-directive “applies” at the nearest enclosing scope that is or +contains the namespace named in the using-directive, and contains the +using-directive. For example,

    +
    namespace A {}
    +namespace B {
    +  namespace C {
    +    using namespace A;  // applies to the file scope
    +  }
    +  using namespace C;    // applies to B
    +}
    +using namespace B::C;   // applies to the file scope
    +
    +
    +

    The primary piece of information that is maintained to optimize unqualified +using-directive lookups is a field in the namespace symbol supplement that +indicates the scope depth of the scope at which a using-directive for that +namespace applies, or contains NO_SCOPE_DEPTH if there is no +using-directive in effect that makes symbols from the associated namespace +visible.

    +

    do_using_directive_lookup simply looks through the inactive symbols for a +symbol whose parent namespace has a using-directive that applies at the +scope depth currently being processed by scope_stack_lookup.

    +

    The problem with this kind of state information is that it needs to be reset +each time a template instantiation begins and restored each time an +instantiation ends. To make the process of clearing and restoring the state +information as efficient as possible, the scope stack entry contains a list of +“active” using-directives for the scope. An active using-directive is +one that appeared in the scope or appeared in one of the namespaces named by a +using-directive in the scope.

    +

    When a using-directive appears, add_active_using_directive is called to +add it to the active using-directive list for the current scope. It then +calls add_active_using_directive_to_scope, which actually adds it to the +list.

    +

    using-directives are transitive, meaning that any using-directives that +appear in the namespace nominated by a using-directive are treated as if +they also appeared in using-directives in the scope containing the original +using-directive. add_active_using_directives_for_namespace is called +to add the namespaces that appear in using-directives in the nominated +namespace to the active using-directive list, which it does by recursively +calling add_active_using_directive_to_scope. When +add_active_using_directive adds a using-directive to a namespace scope +it searches through the scope stack to find active using-directive lists +that refer to the namespace containing the new using-directive. If such +scopes are found, add_active_using_directive_to_scope is called to add the +newly nominated namespace to those scopes.

    +

    add_active_using_directive_to_scope determines the scope depth at which a +using-directive applies. This scope depth is recorded in the namespace +symbol supplement of the namespace being added. The scope stack entry +associated with that scope depth is updated to indicate that there are +using-directives that apply when that scope is reached in an unqualified +lookup.

    +

    set_active_using_list_scope_depths is called to reset and restore the state +of the scope depth information in the namespace symbol supplement and the +using_directives_apply field in the scope stack entry. This is done at the +beginning and end of a template instantiation scope, and is also done whenever +a scope containing active using-directives is popped off of the stack.

    +
    +
    +

    6.6.10. Synthesized Namespace Projection Symbols#

    +

    The addition of namespaces creates situations in which the result of a lookup +can be a set of symbols from different scopes. A synthesized namespace +projection symbol is created to represent the result of such a lookup. +Synthesized namespace projection symbols are created

    +
      +
    • +
      by an unqualified lookup in which the symbols found were made visible by a +using-directive,
      +
      +
    • +
    • +
      by an qualified lookups in which the symbols found were made visible by a +using-directive, and
      +
      +
    • +
    • +
      by an instantiation context lookup in which symbols were found in both the +definition and referencing contexts.
      +
      +
    • +
    +

    The synthesized_namespace_projection flag in the symbol entry identifies a +symbol as a synthesized namespace projection. Such symbols can be of kind +sk_namespace_projection or sk_overloaded_function. In the latter case, +each of the entries on the list of overloaded functions points to a +sk_namespace_projection symbol.

    +

    Where synthesized namespace projection symbols are used, the lookup must result +in at most one symbol being found, or, all of the symbols found must be +functions that can be combined into an overload set. If more than one symbol +is found and they are not all functions, the lookup is ambiguous. The +ambiguous flag in the symbol entry is set in that case.

    +

    The following steps are used to construct a synthesized namespace projection +symbol for a given lookup:

    +
      +
    1. find_synthesized_projection_symbol is called to find a previously +created namespace projection symbol. This is done so that the space used +by a previously created synthesized projection symbol can be reused. +The actual information pointed to by the symbol is not reused because it +may have changed since the last lookup was done. More specifically, a +set of overloaded functions is assumed always to contain at least the +functions that were previously in the set. When looking for a previously +created symbol, the lookup options used for the new lookup must match +the options used when the symbol was created. A number of symbols with +the same name but with different lookup options may be created in a +given scope. Some combinations of lookup options are considered to be +sufficiently unusual that they are not entered in the symbol header for +reuse. Such symbols are identified by setting the do_not_reuse flag in +the symbol entry. find_synthesized_projection_symbol suppresses the +search and returns NULL when asked to find a symbol with a set of lookup +options for which symbols cannot be reused. The lookup options used when +a synthesized namespace projection symbol is created are stored in a set +of flags in the symbol entry. The flags used for this purpose are

      +
        +
      • +
        qualified_lookup
        +
        +
      • +
      • +
        must_be_class_or_namespace_lookup
        +
        +
      • +
      • +
        must_be_tag_lookup
        +
        +
      • +
      • +
        tentative_type_lookup
        +
        +
      • +
      • +
        do_not_reuse
        +
        +
      • +
      • +
        instantiation_context_lookup
        +
        +
      • +
      +
    2. +
    3. +
      As symbols are found that match the lookup criteria, +add_symbol_to_lookup_set is called with a pointer to the previously +created synthesized projection symbol (if any) and the symbol to be added. +The symbol returned is used as the new synthesized projection symbol.
      +
      +
    4. +
    5. +
      add_symbol_to_lookup_set calls merge_function_into_lookup_set +when the symbol being added is a function or function template. Before a +function is actually added, the current lookup set is examined, by calling +already_in_lookup_set, to make sure it is not already present.
      +
      +
    6. +
    7. +
      add_symbol_to_lookup_set determines whether the symbol being added +can coexist with any symbols already in the lookup set, whether the new +symbol should hide a previous symbol, or whether the lookup is ambiguous.
      +
      +
    8. +
    +

    Reusable synthesized projection symbols are entered on the “other” symbols list +in the symbol header and on the synth_namespace_projection_symbols list in +the pointers block for the scope with which they are associated. Symbols that +are not reusable are only entered on the list in the pointers block. +Synthesized projection symbols that are created by a qualified lookup are +entered in the scope of the namespace of the qualifier. All other synthesized +projection symbols are entered into the current scope.

    +
    +
    +

    6.6.11. Overloaded Operators#

    +

    Overloaded operators are not looked up by name, so find_symbol cannot be +used to locate the symbol header. Instead, the header is found by indexing +into the array of symbol header pointers opname_symbol_table. The index +value will be a member of the enumeration an_opname_kind, which maps to the +subset of the enumeration a_token_kind that comprises those operators +subject to overloading. [7]

    +

    When an overloaded operator is explicitly named (for instance, operator+ or +A::operator new), it is represented by a tok_identifier “pseudo-token” +somewhat like qualified names. The symbol locator’s is_operator_name flag +will be set and the field opname will identify the operator being +overloaded. make_opname_locator is called to set these fields and as well +to create and enter the symbol header if one does not yet exist. Scanning the +token sequence representing an overloaded operator is handled by +f_get_opname , [8] which does error checking and also deals with +conversion operators (discussed below).

    +

    nonmember_operator_function_lookup is used to find the set of nonmember +overloaded operator functions for a given operator kind and a pair of operand +types. When looking for a nonmember operator function, one must do a normal +(i.e, unqualified) lookup of the operator name, and one must also look up the +operator name in the namespaces of the operand types and the base classes of +the operand types. For each class type, there is a list of namespaces in which +to look for nonmember operator functions. The list is pointed to by the +operator_lookup_namespaces field of the class symbol supplement. The +search is done by looking at both the active and inactive lists from the +appropriate symbol header and checking whether the parent namespace of the +symbol is on the operator lookup namespaces list of one of the operand class +types. Note that only immediate members of the namespaces on the operator +lookup namespaces list are considered. using-directives in those +namespaces have no effect on the lookup. The result of the lookup is a pointer +to a list of entry of kind a_symbol_list_entry or NULL if no such operator +functions have been declared. Each entry points to a symbol that meets the +lookup criteria. The caller is responsible for freeing the symbol list when it +is no longer needed by calling free_list_of_symbol_list_entries. +opname_function_symbol is a simplified version of +nonmember_operator_function_lookup that is used for looking up new and +delete operators, which cannot be declared in namespaces.

    +

    global_operator_new_or_delete_symbol looks up symbols for the default +versions of operator new and delete at file scope (i.e., ::operator +new(size_t) and ::operator delete(void*)), but unlike +opname_function_symbol it will, if no such symbol exists yet, implicitly +declare the function, creating and entering its symbol and adding the routine +entry to the IL.

    +
    +

    6.6.11.1. Template Conversion Operators#

    +

    When a class contains a template conversion operator, the lookup of a +particular conversion operator may require the partial instantiation of the +conversion operator template. For example:

    +
    struct A {
    +  template <class T> operator T();
    +};
    +int main(){
    +  A a;
    +  a.operator int();
    +}
    +
    +
    +

    Class A does not contain an operator int conversion function that can +be found by the normal lookup mechanism. Instead, the lookup operation must +match the required type (int) with the available conversion templates to +see if a match can be found. look_up_conversion_template_instance is +called to look for the matching conversion template. If more than one matching +template is found a symbol that is marked as ambiguous is returned.

    +

    If the result type of the conversion depends on a template parameter, or if the +class type on which the conversion operator is being called is a nonreal class, +it is not possible to find a matching conversion operator. In such cases an +“unknown conversion function” entry is created. This is represented by a +special kind of template parameter constant that contains a pointer to the +conversion result type.

    +
    +
    +
    +

    6.6.12. Constructors and Destructors#

    +

    Several routines search for a constructor or destructor of a particular kind in +a given class.

    +

    select_default_constructor finds the default constructor for a given class. +A default constructor is one that can be called with no arguments. If the +class has no default constructor, an error is issued.

    +

    select_destructor finds the destructor for a given class. If the class has +no destructor, it returns NULL.

    +

    select_copy_constructor finds a copy constructor for a given class. It can +be told to look for a copy constructor that will accept const- or +volatile-qualified objects. If no appropriate copy constructor exists, an +error is issued.

    +
    +
    +

    6.6.13. User-Defined Conversions#

    +

    Like overloaded operators user-defined conversion functions (or “conversion +operators”) cannot be looked up by name. Rather, the symbol header is looked +up by result type, using the linked list of entries of type +a_conversion_header and pointed to by conversion_header_list, as +described earlier. Since all user-defined conversion functions are member +functions, once the symbol header is found, searching for a symbol simply +involves discriminating on the basis of the parent.class_type field.

    +

    An explicitly named conversion function (e.g., operator int()), is +represented (like overloaded operators) by an identifier token; in its +associated symbol locator is_conversion_name is TRUE and +conversion_result_type points to a type entry for the result of the +conversion. The routine called to find the conversion header (and thereby the +symbol header) and to set these fields is make_type_conversion_locator. It +also creates the conversion header (as well as the symbol header) if none +exists yet. The token sequence representing a conversion function is scanned +by scan_conversion_operator, which is called from f_get_opname.

    +

    Sometimes the question to be answered in processing an expression is, “What +user-defined conversion function exists to convert an object of class A to +type T?” In such cases it would be straightforward to find the appropriate +symbol by using the result type to identify the conversion header and then the +class type to choose among the associated conversion function symbols. But at +other times – for instance, when looking for the best implicit conversion or +when there are inherited conversion functions – the question is subtly +different: “Which, if any, of the user-defined conversion functions that exist +for class A is most suitable for converting to type T?” To optimize +answering this question, another construct appears in the symbol table, +a_conversion_list_entry, each instance of which points to a symbol entry +representing a conversion function. A class’s symbol supplement contains a +pointer to such a list, which is updated in decl_member_function each time +a conversion function is declared; the list also contains projection symbols to +represent inherited conversion functions (see +project_base_class_conversion_functions).

    +
    +
    +
    +

    6.7. “Extern” Symbols#

    +

    When it is required that distinct declarations in different name scopes refer +to the same entity, an extra symbol is created to represent the shared entity. +For instance,

    +
    void f() {
    +  extern int i;
    +}
    +void g() {
    +  extern int i;
    +}
    +extern int i;
    +
    +
    +

    In this example, although all three declarations of i refer to the same +variable, three independent sk_variable symbols are created to represent +it, one in the scope of function f, one in the scope of function g, and +one in the file scope. So a fourth symbol is created at file scope to +represent i – its kind is sk_extern_variable, and it is created at the +first declaration of i. Then, even after the sk_variable symbol for +the declaration of i in function f goes out of scope, the +sk_extern_variable symbol is still around to be found again on the +subsequent declarations of i; this assures that all three i symbols +point to the same IL entity. A similar technique, using sk_extern_function +symbols, is employed for functions. These “extern” symbols are put on the +“other” symbols list instead of being put on either the active or inactive list +and so are not found during normal name lookup.

    +

    The routine that manages all this is find_external_symbol. It also has +special logic, subject to configurable control, to deal with instances in which +different source names resolve to the same “external” name because of object +language constraints – e.g., where linkers can handle only so many characters +or are not case sensitive.

    +
    +
    +

    6.8. Symbol Management#

    +

    It remains to describe briefly some of the other low-level routines and macros +used to manage the symbol table and return information about symbols.

    +
      +
    • +
      alloc_symbol is called to allocate a symbol entry of a specified kind. +When a NULL symbol header is passed, it allocates an error symbol, one +whose header is error_symbol_header. It calls clear_symbol and +set_symbol_kind to initialize the new entities; the latter also +allocates the supplementary constructs for class and projection symbols. +Other routines called to allocate and initialize the entities from which +the symbol table is constructed are
      +
      +
        +
      • +
        alloc_symbol_header,
        +
        +
      • +
      • +
        alloc_conversion_header, and
        +
        +
      • +
      • +
        alloc_conversion_list_entry
        +
        +
      • +
      +
    • +
    • +
      enter_namespace_projection_symbol is called to create new namespace +projection symbols and enter them in the symbol table. Passed a pointer to +the fundamental symbol, it allocates and initializes the symbol and links +it into the symbol table and scope list. This routine is needed because a +namespace projection symbol cannot be entered into the symbol table via +enter_symbol because that doesn’t allow specification/setting of the +fundamental symbol and the fundamental symbol is used by enter_symbol +for checking compatibility with previous declarations of the name in the +current scope.
      +
      +
    • +
    • +
      enter_synthesized_namespace_projection_symbol creates new synthesized +namespace projection symbols and enters them on the “other” symbols list if +they can be reused. This routine also determines the scope list on which +the symbol should be placed based on the lookup options and the qualifier +namespace, and sets the lookup option fields in the symbol entry.
      +
      +
    • +
    • +
      enter_symbol is called to create new symbols and enter them in the +symbol table. Passed a symbol kind, it allocates and initializes the +symbol, marks it as having been referenced, and links it onto the symbol +header’s active list and onto the current scope’s symbol list.
      +
      +
    • +
    • +
      reenter_symbol takes an existing symbol (one that may have been entered +already and then removed) and links it into the symbol table.
      +
      +
    • +
    • +
      full_enter_symbol calls find_symbol to locate the symbol header for +a name and then calls enter_symbol. This is convenient when creating +symbols for the reserved names of keywords and predefined macros (see +enter_keyword and enter_predef_macro in fe_init.c).
      +
      +
    • +
    • +
      link_symbol_into_symbol_table, called from enter_symbol and +elsewhere, links a symbol onto the symbol header’s active list. Though it +normally ends up adding the symbol to the front of the list, it is careful +to account for special cases by determining the precise location based on +the scope number and name space overloading. It will issue a redeclaration +error when it detects that the name has already been declared in the +current scope.
      +
      +
    • +
    • +
      add_symbol_to_scope_list is also called from enter_symbol; it adds +a symbol to the end of the symbol list [9] of the scope stack entry at +the specified scope depth.
      +
      +
    • +
    • +
      enter_overloaded_symbol is called to enter a function symbol in the +symbol table when its name is overloaded. First, it allocates and +initializes the sk_routine or sk_member_function symbol. Then, if +an sk_overloaded_function symbol already exists for the name, the new +symbol is added to its list. If not, a new sk_overloaded_function +symbol must also be created; it will replace the existing function symbol +in the symbol table.
      +
      +
    • +
    • +
      make_namespace_projection_symbol allocates and initializes namespace +projection symbols. A pointer to the fundamental symbol is provided.
      +
      +
    • +
    • +
      make_projection_symbol allocates and initializes sk_projection +symbols, leaving it to the caller, find_projected_symbol, to add the +new symbol to the symbol table, since it may be inserted in either the +active list or the inactive list of the symbol header.
      +
      +
    • +
    • +
      make_template_class_symbol creates and initializes a symbol for an +instance of a class template. It is linked in the template’s instantiation +list rather than added directly to the symbol table.
      +
      +
    • +
    • +
      make_unnamed_tag_symbol is invoked to allocate and initialize a tagless +class, struct, and union symbol. It is not actually entered into the +symbol table since, like error symbols, it uses a special symbol header +(see static variable unnamed_tag_symbol_header). If the class +subsequently acquires a name, relink_unnamed_tag_symbol is called to +modify the symbol entry and add it to the symbol table.
      +
      +
    • +
    • +
      unlink_symbol_from_symbol_table is called from pop_scope for each +name that passes out of scope: it removes the symbol from the symbol +header’s active symbol list, but the symbol remains on the scope list.
      +
      +
    • +
    • +
      remove_symbol removes a symbol from the symbol table, e.g., for a macro +definition when a #undef is encountered. +unlink_symbol_from_symbol_table is called to remove a symbol from the +active list and remove_symbol_from_scope_list is called to remove it +from the symbol list of the scope stack entry.
      +
      +
    • +
    • +
      When cross-reference information is being generated, write_xref_entry +is called to create a record describing a reference and to write it to the +file indicated by f_xref_info.
      +
      +
    • +
    • +
      record_symbol_declaration is called for every declaration and +definition of a name. It sets the source sequence number if this is the +initial declaration, may set the source position (for initial declarations +and for definitions), optionally calls write_xref_entry, and (when +GENERATE_SOURCE_SEQUENCE_LISTS is TRUE) calls +sym_update_source_sequence_list.
      +
      +
    • +
    • +
      mark_defined and mark_declared are macro interfaces to +record_symbol_declaration, for definitions and non-defining +declarations, respectively.
      +
      +
    • +
    • +
      record_symbol_reference is called for nondeclarative references to +symbols. It optionally calls write_xref_entry, specifying the +kind of reference (see a_symbol_reference_kind), sets the +symbol’s referenced flag, and may set the referenced flag in +the IL entry. For variables, it checks for the need to issue a +“used-before-set” warning and calls mark_variable_value_set if +appropriate.
      +
      +
    • +
    • +
      mark_variable_value_set is called to set the value_has_been_set +flag in the symbol of a variable or static data member. For a variable +entry that represents function parameter or a handler parameter it also +sets param_value_has_been_changed.
      +
      +
    • +
    • +
      sym_update_source_sequence_list is called (when +GENERATE_SOURCE_SEQUENCE_LISTS is TRUE) to generate a source sequence +entry for a declaration. (Source sequence lists are discussed in greater +detail in the context of the intermediate language.)
      +
      +
    • +
    • +
      clear_locator is a macro used to clear the fields of a locator and +initialize source_position to a specified value; +set_to_error_locator is similar but is used when errors are +encountered.
      +
      +
    • +
    • +
      set_to_named_error_locator turns a locator into an error locator – but +one that preserves information about the identifier with which the locator +is associated.
      +
      +
    • +
    • +
      tildize_locator takes the locator for an identifier token, turns the +name into a destructor name by prepending a ~, calls find_symbol to +find (or create) the associated symbol header, and returns a locator for +new name.
      +
      +
    • +
    • +
      change_class_locator_into_constructor_locator takes a locator for a +class name (its specific_symbol field will point to the class, struct, +or union symbol) and modifies it to point to a separate header of the same +name that serves as the header for a constructor. [10]
      +
      +
    • +
    • +
      make_opname_locator creates a locator to represent a token sequence +consisting of operator and the token (or token pair) for an +overloadable operator. It looks for the corresponding header in the +opname_symbol_header array; if none is found, it creates one and adds +it to the array.
      +
      +
    • +
    • +
      make_type_conversion_locator creates a locator to represent a token +sequence consisting of operator and tokens making up a type name. It +looks for the corresponding header by scanning conversion_header_list; +if none is found, it creates one, along with a new conversion header entry, +and adds the latter to the head of the linked list.
      +
      +
    • +
    • +
      make_locator_for_symbol is called to initialize a locator based on an +already existing symbol.
      +
      +
    • +
    • +
      set_source_corresp is called to establish a correspondence between an +IL entry and a symbol. It links the IL entry back to the symbol.
      +
      +
    • +
    • +
      set_decl_sequence_number is called to set a declaration sequence number +for a symbol. Such numbers identify the sequential position of one +declaration relative to others in the same translation unit. When a name +is multiply declared, the position of its definition is recorded in the +declaration sequence number.
      +
      +
    • +
    • +
      A number of macros in symbol_tbl.h provide the preferred method of +identifying a given symbol’s special characteristics:
      +
      +
        +
      • +
        is_class_symbol
        +
        +
      • +
      • +
        is_tag_symbol
        +
        +
      • +
      • +
        is_type_symbol
        +
        +
      • +
      • +
        is_function_symbol
        +
        +
      • +
      • +
        is_member_function_symbol
        +
        +
      • +
      • +
        is_constructor_symbol
        +
        +
      • +
      • +
        is_destructor_symbol
        +
        +
      • +
      • +
        is_copy_constructor_symbol
        +
        +
      • +
      +
    • +
    • +
      type_symbol_type is a macro that may be invoked for symbols for which +is_type_symbol is TRUE; it returns a pointer to the associated type +entry.
      +
      +
    • +
    • +
      symbol_supplement_for_class takes a type entry of kind tk_class, +tk_struct, or tk_union and returns a pointer to the associated +symbol’s class symbol supplement entry.
      +
      +
    • +
    +
    +
    +

    6.9. Access Control#

    +

    The function of access control is to determine whether or not a given name can +be accessed from the current location in the source program. Every reference +to a name, whether qualified or not, whether part of an expression or a type, +is checked to make sure the identifier is unambiguous and accessible. There +are several things to remember about access control:

    +
      +
    • +
      Only class members are subject to access control. Non-class members are +always accessible.
      +
      +
    • +
    • +
      Access control is site-specific. A given member can be accessible from one +place in a program and not accessible from somewhere else. In particular, +members and friends of a class have special access to the members of the +class and its base classes.
      +
      +
    • +
    • +
      Access control limits access, not visibility. Members that are not +accessible are still visible. They are found, the access error is issued, +and then (the way the front end does it) they are used anyway.
      +
      +
    • +
    • +
      When members are inherited into derived classes, the access to the members +in the derived class is affected by the type of derivation of the derived +class (see ARM 11.2).
      +
      +
    • +
    • +
      The same member may have different access in different classes, and may be +accessible at a given point in the program through one qualified name and +not through another. In other words, access control applies to names +rather than objects.
      +
      +
    • +
    • +
      A name is ambiguous if the name refers to two or more entities, with no +reason to prefer one over the others. Only inherited class members can be +ambiguous. Ambiguity checking is done before access control checking.
      +
      +
    • +
    +

    The problem of access control, then, reduces to “given a symbol for a class +member, which might be a projection symbol, is the member unambiguous and do we +have access to it from the current location in the program?”

    +

    The ambiguity aspect is easily dealt with: the ambiguous flag in the symbol +indicates whether or not it is ambiguous. The flag can be set only in +projection symbols and in symbols for sets of overloaded functions synthesized +for lookups done in the presence of using-directives.

    +

    Access checking is harder.

    +

    The access to a class member, in its simplest form, is given by the +source_corresp.access field in the member’s IL entry.

    +

    When the member is a direct member of a class, there will be a symbol entry +pointing directly to the IL entry, and the access to that symbol is simply the +access indicated in the IL entry. When the member is inherited, however, each +derived class will have a projection symbol that points to the fundamental +symbol. The access to the member through a projection symbol is filtered +through the class derivations that lead to the derived class containing the +projection symbol; that access is indicated in the projection symbol.

    +

    If the simple access in the symbol or in the projection symbol is +as_public, then the member is accessible. Otherwise, some kind of member +access privilege is required to access it.

    +

    Member access privileges are available when the current position is inside a +class or a function. Being inside a class confers special access to members of +the class and to classes that have befriended the class. Being inside a +function confers special access to classes that have befriended the function, +and, if the function is a member function, to the class of which it is a member +(and classes that have befriended it).

    +

    The scope_stack provides the necessary information about the functions +and/or classes that the current position is inside of.

    +

    For there to be special access to a member x across the derivation +represented by a projection symbol, there must exist a class A somewhere on +the derivation (including either of the endpoints) such that:

    +
      +
    1. A is accessible (meaning that its public members are accessible) from +the current position in the program, starting from the most-derived +class on the derivation. In other words, we can implicitly cast a pointer +to the derived class we start with to a pointer to A.

    2. +
    3. We have member access to A.

    4. +
    5. x is accessible in A, meaning that if one starts with the access +to x in the fundamental class and works outward through the +derivation steps until one gets to A, there is some remaining access +at that point.

    6. +
    +

    The implementation of the above is broken up as follows:

    +
      +
    • +
      access_for_symbol extracts the simple access for a symbol.
      +
      +
    • +
    • +
      access_to_end_of_path determines the effect of a set of derivation +steps on such an access.
      +
      +
    • +
    • +
      have_access_to_symbol determines whether or not there is access to a +symbol. Most of the work is done in have_access_across_path.
      +
      +
    • +
    • +
      The macro is_accessible_imm_base_class determines whether or not a base +class is accessible (ARM 4.6). The macro is also used directly in +determining whether or not base class casts and the like are valid. The +function is_accessible_base_class is similar, but is not limited to +immediate base classes.
      +
      +
    • +
    • +
      have_member_access_privilege determines whether or not there is member +access privilege to a given class.
      +

      +
      When there are protected members or protected derivation steps +involved, derived classes can have a limited form of member access (see +have_protected_member_access_privilege).
      +

      +
      The additional restrictions on access to protected members of ARM 11.5 +require special processing in the expression routines over and above the +access checking done here. The checking there ends up calling the macro +check_protected_member_access, which in turn calls the function +f_check_protected_member_access.
      +
      +
    • +
    • +
      check_ambiguity_and_verify_access (a macro) is the main interface to +access checking. It in turn calls +member_check_ambiguity_and_verify_access for class members.
      +
      +
    • +
    +

    Overloaded functions pose some special problems, because they are represented +as several symbols (which may have distinct accesses) clustered under one +overloaded function symbol. When the cluster is inherited into a derived +class, a single projection symbol points to the overloaded function symbol. +This means that:

    +
      +
    • +
      One cannot determine the access to a name in a set of overloaded functions +until one has determined which specific function is being referenced. For +that reason, when an overloaded function symbol is passed through the +normal access checking routines, it is always judged to be accessible. +Note that ambiguity checking can still be done in the usual way.
      +
      +
    • +
    • +
      Once one has determined which function is being referenced, one cannot use +the normal interface to the access checking routines, because the +projection symbol does not point to the specific function.
      +

      +
      overload_check_ambiguity_and_verify_access does the access check in +this case on the basis of a projection symbol and a (not directly attached) +specific function symbol. In the presence of member +using-declarations, the specific function symbol can be a projection +symbol.
      +
      +
    • +
    +

    It is not possible to determine the access to certain names used in namespace +scope declarations at the point at which the name is seen. In the following +example, the accessibility of A::B in the declaration of A::f cannot be +determined until we know we are scanning a declaration of a member of class +A. In the friend case, we cannot determine the access to A::B until we +know the signature of the function being declared, because we have to determine +that it has been befriended by class A.

    +
    class A {
    +  class B {};
    +  B f();
    +  friend B g(B);
    +};
    +A::B A::f(){ B b; return b; }
    +A::B g(A::B b){ return b; }
    +
    +
    +

    When a namespace scope declaration is processed, a flag is set in the scope +stack indicating that any access errors that occur should, instead of being +issued, be recorded in a list pointed to by the scope stack entry. Later, when +more information about the declaration is available, the accessibility is +rechecked. If the name is now accessible, the entry is removed from the list +of deferred access checks. If it is still not accessible, it will either +remain on the list if the defer access checks flag is still set, otherwise the +error will be issued.

    +

    begin_deferral_of_access_checks and end_deferral_of_access_checks are +macros used to bracket the processing of a declaration that requires deferred +access checking.

    +

    perform_deferred_access_checks is used to retry the access checks that had +failed earlier, and is called during declarator processing to check the +accessibility of member declarations. This is done after the class +reactivation scope for the member declaration has been pushed.

    +

    For the accessibility of friend declarations to be checked, the scope stack +must contain information about the function that is being declared. The +function access scope fulfills this need. After a complete function +declaration has been scanned, perform_deferred_access_checks_for_function +is called with a pointer to the routine that has been declared. It pushes a +function access scope and then calls perform_deferred_access_checks to +determine whether the names are now accessible.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/tables/index.html b/doc/tables/index.html new file mode 100644 index 0000000..888ed78 --- /dev/null +++ b/doc/tables/index.html @@ -0,0 +1,1282 @@ + + + + + 8. Table Management - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    8. Table Management#

    +

    For a description of the intermediate language itself, see +Intermediate Language.

    +

    The source file il_alloc.c contains routines to allocate and clear the +intermediate language tables, and il.c contains routines to debug-print +them. These routines should always be used, so that new tables are always set +to the proper default values and problems with undefined fields are avoided. +il_def.h, il_alloc.h, and il.h contain associated declarations.

    +

    Note that some of these routines should not be called from a back end, because +the front end data structures they need are no longer set up properly at that +point. In general, routines that allocate new storage or new entries should +not be called, and routines that answer questions about existing entries are +okay to call. The

    +
    #if !STANDALONE_UTILITY_PROGRAM
    +
    +
    +

    guards indicate routines that should not be called by back ends.

    +
    +

    8.1. Storage Allocation#

    +

    alloc_cil has an interface like malloc; it allocates space in the +current intermediate language memory region. new_il_region begins a new +intermediate language memory region. switch_il_region switches to a +previously-created region. alloc_il allocates space in the file-scope +intermediate language memory region.

    +

    When the alternate IL file format is used, space is reserved preceding each IL +entry so that the IL entry number can be stored there.

    +
    +
    +

    8.2. Constant Entries#

    +

    Constant entries (type a_constant) are usually allocated by +alloc_constant; fs_constant is similar to it but allocates the constant +entry at the file scope. make_zero_of_proper_type makes a zero constant of +a given type. clear_constant and set_constant_kind are called to +re-initialize existing constant entries, and set_error_constant changes an +existing constant entry to an error constant.

    +

    In most cases, a constant entry need not be unique – the same entry can be +used for all occurrences of a given literal constant. For these cases, one +should call alloc_shareable_constant instead of alloc_constant. (The +interface is slightly different; one passes a filled-in constant entry rather +than just a kind.) alloc_shareable_constant maintains +shareable_constants_table, a hash table that is searched by hashing a +constant entry to a bucket number (routine hash_constant), then searching a +linked list of constants in that bucket to see if there is a match (comparison +is done by eq_constants). If an entry is found, it is reused. If none is +found, one is entered into the table.

    +

    In cases where the constant entry cannot be shared (as when it must be linked +into an initializer list), alloc_unshared_constant should be called +instead. It basically just calls alloc_constant, but adjusts a few things +in the constant entry.

    +
    +
    +

    8.3. Type Entries#

    +

    Type entries (type a_type) are allocated by alloc_type.

    +

    integer_type, fixed_point_type, float_type, string_type, +void_type, and error_type can be called to create type entries for the +most common types; these routines will reuse the entries once they have created +them. make_pointer_type creates a pointer type pointing to a given base +type. It uses the routine get_based_type to determine if a pointer to the +type has already been created, and it calls add_based_type_list_member to +record the fact that a pointer type has been allocated. +make_reference_type is the similar routine for (lvalue) reference types, +and make_rvalue_reference_type is the similar routine for rvalue reference +types. ptr_to_member_type is the similar routine for pointer-to-member +types.

    +

    make_qualified_type is used to add type qualifiers to an existing type; +make_unqualified_type is used to remove them.

    +

    unknown_type creates an unknown type entry; such an entry is used as a +place-holder within the front end and the references to it must be eliminated +before the back end is called. Another type that is normally not seen by the +back end (unless prototype instantiations are recorded in the IL) is the +template parameter type, which is used in processing template declarations.

    +

    There are several routines that allocate various pieces of the description of a +class type:

    +
      +
    • +
      alloc_derivation_step
      +
      +
    • +
    • +
      alloc_base_class_derivation
      +
      +
    • +
    • +
      alloc_overriding_virtual_function
      +
      +
    • +
    • +
      alloc_base_class
      +
      +
    • +
    • +
      alloc_list_entry_for_class
      +
      +
    • +
    • +
      alloc_class_type_supplement
      +
      +
    • +
    +
    +
    +

    8.4. Other Declarative Entries#

    +

    alloc_variable, alloc_field, alloc_label, and alloc_routine +allocate variable, field, label, and routine entries. They do nothing terribly +interesting. remove_from_routines_list can be used to remove a routine +from the routines list so that it can be added again at the position where its +actual definition appears.

    +

    Routines that allocate other IL entities resulting from declarations include:

    +
      +
    • +
      alloc_param_type allocates a param-entry pointed to from the routine +type supplement of a tk_routine type entry.
      +
      +
    • +
    • +
      alloc_template, alloc_template_arg and +alloc_template_param_type_descr are used in template processing.
      +
      +
    • +
    • +
      alloc_namespace allocates an entry to represent either a namespace or a +namespace alias.
      +
      +
    • +
    • +
      alloc_using_decl allocates an entry to represent a using-directive, +a member using-declaration, or a nonmember using-declaration.
      +
      +
    • +
    • +
      alloc_macro allocates an entry representing a macro definition (when +RECORD_MACROS_IN_IL is set).
      +
      +
    • +
    • +
      alloc_pragma allocates an entry representing a #pragma declaration.
      +
      +
    • +
    • +
      alloc_asm_entry allocates an entry representing an asm declaration. +To support certain extensions (i.e., when ASM_FUNCTION_ALLOWED is set) +alloc_asm_function_body is also available.
      +
      +
    • +
    • +
      alloc_scope allocates a scope entry.
      +
      +
    • +
    • +
      alloc_ctor_init allocates a constructor-initializer entry, a list of +which is recorded in the scope entry associated with a constructor.
      +
      +
    • +
    • +
      alloc_temporary_variable allocates a variable entry for a temporary.
      +
      +
    • +
    • +
      alloc_dynamic_init allocates a dynamic initialization entry, used +(among other things) to represent dynamic initialization on variable +declarations.
      +
      +
    • +
    • +
      alloc_local_static_variable_init allocates an entry used to represent +the initialization of a function-local variable with static storage class.
      +
      +
    • +
    • +
      alloc_list_entry_for_routine allocates an entry used to record a list +of routine entries (used to support friend declarations).
      +
      +
    • +
    • +
      alloc_exception_specification allocates an entry that represents an +exception specification in a function declaration.
      +
      +
    • +
    • +
      alloc_accessible_base_class allocates an accessible base class entry +(unused in implementations in which ABI_CHANGES_FOR_RTTI is set).
      +
      +
    • +
    • +
      alloc_hidden_name allocates a hidden-name entry (for use by the +C++-generating back end, when RECORD_HIDDEN_NAMES_IN_IL is set).
      +
      +
    • +
    +
    +
    +

    8.5. Expressions#

    +

    alloc_expr_node allocates an expression node.

    +

    set_expr_node_kind and clear_expr_node re-initialize existing entries. +make_operator_node creates an expression node for an operation.

    +

    set_node_operator changes the operator or type in an existing operation +expression node.

    +

    error_node makes an error expression node (a new one on each call, since +executable constructs cannot be shared).

    +

    There are several utility routines that help in constructing expressions:

    +
      +
    • +
      alloc_node_for_constant builds an expression node that points to a +constant entry.
      +
      +
    • +
    • +
      node_for_integer_constant builds an expression node for an integer +constant.
      +
      +
    • +
    • +
      var_lvalue_expr builds an expression node for a variable as an lvalue.
      +
      +
    • +
    • +
      var_rvalue_expr builds an expression node for a variable as an rvalue.
      +
      +
    • +
    • +
      var_addr_expr builds an expression node for the address of a variable. +The address_taken flag is set.
      +
      +
    • +
    • +
      function_lvalue_expr builds an expression node for a function as an +lvalue.
      +
      +
    • +
    • +
      function_rvalue_node builds an expression node for a function as an +rvalue, i.e., for the address of the function. This is suitable for +calling the function, but not for the “&” operator applied to the +function, because the address_taken flag is not set.
      +
      +
    • +
    • +
      function_addr_expr builds an expression node for the address of a +function. The address_taken flag is set.
      +
      +
    • +
    • +
      rvalue_expr_for_lvalue converts an lvalue expression to an rvalue. It +also works for function lvalues, but not for arrays.
      +
      +
    • +
    • +
      add_indirection_to_node adds an indirection (”*” operator) to an +expression.
      +
      +
    • +
    • +
      add_ref_indirection_to_node adds the reference equivalent of +“*” to an expression.
      +
      +
    • +
    • +
      add_address_of_to_node adds a “&” operator to an expression.
      +
      +
    • +
    • +
      add_reference_to_to_node adds the reference equivalent of “&” to an +expression. (Note that that is not a typo; the name really does have +“to_to_” in it.)
      +
      +
    • +
    • +
      field_lvalue_selection_expr builds an expression for a field selection +that produces an lvalue.
      +
      +
    • +
    • +
      field_rvalue_selection_expr builds an expression for a field selection +that produces an rvalue.
      +
      +
    • +
    +

    copy_expr_tree makes a copy of an expression tree. When it does so, it can +optionally “clone” any temporary variables found within the tree so that the +copy uses different but equivalent temporaries.

    +

    In addition, alloc_lowered_eh_construct_node allocates an expression node +to represent one of several (partially) lowered exception handling constructs +(used only when IL lowering is enabled and DO_FULL_PORTABLE_EH_LOWERING is +configured to FALSE.

    +
    +
    +

    8.6. Statements#

    +

    alloc_statement allocates a statement (which may allocate a supplement of +type a_for_loop, a_switch_stmt_descr, etc.). +alloc_switch_case_entry allocates the entry used to represent one case +(possibly, the “default:” case) of a switch statement.

    +
    +
    +

    8.7. Object Lifetimes#

    +

    alloc_object_lifetime allocates an object lifetime entry, and +bind_object_lifetime binds it to a specified IL entry (a scope, an +expression, a dynamic init, etc.).

    +

    A dynamic init entry with a destructor is added to the destructions list of an +object lifetime by record_end_of_lifetime_destruction, which calls +add_to_destructions_list. Conversely, it is removed from the list by +remove_from_destructions_list.

    +

    During front-end processing object lifetime entries are pushed onto the object +lifetime stack (see push_object_lifetime and global variable +curr_object_lifetime, which is the top of the stack) and popped off the +stack when appropriate (see pop_object_lifetime).

    +

    If, when it is popped off the object lifetime stack, the entry is not actually +required in the IL (see is_useless_object_lifetime), it is unbound from the +IL entry with which it is associated (see unbind_object_lifetime) and +placed on an available list for reuse (see free_object_lifetime).

    +
    +
    +

    8.8. Source Sequence Entries#

    +

    Source-sequence entries are created only when +GENERATE_SOURCE_SOURCE_SEQUENCE_LISTS is configured to TRUE. See +Intermediate Language for additional information.

    +

    f_update_source_sequence_list creates new source sequence entries and adds +them to the appropriate list.

    +
      +
    • +
      For declarations it is called by sym_update_source_sequence_list (in +symbol_ref.c), which also calls alloc_src_seq_secondary_decl when +the declaration is not a primary declaration.
      +
      +
    • +
    • +
      For statements it is called by stmt_update_source_sequence_list (in +statements.c).
      +
      +
    • +
    • +
      In certain other cases – e.g., for the declaration of unnamed enum +types, for which there is no symbol – it is called via macros +update_source_sequence_list and add_to_source_sequence_list.
      +
      +
    • +
    +

    Other functions called to create and manage source sequence lists include:

    +
      +
    • +
      alloc_source_sequence_entry allocates and initializes a source-sequence +entry.
      +
      +
    • +
    • +
      add_source_sequence_entry_to_list is called to add entries to the end +of the list of the current scope stack entry (see source_sequence_list +in a_scope_stack_entry). When pop_scope is called, the list for a +given scope stack entry is either appended to the list of the enclosing +scope stack entry or, for function scopes and the file scope, moved to the +associated IL scope (see source_sequence_list in a_scope).
      +
      +
    • +
    • +
      add_empty_source_sequence_entry creates and adds a source sequence +entry that does not yet point to an IL entry. Such entries are +placeholders to reserve a position in the list for a declarator when the +particular IL entry it represents is not yet known; they do not persist +beyond the front end.
      +
      +
    • +
    • +
      add_end_of_construct_source_sequence_entry creates a source sequence +entry to mark the end of a construct for a given entity (see +alloc_src_seq_end_of_construct) and adds it to the current source +sequence list. (See also Source Sequence Lists.)
      +
      +
    • +
    • +
      make_source_sequence_secondary_decl creates a source sequence entry to +represent a non-defining declaration (see a_src_seq_secondary_decl), +and set_src_seq_secondary_decl_fields can be called to locate the entry +on the current source sequence list (see +last_matching_source_sequence_entry) and to update various of its +pointers and flags.
      +
      +
    • +
    • +
      When either CLASS- or +NONCLASS_TEMPLATE_INSTANTIATIONS_IN_SOURCE_SEQUENCE_LISTS is TRUE, +add_source_sequence_entry_for_partial_instantiation is called to enter +a secondary declaration entry to represent the declaration of a +compiler-generated template specialization that stands for a template +instantiation, and when the body of such a specialization is generated, its +source sequence list is added by insert_instantiation_src_seq_list; in +both cases, find_instantiation_insert_scope is called to locate the +point at which the instantiation should be inserted in the source sequence +list (since it is not necessarily at the end of the list for the current +scope stack entry).
      +
      +
    • +
    • +
      insert_src_seq_list inserts a list into another list at a specified +point; it is also called to append a list to another list.
      +
      +
    • +
    • +
      remove_from_source_sequence_list removes a given source sequence entry +from its list; see also macros unlink_src_seq_entries and +unlink_src_seq_entry (which operate on source sequence lists and single +entries, respectively).
      +
      +
    • +
    • +
      fixup_function_scope_source_sequence_list creates both a sublist header +(see alloc_src_seq_sublist) and the source sequence entry that points +to it.
      +
      +
    • +
    +
    +
    +

    8.9. Lists of Entries#

    +

    The routines

    +
      +
    • +
      add_to_constants_list,
      +
      +
    • +
    • +
      add_to_types_list,
      +
      +
    • +
    • +
      add_to_variables_list,
      +
      +
    • +
    • +
      add_to_parameters_list,
      +
      +
    • +
    • +
      add_to_dynamic_inits_list,
      +
      +
    • +
    • +
      add_to_routines_list, and
      +
      +
    • +
    • +
      add_to_labels_list
      +
      +
    • +
    • +
      add_to_namespaces_list
      +
      +
    • +
    • +
      add_to_using_decls_list
      +
      +
    • +
    • +
      add_to_asm_entries_list
      +
      +
    • +
    • +
      add_to_templates_list
      +
      +
    • +
    • +
      add_to_macros_list
      +
      +
    • +
    • +
      add_to_pragma_list
      +
      +
    • +
    +

    add entries of the indicated type to end of the list of similar entries under a +scope entry. The scope will vary depending on the type of entry and what the +caller specifies. In many cases it is either the current scope or the +innermost namespace scope that is used (e.g., variables, constants, types). +Routines that are not class members are added to the list for the file scope or +a namespace scope. Labels are always added to an sck_function scope. And +so forth.

    +

    There is also an add_to_scopes_list; it is called by create_block_scope +when a scope for a statement block is created. Special handling is required +because the IL scope for a block is not created until there is some declaration +in that block.

    +
    +
    +

    8.10. Orphaned Entries#

    +

    Orphans are entries in the file scope memory region that are referenced only +from function scope memory regions. When the parents of such entries are +written out and then removed from memory, the entries are orphaned because they +are not attached to the rest of the file-scope IL tree.

    +

    The orphan mechanism makes lists of such entries so that they can be found +during traversal of the file-scope IL. In the file scope, each entry is +preceded by space for an orphan-list pointer. When a potential orphan entry is +encountered, for example when an entry in a function scope memory region points +to an entry in the file scope memory region, +add_orphaned_file_scope_il_entry is called. It adds the potential orphan +to a list of entries of its type headed by the proper element of the array +orphaned_file_scope_il_entries and linked by the hidden pointer. An entry +is ignored if it is already on the list (which can be discerned from the fact +that the orphan-list pointer is already non-NULL or the fact that the entry +address matches the last-on-list pointer for that entry type).

    +

    There is also a special mechanism for keeping track of the lists of local +static variables and types in function and block scopes. These are lists that +are entirely in the file scope memory region but originate with a pointer that +is in a function scope memory region. To keep track of these, entries of type +a_scope_orphaned_list_header are allocated in the file scope memory region +and attached to the il_header. Each entry contains a copy of the static +variables and types pointers from a function or block scope, so that the lists +can be visited in the file scope memory region even if the associated function +scope memory region is no longer in memory. See +add_scope_orphaned_il_lists.

    +
    +
    +

    8.11. Source File Information#

    +

    record_start_of_source_file and record_end_of_source_file build +information about the correspondence between source files and sequence numbers. +Basically, this is a tree that shows the nesting of include files, with added +entries to show the information provided by #line directives. These +routines are called from push_input_stack and pop_input_stack in +lexical.c, and proc_line in preproc.c. +conv_seq_to_file_and_line uses that data structure to map sequence numbers +into file names and line numbers.

    +
    +
    +

    8.12. Debug Print Routines#

    +

    The following debug-print routines can be used to display intermediate language +constructs for debugging purposes:

    +
      +
    • +
      db_name
      +
      +
    • +
    • +
      db_type_name
      +
      +
    • +
    • +
      db_name_linkage
      +
      +
    • +
    • +
      db_type
      +
      +
    • +
    • +
      db_abbreviated_type
      +
      +
    • +
    • +
      db_access_control
      +
      +
    • +
    • +
      db_field
      +
      +
    • +
    • +
      db_static_data_member
      +
      +
    • +
    • +
      db_member_function
      +
      +
    • +
    • +
      db_virtual_function_info
      +
      +
    • +
    • +
      db_constant
      +
      +
    • +
    • +
      db_variable
      +
      +
    • +
    • +
      db_expression
      +
      +
    • +
    • +
      db_dynamic_initializer
      +
      +
    • +
    • +
      db_initializer
      +
      +
    • +
    • +
      db_statement
      +
      +
    • +
    • +
      db_statement_list
      +
      +
    • +
    • +
      db_object_lifetime
      +
      +
    • +
    • +
      db_object_lifetime_stack
      +
      +
    • +
    • +
      db_scope
      +
      +
    • +
    • +
      db_source_sequence_entry
      +
      +
    • +
    +
    +

    8.12.1. Types#

    +

    The routines and data structures described in this section are defined in +types.c and types.h. These are routines that manipulate intermediate +language types in various ways. They answer questions about them, and do +various language transformations on them.

    +
    +
    +
    +

    8.13. Typerefs#

    +

    In type trees, typedefs, type qualifiers (e.g., const and volatile), type +operators such as decltype, and various other types are represented by an entry +called a typeref. It indicates a reference to an existing type. For qualified +pointer types, the typeref indicating the qualifier is on top of the +pointer type: for int *const q the type is a consttyperef +pointing to a pointer type entry, which points to an entry for int. Macros +get_type_qualifiers and get_top_level_type_qualifiers (the former may +check for qualifiers on the underlying array element type, the latter does not) +call f_get_type_qualifiers when appropriate, returning a bit set (see +a_type_qualifier_set).

    +

    It is often necessary for code that deals with types to access the target of a +typeref or chain of typerefs. Various convenience functions are provided for +this purpose, including skip_typerefs, skip_typerefs_not_typedefs, +skip_lexical_typerefs, etc.

    +
    +
    +

    8.14. Asking Questions About Types#

    +

    There are many predicates that determine whether or not a given type is of a +given kind. Having predicate functions (instead of doing the testing by direct +coding) is necessary because of the possibility of there being typeref +entries on a type. These predicates are implemented as functions, although +they could be implemented as macros for any cases where it seems desirable. +Within types.c, macros are used so as to avoid having one predicate routine +call a half-dozen others to get an answer. The predicate macros have the same +names as the corresponding predicate functions, with the final _type of the +name removed (i.e., is_integral corresponds to is_integral_type). They +do not call skip_typerefs.

    +

    The predicate functions are

    +
      +
    • +
      is_error_type
      +
      +
    • +
    • +
      is_function_type
      +
      +
    • +
    • +
      is_incomplete_type
      +
      +
    • +
    • +
      is_object_type
      +
      +
    • +
    • +
      is_void_type
      +
      +
    • +
    • +
      is_integral_type
      +
      +
    • +
    • +
      is_signed_integral_type
      +
      +
    • +
    • +
      is_enum_typeis_integral_or_enum_type
      +
      +
    • +
    • +
      is_character_type
      +
      +
    • +
    • +
      is_fixed_point_type
      +
      +
    • +
    • +
      is_floating_type
      +
      +
    • +
    • +
      is_arithmetic_or_enum_type
      +
      +
    • +
    • +
      is_pointer_type
      +
      +
    • +
    • +
      is_reference_type
      +
      +
    • +
    • +
      is_lvalue_reference_type
      +
      +
    • +
    • +
      is_rvalue_reference_type
      +
      +
    • +
    • +
      is_ptr_or_ref_type
      +
      +
    • +
    • +
      is_scalar_type
      +
      +
    • +
    • +
      is_array_type
      +
      +
    • +
    • +
      is_char_array_type
      +
      +
    • +
    • +
      is_class_struct_union_type
      +
      +
    • +
    • +
      is_complete_class_struct_union_type
      +
      +
    • +
    • +
      is_union_type
      +
      +
    • +
    • +
      is_aggregate_or_union_type
      +
      +
    • +
    • +
      is_polymorphic_class_type
      +
      +
    • +
    • +
      is_ptr_to_member_type
      +
      +
    • +
    • +
      is_template_class_type
      +
      +
    • +
    • +
      is_template_param_type
      +
      +
    • +
    • +
      is_nullptr_type
      +
      +
    • +
    +

    Macros that may be called to get information about the type (when +skip_typerefs is not to be called) include

    +
      +
    • +
      is_immediate_error_type
      +
      +
    • +
    • +
      is_immediate_class_type
      +
      +
    • +
    • +
      is_qualified_type
      +
      +
    • +
    • +
      is_const_qualified_type
      +
      +
    • +
    • +
      is_volatile_qualified_type
      +
      +
    • +
    • +
      is_top_level_qualified_type
      +
      +
    • +
    • +
      is_top_level_const_qualified_type
      +
      +
    • +
    • +
      is_top_level_volatile_qualified_type
      +
      +
    • +
    +

    (Among those that check type qualifiers, the is_top_level_xxx versions +differ from the others in not checking for qualifiers on underlying array +element types.) Other type qualifiers besides const and volatile may be +recognized; for instance, when support for restrict is enabled, +is_restrict_qualified_type and is_top_level_restrict_qualified_type are +also defined.

    +

    is_illegal_abstract_class_type returns TRUE if the type is that of an +abstract class, struct, or union, or if it is an array of abstract class +objects, or if it is pointer or reference to an array of abstract class +objects.

    +

    int_kind_is_signed determines whether a given integer kind is a signed +type.

    +

    There are in addition some predicate functions that examine an entire type +tree, if necessary, to return information about a type:

    +
      +
    • +
      is_or_contains_local_type
      +
      +
    • +
    • +
      is_or_contains_unnamed_or_local_type
      +
      +
    • +
    • +
      is_or_contains_template_param
      +
      +
    • +
    • +
      is_or_contains_specific_template_param
      +
      +
    • +
    +

    These routines call traverse_type_tree, a generic type-walking routine; it +is passed the address of a service routine that examines a node in the type +tree, and its detailed behavior is governed by setting some combination of +flags (see a_type_tree_traversal_flag_set).

    +

    Another set of predicates tests C++/CLI types and can be used only inside +#if guards for MICROSOFT_EXTENSIONS_ALLOWED:

    +
      +
    • +
      is_handle_type
      +
      +
    • +
    • +
      is_managed_nullptr_type
      +
      +
    • +
    • +
      is_ref_class_type
      +
      +
    • +
    • +
      is_value_class_type
      +
      +
    • +
    • +
      is_managed_class_type
      +
      +
    • +
    • +
      is_standard_class_type
      +
      +
    • +
    • +
      is_cli_interface_type
      +
      +
    • +
    • +
      is_tracking_reference_type
      +
      +
    • +
    • +
      is_handle_or_tracking_ref_type
      +
      +
    • +
    • +
      is_interior_ptr_type
      +
      +
    • +
    • +
      is_pin_ptr_type
      +
      +
    • +
    • +
      is_cli_array_type
      +
      +
    • +
    • +
      is_handle_to_cli_array_type
      +
      +
    • +
    • +
      is_cli_generic_param_type
      +
      +
    • +
    • +
      is_cli_generic_constraint_type
      +
      +
    • +
    • +
      is_boxable_type
      +
      +
    • +
    • +
      is_delegate_type
      +
      +
    • +
    • +
      is_cli_system_object_type
      +
      +
    • +
    • +
      is_cli_system_string_type
      +
      +
    • +
    +

    To ease pointer/reference/handle tests in code that might have to deal with +C++/CLI types, the following test certain general categories of pointers and +references:

    +
      +
    • +
      is_any_reference_type
      +
      +
    • +
    • +
      is_any_ptr_or_ref_type
      +
      +
    • +
    • +
      is_pointer_or_handle_type
      +
      +
    • +
    • +
      types_are_both_pointers_or_both_handles
      +
      +
    • +
    +
    +
    +

    8.15. Taking Apart Types#

    +

    Given an array type, array_element_type and +underlying_array_element_type return the type of an element; the second +deals with multidimensional arrays. type_pointed_to is used to get the +base type from a pointer or reference type. pm_member_type and +pm_class_type extract the base types from pointer-to-member types. +underlying_type_of_derived_type extracts the underlying type for all +derived types (pointer, pointer-to-member, array, etc.).

    +

    Given a C++/CLI array type, cli_array_element_type returns the type of the +element. cli_array_rank_constant and cli_array_rank return the rank +(number of dimensions) of the array in different forms.

    +
    +
    +

    8.16. Setting Sizes and Alignments of Types#

    +

    The size and alignment for a type are recorded in the type entry (except for +typerefs, which have their sizes and alignments dictated by the type they +refer to). These values, however, are not set all over the front end, but only +by isolated routines. The main routine is set_type_size, which will set +the size of an arbitrary type. The type must be completely built by the time +this routine is called. set_type_size calls set_array_type_size for +arrays. Size and alignment for class types are set by code in layout.c.

    +
    +
    +

    8.17. Modifying Type Trees#

    +

    set_used_in_exception_or_rtti_flag is called for types that appear as the +type of a throw object, in an exception specification list, as the type of a +handler, or in a typeid operator. It sets the type entry’s +used_in_exception_or_rtti flag. To assure that such types have external +linkage, it also calls set_force_external_linkage_flag, which in turn calls +traverse_type_tree to mark all the components of the type tree that have +linkage.

    +

    strip_local_typedefs is called to remove all local typedef components +of a type tree. It calls traverse_and_modify_type_tree to help accomplish +this task. If a subtree of the type tree is modified, a new type tree is built +to accommodate the change.

    +
    +
    +

    8.18. Getting Information About Base Classes#

    +

    find_base_class_of returns a pointer to a base class entry if a given class +type is represented on the base classes list of another class type. Similar +functionality, but with the implied restrictions, is provided by +find_direct_base_class_of and find_direct_or_virtual_base_class_of. +related_class_pointers will do the same for pointers to classes.

    +

    corresponding_base_class, given a base class belonging to one class, +searches the base classes of another class, finds the corresponding entry, and +returns a pointer to it.

    +

    is_on_any_derivation_of returns TRUE if a given base class is on the +derivation of another base class.

    +
    +
    +

    8.19. Routines that Implement Language Concepts#

    +

    The routines described in this section implement concepts of the C or C++ +languages.

    +

    Two routines handle type promotions: type_after_integral_promotion +determines the type that results from integral promotion done in an expression, +and default_argument_promotion determines the type of an argument to a +function with old-style parameter declarations after default promotion. See +also type_after_bit_field_integral_promotion in exprutil.c for a +special case involving bit-fields.

    +

    Several routines compare two types to see if they are compatible in some way. +identical_types determines whether the two types are structurally identical +(they don’t have to be the same pointer). il_identical_types sees if the +two types are identical from an IL perspective (e.g., int and long +might be identical if the front end is configured that way). +types_are_compatible sees if two types are compatible (C standard, +3.1.2.6). (Those three names are actually macros which call +f_identical_types and f_types_are_compatible only if the type pointers +are not exactly the same.) interchangeable_types sees if two types are +interchangeable as arguments to functions (basically, this is true if they are +compatible except for signedness issues).

    +

    impl_pointer_conversion determines whether or not an implicit conversion +from a given type to a given pointer type is valid, with some special cases for +pointers to void and for null pointer constants.

    +

    impl_conversion_possible determines whether or not an implicit conversion +from a given type to another is valid. impl_ptr_to_member_conversion +handles the subcase of implicit conversion of one pointer-to-member type to +another.

    +

    expl_conversion_possible determines whether or not an explicit conversion +(cast) from a given type to another is valid. It relies on two subroutines for +the major subcases:

    +
      +
    • +
      static_cast_conversion_possible and
      +
      +
    • +
    • +
      reinterpret_cast_conversion_possible.
      +
      +
    • +
    +

    composite_type develops a composite type from two types (C standard, +3.1.2.6).

    +

    overload_distinguishable determines whether or not two function types are +sufficiently different that they can be distinguished by overload processing +(and therefore routines with those types can be overloaded).

    +

    impl_handle_conversion determines whether or not an implicit conversion +from a given type to a given C++/CLI handle type is valid.

    +

    boxing_conversion_possible determines whether a conversion from one given +type to another is a C++/CLI boxing conversion. The cases accepted convert a +value type to a handle to that value type.

    +

    unboxing_conversion_possible determines whether a conversion from one given +type to another is a C++/CLI unboxing conversion. The cases accepted convert a +handle type to a value type.

    +

    system_type_from_fundamental_type and fundamental_type_from_system_type +are a pair of functions that convert back and forth between fundamental types +and the corresponding C++/CLI value class types (e.g., between int and +System::Int32).

    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/templates/index.html b/doc/templates/index.html new file mode 100644 index 0000000..9195084 --- /dev/null +++ b/doc/templates/index.html @@ -0,0 +1,3547 @@ + + + + + 13. Templates - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    13. Templates#

    +

    Support for template declarations and the instantiation of classes and objects +based on templates is found principally in templates.c; templates.h +contains the associated declarations.

    +
    +

    13.1. Overview#

    +

    Template support is almost entirely a front-end issue. By default, templates +themselves are not represented in the IL, and classes and functions that are +generated on the basis of templates look just like any other class or function. +The exceptions to this rule are:

    +
      +
    • +
      Classes, functions, variables, and aliases generated from templates +identify the associated template arguments, because those arguments may +be needed in generating the name of the entity.
      +
      +
    • +
    • +
      In automatic instantiation mode additional flags are provided in the +variable and routine entries so that the information provided by the flags +may be represented in the resulting object file in some form.
      +
      +
    • +
    • +
      A template IL entry is created for each template declaration. When +PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, the entry points to a +“prototype instantiation”, which is an IL entry that represents the entity +declared by the template. When RECORD_TEMPLATE_STRINGS is TRUE, the +entry contains a null-terminated string that represents the template +declaration. The IL template entry is also used to represent the value of +a template template argument.
      +
      +
    • +
    • +
      The template instantiation mechanism may require support in the back end. +For example, if each instantiation is placed in its own object file, the +back end must recognize the data structures provided to accomplish this.
      +
      +
    • +
    +

    Generally speaking, when a template definition is scanned, the definition of +the template is saved and then used later to generate instances of the +template. There are two common techniques used by compilers to save the +definition of a template: in the first technique, the template is parsed +(without semantic analysis) and the parse tree is saved; in the second, some +unparsed (more or less textual) representation of the template is saved. A +parse tree may be a reasonable choice for a multi-pass front-end featuring a +separate parser. However, in the EDG C++ front end (which uses a single pass +approach in which parsing and semantic analysis are done together), a textual +representation, which we call a “token cache”, is more appropriate. Correctly +implemented, the two techniques are semantically equivalent.

    +

    When using exported templates (see Exported Templates) the front end +reloads the translation unit(s) that define the exported templates that require +instantiation so that the information from all of the translation units is +available to the front end. Even though there is a great deal of special +processing required to make exported templates work properly, the underlying +mechanism of rescanning tokens from a token cache is still used to produce the +actual instantiation.

    +

    Since the method one chooses to record the definition of the template affects +the data structures used in the implementation and also influences the +terminology used to describe them, it will be helpful to introduce some terms +that are used in the EDG C++ front end:

    +
      +
    • +
      A template denotes a sequence of tokens that, along with one or more +template parameters and a declarative context, is used as the basis for +generating an instance of the template.
      +

      +
      A template entity may be
      +
      +
        +
      • +
        a class template (e.g., class A),
        +
        +
      • +
      • +
        a function template (e.g., function f),
        +
        +
      • +
      • +
        a member function of a class template (e.g., A<T>::f),
        +
        +
      • +
      • +
        a static data member of a class template (e.g., A<T>::t),
        +
        +
      • +
      • +
        a nested class of a class template (e.g., A<T>::B),
        +
        +
      • +
      • +
        a member class template (e.g., A<T>::C),
        +
        +
      • +
      • +
        a member function template (e.g., A<T>::g),
        +
        +
      • +
      • +
        a variable template (e.g., x<T>),
        +
        +
      • +
      • +
        an alias template, or
        +
        +
      • +
      • +
        a partial specialization of a class template, member class template, +or variable template.
        +
        +
      • +
      +
      +
      For example,
      +
      +
      template <class T> void f(T);       // function template
      +template <class T> class A {        // class template
      +  T f() { return t; }               // member function of class template
      +  static T t;                       // static data member of class template
      +  struct B {};                      // nested class of class template
      +  template <class U> void g(U);     // member function template
      +  template <class U> struct C {};   // member class template
      +  template <class U> struct C<U*> {}; // partial specialization
      +  template <class U> static U vt;   // member variable template
      +};
      +template <class T> T x = 1;         // variable template
      +template <class T> using B = A<T*>; // alias template
      +
      +
      +
    • +
    • +
      A template parameter refers to a template formal argument, and a +template argument is a template actual argument.
      +
      +
    • +
    • +
      A template instance is a class (sometimes called a template class) +generated on the basis of a class template, an alias (i.e., typedef, +sometimes called a template alias) generated on the basis of an alias +template, a function (sometimes called a template function) generated on +the basis of a function template, or a variable (sometimes called a +template variable) generated on the basis of a variable template. In +addition, a member function or static data member of a template class is +itself an instance of the corresponding member function or static data +member of the class template. For example,
      +
      +
      template <class T> class A {
      +  static T t;
      +  T f() { return t; }
      +};
      +A<int> ai;
      +template <class T> T g(T t) { return t; }
      +int i = g(0);
      +
      +
      +
      +
      With the declaration of ai an instance of class template A, namely, +A<int>, is generated, and in the process instances A<int>::f and +A<int>::t are also generated. Similarly, the reference to g(int) +causes an instance of function template g to be generated.
      +
      +
    • +
    • +
      In many cases instances of variable templates and static data members of +template classes are treated similarly. The term “template variable” is +used to refer to both cases, unless otherwise specified.
      +
      +
    • +
    • +
      The generation of an instance of a template is called instantiation. +(Sometimes the result of instantiation, namely an instance, is also called +an instantiation.)
      +
      +
    • +
    • +
      An instantiation may be either a partial instantiation or a full +instantiation. A partial instantiation of a class template is like a +declaration of an ordinary class when no body is supplied; similarly, a +partial instantiation of a function template is like a declaration of a +function without a function body. On the other hand, a full instantiation +is the generation of a class or function definition – i.e., it includes +the body. For instance,
      +
      +
      template <class T> class A {};
      +A<long> *pal;
      +A<int> ai;
      +
      +
      +
      +
      In this case the declaration of pal causes the partial instantiation of +A<long> – that is, no body needs to be generated – whereas the +declaration of ai causes the full instantiation of A<int>. The +instantiation of an alias template is always a full instantiation.
      +
      +
    • +
    • +
      The first time a class template is scanned – partly to record its member +functions, static data members, nested classes, and friend declarations, +and partly to check for errors – the result is referred to as a prototype +instantiation of the class template, and the class produced is called a +“nonreal” class; in general, a template class based on template arguments +that include at least one template parameter is called “nonreal”. In +addition, a template class based on a template that is a member of a +nonreal class is also called “nonreal”. Consider this example:
      +
      +
      template <class T, int I> struct A {
      +  template <class T2> struct X {};
      +};
      +template <class T> struct B {
      +  A<T, 0> a;
      +  typename T::X<int> x;
      +};
      +B<A<int,1> > b;
      +
      +
      +
      +
      In this example, when class template A is scanned, the prototype +instantiation produces nonreal class A<T,I>, and during the scanning of +class template B nonreal classes A<T,0> and T::X<int> are +generated. Subsequently, when b is declared and B<A<int,1> > is +instantiated, A<int,0>, a real class, is instantiated to serve as the +type for member B<int>::a, and A<int,1>::X<int> is instantiated to +serve as the type for member B<int>::x.
      +
      +
    • +
    • +
      A prototype instantiation is also performed for alias templates resulting +in a nonreal alias. Nonreal aliases are also created for instantiations of +alias templates if the template argument list depends on a template +parameter. Unlike nonreal classes, nonreal aliases are actually +instantiated by rescanning the tokens of the alias.
      +
      +
    • +
    • +
      Nested classes of class templates are not themselves referred to as +templates, but their member functions and static data members are, +respectively, member functions of class templates and static data members +of class templates, and a member function or static data member of a class +nested within a template class is handled as an instance of the +corresponding member function or static data member from the class +template. A class nested within a nonreal class is considered a nonreal +class.
      +
      +
    • +
    • +
      The definition of a template instance may be supplied explicitly by the +user instead of being generated based on the template. Such instances are +referred to as explicit specializations of the template.
      +
      +
    • +
    • +
      A class template or variable template may be partially specialized. A +partial specialization is an alternate version of the template that is used +to generate instances whose template argument lists match a specified +pattern. For example, a partial specialization could be provided that will +be used to generate all instances for which a specified template argument +is a pointer type.
      +
      +
      template <class T> struct A {};      // primary template
      +template <class T> struct A<T*> {};  // partial specialization
      +
      +
      +
      +
      The template that is specialized by a partial specialization is called +the primary template.
      +
      +
    • +
    • +
      Function templates may be overloaded with normal functions and with other +function templates. Overload resolution is used to select the function or +template to be used for a given call. If, as a result of overload +resolution, there are two or more templates that could generate equivalent +functions, partial ordering rules are used to select the template to be +used. Partial ordering is different from partial specialization in that +there is no relationship between the function templates being ordered (i.e, +one is not considered to be a specialization of the other).
      +
      +
    • +
    • +
      In some modes, prototype instantiations are performed for entities other +than classes and aliases. When semantic analysis of nonclass templates has +been requested, prototype instantiations are done for the bodies and +default arguments of function templates and member functions of class +templates, the initializers of template static data members, and the +default values of template arguments.
      +
      +
    • +
    • +
      Template template parameters are class templates for which the template +definition to be used for a given reference is supplied by a template +template argument.
      +
      +
    • +
    +

    By default, prototype instantiations and entries associated with nonreal +classes and aliases do not appear in the IL. When +PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, IL entries for prototype +instantiations are generated. See Templates for more +information.

    +

    Template definitions are typically placed in header files that are included by +the programs that make use of the templates. Alternatively, the definitions of +template static data members and non-inline template functions may be provided +using the “export” facility of the C++ language (see +Exported Templates).

    +

    The major part of template support falls into several phases. The first is +processing the declaration of the template, which for a class template also +involves doing a prototype instantiation. The second phase is recognizing a +reference to an instance of a template and producing a partial template +instantiation, which can be thought of as an on-the-fly declaration of the +instance. The third phase is the full instantiation of the template instance; +typically, a template class is fully instantiated at the first point of +reference in a given translation unit, but a template function presents special +complications, since the full instantiation of a noninline template function +may occur only once in a program, no matter how many translation units it may +appear in.

    +

    Each of these phases of template processing will be examined in detail, but +first it is necessary to describe the data structures that are built to +represent templates and their instances.

    +
    +
    +

    13.2. Data Structures#

    +

    Each collection of tokens that is stored so that the tokens may be rescanned +later is represented by an entry of type a_template_cache. The fields of +the template cache entry are:

    +
      +
    • +
      tokens, where the tokens are kept on which an instantiation of the +template is to be based.
      +
      +
        +
      • +
        For classes the tokens comprise the base specifiers list as well as the +body of the class.
        +
        +
      • +
      • +
        For functions, including member functions, they extend from the opening +left brace to the closing right brace of the function body, except that +for templates of constructors the ctor-initializer list, if present, is +also included.
        +
        +
      • +
      • +
        For static data members the tokens identify the initializer, if any.
        +
        +
      • +
      +
      +
      The last token in the token cache is always a tok_end_of_source token.
      +
      +
    • +
    • +
      decl_info, a pointer to an entry of type a_template_decl_info, +which describes the context in which the tokens stored in the token cache +appeared.
      +
      +
    • +
    +

    The template declaration information entry (a_template_decl_info) in turn +includes the following fields:

    +
      +
    • +
      parameters, a pointer to list of entries of type a_template_param; +they record the template parameters declared in the template declaration.
      +
      +
        +
      • +
        For type parameters a template param entry points to an sk_type +symbol (which in turn refers to a tk_template_param type entry).
        +
        +
      • +
      • +
        For nontype parameters a template param entry points to an +sk_constant symbol (which refers to a ck_template_param constant +entry).
        +
        +
      • +
      • +
        For template template parameters a template param entry pointed to an +sk_class_template symbol. The template symbol supplement for which +the template_template_param field is TRUE.
        +
        +
      • +
      +
    • +
    • +
      declaration_scope, identifying the sck_template_declaration scope +in which the template parameter symbols were declared.
      +
      +
    • +
    • +
      enclosing_scope, a pointer to the scope containing the template +declaration. This is important, for example, when a function template is +defined in a friend declaration within a class, in which case the class +must be reactivated when instantiations of that function template are +generated.
      +
      +
    • +
    • +
      enclosing_template_decl, a pointer to the template declaration +information for an enclosing template declaration. This is used for member +class templates and member function templates when one needs to know, for +example, not only the template parameters of the member template, but also +the template parameter lists of any enclosing class templates.
      +
      +
    • +
    • +
      decl_seq, the declaration sequence number at the point of the template +declaration. This is used when doing dependent name lookup to exclude +names not visible at the point of the template definition.
      +
      +
    • +
    • +
      nondependent_calls, used when doing dependent name processing to record +the result of overload resolution for nondependent calls that were +evaluated during a prototype instantiation.
      +
      +
    • +
    +

    A template (of whatever flavor) is represented by the combination of a symbol +and an associated entry of type a_template_symbol_supplement (defined in +symbol_tbl.h). An instance of the template is then represented by an entry +that appears on a list pointed to from the template symbol supplement. That is +the basic pattern for representing a template and its instances – a template +symbol, a supplement, and a list of instances – but each sort of template +presents a different version of the pattern.

    +

    The template symbol supplement contains a template cache entry for the template +body and also has fields that are specific to the kind of template it is +associated with; these are discussed below.

    +

    In most cases the instantiation of a template creates one or more classes, +functions, and/or static data members. However, when a class template contains +members that are themselves templates (i.e, member function templates or member +class templates) the instantiation of the enclosing class template results in +the creation of entities that are templates. When this happens, it is +necessary to record the template from which the new template was generated. +The template symbol supplement field named prototype_template contains a +pointer to the symbol associated with the template from which a given member +template was generated. Similarly the prototype template contains a field +named subordinate_templates that points to a list of templates that were +generated from the prototype template.

    +
    +

    13.2.1. Class Templates#

    +

    An sk_class_template symbol represents a class template; it contains a +pointer to a template symbol supplement. The supplement for a class template +includes the variant field instantiations, a pointer to a list of the +symbols (of kind sk_class_or_struct_tag or sk_union_tag) that represent +instances of the template. The symbol for the prototype instantiation is +pointed to by the field prototype_instantiation.

    +

    For each template class represented by a symbol on the instantiations list the +class symbol supplement has several important fields:

    +
      +
    • +
      class_template is a pointer back to the sk_class_template symbol +that represents the template upon which its instantiation is based. +However, for a nested class of a template class the class_template +pointer will always be NULL.
      +
      +
    • +
    • +
      corresp_prototype_sym is a pointer to the template class symbol for the +prototype instantiation and is present for template class instances and +classes nested within template classes.
      +
      +
    • +
    • +
      is_nonreal_class is TRUE for template classes produced by prototype +instantiations (and in general for template classes for which the template +argument list contains at least one template parameter reference). It is +also TRUE for a class that is a nested class of a nonreal template class.
      +
      +
    • +
    +

    A class symbol for a template class (i.e., for an instance of a class template) +does not otherwise appear in the symbol table. It cannot be looked up directly +but rather must be looked up via the class template symbol.

    +

    The type entry associated with a template class is like that of any other class +except that it contains the following additional information about template +classes:

    +
      +
    • +
      template_arg_list points to the template argument used to generate the +type (the template arguments are incorporated in the type so that back ends +can use them to generate names for template classes).
      +
      +
    • +
    • +
      is_template_class TRUE for template class instances and classes nested +within template class instances.
      +
      +
    • +
    • +
      is_nonreal_class is TRUE for nonreal instantiations and for local +classes of prototype instantiations.
      +
      +
    • +
    • +
      is_prototype_instantiation is TRUE for prototype instantiations of +class templates and nested classes of class templates.
      +
      +
    • +
    • +
      is_specialized is TRUE for template classes declared or defined in an +explicit specialization declaration.
      +
      +
    • +
    • +
      specialized_with_old_syntax was specialized, but not with the +“template <>” syntax that is now required by the standard.
      +
      +
    • +
    • +
      partial_spec_template_arg_list is used when a partial specialization is +used to generate the definition of the template class. It points to the +template argument list that is specified with respect to the partial +specialization’s template parameter list.
      +
      +
    • +
    +

    A class template may have associated with it a set of partial specializations +that may be used instead of the primary template when generating full +instantiations of instances of the class template. The template symbol +supplement contains a field named partial_specializations that points to a +list of sk_class_template symbols for any partial specializations that may +exist. Instances created from partial specializations go on the instantiations +list of the primary template. Each partial specialization has its own +prototype instantiation, which also goes on the instantiations list of the +primary template. The class type supplement field +partial_spec_template_arg_list is used in class types generated from class +template partial specializations (including the prototype instantiation). It +contains the template argument list with respect to the partial specialization, +while the template_arg_list field contains the template argument list with +respect to the primary template. In the following example, the template +argument list with respect to the primary template is “<int*, int>”, while +the template argument list with respect to the partial specialization is +“<int>”.

    +
    template <class T1, class T2> struct A {};
    +template <class T> struct A<T*, int> {};
    +A<int*, int> a;
    +
    +
    +

    As mentioned previously, it is here that the type entries of real and nonreal +template classes differ – the template arguments of a nonreal template class +involve at least one tk_template_param type or ck_template_param +constant. In addition, the type entry for a nonreal class does not appear in +the IL that is passed on to the back end for further processing.

    +

    When an instance of a class template is fully instantiated, partial +instantiations for all of its member functions, static data members, and nested +classes are generated. Because these entities are not themselves templates, +they do not have their own template argument lists. The template argument list +for their enclosing class is used when a full instantiation is performed.

    +
    +
    +

    13.2.2. Alias Templates#

    +

    Alias templates are represented in much the same way as class templates. An +sk_class_template symbol is used to represent the alias template, however +the instantiation list and prototype instantiation fields of the template +symbol supplement point to sk_type symbols. The is_alias_template +field of the template symbol supplement is used to identify alias templates.

    +

    The typeref type created for instantiations of alias templates (with typeref +kind trk_is_template_alias) is like that of normal aliases except that it +contains additional information, including the template argument list and flags +such as is_template_alias, is_nonreal, and +is_prototype_instantiation.

    +
    +
    +

    13.2.3. Function Templates#

    +

    An sk_function_template symbol is used to represent a function template, +including member function templates, but not member functions of class +templates. It contains a pointer to a template symbol supplement whose variant +field instantiations points to a list of entries of type +a_template_instance: each time a partial instantiation is performed on the +function template, the resulting instance is recorded in this list.

    +

    Entries of type a_template_instance are also utilized to record instances +of member function of class templates and static data members of class +templates, but they are used somewhat differently in those cases (as described +later). When a template instance is used to record an instance of a function +template, the following use is made of its fields:

    +
      +
    • +
      instance_sym points to the sk_routine symbol that represents the +instance. That symbol will in turn point to the routine entry created to +represent the instantiated function. A full instantiation need not have +been done. The routine entry contains a pointer to the template arguments +on which the instance is based.
      +
      +
    • +
    • +
      template_sym points to the sk_function_template symbol that +represents the template.
      +
      +
    • +
    • +
      instantiation_required is TRUE if the routine instance was actually +called or had its address taken. It means that a full instantiation +needs to be performed – i.e., that the function body needs to be +generated. When this flag is set, the instance is placed on the +instantiations_required list, to assure that it is checked for +additional processing once the entire translation unit has been +scanned.
      +
      +
    • +
    • +
      is_guiding_decl is TRUE if this routine was explicitly declared by the +user (whether or not a body was supplied). When this flag is set, the +symbol pointed to by instance_sym will have been added to the overload +list for this name. Note that a “specific declaration” is different than +an “explicit specialization”. A specifically declared function +participates in overload resolution, but need not be explicitly +specialized.
      +

      +
      Here’s an example:
      +
      +
      template <class T> void f(T) {}
      +void f(int);
      +
      +
      +
      +
      The second declaration assures that f(int) is represented both in the +instantiations list for function template f and on the overload list +associated with an sk_overloaded_function symbol with an identifier +f. Such a declaration affects how the function is found during +overload resolution, but it does not prevent a body from being generated +for it based on the function template.
      +
      +
    • +
    • +
      explicit_instantiation is TRUE if the user has explicitly requested +full instantiation by means of an explicit instantiation directive or +#pragma instantiate directive.
      +
      +
    • +
    • +
      referencing_namespace points to the namespace in which the use that +first required the instantiation of the template was encountered, or NULL +if the first reference was in the global namespace. This field is set when +the instantiation_required flag is set to TRUE.
      +
      +
    • +
    +

    In addition to the pointer to the instantiations list, the template symbol +supplement for a function template makes use of some other variant fields:

    +
      +
    • +
      routine is a pointer to a routine entry. This entry is generated when +the function template declaration is scanned, but it doesn’t actually map +to a real routine (and does not appear in the IL proper). Rather, it +serves as a convenient place to store the routine type and other +information about the function (e.g., the storage class, the special +function kind, and whether inlining was specified in the original +declaration).
      +
      +
    • +
    • +
      func_info is a field of type a_func_info_block and stores +information picked up during declaration processing that needs to be reused +during instantiation (e.g., the names of the function parameters).
      +
      +
    • +
    • +
      def_arg_expr_list is a list of entries containing information about +default arguments to be applied to the function parameters when the +instantiation is done.
      +
      +
    • +
    +

    Whereas, as noted previously, an instance of a class template cannot be looked +up independently of its template, the same is not necessarily the case for an +instance of a function template. When there has been a guiding declaration, +the template function’s symbol may be found during ordinary overload +resolution. However, when there is no guiding declaration, the symbol can only +be found via the function template symbol and its list of instantiations. +Consider this example:

    +
    template <class T> T f(T t) { return t; }
    +char f(char);           // Guiding declaration
    +int i = f(0);           // Instantiation of f(int)
    +void f(int, int);       // Unrelated to the template
    +
    +
    +

    Symbols are arrayed under the symbol header for “f” as follows:

    +
      +
    • +
      overloaded function symbol with overload list:
      +
      +
    • +
    • +
      template function symbol f(T) with instantiation list:
      +
      +
    • +
    • +
      instance entry pointing to routine symbol f(char)
      +
      +
    • +
    • +
      instance entry pointing to routine symbol f(int)
      +
      +
    • +
    • +
      routine symbol f(char)
      +
      +
    • +
    • +
      routine symbol f(int,int)
      +
      +
    • +
    +

    Notice that the symbol for f(char) appears both on the overload list and on +the instantiation list (there are not two different symbols), whereas +f(int) appears only on the instantiation list. The former, consequently, +is subject to the ordinary lookup rules, whereas the latter must be looked up +using the stricter rules for template functions. Guiding declarations have +been removed from the standard language, but are still supported by the front +end depending on the command line options and configuration flags being used. +When guiding declarations are disabled, declarations such as f(char) are +simply declarations of normal functions that are unrelated to the template.

    +
    +
    +

    13.2.4. Member Function of Class Templates#

    +

    A member function of a class template is represented by an +sk_member_function symbol created during the prototype instantiation of the +class template. These symbols look like ordinary member function symbols, +which among other things means they do not have their own pointer to a template +symbol supplement; rather they point to a template instance entry, and it has a +pointer to a template symbol supplement.

    +

    The problem being addressed with this somewhat roundabout arrangement is that a +member function of a class template is really a “quasi-template” whose partial +instantiation is in fact always part of any full instantiation of the class +template to which it belongs. A consequence of this approach is that the +instantiations list from the associated template symbol supplement includes +both

    +
      +
    1. ordinary instance entries that point to ordinary member function symbols +(members of real instantiations of the class template) and

    2. +
    3. one special instance entry that represents the quasi-template by +pointing to a member function symbol of the nonreal prototype +instantiation of the class template.

    4. +
    +

    The template instance entries for member functions are similar to those for +ordinary template functions:

    +
      +
    • +
      instance_sym points to the sk_member_function symbol that +represents the instance.
      +
      +
    • +
    • +
      template_sym points to the sk_member_function symbol that +represents the template.
      +
      +
    • +
    • +
      When instance_sym and template_sym are identical, the +template_info field is non-NULL and points to the template symbol +supplement belonging to this member function of a class template.
      +
      +
    • +
    • +
      The flags are used as for nonmember function instances, except that +specific_decl is always TRUE.
      +
      +
    • +
    +
    +
    +

    13.2.5. Variable Templates#

    +

    A variable template is represented by an sk_variable_template symbol. +Instantiations of the template result in variable entries and associated +sk_variable symbols. Variable templates declared in class scopes are, from +a language point of view, static data members, but they and their +instantiations are represented in the same way as non-member variable +templates. When a variable template is instantiated using a dependent template +argument list, the is_nonreal flag is set in the variable entry. The +variable variant of the template symbol supplement contains information +used for both variable templates and static data members of class templates +(although some fields are only used for one or the other). The +instantiations field points to a list of symbols for the real +instantiations of the variable template. Template instance entries are created +for the real instantiations of a variable template.

    +
    +
    +

    13.2.6. Static Data Members of Class Templates#

    +

    Static data members of class templates are represented much like member +functions of class templates. The template symbol, an +sk_static_data_member symbol from the prototype instantiation of the class +template, points to an instance entry whose template_sym field points back +to it and whose template_info field points on to a template symbol +supplement. The latter has a definitions field that points to the instance +list. The fields in the instance entries are used just like those for member +functions.

    +
    +
    +

    13.2.7. Template Declaration Information#

    +

    As described earlier, each token cache that is used in the template +instantiation process is associated with a pointer to an entry of type +a_template_decl_info, which contains information about the template +parameters, the scope in which the template was declared, and a pointer to an +enclosing template declaration information entry, if applicable. An enclosing +template declaration information pointer is used when a member function +template or member class template is declared within another class template. A +function template, or member function of a class template, contains a token +cache that contains the function declaration and a separate token cache +containing the function body. Each token cache has associated with it a +separate template declaration information pointer, because the two caches may +have come from different declarations with different template parameter lists, +etc.

    +

    There is one template declaration information entry for each template <...> +clause that is scanned (except for those with empty parameter lists, which are +used in explicit specializations). When there is more than one template clause +in a given declaration, the inner template clauses contain a pointer to the +enclosing template declaration clause (the one to the left of a given template +clause).

    +

    When a template is defined within another template the enclosing template +declaration information pointer is NULL indicating that the template +declaration information for the enclosing template should be obtained by +consulting its template symbol supplement.

    +
    +
    +
    +

    13.3. Template Declarations#

    +
    +

    13.3.1. Overview#

    +

    template_directive_or_declaration is the top-level routine for handling +template directives and template declarations. It is called when the +template or export keyword is encountered during declaration +processing. This occurs for template declarations, explicit specialization +declarations, and explicit instantiation directives. For example:

    +
    template <class T> struct A {};       // template declaration
    +export template <class T> void f(T){} // exported template declaration
    +template <> class A<int> {};          // explicit specialization
    +template class A<int>;                // explicit instantiation
    +
    +
    +

    When no template parameter list is present explicit_instantiation is +called. See Explicit Instantiation Directives for further information. When a +template parameter list is present, including an empty one (e.g., <>), +template_or_specialization_declaration is called.

    +

    It first calls cache_template_declaration to create a token cache +containing the entire template declaration, including both the template +parameter list(s) and the declaration that follows. The definition of the +template (e.g., the class or function body) is not included in this cache. An +initial scan of the tokens in the cache is done to determine whether the +declaration is a full specialization, and whether it is a friend declaration.

    +
    +

    13.3.1.1. Template Parameter Clauses#

    +

    A template declaration or template specialization declaration contains one or +more “template parameter clauses”. A template parameter clause consists of the +template keyword followed by a possibly empty template parameter list. The +initial declaration of a template always has a single template parameter clause +(although a template declaration may be nested within another template +declaration). Multiple template parameter clauses are used only when a member +template of a class template is defined or specialized outside of its class.

    +

    Each template parameter list has associated with it a template “nesting depth”. +The nesting depth of the parameter list and the position within the template +parameter list are the attributes used when comparing two template parameters +to see if they represent the same parameter. The names of the template +parameters are not significant. The nesting depth and position are +collectively called the template parameter’s “coordinates”.

    +

    For example:

    +
    template <class T1> struct A {
    +  template <class T2, class T3> void f(T1, T2, T3);
    +};
    +template <class X> template <class Y, class Z> void A<X>::f(X,Y,Z){}
    +
    +
    +

    where

    +
      +
    • +
      T1 and X both have a nesting depth of 1 and a position of 1
      +
      +
    • +
    • +
      T2 and Y both have a nesting depth of 2 and a position of 1
      +
      +
    • +
    • +
      T3 and Z both have a nesting depth of 2 and a position of 2
      +
      +
    • +
    +

    The nesting depth of a template parameter clause in a namespace scope is 1, a +template parameter clause declared within one enclosing class template is 2, +etc. When scanning a template friend declaration any enclosing class templates +are ignored and the template parameter clauses are numbered beginning with 1. +This is necessary so that any types declared in the friend declaration match up +correctly with the template that is being made a friend. For example, to make +the template in the example above a friend of another template, you would do +the following:

    +
    template <class T> struct B {
    +  template <class X>
    +  template <class Y, class Z> friend void A<X>::f(X,Y,Z);
    +};
    +
    +
    +

    The declaration of a template template parmeter also includes a template +parameter clause. The template parameters in the template parameter clause for +a template template parameter have a nesting depth of zero.

    +

    For each nonempty template parameter list, the template parameters from the +parameter list are scanned. This process includes the following steps:

    +
      +
    • +
      An sck_template_declaration scope is pushed. This will be the +declaration scope to which the template parameter names belong.
      +
      +
    • +
    • +
      scan_template_param_list is called to scan the template parameters and +build a linked list of entries of type a_template_param to represent +them. Each template parameter has an associated symbol. These symbols +initially point to special “prototype argument” values that, for class +templates, are used during the prototype instantiation. During real +instantiation these symbols are modified to point to the actual argument +values to be used.
      +
      +
        +
      • +
        A type parameter points to an sk_type symbol that initially points to +a tk_template_param type. The type symbol points to the actual +argument type during an instantiation.
        +
        +
      • +
      • +
        A nontype parameter points to an sk_constant symbol that initially +points to a ck_template_param constant. The constant symbol points +to the actual argument constant during an instantiation.
        +
        +
      • +
      • +
        A template template parameter points to an sk_class_template symbol. +Unlike the type and nontype cases, the template template parameter symbol +always points to the template symbol supplement for that template +template parameter. The argument_template field of the template +symbol supplement points to the actual argument to be used during an +instantiation. Template template parameters differ from other template +parameters in that they have certain properties that must persist through +real instantiations. For example, the default template argument values +used for a template template parameter are always the ones specified in +the template template parameter declaration, never those associated with +the actual template template argument.
        +
        +
      • +
      +
    • +
    • +
      If the template parameter has a default argument, the type or expression is +scanned on the spot if possible. However, if the default argument depends +on another template parameter, the default argument must be rescanned when +its value is needed using the actual argument values for the template +parameters on which it depends. Therefore, its tokens are cached so that +they may be scanned later (see prescan_default_arg_expr). There are a +number of ways in which a default argument can depend on another template +parameter:
      +
      +
        +
      • +
        The type of a nontype parameter may make use of another template type +parameter.
        +
        +
      • +
      • +
        The value of a default nontype argument may depend on a template type +parameter or nontype parameter.
        +
        +
      • +
      • +
        The type used as the default argument for a type parameter may make use +of another template parameter.
        +
        +
      • +
      +
      +
      For example:
      +
      +
      template <class T = int, class T2 = T, int I = 0, T J = I+1> class A {}
      +
      +
      +
      +
      The default type of T and the default constant value for I can +be known when the template parameters are scanned, but the default type +of T2 and the value for J are dependent upon whatever type +T takes on, and the value of J depends on the value used for +I.
      +
      +
    • +
    +
    +
    +

    13.3.1.2. Classifying the Template Declaration#

    +

    When processing specializations a distinction is made between a “full +specialization” and a “template specialization”. A full specialization is one +in which the entity being declared is a class, function, variable, or static +data member, while a template specialization is one in which the entity being +declared is still a template. For example:

    +
    template <class T> struct A {
    +  void f();
    +  template <class T2> void g(T2);
    +  template <class T2> struct B {};
    +  struct C {};
    +};
    +// Full specializations
    +template <> void A<int>::f();
    +template <> struct A<int>::C {};
    +// Template specializations
    +template <> template <class T2> void A<int>::g(T2);
    +template <> template <class T2> struct A<int>::B {};
    +
    +
    +

    A partial specialization of a template is treated as a normal template +declaration, not as a template specialization. A template specialization is a +template with one or more empty template parameter clauses.

    +

    Full specializations are handled by calling full_specialization. See +Explicit Specializations for more information. The rest of this +section describes template_declaration, which is responsible for +processing template declarations and template specializations.

    +

    Earlier, a token cache was built that contains the template parameter clauses +and the declaration that follows them. We are now at the point in the token +stream that marks the division between the two components. Because the +declaration component must be prescanned to determine the kind of template +being declared, and because the declaration may be needed later for the purpose +of generating partial instantiations of functions, the existing cache is split +into a template parameter cache and a template declaration cache. In certain +error cases, such as the presence of a syntax error in the template parameter +list, the template declaration may not have been cached correctly when the +initial cache was built. When this occurs, the template declaration is +recached now that the true position of the beginning of the declaration is +known.

    +

    Next, is_class_template_decl is called. If the declaration is in fact of a +class template, TRUE is returned. If it is not a class template declaration, +FALSE is returned to signal that processing for other kinds of template +declarations should be done.

    +

    The template parameters are checked to ensure that they are compatible with any +previous declaration of the template, and for class members, that the template +parameter lists that correspond to enclosing class templates are compatible +with the template parameter lists of those class templates.

    +
    +
    +
    +

    13.3.2. Class Templates#

    +

    class_template_declaration is called to process class template +declarations. This includes normal class templates, partial specializations, +and template specializations. It is also called to process declarations of +nested classes of class templates that are defined outside of the class. +class_template_declaration performs the following functions:

    +
      +
    • +
      Looks up and verifies the template name.
      +
      +
    • +
    • +
      Creates the sk_class_template symbol and enters it into the symbol +table, if necessary. The symbols for partial specializations are not +entered into the symbol table.
      +
      +
    • +
    • +
      Calls create_prototype_type to create the symbol and type for the +prototype instantiation, and to create the template argument list(s) for +the prototype instantiation.
      +
      +
    • +
    • +
      If a definition is provided, collects the tokens for the base class +specifiers and the class body and caches them for use later.
      +
      +
    • +
    • +
      For partial specializations, the template parameters of the partial +specialization must appear in the template argument list associated with +the partial specialization in such a way that their values can be deduced. +In addition, nontype arguments cannot have types that depend on other +template parameters, nor may they be used in expressions. These error +tests are accomplished by calling +check_partial_spec_nontype_param_usage.
      +
      +
    • +
    • +
      If the template is a partial specialization, +check_for_prior_use_of_partial_spec is called to determine whether the +newly declared partial specialization would have been used to generate any +existing full instantiations of the primary template, had it been declared +when the full instantiation had been done. If any such full instantiations +are found, an error is issued.
      +
      +
    • +
    +

    Then the template declaration scopes that were pushed when the template +parameter clauses were scanned are popped, and instantiate_class_template +is called to do a prototype instantiation – i.e., to scan the template +definition even though the template parameters have not yet been given “real” +values. Because declaration/expression disambiguation often cannot be done +based on dummy types, only declarative information is scanned; inline function +bodies and default argument expressions are cached and, in some modes, have +their prototype instantiations done later. Most syntax errors and some +semantic errors are detected, but some errors cannot be reported until a real +instantiation is done.

    +

    The main benefit of prototype instantiation is to record the names and types of +member functions and static data members – in effect, to create symbols to +represent member functions of class templates and static data members of class +templates. instantiate_class_template accomplishes its work in the +following steps:

    +
      +
    • +
      An sck_template_instantiation scope is pushed onto the scope stack.
      +
      +
    • +
    • +
      The token cache for the class template body is activated.
      +
      +
    • +
    • +
      scan_class_definition is called to process the tokens. Special +provisions are made for prototype instantiations:
      +
      +
        +
      • +
        Diagnostics are suppressed where appropriate.
        +
        +
      • +
      • +
        decl_member_function and decl_static_data_member create template +instance entries, template symbol supplements, and whatever else is +needed to make the member symbols serve as templates.
        +
        +
      • +
      • +
        delayed_scan_fixup_for_class moves the tokens cached for member +function bodies into the appropriate template symbol supplement; it also +moves the entries describing default argument expressions onto a list in +the appropriate template symbol supplement. The cached tokens for +inline-defined friend functions are discarded – they will be picked up +during real instantiation.
        +
        +
      • +
      +
    • +
    • +
      The starting and ending token positions of any nested classes, member +functions whose definitions were provided in the class, and member +templates (functions or classes) whose definitions were provided in the +class are recorded. These token positions will be used to remove the +definitions from the token cache for the class template body.
      +
      +
    • +
    • +
      The template instantiation scope is popped.
      +
      +
    • +
    • +
      The bodies of nested classes, etc. are removed from the class template +body token cache. Nested classes, member functions, and member templates +may all be specialized. In other words, the definitions provided in the +class template definition may not be the ones actually used for a given +instance of the class template, so there is no sense in scanning them while +instantiating the class. As with class templates and function templates, +nested classes of class templates, member functions of class templates, and +member class and function templates are only instantiated when needed, and +may be specialized any time before the point at which they are first used +in a way that requires their instantiation.
      +
      +
    • +
    +
    +
    +

    13.3.3. Alias templates#

    +

    alias_template_declaration is called to process alias template declarations +and performs the following functions:

    +
      +
    • +
      Verifies the template name.
      +
      +
    • +
    • +
      Creates the sk_class_template symbol and enters it into the symbol +table.
      +
      +
    • +
    • +
      Calls create_prototype_type to create the symbol and type for the +prototype instantiation, and to create the template argument list(s) for +the prototype instantiation.
      +
      +
    • +
    • +
      Collects the tokens for the type defined by the alias and caches them for +use later.
      +
      +
    • +
    +

    After calling alias_template_declaration, template_declaration calls +alias_prototype_instantiation to create the prototype instantiation of the +alias.

    +
    +
    +

    13.3.4. Function Templates#

    +

    The above is what happens when is_class_template_decl does in fact +determine that the declaration is a class declaration. However, if it returns +FALSE, template_declaration proceeds to examine what must be a template +declaration for something other than a class template.

    +

    If the template declaration appears within the definition of a class it must be +a member function template declaration or a template friend declaration. If it +is a member function template declaration class_member_template_declaration +(in class_decl.c) is called to scan its declaration, then +complete_function_template_decl is called to create the necessary template +data structures and to scan the template body, if present.

    +

    For all other cases, scan_template_declaration is called to scan the +declaration, which it does by calling decl_specifiers and declarator. +If that produces a function type, the declaration is processed as a function +template or member function of a class template declaration; otherwise, it is +processed as a variable template or static data member of a class template +declaration or reported as an error.

    +

    function_template_declaration is called for function templates. It, in +turn, calls either decl_function_template (in decls.c) or +template_specialization.

    +

    decl_function_template does for member and nonmember template declarations +more or less what decl_routine does for ordinary function declarations. +The processing for nonmember function templates includes the following:

    +
      +
    • +
      id_linkage is called to determine whether this is a redeclaration of a +function template that is already in the symbol table and whether the name +of the function template is overloaded.
      +
      +
    • +
    • +
      If this is not a redeclaration, then:
      +
      +
        +
      • +
        An sk_function_template symbol is entered into the symbol table +(either directly or into an overload set).
        +
        +
      • +
      • +
        A routine entry is allocated and its fields are set to record the type, +storage class, and so forth specified in the declaration. It is not +added to the IL, however, because it does not designate a “real” routine.
        +
        +
      • +
      +
    • +
    +

    Member functions, for which a qualified name must be present, will already have +been declared in the class template definition. Their processing includes a +call to member_function_redecl_sym, which returns the member function +symbol with a matching type signature.

    +

    decl_function_template returns to function_template_declaration an +already existing or newly created symbol that represents the function template. +Then, as with member function template declarations, +complete_function_template_decl is called.

    +
    +

    13.3.4.1. Completing the Function Template#

    +

    The next step is to collect the tokens of the function body (including, for +a constructor, the ctor-initializers) and store them in a cache in the +template symbol supplement. For both member and nonmember function +templates the new template declaration information (parameter list, etc.) +is recorded in the associated template symbol supplement.

    +

    When doing nonclass prototype instantiations, +function_prototype_instantiation is called to perform a prototype +instantiation on the body of a function template or member function of a class +template, and default_arg_prototype_instantiation is called to perform a +prototype instantiation on the default arguments of such functions.

    +
    +
    +
    +

    13.3.5. Variable Templates and Static Data Member Templates#

    +

    Variable template declarations can be either extern declarations, or are +definitions. Static data member declarations are always definitions. For +definitions, the template parameter list is recorded in the template symbol +supplement, and the tokens comprising the initializer, if any, are cached. In +some cases, some or all of the initializer may have already been cached as part +of the template declaration. In such cases, split_token_cache is used to +move the initializer tokens from the declaration cache to the initializer +cache; the remaining initializer tokens are then appended to the initializer +cache.

    +

    When doing nonclass prototype instantiations, +variable_template_prototype_instantiation is called to perform a prototype +instantiation on the initializer of the variable template or template static +data member.

    +
    +
    +

    13.3.6. Variadic Templates#

    +

    The C++11 standard adds “variadic templates,” which are templates that take a +variable number of arguments. For example:

    +
    template<class ...T> void f(T ...args) {
    +  int a[] = {0, args..., 5};
    +}
    +int main() {
    +  f(1, 2, 3, 4);
    +}
    +
    +
    +

    The template f can be called with zero or more arguments. For a given +call, the parameter pack T is deduced to be a list of types, matching the +types of the arguments supplied, and args is a function parameter pack that +is a series of parameters of the types given by T.

    +

    The front end implements variadic templates by storing, along with the tokens +of the template, information on the location and details of any pack references +and expansions. When the template is instantiated, the cached tokens of its +declaration or definition are scanned, and in places where there are pack +expansions, the processing loops over a sequence of tokens, substituting a +different value for the pack name on each iteration, thus producing an expanded +version of the source text.

    +

    The language definition of variadic templates uses a syntax-based trick: in +contexts that allow a list of items (usually, a comma-separated list), an item +in the list can be suffixed by “...” to indicate that it is a pack +expansion. In an instantiation of the template, that pack expansion is +replaced by, in effect, a list of entities generated by the expansion of the +pack. So, in the above example, the aggregate initialization expands to the +equivalent of

    +
    int a[] = {0, 1, 2, 3, 4, 5};
    +
    +
    +

    with the elements of the pack expansion inserted into the surrounding list.

    +

    Such expansions are allowed in parameter lists, call argument lists, +brace-enclosed aggregate initializers, base class specifiers, +mem-initializers, template argument lists, exception specifications, +attributes, and capture lists.

    +

    The front end uses its own trick to expand these patterns. In each of those +contexts, the code that handles the normal, non-variadic, case is enclosed in a +loop with the following general structure:

    +
    a_pack_expansion_stack_entry_ptr pesep;
    +a_boolean                        any_more;
    +
    +any_more = begin_potential_pack_expansion_context(&pesep);
    +while (any_more) {
    +  a_pack_expansion_descr_ptr pedep;
    +
    +  /* Normal processing for one item is done here. */
    +  ...
    +  pedep = end_potential_pack_expansion_context(pesep,
    +                                               /*is_declarator=*/FALSE);
    +  if (pedep != NULL) {
    +    /* Mark the IL created as being for a pack expansion. */
    +  }  /* if */
    +  any_more = advance_to_next_pack_element(pesep);
    +}  /* while */
    +
    +
    +

    When no pack expansions are present, the “begin...” call returns TRUE, the +“end...” call returns NULL, and the “advance...” call returns FALSE, so +the loop goes around exactly once and handles one item on the list.

    +

    When a pack expansion is present, in the prototype instantiation the +“begin...” call returns TRUE, the “end...” call swallows the “...” +indicating the pack expansion and returns a pointer to a structure that +describes the pack expansion, and the “advance...” call returns FALSE. +Again, the loop goes around exactly once, but information about the pack +expansion is recorded in the IL and in data structures attached to the +template.

    +

    In a real instantiation, the loop goes around as many times as the pack being +expanded has values. Each time through, the source token position is reset to +the start of the expansion, the pack identifier is given an appropriate value +for that iteration, and the tokens are scanned again. After the right number +of iterations, the “advance...” call returns FALSE and the loop exits. If +the pack has zero elements, the “begin...” call advances the source token +position to after the “...” at the end of the expansion, and returns FALSE, +and the loop goes around zero times, thus producing no items on the list for +the pack expansion.

    +

    The pattern above appears in every place where a pack expansion could occur. +In a call argument list, for example, it must be done around the scanning of +every argument, which means in a lot of places. (Or, at least, in a lot of +places when inside a template that has variadic parameters.) Almost all the +time, the variadic processing notes a starting position and starts a potential +expansion context, but then finds out later that there is no trailing “...” +and therefore no pack expansion, and discards the information saved. This has +to be done, however, so that we can recall the starting position of a pack +expansion in the cases where one does occur.

    +

    The information saved for a pack expansion in the prototype scope (and, +incidentally, prototype instantiations are forced for variadic templates, so +that such information can be recorded) includes the starting position of the +pack expansion, so that, in a real instantiation, the “begin...” call can +look up the current token position and see whether a pack expansion starts at +the current token, and what the details of the expansion are. The saved +information includes the list of pack names that were referenced and are to be +iterated over in the loop. With that information, the “begin...” routine +can set up the proper looping over the proper sequence of tokens.

    +

    There are variant versions of these variadic-loop-management routines that are +used for expression rescan contexts (no source tokens are consumed; pack +identifiers are updated and the right number of iterations of the loop are +done) and prescan and disambiguation contexts (where we don’t know yet the +context of the code, and therefore can’t be certain about what pack expansions +mean, so we don’t want to record anything permanent).

    +

    Template argument lists need to contain some extra information when variadic +templates are used. For example, for a case like

    +
    template<class U, class ...T> void f(U p, T ...args) {
    +}
    +int main() {
    +  f(1, 2.0, 3.0f);
    +}
    +
    +
    +

    the complete deduced template argument list for f has int for U, +and then a list of double and float for T. In diagnostics, this is +displayed as <int, <double, float>>. Internally, it requires a way to +indicate that part of the list is a pack expansion. That’s the function of the +tak_start_of_pack_expansion kind of template argument: it marks the start +of a sequence of template arguments associated with a pack expansion (and each +member of that sequence is marked with the is_pack_element flag).

    +

    That causes problems for lots of code in the front end that traverses template +argument lists. In most cases, that code does not want to worry about +start-of-pack-expansion entries. It just wants the “real” entries on the list. +That’s what the traversal routines begin_template_arg_list_traversal, +advance_to_next_template_arg, and the “..._simple” versions of those +routines do. They allow easy set up of a traversal of a template argument list +that ignores the start-of-pack-expansion entries. They should be used in +general to process template argument lists, to avoid problems.

    +

    Deduction does special processing to handle parameter packs, matching up +template parameters with multiple types, or nontype values, or template +template parameters. Zero-length packs are a particular problem, in that they +are deduced from an absense of information (e.g., no arguments corresponding to +that parameter pack).

    +

    Overload resolution does special processing for parameter packs, and in +particular has to be careful because the normal one-to-one correspondence +between arguments and parameters does not always hold.

    +

    Initializer processing deals with pack expansions by using expresison caches. +The initializer routines call to fetch one expression. If the expression +scanned is a pack expansion, the first expresison of the expansion is returned, +and the rest are pushed into an expression cache. They are then returned on +subsequent calls at the same or a higher or lower level. If the pack expansion +produces zero expressions, another expression is scanned, unless we hit the end +of the initializer (e.g., a closing brace). In some cases an expression is +prescanned so we can decide whether the expression-list is over before going +down a path in the code that will expects to be able to fetch an expression.

    +

    Partial ordering and partial specialization processing also deal specially with +variadic templates.

    +
    +
    +
    +

    13.4. Templates in the IL#

    +

    An entry of type a_template is created for each template declaration (see +make_il_template_entry). By default, no information about the template +itself is preserved in the IL. There are two different optional mechanisms +that can be used to record information about templates:

    +
      +
    • +
      If PROTOTYPE_INSTANTIATIONS_IN_IL is TRUE, any prototype instantiation +is recorded in the IL. If nonclass prototype instantiations have been +requested, prototype instantiations will be generated for each template +entity declared; otherwise, prototype instantiations will be recorded only +for class templates. A prototype instantiation is an IL entry whose kind +corresponds to the kind of entry being declared, but that represents the +template itself and not any particular instantiation thereof. In other +words, it still contains references to the template parameters. A type +entry is used to represent a class template, a routine entry is used to +represent a function template, and a variable entry is used to represent a +variable template or template static data member.
      +
      +
    • +
    • +
      If RECORD_TEMPLATE_STRINGS to TRUE, the IL template entry will point to +a null-terminated string that reproduces the text (minus comments, after +preprocessing) of the template declaration in the source program (see +make_template_string). If a template has more than one declaration +(e.g., a nondefining declaration followed by a definition), an IL template +entry is produced for each declaration.
      +
      +
    • +
    +

    Both of these mechanisms can be used at the same time. Note that while all +templates can be represented as template strings, only those templates that +make use of the standard-mandated typename and template keywords +can have prototype instantiation IL entries generated (because without such +keywords it is not possible to parse the template definitions in the +absence of a set of actual template argument values). See +Templates for more information.

    +
    +
    +

    13.5. Partial Instantiation#

    +

    Partial instantiation occurs automatically for nested classes, member +functions, and static data members when the class of which they are members is +instantiated. That is to say, the full instantiation of a class necessarily +entails the implicit declaration of all its members: symbols are introduced +into the symbol table, type entries are created as required, IL entries are +created and added to the IL, and so forth. The partial instantiation of class +templates and function templates, on the other hand, is triggered by a +reference.

    +
    +

    13.5.1. Class Templates#

    +

    When a class template reference – class-template-name<template-arg-list> – is encountered, a call is made to +coalesce_template_class_reference to scan the template argument list and +look up the reference. Having verified that types in the template argument +list correspond to type template parameters and constants correspond to nontype +template parameters, it builds a linked-list representation of the template +arguments. If there are more template parameters than template arguments and +if the template parameters have default values, entries are supplied for the +default values as well, whether from a saved constant value or after rescanning +the cached tokens comprising the default argument expression.

    +

    The template argument list is then passed to find_template_class, which +searches among the instantiations that already exist for the class template, +calling equiv_template_arg_lists to compare the template arguments scanned +for the current reference against the template arguments associated with +existing instantiations. If an instance with matching template arguments is +located, the symbol for it is returned. If no match is found, a new symbol is +created (see make_template_class_sym in symbol_tbl.c) and added to the +instantiations list for the class template. A new class type is also created, +but, since this is a partial instantiation, no body is generated for it yet.

    +

    A reference to an instance of a class template always causes a partial +instantiation, but not all references cause full instantiation. Partial +instantiation occurs during the lexical scan of a template class reference, +whereas the decision whether to do full instantiation occurs during semantic +processing. Partial and full instantiation are always separate steps in +template processing.

    +

    Note that a partial instantiation can be generated on the basis of an +incomplete class template. For example:

    +
    template <class T> class A;
    +A<int> *x;
    +
    +
    +

    Even though no body has been supplied for class template A, a partial +instantiation of A<int> can be produced. On the other hand, A<int> is +an incomplete (and incompletable) type, and so an error would be issued if it +were used in a context that required a complete type. Similarly, partial +specializations are not relevant when a partial instantiation is generated. +They are only considered when a full instantiation is done.

    +
    +
    +

    13.5.2. Function Templates#

    +

    A function template may be referenced in several different ways:

    +
      +
    • +
      as a function call,
      +
      +
    • +
    • +
      by taking the address of a function,
      +
      +
    • +
    • +
      and by declaring a function in an explicit specialization, explicit +instantiation, or friend instance declaration.
      +
      +
    • +
    +

    In each case, determining which function template is to be used, and which +instance of the template is being referenced, requires the evaluation of an +explicitly specified template argument list, deducing template arguments from +the function template’s parameters, or some combination of the two. This +process involves the following steps for each of the candidate function +templates:

    +
      +
    • +
      If an explicit template argument list was specified, +substitute_template_arguments is called. Note that an explicit +template argument list is completely scanned before +substitute_template_arguments is called. When it is scanned, the +number of parameters, and their types are not known. Consequently, the +template argument list needs to be converted into one that matches the +template parameter list of the candidate template. This is done by calling +create_initial_template_arg_list. If the specified template arguments +cannot be converted to the types of the corresponding parameters, or if +there are more template arguments than template parameters, no template +argument list is created and the candidate template is disqualified. Note +that an error is not issued because there may be another candidate template +that is actually the one intended to be used.
      +
      +
    • +
    • +
      Once an appropriate template argument list has been produced, +substitute_template_arguments calls copy_type_with_substitution to +create a function type that represents the function type of the candidate +template with the template parameters that correspond to the explicitly +specified template arguments replaced with the specified template argument +values. If the substitution process would result in an invalid type (e.g., +a pointer to a reference type, or an array of void) the candidate template +is disqualified.
      +
      +
    • +
    • +
      Template argument deduction is done using the substituted function type +created above in an attempt to deduce the template arguments that were not +explicitly specified. Template argument deduction is done by calling +matches_template_type, which is described below.
      +
      +
    • +
    • +
      If template argument deduction succeeds, +wrapup_function_template_argument_deduction is called to verify that +values have been deduced for all of the template parameters, and that the +types of any deduced nontype parameters match the types of the +corresponding template parameters. copy_type_with_substitution is +called once again to create a new function type in which all of the +template parameters have been replaced with the corresponding template +argument values.
      +
      +
    • +
    +

    When the reference is from a function call, the routines described above are +called from the overload resolution routines. When the reference is from the +address of a function or from a declaration, these routines are called by +is_match_for_function_template, which in turn is called from either +matching_template_function or has_matching_template_function.

    +

    There are several routines in templates.c that directly and indirectly +support the process described above:

    +
      +
    • +
      matches_template_type is designed to be called successively to build a +template argument list while checking for a match between a type from the +function template routine type and a type from a new routine type; it also +calls itself recursively to apply the processing to type trees. When a +template parameter type is found, the “real” type with which it is paired +is recorded in the corresponding template argument entry – unless it +already has some other type, in which case an inconsistency has been found. +As long as there are no inconsistencies or type incongruities, this process +of augmenting the template argument list continues; otherwise, +matches_template_type returns FALSE to halt further processing and +invalidate the template argument list built thus far.
      +

      +
      After matches_template_type has indicated that each of the arguments +match the template, verify_template_nontype_args must be called to +verify that nontype parameters whose types depend on a template parameter +are consistent with the deduced types. It also supplies types for nontype +parameters that are deduced entirely from array bounds.
      +
      +
    • +
    • +
      compare_function_templates is used to determine whether one function +template is more specialized than another based on the partial ordering +rules for function templates. It is called by the overload resolution +routines to compare two function templates that are otherwise identical +from the point of view of overload resolution.
      +
      +
    • +
    • +
      add_to_partial_order_candidates_list is used in contexts other than +overload resolution in which a function template must be selected from a +set of function templates using the partial ordering rules. This is done +when taking the address of a function that is determined to be an instance +of a function template, and when the lookup of a conversion operator name +results in the partial instantiation of a template (e.g., when operator +int* is a reference to an instance of a function template such as +operator T*). After this routine has been called for each candidate +template, select_best_partial_order_candidate is called to return the +best matching template.
      +
      +
    • +
    • +
      find_template_function is passed a function template symbol and a +template argument list. After checking for the use of a local type among +the template arguments (an error), it goes through the instances that +already exist for the template, calling equiv_template_arg_lists until +a match is found. If none of the existing instances match the new template +argument list, it creates a new instance by calling +make_template_function, to which the new template argument list is +passed.
      +
      +
    • +
    • +
      is_match_for_function_template is passed a function template symbol and +a new routine type. It returns TRUE if the type fits the type signature of +the template and FALSE if not. First, obvious mismatches are detected, +such as mismatches in the number of function parameters. Next, if an +explicit template argument list was specified, the template arguments are +compared with the corresponding template parameters. Type arguments must +be associated with type parameters, nontype arguments must be associated +with nontype parametersm, and the specific nontype value specified must +match the type of the nontype parameter or must be capable of being +converted to the type of the nontype parameter. It then tries to find +among the instances of the template one whose type signature exactly +matches the new routine type. If it finds such an instance, it returns +TRUE, along with the symbol it found. Otherwise, it makes successive calls +to matches_template_type in an attempt to construct a template argument +list based on any explicitly specified template arguments, the template +parameter types, the template routine type, and the new routine type; if +this is successful, it returns TRUE, along with the new template argument +list, but otherwise it returns FALSE.
      +
      +
    • +
    • +
      matching_template_function is passed a function template symbol and a +routine type. It calls is_match_for_function_template which checks for +a match between the routine type and the template. If there is a match but +no instance already exists, it creates a new instance by calling +make_template_function, to which the routine type is passed.
      +
      +
    • +
    • +
      has_matching_template_function is similar to +matching_template_function in that it determines whether a given +routine type matches a potential instance of the specified template, but it +does not create an instance of the template. It is primarily used when +issuing diagnostics, to choose the most appropriate of several possible +messages. In the following example, the error “specializing overloaded +function "A::f" requires template <> syntax” is used because the +function type matches the template declared in the class.
      +
      +
      struct A {
      +  template <class T> void f(T);
      +};
      +void A::f(int) {}
      +
      +
      +
    • +
    • +
      make_template_function is the routine that actually does the partial +instantiation. When it is passed a non-NULL routine type, it simply uses +that type; otherwise, it activates the declaration token cache (see the +decl_token_cache field in the template symbol supplement) and calls +either scan_member_declaration or scan_template_declaration, for +member and nonmember function templates, respectively, to assure that +template arguments are correctly substituted for template parameters in the +new routine type; and then, if there are default arguments, it calls +delayed_scan_for_function_template_default_args. In addition, it +creates the sk_member_funciont or sk_routine symbol entry, the +routine entry, and the template instance, setting all their pointers and +other fields appropriately. The symbol is not entered directly into the +symbol table – it is accessible to lookup via the instantiation list only.
      +
      +
    • +
    +
    +
    +

    13.5.3. Variable Templates#

    +

    A reference to a variable template results in a full instantiation of the +instance if a definition is available. The only exception is when the variable +template is used in a declarative context (i.e., to declare an explicit +specialization of the variable template). In a partial instantiation the +initializer is not scanned.

    +
    +
    +
    +

    13.6. Full Instantiation#

    +

    Full instantiation of a template means providing an instance of the template +with a defining body (or, in the case of a static data member, a definition +with an implicit or explicit initializer). Typically, this occurs +automatically, on the basis of the template provided. However, it can also +occur when the user provides an explicit specialization definition. Both cases +are discussed in this section.

    +
    +

    13.6.1. Explicit Specializations#

    +

    Two forms of explicit specialization are supported by the front end: the new +explicit specialization syntax (e.g., template <> ...), and the old form +that used the normal declaration syntax. The new form is accepted in all +modes, while acceptance of the old form is controlled by a command line option. +Member function templates and member class templates may only be explicitly +specialized using the new syntax.

    +

    For example:

    +
    template <class T> void f(T);
    +template <class T> class A {};
    +template <> class A<int>;       // new specialization declaration
    +template <> class A<int> {};    // new specialization definition
    +class A<char>;                  // old specialization declaration
    +class A<short> {};              // old specialization definition
    +template <> void f(int);        // new specialization declaration
    +template <> void f(int){}       // new specialization definition
    +void f(char);                   // guiding declaration
    +void f(double){}                // old specialization
    +
    +
    +

    Explicit specializations that use the new syntax begin with one or more +template parameter clauses in which the parameter list is empty. An explicit +specialization can be a declaration or a definition. The language requires +that an explicit specialization be declared before its first use in a +translation unit.

    +

    When using the old syntax, only classes can be declared as specializations. +For all other kinds of entities, specializations can only be supplied as +definitions. A function declaration that looks like an old-style +specialization declaration is actually what is known as a “guiding +declaration”, whose only purpose is to cause a template instance to be treated +like a normal function for overload resolution purposes. There are no member +guiding declarations.

    +

    Old-style explicit specializations look like normal class, function, and static +data member declarations and are handled by the same routines that handle +normal declarations.

    +

    full_specialization processes new-style explicit specializations and is +called after the template parameter clauses have been scanned. +decl_specifiers and declarator are called to scan the declaration that +follows the template parameter clauses. If the entity being specialized is a +class, the call to declarator is bypassed. full_specialization then +identifies the template instance that is being specialized.

    +
    +

    13.6.1.1. Class Templates#

    +

    An explicit specialization of a class template occurs when the explicit +specialization syntax is used, or when old specializations are enabled, when an +ordinary class definition is provided in which the class name is a template +class reference, for example:

    +
    template <class T> class A {};
    +template <> class A<short> {};
    +class A<int> {};
    +A<char> x;
    +
    +
    +

    In this example the bodies for A<int> and A<short> are the ones +provided by the user’s explicit definitions. The bodies for all other +instances of template class A, such as A<char>, are based on the +template definition.

    +

    The processing of class template explicit specializations is done within +class_specifier, even when the new specialization syntax is used. This is +necessary because only when class_specifier is called is it possible to +determine whether the class is being specialized or whether the class specifier +is part of an elaborated type specifier in some other kind of declaration.

    +

    When the template class reference is encountered as a tag name (see +scan_tag_name), a partial instantiation is done automatically and the +symbol is entered on the instantiations list of the class template. Then +class_specifier marks the class as being explicitly specialized by setting +the is_specialized flag in the type entry, and adds the definition, if one +has been supplied. Because the is_specialized flag is set, no subsequent +automatic instantiation will be attempted.

    +

    The same processing applies to both class templates and member class templates. +The processing for nested classes of class templates is basically the same +except that, as with other members of class templates, the partial +instantiation of the nested class is done when the enclosing class is +instantiated.

    +
    +
    +

    13.6.1.2. Function Templates and Member Functions of Class Templates#

    +

    An instance of a function template may be explicitly specialized using the +explicit specialization syntax, or when old specializations are enabled, by +providing a function definition that happens to match the type signature of a +function template. For example:

    +
    template <class T> void f(T) {}
    +template <> void f(char);         // explicit specialization
    +void f(int) {}                    // old explicit specialization
    +void f(int,int} {}                // Unrelated to the template
    +
    +
    +

    In both the old and new style specializations, the is_specialized flag in +the routine entry is set, which suppresses the full instantiation of the +template. The old-style specialization of a function also acts as a guiding +declaration for overload resolution purposes.

    +

    When the new specialization syntax is used, find_matching_template_instance +is called to find the template instance that matches the routine type returned +by declarator. This is done not only for instances of function templates +and member function templates, but also for member functions of class +templates.

    +

    Processing for old-style explicit specializations follows the track for +ordinary function definitions. The primary difference appears in +find_linked_symbol (called from decl_routine via id_linkage), which +searches for previous declarations of the entity being declared. If the +ordinary search fails to turn up a matching function but does find a function +template with the given name, a call is made to matching_template_function, +which extends the search to instances of the template function and, as +described above, creates a new one when appropriate. In other words, this +search in id_linkage may have the effect of doing a partial instantiation +of a new template function. Once the instance symbol has been found (or +created by means of a partial instantiation), attaching the function definition +to the routine involves no special processing.

    +

    It can happen that an old-style explicit specialization of a function template +precedes the declaration of the template itself. For example:

    +
    void f(int) {}                 // Specific definition
    +template <class T> void f(T) {}
    +
    +
    +

    When the function template declaration is encountered, +decl_function_template goes back through existing functions of the same +name and calls record_predeclared_template_function for each – if the +function turns out to match the new template, it is retroactively entered as an +instance.

    +

    Old-style explicit specializations of member functions or static data members +of instances of a class templates involve little special handling beyond what +is normally done for definitions of member functions and static data members of +nontemplate classes. Here’s an example:

    +
    template <class T> class A {
    +  void f(T);
    +  static T s;
    +};
    +void A<int>::f(int) {}
    +int A<int>::s = 0;
    +
    +
    +

    The reason no special processing is required is that the full instantiation of +A<int> entails the partial instantiation of its members f(int) and +s. After that it’s just a matter of marking the symbols as defined and +adding the function body or initializer.

    +
    +
    +

    13.6.1.3. Variable Templates#

    +

    The use of a variable template in an expression context results in a full +instantiation if a definition is available. If a definition is not available, +the normal instantiation processing is done as for template functions and +static data members of template classes (e.g., an instantiation could be done +later in the translation unit if a definition was provided, depending on the +instantiation mode). Even though a full instantiation may be done, an external +definition of the instance may or may not be emitted depending on the +instantiation mode.

    +
    +
    +
    +

    13.6.2. Automatically Generated Definitions#

    +
    +

    13.6.2.1. Class Templates#

    +

    The full instantiation of a template class occurs at the first point in the +translation unit where a reference to the instance requires it to be a complete +type. In other words, it is done as soon as necessary, but no sooner. For +example:

    +
    template <class T> class A {};
    +A<int> *p;                   // Partial instantiation of A<int>
    +A<int> a;                    // Full instantiation of A<int>
    +
    +
    +

    The first declaration involving A<int> does not require that it be a +complete type, but the second one does, and so that is the point at which the +full instantiation occurs. At points in the front end where a complete type is +required, the macro complete_class_type_is_needed is invoked, resulting, if +appropriate, in a call to instantiate_template_class to generate the full +instantiation.

    +
    +
    13.6.2.1.1. Partial Specializations#
    +

    A class or variable template may be partially specialized. A partial +specialization is a version of the template that should be used for certain +instantiations. The template to be used is selected based on the template +argument list on which the instantiation is to be based.

    +

    When a full instantiation is required, check_partial_specializations is +called to match the template argument list of the class being instantiated with +each of the partial specializations that have been declared for the template. +matches_partial_specialization is called to perform the actual matching.

    +

    The matching is done using the same process and routines that are used to do +function template argument deduction (see matches_template_type above). If +the template parameters for a given partial specialization can be deduced from +the actual template arguments, then the template class matches the partial +specialization. For example:

    +
    template <class T1, class T2> struct A {};              // #1
    +template <class U1, class U2> struct A<U1*, U2> {};     // #2
    +template <class V1>           struct A<V1, V1> {};      // #3
    +template <class X1>           struct A<X1*, short> {};  // #4
    +A<int, char> a1;  // uses primary template (#1)
    +A<int*, int> a2;  // uses #2
    +A<int, int> a3;   // uses #3
    +
    +
    +

    The declaration of a1 does not match any of the partial specializations, so +the primary template is used. The declaration of a2 matches the partial +specialization labeled #2 because U1 and U2 can be deduced from +<int*, int> (as int and int, respectively). Partial specialization +#3 is used when the two template arguments are the same, as in the declaration +of a3.

    +

    Each partial specialization that matches the argument list is added to a list +of candidate partial specializations using the routine +add_to_partial_order_candidates_list, which compares the new entry with any +entries already on the candidates list. The comparison is done by +is_more_specialized, which determines whether a given partial +specialization is “more specialized” than another. If the entry being added is +not as specialized as an entry already on the list, the new entry is not added. +If the new entry is more specialized than an entry already on the list, that +entry is removed from the list. After all of the partial specializations have +been evaluated, the candidates list contains a set of partial specializations +that match the template argument list of the class being instantiated and which +are unordered relative to one another. If there are no entries on the list, +the primary template is used to generate the class. If there is exactly one +entry on the list, that partial specialization is used to generate the class or +variable. If there is more than one entry on the list, the instantiation is +ambiguous and an error is issued.

    +
    A<int*, int*> a4;  // ambiguous - could be #2 or #3
    +A<int*, short> a5; // uses #4
    +
    +
    +

    The declaration of a5 uses partial specialization #4, even though both #2 +and #4 match. #4 is preferred because it is “more specialized” than #2. +Whether a given partial specialization is more specialized than another is +determined in much the same way in which a partial specialization is determined +to match a given actual template argument list, i.e., though use of the +argument deduction routines. In the example above, if the argument list of #4 +was considered to be the actual argument list and the argument list of #2 was +considered to be the parameter list, the parameters of #2 could be deduced as +U1=X1 and U2=short. If the roles of the two partial specializations +are reversed, making #2 the actual argument list and #4 the formal parameter +list, the type deduction fails. Therefore, #4 is considered more specialized +than #2.

    +
    +
    +
    13.6.2.1.2. Generating the Template Class#
    +

    Once the appropriate template has been selected (i.e., either the primary +template or a partial specialization), the body of the template class is +generated. These are the steps:

    +
      +
    • +
      The pending_instantiations value in the template symbol supplement for +the class template is incremented. This allows the compiler to catch and +report “runaway recursive instantiation,” as the following example would +produce:
      +
      +
      template <int I> class A { A<I+1> a; };
      +A<0> x;
      +
      +
      +
      +
      Once the pending instantiations counter reaches +max_pending_instantiation (a global variable that can be set by a +command-line option, and whose default is defined in lang_feat.h), an +error is issued and the recursion is halted.
      +
      +
    • +
    • +
      push_template_instantiation_scope is called to push a template +instantiation scope onto the scope stack and to do some special processing +for template instantiations:
      +
      +
        +
      • +
        Pointers to the template symbol, the instance symbol, and the template +argument list are recorded in the scope stack entry.
        +
        +
      • +
      • +
        depth_innermost_instantiation_scope is updated with the current scope +stack depth.
        +
        +
      • +
      • +
        update_template_param_symbols is called to bind the symbols for +template parameters to the values in the corresponding template +arguments. For example:
        +
        +
        template <class T, int I> class A {};
        +A<int,0> x;
        +
        +
        +
      • +
      +
      +
      By default the sk_type symbol for template parameter T refers to a +tk_template_param type entry and the sk_constant symbol for I +refers to a ck_template_param constant. But during the instantiation +of A<int,0> – that is, while the template instantiation scope is +active – any reference to T or I should be translated into a +reference to the value of the corresponding template argument, namely, to +int or 0, respectively. This is done by modifying the pointers in +the symbols; the default pointers are restored when the template +instantiation scope is popped.
      +
      +
    • +
    • +
      The cache containing the tokens for class template definition is activated.
      +
      +
    • +
    • +
      scan_class_definition is called. In most respects processing is +identical to the processing for any class definition. The differences have +mainly to do with recording member functions and static data members as +instances:
      +
      +
        +
      • +
        find_corresp_prototype_tag_sym is called to find the symbol for the +prototype instantiation of the class. (When a nested class within a +template class is scanned, the symbol returned is the corresponding +nested class of the prototype instantiation.) That symbol is required for +calling the two routines described next.
        +
        +
      • +
      • +
        find_member_function_template is called for member functions of the +new template class. It locates the template symbol (i.e., the symbol for +the corresponding member function in prototype instantiation), creates a +template instance entry for the new member function, and adds it to the +instantiation list of the template. The template argument list for the +new template class serves for the instance, too.
        +
        +
      • +
      • +
        find_variable_member_template is called for variable templates and +static data members of the new template class. The processing is similar +to what is done for member functions.
        +
        +
      • +
      • +
        find_function_template_member is called for member function templates +of the new template class. The processing is similar to what is done for +member functions.
        +
        +
      • +
      • +
        find_class_template_member is called for member class templates of +the new template class. The processing is similar to what is done for +member functions.
        +
        +
      • +
      • +
        set_nested_template_class_symbol_info is called for nested classes of +the new template class. This call is made by class_specifier when +the nested class is first encountered. The processing is otherwise +similar to what is done for member function.
        +
        +
      • +
      • +
        delayed_scan_fixup_for_class, called at the end of scanning the class +definition, provides somewhat special handling for template classes. For +inline-defined member functions the function bodies are not scanned at +this time; such functions are only instantiated if they are called, so +that errors are not issued on functions that are not actually used. +Also, delayed_scan_for_function_template_default_args is called to +process the default arguments on the function parameters: the token cache +to be used is accessed through the template symbol supplement.
        +
        +
      • +
      +
    • +
    • +
      set_instantiation_required_for_template_class_members is invoked; for +each member function and static data member, both of the template class and +of any classes nested within the template class, it calls +update_instantiation_required_flag.
      +
      +
    • +
    • +
      pop_template_instantiation_scope is called to pop the template +instantiation scope. The template parameter symbols and +depth_innermost_instantiation_scope are restored to the values they had +before the scope was pushed. (Note that the possibility of recursive +instantiation prohibits restoring these values to default values.)
      +
      +
    • +
    • +
      The pending_instantiations value in the template symbol supplement for +the class template is decremented.
      +
      +
    • +
    +
    +
    +
    +

    13.6.2.2. Alias Templates#

    +

    When an instance of an alias template is referenced, find_template_class is +called to look for a previously created template alias or instantiate a new +alias if no previously created instance exists. Template aliases are +instantiated by instantiate_template_alias. Note that unlike class +templates, there are no partial instantiations of alias templates

    +
    +
    +

    13.6.2.3. Function Templates#

    +

    The timing for the instantiation of member and nonmember template functions is +partly controlled by the user (as discussed in the next section). A function +may end up being instantiated

    +
      +
    • +
      at the point of first reference in a given translation unit (e.g., +functions declared inline);
      +
      +
    • +
    • +
      at the end of the translation unit; or
      +
      +
    • +
    • +
      externally to the current translation unit.
      +
      +
    • +
    +

    Wherever it occurs, it is instantiate_template_function that is called to +generate a function body based on a template. These are the steps in the +process:

    +
      +
    • +
      The function’s storage class and name linkage are set, along with its +is_inline flag if required.
      +
      +
    • +
    • +
      The pending_instantiations value in the template symbol supplement is +incremented. As for class templates, this field is used to catch runaway +recursive instantiation.
      +
      +
    • +
    • +
      push_template_instantiation_scope is called to push a template +instantiation scope onto the scope stack.
      +
      +
    • +
    • +
      The token cache is activated.
      +
      +
    • +
    • +
      push_scope is called again to push a function scope onto the scope +stack.
      +
      +
    • +
    • +
      On the basis of the param_id list saved in the template symbol +supplement the function parameters are entered into the symbol table (in +the function scope) by decl_parameter.
      +
      +
    • +
    • +
      For constructors a call is made to ctor_initializer to process the +ctor-initializer list, if any, as well as to do default processing, +and for destructors a call is made to dtor_initializer.
      +
      +
    • +
    • +
      In case a function is being instantiated “on the fly” in the midst of +executable code, the structured statement stack is suspended and a new one +begun by a call to new_struct_stmt_stack.
      +
      +
    • +
    • +
      compound_statement is called to process the tokens comprising the +function body. The IL produced is recorded in the function scope.
      +
      +
    • +
    • +
      If appropriate, restore_struct_stmt_stack is called.
      +
      +
    • +
    • +
      pop_scope is called for the function scope.
      +
      +
    • +
    • +
      pop_template_instantiation_scope is called for the template +instantiation scope.
      +
      +
    • +
    • +
      The pending_instantiations value in the template symbol supplement for +the class template is decremented.
      +
      +
    • +
    +
    +
    +

    13.6.2.4. Variable Templates and Static Data Members of Class Templates#

    +

    instantiate_template_variable is invoked to handle full instantiation of +static data members and for partial and full instantiations of variable +templates. It performs the following:

    +
      +
    • +
      Static data members are marked as defined. Variable templates are marked +as defined if the declaration is a definition.
      +
      +
    • +
    • +
      If an explicit initializer was specified in the static data member template +declaration, then:
      +
      +
        +
      • +
        push_template_instantiation_scope is called to push a template +instantiation scope onto the scope stack.
        +
        +
      • +
      • +
        The token cache is activated.
        +
        +
      • +
      • +
        The type is scanned to determine the type of a template variable, or to +make sure the type agrees with the declaration in the class for static +data members.
        +
        +
      • +
      • +
        For a full instantiation, if a definition is available, initializer +is called to process the tokens comprising the initializer.
        +
        +
      • +
      • +
        pop_template_instantiation_scope is called for the template +instantiation scope.
        +
        +
      • +
      +
    • +
    • +
      If no initializer was specified for a defined variable template or static +data member, def_initializer is called.
      +
      +
    • +
    +
    +
    +
    +
    +

    13.7. Constrained Templates#

    +

    C++20 introduces the notion of “constrained templates”, which is often referred +to as “concepts” (although concepts are just one feature in support of +constrained templates). For example:

    +
    template<typename T> requires(sizeof(T)<4*sizeof(int*))
    +  int hash(T *p);
    +
    +
    +

    Constraints are boolean predicates. In the example above, it’s just a normal +expression. Whenever template instance is considered (e.g., for overload +resolution or for a partial instantiation), its constraint predicates are +substituted and evaluated: If the predicates evaluates to false, the +template is discarded. For functions and partial specializations, that may not +be an error (assuming other candidates satisfy their constraint or are +unconstrained), but other cases will then elicit an error that will indicate +which constraint failed to be satisfied.

    +
    +

    13.7.1. Concepts#

    +

    A constraint expression can be abstracted through a concept template. For +example:

    +
    template<typename T> concept SmallHashable = sizeof(T)<4*sizeof(int*);
    +
    +
    +

    After that definition, the declaration of hash above can instead be rewritten +as:

    +
    template<typename T> requires SmallHashable(T)
    +  int hash(T *p);
    +
    +
    +

    or

    +
    template<typename T>
    +  int hash(T *p) requires SmallHashable(T);
    +
    +
    +

    or

    +
    template<SmallHashable T> int hash(T *p);
    +
    +
    +

    or even

    +
    int hash(SmallHashable auto *p);
    +
    +
    +

    Although concept template are a kind of template, they are not (partially or +fully) instantiated. Instead, they are “substituted” somewhat like function +templates are substituted during the deduction process.

    +

    Concept templates are represented in the IL using a_template entries of +templk_concept kind, and in the symbol table using sk_concept_template +symbols (that point to a_template_symbol_supplement entries with no variant +fields). A templk_concept template points to the predicate, which is +represented as an ordinary expression tree (an_expr_node structure).

    +

    Concept templates can also be “invoked” directly to produce a boolean value. +For example:

    +
    auto cond = SmallHashable<X>;
    +
    +
    +

    Such expressions are represented using enk_concept_id nodes: They point to +a templk_concepta_template entry and, optionally, to a list of +template arguments.

    +
    +
    +

    13.7.2. Representation of constraints#

    +

    As hinted above, there are four possible syntactic locations for constraints:

    +
      +
    • +
      A concept name used to introduce a template type parameter. Such +constraints – called type constraints – are represented as +enk_concept_id nodes pointed to by the +a_template_param_type_supplement associated with the constrained +template parameter. The first template argument for such +enk_concept_id nodes are implied (it’s the template parameter being +constrained) and that is indicated by the is_type_constraint flag in +the enk_concept_id node.
      +
      +
    • +
    • +
      A requires clause following a template<...> header, as in our +original example. Such constrains are represented using +a_requires_clause entries pointed to from a_template_decl, +itself pointed to from a_template. a_requires_clause is itself +mostly a structure pointing to an expression tree.
      +
      +
    • +
    • +
      An implicit template type parameter introduces by a so-called “abbreviated +function template declaration”, as in the example int hash(SmallHashable +auto *p); above. This case is represented very much as the first case +(concept name used to introduce a template type parameter): By having the +associated a_template_param_type_supplement entry point to an +enk_concept_id node representing the constraint. However, in this +case, the a_param_type entry corresponding to the parameter that +introduced the constrained also has the flag is_auto_param set to TRUE.
      +
      +
    • +
    • +
      A trailing requires clause following the function declaration itself, as we +showed in the second variation of our example:
      +
      +
      template<typename T>
      +  int hash(T *p) requires SmallHashable(T);
      +
      +
      +
      +
      This is represented by having the a_routine entry for the prototype +instantiation of the function template point to an entry of type +a_requires_clause. It’s worth noting that this variation of a +constraint can also be applied to ordinary member functions of class +templates (hence the need to point to it from an a_routine entry rather +than a template-specific entry).
      +
      +
      +
      To ease the description of constraints, C++20 also introduces +requires-expressions (not to be confused with requires-clauses, +which were described above). For example:
      +
      +
    • +
    +
    template<typename T> void f() {
    +  bool b = requires { typename T::node; };
    +}
    +
    +
    +

    Such expressions are represented by an enk_requires node, which points to a +list of expression nodes: Entries on that list that are of kind +enk_type_operand, enk_compound_req, and enk_nested_req are of +special significance. See il_def.h and expr.c for details.

    +
    +
    +

    13.7.3. Important Constrained-Template Functions#

    +

    The following are some functions that are central to the handling of +constrained templates:

    +
      +
    • +
      scan_requires_clause and scan_concept_expression (both in +expr.c). These are the functions that parse constraint expressions, +which requires special treatment of the logical operators (&& and +||).
      +
      +
    • +
    • +
      scan_requires_expr (expr.c), which parses requires-expressions.
      +
      +
    • +
    • +
      check_template_constraints (templates.c), which determines if a +given template’s constraints are satisfied by a given set of template +arguments.
      +
      +
    • +
    • +
      requires_clause_satisfied (exprutil.c). This function performs +substitution of constraint expression, which is subject to various subtle +rules. It leans heavily on the expression rescanning facilities (see +Rescanning Expressions).
      +
      +
    • +
    • +
      compare_constraints (exprutil.c). When determining the partial +order of function templates or partial specializations, constraint can play +a special role. This function, is the main function for comparing the +constraints on templates (to determine whether a template is more or less +constrained than another, or maybe neither is more constrained than the +other). The algorithm for this comparison is relatively complex and +described in great detail in exprutil.c.
      +
      +
    • +
    +
    +
    +
    +

    13.8. Managing Instantiation of Functions, Variables, and Static Data Members#

    +

    As noted previously, the full instantiation of template classes occurs as soon +as necessary, but no sooner. The timing for the automatic instantiation of +template functions, variables and members of template classes is more +complicated.

    +

    For example, if a member function of a template class is not referenced, +there is no reason to instantiate it. But even if it is referenced, its +instantiation may occur elsewhere. The EDG C++ front end supports several +methods whereby the user can manage the instantiation of templates: +automatic instantiation, instantiation modes that are specified on the +command line, and explicit instantiation directives included in the source +code of the program. Explicit instantiation directives are supported in +both the form specified by the C++ standard and as #pragma directives. +For a detailed description of how the instantiation modes and pragmas are +used, see Template Instantiation.

    +

    The instantiation_required flag in template instance entries is set to +indicate that a function, variable, or static data member has been referenced +in such a way as to require its definition (i.e., full instantiation) somewhere +in the program, even if not in the current translation unit. For example, +calling a template function causes the flag to be set.

    +

    update_instantiation_required_flag is called to set the flag and to place +the instance on a linked list (see add_to_instantiations_required_list) so +that it can be readily found later, when the actual instantiation is done. +Sometimes the routine to do full instantiation is called immediately, however +(e.g., for calls to template functions that are declared as inline or when +in the midst of instantiation wrapup processing); in such cases the instance is +not placed on the list.

    +

    It is do_any_needed_instantiations, called by +template_and_inline_function_wrapup, as part of the fe_wrapup process, +that goes through the instantiations_required list. It determines for each +instance whether full instantiation is actually required in the current +translation unit as a result of the instantiation mode being used, explicit +instantiation and #pragma directives found in the program (see +should_be_instantiated, which checks instantiation modes and directives), +and whether the instantiation has been assigned to the current translation unit +by the automatic instantiation mechanism. It then will call +instantiate_entity, if appropriate.

    +

    Instantiations are normally generated as part of the object file of the +translation unit in which the instantiations are performed. But when “one +instantiation per object” mode is specified, each instantiation is placed in +its own object file, and the names of those object files are written to the +template information file (which is described below). One instantiation per +object mode is useful when generating libraries that need to include copies of +the instances referenced from the library. If each instance is not placed in +its own object file it may be impossible to link the library with another +library containing some of the same instances. Without this feature it is +necessary to create each individual instantiation object file using the manual +instantiation mechanism.

    +
    +

    13.8.1. Automatic Instantiation#

    +

    The EDG C++ front end provides a complete prototype implementation of an +automatic instantiation mechanism. The EDG automatic instantiation mechanism +is a “linker feedback” mechanism. It works by providing additional information +in the object file that is used by a “prelinker” to determine which template +entities require instantiation so that the program can be linked successfully. +Unlike most aspects of the front end the automatic instantiation mechanism is, +by its nature, dependent on certain operating system and object file format +properties. In particular the prelinker is a separate program that makes use +of the UNIX nm command to access information about the symbols defined in +object files. Furthermore it relies on features implemented in the eccp +driver script. Consequently, this code should be viewed as a sample +implementation that may need adaptation to work on other systems.

    +

    This section describes the steps involved in automatic instantiation. The +steps are described in the sequence in which they would occur while compiling +and linking an application and not necessarily the sequence in which they occur +in a given execution of the front end. While one might expect the two +sequences to be the same the automatic instantiation mechanism may, in fact, +compile a given file a number of times while determining the set of +instantiations that are needed to link the application.

    +
    +

    13.8.1.1. Initial Compilation#

    +

    When a program is compiled, the front end generates a set of flags that are +provided to the back end and are ultimately either output as a separate file by +the front end or are encoded in some form in the generated object file. The +flags are stored in the IL variable and routine entries.

    +
      +
    • +
      The can_be_instantiated flag indicates that this translation unit is +capable of generating an instantiation for a given function, variable, or +static data member (hereafter referred to as a “template entity”). This is +used by the prelinker to determine which source files are possible +instantiation sites for the template entity. This flag is set even if the +translation unit provides an instantiation of the template entity.
      +
      +
    • +
    • +
      The instance_required flag indicates that a definition of the template +entity must be supplied by some translation unit (but not necessarily this +one). Both the instance_required and the can_instantiate flags +indicate that the entity is one that can potentially be defined by a +generated template instantiation. This information allows the prelinker to +distinguish between an unresolved template reference and a plain undefined +symbol. These flags are also used by the prelinker to distinguish class +specializations, whose members cannot be defined by generated +instantiations, from regular template classes whose members may be defined +by generated instantiations.
      +
      +
    • +
    • +
      The do_not_instantiate flag indicates that instantiation of the +template entity has been explicitly prohibited by use of the +do_not_instantiate#pragma directive. When automatic +instantiation is used, the do_not_instantiate pragma prohibits +instantiation not only in the file in which the pragma was included but +anywhere within the application with which the resulting object file is +being linked.
      +
      +
    • +
    +

    In the default configuration, these flags are written to the template +information file, which is descibed below. In earlier versions of the front +end these flags were translated by IL lowering into tentative definitions of +specially named symbols. The old behavior can be selected using the +INSTANTIATION_FLAGS_IN_TEMPLATE_INFO_FILE configuration flag. The flags +were removed from the object file because the amount of space consumed by the +names of the flags could be excessive, because the mangled names of template +entities can be very long. When the flags are generated as part of the object +file, the symbol names include a code that indicates the flag kind and also +includes the name of the symbol being described. The special symbol includes a +prefix of __CBI__ (can be instantiated), __TIR__ (template instance +required), or __DNI__ (do not instantiate) followed by the mangled name of +the entity. For example, a template function of type void f(int) could +have the following flags generated.

    +
    __CBI__f__fi__TIR__f__fi__DNI__f__fi``
    +
    +
    +

    Because they are generated as tentative definitions, they may each appear in +any or all of the object files being linked into an application while only +appearing once in the generated executable file

    +

    When a template class contains noninline virtual functions, the instantiation +mechanism must ensure that the virtual function table is defined. IL lowering +does this by generating a “template instance required” flag for the first +noninline virtual function of any template class, because it’s the presence or +absence of a definition for that function that controls whether or not IL +lowering puts out a definition for the virtual function table. By requiring +the first noninline virtual function to be defined we ensure that the virtual +function table will also be defined

    +
    +
    +

    13.8.1.2. The Template Information and Instantiation Request Files#

    +

    Information is exchanged between the front end and prelinker using the +“template information” and “instantiation request” files. These files are also +known respectively as the .ti and .ii files [1]. The template +information file is used for infomation produced by the front end for use by +the prelinker. The instantiation request file is produced by the prelinker for +use by the front end. The template information file was added in version 2.37 +of the front end to support features such as one-instantiation-per-object mode, +and generation of instantiation flags in a separate file instead of the object +file. The front end can be configured to not use a template information file +in order to be compatible with earlier versions of the front end, but this +requires that the features that use the template information file be disabled.

    +

    The template information file provides several diferent kinds of information to +the prelinker. Each line of the file contains a type code followed by a +string. The type code indicates the type of information being provided. The +following types of lines are generated by either the front end or driver:

    +
      +
    • +
      cmd: command line (supplied by the driver)
      +
      +
    • +
    • +
      dir: compilation directory (supplied by the driver)
      +
      +
    • +
    • +
      fnm: compilation file name (supplied by the driver)
      +
      +
    • +
    • +
      idn: instantiation directory (in one-instantiation-per-object mode, +supplied by the driver)
      +
      +
    • +
    • +
      flg: instantiation flags (when not encoded in the object file)
      +
      +
    • +
    • +
      ifn: instantiation file names (in one-instantiation-per-object mode)
      +
      +
    • +
    • +
      stu: secondary translation units (supplied by the driver)
      +
      +
    • +
    • +
      tnm: export templates defined in this file
      +
      +
    • +
    • +
      dep: dependency information when exported instantiations have been +generated
      +
      +
    • +
    +

    The order in which these are specified is not, in general, significant except +that the prelinker currently requires that the instantiation directory entry +precede any instantiation file name entries.

    +

    The template information and instantiation request files have the same base +name as the source file, but use special suffixes specified by configuration +parameters in host_envir.h, with the default values indicated above.

    +

    At the end of each compilation the front end determines whether any template +entities were referenced in the translation unit. If so a template information +file is created (or an instantiation request file, if template information +files are not being used). If no template entities were referenced in the +translation unit the file will not be created and any existing file will be +removed. When template information files are being used, the instantiation +request file is also removed if the template information file is removed.

    +

    After invoking the front end the driver checks for the existence of either the +template information or instantiation request file, depending on the +configuration. If one exists, the driver updates it with the command line used +to compile the source file, the name of the current directory when the +compilation was done, and the name of the file that was compiled. This +information is used later if the prelinker needs to recompile the file.

    +
    +
    +

    13.8.1.3. Prelinker#

    +

    Once a complete set of object files has been generated, including the +appropriate flags, the prelinker is invoked to determine whether any new +instantiations are required or if any existing instantiations are no longer +required. The command line arguments to the prelinker include a list of input +files to be analyzed. The input files are the object files and libraries that +constitute the application. The prelinker begins by looking for template +information files for each of the object files (or instantiation request files, +if template information files are not being used). If no template information +(or instantiation request) files are present, the prelinker concludes that no +further action is required.

    +

    If there are template information (or instantiation request) files, the +prelinker reads the template information file and the current instantiation +list from the instantiation request file. The instantiation list is the list +of instantiations assigned to a given source file by a previous invocation of +the prelinker. The prelinker uses the UNIX nm command to produce a list of +the global symbols that are referenced or defined by each of the input files. +The prelinker then simulates a link operation to determine which symbols must +be defined for the application to link successfully.

    +

    When the link simulation has been completed, the prelinker processes each input +file to determine whether any new instantiations should be assigned to the +input file or if any existing instantiations should be removed. The prelinker +goes through the current instantiation list from the instantiation request file +to determine whether any of the existing instantiations are no longer needed. +An instantiation may be no longer needed because the template entity is no +longer referenced by the program or because a user supplied specialization has +been provided. If the instantiation is no longer needed, it is removed from +the list (internally; the file will be updated later) and the file is flagged +as requiring recompilation.

    +

    The prelinker then examines any symbols referenced by the input file. The +responsibility for generating an instantiation of a given entity that has not +already been defined is assigned to the first file that is capable of +generating that instantiation.

    +

    If a given file contains instantiations of exported templates, the template +information file contains dependency information. If a source file that is +part of an exported template translation unit changes, the dependency +information is used to detect such a change so that the prelinker can recompile +the file and regenerate the instantiations of the exported templates.

    +
    +
    +

    13.8.1.4. Recompilation#

    +

    Once all of the assignments have been updated, the prelinker once again goes +through the list of object files. For each, if the corresponding instantiation +request file must be updated, the new file is written. Only source files whose +corresponding instantiation request file has been modified will be recompiled.

    +

    At this point the combination of the template information and instantiation +request files contains the information needed to recompile the source file, and +a list of instantiations assigned to the source file (in the form of mangled +function, variable and static data member names).

    +

    Then, during recompilation the front end reads the entries from the +instantiation request file produced by the prelinker and checks them against +entries on its own “instantiations required” list. Whenever a match is found, +based on comparing the mangled name from the instantiation request file and the +name returned by either get_mangled_function_name or +get_mangled_variable_name (in lower_il.c), the +automatically_instantiated flag is set in the template instance entry.

    +

    When the prelinker invokes the front end, it provides a “definition list file”, +which contains a list of all the external definitions found in the object files +and libraries specified on the prelinker command line. The front end reads the +definition list file and determines whether each of the entries on its +instantiations required list has already been defined elsewhere. If an entity +is found that is not defined elsewhere, its automatically_instantiated flag +is set.

    +

    Later, in instantiation_wrapup, instantiations will be generated for all +instances for which the automatically_instantiated flag is set, whether as +a result of being included in the instantiation request file or “adopted” by +the front end when it was determined that the instance was not defined +elsewhere. A list of the entities adopted by the front end is written to the +definition list file. This list is used by the prelinker to add the adopted +entities to the adopting translation unit’s instantiation request file.

    +

    The definition list file permits the front end to perform instantiations that +have become necessary as a result of other instantiations that were assigned by +the prelinker, without requiring that the prelinker invoke the front end an +additional time to perform those instantiations. This reduces the number of +iterations of the prelinker and front end that are required to generate a +complete set of instantiations for a program.

    +

    If an error occurs during a recompilation, the prelinker exits without updating +the remaining information files and without attempting any additional +compilations.

    +
    +
    +

    13.8.1.5. Iteration and Termination#

    +

    If all recompilations complete without error, the prelink process is repeated, +since an instantiation can produce the demand for another instantiation. This +prelink cycle (finding uninstantiated templates, updating the appropriate +instantiation request files, and dispatching recompilations) continues until no +further recompilations are required. [2]

    +

    When the prelinker is finished, the linker is invoked. Note that simply +because the prelinker completes successfully does not assure that the linker +will not detect errors. Unresolvable template references and other linker +errors will not be diagnosed by the prelinker.

    +

    In many cases, once the application has been successfully linked, the +recompilation overhead will have become a one-time-only expense, because the +next time the source file is compiled, the instantiation request file will +provide precisely the right list of instantiations to be done. Recompilation +will be required again only if the instantiation request file is invalidated, +that is:

    +
      +
    • +
      if additional instantiations come to be needed (in this or another file);
      +
      +
    • +
    • +
      if existing instantiations are not longer referenced;
      +
      +
    • +
    • +
      if a different set of command-line options is used to compile the file; or
      +
      +
    • +
    • +
      if the instantiation request file is deleted.
      +
      +
    • +
    +

    Except in such cases, once the complete set of instantiation request files has +been generated, the prelinker should not need to force recompilation for any +source files in the application.

    +
    +
    +

    13.8.1.6. Implementing Alternative Automatic Instantiation Mechanisms#

    +

    The default automatic instantiation implementation uses the instantiation +request file as described above. The routines in templates.c are designed +to permit an alternative mechanism to be used (e.g., querying a database) to +determine whether a given entity should be instantiated. This may be done by +modifying the following routines:

    +
      +
    • +
      init_auto_instantiation_information is called at the beginning of the +automatic instantiation processing. The default version calls +read_auto_instantiation_information, which opens the instantiation +request file and reads its contents.
      +
      +
    • +
    • +
      check_if_entity_should_be_automatically_instantiated is called for each +instantiatable entity (external function, variable, or static data member). +It sets the automatically_instantiated flag if the entity is to be +instantiated in this translation unit, and the add_to_request_file flag +if the instantiation was “adopted” by this translation unit and must be +added to the instantiation request file by the prelinker. The default +version calls check_if_present_in_request_file to determine whether the +specified entity was named in the instantiation request file and/or the +definition list file.
      +
      +
    • +
    • +
      wrapup_auto_instantiation_information is called by fe_wrapup. The +default version calls create_or_remove_instantiation_information_file +and close_or_remove_template_info file.
      +
      +
    • +
    +
    +
    +
    +

    13.8.2. Instantiation Modes#

    +

    The instantiation mode is specified by a command line option and determines +whether the compiler should automatically generate instances of template +entities (function templates, variable templates, member function of template +classes, and static data members of template classes.) The command line option +is used to set the global variable instantiation_mode to one of the +following values:

    +
    + + + + + + + + + + + + + + + +
    +
    tim_none
    +
    +
    +
    Do not automatically create instantiations of any template entities. +This is the default.
    +
    +
    +
    tim_used
    +
    +
    +
    Instantiate those template entities that were used in the compilation. +This will include all static data members for which there are template +definitions.
    +
    +
    +
    tim_all
    +
    +
    +
    Instantiate all template entities declared or referenced in the +compilation unit. For each fully instantiated template class, all of +its member functions and static data members will be instantiated +whether or not they were used. Nonmember template functions will be +instantiated even if the only reference was a declaration.
    +
    +
    +
    tim_local
    +
    +
    +
    Similar to tim_used except that the functions are given internal +linkage. This is intended to provide a very simple mechanism for +those getting started with templates. The compiler will instantiate +the functions, variables and static data members used in the +compilation as local (static) functions and local (static) variables.
    +
    +
    +
    +

    Inline functions are usually instantiated when they are first referenced, and +so unreferenced inline functions are usually not instantiated. However, in +tim_all mode they are always instantiated – either during +instantiation_wrapup or, for member functions for which the body is +supplied in the class template definition, when the class is instantiated.

    +
    +
    +

    13.8.3. #pragma Directives#

    +

    There are three instantiation pragmas, instantiate, which causes the +specified entity to be instantiated, do_not_instantiate, which causes +instantiation of the specified entity to be suppressed, and +can_instantiate, which indicates that the specified entity can be +instantiated by an automatic instantiation mechanism, but need not be. [3] +The do_not_instantiate pragma is typically used with the manual +instantiation mechanisms when a specific definition will be supplied elsewhere.

    +

    The argument to the instantiation pragmas may be a template class name, a +member function name, a variable name, a static data member name, a member +function declaration, a function declaration, an elaborated type specifier for +a class, or a static data member declaration. When a class name or elaborated +type specifier is specified, the directive is applied to all member functions +and static data members of the class.

    +

    Processing the pragmas results in setting some flags in the template instance. +They are later checked by should_be_instantiated (called from +instantiation_wrapup) to determine whether the entity requires full +instantiation. The instantiate pragma sets the instantiation_required +and explicit_instantiation flags and records the current source position +(for reporting errors later). The do_not_instantiate pragma clears +instantiation_required and sets specific_def to block instantiation +based on the instantiation mode.

    +

    Explicit instantiations are processed by instantiation_wrapup in much the +same way as instantiations that may be generated depending on the instantiation +mode. The only difference is that certain conditions that are ignored for +nonexplicit instantiations cause errors to be issued for explicit +instantiation. If no template definition has been supplied from which to +generate an instantiation, an error is issued for explicit instantiation +requests. Likewise, if a specific definition has been supplied and an explicit +instantiation was requested, an error is also issued.

    +
    +
    +

    13.8.4. Explicit Instantiation Directives#

    +

    Explicit instantiation directives are processed in nearly the same way as +instantiation pragmas. The differences between the handling of the +instantiation pragma and an explicit instantiation directive are as follows:

    +
      +
    • +
      Inline functions may be specified in explicit instantiation directives, +even though doing so is meaningless.
      +
      +
    • +
    • +
      An entity may not appear in more than one explicit instantiation directive.
      +
      +
    • +
    • +
      Explicit instantiation directives require that a declaration follow the +template keyword, while the instantiation pragmas permit a simple name +to be specified.
      +
      +
    • +
    +
    +
    +

    13.8.5. Implicit Inclusion#

    +

    In the cfront model of programming with templates the template +declarations are placed in a header (e.g., “.h”) file while the +definitions of noninline functions and static data members are placed in a +source (e.g., “.c”) file. To support this style of programming the +front end provides an optional “implicit inclusion” feature. When this +feature is enabled, the front end will implicitly include a source file +when needed to provide definitions of template entities declared in a given +header file.

    +

    When a header file is included, information about the kind of include statement +used is stored in the IL source file structure. This specifies whether the +include statement was a “normal” include (e.g., #include "file.h") or a +system include (e.g., #include <file.h>).

    +

    At the end of compilation, during instantiation wrapup processing, the source +file associated with a given header file will be included if needed. A file is +“needed” if an instantiation of an entity is required as a result of a command +line option, pragma directive, or instantiation list file. In automatic +instantiation mode implicit inclusions of template definition files will +essentially always be done so that accurate “can be instantiated” flags may be +generated.

    +

    The implicit inclusion is done by searching through each of the directories in +the appropriate search path list (based on the kind of include statement used +to include the header file). A configuration parameter specifies a list of +file suffixes to be used during the search for a file to be implicitly +included. In each directory on the search path each of the possible suffixes +will be tried in sequence. If no matching file is found, the next directory in +the list is used. If no matching file is found in any directory, no error is +reported (unless the instantiation was explicitly requested using an +instantiate pragma in which case an error will be issued indicating that no +template definition was supplied).

    +
    +
    +

    13.8.6. Instantiating Non-Template Inline Functions#

    +

    The front end provides two implementations of C++``extern inline`` functions, +referred to as “lower extern inline” and “instantiate extern inline”. The +“lower” version is the default, and causes extern inline functions to be +translated into static functions with special care taken to ensure that +entities such as local static variables have the proper semantics. (See the +comments on the definition of INSTANTIATE_EXTERN_INLINE in targ_def.h +for the advantages and disadvantages of each implementation.)

    +

    The “instantiate” version, which is enabled by setting the +INSTANTIATE_EXTERN_INLINE configuration flag, ensures that only a single +external out-of-line copy of the inline function is generated, and then only if +one is required by the program. The automatic template instantiation mechanism +is used to implement this mechanism.

    +

    When an inline function is defined, add_to_inline_function_list is called +to add the function to a list of all of the inline functions in the translation +unit. During the wrapup processing at the end of the compilation, +inline_function_wrapup uses the inline function list to determine which +inline functions should have their bodies emitted as part of this compilation. +The suppress_inline_body flag in the routine entry is cleared if a back end +should emit an out-of-line body of an inline function. +update_inline_function_flags emits instantiation flags as is done for +template entities. The prelinker will then assign the “instantiation” of +inline functions for which out-of-line bodies are required.

    +
    +
    +
    +

    13.9. Exported Templates#

    +

    The C++ standard specifies that the definition of certain templates (static +data members and non-inline functions) can be separately compiled. This +feature is generally referred to as “export” as such templates are declared +using the export keyword. The definition of an exported template is +provided in a single translation unit. Other translation units that use the +template require only a declaration of the template.

    +

    Exported templates require special processing not needed for normal +(non-exported) templates:

    +
      +
    • +
      When the definition of an exported template is encountered, a record of the +translation unit containing the exported template must be made so that the +definition can be found later when an instantiation is needed.
      +
      +
    • +
    • +
      When an instantiation of an exported template is generated, the front end +must be able to search for a definition of the template.
      +
      +
    • +
    • +
      Generating an instantiation of an exported template requires that the front +end have access to information about the translation unit containing the +template definition and the translation unit containing the reference. One +exported template may call another, which may call another, and so on. As +a result, the front end must be able to simultaneously process an arbitrary +number of translation units at the same time (see Multiple Translation Units).
      +
      +
    • +
    • +
      Whenever a partial or full instantiation of an entity must be done, the +front end must update its context information so that the translation unit +containing the template is the current translation unit +(see Initialization, Termination, and Keeping Translation Units Separate).
      +
      +
    • +
    +

    When an exported template is defined, information about the definition must be +recorded. add_to_exported_templates_list is called when an exported +definition is encountered. This information is used at the end of the +compilation to create a file that provides a list of the exported templates +defined in the translation unit. This file is known as the “exported template” +file and, by default, has a suffix of .et. The following is an example of +an exported template file:

    +
    fnm:t.c
    +tnm:f__tm__4_Z1Z__FZ1Z_v
    +tnm:f2__tm__4_Z1Z__FZ1Z_v
    +mid:t_c_ee131b0b
    +def:XXX=3
    +und:YYY
    +end:
    +
    +
    +

    The following types of lines appear in such a file:

    +
      +
    • +
      fnm: The name of the primary source file to be used when reloading the +translation unit.
      +
      +
    • +
    • +
      tnm: The mangled name of a template defined in the translation unit.
      +
      +
    • +
    • +
      mid: The module ID to be used when instantiating templates from the +file.
      +
      +
    • +
    • +
      def: A command-line macro definition to be used when reloading the +translation unit.
      +
      +
    • +
    • +
      und: A command-line macro un-definition to be used when reloading the +translation unit.
      +
      +
    • +
    • +
      end: The end of the entries associated with the previous fnm: +entry.
      +
      +
    • +
    +

    The information for a given file always begins with “fnm:” and ends with +“end:”. This makes it possible to concatenate a group of exported template +files together, which is useful when creating a library that defines exported +templates.

    +

    When the front end compiles a file that makes use of exported templates, a +search path of exported template directories is used to locate the file that +defines a given exported template. The entries on the search path are +specified with the --template_directory command-line option. The front end +searches each of the directories in the search path to find any exported +template files that exist there. Each of the exported template files is read +to determine which exported templates are defined, and the name of the file +that defines each template. An exported template directory can also contain a +file named export_info, which provides information used when reloading +exported template translation units. The export info file contains the include +search path to be used when reloading a translation unit. If no export info +file is present, the include search path associated with the primary +translation unit is used.

    +

    A translation unit may contain entities that must be given unique names (e.g., +unnamed namespace members). A “module ID” is used as part of the name in such +cases to ensure that the name is unique. The instantiation of an exported +template must be able to refer to, and generate additional, entities with +appropriate unique names. To accomplish this, the module ID is saved in the +exported template file and that module ID is re-used when the translation unit +containing the exported template definitions is reloaded.

    +

    When an exported template translation unit is reloaded, it undergoes what is +basically the normal compilation process, except that none of the external +entities defined in the translation unit are emitted. Only the instantiations +of exported templates, and other templates or inline functions referenced as a +result of such instantiations (directly or indirectly) are emitted. The +entities that are emitted are copied into the IL of the primary file being +compiled (see Copying from Secondary Translation Units). The command-line options used when the +exported template translation unit is loaded are the same options used to +compile the primary translation unit. The only exceptions are command-line +macro definitions/undefinitions, and the include search path to be used. The +command-line macro definitions/undefinitions are saved in the exported template +file, and those values are used when the exported template translation unit is +loaded (include search path handling is described above).

    +

    A mangled name is generated for each exported template. It is this mangled +name that is used to match a reference to an exported template with the +definition found elsewhere. A hash table of exported template definitions is +built as the exported template files are read. When an instantiation is +needed, the mangled name is looked up in the hash table to see if a definition +is available. If a definition is available, process_translation_unit is +called to load the translation unit that defines the exported template.

    +

    A template instance entry is created for each function, variable, or static +data member instance that is partially or fully instantiated. If a given +instance is declared in more than one translation unit, there will be multiple +template instance entries created. In addition, a “master instance” entry is +created to represent the information that is shared among translation units. +For template instances in the primary translation unit, the master instance is +created when the template instance is added to the instantiation required list. +For template instances in secondary translation units, the correspondence +information is used to find a master instance entry that may have been already +created for an earlier translation unit. Because the correspondence +information is not set until a translation unit has been completely scanned, +the master instance information cannot be established until after scanning has +completed. The master instance entry points to the template instance entry +associated with the canonical copy of the instance (see +Canonical Entries). Each template instance contains a pointer to the +associated master instance.

    +

    Instantiations of exported templates are generated during the “instantiation +wrapup” process, which is performed by template_and_inline_function_wrapup. +The instantiations required list for each translation unit is examined, and +instantiations are generated if appropriate. An instantiation in one +translation unit may result in the need for an instantiation in another +translation unit. Because the other translation unit may already have been +processed, the wrapup process must iterate over the set of translation units +until no additional instantiations are added for during an iteration.

    +

    The instantiation of a function, variable, or static data member is initiated +by calling instantiate_entity with the template instance entry of the +instance to be generated. For exported templates defined in other translation +units, the translation unit is loaded and find_corresponding_instance is +called to find or create the template instance entry in the exported template +translation unit that corresponds to the one for which the instantiation is +being generated. The corresponding instance is then used for the remainder of +the instantiation process.

    +

    A “translation unit stack” is maintained when instantiating an entities defined +in other translation units. This stack serves two purposes: it provides a +sequence of lookup contexts for resolving dependent function names during the +instantiation process, and it provides a record of the translation unit +switches that have taken place so that the prior translation unit state can be +restored when an instantiation has completed.

    +
    +
    +

    13.10. C++/CLI Generics#

    +

    C++/CLI generics are sort of like templates, and sort of not. They have +arguments, but the arguments are more constrained than for templates, being +effectively only managed class types or handles to them, value classes, +fundamental types, or scoped enum types. (And types only: No nontype +arguments, no template template arguments.) In addition, generics can have +user-written constraint clauses that further restrict the valid argument values +to certain kinds of class types. Generic classes do get instantiated for each +set of template arguments, much like template classes, but generic functions +effectively have just one instantiation, which corresponds to a single routine +body that can operate on all types. That’s possible because the function can +only perform those operations that are valid based on the declared constraints. +That allows the instantiation of generic functions to be delayed until runtime +and for most references to share a single instantiation (for example, all +instantiations based on handles to ref classes share a single instantiation at +runtime). That in turn forces some restrictions on the code that can be +written in generic functions.

    +

    Generics are represented as templates marked with the is_generic_definition +flag in the class type or routine entry. If they have constraints, those are +represented by entries of type a_generic_constraint and +a_generic_constraint_clause.

    +

    Generic classes and generic functions don’t get the standard prototype +instantiations. Instead, they undergo a process similar to prototype +instantiation (and kicked off by the same routine that does prototype +instantiations) using invented types based on the constraints. The result is +marked as a “generic definition” instead of a prototype instantiation. The +same process applies to static data members as well.

    +

    During the generic definition instantiation, a “constraint type” is created for +each generic parameter. It is a class type that reflects the constraints, +e.g., if the generic parameter is required to be derived from a class X, the +constraint type has X as a base class. The constraint type is a real type (not +a nonreal type), and lookups can be done in it. Such lookups in fact +significantly define what can be done with an object of that generic parameter +type, in the sense, for example, that a “+” operation can be done only if a +lookup finds an appropriate “operator+” function in the constraint type.

    +

    The actual type that is used for a given generic parameter type during the +generic defintition instantiation is known as the “generic definition argument +type.” It is a handle to the constraint type except in cases when the generic +parameter is constrained to be a value class type, in which case it is the same +as the constraint type.

    +

    During the generic definition instantiation, the template parameter symbols for +the generic are set to the generic definition argument type. That makes a lot +of processing, in declarations and expressions, work out fine without special +handling: uses of the template parameter name produce the generic definition +argument type, and for the most part that that can be processed without +difficulty. In particular, the generic definition argument type is not a +dependent type, and therefore real types can be built (instead of unknown +template parameter types), real results of overload resolution can be +determined, etc. However, there are also cases where one wants to think of the +type as being the generic parameter type. There’s a duality here: the template +parameter type and the generic definition argument type are really equivalent +types, and sometimes we want one and sometimes the other. We chose to make the +default value be the generic definition argument type, because that seemed to +work out better in terms of requiring less special-case code, but whichever way +we had decided that there would be cases that wanted to look at the type the +other way. Fortunately, because the types point to each other, it’s easy to +flip to the other representation if one has the wrong one. See, for example, +generic_param_if_generic_definition_argument.

    +

    Because the rules for valid generic template arguments are different than those +for normal template arguments, a special routine is used to scan generic +template argument lists: scan_generic_argument_list. It calls +is_valid_generic_argument to check that each argument is valid for any +kind of generic. Later, when one has a full set of generic type arguments +(whether from an explicit list or through type deduction), +verify_generic_arg_list_satisfies_constraints is called to check that the +arguments satisfy their constraints.

    +

    Generic classes can overload on arity, meaning that there can be multiple +generic classes with the same name, but differing numbers of type arguments, +declared in the same scope. That is not valid in source code, but it does come +up in libraries written in other languages and imported via metadata. When +such overloading occurs, the first generic that is declared is what is entered +into the symbol table and what is returned by lookup. The template symbol +supplement for that symbol has a pointer to a list of any other generic classes +with the same name and different arities in the same scope. If there is also a +non-generic class in the same scope, it is pointed to by another pointer there. +With this information, references to the name can be resolved to the proper +instance of the generic or to the non-generic.

    +

    Template deduction for generics is done in the usual way; there are no special +tricks to speak of.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/testing/index.html b/doc/testing/index.html new file mode 100644 index 0000000..6b71551 --- /dev/null +++ b/doc/testing/index.html @@ -0,0 +1,1115 @@ + + + + + 26. EDG Testing Framework - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    26. EDG Testing Framework#

    +

    The EDG front end testing framework is fundamentally based on process exit +codes and recorded “expected output.”

    +
    +

    26.1. Writing a Test File#

    +

    Test files are written using a series of directives at the start of the test +file.

    +

    The following is a sample single-file test (the common case) to help illustrate +some of the features described below:

    +
    //remark:Simple friend functions in class template
    +//options::;cn
    +template <class T> class A {
    +  friend int f(A);
    +  int     i;
    +};
    +
    +A<int>  a;
    +
    +int f(A<int> a) {
    +  return a.i;     // Should be OK
    +}
    +
    +#if TEST_NUMBER==2
    +int f(A<int> a, int i) {
    +  return a.i;     // No access -- should fail
    +}
    +#endif
    +
    +
    +
    +

    26.1.1. Single-file Testing#

    +

    Individual test files end in either .sft.c or .sft.cpp depending on +the programming language being tested. The testing directives that can be +used in a single-file test are enumerated below. Additional directives +have meaning in multi-file tests and are described in Multi-file Testing.

    +
    +
    +
    //remark:A string that gets printed on the output
    +
    //type:xx
    +
    //name:xxx
    +
    //options:-a:-b=xx:-c=
    +
    //options_all:-A
    +
    //options_sep:x
    +
    //match_regex:regular expression
    +
    //cases:n
    +
    //eccp_command:compile-command
    +
    //ulimit:options
    +
    //linker_options:options
    +
    //execution_args:command line arguments
    +
    //use_system_includes:true/false
    +
    //edg_header_pack:string
    +
    //require:string
    +
    //filter:pipe-command
    +
    +
    +

    xx is a type identifier. The accepted values are:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Identifier

    Meaning

    fn

    front end only negative

    fp

    front end only positive

    fc

    front end - expect catastrophic error

    cn

    compile negative

    cp

    compile positive (including compiling generated C) - DEFAULT

    cc

    compile - expect catastrophic error

    ln

    compile and link negative

    lp

    compile and link positive

    rn

    runtime negative

    rp

    runtime positive

    ra

    runtime - expect abort

    cppbe

    a special C++-generating back end only mode that dumps the +generated code for review and validation

    s

    skip the test

    +
    +

    Positive tests expect a return code of zero. Negative tests expect a +non-zero return code.

    +

    The //name: directive specifies the name to be used when the file is +compiled. This is useful for tests that need to test platform support for +Unicode file names and similar file name-dependent scenarios.

    +

    The //options: directive specifies a set of command line options to be +used, separated (by default) by colons. The compiler will be invoked once +for each set of options. An option set can override the type specified by +appending the optional string ;xx on the end of an option +specification.

    +

    If the options need to include a colon, the //options_sep: directive +can be used to specify a different separator. For example, +//options_sep:! will change the separator to !. The separator can +be multiple characters.

    +

    The //options_all: directive specifies a set of command line options +that will be provided on every compilation. This is useful for tests with +a single case and for options that don’t vary from case to case. This may +be used in conjunction with the //options: directive. The options from +each option set are put in the command line after the //options_all: +string so that they can override values in the //options_all: string.

    +

    The //match_regex: directive allows specification of a regular +expression (expressed in the Python regex dialect) that must be found in +the output for the test to pass. Matches will additionally add sections to +the captured output highlighting the matching lines (thus serving as a +further sanity check against unintended changes). This directive is +particularly useful if wanting to require fine grained details like +specific diagnostics, IL output fragments, or generated C++ code (when +using a cppbe test).

    +

    The //linker_options: directive specifies an additional set of options +that are placed at the end of the command used to compile and link the +program and is intended to be used for library names.

    +

    The string specified in the //remark: directive is printed in the test +results output to help identify what a test is doing.

    +

    As shown in the initial testing example, it is often useful to be able to have +code conditionally compiled for each of the different compilations specified by +the options string. The test driver defines a preprocessor variable named +TEST_NUMBER. This variable has the value “1” for the first set of options, +“2” for the second, and so on.

    +

    If you have a number of test cases that don’t require different command +line options and that have the same result type you can use the +//cases:n directive to specify that the compiler should by invoked +n times, with TEST_NUMBER set to the current invocation number.

    +

    //options: and //cases: can be used together. For example, you may +have five test cases but only need to specify options for the first two.

    +
    //options:-A;cn:-O;cn
    +//cases:5
    +
    +
    +

    The //ulimit: directive specifies command-line options passed to a +ulimit command prior to compiling, linking, and running the test. This +can be used to prevent a test from exhausting system resources or running +in a non-terminating loop.

    +

    Special characters can be incorporated into the test case by using special +escape sequences. The escapes are of the form ???nnn where n is +a decimal digit.

    +

    If //require: is specified, the string that follows is searched for in the +output of --dump_configuration; if not found, the test is skipped. If +multiple //require: cases are specified, all strings must be found or the +test will be skipped.

    +

    If //use_system_includes: is set to true, the system headers +associated with the current EDG base will be added to the default include +paths. Additionally, EDG compiler emulation modes will be enabled as +appropriate. For instance, if the test is run using a GCC 15.1 base this will +add the include paths for system headers associated with GCC 15.1 and +--gnu_version 150100 to the command line. Otherwise, if this directive is +set to false, EDG headers in include_c99 (for C programs) and +include_c++ (for C++ programs) will be added to the default include paths.

    +

    The //edg_header_pack: directive specifies an “EDG header pack” to include +as system headers for testing. Header packs are include directories that are +themselves subdirectories of $TEST_ROOT/.includes/. For instance, +//edg_header_pack: foo will result in a hidden +--sys_include $TEST_ROOT/.includes/foo command line argument.

    +

    If //filter: is specified, the specified command will be used to filter +the run_test output before diff-ing it. By default, a test driver +uses in-process test normalization logic as a filter.

    +
    +
    +

    26.1.2. Multi-file Testing#

    +

    Multi-file tests work similarly to single-file tests; however, they end +with either .mft.c or .mft.cpp. Additionally, for correct +operation, these tests live in their own test directory, typically +following the convention of test-name/test.mft.cpp. This allows the +test to live alongside its supporting files.

    +

    For instance, testing a simple C++ #include might using the following +structure:

    +
    simple-include/
    +  test.h
    +  test.mft.cpp
    +
    +
    +

    Similarly, for testing an import of a module, the test might use the +following structure:

    +
    modules-function/
    +  exporting-module.ixx
    +  test.mft.cpp
    +
    +
    +

    where test.mft.cpp contains the testing directives (described below) that +compile exporting-module.ixx.

    +

    As previously noted, there are additional directives which are useful for +multi-file testing:

    +
    +
    +
    //header_unit_files:t.h t2.h
    +
    //module_files:i-part.ixx internal:i-internal.cpp i.ixx obj:msvc-module.ixx
    +
    //script:script_file
    +
    +
    +

    The //header_unit_files: directive specifies any header files that should +be compiled via --create_header_unit and passed to the test invocation via +a --header_unit mapping.

    +

    The //module_files: directive specifies any module files to be compiled for +the test.

    +

    In most cases these files should be listed without a prefix; such files are +presumed to be module interface source files and will be compiled with the +--module_interface flag to generate both an IFC and a .obj file for +the module source file.

    +

    If given the obj: prefix it’s assumed the IFC file is already present and +only the .obj file should be compiled.

    +

    If given the internal: prefix this is a module implementation unit that an +IFC file should be force-generated for (this is unusual). These module +source files are compiled under the --module_internal_partition flag to +generate both an IFC and a .obj file.

    +

    If //script: is specified, that script is executed instead of any other +commands. In general, the test type does not matter for script files except +for checking the return code. For example, a cp test will expect a zero +return code, while a cn will expect a non-zero. The script will be passed +command-line arguments in the same way that the compile command would.

    +
    +
    +

    26.1.3. Advanced Concepts#

    +

    The directives are processed in the following sequence:

    +
      +
    • those specified in $TEST_ROOT/.run_test_flags

    • +
    • (for multi-file tests) the flags.txt file in the directory of the test

    • +
    • those specified at the start of the test file

    • +
    +

    In some cases later directives overwrite earlier ones (e.g., //type:). +In other cases, a list of the specified values is accumulated (in the order in +which the various lists are specified above). The directives for which the +values are accumulated are:

    +
      +
    • options

    • +
    • options_all

    • +
    • match_regex

    • +
    • linker_options

    • +
    • execution_args

    • +
    • require

    • +
    • header_unit_files

    • +
    • module_files

    • +
    +

    Compile tests are processed through eccp -c. Runtime tests are +compiled and linked using eccp. Compile and link tests are also +compiled and linked using eccp, however a ln test is expected to +return a non-zero status from eccp where a rn test is expected to +return a zero status from eccp and a nonzero status when the program is +executed. If the //eccp_command: directive is used, the command +specified is used instead of the eccp command.

    +
    +
    +
    +

    26.2. Testing Tools#

    +

    There are two primary tools for testing, edgy and edg-run-test. +Both of these tools rely on the same internal edgtest Python library, +they just provide a different interface to it.

    +

    In most cases edgy is the preferred testing tool as it’s designed for +large-scale testing. However, when authoring a new test edg-run-test +can be a great way to get immediate feedback.

    +
    +

    26.2.1. edgy#

    +

    Usage information:

    +
    usage: edgy [-h] [-c RUN_CONFIGS] [--runs-dir TEST_RUNS_DIRECTORY]
    +            [--run-timestamp TEST_RUN_TIMESTAMP] [-j JOB_COUNT] [-T TIMEOUT_SECONDS]
    +            [-A] [-D] [-E] [-M] [-R] [-n MAX_FAIL_COUNT] [--pick PICK_COUNT]
    +            [--disp-run-dir] [-W] [--crash-avoidance] [--no-flakey-tests]
    +            [--replay {all-failing,output-mismatch,regress,unexpected}]
    +            [--slow-tests NUM_SLOW_TESTS_REPORTED] [--fully-random-order]
    +            [--cmd] [--verbose] [filters]
    +
    +EDG test runner.
    +
    +positional arguments:
    +  filters               the test filter to apply; "all" for all suites
    +
    +options:
    +  -h, --help            show this help message and exit
    +  -c, --config RUN_CONFIGS
    +                        the run configurations to apply
    +  --runs-dir TEST_RUNS_DIRECTORY
    +                        override the directory where tests runs are stored
    +  --run-timestamp TEST_RUN_TIMESTAMP
    +                        override the timestamp when creating a new test run (does
    +                        not apply to replay runs)
    +  -j, --jobs JOB_COUNT  the number of concurrent jobs
    +  -T, --timeout TIMEOUT_SECONDS
    +                        the number of seconds to wait for tests before killing them
    +                        (0 to disable)
    +  -A                    include slow tests (marked by an "_" prefix)
    +  -D, --debug-failures  print debug commands for failures
    +  -E, --no-expectations
    +                        disable expectations
    +  -M, --meticulous      disable faster mode (on by default) and run all expensive
    +                        checking
    +  -R, --regress         silence non-regressive changes
    +  -n, --max-failure-count MAX_FAIL_COUNT
    +                        the maximum number of failures
    +  --pick PICK_COUNT     the maximum number of tests to run (this option implies
    +                        --fully-random-order)
    +  --disp-run-dir        print the directory where the run output is being stored
    +  -W, --record          record tests
    +  --crash-avoidance     avoid tests that are likely to crash the compiler (this option
    +                        also implies --no-flakey-tests)
    +  --no-flakey-tests     do not run tests that are known to be flakey
    +  --replay {all-failing,output-mismatch,regress,unexpected}
    +                        rerun tests from the last run
    +  --slow-tests NUM_SLOW_TESTS_REPORTED
    +                        the number of the slowest tests to report
    +  --fully-random-order  completely randomize test execution order (this can help lower
    +                        system pressure by mixing more "intensive" test suites with
    +                        less intensive test suites)
    +  --cmd                 print all run test commands
    +  --verbose             enable verbose mode
    +
    +
    +
    +

    26.2.1.1. Setup Requirements#

    +

    edgy was designed to be usable from any directory. To facilitate this, +the EDG_TEST_HOME environment variable must be set to the directory +where the tests subdirectory and .edgy/config.json are.

    +

    In the typical configuration, CPFE should be set to the C-generating +back end binary being tested and CPFE_CP should be set to the +C++-generating back end binary being tested.

    +
    +
    +

    26.2.1.2. Filtering#

    +

    `edgy works off of one or more (comma-separated) filters. These +filters are typically test suite names, e.g.,

    +
    edgy regressions,stdlib
    +
    +
    +
    +
    26.2.1.2.1. Filter Reduction#
    +

    These can be reduced by adding addition path components. For instance, if +you want to run the tests in the modules directory of the +regressions test suite, you can do so via

    +
    edgy regressions/modules
    +
    +
    +

    You can also elaborate on this to dive down to a single test, e.g., +regressions/foo.sft.cpp:

    +
    edgy regressions/modules/foo.sft.cpp
    +
    +
    +
    +
    +
    26.2.1.2.2. Special Filters#
    +

    There are also a couple of special filters, the primary one is all +(which simply means all the test suites edgy knows about), e.g.,

    +
    edgy all
    +
    +
    +

    An additional very useful one is the mine filter. This filter is +configured by setting the EDGY_MY_TESTS environment variable to a +comma-separated list of test suites. For instance, if concerned primarily +with regressions and the stdlib impact in your work, this might be +a reasonable use:

    +
    export EDGY_MY_TESTS=regressions,stdlib
    +edgy mine
    +
    +
    +

    Note that special filters cannot be reduced (e.g., edgy mine/xyz +does not work).

    +
    +
    +
    26.2.1.2.3. Negative Filters#
    +

    Negative filters can be applied as well. These start with a ! and are +applied as a reduction of positive filters, e.g.,

    +
    edgy regressions,!regressions/modules
    +
    +
    +

    Here we’re running all tests in the regressions suite except for the +tests in the modules subdirectory.

    +
    +
    +
    26.2.1.2.4. File-Loaded Filters#
    +

    Filters can also be loaded from a file:

    +
    $> cat my_filters.txt
    +regressions
    +!regressions/modules
    +$> edgy @my_filters.txt
    +
    +
    +

    The above is logically equivalent to the above negative filter example (the +filters are just spelled out in a file on a line-separated basis).

    +

    This feature is particularly useful for working with fine-grained lists of +tests (such as edgy’s .elog files).

    +
    +
    +
    +

    26.2.1.3. Live Feedback#

    +
    +
    26.2.1.3.1. Test Run Status#
    +

    Progress reporting is provided by a (fairly rapidly) updating status line:

    +
    588/83,651 (0%) in 00:00:04 ~127/sec (00:10:54 remaining)
    +
    +
    +

    This status line shows:

    +
    <number of completed tests>/<number of tests to run total>
    +(<percentage of tests completed>%) in <elapsed time>
    +~<tests per second>/sec
    +(<estimated time remaining at current test per second> remaining)
    +
    +
    +
    +
    +
    26.2.1.3.2. Problem Reporting#
    +

    Any encountered problems are reported above the status line as they’re +discovered.

    +

    A completed run might look something like:

    +
    - regressions/foo.sft.cpp cp::ABORT:
    ++ regressions/foo.sft.cpp cp::PASS--OUTPUT MISMATCH:
    +
    +
    +

    “+” is used to indicate an unexpected problem, while “-” is used to indicate an +unsatisfied expectation (the above is an example of what might happen if there +was a regression resulting in a crash that has been resolved).

    +

    When multiple configurations are in use, the configuration is specified in +parens prior to the test “name”, e.g.:

    +
    + (edg_x86_64) regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH:
    ++ (edg_x86_64_cp) regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH:
    +
    +
    +

    edgy also will print “commentary” in this output without using a marking +character. These are used to report extra information that might be +good to know (e.g., that a particular test ran very slowly), e.g.,

    +
    + regressions/foo.sft.cpp fp::PASS--OUTPUT MISMATCH:
    +  Consider marking regressions/foo.sft.cpp slow (Took: 00:01:04)
    +
    +
    +
    +
    +
    26.2.1.3.3. Test Termination#
    +

    edgy supports early termination when it receives SIGINT (Ctrl + C +in most shells) or SIGTERM. Early termination will make edgy quickly +terminate all spawned process groups (and thus their processes). Any tests +terminated in this fashion will be reported to the user with an “X” prefix, +e.g.,

    +
    X regressions/foo.sft.cpp
    +X stdlib/bar/test.mft.cpp
    +X regressions/baz/test.mft.cpp
    +
    +
    +

    Note: This is particularly helpful both for killing (and finding) tests that +are stuck in an infinite loop if your tests aren’t terminating.

    +
    +
    +
    +

    26.2.1.4. Failure Debug Mode#

    +

    edgy has a failure debug mode (enabled via -D or +--debug-failures) that enables additional “commentary” for failed +tests, aimed at debugging issues with said tests.

    +

    For exposition purposes the below section uses <TEST_ROOT> for the path +represented by EDG_TEST_HOME and <BUILD_BIN> for the location of +the directory containing the front end cpfe binary. Additionally \ +lines have been added to wrap lines.

    +

    As an example, commentary from this option typically looks something like:

    +
    RUN_TEST_DEFAULT_CONFIG="edg_x86_64" LC_ALL="C" CDISP="<BUILD_BIN>" \
    +  edg-run-test -o \
    +  <TEST_ROOT>/runs/2026.06.25-17.14.55/edg_x86_64/regressions
    +  --driver-debug --faster -t \
    +  <TEST_ROOT>/tests/regressions \
    +  <TEST_ROOT>/tests/regressions/foo.sft.cpp
    +
    +
    +

    This can be copied verbatim and when executed will print something like +the following:

    +
    Source file clone:
    +cd $(clone-test-to-tmp <TEST_ROOT>/tests/regressions/foo.sft.cpp)
    +<BUILD_BIN>/cpfe -DTEST_NUMBER=1 --c++20 Test_name.c
    +
    +
    +

    This combined information can then be used to set up a test directory, and a +debug command, following the general setup:

    +
    <make test directory>
    +<set environment variables> <debugger command> <front end invocation>
    +
    +
    +

    Using the above sample output, that would look something like:

    +
    cd $(clone-test-to-tmp <TEST_ROOT>/tests/regressions/foo.sft.cpp)
    +RUN_TEST_DEFAULT_CONFIG="edg_x86_64" LC_ALL="C" CDISP="<BUILD_BIN>" \
    +  gdb --args <BUILD_BIN>/cpfe -DTEST_NUMBER=1 --c++20 Test_name.c
    +
    +
    +

    This will quickly give you a debugger invocation (modulo any bugs/missing +features for test directory setup driver debug) that should exactly reproduce +the circumstances that resulted in edgy seeing what it saw.

    +

    Note that many tests may not have a Source file clone line reported by +the test executor. In these cases it’s perfectly safe to omit this (i.e., +<make test directory> may not always be a part of the pattern).

    +
    +
    +

    26.2.1.5. Regress Mode#

    +

    edgy has a test regression reporting mode (enabled via -R or +--regress). This is aimed at reporting only those tests whose status +changed to something worse and is particularly useful for noisy tests where +there may be lots of valid --OUTPUT-MISMATCHs. The severity ranking +used to determine what’s “worse” is represented in the following table:

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Test Status

    Severity Ranking

    PASS

    0

    FAIL

    1

    BADC

    1

    CATASTROPHE

    2

    ABORT

    3

    RUNTIME ABORT

    3

    +
    +

    As an example, a FAIL to an ABORT will be reported, but an +ABORT to a FAIL will not be reported. Similarly, FAIL to +BADC (or vice versa) will not be reported.

    +
    +
    +

    26.2.1.6. Failure Limiting#

    +

    edgy has a failure limit mode (enabled via -n MAX_FAIL_COUNT or +--max-failure-count MAX_FAIL_COUNT, where MAX_FAIL_COUNT is an +integer) that stops test execution after MAX_FAIL_COUNT tests have +been reported as problematic. This is compatible with regression mode, and +will only count reported regressions.

    +
    +
    +

    26.2.1.7. Re-record Mode#

    +

    edgy has a mode for updating test recordings and patching expectations +in the process (enabled via -W or --record).

    +

    As this mode is intended for usage only to update output, edgy does not +check expectations or otherwise report test status during re-recording. +The process for using re-record mode is something akin to the following:

    +
      +
    1. Run the tests

    2. +
    3. Review the changes

    4. +
    5. Determine if any tests’ expectations or output need to be updated

    6. +
    7. Rerecord the tests that need to be updated (e.g, +edgy -W regressions/foo.sft.cpp)

    8. +
    +
    +
    +

    26.2.1.8. No Expectations Mode#

    +

    edgy has a no expectations mode (enabled via -E or +--no-expectations) which as the name implies disables expectations. +This is useful for seeing true test statuses (i.e., seeing all failures, +including failures that were previously marked as expected).

    +
    +
    +

    26.2.1.9. No Flakey Tests Mode#

    +

    edgy has a “no flakey tests” mode (enabled via --no-flakey-tests) +which, as the name implies, skips known flakey tests. This is useful for +avoiding problematic tests that are known to regularly misdiagnose problems +in your configuration.

    +

    For this to work, the configuration in use must have the flakey tests +listed in the $EDG_TEST_HOME/flakey-tests directory. For example, to +mark regressions/baz/foo.sft.cpp flakey in the foo-bar +configuration, one would add a file +$EDG_TEST_HOME/flakey-tests/foo-bar/regressions.txt with the contents:

    +
    baz/foo.sft.cpp
    +
    +
    +

    Note: It’s recommended (but not required) to organize this file alphabetically +for easier maintenance.

    +
    +
    +

    26.2.1.10. Replay mode#

    +

    edgy has a mode for replaying a portion of the previous test run +(enabled via --replay). It’s important to note that the “runs” that +are replayed are the original “run” not a “replay”, i.e., replay 2 is not +run against replay 1 but is run against the last run that wasn’t a replay +run.

    +

    Replay mode is compatible with the normal edgy options (e.g., filters). +Replay mode itself supports the following sub-options:

    +
    + + + + + + + + + + + + + + + + + + + + +

    Option

    Description

    all-failing

    All tests without PASS status/all tests that +appear in the previous run’s log files.

    output-mismatch

    All tests with OUTPUT MISMATCH status (including +tests that are otherwise passing).

    regress

    All tests that had a status regression vs the current +configuration’s expectations (see the +Regress Mode section for more information +about status regressions).

    unexpected

    All tests that are reporting a status differing from +the current configuration’s expectations.

    +
    +

    Replay results are stored in the last test execution’s run output directory +(typically tests/runs/some-timestamp) in their own replays +subdirectory. Every time a replay is performed a new subdirectory will be +created within the respective replays subdirectory for the replay output. +This gives replay runs a few special characteristics:

    +
      +
    • Test selections are stable across all replay runs (in other words, if you +have run “T” you’re replaying, replay “{N, N + 1, …}” will not affect each +other’s output/test selections).

    • +
    • Replays can be run many times without resulting in edgy’s test run +cleanup deleting anything.

    • +
    +

    As a visual aid, this is the expected directory structure for a run with two +replays in the runs directory:

    +
    .
    +├── 2026.06.07-16.19.15
    +│   ├── replays
    +│   │   ├── 1
    +│   │   │   └── edg_x86_64
    +│   │   │       ├── regressions
    +│   │   │       │   ├── test-a.rt
    +│   │   │       │   ├── test-b.rt
    +│   │   │       │   └── test-c.rt
    +│   │   │       └── regressions.log
    +│   │   └── 2
    +│   │       └── edg_x86_64
    +│   │           ├── regressions
    +│   │           │   ├── test-a.rt
    +│   │           │   ├── test-b.rt
    +│   │           │   └── test-c.rt
    +│   │           └── regressions.log
    +│   └── edg_x86_64
    +│       ├── regressions
    +│       │   ├── test-a.rt
    +│       │   ├── test-b.rt
    +│       │   └── test-c.rt
    +│       └── regressions.log
    +...
    +
    +
    +
    +
    26.2.1.10.1. Replaying Failed Test#
    +

    As an example, consider you’ve run a test suite:

    +
    edgy regressions
    +
    +
    +

    This then revealed 5 of the 500 tests are failing. You then make a change, and +then want to run those 5 tests again to see if you’ve fixed the problem:

    +
    edgy --replay all-failing
    +
    +
    +

    This runs only the 5 failing tests.

    +
    +
    +
    26.2.1.10.2. Replaying Subset of Failed Test#
    +

    As an example, consider you’ve run a test suite:

    +
    edgy regressions
    +
    +
    +

    This then revealed 50 of the 500 tests are failing, but you’re only +interested in the 10 tests in regressions/foo. You then make a change, +and then want to run those 10 tests again to see if you’ve fixed the +problem:

    +
    edgy --replay all-failing regressions/foo
    +
    +
    +

    This runs only the 10 failing tests.

    +
    +
    +
    26.2.1.10.3. Replaying Mismatched#
    +

    As an example, consider you’ve run a test suite:

    +
    edgy regressions
    +
    +
    +

    This then revealed 5 of the 500 tests have an output mismatch due to changes +you made. You review the changes, and decide you want to rerecord these +tests:

    +
    edgy --replay output-mismatch -W
    +
    +
    +

    This runs only the 5 tests with the output mismatch, rerecording them and +updating expectations in the process.

    +
    +
    +
    26.2.1.10.4. Replaying Regressions#
    +

    As an example, consider you’re working with volatile code that’s failing many +tests, and you’re using regression mode to focus down the reported tests:

    +
    edgy -R regressions
    +
    +
    +

    This then revealed 5 of the 500 tests are regressing while 50 are unexpected +status changes, and 200 are failing. The other replay modes will not help you +realistically narrow down the set of test output being reviewed. This is where +regress replays shine:

    +
    edgy --replay regress
    +
    +
    +

    This runs only the 5 tests that actually have regressive status changes, +allowing you to evaluate much more effectively whether your iterative +changes are improvements.

    +
    +
    +
    26.2.1.10.5. Replaying Unexpected#
    +

    As an example, consider you’ve run a test suite:

    +
    edgy regressions
    +
    +
    +

    This then revealed 5 of the 500 tests differ from their expected status or +otherwise have an output mismatch. You review the changes, and decide you want +to rerecord these tests:

    +
    edgy --replay unexpected -W
    +
    +
    +

    This runs only the 5 tests, rerecording them and updating expectations in the +process.

    +
    +
    +
    +

    26.2.1.11. Slow Test Reporting#

    +

    edgy has a slow test reporting mode (enabled via --slow-tests +NUM_SLOW_TESTS_REPORTED, where NUM_SLOW_TESTS_REPORTED is an integer) +that reports the NUM_SLOW_TESTS_REPORTED slowest test executions. This +is compatible with all modes (with the exception of re-record mode which does +not record the necessary timings).

    +
    +
    +

    26.2.1.12. Verbose Mode#

    +

    edgy has a verbose mode (enabled via --verbose) that enables +printing of additional details. Verbose mode provides additional +information about environment variables, what cleanup actions are being +taken, and remarks for failure debugging are turned on for every tests +(regardless of its pass/fail status). This can be useful for initial +setup, or when attempting to get a debug invocation for one or more test(s) +that aren’t currently failing.

    +
    +
    +

    26.2.1.13. Copying Tested Binaries#

    +

    By default edgy copies the executables being tested for each test run. +This allows for (some degree of) working on the front end while testing +occurs as updated binaries will not impact testing.

    +

    If the environment variable EDG_TEST_NO_COPY_X is set or +TEST_X (where X is the environment variable corresponding +to the tested binary – typically CPFE or CPFE_CP) is set, this +functionality is disabled.

    +
    +
    +

    26.2.1.14. Test Run Cleanup#

    +

    If the environment variable EDG_TEST_RUNS_KEPT is set to a valid +integer N (e.g., 10), edgy will only keep the last N entries in the +run directory.

    +

    Note: This does not take into account directory names, it simply deletes +directories in the runs directory based on their modification time. +Make sure you don’t have any subdirectories in the runs directory that +should be kept around before setting this environment variable.

    +
    +
    +

    26.2.1.15. Multi-Configuration Support#

    +

    edgy, as previously noted, has support for simultaneous testing of +different configurations. The configurations that can be tested, as well as +the default set of configurations to test, is configured in the +.edgy/config.json file.

    +

    To manually specify which configurations to run, the -c flag can be +used with a comma-separated list of configurations, e.g.:

    +
    edgy -c edg_x86_64,edg_x86_64_cp regressions
    +
    +
    +

    This will run the regression test suite, in both the edg_x86_64 and +edg_x86_64_cp configurations (which is also the default as edgy is +typically configured).

    +
    +
    +
    +

    26.2.2. edg-run-test#

    +

    Usage information:

    +
    usage: edg-run-test [-h] [-d] [-r] [--driver-debug] [--faster] [-q] [-t TOP_DIR]
    +                    [-o OUTPUT_DIR] test_files [test_files ...]
    +
    +EDG Python based test executor.
    +
    +positional arguments:
    +  test_files            the paths to the test files to run
    +
    +options:
    +  -h, --help            show this help message and exit
    +  -d, --debug           keep the output files
    +  -r, --record, --silent-record
    +                        update the expected test output to be the output from this run.
    +  --driver-debug        add --driver_debug to the test's command line arguments. The
    +                        resulting additional output will be printed to stdout with the
    +                        original test file replacing the generic name. This makes the
    +                        underlying command more easily accessible so that it may be
    +                        more easily fed to a debugger (e.g., gdb) or checked for
    +                        correctness.
    +  --faster              enable command line flags that might speed up the compilation
    +                        of the test files
    +  -q                    only display log output for errors
    +  -t, --top-dir TOP_DIR
    +                        the path to the contextually "top" directory
    +  -o OUTPUT_DIR         the path where output will be stored
    +
    +
    +

    edg-run-test is a considerably simpler tool than edgy. Consider +the following edgy command:

    +
    edgy regressions
    +
    +
    +

    Assuming EDG_TEST_HOME is /edg/tests, the corresponding +edg-run-test invocation would be approximately the following:

    +
    edg-run-test -t /edg/tests/tests/regressions \
    +  /edg/tests/tests/regressions/**/*.sft.c   \
    +  /edg/tests/tests/regressions/**/*.sft.cpp \
    +  /edg/tests/tests/regressions/**/*.mft.c   \
    +  /edg/tests/tests/regressions/**/*.mft.cpp
    +
    +
    +

    Here TEST_ROOT is specified by -t so that any .run_test_flags file +can be correctly processed.

    +

    Of note, edg-run-test does not support expectations or have a notion of +configuration, so this will report the status of all tests regardless of +expected output.

    +

    Additionally, by default all statuses are reported; -q can be used to +reduce the output to something closer to what’s given by edgy.

    +

    The tested binary is the binary found at the CPFE environment variable by +default. However, alternative environment variables can be tested by +specifying the PRIMARY_CPFE environment variable to a different environment +variable (e.g., CPFE_CUSTOM).

    +

    The occasional advantage of edg-run-test over edgy is simplicity. +It’s possible to author a new test outside of the test tree and quickly +execute and iterate on the test before moving the file(s) to include the +test in a test suite.

    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/trans_unit/index.html b/doc/trans_unit/index.html new file mode 100644 index 0000000..4210d52 --- /dev/null +++ b/doc/trans_unit/index.html @@ -0,0 +1,812 @@ + + + + + 17. Multiple Translation Units - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    17. Multiple Translation Units#

    +

    A translation unit is a set of source files translated as a unit, comprising +a primary source file and all of the source files included by that file. +Sometimes, the front end has to deal with more than one translation unit at a +time:

    +
      +
    • +
      When exported templates are used, the source file in which a template is +defined may be different than the one in which is it used. The front end +has to read in a translation unit for the defining source file while +retaining the translation unit for the referencing source file, and then +perform the instantiation in a merged context that includes both +translation units. Additional translation units may be read in for +instantiations of other templates.
      +
      +
    • +
    • +
      When COMPILE_MULTIPLE_TRANSLATION_UNITS is TRUE, multiple files can be +specified on the command line for the front end. Each file is read in turn +as the primary file of a translation unit.
      +
      +
    • +
    +

    In both these cases, the first translation unit read is called the primary +translation unit, and any translation units read after the first are called +secondary translation units. The translation units are kept separate within +the front end. They have separate intermediate language (IL) trees and +conceptually separate symbol tables. After all translation units have been +processed, the IL for each secondary translation unit is merged into the IL for +the primary translation unit. Duplicate copies of entities that appear in more +than one translation unit are eliminated during the merge, and errors are +issued for conflicts between entities that have incompatible definitions in +different translation units. The final merged primary IL tree is then passed +to a back end, looking much like an IL tree from a simple one-translation-unit +compilation.

    +

    The process of translating a primary translation unit and zero or more +secondary translation units into an IL tree is called a compilation.

    +

    Note that when COMPILE_MULTIPLE_SOURCE_FILES [1] is TRUE and the front +end is given several source file names on the command line, each translation +unit is treated as a separate compilation. It is read separately and its IL +tree is written to a separate IL file. No merging is done on the translation +unit IL trees, and no checking for matching between translation units. There +are no secondary translation units in this mode (except those that might be +brought in for exported templates).

    +

    The principal source files of the front end involved in +multiple-translation-unit processing are trans_unit.c, trans_unit.h, +trans_corresp.c, trans_corresp.h, trans_copy.c, and +trans_copy.h.

    +
    +

    17.1. Initialization, Termination, and Keeping Translation Units Separate#

    +

    By and large, the code in the front end is written as if there is only one +translation unit. Global variables and tables indicate the state at the +current point in the input, which is a particular point within a single +translation unit. For the handling of multiple translation units, this global +state must be carefully managed, and updated when one switches between +translation units.

    +

    The process of initialization in the front end is broken down into three parts:

    +
      +
    • +
      Initialization that is done only once in the entire front end invocation. +Initialization routines in this class have names that have the suffix +“_one_time_init”.
      +
      +
    • +
    • +
      Initialization that is redone for each compilation. Initialization +routines in this class have names that have the suffix “_init”.
      +
      +
    • +
    • +
      Initialization that is redone for each translation unit. Initialization +routines in this class have names that have the suffix +“_trans_unit_init”.
      +
      +
    • +
    +

    It can be seen that in COMPILE_MULTIPLE_TRANSLATION_UNITS mode, the front +end does one-time initialization, compilation initialization, and then, for +each source file specified on the command line, translation unit +initialization. In COMPILE_MULTIPLE_SOURCE_FILES mode, on the other hand, +the front end does one-time initialization and then, for each source file +specified on the command line, compilation initialization and then +translation-unit initialization. See the top-level routines in fe_init.c.

    +

    Similarly, termination is done in several parts:

    +
      +
    • +
      pop_scope for the file scope does necessary processing at the end of +the file scope for a translation unit.
      +
      +
    • +
    • +
      translation_unit_wrapup does necessary processing at the end of a +translation unit.
      +
      +
    • +
    • +
      fe_wrapup does necessary processing at the end of a compilation. This +includes calling template_and_inline_function_wrapup, which does most +template instantiation.
      +
      +
    • +
    • +
      wrap_up_file_scopes finishes up each translation unit and merges the +IL.
      +
      +
    • +
    +

    The instantiation process (during the third step above) can bring in additional +secondary translation units for exported templates, which go through their own +initialization, reading/parsing, and termination phases. Eventually, all +necessary templates have been instantiated, which means all necessary +translation units have been created and processed, and wrap_up_file_scopes +is called.

    +

    The source code for a secondary translation unit is read, and the corresponding +IL is generated, all at one time. There is no switching between translation +units while the source code is being read. Once a secondary translation unit +has been read, additional processing may be done in that translation unit that +will add more IL to it, but that is done through template instantiations, and +never by going back and reading more source code. Likewise, instantiations can +add additional IL to the primary translation unit, but no additional source +code will be read into it.

    +

    A structure of type a_translation_unit contains information about a single +translation unit within a compilation, and the global variable +curr_translation_unit points to the entry for the translation unit that is +currently active. By calling switch_translation_unit, one can switch to a +different translation unit, i.e., make another translation unit the “active” +one. This is a relatively expensive process that changes the values of many +global variables to match the new translation unit.

    +

    How does switch_translation_unit know what to update? It updates the +variables recorded by calling register_trans_unit_variable during one-time +initialization. Variables registered in that way are known as trans unit +variables, and their per-translation-unit values are recorded in a data +structure associated with the a_translation_unit structure: They are saved +when the translation unit becomes inactive, and restored when the translation +unit is reactivated. Certain values that need to be accessed efficiently even +when the corresponding translation unit is not the active one are stored +directly in the a_translation_unit structure (e.g., +file_scope_pointers_block), or are pointed to by fields in that structure +(e.g., module_id_ptr; variables of this kind are registered via +register_trans_unit_variable_with_field).

    +

    process_translation_unit is the driver for the reading/parsing of a single +translation unit.

    +

    Some data structures and numbering sequences are deliberately shared across +multiple translation units. The source file data structure and source line +sequence numbers, for example, are shared, so that a source position consisting +of a sequence number and column number is unique across the entire compilation. +Likewise, the symbol table and scope number sequence is shared, which ensures +that scopes always have unique numbers, and therefore that one can do a lookup +in the symbol table by scope number and find only entities from a single scope +from a single translation unit.

    +
    +
    +

    17.2. Memory Regions and Intermediate Language#

    +

    Each secondary translation unit has its own set of IL memory regions, one for +its file scope and one for each top-level function definition. The global +variable file_scope_region_number indicates the region number of the file +scope of the current translation unit, whether it is a primary or secondary +translation unit.

    +

    The function alloc_primary_file_scope_il allocates space in the primary +translation unit IL even if the current translation unit is a secondary +translation unit.

    +

    The macro is_secondary_trans_unit returns true for an IL entry allocated in +a memory region that is part of a secondary translation unit. The global array +trans_unit_for_scope maps a scope number back to a pointer to the +translation unit that contains that scope. Note that when IL is moved from +secondary translation units to the primary IL at the end of the compilation, +the value of is_secondary_trans_unit will change, but that of +trans_unit_for_scope stays as it was.

    +

    The front end memory region is shared across all translation units.

    +
    +
    +

    17.3. Translation Unit Correspondences#

    +

    Each IL entry with external linkage is assigned to a correspondence set +containing all of the related IL entries from different translation units, +i.e., all the entries that represent the same entity. So, for example, all +external global variables called “i” will be in one correspondence set.

    +

    A correspondence set is represented by an entry of type +a_trans_unit_corresp, which is allocated in front end memory (so it is not +really part of the IL). Each entry that is a member of the correspondence set +points to the appropriate a_trans_unit_corresp entry via the +trans_unit_corresp pointer in its source_corresp field. These pointers +are set when secondary translation units are processed, and therefore in a +compilation consisting only of a single translation unit the pointers will be +NULL and the correspondence-set entries will not be allocated. [2] For +entries without linkage, or with internal linkage, the trans_unit_corresp +pointer is always NULL.

    +

    IL entries of type a_base_class are also matched up in correspondence sets +and therefore contain a trans_unit_corresp pointer (though it is not part +of a source_corresp field in that case).

    +
    +
    +

    17.4. Canonical Entries#

    +

    In each correspondence set, one entry is chosen as the canonical entry, and +the canonical field in the a_trans_unit_corresp points to it. The +entry chosen as the canonical entry is an instance that contains the most +detailed information available about the entity: one with a definition if a +definition is available, and a specialization if both specialized and +unspecialized versions of a template instance are available. All other things +being e qual, an entry in the primary IL is chosen over one in a secondary +translation unit, because that means less copying later.

    +

    The canonical entry chosen can change as the compilation progresses. The first +instance seen will generally be chosen as the canonical entry, but it may be +replaced afterwards by a better choice from some other secondary translation +unit scanned later.

    +

    Note that it is possible for a class or namespace not to be the canonical entry +in its correspondence set while at the same time some of its members are the +canonical entries in their sets.

    +

    The macro canonical_il_entry_of can be used to fetch the address of the +canonical entry corresponding to a given entry. For an entry without linkage, +the entry itself is returned.

    +
    +
    +

    17.5. The Copy Address Pointer#

    +

    All IL entries have a prefix that contains various flags and numbers. IL +entries in the file scope of a secondary translation unit have, in addition, a +copy address pointer, which is set during the copy process to indicate the +address in the primary IL to which the entry should be copied or remapped.

    +

    For entries in correspondence sets, generally the canonical entry will be +copied to the primary IL and its copy address pointer will be set to the +address of the copy. The other members of the correspondence set will not be +copied, but their copy address pointers will be set to the same copy address so +that references to them can be remapped to the unique copy in the primary IL.

    +

    For entries not in correspondence sets, including non-declarative entries like +statement and expression nodes, no copy address is pre-assigned. When the +entry is encountered during the copy process, it is copied to the primary IL +and the copy address pointer is set to the address of the copy. All references +to the entry encountered thereafter are remapped to the established copy +address.

    +

    In some cases, entries in the secondary IL are “merged” into the primary IL. +This is necessary, for example, if the canonical entry for a correspondence set +is in a secondary translation unit but there is also a member of that +correspondence set in the primary IL. The address in the primary IL must be +preserved (because there are references to it from elsewhere in the primary IL, +which will not be rewritten), so the canonical entity must be copied on top of +the existing primary IL entry. In such cases, the copy address pointer is used +to form a two-element list: The copy address pointer of the entry in the +secondary translation unit points to allocated space for a copy (also in the +secondary translation unit IL), and the copy address pointer of that copy entry +points in turn to the address of the existing entry in the primary IL. The +copy process copies the original entry to the intermediate copy, with pointer +remapping, and then later overwrites the primary IL entry, carefully preserving +certain information (e.g., next-on-list pointers).

    +

    The macro trans_unit_copy_address_of gives access to the correspondence +pointer of an IL entry (for both fetching and setting). The macro +checked_trans_unit_copy_address_of does the same thing, but also checks +that the entry pointer provided is actually in the file scope of a secondary +translation unit.

    +
    +
    +

    17.6. Correspondence Checking#

    +

    The code in trans_corresp.c establishes correspondences between entities in +a secondary translation unit and similar entities in the primary translation +unit and in other secondary translation units. It sets the correspondence +pointer of IL entries to indicate the correspondences found. While +establishing these correspondences, it checks that linked entities are in fact +compatible, and issues errors when they are not. The entities that have +correspondences set in this way are types, routines, variables, fields, +namespaces, base classes (i.e., a_base_class entries), using-declarations +appearing in class scopes, and templates (including template instances).

    +

    Correspondence checking can occur in three stages of the compilation:

    +
      +
    • +
      Built-in types have their correspondences set by record_builtin_type as +soon as they are created.
      +
      +
    • +
    • +
      When a translation unit has been processed, +set_trans_unit_correspondences is called from +translation_unit_wrapup to establish correspondences for the entities +that were created in that translation unit. The global variable +correspondence_checking_underway is TRUE during this stage (and only +during this stage); after that correspondence_checking_done is TRUE.
      +
      +
    • +
    • +
      The correspondence checking process is notified of every template +instantiation by calls to record_instantiation. When this occurs in a +translation unit after its translation_unit_wrapup call, the +correspondence pointer is established for the new instantiation. The +instantiation process also notifies the correspondence checking process of +template instantiations being completed, through calls to +establish_class_instantiation_corresp, +establish_function_instantiation_corresp, +establish_variable_instantiation_corresp, +establish_block_extern_function_correspondence, +establish_block_extern_variable_correspondence and +establish_friend_type_correspondence.
      +
      +
    • +
    +
    +

    17.6.1. Finding Corresponding Pairs#

    +

    Several different mechanisms are used to find an entity in another translation +unit that corresponds to a given entity:

    +
      +
    • +
      For named entities in namespace scope, the symbol table is used. The +search process simply traverses the list of symbols attached to the symbol +header of the entity for which a correspondence is being searched. This is +done in functions with the prefix find_ (e.g., +find_type_correspondence).
      +
      +
    • +
    • +
      For class members, we can rely on the fact that the lists of IL entities +representing the members should have their elements correspond on a +one-to-one basis. Hence no search is needed, although care must be taken +with compiler-generated members that may not appear in every translation +unit. This principle is implemented by +establish_trans_unit_correspondences_for_class. A similar process can +be used for enumeration constants.
      +
      +
    • +
    • +
      Correspondences for instantiations of templates are usually established +after the templates from which they are generated have been matched up. To +support the search for a matching instantiation, a field +all_instantiations was added to a_template_symbol_supplement. This +field is set only in the supplement for the canonical template entry and +points to a list of all the instantiation symbols for the template, +including those for corresponding templates in other translation units. +Some of the key functions manipulating this list are add_instantiation, +find_class_template_instantiation and +find_function_template_instantiation.
      +
      +
    • +
    • +
      Correspondences are also sometimes established between unnamed types. This +happens when matching up declarations of entities with linkage involving +unnamed types. For example:
      +
      +
      struct { float a, b; } *p, q; // Could appear in two translation units
      +
      +
      +
      +
      In such cases, the correspondence is first established for the entities +with linkage (variables or routines), and the correspondence between the +types is sought by comparing the two types using f_types_are_compatible +with the option TCF_SEEK_CORRESP.
      +
      +
    • +
    +
    +
    +

    17.6.2. Ordering Dependencies#

    +

    Determining whether two entities from different translation units correspond +may require that other correspondences are known. For example, suppose we have +two namespace scope functions f that are declared as

    +
    extern R N::f();
    +
    +
    +

    then the two must correspond if the entities denoted by N correspond, and +if that is the case the entities denoted by R must correspond too. The +ordering of corresponding checks must therefore be managed carefully.

    +

    To reduce the magnitude of this issue, correspondences are determined in two +steps. In the first step, correspondences are established: Only those +components of the entity that uniquely identify it are compared (e.g., the +entity’s name, its enclosing classes and namespaces, parameter types of +functions, etc.) and if they match the correspondence pointer is set. Some +diagnostics may be issued at this time. This process is mostly done in +functions with the prefix establish_. In the second step, which starts +after all the correspondences for the translation unit have been established, +the correspondences are verified. This involves comparing the remaining +relevant attributes of entities that were found to correspond after the first +step; diagnostics are issued if the entities do not match. Most of the +verification work is done in functions with the prefix verify_. This +separation into two steps makes sure that in our example above the +correspondence for R has been established by the time it is needed.

    +

    To deal with other ordering issues, such as the requirement that the +correspondence of N be established in our example, the correspondence +checking process may be stacked. For example, while searching for a +correspondence for N::f above, another search for a correspondence for +N may be initiated. This is driven by calls to functions named +canonical_entity_entry_of where entity is one of +namespace, type, field, routine, variable or template. +If a correspondence was already established, these functions return the +requested canonical entry; if not, they first determine the correspondence by +calling determine_correspondence [3].

    +

    Other ordering issues sometimes arise because establishing a correspondence for +a template instantiation seemingly leads to infinite recursion. Such +situations are resolved in part by placing appropriate markers in the +all_instantiations list and in part by as much as possible establishing the +correspondences of all templates before attempting to match their +instantiations. To that end, the front end maintains a list of instantiations +whose correspondences are yet to be determined (the list is pointed to by +instantiations_to_process). That list is processed at appropriate times +(i.e., when the correspondences of the various templates have been found) by +calls to process_pending_instantiations.

    +

    Finally, we should note that the verification process always compares an entity +with its canonical counterpart. If a canonical entry (from an already +processed translation unit) is replaced by a new entry (from the current +translation unit) the former will need to be compared with the latter when all +the correspondences have been established in the current translation unit. +This is done in process_verification_list.

    +
    +
    +

    17.6.3. Debugging Facilities#

    +

    When the preprocessor symbol DEBUG is TRUE,a few facilities are provided by +trans_corresp.c to help identify problems during correspondence checking. +First, the command-line option “-d-trans_corresp” will cause a line of +output to be produced for each correspondence pointer being set (or cleared), +as well as for certain operations on the all_instantiations lists. Second, +the function db_corresp can be called from a debugger to examine the +correspondence of a given entity. Finally, the modification of a +correspondence pointer for a specific entity can easily be intercepted in a +debug environment where addresses are reproducible from run to run. To enable +this, set breakpoints on main and on corresp_intercept. Rerun the +front end and at the stop in main, set the static variable +trace_corresp_ptr to the address of the entity whose correspondence value +should be tracked: corresp_intercept will be called (triggering the +breakpoint) when that value is modified.

    +
    +
    +
    +

    17.7. Copying from Secondary Translation Units#

    +

    The code in trans_copy.c copies IL from a secondary translation unit to the +primary translation unit IL. It is run after elimination of unneeded entries +in the secondary translation unit, so it copies only entries that are actually +“needed.” It also runs after correspondence checking has established the +correspondences between externally-linked entities, so it does not copy entries +for which there is already an instance in the primary translation unit IL; for +such cases, all references to the entity are simply rewritten to point to the +primary IL instance.

    +

    The secondary translation unit IL consists of a file scope memory region and +zero or more function scope memory regions. The file scope memory region is +actually copied into the primary IL, via a tree walk, with duplicates +eliminated as indicated above. The function scope memory regions, on the other +hand, are not copied. Instead, they are walked to update pointers +appropriately, and then the memory region numbers are simply reassigned to the +primary IL.

    +

    The copy process is handled by copy_secondary_trans_unit_IL_to_primary, +which has five main phases:

    +
      +
    • +
      prepare_for_trans_unit_copy walks through the declaration lists of the +file scope of a secondary translation unit and its subscopes, and puts each +entry into one of four categories: (a) entries that should be copied to the +primary IL; (b) entries that should overwrite a corresponding entry in the +primary IL (e.g., a function in the secondary translation unit that has a +definition, where the corresponding function in the primary IL has only a +declaration); (c) entries that are in a correspondence set but are not the +canonical entry, which should be removed from the lists and discarded; and +(d) entries in a correspondence set that provide additional (minor) +information over what is present in the canonical entry, which should be +merged into the corresponding entry.
      +
      +
    • +
    • +
      copy_from_secondary_to_primary_IL uses the IL-walking routines to walk +the IL tree, copy over entries that need to be copied, and update pointers +so that the copied IL refers only to copies or to pre-existing entries in +the primary IL.
      +
      +
    • +
    • +
      copy_function_bodies_to_primary_IL processes the bodies of any +functions that are to be moved over, by using the IL-walking routines to +walk the IL tree and update pointers appropriately.
      +
      +
    • +
    • +
      finish_trans_unit_copy walks through the declaration lists again, and +links copied entries into the declaration lists of the primary IL. A +struct type copied over, for example, would be linked into the types list +of the primary scope of the primary IL. Variables, types, and routines +that must be merged into the corresponding entries are also copied onto the +corresponding entries at this point. This part of the processing runs +while switched into the primary translation unit. See also +finish_moved_entity_processing, which is similar but reaches all copied +or merged entities, even those from non-merged scopes.
      +
      +
    • +
    • +
      finish_processing_for_function_bodies calls +finish_function_body_processing for each copied function scope memory +region, and kicks off IL lowering for the function if it’s needed. This +part of the processing runs while switched into the primary translation +unit.
      +
      +
    • +
    +

    For entries that are being merged into the primary IL, the copy process sets +the il_lowering flag in the IL entry prefix to indicate merging rather than +copying. (The flag is available for this use because IL lowering is never done +on secondary translation units.) For merged entries, the copy process uses an +extra copy of the entity allocated in the secondary translation unit: The +entity’s copy address pointer points to the copy, whose copy address pointer +points to the corresponding entity in the primary IL. During the copy, the +original entry is copied to the copy space, and its pointers are remapped +there. This allows finish_trans_unit_copy later to have access to both the +original entity in the primary IL and the entity from the secondary translation +unit as updated for the copy. This is often important because some flags from +the two entries need to be merged.

    +

    The bodies of functions not copied over are eliminated, and likewise for the +initializers of variables. See clear_body_for_routine and +clear_variable_definition. Non-template functions and variables in +secondary translation units included only to get exported templates are turned +into external declarations, because the definition of those entities is put out +when the file is compiled as a primary translation unit.

    +

    The IL for secondary translation units can contain references to other +translation units. In some ways, the IL trees for all secondary translation +units have to be viewed as one big somewhat interconnected tree. For this +reason, each of the processing phases described above is done for all secondary +translation units before advancing to the next phase.

    +

    Part of the function of the copy process is to produce a primary IL tree that +contains no references to IL entries in secondary translation units, and this +is done by making sure that every entity copied over has only pointers that +refer to the primary IL. Sometimes, however, the instantiation of a template +that is defined in the primary translation unit introduces exactly the kind of +mixed-translation-unit IL that we are trying to avoid. To eliminate such +references, a pair of routines in trans_copy.c is called:

    +
      +
    • +
      mark_secondary_trans_unit_IL_entities_used_from_primary_as_needed +sweeps the primary translation unit IL and looks for references to +secondary translation unit entries. When it finds them, it marks the +secondary translation unit entries as needed so that they will be copied to +the primary IL when the secondary translation unit is copied.
      +
      +
    • +
    • +
      rewrite_secondary_trans_unit_IL_entity_pointers_used_in_primary sweeps +the primary translation unit IL after the secondary translation units have +been copied in, and looks for references to secondary translation unit +entries. When it finds them, it rewrites them either as references to the +corresponding entity in the primary translation unit (if there is one) or +it copies them and rewrites the pointer to the copy.
      +
      +
    • +
    +

    In some (relatively rare) cases, the merged IL produced by the copy process has +some type entries out of order on the type lists, where “out of order” is +defined according to the peculiar ordering required by the C-generating back +end so that it can generate compilable C code. +fix_type_list_ordering_problems is called after IL lowering to examine the +file-scope types list to look for ordering problems and to move types to fix +those problems. If there are no ordering problems (which is almost always the +case), the checking is done fairly quickly and efficiently.

    +
    +
    +

    17.8. Externalization of statics#

    +

    When a source file includes exported templates, it is possible that the +exported templates will refer to static entities in the file. Because the +template instances may be generated as part of the translation of other source +files, and be included in the object code for those files, it may be necessary +to refer to the static entities from another compilation. Therefore, the front +end externalizes all statics when a compilation includes exported templates. +This gives the static functions and variables external linkage and special +mangled names. This has a number of consequences, such as that static inline +functions become extern inline functions, which in some configurations makes +them instantiatable. See externalize_statics_for_exported_templates.

    +
    +
    +

    17.9. One-instantiation-per-object mode#

    +

    In one-instantiation-per-object mode, each instantiated template is put into a +separate “slice” of the IL, so that a back end can put out each instantiation +in a separate object file. The slices are defined by having a separate +“needed” flag for each slice (there’s an array of them attached to each IL +entity), and setting the slice-specific needed flags so that each slice +contains only the types, variables, etc. referenced by the template +instantiation in that slice.

    +

    When there are multiple translation units, the per-instantiation needed flags +are not maintained in the secondary translation unit IL. Once the IL is copied +to the primary IL, the flags are built up and maintained appropriately there.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/doc/utilities/index.html b/doc/utilities/index.html new file mode 100644 index 0000000..4aeb07f --- /dev/null +++ b/doc/utilities/index.html @@ -0,0 +1,656 @@ + + + + + 22. Utility Programs - CPFE 7.0 documentation + + + + + + + + + + + + + + +
    +
    +
    + + + + CPFE + +
    + +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + + +
    + +
    +
    +

    22. Utility Programs#

    +

    Several utility programs are provided with the front end. Most of the utility +programs help with various link-time issues and are meant to be called from a +driver program or script. One (mk_errinfo) is a tool program used when +modifying the front end. The source for these programs is in the util +directory of the release structure.

    + +
    +

    22.2. edg_munch#

    +

    edg_munch is the EDG version of the USL munch utility. Its source +code is in edg_munch.c, with associated declarations in +edg_munch.h. edg_munch implements a lowest-common-denominator +method for getting global initialization and termination code executed on +systems that have no special support for that. [1]

    +

    edg_munch operates by reading as input a file that is the output of nm +run on a linked executable program. It looks for names beginning with +__sti__ or __std__, those being, respectively, initialization and +termination routines to be called at runtime. It generates a C program that +defines a data structure containing a list of pointers to the initialization +and termination routines. This generated program is then compiled and linked +in with the executable. The data structure is consulted at runtime by startup +code invoked from _main, and the routines on the list are invoked at the +appropriate times.

    +

    edg_munch takes only a single option: -u, if used, specifies whether +external names have an added leading underscore. The command-line option +selects the opposite of the configuration flag +TARG_EXTERNAL_NAMES_GET_UNDERSCORE_ADDED.

    +
    +
    +

    22.3. edg_decode#

    +

    edg_decode is a name demangler. The demangling code is in decode.c, +with associated declarations in decode.h. A main program that uses the +demangling code is provided in edg_decode.c.

    +

    edg_decode reads input from stdin and writes output to stdout. +Things that look like mangled names in the input are demangled. Everything +else is passed through unchanged. This makes the program suitable, for +example, as a filter for the output of a linker: error messages in general are +passed through unaltered, but mangled names are demangled. For example, using +the cfront-like ABI,

    +
    ld: Undefined symbol
    +   _f__Fif
    +
    +
    +

    is turned into

    +
    ld: Undefined symbol
    +   f(int, float)
    +
    +
    +

    Mangled names that are ill-formed in some way are also passed through +unchanged.

    +

    edg_decode usually has only a single option: -u, if used, specifies +whether external names have an added leading underscore. The command-line +option selects the opposite of the configuration flag +TARG_EXTERNAL_NAMES_GET_UNDERSCORE_ADDED. When the IA-64 ABI is used, +however, there is also a -g option, which selects the opposite of the +configuration flag DEFAULT_EMULATE_GNU_ABI_BUGS, which when TRUE extends the +demangling to cover some invalid mangled names put out by g++ 3.2 (and the EDG +front end, when configured to emulate those bugs).

    +

    The demangling is intended to work only on names of external entities. There +is some name mangling done for internal entities, or by the C-generating back +end, that this program does not try to decode.

    +

    In the cfront-like ABI, names that contain double underscores in the source +code will probably not be demangled correctly. This is an unfortunate +consequence of using a mangling scheme that is based on the one used by cfront. +The standard forbids use of double underscores in names in user code, reserving +such names for the implementation, so the effect of this shortcoming is +limited. Implementors should try to avoid using such names for entities with +external linkage. Double underscores at the beginnings of external names do, +however, work correctly. In the IA-64 ABI, a similar problem applies to names +that begin with “_Z”.

    +

    The name demangling is also available through a callable interface, which is +used in edg_prelink. See routine decode_identifier.

    +
    +
    +

    22.4. mk_errinfo#

    +

    mk_errinfo translates a text file containing error message codes and +associated descriptions into a pair of header files that represent this +information in a manner more readily used by the front end.

    +

    The invocation of the mk_errinfo is typically

    +
    mk_errinfo error_msg.txt error_tag.txt err_codes.h err_data.h
    +
    +
    +

    The error_msg.txt file defines the diagnostic messages generated by the +front end. This file, along with error_tag.txt, is processed by +mk_errinfo to generate the err_codes.h and err_data.h include +files. mk_errinfo may also be used to automatically generate the file used +to generate the Error Messages appendix of this manual.

    +

    When used to generate a documentation file, the invocation is typically one of +the following:

    +
    +
    +
    mk_errinfo -d error_msg.txt error_tag.txt generated.tex
    +
    mk_errinfo -mml error_msg.txt error_tag.txt generated.mml
    +
    mk_errinfo -rst error_msg.txt error_tag.txt generated.rst
    +
    +
    +

    generated.tex is the name of the generated output file containing the +documentation in LaTeX format. generated.mml is the name of the generated +output file containing the documentation in MML (Maker Markup Language), which +can be used to create a FrameMaker document. generated.rst is the name of +the generated output file containing the documentation in reStructuredText +format, which can be used with Sphinx and various other tools.

    +

    error_msg.txt contains lines that have the following form:

    +
    error_code;tag;"text"
    +
    +
    +

    The error code is the enumeration element name that is used by the front end. +The file must be specified in enumeration order. To preserve the numbering of +error codes, errors may not be inserted in the middle of the file, nor may +lines be removed. If an error message is no longer in use, the line on which +it is defined should be prefixed with the string REMOVED. This will retain +its sequence number but eliminate it from the generated tables.

    +

    The tag is an alias for a given error code to be used by the end-user to name +that error in the command-line options that change the severities of +diagnostics. If no tag is specified, the error code (with the ec_ removed) +is used as the tag.

    +

    Some messages are used as part of the formatting of other messages (for +example, the messages used to provide error context information). These +messages should have a tag of INTERNAL. This prevents the message from +being entered in the tag table and also prevents the message from appearing in +the automatically generated documentation file.

    +

    The text string contains a quoted string similar to one that would be used in a +C program to define the equivalent string. Any quote characters within the +text string must be escaped.

    +

    The text string includes markers indicating the location of fill-ins in the +message (e.g., %t for a type). Full information on those fill-in codes can +be found in Error Reporting.

    +

    The message text may include supplementary information that is only used to +improve the automatically generated documentation file (which is formatted +into the Error Messages appendix of this manual). For example, an +error text string might look like this

    +
    "a message with %s\='fill-in' included"
    +
    +
    +

    The string \='fill-in' is used when creating the documentation file as the +value to be substituted for the %s. This string is removed from the error +text information when the err_data.h file is created.

    +

    error_tag.txt is used to supply additional tags that may be used as aliases +for diagnostic messages. This mechanism is intended to be used by customers +who are packaging the front end as part of their product and allows them to +assign their own set of error tags without the need to modify the distributed +error_msg.txt file. Note that these tags are used in addition to (not in +place of) the default tags specified in the error_msg.txt file.

    +

    Each line should be formatted as:

    +
    error_code;tag
    +
    +
    +

    The error code is the enumeration element name used by the front end. The tag +is the alias being assigned. There may be more than one alias that references +a given enumerator.

    +

    In both error_msg.txt and error_tag.txt, blank lines are ignored and +lines that begin with a “#” are treated as comments.

    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/index.html b/index.html index cafc874..3fc05da 100644 --- a/index.html +++ b/index.html @@ -1,19 +1,65 @@ ---- -layout: default -title: Open Source Transition -banner: true -description: >- - On September 30, 2026, EDG's C++ front end went open source, with The C++ - Alliance as its nonprofit home. What changes for EDG users, how to - contribute, and where to follow the work. ---- + + + + + Open Source Transition · EDGCPP + + + + + + + + + + + + + + + + + + + + + +

    The EDG open source transition

    EDG is open source.

    On September 30, 2026, the source for EDG's C++ front end went public, and The C++ Alliance became its nonprofit home. Same engine, same standards, professionally maintained, and open to contributions.

    @@ -36,7 +82,7 @@

    The history of EDG

    Coming soon

    The full story is still being written

    -

    This section will cover EDG's founding, the people behind it, the milestones of its front end, and the compilers and tools built on top of it. Have a piece of that history to share? Open an issue on the site's repository.

    +

    This section will cover EDG's founding, the people behind it, the milestones of its front end, and the compilers and tools built on top of it. Have a piece of that history to share? Open an issue on the site's repository.

    @@ -69,7 +115,7 @@

    Domain expertise

    Why The C++ Alliance

    The C++ Alliance is a nonprofit with proven fiscal-sponsorship infrastructure, C++ compiler engineers on staff, and deep roots in the C++ standards and Boost communities. It now serves as EDG's nonprofit home.

    -

    Learn more about The C++ Alliance

    +

    Learn more about The C++ Alliance